diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..f217fb336 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# EditorConfig helps developers define and maintain consistent coding styles between different editors and IDEs. +# +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 4 diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..5f454fdfb --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + groups: + github-actions: + patterns: + - '*' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..dd628c91b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,35 @@ +name: CI + +on: [push, pull_request] + +jobs: + build: + name: Build Spark + + runs-on: ubuntu-latest + strategy: + matrix: + java: + - 11 + - 17 + - 21 + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up JDK ${{ matrix.java }} + uses: actions/setup-java@v5 + with: + java-version: ${{ matrix.java }} + distribution: zulu + + - name: Cache Maven packages + uses: actions/cache@v5 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 + + - name: Build with Maven + run: mvn --batch-mode --update-snapshots verify diff --git a/.gitignore b/.gitignore index 40b12a945..ad163e4a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # Spark ignores -/target +**/target # Java ignores *.class @@ -19,6 +19,7 @@ bin/ *.iws *.iml out/ +!.idea/icon.svg # Netbeans ignores nbproject/ diff --git a/.idea/icon.svg b/.idea/icon.svg new file mode 100644 index 000000000..19391b75b --- /dev/null +++ b/.idea/icon.svg @@ -0,0 +1,49 @@ + +image/svg+xml diff --git a/.transifex.yml b/.transifex.yml new file mode 100644 index 000000000..5707af768 --- /dev/null +++ b/.transifex.yml @@ -0,0 +1,42 @@ +git: + filters: + - filter_type: file + source_file: core/src/main/resources/i18n/spark_i18n.properties + file_format: UNICODEPROPERTIES + translation_files_expression: 'core/src/main/resources/i18n/spark_i18n_.properties' + source_language: en + - filter_type: file + source_file: plugins/fastpath/src/main/resources/i18n/fastpath_i18n.properties + file_format: UNICODEPROPERTIES + translation_files_expression: 'plugins/fastpath/src/main/resources/i18n/fastpath_i18n_.properties' + source_language: en + - filter_type: file + source_file: plugins/meet/src/main/resources/i18n/meet_i18n.properties + file_format: UNICODEPROPERTIES + translation_files_expression: 'plugins/meet/src/main/resources/i18n/meet_i18n_.properties' + source_language: en + - filter_type: file + source_file: plugins/otr/src/main/resources/i18n/otrplugin_i18n.properties + file_format: UNICODEPROPERTIES + translation_files_expression: 'plugins/meet/src/main/resources/i18n/otrplugin_i18n_.properties' + source_language: en + - filter_type: file + source_file: plugins/roar/src/main/resources/i18n/roar_i18n.properties + file_format: UNICODEPROPERTIES + translation_files_expression: 'plugins/roar/src/main/resources/i18n/roar_i18n_.properties' + source_language: en + - filter_type: file + source_file: plugins/spelling/src/main/resources/i18n/spellchecker_i18n.properties + file_format: UNICODEPROPERTIES + translation_files_expression: 'plugins/spelling/src/main/resources/i18n/spellchecker_i18n_.properties' + source_language: en + - filter_type: file + source_file: plugins/transferguard/src/main/resources/i18n/transferguard_i18n.properties + file_format: UNICODEPROPERTIES + translation_files_expression: 'plugins/transferguard/src/main/resources/i18n/transferguard_i18n_.properties' + source_language: en + - filter_type: file + source_file: plugins/translator/src/main/resources/i18n/translator_i18n.properties + file_format: UNICODEPROPERTIES + translation_files_expression: 'plugins/translator/src/main/resources/i18n/translator_i18n_.properties' + source_language: en diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 38b87201b..000000000 --- a/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: java -jdk: - - oraclejdk8 -script: ant -f build/build.xml clean release build.plugins diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 0868b28d5..0bc6e4c1a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ Spark +![spark-64x64](https://user-images.githubusercontent.com/71222850/188323351-2b177f8b-6dbe-4ad5-b1ca-1fbaa8355798.png) ===== [Spark] is an Open Source, cross-platform IM client optimized for businesses and organizations. @@ -16,13 +17,72 @@ Combined with the [Openfire] server, [Spark] is the easiest and best alternative [![Build Status](https://travis-ci.org/igniterealtime/Spark.svg?branch=master)](https://travis-ci.org/igniterealtime/Spark) +Resources +--------- + +- Translation: https://explore.transifex.com/igniterealtime/spark/ +- Documentation: https://www.igniterealtime.org/projects/spark/documentation.jsp +- Community: https://discourse.igniterealtime.org/c/spark +- Bug Tracker: https://igniterealtime.atlassian.net/browse/SPARK +- Nightly Builds: https://www.igniterealtime.org/downloads/nightly_spark.jsp + +Install ------- -[Ignite Realtime] is an Open Source community composed of end-users and developers around the world who -are interested in applying innovative, open-standards-based Real Time Collaboration to their businesses and organizations. -We're aimed at disrupting proprietary, non-open standards-based systems and invite you to participate in what's already one +Download last release from [GitHub releases page](https://github.com/igniterealtime/Spark/releases/latest) +or [nightly build](https://igniterealtime.org/downloads/nightly_spark.jsp) with latest changes. +For Windows, if you are not sure, if it's recommended to download the `spark_*-64bit.msi`. +If you don't have Java JRE installed then download and install an `.msi` file the of the JRE 17 or newer from +[Zulu](https://www.azul.com/downloads/?os=windows&architecture=x86-64-bit&package=jre#zulu) +or [Oracle](https://www.oracle.com/java/technologies/downloads/#jdk25-windows). + +Screenshots +--------- +![Spark_Login](https://user-images.githubusercontent.com/71222850/188326816-a911aff6-34d5-4cac-b253-24901a1f3bc1.png) + +![Spark_menu](https://user-images.githubusercontent.com/71222850/188326850-907f871a-9dac-4669-bffa-0faad24c61e1.png) + +![Spark_MUC](https://user-images.githubusercontent.com/71222850/188327252-27a6aae4-6595-479a-8b44-da223bcae53d.png) + + +Bug Reporting +------------- + +Only a few users have access for filling bugs in the tracker. New +users should: + +1. Create a Discourse account +2. Login to a Discourse account +3. Click on the New Topic button +4. Choose the [Spark Dev category](https://discourse.igniterealtime.org/c/spark/spark-dev) and provide a detailed description of the bug. + +Please search for your issues in the bug tracker before reporting. + +Run from sources +---------------- + +```bash +$ git clone https://github.com/igniterealtime/Spark.git +$ cd Spark/core +$ mvn exec:java +``` + +* Setup IDE with the source: + * [Intellij](https://download.igniterealtime.org/spark/docs/latest/documentation/ide-intellij-setup.html), + * [Eclipse](https://download.igniterealtime.org/spark/docs/latest/documentation/ide-eclipse-setup.html), + * [Visual Studio Code](https://download.igniterealtime.org/spark/docs/latest/documentation/ide-vscode-setup.html). +* [Plugins development guide](https://download.igniterealtime.org/sparkplug_kit/docs/latest/sparkplug_dev_guide.html) +* [Spark Development Forum](https://discourse.igniterealtime.org/c/spark/spark-dev) + + +Ignite Realtime +=============== + +[Ignite Realtime] is an Open Source community composed of end-users and developers around the world who +are interested in applying innovative, open-standards-based Real Time Collaboration to their businesses and organizations. +We're aimed at disrupting proprietary, non-open standards-based systems and invite you to participate in what's already one of the biggest and most active Open Source communities. -[Spark]:http://www.igniterealtime.org/projects/spark/index.jsp -[Openfire]:http://www.igniterealtime.org/projects/openfire/index.jsp -[Ignite Realtime]:http://www.igniterealtime.org +[Spark]:https://www.igniterealtime.org/projects/spark/index.jsp +[Openfire]:https://www.igniterealtime.org/projects/openfire/index.jsp +[Ignite Realtime]:https://www.igniterealtime.org diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..138933d01 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,17 @@ +# Security Policy + +## Supported Versions + +Use this section to tell people about which versions of your project are +currently being supported with security updates. + +| Version | Supported | +| ------- | ------------------ | +| 2.9.x | :white_check_mark: | +| 2.8.x | :x: | +| 2.7.x | :x: | +| 2.6.x | :x: | + +## Reporting a Vulnerability + +Please report vulnerabilities to security@igniterealtime.org diff --git a/build/build.properties b/build/build.properties deleted file mode 100644 index 4df22fc04..000000000 --- a/build/build.properties +++ /dev/null @@ -1,38 +0,0 @@ -# build.properties -# -# The file "7za.exe" must be in your PATH -# This file is supplied with IzPack -# This file is located in "C:\apps\IzPack\utils\wrappers\izpack2exe" -# "python" must be in your PATH, -# i.e. executing "python" on the command line must work -# Obtainable from several places, including: -# http://www.python.org/download/ -# https://www.activestate.com/activepython/downloads/ - -# Advanced Installer (commercial; Free edition available) -# available from http://www.advancedinstaller.com/ -#advinst.path=C:\\Program Files\\Caphyon\\Advanced Installer 7.2.1 - -# install4j (commercial) -# vailable from http://www.ej-technologies.com/products/install4j/overview.html -#installer.install4j.home=C:\\C:\\Program Files\\xxx - -# IzPack (Open Source) -# Available from http://izpack.org/ -#installer.izpack.dir=C:\\apps\\IzPack - -# Launch4J (Open Source) -# Available from http://launch4j.sourceforge.net/ -#launch4j.dir=C:\\apps\\Launch4j - -# Inno Setup (Open Source) -# Available from http://www.jrsoftware.org/isinfo.php -#innosetup.dir=C:\\Program Files\\Inno Setup 5 - -# -# HTTP Proxy -# -#proxy.host= -#proxy.port= -#proxy.user -#proxy.pass diff --git a/build/build.xml b/build/build.xml deleted file mode 100644 index fac195dc1..000000000 --- a/build/build.xml +++ /dev/null @@ -1,1144 +0,0 @@ - - - - - - Spark build script. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Spark Build - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - migrating - sunsecure - imports - strings - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${proxy.host} ${proxy.port} ${proxy.user} ${proxy.pass} - - - - - - - - - - - - - - - - - - - diff --git a/build/builder/build/build.xml b/build/builder/build/build.xml deleted file mode 100644 index 5c7c5731e..000000000 --- a/build/builder/build/build.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/builder/how-to-build.txt b/build/builder/how-to-build.txt deleted file mode 100644 index 83244f9c6..000000000 --- a/build/builder/how-to-build.txt +++ /dev/null @@ -1,16 +0,0 @@ -Building a Sparkplug - -To easily build a Sparkplug, we have added a simple ANT script to create a deployed plug. To create, do the following: - -1) Copy your java source files to the src directory. -2) Place any dependencies (besides Spark) into the lib directory. -3) Update the plugin.xml file to represent your plugin. -4) Go to the build directory, and type ant jar to build your plugin or -.... type "ant run" to build and deploy your plugin directly to Spark and -have Spark startup to test your plugin right away. - -Your new plugin will be called myplugin.jar. - -If you wish to deploy your plugin later, just copy your new myplugin.jar to the plugins directory of your Sparkplug distro kit. - -Enjoy! diff --git a/build/builder/plugin.xml b/build/builder/plugin.xml deleted file mode 100644 index 63f317888..000000000 --- a/build/builder/plugin.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - My Plugin - 1.0 - You - http://www.jivesoftware.org - foo@foo.com - Sample Plugin - example.ExamplePlugin - 2.6.0 - Windows,Linux,Mac - 1.6.0_00 - - - - - diff --git a/build/builder/src/example/ExamplePlugin.java b/build/builder/src/example/ExamplePlugin.java deleted file mode 100644 index a251379a0..000000000 --- a/build/builder/src/example/ExamplePlugin.java +++ /dev/null @@ -1,50 +0,0 @@ -package example; - -import javax.swing.JOptionPane; - -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.Plugin; - -/** - * Example Plugin to demonstrate the use of Plugins - * @author wolf.posdorfer - * - */ -public class ExamplePlugin implements Plugin{ - - @Override - public void initialize() { - // Use this method to initialize your Plugin - - - // The following will add an Entry into the Spark Preferences Window - ExamplePreference mypreference = new ExamplePreference(); - SparkManager.getPreferenceManager().addPreference(mypreference); - - - - // Show a Message When my plugin is loaded - JOptionPane.showMessageDialog(null, "Plugin has been successfully loaded"); - } - - @Override - public void shutdown() { - JOptionPane.showMessageDialog(null, "Plugin has been shutdown"); - } - - @Override - public boolean canShutDown() { - - return false; - } - - @Override - public void uninstall() { - - // use this method to remove stored preferences used by this plugin - - JOptionPane.showMessageDialog(null, "Plugin has been uninstalled"); - - } - -} diff --git a/build/builder/src/example/ExamplePreference.java b/build/builder/src/example/ExamplePreference.java deleted file mode 100644 index 791edb363..000000000 --- a/build/builder/src/example/ExamplePreference.java +++ /dev/null @@ -1,78 +0,0 @@ -package example; - -import javax.swing.Icon; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JPanel; - -import org.jivesoftware.spark.preference.Preference; - -public class ExamplePreference implements Preference{ - - @Override - public String getTitle() { - return "Example"; - } - - @Override - public Icon getIcon() { - return null; - } - - @Override - public String getTooltip() { - return "tooltip of my preference"; - } - - @Override - public String getListName() { - return "Example"; - } - - @Override - public String getNamespace() { - return "EXAMPLE"; - } - - @Override - public JComponent getGUI() { - - JPanel panel = new JPanel(); - panel.add(new JButton("Welcome to my Preferences")); - return panel; - // you would need to add your own JComponent class here - } - - @Override - public void load() { - //initizialize the gui maybe - // or load saved preferences - - } - - @Override - public void commit() { - // save changes in the preference gui - } - - @Override - public boolean isDataValid() { - return false; - } - - @Override - public String getErrorMessage() { - return "EEERROOOOORRR"; - } - - @Override - public Object getData() { - return null; - } - - @Override - public void shutdown() { - // do something - } - -} diff --git a/build/built_target.bat b/build/built_target.bat deleted file mode 100644 index 57eafe4ed..000000000 --- a/build/built_target.bat +++ /dev/null @@ -1 +0,0 @@ -ant -f %1 jar \ No newline at end of file diff --git a/build/built_target.sh b/build/built_target.sh deleted file mode 100644 index bb5a26e1b..000000000 --- a/build/built_target.sh +++ /dev/null @@ -1 +0,0 @@ -ant -f $1 jar diff --git a/build/checkstyle.xml b/build/checkstyle.xml deleted file mode 100644 index 43ba0d4b5..000000000 --- a/build/checkstyle.xml +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/debian/changelog b/build/debian/changelog deleted file mode 100644 index fac92c422..000000000 --- a/build/debian/changelog +++ /dev/null @@ -1,6 +0,0 @@ -spark-messenger (2.7.7) unstable; urgency=medium - - [ Ignite Realtime Community ] - * For full changelog, see http://www.igniterealtime.org/builds/spark/docs/latest/changelog.html - - -- wroot Tue, 24 Apr 2016 11:32:51 +0200 diff --git a/build/debian/compat b/build/debian/compat deleted file mode 100644 index 7ed6ff82d..000000000 --- a/build/debian/compat +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/build/debian/conffiles b/build/debian/conffiles deleted file mode 100644 index e69de29bb..000000000 diff --git a/build/debian/control b/build/debian/control deleted file mode 100644 index b169a2475..000000000 --- a/build/debian/control +++ /dev/null @@ -1,13 +0,0 @@ -Source: spark-messenger -Section: net -Priority: optional -Maintainer: Jive Software -Build-Depends: debhelper, cdbs, patchutils, sun-java6-jdk, ant, fakeroot -Standards-Version: 3.7.2 - -Package: spark-messenger -Section: net -Priority: optional -Pre-Depends: sun-java6-jre -Architecture: all -Description: Cross-platform real-time collaboration client optimized for business and organizations. diff --git a/build/debian/copyright b/build/debian/copyright deleted file mode 100644 index ea5e2430f..000000000 --- a/build/debian/copyright +++ /dev/null @@ -1,13 +0,0 @@ -This package was debianized by Jive Software - on Apri 28, 2008. - The source was downloaded from http://www.igniterealtime.org. - -Upstream author: Jive Software - -This software is copyright (c) 2007 by Jive Software - -You are free to distribute this software under the terms of -the GNU General Public License. On Debian systems, the complete -text of the GNU General Public License can be found in the file -'/usr/share/common-licenses/GPL'. - diff --git a/build/debian/files b/build/debian/files deleted file mode 100644 index 8821bb9e5..000000000 --- a/build/debian/files +++ /dev/null @@ -1 +0,0 @@ -spark_2.7.7_all.deb net optional diff --git a/build/debian/patches/01_spark_home_dir.patch b/build/debian/patches/01_spark_home_dir.patch deleted file mode 100644 index f99dde74c..000000000 --- a/build/debian/patches/01_spark_home_dir.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- spark/src/resources/startup.sh.orgi 2009-10-27 09:28:27.000000000 +0100 -+++ spark/src/resources/startup.sh 2009-10-27 09:29:19.000000000 +0100 -@@ -1,6 +1,6 @@ - #!/bin/bash - --scriptdir="`dirname ${0}`"; -+scriptdir="/usr/share/spark/bin"; - cd "${scriptdir}/.."; - wd="`pwd`"; - libdir="${wd}/lib"; - diff --git a/build/debian/postinst b/build/debian/postinst deleted file mode 100644 index 745c7bed6..000000000 --- a/build/debian/postinst +++ /dev/null @@ -1,22 +0,0 @@ -#! /bin/sh -set -e - -case "$1" in - configure) - - chmod -R 755 /usr/share/spark/bin/spark - - - ;; - - abort-upgrade|abort-remove|abort-deconfigure) - - ;; - - *) - echo "postinst called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - - diff --git a/build/debian/postrm b/build/debian/postrm deleted file mode 100755 index 20afb2181..000000000 --- a/build/debian/postrm +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh - -set -e - -case "$1" in - purge) - ;; - - remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) - - - ;; - - *) - echo "postrm called with unknown argument \`$1'" >&2 - exit 1 - -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff --git a/build/debian/prerm b/build/debian/prerm deleted file mode 100644 index 823d8fe15..000000000 --- a/build/debian/prerm +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -set -e - diff --git a/build/debian/rules b/build/debian/rules deleted file mode 100755 index 65b36b332..000000000 --- a/build/debian/rules +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/make -f - -include /usr/share/cdbs/1/rules/simple-patchsys.mk -include /usr/share/cdbs/1/rules/debhelper.mk -include /usr/share/cdbs/1/class/ant.mk - -DEST := $(CURDIR)/debian/spark-messenger/ -TARGET := $(CURDIR)/target/build -SPARK := $(DEST)/usr/share/spark - -JAVA_HOME := /usr/lib/jvm/j2sdk1.7-oracle -DEB_ANT_BUILDFILE := build/build.xml -DEB_ANT_BUILD_TARGET := jar -DEB_ANT_CLEAN_TARGET := clean - -install/spark-messenger:: - cp $(TARGET)/bin/startup.sh $(SPARK)/bin/spark - cp $(TARGET)/lib/*.jar $(SPARK)/lib/ - cp -r $(TARGET)/resources $(SPARK)/ - cp -r $(TARGET)/plugins $(SPARK)/ - cp -r $(TARGET)/xtra $(SPARK)/ - diff --git a/build/debian/spark-messenger.dirs b/build/debian/spark-messenger.dirs deleted file mode 100644 index 43e6aebda..000000000 --- a/build/debian/spark-messenger.dirs +++ /dev/null @@ -1,7 +0,0 @@ -/usr/share/spark/bin -/usr/share/spark/lib -/usr/share/spark/lib/linux -/usr/share/spark/resources -/usr/share/spark/plugins -/usr/share/spark/xtra - diff --git a/build/debian/spark-messenger.links b/build/debian/spark-messenger.links deleted file mode 100644 index 2c5cd866c..000000000 --- a/build/debian/spark-messenger.links +++ /dev/null @@ -1 +0,0 @@ -/usr/share/spark/bin/spark /usr/bin/spark diff --git a/build/docbook/filter_language.xsl b/build/docbook/filter_language.xsl deleted file mode 100755 index a660b223b..000000000 --- a/build/docbook/filter_language.xsl +++ /dev/null @@ -1,30 +0,0 @@ - - - - en - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/installer/images/liveassistant-16x16.png b/build/installer/images/liveassistant-16x16.png deleted file mode 100644 index 405a6a517..000000000 Binary files a/build/installer/images/liveassistant-16x16.png and /dev/null differ diff --git a/build/installer/images/liveassistant-32x32.png b/build/installer/images/liveassistant-32x32.png deleted file mode 100644 index 410fdc582..000000000 Binary files a/build/installer/images/liveassistant-32x32.png and /dev/null differ diff --git a/build/installer/images/mac/dmgBackground.png b/build/installer/images/mac/dmgBackground.png deleted file mode 100644 index ca9d7b124..000000000 Binary files a/build/installer/images/mac/dmgBackground.png and /dev/null differ diff --git a/build/installer/izpack/RegistrySpec.xml b/build/installer/izpack/RegistrySpec.xml deleted file mode 100644 index 9a2ba2c6d..000000000 --- a/build/installer/izpack/RegistrySpec.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - diff --git a/build/installer/izpack/default_shortcutSpec.xml b/build/installer/izpack/default_shortcutSpec.xml deleted file mode 100644 index e6ab4b173..000000000 --- a/build/installer/izpack/default_shortcutSpec.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/build/installer/izpack/launch4j-starter.tmpl b/build/installer/izpack/launch4j-starter.tmpl deleted file mode 100644 index 5941566a7..000000000 --- a/build/installer/izpack/launch4j-starter.tmpl +++ /dev/null @@ -1,46 +0,0 @@ - - true - gui - lib/spark.jar - @SPARKDIR@/starter.exe - Spark - - . - normal - http://java.com/download - - false - false - - @SPARKDIR@/../../src/resources/images/spark.ico - - org.jivesoftware.Restarter - ./lib/spark.jar - - - ./jre/ - 1.6.0 - - preferJre - -Dappdir="." -Djava.library.path="./lib/windows/" - - - 2.6.0.0 - 2.6.0 - Spark Client - http://igniterealtime.org - 2.6.0.0 - 2.6.0 - Spark - Igniterealtime - Spark Client - starter.exe - - - An error occurred while starting the application. - This application was configured to use a bundled Java Runtime Environment but the runtime is missing or corrupted. - This application requires a Java Runtime Environment.\nAt least version - The registry refers to a nonexistent Java Runtime Environment installation or the runtime is corrupted. - An application instance is already running. - - diff --git a/build/installer/izpack/launch4j.tmpl b/build/installer/izpack/launch4j.tmpl deleted file mode 100644 index afe37e1a7..000000000 --- a/build/installer/izpack/launch4j.tmpl +++ /dev/null @@ -1,48 +0,0 @@ - - false - gui - @SPARKDIR@/lib/startup.jar - @SPARKDIR@/Spark.exe - Spark - - . - normal - http://java.com/download - - true - false - - - org.jivesoftware.launcher.Startup - ./resources - ./lib/*.jar - ./lib/windows/*.jar - - @SPARKDIR@/../../src/resources/images/spark.ico - - ./jre/ - 1.6.0 - - preferJre - -Dappdir="." -Djava.library.path="./lib/windows/" - - - 2.6.0.0 - 2.6.0 - Spark Client - http://igniterealtime.org - 2.6.0.0 - 2.6.0 - Spark - Igniterealtime - Spark Client - Spark.exe - - - An error occurred while starting the application. - This application was configured to use a bundled Java Runtime Environment but the runtime is missing or corrupted. - This application requires a Java Runtime Environment.\nAt least version - The registry refers to a nonexistent Java Runtime Environment installation or the runtime is corrupted. - An application instance is already running. - - diff --git a/build/installer/izpack/spark b/build/installer/izpack/spark deleted file mode 100644 index c525e3ead..000000000 --- a/build/installer/izpack/spark +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh -# -# Spark Startup -# -SPARK_OPTS="" - -# Detect Java -JAVACMD=$(which java) -if [ ! -e "$JAVACMD" ]; then - # JAVA_HOME set? - if [ "" != "$JAVA_HOME" ]; then - JAVACMD="$JAVA_HOME/bin/java" - fi -fi - -if [ -z "$JAVACMD" ]; then - echo "Java VM not found." - exit 1 -fi - - -# Start Spark -"$JAVACMD" $SPARK_OPTS -Xmx64M -Dappdir=$INSTALL_PATH \ - -cp $INSTALL_PATH/lib/log4j.jar:$INSTALL_PATH/lib/linux/fmj.jar:$INSTALL_PATH/lib/startup.jar:$INSTALL_PATH/lib/linux/jdic.jar:$INSTALL_PATH/resources \ - org.jivesoftware.launcher.Startup $@ diff --git a/build/installer/izpack/unix_shortcutSpec.xml b/build/installer/izpack/unix_shortcutSpec.xml deleted file mode 100644 index 46574bfce..000000000 --- a/build/installer/izpack/unix_shortcutSpec.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - description="Spark - XMPP Client" - - - - - - - - diff --git a/build/installer/mac/dmg_spark.scpt b/build/installer/mac/dmg_spark.scpt deleted file mode 100644 index 9697584bb..000000000 Binary files a/build/installer/mac/dmg_spark.scpt and /dev/null differ diff --git a/build/installer/mac/dmg_spark.txt b/build/installer/mac/dmg_spark.txt deleted file mode 100644 index a5615bafb..000000000 --- a/build/installer/mac/dmg_spark.txt +++ /dev/null @@ -1 +0,0 @@ -on run {volumeName, artPath, theHeight, theWidth, x1, y1, x2, y2, iconSize} tell application "Finder" tell disk (volumeName as string) open delay 2 set dsStore to "\"" & "/Volumes/" & volumeName & "/" & ".DS_STORE\"" tell container window set current view to icon view set toolbar visible to false set statusbar visible to false set the bounds to {10, 10, 658, 482} set statusbar visible to false end tell set opts to the icon view options of container window set the arrangement of opts to not arranged set the icon size of opts to 128 --iconSize set background picture of opts to file ".background:dmgBackground.png" -- Icon positions delay 2 set position of item "Spark.app" to {140, 250} set position of item "Applications" to {395, 250} delay 2 update without registering applications end tell delay 10 end tell end run \ No newline at end of file diff --git a/build/installer/mac/tar.sh b/build/installer/mac/tar.sh deleted file mode 100755 index 07829ca37..000000000 --- a/build/installer/mac/tar.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -cd $1 - -rm Spark.tar -rm Spark.tar.gz - -tar -cf Spark.tar Spark.app -gzip Spark.tar - diff --git a/build/installer/spark-izpack.xml b/build/installer/spark-izpack.xml deleted file mode 100644 index b69407942..000000000 --- a/build/installer/spark-izpack.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - Spark - 2.6.0 - http://www.igniterealtime.org - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - XMPP Client - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/installer/spark-izpack5.xml b/build/installer/spark-izpack5.xml deleted file mode 100644 index fbc6eb031..000000000 --- a/build/installer/spark-izpack5.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - Spark - 2.7.2 - http://www.igniterealtime.org - - - 1.7 - no - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Spark Client - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/installer/spark.aip b/build/installer/spark.aip deleted file mode 100644 index 682515961..000000000 --- a/build/installer/spark.aip +++ /dev/null @@ -1,1073 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/installer/spark.aip.tmpl b/build/installer/spark.aip.tmpl deleted file mode 100644 index 612b5178f..000000000 --- a/build/installer/spark.aip.tmpl +++ /dev/null @@ -1,1072 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/build/installer/spark.install4j b/build/installer/spark.install4j deleted file mode 100644 index c38fcf18a..000000000 --- a/build/installer/spark.install4j +++ /dev/null @@ -1,630 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ../../src/resources/images/spark-60x60.png - - - - - - ../../src/resources/images/spark-16x16.png - - - - - ../../src/resources/images/spark-32x32.png - - - - - false - - - true - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - context.getBooleanVariable("sys.confirmedUpdateInstallation") - - - - - - - - - - - !context.getBooleanVariable("sys.confirmedUpdateInstallation") - - - - - - - - - - - - - - - - - - - - - - - - - ${compiler:sys.fullName} - - - - - !context.getBooleanVariable("sys.confirmedUpdateInstallation") - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${i18n:CreateDesktopIcon} - - - true - - - createDesktopLinkAction - - - - - - - - - - - - - ${i18n:CreateQuickLaunchIcon} - - - true - - - createQuicklaunchIconAction - - - - - component.setVisible(Util.isWindows()); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${compiler:sys.fullName} ${compiler:sys.version} - - - - - - - - - - - - - Spark - - - - ${compiler:sys.fullName} - - - - - context.getBooleanVariable("createDesktopLinkAction") - - - - - - - ${i18n:UninstallerMenuEntry(${compiler:sys.fullName})} - - - - - !context.getBooleanVariable("sys.programGroupDisabled") - - - - - - - - - - - - - - - - - - - - - 4 - - - - - context.getBooleanVariable("executeLauncherAction") && (!context.isUnattended()) - - - - - - - - - - - - - - - - - ${i18n:RunEntryExec("${compiler:sys.fullName}")} - - - true - - - executeLauncherAction - - - - - - - - - - - - - - - - - - ../../src/resources/images/spark-60x60.png - - - - - - ../../src/resources/images/spark-16x16.png - - - - - ../../src/resources/images/spark-32x32.png - - - - - false - - - true - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/installer/spark.iss b/build/installer/spark.iss deleted file mode 100644 index 869cac069..000000000 --- a/build/installer/spark.iss +++ /dev/null @@ -1,30 +0,0 @@ -; -- Spark.iss -- -; Demonstrates copying 3 files and creating an icon. - -; SEE THE DOCUMENTATION FOR DETAILS ON CREATING .ISS SCRIPT FILES! - -[Setup] -AppName=Spark -AppVerName=Spark Version 2.6.0 -DefaultDirName={pf}\Spark -DefaultGroupName=Spark -UninstallDisplayIcon={app}\Spark.exe -Compression=lzma -SolidCompression=yes -OutputDir=userdocs:Spark Setup - -[Files] -Source: "..\..\target\build\Spark.exe"; DestDir: "{app}" -Source: "..\..\target\build\starter.exe"; DestDir: "{app}" -Source: "..\..\target\build\lib\*"; DestDir: "{app}\lib" -Source: "..\..\target\build\lib\windows\*"; DestDir: "{app}\lib\windows\" -Source: "..\..\target\build\plugins\*"; DestDir: "{app}\plugins" -Source: "..\..\target\build\resources\*"; DestDir: "{app}\resources" -Source: "..\..\target\build\xtra\emoticons\*"; DestDir: "{app}\xtra\emoticons\" - -[Icons] -Name: "{group}\Spark"; Filename: "{app}\Spark.exe" - -[Registry] -Root: HKCR; Subkey: "Applications\Spark.exe"; ValueName: "TaskbarGroupIcon"; ValueData: "{app}\resources\spark.ico" - diff --git a/build/installer/spark_install4j_3_2_1.install4j b/build/installer/spark_install4j_3_2_1.install4j deleted file mode 100644 index 42b43a01d..000000000 --- a/build/installer/spark_install4j_3_2_1.install4j +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/lib/ant-contrib.jar b/build/lib/ant-contrib.jar deleted file mode 100644 index db90b0aae..000000000 Binary files a/build/lib/ant-contrib.jar and /dev/null differ diff --git a/build/lib/appbundler-1.0ea.jar b/build/lib/appbundler-1.0ea.jar deleted file mode 100644 index e131e5bf8..000000000 Binary files a/build/lib/appbundler-1.0ea.jar and /dev/null differ diff --git a/build/lib/asm.jar b/build/lib/asm.jar deleted file mode 100644 index b3baf3feb..000000000 Binary files a/build/lib/asm.jar and /dev/null differ diff --git a/build/lib/checkstyle.jar b/build/lib/checkstyle.jar deleted file mode 100644 index faeedde34..000000000 Binary files a/build/lib/checkstyle.jar and /dev/null differ diff --git a/build/lib/dist/JTattoo.jar b/build/lib/dist/JTattoo.jar deleted file mode 100644 index 81cb09285..000000000 Binary files a/build/lib/dist/JTattoo.jar and /dev/null differ diff --git a/build/lib/dist/activation.jar b/build/lib/dist/activation.jar deleted file mode 100644 index aaf5e8d16..000000000 Binary files a/build/lib/dist/activation.jar and /dev/null differ diff --git a/build/lib/dist/asterisk-im-client-2.0.0-SNAPSHOT.jar b/build/lib/dist/asterisk-im-client-2.0.0-SNAPSHOT.jar deleted file mode 100644 index 56d7ba715..000000000 Binary files a/build/lib/dist/asterisk-im-client-2.0.0-SNAPSHOT.jar and /dev/null differ diff --git a/build/lib/dist/bccontrib.jar b/build/lib/dist/bccontrib.jar deleted file mode 100644 index 48d62df43..000000000 Binary files a/build/lib/dist/bccontrib.jar and /dev/null differ diff --git a/build/lib/dist/bcpkix.jar b/build/lib/dist/bcpkix.jar deleted file mode 100644 index 38fb50382..000000000 Binary files a/build/lib/dist/bcpkix.jar and /dev/null differ diff --git a/build/lib/dist/bcprov.jar b/build/lib/dist/bcprov.jar deleted file mode 100644 index 0b80922e6..000000000 Binary files a/build/lib/dist/bcprov.jar and /dev/null differ diff --git a/build/lib/dist/cobra.jar b/build/lib/dist/cobra.jar deleted file mode 100644 index 3e26322f8..000000000 Binary files a/build/lib/dist/cobra.jar and /dev/null differ diff --git a/build/lib/dist/dom4j.jar b/build/lib/dist/dom4j.jar deleted file mode 100644 index 95da51b07..000000000 Binary files a/build/lib/dist/dom4j.jar and /dev/null differ diff --git a/build/lib/dist/ext/jweb-ext.jar b/build/lib/dist/ext/jweb-ext.jar deleted file mode 100644 index eb13d332c..000000000 Binary files a/build/lib/dist/ext/jweb-ext.jar and /dev/null differ diff --git a/build/lib/dist/ext/primary.jar b/build/lib/dist/ext/primary.jar deleted file mode 100644 index b4c91f9ea..000000000 Binary files a/build/lib/dist/ext/primary.jar and /dev/null differ diff --git a/build/lib/dist/fmj.jar b/build/lib/dist/fmj.jar deleted file mode 100644 index 9e56a314a..000000000 Binary files a/build/lib/dist/fmj.jar and /dev/null differ diff --git a/build/lib/dist/ice4j.jar b/build/lib/dist/ice4j.jar deleted file mode 100644 index 65b9d321d..000000000 Binary files a/build/lib/dist/ice4j.jar and /dev/null differ diff --git a/build/lib/dist/jdom.jar b/build/lib/dist/jdom.jar deleted file mode 100644 index e4d827b84..000000000 Binary files a/build/lib/dist/jdom.jar and /dev/null differ diff --git a/build/lib/dist/jna.jar b/build/lib/dist/jna.jar deleted file mode 100644 index 9f96e4b77..000000000 Binary files a/build/lib/dist/jna.jar and /dev/null differ diff --git a/build/lib/dist/js.jar b/build/lib/dist/js.jar deleted file mode 100644 index 2b926505d..000000000 Binary files a/build/lib/dist/js.jar and /dev/null differ diff --git a/build/lib/dist/json-simple-1.1.1.jar b/build/lib/dist/json-simple-1.1.1.jar deleted file mode 100644 index 66347a6c8..000000000 Binary files a/build/lib/dist/json-simple-1.1.1.jar and /dev/null differ diff --git a/build/lib/dist/jspeex.jar b/build/lib/dist/jspeex.jar deleted file mode 100644 index 894257fcd..000000000 Binary files a/build/lib/dist/jspeex.jar and /dev/null differ diff --git a/build/lib/dist/jxmpp-core.jar b/build/lib/dist/jxmpp-core.jar deleted file mode 100644 index 4751dd7e8..000000000 Binary files a/build/lib/dist/jxmpp-core.jar and /dev/null differ diff --git a/build/lib/dist/jxmpp-util-cache.jar b/build/lib/dist/jxmpp-util-cache.jar deleted file mode 100644 index 958036237..000000000 Binary files a/build/lib/dist/jxmpp-util-cache.jar and /dev/null differ diff --git a/build/lib/dist/libjitsi.jar b/build/lib/dist/libjitsi.jar deleted file mode 100644 index baf91992e..000000000 Binary files a/build/lib/dist/libjitsi.jar and /dev/null differ diff --git a/build/lib/dist/linux/libcivil.so b/build/lib/dist/linux/libcivil.so deleted file mode 100755 index a3b0ab6ab..000000000 Binary files a/build/lib/dist/linux/libcivil.so and /dev/null differ diff --git a/build/lib/dist/linux/libjnawtrenderer.so b/build/lib/dist/linux/libjnawtrenderer.so deleted file mode 100644 index 9285b2239..000000000 Binary files a/build/lib/dist/linux/libjnawtrenderer.so and /dev/null differ diff --git a/build/lib/dist/linux/libjnffmpeg.so b/build/lib/dist/linux/libjnffmpeg.so deleted file mode 100644 index e0593e9a6..000000000 Binary files a/build/lib/dist/linux/libjnffmpeg.so and /dev/null differ diff --git a/build/lib/dist/linux/libjng722.so b/build/lib/dist/linux/libjng722.so deleted file mode 100644 index fb59f7127..000000000 Binary files a/build/lib/dist/linux/libjng722.so and /dev/null differ diff --git a/build/lib/dist/linux/libjnopus.so b/build/lib/dist/linux/libjnopus.so deleted file mode 100644 index 765518a19..000000000 Binary files a/build/lib/dist/linux/libjnopus.so and /dev/null differ diff --git a/build/lib/dist/linux/libjnportaudio.so b/build/lib/dist/linux/libjnportaudio.so deleted file mode 100644 index 5280e45bf..000000000 Binary files a/build/lib/dist/linux/libjnportaudio.so and /dev/null differ diff --git a/build/lib/dist/linux/libjnpulseaudio.so b/build/lib/dist/linux/libjnpulseaudio.so deleted file mode 100644 index ed76a9045..000000000 Binary files a/build/lib/dist/linux/libjnpulseaudio.so and /dev/null differ diff --git a/build/lib/dist/linux/libjnscreencapture.so b/build/lib/dist/linux/libjnscreencapture.so deleted file mode 100644 index f7112f885..000000000 Binary files a/build/lib/dist/linux/libjnscreencapture.so and /dev/null differ diff --git a/build/lib/dist/linux/libjnspeex.so b/build/lib/dist/linux/libjnspeex.so deleted file mode 100644 index 696204468..000000000 Binary files a/build/lib/dist/linux/libjnspeex.so and /dev/null differ diff --git a/build/lib/dist/linux/libjnvideo4linux2.so b/build/lib/dist/linux/libjnvideo4linux2.so deleted file mode 100644 index 01de3f422..000000000 Binary files a/build/lib/dist/linux/libjnvideo4linux2.so and /dev/null differ diff --git a/build/lib/dist/linux/libjnvpx.so b/build/lib/dist/linux/libjnvpx.so deleted file mode 100644 index a95aadab1..000000000 Binary files a/build/lib/dist/linux/libjnvpx.so and /dev/null differ diff --git a/build/lib/dist/lobo-pub.jar b/build/lib/dist/lobo-pub.jar deleted file mode 100644 index a334ebd2f..000000000 Binary files a/build/lib/dist/lobo-pub.jar and /dev/null differ diff --git a/build/lib/dist/lobo.jar b/build/lib/dist/lobo.jar deleted file mode 100644 index 5615126e2..000000000 Binary files a/build/lib/dist/lobo.jar and /dev/null differ diff --git a/build/lib/dist/log4j.jar b/build/lib/dist/log4j.jar deleted file mode 100644 index 493a3ccc1..000000000 Binary files a/build/lib/dist/log4j.jar and /dev/null differ diff --git a/build/lib/dist/log4j.properties b/build/lib/dist/log4j.properties deleted file mode 100644 index a736d0211..000000000 --- a/build/lib/dist/log4j.properties +++ /dev/null @@ -1,58 +0,0 @@ -#------------------------------------------------------------------------------ -# -# The following properties set the logging levels and log appender. The -# log4j.rootCategory variable defines the default log level and one or more -# appenders. For the console, use 'S'. For the daily rolling file, use 'R'. -# For an HTML formatted log, use 'H'. -# -# To override the default (rootCategory) log level, define a property of the -# form (see below for available values): -# -# log4j.logger. = -# -# Available logger names: -# TODO -# -# Possible Log Levels: -# FATAL, ERROR, WARN, INFO, DEBUG -# -#------------------------------------------------------------------------------ -log4j.rootCategory=INFO, S - -log4j.logger.com.dappit.Dapper.parser=ERROR -log4j.logger.org.w3c.tidy=FATAL - -#------------------------------------------------------------------------------ -# -# The following properties configure the console (stdout) appender. -# See http://logging.apache.org/log4j/docs/api/index.html for details. -# -#------------------------------------------------------------------------------ -log4j.appender.S = org.apache.log4j.ConsoleAppender -log4j.appender.S.layout = org.apache.log4j.PatternLayout -log4j.appender.S.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n - -#------------------------------------------------------------------------------ -# -# The following properties configure the Daily Rolling File appender. -# See http://logging.apache.org/log4j/docs/api/index.html for details. -# -#------------------------------------------------------------------------------ -log4j.appender.R = org.apache.log4j.DailyRollingFileAppender -log4j.appender.R.File = logs/logs.log -log4j.appender.R.Append = true -log4j.appender.R.DatePattern = '.'yyy-MM-dd -log4j.appender.R.layout = org.apache.log4j.PatternLayout -log4j.appender.R.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n - -#------------------------------------------------------------------------------ -# -# The following properties configure the Rolling File appender in HTML. -# See http://logging.apache.org/log4j/docs/api/index.html for details. -# -#------------------------------------------------------------------------------ -log4j.appender.H = org.apache.log4j.RollingFileAppender -log4j.appender.H.File = logs/log.html -log4j.appender.H.MaxFileSize = 100KB -log4j.appender.H.Append = false -log4j.appender.H.layout = org.apache.log4j.HTMLLayout \ No newline at end of file diff --git a/build/lib/dist/lti-civil.jar b/build/lib/dist/lti-civil.jar deleted file mode 100644 index 010727203..000000000 Binary files a/build/lib/dist/lti-civil.jar and /dev/null differ diff --git a/build/lib/dist/mac/JavaSoundStream.fix.jar b/build/lib/dist/mac/JavaSoundStream.fix.jar deleted file mode 100644 index 820d70f42..000000000 Binary files a/build/lib/dist/mac/JavaSoundStream.fix.jar and /dev/null differ diff --git a/build/lib/dist/osgi.core.jar b/build/lib/dist/osgi.core.jar deleted file mode 100644 index c3a677e8a..000000000 Binary files a/build/lib/dist/osgi.core.jar and /dev/null differ diff --git a/build/lib/dist/platform.jar b/build/lib/dist/platform.jar deleted file mode 100644 index b55af7e48..000000000 Binary files a/build/lib/dist/platform.jar and /dev/null differ diff --git a/build/lib/dist/sdes4j.jar b/build/lib/dist/sdes4j.jar deleted file mode 100644 index aeda2afd3..000000000 Binary files a/build/lib/dist/sdes4j.jar and /dev/null differ diff --git a/build/lib/dist/smack-bosh.jar b/build/lib/dist/smack-bosh.jar deleted file mode 100644 index 6bf7545cd..000000000 Binary files a/build/lib/dist/smack-bosh.jar and /dev/null differ diff --git a/build/lib/dist/smack-compression-jzlib.jar b/build/lib/dist/smack-compression-jzlib.jar deleted file mode 100644 index 7a728d0ce..000000000 Binary files a/build/lib/dist/smack-compression-jzlib.jar and /dev/null differ diff --git a/build/lib/dist/smack-core.jar b/build/lib/dist/smack-core.jar deleted file mode 100644 index 424470e4a..000000000 Binary files a/build/lib/dist/smack-core.jar and /dev/null differ diff --git a/build/lib/dist/smack-debug-slf4j.jar b/build/lib/dist/smack-debug-slf4j.jar deleted file mode 100644 index 7a395c100..000000000 Binary files a/build/lib/dist/smack-debug-slf4j.jar and /dev/null differ diff --git a/build/lib/dist/smack-debug.jar b/build/lib/dist/smack-debug.jar deleted file mode 100644 index e0c378996..000000000 Binary files a/build/lib/dist/smack-debug.jar and /dev/null differ diff --git a/build/lib/dist/smack-experimental.jar b/build/lib/dist/smack-experimental.jar deleted file mode 100644 index 061f26c62..000000000 Binary files a/build/lib/dist/smack-experimental.jar and /dev/null differ diff --git a/build/lib/dist/smack-extensions.jar b/build/lib/dist/smack-extensions.jar deleted file mode 100644 index 06947723c..000000000 Binary files a/build/lib/dist/smack-extensions.jar and /dev/null differ diff --git a/build/lib/dist/smack-im.jar b/build/lib/dist/smack-im.jar deleted file mode 100644 index e24ae21aa..000000000 Binary files a/build/lib/dist/smack-im.jar and /dev/null differ diff --git a/build/lib/dist/smack-java7.jar b/build/lib/dist/smack-java7.jar deleted file mode 100644 index 884a461ba..000000000 Binary files a/build/lib/dist/smack-java7.jar and /dev/null differ diff --git a/build/lib/dist/smack-legacy.jar b/build/lib/dist/smack-legacy.jar deleted file mode 100644 index dffd4b2af..000000000 Binary files a/build/lib/dist/smack-legacy.jar and /dev/null differ diff --git a/build/lib/dist/smack-resolver-javax.jar b/build/lib/dist/smack-resolver-javax.jar deleted file mode 100644 index 191f315da..000000000 Binary files a/build/lib/dist/smack-resolver-javax.jar and /dev/null differ diff --git a/build/lib/dist/smack-sasl-javax.jar b/build/lib/dist/smack-sasl-javax.jar deleted file mode 100644 index cd22433ee..000000000 Binary files a/build/lib/dist/smack-sasl-javax.jar and /dev/null differ diff --git a/build/lib/dist/smack-tcp.jar b/build/lib/dist/smack-tcp.jar deleted file mode 100644 index 2d5e26126..000000000 Binary files a/build/lib/dist/smack-tcp.jar and /dev/null differ diff --git a/build/lib/dist/substance.jar b/build/lib/dist/substance.jar deleted file mode 100644 index 6d8c641e7..000000000 Binary files a/build/lib/dist/substance.jar and /dev/null differ diff --git a/build/lib/dist/swingx-all-1.6.3.jar b/build/lib/dist/swingx-all-1.6.3.jar deleted file mode 100644 index b6f4414d8..000000000 Binary files a/build/lib/dist/swingx-all-1.6.3.jar and /dev/null differ diff --git a/build/lib/dist/systeminfo.jar b/build/lib/dist/systeminfo.jar deleted file mode 100644 index 73ff10b07..000000000 Binary files a/build/lib/dist/systeminfo.jar and /dev/null differ diff --git a/build/lib/dist/trident.jar b/build/lib/dist/trident.jar deleted file mode 100644 index 54fb61472..000000000 Binary files a/build/lib/dist/trident.jar and /dev/null differ diff --git a/build/lib/dist/windows/civil.dll b/build/lib/dist/windows/civil.dll deleted file mode 100644 index 7bdb64c07..000000000 Binary files a/build/lib/dist/windows/civil.dll and /dev/null differ diff --git a/build/lib/dist/windows/jnawtrenderer.dll b/build/lib/dist/windows/jnawtrenderer.dll deleted file mode 100644 index bc476fd12..000000000 Binary files a/build/lib/dist/windows/jnawtrenderer.dll and /dev/null differ diff --git a/build/lib/dist/windows/jndirectshow.dll b/build/lib/dist/windows/jndirectshow.dll deleted file mode 100644 index 1266a10cd..000000000 Binary files a/build/lib/dist/windows/jndirectshow.dll and /dev/null differ diff --git a/build/lib/dist/windows/jnffmpeg.dll b/build/lib/dist/windows/jnffmpeg.dll deleted file mode 100644 index 50effd793..000000000 Binary files a/build/lib/dist/windows/jnffmpeg.dll and /dev/null differ diff --git a/build/lib/dist/windows/jng722.dll b/build/lib/dist/windows/jng722.dll deleted file mode 100644 index ccb8bab63..000000000 Binary files a/build/lib/dist/windows/jng722.dll and /dev/null differ diff --git a/build/lib/dist/windows/jnopus.dll b/build/lib/dist/windows/jnopus.dll deleted file mode 100644 index d56c850fe..000000000 Binary files a/build/lib/dist/windows/jnopus.dll and /dev/null differ diff --git a/build/lib/dist/windows/jnportaudio.dll b/build/lib/dist/windows/jnportaudio.dll deleted file mode 100644 index 174dcc3ca..000000000 Binary files a/build/lib/dist/windows/jnportaudio.dll and /dev/null differ diff --git a/build/lib/dist/windows/jnscreencapture.dll b/build/lib/dist/windows/jnscreencapture.dll deleted file mode 100644 index b53fffbda..000000000 Binary files a/build/lib/dist/windows/jnscreencapture.dll and /dev/null differ diff --git a/build/lib/dist/windows/jnspeex.dll b/build/lib/dist/windows/jnspeex.dll deleted file mode 100644 index fd3615e07..000000000 Binary files a/build/lib/dist/windows/jnspeex.dll and /dev/null differ diff --git a/build/lib/dist/windows/jnvpx.dll b/build/lib/dist/windows/jnvpx.dll deleted file mode 100644 index f297d0df1..000000000 Binary files a/build/lib/dist/windows/jnvpx.dll and /dev/null differ diff --git a/build/lib/dist/windows/jnwasapi.dll b/build/lib/dist/windows/jnwasapi.dll deleted file mode 100644 index dec6d661e..000000000 Binary files a/build/lib/dist/windows/jnwasapi.dll and /dev/null differ diff --git a/build/lib/dist/windows/jnwincoreaudio.dll b/build/lib/dist/windows/jnwincoreaudio.dll deleted file mode 100644 index 540a68f02..000000000 Binary files a/build/lib/dist/windows/jnwincoreaudio.dll and /dev/null differ diff --git a/build/lib/dist/xpp3.jar b/build/lib/dist/xpp3.jar deleted file mode 100644 index 451ac82af..000000000 Binary files a/build/lib/dist/xpp3.jar and /dev/null differ diff --git a/build/lib/dist/xstream.jar b/build/lib/dist/xstream.jar deleted file mode 100644 index e212047b5..000000000 Binary files a/build/lib/dist/xstream.jar and /dev/null differ diff --git a/build/lib/dist/zrtp4j-light.jar b/build/lib/dist/zrtp4j-light.jar deleted file mode 100644 index 8fd155396..000000000 Binary files a/build/lib/dist/zrtp4j-light.jar and /dev/null differ diff --git a/build/lib/i4jruntime.jar b/build/lib/i4jruntime.jar deleted file mode 100644 index b364b6d59..000000000 Binary files a/build/lib/i4jruntime.jar and /dev/null differ diff --git a/build/lib/junit.jar b/build/lib/junit.jar deleted file mode 100644 index 5b4bb849a..000000000 Binary files a/build/lib/junit.jar and /dev/null differ diff --git a/build/lib/merge/Wrapper.dll b/build/lib/merge/Wrapper.dll deleted file mode 100644 index 3fea10f87..000000000 Binary files a/build/lib/merge/Wrapper.dll and /dev/null differ diff --git a/build/lib/merge/commons-codec.jar b/build/lib/merge/commons-codec.jar deleted file mode 100644 index 957b6752a..000000000 Binary files a/build/lib/merge/commons-codec.jar and /dev/null differ diff --git a/build/lib/merge/commons-httpclient.jar b/build/lib/merge/commons-httpclient.jar deleted file mode 100644 index 9a6881b7d..000000000 Binary files a/build/lib/merge/commons-httpclient.jar and /dev/null differ diff --git a/build/lib/merge/commons-logging.jar b/build/lib/merge/commons-logging.jar deleted file mode 100644 index b99c9375a..000000000 Binary files a/build/lib/merge/commons-logging.jar and /dev/null differ diff --git a/build/lib/merge/jaxen.jar b/build/lib/merge/jaxen.jar deleted file mode 100644 index b63363113..000000000 Binary files a/build/lib/merge/jaxen.jar and /dev/null differ diff --git a/build/lib/merge/looks.jar b/build/lib/merge/looks.jar deleted file mode 100644 index 2495ebb2e..000000000 Binary files a/build/lib/merge/looks.jar and /dev/null differ diff --git a/build/lib/merge/updater.jar b/build/lib/merge/updater.jar deleted file mode 100644 index 9ac1274eb..000000000 Binary files a/build/lib/merge/updater.jar and /dev/null differ diff --git a/build/lib/pack200task.jar b/build/lib/pack200task.jar deleted file mode 100644 index 80422e416..000000000 Binary files a/build/lib/pack200task.jar and /dev/null differ diff --git a/build/lib/pmd.jar b/build/lib/pmd.jar deleted file mode 100644 index 986ad2010..000000000 Binary files a/build/lib/pmd.jar and /dev/null differ diff --git a/build/lib/versions.txt b/build/lib/versions.txt deleted file mode 100644 index 53855e09a..000000000 --- a/build/lib/versions.txt +++ /dev/null @@ -1,55 +0,0 @@ -Name | Version | License | URL -------------------------------------+-----------------------+-------------------+------------------------------------- -ant-contrib.jar | ? | Apache | http://ant-contrib.sourceforge.net/ -i4jruntime.jar | ? | Commercial | http://www.ej-technologies.com -jarbundler-1.4.jar | ? | GPL | http://informagen.com/JarBundler/index.html -pack200task.jar | ? | Sun | https://java-pack200-ant-task.dev.java.net/ -pmd.jar | 4.2.5 | BSD | http://pmd.sf.net -asm.jar | 3.1 | BSD | http://pmd.sf.net -checkstyle.jar | 6.18-all | Apache 2 | https://sourceforge.net/projects/checkstyle/ -junit.jar | 4.8.2 | CPL | http://www.junit.org -dist/activation.jar | ? | Sun | http://java.sun.com/javase/technologies/desktop/javabeans/jaf/downloads/index.html -dist/asterisk-im-client.jar | 2.0.0-SNAPSHOT | GPL | http://igniterealtime.org/ -dist/jxmpp-core | 0.4.2 | Apache | https://github.com/igniterealtime/jxmpp -dist/jxmpp-util-cache | 0.4.2 | Apache | https://github.com/igniterealtime/jxmpp -dist/dom4j.jar | 2.0.0.a | BSD | http://www.dom4j.org/ -dist/linux/jdic.jar | ? | LGPL | https://jdic.dev.java.net/ -dist/mac/javaSoundStream.fix.jar | ? | ? | ? -dist/smack-bosh.jar | 4.1.7 | Apache | http://www.igniterealtime.org/projects/smack/index.jsp -dist/smack-compression-jzlib.jar | 4.1.7 | Apache | http://www.igniterealtime.org/projects/smack/index.jsp -dist/smack-core.jar | 4.1.7 | Apache | http://www.igniterealtime.org/projects/smack/index.jsp -dist/smack-debug.jar | 4.1.7 | Apache | http://www.igniterealtime.org/projects/smack/index.jsp -dist/smack-debug-slf4j.jar | 4.1.7 | Apache | http://www.igniterealtime.org/projects/smack/index.jsp -dist/smack-experimental.jar | 4.1.7 | Apache | http://www.igniterealtime.org/projects/smack/index.jsp -dist/smack-extensions.jar | 4.1.7 | Apache | http://www.igniterealtime.org/projects/smack/index.jsp -dist/smack-im.jar | 4.1.7 | Apache | http://www.igniterealtime.org/projects/smack/index.jsp -dist/smack-java7.jar | 4.1.7 | Apache | http://www.igniterealtime.org/projects/smack/index.jsp -dist/smack-legacy.jar | 4.1.7 | Apache | http://www.igniterealtime.org/projects/smack/index.jsp -dist/smack-resolver-javax.jar | 4.1.7 | Apache | http://www.igniterealtime.org/projects/smack/index.jsp -dist/smack-sasl-javax.jar | 4.1.7 | Apache | http://www.igniterealtime.org/projects/smack/index.jsp -dist/smack-tcp.jar | 4.1.7 | Apache | http://www.igniterealtime.org/projects/smack/index.jsp -dist/swingx.jar | ? | LGPL | https://swingx.dev.java.net/ -dist/systeminfo.jar | ? | LGPL | https://jdic.dev.java.net/incubator/systeminfo/index.html -dist/windows/jacob.jar | 1.14.1 | LGPL | http://jacob-project.sourceforge.net/ -dist/windows/jdic.jar | ? | LGPL | https://jdic.dev.java.net/ -dist/xpp3.jar | 1.1.4.c | Apache* | http://www.extreme.indiana.edu/xgws/xsoap/xpp/mxp1/ -dist/xstream.jar | ? | ? | http://xstream.codehaus.org/ -dist/fmj.jar | 09-10-26 SVN | LGPL | http://sf.net/projects/fmj -dist/jdom.jar | 1.1.1 | BSD | http://www.jdom.org -dist/ext/jweb-ext.jar | 0.98.4 | LGPL | http://lobobrowser.org -dist/ext/primary.jar | 0.98.4 | LGPL | http://lobobrowser.org -dist/cobra.jar | 0.98.4 | LGPL | http://lobobrowser.org -dist/js.jar | 0.98.4 | LGPL | http://lobobrowser.org -dist/lobo-pub.jar | 0.98.4 | LGPL | http://lobobrowser.org -dist/lobo.jar | 0.98.4 | LGPL | http://lobobrowser.org -dist/substance.jar | 7.2.1 | BSD | https://github.com/Insubstantial -dist/trident.jar | 7.2.1 | BSD | https://github.com/Insubstantial -dist/JTattoo.jar | 1.6.9 | Apache(?) | http://www.jtattoo.net -merge/commons-codec.jar | 1.3 | Apache | http://commons.apache.org/codec/ -merge/commons-httpclient.jar | ? | Apache | http://hc.apache.org/ -merge/commons-logging.jar | ? | Apache | http://commons.apache.org/logging/ -merge/jaxen.jar | 1.1.1 | BSD | http://jaxen.codehaus.org/ -merge/looks.jar | ? | BSD | http://www.jgoodies.com/downloads/libraries.html -merge/updater.jar | ? | ? | Jive? - -* xpp3-1.1.4.c has multiple licenses. \ No newline at end of file diff --git a/build/projects/Spark.iml b/build/projects/Spark.iml deleted file mode 100644 index d1673326f..000000000 --- a/build/projects/Spark.iml +++ /dev/null @@ -1,375 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/projects/Spark.ipr b/build/projects/Spark.ipr deleted file mode 100644 index 42c6617eb..000000000 --- a/build/projects/Spark.ipr +++ /dev/null @@ -1,457 +0,0 @@ - - - - - - - - - - - - - - - - - - - - 0 - 0 - 0 - N - -12610845 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/rpm/spark.spec b/build/rpm/spark.spec deleted file mode 100644 index 2aed0b4b1..000000000 --- a/build/rpm/spark.spec +++ /dev/null @@ -1,179 +0,0 @@ -Name: Spark -Summary: Spark RPM-Paket -Version: %{SPARK_VERSION} -Release: 1 -License: Apache license v2.0 -Group: misc/Spark -Source: %{SPARK_SOURCE} -BuildRoot: %{_tmppath}/build-root-%{name} -Packager: igniterealtime.org -Distribution: Linux -Prefix: /usr/share -Url: http://www.igniterealtime.org/downloads/source.jsp - -%define prefix /usr/share -%define homedir %{prefix}/spark -%define debug_package %{nil} - -%description -Instant Messenger - -%prep -%setup -q spark_src - -%build -cd build -/opt/apache-ant-1.8.1/bin/ant jar -cd .. - - -%install -# Prep the install location. -rm -rf $RPM_BUILD_ROOT -mkdir -p $RPM_BUILD_ROOT%{prefix} - -# Copy over the main install tree. -cp -R target/build $RPM_BUILD_ROOT%{homedir} - -mkdir -p $RPM_BUILD_ROOT/usr/bin/ - -#pushd $RPM_BUILD_ROOT%{homedir} -cd $RPM_BUILD_ROOT%{homedir} -#gzip -cd %{SOURCE1} | tar xvf - -#popd - -echo "#!/bin/bash" > $RPM_BUILD_ROOT/usr/bin/spark -echo "SPARKDIR=/usr/share/spark/" >> $RPM_BUILD_ROOT/usr/bin/spark -echo "-Dappdir=\$SPARKDIR -cp \$SPARKDIR/lib/log4j.jar:\$SPARKDIR/lib/jdom.jar:\$SPARKDIR/lib/fmj.jar:\$SPARKDIR/lib/startup.jar:\$SPARKDIR/lib/linux/jdic.jar:\$SPARKDIR/resources org.jivesoftware.launcher.Startup" >> $RPM_BUILD_ROOT/usr/bin/spark - -chmod -R 755 $RPM_BUILD_ROOT/usr/bin/spark - -rm -r $RPM_BUILD_ROOT/usr/share/spark/lib/windows -rm -r $RPM_BUILD_ROOT/usr/share/spark/lib/windows64 - -# Force a happy exit even if openfire condrestart script didn't exit cleanly. -exit 0 - - -%files -%dir /usr/bin/spark -%dir /usr/share/spark/bin -%dir /usr/share/spark -%dir /usr/share/spark/xtra -/usr/share/spark/bin/* -%dir /usr/share/spark/documentation/ -/usr/share/spark/documentation/* -%dir /usr/share/spark/documentation/images/ -/usr/share/spark/documentation/images/* -%dir /usr/share/spark/lib -/usr/share/spark/lib/activation.jar -/usr/share/spark/lib/asterisk-im-client.jar -/usr/share/spark/lib/base.jar -/usr/share/spark/lib/bccontrib.jar -/usr/share/spark/lib/bcpkix.jar -/usr/share/spark/lib/bcprov.jar -/usr/share/spark/lib/dom4j.jar -/usr/share/spark/lib/fmj.jar -/usr/share/spark/lib/jdom.jar -/usr/share/spark/lib/i4jruntime.jar -/usr/share/spark/lib/ice4j.jar -/usr/share/spark/lib/json-simple-1.1.1.jar -/usr/share/spark/lib/jspeex.jar -/usr/share/spark/lib/JTattoo.jar -/usr/share/spark/lib/libjitsi.jar -%dir /usr/share/spark/lib/linux/ -/usr/share/spark/lib/linux/libcivil.so -/usr/share/spark/lib/linux/libjnawtrenderer.so -/usr/share/spark/lib/linux/libjnffmpeg.so -/usr/share/spark/lib/linux/libjng722.so -/usr/share/spark/lib/linux/libjnopus.so -/usr/share/spark/lib/linux/libjnportaudio.so -/usr/share/spark/lib/linux/libjnpulseaudio.so -/usr/share/spark/lib/linux/libjnscreencapture.so -/usr/share/spark/lib/linux/libjnspeex.so -/usr/share/spark/lib/linux/libjnvideo4linux2.so -/usr/share/spark/lib/linux/libjnvpx.so -%dir /usr/share/spark/lib/linux64/ -/usr/share/spark/lib/linux64/libcivil.so -/usr/share/spark/lib/linux64/libjnawtrenderer.so -/usr/share/spark/lib/linux64/libjnffmpeg.so -/usr/share/spark/lib/linux64/libjng722.so -/usr/share/spark/lib/linux64/libjnopus.so -/usr/share/spark/lib/linux64/libjnportaudio.so -/usr/share/spark/lib/linux64/libjnpulseaudio.so -/usr/share/spark/lib/linux64/libjnscreencapture.so -/usr/share/spark/lib/linux64/libjnspeex.so -/usr/share/spark/lib/linux64/libjnvideo4linux2.so -/usr/share/spark/lib/linux64/libjnvpx.so -/usr/share/spark/lib/linux64/libodbc.so -/usr/share/spark/lib/linux64/libodbcinst.so -%dir /usr/share/spark/lib/mac/ -/usr/share/spark/lib/mac/JavaSoundStream.fix.jar -/usr/share/spark/lib/mac/libjnawtrenderer.jnilib -/usr/share/spark/lib/mac/libjnffmpeg.jnilib -/usr/share/spark/lib/mac/libjng722.jnilib -/usr/share/spark/lib/mac/libjnmaccoreaudio.jnilib -/usr/share/spark/lib/mac/libjnopus.jnilib -/usr/share/spark/lib/mac/libjnportaudio.jnilib -/usr/share/spark/lib/mac/libjnquicktime.jnilib -/usr/share/spark/lib/mac/libjnscreencapture.jnilib -/usr/share/spark/lib/mac/libjnspeex.jnilib -/usr/share/spark/lib/mac/libjnvpx.jnilib -/usr/share/spark/lib/mac/libSystemUtilities.jnilib -/usr/share/spark/lib/osgi.core.jar -/usr/share/spark/lib/sdes4j.jar -/usr/share/spark/lib/smack.jar -/usr/share/spark/lib/smackx-debug.jar -/usr/share/spark/lib/smackx.jar -/usr/share/spark/lib/smackx-workgroup.jar -/usr/share/spark/lib/spark.jar -/usr/share/spark/lib/startup.jar -/usr/share/spark/lib/swingx-all-1.6.3.jar -/usr/share/spark/lib/systeminfo.jar -/usr/share/spark/lib/xpp.jar -/usr/share/spark/lib/xstream.jar -/usr/share/spark/lib/lti-civil.jar -/usr/share/spark/lib/log4j.jar -/usr/share/spark/lib/log4j.properties -/usr/share/spark/lib/jna.jar -/usr/share/spark/lib/platform.jar -/usr/share/spark/lib/js.jar -/usr/share/spark/lib/cobra.jar -/usr/share/spark/lib/lobo-pub.jar -/usr/share/spark/lib/lobo.jar -/usr/share/spark/lib/substance.jar -/usr/share/spark/lib/trident.jar -/usr/share/spark/lib/zrtp4j-light.jar -%dir /usr/share/spark/lib/ext/ -/usr/share/spark/lib/ext/jweb-ext.jar -/usr/share/spark/lib/ext/primary.jar -%dir /usr/share/spark/logs/ -%doc /usr/share/spark/logs/error.log -%dir /usr/share/spark/plugins/ -/usr/share/spark/plugins/idlelinux.jar -/usr/share/spark/plugins/sparkphone.jar -/usr/share/spark/plugins/jingle.jar -/usr/share/spark/plugins/jniwrapper.jar -/usr/share/spark/plugins/spelling-plugin.jar -/usr/share/spark/plugins/fastpath.jar -/usr/share/spark/plugins/roar.jar -/usr/share/spark/plugins/otrplug.jar -/usr/share/spark/plugins/transferguard.jar -%dir /usr/share/spark/resources/ -/usr/share/spark/resources/Info.plist -/usr/share/spark/resources/jniwrap.dll -/usr/share/spark/resources/jniwrap.lic -%dir /usr/share/spark/resources/sounds/ -/usr/share/spark/resources/sounds/bell.wav -/usr/share/spark/resources/sounds/chat_request.wav -/usr/share/spark/resources/sounds/incoming.wav -/usr/share/spark/resources/sounds/outgoing.wav -/usr/share/spark/resources/sounds/presence_changed.wav -/usr/share/spark/resources/startup.sh -/usr/share/spark/resources/systeminfo.dll -%dir /usr/share/spark/xtra/emoticons/ -/usr/share/spark/xtra/emoticons/Default.adiumemoticonset.zip -/usr/share/spark/xtra/emoticons/GTalk.AdiumEmoticonset.zip -/usr/share/spark/xtra/emoticons/POPO.adiumemoticonset.zip -/usr/share/spark/xtra/emoticons/sparkEmoticonSet.zip -#%{homedir}/jre \ No newline at end of file diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 000000000..8df3cc8ad --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,313 @@ + + 4.0.0 + + + org.igniterealtime.spark + parent + 3.1.0-SNAPSHOT + + + spark-core + jar + + Spark Core + The essentials of Spark, including the user interface and startup scripts, excluding most optional components + + + 1.79 + + + + spark + + + src/main/resources + true + + **/spark.properties + + + + src/main/resources + false + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.2 + + + + org.jivesoftware.launcher.Startup + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.1.1 + + + src/assembly/installation-directory.xml + + + + + make-assembly + package + + single + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + org.jivesoftware.launcher.Startup + + + + org.apache.maven.plugins + maven-resources-plugin + 3.1.0 + + + + + + org.igniterealtime.smack + smack-tcp + ${dependency.smack.version} + + + org.igniterealtime.smack + smack-im + ${dependency.smack.version} + + + org.igniterealtime.smack + smack-extensions + ${dependency.smack.version} + + + org.igniterealtime.smack + smack-experimental + ${dependency.smack.version} + + + org.igniterealtime.smack + smack-debug + ${dependency.smack.version} + + + org.igniterealtime.smack + smack-debug-slf4j + ${dependency.smack.version} + + + org.igniterealtime.smack + smack-legacy + ${dependency.smack.version} + + + org.igniterealtime.smack + smack-java11 + ${dependency.smack.version} + + + org.igniterealtime.smack + smack-sasl-javax + ${dependency.smack.version} + + + org.igniterealtime.smack + smack-xmlparser + ${dependency.smack.version} + + + org.igniterealtime.smack + smack-core + ${dependency.smack.version} + + + org.igniterealtime.spark + emoticons + ${project.version} + runtime + sparkEmoticonSet + zip + + + org.igniterealtime.spark + emoticons + ${project.version} + runtime + POPO.adiumemoticonset + zip + + + org.igniterealtime.spark + emoticons + ${project.version} + runtime + GTalk.AdiumEmoticonset + zip + + + org.igniterealtime.spark + emoticons + ${project.version} + runtime + Default.adiumemoticonset + zip + + + org.minidns + minidns-core + 1.1.1 + + + org.jxmpp + jxmpp-core + 1.1.0 + + + org.jxmpp + jxmpp-jid + 1.1.0 + + + org.dom4j + dom4j + 2.1.4 + + + org.apache.httpcomponents.client5 + httpclient5 + 5.2.3 + + + org.apache.httpcomponents.core5 + httpcore5 + 5.2.4 + + + org.apache.commons + commons-lang3 + 3.20.0 + + + org.swinglabs.swingx + swingx-all + 1.6.5-1 + + + + net.java.dev.jna + jna-platform + 5.12.1 + + + net.java.dev.jna + jna + 5.12.1 + + + + com.thoughtworks.xstream + xstream + 1.4.21 + + + + com.install4j + install4j-runtime + 12.0.3 + + + + jaxen + jaxen + 1.2.0 + + + junit + junit + 4.13.2 + test + + + net.coobird + thumbnailator + 0.4.21 + + + org.bouncycastle + bcprov-jdk18on + ${bouncycastle.version} + + + org.bouncycastle + bcpkix-jdk18on + ${bouncycastle.version} + + + org.bouncycastle + bctls-jdk18on + ${bouncycastle.version} + + + com.formdev + flatlaf + 3.1.1 + jar + + + javax.xml.bind + jaxb-api + 2.3.1 + + + org.jasypt + jasypt + 1.9.3 + + + + + + owasp-check + + + + org.owasp + dependency-check-maven + 12.1.6 + + + + check + + + + + + + + false + + + + + diff --git a/core/src/assembly/installation-directory.xml b/core/src/assembly/installation-directory.xml new file mode 100644 index 000000000..6bebb5ea0 --- /dev/null +++ b/core/src/assembly/installation-directory.xml @@ -0,0 +1,67 @@ + + installation-directory + + tar + + false + + + lib + runtime + + org.igniterealtime.spark:emoticons + + + + xtra/emoticons + runtime + + org.igniterealtime.spark:emoticons + + ${artifact.classifier}.${artifact.extension} + + + + + + ${project.basedir}/src/dist/native/ + lib + + + + + src/main/resources/ + plugins + 0755 + + **/* + + + + + ${project.basedir}/src/dist/sounds/ + resources/sounds + + + + + + + + ${project.basedir}/src/dist/startup.bat + bin + 0755 + + + ${project.basedir}/src/dist/startup.sh + bin + 0755 + + + ${project.basedir}/src/dist/Info.plist + resources + + + diff --git a/src/resources/Info.plist b/core/src/dist/Info.plist similarity index 100% rename from src/resources/Info.plist rename to core/src/dist/Info.plist diff --git a/build/lib/dist/linux64/libcivil.so b/core/src/dist/native/linux64/libcivil.so similarity index 100% rename from build/lib/dist/linux64/libcivil.so rename to core/src/dist/native/linux64/libcivil.so diff --git a/build/lib/dist/linux64/libjnawtrenderer.so b/core/src/dist/native/linux64/libjnawtrenderer.so similarity index 100% rename from build/lib/dist/linux64/libjnawtrenderer.so rename to core/src/dist/native/linux64/libjnawtrenderer.so diff --git a/build/lib/dist/linux64/libjnffmpeg.so b/core/src/dist/native/linux64/libjnffmpeg.so similarity index 100% rename from build/lib/dist/linux64/libjnffmpeg.so rename to core/src/dist/native/linux64/libjnffmpeg.so diff --git a/build/lib/dist/linux64/libjng722.so b/core/src/dist/native/linux64/libjng722.so similarity index 100% rename from build/lib/dist/linux64/libjng722.so rename to core/src/dist/native/linux64/libjng722.so diff --git a/build/lib/dist/linux64/libjnopus.so b/core/src/dist/native/linux64/libjnopus.so similarity index 100% rename from build/lib/dist/linux64/libjnopus.so rename to core/src/dist/native/linux64/libjnopus.so diff --git a/build/lib/dist/linux64/libjnportaudio.so b/core/src/dist/native/linux64/libjnportaudio.so similarity index 100% rename from build/lib/dist/linux64/libjnportaudio.so rename to core/src/dist/native/linux64/libjnportaudio.so diff --git a/build/lib/dist/linux64/libjnpulseaudio.so b/core/src/dist/native/linux64/libjnpulseaudio.so similarity index 100% rename from build/lib/dist/linux64/libjnpulseaudio.so rename to core/src/dist/native/linux64/libjnpulseaudio.so diff --git a/build/lib/dist/linux64/libjnscreencapture.so b/core/src/dist/native/linux64/libjnscreencapture.so similarity index 100% rename from build/lib/dist/linux64/libjnscreencapture.so rename to core/src/dist/native/linux64/libjnscreencapture.so diff --git a/build/lib/dist/linux64/libjnspeex.so b/core/src/dist/native/linux64/libjnspeex.so similarity index 100% rename from build/lib/dist/linux64/libjnspeex.so rename to core/src/dist/native/linux64/libjnspeex.so diff --git a/build/lib/dist/linux64/libjnvideo4linux2.so b/core/src/dist/native/linux64/libjnvideo4linux2.so similarity index 100% rename from build/lib/dist/linux64/libjnvideo4linux2.so rename to core/src/dist/native/linux64/libjnvideo4linux2.so diff --git a/build/lib/dist/linux64/libjnvpx.so b/core/src/dist/native/linux64/libjnvpx.so similarity index 100% rename from build/lib/dist/linux64/libjnvpx.so rename to core/src/dist/native/linux64/libjnvpx.so diff --git a/build/lib/dist/linux64/libodbc.so b/core/src/dist/native/linux64/libodbc.so similarity index 100% rename from build/lib/dist/linux64/libodbc.so rename to core/src/dist/native/linux64/libodbc.so diff --git a/build/lib/dist/linux64/libodbcinst.so b/core/src/dist/native/linux64/libodbcinst.so similarity index 100% rename from build/lib/dist/linux64/libodbcinst.so rename to core/src/dist/native/linux64/libodbcinst.so diff --git a/build/lib/dist/mac/libSystemUtilities.jnilib b/core/src/dist/native/mac/libSystemUtilities.jnilib similarity index 100% rename from build/lib/dist/mac/libSystemUtilities.jnilib rename to core/src/dist/native/mac/libSystemUtilities.jnilib diff --git a/build/lib/dist/mac/libjnawtrenderer.jnilib b/core/src/dist/native/mac/libjnawtrenderer.jnilib similarity index 100% rename from build/lib/dist/mac/libjnawtrenderer.jnilib rename to core/src/dist/native/mac/libjnawtrenderer.jnilib diff --git a/build/lib/dist/mac/libjnffmpeg.jnilib b/core/src/dist/native/mac/libjnffmpeg.jnilib similarity index 100% rename from build/lib/dist/mac/libjnffmpeg.jnilib rename to core/src/dist/native/mac/libjnffmpeg.jnilib diff --git a/build/lib/dist/mac/libjng722.jnilib b/core/src/dist/native/mac/libjng722.jnilib similarity index 100% rename from build/lib/dist/mac/libjng722.jnilib rename to core/src/dist/native/mac/libjng722.jnilib diff --git a/build/lib/dist/mac/libjnmaccoreaudio.jnilib b/core/src/dist/native/mac/libjnmaccoreaudio.jnilib similarity index 100% rename from build/lib/dist/mac/libjnmaccoreaudio.jnilib rename to core/src/dist/native/mac/libjnmaccoreaudio.jnilib diff --git a/build/lib/dist/mac/libjnopus.jnilib b/core/src/dist/native/mac/libjnopus.jnilib similarity index 100% rename from build/lib/dist/mac/libjnopus.jnilib rename to core/src/dist/native/mac/libjnopus.jnilib diff --git a/build/lib/dist/mac/libjnportaudio.jnilib b/core/src/dist/native/mac/libjnportaudio.jnilib similarity index 100% rename from build/lib/dist/mac/libjnportaudio.jnilib rename to core/src/dist/native/mac/libjnportaudio.jnilib diff --git a/build/lib/dist/mac/libjnquicktime.jnilib b/core/src/dist/native/mac/libjnquicktime.jnilib similarity index 100% rename from build/lib/dist/mac/libjnquicktime.jnilib rename to core/src/dist/native/mac/libjnquicktime.jnilib diff --git a/build/lib/dist/mac/libjnscreencapture.jnilib b/core/src/dist/native/mac/libjnscreencapture.jnilib similarity index 100% rename from build/lib/dist/mac/libjnscreencapture.jnilib rename to core/src/dist/native/mac/libjnscreencapture.jnilib diff --git a/build/lib/dist/mac/libjnspeex.jnilib b/core/src/dist/native/mac/libjnspeex.jnilib similarity index 100% rename from build/lib/dist/mac/libjnspeex.jnilib rename to core/src/dist/native/mac/libjnspeex.jnilib diff --git a/build/lib/dist/mac/libjnvpx.jnilib b/core/src/dist/native/mac/libjnvpx.jnilib similarity index 100% rename from build/lib/dist/mac/libjnvpx.jnilib rename to core/src/dist/native/mac/libjnvpx.jnilib diff --git a/build/lib/dist/windows64/civil.dll b/core/src/dist/native/windows64/civil.dll similarity index 100% rename from build/lib/dist/windows64/civil.dll rename to core/src/dist/native/windows64/civil.dll diff --git a/build/lib/dist/windows64/jnawtrenderer.dll b/core/src/dist/native/windows64/jnawtrenderer.dll similarity index 100% rename from build/lib/dist/windows64/jnawtrenderer.dll rename to core/src/dist/native/windows64/jnawtrenderer.dll diff --git a/build/lib/dist/windows64/jndirectshow.dll b/core/src/dist/native/windows64/jndirectshow.dll similarity index 100% rename from build/lib/dist/windows64/jndirectshow.dll rename to core/src/dist/native/windows64/jndirectshow.dll diff --git a/build/lib/dist/windows64/jnffmpeg.dll b/core/src/dist/native/windows64/jnffmpeg.dll similarity index 100% rename from build/lib/dist/windows64/jnffmpeg.dll rename to core/src/dist/native/windows64/jnffmpeg.dll diff --git a/build/lib/dist/windows64/jng722.dll b/core/src/dist/native/windows64/jng722.dll similarity index 100% rename from build/lib/dist/windows64/jng722.dll rename to core/src/dist/native/windows64/jng722.dll diff --git a/build/lib/dist/windows64/jnopus.dll b/core/src/dist/native/windows64/jnopus.dll similarity index 100% rename from build/lib/dist/windows64/jnopus.dll rename to core/src/dist/native/windows64/jnopus.dll diff --git a/build/lib/dist/windows64/jnportaudio.dll b/core/src/dist/native/windows64/jnportaudio.dll similarity index 100% rename from build/lib/dist/windows64/jnportaudio.dll rename to core/src/dist/native/windows64/jnportaudio.dll diff --git a/build/lib/dist/windows64/jnscreencapture.dll b/core/src/dist/native/windows64/jnscreencapture.dll similarity index 100% rename from build/lib/dist/windows64/jnscreencapture.dll rename to core/src/dist/native/windows64/jnscreencapture.dll diff --git a/build/lib/dist/windows64/jnspeex.dll b/core/src/dist/native/windows64/jnspeex.dll similarity index 100% rename from build/lib/dist/windows64/jnspeex.dll rename to core/src/dist/native/windows64/jnspeex.dll diff --git a/build/lib/dist/windows64/jnvpx.dll b/core/src/dist/native/windows64/jnvpx.dll similarity index 100% rename from build/lib/dist/windows64/jnvpx.dll rename to core/src/dist/native/windows64/jnvpx.dll diff --git a/build/lib/dist/windows64/jnwasapi.dll b/core/src/dist/native/windows64/jnwasapi.dll similarity index 100% rename from build/lib/dist/windows64/jnwasapi.dll rename to core/src/dist/native/windows64/jnwasapi.dll diff --git a/build/lib/dist/windows64/jnwincoreaudio.dll b/core/src/dist/native/windows64/jnwincoreaudio.dll similarity index 100% rename from build/lib/dist/windows64/jnwincoreaudio.dll rename to core/src/dist/native/windows64/jnwincoreaudio.dll diff --git a/core/src/dist/sounds/bell.wav b/core/src/dist/sounds/bell.wav new file mode 100644 index 000000000..d60c75ea5 Binary files /dev/null and b/core/src/dist/sounds/bell.wav differ diff --git a/src/resources/sounds/chat_request.wav b/core/src/dist/sounds/chat_request.wav similarity index 100% rename from src/resources/sounds/chat_request.wav rename to core/src/dist/sounds/chat_request.wav diff --git a/core/src/dist/sounds/incoming.wav b/core/src/dist/sounds/incoming.wav new file mode 100644 index 000000000..a6eebecb7 Binary files /dev/null and b/core/src/dist/sounds/incoming.wav differ diff --git a/core/src/dist/sounds/outgoing.wav b/core/src/dist/sounds/outgoing.wav new file mode 100644 index 000000000..3c8bf5a6a Binary files /dev/null and b/core/src/dist/sounds/outgoing.wav differ diff --git a/src/resources/sounds/presence_changed.wav b/core/src/dist/sounds/presence_changed.wav similarity index 100% rename from src/resources/sounds/presence_changed.wav rename to core/src/dist/sounds/presence_changed.wav diff --git a/core/src/dist/startup.bat b/core/src/dist/startup.bat new file mode 100644 index 000000000..ebf7b7ddb --- /dev/null +++ b/core/src/dist/startup.bat @@ -0,0 +1,21 @@ +if %PROCESSOR_ARCHITECTURE%==x86 ( + rem 32 bit +) else ( + set SPARK64=64 +) + + +:run +if "%1" == "-debug" goto debug +if "%1" == "-noconsole" goto noconsole +java -Dappdir=.. -cp ../lib/*;../resources;../lib/windows%SPARK64%; -Djava.library.path="../lib/windows%SPARK64%/" org.jivesoftware.launcher.Startup +goto end + +:noconsole +javaw -Dappdir=.. -cp ../lib/*;../resources;../lib/windows%SPARK64%; -Djava.library.path="../lib/windows%SPARK64%/" org.jivesoftware.launcher.Startup +goto end + +:debug +start "Spark" "%JAVA_HOME%\bin\java" -Ddebugger=true -Ddebug.mode=true -XX:+HeapDumpOnOutOfMemoryError -Xint -server -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 -Dappdir=.. -cp ../lib/*;../resources;../lib/windows%SPARK64%/; org.jivesoftware.launcher.Startup +goto end +:end diff --git a/core/src/dist/startup.sh b/core/src/dist/startup.sh new file mode 100644 index 000000000..7815ad11d --- /dev/null +++ b/core/src/dist/startup.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +scriptdir="`dirname ${0}`"; +cd "${scriptdir}/.."; +wd="`pwd`"; +libdir="${wd}/lib"; + +classpath="${libdir}/*:${wd}/resources"; + +# add java library path folder depending on architecture +case "`uname -m`" in + "x86_64") + javalibrarypath="-Djava.library.path=${libdir}/linux64"; + ;; + + "*") + javalibrarypath="-Djava.library.path=${libdir}/linux"; + ;; +esac; + +echo "using classpath: ${classpath}"; + +mainclass="org.jivesoftware.launcher.Startup"; + +if [ "${1}" = "-debug" ]; then + java -Ddebugger=true \ + -Ddebug.mode=true \ + -XX:+HeapDumpOnOutOfMemoryError \ + -Xint \ + -server \ + -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 \ + -Dappdir=${wd} \ + ${javalibrarypath} \ + -cp ${classpath} \ + ${mainclass} + +else + + java \ + -Dappdir=${wd} \ + ${javalibrarypath} \ + -cp ${classpath} \ + ${mainclass} + +fi; + diff --git a/documentation/LICENSE.html b/core/src/documentation/LICENSE.html similarity index 92% rename from documentation/LICENSE.html rename to core/src/documentation/LICENSE.html index 89078deb1..afd900f4c 100644 --- a/documentation/LICENSE.html +++ b/core/src/documentation/LICENSE.html @@ -183,18 +183,18 @@

Spark License


Version 2.0, January 2004

-http://www.apache.org/licenses/

+http://www.apache.org/licenses/

-

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

+

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

-

1. Definitions.

+

1. Definitions.

"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this -document.

+document.

"Licensor" shall mean the copyright owner or entity authorized by -the copyright owner that is granting the License.

+the copyright owner that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control @@ -202,24 +202,24 @@

Spark License

means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership -of such entity.

+of such entity.

"You" (or "Your") shall mean an individual or Legal -Entity exercising permissions granted by this License.

+Entity exercising permissions granted by this License.

"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation -source, and configuration files.

+source, and configuration files.

"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media -types.

+types.

"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in -the Appendix below).

+the Appendix below).

"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the @@ -227,7 +227,7 @@

Spark License

represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative -Works thereof.

+Works thereof.

"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or @@ -240,18 +240,18 @@

Spark License

control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in -writing by the copyright owner as "Not a Contribution."

+writing by the copyright owner as "Not a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and -subsequently incorporated within the Work.

+subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and -such Derivative Works in Source or Object form.

+such Derivative Works in Source or Object form.

3. Grant of Patent LicenseSpark License counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for -that Work shall terminate as of the date such litigation is filed.

+that Work shall terminate as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the -following conditions:

+following conditions:

1.      You must give any other recipients of the Work or Derivative Works a copy of this -License; and

+License; and

2.      You must cause any modified files to carry prominent notices stating that You -changed the files; and

+changed the files; and

4.Spark License provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work -otherwise complies with the conditions stated in this License.

+otherwise complies with the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted @@ -327,13 +327,13 @@

Spark License

of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such -Contributions.

+Contributions.

6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE -file.

+file.

7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work @@ -343,7 +343,7 @@

Spark License

NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of -permissions under this License.

+permissions under this License.

8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), @@ -354,7 +354,7 @@

Spark License

or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor -has been advised of the possibility of such damages.

+has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to @@ -364,17 +364,18 @@

Spark License

on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason -of your accepting any such warranty or additional liability.

+of your accepting any such warranty or additional liability.

-

END OF TERMS AND CONDITIONS

+

END OF TERMS AND CONDITIONS

-

 

+

 

+ diff --git a/core/src/documentation/README.html b/core/src/documentation/README.html new file mode 100644 index 000000000..5c1b17990 --- /dev/null +++ b/core/src/documentation/README.html @@ -0,0 +1,251 @@ + + + +Spark Readme + + + + +
+ + + + +
+ Spark is a feature rich instant messaging (IM) and group chat client that uses the XMPP protocol.
+Further information can be found on the Spark website. + + + +

Changelog

+View the changelog for a list of changes since the last release. + +

Support

+Free support is provided by the Spark community in the forums. + + +

Developer Documentation

+ + + +

License Agreements

+The Spark source code is governed by the Apache-License 2, which can be found in the LICENSE.html file in this distribution.
+Spark also contains Open Source software from third-parties.
+Licensing terms for those components is specifically noted in the relevant source files.

+ +New default emoticons provided by Twemoji (graphics licensed under CC-BY 4.0: https://creativecommons.org/licenses/by/4.0/)

+ +Spark contains icons which are free for non-commercial use, +are licensed from INCORS GmbH or owned by Jive Software.
+All icons and images in Spark owned by INCORS GmbH or Jive Software are provided under the following license agreement:
+ +
 
+License Agreement
+ 
+This is a legal agreement between You, the User of the Spark application
+("The Software"), and Jive Software ("Jive Software"). By downloading the Software,
+you agree to be bound by the terms of this agreement.
+ 
+All ownership and copyright of the images and icons included in the Software
+distribution remain the property of Jive Software and INCORS GmbH. Jive Software
+grants to you a nonexclusive, non-sublicensable right to use the icons royalty-free
+as part of Spark.
+ 
+You may not lease, license or sub-license the icons, or a subset of the icons,
+or any modified icons to any third party. You may not incorporate them into your
+own software or design products.
+ 
+All icon files are provided "As is" without warranties of merchantability and
+fitness for a particular purpose. You agree to hold Jive Software harmless for
+any result that may occur during the course of using the licensed icons.
+ 
+This License Agreement shall be governed and construed in accordance with the
+laws of Oregon. If any provision of this License Agreement is held to be
+unenforceable, this License Agreement will remain in effect with the provision
+omitted.      
+ +
+
+ + diff --git a/core/src/documentation/changelog.html b/core/src/documentation/changelog.html new file mode 100644 index 000000000..04688c054 --- /dev/null +++ b/core/src/documentation/changelog.html @@ -0,0 +1,4054 @@ + + + + +Spark Changelog + + + + +
+ + + + +
+ +

3.0.2 -- March 31, 2023

+

Bug

+
    +
  • [SPARK-1815] - Roar custom popup can't be closed after closing the chat window
  • +
  • [SPARK-2163] - TicTacToe throws exception for username with a space
  • +
  • [SPARK-2318] - Roar ignores Popup display settings
  • +
  • [SPARK-2320] - Save password from Preferences menu
  • +
  • [SPARK-2327] - Chat window freezes when opponent is typing to you
  • +
+ +

Task

+
    +
  • [SPARK-2319] - Update Roar Plugin to 1.0 version
  • +
+ +

Improvement

+
    +
  • [SPARK-1782] - Roar popups shouldn't be shown when a tab is in focus
  • +
  • [SPARK-2321] - Don't show empty broadcast message
  • +
  • [SPARK-2322] - Raise the minimum requirements for plugins
  • +
  • [SPARK-2324] - Upgrade XStream to v1.4.20 or later
  • +
  • [SPARK-2326] - Update HTTP Client library
  • +
+ +

New Feature

+
    +
  • [SPARK-1457] - Update Translator plugin to use other translation API
  • +
+ +

3.0.1 -- December 12, 2022

+

Bug

+
    +
  • [SPARK-2310] - macOS doesn't use Look and Feel FlatLaf
  • +
  • [SPARK-2313] - History not saved in some cases
  • +
  • [SPARK-2316] - Unable to open MUC while MUC private chat is open
  • +
  • [SPARK-2317] - HTTP File Upload Plugin button not showing in private chat
  • +
+ +

Task

+ + +

Improvement

+ + +

3.0.0 -- November 14, 2022

+

Improvement

+
    +
  • [SPARK-1708] - Update or change spellchecker library
  • +
  • [SPARK-2016] - Add support for 64-bit Java
  • +
  • [SPARK-2063] - Make font size in Conversation History window configurable
  • +
  • [SPARK-2076] - Contact list font size setting should be applied to groups names
  • +
  • [SPARK-2077] - List of available logins should be scrollable
  • +
  • [SPARK-2098] - Show "Reconnect now" button while reconnect countdown is running
  • +
  • [SPARK-2120] - Add an option to increase font size in message compose area
  • +
  • [SPARK-2121] - Bring up roster window when shortcut is opened
  • +
  • [SPARK-2125] - Bookmarks should be sorted alphabetically
  • +
  • [SPARK-2128] - Remove translations encoding workaround for Java 8
  • +
  • [SPARK-2204] - Code cleanup
  • +
  • [SPARK-2208] - Use Name instead of Username when initiating chat from search results
  • +
  • [SPARK-2210] - Replace deprecated Base64 Decoder
  • +
  • [SPARK-2212] - Update Smack to 4.4
  • +
  • [SPARK-2214] - Look and feel refresh
  • +
  • [SPARK-2217] - Update Russian translation
  • +
  • [SPARK-2221] - Increase default Idle value to 5 instead of 3 minutes
  • +
  • [SPARK-2233] - Allow to search contacts without special letters interfering
  • +
  • [SPARK-2236] - Create status icons for the new Spark design
  • +
  • [SPARK-2238] - Fix potential NPE in FastPath invitation handler
  • +
  • [SPARK-2249] - Add translation for hours, min to Awaytime
  • +
  • [SPARK-2257] - Explicitly define calls on or off the Event Dispatch Thread
  • +
  • [SPARK-2264] - Use nickname in bookmark if set
  • +
  • [SPARK-2267] - Update XStream to 1.4.19 or later
  • +
  • [SPARK-2272] - Remove URL hack
  • +
  • [SPARK-2275] - Replace deprecated custom ulit class Base64
  • +
  • [SPARK-2276] - Create x64 installer for Spark
  • +
  • [SPARK-2278] - Spark should remove plugins in profile if they don't exist in installation folder
  • +
  • [SPARK-2280] - Add clear button for Login text fields and eye button to show password
  • +
  • [SPARK-2282] - Add "Other Users" button for Login text field
  • +
  • [SPARK-2291] - Fix Zip Slip Vulnerability
  • +
  • [SPARK-2292] - Improve the log window
  • +
  • [SPARK-2296] - Add localizations in install4j installer
  • +
  • [SPARK-2297] - Add Windows on ARM installer
  • +
  • [SPARK-2298] - Update install4j runtime to 10.0.3
  • +
  • [SPARK-2299] - MacOS replace deprecated installer
  • +
  • [SPARK-2301] - Update HTTP File Upload Plugin to 0.4 version
  • +
  • [SPARK-2304] - Add day and week periods for Transcript History
  • +
+ +

Task

+ + +

New Feature

+
    +
  • [SPARK-1585] - Add support for XEP-0280 Message Carbons
  • +
  • [SPARK-1598] - Add an option to ask for confirmation when closing conversation window with multiple chats
  • +
  • [SPARK-1795] - Provide MSI installer for Windows
  • +
  • [SPARK-1828] - Bundle Pade Meetings plugin
  • +
  • [SPARK-2116] - Add an option to set how many previous messages should be shown in a chat window
  • +
  • [SPARK-2144] - Add a button to restart Spark if network error happens
  • +
  • [SPARK-2256] - Add control over Idle settings
  • +
  • [SPARK-2277] - Add control over IBB file transfer via ClientControl
  • +
+ +

Bug

+
    +
  • [SPARK-1908] - Offline message is not added to the history until chat window is closed
  • +
  • [SPARK-1918] - Emoticons packs are not updated after the upgrade
  • +
  • [SPARK-1992] - Fix the View logs menu
  • +
  • [SPARK-2073] - Domain field is editable during Auto login when it is disabled in default.properties
  • +
  • [SPARK-2115] - Show warning when password change failed
  • +
  • [SPARK-2160] - Translations are garbled when using newer Java
  • +
  • [SPARK-2161] - Spark locks up when downloading Pade Meetings libraries
  • +
  • [SPARK-2164] - Message shown in a wrong tab when multiple resources are logged in
  • +
  • [SPARK-2182] - Switches to using hostname as resource after a re-login
  • +
  • [SPARK-2195] - Login window distorted by long domain name
  • +
  • [SPARK-2203] - Downloads fail when username has non-latin characters
  • +
  • [SPARK-2207] - Display the correct name for the transferred file
  • +
  • [SPARK-2209] - File transfer using IBB fails after a reconnection
  • +
  • [SPARK-2211] - Empty lines are removed in a message
  • +
  • [SPARK-2213] - Failing to invite contact to a room
  • +
  • [SPARK-2218] - MOTD broadcast message is not displayed on startup
  • +
  • [SPARK-2222] - Number of unread messages not being shown in the first tab title
  • +
  • [SPARK-2223] - Loads MUC history into private MUC chat
  • +
  • [SPARK-2227] - Vcard popup not showing when contact window is maximized
  • +
  • [SPARK-2228] - When chat window is maximized emoticons selection window goes beyond taskbar
  • +
  • [SPARK-2232] - Can't log in with debugger enabled
  • +
  • [SPARK-2234] - Spark often 'freezes' when a new chat window is opened
  • +
  • [SPARK-2237] - Revive the 'spell checker' plugin \(using Jitsi-provided dependencies\)
  • +
  • [SPARK-2241] - Exception related to XStream
  • +
  • [SPARK-2243] - After upgrading Smack SSO authorization \(GSSAPI\) is broked.
  • +
  • [SPARK-2246] - After upgrading Smack Search checkbox boolean is disabled
  • +
  • [SPARK-2250] - Incorrect display of the name if the contact is not in the list of users.
  • +
  • [SPARK-2251] - Fix NullPointerException in SettingManager for Windows
  • +
  • [SPARK-2252] - Spark cannot find download folder due to non-English language in Linux
  • +
  • [SPARK-2253] - Pade Meetings create incorrect path for Windows
  • +
  • [SPARK-2259] - XStream ForbiddenClassException in CustomStatusItem Class
  • +
  • [SPARK-2263] - Bookmarks sometimes seem to have no name
  • +
  • [SPARK-2265] - Sorting MUC rooms by occupants should use numeric sorting
  • +
  • [SPARK-2266] - Always accepts self-signed certificates
  • +
  • [SPARK-2269] - Incorrect handling of carbons
  • +
  • [SPARK-2270] - Unable to login with Java 16 or higher
  • +
  • [SPARK-2273] - Login with the "Enter" button to the account does not work
  • +
  • [SPARK-2274] - Login with option "Auto login" to the account does not work
  • +
  • [SPARK-2281] - After upgrading Smack "View client version" menu doesn't work
  • +
  • [SPARK-2283] - Configure room button not working after Smack update
  • +
  • [SPARK-2285] - User can open chat with dummy@dummy.example
  • +
  • [SPARK-2288] - The BroadcastPane becomes very wide when a long message is received
  • +
  • [SPARK-2289] - The name sender of the broadcast message in the chat in small letters
  • +
  • [SPARK-2294] - UI freezes when accepting a room invite
  • +
  • [SPARK-2295] - Unable to create an account through Spark
  • +
+ +

2.9.4 -- November 14, 2020

+

Bug +

+
    +
  • [SPARK-2184] - Spark should not reject end-entity certificates without basic constraints +
  • +
  • [SPARK-2185] - The CertPath that's verified should not be allowed to be empty +
  • +
  • [SPARK-2186] - Certificate validation should target the end-entity certificate, not the CA +
  • +
  • [SPARK-2187] - Spark should not offer to add CA certs that it already has in the truststore +
  • +
  • [SPARK-2188] - Some certificate chain validations fail with 'Certificate does not specify OCSP responder' +
  • +
  • [SPARK-2192] - File transfer duration sometimes incorrect +
  • +
  • [SPARK-2194] - The option to ignore certificate expiry not working +
  • +
  • [SPARK-2196] - Start a conference menu option not working +
  • +
  • [SPARK-2201] - Not all passwords removed when 'save password' is unchecked +
  • +
+ +

New Feature +

+
    +
  • [SPARK-2190] - Add option to auto-accept file transfers +
  • +
+ +

Improvement +

+
    +
  • [SPARK-1160] - Replace deprecated methods +
  • +
  • [SPARK-1469] - Code Cleanup +
  • +
  • [SPARK-2005] - Add option to disable selected plugins via Client Control +
  • +
  • [SPARK-2198] - Prevent incoming file transfer to overwrite existing file +
  • +
  • [SPARK-2199] - Show directory if file can't be opened +
  • +
  • [SPARK-2202] - Have explicit option to remove all saved passwords +
  • +
+ +

Task +

+ + + +

2.9.3 -- October 24, 2020

+

Bug +

+
    +
  • [SPARK-2064] - Should reconnect to rooms after a reconnect to server +
  • +
  • [SPARK-2143] - Contacts marked in red and duplicated during a reconnect +
  • +
  • [SPARK-2153] - Private messaging not working in group chat +
  • +
  • [SPARK-2162] - History issues for contacts with spaces in usernames +
  • +
  • [SPARK-2167] - Hostname field shouln't be editable after a failed auto-login attempt when disabled +
  • +
  • [SPARK-2174] - Old presence shown in the opened chat window after a reconnect +
  • +
  • [SPARK-2177] - Incorrect own presence state during and after a reconnection +
  • +
  • [SPARK-2179] - System message about incoming buzz is incorrectly escaping spaces +
  • +
+ +

Task +

+ + +

Improvement +

+
    +
  • [SPARK-2165] - Clean up grammar and typos in translation variables +
  • +
  • [SPARK-2168] - Make Spark save file transfer events to history +
  • +
  • [SPARK-2169] - Network addresses enclosed in quotes should be presented correctly +
  • +
  • [SPARK-2172] - Shouldn't switch to new tab when first MUC private message arrives +
  • +
+ +

2.9.2 -- August 30, 2020

+

Bug +

+
    +
  • [SPARK-2154] - Offline messages not being shown +
  • +
  • [SPARK-2156] - Incorrect comparison of server address +
  • +
  • [SPARK-2157] - Incorrect comparison of agent JID +
  • +
  • [SPARK-2158] - Incorrect comparison of version identifier in plugin dependency parsing +
  • +
  • [SPARK-2159] - Incorrect comparison of group chat particpant JIDs +
  • +
+ +

Improvement +

+
    +
  • [SPARK-2155] - Don't hide runtime exceptions while processing incoming stanzas. +
  • +
+ + +

2.9.1 -- August 25, 2020

+

Bug +

+
    +
  • [SPARK-2139] - Reversi: IndexOutOfBoundError and user can make consecutive moves +
  • +
  • [SPARK-2148] - History chat transcript displays own JID instead of nickname +
  • +
  • [SPARK-2149] - User is Online/Offline toast popups not working properly +
  • +
+ + +

2.9.0 -- August 17, 2020

+ +

Bug +

+
    +
  • [SPARK-1537] - Add Contact dialog requires at least 5 letters to find a contact +
  • +
  • [SPARK-1635] - History viewer adds spaces between messages when changing a view +
  • +
  • [SPARK-1649] - Shouldn't show a toast popup for a last message in history when joining a room +
  • +
  • [SPARK-1757] - Messages in MUC history are out of order +
  • +
  • [SPARK-1806] - PrivacyManager throws an exception +
  • +
  • [SPARK-1809] - Privacy plugin doesn't work +
  • +
  • [SPARK-1811] - View client version menu option doesn't show information +
  • +
  • [SPARK-1812] - Some vCard fields are empty when checking contact's profile +
  • +
  • [SPARK-1817] - Reversi and tic tac toe plugins failed to build +
  • +
  • [SPARK-1873] - Search doesn't work with AD integration +
  • +
  • [SPARK-1888] - Plugins not being extracted completely +
  • +
  • [SPARK-1895] - Errors are not (always) shown in one-on-one chat. +
  • +
  • [SPARK-1902] - Throws an exception when using custom emoticons set +
  • +
  • [SPARK-1905] - Contact list tooltip causes temporary freeze +
  • +
  • [SPARK-1916] - Not able to move or copy contacts when Rename contact is disabled +
  • +
  • [SPARK-2009] - Should allow profile changes when Avatar tab is disabled +
  • +
  • [SPARK-2025] - Process Data Forms with Bool fields that have no value. +
  • +
  • [SPARK-2028] - Fix logic error in UserSearchResult +
  • +
  • [SPARK-2029] - Shouldn't check for voice status +
  • +
  • [SPARK-2114] - Spark does not parse Java version string correctly. +
  • +
  • [SPARK-2134] - ROAR plugin should not depend on com.sun package +
  • +
  • [SPARK-2141] - Contact list does not show users that are not in a group +
  • +
+ +

New Feature +

+
    +
  • [SPARK-1203] - Add a GUI for managing TLS\SSL certificates +
  • +
  • [SPARK-1589] - Add option to disable invisible login and status via default.properties +
  • +
  • [SPARK-1877] - Make reconnection delay between attempts configurable +
  • +
  • [SPARK-1946] - Add option to disable Start a chat via Client Control +
  • +
  • [SPARK-1968] - Replace DummyTrustManager with complex trust manager +
  • +
  • [SPARK-2001] - Add a popup for accepting certificate from a connection +
  • +
  • [SPARK-2015] - Add an option to force IBB for file transfers +
  • +
  • [SPARK-2030] - Add support for Message Styling +
  • +
  • [SPARK-2040] - Add Http File Upload plugin +
  • +
  • [SPARK-2041] - Add initial documentation +
  • +
  • [SPARK-2086] - Hostname and Version as resource available in Client Control plugin +
  • +
+ +

Task +

+
    +
  • [SPARK-1865] - Update bundled JRE with the latest version +
  • +
  • [SPARK-1950] - Remove & from Plugins menu translations +
  • +
  • [SPARK-2132] - Replace JxBrowser with anything else +
  • +
+ +

Improvement +

+
    +
  • [SPARK-905] - Add date stamp for current messages +
  • +
  • [SPARK-939] - Stretch and move Find dialog +
  • +
  • [SPARK-945] - Preferences, broadcast, profile windows should be saving their sizes and positions +
  • +
  • [SPARK-1519] - Spark should show a time stamp for every MUC message/activity +
  • +
  • [SPARK-1688] - Update JTattoo to the latest version +
  • +
  • [SPARK-1784] - ROAR should show MUC popups when window is not in focus +
  • +
  • [SPARK-1791] - Migrate Spark build from Ant to Maven +
  • +
  • [SPARK-1843] - Update Smack to 4.3 branch +
  • +
  • [SPARK-1868] - Add an option to disable Invisible presence +
  • +
  • [SPARK-1871] - Fix output of nicknames in Broadcast History +
  • +
  • [SPARK-1872] - Should resize large photo when applying as an avatar +
  • +
  • [SPARK-1875] - Spark history search should show context +
  • +
  • [SPARK-1876] - Spark history window should wrap text +
  • +
  • [SPARK-1883] - Spark should remove/overwrite old versions of libs during update +
  • +
  • [SPARK-1887] - Shouldn't show a toast popup for your own message in MUC +
  • +
  • [SPARK-1899] - Room password dialog should mask/hide the actual password +
  • +
  • [SPARK-1903] - Highlight searched keyword in the history search +
  • +
  • [SPARK-1904] - Various improvements to avatar management +
  • +
  • [SPARK-1909] - Transcript Window should be recomposable +
  • +
  • [SPARK-1910] - Replace (some) emojis with emoticons +
  • +
  • [SPARK-1912] - Remove green username colors from chat room +
  • +
  • [SPARK-1915] - Implement separate History settings in Client Control +
  • +
  • [SPARK-1947] - Improve rooms browser, dialogs and error messages +
  • +
  • [SPARK-1948] - Add an EditorConfig file +
  • +
  • [SPARK-1961] - Improve startup by disabling CPU-hungry themes +
  • +
  • [SPARK-1962] - Use a key-based lookup to find an emoticon +
  • +
  • [SPARK-1963] - Lazy load vcard data +
  • +
  • [SPARK-1964] - Non-UI processing should not occur on Event Queue dispatch thread +
  • +
  • [SPARK-1965] - Use unarchived emoticons packages in version control +
  • +
  • [SPARK-1972] - Security settings should go in dedicated tab +
  • +
  • [SPARK-1973] - Add visual hint for "not encrypted" connections +
  • +
  • [SPARK-1974] - Updated Lithuanian translation +
  • +
  • [SPARK-1976] - More descriptive error messages when login fails. +
  • +
  • [SPARK-1983] - Update Polish translation +
  • +
  • [SPARK-1984] - Update LittleLuck skin to 2.0.1 +
  • +
  • [SPARK-1985] - Add support for TLS Mutual Authentication +
  • +
  • [SPARK-1990] - Remove PKI tab +
  • +
  • [SPARK-1998] - Add French spelling dictionary +
  • +
  • [SPARK-2014] - Rename 5223 port description +
  • +
  • [SPARK-2019] - Add (requires restart) to single click in system tray option +
  • +
  • [SPARK-2024] - Update Ukranian translation +
  • +
  • [SPARK-2039] - Don't require i18n source files to be encoded +
  • +
  • [SPARK-2047] - Improve on version detection +
  • +
  • [SPARK-2052] - Updated Brazilian Portuguese translation +
  • +
  • [SPARK-2062] - Fix legacy links to community.igniterealtime.org +
  • +
  • [SPARK-2081] - Client Control: Save Password & Auto Login option should also hide in Preferences +
  • +
  • [SPARK-2089] - Schedule loadContactList() outside of sharedGroupLoader +
  • +
  • [SPARK-2090] - Replace deprecated Smack APIs +
  • +
  • [SPARK-2101] - Transfer Guard settings should be in Spark profile +
  • +
  • [SPARK-2111] - Add working with Spark source in VS Code guide +
  • +
  • [SPARK-2130] - Fix French translation +
  • +
  • [SPARK-2133] - Allow translations to be found when running from IDE +
  • +
  • [SPARK-2135] - ROAR setting changes should not require a restart +
  • +
  • [SPARK-2136] - ROAR should not offer 'system notification' if unsupported by OS +
  • +
  • [SPARK-2137] - Plugins should be runnable from IDE +
  • +
  • [SPARK-2146] - Update Bouncy Castle library to 1.66 +
  • +
  • [SPARK-2147] - Guard against CVE-2020-10683 (dom4j reading external entities) +
  • +
+ + +

2.8.3 -- January 29, 2017

+

Bug +

+
    +
  • [SPARK-1844] - Not saving settings without opening Advanced menu once +
  • +
  • [SPARK-1848] - Setting "Chat Window Always on Top" also enables "Main Window Always on Top" behavior +
  • +
  • [SPARK-1853] - NPE when not setting an avatar +
  • +
  • [SPARK-1854] - Joining a MUC with a duplicate nickname results in strange behavior. +
  • +
  • [SPARK-1855] - ContactList should not pop up when logging off +
  • +
  • [SPARK-1858] - Password not removed from spark.properties when "Save Password" option is disabled +
  • +
  • [SPARK-1863] - Resets initially empty values in Advanced menu when logging out +
  • +
+ +

New Feature +

+
    +
  • [SPARK-1825] - Add an option to see a history of broadcasts +
  • +
  • [SPARK-1852] - Add anonymous SASL login support +
  • +
+ +

Task +

+
    +
  • [SPARK-1821] - Update bundled JRE with the latest version +
  • +
  • [SPARK-1856] - Remove unused static analyzers +
  • +
  • [SPARK-1857] - Remove legacy CVS keywords +
  • +
  • [SPARK-1862] - Remove obsolete information from Readme and update links +
  • +
+ +

Improvement +

+
    +
  • [SPARK-1847] - Remove Log out menu when Auto Login and Save Password are disabled +
  • +
  • [SPARK-1849] - Make logs rotate based on size or time +
  • +
  • [SPARK-1850] - Shouldn't save password when SSO is being used +
  • +
  • [SPARK-1860] - Implement group chat duplicate name deconfliction similar to 2.7.7 +
  • +
  • [SPARK-1864] - Add translations to MUC dialogs +
  • +
  • [SPARK-1867] - Update German translation +
  • +
+ + +

2.8.2 -- November 25, 2016

+

Bug +

+
    +
  • [SPARK-1516] - Spark should not let open profile edit by clicking the avatar if profile changing is disabled +
  • +
  • [SPARK-1520] - Systray icon changes to online when one opens the chat window +
  • +
  • [SPARK-1593] - Spark shouldn't add Offline status when a user goes invisible +
  • +
  • [SPARK-1758] - Unfiled group appears when contact goes online +
  • +
  • [SPARK-1801] - Fix links opening in KDE environment (updated) +
  • +
  • [SPARK-1816] - Shouldn't freeze when using unsupported plugins +
  • +
  • [SPARK-1820] - Can't switch back to online presence after turning invisible on +
  • +
  • [SPARK-1827] - Shouldn't allow broadcast to selected users when it is disabled in Client Control +
  • +
+ +

New Feature +

+
    +
  • [SPARK-1802] - Add LittleLuck skin +
  • +
  • [SPARK-1835] - Modify Spark to work with new Openfire Client Control plugin settings +
  • +
+ +

Task +

+
    +
  • [SPARK-1732] - Update bundled JRE with the latest version +
  • +
  • [SPARK-1837] - Update Smack to the latest version (4.1.9) +
  • +
+ +

Improvement +

+
    +
  • [SPARK-1021] - Default to Name field as nickname when adding a contact +
  • +
  • [SPARK-1434] - Add Polish Spelling option +
  • +
  • [SPARK-1789] - Change Accept all certificates option to disabled by default +
  • +
  • [SPARK-1822] - Add additional default properties to control GUI settings +
  • +
  • [SPARK-1824] - Update Polish translation +
  • +
  • [SPARK-1831] - Update Italian translation +
  • +
+ + +

2.8.1 -- October 1, 2016

+

Bug +

+
    +
  • [SPARK-1786] - Wrong error message when a server is unavailable +
  • +
  • [SPARK-1799] - Fix url to Spark forums on the help menu +
  • +
  • [SPARK-1801] - Fix links opening in KDE environment +
  • +
  • [SPARK-1804] - Unsupported iteration removal function used. +
  • +
  • [SPARK-1808] - ContactList does not act on 'subscribed' event +
  • +
  • [SPARK-1812] - Some vCard fields are empty when checking contact's profile +
  • +
+ +

New Feature +

+
    +
  • [SPARK-1787] - Add option to disable TLS hostname verification +
  • +
+ +

Improvement +

+
    +
  • [SPARK-1788] - Update translations +
  • +
  • [SPARK-1790] - Rename Server field to Domain +
  • +
  • [SPARK-1798] - Exception thrown by listener should be handled +
  • +
  • [SPARK-1805] - PrivacyManager should log exceptions in log +
  • +
+ + +

2.8.0 -- August 25, 2016

+

Bug +

+
    +
  • [SPARK-1130] - Spark behaves wrong with chats with similar names +
  • +
  • [SPARK-1275] - Add contact dialog makes Spark lose connection +
  • +
  • [SPARK-1564] - Should set priority to 0 when Idle status turns on +
  • +
  • [SPARK-1613] - Long lines of text without spaces break the word wrap +
  • +
  • [SPARK-1736] - NPE in Roar plugin prevents messages to show up on fresh profiles +
  • +
  • [SPARK-1738] - RPM build fails after Smack 4 update +
  • +
  • [SPARK-1739] - Not trusting Openfire certificate after Smack 4 update +
  • +
  • [SPARK-1742] - Spark won't start when bookmark service is unavailable. +
  • +
  • [SPARK-1743] - MUC nickname sharing fails. +
  • +
  • [SPARK-1744] - Shouldnt send chat state notifications when the chat isn't active yet +
  • +
  • [SPARK-1745] - Fastpath plugin doesn't start after Smack 4 update +
  • +
  • [SPARK-1747] - Spark appears to fall back to a non-sasl when authenticating +
  • +
  • [SPARK-1749] - Not showing the context menu for participants in MUC +
  • +
  • [SPARK-1750] - Spark is not automatically reconnecting after Smack 4 update +
  • +
  • [SPARK-1751] - Only a few first messages show up and no other messages come through +
  • +
  • [SPARK-1752] - File transfer and screenshot sending doesn't work after Smack 4 update +
  • +
  • [SPARK-1755] - Redundant Roar popups and history entries when receiving messages +
  • +
  • [SPARK-1756] - Prevent NPE in error handling (Group chat - Smack 4) +
  • +
  • [SPARK-1761] - Fixing RPM build after Bamboo migration +
  • +
  • [SPARK-1763] - Can't create new account on a server (Smack 4 issue) +
  • +
  • [SPARK-1764] - Transcript file is not being closed on exit +
  • +
  • [SPARK-1766] - File Streams not being closed on a few files +
  • +
  • [SPARK-1768] - Fix Debian build +
  • +
  • [SPARK-1772] - Not showing correct room affiliation icons for different roles +
  • +
  • [SPARK-1773] - Spark does not detect keystrokes when switched away due to idle on mac and linux +
  • +
  • [SPARK-1776] - Private messages in MUC do not show up (Smack 4) +
  • +
  • [SPARK-1777] - Presence getting stuck in Away mode sometimes +
  • +
  • [SPARK-1778] - Spark shouldn't lookup an empty username +
  • +
  • [SPARK-1779] - No vertical scrollbar in the participants list +
  • +
  • [SPARK-1783] - ROAR plugin should not assume Opaque is supported +
  • +
+ +

New Feature +

+
    +
  • [SPARK-1596] - Different settings for group chat Roar popups +
  • +
  • [SPARK-1599] - Add an option for custom Roar popup based on a keyword +
  • +
  • [SPARK-1709] - Add Russian dictionary for spellchecker +
  • +
  • [SPARK-1729] - Add an option to save group chat password +
  • +
  • [SPARK-1731] - Add Ukrainian translation +
  • +
+ +

Task +

+
    +
  • [SPARK-1722] - Update bundled JRE with the latest version +
  • +
+ +

Improvement +

+
    +
  • [SPARK-1559] - Add URL support to server broadcast dialog +
  • +
  • [SPARK-1567] - Update Smack to the 4th version (4.1.7) +
  • +
  • [SPARK-1646] - Should switch to Away mode when locking screen on Windows 10 +
  • +
  • [SPARK-1735] - Small group chat user-interface improvements +
  • +
  • [SPARK-1741] - Replace old code constructs +
  • +
  • [SPARK-1746] - Update Lithuanian translation +
  • +
  • [SPARK-1753] - Don't be disconnected when receiving invalid stanzas +
  • +
  • [SPARK-1754] - Update Italian translation +
  • +
  • [SPARK-1769] - Update Substance LaF to the latest version +
  • +
  • [SPARK-1771] - Update Smack to 4.1.8 version +
  • +
  • [SPARK-1775] - Prevent exceptions from going unnoticed +
  • +
+ + +

2.7.7 -- April 24, 2016

+

Bug +

+
    +
  • [SPARK-1597] - UNC links in file://\\\ format should work in the chat window +
  • +
  • [SPARK-1660] - Should not fallback to direct connection when proxy is enabled +
  • +
  • [SPARK-1695] - Windows installer is including linux lib folder +
  • +
  • [SPARK-1717] - Failing dependencies when installing RPM version +
  • +
  • [SPARK-1721] - Fix a typo in Network Address Manager in SIP plugin +
  • +
  • [SPARK-1724] - OTR plugin not working after bouncy castle lib update +
  • +
  • [SPARK-1726] - Spark is setting negative priority when switching to Idle +
  • +
+ +

New Feature +

+
    +
  • [SPARK-1720] - Add option to disable Incoming Call notification popup +
  • +
+ +

Task +

+
    +
  • [SPARK-1687] - Update bundled JRE with the latest version +
  • +
+ +

Improvement +

+
    +
  • [SPARK-1716] - Fix alignment of fields on Business card in Profile +
  • +
  • [SPARK-1718] - Remove old java from RPM installation +
  • +
  • [SPARK-1723] - Update of German translation +
  • +
  • [SPARK-1727] - Fix and update Lithuanian translation +
  • +
+ + +

2.7.6 -- March 15, 2016

+

Bug +

+
    +
  • [SPARK-1192] - Preferences window doesn't open on Mac OS X +
  • +
  • [SPARK-1197] - File transfers don't work on Mac OS X +
  • +
  • [SPARK-1455] - Spark is getting stuck with "On Phone" status after unlocking Windows +
  • +
  • [SPARK-1530] - Broadcast message is not shown with bolded red font in the tab +
  • +
  • [SPARK-1620] - Sound files are not copied into user's profile on Mac OS X +
  • +
  • [SPARK-1667] - Bookmarks menu shows last when using Substance skins +
  • +
  • [SPARK-1671] - Add i18n translation for "(Offline)" prefix before offline message +
  • +
  • [SPARK-1674] - Add Mac OS X installer with bundled JRE +
  • +
  • [SPARK-1677] - Shows app name as Startup instead of Spark on Mac OS X +
  • +
  • [SPARK-1689] - RPM build fails after Libjitsi update +
  • +
  • [SPARK-1692] - Native Jitsi libraries not loading on Mac OSX +
  • +
  • [SPARK-1696] - Fastpath not working on Mac OS X +
  • +
  • [SPARK-1697] - Roar plugins doesn't work on Mac OS X +
  • +
  • [SPARK-1701] - Plugins are not being copied to user's home folder on Mac OS X +
  • +
  • [SPARK-1703] - Spark is constantly trying to access e4j_pxxxx.tmp file +
  • +
  • [SPARK-1704] - Emoticons not loading on mac osx +
  • +
  • [SPARK-1714] - Disconnecting when saving or retrieving Notes +
  • +
+ +

New Feature +

+
    +
  • [SPARK-1675] - Add Lithuanian translation for Fastpath plugin +
  • +
+ +

Task +

+
    +
  • [SPARK-1643] - Update bundled JRE with the latest version +
  • +
  • [SPARK-1679] - Fix the wrong year on the About window on Mac OS X +
  • +
  • [SPARK-1693] - Increase checkstyle's maxerror value +
  • +
  • [SPARK-1712] - Change JDK to 1.8 in Bamboo build plans (Ant) +
  • +
+ +

Improvement +

+
    +
  • [SPARK-1680] - Update top menu item name "Spark" to more commonly used name "File" +
  • +
  • [SPARK-1681] - Update Spark's User Guide +
  • +
  • [SPARK-1684] - Toaster Pop up for Incoming Call is too short. +
  • +
  • [SPARK-1685] - Idle state shouldn't override custom status message +
  • +
  • [SPARK-1691] - Change JNA to version to 3.4.2 +
  • +
+ + +

2.7.5 -- January 14, 2016

+

Bug +

+
    +
  • [SPARK-1664] - RPM build fails after Smack library update +
  • +
  • [SPARK-1669] - Fix Lithuanian translation of Tic Tac Toe game +
  • +
  • [SPARK-1672] - Spark is not showing "(Offline)" prefix for offline messages on Openfire 4.0.0 +
  • +
  • [SPARK-1673] - Only first offline message is shown +
  • +
+ +

Improvement +

+
    +
  • [SPARK-1091] - Create an installer for Mac OS X +
  • +
  • [SPARK-1661] - Change "on phone" to "on the phone" +
  • +
  • [SPARK-1663] - Update jarbundler and ant build file +
  • +
  • [SPARK-1666] - Update Simplified Chinese translation +
  • +
+ +

New Feature +

+
    +
  • [SPARK-1668] - Lithuanian translation for the Battleships game +
  • +
+ +

2.7.4 -- December 18, 2015

+

Bug +

+
    +
  • [SPARK-847] - "Contact List font size" not applied to Offline users group +
  • +
  • [SPARK-1066] - Proxy is not working +
  • +
  • [SPARK-1576] - Spark is not showing room participants when presence icons should be showing +
  • +
  • [SPARK-1592] - Should not show 'Send a file' menu when file transfer is disabled +
  • +
  • [SPARK-1645] - Notifications settings disappear when updates are disabled via default.properties +
  • +
  • [SPARK-1648] - Toast popups are not shown for group chat messages +
  • +
  • [SPARK-1650] - A 'default' directory should not be required when selecting files to transfer +
  • +
  • [SPARK-1658] - NullPointerExceptions when joining an anonymous MUC +
  • +
+ +

Improvement +

+
    +
  • [SPARK-1651] - Add i18n translation for Transfer Guard plugin's name in the Preferences +
  • +
  • [SPARK-1652] - Add scrollbar in Emoticon picker +
  • +
  • [SPARK-1655] - Updated Russian translation +
  • +
  • [SPARK-1656] - Update Chinese (Traditional) translation +
  • +
  • [SPARK-1659] - Another Russian translation update +
  • +
+ +

New Feature +

+
    +
  • [SPARK-1644] - Add an option to hide auto login checkbox along with the save password box +
  • +
  • [SPARK-1653] - Add Chinese (Traditional) translation for Transfer Guard plugin +
  • +
+ +

2.7.3 -- October 23, 2015

+

Bug +

+
    +
  • [SPARK-1144] - Ant buildscript should not check for explicit Ant version numbers +
  • +
  • [SPARK-1329] - Various confirmation dialogs should use i18n strings for Yes, No and Cancel buttons +
  • +
  • [SPARK-1631] - Messages are not shown as sent or received when no history is shown +
  • +
  • [SPARK-1634] - Fix Class not found exception in LaF +
  • +
+ +

Improvement +

+
    +
  • [SPARK-985] - Online/Offline toast popups improvement +
  • +
  • [SPARK-1472] - Add "Avatar:" to translation file +
  • +
  • [SPARK-1473] - Alert notification popup should show the sender's name +
  • +
  • [SPARK-1517] - Append contact name on every line of conversation history +
  • +
  • [SPARK-1571] - Add phone number to vCard popup +
  • +
  • [SPARK-1627] - Change default reconnection option to Display in contact group +
  • +
  • [SPARK-1633] - Add support for IzPack 5 in the build process +
  • +
  • [SPARK-1641] - Fixed typos in the group chat dialogs +
  • +
  • [SPARK-1642] - Update the Bring window to front code +
  • +
+ +

New Feature +

+
    +
  • [SPARK-1436] - Add option to disable chat history via default.properties +
  • +
  • [SPARK-1638] - Add option to hide chat history settings via default.properties +
  • +
  • [SPARK-1640] - Add option to hide save password checkboxes +
  • +
+ +

Task +

+
    +
  • [SPARK-1626] - Update bundled JRE with the latest version +
  • +
+ +

2.7.2 -- August 31, 2015

+

Bug +

+
    +
  • [SPARK-1458] - Spark prepends the default status text to a custom one +
  • +
+ +

Improvement +

+
    +
  • [SPARK-1621] - Add a caption "0 = infinite" to the duration option of Roar popups +
  • +
+ +

New Feature +

+
    +
  • [SPARK-1614] - Add an option to show seconds in a message time stamp +
  • +
  • [SPARK-1619] - Add an option to use Spark version as a resource +
  • +
  • [SPARK-1622] - Add options to default.properties to use hostname or version as resource +
  • +
+ +

Task +

+
    +
  • [SPARK-1615] - Update bundled JRE with the latest version +
  • +
+ +

2.7.1 -- June 12th, 2015

+

Bug +

+
    +
  • [SPARK-864] - Printing conversation margin cuts off characters from lines that wrap +
  • +
  • [SPARK-1512] - ***<user> is online at message does not always show in chat room +
  • +
  • [SPARK-1513] - After receiving XML data as a message Spark stops displaying history +
  • +
  • [SPARK-1604] - Buzz and stale settings overlap in the Preferences window +
  • +
+ +

Improvement +

+
    +
  • [SPARK-1588] - Update French translation +
  • +
  • [SPARK-1607] - Show JID as contact name if instead an empty string would have been shown +
  • +
  • [SPARK-1609] - Default resource should be "Spark" without a version number +
  • +
  • [SPARK-1611] - Update Lithuanian translation +
  • +
  • [SPARK-1617] - Fix loading of Spellchecker's IgnoreUppercase setting +
  • +
+ +

New Feature +

+
    +
  • [SPARK-979] - Add an option to disable graying out and italic for idle contacts +
  • +
  • [SPARK-1503] - Option to use hostname as a resource +
  • +
+ +

Task +

+
    +
  • [SPARK-1584] - Update bundled JRE with the latest version +
  • +
+ +

2.7.0 -- April 24th, 2015

+ +

Sub-task +

+
    +
  • [SPARK-802] - After a Reconnection error it does not attempt anymore +
  • +
  • [SPARK-1002] - Use some form of "reconnection logic" +
  • +
  • [SPARK-1204] - Counter for online contacts in group sometimes is wrong +
  • +
  • [SPARK-1313] - Enhance ability to overwrite spark properties values through plugin +
  • +
  • [SPARK-1326] - Make tabs position optional: TOP or BOTTOM; make search input appearance optional +
  • +
  • [SPARK-1465] - Checkboxes appear bigger then normal since the jtattoo update +
  • +
  • [SPARK-1478] - Getting vcards from server could freeze Spark at startup +
  • +
  • [SPARK-1482] - Scratchpad plugin could freeze spark at startup +
  • +
  • [SPARK-1483] - Privacy plugin could freeze spark at startup +
  • +
  • [SPARK-1528] - Should show user's Name instead of Username when receiving a broadcast +
  • +
  • [SPARK-1541] - Receiving lots of conference rooms could freeze spark for some time +
  • +
+ +

Bug +

+
    +
  • [SPARK-845] - displaying of chat log with "<script" within the message causes trouble +
  • +
  • [SPARK-987] - Spark has the wrong icons +
  • +
  • [SPARK-1042] - Spark looses the content of custom (not shared) group with the shared contacts +
  • +
  • [SPARK-1058] - Spark should let to change the language of GUI to any available +
  • +
  • [SPARK-1074] - Sending part doesnt get a notification about the transfer cancellation +
  • +
  • [SPARK-1097] - Delete the obsolete Available translation string from the i18n file +
  • +
  • [SPARK-1163] - Spark displays wrong error when nickname change is forbidden +
  • +
  • [SPARK-1177] - Memory leak ChatRoom +
  • +
  • [SPARK-1186] - Ctrl + W not working as expected in chat window +
  • +
  • [SPARK-1212] - Shouldn't be able to search for yourself and add yourself to a roster +
  • +
  • [SPARK-1223] - Masterticket: Clean up the error log +
  • +
  • [SPARK-1224] - Masterticket: Rework Reconnection Logic +
  • +
  • [SPARK-1324] - SparkToaster showing avatars in real size +
  • +
  • [SPARK-1355] - No history in Groups chat +
  • +
  • [SPARK-1362] - No confirmation on the sender's part that the file transfer completed +
  • +
  • [SPARK-1382] - File Transfer from WinXP to Win7x64 does not work in nightlies +
  • +
  • [SPARK-1387] - Reversi is not starting +
  • +
  • [SPARK-1397] - Fix the displaying of system tray icons +
  • +
  • [SPARK-1408] - Remove "#" character next to Accounts button on the login screen +
  • +
  • [SPARK-1411] - Sometimes file transfer indication is not updated on the receiving side +
  • +
  • [SPARK-1414] - Chat window is not flashing when receiving new message on Windows 7 64 bit +
  • +
  • [SPARK-1417] - Temporary conference are getting bookmarked +
  • +
  • [SPARK-1419] - Chat room configuration shows wrong roles for which presence is broadcast +
  • +
  • [SPARK-1420] - The messages in the set status message window is not getting deleted +
  • +
  • [SPARK-1421] - Application version and application name are hardcoded +
  • +
  • [SPARK-1422] - persist vcard may throw file not found exception when jid is empty +
  • +
  • [SPARK-1423] - typo error in LayoutSettings.java +
  • +
  • [SPARK-1427] - Default Appearance/Colors cannot be overwritten through plugin;Group-Chat colors are hard-coded +
  • +
  • [SPARK-1431] - Update Smack to the next version. +
  • +
  • [SPARK-1437] - Bug in PrivacyManager that can break smack communication +
  • +
  • [SPARK-1438] - Avatars are not scaled in user login/logout notification dialog +
  • +
  • [SPARK-1439] - Plugins are loaded in random order - plugins with no dependency has to be loaded first +
  • +
  • [SPARK-1440] - Bug in ConferenceUtils.java that can break smack communication +
  • +
  • [SPARK-1441] - ContactItem in shared group - right click popup menu performs copy when move is selected +
  • +
  • [SPARK-1442] - JabberVersion.java uses hardcoded value "Spark IM Client" for version name +
  • +
  • [SPARK-1447] - Chat logs are getting corrupted (after the upgrade to 2.6.3) +
  • +
  • [SPARK-1449] - UNC Path does not link to folder +
  • +
  • [SPARK-1451] - Vcard popup is not always showing up on mouse hover +
  • +
  • [SPARK-1452] - If conferences tab is hidden, then Fastpath tab is hidden also +
  • +
  • [SPARK-1462] - Spark doesn't list rooms when subject has a null value +
  • +
  • [SPARK-1464] - When user accepts group chat invitation, status is always online +
  • +
  • [SPARK-1470] - Typing notification diesn't change its status +
  • +
  • [SPARK-1475] - Connection crashen when sending control characters +
  • +
  • [SPARK-1480] - Reduce VCARD loading of Spark +
  • +
  • [SPARK-1485] - Subscription dialog is hidden when received +
  • +
  • [SPARK-1488] - On unclean disconnect, chat windows, that were already open, cannot be closed +
  • +
  • [SPARK-1490] - Broadcast menu duplicates users in the Online group +
  • +
  • [SPARK-1514] - Ghost icon gets lost when user comes (back) online +
  • +
  • [SPARK-1524] - Spark is not reconnecting automatically after connection loss +
  • +
  • [SPARK-1531] - URL links not working without http:// part +
  • +
  • [SPARK-1534] - Roar should show a popup for broadcast messages and play a sound +
  • +
  • [SPARK-1535] - Custom status message is not set if selected from saved custom statuses +
  • +
  • [SPARK-1546] - Spark visually shows that a message is not sent +
  • +
  • [SPARK-1550] - Integrate next SMACK lib release into Spark (any version post-3.3.0) +
  • +
  • [SPARK-1553] - Privacy feature lookup and invisibility +
  • +
  • [SPARK-1558] - Multiple memory leaks +
  • +
  • [SPARK-1565] - Roar plugin shouldn't show many popups when joining a chat room with old history +
  • +
+ +

Improvement +

+
    +
  • [SPARK-33] - Add more content to the About Box +
  • +
  • [SPARK-822] - fix Spark icon +
  • +
  • [SPARK-891] - Typing notifications would be easier to see if also displayed near typing area +
  • +
  • [SPARK-1060] - Spark should remember Preferences window (and others) position on the screen +
  • +
  • [SPARK-1179] - Add time stamps and improve layout of conversation history +
  • +
  • [SPARK-1188] - Emphasize broadcast message in the chat window +
  • +
  • [SPARK-1215] - Log out doesn't log out, it shuts down spark +
  • +
  • [SPARK-1333] - Update Lithuanian translation +
  • +
  • [SPARK-1381] - Group Chat - Actions/Start a conference menu: propose bookmarked room (if any) instead of adhoc (random) room name +
  • +
  • [SPARK-1407] - Fix the direction of 5000 history messages limit and make a GUI option +
  • +
  • [SPARK-1418] - Update simplified Chinese translation +
  • +
  • [SPARK-1429] - Update French translation +
  • +
  • [SPARK-1459] - Update to the latest JTattoo version (Nov 2011) +
  • +
  • [SPARK-1466] - Update the Finnish translation +
  • +
  • [SPARK-1476] - Update the smack to 3.2.2 +
  • +
  • [SPARK-1479] - SettingsManager hadr-codes executable name: Spark.exe +
  • +
  • [SPARK-1487] - Size of chat input field is to small, it dont fit to the rest of the chatwindow +
  • +
  • [SPARK-1491] - Update Polish translation +
  • +
  • [SPARK-1515] - Migrate to latest JTattoo Release +
  • +
  • [SPARK-1526] - Minimized roster window should appear when clicking on a systray icon +
  • +
  • [SPARK-1539] - Update Substance LaF to the latest version +
  • +
  • [SPARK-1540] - Update POPO emoticons set +
  • +
  • [SPARK-1542] - Icon of refresh button in the ConferenceRoomBrowser should change when loading +
  • +
  • [SPARK-1544] - Spark should relog on newly applied LaF +
  • +
  • [SPARK-1545] - Drop Java 5 and 6 support +
  • +
  • [SPARK-1552] - Update Smack to 3.3.1 version +
  • +
  • [SPARK-1566] - Roar popup will change to "broadcast - (sender's name)" when receiving a broadcast message +
  • +
  • [SPARK-1595] - Add an option for Roar popups to stay indefinitely +
  • +
+ +

New Feature +

+
    +
  • [SPARK-1105] - Spark should indicate different permissions in MUC with additional icons or colors +
  • +
  • [SPARK-1356] - Limit filetransfer speed +
  • +
  • [SPARK-1378] - Create TicTacToe for Spark +
  • +
  • [SPARK-1405] - Improved last activity recognition +
  • +
  • [SPARK-1435] - Make an option to disable Log out in Spark menu via default.properties +
  • +
  • [SPARK-1486] - For customizing purposes, provide ability to register own error and warning handler in logging mechanism of spark +
  • +
  • [SPARK-1493] - Add translation file for the Transfer Guard plugin +
  • +
  • [SPARK-1521] - Add invisible presence state +
  • +
  • [SPARK-1529] - Display the entire group chat history +
  • +
+ +

Task +

+
    +
  • [SPARK-1098] - Investigate two functions in ContactItem.java which can cause issues +
  • +
  • [SPARK-1232] - Release Blocker: Nightly build is not compiling the plugins +
  • +
  • [SPARK-1306] - Attach newest source code, JTattoo Tab Rendering in Spark +
  • +
  • [SPARK-1400] - Update to latest version Exe4J +
  • +
  • [SPARK-1412] - Drop Java 5 support +
  • +
  • [SPARK-1413] - Update build.xml to check for Java 7 +
  • +
  • [SPARK-1416] - Update JRE to 7 version +
  • +
  • [SPARK-1500] - Add Portuguese Brazilian Spelling +
  • +
  • [SPARK-1525] - Update smack +
  • +
  • [SPARK-1538] - Update to latest Trident lib +
  • +
  • [SPARK-1555] - Update build.xml to support Ant 1.9 +
  • +
  • [SPARK-1602] - Update bundled JRE to 1.7.0_76 +
  • +
+ +

2.6.3 -- July 1st, 2011

+ + +Highlights: +
    +
  • Bug Fixes only
  • +
+ +

Bug fix

+
    +
  • [SPARK-615] - Fixed issue with XMPP URI conference chats.
  • +
  • [SPARK-740] - XMPP URI not working in IE
  • +
  • [SPARK-1379] - Support for XEP-0147
  • +
  • [SPARK-1383] - Login screen shows disabled fields.
  • +
  • [SPARK-1392] - Check if Spark is really checking for updates even if that option is turned off
  • +
  • [SPARK-1394] - Search in history is not working
  • +
  • [SPARK-1395] - NPE when exiting a chat window with ESC
  • +
  • [SPARK-1396] - Send Broadcast Window doesn't show when not using JTattoo
  • +
  • [SPARK-1398] - scrollToBottom causes UiThreadingViolationException when using Substance Skins
  • +
+ + +

2.6.2 Hot Fix -- June 23rd, 2011

+ + +Highlights: +
    +
  • Support XMPP servers without ability to manage privacy lists
  • +
+ +

Bug fix +

+
    +
  • [SMACK-338] - IBB filetransfer doesn't work as expected
  • +
+ +

2.6.1 all resolved issues in Spark and Smack -- June 22nd, 2011

+ +Highlights: +
    +
  • File transfer bug resolved
  • +
  • Standard Mac Look and Feel on that very plattform
  • +
  • OTR (off the record) encryption for chat
  • +
  • I18n updates
  • +
  • New notification mechanism (Roar)
  • +
  • Clean up and enhancements for look and feel
  • +
+ + + +

Bug fixes (35 bugs + 3 SMACK related) +

+
    +
  • [SMACK-338] - IBB filetransfer doesn't work as expected +
  • +
  • [SMACK-273] - Bug in RoomListenerMultiplexor.java +
  • +
  • [SMACK-329] - XHTMLText uses improper format for br tag +
  • +
  • [SPARK-791] - Vcard cache not expiring +
  • +
  • [SPARK-1067] - System Look and Feel option should be using system theme highlighting colors +
  • +
  • [SPARK-1080] - IzPack uninstaller doesnt remove Spark entries from Programs and Features list +
  • +
  • [SPARK-1095] - Nested groups are not sorted by name +
  • +
  • [SPARK-1164] - Chat window doesnt scroll to bottom when opened +
  • +
  • [SPARK-1177] - Memory leak ChatRoom +
  • +
  • [SPARK-1198] - Spark has no button for Send Files or Capture in message window on MAC OS X +
  • +
  • [SPARK-1200] - Context menu doesn't show up in chat input area on Windows 7 +
  • +
  • [SPARK-1207] - Linux version of Spark quits when doing logout +
  • +
  • [SPARK-1253] - Transport icons disappear after saving preferences +
  • +
  • [SPARK-1274] - Reverse alphabetical sorting of participants in the group chat +
  • +
  • [SPARK-1275] - contact add loses connection when no username provided +
  • +
  • [SPARK-1280] - Crtl-Backspace doe not work in Chat Windows +
  • +
  • [SPARK-1281] - Spark doesn't goes online after auto away when using Remote Desktop connection +
  • +
  • [SPARK-1283] - File transfer between 2.5.8 and 2.6.0_12222 is broken +
  • +
  • [SPARK-1294] - Spark 2.6 RC2 No Phone Call Button +
  • +
  • [SPARK-1324] - SparkToaster showing avatars in real size +
  • +
  • [SPARK-1325] - Spark File Transfer. Let spark find the right IP +
  • +
  • [SPARK-1331] - Spark->Preferences->Appearance: Null Pointer exception when no emoticon set is available +
  • +
  • [SPARK-1336] - NPE In getContactGroupByJID +
  • +
  • [SPARK-1338] - Spark 12384 is not starting with old profile +
  • +
  • [SPARK-1340] - Spark login profile picker doesn't show profiles with same names but different servers +
  • +
  • [SPARK-1350] - File transfer and windows network path +
  • +
  • [SPARK-1351] - Remove plugins does not remove plugins +
  • +
  • [SPARK-1357] - When in fullscreen mode and switching to smaller screen, spark doesnt rezise to fit smaller screen +
  • +
  • [SPARK-1364] - Investigate the Spark automatic update from the site issue +
  • +
  • [SPARK-1366] - Review padlock icon usage +
  • +
  • [SPARK-1373] - Bring Reversi back, please! +
  • +
  • [SPARK-1375] - Context Menue in roster dows not allow a broadcast to the selected user +
  • +
  • [SPARK-1376] - Fix the "Check for new version" Function +
  • +
  • [SPARK-1383] - Login screen shows disabled fields. +
  • +
  • [SPARK-1385] - Format Bug in Transcript +
  • +
  • [SPARK-1387] - Reversi is not starting +
  • +
  • [SPARK-1388] - Typo in spark i18n - avtivate +
  • +
  • [SPARK-1389] - History is diplayed twice +
  • +
+ +

New Features, Improvements, Tasks (55 issues) +

+
    +
  • [SPARK-548] - Add support for animated gifs as avatars +
  • +
  • [SPARK-884] - OTR support for chat +
  • +
  • [SPARK-1277] - Installer should include Java 1.6.0 (build 10) or higher +
  • +
  • [SPARK-1278] - Allow Nimbus Skinning +
  • +
  • [SPARK-1303] - Preferences: Automatically join Groupchat (muc) on invite +
  • +
  • [SPARK-1323] - Allow larger VCard Images +
  • +
  • [SPARK-1342] - MotD opens in Fullscreen since Spark 2.6.0 update +
  • +
  • [SPARK-1344] - Add some more plugins to 2.6.1 +
  • +
  • [SPARK-1345] - Reduce the delivered skins to the usable ones +
  • +
  • [SPARK-1352] - Prevent messages from the server to be stored in Client history +
  • +
  • [SPARK-1354] - Force 32 bit execution on Mac Plattfom +
  • +
  • [SPARK-1359] - Plugin Blacklist +
  • +
  • [SPARK-1367] - Speelchecker default Language +
  • +
  • [SPARK-1369] - When debugger enabled should be able to send raw packets somehow +
  • +
  • [SPARK-1379] - Support for XEP-0147 +
  • + +
  • [SPARK-948] - Bring window to front shouldnt steal focus +
  • +
  • [SPARK-984] - Should be an option to disable username color randomizer in MUC +
  • +
  • [SPARK-1218] - Make Room Configuration dialog translatable +
  • +
  • [SPARK-1220] - Create FlashWindow.dll 64-bit version +
  • +
  • [SPARK-1235] - Add context menu to Ctrl-F, Ctrl-E, Ctrl-T dialogs +
  • +
  • [SPARK-1254] - Select Spellchecker Language in Chatwindow +
  • +
  • [SPARK-1316] - Privacy Plugin needs refactoring +
  • +
  • [SPARK-1332] - Make possible to translate hardcoded strings +
  • +
  • [SPARK-1333] - Update Lithuanian translation +
  • +
  • [SPARK-1334] - Add the login server as STUN server to spark.properties +
  • +
  • [SPARK-1335] - Spark should save received broadcast messages in the chat history +
  • +
  • [SPARK-1341] - Profile picker button should have a button design (with a border) +
  • +
  • [SPARK-1343] - Broadcast window covers whole screen if message is longer than {1*10^x , x?R>5} characters +
  • +
  • [SPARK-1346] - PluginLoader should get a <minJava>1.x.x_xx</minJava> tag +
  • +
  • [SPARK-1347] - apple plugin needs configurable behaviour +
  • +
  • [SPARK-1348] - Make possible to set Join on startup from other interface +
  • +
  • [SPARK-1349] - Option to disable translator plugin +
  • +
  • [SPARK-1361] - If History has more than 5000 Messages it takes forever to load +
  • +
  • [SPARK-1372] - Clicking the [X] in the contact subscription request should be the same as "Decline" +
  • + +
  • [SPARK-1230] - Masterticket: Translations +
  • +
  • [SPARK-1298] - Clean Up Spark UI +
  • +
  • [SPARK-1322] - Rename Debian package +
  • +
  • [SPARK-1360] - Check FMJ lib for revision +
  • +
  • [SPARK-1368] - Check Spark 2.6.1 on W7 without admin rights +
  • +
  • [SPARK-1380] - Exchange of the Spark Spash Screen +
  • +
  • [SPARK-1384] - Change XMPP Ressource String +
  • +
  • [SPARK-1386] - Privacy Plugin shouldn't load if not supported +
  • +
  • [SPARK-1390] - Remove games from the release +
  • + +
  • [SPARK-804] - MSN Offline users in roster +
  • +
  • [SPARK-854] - reconect hangs within "Reconnecting ..." +
  • +
  • [SPARK-1167] - New chat window steals focus when Spark receives new message +
  • +
  • [SPARK-1265] - Fix tabs stacking direction and tabs size with multirow tabbar +
  • +
  • [SPARK-1290] - Redesign "Invisible" Button +
  • +
  • [SPARK-1304] - Allow to hide the conference tab in the Spark screen +
  • +
  • [SPARK-1337] - Create Button to login with other Profiles in LoginDialog +
  • +
  • [SPARK-1353] - JTattoo Render Error +
  • +
  • [SPARK-1358] - Add features to default.properties FILE_TRANSFER_WARNING_SIZE and FILE_TRANSFER_MAXIMUM_SIZE +
  • +
  • [SPARK-1370] - W7 64 Bit: Plugin's are missing +
  • +
  • [SPARK-1371] - Add tooltip to button in chat window +
  • +
  • [SPARK-1374] - Spark freezes on close +
  • + +
+ + + + +

2.6.0 all resolved issues in Spark and Smack -- May 6th, 2011

+ +Highlights: +
    +
  • Large parts of the code were licenced as Apache 2.0
  • +
  • Commercial packages were removed in favour of open source solutions
  • +
  • Updated Smack library to 3.2
  • +
  • Fixes for roster management and reconnection mechanisms
  • +
  • Reworked look and feel
  • +
  • New skinning library
  • +
  • I18n updates
  • +
  • Clean error log after startup
  • +
  • Support for privacy mode
  • +
  • Spark does not call hard coded fallback servers for STUN services anymore
  • +
  • Major feature updates for conference rooms
  • +
  • More preferences
  • +
  • Ability to set default data in ini files for corporate customizing
  • + + +
+

New Features & Improvements (more than 190 issues)

+
    + + + +
  • [SMACK-137] - File + Transfer Settings
  • + +
  • [SMACK-156] - Add + the ability to register for roster events before logging in
  • + +
  • [SMACK-175] - fix + UNSUBsCRIPTION_PENDING in RosterPacket
  • + +
  • [SMACK-235] - Improve + performance of Roster class
  • + +
  • [SMACK-240] - Update + Jingle implementation to newest version
  • + +
  • [SMACK-241] - Update + Base64 implementation to match Openfire's
  • + +
  • [SMACK-244] - Update + JSTUN to 0.7.2
  • + +
  • [SMACK-245] - Update + Jingle implementation to newest version
  • + +
  • [SMACK-246] - Improve + Jingle logging using commons-logging
  • + +
  • [SMACK-247] - Keep + Jingle compliant with on-going protocol development.
  • + +
  • [SMACK-254] - Offer + an alternative to loading the Roster on login
  • + +
  • [SMACK-261] - Minor + Jingle cleanup to better support Jingle in Spark
  • + +
  • [SMACK-277] - Update + XMLUnit to the latest version
  • + +
  • [SMACK-282] - Support + SASL-related error conditions.
  • + +
  • [SMACK-285] - Add + support for Nicks
  • + +
  • [SMACK-289] - There + is no way of retrieving items from a pubsub node when the user has multiple + subscriptions.
  • + +
  • [SMACK-294] - Handle + empty roster groups and no goups in the same way
  • + +
  • [SMACK-295] - Fire + reconnectionSuccessful event when session is established
  • + +
  • [SMACK-297] - add + configuration for local Socks5 proxy
  • + +
  • [SMACK-298] - Respond + to all incoming Socks5 bytestream requests
  • + +
  • [SMACK-299] - Improve + accepting of Socks5 bytestream requests
  • + +
  • [SMACK-300] - improve + local Socks5 proxy implemetation
  • + +
  • [SMACK-301] - support + for bytestream packets to query Socks5 proxy for network address
  • + +
  • [SMACK-302] - Improve + establishing of Socks5 bytestreams
  • + +
  • [SMACK-303] - integrate + of the extracted Socks5 bytestream API in file transfer API
  • + +
  • [SMACK-304] - Extend + the IQ API to create empty IQ results and IQ error response packets
  • + +
  • [SMACK-307] - Improve + Message Parser Robustness and Message Body I18N
  • + +
  • [SMACK-309] - Fully + implement XEP-0047 In-Band Bytestreams
  • + +
  • [SMACK-310] - Add + Support for Localized Message Subjects
  • + +
  • [SMACK-317] - PrivacyItem + class changes
  • + +
  • [SMACK-142] - Add + support for Kerberos/NTLM
  • + +
  • [SMACK-210] - Support + MD5 SASL
  • + +
  • [SMACK-226] - Need + to add in http/socks proxy support to XMLConnection.
  • + +
  • [SMACK-242] - Add + support for JEP-50: ad-hoc commands
  • + +
  • [SMACK-251] - Add + support for XEP-0163: Personal Eventing Protocol
  • + +
  • [SMACK-255] - Add + ability to set mime type for avatar
  • + +
  • [SMACK-256] - Add + support for new sophisticated TLS mechanisms including SmartCard and Apple's + KeychainStore
  • + +
  • [SMACK-272] - Add + support for pubsub (XEP-0060)
  • + +
  • [SMACK-296] - Add + support for XEP-0224: Attention
  • + +
  • [SMACK-319] - Add + common interfaces for SOCKS5 Bytestreams and In-Band Bytestreams
  • + +
  • [SMACK-279] - SMACK-187 + Create a abstract connection class to allow other implementations connecting + to a XMPP server.
  • + +
  • [SMACK-280] - SMACK-187 + The authentification should use the Connection#sendPacket method and work + transparent with packets and packet listeners.
  • + +
  • [SMACK-281] - SMACK-187 + Move IQ and stream error parsing from PacketReader which depends on the + connection type to PacketParserUtils.
  • + +
  • [SMACK-259] - Update + XPP library to latest version
  • + +
  • [SMACK-283] - Investigate + why Jingle is connecting to stun.xten.net
  • + +
  • [SPARK-1321] - Update Smack to final release + 3.2
  • +
  • [SPARK-1319] - Review Tray Icon of Spark on + Windows
  • +
  • [SPARK-1318] - STUN fallback in error log
  • +
  • [SPARK-1317] - Privacy Plugin causes error log + entry at startup
  • +
  • [SPARK-1312] - Load plugins before Login page + and workspace are initialized
  • +
  • [SPARK-1308] - JTattoo menubar decoration
  • +
  • [SPARK-1307] - Update build.xml to support Ant + 1.8
  • +
  • [SPARK-1300] - Remove Buttons from Spark
  • +
  • [SPARK-1293] - Include JGoodies as LaF
  • +
  • [SPARK-1103] - Add an option to register with + conference room
  • +
  • [SPARK-1091] - Create an installer for Mac OS X
  • +
  • [SPARK-1060] - Spark should remember + Preferences window (and others) position on the screen
  • +
  • [SPARK-1050] - Create a horizontal scrollbar in + the emoticons picker for large emoticons packages
  • +
  • [SPARK-1037] - Timing issue prevents contact + list from updating correctly
  • +
  • [SPARK-1035] - Add ability to have an invisible + presence
  • +
  • [SPARK-764] - Auto-reconnect does not send + available presence or ask for roster
  • +
  • [SPARK-744] - Spark fails to login after + restore from Hibernation
  • +
  • [SPARK-726] - Spark needs to use the users + presence prior to reconnect.
  • +
  • [SPARK-533] - Buzz feature improvements
  • +
  • [SPARK-915] - Tab + completion of conference room nicknames
  • + +
  • [SPARK-1105] - Spark + should indicate different permissions in MUC with additional icons or colors
  • + + +
  • [SPARK-1187] - Auto + tab completion in Spark
  • + + +
  • [SPARK-1261] - Default + properties should be stored visible in the Spark bin directory
  • + + +
  • [SPARK-1264] - Show + Transports in tab
  • + + +
  • [SPARK-1090] - Spark + should show time stamps in the full history
  • + + +
  • [SPARK-1175] - label.message + shows & in most translations
  • + + +
  • [SPARK-1222] - [Patch + ready to commit] Update Lithuanian translation
  • + + +
  • [SPARK-1259] - Add + to i18n new strings in Codecs menu
  • + + +
  • [SPARK-1124] - Chat + window is not flashing when receiving new message
  • + + +
  • [SPARK-1009] - Make gateway icons more + transparent to fit with new theme
  • + + +
  • [SPARK-1010] - On toast popup from a MUC show + the nickname of whoever said the comment
  • + + +
  • [SPARK-1012] - Update Jingle implementation to + latest in Smack
  • + + +
  • [SPARK-1024] - Add finish translation
  • + + +
  • [SPARK-1025] - Make rename global and not + limited to just the contact list
  • + + +
  • [SPARK-1032] - Improve the downloading class
  • + + +
  • [SPARK-1036] - Refactor JinglePlugin to + correctly utilize the latest Smack/Jingle library
  • + + +
  • [SPARK-1040] - Need to release a new SmackLib + that includes part of the changes needed to make Jingle work in Spark
  • + + +
  • [SPARK-1043] - Should automatically set Away + status when Desktop is locked
  • + + +
  • [SPARK-1044] - Replace spellchecker with new + multi-language spellchecker
  • + + +
  • [SPARK-1047] - Improve support of transparent + avatars
  • + + +
  • [SPARK-1054] - Swedish translation
  • + + +
  • [SPARK-1065] - Change Library from JMF to FMJ
  • + + +
  • [SPARK-1070] - Spark should have a faster + reaction on mouse movements when changing status
  • + + +
  • [SPARK-1077] - Add localization support for + hardcoded strings in the GUI
  • + + +
  • [SPARK-1086] - Change the title of the + broadcast message sent from the server
  • + + +
  • [SPARK-1090] - Spark should show time stamps in + the full history
  • + + +
  • [SPARK-1093] - Add Expand/Collapse all Groups + to shared groups
  • + + +
  • [SPARK-1102] - Updated Russion translation for + spark & spellchecker plugin
  • + + +
  • [SPARK-1107] - Updated Chinese translation
  • + + +
  • [SPARK-1115] - Update build.properties with + external resources information
  • + + +
  • [SPARK-1119] - Spark should parse /me in toast + popup
  • + + +
  • [SPARK-1120] - Spark should show who has + changed room's topic
  • + + +
  • [SPARK-1121] - Should be a way to copy URL + without selecting the whole URL text
  • + + +
  • [SPARK-1123] - Linux system tray improvements
  • + + +
  • [SPARK-1125] - Make deb package compatible with + Ubuntu 9.10
  • + + +
  • [SPARK-1127] - Correction of lithuanian + translation
  • + + +
  • [SPARK-1128] - Add a divider between recent + conversation and current conversation in a chat window
  • + + +
  • [SPARK-1136] - Add i18n file to FastPath plugin
  • + + +
  • [SPARK-1137] - Improve latencies in softphone + DTMF tone soundings
  • + + +
  • [SPARK-1139] - Improved linux startup.sh
  • + + +
  • [SPARK-1142] - Replace synthetica with + substance
  • + + +
  • [SPARK-1145] - Add Korean language
  • + + +
  • [SPARK-1156] - Remove double happy emoticon in + default set
  • + + +
  • [SPARK-1157] - Cleaned up resource bundle for + Spark
  • + + +
  • [SPARK-1159] - improve error logging
  • + + +
  • [SPARK-1174] - Korean translation update
  • + + +
  • [SPARK-1178] - Update turkish translation
  • + + +
  • [SPARK-1184] - Make Spark search for a profile + in old profile location
  • + + +
  • [SPARK-1190] - "Alert when user is + available" should open a new chat window
  • + + +
  • [SPARK-1208] - Change the default file transfer + save path
  • + + +
  • [SPARK-1220] - Create FlashWindow.dll 64-bit + version
  • + + +
  • [SPARK-1247] - Fix naming of the new setting + about showing muc roles icons
  • + + +
  • [SPARK-1259] - Add to i18n new strings in + Codecs menu
  • + + +
  • [SPARK-229] - Combine username and server into + a single field
  • + + +
  • [SPARK-251] - Conference button in one-to-one + Chat Does Not Show Feedback to the User
  • + + +
  • [SPARK-254] - Chat History needs to be + seperated into two files.
  • + + +
  • [SPARK-372] - change "Force Old SSL" + to "Force TLS" within the advanced options
  • + + +
  • [SPARK-373] - move SysTray code into a plugin
  • + + +
  • [SPARK-375] - allow to select the language + during installation or later
  • + + +
  • [SPARK-38] - Add support for configuring the + list of owners, admins, ban list and members list
  • + + +
  • [SPARK-389] - MUC, direct chat: chat history + uses room name and not user name
  • + + +
  • [SPARK-412] - improve "Refresh" in + "Browse Conference Rooms" window
  • + + +
  • [SPARK-413] - improve display of buttons in + "Browse Conference Rooms"
  • + + +
  • [SPARK-431] - add "Save / Apply" and + a "Cancel" button to Preferences Dialog
  • + + +
  • [SPARK-496] - Add preference to change look + and feel
  • + + +
  • [SPARK-671] - hide "show chat + history" button if chat history is disabled
  • + + +
  • [SPARK-677] - Hide Offline Users option in the + roster
  • + + +
  • [SPARK-678] - Alphabetize offline users in the + roster
  • + + +
  • [SPARK-700] - Add an option to turn off + Spark's update-checking feature
  • + + +
  • [SPARK-849] - "[ ] Enable Emotions" + should disable more
  • + + +
  • [SPARK-87] - Add ability to view users VCard + in Group Chat.
  • + + +
  • [SPARK-912] - Localization improvements w/ + bonus other improvements
  • + + +
  • [SPARK-930] - Offline contacts in broadcast + window
  • + + +
  • [SPARK-933] - Should show avatars in roster + instead of transport icons
  • + + +
  • [SPARK-934] - SysTray icon behaviour on click, + double click
  • + + +
  • [SPARK-940] - Startup registry entry and + Preferences setting issue
  • + + +
  • [SPARK-954] - Need an option to disable + showing previous conversation in chat window
  • + + +
  • [SPARK-959] - Broadcast dialog input field + should do text wrapping
  • + + +
  • [SPARK-963] - Should be an option to switch to + 24h time format in chat window
  • + + +
  • [SPARK-970] - Improve highliting of tabs
  • + + +
  • [SPARK-975] - Add an option to delete entries + in Tasks permanently
  • + + +
  • [SPARK-980] - Add an option to disable vcard + popups
  • + + +
  • [SPARK-993] - Improve the GUI
  • + + +
  • [SPARK-1011] - When someone says my name in an + MUC, show a custom toast popup if enabled
  • + + +
  • [SPARK-1018] - Add options to expand and + collapse all groups together
  • + + +
  • [SPARK-1049] - Turkish Language Pack
  • + + +
  • [SPARK-1052] - Create a new ant target to make + an IzPack and RPM Installer
  • + + +
  • [SPARK-1057] - Add an option to suppress + join/leave messages in the group chat
  • + + +
  • [SPARK-1072] - Add an option to make chat + window always stay on top
  • + + +
  • [SPARK-1076] - Add lithuanian translation
  • + + +
  • [SPARK-1078] - Add Lithuanian Spelling option
  • + + +
  • [SPARK-1105] - Spark should indicate different + permissions in MUC with additional icons or colors
  • + + +
  • [SPARK-1108] - Spark Kirghiz translation
  • + + +
  • [SPARK-1110] - Jingle and Flashing plugin + Chinese (CHN) translation
  • + + +
  • [SPARK-1135] - Add Korean translation
  • + + +
  • [SPARK-1141] - Allow to disable the add contact + feature
  • + + +
  • [SPARK-1143] - Add Plugin Dependencies
  • + + +
  • [SPARK-1146] - Fastpath Brasilian translation
  • + + +
  • [SPARK-1147] - Phonebook for SIPClient
  • + + +
  • [SPARK-1148] - Support Speex and iLBC Codec
  • + + +
  • [SPARK-1149] - Allow to disable and reorder sip + codecs
  • + + +
  • [SPARK-1187] - Auto tab completion in Spark
  • + + +
  • [SPARK-1201] - Create a plugin to add Send + button to chat input area
  • + + +
  • [SPARK-1246] - Publish smack.packet.PrivacyItem + class setOrder() for RC2
  • + + +
  • [SPARK-1250] - Scroll Bar does not scroll for a + window
  • + + +
  • [SPARK-1261] - Default properties should be + stored visible in the Spark bin directory
  • + + +
  • [SPARK-409] - option to disable the password + change fields
  • + + +
  • [SPARK-448] - show offline users in their + group and not in offline group
  • + + +
  • [SPARK-467] - Persist search information when + doing user searches on multiple search services.
  • + + +
  • [SPARK-640] - File Transfer detection with + disabling if necessary
  • + + +
  • [SPARK-724] - Reorder tabs in chat window
  • + + +
  • [SPARK-730] - Skin: Need to key account login + from users Enterprise License.
  • + + +
  • [SPARK-736] - Set Spark away when workstation + is locked.
  • + + +
  • [SPARK-739] - Need to add a turkish + translation to Spark.
  • + + +
  • [SPARK-799] - Server is editable on failed + login
  • + + +
  • [SPARK-801] - Add a SpellChecker in other + languages
  • + + +
  • [SPARK-877] - Add a Re-Detect Audio Devices to + SparkPhone
  • + + +
  • [SPARK-896] - Spark chat logs should be + searchable
  • + + +
  • [SPARK-915] - Tab completion of conference + room nicknames
  • + + +
  • [SPARK-928] - Hide Offline group option
  • + + +
  • [SPARK-943] - Add an option to read and copy + contact's status message
  • + + +
  • [SPARK-947] - Add QQ transport support?
  • + + +
  • [SPARK-961] - Option to leave nickname blank + by default in add contact window
  • + + +
  • [SPARK-971] - System Tray notification about + incoming messages
  • + + +
  • [SPARK-972] - Typing Notification in System + Tray
  • + + +
  • [SPARK-991] - Group Chat Highlighting
  • + +
+ + + +

Bug Fixes (more than 250 issues)

+
    + +
  • [SMACK-330] - Added missing node attribute in the item element for pubsub.
  • + +
  • [SMACK-325] - Reconnection Manager can be running twice
  • + +
  • [SMACK-334] - Error in form for FileTransferNegotiator
  • +
  • [SMACK-163] - Fix NPE in RoomInfo when subject has not value
  • + +
  • [SMACK-207] - Parsing of + messages may disconnect Smack/Spark
  • + +
  • [SMACK-225] - Improper + handeling of DNS SRV records
  • + +
  • [SMACK-232] - Better + handling of Roster error
  • + +
  • [SMACK-236] - Rename + stanza error "unexpected-condition" to + "unexpected-request"
  • + +
  • [SMACK-243] - Packet + with wrong date format makes Smack to disconnect
  • + +
  • [SMACK-258] - Fix + disconnection issue when parsing SASL success that contains a payload
  • + +
  • [SMACK-260] - error + presence packets when server is down
  • + +
  • [SMACK-264] - fix + for NPE in SASLMechanism.java
  • + +
  • [SMACK-269] - Smack + 3.1.0 creates a new chat for every incoming message
  • + +
  • [SMACK-271] - Deadlock + in XMPPConnection while login and parsing stream features
  • + +
  • [SMACK-275] - Patch: + Fix for broken SASL DIGEST-MD5 implementation
  • + +
  • [SMACK-288] - The + parsing of the result for a LeafNode.getItems() call is incorrect. It creates + a DefaultPacketExtension instead of an Item for every other item in the + result.
  • + +
  • [SMACK-290] - Deadlock + while getting Roster before it's initialized
  • + +
  • [SMACK-291] - RosterGroup + modifications should depend on roster push
  • + +
  • [SMACK-293] - Support + optional roster subscription attribute
  • + +
  • [SMACK-305] - RosterEntry#getGroups + causing a roster reload
  • + +
  • [SMACK-308] - Multiple + errors in pubsub GetItemsRequest
  • + +
  • [SMACK-312] - Only + fire RosterListener#entriesUpdated for RosterEntries that changed
  • + +
  • [SMACK-313] - Pubsub + library doesn't allow the packet id to be specified.
  • + +
  • [SMACK-316] - Smack + FromMatchesFilter behaves wrong with chats with similar names
  • + +
  • [SMACK-321] - Usage + of SimpleDateFormat is not threadsafe
  • + +
  • [SMACK-327] - getFeatures() + method on DiscoverInfo is improperly set to be package protected instead of + public
  • + +
  • [SMACK-328] - Number + format exception while parsing dates.
  • + +
  • [SMACK-332] - Smack + 3.2.0b2 shows wrong version in Smack Dubugger Window
  • + +
  • [SPARK-1320] - Errors in + privacy plugin i18n string
  • + +
  • [SPARK-1315] - Spark + cannot find spark.jar to load different languages
  • + +
  • [SPARK-1310] - Local + users are loading slowly
  • + +
  • [SPARK-1309] - Colorsettings + are possibly outdated if profile not cleaned regularly and colors.tab is + deactivated
  • + +
  • [SPARK-1305] - No + rooms are shown in room browser
  • + +
  • [SPARK-1295] - Left + menu panel in Preferences gets squeezed
  • + +
  • [SPARK-1294] - Spark + 2.6 RC2 No Phone Call Button
  • + +
  • [SPARK-743] - Changes + in the user.home directory
  • + + + +
  • [SPARK-1130] - Spark + behaves wrong with chats with similar names
  • + + +
  • [SPARK-1270] - Name Completion on Shared Rosters without Vcards causes NPE
  • +
  • [SPARK-1268] - Cursor changes to hand after sending a message
  • +
  • [SPARK-1267] - Set a default size for Preferences window for new profiles
  • +
  • [SPARK-1183] - Spellchecker is not working normally
  • +
  • [SPARK-1161] - Set a default minimum size of a tab
  • +
  • [SPARK-1068] - Spark is not reacting to outside keyboard events when setting the auto Away status
  • + +
  • [SPARK-1209] - Agent + names are missing in Fastpath Online Agents tab
  • + + +
  • [SPARK-1260] - Search + Dialog error
  • + + +
  • [SPARK-1262] - BUG: + spark_2_6_0_12103 : spark download folder not working
  • + + +
  • [SPARK-618] - Fixed multiple message issue with Broadcast.
  • + + +
  • [SPARK-1004] - if a username is too long then + it gets cut off
  • + + +
  • [SPARK-1016] - Spark should preserve custom + status between automatic changes of presence
  • + + +
  • [SPARK-1019] - Spark IRC support passing wrong + variable for nickname
  • + + +
  • [SPARK-102] - Changing temp conf room name to + permanent name leads to odd behavior
  • + + +
  • [SPARK-1020] - is part of SPARK-1228 + Spark shows wrong popup upon receiving group chat invitation
  • + + +
  • [SPARK-1022] - Linux Tray Icon not appearing
  • + + +
  • [SPARK-1023] - Add remove button to call + history
  • + + +
  • [SPARK-1027] - Prevent duplicate conferences
  • + + +
  • [SPARK-1028] - Spark is still showing null + avatars/display pictures
  • + + +
  • [SPARK-1029] - Clicking the information button + will send the chat text field
  • + + +
  • [SPARK-1034] - Spark 2.6.0b2 Does not display + the entire preference window.
  • + + +
  • [SPARK-1038] - Spark does not currently build + on OS X
  • + + +
  • [SPARK-1039] - Fastpath does not compile + against latest Smack
  • + + +
  • [SPARK-1041] - Update Spanish translation
  • + + +
  • [SPARK-1046] - Log out with reason not work on + other langauges
  • + + +
  • [SPARK-1048] - Correct accuracy of screenshot
  • + + +
  • [SPARK-1055] - is part of SPARK-1224 + Make an option to supress the reconnection popup
  • + + +
  • [SPARK-1056] - Save Spark window positions on + non-primary screen
  • + + +
  • [SPARK-1059] - Show a toast popup when + "Alert when available" is selected
  • + + +
  • [SPARK-1061] - Show new messages in systemtray + option is not working
  • + + +
  • [SPARK-1063] - Spark is not reacting to + keyboard events when setting the auto Away status
  • + + +
  • [SPARK-1064] - Scratchpad (Tasks) Dialog has + graphical errors
  • + + +
  • [SPARK-1069] - Spark continuos flashing + continues to flash after the chat window gets focus
  • + + +
  • [SPARK-1081] - Spark is now showing + APPLICATION_NAME in the tooltip
  • + + +
  • [SPARK-1082] - Spark is showing 2 systray icons + on 64-bit Windows 7
  • + + +
  • [SPARK-1083] - Fix gateway icons toolbar + initialization
  • + + +
  • [SPARK-1085] - Add Fastpath plugin to a Spark + build
  • + + +
  • [SPARK-1089] - Spark should show 24h time + stamps in a previous conversation history
  • + + +
  • [SPARK-1092] - Spark is not showing Canned + responses stored on the server and cant create new ones
  • + + +
  • [SPARK-1096] - Custom status messages should be + sorted by name
  • + + +
  • [SPARK-1097] - Delete the obsolete Available + translation string from the i18n file
  • + + +
  • [SPARK-1099] - Spark is showing received + message twice in MUC private chat
  • + + +
  • [SPARK-1101] - Fix typos in Russian translation + file
  • + + +
  • [SPARK-1109] - incorrect charset in method + MediaPreferencePanel.scanDevices on Windows 2000(CHN)
  • + + +
  • [SPARK-1111] - Recent conversation is still + showing after history cleaning with not english GUI language
  • + + +
  • [SPARK-1112] - Minor visual issues with history + cleaning
  • + + +
  • [SPARK-1116] - Private chat history in MUC is + not saving
  • + + +
  • [SPARK-1117] - Can't change priority field of a + custom status
  • + + +
  • [SPARK-1118] - Not possible to resize text + input area in the chat window
  • + + +
  • [SPARK-1122] - Spark is not sending typing + notifications
  • + + +
  • [SPARK-1124] - is part of SPARK-1228 + Chat window is not flashing when receiving new message
  • + + +
  • [SPARK-1126] - Chat window doesnt appear upon + receiving new message
  • + + +
  • [SPARK-1129] - Idle Enabled shouldn't override + a custom Away status
  • + + +
  • [SPARK-1130] - Spark behaves wrong with chats + with similar names
  • + + +
  • [SPARK-1131] - Log out stopped working in the + latest SVN
  • + + +
  • [SPARK-1132] - Couldn't Get all contact items + from ContactList
  • + + +
  • [SPARK-1133] - Contact list issue
  • + + +
  • [SPARK-1138] - Softphone panel not redisplaying + after close
  • + + +
  • [SPARK-1140] - Change to Apache 2.0 license
  • + + +
  • [SPARK-1144] - Ant buildscript should not check + for explicit Ant version numbers
  • + + +
  • [SPARK-1151] - Taskbar Flashing and + Spellchecker tabs not available in Preferences
  • + + +
  • [SPARK-1152] - Startup.sh doesn't work on + Ubuntu 10.04
  • + + +
  • [SPARK-1153] - Wrong contacts count on + reconnect
  • + + +
  • [SPARK-1154] - Linux version doesn't have Log + out option
  • + + +
  • [SPARK-1155] - Empty messages in Group Chat
  • + + +
  • [SPARK-1158] - Group title doesn't updates + after moving ContactItem from one group to another
  • + + +
  • [SPARK-1163] - Spark displays wrong error when + nickname change is forbidden
  • + + +
  • [SPARK-1164] - Chat window is not positioning + at the last history message when opening window
  • + + +
  • [SPARK-1166] - Spark is not showing a progress + of file transfer
  • + + +
  • [SPARK-1168] - Offline users are shown on login + when option is set to not to show them
  • + + +
  • [SPARK-1169] - is part of SPARK-1229 + Spark shows offline roster after reconnecting
  • + + +
  • [SPARK-1171] - Chat window is not drawn + correctly when opened on a primary monitor
  • + + +
  • [SPARK-1172] - Flashing and Spellchecker + options are absent in Preferences
  • + + +
  • [SPARK-1173] - Reconnection with new and + different IP fails after network loss
  • + + +
  • [SPARK-1180] - Fix the placement of the + Bookmarks menu
  • + + +
  • [SPARK-1182] - File path for a URL bookmark is + not working
  • + + +
  • [SPARK-1186] - Ctrl + W not working as expected + in chat window
  • + + +
  • [SPARK-1189] - Spark systray menu is overlapped + by vertical taskbar
  • + + +
  • [SPARK-1194] - Move/copy contact item to new + group don't check item into new group offline contacts
  • + + +
  • [SPARK-1196] - is part of SPARK-1223 + Spellchecker Bug: Java AWT-EventQueue-1 - null pointer exception
  • + + +
  • [SPARK-1206] - is part of SPARK-1228 + New chat window is not opened while receiving offline messages on login
  • + + +
  • [SPARK-1211] - Spark doesn't show room in the + rooms list
  • + + +
  • [SPARK-1212] - Shouldn't be able to search for + yourself and add yourself to a roster
  • + + +
  • [SPARK-1213] - Spark duplicates rooms in the + conference browser when hitting Refresh button fast
  • + + +
  • [SPARK-1216] - Upgrade Smack in Trunk to Smack + 3.2 beta 2
  • + + +
  • [SPARK-1217] - Locales prevent Plugins from + loading
  • + + +
  • [SPARK-1219] - is part of SPARK-1230 + Polish translation
  • + + +
  • [SPARK-1221] - is part of SPARK-1223 + Bookmark Plugin causes error in error log
  • + + +
  • [SPARK-1225] - is part of SPARK-1223 + Warning Log4J: No appenders could be found for logger
  • + + +
  • [SPARK-1226] - is part of SPARK-1223 + SIP Codec causes error on load
  • + + +
  • [SPARK-1227] - is part of SPARK-1223 + [Patch] Remove sound driver report from error log
  • + + +
  • [SPARK-1229] - Masterticket: Roster Management
  • + + +
  • [SPARK-1231] - Wrong time on loading history + messages in conferences
  • + + +
  • [SPARK-1233] - [Patch ready to commit] Mouse + Click on Avatar in VCard Preview opens another VCard Preview
  • + + +
  • [SPARK-1237] - Remove stun.xten.net as fixed + URL for STUN fall back from Jingle. This should be set in spark.properties
  • + + +
  • [SPARK-1240] - Spark is not saving "Show + empty groups" setting between restarts
  • + + +
  • [SPARK-1241] - is part of SPARK-1223 + UiThreadingViolationException when loading Flashing Plugin
  • + + +
  • [SPARK-1242] - Group disappears after a rename.
  • + +
  • [SPARK-1248] - is part of SPARK-1223 + ArrayIndexOutOfBoundsException in + javax.swing.plaf.basic.BasicListUI.updateLayoutState
  • + + +
  • [SPARK-1249] - is part of SPARK-902 + item-not-found(404) in PrivacyManager
  • + + +
  • [SPARK-1251] - is part of SPARK-902 + PrivacyPlugin causes NullPointerE. when clicking on "block + contact"
  • + + +
  • [SPARK-1252] - is part of SPARK-902 + PrivcyPlugin No rightclick menu on ContactGroups
  • + + +
  • [SPARK-1255] - Translator plugin is not working
  • + + +
  • [SPARK-1256] - Remove & from Check for + updates menu entry
  • + + +
  • [SPARK-158] - Unable to open files after file + transfer.
  • + + +
  • [SPARK-210] - Kicked out user gets incomplete + message, and upon re-entry, doesn't see other room participants
  • + + +
  • [SPARK-237] - Add debug mode to allow for full + debugging capabilities on startup.
  • + + +
  • [SPARK-24] - Memory does not decrease after + closing chat window.
  • + + +
  • [SPARK-261] - Paste in ChatWindow does not + work as expected.
  • + + +
  • [SPARK-278] - URL parser issues
  • + + +
  • [SPARK-284] - Same Alt-? hotkeys set for + different options on the same menu
  • + + +
  • [SPARK-286] - unicode display bug / window + title
  • + + +
  • [SPARK-311] - File Transfer Not Possible + Unless User Is in Contact List
  • + + +
  • [SPARK-340] - is part of SPARK-1229 + Duplicate text entries appear when reconnecting Spark
  • + + +
  • [SPARK-349] - MUC / Create Room: fix strange + behaviour
  • + + +
  • [SPARK-381] - Users with European characters + in their JID can not login
  • + + +
  • [SPARK-404] - Chat history should be saved on + a timer and on shutdown.
  • + + +
  • [SPARK-421] - Add new file transfer within + HTML Viewer.
  • + + +
  • [SPARK-423] - Need a default Spark Theme for + the Chat Window themes.
  • + + +
  • [SPARK-455] - Auto away status does not work + in LInux version of Spark
  • + + +
  • [SPARK-458] - Add support for 64 bit machines
  • + + +
  • [SPARK-475] - Spark 2.0.8 custom skin w/ + wildfire spark version set, always thinks there's a newer version
  • + + +
  • [SPARK-547] - Decrease screenshot memory usage
  • + + +
  • [SPARK-570] - display all received chat + messages
  • + + +
  • [SPARK-572] - Custom status messages under + "On Phone" status now show as phone icon.
  • + + +
  • [SPARK-575] - Spark does not un-escape + usernames properly
  • + + +
  • [SPARK-581] - Fix cut and paste issue in Chat + Window.
  • + + +
  • [SPARK-586] - remove top-left JMC window
  • + + +
  • [SPARK-608] - Updated Spark to use latest + workgroup api.
  • + + +
  • [SPARK-619] - On Linux a user does not come + back from the "Away due to idle" to "Available"
  • + + +
  • [SPARK-624] - ChatRoomNotFoundException + receiving a broadcast
  • + + +
  • [SPARK-625] - Fixes for Jingle on Linux
  • + + +
  • [SPARK-627] - Fixes for SIP on Debian
  • + + +
  • [SPARK-631] - Fix layout for long names in + roster
  • + + +
  • [SPARK-632] - Small "Join Conference + Room" windows in Linux and Vista
  • + + +
  • [SPARK-637] - BUZZ highlight chat tab
  • + + +
  • [SPARK-64] - some animated avatars don't work
  • + + +
  • [SPARK-657] - Improvements for Private Chats + from a Conference Room
  • + + +
  • [SPARK-667] - Spark should only transform + first /me
  • + + +
  • [SPARK-690] - JMF cannot find formats on VISTA
  • + + +
  • [SPARK-692] - multiple bugs with 64-bit OS on + LInux
  • + + +
  • [SPARK-696] - Roster gets out of order over + time
  • + + +
  • [SPARK-697] - Unable to load plugin + TranslatorPlugin
  • + + +
  • [SPARK-699] - Spark is sending multiple, + duplicate, inconsistent Disco Info responses
  • + + +
  • [SPARK-706] - Usernames need to be escaped + when looking up profiles.
  • + + +
  • [SPARK-708] - Need to remove any network calls + when opening a chat room.
  • + + +
  • [SPARK-71] - Custom status messages should be + available in system tray
  • + + +
  • [SPARK-710] - Right-click on URL link inside + transcript window causes browser to be invoked.
  • + + +
  • [SPARK-712] - Groupchat List can become + corrupted.
  • + + +
  • [SPARK-713] - URLs with commas break before + first comma
  • + + +
  • [SPARK-715] - Login screen uses password from + memory if it exists and not the login field.
  • + + +
  • [SPARK-720] - Communication end is not + interpreted
  • + + +
  • [SPARK-721] - Rejecting a SIP call in Spark + does not reject the hard phone call
  • + + +
  • [SPARK-734] - Error: Couldn't find per display + information - JDK 1.6 on Linux
  • + + +
  • [SPARK-741] - Incorrect list of people in the + group chat
  • + + +
  • [SPARK-749] - Ctrl+F does not sort user names
  • + + +
  • [SPARK-750] - chat history not saved
  • + + +
  • [SPARK-756] - Users Leave and Rejoin Groupchat + Causes Them to Not Appear in User List
  • + + +
  • [SPARK-762] - Can Receive Multiple Invitations + To The Same Room
  • + + +
  • [SPARK-765] - Messages without type attribute + are displayed twice (broadcasts)
  • + +
  • [SPARK-769] - is part of SPARK-1229 + Autoreconnect does not always complete the "session + establishment" and does not request users' presence
  • + + +
  • [SPARK-772] - registration / JID escaping
  • + + +
  • [SPARK-776] - Remove systray icon after close
  • + + +
  • [SPARK-777] - is part of SPARK-1229 + Hidden Empty Groups do not become visible
  • + + +
  • [SPARK-780] - is part of SPARK-1224 + Cannot load contacts on reconnection
  • + + +
  • [SPARK-788] - Some avatars are not correctly + displayed
  • + + +
  • [SPARK-789] - Some text not internationalized
  • + + +
  • [SPARK-806] - Chat text box does not have a + scroll when the text to send is large
  • + + +
  • [SPARK-814] - is part of SPARK-1155 + Empty Conversations in Group Chat
  • + + +
  • [SPARK-815] - Local time is not completed in + the Client Version
  • + + +
  • [SPARK-816] - The google talk emoticon: \m/ is + not translated to gif
  • + + +
  • [SPARK-824] - Group Chat Messages from blocked + users are displayed in the Toast Popup
  • + + +
  • [SPARK-835] - Update translations inside Spark
  • + + +
  • [SPARK-841] - Spark does not notify a user + when they are removed from the room.
  • + + +
  • [SPARK-848] - Jabber:IQ:Time not showing up on + request.
  • + + +
  • [SPARK-861] - Spark skinning windows installer + requires MSVCR71.dll
  • + + +
  • [SPARK-872] - Skinned spark does not handle + xmpp: addresses
  • + + +
  • [SPARK-878] - Linux idle plugin not properly + handling coming back from idle
  • + + +
  • [SPARK-879] - Double contacts appear in + roster.
  • + + +
  • [SPARK-883] - Control+T window shows no data
  • + + +
  • [SPARK-886] - Reconnection logic not working + properly
  • + + +
  • [SPARK-889] - New tab/window focus does not + cause focus to be in typing area of window
  • + + +
  • [SPARK-892] - is part of SPARK-1224 + Spark should automatically reconnect you to chatrooms after a reconnection
  • + + +
  • [SPARK-897] - PARK-874 still seems to be + occuring
  • + + +
  • [SPARK-898] - org/jivesoftware/spark/ui/RetryPanel.java + uses non-standard Smack
  • + + +
  • [SPARK-901] - Fix JVM crash when using Jingle + on the Mac OS X
  • + + +
  • [SPARK-903] - Removing a bookmark doesn't + remove it from the bookmarks menu in os x, maybe others
  • + + +
  • [SPARK-906] - Spark's build should unpack + .pack'd files at build time, not at first startup
  • + + +
  • [SPARK-908] - Messages sent by pressing the + View Profile Icon
  • + + +
  • [SPARK-909] - Spark Crashes after ending a + Muted Call
  • + + +
  • [SPARK-910] - Some avatars are not displayed
  • + + +
  • [SPARK-913] - Settings not always being saved + after changes made
  • + + +
  • [SPARK-914] - Spark does not handle messages + with subjects very well
  • + + +
  • [SPARK-917] - Spark Phone is not Unregistering + on Spark Logout
  • + + +
  • [SPARK-921] - Sometimes Spark can't change to + Available automatically
  • + + +
  • [SPARK-922] - is part of SPARK-1228 + Broadcast window resizing should be fixed
  • + + +
  • [SPARK-923] - Fix room topic change tooltip
  • + + +
  • [SPARK-924] - Fix incoming message + notification tooltip showing wrong presence status
  • + + +
  • [SPARK-925] - Should receive offline + broadcasts after logging in
  • + + +
  • [SPARK-926] - Custom status editing no longer + working in trunk
  • + + +
  • [SPARK-937] - Wrong notification popup upon + receiving a file
  • + + +
  • [SPARK-941] - Pressing Cancel in "Log out + with reason" window shouldnt log out
  • + + +
  • [SPARK-944] - After language change should be + "Exit now?", not "Restart now?"
  • + + +
  • [SPARK-950] - Spark is not showing /" + chars in chat window
  • + + +
  • [SPARK-952] - Links will not open from chat + windows under Linux
  • + + +
  • [SPARK-960] - Spark does not remember group + state.
  • + + +
  • [SPARK-962] - Spark gets confused when + multiple conference services are available
  • + + +
  • [SPARK-969] - When someone performs a file + transfer or non-message related event, the last message before it is shown in + growl notifications
  • + + +
  • [SPARK-978] - Buzz delay should not reset + after closing chat window
  • + + +
  • [SPARK-988] - DoS (disconnect of other + clients)
  • + + +
  • [SPARK-990] - View Downloads doesn't pop-up + Downloads window
  • + + +
  • [SPARK-994] - Bookmarks menu is not refreshing + immediately
  • + + +
  • [SPARK-997] - An error occurs when enetering + no Gateway username
  • + +
+ + + + +

2.5.8 -- November 14th, 2007

+

New Features

+
    +
  • [SPARK-820] - Empty roster items now show jid instead of blank.
  • +
  • [SPARK-856] - Updated avatar size in contact list, also selectable from three choices.
  • +
  • [SPARK-867] - GaduGadu, IRC, and SIMPLE transports now supported.
  • +
  • [SPARK-868] - Entire status message now displayed with word/line wrapping on tooltip.
  • +
  • SIP Phone plugin is now open source.
  • +
+ +

Bug Fixes

+
    +
  • [SPARK-618] - Fixed multiple message issue with Broadcast.
  • +
  • [SPARK-857] - Fixed language selection menu is not displaying.
  • +
  • [SPARK-860] - Show offline users in broadcast window.
  • +
  • [SPARK-855] - Allowed mainWindowHeight to have low values.
  • +
  • [SPARK-869] - Gateway icons are now lightning up properly.
  • +
  • [SPARK-870] - Window positions/sizes are being saved upon window close now.
  • +
  • [SPARK-874] - Spark is now able to handle the new conference search capability of Openfire 3.4.1
  • +
+ +

2.5.7 -- September 20th, 2007

+

New Features

+
    +
  • [SPARK-792] - Add Language Selection to Spark Installation
  • +
  • [SPARK-846] - Allow option to show avatars in Contact List.
  • +
+ +

Bug Fixes

+
    +
  • [SPARK-782] - Fixed system tray with limited users and on linux.
  • +
  • [SPARK-818] - Improvements to reconnection code.
  • +
  • [SPARK-825] - Fixed sip stack sending superfluous REGISTER Packet
  • +
  • [SPARK-827] - Fixed limited users issue.l
  • +
  • [SPARK-829] - Fixed XMPP URI in registry.
  • +
  • [SPARK-830] - Fixed start on startup issue with installer.
  • +
  • [SPARK-831] - Fixed XMPP URI not starting conversations when spark is not running.
  • +
  • [SPARK-832] - Fixed offline messages not showing up in certain situations.
  • +
  • [SPARK-833] - Fixed bad MSI installer.
  • +
  • [SPARK-834] - Upgraded to the latest SMACK.
  • +
  • [SPARK-836] - JNIWrapper is now being included with the linux distro.
  • +
  • [SPARK-838] - Fixed gateway issue on initial roster loading.pear.
  • +
  • [SPARK-839] - Fixed loading of spark in system tray.
  • +
  • [SPARK-840] - Added chinese translation to Spark
  • +
+ +

2.5.6 -- August 23rd, 2007

+

Bug Fixes

+
    +
  • [SPARK-767] - Fixed roster not populating offline users in their respective groups.
  • +
  • [SPARK-807] - Fixed sending of empty broadcast messages.
  • +
  • [SPARK-810] - Added in system tray for linux (requires Java 1.6)
  • +
  • [SPARK-811] - Fixed spark not loading JMF Native libraries
  • +
  • [SPARK-813] - Added GTalk and XMPP gateways.
  • +
  • [SPARK-819] - Fixed issue with file picker hanging spark.
  • +
  • [SPARK-821] - Fixed timestamps in conference rooms.
  • +
  • [SPARK-823] - Explicit loading of plugins no longer fails due to wrong classloader.
  • +
+ +

2.5.5 -- August 5th, 2007

+

Bug Fixes

+
    +
  • [SPARK-719] - Fixed communication time in Phone.
  • +
  • [SPARK-755] - Fixed Spark crash after login with latest jvm build 1.6.0_01-b06
  • +
  • [SPARK-773] - Fixed file transfer issue after reconnection.
  • +
  • [SPARK-774] - Fixed search service issue after reconnection.
  • +
  • [SPARK-781] - Fixed one to one conversation in group chat room using a single user.
  • +
  • [SPARK-782] - Fixed system tray not appearing on certain users computers.
  • +
  • [SPARK-784] - Update spanish translation file.
  • +
  • [SPARK-786] - Updated the italian translation.
  • +
  • [SPARK-790] - Fixed toaster not timing with Fastpath notifications.
  • +
  • [SPARK-793] - Fixed bookmarks causing NPE on room discovery.
  • +
  • [SPARK-797] - Spark should not show presence updates in chat window if the user is still online.
  • +
  • [SPARK-798] - Fixed chat window not opening when Timer is cancelled.
  • +
  • [SPARK-800] - Increased File Transfer timeout time.
  • +
+ +

2.5.4 Beta 1 -- June 11th, 2007

+

Bug Fixes

+
    +
  • [SPARK-759] - Fixed File transfer issue on Mac OSX.
  • +
  • [SPARK-763] - Moving all native code to plugin for better linux support.
  • +
  • [SPARK-766] - One to one conversation in group chat room always sending to same user.
  • +
  • [SPARK-770] - Need to fix minor i18n German translation issues.
  • +
  • [SPARK-771] - Multiple offline contacts showing up in roster after reconnection.
  • +
+ + + +

2.5.3 Beta 2 -- May 28th, 2007

+ +

Bug Fixes

+
    +
  • [SPARK-748] - Ctrl-f does not pick up different users with same contact name.
  • +
  • [SPARK-753] - FRAME_IMAGE not found
  • +
  • [SPARK-757] - Upgrade smack to fix SRV DNS issue in SASL.
  • +
  • [SPARK-758] - Spark needs to send messages to full jid on opening of chat room.
  • +
+ + +

2.5.3 Beta 1 -- May 11th, 2007

+ +

New Features

+
    +
  • [SPARK-111] - Users can now select contact items from multiple groups, which allows for better broadcast handling.
  • +
  • [SPARK-662] - Add new emoticons to default emoticon pack.
  • +
  • [SPARK-725] - Added Single Sign-ON (SSO) support.
  • +
  • [SPARK-727] - Added new Spark Users Guide
  • +
  • [SPARK-729] - Skin: Added option for SSO boolean. If selected Spark just tries to connect to the given server as an SSO situation.
  • +
  • [SPARK-735] - Added integrated sso - smack code into Spark.
  • +
+ +

Bug Fixes

+
    +
  • [SPARK-718] - Fixed small asterisk-IM issue.
  • +
  • [SPARK-732] - Fixed conference room participant list issue when renaming nickname.
  • +
  • [SPARK-742] - Jingle now uses preffered codec.
  • +
  • [SPARK-746] - Fixed issue with Update checker not updating users from beta to release.
  • +
  • [SPARK-748] - Fixed CTRL+F issue handling multiple matching nicknames.
  • +
+ +

2.5.2 -- May 3rd, 2007

+ +

New Features

+
    +
  • [SPARK-2] - Spark now display offline status information.
  • +
  • [SPARK-399] - Added new color randomizer for user names in group chat rooms.
  • +
  • [SPARK-401] - Added better error handling during conference room creation.
  • +
  • [SPARK-609] - Added a new Conference invitation ui.
  • +
  • [SPARK-661] - Updated the Italian translation.
  • +
  • [SPARK-664] - Added beta release support to the upgrade notification system.
  • +
  • [SPARK-665] - Change update checks to weekly.
  • +
  • [SPARK-674] - Added RTP Media Listening for jingle, improving connectivity check.
  • +
  • [SPARK-679] - Improved notifications when user comes online/offline.
  • +
  • [SPARK-691] - Improved UI for contact list groups.
  • +
  • [SPARK-701] - Added Japanese translation.
  • +
+ +

Bug Fixes

+
    +
  • [SPARK-598] - MSI now supports automatic upgrades.
  • +
  • [SPARK-626] - Added in missing jars to classpath on linux.
  • +
  • [SPARK-659] - Socks5 proxy not uses the username and password.
  • +
  • [SPARK-666] - Fixed file transfer timeout issue.
  • +
  • [SPARK-669] - Fixed issue with invalid title showing up in contact info.
  • +
  • [SPARK-682] - Dialing an invalid number is now handled properly by Spark
  • +
  • [SPARK-693] - Changed the buzz icon tool tip.
  • +
  • [SPARK-704] - Users are now able to create new conference rooms when using limited permissions for Group Chat.
  • +
  • [SPARK-714] - SparkPhone handles registration failures properly.
  • +
+ + +

2.5.2 Beta 1 -- April 20th, 2007

+ +

New Features

+
    +
  • [SPARK-399] - Added color randomizer for user names in group chat rooms.
  • +
  • [SPARK-609] - Added new Conference Invitation UI.
  • +
  • [SPARK-674] - Added RTP Media Listening for jingle, improving connectivity check.
  • +
  • [SPARK-691] - Improved UI for contact list groups.
  • +
  • [SPARK-701] - Added Japanese translation.
  • +
+ +

Bug Fixes

+
    +
  • [SPARK-2] - Spark now displays offline status messages.
  • +
  • [SPARK-401] - Added better error handling during MUC creation.
  • +
  • [SPARK-598] - Fixed issue with upgrades and MSI builds.
  • +
  • [SPARK-626] - Fixed issue with missing jars from the classpath in Linux.
  • +
  • [SPARK-659] - Socks5 proxy now uses specified username and password.
  • +
  • [SPARK-661] - Updated Italian translation.
  • +
  • [SPARK-664] - Add beta releases to the upgrade notification system
  • +
  • [SPARK-665] - Changed update check to check only once a week and not on every log in.
  • +
  • [SPARK-666] - Fixed file transfer on Mac.
  • +
  • [SPARK-669] - Fixed issue with VCard info showing up for the wrong contact.
  • +
  • [SPARK-679] - Improved notification when user comes online.
  • +
  • [SPARK-682] - Dialing an invalid number is now handled properly by Spark.
  • +
  • [SPARK-693] - Fixed buzz icon tooltip.
  • +
  • [SPARK-714] - Fixed issue with SparkPhone opening 2 Phone Panel after several registration fails and many disconnections
  • +
+ +

2.5.1 -- April 14th, 2007

+ +

No Changes.

+ + +

2.5.1 Beta 1 -- April 9th, 2007

+ +

New Features

+
    +
  • [SPARK-2] - Show offline status information
  • +
+ + +

Bug Fixes

+
    +
  • [SPARK-623] - Fixed error when trying to establish a voice communication.
  • +
  • [SPARK-633] - Fixed screenshot issue on Linux.
  • +
  • [SPARK-644] - Fixed timing issue with Jingle calls and UI.
  • +
  • [SPARK-645] - Fix tab switching issue on Mac.
  • +
  • [SPARK-647] - Fixed growl issue on Mac.
  • +
  • [SPARK-649] - Fixed screenshot tool on Mac.
  • +
  • [SPARK-650] - Improved descriptive text for Jingle calls.s
  • +
  • [SPARK-652] - Fixed issue with missing icon when viewing plugin information.
  • +
  • [SPARK-654] - Fixed issue registering soft phone on Mac.
  • +
  • [SPARK-655] - Fixed buzz icon and placement
  • +
  • [SPARK-656] - Installer is now adding desktop shortcuts.
  • +
  • [SPARK-658] - Added in missing emoticons.
  • +
  • [SPARK-660] - Emoticon packs can now be unzipped without admin rights.
  • +
  • [SPARK-668] - Fixed issue where first message would be dropped.
  • +
  • [SPARK-673] - Fixed logic with update checker and beta/alpha releases.
  • +
  • [SPARK-681] - Spark now closes a Jingle Session if it establish and don't receive media for more than X(20) seconds
  • +
  • [SPARK-689] - Fixed jingle binding issue on Vista.
  • +
+ +

2.5.0 -- March 30th, 2007

+ +

New Features

+
    +
  • [SPARK-2] - Now show status of offline users.
  • +
  • [SPARK-382] - Added ctrl+e to display last 10 conversations.
  • +
  • [SPARK-410] - Now all plugins to be operating-system specific
  • +
  • [SPARK-559] - Refactored ContactList, ContactGroup and ContactItem to allow all event operations to run through the ContactList itself.
  • +
  • [SPARK-561] - Added new tray notification for incoming fastpath chat requests.
  • +
  • [SPARK-567] - Added Pack200 support to lower the overall deployment size of Spark.
  • +
  • [SPARK-568] - Added typing notification for Fastpath Conference chats.
  • +
  • [SPARK-571] - Added client to client VOIP support.
  • +
  • [SPARK-255] - Added drag and drop contacts into conference rooms to invite.
  • +
  • [SPARK-452] - Added IRC-Style Shortcuts
  • +
  • [SPARK-200] - Allow drag and drop out of the chat window before and after file transfer
  • +
  • [SPARK-517] - Simplified the viewing of users vCard information.
  • +
  • [SPARK-519] - Bookmarks are now located in the Spark main window menu bar.
  • +
  • [SPARK-515] - Spark now has an Enhanced Look and Feel.
  • +
  • [SPARK-518] - Added new auto-grow send field box.
  • +
  • [SPARK-523] - Added support for chat and email options in contact tooltips.
  • +
  • [SPARK-524] - Spark now shows full address of conference room.
  • +
  • [SPARK-528] - Message history is now grouped by Day, Month, Year.
  • +
  • [SPARK-531] - Added the new "Buzz" feature, which allows users to give others a little nudge.
  • +
  • [SPARK-485] - Added preference to specify tabs on top or bottom of Chat Room.
  • +
  • [SPARK-562] - Added Workgroup to Workgroup transfer.
  • +
  • [SPARK-563] - Added in Queue To Queue transfer.
  • +
  • [SPARK-610] - Added OSX dock notification with new incoming messages.
  • +
+ +

Bug Fixes

+
    +
  • [SPARK-453] - Linux distribution no longer depends on the windows dir.
  • +
  • [SPARK-471] - Fixed presence issue inside chat rooms.
  • +
  • [SPARK-510] - Conference Invitation page needs UI improvements.
  • +
  • [SPARK-551] - Handle gateway jids and adding of gateway users more gracefully.
  • +
  • [SPARK-552] - Added new error handling UI for Soft Phone.
  • +
  • [SPARK-553] - Presence now changes back to normal presence when hanging up phone call.
  • +
  • [SPARK-554] - Opening of a chat room now hides contact tooltip.
  • +
  • [SPARK-555] - Usernames with escapeable characters are now handled correctly in history.
  • +
  • [SPARK-556] - VCardManager now caches invalid vCards to prevent network abuse.
  • +
  • [SPARK-557] - Soft Phone only loads vCards if the user is registered.
  • +
  • [SPARK-558] - IRC-Style Shortcuts are now displayed in history.
  • +
  • [SPARK-565] - Users are now notified that they need to reconnect to a conference room when disconnected.
  • +
  • [SPARK-314] - Fixed Apple-W to close a chat tab/window.
  • +
  • [SPARK-376] - Fixed problem with usernames with characters like \ / : * ? " < > | in their name.
  • +
  • [SPARK-455] - Fixed auto away issue on linux.
  • +
  • [SPARK-456] - Fix issue with links in send area.
  • +
  • [SPARK-463] - Fixed issue with spaces in gateway contact names.
  • +
  • [SPARK-472] - Fixed double messages with broadcasts.
  • +
  • [SPARK-478] - Fixed issue with losing conference invitations after Spark reconnects.
  • +
  • [SPARK-481] - Fixed reconnect issue with idle.
  • +
  • [SPARK-486] - Timestamps are no correct when running on Vista.
  • +
  • [SPARK-487] - Users can now send screen shots when running Spark on Vista
  • +
  • [SPARK-488] - Fixed file transfer on Vista
  • +
  • [SPARK-500] - Fixed gateway presence change when user is disconnected causes Spark crash.
  • +
  • [SPARK-501] - Fixed Ctrl+F issue on OSX.
  • +
  • [SPARK-502] - Turned off DTD validation in EmoticonManager.
  • +
  • [SPARK-503] - Fixed grin emoticon not showing issue.
  • +
  • [SPARK-509] - Fixed multiple presences being sent issue on VCard change.
  • +
  • [SPARK-511] - No longer put users in invalid conference room.
  • +
  • [SPARK-532] - Spark now alert users when there is no program associated with a file a user is trying to open after File Transfer.
  • +
  • [SPARK-534] - Linux build is no longer corrupted.
  • +
  • [SPARK-535] - Spark no longer validates DTD for Emoticons.plist.
  • +
  • [SPARK-536] - MSI files now contain the Spark.exe file.
  • +
  • [SPARK-537] - Added a universal binary of the JavaApplicationStub for Spark.
  • +
  • [SPARK-538] - Fastpath auto-logs in after disconnect.
  • +
  • [SPARK-540] - Improved error message on login failure.
  • +
  • [SPARK-542] - HTTPS Proxy is now working.
  • +
  • [SPARK-543] - Notifications can now be disabled.
  • +
  • [SPARK-544] - Roster window shows nickname option if specified in Profile.
  • +
  • [SPARK-545] - Clearing avatar takes immeditate effect.
  • +
  • [SPARK-546] - Chat History now shows approriate nicknmes when possible.
  • +
  • [SPARK-549] - [Mac] Starting new conversations no longer fails to bring the message window to the front
  • +
  • [SPARK-550] - Fixed notification issue with tray popups and bring to front.
  • +
  • [SPARK-497] - Fixed "Away due to idle" on/off preference issue.
  • +
  • [SPARK-499] - Fixed error occuring when choosing invalid emoticon packs.
  • +
  • [SPARK-505] - Fixed loading of cached vcard when editing personal profile.
  • +
  • [SPARK-508] - Conference rooms jids are now escaped.
  • +
  • [SPARK-513] - Fixed inconsistent behavior in tab notifications.
  • +
  • [SPARK-514] - Fixed loading of file chooser in avatar panel.
  • +
  • [SPARK-516] - Spark now uses default look and feel when running on Windows Vista.
  • +
  • [SPARK-520] - Fixed hanging of Spark when adding new contacts.
  • +
  • [SPARK-521] - Group chat rooms now ignore presences with type error.
  • +
  • [SPARK-522] - Tabs within Spark are now easier to determine active/inactive.
  • +
  • [SPARK-525] - Spark no longer persists password if user requests password to not be saved.
  • +
  • [SPARK-526] - Fixed "Join on startup" in Conference room tab.
  • +
  • [SPARK-527] - Auto-joined rooms now display spell-checker and emoticon picklist.
  • +
  • [SPARK-529] - Conference invitation dialog now shows names in alphabetical order along with their presence.
  • +
  • [SPARK-235] - Spark now supports Adium emoticon packs.
  • +
  • [SPARK-390] - Fixed presence issue caused by installed gateways.
  • +
  • [SPARK-405] - Conference bookmarks are now persisted on the server.
  • +
  • [SPARK-420] - Fixed window repainting on tab transitions.
  • +
  • [SPARK-424] - Fixed contact list error occuring on reconnect.
  • +
  • [SPARK-427] - Spark now allows for actions to occur on tooltips.
  • +
  • [SPARK-473] - Fixed presence issue in group chat rooms.
  • +
  • [SPARK-483] - Update logic in show/away actions on tray icon.
  • +
  • [SPARK-484] - Auto Login into conference rooms causes chat room buttons to not appear.
  • +
  • [SPARK-491] - Bookmarks are now persisted to the server.
  • +
  • [SPARK-492] - Spark now defaults presence priority to 1 rather than 0.
  • +
  • [SPARK-493] - Chat history broken
  • +
  • [SPARK-494] - Transcripts were being corrupted when persisting Unicode.
  • +
  • [SPARK-506] - Fixed send field resize issue when chat frame was resized.
  • +
  • [SPARK-507] - Fixed asterisks plugin. Asterisks is now fully functional.
  • +
  • [SPARK-530] - Improved performance of loading and persisting of transcripts.
  • + + +
  • [SPARK-569] - Jingle doesn't detect when other client supports Jingle
  • +
  • [SPARK-574] - Workgroup now accepts AgentSession status change.
  • +
  • [SPARK-576] - Typing in chat window disabled after re-connect
  • +
  • [SPARK-577] - Fixed softphone issue when preferecnes could not be loaded.
  • +
  • [SPARK-578] - Available Contacts does not display properly in OSX.
  • +
  • [SPARK-579] - Jingle UI will now show regardless of volume control settings.
  • +
  • [SPARK-580] - MSI build now uses pack200 builds.
  • +
  • [SPARK-582] - Growl notifications in OSX are now working properly.
  • +
  • [SPARK-583] - Fixed Typing notification in ContactList
  • +
  • [SPARK-584] - Ctrl-x and cut now work correctly in send area.
  • +
  • [SPARK-585] - Fixed VCard viewer close button issue.
  • +
  • [SPARK-587] - Update file pickers within Spark
  • +
  • [SPARK-588] - Window controls will not go away
  • +
  • [SPARK-589] - Fixed issue with fastpath tabs turning red without having any new messages.
  • +
  • [SPARK-590] - Fixed layout setting of chat window.
  • +
  • [SPARK-591] - Disconnected spark no longer attempts online activities.
  • +
  • [SPARK-592] - Fixed stale chats.
  • +
  • [SPARK-593] - Updated ringing sound file.
  • +
  • [SPARK-594] - Added notification in Jingle rooms when negotiating call.
  • +
  • [SPARK-595] - Fixed SIP Regsitration on computers with VMWare.
  • +
  • [SPARK-596] - Removed contact info options in tooltip.
  • +
  • [SPARK-597] - Added new icon to represent Jingle calls.
  • +
  • [SPARK-599] - Gateways are no longer loaded on the event thread.
  • +
  • [SPARK-600] - Broadcast button in wrong place
  • +
  • [SPARK-601] - Ending SIP calls does not work properly
  • +
  • [SPARK-602] - Last activity on unsupported clients is handled more gracefully.
  • +
  • [SPARK-603] - SIP: Caller ID missing from incoming call notification
  • +
  • [SPARK-604] - SIP: wrong icon in missed calls list
  • +
  • [SPARK-605] - SIP: two bugs in call history
  • +
  • [SPARK-606] - SIP: escape button doesn't work on dedicated call tab
  • +
  • [SPARK-607] - SIP: voicemail button should always show number of messages
  • +
  • [SPARK-611] - Fixed layout of command buttons on OSX.
  • +
  • [SPARK-612] - Spark now displays notifications from Gateways.
  • +
  • [SPARK-613] - Gateway icons now display disconnection from gateways.
  • +
  • [SPARK-614] - Fixed issue with reconnection.
  • +
  • [SPARK-616] - Fixed issue with redial in Soft Phone.
  • +
  • [SPARK-617] - Send correct presence upon reconnection.,
  • +
  • [SPARK-618] - Fixed multiple message issue with Broadcast.
  • +
  • [SPARK-620] - Mute does not work
  • +
  • [SPARK-621] - Clicking on a user's avatar, then view full profile brings up "edit profile information"
  • +
  • [SPARK-622] - Error at reconnection - no users are connected
  • +
  • [SPARK-628] - No room found answering a SIP call
  • +
  • [SPARK-629] - Fixed incoming Jingle call ui when user has no vcard.
  • +
  • [SPARK-630] - Updated Spark message icon.
  • +
  • [SPARK-641] - Fix User Home Directory in Linux to ".Spark"
  • +
  • [SPARK-646] - SIP Previous Conversations List is in reverse order
  • +
+ + +

2.0.8 -- January 23rd, 2007

+ +

New Features

+
    +
  • [SPARK-462] - Added notification preferences for user presence.
  • +
+

Bug Fixes

+
    +
  • [SPARK-449] - Fix chat transcript parsing error with UTF-8
  • +
  • [SPARK-450] - Fixed tab refreshing problem.
  • +
  • [SPARK-460] - Remove old icons from group chat room.
  • +
  • [SPARK-461] - Improved Toaster popup UI
  • +
  • [SPARK-465] - Conference Participant list becomes corrupted on presence changes.
  • +
  • [SPARK-468] - Logging out with Chat windows open does not save chat transcript.
  • +
  • [SPARK-469] - Spark needs to do update checks against the new Ignite site.
  • +
  • [SPARK-470] - VCard loading for email chat info should not be in own thread.
  • +
  • [SPARK-475] - Spark 2.0.8 custom skin w/ wildfire spark version set, always thinks there's a newer version
  • +
  • [SPARK-476] - Asterisks plugin is fully functional.
  • +
  • [SPARK-477] - Users are being removed from the participant list on presence change.
  • +
  • [SPARK-479] - VCard caching not updating avatar.
  • +
  • [SPARK-480] - Stale chats logic removes incoming message notification.
  • +
+ +

2.0.7 -- December 4th, 2006

+ +

New Features

+
    +
  • [SPARK-444] - Added one-click hide from system tray.
  • +
  • [SPARK-445] - Added simple log viewer.
  • +
  • [SPARK-447] - Added Typing notification to individual tabs and Frame.
  • +
  • [SPARK-398] - Nicknames should be sortable in group chat rooms.
  • +
+

Bug Fixes

+
    +
  • [SPARK-428] - Fixed issue with removing start on startup in preferences.
  • +
  • [SPARK-435] - Setting presence to DND works correctly.
  • +
  • [SPARK-436] - Verify new JID escaping with transports works correctly.
  • +
  • [SPARK-437] - Auto reconnect to notify each connection manager to reset themselves.
  • +
  • [SPARK-438] - Rooms need to be active when Reconnection was successfull
  • +
  • [SPARK-439] - Yahoo! Logo shows up in vcard popup for offline users
  • +
  • [SPARK-440] - No longer sending presence to Gateway if not signed in.
  • +
  • [SPARK-441] - Chat room send field no longer becomes disabled.
  • +
  • [SPARK-442] - Logging out causes temporary blank spark to appear.
  • +
  • [SPARK-443] - The Translator plug-in does not work
  • +
  • [SPARK-446] - No longer show toast popups when a message has an error.
  • +
+ + +

2.0.6 -- November 20, 2006

+ +

Bug Fixes

+
    +
  • [SPARK-414] - Added Grabber icon to the bottom right of each frame.
  • +
  • [SPARK-415] - Removed background from JButtons for better UI on OSX.
  • +
  • [SPARK-416] - Replaced old icon for menu tray.
  • +
  • [SPARK-418] - Improved upon Members Only Group Chats.
  • +
  • [SPARK-419] - Fixed MSI build.
  • +
  • [SPARK-425] - Creating account with in-band registration caused NPE in spark.
  • +
  • [SPARK-426] - Improve compatibility with GTalk.
  • +
  • [SPARK-428] - Fixed issue with removing start on startup in preferences.
  • +
  • [SPARK-429] - Improved Gateway tooltips.
  • +
  • [SPARK-430] - MSN roster invites work.
  • +
  • [SPARK-432] - Adding new users will not offer gateway if the user is not from an external system.
  • +
  • [SPARK-433] - Fixed lost message issue with GTalk users.
  • +
  • [SPARK-353] - Improved upon conference invitations.
  • +
+ +

2.0.5 -- October 30, 2006

+ +

New Features

+
    +
  • [SPARK-358] - Added a beta version of the MSI installer.
  • +
  • [SPARK-402] - Added ability to add new contacts through transports.
  • +
+

Bug Fixes

+
    +
  • [SPARK-393] - Fixed blank tab on MAC OSX when presence changed.
  • +
  • [SPARK-400] - Spark now checks for available real estate on monitor.
  • +
  • [SPARK-403] - Fixed private chats in group chat rooms.
  • +
+ + +

2.0.4 -- October 18, 2006

+ +

Bug Fixes

+
    +
  • [SPARK-394] - Fixed user search.
  • +
  • [SPARK-395] - Fixed issue with broadcasts.
  • +
  • [SPARK-396] - Auto discovery is now working with SRV lookup.
  • +
  • [SPARK-397] - Fixed some minor issues with group chat rooms.
  • +
+ +

2.0.3 -- October 11, 2006

+ +

New Features

+
    +
  • [SPARK-364] - Added French translation to Spark.
  • +
  • [SPARK-385] - Added Italian translation to Spark.
  • +
  • [SPARK-386] - Added Dutch translation to Spark.
  • +
+

Bug Fixes

+
    +
  • [SPARK-379] - Fixed exception that occured when services could be loaded from the server.
  • +
  • [SPARK-383] - Gateway information is now based on disco and not the subdomain name.
  • +
  • [SPARK-387] - Fixed disconnect on illegal error packet.
  • +
  • [SPARK-388] - Fixed flaky gateway detection in contact list
  • +
  • [SPARK-392] - Fixed removal of sames user in multiple rooms.
  • +
+ + +

2.0.2 -- September 28, 2006

+ +

New Features

+
    +
  • [SPARK-363] - Added screen selection capability to the screenshot feature.
  • +
  • [SPARK-356] - Added German translation to Spark.
  • +
  • [SPARK-359] - Updated icons and text in Spark to reflect functionallity better.
  • +
  • [SPARK-370] - Added sound preference for incoming chat invitations.
  • +
  • [SPARK-374] - Improved message notifications using sounds and toasters.
  • +
+ +

Bug Fixes

+
    +
  • [SPARK-357] - Spark Manager now handles the online spark distribution correctly.
  • +
  • [SPARK-360] - Added missing i18n properties.
  • +
  • [SPARK-361] - Fixed case where users were showing up as offline when they are online.
  • +
  • [SPARK-362] - Allow passwords with leading and trailing spaces.
  • +
  • [SPARK-365] - File transfers through a proxy no longer fails.
  • +
  • [SPARK-366] - Show login failure when Spark is in the system tray and login fails.
  • +
  • [SPARK-367] - Spark can now run with limited operating system permissions.
  • +
  • [SPARK-368] - Fixed error with wildcard searchs.
  • +
  • [SPARK-369] - Fixed connection issue with Facetime and Akonix.
  • +
  • [SPARK-371] - Added back ctrl+n (now ctrl+f) for user searching within contact list and chat window.
  • +
+ + +

2.0.1 -- September 11, 2006

+ +

New Features

+
    +
  • [SPARK-350] - Added icons and registration for ICQ gateways.
  • +
+ +

Bug Fixes

+
    +
  • [SPARK-341] - Changed online installer to require JRE 1.5.
  • +
  • [SPARK-342] - Spark will not start if the language settings do not match i18n.
  • +
  • [SPARK-343] - Spark handles upgrades with the online tag.
  • +
  • [SPARK-344] - Fixed invalid paths with sound preference.
  • +
  • [SPARK-345] - XMPP URI mapping now registers correctly with the registry.
  • +
  • [SPARK-346] - Search no longer crashes in Spark
  • +
  • [SPARK-347] - Fixed multiple presence packets being sent on idle.
  • +
  • [SPARK-348] - Gateway plugin now checks the server on separate thread.
  • +
  • [SPARK-351] - Changed Spark to use default look and feel on OSX.
  • +
  • [SPARK-352] - Display correct message on uninstalls of plugins in the plugin viewer.
  • +
+ +

2.0.0 -- September 7, 2006

+ +

New Features

+
    +
  • Initial release as an Open Source project!
  • +
  • [SPARK-5] - Added resource bundle support so that Spark can support translations.
  • +
  • [SPARK-28] - Added ability to send a file transfer to an offline contact (file is sent when they become available).
  • +
  • [SPARK-45] - Added support for storing group chat bookmarks (JEP-0048).
  • +
  • [SPARK-78] - Improved tab management.
  • +
  • [SPARK-162] - Improved UI of chat history when opening window.
  • +
  • [SPARK-169] - Spark now stacks chat tabs instead of scrolling them.
  • +
  • [SPARK-177] - Added XMPP URI Mapping to Spark
  • +
  • [SPARK-181] - Improved the Mac installer.
  • +
  • [SPARK-290] - Added ability to resend files when transfer fails.
  • +
  • [SPARK-291] - Add file transfer timeout setting to preferences.
  • +
  • [SPARK-292] - starting conversations with "user" (not really a JID) is possible, Spark could attach "@server.com" to make it + "user@server" +
  • +
  • [SPARK-298] - Presence updates now show timestamp.
  • +
  • [SPARK-299] - Incremental scroll units should be moved to 150 instead of 50.
  • +
  • [SPARK-302] - Added nested groups support.
  • +
  • [SPARK-314] - Apple-W now closes a chat tab/window on Mac.
  • +
  • [SPARK-315] - Improved Growl support on Mac.
  • +
  • [SPARK-324] - It's now possible to logout with a reason.
  • +
  • [SPARK-330] - The preferences dialog is no longer modal.
  • +
  • [SPARK-332] - Added activity monitoring for users typing, going offline and online to contact list.
  • +
  • [SPARK-333] - Added support for gateways.
  • +
  • [SPARK-335] - Added new notification preferences.
  • +
+ +

Bug Fixes

+
    +
  • [SPARK-14] - Spark no longer unchecks the auto-login feature on disconnects.
  • +
  • [SPARK-88] - The update process now checks to see if the update is already downloaded (in case the user never restarted Spark). +
  • +
  • [SPARK-101] - The chat window now has proper Mac OS X menus.
  • +
  • [SPARK-208] - Allow VM params to be set for graphics rendering options.
  • +
  • [SPARK-218] - Non-English characters were noe displayed correctly in vCards.
  • +
  • [SPARK-221] - Sparkplugs were not "sticking" after restart on the Mac.
  • +
  • [SPARK-238] - Setting download directory in Spark is now persisted on logout.
  • +
  • [SPARK-240] - Some commands should not be offered for workgroups in roster.
  • +
  • [SPARK-245] - 0 byte files were crashing Spark.
  • +
  • [SPARK-253] - GroupChatRoomInfo needs to support DBCS.
  • +
  • [SPARK-279] - Special characters in the away message could crash Spark.
  • +
  • [SPARK-280] - Spark was not showing avatars created in Google.
  • +
  • [SPARK-281] - Conference button hidden in chat room toolbar.
  • +
  • [SPARK-282] - Broadcast message functionallity is now dictated by the broadcast plugin in spark.
  • +
  • [SPARK-283] - In some cases, Spark was not starting due to an exception in Tray handling.
  • +
  • [SPARK-285] - The link-2-text filter was not matching all URL's correctly.
  • +
  • [SPARK-288] - Spark was ignoring error messages in certain cases.
  • +
  • [SPARK-293] - Cancel of Spark Manager download does was actually closing the input stream.
  • +
  • [SPARK-294] - Improved logic around avatar handling.
  • +
  • [SPARK-297] - Mac/Linux - conference invites were never received.
  • +
  • [SPARK-300] - Unsubscribe packet was triggering unsubscribe response.
  • +
  • [SPARK-301] - Offline messages were not saved in transcript history.
  • +
  • [SPARK-303] - Fixed memory leak in ChatRoom.
  • +
  • [SPARK-304] - Added chat history to the chat room window.
  • +
  • [SPARK-305] - Added a preference option to specify a download folder.
  • +
  • [SPARK-306] - The text ": - )" now shows a smiley.
  • +
  • [SPARK-317] - Fixed error when loading user history.
  • +
  • [SPARK-318] - Added a way to specify cleanly that a Sparkplug will fail when Spark API changes.
  • +
  • [SPARK-321] - Pending Presence subscription from other users were not showing up in Spark.
  • +
  • [SPARK-322] - Fixed error retrieving vCards from dJabberd
  • +
  • [SPARK-323] - The auto-away feature now changes presence priority to 0.
  • +
  • [SPARK-326] - Double clicking on a user search result was not starting a chat conversation.
  • +
  • [SPARK-328] - Fixed bug where Spark wouldn't start due to bad proxy config.
  • +
  • [SPARK-331] - Message of type HEADLINE can now popup as a toaster.
  • +
+ + + + +
+
+ + + diff --git a/documentation/changes.xsl b/core/src/documentation/changes.xsl similarity index 100% rename from documentation/changes.xsl rename to core/src/documentation/changes.xsl diff --git a/core/src/documentation/ide-eclipse-setup.html b/core/src/documentation/ide-eclipse-setup.html new file mode 100644 index 000000000..307071e8a --- /dev/null +++ b/core/src/documentation/ide-eclipse-setup.html @@ -0,0 +1,118 @@ + + + + + Spark source code in Eclipse IDE + + + +
+
+

Spark source code in Eclipse IDE

+

+ This is a short tutorial on how to load the Spark source code in the Eclipse IDE. +

+
+

+ Eclipse is very versatile, and offers many options that are not explored in this guide. Instead, this guide + focuses on the bare minimum that is needed to get started. +

+ +

Prepare your environment

+

+ This guide assumes that you have Eclipse installed, and have a copy of the source code available locally. + Additionally, a Java Development Kit (version 8) should be installed. +

+

+ Start by creating a new, empty workspace. +

+ +

Create a project and import the source code

+

+ The Spark source code is using an Apache Maven project structure. As Eclipse recognizes this structure, + importing the source code into an Eclipse project is very easy. +

+

+ The 'import' option (in the 'file' menu) can be used to quickly import the Spark source code into a new + Eclipse project. +

+ +
+ Use the 'import' functionality of Eclipse. + Select the option that will import our (pre)existing Maven project. + Eclipse identifies all modules automatically. +
Use the 'import' functionality of Eclipse to import the source code.
+
+ +

+ Using the 'import' option, select the option that allows you to import an existing Maven project into your + Eclipse project. Then, select the directory in which the Spark source code is stored. +

+

+ Eclipse will automatically recognize and process the Maven structure of Spark, as soon as it is pointed to + the correct directory. It will immediately display the hierarchy of modules as a result. +

+

+ Once the import wizard has been closed, the Eclipse workspace will show all modules that are part of Spark. + That's all to it! You're ready to start working on the code now! +

+ +
+ Spark modules in the Eclipse workspace. +
Spark modules in the Eclipse workspace
+
+ +

Run Spark from Eclipse

+

+ When developing, it is often useful to run the code straight from your IDE. The following will explain how + you can start a Spark instance from the code that is in the Eclipse workspace. +

+ +
+ Launch the 'Startup' class as a Java application. + The Spark login screen, after launching the 'Startup' class. +
Run Spark straight from the source code.
+
+ +

+ The 'spark-core' module contains a class named Startup (in the org.jivesoftware.launcher + package) that can be used to start Spark. Find the class in the Eclipse Package Explorer, and open its context + menu (right-click on the file). In that menu, use the 'Run as Java Application' option. Eclipse wil start + to build Spark from the source code, after which Spark itself is started. If everything goes well, you will + see the Spark login screen within a matter of seconds! +

+ +
+ + diff --git a/core/src/documentation/ide-intellij-setup.html b/core/src/documentation/ide-intellij-setup.html new file mode 100644 index 000000000..872935834 --- /dev/null +++ b/core/src/documentation/ide-intellij-setup.html @@ -0,0 +1,126 @@ + + + + + Spark source code in IntelliJ IDE + + + +
+
+

Spark source code in IntelliJ IDE

+

+ This is a short tutorial on how to load the Spark source code in the IntelliJ IDE. +

+
+

+ IntelliJ is very versatile, and offers many options that are not explored in this guide. Instead, this guide + focuses on the bare minimum that is needed to get started. +

+ +

Prepare your environment

+

+ This guide assumes that you have IntelliJ installed, and have a copy of the source code available locally. + Additionally, a Java Development Kit (version 8) should be installed. +

+

+ Start by creating a new, empty workspace. +

+ +

Create a project and import the source code

+

+ The Spark source code is using an Apache Maven project structure. As IntelliJ recognizes this structure, + importing the source code into an IntelliJ project is very easy. +

+

+ Select the 'import' option. This will quickly import the Spark source code into a new + IntelliJ project. +

+ +
+ Use the 'import' functionality of IntelliJ. + Select the option that will import our (pre)existing Maven project. + IntelliJ project options. Defaults should be ok +
Creating a new project in IntelliJ.
+
+ +

+ Using the 'import' option, select the directory in which the Spark source code is stored. Select the Maven project file (pom.xml). +

+

+ IntelliJ will automatically recognize and process the Maven structure of Spark, as soon as it is pointed to + the correct directory. In most cases, You can accept the defaults on the following screens of the import wizard. +

+ +
+ Project to import. + Select the SDK to use. This should auto detect your JDK and path + IntelliJ Project Name and Path. Defaults should be ok. +
Use the 'import' functionality of IntelliJ to import the source code.
+
+ +

+ Once the import wizard has been closed, the IntelliJ workspace will show. There are menu bars to the left and right edge. Left edge, click "Project" to extend Project tree. On the right, click "Maven Project" to extend Modules. + That's it! You're ready to start working on the code now! +

+ +
+ IntelliJ workspace. + IntelliJ workspace. +
Spark modules in the IntelliJ workspace
+
+ +

Run Spark from IntelliJ

+

+ When developing, it is often useful to run the code straight from your IDE. The following will explain how + you can start a Spark instance from the code that is in the IntelliJ workspace. +

+ +
+ Launch the 'Startup' class as a Java application. + The Spark login screen, after launching the 'Startup' class. +
Run Spark straight from the source code.
+
+ +

+ The 'spark-core' module contains a class named Startup (in the org.jivesoftware.launcher + package) that can be used to start Spark. Find the class in the Project Explorer, and open its context + menu (right-click on the file). In that menu, use the 'Run Startup.main()' option. IntelliJ wil start + to build Spark from the source code, after which Spark itself is started. If everything goes well, you will + see the Spark login screen within a matter of seconds! +

+ +
+ + diff --git a/core/src/documentation/ide-vscode-setup.html b/core/src/documentation/ide-vscode-setup.html new file mode 100644 index 000000000..a43d50395 --- /dev/null +++ b/core/src/documentation/ide-vscode-setup.html @@ -0,0 +1,121 @@ + + + + + Spark source code in Visual Studio Code IDE + + + +
+
+

Spark source code in Visual Studio Code IDE

+

+ This is a short tutorial on how to load the Spark source code in the Visual Studio Code IDE. +

+
+

+ Visual Studio Code or VS Code is a fast editor and ships with great editing features. It includes support for debugging, + embedded Git control, syntax highlighting, intelligent code completion, snippets, and code refactoring. + In part thanks to the huge ecosystem of extensions that enhance and enrich the experience in VS Code, + turning it into a super smart text editor, fast and lightweight. This guide focuses on the bare minimum that + is needed to get started Spark source code with VS Code. +

+ +

Prepare your environment

+

+ The rest of this guide will assume you have at least those parts installed: +

    +
  • JAVA Development Kit (version 8)
  • +
  • Maven
  • +
  • Copy of the Spark source code available locally
  • +
  • Visual Studio Code
  • +
+

+ Start by Adding Java language support to VS Code by installing the popular minimum requirement Java extensions. + There is a Java Extension Pack, which contains the most popular extensions for most Java developers: +

+

+ Launch your VS Code and bring up extensions view by clicking on the Extensions icon in the Activity Bar + on the left side of VS Code or View > Extensions then write the name of extension Java Extension Pack and + then click on install link to install all extensions for Pack. +

+
+ Installing Java Extension Pack to VS Code. +
Installing Java Extension Pack to VS Code.
+
+ +

Open the source code folder

+

+ The Spark source code is using an Apache Maven project structure. As VS Code (with Maven Extension) recognizes this structure, + opening the source code into an VS Code project is very easy. +

+

+ Select the 'Open' option -- File > Open and choose your spark source code folder then click on the open button. + This will quickly import the Spark source code into VS Code . +

+ +
+ Use the 'Open' functionality of VS Code. + Select the folder that will open in our VS Code. + Overview of project in Visual Studio Code +
Opening Spark Source folder on VS Code.
+
+ +

+ VS Code will automatically recognize and process the Maven structure of Spark (pom.xml file) and it will automatically download all dependencies. +

+ +

Run Spark from VS Code

+

+ When developing, it is often useful to run the code straight from your IDE. The following will explain how + you can start a Spark instance from the code that is in the VS Code workspace. +

+ +
+ Launch the 'Startup' class as a Java application. + The Spark login screen, after launching the 'Startup' class. +
Run Spark straight from the source code.
+
+ +

+ The 'spark-core' module contains a class named Startup (in the org.jivesoftware.launcher + package) that can be used to start Spark. Find the class in the Project Explorer, open that class you will notice two hyperlinks above + the main method, like in the picture above. You can click on Run and the code will be compiled and executed. VS Code will start + to build Spark from the source code, after which Spark itself is started. If everything goes well, you will + see the Spark login screen within a matter of seconds! +

+ +
+ + diff --git a/core/src/documentation/images/IntelliJ-1.JPG b/core/src/documentation/images/IntelliJ-1.JPG new file mode 100644 index 000000000..72ec4452d Binary files /dev/null and b/core/src/documentation/images/IntelliJ-1.JPG differ diff --git a/core/src/documentation/images/IntelliJ-10.JPG b/core/src/documentation/images/IntelliJ-10.JPG new file mode 100644 index 000000000..9458ea8ec Binary files /dev/null and b/core/src/documentation/images/IntelliJ-10.JPG differ diff --git a/core/src/documentation/images/IntelliJ-2.JPG b/core/src/documentation/images/IntelliJ-2.JPG new file mode 100644 index 000000000..cc66c88b7 Binary files /dev/null and b/core/src/documentation/images/IntelliJ-2.JPG differ diff --git a/core/src/documentation/images/IntelliJ-3.JPG b/core/src/documentation/images/IntelliJ-3.JPG new file mode 100644 index 000000000..6b767f25f Binary files /dev/null and b/core/src/documentation/images/IntelliJ-3.JPG differ diff --git a/core/src/documentation/images/IntelliJ-4.JPG b/core/src/documentation/images/IntelliJ-4.JPG new file mode 100644 index 000000000..c606c9687 Binary files /dev/null and b/core/src/documentation/images/IntelliJ-4.JPG differ diff --git a/core/src/documentation/images/IntelliJ-5.JPG b/core/src/documentation/images/IntelliJ-5.JPG new file mode 100644 index 000000000..ad3784e25 Binary files /dev/null and b/core/src/documentation/images/IntelliJ-5.JPG differ diff --git a/core/src/documentation/images/IntelliJ-6.JPG b/core/src/documentation/images/IntelliJ-6.JPG new file mode 100644 index 000000000..95f7d5e02 Binary files /dev/null and b/core/src/documentation/images/IntelliJ-6.JPG differ diff --git a/core/src/documentation/images/IntelliJ-7.JPG b/core/src/documentation/images/IntelliJ-7.JPG new file mode 100644 index 000000000..a5a2927fd Binary files /dev/null and b/core/src/documentation/images/IntelliJ-7.JPG differ diff --git a/core/src/documentation/images/IntelliJ-8.JPG b/core/src/documentation/images/IntelliJ-8.JPG new file mode 100644 index 000000000..1504d95fe Binary files /dev/null and b/core/src/documentation/images/IntelliJ-8.JPG differ diff --git a/core/src/documentation/images/IntelliJ-9.JPG b/core/src/documentation/images/IntelliJ-9.JPG new file mode 100644 index 000000000..694703f1a Binary files /dev/null and b/core/src/documentation/images/IntelliJ-9.JPG differ diff --git a/core/src/documentation/images/VSCode-1.png b/core/src/documentation/images/VSCode-1.png new file mode 100644 index 000000000..8dc4ebc40 Binary files /dev/null and b/core/src/documentation/images/VSCode-1.png differ diff --git a/core/src/documentation/images/VSCode-2.png b/core/src/documentation/images/VSCode-2.png new file mode 100644 index 000000000..ee7cbdd01 Binary files /dev/null and b/core/src/documentation/images/VSCode-2.png differ diff --git a/core/src/documentation/images/VSCode-3.png b/core/src/documentation/images/VSCode-3.png new file mode 100644 index 000000000..99ae25e91 Binary files /dev/null and b/core/src/documentation/images/VSCode-3.png differ diff --git a/core/src/documentation/images/VSCode-4.png b/core/src/documentation/images/VSCode-4.png new file mode 100644 index 000000000..67819c9b7 Binary files /dev/null and b/core/src/documentation/images/VSCode-4.png differ diff --git a/core/src/documentation/images/VSCode-5.png b/core/src/documentation/images/VSCode-5.png new file mode 100644 index 000000000..d71738523 Binary files /dev/null and b/core/src/documentation/images/VSCode-5.png differ diff --git a/core/src/documentation/images/VSCode-6.png b/core/src/documentation/images/VSCode-6.png new file mode 100644 index 000000000..95a5e97dc Binary files /dev/null and b/core/src/documentation/images/VSCode-6.png differ diff --git a/documentation/images/banner-spark.gif b/core/src/documentation/images/banner-spark.gif similarity index 100% rename from documentation/images/banner-spark.gif rename to core/src/documentation/images/banner-spark.gif diff --git a/documentation/images/banner-spring.gif b/core/src/documentation/images/banner-spring.gif similarity index 100% rename from documentation/images/banner-spring.gif rename to core/src/documentation/images/banner-spring.gif diff --git a/documentation/images/chat-room.png b/core/src/documentation/images/chat-room.png similarity index 100% rename from documentation/images/chat-room.png rename to core/src/documentation/images/chat-room.png diff --git a/documentation/images/contact-list.png b/core/src/documentation/images/contact-list.png similarity index 100% rename from documentation/images/contact-list.png rename to core/src/documentation/images/contact-list.png diff --git a/core/src/documentation/images/eclipse-maven-step-1.png b/core/src/documentation/images/eclipse-maven-step-1.png new file mode 100644 index 000000000..6519e8c7b Binary files /dev/null and b/core/src/documentation/images/eclipse-maven-step-1.png differ diff --git a/core/src/documentation/images/eclipse-maven-step-2.png b/core/src/documentation/images/eclipse-maven-step-2.png new file mode 100644 index 000000000..167185660 Binary files /dev/null and b/core/src/documentation/images/eclipse-maven-step-2.png differ diff --git a/core/src/documentation/images/eclipse-maven-step-3.png b/core/src/documentation/images/eclipse-maven-step-3.png new file mode 100644 index 000000000..dd9e890aa Binary files /dev/null and b/core/src/documentation/images/eclipse-maven-step-3.png differ diff --git a/core/src/documentation/images/eclipse-maven-step-4.png b/core/src/documentation/images/eclipse-maven-step-4.png new file mode 100644 index 000000000..5680285dd Binary files /dev/null and b/core/src/documentation/images/eclipse-maven-step-4.png differ diff --git a/core/src/documentation/images/eclipse-maven-step-5.png b/core/src/documentation/images/eclipse-maven-step-5.png new file mode 100644 index 000000000..2c16b79be Binary files /dev/null and b/core/src/documentation/images/eclipse-maven-step-5.png differ diff --git a/core/src/documentation/images/eclipse-maven-step-6.png b/core/src/documentation/images/eclipse-maven-step-6.png new file mode 100644 index 000000000..20d0eb626 Binary files /dev/null and b/core/src/documentation/images/eclipse-maven-step-6.png differ diff --git a/documentation/images/login-dialog.png b/core/src/documentation/images/login-dialog.png similarity index 100% rename from documentation/images/login-dialog.png rename to core/src/documentation/images/login-dialog.png diff --git a/documentation/sample_plugin_repository.xml b/core/src/documentation/sample_plugin_repository.xml similarity index 92% rename from documentation/sample_plugin_repository.xml rename to core/src/documentation/sample_plugin_repository.xml index 29eeb015b..be5191098 100644 --- a/documentation/sample_plugin_repository.xml +++ b/core/src/documentation/sample_plugin_repository.xml @@ -18,11 +18,11 @@ Joe Mamma http://www.jivesoftware.com Joe@Mama.com - Adds some weird features you dont want + Adds some weird features you don't want org.weird.feature.class.mainclass 2.6.0 http://localhost/test.jar http://www.google.de/search?q=changelog http://www.google.de/search?q=readme - \ No newline at end of file + diff --git a/core/src/documentation/spark guide/Spark.default.properties.guide.html b/core/src/documentation/spark guide/Spark.default.properties.guide.html new file mode 100644 index 000000000..6551d9c25 --- /dev/null +++ b/core/src/documentation/spark guide/Spark.default.properties.guide.html @@ -0,0 +1,195 @@ +

Spark default.properties set up guide

+ +

Author: Wolf Posdorfer

+

To fully configure your default.properties file you can follow this small guide.

+

The default.properties are located at:

+

In your source folder under src/main/resources/default.properties

+

By editing the spark.jar in your installation folder. Go to C:/Programs/Spark/lib/spark.jar and open it with any Archive-program (like 7z). +Then navigate to spark.jar/org/jivesoftware/resource/default.properties

+

Now you will have to open it with any text editor, modify it and save it. If you're using method b, your archive-program will ask you to repack, please do so. +You can then copy this file into any other installation of Spark. You should note that spark.jar will be overwritten with a subsequent Spark upgrade and all custom settings will be lost. +So one should edit spark.jar and redistribute it to all the clients after every new Spark version release.

+

+

Items crossed with red markers are Items that become invisible or disabled when setting a specific option.

+
+# Specify a fixed Hostname
+# Changing the Hostname will also be prohibited if set
+HOST_NAME = example.com
+
+

+
+# Proxy Settings
+# Protocols are "SOCKS" or "HTTP", case sensitive
+PROXY_PROTOCOL = SOCKS
+PROXY_HOST = myProxy.com
+PROXY_PORT = 8080
+
+

+
+# Remove account creation Button from Loginwindow
+# Users wont be able to register new Accounts from within Spark
+ACCOUNT_DISABLED = true
+# Remove Advanced Configuration Button from Loginwindow
+# Users wont be able to access the advanced configuration
+ADVANCED_DISABLED = true
+
+

+
+
+# Branding only
+# Branded images appear in the Top-Right corner, and must be included in the classpath
+# place them in src/resource/images and path will be "images/file.jpg"
+# BRANDED_IMAGE = images/my-corporation-logo.png
+BRANDED_IMAGE = images/colors.png
+
+

+
+# Disables updateability, you should set this, if you have a custom Spark-build
+# or are in an environment where installfiles are distributed via network
+DISABLE_UPDATES = true
+
+

+
+# If true, Spark cannot shut down
+# users wont be able to shut down Spark
+DISABLE_EXIT = true
+
+

+
+# Specify a size(in bytes) on which Users will get a warning of a possibly too big file
+FILE_TRANSFER_WARNING_SIZE = 1024
+FILE_TRANSFER_MAXIMUM_SIZE = 10048
+

+
+# Disables adding of contacts
+# The User wont be able to add contacts, usefull for shared roster management
+ADD_CONTACT_DISABLED = true
+
+

+
+# Disables adding contact groups
+# The User wont be able to add contact groups, usefull for shared roster management
+ADD_CONTACT_GROUP_DISABLED = true
+
+

+
+# Sets the Location of the Userguide
+HELP_USER_GUIDE = https://igniterealtime.org/builds/spark/docs/spark_user_guide.pdf
+# Set to true, if you dont want this displayed
+HELP_USER_GUIDE_DISABLED = 
+# Sets the Location of the Help-Forum
+HELP_FORUM = https://discourse.igniterealtime.org/c/spark/spark-support?forumID=49
+# Set to true, if you dont want this displayed
+HELP_FORUM_DISABLED = 
+# Following Text will be displayed instead of "Spark forum"
+# leave blank for default
+HELP_FORUM_TEXT = My Own Forum
+
+

+
+# Disable Installing of Plugins
+# set true if you want to disable installing of Plugins
+INSTALL_PLUGINS_DISABLED = true
+# Disable deleting of Plugins
+# set true if you want to disable deinstalling of Plugins
+DEINSTALL_PLUGINS_DISABLED = true
+
+

+
+# Put plugins here that you dont want enabled
+# comma separated, case insensitive
+# names of plugins can be found in the plugin.xml
+# example: Fastpath,Jingle Client,Phone Client,Window Flashing Plugin
+# default is empty
+PLUGIN_BLACKLIST = Fastpath
+# Disable Plugins by entrypoint Class 
+# Comma separated, case sensitive
+# example org.jivesoftware.fastpath.FastpathPlugin
+PLUGIN_BLACKLIST_CLASS = org.jivesoftware.spark.translator.TranslatorPlugin
+
+

This will disable all Plugins with <name>Fastpath</name> and all plugins with <class>org.jivesoftware.spark.translator.TranslatorPlugin</class>

+

The appropriate Names or Classes can be found in the plugin.xml within the plugin.jar

+
+# by Default Server-Broadcast get their own JFrame containing the Message
+# also HTML tags like <b> <i> <u> can be used
+# if you want server broadcasts handled like every other message including transcripts
+# set this to true
+BROADCAST_IN_CHATWINDOW = true BROADCAST_IN_CHATWINDOW = false
+
+

+
+# Disable Look&Feel change || "true" = disabled , anything else = enabled
+# By Default the user can Change his Look&Feel in the Preferences Menu, 
+#if you dont want this then set it to true
+# Preferences -> Appearence -> Customization Tab
+LOOK_AND_FEEL_DISABLED = true
+# Disable if you dont want Users to be able to Change the Textcolors in the Preference Menu
+# the colors will be loaded from below
+# Preferences -> Appearence -> ColorTab 
+CHANGE_COLORS_DISABLED = true
+
+

+
+# Changes the Default Look&Feel
+DEFAULT_LOOK_AND_FEEL = org.jivesoftware.spark.ui.themes.lafs.SparkLightLaf
+# Default Spark skin for Mac is empty. This will load the OSX Look&Feel
+DEFAULT_LOOK_AND_FEEL_MAC = 
+
+

Look and Feels are: +

    +
  • On Windows:
  • +
      +
    • javax.swing.plaf.metal.MetalLookAndFeel
    • +
    • com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel
    • +
    • com.sun.java.swing.plaf.motif.MotifLookAndFeel
    • +
    • com.sun.java.swing.plaf.windows.WindowsLookAndFeel
    • +
    • com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel
    • +
    +
  • On any System:
  • +
      +
    • com.jtattoo.plaf.acryl.AcrylLookAndFeel
    • +
    • com.jtattoo.plaf.aero.AeroLookAndFeel
    • +
    • com.jtattoo.plaf.aluminium.AluminiumLookAndFeel
    • +
    • com.jtattoo.plaf.bernstein.BernsteinLookAndFeel
    • +
    • com.jtattoo.plaf.fast.FastLookAndFeel
    • +
    • com.jtattoo.plaf.graphite.GraphiteLookAndFeel
    • +
    • com.jtattoo.plaf.hifi.HiFiLookAndFeel
    • +
    • com.jtattoo.plaf.luna.LunaLookAndFeel
    • +
    • com.jtattoo.plaf.mcwin.McWinLookAndFeel
    • +
    • com.jtattoo.plaf.mint.MintLookAndFeel
    • +
    • com.jtattoo.plaf.noire.NoireLookAndFeel
    • +
    • com.jtattoo.plaf.smart.SmartLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceAutumnLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceBusinessBlackSteelLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceBusinessBlueSteelLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceBusinessLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceChallengerDeepLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceCremeCoffeeLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceCremeLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceDustCoffeeLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceDustLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceEmeraldDuskLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceMagmaLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceMistAquaLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceMistSilverLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceModerateLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceNebulaBrickWallLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceNebulaLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceOfficeBlue2007LookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceOfficeSilver2007LookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceRavenGraphiteGlassLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceRavenGraphiteLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceRavenLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceSaharaLookAndFeel
    • +
    • org.jvnet.substance.skin.SubstanceTwilightLookAndFeel
    • +
    • org.jvnet.substance.api.skin.SubstanceGeminiLookAndFeel
    • +
    • org.jvnet.substance.api.skin.SubstanceGraphiteAquaLookAndFeel
    • +
    • org.jvnet.substance.api.skin.SubstanceMagellanLookAndFeel
    • +
    +
+

diff --git a/documentation/spark guide/images/filelist.xml b/core/src/documentation/spark guide/images/filelist.xml similarity index 94% rename from documentation/spark guide/images/filelist.xml rename to core/src/documentation/spark guide/images/filelist.xml index 0cffc54cc..7add029e1 100644 --- a/documentation/spark guide/images/filelist.xml +++ b/core/src/documentation/spark guide/images/filelist.xml @@ -16,6 +16,5 @@ - - \ No newline at end of file + diff --git a/documentation/spark guide/images/image001.png b/core/src/documentation/spark guide/images/image001.png similarity index 100% rename from documentation/spark guide/images/image001.png rename to core/src/documentation/spark guide/images/image001.png diff --git a/documentation/spark guide/images/image003.png b/core/src/documentation/spark guide/images/image003.png similarity index 100% rename from documentation/spark guide/images/image003.png rename to core/src/documentation/spark guide/images/image003.png diff --git a/documentation/spark guide/images/image005.png b/core/src/documentation/spark guide/images/image005.png similarity index 100% rename from documentation/spark guide/images/image005.png rename to core/src/documentation/spark guide/images/image005.png diff --git a/documentation/spark guide/images/image007.png b/core/src/documentation/spark guide/images/image007.png similarity index 100% rename from documentation/spark guide/images/image007.png rename to core/src/documentation/spark guide/images/image007.png diff --git a/documentation/spark guide/images/image009.png b/core/src/documentation/spark guide/images/image009.png similarity index 100% rename from documentation/spark guide/images/image009.png rename to core/src/documentation/spark guide/images/image009.png diff --git a/documentation/spark guide/images/image011.png b/core/src/documentation/spark guide/images/image011.png similarity index 100% rename from documentation/spark guide/images/image011.png rename to core/src/documentation/spark guide/images/image011.png diff --git a/documentation/spark guide/images/image013.png b/core/src/documentation/spark guide/images/image013.png similarity index 100% rename from documentation/spark guide/images/image013.png rename to core/src/documentation/spark guide/images/image013.png diff --git a/documentation/spark guide/images/image015.png b/core/src/documentation/spark guide/images/image015.png similarity index 100% rename from documentation/spark guide/images/image015.png rename to core/src/documentation/spark guide/images/image015.png diff --git a/documentation/spark guide/images/image017.png b/core/src/documentation/spark guide/images/image017.png similarity index 100% rename from documentation/spark guide/images/image017.png rename to core/src/documentation/spark guide/images/image017.png diff --git a/documentation/spark guide/images/image019.png b/core/src/documentation/spark guide/images/image019.png similarity index 100% rename from documentation/spark guide/images/image019.png rename to core/src/documentation/spark guide/images/image019.png diff --git a/documentation/spark guide/images/image021.png b/core/src/documentation/spark guide/images/image021.png similarity index 100% rename from documentation/spark guide/images/image021.png rename to core/src/documentation/spark guide/images/image021.png diff --git a/documentation/spark guide/images/image023.png b/core/src/documentation/spark guide/images/image023.png similarity index 100% rename from documentation/spark guide/images/image023.png rename to core/src/documentation/spark guide/images/image023.png diff --git a/documentation/spark guide/images/image025.png b/core/src/documentation/spark guide/images/image025.png similarity index 100% rename from documentation/spark guide/images/image025.png rename to core/src/documentation/spark guide/images/image025.png diff --git a/documentation/spark guide/images/image027.png b/core/src/documentation/spark guide/images/image027.png similarity index 100% rename from documentation/spark guide/images/image027.png rename to core/src/documentation/spark guide/images/image027.png diff --git a/documentation/spark guide/images/image029.png b/core/src/documentation/spark guide/images/image029.png similarity index 100% rename from documentation/spark guide/images/image029.png rename to core/src/documentation/spark guide/images/image029.png diff --git a/documentation/spark guide/images/image031.png b/core/src/documentation/spark guide/images/image031.png similarity index 100% rename from documentation/spark guide/images/image031.png rename to core/src/documentation/spark guide/images/image031.png diff --git a/core/src/documentation/spark.doap b/core/src/documentation/spark.doap new file mode 100644 index 000000000..99a4fc681 --- /dev/null +++ b/core/src/documentation/spark.doap @@ -0,0 +1,261 @@ + + + + Spark + spark + + XMPP Client + + Spark is an Open Source, cross-platform IM client optimized for businesses and organizations. It features + built-in support for group chat, telephony integration, and strong security. It also offers a great end-user + experience with features like in-line spell checking, group chat room bookmarks, and tabbed conversations. + + + + + + + + + + + + + + + + + + Java + Linux + macOS + Windows + + + + + + + + + + + + + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + partial + Images only. + + + + + + complete + + + + + + partial + + + + + + complete + + + + + + complete + + + + + + complete + + + + + + complete + Http File Upload Plugin (fileupload) + + + + + + complete + Off the Record (OTR) Plugin + + + + + + partial + 2.0 + Only for MUC nicknames. Preferences / Group Chat / Names have random colors + + + + + + partial + + + + + + complete + Online Meetings (meet) plugin + + + + diff --git a/documentation/sparkplug_compile.html b/core/src/documentation/sparkplug_compile.html similarity index 96% rename from documentation/sparkplug_compile.html rename to core/src/documentation/sparkplug_compile.html index 5fb75ec4d..52ba72978 100644 --- a/documentation/sparkplug_compile.html +++ b/core/src/documentation/sparkplug_compile.html @@ -31,13 +31,12 @@

Before compiling the Plugin

-

How to build a SparkPlug

You will find an example plugin located in the trunk of the Spark-Repository.
> [DIRECTORY]/build/builder/

-It already has the basic steps implemented to get the Plugin loaded and have an own menu entry within the Spark Preferences
+It already has the basic steps implemented to get the Plugin loaded and have an own menu entry within the Spark Preferences
to compile it open a terminal (or your JAVA IDE) and execute the build.xml with target <jar>

@@ -75,7 +74,7 @@

How to build a SparkPlug

-[Directory] refers to the Path on your harddrive where your spark-trunk directory is located
+[Directory] refers to the Path on your hard drive where your spark-trunk directory is located
e.g.: C:/spark/ diff --git a/documentation/sparkplug_dev_guide.html b/core/src/documentation/sparkplug_dev_guide.html similarity index 99% rename from documentation/sparkplug_dev_guide.html rename to core/src/documentation/sparkplug_dev_guide.html index 28e4a2093..2d5ac592e 100644 --- a/documentation/sparkplug_dev_guide.html +++ b/core/src/documentation/sparkplug_dev_guide.html @@ -27,7 +27,7 @@

What Are Sparkplugs?

How to build

-Spark Plugin Compile Guide

+Spark Plugin Compile Guide

Once I Build It, Then What?

After you've built your amazingly cool Sparkplug, it's easy to rollout to your users. Just have them drop it in the plugins directory of @@ -830,10 +830,6 @@

How can I add my own Preferences?

  • Create a class that implements Preference.
     /**
    - * $RCSfile: ,v $
    - * $Revision: $
    - * $Date:  $
    - *
      * Copyright (C) 1999-2005 Jive Software. All rights reserved.
      *
      * This software is the proprietary information of Jive Software.
    diff --git a/documentation/style.css b/core/src/documentation/style.css
    similarity index 100%
    rename from documentation/style.css
    rename to core/src/documentation/style.css
    diff --git a/core/src/main/java/org/jivesoftware/AccountCreationWizard.java b/core/src/main/java/org/jivesoftware/AccountCreationWizard.java
    new file mode 100644
    index 000000000..4755dac86
    --- /dev/null
    +++ b/core/src/main/java/org/jivesoftware/AccountCreationWizard.java
    @@ -0,0 +1,557 @@
    +/**
    + * Copyright (C) 2004-2011 Jive Software. All rights reserved.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *     http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +
    +package org.jivesoftware;
    +
    +import org.jivesoftware.resource.Res;
    +import org.jivesoftware.smack.*;
    +import org.jivesoftware.smack.ConnectionConfiguration.DnssecMode;
    +import org.jivesoftware.smack.packet.StanzaError;
    +import org.jivesoftware.smack.parsing.ExceptionLoggingCallback;
    +import org.jivesoftware.smack.tcp.XMPPTCPConnection;
    +import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
    +import org.jivesoftware.smack.util.DNSUtil;
    +import org.jivesoftware.smackx.bob.element.BoBDataExtension;
    +import org.jivesoftware.smackx.iqregister.AccountManager;
    +import org.jivesoftware.smackx.iqregister.packet.Registration;
    +import org.jivesoftware.smackx.xdata.FormField;
    +import org.jivesoftware.smackx.xdata.form.FillableForm;
    +import org.jivesoftware.smackx.xdata.packet.DataForm;
    +import org.jivesoftware.spark.component.TitlePanel;
    +import org.jivesoftware.spark.ui.DataFormUI;
    +import org.jivesoftware.spark.util.ModelUtil;
    +import org.jivesoftware.spark.util.ResourceUtils;
    +import org.jivesoftware.spark.util.SwingWorker;
    +import org.jivesoftware.spark.util.log.Log;
    +import org.jivesoftware.sparkimpl.certificates.SparkSSLSocketFactory;
    +import org.jivesoftware.sparkimpl.certificates.SparkSSLContextCreator;
    +import org.jivesoftware.sparkimpl.certificates.SparkTrustManager;
    +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences;
    +import org.jivesoftware.sparkimpl.settings.local.SettingsManager;
    +import org.jxmpp.jid.DomainBareJid;
    +import org.jxmpp.jid.parts.Localpart;
    +import org.jxmpp.stringprep.XmppStringprepException;
    +import org.jxmpp.util.XmppStringUtils;
    +import org.minidns.dnsname.DnsName;
    +
    +import javax.net.ssl.SSLContext;
    +import javax.swing.*;
    +import java.awt.*;
    +import java.io.IOException;
    +import java.net.InetAddress;
    +import java.security.KeyManagementException;
    +import java.security.KeyStoreException;
    +import java.security.NoSuchAlgorithmException;
    +import java.security.NoSuchProviderException;
    +import java.security.UnrecoverableKeyException;
    +import java.util.*;
    +import java.util.List;
    +
    +import static java.awt.GridBagConstraints.*;
    +import static java.awt.GridBagConstraints.BOTH;
    +import static java.awt.GridBagConstraints.EAST;
    +import static java.awt.GridBagConstraints.NONE;
    +import static org.jivesoftware.sparkimpl.certificates.SparkSSLContextCreator.Options.ONLY_SERVER_SIDE;
    +
    +/**
    + * Allows the creation of accounts on an XMPP server.
    + */
    +public class AccountCreationWizard extends JPanel {
    +    private final JComboBox serverField = new JComboBox<>();
    +
    +    private final JButton startRegistrationButton = new JButton();
    +
    +    private final JLabel instructionsLabel = new JLabel();
    +
    +    private final FormPanel formPanel = new FormPanel();
    +
    +    private final JPanel formPanelFields = new JPanel();
    +
    +    private final JLabel captcha = new JLabel();
    +
    +    private final JButton createAccountButton = new JButton();
    +
    +    private JDialog dialog;
    +
    +    private DataFormUI registrationForm;
    +
    +    private boolean registered;
    +    private XMPPConnection connection = null;
    +    private final JProgressBar progressBar;
    +
    +    static class FormPanel extends JPanel {
    +        private final JTextField usernameField = new JTextField();
    +
    +        private final JPasswordField passwordField = new JPasswordField();
    +
    +        private final JPasswordField confirmPasswordField = new JPasswordField();
    +
    +        public FormPanel() {
    +            super();
    +            JLabel usernameLabel = new JLabel();
    +            ResourceUtils.resLabel( usernameLabel, usernameField, Res.getString("label.username") + ":");
    +            JLabel passwordLabel = new JLabel();
    +            ResourceUtils.resLabel( passwordLabel, passwordField, Res.getString("label.password") + ":");
    +            JLabel confirmPasswordLabel = new JLabel();
    +            ResourceUtils.resLabel( confirmPasswordLabel, confirmPasswordField, Res.getString("label.confirm.password") + ":");
    +
    +            setLayout(new GridBagLayout());
    +            Insets insets = new Insets(5, 5, 5, 5);
    +            add( usernameLabel, new GridBagConstraints(0, 1, 1, 1, 0, 0, WEST, NONE, insets, 0, 0));
    +            add(usernameField, new GridBagConstraints(1, 1, 3, 1, 1, 0, WEST, HORIZONTAL, insets, 150, 0));
    +
    +            add( passwordLabel, new GridBagConstraints(0, 2, 1, 1, 0, 0, WEST, NONE, insets, 0, 0));
    +            add(passwordField, new GridBagConstraints(1, 2, 3, 1, 0, 0, WEST, HORIZONTAL, insets, 0, 0));
    +
    +            add( confirmPasswordLabel, new GridBagConstraints(0, 3, 1, 1, 0, 0, WEST, NONE, insets, 0, 0));
    +            add(confirmPasswordField, new GridBagConstraints(1, 3, 3, 1, 1, 0, WEST, HORIZONTAL, insets, 0, 0));
    +        }
    +    }
    +
    +    public AccountCreationWizard() {
    +        // Associate Mnemonics
    +        serverField.setEditable(true);
    +        List providers = XmppProviders.getXmppProvidersModel();
    +        for (String provider : providers) {
    +            serverField.addItem(provider);
    +        }
    +        // Randomly pre-select a provider
    +        int randomProviderIdx = new Random().nextInt(providers.size());
    +        serverField.setSelectedIndex(randomProviderIdx);
    +
    +        ResourceUtils.resButton(startRegistrationButton, Res.getString("button.start.registration"));
    +        startRegistrationButton.addActionListener( actionEvent -> startRegistration() );
    +
    +        instructionsLabel.setVisible(false);
    +
    +        formPanel.setVisible(false);
    +        formPanelFields.setVisible(false);
    +
    +        captcha.setPreferredSize(new java.awt.Dimension(250, 80));
    +        captcha.setRequestFocusEnabled(false);
    +        captcha.setHorizontalAlignment(SwingConstants.CENTER);
    +        instructionsLabel.setVisible(false);
    +
    +        JLabel serverLabel = new JLabel();
    +        ResourceUtils.resLabel( serverLabel, serverField, Res.getString("label.server") + ":");
    +        ResourceUtils.resButton(createAccountButton, Res.getString("button.create.account"));
    +        createAccountButton.setEnabled(false);
    +        createAccountButton.addActionListener( actionEvent -> createAccount() );
    +
    +        progressBar = new JProgressBar();
    +        progressBar.setVisible(false);
    +
    +        JButton closeButton = new JButton();
    +        ResourceUtils.resButton( closeButton, Res.getString("button.close"));
    +        closeButton.addActionListener( actionEvent -> dialog.dispose() );
    +
    +        setLayout(new GridBagLayout());
    +        // Add component to UI
    +        Insets insets = new Insets(5, 5, 5, 5);
    +        add( serverLabel, new GridBagConstraints(0, 0, 1, 1, 0, 0, WEST, NONE, insets, 0, 0));
    +        add(serverField, new GridBagConstraints(1, 0, 3, 1, 0, 0, WEST, HORIZONTAL, insets, 0, 0));
    +        add(startRegistrationButton, new GridBagConstraints(1, 1, 3, 1, 0, 0, WEST, HORIZONTAL, insets, 0, 0));
    +        add(instructionsLabel, new GridBagConstraints(0, 2, 4, 1, 1, 0, WEST, BOTH, insets, 0, 0));
    +        add(formPanel, new GridBagConstraints(0, 3, 4, 1, 1, 0, WEST, BOTH, insets, 0, 0));
    +        add(formPanelFields, new GridBagConstraints(0, 4, 4, 1, 1, 0, WEST, BOTH, insets, 0, 0));
    +        add(captcha, new GridBagConstraints(0, 5, 4, 1, 1, 0, CENTER, BOTH, insets, 0, 0));
    +        add(progressBar, new GridBagConstraints(1, 6, 4, 1, 1, 0, WEST, HORIZONTAL, insets, 0, 0));
    +        add(createAccountButton, new GridBagConstraints(2, 7, 1, 1, 1, 0, EAST, NONE, insets, 0, 0));
    +        add( closeButton, new GridBagConstraints(3, 7, 1, 1, 0, 0, EAST, NONE, insets, 0, 0));
    +    }
    +
    +    /**
    +     * Returns the username to use for the new account.
    +     */
    +    public String getUsername() {
    +        return XmppStringUtils.escapeLocalpart(formPanel.usernameField.getText().toLowerCase());
    +    }
    +
    +    /**
    +     * Returns the username to use for the new account.
    +     */
    +    public String getUsernameWithoutEscape() {
    +        return formPanel.usernameField.getText();
    +    }
    +    
    +    /**
    +     * Returns the password to use for the new account.
    +     */
    +    public String getPassword() {
    +        return new String(formPanel.passwordField.getPassword());
    +    }
    +
    +    /**
    +     * Returns the confirmation password to use for the new account.
    +     */
    +    public String getConfirmPassword() {
    +        return new String(formPanel.confirmPasswordField.getPassword());
    +    }
    +
    +    /**
    +     * Returns the server to use with the new account.
    +     */
    +    public String getServer() {
    +        String selectedServer = (String) serverField.getSelectedItem();
    +        return selectedServer != null ? selectedServer.trim() : "";
    +    }
    +
    +    public void setServer(DomainBareJid xmppDomain) {
    +        if (xmppDomain == null) {
    +            return;
    +        }
    +        serverField.setSelectedItem(xmppDomain.toString());
    +    }
    +
    +    /**
    +     * Returns true if the passwords match.
    +     */
    +    public boolean isPasswordValid() {
    +        return getPassword().equals(getConfirmPassword());
    +    }
    +
    +    /**
    +     * Start registration and fetch signup form.
    +     */
    +    private void startRegistration() {
    +        final Component ui = this;
    +        try {
    +            connection = getConnection();
    +        } catch (SmackException | IOException | XMPPException e) {
    +            String th = e.getCause() == null ? e.getMessage() : e.getCause().getMessage();
    +            JOptionPane.showMessageDialog(ui, Res.getString("message.connection.failed", getServer())
    +                + "\n" + th, Res.getString("title.create.problem"), JOptionPane.ERROR_MESSAGE);
    +            return;
    +        }
    +        try {
    +            final AccountManager accountManager = AccountManager.getInstance(connection);
    +            if (accountManager.supportsAccountCreation()) {
    +                formPanel.setVisible(true);
    +                createAccountButton.setEnabled(true);
    +                String instructions = null;
    +                Icon captchaIcon = null;
    +                Registration info = accountManager.getRegistrationInfo();
    +                if (info != null) {
    +                    // try to get the CAPTCHA image from 
    +                    //  BASE64_OF_PNG_HERE
    +                    BoBDataExtension captchaBob = info.getExtension(BoBDataExtension.class);
    +                    if (captchaBob != null && captchaBob.getBobData().getType().startsWith("image/")) {
    +                        byte[] imageData = captchaBob.getBobData().getContent();
    +                        captchaIcon = new ImageIcon(imageData);
    +                    }
    +                    DataForm regFields = info.getExtension(DataForm.class);
    +                    if (regFields != null) {
    +                        registrationForm = getRegistrationForm(regFields, captchaIcon != null);
    +                        instructions = String.join("\n", regFields.getInstructions());
    +                    } else {
    +                        instructions = info.getInstructions();
    +                    }
    +                }
    +                if (registrationForm != null) {
    +                    formPanelFields.add(registrationForm);
    +                    formPanelFields.setVisible(true);
    +                }
    +                if (instructions != null) {
    +                    instructionsLabel.setText(instructions);
    +                    instructionsLabel.setVisible(true);
    +                }
    +                if (captchaIcon != null) {
    +                    captcha.setIcon(captchaIcon);
    +                    instructionsLabel.setVisible(true);
    +                }
    +            } else {
    +                String message = Res.getString("message.create.account.not.allowed");
    +                JOptionPane.showMessageDialog(this, message, Res.getString("title.create.problem"), JOptionPane.ERROR_MESSAGE);
    +            }
    +        } catch (XMPPException | SmackException | InterruptedException e) {
    +            StanzaError.Condition condition = null;
    +            if (e instanceof XMPPException.XMPPErrorException) {
    +                condition = ((XMPPException.XMPPErrorException) e).getStanzaError().getCondition();
    +            }
    +            if (condition == null) {
    +                condition = StanzaError.Condition.internal_server_error;
    +            }
    +            accountCreationFailed(condition);
    +        }
    +    }
    +
    +    private DataFormUI getRegistrationForm(DataForm regFields, boolean noCaptcha) {
    +        // Create a new form without username and password that we will render ourselves
    +        DataForm.Builder extRegFields = regFields.asBuilder()
    +            .removeField("username")
    +            .removeField("password");
    +        if (noCaptcha) {
    +            extRegFields.removeField("captcha-fallback-url");
    +            extRegFields.removeField("captcha-fallback-text");
    +        }
    +        DataFormUI dataFormUI = new DataFormUI(extRegFields.build());
    +        return dataFormUI;
    +    }
    +
    +    /**
    +     * Creates the new account using the supplied information.
    +     */
    +    private void createAccount() {
    +        boolean errors = false;
    +        String errorMessage = "";
    +
    +        String server = getServer();
    +        if (!ModelUtil.hasLength(getUsername())) {
    +            errors = true;
    +            formPanel.usernameField.requestFocus();
    +            errorMessage = Res.getString("message.username.error");
    +        }
    +        else if (!ModelUtil.hasLength(getPassword())) {
    +            errors = true;
    +            errorMessage = Res.getString("message.password.error");
    +        }
    +        else if (!ModelUtil.hasLength(getConfirmPassword())) {
    +            errors = true;
    +            errorMessage = Res.getString("message.confirmation.password.error");
    +        }
    +        else if (!ModelUtil.hasLength(server)) {
    +            errors = true;
    +            errorMessage = Res.getString("message.account.error");
    +        }
    +        else if (!isPasswordValid()) {
    +            errors = true;
    +            errorMessage = Res.getString("message.confirmation.password.error");
    +        }
    +
    +        if (errors) {
    +        	UIManager.put("OptionPane.okButtonText", Res.getString("ok"));
    +            JOptionPane.showMessageDialog(this, errorMessage, Res.getString("title.create.problem"), JOptionPane.ERROR_MESSAGE);
    +            return;
    +        }
    +
    +        final Component ui = this;
    +        progressBar.setIndeterminate(true);
    +        progressBar.setStringPainted(true);
    +        progressBar.setString(Res.getString("message.registering", server));
    +        progressBar.setVisible(true);
    +
    +        final SwingWorker worker = new SwingWorker() {
    +            StanzaError.Condition condition = null;
    +            String th;
    +
    +
    +            @Override
    +			public Object construct() {
    +                try {
    +                    createAccountButton.setEnabled(false);
    +                    connection = getConnection();
    +                }
    +                catch (SmackException | IOException | XMPPException e) {
    +                    th = e.getCause() == null ? e.getMessage() : e.getCause().getMessage();
    +                    return e;
    +                }
    +                try {
    +                    Map attrs = getRegistrationAttributes();
    +                    Localpart localpart = Localpart.from(getUsername());
    +                    final AccountManager accountManager = AccountManager.getInstance(connection);
    +                    accountManager.createAccount(localpart, getPassword(), attrs);
    +                }
    +                catch (XMPPException | SmackException | InterruptedException | XmppStringprepException e) {
    +                    if ( e instanceof XMPPException.XMPPErrorException ) {
    +                        condition = ( (XMPPException.XMPPErrorException) e ).getStanzaError().getCondition();
    +                    }
    +                    if ( condition == null ) {
    +                        condition = StanzaError.Condition.internal_server_error;
    +                    }
    +                }
    +                return "ok";
    +            }
    +
    +            @Override
    +			public void finished() {
    +                progressBar.setVisible(false);
    +                if (connection == null) {
    +                    if (ui.isShowing()) {
    +                        createAccountButton.setEnabled(true);
    +                        UIManager.put("OptionPane.okButtonText", Res.getString("ok"));
    +                        JOptionPane.showMessageDialog(ui, Res.getString("message.connection.failed", server)
    +                            + "\n" + th, Res.getString("title.create.problem"), JOptionPane.ERROR_MESSAGE);
    +                        createAccountButton.setEnabled(true);
    +                    }
    +                    return;
    +                }
    +
    +                if (condition == null) {
    +                    accountCreationSuccessful();
    +                }
    +                else {
    +                    accountCreationFailed(condition);
    +                }
    +            }
    +        };
    +
    +        worker.start();
    +    }
    +
    +    private Map getRegistrationAttributes() {
    +        if (registrationForm == null) {
    +            return Map.of();
    +        }
    +        FillableForm filledForm = registrationForm.getFilledForm();
    +        List fields = filledForm.getDataFormToSubmit().getFields();
    +        Map attrs = new HashMap<>(fields.size());
    +        for (FormField f : fields) {
    +            attrs.put(f.getFieldName(), f.getFirstValue());
    +        }
    +        return attrs;
    +    }
    +
    +    /**
    +     * Called if the account creation failed.
    +     *
    +     * @param condition the error code.
    +     */
    +    private void accountCreationFailed( StanzaError.Condition condition ) {
    +        String message;
    +        if (condition == StanzaError.Condition.conflict) {
    +            message = Res.getString("message.already.exists");
    +            formPanel.usernameField.setText("");
    +            formPanel.usernameField.requestFocus();
    +        } else if (condition == StanzaError.Condition.not_allowed || condition == StanzaError.Condition.forbidden || condition == StanzaError.Condition.service_unavailable) {
    +            message = Res.getString("message.create.account.not.allowed");
    +        } else {
    +            message = Res.getString("message.create.account") + " " + condition;
    +        }
    +        UIManager.put("OptionPane.okButtonText", Res.getString("ok"));
    +        JOptionPane.showMessageDialog(this, message, Res.getString("title.create.problem"), JOptionPane.ERROR_MESSAGE);
    +        createAccountButton.setEnabled(true);
    +    }
    +
    +    /**
    +     * Called if the account was created successfully.
    +     */
    +    private void accountCreationSuccessful() {
    +        registered = true;
    +        UIManager.put("OptionPane.okButtonText", Res.getString("ok"));
    +        JOptionPane.showMessageDialog(this, Res.getString("message.account.created"), Res.getString("title.account.created"), JOptionPane.INFORMATION_MESSAGE);
    +        dialog.dispose();
    +    }
    +
    +    /**
    +     * Invokes the AccountCreationWizard.
    +     *
    +     * @param parent the parent frame to use.
    +     */
    +    public void invoke(JFrame parent) {
    +        dialog = new JDialog(parent, Res.getString("title.create.new.account"), true);
    +
    +        TitlePanel titlePanel = new TitlePanel(Res.getString("title.account.create.registration"), Res.getString("message.account.create"), null, true);
    +        dialog.getContentPane().setLayout(new BorderLayout());
    +        dialog.getContentPane().add(titlePanel, BorderLayout.NORTH);
    +        dialog.getContentPane().add(this, BorderLayout.CENTER);
    +        dialog.pack();
    +        dialog.setSize(400, 580);
    +        dialog.setLocationRelativeTo(parent);
    +        dialog.setVisible(true);
    +    }
    +
    +    /**
    +     * Creates an XMPPConnection based on the users settings.
    +     */
    +    private XMPPConnection getConnection() throws SmackException, IOException, XMPPException
    +    {
    +        final LocalPreferences localPreferences = SettingsManager.getLocalPreferences();
    +        int port = localPreferences.getXmppPort();
    +        String serverName = getServer();
    +        int checkForPort = serverName.indexOf(":");
    +        if (checkForPort != -1) {
    +            String portString = serverName.substring(checkForPort + 1);
    +            if (ModelUtil.hasLength(portString)) {
    +                // Set new port.
    +                port = Integer.parseInt(portString);
    +            }
    +        }
    +
    +        ConnectionConfiguration.SecurityMode securityMode = localPreferences.getSecurityMode();
    +        boolean useDirectTls = localPreferences.isDirectTls();
    +        boolean hostPortConfigured = localPreferences.isHostAndPortConfigured();
    +
    +        final XMPPTCPConnectionConfiguration.Builder builder = XMPPTCPConnectionConfiguration.builder()
    +                .setUsernameAndPassword( "username", "password" )
    +                .setXmppDomain( serverName )
    +                .setPort( port )
    +            .setHostAddress(InetAddress.getByName("127.0.0.1"))
    +                .setCompressionEnabled( localPreferences.isCompressionEnabled() )
    +                .setSecurityMode( securityMode );
    +
    +        if ( hostPortConfigured )
    +        {
    +            builder.setHost( localPreferences.getXmppHost() );
    +        }
    +        configureConnectionTls(builder, securityMode, useDirectTls, hostPortConfigured, serverName);
    +        final XMPPTCPConnectionConfiguration configuration = builder.build();
    +        final AbstractXMPPConnection connection = new XMPPTCPConnection( configuration );
    +        connection.setParsingExceptionCallback( new ExceptionLoggingCallback() );
    +        try {
    +            connection.connect();
    +        } catch (InterruptedException e) {
    +            throw new IllegalStateException(e);
    +        }
    +
    +        return connection;
    +    }
    +
    +    private void configureConnectionTls(XMPPTCPConnectionConfiguration.Builder builder, ConnectionConfiguration.SecurityMode securityMode, boolean useDirectTls, boolean hostPortConfigured, String serverName) throws SmackException.SmackMessageException {
    +        if (securityMode != ConnectionConfiguration.SecurityMode.disabled) {
    +            if (!useDirectTls) {
    +                // This use STARTTLS which starts initially plain connection to upgrade it to TLS, it use the same port as
    +                // plain connections which is 5222.
    +                SparkSSLContextCreator.Options options = ONLY_SERVER_SIDE;
    +                try {
    +                    SSLContext context = SparkSSLContextCreator.setUpContext(options);
    +                    builder.setSslContextFactory(() -> context);
    +                    builder.setSecurityMode(securityMode);
    +                    builder.setCustomX509TrustManager(new SparkTrustManager());
    +                } catch (NoSuchAlgorithmException | KeyManagementException | UnrecoverableKeyException | KeyStoreException | NoSuchProviderException e) {
    +                    Log.warning("Could not establish secured connection", e);
    +                }
    +            } else { // useDirectTls
    +                if (!hostPortConfigured) {
    +                    // SMACK 4.1.9 does not support XEP-0368, and does not apply a port change, if the host is not changed too.
    +                    // Here, we force the host to be set (by doing a DNS lookup), and force the port to 5223 (which is the
    +                    // default 'old-style' SSL port).
    +                    DnsName serverNameDnsName = DnsName.from(serverName);
    +                    java.util.List resolvedAddresses = DNSUtil.getDNSResolver().lookupHostAddress(serverNameDnsName, null, DnssecMode.disabled);
    +                    if (resolvedAddresses.isEmpty()) {
    +                        throw new SmackException.SmackMessageException("Could not resolve " + serverNameDnsName);
    +                    }
    +                    builder.setHost( resolvedAddresses.get( 0 ).getHostName() );
    +                    builder.setPort( 5223 );
    +                }
    +                SparkSSLContextCreator.Options options = ONLY_SERVER_SIDE;
    +                builder.setSocketFactory( new SparkSSLSocketFactory(options) );
    +                // SMACK 4.1.9  does not recognize an 'old-style' SSL socket as being secure, which will cause a failure when
    +                // the 'required' Security Mode is defined. Here, we work around this by replacing that security mode with an
    +                // 'if-possible' setting.
    +                builder.setSecurityMode( ConnectionConfiguration.SecurityMode.ifpossible );
    +            }
    +        }
    +    }
    +
    +    /**
    +     * Returns true if the user is registered.
    +     */
    +    public boolean isRegistered() {
    +        return registered;
    +    }
    +}
    +
    diff --git a/core/src/main/java/org/jivesoftware/MainWindow.java b/core/src/main/java/org/jivesoftware/MainWindow.java
    new file mode 100644
    index 000000000..539e67066
    --- /dev/null
    +++ b/core/src/main/java/org/jivesoftware/MainWindow.java
    @@ -0,0 +1,911 @@
    +/*
    + * Copyright (C) 2004-2011 Jive Software. All rights reserved.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *     http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.jivesoftware;
    +
    +import org.jivesoftware.launcher.Startup;
    +import org.jivesoftware.resource.Default;
    +import org.jivesoftware.resource.Res;
    +import org.jivesoftware.resource.SparkRes;
    +import org.jivesoftware.smack.AbstractXMPPConnection;
    +import org.jivesoftware.smack.SmackConfiguration;
    +import org.jivesoftware.smack.SmackException;
    +import org.jivesoftware.smack.XMPPConnection;
    +import org.jivesoftware.smack.packet.Presence;
    +import org.jivesoftware.smack.packet.StanzaBuilder;
    +import org.jivesoftware.spark.SparkManager;
    +import org.jivesoftware.spark.ui.ChatFrame;
    +import org.jivesoftware.spark.ui.RawPacketSender;
    +import org.jivesoftware.spark.util.*;
    +import org.jivesoftware.spark.util.SwingWorker;
    +import org.jivesoftware.spark.util.log.Log;
    +import org.jivesoftware.sparkimpl.plugin.alerts.InputTextAreaDialog;
    +import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettingsManager;
    +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise;
    +import org.jivesoftware.sparkimpl.settings.JiveInfo;
    +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences;
    +import org.jivesoftware.sparkimpl.settings.local.SettingsManager;
    +import org.jivesoftware.sparkimpl.updater.CheckUpdates;
    +
    +import javax.swing.*;
    +import javax.swing.event.HyperlinkEvent;
    +import java.awt.*;
    +import java.awt.event.*;
    +import java.io.File;
    +import java.io.IOException;
    +import java.util.TimerTask;
    +import java.util.concurrent.CopyOnWriteArrayList;
    +
    +/**
    + * The MainWindow class acts as both the DockableHolder and the proxy
    + * to the Workspace in Spark.
    + */
    +public final class MainWindow extends ChatFrame implements ActionListener {
    +	private final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList<>();
    +    private final LocalPreferences pref = SettingsManager.getLocalPreferences();
    +
    +    private final JMenu connectMenu = new JMenu();
    +    private final JMenu contactsMenu = new JMenu();
    +    private final JMenu actionsMenu = new JMenu();
    +    private final JMenu pluginsMenu = new JMenu();
    +    private final JMenu helpMenu = new JMenu();
    +
    +    private JMenuItem preferenceMenuItem;
    +    private JCheckBoxMenuItem alwaysOnTopItem;
    +
    +    private final JMenuItem menuAbout = new JMenuItem(SparkRes.getImageIcon(SparkRes.Icon.INFORMATION_IMAGE));
    +    private final JMenuItem sparkforumItem = new JMenuItem();
    +
    +    private final JMenuBar mainWindowBar = new JMenuBar();
    +
    +    private boolean focused;
    +    private final JToolBar topToolbar = new JToolBar();
    +    private JSplitPane splitPane;
    +    private JEditorPane aboutBoxPane;
    +    private static MainWindow singleton;
    +
    +    /**
    +     * Returns the singleton instance of MainWindow,
    +     * creating it if necessary.
    +     * 

    + * + * @return the singleton instance of MainWindow + */ + public static synchronized MainWindow getInstance() { + if (null == singleton) { + singleton = new MainWindow(JiveInfo.getName(), SparkManager.getApplicationImage()); + } + return singleton; + } + + + /** + * Constructs the UI for the MainWindow. The MainWindow UI is the container for the + * entire Spark application. + * + * @param title the title of the frame. + * @param icon the icon used in the frame. + */ + private MainWindow(String title, ImageIcon icon) { + + + // Initialize and dock the menus + buildMenu(); + + + + // Add Workspace Container + getContentPane().setLayout(new BorderLayout()); + + setMinimumSize( new Dimension( 100, 200 ) ); + final Rectangle mainWindowBounds = LayoutSettingsManager.getLayoutSettings().getMainWindowBounds(); + if ( mainWindowBounds == null || mainWindowBounds.width <= 0 || mainWindowBounds.height <= 0 ) + { + // Use default settings. + setSize(500, 520); + GraphicUtils.centerWindowOnScreen(this); + } + else + { + setBounds( mainWindowBounds ); + } + + // Add menubar + this.setJMenuBar(mainWindowBar); + this.getContentPane().add(topToolbar, BorderLayout.NORTH); + + setTitle(title); + setIconImage(icon.getImage()); + + addComponentListener( new ComponentAdapter() + { + @Override + public void componentResized( ComponentEvent e ) + { + LayoutSettingsManager.getLayoutSettings().setMainWindowBounds( getBounds() ); + } + + @Override + public void componentMoved( ComponentEvent e ) + { + LayoutSettingsManager.getLayoutSettings().setMainWindowBounds( getBounds() ); + } + } ); + + // Setup WindowListener to be the proxy to the actual window listener + // which cannot normally be used outside of the Window component because + // of protected access. + addWindowListener(new WindowAdapter() { + + /** + * This event fires when the application is closing. + * This allows Plugins to do any persistence or other + * work before exiting. + * + * @param e WindowEvent is never used. + */ + @Override + public void windowClosing(WindowEvent e) { + setVisible(false); + } + }); + + this.addWindowFocusListener(new MainWindowFocusListener()); + } + + /** + * Adds a MainWindow listener to {@link MainWindow}. The + * listener will be called when either the MainWindow has been minimized, maximized, + * or is shutting down. + * + * @param listener the MainWindowListener to register + */ + public void addMainWindowListener(MainWindowListener listener) { + listeners.addIfAbsent(listener); + } + + /** + * Removes the specified {@link MainWindowListener}. + * + * @param listener the MainWindowListener to remove. + */ + public void removeMainWindowListener(MainWindowListener listener) { + listeners.remove(listener); + } + + /** + * Notifies all {@link MainWindowListener}s that the MainWindow + * is shutting down. + */ + private void fireWindowShutdown() + { + for ( MainWindowListener listener : listeners ) + { + try + { + listener.shutdown(); + } + catch ( Exception e ) + { + Log.error( "A MainWindowListener (" + listener + ") threw an exception while processing a 'shutdown' event.", e ); + } + } + } + + /** + * Invokes the Preferences Dialog. + * + * @param e the ActionEvent + */ + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource().equals(preferenceMenuItem)) { + SparkManager.getPreferenceManager().showPreferences(); + } + } + + /** + * Prepares Spark for shutting down by first calling all {@link MainWindowListener}s and + * setting the Agent to be offline. + */ + public void shutdown() { + final AbstractXMPPConnection con = SparkManager.getConnection(); + + if (con.isConnected()) { + // Send disconnect. + con.disconnect(); + } + + // Notify all MainWindowListeners + try { + fireWindowShutdown(); + } + catch (Exception ex) { + Log.error(ex); + } + // Close application. + System.exit(1); + + } + + /** + * Prepares Spark for shutting down by first calling all {@link MainWindowListener}s and + * setting the Agent to be offline. + * + * @param sendStatus true if Spark should send a presence with a status message. + */ + public void logout(boolean sendStatus) { + final XMPPConnection con = SparkManager.getConnection(); + String status = null; + + if (con.isConnected() && sendStatus) { + final InputTextAreaDialog inputTextDialog = new InputTextAreaDialog(); + status = inputTextDialog.getInput(Res.getString("title.status.message"), Res.getString("message.current.status"), + SparkRes.getImageIcon(SparkRes.Icon.USER1_MESSAGE_24x24), this); + } + + if (status != null || !sendStatus) + { + // Notify all MainWindowListeners + try { + // Set auto-login to false; + pref.setAutoLogin(false); + fireWindowShutdown(); + setVisible(false); + } + finally { + closeConnectionAndInvoke(status); + } + } + } + + /** + * Closes the current connection and restarts Spark. + * + * @param reason the reason for logging out. This can be if user gave no reason. + */ + public void closeConnectionAndInvoke(String reason) { + final AbstractXMPPConnection con = SparkManager.getConnection(); + if (con.isConnected()) { + if (reason != null) { + Presence byePresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .setStatus(reason) + .setPriority(-1) + .build(); + try + { + con.disconnect(byePresence); + } + catch ( SmackException.NotConnectedException e ) + { + Log.error( "Unable to sign out with presence.", e); + con.disconnect(); + } + } + else { + con.disconnect(); + } + } + if (!restartApplicationWithScript()) { + restartApplicationWithJava(); + } + } + + private File getLibDirectory() { + File jarFile; + try{ + jarFile = new File(Startup.class.getProtectionDomain().getCodeSource().getLocation().toURI()); + } catch(Exception e) { + Log.error("Cannot get jar file containing the startup class", e); + return null; + } + if ( !jarFile.getName().endsWith(".jar") ) { + Log.error("The startup class is not packaged in a jar file"); + return null; + } + return jarFile.getParentFile(); + } + + private String getClasspath() throws IOException { + File libDir = getLibDirectory(); + String libPath = null; + String[] files = new String[0]; + + if (libDir != null) { + libPath = libDir.getCanonicalPath(); + files = libDir.list(); + } + + StringBuilder classpath = new StringBuilder(); + if (files != null) { + for (String file : files) { + if (file.endsWith(".jar")) { + classpath.append(libPath).append(File.separatorChar).append(file).append(File.pathSeparatorChar); + } + } + } + return classpath.toString(); + } + + private String getCommandPath() throws IOException{ + File libDir = getLibDirectory(); + if (libDir == null) { + return null; + } + return libDir.getParentFile().getCanonicalPath(); + } + + public boolean restartApplicationWithScript() { + String command = null; + try { + String commandPath = getCommandPath(); + if (commandPath == null) { + return false; + } + if (Spark.isWindows()) { + String sparkExe = commandPath + File.separator + Default.getString(Default.SHORT_NAME) + ".exe"; + if (!new File(sparkExe).exists()) { + Log.warning("Client EXE file does not exist"); + return false; + } + String starterExe = commandPath + File.separator + "starter.exe"; + if (!new File(starterExe).exists()) { + Log.warning("Starter EXE file does not exist"); + return false; + } + command = starterExe + " \"" + sparkExe + "\""; + } else if (Spark.isLinux()) { + command = commandPath + File.separator + Default.getString(Default.SHORT_NAME); + if (!new File(command).exists()) { + Log.warning("Client startup script does not exist"); + return false; + } + } else if (Spark.isMac()) { + command = "open -a " + Default.getString(Default.SHORT_NAME); + } + + Runtime.getRuntime().exec(command); + System.exit(0); + return true; + } catch (Exception e) { + Log.error("Error trying to restart application with script", e); + return false; + } + } + + public boolean restartApplicationWithJava() { + String javaBin = System.getProperty("java.home") + File.separatorChar + "bin" + File.separatorChar + "java"; + try { + String[] toExec = new String[] { + javaBin, "-cp", getClasspath(), "org.jivesoftware.launcher.Startup"}; + Runtime.getRuntime().exec(toExec); + } catch (Exception e) { + Log.error("Error trying to restart application with java", e); + return false; + } + System.exit(0); + return true; + } + + /** + * Setup the Main Toolbar with File, Tools and Help. + */ + private void buildMenu() { + + // setup file menu + final JMenuItem exitMenuItem = new JMenuItem(); + + // Setup ResourceUtils + ResourceUtils.resButton(connectMenu, "&" + Res.getString("menuitem.connect")); + ResourceUtils.resButton(contactsMenu, Res.getString("menuitem.contacts")); + ResourceUtils.resButton(actionsMenu, Res.getString("menuitem.actions")); + ResourceUtils.resButton(exitMenuItem, Res.getString("menuitem.exit")); + ResourceUtils.resButton(pluginsMenu, Res.getString("menuitem.plugins")); + + exitMenuItem.setIcon(null); + + mainWindowBar.add(connectMenu); + mainWindowBar.add(contactsMenu); + mainWindowBar.add(actionsMenu); + //mainWindowBar.add(pluginsMenu); + mainWindowBar.add(helpMenu); + + + preferenceMenuItem = new JMenuItem(SparkRes.getImageIcon(SparkRes.Icon.PREFERENCES_IMAGE)); + preferenceMenuItem.setText(Res.getString("title.spark.preferences")); + preferenceMenuItem.addActionListener(this); + + // Show the "Preferences" menu item ONLY in Maintenance Mode or when DISABLE_PREFERENCES_MENU_ITEM = false and Client Control allows it. + File myMaintFile = new File(Default.getString(Default.MAINTENANCE_FILE_PATH)); + + final boolean maintMode = (myMaintFile.exists() && !myMaintFile.isDirectory()); + final boolean prefsAllowed = (!Default.getBoolean(Default.DISABLE_PREFERENCES_MENU_ITEM) && Enterprise.containsFeature(Enterprise.PREFERENCES_MENU_FEATURE)); + + if (maintMode || prefsAllowed) connectMenu.add(preferenceMenuItem); + + alwaysOnTopItem = new JCheckBoxMenuItem(); + ResourceUtils.resButton(alwaysOnTopItem, Res.getString("menuitem.always.on.top")); + alwaysOnTopItem.addActionListener( actionEvent -> { + pref.setMainWindowAlwaysOnTop(alwaysOnTopItem.isSelected()); + MainWindow.getInstance().setAlwaysOnTop(alwaysOnTopItem.isSelected()); + } ); + + alwaysOnTopItem.setSelected(pref.isMainWindowAlwaysOnTop()); + this.setAlwaysOnTop(pref.isMainWindowAlwaysOnTop()); + + connectMenu.add(alwaysOnTopItem); + + // Set up the Logout and Exit menus... + if (!Default.getBoolean(Default.DISABLE_EXIT) && Enterprise.containsFeature(Enterprise.LOGOUT_EXIT_FEATURE)) { + connectMenu.addSeparator(); + if(!Default.getBoolean(Default.HIDE_SAVE_PASSWORD_AND_AUTO_LOGIN) && pref.getPswdAutologin()) { + JMenuItem logoutMenuItem = new JMenuItem(); + ResourceUtils.resButton(logoutMenuItem, Res.getString("menuitem.logout.no.status")); + logoutMenuItem.addActionListener( e -> logout(false) ); + + JMenuItem logoutWithStatus = new JMenuItem(); + ResourceUtils.resButton(logoutWithStatus, Res.getString("menuitem.logout.with.status")); + logoutWithStatus.addActionListener( e -> logout(true) ); + + connectMenu.add(logoutMenuItem); + connectMenu.add(logoutWithStatus); + connectMenu.addSeparator(); + } + connectMenu.add(exitMenuItem); + } + + JMenuItem updateMenu= new JMenuItem("", SparkRes.getImageIcon(SparkRes.Icon.CHECK_UPDATE)); + ResourceUtils.resButton(updateMenu, Res.getString("menuitem.check.for.updates")); + updateMenu.addActionListener( e -> checkForUpdates(true) ); + + // Add Error Dialog Viewer + final Action viewErrors = new AbstractAction() { + private static final long serialVersionUID = -420926784631340112L; + + @Override + public void actionPerformed(ActionEvent e) { + File logDir = new File(Spark.getLogDirectory(), "errors.log.0"); + if (!logDir.exists()) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(SparkManager.getMainWindow(), "No error logs found.", "Error Log", JOptionPane.INFORMATION_MESSAGE); + } + else { + showErrorLog(); + } + } + }; + + viewErrors.putValue(Action.NAME, Res.getString("menuitem.view.logs")); + + final Action viewHelpGuideAction = new AbstractAction() { + + final String url = Default.getString(Default.HELP_USER_GUIDE); + private static final long serialVersionUID = 2680369963282231348L; + + @Override + public void actionPerformed(ActionEvent actionEvent) { + try { + + BrowserLauncher.openURL(url); + } + catch (Exception e) { + Log.error("Unable to load online help.", e); + } + } + }; + + + if (!Default.getBoolean(Default.HELP_USER_GUIDE_DISABLED) && Enterprise.containsFeature(Enterprise.HELP_USERGUIDE_FEATURE)) { + viewHelpGuideAction.putValue(Action.NAME, + Res.getString("menuitem.user.guide")); + viewHelpGuideAction.putValue(Action.SMALL_ICON, + SparkRes.getImageIcon(SparkRes.Icon.SMALL_QUESTION)); + helpMenu.add(viewHelpGuideAction); + } + + if (!Default.getBoolean(Default.HELP_FORUM_DISABLED) && Enterprise.containsFeature(Enterprise.HELP_FORUMS_FEATURE)) helpMenu.add(sparkforumItem); + + // Build Help Menu + if (!Default.getBoolean(Default.DISABLE_UPDATES) && Enterprise.containsFeature(Enterprise.UPDATES_FEATURE)) helpMenu.add(updateMenu); + + helpMenu.addSeparator(); + helpMenu.add(viewErrors); + helpMenu.add(menuAbout); + + // ResourceUtils - Adds mnemonics + ResourceUtils.resButton(preferenceMenuItem, Res.getString("menuitem.preferences")); + ResourceUtils.resButton(helpMenu, Res.getString("menuitem.help")); + ResourceUtils.resButton(menuAbout, Res.getString("menuitem.about")); + + if (!Default.getString(Default.HELP_FORUM_TEXT).isEmpty()) { + ResourceUtils.resButton(sparkforumItem, Default.getString(Default.HELP_FORUM_TEXT)); + } else { + ResourceUtils.resButton(sparkforumItem, Res.getString("menuitem.online.help")); + } + // Register shutdown with the exit menu. + exitMenuItem.addActionListener(new AbstractAction() { + private static final long serialVersionUID = -2301236575241532698L; + + @Override + public void actionPerformed(ActionEvent e) { + shutdown(); + } + }); + + sparkforumItem.addActionListener(new AbstractAction() { + private static final long serialVersionUID = -1423433460333010339L; + + final String url = Default.getString(Default.HELP_FORUM); + + @Override + public void actionPerformed(ActionEvent e) { + try { + BrowserLauncher.openURL(url); + } catch (Exception browserException) { + Log.error("Error launching browser:", browserException); + } + } + }); + + // Show About Box + menuAbout.addActionListener(new AbstractAction() { + private static final long serialVersionUID = -7173666373051354502L; + + @Override + public void actionPerformed(ActionEvent e) { + showAboutBox(); + } + }); + + if (!Default.getBoolean(Default.DISABLE_UPDATES) && Enterprise.containsFeature(Enterprise.UPDATES_FEATURE)) { + // Execute spark update checker after one minute. + final TimerTask task = new SwingTimerTask() { + @Override + public void doRun() { + checkForUpdates(false); + } + }; + + TaskEngine.getInstance().schedule(task, 60000); + } + + if(pref.isDebuggerEnabled()) + { + JMenuItem rawPackets = new JMenuItem(SparkRes.getImageIcon(SparkRes.Icon.TRAY_IMAGE)); + rawPackets.setText("Send Packets"); + rawPackets.addActionListener( e -> new RawPacketSender() ); + + connectMenu.add(rawPackets,2); + } + + } + + /** + * Returns the JMenuBar for the MainWindow. You would call this if you + * wished to add or remove menu items to the main menubar. (File | Tools | Help) + * + * @return the Jive Talker Main Window MenuBar + */ + public JMenuBar getMenu() { + return mainWindowBar; + } + + /** + * Returns the Menu in the JMenuBar by it's name. For example:

    + *

    +     * JMenu toolsMenu = getMenuByName("Tools");
    +     * 
    + *

    + * + * @param name the name of the Menu. + * @return the JMenu item with the requested name. + */ + public JMenu getMenuByName(String name) { + for (int i = 0; i < getMenu().getMenuCount(); i++) { + JMenu menu = getMenu().getMenu(i); + if (menu.getText().equals(name)) { + return menu; + } + } + return null; + } + + /** + * Returns true if the Spark window is in focus. + * + * @return true if the Spark window is in focus. + */ + @Override + public boolean isInFocus() { + return focused; + } + + private class MainWindowFocusListener implements WindowFocusListener { + + @Override + public void windowGainedFocus(WindowEvent e) { + focused = true; + } + + @Override + public void windowLostFocus(WindowEvent e) { + focused = false; + } + } + + /** + * Return the top toolbar in the Main Window to allow for customization. + * + * @return the MainWindows top toolbar. + */ + public JToolBar getTopToolBar() { + return topToolbar; + } + + /** + * Checks for the latest update on the server. + * + * @param forced true if you want to bypass the normal checking security. + */ + private void checkForUpdates(final boolean forced) { + final CheckUpdates updater = new CheckUpdates(); + try { + final SwingWorker updateThread = new SwingWorker() { + @Override + public Object construct() { + try { + Thread.sleep(50); + } + catch (InterruptedException e) { + Log.error(e); + } + return "ok"; + } + + @Override + public void finished() { + try { + updater.checkForUpdate(forced); + } + catch (Exception e) { + Log.error("There was an error while checking for a new update.", e); + } + } + }; + + updateThread.start(); + + } + catch (Exception e) { + Log.warning("Error updating.", e); + } + } + + /** + * Sets About Box Pane for Spark. + */ + private void setAboutBoxPane() { + + // Get values from default.properties file + final String APPLICATION_INFO1 = Default.getString(Default.APPLICATION_INFO1); + final String APPLICATION_INFO2 = Default.getString(Default.APPLICATION_INFO2); + final String APPLICATION_INFO3 = Default.getString(Default.APPLICATION_INFO3); + final String APPLICATION_LICENSE_LINK = Default.getString(Default.APPLICATION_LICENSE_LINK); + final String APPLICATION_LICENSE_LINK_TXT = Default.getString(Default.APPLICATION_LICENSE_LINK_TXT); + final String APPLICATION_INFO4 = Default.getString(Default.APPLICATION_INFO4); + final String APPLICATION_LINK = Default.getString(Default.APPLICATION_LINK); + final String APPLICATION_LINK_TXT = Default.getString(Default.APPLICATION_LINK_TXT); + final boolean DISPLAY_DEV_INFO = Default.getBoolean(Default.DISPLAY_DEV_INFO); + final String JAVA_VERSION = Default.getString(Default.JAVA_VERSION); + + // Construct About Box text + StringBuilder aboutBoxText = new StringBuilder(); + aboutBoxText.append(JiveInfo.getName()).append(" ").append(JiveInfo.getVersion()); + + // Add APPLICATION_INFO1 if not empty + if (!("".equals(APPLICATION_INFO1))) { + aboutBoxText.append("
    ").append(APPLICATION_INFO1); + } + + // Add APPLICATION_INFO2 if not empty + if (!( "".equals(APPLICATION_INFO2))) { + aboutBoxText.append("
    ").append(APPLICATION_INFO2); + } + + // Add APPLICATION_INFO3 if not empty + if (!("".equals(APPLICATION_INFO3))) { + aboutBoxText.append("
    ").append(APPLICATION_INFO3); + } + + // Add APPLICATION_LICENSE_LINK if not empty + if (!( "".equals(APPLICATION_LICENSE_LINK))) { + aboutBoxText.append("
    ") + .append(APPLICATION_LICENSE_LINK_TXT).append(""); + } + + // Add APPLICATION_LINK if not empty + if (!( "".equals(APPLICATION_LINK))) { + aboutBoxText.append("
    ") + .append(APPLICATION_LINK_TXT).append(""); + } + + // Add APPLICATION_INFO4 if not empty + if (!( "".equals(APPLICATION_INFO4))) { + aboutBoxText.append("
    ").append(APPLICATION_INFO4); + } + + aboutBoxText.append("
    Smack Version: ").append(SmackConfiguration.getVersion()); + + if (DISPLAY_DEV_INFO) { + // Add Java JRE Version if is empty + if ("".equals(JAVA_VERSION)) { + aboutBoxText.append("
    JRE Version: ").append(System.getProperty("java.version")); + aboutBoxText.append(" ").append(System.getProperty("sun.arch.data.model")).append("-bit"); + } + } + + // copy window style + JPanel p = new JPanel(); + Font font = p.getFont(); + + // create some css from the JPanel's font + String style = ( "font-family:" + font.getFamily() + ";" ) + + "font-weight:" + ( font.isBold() ? "bold" : "normal" ) + ";" + + "font-size:" + font.getSize() + "pt;"; + + // assemble html + JEditorPane ep = new JEditorPane("text/html", ( "" + aboutBoxText.toString() + "" ) ); + + // handle link events + ep.addHyperlinkListener( e -> { + // if a link is clicked, and it is the APPLICATION_LICENSE_LINK, then load that page + if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED) + && e.getURL().toString().equalsIgnoreCase(Default.getString(Default.APPLICATION_LICENSE_LINK))) { + try { + + BrowserLauncher.openURL(Default.getString(Default.APPLICATION_LICENSE_LINK)); + + } catch (Exception f) { + Log.error("There was an error loading the URL", f); + } + + // else if a link is clicked, and it is the APPLICATION_LINK, then load that page + } else if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED) + && e.getURL().toString().equalsIgnoreCase(Default.getString(Default.APPLICATION_LINK))) { + try { + + BrowserLauncher.openURL(Default.getString(Default.APPLICATION_LINK)); + + } catch (Exception f) { + Log.error("There was an error loading the URL", f); + } + } + + } ); + ep.setEditable(false); + ep.setBackground(p.getBackground()); + this.aboutBoxPane = ep; + + } + + /** + * Returns About Box Pane. + * @return JEditorPane About Box + */ + private JEditorPane getAboutBoxPane() { + if (null == this.aboutBoxPane) { + setAboutBoxPane(); + } + return this.aboutBoxPane; + } + + /** + * Displays the About Box for Spark. + */ + private static void showAboutBox() { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(SparkManager.getMainWindow(), SparkManager.getMainWindow().getAboutBoxPane(), + Res.getString("title.about"), JOptionPane.INFORMATION_MESSAGE, SparkRes.getImageIcon(SparkRes.Icon.MAIN_IMAGE)); + } + + /** + * Displays the Spark error log. + */ + private void showErrorLog() { + final File logDir = new File(Spark.getLogDirectory(), "errors.log.0"); + + // Read file and show + final String errorLogs = URLFileSystem.getContents(logDir); + + final JFrame frame = new JFrame(Res.getString("title.client.logs")); + frame.setLayout(new BorderLayout()); + frame.setIconImage(SparkManager.getApplicationImage().getImage()); + + final JTextPane pane = new JTextPane(); + pane.setBackground(Color.white); + pane.setFont(new Font("Dialog", Font.PLAIN, 12)); + pane.setEditable(false); + pane.setText(errorLogs); + + final JButton copyButton = new JButton(Res.getString("button.copy.to.clipboard")); + copyButton.setIcon(SparkRes.getImageIcon(SparkRes.Icon.COPY_16x16)); + final JButton openFolder = new JButton(Res.getString("open.folder")); + openFolder.setIcon(SparkRes.getImageIcon(SparkRes.Icon.FOLDER)); + + final JPanel panel = new JPanel(); + panel.add(openFolder, BorderLayout.LINE_START); + panel.add(copyButton, BorderLayout.LINE_END); + + frame.add(new JScrollPane(pane), BorderLayout.CENTER); + frame.add(panel, BorderLayout.SOUTH); + + + copyButton.addActionListener( e -> { + SparkManager.setClipboard(errorLogs); + copyButton.setEnabled(false); + } ); + + openFolder.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + openFolder.setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + openFolder.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + + @Override + public void mousePressed(MouseEvent event) { + try { + Desktop.getDesktop().open(Spark.getLogDirectory()); + } catch (IOException e) { + Log.error("An error occurred while trying to open logs file: " + Spark.getLogDirectory(), e); + } + } + }); + + frame.pack(); + frame.setSize(530, 500); + + GraphicUtils.centerWindowOnScreen(frame); + frame.setVisible(true); + } + + /** + * Return true if the MainWindow is docked. + * + * @return true if the window is docked. + */ + public boolean isDocked() { + return pref.isDockingEnabled(); + } + + /** + * Returns the inner split pane. + * + * @return the split pane. + */ + public JSplitPane getSplitPane() { + // create the split pane only if required. + if (splitPane == null) { + splitPane = new JSplitPane(); + } + return this.splitPane; + } +} diff --git a/src/java/org/jivesoftware/MainWindowListener.java b/core/src/main/java/org/jivesoftware/MainWindowListener.java similarity index 97% rename from src/java/org/jivesoftware/MainWindowListener.java rename to core/src/main/java/org/jivesoftware/MainWindowListener.java index beb6f2dd3..1494431b1 100644 --- a/src/java/org/jivesoftware/MainWindowListener.java +++ b/core/src/main/java/org/jivesoftware/MainWindowListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/Restarter.java b/core/src/main/java/org/jivesoftware/Restarter.java similarity index 88% rename from src/java/org/jivesoftware/Restarter.java rename to core/src/main/java/org/jivesoftware/Restarter.java index 71b1ead59..0450cc1e2 100644 --- a/src/java/org/jivesoftware/Restarter.java +++ b/core/src/main/java/org/jivesoftware/Restarter.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,7 +34,7 @@ public class Restarter { * * @param args the array of arguments. */ - public static void main(String args[]) { + public static void main(String[] args) { if (args.length == 0) { return; } @@ -85,16 +81,6 @@ public static boolean isWindows() { return osName.startsWith("windows"); } - /** - * Returns true if Spark is running on vista. - * - * @return true if running on Vista. - */ - public static boolean isVista() { - final String osName = System.getProperty("os.name").toLowerCase(); - return osName.contains("vista"); - } - /** * Return if we are running on a mac. * diff --git a/core/src/main/java/org/jivesoftware/Spark.java b/core/src/main/java/org/jivesoftware/Spark.java new file mode 100644 index 000000000..6060d5198 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/Spark.java @@ -0,0 +1,364 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.jivesoftware; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.ui.themes.ColorSettingManager; +import org.jivesoftware.spark.ui.themes.ColorSettings; +import org.jivesoftware.spark.ui.themes.LookAndFeelManager; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.UIComponentRegistry; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import javax.swing.*; +import java.awt.*; +import java.io.File; +import java.io.IOException; +import java.util.Locale; + +import org.jivesoftware.gui.LoginUIPanel; + +import static org.apache.commons.lang3.SystemUtils.*; + + +/** + * In many cases, you will need to know the structure of the Spark installation, such as the directory structures, what + * type of system Spark is running on, and also the arguments which were passed into Spark on startup. The Spark + * class provides some simple static calls to retrieve this information. + */ +public final class Spark { + private static File USER_SPARK_HOME; + public static String ARGUMENTS; + private static File RESOURCE_DIRECTORY; + private static File BIN_DIRECTORY; + private static File LOG_DIRECTORY; + private static File PLUGIN_DIRECTORY; + private static File SECURITY_DIRECTORY; + + + /** + * Private constructor that invokes the LoginDialog and + * the Spark Main Application. + */ + public Spark() { + } + + private static synchronized File initializeDirectory(File directoryHome, String directoryName) { + File targetDir = new File(directoryHome, directoryName).getAbsoluteFile(); + if (!targetDir.exists()) { + targetDir.mkdirs(); + } + return targetDir; + } + + private static File initializeDirectory(String directoryName) { + return initializeDirectory(USER_SPARK_HOME , directoryName); + } + + /** + * Configures environment; starts application; invokes login + */ + public void startup() { + // Sets user home based on environment or properties + if (System.getenv("APPDATA") != null && !System.getenv("APPDATA").isEmpty()) { + USER_SPARK_HOME = new File(System.getenv("APPDATA") + "/" + getUserConf()); + } else { + USER_SPARK_HOME = new File(System.getProperties().getProperty("user.home") + "/" + getUserConf()); + } + + String current = System.getProperty("java.library.path"); + String classPath = System.getProperty("java.class.path"); + + // Set UIManager properties for JTree + System.setProperty("apple.laf.useScreenMenuBar", "true"); + + // Update Library Path + String javaLibraryPath = current + ";"; + + SparkCompatibility.transferConfig(USER_SPARK_HOME); + + RESOURCE_DIRECTORY = initializeDirectory("resources"); + BIN_DIRECTORY = initializeDirectory("bin"); + LOG_DIRECTORY = initializeDirectory("logs"); + File USER_DIRECTORY = initializeDirectory("user"); + PLUGIN_DIRECTORY = initializeDirectory("plugins"); + File XTRA_DIRECTORY = initializeDirectory("xtra"); + SECURITY_DIRECTORY = initializeDirectory("security"); + // TODO implement copyEmoticonFiles(); + final String workingDirectory = System.getProperty("appdir"); + if (workingDirectory == null) { + System.out.println("Warning: no working directory set. This might cause updated data to be missed. Please set a system property 'appdir' to the location where Spark is installed to correct this."); + // Terminate if required directories cannot be created + if (!RESOURCE_DIRECTORY.exists() || !LOG_DIRECTORY.exists() || !USER_DIRECTORY.exists() || !PLUGIN_DIRECTORY.exists() || !XTRA_DIRECTORY.exists() || !SECURITY_DIRECTORY.exists()) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(new JFrame(), "Unable to create directories necessary for runtime.", "Spark Error", JOptionPane.ERROR_MESSAGE); + System.exit(1); + } + } else { + // This is the Spark.exe or Spark.dmg installed executable. + File workingDir = new File(workingDirectory); + RESOURCE_DIRECTORY = initializeDirectory(workingDir, "resources"); + BIN_DIRECTORY = initializeDirectory(workingDir, "bin"); + File emoticons = new File(XTRA_DIRECTORY, "emoticons").getAbsoluteFile(); + if (!emoticons.exists()) { + File[] emoticonsFiles = emoticons.listFiles(); + if (emoticonsFiles == null || emoticonsFiles.length == 0) { + // Copy emoticon files from installation directory to the spark user home directory + copyEmoticonFiles(workingDirectory); + } + } + SECURITY_DIRECTORY = initializeDirectory(workingDir, "security"); + LOG_DIRECTORY = initializeDirectory("logs"); + LOG_DIRECTORY = new File(USER_SPARK_HOME, "logs").getAbsoluteFile(); + LOG_DIRECTORY.mkdirs(); + try { + javaLibraryPath += RESOURCE_DIRECTORY.getCanonicalPath() + ";"; + } catch (IOException e) { + e.printStackTrace(); + } + } + + // Set the default language set by the user + loadLanguage(); + + // Loads the LookandFeel + LookAndFeelManager.loadPreferredLookAndFeel(); + + javaLibraryPath += classPath + ";" + RESOURCE_DIRECTORY.getAbsolutePath(); + + // Update System Properties + System.setProperty("java.library.path", javaLibraryPath); + System.setProperty("sun.java2d.noddraw", "true"); + System.setProperty("file.encoding", "UTF-8"); + + // Start Application + SwingUtilities.invokeLater(Spark::new); + installBaseUIProperties(); + if (Default.getBoolean(Default.CHANGE_COLORS_DISABLED)) { + ColorSettingManager.restoreDefault(); + } + + try { + EventQueue.invokeAndWait(() -> { + final LoginUIPanel dialog = UIComponentRegistry.createLoginDialog(); + dialog.invoke(); + }); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + // Setup the look and feel of this application. + static { + com.install4j.api.launcher.StartupNotification.registerStartupListener(new SparkStartupListener()); + } + + public static boolean isWindows() { + return IS_OS_WINDOWS; + } + + public static boolean isMac() { + return IS_OS_MAC; + } + + public static boolean isLinux() { + return IS_OS_LINUX; + } + + /** + * Returns the value associated with a passed in argument. Spark + * accepts HTTP style attributes to allow for name-value pairing. + * e.g. username=foo&password=pwd. + * To retrieve the value of a username, you would do the following: + *
    +     * String value = Spark.getArgumentValue("username");
    +     * 
    + * + * @param argumentName the name of the argument to retrieve. + * @return the value of the argument. If no argument was found, null will be returned. + */ + public static String getArgumentValue(String argumentName) { + if (ARGUMENTS == null) { + return null; + } + String arg = argumentName + "="; + + int index = ARGUMENTS.indexOf(arg); + if (index == -1) { + return null; + } + + String value = ARGUMENTS.substring(index + arg.length()); + int index2 = value.indexOf("&"); + if (index2 != -1) { + // Must be the last argument + value = value.substring(0, index2); + } + return value; + } + + public void setArgument(String arguments) { + ARGUMENTS = arguments; + } + + /** + * Returns the bin directory of the Spark install. The bin directory contains the startup scripts needed + * to start Spark. + * + * @return the bin directory. + */ + public static File getBinDirectory() { + if (BIN_DIRECTORY == null) { + BIN_DIRECTORY = initializeDirectory("bin"); + } + return BIN_DIRECTORY; + } + + /** + * Returns the resource directory of the Spark install. The resource directory contains all native + * libraries needed to run os specific operations, such as tray support. You may place other native + * libraries within this directory if you wish to have them placed into the system.library.path. + * + * @return the resource directory. + */ + public static File getResourceDirectory() { + if (RESOURCE_DIRECTORY == null) { + RESOURCE_DIRECTORY = initializeDirectory("resources"); + } + return RESOURCE_DIRECTORY; + } + + /** + * Returns the plugins directory of the Spark installation. THe plugins-dir contains all the third-party plugins. + * + * @return the plugins directory + */ + public static File getPluginDirectory() { + if (PLUGIN_DIRECTORY == null) { + PLUGIN_DIRECTORY = initializeDirectory("plugins"); + } + return PLUGIN_DIRECTORY; + } + + /** + * Returns the log directory. The log directory contains all debugging and error files for Spark. + * + * @return the log directory. + */ + public static File getLogDirectory() { + if (LOG_DIRECTORY == null) { + LOG_DIRECTORY = initializeDirectory("logs"); + } + return LOG_DIRECTORY; + } + + /** + * Keep track of the users configuration directory. + * + * @return Directory name depending on Operating System. + */ + public static String getUserConf() { + if (isLinux()) { + return Default.getString(Default.USER_DIRECTORY_LINUX); + } + if (isMac()) { + return Default.getString(Default.USER_DIRECTORY_MAC); + } + return Default.getString(Default.USER_DIRECTORY_WINDOWS); + } + + + /** + * Returns the Spark directory for the current user (user.home). The user home is where all user specific + * files are placed to run Spark within a multi-user system. + * + * @return the user home / Spark; + */ + public static File getSparkUserHome() { + return USER_SPARK_HOME; + } + + /** + * Return the base user home. + * + * @return the user home. + */ + public static String getUserHome() { + return System.getProperties().getProperty("user.home"); + } + + public static boolean disableUpdatesOnCustom() { + return Default.getBoolean(Default.DISABLE_UPDATES); + } + + public static synchronized void setApplicationFont(Font f) { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + for (Object ui_property : defaults.keySet()) { + if (ui_property.toString().endsWith(".font")) { + UIManager.put(ui_property, f); + } + } + } + + /** + * Sets Spark specific colors + */ + public static void installBaseUIProperties() { + setApplicationFont(new Font("Dialog", Font.PLAIN, 11)); + UIManager.put("ContactItem.border", BorderFactory.createLineBorder(Color.white)); + //UIManager.put("TextField.font", new Font("Dialog", Font.PLAIN, 11)); + //UIManager.put("Label.font", new Font("Dialog", Font.PLAIN, 11)); + + ColorSettings colorsettings = ColorSettingManager.getColorSettings(); + for (String property : colorsettings.getKeys()) { + Color c = colorsettings.getColorFromProperty(property); + UIManager.put(property, c); + } + } + + /** + * Loads the language set by the user. If no language is set, then the default implementation will be used. + */ + private void loadLanguage() { + final LocalPreferences preferences = SettingsManager.getLocalPreferences(); + final String setLanguage = preferences.getLanguage(); + if (ModelUtil.hasLength(setLanguage)) { + Locale userLocale = Locale.forLanguageTag(setLanguage.replace("_", "-")); + Locale.setDefault(userLocale); + } + } + + public void copyEmoticonFiles(String workdir) { + // Current Plugin directory + File newEmoticonDir = new File(Spark.getLogDirectory().getParentFile(), "xtra" + File.separator + "emoticons").getAbsoluteFile(); + newEmoticonDir.mkdirs(); + + File EMOTICON_DIRECTORY = new File(workdir + File.separator + "xtra" + File.separator + "emoticons"); + File[] emoticonsFiles = EMOTICON_DIRECTORY.listFiles(); + if (emoticonsFiles != null) { + for (File file : emoticonsFiles) { + if (file.isFile()) { + // Copy over + File newFile = new File(newEmoticonDir, file.getName()); + } + } + } + } +} diff --git a/core/src/main/java/org/jivesoftware/SparkCompatibility.java b/core/src/main/java/org/jivesoftware/SparkCompatibility.java new file mode 100644 index 000000000..1f9b1754c --- /dev/null +++ b/core/src/main/java/org/jivesoftware/SparkCompatibility.java @@ -0,0 +1,122 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware; + +import org.apache.commons.lang3.SystemUtils; +import org.jivesoftware.spark.util.log.Log; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; + + +public class SparkCompatibility { + + /** + * Copies the old USER_SPARK_HOME to the new directory if it does not exist + */ + public static void transferConfig(File newSparkHomeDir) { + if (newSparkHomeDir.exists()) { + return; + } + // Old Spark settings directory + final String OLD_USER_SPARK_HOME = System.getProperties().getProperty("user.home") + "/" + Spark.getUserConf(); + final String OLD_USER_SPARK_HOME_MAC = System.getProperties().getProperty("user.home") + "/Spark"; + File oldSparkHomeDir; + if (SystemUtils.IS_OS_MAC) { + oldSparkHomeDir = new File(OLD_USER_SPARK_HOME_MAC); + } else { + oldSparkHomeDir = new File(OLD_USER_SPARK_HOME); + } + + if (oldSparkHomeDir.exists()) { + // Absolute paths to a collection of files or directories to skip + Collection skipFiles = List.of( + new File(newSparkHomeDir, "plugins").getAbsolutePath() + ); + try { + copyDirectory(oldSparkHomeDir, newSparkHomeDir, skipFiles); + } catch (IOException e) { + Log.error("Unable to copy old Spark home directory", e); + } + } + } + + /** + * Copies the directories / files recursively + * + * @param src The source dir/file to copy + * @param dest The destination dir/file to copy + * @param skipFiles A collection of files to skip + */ + private static void copyDirectory(File src, File dest, Collection skipFiles) throws IOException { + if (src.isDirectory()) { + if (!dest.exists()) { + dest.mkdir(); + } + String[] children = src.list(); + for (String child : children) { + // Skip any directories / files which may need to be skipped. + if (!skipFiles.contains((new File(dest, child).getAbsolutePath()))) { + copyDirectory(new File(src, child), new File(dest, child), new HashSet<>()); + } + } + } else { + InputStream in; + OutputStream out; + + try { + in = new FileInputStream(src); + out = new FileOutputStream(dest); + } catch (FileNotFoundException e) { + IOException wrapper = new IOException("copyDirectory: Unable to open handle on file: " + + src.getAbsolutePath() + "and" + dest.getAbsolutePath() + ".", e); + wrapper.setStackTrace(e.getStackTrace()); + throw wrapper; + } catch (SecurityException e) { + IOException wrapper = new IOException("copyDirectory: access denied to copy file: " + + src.getAbsolutePath() + "and" + dest.getAbsolutePath() + ".", e); + wrapper.setStackTrace(e.getStackTrace()); + throw wrapper; + } + try { + // Copy the bits from instream to outstream + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + } catch (IOException e) { + IOException wrapper = new IOException("copyDirectory: Unable to copy file: " + + src.getAbsolutePath() + "to" + dest.getAbsolutePath() + ".", e); + wrapper.setStackTrace(e.getStackTrace()); + throw wrapper; + } finally { + in.close(); + out.close(); + } + } + } + +} diff --git a/src/java/org/jivesoftware/SparkStartupListener.java b/core/src/main/java/org/jivesoftware/SparkStartupListener.java similarity index 82% rename from src/java/org/jivesoftware/SparkStartupListener.java rename to core/src/main/java/org/jivesoftware/SparkStartupListener.java index 743fbd85f..51d8c7c9b 100644 --- a/src/java/org/jivesoftware/SparkStartupListener.java +++ b/core/src/main/java/org/jivesoftware/SparkStartupListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,9 +25,13 @@ */ public class SparkStartupListener implements com.install4j.api.launcher.StartupNotification.Listener { + @Override public void startupPerformed(String args) { if (args != null && !args.trim().isEmpty()) { - SparkManager.getChatManager().handleURIMapping(args); - } + SparkManager.getUriManager().handleURIMapping(args, true); + } else { + SparkManager.getMainWindow().setVisible(true); + SparkManager.getMainWindow().toFront(); + } } } diff --git a/core/src/main/java/org/jivesoftware/XmppProviders.java b/core/src/main/java/org/jivesoftware/XmppProviders.java new file mode 100644 index 000000000..d0c657e5f --- /dev/null +++ b/core/src/main/java/org/jivesoftware/XmppProviders.java @@ -0,0 +1,105 @@ +/** + * Copyright (C) 2004-2024 Jive Software. All rights reserved. + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.jivesoftware; + +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.jivesoftware.spark.util.log.Log; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; + + +public class XmppProviders { + /** + * Providers A + */ + private static final String[] providers = new String[]{ + "07f.de", + "chalec.org", + "chapril.org", + "chatrix.one", + "draugr.de", + "hookipa.net", + "jabber.fr", + "macaw.me", + "magicbroccoli.de", + "nixnet.services", + "projectsegfau.lt", + "redlibre.es", + "suchat.org", + "sure.im", + "trashserver.net", + "xmpp.earth", + "yax.im", + }; + + public static List getXmppProvidersModel() { + List providersList = downloadProvidersList(); + if (providersList != null) { + return providersList; + } + // fallback to static list + providersList = asList(providers); + return providersList; + } + + static List downloadProvidersList() { + Log.debug("Download providers"); + try (CloseableHttpClient httpClient = HttpClients.createSystem()) { + HttpGet request = new HttpGet("https://data.xmpp.net/providers/v2/providers-As.json"); + try (ClassicHttpResponse httpResponse = httpClient.executeOpen(null, request, null)) { + final int statusCode = httpResponse.getCode(); + if (statusCode == 200) { + String json = EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8); + return parseProvidersJson(json); + } + Log.error("Download providers: bad status " + statusCode); + return null; + } + } catch (Exception e) { + Log.error("Download providers: error", e); + return null; + } + } + + static List parseProvidersJson(String json) { + // manually parse JSON array + json = json.trim(); + if (json.charAt(0) != '[' || json.charAt(json.length() - 1) != ']') { + return null; + } + String[] lines = json.substring(1, json.length() - 1).split(","); + List providers = new ArrayList<>(lines.length); + for (String line : lines) { + line = line.trim(); + if (line.charAt(0) != '"' || line.charAt(line.length() - 1) != '"') { + continue; + } + String provider = line.substring(1, line.length() - 1); + providers.add(provider); + } + return providers; + } +} diff --git a/core/src/main/java/org/jivesoftware/gui/LoginUIPanel.form b/core/src/main/java/org/jivesoftware/gui/LoginUIPanel.form new file mode 100644 index 000000000..c089dd7a1 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/gui/LoginUIPanel.form @@ -0,0 +1,428 @@ + + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/src/main/java/org/jivesoftware/gui/LoginUIPanel.java b/core/src/main/java/org/jivesoftware/gui/LoginUIPanel.java new file mode 100644 index 000000000..c0b25b9d4 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/gui/LoginUIPanel.java @@ -0,0 +1,1713 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.gui; + +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.GridBagLayout; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Principal; +import java.security.UnrecoverableKeyException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; +import javax.net.ssl.SSLContext; +import javax.security.auth.Subject; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.login.Configuration; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JPopupMenu; +import javax.swing.JSplitPane; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.text.JTextComponent; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; +import org.jivesoftware.AccountCreationWizard; +import org.jivesoftware.MainWindow; +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.AbstractXMPPConnection; +import org.jivesoftware.smack.ConnectionConfiguration; +import org.jivesoftware.smack.ReconnectionManager; +import org.jivesoftware.smack.SASLAuthentication; +import org.jivesoftware.smack.SmackConfiguration; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.ConnectionConfiguration.DnssecMode; +import org.jivesoftware.smack.parsing.ExceptionLoggingCallback; +import org.jivesoftware.smack.proxy.ProxyInfo; +import org.jivesoftware.smack.sasl.javax.SASLExternalMechanism; +import org.jivesoftware.smack.sasl.javax.SASLGSSAPIMechanism; +import org.jivesoftware.smack.tcp.XMPPTCPConnection; +import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; +import org.jivesoftware.smack.util.DNSUtil; +import org.jivesoftware.smack.util.TLSUtils; +import org.jivesoftware.smackx.carbons.CarbonManager; +import org.jivesoftware.smackx.chatstates.ChatStateManager; +import org.jivesoftware.smackx.iqregister.AccountManager; +import org.jivesoftware.spark.PluginManager; +import org.jivesoftware.spark.SessionManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.Workspace; +import org.jivesoftware.spark.component.MessageDialog; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.sasl.SASLGSSAPIv3CompatMechanism; +import org.jivesoftware.spark.ui.login.GSSAPIConfiguration; +import org.jivesoftware.spark.ui.login.LoginSettingDialog; +import org.jivesoftware.spark.util.*; + +import static org.jivesoftware.spark.util.StringUtils.modifyWildcards; +import static org.jivesoftware.sparkimpl.certificates.SparkSSLContextCreator.Options.BOTH; +import static org.jivesoftware.sparkimpl.certificates.SparkSSLContextCreator.Options.ONLY_SERVER_SIDE; + +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.certificates.CertificateModel; +import org.jivesoftware.sparkimpl.certificates.SparkSSLContextCreator; +import org.jivesoftware.sparkimpl.certificates.SparkSSLSocketFactory; +import org.jivesoftware.sparkimpl.certificates.SparkTrustManager; +import org.jivesoftware.sparkimpl.certificates.UnrecognizedServerCertificatePanel; +import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettings; +import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettingsManager; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; +import org.jivesoftware.sparkimpl.settings.JiveInfo; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Resourcepart; +import org.jxmpp.stringprep.XmppStringprepException; +import org.jxmpp.util.XmppStringUtils; +import org.minidns.dnsname.DnsName; + +/** + * Dialog to log in a user into the XMPP server. + * The LoginDialog is used only for login in registered users into the XMPP server. + * @author KeepToo + */ +public class LoginUIPanel extends javax.swing.JPanel implements KeyListener, FocusListener, CallbackHandler { + + private JFrame loginDialog; + private static final String BUTTON_PANEL = "buttonpanel"; // NOTRANS + private static final String PROGRESS_BAR = "progressbar"; // NOTRANS + private LocalPreferences localPref; + private ArrayList _usernames = new ArrayList<>(); + private String loginUsername; + private String loginPassword; + private String loginServer; + private static final long serialVersionUID = 2445523786538863459L; + + // Panel used to hold buttons + private final CardLayout cardLayout = new CardLayout(0, 5); + final JPanel cardPanel = new JPanel(cardLayout); + + final JPanel buttonPanel = new JPanel(new GridBagLayout()); + private AbstractXMPPConnection connection = null; + + private RolloverButton otherUsers = new RolloverButton(SparkRes.getImageIcon(SparkRes.Icon.PANE_DOWN_ARROW_IMAGE)); + + /** + * Creates new form LoginWindow + */ + public LoginUIPanel() { + initComponents(); + + localPref = SettingsManager.getLocalPreferences(); + + //SPARK-2115 SPARK-2295 Allow account creation or password changes over an insecure (e.g. unencrypted) connections. + AccountManager.sensitiveOperationOverInsecureConnectionDefault(true); + + init(); + // Check if upgraded needed. + try { + checkForOldSettings(); + } catch (Exception e) { + Log.error(e); + } + } + + // Should be called only from the Event Dispatcher Thread. + private void init() { + // Most Swing components are not thread safe, and _must_ be executed on the Event Dispatcher Thread. + if (SmackConfiguration.DEBUG && !EventQueue.isDispatchThread()) { + throw new IllegalStateException("Must be called on the Event Dispatcher Thread (but was not)"); + } + + ResourceUtils.resButton(cbSavePassword, Res.getString("checkbox.save.password")); + ResourceUtils.resButton(cbAutoLogin, Res.getString("checkbox.auto.login")); + ResourceUtils.resButton(btnSignUp, Res.getString("label.accounts")); + ResourceUtils.resButton(cbLoginInvisible, Res.getString("checkbox.login.as.invisible")); + ResourceUtils.resButton(cbAnonymous, Res.getString("checkbox.login.anonymously")); + ResourceUtils.resButton(btnReset, Res.getString("label.passwordreset")); + configureVisibility(); + + lblProgress.setVisible(false); + cbSavePassword.setOpaque(false); + cbAutoLogin.setOpaque(false); + cbLoginInvisible.setOpaque(false); + cbAnonymous.setOpaque(false); + // btnReset.setVisible(false); + + // Add KeyListener + tfUsername.addKeyListener(this); + tfPassword.addKeyListener(this); + tfDomain.addKeyListener(this); + + tfPassword.addFocusListener(this); + tfUsername.addFocusListener(this); + tfDomain.addFocusListener(this); + + otherUsers.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + getPopup().show(otherUsers, e.getX(), e.getY()); + } + }); + + // Make same size + GraphicUtils.makeSameSize(tfUsername, tfPassword); + + // Set progress bar description + lblProgress.setText(Res.getString("message.authenticating")); + lblProgress.setVerticalTextPosition(JLabel.BOTTOM); + lblProgress.setHorizontalTextPosition(JLabel.CENTER); + lblProgress.setHorizontalAlignment(JLabel.CENTER); + + // Set Resources + // ResourceUtils.resLabel(usernameLabel, tfUsername, Res.getString("label.username")); + //ResourceUtils.resLabel(passwordLabel, passwordField, Res.getString("label.password")); + ResourceUtils.resButton(btnLogin, Res.getString("button.login")); + ResourceUtils.resButton(btnAdvanced, Res.getString("button.advanced")); + + // Load previous instances + String userProp = localPref.getLastUsername(); + String serverProp = localPref.getServer(); + + File file = new File(Spark.getSparkUserHome(), "/user/"); + File[] userprofiles = file.listFiles(); + userprofiles = userprofiles != null ? userprofiles : new File[]{}; + for (File f : userprofiles) { + if (f.getName().contains("@")) { + _usernames.add(f.getName()); + } else { + Log.error("Profile contains wrong format: \"" + f.getName() + + "\" located at: " + f.getAbsolutePath()); + } + } + + if (userProp != null) { + tfUsername.setText(XmppStringUtils.unescapeLocalpart(userProp)); + } + if (serverProp != null) { + tfDomain.setText(serverProp); + } + + // Check Settings + if (localPref.isSavePassword()) { + String encryptedPassword = localPref.getPasswordForUser(getBareJid()); + if (encryptedPassword != null) { + tfPassword.setText(encryptedPassword); + } + cbSavePassword.setSelected(true); + btnLogin.setEnabled(true); + } + cbAutoLogin.setSelected(localPref.isAutoLogin()); + cbLoginInvisible.setSelected(localPref.isLoginAsInvisible()); + cbAnonymous.setSelected(localPref.isLoginAnonymously()); + tfUsername.setEnabled(!cbAnonymous.isSelected()); + tfPassword.setEnabled(!cbAnonymous.isSelected()); + // Add a clear button for username, password and domain fields + tfUsername.putClientProperty("JTextField.showClearButton",true); + tfDomain.putClientProperty("JTextField.showClearButton",true); + tfPassword.putClientProperty("JTextField.showClearButton",true); + useSSO(localPref.isSSOEnabled()); + if (cbAutoLogin.isSelected()) { + TaskEngine.getInstance().submit(this::login); + return; + } + + // Handle arguments + String username = Spark.getArgumentValue("username"); + String password = Spark.getArgumentValue("password"); + String server = Spark.getArgumentValue("server"); + + if (username != null) { + tfUsername.setText(username); + } + + if (password != null) { + tfPassword.setText(password); + } + + if (server != null) { + tfDomain.setText(server); + } + + if (username != null && server != null && password != null) { + TaskEngine.getInstance().submit(this::login); + } + + final String lockedDownURL = Default.getString(Default.HOST_NAME); + if (ModelUtil.hasLength(lockedDownURL)) { + tfDomain.setText(lockedDownURL); + } + + //reset ui + tfDomain.putClientProperty("JTextField.placeholderText", Res.getString("hint.login.domain")); + tfPassword.putClientProperty("JTextField.placeholderText", Res.getString("hint.login.password")); + tfUsername.putClientProperty("JTextField.placeholderText", Res.getString("hint.login.username")); + + //If users account > 1 then show account list button "otherUsers" + if(_usernames.size() > 1){ + tfUsername.putClientProperty("JTextField.trailingComponent",otherUsers); + } + + setComponentsAvailable(true); + } + + // Should be called only from the Event Dispatcher Thread. + private void configureVisibility() { + // Most Swing components are not thread safe, and _must_ be executed on the Event Dispatcher Thread. + if (SmackConfiguration.DEBUG && !EventQueue.isDispatchThread()) { + throw new IllegalStateException("Must be called on the Event Dispatcher Thread (but was not)"); + } + + int height = filler3.getPreferredSize().height; + if (Default.getBoolean(Default.HIDE_SAVE_PASSWORD_AND_AUTO_LOGIN) || !localPref.getPswdAutologin()) { + + pnlCheckboxes.remove(cbAutoLogin); + pnlCheckboxes.remove(cbSavePassword); + height = height + 20; + } + // Add option to hide "Login as invisible" selection on the login screen + if (Default.getBoolean(Default.HIDE_LOGIN_AS_INVISIBLE) || !localPref.getInvisibleLogin()) { + pnlCheckboxes.remove(cbLoginInvisible); + height = height + 10; + } + + // Add option to hide "Login anonymously" selection on the login screen + if (Default.getBoolean(Default.HIDE_LOGIN_ANONYMOUSLY) || !localPref.getAnonymousLogin()) { + pnlCheckboxes.remove(cbAnonymous); + height = height + 10; + } + + if (Default.getBoolean(Default.ACCOUNT_DISABLED) || !localPref.getAccountsReg()) { + pnlBtns.remove(btnSignUp); + height = height + 15; + } + + if (!Default.getBoolean(Default.PASSWORD_RESET_ENABLED)) { + pnlBtns.remove(btnReset); + } + + if (Default.getBoolean(Default.ADVANCED_DISABLED) || !localPref.getAdvancedConfig()) { + pnlBtns.remove(btnAdvanced); + height = height + 15; + } + filler3.setPreferredSize(new Dimension(220, height)); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + pnlLeft = new javax.swing.JPanel(); + filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 50), new java.awt.Dimension(250, 50), new java.awt.Dimension(32767, 50)); + lblLogo = new javax.swing.JLabel(); + jLabel1 = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + pnlCenter = new javax.swing.JPanel(); + filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(220, 20), new java.awt.Dimension(0, 32767)); + pnlInputs = new javax.swing.JPanel(); + tfUsername = new javax.swing.JTextField(); + tfDomain = new javax.swing.JTextField(); + tfPassword = new javax.swing.JPasswordField(); + pnlCheckboxes = new javax.swing.JPanel(); + cbSavePassword = new javax.swing.JCheckBox(); + cbAutoLogin = new javax.swing.JCheckBox(); + cbLoginInvisible = new javax.swing.JCheckBox(); + cbAnonymous = new javax.swing.JCheckBox(); + pnlBtns = new javax.swing.JPanel(); + btnLogin = new javax.swing.JButton(); + btnSignUp = new javax.swing.JButton(); + btnAdvanced = new javax.swing.JButton(); + btnReset = new javax.swing.JButton(); + + setLayout(new java.awt.BorderLayout()); + + pnlLeft.setPreferredSize(new java.awt.Dimension(260, 0)); + pnlLeft.add(filler1); + + lblLogo.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + lblLogo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/spark-64x64.png"))); // NOI18N + lblLogo.setPreferredSize(new java.awt.Dimension(250, 80)); + lblLogo.setRequestFocusEnabled(false); + pnlLeft.add(lblLogo); + + jLabel1.setFont(new java.awt.Font("Tahoma", 0, 18)); // NOI18N + jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + jLabel1.setText("Spark"); + jLabel1.setPreferredSize(new java.awt.Dimension(250, 22)); + pnlLeft.add(jLabel1); + + jLabel2.setText("Instant Messenger"); + pnlLeft.add(jLabel2); + + lblProgress.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + lblProgress.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/ripple.gif"))); // NOI18N + lblProgress.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + lblProgress.setPreferredSize(new java.awt.Dimension(250, 90)); + lblProgress.setRequestFocusEnabled(false); + lblProgress.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + pnlLeft.add(lblProgress); + + add(pnlLeft, java.awt.BorderLayout.WEST); + + pnlCenter.setBackground(new java.awt.Color(255, 255, 255)); + pnlCenter.setMinimumSize(new java.awt.Dimension(0, 0)); + pnlCenter.setPreferredSize(new java.awt.Dimension(250, 0)); + java.awt.FlowLayout flowLayout1 = new java.awt.FlowLayout(); + flowLayout1.setAlignOnBaseline(true); + pnlCenter.setLayout(flowLayout1); + pnlCenter.add(filler3); + + pnlInputs.setBackground(new java.awt.Color(255, 255, 255)); + pnlInputs.setPreferredSize(new java.awt.Dimension(220, 110)); + + tfUsername.setPreferredSize(new java.awt.Dimension(200, 30)); + tfUsername.addMouseListener(new MouseAdapter() { + public void mouseEntered(MouseEvent evt) { + tfUsernameMouseEntered(evt); + } + public void mouseExited(MouseEvent evt) { + tfUsernameMouseExited(evt); + } + public void mousePressed(MouseEvent evt) { + tfUsernameMousePressed(evt); + } + }); + pnlInputs.add(tfUsername); + + tfDomain.setPreferredSize(new java.awt.Dimension(200, 30)); + pnlInputs.add(tfDomain); + + tfPassword.setPreferredSize(new java.awt.Dimension(200, 30)); + pnlInputs.add(tfPassword); + + pnlCenter.add(pnlInputs); + + pnlCheckboxes.setBackground(new java.awt.Color(255, 255, 255)); + pnlCheckboxes.setLayout(new javax.swing.BoxLayout(pnlCheckboxes, javax.swing.BoxLayout.Y_AXIS)); + + cbSavePassword.setBackground(new java.awt.Color(255, 255, 255)); + cbSavePassword.setText("Save Password"); + cbSavePassword.setPreferredSize(new java.awt.Dimension(200, 20)); + cbSavePassword.addActionListener(this::cbSavePasswordActionPerformed); + pnlCheckboxes.add(cbSavePassword); + + cbAutoLogin.setBackground(new java.awt.Color(255, 255, 255)); + cbAutoLogin.setText("Auto login"); + cbAutoLogin.setPreferredSize(new java.awt.Dimension(200, 20)); + cbAutoLogin.addActionListener(this::cbAutoLoginActionPerformed); + pnlCheckboxes.add(cbAutoLogin); + + cbLoginInvisible.setBackground(new java.awt.Color(255, 255, 255)); + cbLoginInvisible.setText("Login as invisible"); + cbLoginInvisible.setPreferredSize(new java.awt.Dimension(200, 20)); + pnlCheckboxes.add(cbLoginInvisible); + + cbAnonymous.setBackground(new java.awt.Color(255, 255, 255)); + cbAnonymous.setText("Login anonymously"); + cbAnonymous.setPreferredSize(new java.awt.Dimension(200, 20)); + cbAnonymous.addActionListener(this::cbAnonymousActionPerformed); + pnlCheckboxes.add(cbAnonymous); + + pnlCenter.add(pnlCheckboxes); + + pnlBtns.setBackground(new java.awt.Color(255, 255, 255)); + pnlBtns.setPreferredSize(new java.awt.Dimension(220, 120)); + + btnLogin.setBackground(new java.awt.Color(241, 100, 34)); + btnLogin.setForeground(new java.awt.Color(255, 255, 255)); + btnLogin.setText("Login"); + btnLogin.setEnabled(false); + btnLogin.setPreferredSize(new java.awt.Dimension(210, 30)); + btnLogin.addActionListener(this::btnLoginActionPerformed); + pnlBtns.add(btnLogin); + + btnSignUp.setBackground(new java.awt.Color(255, 255, 255)); + btnSignUp.setText("Account"); + btnSignUp.setBorderPainted(false); + btnSignUp.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING); + btnSignUp.setOpaque(false); + btnSignUp.setPreferredSize(new java.awt.Dimension(95, 28)); + btnSignUp.addActionListener(this::btnCreateAccountActionPerformed); + pnlBtns.add(btnSignUp); + + btnAdvanced.setBackground(new java.awt.Color(255, 255, 255)); + btnAdvanced.setText("Advanced"); + btnAdvanced.setBorderPainted(false); + btnAdvanced.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING); + btnAdvanced.setOpaque(false); + btnAdvanced.setPreferredSize(new java.awt.Dimension(110, 28)); + btnAdvanced.addActionListener(this::btnAdvancedActionPerformed); + pnlBtns.add(btnAdvanced); + + btnReset.setBackground(new java.awt.Color(255, 255, 255)); + btnReset.setText("Reset Password"); + btnReset.setBorderPainted(false); + btnReset.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING); + btnReset.setOpaque(false); + btnReset.setPreferredSize(new java.awt.Dimension(210, 28)); + btnReset.addActionListener(this::btnResetActionPerformed); + pnlBtns.add(btnReset); + + pnlCenter.add(pnlBtns); + + add(pnlCenter, java.awt.BorderLayout.CENTER); + }// //GEN-END:initComponents + + private void btnLoginActionPerformed(ActionEvent evt) {//GEN-FIRST:event_btnLoginActionPerformed + TaskEngine.getInstance().submit(this::login); + }//GEN-LAST:event_btnLoginActionPerformed + + private void btnCreateAccountActionPerformed(ActionEvent evt) {//GEN-FIRST:event_btnCreateAccountActionPerformed + // pre-fill the user domain from the login page i.e. if it already tried to login + DomainBareJid xmppDomain = JidCreate.domainBareFromOrNull(tfDomain.getText().trim()); + startAccountRegistrationWizard(xmppDomain); + }//GEN-LAST:event_btnCreateAccountActionPerformed + + public void startAccountRegistrationWizard(DomainBareJid xmppDomain) { + AccountCreationWizard createAccountPanel = new AccountCreationWizard(); + createAccountPanel.setServer(xmppDomain); + createAccountPanel.invoke(loginDialog); + if (createAccountPanel.isRegistered()) { + tfUsername.setText(createAccountPanel.getUsernameWithoutEscape()); + tfPassword.setText(createAccountPanel.getPassword()); + tfDomain.setText(createAccountPanel.getServer()); + btnLogin.setEnabled(true); + btnLoginActionPerformed(null); + } + }//GEN-LAST:event_btnCreateAccountActionPerformed + + private void btnAdvancedActionPerformed(ActionEvent evt) {//GEN-FIRST:event_btnAdvancedActionPerformed + final LoginSettingDialog loginSettingsDialog = new LoginSettingDialog(); + loginSettingsDialog.invoke(loginDialog); + useSSO(localPref.isSSOEnabled()); + }//GEN-LAST:event_btnAdvancedActionPerformed + + + private void cbSavePasswordActionPerformed(ActionEvent evt) {//GEN-FIRST:event_cbSavePasswordActionPerformed + cbAutoLogin.setEnabled(cbSavePassword.isSelected()); + if (!cbSavePassword.isSelected()) { + cbAutoLogin.setSelected(false); + } + }//GEN-LAST:event_cbSavePasswordActionPerformed + + private void cbAutoLoginActionPerformed(ActionEvent evt) {//GEN-FIRST:event_cbAutoLoginActionPerformed + if ((cbAutoLogin.isSelected() && (!localPref.isSSOEnabled()))) { + cbSavePassword.setSelected(true); + } + }//GEN-LAST:event_cbAutoLoginActionPerformed + + private void cbAnonymousActionPerformed(ActionEvent evt) {//GEN-FIRST:event_cbAnonymousActionPerformed + tfUsername.setEnabled(!cbAnonymous.isSelected()); + tfPassword.setEnabled(!cbAnonymous.isSelected()); + validateDialog(); + }//GEN-LAST:event_cbAnonymousActionPerformed + + private void tfUsernameMousePressed(MouseEvent evt) {//GEN-FIRST:event_tfUsernameMousePressed + if (SwingUtilities.isRightMouseButton(evt)) { + getPopup().show(tfUsername, evt.getX(), evt.getY()); + } + }//GEN-LAST:event_tfUsernameMousePressed + + private void tfUsernameMouseEntered(MouseEvent evt) {//GEN-FIRST:event_tfUsernameMouseEntered + // getPopup().show(tfUsername, evt.getX(), evt.getY()); + }//GEN-LAST:event_tfUsernameMouseEntered + + private void tfUsernameMouseExited(MouseEvent evt) {//GEN-FIRST:event_tfUsernameMouseExited + // getPopup().setVisible(false); + }//GEN-LAST:event_tfUsernameMouseExited + + private void btnResetActionPerformed(ActionEvent evt) {//GEN-FIRST:event_btnResetActionPerformed + final String url = Default.getString(Default.PASSWORD_RESET_URL); + try { + BrowserLauncher.openURL(url); + } catch (Exception e) { + Log.error("Unable to load password reset.", e); + } + }//GEN-LAST:event_btnResetActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnAdvanced; + private javax.swing.JButton btnSignUp; + private javax.swing.JButton btnLogin; + private javax.swing.JButton btnReset; + private javax.swing.JCheckBox cbAnonymous; + private javax.swing.JCheckBox cbAutoLogin; + private javax.swing.JCheckBox cbLoginInvisible; + private javax.swing.JCheckBox cbSavePassword; + private javax.swing.Box.Filler filler1; + private javax.swing.Box.Filler filler3; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel lblLogo; + public final javax.swing.JLabel lblProgress = new javax.swing.JLabel(); + private javax.swing.JPanel pnlBtns; + private javax.swing.JPanel pnlCenter; + private javax.swing.JPanel pnlCheckboxes; + private javax.swing.JPanel pnlInputs; + private javax.swing.JPanel pnlLeft; + private javax.swing.JTextField tfDomain; + private javax.swing.JPasswordField tfPassword; + private javax.swing.JTextField tfUsername; + // End of variables declaration//GEN-END:variables + + public JTextField getUsernameField() { + return tfUsername; + } + + public JPasswordField getPasswordField() { + return tfPassword; + } + + public JButton getBtnLogin() { + return btnLogin; + } + + public JCheckBox getCbAutoLogin() { + return cbAutoLogin; + } + + /** + * Invokes the LoginDialog to be visible. + */ + public void invoke() { + // Before creating any connections. Update proxy if needed. + try { + updateProxyConfig(); + } catch (Exception e) { + Log.error(e); + } + loginDialog = new JFrame(JiveInfo.getName()); + + // Construct Dialog + EventQueue.invokeLater(() -> { + loginDialog.setIconImage(SparkManager.getApplicationImage().getImage()); + loginDialog.setContentPane(this); + loginDialog.setResizable(false); + loginDialog.pack(); + loginDialog.setSize(550, 390); + // Center dialog on screen + GraphicUtils.centerWindowOnScreen(loginDialog); + + // Show dialog + loginDialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + quitLogin(); + } + }); + if (ModelUtil.hasLength(getUsernameField().getText())) { + getPasswordField().requestFocus(); + } + + if (!localPref.isStartedHidden() || !localPref.isAutoLogin()) { + // Make dialog top most. + loginDialog.setVisible(true); + } + }); + } + + protected void afterLogin() { + Log.debug("Performing post-login tasks"); + + // The Event Dispatcher Thread should only be used for fast tasks. The tasks in this method potentially are not. + if (SmackConfiguration.DEBUG && EventQueue.isDispatchThread()) { + throw new IllegalStateException("Must NOT be called on the Event Dispatcher Thread (but was)"); + } + + // Make certain Enterprise features persist across future logins + persistEnterprise(); + + // Load plugins before Workspace initialization to avoid any UI delays during plugin rendering, but after + // Enterprise initialization, which can pull in additional plugin configuration (eg: blacklist). + PluginManager.getInstance().loadPlugins(); + + // Initialize and write default values from "Advanced Connection Preferences" to disk + initAdvancedDefaults(); + + Log.debug("Finished post-login tasks"); + } + + protected XMPPTCPConnectionConfiguration retrieveConnectionConfiguration() { + int port = localPref.getXmppPort(); + + int checkForPort = loginServer.indexOf(":"); + if (checkForPort != -1) { + if (checkForPort != loginServer.length() - 2) { // : at end of string, so no port + String portString = loginServer.substring(checkForPort + 1); + // Set new port. + port = Integer.parseInt(portString); + } + // strip the port from loginServer hostname + loginServer = loginServer.substring(0, checkForPort); + } + + ConnectionConfiguration.SecurityMode securityMode = localPref.getSecurityMode(); + boolean useDirectTls = localPref.isDirectTls(); + boolean hostPortConfigured = localPref.isHostAndPortConfigured(); + + ProxyInfo proxyInfo = null; + if (localPref.isProxyEnabled()) { + ProxyInfo.ProxyType pType = localPref.getProtocol().equals("SOCKS") + ? ProxyInfo.ProxyType.SOCKS5 : ProxyInfo.ProxyType.HTTP; + String pHost = ModelUtil.hasLength(localPref.getHost()) + ? localPref.getHost() : null; + int pPort = ModelUtil.hasLength(localPref.getPort()) + ? Integer.parseInt(localPref.getPort()) : 0; + String pUser = ModelUtil.hasLength(localPref.getProxyUsername()) + ? localPref.getProxyUsername() : null; + String pPass = ModelUtil.hasLength(localPref.getProxyPassword()) + ? localPref.getProxyPassword() : null; + + if (pHost != null && pPort != 0) { + + if (pUser == null || pPass == null) { + + proxyInfo = new ProxyInfo(pType, pHost, pPort, null, null); + } else { + + proxyInfo = new ProxyInfo(pType, pHost, pPort, pUser, pPass); + + } + } else { + Log.error("No proxy info found but proxy type is enabled!"); + } + } + + DomainBareJid xmppDomain; + try { + xmppDomain = JidCreate.domainBareFrom(loginServer); + } catch (XmppStringprepException e) { + throw new IllegalStateException(e); + } + + final XMPPTCPConnectionConfiguration.Builder builder = XMPPTCPConnectionConfiguration.builder() + .setUsernameAndPassword(loginUsername, loginPassword) + .setXmppDomain(xmppDomain) + .setPort(port) + .setSendPresence(false) + .setCompressionEnabled(localPref.isCompressionEnabled()) + .setSecurityMode(securityMode); + + if (localPref.isDebuggerEnabled()) { + builder.enableDefaultDebugger(); + } + + if (hostPortConfigured) { + builder.setHost(localPref.getXmppHost()); + } + + if (localPref.isProxyEnabled()) { + builder.setProxyInfo(proxyInfo); + } + configureConnectionTls(builder, securityMode, useDirectTls, hostPortConfigured, loginServer); + + // SPARK-1747: Don't use the GSS-API SASL mechanism when SSO is disabled. + SASLAuthentication.unregisterSASLMechanism(SASLGSSAPIMechanism.class.getName()); + SASLAuthentication.unregisterSASLMechanism(SASLGSSAPIv3CompatMechanism.class.getName()); + + // Add the mechanism only when SSO is enabled (which allows us to register the correct one). + if (localPref.isSSOEnabled()) { + // SPARK-1740: Register a mechanism that's compatible with Smack 3, when requested. + if (localPref.isSaslGssapiSmack3Compatible()) { + // SPARK-1747: Don't use the GSSAPI mechanism when SSO is disabled. + SASLAuthentication.registerSASLMechanism(new SASLGSSAPIv3CompatMechanism()); + } else { + SASLAuthentication.registerSASLMechanism(new SASLGSSAPIMechanism()); + } + } + + if (localPref.isLoginAnonymously() && !localPref.isSSOEnabled()) { + //later login() is called without arguments + builder.performSaslAnonymousAuthentication(); + } + + // TODO These were used in Smack 3. Find Smack 4 alternative. +// config.setRosterLoadedAtLogin(true); +// if(ModelUtil.hasLength(localPref.getTrustStorePath())) { +// config.setTruststorePath(localPref.getTrustStorePath()); +// config.setTruststorePassword(localPref.getTrustStorePassword()); +// } + return builder.build(); + } + + private void configureConnectionTls(XMPPTCPConnectionConfiguration.Builder builder, ConnectionConfiguration.SecurityMode securityMode, boolean useDirectTls, boolean hostPortConfigured, String serverName) { + if (securityMode != ConnectionConfiguration.SecurityMode.disabled) { + if (localPref.isDisableHostnameVerification()) { + TLSUtils.disableHostnameVerificationForTlsCertificates(builder); + } + if (!useDirectTls) { + // This use STARTTLS which starts initially plain connection to upgrade it to TLS. + // It will use the same port as plain connections which is 5222. + SparkSSLContextCreator.Options options = localPref.isAllowClientSideAuthentication() ? BOTH : ONLY_SERVER_SIDE; + try { + SSLContext context = SparkSSLContextCreator.setUpContext(options); + builder.setSslContextFactory(() -> context); + builder.setSecurityMode(securityMode); + builder.setCustomX509TrustManager(new SparkTrustManager()); + } catch (NoSuchAlgorithmException | KeyManagementException | UnrecoverableKeyException | KeyStoreException | NoSuchProviderException e) { + Log.warning("Could not establish secured connection", e); + } + } else { // useDirectTls + if (!hostPortConfigured) { + // SMACK 4.1.9 does not support XEP-0368, and does not apply a port change, if the host is not changed too. + // Here, we force the host to be set (by doing a DNS lookup), and force the port to 5223 (which is the + // default 'old-style' SSL port). + DnsName serverNameDnsName = DnsName.from(serverName); + List resolvedAddresses = DNSUtil.getDNSResolver().lookupHostAddress(serverNameDnsName, null, DnssecMode.disabled); + if (resolvedAddresses.isEmpty()) { + throw new RuntimeException("Could not resolve " + serverNameDnsName); + } + builder.setHost(resolvedAddresses.get(0).getHostName()); + builder.setPort(5223); + } + SparkSSLContextCreator.Options options = localPref.isAllowClientSideAuthentication() ? BOTH : ONLY_SERVER_SIDE; + builder.setSocketFactory(new SparkSSLSocketFactory(options)); + // SMACK 4.1.9 does not recognize an 'old-style' SSL socket as being secure, which will cause a failure when + // the 'required' Security Mode is defined. Here, we work around this by replacing that security mode with an + // 'if-possible' setting. + builder.setSecurityMode(ConnectionConfiguration.SecurityMode.ifpossible); + } + SASLAuthentication.registerSASLMechanism(new SASLExternalMechanism()); + } + } + + /** + * Returns the username the user defined. + * + * Should be called only from the Event Dispatcher Thread. + * + * @return the username. + */ + private String getUsername() { + // Most Swing components are not thread safe, and _must_ be executed on the Event Dispatcher Thread. + if (SmackConfiguration.DEBUG && !EventQueue.isDispatchThread()) { + throw new IllegalStateException("Must be called on the Event Dispatcher Thread (but was not)"); + } + return XmppStringUtils.escapeLocalpart(tfUsername.getText().trim()); + } + + /** + * Returns the resulting bareJID from username and server + * + * Should be called only from the Event Dispatcher Thread. + * + * @return the bare JID that's being logged in with. + */ + private String getBareJid() { + // Most Swing components are not thread safe, and _must_ be executed on the Event Dispatcher Thread. + if (SmackConfiguration.DEBUG && !EventQueue.isDispatchThread()) { + throw new IllegalStateException("Must be called on the Event Dispatcher Thread (but was not)"); + } + return tfUsername.getText() + "@" + tfDomain.getText(); + } + + /** + * Returns the password specified by the user. + * + * Should be called only from the Event Dispatcher Thread. + * + * @return the password. + */ + private String getPassword() { + // Most Swing components are not thread safe, and _must_ be executed on the Event Dispatcher Thread. + if (SmackConfiguration.DEBUG && !EventQueue.isDispatchThread()) { + throw new IllegalStateException("Must be called on the Event Dispatcher Thread (but was not)"); + } + return new String(tfPassword.getPassword()); + } + + /** + * Returns the server name specified by the user. + * + * Should be called only from the Event Dispatcher Thread. + * + * @return the server name. + */ + private String getServerName() { + // Most Swing components are not thread safe, and _must_ be executed on the Event Dispatcher Thread. + if (SmackConfiguration.DEBUG && !EventQueue.isDispatchThread()) { + throw new IllegalStateException("Must be called on the Event Dispatcher Thread (but was not)"); + } + return tfDomain.getText().trim(); + } + + /** + * Return whether user wants to login as invisible or not. + * + * Should be called only from the Event Dispatcher Thread. + * + * @return the true if user wants to login as invisible. + */ + boolean isLoginAsInvisible() { + // Most Swing components are not thread safe, and _must_ be executed on the Event Dispatcher Thread. + if (SmackConfiguration.DEBUG && !EventQueue.isDispatchThread()) { + throw new IllegalStateException("Must be called on the Event Dispatcher Thread (but was not)"); + } + return cbLoginInvisible.isSelected(); + } + + private JPopupMenu getPopup() { + JPopupMenu popup = new JPopupMenu(); + for (final String key : _usernames) { + + JMenuItem menu = new JMenuItem(key); + + BareJid jid = JidCreate.bareFromOrNull(key); + if (jid == null) { + continue; + } + final String username = jid.getLocalpartOrNull().toString(); + final String host = jid.getDomain().toString(); + menu.addActionListener(e -> { + tfUsername.setText(username); + tfDomain.setText(host); + + try { + String passwordForUser = localPref.getPasswordForUser(getBareJid()); + tfPassword.setText(passwordForUser); + } catch (Exception ignored) { + } + validateDialog(); + }); + + popup.add(menu); + } + return popup; + } + + /** + * KeyListener implementation. + * + * @param e the KeyEvent to process. + */ + @Override + public void keyTyped(KeyEvent e) { + validate(e); + } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_RIGHT + && ((JTextField) e.getSource()).getCaretPosition() == ((JTextField) e.getSource()).getText().length()) { + getPopup().show(otherUsers, 0, 0); + } + } + + @Override + public void keyReleased(KeyEvent e) { + validateDialog(); + } + + /** + * Checks the users input and enables/disables the login button depending on + * state. + * + * Should be called only from the Event Dispatcher Thread. + */ + private void validateDialog() { + // Most Swing components are not thread safe, and _must_ be executed on the Event Dispatcher Thread. + if (SmackConfiguration.DEBUG && !EventQueue.isDispatchThread()) { + throw new IllegalStateException("Must be called on the Event Dispatcher Thread (but was not)"); + } + btnLogin.setEnabled(cbAnonymous.isSelected() + || ModelUtil.hasLength(getUsername()) + && (ModelUtil.hasLength(getPassword()) || localPref.isSSOEnabled()) + && ModelUtil.hasLength(getServerName())); + } + + /** + * Validates key input. + * + * @param e the keyEvent. + */ + private void validate(KeyEvent e) { + if (btnLogin.isEnabled() && e.getKeyChar() == KeyEvent.VK_ENTER) { + TaskEngine.getInstance().submit(this::login); + } + } + + @Override + public void focusGained(FocusEvent e) { + Object o = e.getSource(); + if (o instanceof JTextComponent) { + ((JTextComponent) o).selectAll(); + } + } + + @Override + public void focusLost(FocusEvent e) { + } + + /** + * Enables/Disables the editable components in the login screen. + * + * Should be called only from the Event Dispatcher Thread. + * + * @param available true to enable components, otherwise false to disable. + */ + private void setComponentsAvailable(boolean available) + { + // Most Swing components are not thread safe, and _must_ be executed on the Event Dispatcher Thread. + if (SmackConfiguration.DEBUG && !EventQueue.isDispatchThread()) { + throw new IllegalStateException("Must be called on the Event Dispatcher Thread (but was not)"); + } + + cbSavePassword.setEnabled(available); + cbAutoLogin.setEnabled(available); + cbLoginInvisible.setEnabled(available); + cbAnonymous.setEnabled(available); + btnLogin.setEnabled(available); + btnAdvanced.setEnabled(available); + btnSignUp.setEnabled(available); + + // Need to set both editable and enabled for best behavior. + tfUsername.setEditable(available); + tfUsername.setEnabled(available && !cbAnonymous.isSelected()); + + tfPassword.setEditable(available); + tfPassword.setEnabled(available && !cbAnonymous.isSelected()); + + if (Default.getBoolean(Default.HOST_NAME_CHANGE_DISABLED) || !localPref.getHostNameChange()) { + tfDomain.setEditable(false); + tfDomain.setEnabled(false); + } else { + tfDomain.setEditable(available); + tfDomain.setEnabled(available); + } + + if (available) { + // Reapply focus to password field + tfPassword.requestFocus(); + } + } + + /** + * Displays the progress bar. + * + * Should be called only from the Event Dispatcher Thread. + * + * @param visible true to display progress bar, false to hide it. + */ + private void setProgressBarVisible(boolean visible) { + // Most Swing components are not thread safe, and _must_ be executed on the Event Dispatcher Thread. + if (SmackConfiguration.DEBUG && !EventQueue.isDispatchThread()) { + throw new IllegalStateException("Must be called on the Event Dispatcher Thread (but was not)"); + } + + lblProgress.setVisible(visible); + } + + @Override + public Dimension getPreferredSize() { + final Dimension dim = super.getPreferredSize(); + dim.height = 230; + return dim; + } + + public void useSSO(boolean use) { + if (use) { + //usernameLabel.setVisible(true); + tfUsername.setVisible(true); + + //passwordLabel.setVisible(false); + tfPassword.setVisible(false); + + cbSavePassword.setVisible(false); + cbSavePassword.setSelected(false); + + tfDomain.setVisible(true); + + cbAutoLogin.setVisible(true); + //serverLabel.setVisible(true); + cbLoginInvisible.setVisible(true); + cbAnonymous.setVisible(false); + + if (localPref.getDebug()) { + System.setProperty("java.security.krb5.debug", "true"); + System.setProperty("sun.security.krb5.debug", "true"); + } else { + System.setProperty("java.security.krb5.debug", "false"); + System.setProperty("sun.security.krb5.debug", "false"); + } + + String ssoMethod = localPref.getSSOMethod(); + if (!ModelUtil.hasLength(ssoMethod)) { + ssoMethod = "file"; + } + + System.setProperty("javax.security.auth.useSubjectCredsOnly", "false"); + GSSAPIConfiguration config = new GSSAPIConfiguration(ssoMethod.equals("file")); + Configuration.setConfiguration(config); + + LoginContext lc; + String princName = localPref.getLastUsername(); + String princRealm = null; + try { + lc = new LoginContext("com.sun.security.jgss.krb5.initiate"); + lc.login(); + Subject mySubject = lc.getSubject(); + + for (Principal p : mySubject.getPrincipals()) { + //TODO: check if principal is a kerberos principal first... + String name = p.getName(); + int indexOne = name.indexOf("@"); + if (indexOne != -1) { + princName = name.substring(0, indexOne); + princRealm = name.substring(indexOne + 1); + } + btnLogin.setEnabled(true); + } + } catch (LoginException le) { + Log.debug(le.getMessage()); + //useSSO(false); + } + + String ssoKdc; + if (ssoMethod.equals("dns")) { + if (princRealm != null) { //princRealm is null if we got a LoginException above. + ssoKdc = getDnsKdc(princRealm); + System.setProperty("java.security.krb5.realm", princRealm); + System.setProperty("java.security.krb5.kdc", ssoKdc); + } + } else if (ssoMethod.equals("manual")) { + princRealm = localPref.getSSORealm(); + ssoKdc = localPref.getSSOKDC(); + System.setProperty("java.security.krb5.realm", princRealm); + System.setProperty("java.security.krb5.kdc", ssoKdc); + } else { + //Assume "file" method. We don't have to do anything special, + //java takes care of it for us. Unset the props if they are set + System.clearProperty("java.security.krb5.realm"); + System.clearProperty("java.security.krb5.kdc"); + } + + String userName = localPref.getLastUsername(); + if (ModelUtil.hasLength(userName)) { + tfUsername.setText(userName); + } else { + tfUsername.setText(princName); + } + } else { + cbAutoLogin.setVisible(true); + tfUsername.setVisible(true); + tfPassword.setVisible(true); + cbSavePassword.setVisible(true); + // usernameLabel.setVisible(true); + // passwordLabel.setVisible(true); + // serverLabel.setVisible(true); + tfDomain.setVisible(true); + cbLoginInvisible.setVisible(true); + cbAnonymous.setVisible(true); + + Configuration.setConfiguration(null); + + validateDialog(); + } + } + + /** + * Login to the specified server using username, password, and workgroup. + * Handles error representation as well as logging. + * + * Should _not_ be called from the Event Dispatcher Thread. + */ + private void login() { + Log.debug("Start login"); + + if (localPref.isDebuggerEnabled()) { + SmackConfiguration.DEBUG = true; + } + + // The Event Dispatcher Thread should only be used for fast tasks. Network IO is not one of those. + if (SmackConfiguration.DEBUG && EventQueue.isDispatchThread()) { + throw new IllegalStateException("Must NOT be called on the Event Dispatcher Thread (but was)"); + } + + localPref = SettingsManager.getLocalPreferences(); + SmackConfiguration.setDefaultReplyTimeout(localPref.getTimeOut() * 1000); + + AtomicBoolean savePasswordAfterSuccessfulLogin = new AtomicBoolean(false); + AtomicBoolean autoLogin = new AtomicBoolean(false); + try { + EventQueue.invokeAndWait(() -> { + setComponentsAvailable(false); + setProgressBarVisible(true); + + setLoginUsername(getUsername()); + setLoginPassword(getPassword()); + setLoginServer(getServerName()); + + localPref.setLoginAsInvisible(cbLoginInvisible.isSelected()); + localPref.setLoginAnonymously(cbAnonymous.isSelected()); + savePasswordAfterSuccessfulLogin.set(cbSavePassword.isSelected()); + autoLogin.set(cbAutoLogin.isSelected()); + }); + } catch (InterruptedException | InvocationTargetException e) { + throw new IllegalStateException("Exception while modifying UI components during login.", e); + } + + try { + // TODO: SPARK-2140 - add support to Spark for stream management. Challenges expected around reconnection logic! + XMPPTCPConnection.setUseStreamManagementDefault(false); + + connection = new XMPPTCPConnection(retrieveConnectionConfiguration()); + connection.setParsingExceptionCallback(new ExceptionLoggingCallback()); + + connection.connect(); + + if (localPref.isLoginAnonymously() && !localPref.isSSOEnabled()) { + // ConnectionConfiguration.performSaslAnonymousAuthentication() used earlier in connection configuration builder, + // so now we can just login() + connection.login(); + } else { + String resource = localPref.getResource(); + if (Default.getBoolean(Default.USE_HOSTNAME_AS_RESOURCE) || localPref.isUseHostnameAsResource()) { + try { + resource = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + Log.warning("Cannot set hostname as resource - unable to retrieve hostname.", e); + } + } else if (Default.getBoolean(Default.USE_VERSION_AS_RESOURCE) || localPref.isUseVersionAsResource()) { + resource = JiveInfo.getName() + " " + JiveInfo.getVersion(); + } + + localPref.setResource(resource); + Resourcepart resourcepart = Resourcepart.from(modifyWildcards(resource).trim()); + connection.login(getLoginUsername(), getLoginPassword(), resourcepart); + } + Log.debug("Logged in!"); + + final SessionManager sessionManager = SparkManager.getSessionManager(); + sessionManager.setServerAddress(connection.getXMPPServiceDomain()); + sessionManager.initializeSession(connection, getLoginUsername(), getLoginPassword()); + sessionManager.setJID(connection.getUser()); + + final ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(connection); + reconnectionManager.setFixedDelay(localPref.getReconnectDelay()); + reconnectionManager.setReconnectionPolicy(ReconnectionManager.ReconnectionPolicy.FIXED_DELAY); + reconnectionManager.enableAutomaticReconnection(); + + final CarbonManager carbonManager = CarbonManager.getInstanceFor(connection); + if (carbonManager.isSupportedByServer()) { + carbonManager.enableCarbons(); + } + } catch (Exception xee) { + Log.error("Exception in Login:", xee); + + final String errorMessage; + if (localPref.isSSOEnabled()) { + errorMessage = Res.getString("title.advanced.connection.sso.unable"); + } else if (xee.getMessage() != null && xee.getMessage().contains("not-authorized")) { + errorMessage = Res.getString("message.invalid.username.password"); + } else if (xee.getMessage() != null && (xee.getMessage().contains("java.net.UnknownHostException:") || xee.getMessage().contains("Network is unreachable") || xee.getMessage().contains("java.net.ConnectException: Connection refused:"))) { + errorMessage = Res.getString("message.server.unavailable"); + } else if (xee.getMessage() != null && xee.getMessage().contains("Hostname verification of certificate failed")) { + errorMessage = Res.getString("message.cert.hostname.verification.failed"); + } else if (xee.getMessage() != null && xee.getMessage().contains("unable to find valid certification path to requested target")) { + errorMessage = Res.getString("message.cert.verification.failed"); + } else if (xee.getMessage() != null && xee.getMessage().contains("StanzaError: conflict")) { + errorMessage = Res.getString("label.conflict.error"); + } else if (xee instanceof SmackException) { + errorMessage = xee.getLocalizedMessage(); + } else { + errorMessage = Res.getString("message.unrecoverable.error"); + } + + EventQueue.invokeLater(() -> { + setEnabled(true); + setComponentsAvailable(true); + setProgressBarVisible(false); + + // Show error dialog + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + if (!loginDialog.isVisible()) { + loginDialog.setVisible(true); + } + if (loginDialog.isVisible()) { + if (xee.getMessage() != null && xee.getMessage().contains("Self Signed certificate")) { + // Handle specific case: if server certificate is self-signed, but self-signed certs are not allowed, show a popup allowing the user to override. + // Prompt user if they'd like to add the failed chain to the trust store. + final Object[] options = { + Res.getString("yes"), + Res.getString("no") + }; + + final int userChoice = JOptionPane.showOptionDialog(this, + Res.getString("dialog.certificate.ask.allow.self-signed"), + Res.getString("title.certificate"), + JOptionPane.YES_NO_OPTION, + JOptionPane.WARNING_MESSAGE, + null, + options, + options[1]); + + if (userChoice == JOptionPane.YES_OPTION) { + // Toggle the preference. + localPref.setAcceptSelfSigned(true); + // Attempt to login again. + TaskEngine.getInstance().submit(this::login); + } + } else { + final X509Certificate[] lastFailedChain = SparkTrustManager.getLastFailedChain(); + final SparkTrustManager sparkTrustManager = (SparkTrustManager) SparkTrustManager.getTrustManagerList()[0]; + // Handle specific case: if path validation failed because of an unrecognized CA, show popup allowing the user to add the certificate. + if (lastFailedChain != null && ((xee.getMessage() != null && xee.getMessage().contains("Certificate not in the TrustStore")) || !sparkTrustManager.containsTrustAnchorFor(lastFailedChain))) { + // Prompt user if they'd like to add the failed chain to the trust store. + final CertificateModel certModel = new CertificateModel(lastFailedChain[0]); + final Object[] options = { + Res.getString("yes"), + Res.getString("no") + }; + + final int userChoice = JOptionPane.showOptionDialog(this, + new UnrecognizedServerCertificatePanel(certModel), + Res.getString("title.certificate"), + JOptionPane.YES_NO_OPTION, + JOptionPane.WARNING_MESSAGE, + null, + options, + options[1]); + + if (userChoice == JOptionPane.YES_OPTION) { + // Add the certificate chain to the truststore. + sparkTrustManager.addChain(lastFailedChain); + + // Attempt to login again. + TaskEngine.getInstance().submit(this::login); + } + } else { + // For anything else, show a generic error dialog. + MessageDialog.showErrorDialog(loginDialog, errorMessage, xee); + } + } + } + }); + } + + // Since the connection and workgroup are valid. Add a ConnectionListener + connection.addConnectionListener(SparkManager.getSessionManager()); + + // Initialize chat state notification mechanism in smack + ChatStateManager.getInstance(SparkManager.getConnection()); + + // Persist information + localPref.setLastUsername(getLoginUsername()); + + // Check to see if the password should be saved or cleared from file. + if (savePasswordAfterSuccessfulLogin.get()) { + try { + localPref.setPasswordForUser(getBareJid(), getLoginPassword()); + } catch (Exception e) { + Log.error("Error storing encrypted password.", e); + } + } else { + try { + localPref.clearPasswordForAllUsers(); + } catch (Exception e) { + Log.debug("Unable to clear saved password..." + e); + } + } + + localPref.setSavePassword(savePasswordAfterSuccessfulLogin.get()); + localPref.setAutoLogin(autoLogin.get()); + localPref.setServer(getLoginServer()); + afterLogin(); + + EventQueue.invokeLater(()-> { + lblProgress.setText(Res.getString("message.connecting.please.wait")); + + // Startup Spark + startSpark(); + + // dispose login dialog + loginDialog.dispose(); + + // Show ChangeLog if we need to. + // new ChangeLogDialog().showDialog(); + }); + } + + @Override + public void handle(Callback[] callbacks) throws IOException { + for (Callback callback : callbacks) { + if (callback instanceof NameCallback) { + NameCallback ncb = (NameCallback) callback; + ncb.setName(getLoginUsername()); + } else if (callback instanceof PasswordCallback) { + PasswordCallback pcb = (PasswordCallback) callback; + pcb.setPassword(getPassword().toCharArray()); + } else { + Log.error("Unknown callback requested: " + callback.getClass().getSimpleName()); + } + } + } + + /** + * If the user quits, just shut down the application. + */ + private void quitLogin() { + System.exit(1); + } + + /** + * Initializes Spark's main window. + * + * Should only be called from the Event Dispatcher Thread + */ + private void startSpark() { + Log.debug("Starting Spark's main window."); + // Most Swing components are not thread safe, and _must_ be executed on the Event Dispatcher Thread. + if (SmackConfiguration.DEBUG && !EventQueue.isDispatchThread()) { + throw new IllegalStateException("Must be called on the Event Dispatcher Thread (but was not)"); + } + // Invoke the MainWindow. + try { + final MainWindow mainWindow = MainWindow.getInstance(); + + /* + if (tray != null) { + // Remove trayIcon + tray.removeTrayIcon(trayIcon); + } + */ + // Creates the Spark Workspace and add to MainWindow + Workspace workspace = Workspace.getInstance(); + + LayoutSettings settings = LayoutSettingsManager.getLayoutSettings(); + + LocalPreferences pref = SettingsManager.getLocalPreferences(); + if (pref.isDockingEnabled()) { + JSplitPane splitPane = mainWindow.getSplitPane(); + workspace.getCardPanel().setMinimumSize(null); + splitPane.setLeftComponent(workspace.getCardPanel()); + SparkManager.getChatManager().getChatContainer().setMinimumSize(null); + splitPane.setRightComponent(SparkManager.getChatManager().getChatContainer()); + int dividerLoc = settings.getSplitPaneDividerLocation(); + if (dividerLoc != -1) { + mainWindow.getSplitPane().setDividerLocation(dividerLoc); + } else { + mainWindow.getSplitPane().setDividerLocation(240); + } + + mainWindow.getContentPane().add(splitPane, BorderLayout.CENTER); + } else { + mainWindow.getContentPane().add(workspace.getCardPanel(), BorderLayout.CENTER); + } + + final Rectangle mainWindowBounds = settings.getMainWindowBounds(); + if (mainWindowBounds == null || mainWindowBounds.width <= 0 || mainWindowBounds.height <= 0) { + // Use Default size + mainWindow.setSize(500, 520); + + // Center Window on Screen + GraphicUtils.centerWindowOnScreen(mainWindow); + } else { + mainWindow.setBounds(mainWindowBounds); + } + + if (loginDialog != null) { + if (loginDialog.isVisible()) { + mainWindow.setVisible(true); + } + loginDialog.dispose(); + } + // Build the layout in the workspace + workspace.buildLayout(); + Log.debug("Finished starting Spark's main window."); + } catch (Exception e) { + Log.error("An exception occurred while trying to open Spark's main window.", e); + } + } + + /** + * Updates System properties with Proxy configuration. + * + * @throws Exception thrown if an exception occurs. + */ + private void updateProxyConfig() throws Exception { + if (ModelUtil.hasLength(Default.getString(Default.PROXY_PORT)) && ModelUtil.hasLength(Default.getString(Default.PROXY_HOST))) { + String port = Default.getString(Default.PROXY_PORT); + String host = Default.getString(Default.PROXY_HOST); + System.setProperty("socksProxyHost", host); + System.setProperty("socksProxyPort", port); + return; + } + + boolean proxyEnabled = localPref.isProxyEnabled(); + if (proxyEnabled) { + String host = localPref.getHost(); + String port = localPref.getPort(); + String username = localPref.getProxyUsername(); + String password = localPref.getProxyPassword(); + String protocol = localPref.getProtocol(); + + if (protocol.equals("SOCKS")) { + System.setProperty("socksProxyHost", host); + System.setProperty("socksProxyPort", port); + + if (ModelUtil.hasLength(username) && ModelUtil.hasLength(password)) { + System.setProperty("java.net.socks.username", username); + System.setProperty("java.net.socks.password", password); + } + } else { + System.setProperty("http.proxyHost", host); + System.setProperty("http.proxyPort", port); + System.setProperty("https.proxyHost", host); + System.setProperty("https.proxyPort", port); + + if (ModelUtil.hasLength(username) && ModelUtil.hasLength(password)) { + System.setProperty("http.proxyUser", username); + System.setProperty("http.proxyPassword", password); + } + + } + } + } + + /** + * Checks for historic Spark settings and upgrades the user. + * + * @throws Exception thrown if an error occurs. + */ + private void checkForOldSettings() throws Exception { + // Check for old settings.xml + File settingsXML = new File(Spark.getSparkUserHome(), "/settings.xml"); + if (settingsXML.exists()) { + SAXReader saxReader = SAXReader.createDefault(); + Document pluginXML; + try { + pluginXML = saxReader.read(settingsXML); + } catch (DocumentException e) { + Log.error(e); + return; + } + + List plugins = pluginXML.selectNodes("/settings"); + for (Object plugin1 : plugins) { + Element plugin = (Element) plugin1; + + String username = plugin.selectSingleNode("username").getText(); + localPref.setLastUsername(username); + + String server = plugin.selectSingleNode("server").getText(); + localPref.setServer(server); + + String autoLogin = plugin.selectSingleNode("autoLogin").getText(); + localPref.setAutoLogin(Boolean.parseBoolean(autoLogin)); + + String savePassword = plugin.selectSingleNode("savePassword").getText(); + localPref.setSavePassword(Boolean.parseBoolean(savePassword)); + + String password = plugin.selectSingleNode("password").getText(); + localPref.setPasswordForUser(username + "@" + server, password); + } + + // Delete settings File + settingsXML.delete(); + } + } + + /** + * Use DNS to lookup a KDC + * + * @param realm The realm to look up + * @return the KDC hostname + */ + private String getDnsKdc(String realm) { + //Assumption: the KDC will be found with the SRV record + // _kerberos._udp.$realm + try { + Hashtable env = new Hashtable<>(); + env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory"); + DirContext context = new InitialDirContext(env); + Attributes dnsLookup = context.getAttributes("_kerberos._udp." + realm, new String[]{"SRV"}); + + ArrayList priorities = new ArrayList<>(); + HashMap> records = new HashMap<>(); + for (Enumeration e = dnsLookup.getAll(); e.hasMoreElements();) { + Attribute record = (Attribute) e.nextElement(); + for (Enumeration e2 = record.getAll(); e2.hasMoreElements();) { + String sRecord = (String) e2.nextElement(); + String[] sRecParts = sRecord.split(" "); + Integer pri = Integer.valueOf(sRecParts[0]); + if (priorities.contains(pri)) { + List recs = records.get(pri); + if (recs == null) { + recs = new ArrayList<>(); + } + recs.add(sRecord); + } else { + priorities.add(pri); + List recs = new ArrayList<>(); + recs.add(sRecord); + records.put(pri, recs); + } + } + } + Collections.sort(priorities); + List l = records.get(priorities.get(0)); + String toprec = l.get(0); + String[] sRecParts = toprec.split(" "); + return sRecParts[3]; + } catch (NamingException e) { + return ""; + } + } + + protected String getLoginUsername() { + return loginUsername; + } + + protected void setLoginUsername(String loginUsername) { + this.loginUsername = loginUsername; + } + + protected String getLoginPassword() { + return loginPassword; + } + + protected void setLoginPassword(String loginPassword) { + this.loginPassword = loginPassword; + } + + protected String getLoginServer() { + return loginServer; + } + + protected void setLoginServer(String loginServer) { + this.loginServer = loginServer; + } + + protected ArrayList getUsernames() { + return _usernames; + } + + private void persistEnterprise() { + new Enterprise(); + //Check that the ClientControl plugin Openfire is installed on the server. + if(Enterprise.isSparkManagerInstalled()){ + localPref.setAccountsReg(Enterprise.containsFeature(Enterprise.ACCOUNTS_REG_FEATURE)); + localPref.setAdvancedConfig(Enterprise.containsFeature(Enterprise.ADVANCED_CONFIG_FEATURE)); + localPref.setHostNameChange(Enterprise.containsFeature(Enterprise.HOST_NAME_FEATURE)); + localPref.setInvisibleLogin(Enterprise.containsFeature(Enterprise.INVISIBLE_LOGIN_FEATURE)); + localPref.setAnonymousLogin(Enterprise.containsFeature(Enterprise.ANONYMOUS_LOGIN_FEATURE)); + localPref.setPswdAutologin(Enterprise.containsFeature(Enterprise.SAVE_PASSWORD_FEATURE)); + if (Enterprise.containsFeature(Enterprise.HOSTNAME_AS_RESOURCE_FEATURE) != Enterprise.containsFeature(Enterprise.VERSION_AS_RESOURCE_FEATURE)) { + localPref.setUseHostnameAsResource(Enterprise.containsFeature(Enterprise.HOSTNAME_AS_RESOURCE_FEATURE)); + localPref.setUseVersionAsResource(Enterprise.containsFeature(Enterprise.VERSION_AS_RESOURCE_FEATURE)); + } + localPref.setFileTransferIbbOnly(Enterprise.containsFeature(Enterprise.IBB_FEATURE)); + } + } + + private void initAdvancedDefaults() { + localPref.setCompressionEnabled(localPref.isCompressionEnabled()); + localPref.setDebuggerEnabled(localPref.isDebuggerEnabled()); + localPref.setDisableHostnameVerification(localPref.isDisableHostnameVerification()); + localPref.setHostAndPortConfigured(localPref.isHostAndPortConfigured()); + localPref.setProtocol("SOCKS"); + localPref.setProxyEnabled(localPref.isProxyEnabled()); + // localPref.setProxyPassword(""); + // localPref.setProxyUsername(""); + localPref.setResource(localPref.getResource()); + localPref.setSaslGssapiSmack3Compatible(localPref.isSaslGssapiSmack3Compatible()); + localPref.setDirectTls(localPref.isDirectTls()); + localPref.setSecurityMode(localPref.getSecurityMode()); + localPref.setSSOEnabled(localPref.isSSOEnabled()); + localPref.setSSOMethod("file"); + localPref.setTimeOut(localPref.getTimeOut()); + // localPref.setTrustStorePassword(""); + // localPref.setTrustStorePath(""); + localPref.setUseHostnameAsResource(localPref.isUseHostnameAsResource()); + localPref.setUseVersionAsResource(localPref.isUseVersionAsResource()); + // localPref.setXmppHost(""); + localPref.setXmppPort(localPref.getXmppPort()); + + if(Default.getBoolean(Default.IDLE_LOCK) || !Enterprise.containsFeature(Enterprise.IDLE_FEATURE)) { + localPref.setIdleTime(Integer.parseInt(Default.getString(Default.IDLE_TIME))); + localPref.setIdleMessage(Res.getString("status.away")); + localPref.setIdleOn(true); + } + } + +} diff --git a/src/java/org/jivesoftware/launcher/Installer.java b/core/src/main/java/org/jivesoftware/launcher/Installer.java similarity index 91% rename from src/java/org/jivesoftware/launcher/Installer.java rename to core/src/main/java/org/jivesoftware/launcher/Installer.java index 24e5394d1..1a329cfda 100644 --- a/src/java/org/jivesoftware/launcher/Installer.java +++ b/core/src/main/java/org/jivesoftware/launcher/Installer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +19,6 @@ import com.install4j.api.actions.InstallAction; import com.install4j.api.context.Context; import com.install4j.api.context.InstallerContext; -import com.install4j.api.context.UserCanceledException; import com.install4j.api.windows.RegistryRoot; import com.install4j.api.windows.WinRegistry; @@ -40,10 +35,12 @@ public int getPercentOfTotalInstallation() { } - public void init(Context context) { + @Override + public void init(Context context) { } - public boolean install(InstallerContext installerContext) throws UserCanceledException { + @Override + public boolean install(InstallerContext installerContext) { final String osName = System.getProperty("os.name").toLowerCase(); boolean isWindows = osName.startsWith("windows"); @@ -74,10 +71,17 @@ public boolean install(InstallerContext installerContext) throws UserCanceledExc return true; } - public void rollback(InstallerContext installerContext) { + @Override + public void rollback(InstallerContext installerContext) { WinRegistry.deleteValue(RegistryRoot.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", "Spark"); } + @Override + public boolean isRollbackSupported() + { + return true; + } + /** * Adds Spark to the users registry. * @@ -99,8 +103,6 @@ public void addSparkToStartup(String sparkPath) { */ private void setURI(String path) { boolean exists = WinRegistry.keyExists(RegistryRoot.HKEY_CLASSES_ROOT, "xmpp"); - if (exists) { - } // JOptionPane.showConfirmDialog(null, "Another application is currently registered to handle XMPP instant messaging. Make Spark the default XMPP instant messaging client?", "Confirmation", } WinRegistry.deleteKey(RegistryRoot.HKEY_CLASSES_ROOT, "xmpp", true); diff --git a/src/java/org/jivesoftware/launcher/JiveClassLoader.java b/core/src/main/java/org/jivesoftware/launcher/JiveClassLoader.java similarity index 97% rename from src/java/org/jivesoftware/launcher/JiveClassLoader.java rename to core/src/main/java/org/jivesoftware/launcher/JiveClassLoader.java index 7bc537e52..2e048b812 100644 --- a/src/java/org/jivesoftware/launcher/JiveClassLoader.java +++ b/core/src/main/java/org/jivesoftware/launcher/JiveClassLoader.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/src/main/java/org/jivesoftware/launcher/Startup.java b/core/src/main/java/org/jivesoftware/launcher/Startup.java new file mode 100644 index 000000000..532f9b845 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/launcher/Startup.java @@ -0,0 +1,98 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.launcher; + +import java.io.File; +import java.lang.reflect.Method; + +/** + */ +public class Startup { + + /** + * Default to this location if one has not been specified + */ + private static final String DEFAULT_LIB_DIR = "../lib"; + + public static void main(String[] args) { + new Startup().start(args); + } + + /** + * Starts the server by loading and instantiating the bootstrap + * container. Once the start method is called, the server is + * started and the server starter should not be used again. + * + * @param args the arguments passed into this initial instance of Spark. + */ + private void start(String[] args) { + // Setup the classpath using JiveClassLoader + try { + // Load up the bootstrap container + final ClassLoader parent = findParentClassLoader(); + + File libDir; + final String workingDirectory = System.getProperty("appdir"); + if (workingDirectory == null) { + libDir = new File(DEFAULT_LIB_DIR); + } + else { + libDir = new File(new File(workingDirectory), "lib"); + } + + File pluginDir = new File(libDir.getParentFile(), "plugins"); + + // Load them into the classloader + final ClassLoader loader = new JiveClassLoader(parent, libDir); + + Thread.currentThread().setContextClassLoader(loader); + + // Get class + Class sparkClass = loader.loadClass("org.jivesoftware.Spark"); + Object instanceOfSpark = sparkClass.newInstance(); + + // Handle arguments + if (args.length > 0) { + String argument = args[0]; + Method setArgument = sparkClass.getMethod("setArgument", String.class); + setArgument.invoke(instanceOfSpark, argument); + } + + Method startupMethod = sparkClass.getMethod("startup"); + startupMethod.invoke(instanceOfSpark); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Locates the best class loader based on context (see class description). + * + * @return The best parent classloader to use + */ + private ClassLoader findParentClassLoader() { + ClassLoader parent = Thread.currentThread().getContextClassLoader(); + if (parent == null) { + parent = this.getClass().getClassLoader(); + if (parent == null) { + parent = ClassLoader.getSystemClassLoader(); + } + } + return parent; + } + +} diff --git a/core/src/main/java/org/jivesoftware/resource/Default.java b/core/src/main/java/org/jivesoftware/resource/Default.java new file mode 100644 index 000000000..bfc7c5b1c --- /dev/null +++ b/core/src/main/java/org/jivesoftware/resource/Default.java @@ -0,0 +1,290 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.resource; + +import org.jivesoftware.spark.PluginRes; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; + +import javax.swing.ImageIcon; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.*; + +import static org.jivesoftware.sparkimpl.plugin.manager.Enterprise.PLUGINS_BLACKLIST_NODE; + +public class Default { + private static final Properties prb; + + private static final Map customMap = new HashMap<>(); + + private static final Map cache = new HashMap<>(); + + public static final String MAIN_IMAGE = "MAIN_IMAGE"; + public static final String APPLICATION_INFO1 = "APPLICATION_INFO1"; + public static final String APPLICATION_INFO2 = "APPLICATION_INFO2"; + public static final String APPLICATION_INFO3 = "APPLICATION_INFO3"; + public static final String APPLICATION_LICENSE_LINK = "APPLICATION_LICENSE_LINK"; + public static final String APPLICATION_LICENSE_LINK_TXT = "APPLICATION_LICENSE_LINK_TXT"; + public static final String APPLICATION_INFO4 = "APPLICATION_INFO4"; + public static final String APPLICATION_LINK = "APPLICATION_LINK"; + public static final String APPLICATION_LINK_TXT = "APPLICATION_LINK_TXT"; + public static final String DISPLAY_DEV_INFO = "DISPLAY_DEV_INFO"; + public static final String JAVA_VERSION = "JAVA_VERSION"; + public static final String SHORT_NAME = "SHORT_NAME"; + public static final String LOGIN_DIALOG_BACKGROUND_IMAGE = "LOGIN_DIALOG_BACKGROUND_IMAGE"; + public static final String HOST_NAME = "HOST_NAME"; + public static final String HOST_NAME_CHANGE_DISABLED = "HOST_NAME_CHANGE_DISABLED"; + public static final String SHOW_POWERED_BY = "SHOW_POWERED_BY"; + public static final String TOP_BOTTOM_BACKGROUND_IMAGE = "TOP_BOTTOM_BACKGROUND_IMAGE"; + public static final String BRANDED_IMAGE = "BRANDED_IMAGE"; + public static final String DISABLE_UPDATES = "DISABLE_UPDATES"; + public static final String SECONDARY_BACKGROUND_IMAGE = "SECONDARY_BACKGROUND_IMAGE"; + public static final String HOVER_TEXT_COLOR = "HOVER_TEXT_COLOR"; + public static final String TEXT_COLOR = "TEXT_COLOR"; + public static final String TAB_START_COLOR = "TAB_START_COLOR"; + public static final String TAB_END_COLOR = "TAB_END_COLOR"; + public static final String CONTACT_GROUP_START_COLOR = "CONTACT_GROUP_START_COLOR"; + public static final String CONTACT_GROUP_END_COLOR = "CONTACT_GROUP_END_COLOR"; + public static final String PROXY_HOST = "PROXY_HOST"; + public static final String PROXY_PORT = "PROXY_PORT"; + public static final String ACCOUNT_DISABLED = "ACCOUNT_DISABLED"; + public static final String PASSWORD_RESET_ENABLED = "PASSWORD_RESET_ENABLED"; + public static final String PASSWORD_RESET_URL = "PASSWORD_RESET_URL"; + public static final String ADD_CONTACT_DISABLED = "ADD_CONTACT_DISABLED"; + public static final String CHANGE_PASSWORD_DISABLED = "CHANGE_PASSWORD_DISABLED"; + public static final String TRAY_IMAGE = "TRAY_IMAGE"; + public static final String FRAME_IMAGE = "FRAME_IMAGE"; + public static final String LOOK_AND_FEEL_DISABLED = "LOOK_AND_FEEL_DISABLED"; + public static final String DEFAULT_LOOK_AND_FEEL = "DEFAULT_LOOK_AND_FEEL"; + public static final String DEFAULT_LOOK_AND_FEEL_MAC = "DEFAULT_LOOK_AND_FEEL_MAC"; + public static final String INSTALL_PLUGINS_DISABLED = "INSTALL_PLUGINS_DISABLED"; + public static final String UNINSTALL_PLUGINS_DISABLED = "UNINSTALL_PLUGINS_DISABLED"; + public static final String ADVANCED_DISABLED = "ADVANCED_DISABLED"; + public static final String SSO_DISABLED = "SSO_DISABLED"; + public static final String PROXY_DISABLED = "PROXY_DISABLED"; + public static final String PKI_DISABLED = "PKI_DISABLED"; + public static final String CERTIFICATES_MANAGER_DISABLED = "CERTIFICATES_MANAGER_DISABLED"; + public static final String MUTUAL_AUTH_DISABLED = "MUTUAL_AUTH_DISABLED"; + public static final String HELP_USER_GUIDE = "HELP_USER_GUIDE"; + public static final String BROADCAST_IN_CHAT_WINDOW = "BROADCAST_IN_CHAT_WINDOW"; + public static final String FILE_TRANSFER_WARNING_SIZE = "FILE_TRANSFER_WARNING_SIZE"; + public static final String FILE_TRANSFER_MAXIMUM_SIZE = "FILE_TRANSFER_MAXIMUM_SIZE"; + public static final String TABS_PLACEMENT_TOP = "TABS_PLACEMENT_TOP"; + public static final String HIDE_PERSON_SEARCH_FIELD = "HIDE_PERSON_SEARCH_FIELD"; + public static final String USER_DIRECTORY_WINDOWS = "USER_DIRECTORY_WINDOWS"; + public static final String USER_DIRECTORY_LINUX = "USER_DIRECTORY_LINUX"; + public static final String USER_DIRECTORY_MAC = "USER_DIRECTORY_MAC"; + public static final String HISTORY_DISABLED = "HISTORY_DISABLED"; + public static final String HIDE_HISTORY_SETTINGS = "HIDE_HISTORY_SETTINGS"; + public static final String HIDE_SAVE_PASSWORD_AND_AUTO_LOGIN = "HIDE_SAVE_PASSWORD_AND_AUTO_LOGIN"; + public static final String HIDE_LOGIN_AS_INVISIBLE = "HIDE_LOGIN_AS_INVISIBLE"; + public static final String HIDE_LOGIN_ANONYMOUSLY = "HIDE_LOGIN_ANONYMOUSLY"; + public static final String MAINTENANCE_FILE_PATH = "MAINTENANCE_FILE_PATH"; + public static final String HIDE_START_A_CHAT = "HIDE_START_A_CHAT"; + public static final String ACCEPT_EXPIRED = "ACCEPT_EXPIRED"; + public static final String ACCEPT_NOT_VALID_YET = "ACCEPT_NOT_VALID_YET"; + public static final String ACCEPT_SELF_SIGNED = "ACCEPT_SELF_SIGNED"; + public static final String ACCEPT_REVOKED = "ACCEPT_REVOKED"; + public static final String CHECK_CRL = "CHECK_CRL"; + public static final String CHECK_OCSP = "CHECK_OCSP"; + public static final String ALLOW_SOFT_FAIL = "ALLOW_SOFT_FAIL"; + public static final String ALLOW_CLIENT_SIDE_AUTH = "ALLOW_CLIENT_SIDE_AUTH"; + public static final String DISABLE_HOSTNAME_VERIFICATION = "DISABLE_HOSTNAME_VERIFICATION"; + public static final String SECURITY_MODE = "SECURITY_MODE"; + public static final String HOST_AND_PORT_CONFIGURED = "HOST_AND_PORT_CONFIGURED"; + public static final String XMPP_PORT = "XMPP_PORT"; + public static final String USE_HOSTNAME_AS_RESOURCE = "USE_HOSTNAME_AS_RESOURCE"; + public static final String USE_VERSION_AS_RESOURCE = "USE_VERSION_AS_RESOURCE"; + public static final String TIME_OUT = "TIME_OUT"; + public static final String COMPRESSION_ENABLED = "COMPRESSION_ENABLED"; + public static final String DEBUGGER_ENABLED = "DEBUGGER_ENABLED"; + public static final String USE_SSO = "USE_SSO"; + public static final String USE_SASL_GSS_API_SMACK_3_COMPATIBLE = "USE_SASL_GSS_API_SMACK_3_COMPATIBLE"; + public static final String SSO_METHOD = "SSO_METHOD"; + public static final String PROXY_ENABLED = "PROXY_ENABLED"; + public static final String OLD_SSL_ENABLED = "OLD_SSL_ENABLED"; + public static final String FILE_TRANSFER_IBB_ONLY = "FILE_TRANSFER_IBB_ONLY"; + public static final String FILE_TRANSFER_AUTO_ACCEPT_PRESENCE = "FILE_TRANSFER_AUTO_ACCEPT_PRESENCE"; + public static final String CHANGE_COLORS_DISABLED = "CHANGE_COLORS_DISABLED"; + public static final String ADD_CONTACT_GROUP_DISABLED = "ADD_CONTACT_GROUP_DISABLED"; + public static final String DISABLE_AVATAR_TAB = "DISABLE_AVATAR_TAB"; + public static final String DISABLE_BROADCAST_MENU_ITEM = "DISABLE_BROADCAST_MENU_ITEM"; + public static final String DISABLE_EDIT_PROFILE = "DISABLE_EDIT_PROFILE"; + public static final String DISABLE_EXIT = "DISABLE_EXIT"; + public static final String DISABLE_FILE_TRANSFER = "DISABLE_FILE_TRANSFER"; + public static final String DISABLE_MOVE_AND_COPY = "DISABLE_MOVE_AND_COPY"; + public static final String DISABLE_PLUGINS_MENU_ITEM = "DISABLE_PLUGINS_MENU_ITEM"; + public static final String DISABLE_PREFERENCES_MENU_ITEM = "DISABLE_PREFERENCES_MENU_ITEM"; + public static final String DISABLE_PRESENCE_STATUS_CHANGE = "DISABLE_PRESENCE_STATUS_CHANGE"; + public static final String DISABLE_REMOVALS = "DISABLE_REMOVALS"; + public static final String DISABLE_RENAMES = "DISABLE_RENAMES"; + public static final String DISABLE_VIEW_NOTES = "DISABLE_VIEW_NOTES"; + public static final String DISABLE_VIEW_TASK_LIST = "DISABLE_VIEW_TASK_LIST"; + public static final String HELP_FORUM = "HELP_FORUM"; + public static final String HELP_FORUM_DISABLED = "HELP_FORUM_DISABLED"; + public static final String HELP_FORUM_TEXT = "HELP_FORUM_TEXT"; + public static final String HELP_USER_GUIDE_DISABLED = "HELP_USER_GUIDE_DISABLED"; + public static final String PLUGIN_BLACKLIST = "PLUGIN_BLACKLIST"; + public static final String PLUGIN_BLACKLIST_CLASS = "PLUGIN_BLACKLIST_CLASS"; + public static final String PLUGIN_REPOSITORY = "PLUGIN_REPOSITORY"; + public static final String PROXY_PROTOCOL = "PROXY_PROTOCOL"; + public static final String IDLE_LOCK = "IDLE_LOCK"; + public static final String IDLE_TIME = "IDLE_TIME"; + + private static final ClassLoader cl = SparkRes.class.getClassLoader(); + + static { + prb = new Properties(); + try + { + InputStream resourceAsStream = cl.getResourceAsStream( "default.properties" ); + if (resourceAsStream != null) { + prb.load( resourceAsStream ); + } + } + catch ( IOException e ) + { + e.printStackTrace(); + } + } + + public static void putCustomValue(String value, Object object) { + customMap.put(value, object); + } + + public static void removeCustomValue(String value) { + customMap.remove(value); + } + + public static void clearCustomValues() { + customMap.clear(); + } + + public static String getString(String propertyName) { + String pluginString = PluginRes.getDefaultRes(propertyName); + return pluginString != null ? pluginString : prb.getProperty(propertyName); + } + + public static boolean getBoolean(String propertyName) { + String prop = getString(propertyName); + return prop != null && Boolean.parseBoolean(prop.trim()); + } + + public static ImageIcon getImageIcon(String imageName) { + // Check custom map + Object o = customMap.get(imageName); + if (o instanceof ImageIcon) { + return (ImageIcon)o; + } + + // Otherwise check cache + o = cache.get(imageName); + if (o != null) { + return (ImageIcon)o; + } + + // Otherwise, load and add to cache. + try { + final URL imageURL = getURL(imageName); + if (imageURL == null) { + Log.debug(imageName + " not found."); + return null; + } + + final ImageIcon icon = new ImageIcon(imageURL); + cache.put(imageName, icon); + return icon; + } + catch (Exception e) { + Log.warning("Unable to load " + imageName, e); + } + return null; + } + + public static URL getURL(String propertyName) { + URL pluginUrl = PluginRes.getDefaultURL(propertyName); + if (pluginUrl != null) return pluginUrl; + String resourceName = getString(propertyName); + if (resourceName == null) { + return null; + } + return cl.getResource(resourceName); + } + + + public static URL getURLWithoutException(String propertyName) { + // Otherwise, load and add to cache. + try { + return getURL(propertyName); + } + catch (Exception ex) { + Log.debug(propertyName + " not found."); + } + return null; + } + + /** + * Returns a Collection of Plugins on the Blacklist
    + * Containing the Name and also if specified the entrypoint-class + * @return Collection + */ + public static Collection getPluginBlacklist() { + ArrayList list = new ArrayList<>(); + + // Load the blacklist from the (local) configuration. + String pluginlist = getString(Default.PLUGIN_BLACKLIST).replace(" ", "").toLowerCase(); + StringTokenizer tokenizer = new StringTokenizer(pluginlist, ","); + + while (tokenizer.hasMoreTokens()) { + final String pluginName = tokenizer.nextToken(); + Log.debug("Local config plugin blacklist: " + pluginName); + list.add(pluginName); + } + + StringTokenizer clazztokenz = new StringTokenizer( + getString(Default.PLUGIN_BLACKLIST_CLASS).replace(" ", ""), ","); + + while (clazztokenz.hasMoreTokens()) { + final String pluginClass = clazztokenz.nextToken(); + Log.debug("Local config plugin blacklist: " + pluginClass); + list.add(pluginClass); + } + + // Load the blacklist from Openfire's clientControl plugin + for( final String entry : Enterprise.getItemsForNode(PLUGINS_BLACKLIST_NODE) ) { + final String normalized = entry.toLowerCase(); + Log.debug("Server-dictated plugin blacklist: " + normalized); + if (!list.contains(normalized)) { + list.add(normalized); + } + } + + return list; + } + + /** + * Returns all Keys stored in the default.properties file + * @return {@link Enumeration}<{@link String}> + */ + public static Enumeration getAllKeys() + { + return (Enumeration) prb.propertyNames(); + } + +} diff --git a/src/java/org/jivesoftware/resource/Res.java b/core/src/main/java/org/jivesoftware/resource/Res.java similarity index 83% rename from src/java/org/jivesoftware/resource/Res.java rename to core/src/main/java/org/jivesoftware/resource/Res.java index 17aa9ae13..ad9f2a2f3 100644 --- a/src/java/org/jivesoftware/resource/Res.java +++ b/core/src/main/java/org/jivesoftware/resource/Res.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,16 +28,14 @@ * @author Derek DeMoro */ public class Res { - private static PropertyResourceBundle prb; + private static final PropertyResourceBundle prb; private Res() { } - static ClassLoader cl = Res.class.getClassLoader(); - static { - prb = (PropertyResourceBundle)ResourceBundle.getBundle("i18n/spark_i18n"); + prb = (PropertyResourceBundle)ResourceBundle.getBundle("i18n/spark_i18n", new UTF8Control()); } public static String getString(String propertyName) { @@ -58,11 +52,16 @@ public static String getString(String propertyName) { public static String getString(String propertyName, Object... obj) { String pluginString = PluginRes.getI18nRes(propertyName); - String str = pluginString != null ? pluginString : prb.getString(propertyName); - if (str == null) { - return propertyName; - } - + String str; + try { + str = pluginString != null ? pluginString : prb.getString(propertyName); + if (str == null) { + return propertyName; + } + } catch (Exception e) { + Log.error(e); + return propertyName; + } return MessageFormat.format(str, obj); } diff --git a/core/src/main/java/org/jivesoftware/resource/SparkRes.java b/core/src/main/java/org/jivesoftware/resource/SparkRes.java new file mode 100644 index 000000000..d0d62e570 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/resource/SparkRes.java @@ -0,0 +1,462 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.resource; + +import org.jivesoftware.spark.PluginRes; +import org.jivesoftware.spark.util.log.Log; + +import javax.swing.ImageIcon; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.JScrollPane; + +import java.awt.BorderLayout; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.*; + +public class SparkRes { + + private static final Properties prb; + + public enum Icon { + ACCEPT_CHAT("ACCEPT_CHAT"), + ACCEPT_INVITE_IMAGE("ACCEPT_INVITE_IMAGE"), + ADDRESS_BOOK_16x16("ADDRESS_BOOK_16x16"), + ADD_BOOKMARK_ICON("ADD_BOOKMARK_ICON"), + ADD_CONTACT_IMAGE("ADD_CONTACT_IMAGE"), + ADD_IMAGE_24x24("ADD_IMAGE_24x24"), + ADD_LINK_TO_CHAT("ADD_LINK_TO_CHAT"), + ADD_TO_CHAT("ADD_TO_CHAT"), + ADD_TO_KB("ADD_TO_KB"), + ALERT("ALERT"), + ALL_CHATS("ALL_CHATS"), + AVAILABLE_USER("AVAILABLE_USER"), + AWAY_USER("AWAY_USER"), + BACKGROUND_IMAGE("BACKGROUND_IMAGE"), + BLANK_24x24("BLANK_24x24"), + BLANK_IMAGE("BLANK_IMAGE"), + BLOCK_CONTACT_16x16("BLOCK_CONTACT_16x16"), + BLUE_BALL("BLUE_BALL"), + BOOKMARK_ICON("BOOKMARK_ICON"), + BRICKWALL_IMAGE("BRICKWALL_IMAGE"), + BUSY_IMAGE("BUSY_IMAGE"), + BUZZ_IMAGE("BUZZ_IMAGE"), + CALENDAR_IMAGE("CALENDAR_IMAGE"), + CALL_ICON("CALL_ICON"), + CANCEL_IMAGE("CANCEL_IMAGE"), + CHANGELOG_IMAGE("CHANGELOG_IMAGE"), + CHATTING_AGENT_IMAGE("CHATTING_AGENT_IMAGE"), + CHATTING_CUSTOMER_IMAGE("CHATTING_CUSTOMER_IMAGE"), + CHAT_QUEUE("CHAT_QUEUE"), + CHAT_WORKSPACE("CHAT_WORKSPACE"), + CHECK_UPDATE("CHECK_UPDATE"), + CIRCLE_CHECK_IMAGE("CIRCLE_CHECK_IMAGE"), + CLEAR_BALL_ICON("CLEAR_BALL_ICON"), + CLIPBOARD("CLIPBOARD"), + CLOSE_IMAGE("CLOSE_IMAGE"), + CLOSE_RED_X_IMAGE("CLOSE_RED_X_IMAGE"), + CLOSE_WHITE_X_IMAGE("CLOSE_WHITE_X_IMAGE"), + COLOR_ICON("COLOR_ICON"), + COMPUTER_IMAGE_16x16("COMPUTER_IMAGE_16x16"), + CONFERENCE_IMAGE_16x16("CONFERENCE_IMAGE_16x16"), + CONFERENCE_IMAGE_24x24("CONFERENCE_IMAGE_24x24"), + CONFERENCE_IMAGE_48x48("CONFERENCE_IMAGE_48x48"), + COPY_16x16("COPY_16x16"), + CO_BROWSER_TAB_TITLE("CO_BROWSER_TAB_TITLE"), + CREATE_FAQ_ENTRY("CREATE_FAQ_ENTRY"), + CREATE_FAQ_TITLE("CREATE_FAQ_TITLE"), + CURRENT_AGENTS("CURRENT_AGENTS"), + CURRENT_CHATS("CURRENT_CHATS"), + DATA_DELETE_16x16("DATA_DELETE_16x16"), + DATA_REFRESH_16x16("DATA_REFRESH_16x16"), + DEFAULT_AVATAR_16x16_IMAGE("DEFAULT_AVATAR_16x16_IMAGE"), + DEFAULT_AVATAR_32x32_IMAGE("DEFAULT_AVATAR_32x32_IMAGE"), + DEFAULT_AVATAR_64x64_IMAGE("DEFAULT_AVATAR_64x64_IMAGE"), + DELETE_BOOKMARK_ICON("DELETE_BOOKMARK_ICON"), + DESKTOP_IMAGE("DESKTOP_IMAGE"), + DIAL_PHONE_IMAGE_16x16("DIAL_PHONE_IMAGE_16x16"), + DIAL_PHONE_IMAGE_24x24("DIAL_PHONE_IMAGE_24x24"), + DIVIDER_IMAGE("DIVIDER_IMAGE"), + DOCUMENT_16x16("DOCUMENT_16x16"), + DOCUMENT_EXCHANGE_IMAGE("DOCUMENT_EXCHANGE_IMAGE"), + DOCUMENT_FIND_16x16("DOCUMENT_FIND_16x16"), + DOCUMENT_INFO_32x32("DOCUMENT_INFO_32x32"), + DOOR_IMAGE("DOOR_IMAGE"), + DOWNLOAD_16x16("DOWNLOAD_16x16"), + DOWN_ARROW_IMAGE("DOWN_ARROW_IMAGE"), + DOWN_OPTION_IMAGE("DOWN_OPTION_IMAGE"), + EARTH_LOCK_16x16("EARTH_LOCK_16x16"), + EARTH_VIEW_16x16("EARTH_VIEW_16x16"), + END_BUTTON_24x24("END_BUTTON_24x24"), + ERASER_IMAGE("ERASER_IMAGE"), + ERROR_DIALOG_TITLE("ERROR_DIALOG_TITLE"), + ERROR_INVALID_WORKGROUP("ERROR_INVALID_WORKGROUP"), + FACEBOOK_TRANSPORT_ACTIVE_IMAGE("FACEBOOK_TRANSPORT_ACTIVE_IMAGE"), + FACEBOOK_TRANSPORT_INACTIVE_IMAGE("FACEBOOK_TRANSPORT_INACTIVE_IMAGE"), + FAQ_TAB_TITLE("FAQ_TAB_TITLE"), + FASTPATH_IMAGE_16x16("FASTPATH_IMAGE_16x16"), + FASTPATH_IMAGE_24x24("FASTPATH_IMAGE_24x24"), + FASTPATH_IMAGE_32x32("FASTPATH_IMAGE_32x32"), + FASTPATH_IMAGE_64x64("FASTPATH_IMAGE_64x64"), + FASTPATH_OFFLINE_IMAGE_16x16("FASTPATH_OFFLINE_IMAGE_16x16"), + FASTPATH_OFFLINE_IMAGE_24x24("FASTPATH_OFFLINE_IMAGE_24x24"), + FILTER_LABEL("FILTER_LABEL"), + FIND_IMAGE("FIND_IMAGE"), + FIND_TEXT_IMAGE("FIND_TEXT_IMAGE"), + FOLDER("FOLDER"), + FOLDER_CLOSED("FOLDER_CLOSED"), + FONT_16x16("FONT_16x16"), + FORUM_TAB_TITLE("FORUM_TAB_TITLE"), + FRAME_ALWAYS_ON_TOP_ACTIVE("FRAME_ALWAYS_ON_TOP_ACTIVE"), + FRAME_ALWAYS_ON_TOP_DEACTIVE("FRAME_ALWAYS_ON_TOP_DEACTIVE"), + FREE_TO_CHAT_IMAGE("FREE_TO_CHAT_IMAGE"), + FUNNEL_DOWN_16x16("FUNNEL_DOWN_16x16"), + GADUGADU_TRANSPORT_ACTIVE_IMAGE("GADUGADU_TRANSPORT_ACTIVE_IMAGE"), + GADUGADU_TRANSPORT_INACTIVE_IMAGE("GADUGADU_TRANSPORT_INACTIVE_IMAGE"), + GO("GO"), + GREEN_BALL("GREEN_BALL"), + GREEN_FLAG_16x16("GREEN_FLAG_16x16"), + HEADSET_IMAGE("HEADSET_IMAGE"), + HELP2_24x24("HELP2_24x24"), + HISTORY_16x16("HISTORY_16x16"), + HISTORY_24x24_IMAGE("HISTORY_24x24"), + ID_CARD_48x48("ID_CARD_48x48"), + IM_AVAILABLE_STALE_IMAGE("IM_AVAILABLE_STALE_IMAGE"), + IM_AWAY("IM_AWAY"), + IM_AWAY_STALE_IMAGE("IM_AWAY_STALE_IMAGE"), + IM_DND("IM_DND"), + IM_DND_STALE_IMAGE("IM_DND_STALE_IMAGE"), + IM_FREE_CHAT_STALE_IMAGE("IM_FREE_CHAT_STALE_IMAGE"), + IM_UNAVAILABLE_STALE_IMAGE("IM_UNAVAILABLE_STALE_IMAGE"), + IM_XA("IM_XA"), + IM_XA_STALE_IMAGE("IM_XA_STALE_IMAGE"), + INFORMATION_ICO("INFORMATION_ICO"), + INFORMATION_IMAGE("INFORMATION_IMAGE"), + INVALID_USERNAME_PASSWORD("INVALID_USERNAME_PASSWORD"), + INVISIBLE("INVISIBLE"), + INVITE_MORE_IMAGE("INVITE_MORE_IMAGE"), + IRC_TRANSPORT_ACTIVE_IMAGE("IRC_TRANSPORT_ACTIVE_IMAGE"), + IRC_TRANSPORT_INACTIVE_IMAGE("IRC_TRANSPORT_INACTIVE_IMAGE"), + JOIN_GROUPCHAT_IMAGE("JOIN_GROUPCHAT_IMAGE"), + KNOWLEDGE_BASE_TAB_TITLE("KNOWLEDGE_BASE_TAB_TITLE"), + LANGUAGE_ICON("LANGUAGE_ICON"), + LEFT_ARROW_IMAGE("LEFT_ARROW_IMAGE"), + LIGHTBULB_ON_16x16_IMAGE("LIGHTBULB_ON_16x16_IMAGE"), + LIGHTING_BOLT_IMAGE("LIGHTING_BOLT_IMAGE"), + LINK_16x16("LINK_16x16"), + LINK_DELETE_16x16("LINK_DELETE_16x16"), + LOCK_16x16("LOCK_16x16"), + LOCK_UNLOCK_16x16("LOCK_UNLOCK_16x16"), + LOGIN_DIALOG_AUTHENTICATING("LOGIN_DIALOG_AUTHENTICATING"), + LOGIN_DIALOG_LOGIN("LOGIN_DIALOG_LOGIN"), + LOGIN_DIALOG_LOGIN_TITLE("LOGIN_DIALOG_LOGIN_TITLE"), + LOGIN_DIALOG_PASSWORD("LOGIN_DIALOG_PASSWORD"), + LOGIN_DIALOG_QUIT("LOGIN_DIALOG_QUIT"), + LOGIN_DIALOG_USERNAME("LOGIN_DIALOG_USERNAME"), + LOGIN_DIALOG_WORKSPACE("LOGIN_DIALOG_WORKSPACE"), + LOGIN_KEY_IMAGE("LOGIN_KEY_IMAGE"), + MAGICIAN_IMAGE("MAGICIAN_IMAGE"), + MAIL_16x16("MAIL_16x16"), + MAIL_FORWARD_16x16("MAIL_FORWARD_16x16"), + MAIL_IMAGE_32x32("MAIL_IMAGE_32x32"), + MAIL_INTO_16x16("MAIL_INTO_16x16"), + MAIN_ICNS_FILE("MAIN_ICNS_FILE"), + MAIN_IMAGE("MAIN_IMAGE"), + MAIN_IMAGE_ICO("MAIN_IMAGE_ICO"), + MAIN_TITLE("MAIN_TITLE"), + MEGAPHONE_16x16("MEGAPHONE_16x16"), + MESSAGE_AWAY("MESSAGE_AWAY"), + MESSAGE_DND("MESSAGE_DND"), + MESSAGE_NEW_TRAY("MESSAGE_NEW_TRAY"), + MESSAGE_NEW_TRAY_LINUX("MESSAGE_NEW_TRAY_LINUX"), + MINUS_SIGN("MINUS_SIGN"), + MOBILE_PHONE_IMAGE("MOBILE_PHONE_IMAGE"), + MODERATOR_IMAGE("MODERATOR_IMAGE"), + MYSPACE_TRANSPORT_ACTIVE_IMAGE("MYSPACE_TRANSPORT_ACTIVE_IMAGE"), + MYSPACE_TRANSPORT_INACTIVE_IMAGE("MYSPACE_TRANSPORT_INACTIVE_IMAGE"), + NEW_MESSAGE("NEW_MESSAGE"), + NOTEBOOK_IMAGE("NOTEBOOK_IMAGE"), + NOTE_EDIT_16x16("NOTE_EDIT_16x16"), + NOTIFICATIONS("NOTIFICATIONS"), + OFFLINE_ICO("OFFLINE_ICO"), + OFFLINE_IMAGE("OFFLINE_IMAGE"), + ONLINE_ICO("ONLINE_ICO"), + ON_PHONE_IMAGE("ON_PHONE_IMAGE"), + PALETTE_24x24_IMAGE("PALETTE_24x24_IMAGE"), + PANE_DOWN_ARROW_IMAGE("PANE_DOWN_ARROW_IMAGE"), + PANE_UP_ARROW_IMAGE("PANE_UP_ARROW_IMAGE"), + PAWN_GLASS_GREEN("PAWN_GLASS_GREEN"), + PAWN_GLASS_RED("PAWN_GLASS_RED"), + PAWN_GLASS_WHITE("PAWN_GLASS_WHITE"), + PAWN_GLASS_YELLOW("PAWN_GLASS_YELLOW"), + PEOPLE_IMAGE("PEOPLE_IMAGE"), + PHOTO_IMAGE("PHOTO_IMAGE"), + PLUGIN_IMAGE("PLUGIN_IMAGE"), + PLUS_SIGN("PLUS_SIGN"), + POWERED_BY_IMAGE("POWERED_BY_IMAGE"), + PREFERENCES_IMAGE("PREFERENCES_IMAGE"), + PRINTER_IMAGE_16x16("PRINTER_IMAGE_16x16"), + PRIVACY_CHECK("PRIVACY_CHECK"), + PRIVACY_DEACTIVATE_LIST("PRIVACY_DEACTIVATE_LIST"), + PRIVACY_ICON("PRIVACY_ICON"), + PRIVACY_ICON_SMALL("PRIVACY_ICON_SMALL"), + PRIVACY_LIGHTNING("PRIVACY_LIGHTNING"), + PRIVACY_MSG_ALLOW("PRIVACY_MSG_ALLOW"), + PRIVACY_MSG_DENY("PRIVACY_MSG_DENY"), + PRIVACY_PIN_ALLOW("PRIVACY_PIN_ALLOW"), + PRIVACY_PIN_DENY("PRIVACY_PIN_DENY"), + PRIVACY_POUT_ALLOW("PRIVACY_POUT_ALLOW"), + PRIVACY_POUT_DENY("PRIVACY_POUT_DENY"), + PRIVACY_QUERY_ALLOW("PRIVACY_QUERY_ALLOW"), + PRIVACY_QUERY_DENY("PRIVACY_QUERY_DENY"), + PROFILE_ICON("PROFILE_ICON"), + PROFILE_IMAGE_16x16("PROFILE_IMAGE_16x16"), + PROFILE_IMAGE_24x24("PROFILE_IMAGE_24x24"), + PROFILE_TAB_TITLE("PROFILE_TAB_TITLE"), + PUSH_URL_16x16("PUSH_URL_16x16"), + QQ_TRANSPORT_ACTIVE_IMAGE("QQ_TRANSPORT_ACTIVE_IMAGE"), + QQ_TRANSPORT_INACTIVE_IMAGE("QQ_TRANSPORT_INACTIVE_IMAGE"), + QUESTIONS_ANSWERS("QUESTIONS_ANSWERS"), + README_IMAGE("README_IMAGE"), + RED_BALL("RED_BALL"), + RED_FLAG_16x16("RED_FLAG_16x16"), + REFRESH_IMAGE("REFRESH_IMAGE"), + REJECT_CHAT("REJECT_CHAT"), + REJECT_INVITE_IMAGE("REJECT_INVITE_IMAGE"), + RIGHT_ARROW_IMAGE("RIGHT_ARROW_IMAGE"), + SAMETIME_TRANSPORT_ACTIVE_IMAGE("SAMETIME_TRANSPORT_ACTIVE_IMAGE"), + SAMETIME_TRANSPORT_INACTIVE_IMAGE("SAMETIME_TRANSPORT_INACTIVE_IMAGE"), + SAVE_AS_16x16("SAVE_AS_16x16"), + SEARCH("SEARCH"), + SEARCH_IMAGE_32x32("SEARCH_IMAGE_32x32"), + SEARCH_USER_16x16("SEARCH_USER_16x16"), + SEND("SEND"), + SEND_FILE_24x24("SEND_FILE_24x24"), + SEND_FILE_ICON("SEND_FILE_ICON"), + SEND_MAIL_IMAGE_16x16("SEND_MAIL_IMAGE_16x16"), + SERVER_ICON("SERVER_ICON"), + SERVER_UNAVAILABLE("SERVER_UNAVAILABLE"), + SETTINGS_IMAGE_16x16("SETTINGS_IMAGE_16x16"), + SETTINGS_IMAGE_24x24("SETTINGS_IMAGE_24x24"), + SIMPLE_TRANSPORT_ACTIVE_IMAGE("SIMPLE_TRANSPORT_ACTIVE_IMAGE"), + SIMPLE_TRANSPORT_INACTIVE_IMAGE("SIMPLE_TRANSPORT_INACTIVE_IMAGE"), + SMALL_ABOUT_IMAGE("SMALL_ABOUT_IMAGE"), + SMALL_ADD_IMAGE("SMALL_ADD_IMAGE"), + SMALL_AGENT_IMAGE("SMALL_AGENT_IMAGE"), + SMALL_ALARM_CLOCK("SMALL_ALARM_CLOCK"), + SMALL_ALL_AGENTS_IMAGE("SMALL_ALL_AGENTS_IMAGE"), + SMALL_ALL_CHATS_IMAGE("SMALL_ALL_CHATS_IMAGE"), + SMALL_BUSINESS_MAN_VIEW("SMALL_BUSINESS_MAN_VIEW"), + SMALL_CHECK("SMALL_CHECK"), + SMALL_CIRCLE_DELETE("SMALL_CIRCLE_DELETE"), + SMALL_CLOSE_BUTTON("SMALL_CLOSE_BUTTON"), + SMALL_CURRENT_AGENTS("SMALL_CURRENT_AGENTS"), + SMALL_DATA_FIND_IMAGE("SMALL_DATA_FIND_IMAGE"), + SMALL_DELETE("SMALL_DELETE"), + SMALL_DOCUMENT_ADD("SMALL_DOCUMENT_ADD"), + SMALL_DOCUMENT_VIEW("SMALL_DOCUMENT_VIEW"), + SMALL_ENTRY("SMALL_ENTRY"), + SMALL_MESSAGE_EDIT_IMAGE("SMALL_MESSAGE_EDIT_IMAGE"), + SMALL_MESSAGE_IMAGE("SMALL_MESSAGE_IMAGE"), + SMALL_PIN_BLUE("SMALL_PIN_BLUE"), + SMALL_PROFILE_IMAGE("SMALL_PROFILE_IMAGE"), + SMALL_QUESTION("SMALL_QUESTION"), + SMALL_SCROLL_REFRESH("SMALL_SCROLL_REFRESH"), + SMALL_STOP("SMALL_STOP"), + SMALL_USER1_INFORMATION("SMALL_USER1_INFORMATION"), + SMALL_USER1_MESSAGE("SMALL_USER1_MESSAGE"), + SMALL_USER1_MOBILEPHONE("SMALL_USER1_MOBILEPHONE"), + SMALL_USER1_NEW("SMALL_USER1_NEW"), + SMALL_USER1_STOPWATCH("SMALL_USER1_STOPWATCH"), + SMALL_USER1_TIME("SMALL_USER1_TIME"), + SMALL_USER_DELETE("SMALL_USER_DELETE"), + SMALL_USER_ENTER("SMALL_USER_ENTER"), + SMALL_WORKGROUP_QUEUE_IMAGE("SMALL_WORKGROUP_QUEUE_IMAGE"), + SOUND_PREFERENCES_IMAGE("SOUND_PREFERENCES_IMAGE"), + SPARK_IMAGE("SPARK_IMAGE"), + SPARK_IMAGE_32x32("SPARK_IMAGE_32x32"), + SPARK_LOGOUT_IMAGE("SPARK_LOGOUT_IMAGE"), + SPELL_CHECK_IMAGE("SPELL_CHECK_IMAGE"), + STAR_ADMIN("STAR_ADMIN"), + STAR_BLUE_IMAGE("STAR_BLUE_IMAGE"), + STAR_GREEN_IMAGE("STAR_GREEN_IMAGE"), + STAR_GREY_IMAGE("STAR_GREY_IMAGE"), + STAR_MODERATOR("STAR_MODERATOR"), + STAR_OWNER("STAR_OWNER"), + STAR_RED_IMAGE("STAR_RED_IMAGE"), + STAR_YELLOW_IMAGE("STAR_YELLOW_IMAGE"), + STICKY_NOTE_IMAGE("STICKY_NOTE_IMAGE"), + TASK_DELETE_IMAGE("TASK_DELETE_IMAGE"), + TELEPHONE_24x24("TELEPHONE_24x24"), + TEXT_BOLD("TEXT_BOLD"), + TEXT_ITALIC("TEXT_ITALIC"), + TEXT_NORMAL("TEXT_NORMAL"), + TEXT_UNDERLINE("TEXT_UNDERLINE"), + TIME_LEFT("TIME_LEFT"), + TOOLBAR_BACKGROUND("TOOLBAR_BACKGROUND"), + TOOLBOX("TOOLBOX"), + TRAFFIC_LIGHT_IMAGE("TRAFFIC_LIGHT_IMAGE"), + TRANSFER_IMAGE_24x24("TRANSFER_IMAGE_24x24"), + TRANSPORT_ICON("TRANSPORT_ICON"), + TRAY_AWAY("TRAY_AWAY"), + TRAY_AWAY_LINUX("TRAY_AWAY_LINUX"), + TRAY_CONNECTING("TRAY_CONNECTING"), + TRAY_CONNECTING_LINUX("TRAY_CONNECTING_LINUX"), + TRAY_DND("TRAY_DND"), + TRAY_DND_LINUX("TRAY_DND_LINUX"), + TRAY_IMAGE("TRAY_IMAGE"), + TRAY_IMAGE_LINUX("TRAY_IMAGE_LINUX"), + TRAY_OFFLINE("TRAY_OFFLINE"), + TRAY_OFFLINE_LINUX("TRAY_OFFLINE_LINUX"), + TRAY_XAWAY("TRAY_XAWAY"), + TRAY_XAWAY_LINUX("TRAY_XAWAY_LINUX"), + TYPING_TRAY("TYPING_TRAY"), + TYPING_TRAY_LINUX("TYPING_TRAY_LINUX"), + UNBLOCK_CONTACT_16x16("UNBLOCK_CONTACT_16x16"), + UNRECOVERABLE_ERROR("UNRECOVERABLE_ERROR"), + UPLOAD_ICON("UPLOAD_ICON"), + USER1_32x32("USER1_32x32"), + USER1_ADD_16x16("USER1_ADD_16x16"), + USER1_BACK_16x16("USER1_BACK_16x16"), + USER1_MESSAGE_24x24("USER1_MESSAGE_24x24"), + USER_HEADSET_24x24("USER_HEADSET_24x24"), + VIEW("VIEW"), + VIEW_IMAGE("VIEW_IMAGE"), + WORKGROUP_QUEUE("WORKGROUP_QUEUE"), + XMPP_TRANSPORT_ACTIVE_IMAGE("XMPP_TRANSPORT_ACTIVE_IMAGE"), + XMPP_TRANSPORT_INACTIVE_IMAGE("XMPP_TRANSPORT_INACTIVE_IMAGE"), + YELLOW_BALL("YELLOW_BALL"), + YELLOW_FLAG_16x16("YELLOW_FLAG_16x16"), + ; + final String propertyName; + + Icon(String propertyName) { + this.propertyName = propertyName; + } + } + + public static final String APP_NAME = "APP_NAME"; + public static final String DUMMY_CONTACT_IMAGE = "DUMMY_CONTACT_IMAGE"; + public static final String EXECUTABLE_NAME = "EXECUTABLE_NAME"; + public static final String WELCOME = "WELCOME"; + + private static final Map iconsCache = new EnumMap<>(Icon.class); + + private static final ClassLoader cl = SparkRes.class.getClassLoader(); + + static { + prb = new Properties(); + try { + InputStream resourceAsStream = cl.getResourceAsStream("spark.properties"); + if (resourceAsStream != null) { + prb.load(resourceAsStream); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static String getString(String propertyName) { + String pluginString = PluginRes.getSparkRes(propertyName); + return pluginString != null ? pluginString : prb.getProperty(propertyName); + } + + public static ImageIcon getImageIcon(Icon imageName) { + ImageIcon cachedImageIcon = iconsCache.get(imageName); + if (cachedImageIcon != null) { + return cachedImageIcon; + } + try { + final String iconURI = getString(imageName.propertyName); + final URL imageURL = cl.getResource(iconURI); + if (imageURL != null) { + ImageIcon imageIcon = new ImageIcon(imageURL); + iconsCache.put(imageName, imageIcon); + return imageIcon; + } else { + Log.warning(imageName + " not found."); + } + } + catch (Exception e) { + Log.warning("Unable to load image " + imageName, e); + } + return null; + } + + public static URL getURL(String propertyName) { + URL pluginUrl = PluginRes.getSparkURL(propertyName); + return pluginUrl != null ? pluginUrl : cl.getResource(getString(propertyName)); + } + + public static void main(String[] args) { + + JFrame frame = new JFrame(); + frame.getContentPane().setLayout(new BorderLayout()); + + JEditorPane pane = new JEditorPane(); + frame.getContentPane().add(new JScrollPane(pane)); + + StringBuilder buf = new StringBuilder(); + Enumeration enumeration = (Enumeration) prb.propertyNames(); + while (enumeration.hasMoreElements()) { + String token = enumeration.nextElement(); + String value = prb.getProperty(token).toLowerCase(); + if (value.endsWith(".gif") || value.endsWith(".png") || value.endsWith(".jpg") || value.endsWith(".jpeg")) { +// SparkRes.getImageIcon(token); + SparkRes.getImageIcon(null); + } + String str = "public static final String " + token + " = \"" + token + "\";\n"; + buf.append(str); + } + + checkImageDir(); + pane.setText(buf.toString()); + frame.pack(); + frame.setVisible(true); + } + + private static void checkImageDir() { + File[] files = new File("c:\\code\\liveassistant\\client\\resources\\images").listFiles(); + final int no = files != null ? files.length : 0; + for (int i = 0; i < no; i++) { + try { + File imageFile = files[i]; + String name = imageFile.getName(); + + // Check to see if the name of the file exists + boolean exists = false; + Enumeration enumeration = (Enumeration) prb.propertyNames(); + while (enumeration.hasMoreElements()) { + String token = enumeration.nextElement(); + String value = prb.getProperty(token).toLowerCase(); + if (value.endsWith(name)) { + exists = true; + } + } + + if (!exists) { + Log.error(imageFile.getAbsolutePath() + " is not used."); + } + } catch (NullPointerException e) { + // TODO: Should we worry about this? + } + } + } + +} diff --git a/core/src/main/java/org/jivesoftware/resource/UTF8Control.java b/core/src/main/java/org/jivesoftware/resource/UTF8Control.java new file mode 100644 index 000000000..9e31ee6a3 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/resource/UTF8Control.java @@ -0,0 +1,45 @@ +package org.jivesoftware.resource; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.StandardCharsets; +import java.util.Locale; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +public class UTF8Control extends ResourceBundle.Control { + public ResourceBundle newBundle + (String baseName, Locale locale, String format, ClassLoader loader, boolean reload) + throws IllegalAccessException, InstantiationException, IOException + { + // The below is a copy of the default implementation. + String bundleName = toBundleName(baseName, locale); + String resourceName = toResourceName(bundleName, "properties"); + ResourceBundle bundle = null; + InputStream stream = null; + if (reload) { + URL url = loader.getResource(resourceName); + if (url != null) { + URLConnection connection = url.openConnection(); + if (connection != null) { + connection.setUseCaches(false); + stream = connection.getInputStream(); + } + } + } else { + stream = loader.getResourceAsStream(resourceName); + } + if (stream != null) { + try { + // Only this line is changed to make it to read properties files as UTF-8. + bundle = new PropertyResourceBundle(new InputStreamReader(stream, StandardCharsets.UTF_8)); + } finally { + stream.close(); + } + } + return bundle; + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ButtonFactory.java b/core/src/main/java/org/jivesoftware/spark/ButtonFactory.java new file mode 100644 index 000000000..1c25706c8 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ButtonFactory.java @@ -0,0 +1,112 @@ +/** + * Copyright (C) 2011 eZuce Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark; + +import java.net.URL; + +import javax.swing.ImageIcon; +import javax.swing.JLabel; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.ui.ChatRoomButton; +import org.jivesoftware.sparkimpl.plugin.emoticons.Emoticon; +import org.jivesoftware.sparkimpl.plugin.emoticons.EmoticonManager; + +public class ButtonFactory { + + private static final ButtonFactory instance = new ButtonFactory(); + + protected ButtonFactory() { + // nothing + } + + public static ButtonFactory getInstance() { + return instance; + } + + public ChatRoomButton createChatTranscriptButton() { + return new ChatRoomButton(SparkRes.getImageIcon(SparkRes.Icon.HISTORY_24x24_IMAGE)); + } + + public ChatRoomButton createSendFileButton() { + return new ChatRoomButton("", SparkRes.getImageIcon(SparkRes.Icon.SEND_FILE_24x24)); + } + + public ChatRoomButton createScreenshotButton() { + return new ChatRoomButton("", SparkRes.getImageIcon(SparkRes.Icon.PHOTO_IMAGE)); + } + + public ChatRoomButton createInviteConferenceButton() { + return new ChatRoomButton("", SparkRes.getImageIcon(SparkRes.Icon.CONFERENCE_IMAGE_24x24)); + } + + public RolloverButton createBuzzButton() { + return new RolloverButton(SparkRes.getImageIcon(SparkRes.Icon.BUZZ_IMAGE)); + } + + public RolloverButton createEmoticonButton() { + final EmoticonManager emoticonManager = EmoticonManager.getInstance(); + final String activeEmoticonSetName = emoticonManager.getActiveEmoticonSetName(); + final Emoticon smileEmoticon = emoticonManager.getEmoticon(activeEmoticonSetName, ":)"); + if (smileEmoticon != null) { + URL emotionURL = emoticonManager.getEmoticonURL(smileEmoticon); + ImageIcon icon = new ImageIcon(emotionURL); + return new RolloverButton(icon); + } + return new RolloverButton(":)"); + } + + public JLabel createDivider() { + return new JLabel(SparkRes.getImageIcon(SparkRes.Icon.DIVIDER_IMAGE)); + } + + public RolloverButton createSettingsButton() { + RolloverButton settings = new RolloverButton(SparkRes.getImageIcon(SparkRes.Icon.SETTINGS_IMAGE_16x16)); + settings.setToolTipText(Res.getString("title.configure.room")); + return settings; + } + + public RolloverButton createTemaButton() { + RolloverButton thema = new RolloverButton(SparkRes.getImageIcon(SparkRes.Icon.TYPING_TRAY)); + thema.setToolTipText(Res.getString("menuitem.change.subject")); + return thema; + } + + public RolloverButton createRegisterButton() { + RolloverButton register = new RolloverButton(SparkRes.getImageIcon(SparkRes.Icon.PEOPLE_IMAGE)); + register.setToolTipText(Res.getString("button.register").replace("&", "")); + return register; + } + + public RolloverButton createAlwaysOnTop(boolean isAlwaysOnTopActive) { + RolloverButton alwaysOnTopItem = new RolloverButton(); + if (isAlwaysOnTopActive) { + alwaysOnTopItem.setIcon(SparkRes.getImageIcon(SparkRes.Icon.FRAME_ALWAYS_ON_TOP_ACTIVE)); + } else { + alwaysOnTopItem.setIcon(SparkRes.getImageIcon(SparkRes.Icon.FRAME_ALWAYS_ON_TOP_DEACTIVE)); + } + + alwaysOnTopItem.setToolTipText(Res.getString("menuitem.always.on.top")); + return alwaysOnTopItem; + + } + + public ChatRoomButton createOtrButton() { + return new ChatRoomButton(); + } +} diff --git a/src/java/org/jivesoftware/spark/ChatAreaSendField.java b/core/src/main/java/org/jivesoftware/spark/ChatAreaSendField.java similarity index 96% rename from src/java/org/jivesoftware/spark/ChatAreaSendField.java rename to core/src/main/java/org/jivesoftware/spark/ChatAreaSendField.java index 0606c669f..1c22b8cd6 100644 --- a/src/java/org/jivesoftware/spark/ChatAreaSendField.java +++ b/core/src/main/java/org/jivesoftware/spark/ChatAreaSendField.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,8 +36,8 @@ */ public class ChatAreaSendField extends JPanel { private static final long serialVersionUID = 6226413259528399476L; - private ChatInputEditor textField; - private JButton button; + private final ChatInputEditor textField; + private final JButton button; /** * Creates a new IconTextField with Icon. diff --git a/core/src/main/java/org/jivesoftware/spark/ChatManager.java b/core/src/main/java/org/jivesoftware/spark/ChatManager.java new file mode 100644 index 000000000..ac8f4c3f5 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ChatManager.java @@ -0,0 +1,821 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark; + +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.chat2.Chat; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smackx.chatstates.ChatState; +import org.jivesoftware.smackx.chatstates.ChatStateListener; +import org.jivesoftware.smackx.chatstates.ChatStateManager; +import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jivesoftware.smackx.muc.MultiUserChatManager; +import org.jivesoftware.spark.component.tabbedPane.SparkTab; +import org.jivesoftware.spark.decorator.DefaultTabHandler; +import org.jivesoftware.spark.ui.*; +import org.jivesoftware.spark.ui.conferences.RoomInvitationListener; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.UIComponentRegistry; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.EntityJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Localpart; +import org.jxmpp.jid.parts.Resourcepart; + +import javax.swing.*; +import java.awt.*; +import java.util.*; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Handles the Chat Management of each individual Workspace. + * The ChatManager is responsible for the creation and removal of chat rooms, transcripts, transfers, and room invitations. + */ +public class ChatManager { + + private static ChatManager singleton; + private static final Object LOCK = new Object(); + + // Define Default Colors + public static final Color TO_COLOR = (Color)UIManager.get("User.foreground"); + public static final Color FROM_COLOR = (Color)UIManager.get("OtherUser.foreground"); + public static final Color NOTIFICATION_COLOR = (Color)UIManager.get("Notification.foreground"); + public static final Color ERROR_COLOR = (Color)UIManager.get("Error.foreground"); + + private final CopyOnWriteArrayList messageFilters = new CopyOnWriteArrayList<>(); + + private final CopyOnWriteArrayList globalMessageListeners = new CopyOnWriteArrayList<>(); + + private final CopyOnWriteArrayList invitationListeners = new CopyOnWriteArrayList<>(); + + private final CopyOnWriteArrayList interceptors = new CopyOnWriteArrayList<>(); + + private final CopyOnWriteArrayList sparkTabHandlers = new CopyOnWriteArrayList<>(); + + + private final ChatContainer chatContainer; + + private String conferenceService; + + private final CopyOnWriteArrayList contactItemHandlers = new CopyOnWriteArrayList<>(); + + private final Set typingNotificationList = new HashSet<>(); + + private final CopyOnWriteArrayList chatMessageHandlers = new CopyOnWriteArrayList<>(); + + /** + * The listener instance that we use to track chat states according to XEP-0085 + */ + private final SmackChatStateListener smackChatStateListener = new SmackChatStateListener(); + + /** + * Returns the singleton instance of ChatManager. + */ + public static ChatManager getInstance() { + synchronized (LOCK) { + if (null == singleton) { + ChatManager controller = new ChatManager(); + singleton = controller; + return controller; + } + } + return singleton; + } + + + /** + * Create a new instance of ChatManager. + */ + private ChatManager() { + chatContainer = UIComponentRegistry.createChatContainer(); + // Add Default Chat Room Decorator + addSparkTabHandler(new DefaultTabHandler()); + // Add a Message Handler + ChatStateManager chatStateManager = ChatStateManager.getInstance(SparkManager.getConnection()); + chatStateManager.addChatStateListener(smackChatStateListener); + } + + + /** + * Used to listen for rooms opening, closing or being activated (already opened, but tabbed to) + * + * @param listener the ChatRoomListener to add + */ + public void addChatRoomListener(ChatRoomListener listener) { + getChatContainer().addChatRoomListener(listener); + } + + /** + * Removes a listener + */ + public void removeChatRoomListener(ChatRoomListener listener) { + getChatContainer().removeChatRoomListener(listener); + } + + + /** + * Removes the personal 1 to 1 chat from the ChatFrame. + */ + public void removeChat(ChatRoom chatRoom) { + chatContainer.closeTab(chatRoom); + } + + + /** + * Returns all ChatRooms currently active. + */ + public ChatContainer getChatContainer() { + return chatContainer; + } + + public GroupChatRoom getGroupChat(EntityBareJid roomAddress) throws ChatNotFoundException { + if ( roomAddress == null ) { + throw new ChatNotFoundException(); + } + return getGroupChat(roomAddress.toString()); + } + + /** + * Returns the MultiUserChat associated with the specified roomName. + * + * @param roomName the name of the chat room. + * @return the MultiUserChat found for the roomName. + * @throws ChatNotFoundException thrown if no ChatRoom is found. + */ + public GroupChatRoom getGroupChat(String roomName) throws ChatNotFoundException { + for (ChatRoom chatRoom : getChatContainer().getChatRooms()) { + if (chatRoom instanceof GroupChatRoom) { + GroupChatRoom groupChat = (GroupChatRoom)chatRoom; + if (groupChat.getBareJid().equals(roomName)) { + return groupChat; + } + } + } + throw new ChatNotFoundException("Could not locate Group Chat Room - " + roomName); + } + + /** + * Creates and/or opens a chat room with the specified user. + * + * @param jid the jid of the user to chat with. + * @param nicknameCs the nickname to use for the user. + * @param title the title to use for the room. + * @return the newly created ChatRoom. + */ + public ChatRoom createChatRoom(EntityJid jid, CharSequence nicknameCs, CharSequence title) { + Resourcepart nickname = Resourcepart.fromOrThrowUnchecked(nicknameCs); + ChatRoom chatRoom; + try { + chatRoom = getChatContainer().getChatRoom(jid); + } + catch (ChatRoomNotFoundException e) { + chatRoom = UIComponentRegistry.createChatRoom(jid, nickname, title); + getChatContainer().addChatRoom(chatRoom); + } + return chatRoom; + } + + /** + * Returns the ChatRoom for the giving jid. If the ChatRoom is not found, + * a new ChatRoom will be created. + * + * @param bareJid the jid of the user to chat with. + * @param bareJid + * @return the ChatRoom. + */ + public ChatRoom getChatRoom(EntityBareJid bareJid) { + EntityBareJid jid = bareJid.asEntityBareJidOrThrow(); + ChatRoom chatRoom; + try { + chatRoom = getChatContainer().getChatRoom(jid); + } + catch (ChatRoomNotFoundException e) { + ContactList contactList = SparkManager.getWorkspace().getContactList(); + ContactItem item = contactList.getContactItemByJID(jid); + if (item != null) { + String nicknameString = item.getDisplayName(); + Resourcepart nickname = Resourcepart.fromOrThrowUnchecked(nicknameString); + chatRoom = UIComponentRegistry.createChatRoom(jid, nickname, nickname); + } + else { + // TODO Better nickname? + Resourcepart nickname = Resourcepart.EMPTY; + chatRoom = UIComponentRegistry.createChatRoom(jid, nickname, jid); + } + getChatContainer().addChatRoom(chatRoom); + } + + return chatRoom; + } + + /** + * Creates a new public Conference Room. + * + * @param roomName the name of the room. + * @param serviceName the service name to use (ex.conference.jivesoftware.com) + * @return the new ChatRoom created. If an error occurred, null will be returned. + */ + public ChatRoom createConferenceRoom(Localpart roomName, DomainBareJid serviceName) { + EntityBareJid roomAddress = JidCreate.entityBareFrom(roomName, serviceName); + final MultiUserChat chatRoom = SparkManager.getMucManager().getMultiUserChat( roomAddress); + + final GroupChatRoom room = UIComponentRegistry.createGroupChatRoom(chatRoom); + + try { + LocalPreferences pref = SettingsManager.getLocalPreferences(); + Resourcepart nickname = pref.getNickname(); + chatRoom.create(nickname).makeInstant(); + } + catch (XMPPException | SmackException | InterruptedException e1) { + Log.error("Unable to send conference room chat configuration form.", e1); + return null; + } + + getChatContainer().addChatRoom(room); + return room; + } + + /** + * Activate a chat room with the selected user. + * + * @param jidCs the jid of the user to chat with. + * @param nicknameString the nickname of the user. + */ + public void activateChat(final CharSequence jidCs, final String nicknameString) { + final Resourcepart nickname = Resourcepart.fromOrThrowUnchecked(nicknameString); + final EntityBareJid jid = JidCreate.entityBareFromUnescapedOrThrowUnchecked(jidCs); + + SwingWorker worker = new SwingWorker() { + final ChatManager chatManager = SparkManager.getChatManager(); + ChatRoom chatRoom; + + @Override + public Object construct() { + try { + Thread.sleep(10); + } + catch (InterruptedException e) { + Log.error("Error in activate chat.", e); + } + + ChatContainer chatRooms = chatManager.getChatContainer(); + try { + chatRoom = chatRooms.getChatRoom(jid); + } + catch (ChatRoomNotFoundException e) { + // Do nothing + } + return chatRoom; + } + + @Override + public void finished() { + if (chatRoom == null) { + chatRoom = UIComponentRegistry.createChatRoom(jid, nickname, nickname); + chatManager.getChatContainer().addChatRoom(chatRoom); + } + chatManager.getChatContainer().activateChatRoom(chatRoom); + } + }; + + worker.start(); + + } + + /** + * Checks if a ChatRoom exists. + * + * @param jid the jid of the user. + * @return true if the ChatRoom exists. + */ + public boolean chatRoomExists(String jid) { + try { + getChatContainer().getChatRoom(jid); + } + catch (ChatRoomNotFoundException e) { + return false; + } + return true; + } + + /** + * Adds a new MessageFilter. + * + * @param filter the MessageFilter. + */ + public void addMessageFilter(MessageFilter filter) { + messageFilters.addIfAbsent(filter); + } + + /** + * Removes a MessageFilter. + */ + public void removeMessageFilter(MessageFilter filter) { + messageFilters.remove(filter); + } + + /** + * Adds a new GlobalMessageListener. + */ + public void addGlobalMessageListener(GlobalMessageListener listener) { + globalMessageListeners.addIfAbsent(listener); + } + + /** + * Removes a GlobalMessageListener. + * + * @param listener the listener. + */ + public void removeGlobalMessageListener(GlobalMessageListener listener) { + globalMessageListeners.remove(listener); + } + + /** + * Notifies all GlobalMessageListeners of a new incoming message. + * + * @param chatRoom the ChatRoom where the message was sent to. + * @param message the Message + */ + public void fireGlobalMessageReceivedListeners(ChatRoom chatRoom, Message message ) + { + for ( GlobalMessageListener listener : globalMessageListeners ) + { + try + { + listener.messageReceived( chatRoom, message ); + } + catch ( Exception e ) + { + Log.error( "A GlobalMessageListener ('" + listener + "') threw an exception while processing an incoming chat message (from '" + message.getFrom() + "') in a chat room ('" + chatRoom + "').", e ); + } + } + } + + /** + * Notifies all GlobalMessageListeners of a new message sent. + * + * @param chatRoom the ChatRoom where the message was sent from. + * @param message the Message sent. + */ + public void fireGlobalMessageSentListeners( ChatRoom chatRoom, Message message ) + { + for ( GlobalMessageListener listener : globalMessageListeners ) + { + try + { + listener.messageSent( chatRoom, message ); + } + catch ( Exception e ) + { + Log.error( "A GlobalMessageListener ('" + listener + "') threw an exception while processing an outgoing chat message (to '" + message.getTo() + "') in a chat room ('" + chatRoom + "').", e ); + } + } + } + + /** + * Filters all incoming messages. + * + * @param room the room the message belongs to. + * @param messageBuilder the message to filter. + */ + public void filterIncomingMessage( ChatRoom room, MessageBuilder messageBuilder ) + { + try + { + // TODO This probably does not belong here (but in a filter?) + cancelledNotification( messageBuilder.getFrom(), ChatState.paused ); + } + catch ( Exception e ) + { + Log.error( e ); + } + + for ( final MessageFilter filter : messageFilters ) + { + try + { + filter.filterIncoming( room, messageBuilder ); + } + catch ( Exception e ) + { + Log.error( "A MessageFilter ('" + filter + "') threw an exception while processing an incoming chat message (from '" + messageBuilder.getFrom() + "') in a chat room ('" + room + "').", e ); + } + } + } + + /** + * Notifies all MessageFilters about a new outgoing message. + * + * @param room the ChatRoom the message belongs too. + * @param messageBuilder the Message being sent. + */ + public void filterOutgoingMessage(ChatRoom room, MessageBuilder messageBuilder ) + { + for ( final MessageFilter filter : messageFilters ) + { + try + { + filter.filterOutgoing( room, messageBuilder ); + } + catch ( Exception e ) + { + Log.error( "A MessageFilter ('" + filter + "') threw an exception while processing an outgoing chat message (from '" + messageBuilder.getFrom() + "') in a chat room ('" + room + "').", e ); + } + } + } + + /** + * Adds a RoomInvitationListener. A RoomInvitationListener is + */ + public void addInvitationListener(RoomInvitationListener listener) { + invitationListeners.addIfAbsent(listener); + } + + /** + * Removes a RoomInvitationListener. + */ + public void removeInvitationListener(RoomInvitationListener listener) { + invitationListeners.remove(listener); + } + + /** + * Returns all registered RoomInvitationListeners. + */ + public Collection getInvitationListeners() { + return Collections.unmodifiableCollection(invitationListeners); + } + + /** + * Returns the default conference service. (ex. conference.jivesoftware.com) + * + * @return the default conference service to interact with MUC. + */ + public String getDefaultConferenceService() { + if (conferenceService == null) { + try { + final MultiUserChatManager multiUserChatManager = SparkManager.getMucManager(); + List col = multiUserChatManager.getMucServiceDomains(); + if (col.size() > 0) { + conferenceService = col.iterator().next().toString(); + } + } + catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + } + } + return conferenceService; + } + + /** + * Adds a new ContactItemHandler. + */ + public void addContactItemHandler(ContactItemHandler handler) { + contactItemHandlers.addIfAbsent(handler); + } + + public void addChatMessageHandler(ChatMessageHandler handler) { + chatMessageHandlers.addIfAbsent(handler); + } + + public void removeChatMessageHandler(ChatMessageHandler handler) { + chatMessageHandlers.remove(handler); + } + + /** + * Removes a ContactItemHandler. + */ + public void removeContactItemHandler(ContactItemHandler handler) { + contactItemHandlers.remove(handler); + } + + public void fireMessageReceived( Message message ) + { + for ( ChatMessageHandler handler : chatMessageHandlers ) + { + try + { + handler.messageReceived( message ); + } + catch ( Exception e ) + { + Log.error( "A ChatMessageHandler ('" + handler + "') threw an exception while processing this message: " + message, e ); + } + } + } + + /** + * Notifies all ContactItemHandlers of presence changes. + * + * @param item the ContactItem where the presence changed. + * @param presence the new presence. + * @return true if it was handled. + */ + public boolean fireContactItemPresenceChanged( ContactItem item, Presence presence ) + { + for ( ContactItemHandler handler : contactItemHandlers ) + { + try + { + if ( handler.handlePresence( item, presence ) ) + { + return true; + } + } + catch ( Exception e ) + { + Log.error( "A ContactItemHandler ('" + handler + "') threw an exception while processing a presence change (ContactItem: '" + item + "', presence: [" + presence + "])", e ); + } + } + return false; + } + + /** + * Notifies all ContactItemHandlers that a ContactItem was double-clicked. + * + * @param item the ContactItem that was double-clicked. + * @return true if the event was intercepted and handled. + */ + public boolean fireContactItemDoubleClicked( ContactItem item ) + { + for ( ContactItemHandler handler : contactItemHandlers ) + { + try + { + if ( handler.handleDoubleClick( item ) ) + { + return true; + } + } + catch ( Exception e ) + { + Log.error( "A ContactItemHandler ('" + handler + "') threw an exception while processing a double click on ContactItem: '" + item + "'.", e ); + } + } + return false; + } + + /** + * Returns the icon from a ContactItemHandler. + * + * @param jid the jid. + */ + public Icon getIconForContactHandler( String jid ) + { + BareJid bareJid = JidCreate.bareFromOrThrowUnchecked(jid); + for ( ContactItemHandler handler : contactItemHandlers ) + { + try + { + Icon icon = handler.getIcon( bareJid ); + if ( icon != null ) + { + return icon; + } + } + catch ( Exception e ) + { + Log.error( "A ContactItemHandler ('" + handler + "') threw an exception while processing an icon request for: '" + jid + "'.", e ); + } + } + + return null; + } + + /** + * Returns the icon to use in the tab. + * + * @param presence the presence. + */ + public Icon getTabIconForContactHandler( Presence presence ) + { + for ( ContactItemHandler handler : contactItemHandlers ) + { + try + { + Icon icon = handler.getTabIcon( presence ); + if ( icon != null ) + { + return icon; + } + } + catch ( Exception e ) + { + Log.error( "A ContactItemHandler ('" + handler + "') threw an exception while processing a tab icon request for: '" + presence + "'.", e ); + } + } + return null; + } + + public void composingNotification(final Jid from) { + SwingUtilities.invokeLater( () -> { + final ContactList contactList = SparkManager.getWorkspace().getContactList(); + + ChatRoom chatRoom; + try { + chatRoom = getChatContainer().getChatRoom( from.asBareJid() ); + if (chatRoom instanceof ChatRoomImpl) { + typingNotificationList.add(chatRoom); + // Notify Decorators + notifySparkTabHandlers(chatRoom); + ((ChatRoomImpl)chatRoom).notifyChatStateChange(ChatState.composing); + } + } + catch (ChatRoomNotFoundException e) { + // Do nothing + } + contactList.setIconFor(from, SparkRes.getImageIcon(SparkRes.Icon.SMALL_MESSAGE_EDIT_IMAGE)); + } ); + } + + public void cancelledNotification(final Jid from, final ChatState state) { + SwingUtilities.invokeLater( () -> { + ContactList contactList = SparkManager.getWorkspace().getContactList(); + + ChatRoom chatRoom; + try { + chatRoom = getChatContainer().getChatRoom(from.asBareJid()); + if (chatRoom instanceof ChatRoomImpl) { + typingNotificationList.remove(chatRoom); + // Notify Decorators + notifySparkTabHandlers(chatRoom); + ((ChatRoomImpl)chatRoom).notifyChatStateChange(state); + } + } + catch (ChatRoomNotFoundException e) { + // Do nothing + } + contactList.useDefaults(from); + } ); + } + + /** + * Adds a room where the user is typing. + * + * @param chatRoom the room where the user is typing. + */ + public void addTypingNotification(ChatRoom chatRoom) { + typingNotificationList.add(chatRoom); + } + + /** + * Removes a room from the typing notification list. + * + * @param chatRoom the room to remove. + */ + public void removeTypingNotification(ChatRoom chatRoom) { + typingNotificationList.remove(chatRoom); + } + + /** + * Returns true if the ChatRoom state is in typing mode. + * + * @param chatRoom the ChatRoom to check. + */ + public boolean containsTypingNotification(ChatRoom chatRoom) { + return typingNotificationList.contains(chatRoom); + } + + /** + * Returns true if the room is "stale". A stale room is a room that has + * not been active for a specific amount of time. + * + * @param chatRoom the ChatRoom. + */ + public boolean isStaleRoom(ChatRoom chatRoom) { + // Check if the room is stale + return chatContainer.getStaleChatRooms().contains(chatRoom); + } + + /** + * Adds a TranscriptWindowInterceptor. + * + * @param interceptor the interceptor. + */ + public void addTranscriptWindowInterceptor(TranscriptWindowInterceptor interceptor) { + interceptors.addIfAbsent(interceptor); + } + + /** + * Removes a TranscriptWindowInterceptor. + * + * @param interceptor the interceptor. + */ + public void removeTranscriptWindowInterceptor(TranscriptWindowInterceptor interceptor) { + interceptors.remove(interceptor); + } + + /** + * Returns the list of TranscriptWindowInterceptors. + */ + public Collection getTranscriptWindowInterceptors() { + return interceptors; + } + + /** + * Adds a new ContainerDecorator. The ContainerDecorator will be added to the top of the stack and will therefore + * take priority on notification calls. If all decorators return false, the DefaultChatRoomDecorator will be used. + * + * @param decorator the decorator to add. + */ + public void addSparkTabHandler(SparkTabHandler decorator) { + sparkTabHandlers.add(0, decorator); + } + + /** + * Removes a ContainerDecorator + * + * @param decorator the decorator to remove. + */ + public void removeSparkTabHandler(SparkTabHandler decorator) { + sparkTabHandlers.remove(decorator); + } + + /** + * Notifies all ContainerDecorator + * + * @param component the component within the tab. + */ + public void notifySparkTabHandlers( Component component ) + { + final SparkTab tab = chatContainer.getTabContainingComponent( component ); + if ( tab == null ) + { + return; + } + boolean isChatFrameInFocus = getChatContainer().getChatFrame().isInFocus(); + boolean isSelectedTab = getChatContainer().getSelectedComponent() == component; + for ( SparkTabHandler decorator : sparkTabHandlers ) + { + try + { + boolean isHandled = decorator.isTabHandled( tab, component, isSelectedTab, isChatFrameInFocus ); + if ( isHandled ) + { + tab.validateTab(); + return; + } + } + catch ( Exception e ) + { + Log.error( "A SparkTabHandler ('" + decorator + "') threw an exception.", e ); + } + } + } + + /** + * Returns all selected users in the ContactList. + * + * @return all selected ContactItem in the ContactList. + */ + public Collection getSelectedContactItems() { + final ContactList contactList = SparkManager.getWorkspace().getContactList(); + return contactList.getSelectedUsers(); + } + + /** + * The listener that we use to track chat state notifications according to XEP-0085. + */ + private class SmackChatStateListener implements ChatStateListener { + /** + * Called by smack when the state of a chat changes. + * + * @param chat the chat that is concerned by this event. + * @param state the new state of the chat. + */ + @Override + public void stateChanged(Chat chat, ChatState state, Message message) { + Jid participant = chat.getXmppAddressOfChatPartner(); + if (ChatState.composing.equals(state)) { + composingNotification(participant); + } else { + cancelledNotification(participant, state); + } + } + } +} diff --git a/src/java/org/jivesoftware/spark/ChatMessageHandler.java b/core/src/main/java/org/jivesoftware/spark/ChatMessageHandler.java similarity index 100% rename from src/java/org/jivesoftware/spark/ChatMessageHandler.java rename to core/src/main/java/org/jivesoftware/spark/ChatMessageHandler.java diff --git a/src/java/org/jivesoftware/spark/ChatNotFoundException.java b/core/src/main/java/org/jivesoftware/spark/ChatNotFoundException.java similarity index 95% rename from src/java/org/jivesoftware/spark/ChatNotFoundException.java rename to core/src/main/java/org/jivesoftware/spark/ChatNotFoundException.java index 4ae2730a3..c3fcba1fd 100644 --- a/src/java/org/jivesoftware/spark/ChatNotFoundException.java +++ b/core/src/main/java/org/jivesoftware/spark/ChatNotFoundException.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/spark/DataManager.java b/core/src/main/java/org/jivesoftware/spark/DataManager.java similarity index 90% rename from src/java/org/jivesoftware/spark/DataManager.java rename to core/src/main/java/org/jivesoftware/spark/DataManager.java index 18602c71f..7a9bc5114 100644 --- a/src/java/org/jivesoftware/spark/DataManager.java +++ b/core/src/main/java/org/jivesoftware/spark/DataManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,15 +18,14 @@ import org.jivesoftware.spark.plugin.MetadataListener; import org.jivesoftware.spark.ui.ChatRoom; -import java.util.ArrayList; -import java.util.List; import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; /** * Allows a mechanism to associated data with chat rooms. */ public class DataManager { - private List metadataListeners = new ArrayList<>(); + private final CopyOnWriteArrayList metadataListeners = new CopyOnWriteArrayList<>(); private static DataManager singleton; private static final Object LOCK = new Object(); @@ -66,7 +61,7 @@ private DataManager() { // Allows for more associated data to individual chat rooms. public void addMetadataListener(MetadataListener listener) { - metadataListeners.add(listener); + metadataListeners.addIfAbsent(listener); } public void removeMetadataListener(MetadataListener listener) { diff --git a/core/src/main/java/org/jivesoftware/spark/Event.java b/core/src/main/java/org/jivesoftware/spark/Event.java new file mode 100644 index 000000000..7cdfe09c7 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/Event.java @@ -0,0 +1,12 @@ +package org.jivesoftware.spark; + +/** + * Notification events + */ +public enum Event { + CHAT_REQUEST, + INCOMING_INVITATION, + MSG_INCOMING, + MSG_OUTCOMING, + STATUS_OFFLINE, +} diff --git a/src/java/org/jivesoftware/spark/NativeHandler.java b/core/src/main/java/org/jivesoftware/spark/NativeHandler.java similarity index 96% rename from src/java/org/jivesoftware/spark/NativeHandler.java rename to core/src/main/java/org/jivesoftware/spark/NativeHandler.java index 7992c1458..49d961b0b 100644 --- a/src/java/org/jivesoftware/spark/NativeHandler.java +++ b/core/src/main/java/org/jivesoftware/spark/NativeHandler.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/spark/NativeManager.java b/core/src/main/java/org/jivesoftware/spark/NativeManager.java similarity index 96% rename from src/java/org/jivesoftware/spark/NativeManager.java rename to core/src/main/java/org/jivesoftware/spark/NativeManager.java index 2e2172554..e11d449e2 100644 --- a/src/java/org/jivesoftware/spark/NativeManager.java +++ b/core/src/main/java/org/jivesoftware/spark/NativeManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,7 +29,7 @@ */ public class NativeManager { - private List nativeHandlers = new ArrayList<>(); + private final List nativeHandlers = new ArrayList<>(); public NativeManager() { diff --git a/core/src/main/java/org/jivesoftware/spark/PluginManager.java b/core/src/main/java/org/jivesoftware/spark/PluginManager.java new file mode 100644 index 000000000..3c55a1f09 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/PluginManager.java @@ -0,0 +1,1104 @@ +/* + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.Node; +import org.dom4j.io.SAXReader; +import org.jivesoftware.MainWindowListener; +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Default; +import org.jivesoftware.spark.PluginRes.ResourceType; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.plugin.PluginClassLoader; +import org.jivesoftware.spark.plugin.PluginDependency; +import org.jivesoftware.spark.plugin.PublicPlugin; +import org.jivesoftware.spark.util.StringUtils; +import org.jivesoftware.spark.util.URLFileSystem; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.JiveInfo; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import java.awt.*; +import java.io.*; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.*; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import static org.jivesoftware.sparkimpl.plugin.InternalPlugins.getInternalPlugins; + +/** + * This manager is responsible for the loading of all Plugins and Workspaces within the Spark environment. + * + * @author Derek DeMoro + */ +public class PluginManager implements MainWindowListener +{ + public static final Map INCOMPATIBLE_PLUGINS = Map.of( + normalizePluginName("OTR Plugin"), "0.4 Beta" + ); + + private final List plugins = new ArrayList<>(); + + private final List publicPlugins = new CopyOnWriteArrayList<>(); + private static PluginManager singleton; + + /** + * The root Plugins Directory. + */ + public static File PLUGINS_DIRECTORY = new File( Spark.getBinDirectory().getParent(), "plugins" ).getAbsoluteFile(); + public static File PROFILE_PLUGINS_DIRECTORY = new File( Spark.getLogDirectory().getParentFile(), "plugins" ).getAbsoluteFile(); + + private PluginClassLoader classLoader; + + private final Collection _blacklistPlugins; + + /** + * Returns the singleton instance of PluginManager, creating it if necessary. + * + * @return the singleton instance of PluginManager (never null). + */ + public synchronized static PluginManager getInstance() + { + if ( null == singleton ) + { + singleton = new PluginManager(); + } + return singleton; + } + + private PluginManager() + { + try + { + PLUGINS_DIRECTORY = new File( Spark.getBinDirectory().getParentFile(), "plugins" ).getCanonicalFile(); + } + catch ( IOException e ) + { + Log.error( e ); + } + + // Do not use deployable plugins if not installed. + if ( System.getProperty( "plugin" ) == null ) + { + movePlugins(); + } + + // Create the extension directory if one does not exist. + if ( !PLUGINS_DIRECTORY.exists() ) + { + PLUGINS_DIRECTORY.mkdirs(); + } + Log.debug("Loading plugins from: " + PLUGINS_DIRECTORY.getAbsolutePath()); + + _blacklistPlugins = Default.getPluginBlacklist(); + } + + private void movePlugins() + { + // Current Plugin directory + File newPlugins = PROFILE_PLUGINS_DIRECTORY; + newPlugins.mkdirs(); + deleteOldPlugins( newPlugins ); + deletePluginIfNotExistInInstallFolder( newPlugins ); + + File[] files = PLUGINS_DIRECTORY.listFiles(); + if ( files != null ) + { + for (File file : files) { + if (file.isFile()) { + // Copy over + File newFile = new File(newPlugins, file.getName()); + + if (newFile.lastModified() >= file.lastModified()) { + continue; + } + + try { + URLFileSystem.copy(file.toURI().toURL(), newFile); + } catch (IOException e) { + Log.error(e); + } + } + } + } + + PLUGINS_DIRECTORY = newPlugins; + } + + /** + * Deletes Plugins in pathToSearch that have a different md5-hash than its correspondant in install\spark\plugins\ + */ + private void deleteOldPlugins( File pathToSearch ) + { + final String installPath = Spark.getBinDirectory().getParentFile() + File.separator + "plugins" + File.separator; + final File[] files = new File( installPath ).listFiles(); + final List installerFiles; + if ( files == null ) + { + installerFiles = Collections.emptyList(); + } + else + { + installerFiles = Arrays.asList( files ); + } + + final File[] installedPlugins = pathToSearch.listFiles( File::isDirectory ); + if ( installedPlugins == null ) + { + return; + } + + for ( final File file : installedPlugins ) + { + final File jarFile = new File( pathToSearch, file.getName() + ".jar" ); + if ( !jarFile.exists() ) + { + uninstall( file ); + } + else + { + try + { + final File f = new File( installPath + jarFile.getName() ); + // Compare old and new files by checksums + if ( installerFiles.contains( f ) ) + { + final String oldFile = StringUtils.getMD5Checksum( jarFile.getAbsolutePath() ); + final String newFile = StringUtils.getMD5Checksum( f.getAbsolutePath() ); + if ( !oldFile.equals( newFile ) ) + { + Log.debug( "deleting: " + file.getAbsolutePath() + "," + jarFile.getAbsolutePath() ); + uninstall( file ); + jarFile.delete(); + } + } + } + catch ( Exception e ) + { + Log.error( "No such file", e ); + } + } + } + } + + /** + * Deletes Plugins in pathToSearch which doesn't exist in install\spark\plugins\ + */ + private void deletePluginIfNotExistInInstallFolder(File pathToSearch) + { + final File[] files = new File( PLUGINS_DIRECTORY.toString() ).listFiles(); + Set installerFiles; + if ( files == null ) + { + installerFiles = Collections.emptySet(); + } + else + { + installerFiles = new TreeSet<>(); + for (File file : files) { + installerFiles.add(file.getName()); + installerFiles.add(file.getName().split("\\.")[0]); + } + } + + final File[] installedPlugins = pathToSearch.listFiles(); + if ( installedPlugins == null ) + { + return; + } + for(File plugin : installedPlugins){ + if(!installerFiles.contains(plugin.getName())){ + uninstall(plugin); + } + } + } + + /** + * Loads all {@link Plugin} from the agent plugins.xml and extension lib. + */ + public void loadPlugins() + { + // Delete all old plugins + File[] oldFiles = PLUGINS_DIRECTORY.listFiles(); + if ( oldFiles != null ) + { + for ( File file : oldFiles ) + { + if ( file.isDirectory() ) + { + // Check to see if it has an associated .jar + File jarFile = new File( PLUGINS_DIRECTORY, file.getName() + ".jar" ); + if ( !jarFile.exists() ) + { + uninstall( file ); + } + } + } + } + + updateClasspath(); + + loadInternalPlugins(); + + // Load extension plugins + loadPublicPlugins(); + + // For development purposes, load the plugin specified by -Dplugin=... + String plugin = System.getProperty( "plugin" ); + if ( plugin != null ) + { + final StringTokenizer st = new StringTokenizer( plugin, ",", false ); + while ( st.hasMoreTokens() ) + { + String token = st.nextToken(); + File pluginXML = new File( token ); + loadPublicPlugin( pluginXML.getParentFile() ); + } + } + + loadPluginResources(); + } + + private boolean hasDependencies( File pluginFile ) + { + SAXReader saxReader = SAXReader.createDefault(); + try + { + final Document pluginXML = saxReader.read( pluginFile ); + final List dependencies = pluginXML.selectNodes( "plugin/depends/plugin" ); + return dependencies != null && !dependencies.isEmpty(); + } + catch ( DocumentException e ) + { + Log.error( "Unable to read plugin dependencies from " + pluginFile, e ); + return false; + } + } + + static String normalizePluginName( String value ) + { + return value.replaceAll( "[^0-9a-zA-Z]", "" ).toLowerCase(); + } + + /** + * Loads public plugins. + * + * @param pluginDir the directory of the expanded public plugin. + * @return the new Plugin model for the Public Plugin. + */ + private Plugin loadPublicPlugin( File pluginDir ) + { + File pluginFile = new File( pluginDir, "plugin.xml" ); + SAXReader saxReader = SAXReader.createDefault(); + Document pluginXML = null; + try + { + pluginXML = saxReader.read( pluginFile ); + } + catch ( DocumentException e ) + { + Log.error( "Unable to read plugin XML file from " + pluginDir, e ); + return null; + } + + List plugins = pluginXML.selectNodes( "/plugin" ); + for ( Node plugin : plugins ) + { + PublicPlugin publicPlugin = new PublicPlugin(); + + String clazz = null; + String name; + String minVersion; + String version; + + try + { + name = plugin.selectSingleNode( "name" ) != null ? plugin.selectSingleNode( "name" ).getText().trim() : null; + clazz = plugin.selectSingleNode( "class" ) != null ? plugin.selectSingleNode( "class" ).getText().trim() : null; + version = plugin.selectSingleNode( "version" ) != null ? plugin.selectSingleNode( "version" ).getText().trim() : null; + + try + { + String lower = normalizePluginName( name ); + // Don't load the plugin if it's known to be incompatible with this version of Spark. + if ( INCOMPATIBLE_PLUGINS.containsKey( lower ) && INCOMPATIBLE_PLUGINS.get( lower ).compareTo( version ) >= 0 ) { + Log.warning( "Not loading plugin " + name + " (version " + version + ") as it is incompatible with this version of Spark." ); + return null; + } + // Don't load the plugin if it's on the Blacklist + if ( _blacklistPlugins.contains( lower ) || _blacklistPlugins.contains( clazz ) + || SettingsManager.getLocalPreferences().getDeactivatedPlugins().contains( name ) ) + { + Log.warning( "Not loading plugin " + name + " as it is blacklisted." ); + return null; + } + } + catch ( Exception e ) + { + Log.warning( "An exception occurred while checking the plugin blacklist for " + name, e ); + return null; + } + + // Check for a minimum version of Spark + try + { + minVersion = plugin.selectSingleNode( "minSparkVersion" ) != null ? plugin.selectSingleNode( "minSparkVersion" ).getText().trim() : ""; + + String buildNumber = JiveInfo.getVersion(); + boolean ok = buildNumber.compareTo( minVersion ) >= 0; + + if ( !ok ) + { + Log.warning( "Not loading plugin " + name + " as it is not supported by Spark version." ); + return null; + } + } + catch ( Exception e ) + { + Log.error( "Unable to load plugin " + name + " due to missing -Tag in plugin.xml." ); + return null; + } + + // Check for minimum Java version + try + { + Node nodeJavaVersion = plugin.selectSingleNode("java"); + final String pluginMinVersion = nodeJavaVersion != null ? nodeJavaVersion.getText().trim() : ""; + final int jv = !pluginMinVersion.isEmpty() ? StringUtils.getJavaMajorVersion(pluginMinVersion) : 11; + final int mv = StringUtils.getJavaMajorVersion( System.getProperty( "java.version" ) ); + + boolean ok = ( mv >= jv ); + + if ( !ok ) + { + Log.error( "Unable to load plugin " + name +" due to old JavaVersion.\n" + + "It Requires " + pluginMinVersion + + " you have " + System.getProperty( "java.version" ) ); + return null; + } + + } + catch ( NullPointerException e ) + { + Log.warning( "Plugin " + name + " has no -Tag, consider getting a newer Version" ); + } + + // set dependencies + try + { + List dependencies = plugin.selectNodes( "depends/plugin" ); + for ( Node depend1 : dependencies ) + { + Element depend = (Element) depend1; + PluginDependency dependency = new PluginDependency(); + dependency.setVersion( depend.selectSingleNode( "version" ).getText() ); + dependency.setName( depend.selectSingleNode( "name" ).getText() ); + publicPlugin.addDependency( dependency ); + } + } + catch ( Exception e ) + { + Log.warning( "An exception occurred during the setting of dependencies while loading plugin " + name, e ); + } + + // Do operating system check. + boolean operatingSystemOK = isOperatingSystemOK( plugin ); + if ( !operatingSystemOK ) + { + return null; + } + + publicPlugin.setPluginClass( clazz ); + publicPlugin.setName( name ); + + try + { + publicPlugin.setVersion( version ); + + String author = plugin.selectSingleNode( "author" ) != null ? plugin.selectSingleNode( "author" ).getText() : null; + publicPlugin.setAuthor( author ); + + String email = plugin.selectSingleNode( "email" ) != null ? plugin.selectSingleNode( "email" ).getText() : null; + publicPlugin.setEmail( email ); + + String description = plugin.selectSingleNode( "description" ) != null ? plugin.selectSingleNode( "description" ).getText() : null; + publicPlugin.setDescription( description ); + + String homePage = plugin.selectSingleNode( "homePage" ) != null ? plugin.selectSingleNode( "homePage" ).getText() : null; + publicPlugin.setHomePage( homePage ); + } + catch ( Exception e ) + { + Log.debug( "An ignorable exception occurred while loading plugin " + name + ": " + e.getMessage() ); + } + + try + { + Class pluginType = getParentClassLoader().loadClass( clazz ).asSubclass(Plugin.class); + Plugin pluginInstance = pluginType.getDeclaredConstructor().newInstance(); + Log.debug( name + " has been loaded." ); + publicPlugin.setPluginDir( pluginDir ); + publicPlugins.add( publicPlugin ); + + registerPlugin(pluginInstance); + return pluginInstance; + } + catch ( Throwable e ) + { + Log.error( "Unable to load plugin " + clazz + ".", e ); + } + } + catch ( Exception ex ) + { + Log.error( "Unable to load plugin " + clazz + ".", ex ); + } + } + return null; + } + + /** + * Loads an internal plugin. + */ + private void loadInternalPlugins() { + for (PublicPlugin plugin : getInternalPlugins()) { + EventQueue.invokeLater(() -> { + try { + Class pluginType = Class.forName(plugin.getPluginClass()).asSubclass(Plugin.class); + Plugin pluginInstance = pluginType.getDeclaredConstructor().newInstance(); + Log.debug(plugin.getName() + " has been loaded. Internal plugin."); + registerPlugin(pluginInstance); + } catch (Throwable ex) { + Log.error("Unable to load plugin " + plugin.getPluginClass(), ex); + } + }); + } + } + + private void updateClasspath() + { + try + { + classLoader = new PluginClassLoader( getParentClassLoader(), PLUGINS_DIRECTORY ); + PluginRes.setClassLoader( classLoader ); + } + catch ( MalformedURLException e ) + { + Log.error( "Error updating classpath.", e ); + } + Thread.currentThread().setContextClassLoader( classLoader ); + } + + private void loadPluginResources( String resourceName, ResourceType type ) + { + try + { + PropertyResourceBundle prbPlugin = (PropertyResourceBundle) ResourceBundle.getBundle( resourceName, Locale.getDefault(), classLoader ); + for ( String key : prbPlugin.keySet() ) + { + PluginRes.putRes( key, prbPlugin.getString( key ), type ); + } + } + catch ( Exception ex ) + { + Log.debug( resourceName + " is not overwritten in plugin " ); + } + } + + /** + * Loads property resources from spark.properties, default.properties, spark_i18n.properties (properly localized) + * located in a plugin's jar, if any In case the plugin contains preferences.properties, plugin specific defaults will + * be loaded instead of spark defaults for preferences This method is called right after all plugins are loaded, + * specifically after plugins class loader is initialized and plugins jars are loaded in classpath + */ + private void loadPluginResources() + { + loadPluginResources( "spark", ResourceType.SPARK ); + loadPluginResources( "default", ResourceType.DEFAULT ); + loadPluginResources( "preferences", ResourceType.PREFERENCES ); + loadPluginResources( "spark_i18n", ResourceType.I18N ); + } + + /** + * Returns the plugin classloader. + * + * @return the plugin classloader. + */ + public ClassLoader getPluginClassLoader() + { + return classLoader; + } + + /** + * Registers a plugin. + * + * @param plugin the plugin to register. + */ + public void registerPlugin( Plugin plugin ) + { + plugins.add( plugin ); + } + + /** + * Removes a plugin from the plugin list. + * + * @param plugin the plugin to remove. + */ + public void removePlugin( Plugin plugin ) + { + plugins.remove( plugin ); + } + + /** + * Returns a Collection of Plugins. + */ + public Collection getPlugins() + { + return plugins; + } + + /** + * Returns the instance of the plugin class initialized during startup. + * + * @param communicatorPlugin the plugin to find. + */ + public Plugin getPlugin( Class communicatorPlugin ) + { + for ( Plugin plugin : getPlugins() ) + { + if ( plugin.getClass() == communicatorPlugin ) + { + return plugin; + } + } + return null; + } + + /** + * Loads and initializes all Plugins. + * + * @see Plugin + */ + public void initializePlugins() + { + try + { + Log.debug("Start plugin dependency check"); + int j; + boolean dependencyFound; + + // Dependency check + for ( int i = 0; i < publicPlugins.size(); i++ ) + { + // if dependencies are available, check these + PublicPlugin publicPlugin = publicPlugins.get(i); + if (!publicPlugin.getDependency().isEmpty()) + { + List dependencies = publicPlugin.getDependency(); + + // go through all dependencies + for ( PluginDependency dependency : dependencies ) + { + j = 0; + dependencyFound = false; + + // look for the specific plugin + for ( PublicPlugin plugin : publicPlugins ) + { + if ( plugin.getName() != null && plugin.getName().equals( dependency.getName() ) ) + { + // if the version is compatible then reorder + if ( dependency.compareVersion( plugin.getVersion() ) ) + { + dependencyFound = true; + + // when the depended Plugin hadn't been installed yet + if ( j > i ) + { + // find the position of plugins-List because it has more entries + int counter = 0, x = 0, z = 0; + for ( Plugin plug : plugins ) + { + // find the position of the aim-object + if ( plug.getClass().toString().substring( 6 ).equals( publicPlugins.get( j ).getPluginClass() ) ) + { + x = counter; + } + // find the change-position + else if ( plug.getClass().toString().substring( 6 ).equals( publicPlugin.getPluginClass() ) ) + { + z = counter; + } + counter++; + } + + // change the order + publicPlugins.add( i, publicPlugins.get( j ) ); + publicPlugins.remove( j + 1 ); + + plugins.add( z, plugins.get( x ) ); + plugins.remove( x + 1 ); + + // start again, to check the other dependencies + i--; + } + } + // else don't load the plugin and show an error + else + { + Log.error( "Depended Plugin " + dependency.getName() + " hasn't the right version (" + dependency.getVersion() + "<>" + plugin.getVersion() ); + } + break; + } + j++; + } + + // If the depended Plugin wasn't found, then show error. + if ( !dependencyFound ) + { + Log.error( "Depended Plugin " + dependency.getName() + " is missing for the Plugin " + publicPlugin.getName() ); + + // find the position of plugins-List because it has more entries + int counter = 0; + for ( Plugin plug : plugins ) + { + // find the delete-position + if ( plug.getClass().toString().substring( 6 ).equals( publicPlugin.getPluginClass() ) ) + { + break; + } + counter++; + } + // delete the Plugin, because the depended Plugin is missing + publicPlugins.remove( i ); + plugins.remove( counter ); + i--; + break; + } + } + } + } + Log.debug("Completed plugin dependency check"); + + EventQueue.invokeLater( () -> { + for ( Plugin plugin : plugins ) + { + try + { + plugin.initialize(); + Log.debug("Initialized " + plugin.getClass().getSimpleName()); + } + catch ( Throwable e ) + { + Log.error( "An exception occurred while initializing plugin " + plugin.getClass().getSimpleName(), e ); + } + } + } ); + } + catch ( Exception e ) + { + Log.error( "An exception occurred while initializing plugins.", e ); + } + } + + @Override + public void shutdown() + { + for ( Plugin plugin : plugins ) + { + try + { + plugin.shutdown(); + } + catch ( NoSuchMethodError e ) + { + Log.error( "NoSuchMethodError on shutdown of plugin" + e ); + } + catch ( Exception e ) + { + Log.warning( "Exception on shutdown of plugin.", e ); + } + } + } + + @Override + public void mainWindowActivated() + { + } + + @Override + public void mainWindowDeactivated() + { + } + + /** + * Locates the best class loader based on context (see class description). + * + * @return The best parent classloader to use + */ + private ClassLoader getParentClassLoader() + { + ClassLoader parent = Thread.currentThread().getContextClassLoader(); + if ( parent == null ) + { + parent = this.getClass().getClassLoader(); + if ( parent == null ) + { + parent = ClassLoader.getSystemClassLoader(); + } + } + return parent; + } + + /** + * Expands all plugin packs (.jar files located in the plugin dir with plugin.xml). + */ + private void expandNewPlugins() + { + File[] jars = PLUGINS_DIRECTORY.listFiles( ( dir, name ) -> { + boolean accept = false; + String smallName = name.toLowerCase(); + if ( smallName.endsWith( ".jar" ) ) + { + accept = true; + } + return accept; + } ); + + // Do nothing if no jar or zip files were found + if ( jars == null ) + { + return; + } + + for ( File jar : jars ) + { + if ( jar.isFile() ) + { + + URL url = null; + try + { + url = jar.toURI().toURL(); + } + catch ( MalformedURLException e ) + { + Log.error( e ); + } + String name = URLFileSystem.getName( url ); + File directory = new File( PLUGINS_DIRECTORY, name ); + if ( directory.exists() && directory.isDirectory() ) + { + // Check to see if directory contains the plugin.xml file. + // If not, delete directory. + File pluginXML = new File( directory, "plugin.xml" ); + if ( pluginXML.exists() ) + { + if ( pluginXML.lastModified() < jar.lastModified() ) + { + uninstall( directory ); + unzipPlugin( jar, directory ); + } + continue; + } + uninstall( directory ); + } + else + { + // Unzip contents into directory + unzipPlugin( jar, directory ); + } + } + } + } + + private void loadPublicPlugins() + { + // First, expand all plugins that have yet to be expanded. + expandNewPlugins(); + File[] files = PLUGINS_DIRECTORY.listFiles( ( dir, name ) -> dir.isDirectory() ); + // Do nothing if no jar or zip files were found + if ( files == null ) + { + return; + } + //Make sure to load first the plugins with no dependencies + // If a plugin with dependencies gets loaded before one of the dependencies, + //class not found exception may be thrown if a dependency class is used during plugin creation + List dependencies = new ArrayList<>(); + List nodependencies = new ArrayList<>(); + for ( File file : files ) + { + File pluginXML = new File( file, "plugin.xml" ); + if ( pluginXML.exists() ) + { + if ( hasDependencies( pluginXML ) ) + { + dependencies.add( file ); + } + else + { + nodependencies.add( file ); + } + } + } + + try + { + for ( File file : nodependencies ) + { + loadPlugin( classLoader, file ); + } + for ( File file : dependencies ) + { + loadPlugin( classLoader, file ); + } + } + catch ( Throwable e ) + { + Log.error( "Unable to load dirs", e ); + } + } + + private void loadPlugin( PluginClassLoader classLoader, File file ) throws MalformedURLException + { + Log.debug("Start loading plugin " + file.getAbsolutePath()); + classLoader.addPlugin( file ); + loadPublicPlugin( file ); + } + + /** + * Adds and installs a new plugin into Spark. + * + * @param plugin the plugin to install. + * @throws Exception thrown if there was a problem loading the plugin. + */ + public void addPlugin( PublicPlugin plugin ) throws Exception + { + expandNewPlugins(); + + URL url = new URL( plugin.getDownloadURL() ); + String name = URLFileSystem.getName( url ); + File pluginDownload = new File( PluginManager.PLUGINS_DIRECTORY, name ); + + ( (PluginClassLoader) getParentClassLoader() ).addPlugin( pluginDownload ); + + Plugin pluginInstance = loadPublicPlugin(pluginDownload); + if (pluginInstance == null) { + return; + } + + try + { + EventQueue.invokeAndWait( () -> { + Log.debug( "Trying to initialize " + pluginInstance ); + pluginInstance.initialize(); + Log.debug( "Done initializing " + pluginInstance ); + + } ); + } + catch ( Exception e ) + { + Log.error( e ); + } + + } + + /** + * Unzips a plugin from a JAR file into a directory. If the JAR file + * isn't a plugin, this method will do nothing. + * + * @param file the JAR file + * @param dir the directory to extract the plugin to. + */ + private void unzipPlugin( File file, File dir ) + { + try + { + ZipFile zipFile = new JarFile( file ); + // Ensure that this JAR is a plugin. + if ( zipFile.getEntry( "plugin.xml" ) == null ) + { + return; + } + dir.mkdir(); + for ( Enumeration e = zipFile.entries(); e.hasMoreElements(); ) + { + JarEntry entry = (JarEntry) e.nextElement(); + File entryFile = new File( dir, entry.getName() ); + + //Fix Zip Slip Vulnerability + if (!entryFile.toPath().normalize().startsWith(dir.toPath().normalize())) { + throw new RuntimeException("Bad zip entry"); + } + + // Ignore any MANIFEST.MF entries. + if (entry.getName().toUpperCase().endsWith("MANIFEST.MF")) + { + continue; + } + if ( !entry.isDirectory() ) + { + entryFile.getParentFile().mkdirs(); + FileOutputStream out = new FileOutputStream( entryFile ); + InputStream zin = zipFile.getInputStream( entry ); + byte[] b = new byte[ 512 ]; + int len; + while ( ( len = zin.read( b ) ) != -1 ) + { + out.write( b, 0, len ); + } + out.flush(); + out.close(); + zin.close(); + } + } + zipFile.close(); + } + catch ( Throwable e ) + { + Log.error( "Error unzipping plugin", e ); + } + } + + /** + * Returns a collection of all public plugins. + * + * @return the collection of public plugins. + */ + public List getPublicPlugins() + { + return publicPlugins; + } + + private void uninstall( File pluginDir ) + { + try + { + Files.walkFileTree( pluginDir.toPath(), new SimpleFileVisitor() + { + @Override + public FileVisitResult visitFile( Path file, BasicFileAttributes attrs ) throws IOException + { + Files.delete( file ); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory( Path dir, IOException exc ) throws IOException + { + Files.delete( dir ); + return FileVisitResult.CONTINUE; + } + } ); + } + catch ( IOException e ) + { + Log.error( "An unexpected exception occurred while trying to uninstall a plugin from: " + pluginDir, e ); + } + } + + /** + * Removes and uninstall a plugin from Spark. + * + * @param plugin the plugin to uninstall. + */ + public void removePublicPlugin( PublicPlugin plugin ) + { + for ( PublicPlugin publicPlugin : getPublicPlugins() ) + { + if ( plugin.getName().equals( publicPlugin.getName() ) ) + { + uninstall( plugin.getPluginDir() ); + publicPlugins.remove( plugin ); + } + } + } + + /** + * Returns true if the specified plugin is installed. + * + * @param plugin the PublicPlugin plugin to check. + * @return true if installed. + */ + public boolean isInstalled( PublicPlugin plugin ) + { + for ( PublicPlugin publicPlugin : getPublicPlugins() ) + { + if ( plugin.getName().equals( publicPlugin.getName() ) ) + { + return true; + } + } + + return false; + } + + /** + * Checks the plugin for the required operating system. + * + * @param plugin the Plugin element to check. + * @return true if the operating system is ok for the plugin to run on. + */ + private boolean isOperatingSystemOK( Node plugin ) + { + try + { + final Element osElement = (Element) plugin.selectSingleNode( "os" ); + if ( osElement != null ) + { + String operatingSystem = osElement.getText(); + boolean ok = false; + final String currentOS = JiveInfo.getOS().toLowerCase(); + // Iterate through comma-delimited string + StringTokenizer tkn = new StringTokenizer( operatingSystem, "," ); + while ( tkn.hasMoreTokens() ) + { + String os = tkn.nextToken().toLowerCase(); + if ( currentOS.contains( os ) || currentOS.equalsIgnoreCase( os ) ) + { + ok = true; + } + } + + if ( !ok ) + { + Log.debug( "Unable to load plugin " + plugin.selectSingleNode( "name" ).getText() + " due to invalid operating system. Required OS = " + operatingSystem ); + return false; + } + } + } + catch ( Exception e ) + { + Log.error("An exception occurred while trying to determine operating system compatibility of plugin '" + plugin + "'", e); + } + + return true; + } +} diff --git a/src/java/org/jivesoftware/spark/PluginRes.java b/core/src/main/java/org/jivesoftware/spark/PluginRes.java similarity index 98% rename from src/java/org/jivesoftware/spark/PluginRes.java rename to core/src/main/java/org/jivesoftware/spark/PluginRes.java index 16fbf5044..98c1acda7 100644 --- a/src/java/org/jivesoftware/spark/PluginRes.java +++ b/core/src/main/java/org/jivesoftware/spark/PluginRes.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2011 eZuce Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/src/main/java/org/jivesoftware/spark/PresenceManager.java b/core/src/main/java/org/jivesoftware/spark/PresenceManager.java new file mode 100644 index 000000000..2c2265200 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/PresenceManager.java @@ -0,0 +1,290 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smack.packet.XmlElement; +import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smackx.muc.packet.MUCUser; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.EntityFullJid; +import org.jxmpp.jid.Jid; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static org.jivesoftware.smack.util.StringUtils.isNullOrEmpty; + +/** + * Handles the most common presence checks. + * + * @author Derek DeMoro + */ +public class PresenceManager { + + private static final List PRESENCES = new ArrayList<>(); + + + static { + // Add Available Presence + final Presence availablePresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .setStatus(Res.getString("status.online")) + .setPriority(1) + .setMode(Presence.Mode.available) + .build(); + + final Presence freeToChatPresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .setStatus(Res.getString("status.free.to.chat")) + .setPriority(1) + .setMode(Presence.Mode.chat) + .build(); + + final Presence awayPresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .setStatus(Res.getString("status.away")) + .setPriority(0) + .setMode(Presence.Mode.away) + .build(); + + final Presence phonePresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .setStatus(Res.getString("status.on.phone")) + .setPriority(0) + .setMode(Presence.Mode.away) + .build(); + + final Presence dndPresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .setStatus(Res.getString("status.do.not.disturb")) + .setPriority(0) + .setMode(Presence.Mode.dnd) + .build(); + + final Presence extendedAway = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .setStatus(Res.getString("status.extended.away")) + .setPriority(0) + .setMode(Presence.Mode.xa) + .build(); + + final Presence invisible = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .setStatus(Res.getString("status.invisible")) + .setPriority(0) + .setMode(Presence.Mode.available) + .build(); + + PRESENCES.add(freeToChatPresence); + PRESENCES.add(availablePresence); + PRESENCES.add(awayPresence); + PRESENCES.add(phonePresence); + PRESENCES.add(extendedAway); + PRESENCES.add(dndPresence); + + if (!Default.getBoolean(Default.HIDE_LOGIN_AS_INVISIBLE) && Enterprise.containsFeature(Enterprise.INVISIBLE_LOGIN_FEATURE)) PRESENCES.add(invisible); + } + + /** + * Building Presence related data. + */ + private PresenceManager() { + + } + + /** + * Returns true if the user is online. + * + * @param jid the JID of the user. + * @return true if online. + */ + public static boolean isOnline(BareJid jid) { + Roster roster = SparkManager.getRoster(); + Presence presence = roster.getPresence(jid); + return presence.isAvailable(); + } + + /** + * Returns true if the user is online and their status is available or free to chat. + * + * @param jid the jid of the user. + * @return true if the user is online and available. + */ + public static boolean isAvailable(BareJid jid) { + Roster roster = SparkManager.getRoster(); + Presence presence = roster.getPresence(jid); + return presence.isAvailable() && !presence.isAway(); + } + + /** + * Returns true if the user is online and their mode is available or free to chat. + * + * @param presence the users presence. + * @return true if the user is online and their mode is available or free to chat. + */ + public static boolean isAvailable(Presence presence) { + return presence.isAvailable() && !presence.isAway(); + } + + /** + * Returns the presence of a user. + * + * @param jid the users JID. + * @return the users presence. + */ + public static Presence getPresence(BareJid jid) { + if (jid.equals(SparkManager.getSessionManager().getUserBareAddress())) { + return SparkManager.getWorkspace().getStatusBar().getPresence(); + } else { + Roster roster = SparkManager.getRoster(); + return roster.getPresence(jid); + } + } + + /** + * Returns the fully qualified jid of a user. May return {@code null}. + * + * @param jid the users bare JID (ex. derek@jivesoftware.com) + * @return the fully qualified JID of a user (ex. derek@jivesoftware.com --> derek@jivesoftware.com/spark) or {@code null}. + */ + public static EntityFullJid getFullyQualifiedJID(BareJid jid) { + Roster roster = SparkManager.getRoster(); + Presence presence = roster.getPresence(jid); + Jid result = presence.getFrom(); + return result.asEntityFullJidIfPossible(); + } + + public static String getJidFromMUCPresence(Presence presence) { + Collection extensions = presence.getExtensions(); + for (XmlElement extension : extensions) { + if (extension instanceof MUCUser) { + final MUCUser mucUser = (MUCUser) extension; + Jid fullJid = mucUser.getItem().getJid(); + if ( fullJid == null) { + return null; + } + return fullJid.asBareJid().toString(); + } + } + return null; + } + + /** + * Returns the icon associated with a users presence. + * + * @param presence the users presence. + * @return the icon associated with it. + */ + public static Icon getIconFromPresence(Presence presence) { + if (isInvisible(presence)) { + return SparkRes.getImageIcon(SparkRes.Icon.CLEAR_BALL_ICON); + } + + // Handle offline presence + if (!presence.isAvailable()) { + return SparkRes.getImageIcon(SparkRes.Icon.CLEAR_BALL_ICON); + } + + Presence.Mode presenceMode = presence.getMode(); + if (presenceMode == null) { + presenceMode = Presence.Mode.available; + } + + Icon icon = null; + + if (presenceMode.equals(Presence.Mode.available)) { + icon = SparkRes.getImageIcon(SparkRes.Icon.GREEN_BALL); + } + else if (presenceMode.equals(Presence.Mode.chat)) { + icon = SparkRes.getImageIcon(SparkRes.Icon.FREE_TO_CHAT_IMAGE); + } + else if (isOnPhone(presence)) { + icon = SparkRes.getImageIcon(SparkRes.Icon.ON_PHONE_IMAGE); + } + else if (presenceMode.equals(Presence.Mode.away)) { + icon = SparkRes.getImageIcon(SparkRes.Icon.IM_AWAY); + } + else if (presenceMode.equals(Presence.Mode.dnd)) { + icon = SparkRes.getImageIcon(SparkRes.Icon.IM_DND); + } + else if (presenceMode.equals(Presence.Mode.xa)) { + icon = SparkRes.getImageIcon(SparkRes.Icon.IM_XA); + } + + // Check For ContactItem handlers + Icon handlerIcon = SparkManager.getChatManager().getTabIconForContactHandler(presence); + if (handlerIcon != null) { + icon = handlerIcon; + } + + + return icon; + } + + /** + * Returns the Presence Map. + * + * @return the Presence Map. + */ + public static List getPresences() { + return PRESENCES; + } + + public static boolean isOnPhone(Presence presence) { + Presence.Mode presenceMode = presence.getMode(); + if (presenceMode == null) { + presenceMode = Presence.Mode.available; + } + return presence.getStatus() != null && + presence.getStatus().contains(Res.getString("status.on.phone")) && + presenceMode.equals(Presence.Mode.away); + } + + public static boolean isInvisible(Presence presence) { + return presence != null && presence.getType() == Presence.Type.unavailable + && (Res.getString("status.invisible").equalsIgnoreCase(presence.getStatus()) + || isNullOrEmpty(presence.getStatus())) + && Presence.Mode.available == presence.getMode(); + } + + public static Presence getAvailablePresence() { + return PRESENCES.get(1); + } + + public static Presence getUnavailablePresence() { + return PRESENCES.get(6); + } + + public static boolean areEqual(Presence p1, Presence p2) { + if (p1 == p2) + return true; + + if (p1 == null || p2 == null) + return false; + + return p1.getType() == p2.getType() && p1.getMode() == p2.getMode() + && p1.getStatus().equals(p2.getStatus()); + } + +} diff --git a/core/src/main/java/org/jivesoftware/spark/SessionManager.java b/core/src/main/java/org/jivesoftware/spark/SessionManager.java new file mode 100644 index 000000000..35f55f740 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/SessionManager.java @@ -0,0 +1,285 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.*; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smack.provider.ProviderManager; +import org.jivesoftware.smackx.iqprivate.PrivateDataManager; +import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; +import org.jivesoftware.smackx.disco.packet.DiscoverItems; +import org.jivesoftware.spark.ui.PresenceListener; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.manager.Features; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.EntityFullJid; +import org.jxmpp.util.XmppStringUtils; + +import javax.swing.SwingUtilities; + +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * This manager is responsible for the handling of the XMPPConnection used within Spark. This is used + * for the changing of the user's presence, the handling of connection errors and the ability to add + * presence listeners and retrieve the connection used in Spark. + * + * @author Derek DeMoro + */ +public final class SessionManager implements ConnectionListener { + private AbstractXMPPConnection connection; + private PrivateDataManager personalDataManager; + + private DomainBareJid serverAddress; + private String username; + private String password; + + private EntityFullJid JID; + + private final CopyOnWriteArrayList presenceListeners = new CopyOnWriteArrayList<>(); + + private EntityBareJid userBareAddress; + private DiscoverItems discoverItems; + + // Stores our presence state at the time that the last connectionClosedOnError happened. + private Presence preError; + + public SessionManager() { + } + + /** + * Initializes session. + * + * @param connection the XMPPConnection used in this session. + * @param username the agent's username. + * @param password the agent's password. + */ + public void initializeSession( AbstractXMPPConnection connection, String username, String password) { + this.connection = connection; + this.username = username; + this.password = password; + this.userBareAddress = connection.getUser().asEntityBareJid(); + + // create a workgroup session + personalDataManager = PrivateDataManager.getInstanceFor( connection ); + + // Discover items + discoverItems(); + + ProviderManager.addExtensionProvider(Features.ELEMENT_NAME, Features.NAMESPACE, new Features.Provider()); + } + + /** + * Does the initial service discovery. + */ + private void discoverItems() { + ServiceDiscoveryManager discoManager = SparkManager.getDiscoManager(); + try { + discoverItems = discoManager.discoverItems(connection.getXMPPServiceDomain()); + } + catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + discoverItems = new DiscoverItems(); + } + } + + /** + * Returns the XMPPConnection used for this session. + */ + public AbstractXMPPConnection getConnection() { + return connection; + } + + + /** + * Returns the PrivateDataManager responsible for handling all private data for individual + * agents. + */ + public PrivateDataManager getPersonalDataManager() { + return personalDataManager; + } + + /** + * Returns the host for this connection. + */ + public DomainBareJid getServerAddress() { + return serverAddress; + } + + /** + * Set the server address + * + * @param address the address of the server. + */ + public void setServerAddress(DomainBareJid address) { + this.serverAddress = address; + } + + /** + * Notify agent the connection was closed due to an exception. + * + * @param ex the Exception that took place. + */ + @Override + public void connectionClosedOnError(final Exception ex) { + SwingUtilities.invokeLater( () -> { + preError = Workspace.getInstance().getStatusBar().getPresence(); + final Presence presence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .setStatus(Res.getString("status.offline")) + .build(); + changePresence(presence); + + Workspace.getInstance().getStatusBar().setStatusPanelEnabled(false); + Log.debug("Connection closed on error.: " + ex.getMessage()); + } ); + } + + @Override + public void connected( XMPPConnection xmppConnection ) + { + + } + + @Override + public void authenticated( XMPPConnection xmppConnection, boolean b ) + { + reconnectionSuccessful(); + } + + /** + * Notify the agent that the connection has been closed. + */ + @Override + public void connectionClosed() { + } + + /** + * Return the username associated with this session. + */ + public String getUsername() { + return XmppStringUtils.unescapeLocalpart(username); + } + + /** + * Return the password associated with this session. + */ + public String getPassword() { + return password; + } + + /** + * Update the current availability of the user + * + * @param presence the current presence of the user. + */ + public void changePresence(Presence presence) { + // Fire Presence Listeners + for (PresenceListener listener : this.presenceListeners) { + listener.presenceChanged(presence); + } + + // Do NOT send presence if disconnected. + if (connection.isConnected()) { + // Send Presence Packet + try + { + connection.sendStanza(presence); + } + catch ( SmackException.NotConnectedException | InterruptedException e ) + { + Log.error( "Unable to send presence to " + presence.getTo(), e ); + } + } + } + + /** + * Returns the jid of the Spark user. + * + * @return the jid of the Spark user. + */ + public EntityFullJid getJID() { + return JID; + } + + /** + * Sets the jid of the current Spark user. + * + * @param jid the jid of the current Spark user. + */ + public void setJID(EntityFullJid jid) { + this.JID = jid; + } + + /** + * Adds a PresenceListener to Spark. PresenceListener's are used + * to allow notification of when the Spark users changes their presence. + * + * @param listener the listener. + */ + public void addPresenceListener(PresenceListener listener) { + presenceListeners.addIfAbsent(listener); + } + + /** + * Remove a PresenceListener from Spark. + * + * @param listener the listener. + */ + public void removePresenceListener(PresenceListener listener) { + presenceListeners.remove(listener); + } + + /** + * Returns the users bare JID. A bare-JID is the JID without a resource (ex. derek@jivesoftware.com/spark would + * be derek@jivesoftware.com) + * + * @return the users bare JID. + */ + public EntityBareJid getUserBareAddress() { + return userBareAddress; + } + + /** + * Returns the Discovered Items found on startup. + */ + public DiscoverItems getDiscoveredItems() { + return discoverItems; + } + + public void setConnection(AbstractXMPPConnection con) { + this.connection = con; + } + + private void reconnectionSuccessful() + { + // Restore the presence state that we were in just before the disconnection happened. + if ( preError != null ) + { + SwingUtilities.invokeLater( () -> + { + changePresence( preError ); + preError = null; + + Workspace.getInstance().getStatusBar().setStatusPanelEnabled(true); + }); + } + } + +} diff --git a/core/src/main/java/org/jivesoftware/spark/SoundManager.java b/core/src/main/java/org/jivesoftware/spark/SoundManager.java new file mode 100644 index 000000000..3f7d882a7 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/SoundManager.java @@ -0,0 +1,206 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark; + +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.preference.sounds.SoundPreference; +import org.jivesoftware.sparkimpl.preference.sounds.SoundPreferences; + +import javax.sound.sampled.*; +import java.io.File; +import java.util.WeakHashMap; + +/** + * This manager is responsible for the playing, stopping and caching of sounds within Spark. You would + * use this manager when you wish to play audio without adding too much memory overhead. + */ +public class SoundManager { + + private final WeakHashMap clipCache = new WeakHashMap<>(); + + /** + * When the runtime has no usable audio device/mixer, attempting to play sounds will repeatedly throw. + * We detect that scenario once and disable sound playback to avoid log spam and wasted work. + */ + private boolean soundSystemUnavailable; + private boolean soundSystemUnavailableLogged; + + public void playClip(Event e) { + SoundPreference soundPreference = (SoundPreference) SparkManager.getPreferenceManager().getPreference(new SoundPreference().getNamespace()); + SoundPreferences preferences = soundPreference.getPreferences(); + if (preferences == null) { + return; + } + String soundFile = ""; + // Determines sound file based on event and preferences + switch (e) { + case MSG_INCOMING: + if (preferences.isPlayIncomingSound()) { + soundFile = preferences.getIncomingSound(); + } + break; + case MSG_OUTCOMING: + if (preferences.isPlayOutgoingSound()) { + soundFile = preferences.getOutgoingSound(); + } + break; + case CHAT_REQUEST: + if (preferences.isPlayChatRequestSound()) { + soundFile = preferences.getChatRequestSound(); + } + break; + case INCOMING_INVITATION: + if (preferences.playIncomingInvitationSound()) { + soundFile = preferences.getIncomingInvitationSoundFile(); + } + break; + case STATUS_OFFLINE: + if (preferences.isPlayOfflineSound()) { + soundFile = preferences.getOfflineSound(); + } + break; + default: + return; + } + if (soundFile == null || soundFile.isEmpty()) { + return; + } + SparkManager.getSoundManager().playClip(new File(soundFile)); + } + + /** + * Plays a sound file. + * + * @param soundFile the File object representing the wav file. + */ + public void playClip(final File soundFile) { + if (soundSystemUnavailable) { + return; + } + + final Runnable playThread = () -> { + Clip ac = clipCache.get(soundFile.toString()); + if (ac == null) { + // Add new clip + try (AudioInputStream originalStream = AudioSystem.getAudioInputStream(soundFile)) { + ac = tryOpenClipWithFallbacks(originalStream); + if (ac != null) { + clipCache.put(soundFile.toString(), ac); + } + } catch (Exception e) { + Log.warning("Unable to load sound: " + soundFile, e); + } + } + // Starts cached or newly loaded audio clip + if (ac != null) { + try { + if (ac.isRunning()) { + ac.stop(); + } + ac.setFramePosition(0); + ac.start(); + } catch (Exception e) { + Log.error("Unable to play sound: " + soundFile + "\n\t: " + e); + } + } + }; + + TaskEngine.getInstance().submit(playThread); + } + + private Clip tryOpenClipWithFallbacks(AudioInputStream originalStream) { + // 1) Try original format first (fast path) + Clip clip = tryOpenClip(originalStream); + if (clip != null) { + return clip; + } + + // ... existing code ... + // 2) Try decoding to a very common PCM format (16-bit LE, same sample rate/channels as source) + try { + final AudioFormat src = originalStream.getFormat(); + final float sampleRate = src.getSampleRate() > 0 ? src.getSampleRate() : 44100.0f; + final int channels = src.getChannels() > 0 ? src.getChannels() : 2; + + final AudioFormat pcm = new AudioFormat( + AudioFormat.Encoding.PCM_SIGNED, + sampleRate, + 16, + channels, + channels * 2, + sampleRate, + false + ); + + try (AudioInputStream pcmStream = AudioSystem.getAudioInputStream(pcm, originalStream)) { + clip = tryOpenClip(pcmStream); + if (clip != null) { + return clip; + } + } + } catch (Exception ignored) { + // fall through to more aggressive fallbacks + } + + // 3) Fallback: mono 22.05kHz PCM (last resort for constrained devices/backends) + try { + final AudioFormat monoLow = new AudioFormat( + AudioFormat.Encoding.PCM_SIGNED, + 22050.0f, + 16, + 1, + 2, + 22050.0f, + false + ); + + try (AudioInputStream monoLowStream = AudioSystem.getAudioInputStream(monoLow, originalStream)) { + clip = tryOpenClip(monoLowStream); + if (clip != null) { + return clip; + } + } + } catch (Exception ignored) { + // fall through + } + + return null; + } + + private Clip tryOpenClip(AudioInputStream stream) { + try { + final AudioFormat format = stream.getFormat(); + final DataLine.Info info = new DataLine.Info(Clip.class, format); + if (!AudioSystem.isLineSupported(info)) { + return null; + } + final Clip clip = (Clip) AudioSystem.getLine(info); + clip.open(stream); + return clip; + } catch (LineUnavailableException e) { + // This often indicates: no audio device/mixer, or the backend cannot provide a Clip line. + soundSystemUnavailable = true; + if (!soundSystemUnavailableLogged) { + soundSystemUnavailableLogged = true; + Log.warning("Sound playback disabled: no supported audio line is available in this environment.", e); + } + return null; + } catch (Exception e) { + return null; + } + } +} diff --git a/src/java/org/jivesoftware/spark/SparkManager.java b/core/src/main/java/org/jivesoftware/spark/SparkManager.java similarity index 88% rename from src/java/org/jivesoftware/spark/SparkManager.java rename to core/src/main/java/org/jivesoftware/spark/SparkManager.java index d05cc6ede..170442837 100644 --- a/src/java/org/jivesoftware/spark/SparkManager.java +++ b/core/src/main/java/org/jivesoftware/spark/SparkManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +19,10 @@ import org.jivesoftware.Spark; import org.jivesoftware.resource.Default; import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.AbstractXMPPConnection; import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smackx.muc.MultiUserChatManager; import org.jivesoftware.smackx.xevent.MessageEventManager; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.spark.filetransfer.SparkTransferManager; @@ -33,6 +32,7 @@ import org.jivesoftware.spark.ui.ChatRoom; import org.jivesoftware.spark.ui.ContactList; import org.jivesoftware.spark.ui.TranscriptWindow; +import org.jivesoftware.spark.uri.UriManager; import org.jivesoftware.spark.util.log.Log; import org.jivesoftware.sparkimpl.profile.VCardManager; @@ -49,7 +49,7 @@ /** * Used as the System Manager for the Spark IM client. The SparkManager is responsible for - * the loading of other system managers on an as needed basis to prevent too much upfront loading + * the loading of other system managers on an as-needed basis to prevent too much upfront loading * of resources. Some of the Managers and components you can access from here are: *

    *

    @@ -76,14 +76,11 @@ *
    * Workspace - The inner pane of the Spark client. Use for adding or removing tabs to the main Spark panel. *
    - * Notifications - Use to display tray icon notifications (system specific), such as toaster popups or changing + * Notifications - Use to display tray icon notifications (system-specific), such as toaster popups or changing * the icon of the system tray. * * @author Derek DeMoro - * @version 1.0, 03/12/14 */ - - public final class SparkManager { /** @@ -96,12 +93,16 @@ public final class SparkManager { private static SoundManager soundManager; private static PreferenceManager preferenceManager; private static MessageEventManager messageEventManager; + private static MultiUserChatManager mucManager; + private static ServiceDiscoveryManager discoManager; private static UserManager userManager; private static ChatManager chatManager; + private static UriManager uriManager; private static VCardManager vcardManager; private static NativeManager nativeManager; private static Component focusedComponent; + private static Roster roster; private SparkManager() { @@ -173,10 +174,31 @@ public static PreferenceManager getPreferenceManager() { * * @return the {@link XMPPConnection} associated with this session. */ - public static XMPPConnection getConnection() { + public static AbstractXMPPConnection getConnection() { return sessionManager.getConnection(); } + public static MultiUserChatManager getMucManager() { + if (mucManager == null) { + mucManager = MultiUserChatManager.getInstanceFor(getConnection()); + } + return mucManager; + } + + public static ServiceDiscoveryManager getDiscoManager() { + if (discoManager == null) { + discoManager = ServiceDiscoveryManager.getInstanceFor(SparkManager.getConnection()); + } + return discoManager; + } + + public static Roster getRoster() { + if (roster == null) { + roster = Roster.getInstanceFor(SparkManager.getConnection()); + } + return roster; + } + /** * Returns the UserManager for LiveAssistant. The UserManager * keeps track of all users in current chats. @@ -204,6 +226,16 @@ public static ChatManager getChatManager() { return chatManager; } + /** + * Returns the UriManager. The UriManager is responsible for handling of XMPP URI. + */ + public static UriManager getUriManager() { + if (uriManager == null) { + uriManager = new UriManager(); + } + return uriManager; + } + /** * Retrieves the inner container for Spark. The Workspace is the container for all plugins into the Spark * install. Plugins would use this for the following: @@ -222,7 +254,6 @@ public static ChatManager getChatManager() { * @return Workspace the spark manager is associated with. */ public static Workspace getWorkspace() { - return Workspace.getInstance(); } @@ -359,7 +390,7 @@ public static ContactList getContactList() { * @return the UserDirectory for Spark. */ public static File getUserDirectory() { - final String bareJID = sessionManager.getBareAddress(); + final String bareJID = sessionManager.getUserBareAddress().asUnescapedString(); File userDirectory = new File(Spark.getSparkUserHome(), "/user/" + bareJID); if (!userDirectory.exists()) { userDirectory.mkdirs(); @@ -383,7 +414,7 @@ public static Component getFocusedComponent() { */ public static void addFeature(String namespace) { // Obtain the ServiceDiscoveryManager associated with my XMPPConnection - ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(getConnection()); + ServiceDiscoveryManager discoManager = getDiscoManager(); // Register that a new feature is supported by this XMPP entity discoManager.addFeature(namespace); @@ -396,7 +427,7 @@ public static void addFeature(String namespace) { */ public static void removeFeature(String namespace) { // Obtain the ServiceDiscoveryManager associated with my XMPPConnection - ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(getConnection()); + ServiceDiscoveryManager discoManager = getDiscoManager(); // Register that a new feature is supported by this XMPP entity discoManager.removeFeature(namespace); @@ -410,7 +441,7 @@ public static void removeFeature(String namespace) { public static ImageIcon getApplicationImage() { ImageIcon mainImage = Default.getImageIcon(Default.FRAME_IMAGE); if (mainImage == null) { - mainImage = SparkRes.getImageIcon(SparkRes.MAIN_IMAGE); + mainImage = SparkRes.getImageIcon(SparkRes.Icon.MAIN_IMAGE); } return mainImage; } diff --git a/core/src/main/java/org/jivesoftware/spark/UserManager.java b/core/src/main/java/org/jivesoftware/spark/UserManager.java new file mode 100644 index 000000000..e8e041439 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/UserManager.java @@ -0,0 +1,475 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smackx.muc.MUCAffiliation; +import org.jivesoftware.smackx.muc.MUCRole; +import org.jivesoftware.smackx.muc.Occupant; +import org.jivesoftware.smackx.vcardtemp.packet.VCard; +import org.jivesoftware.spark.component.JContactItemField; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ContactGroup; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.spark.ui.ContactList; +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.SwingTimerTask; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.profile.VCardManager; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.EntityFullJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Domainpart; +import org.jxmpp.jid.parts.Localpart; +import org.jxmpp.jid.parts.Resourcepart; +import org.jxmpp.stringprep.XmppStringprepException; +import org.jxmpp.util.XmppStringUtils; + +import javax.swing.BorderFactory; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TimerTask; + +import static org.jivesoftware.spark.ui.ContactItem.CONTACT_ITEM_COMPARATOR; + +/** + * Handles all users in the agent application. + * Each user or chatting user can be referenced from the User Manager. + * You would use the UserManager to get visitors in a chat room or secondary agents. + */ +public class UserManager { + + private final Map parents = new HashMap<>(); + + public UserManager() { + } + + public String getNickname() { + final VCardManager vCardManager = SparkManager.getVCardManager(); + VCard vcard = vCardManager.getVCard(); + if (vcard == null) { + return SparkManager.getSessionManager().getUsername(); + } + else { + String nickname = vcard.getNickName(); + if (ModelUtil.hasLength(nickname)) { + return nickname; + } + else { + String firstName = vcard.getFirstName(); + if (ModelUtil.hasLength(firstName)) { + return firstName; + } + } + } + + // Default to node if nothing. + String username = SparkManager.getSessionManager().getUsername(); + username = XmppStringUtils.unescapeLocalpart(username); + + return username; + } + + public String getNickname(BareJid jid) { + String vcardNickname = null; + VCard vCard = SparkManager.getVCardManager().getVCard(jid); + if (vCard != null && vCard.getError() == null) { + String fullName = vCard.getField("FN"); + String nickname = vCard.getNickName(); + if (ModelUtil.hasLength(nickname)) { + vcardNickname = nickname; + } + else if (ModelUtil.hasLength(fullName)) { + vcardNickname = fullName; + } + } + + return vcardNickname; + } + + + /** + * Return a Collection of all user jids found in the specified room. + * + * @param room the name of the chatroom + * @param fullJID set to true if you wish to have the full jid with resource, otherwise false + * for the bare jid. + * @return a Collection of jids found in the room. + */ + public Collection getUserJidsInRoom(EntityBareJid room, boolean fullJID) { + return new ArrayList<>(); + } + + /** + * Checks to see if the user is an owner of the specified room. + * + * @param groupChatRoom the group chat room. + * @param nickname the user's nickname. + * @return true if the user is an owner. + */ + public boolean isOwner(GroupChatRoom groupChatRoom, Resourcepart nickname) + { + return isOwner( getOccupant( groupChatRoom, nickname ) ); + } + + /** + * Checks to see if the Occupant is the owner of the room. + * + * @param occupant the occupant of a room. + * @return true if the user is an owner. + */ + public boolean isOwner(Occupant occupant) + { + return occupant != null && occupant.getAffiliation() == MUCAffiliation.owner; + } + + /** + * Checks if the Occupant is a Member in this Room
    + * admins and owners are also members!!! + */ + public boolean isMember(Occupant occupant) + { + return occupant != null && ( occupant.getAffiliation() == MUCAffiliation.owner || occupant.getAffiliation() == MUCAffiliation.member || occupant.getAffiliation() == MUCAffiliation.admin ); + } + + /** + * Checks to see if the Occupant is a moderator. + * + * @param groupChatRoom the group chat room. + * @param nickname the nickname of the user. + * @return true if the user is a moderator. + */ + public boolean isModerator(GroupChatRoom groupChatRoom, Resourcepart nickname) + { + return isModerator( getOccupant( groupChatRoom, nickname ) ); + } + + /** + * Checks to see if the Occupant is a moderator. + * + * @param occupant the Occupant of a room. + * @return true if the user is a moderator. + */ + public boolean isModerator(Occupant occupant) { + return occupant != null && occupant.getRole() == MUCRole.moderator; + } + + /** + * Returns the occupant of the room identified by their nickname. + * + * @param groupChatRoom the GroupChatRoom. + * @param nickname the users nickname. + * @return the Occupant found. + */ + public Occupant getOccupant(GroupChatRoom groupChatRoom, Resourcepart nickname) { + EntityFullJid userJID = JidCreate.entityFullFrom(groupChatRoom.getBareJid(), nickname); + Occupant occ = null; + try { + occ = groupChatRoom.getMultiUserChat().getOccupant(userJID); + } + catch (Exception e) { + Log.error(e); + } + return occ; + } + + /** + * Checks the nickname of a user in a room and determines if they are an + * administrator of the room. + * + * @param groupChatRoom the GroupChatRoom. + * @param nickname the nickname of the user. Note: In MultiUserChats, users nicknames + * are defined by the resource(ex.theroom@conference.jivesoftware.com/derek) would have + * derek as a nickname. + * @return true if the user is an admin. + */ + public boolean isAdmin(GroupChatRoom groupChatRoom, Resourcepart nickname) { + return isAdmin( getOccupant(groupChatRoom, nickname) ); + } + + /** + * Checks to see if the Occupant is an admin. + * + * @param occupant the occupant of a room. + * @return true if the user is an admin. + */ + public boolean isAdmin(Occupant occupant) + { + return occupant != null && occupant.getAffiliation() == MUCAffiliation.admin; + } + + public boolean hasVoice(GroupChatRoom groupChatRoom, Resourcepart nickname) { + Occupant occupant = getOccupant(groupChatRoom, nickname); + if (occupant != null) { + return MUCRole.visitor != occupant.getRole(); + } + return true; + } + + /** + * Resolves display name from a contact list or JID + */ + public String getUserNicknameFromJID(BareJid jid) { + ContactList contactList = SparkManager.getWorkspace().getContactList(); + ContactItem item = contactList.getContactItemByJID(jid); + if (item != null) { + return item.getDisplayName(); + } + + return unescapeJID(jid); + } + + public Resourcepart getUserNicknameAsResourcepartFromJID(BareJid jid) { + return Resourcepart.fromOrThrowUnchecked(getUserNicknameFromJID(jid)); + } + + /** + * Escapes a complete JID by examining the Node itself and escaping when necessary. + * + * @param jid the users JID + * @return the escaped JID. + */ + public static String escapeJID(String jid) { + if (jid == null) { + return null; + } + + String node = XmppStringUtils.parseLocalpart(jid); + String restOfJID = jid.substring(node.length()); + String builder = XmppStringUtils.escapeLocalpart(node) + restOfJID; + return builder; + } + + public static String unescapeJID(CharSequence jid) { + BareJid bareJid = JidCreate.bareFromOrThrowUnchecked(jid); + return unescapeJID(bareJid); + } + + /** + * Unescapes a complete JID by examining the node itself and unescaping when necessary. + * + * @param jid the users jid. + * @return the unescaped JID. + */ + public static String unescapeJID(BareJid jid) { + if (jid == null) { + return null; + } + + Localpart node = jid.getLocalpartOrNull(); + Domainpart restOfJID = jid.getDomain(); + return node != null ? XmppStringUtils.unescapeLocalpart(node.toString()) + '@' + restOfJID : restOfJID.toString(); + } + + /** + * Returns the full jid w/ resource of a user by their display name + * in the ContactList. + * + * @param displayName the displayed name of the user. + * @return the full jid w/ resource of the user. + */ + public EntityFullJid getJIDFromDisplayName(CharSequence displayName) { + ContactList contactList = SparkManager.getWorkspace().getContactList(); + ContactItem item = contactList.getContactItemByDisplayName(displayName); + if (item != null) { + return getFullJID(item.getJid()); + } + + return null; + } + + /** + * Returns the full jid (with resource) based on the user's jid. + * + * @param bareJid the users bare JID. + * @return the full JID with resource. + */ + public EntityFullJid getFullJID(BareJid bareJid) { + Presence presence = PresenceManager.getPresence(bareJid); + Jid jid = presence.getFrom(); + return jid.asEntityFullJidIfPossible(); + } + + + public void searchContacts(String contact, final JFrame parent) { + // Caches parent glass pane for later restoration + if (parents.get(parent) == null && parent.getGlassPane() !=null) { + parents.put(parent, parent.getGlassPane()); + } + + // Make sure we are using the default glass pane + final Component glassPane = parents.get(parent); + parent.setGlassPane(glassPane); + + final Map contactMap = new HashMap<>(); + final List contacts = new ArrayList<>(); + + final ContactList contactList = SparkManager.getWorkspace().getContactList(); + + for (ContactGroup contactGroup : contactList.getContactGroups()) { + contactGroup.clearSelection(); + for (ContactItem contactItem : contactGroup.getContactItems()) { + if (contactMap.putIfAbsent(contactItem.getJid().toString(), contactItem) == null) { + contacts.add(contactItem); + } + } + } + + // Sort + contacts.sort(CONTACT_ITEM_COMPARATOR); + + final JContactItemField contactField = new JContactItemField( new ArrayList<>( contacts )); + + + JPanel layoutPanel = new JPanel(); + layoutPanel.setLayout(new GridBagLayout()); + JLabel enterLabel = new JLabel(Res.getString("label.contact.to.find")); + enterLabel.setFont(new Font("dialog", Font.BOLD, 10)); + layoutPanel.add(enterLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 5), 0, 0)); + layoutPanel.add(contactField, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); + layoutPanel.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); + + contactField.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent keyEvent) { + if (keyEvent.getKeyChar() == KeyEvent.VK_ENTER) { + if (ModelUtil.hasLength(contactField.getText())) { + ContactItem item = contactMap.get(contactField.getText()); + if (item == null) { + item = contactField.getSelectedContactItem(); + } + if (item != null) { + parent.setGlassPane(glassPane); + parent.getGlassPane().setVisible(false); + contactField.dispose(); + SparkManager.getChatManager().activateChat(item.getJid(), item.getDisplayName()); + } + } + + } + else if (keyEvent.getKeyChar() == KeyEvent.VK_ESCAPE) { + parent.setGlassPane(glassPane); + parent.getGlassPane().setVisible(false); + contactField.dispose(); + } + } + }); + + contactField.getList().addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if(SwingUtilities.isRightMouseButton(e)) + { + contactField.setSelectetIndex(e); + ContactItem item = contactField.getSelectedContactItem(); + MouseEvent exx = new MouseEvent((Component) e.getSource(),e.getID(), e.getWhen(),e.getModifiers(),e.getX()+20, e.getY(), e.getClickCount(), false); + SparkManager.getContactList().setSelectedUser(item.getJid().asBareJid()); + SparkManager.getContactList().showPopup(contactField.getPopup(),exx,item); + } + + if (e.getClickCount() == 2) { + if (ModelUtil.hasLength(contactField.getText())) { + ContactItem item = contactMap.get(contactField.getText()); + if (item == null) { + item = contactField.getSelectedContactItem(); + } + if (item != null) { + parent.setGlassPane(glassPane); + parent.getGlassPane().setVisible(false); + contactField.dispose(); + SparkManager.getChatManager().activateChat(item.getJid(), item.getDisplayName()); + } + } + } + } + }); + + + final JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.setLayout(new GridBagLayout()); + mainPanel.add(layoutPanel, new GridBagConstraints(0, 0, 1, 1, 0.5, 0.5, GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(SparkManager.getMainWindow().getTopToolBar().getHeight()+SparkManager.getWorkspace().getStatusBar().getHeight() + 47, 1, 5, 1), 200, 0)); + mainPanel.setOpaque(false); + + contactField.setText(contact); + parent.setGlassPane(mainPanel); + parent.getGlassPane().setVisible(true); + contactField.focus(); + + mainPanel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent mouseEvent) { + parent.setGlassPane(glassPane); + parent.getGlassPane().setVisible(false); + contactField.dispose(); + } + }); + + parent.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent windowEvent) { + parent.setGlassPane(glassPane); + parent.getGlassPane().setVisible(false); + contactField.dispose(); + parent.removeWindowListener(this); + } + + @Override + public void windowDeactivated(final WindowEvent windowEvent) { + TimerTask task = new SwingTimerTask() { + @Override + public void doRun() { + if (contactField.canClose()) { + windowClosing(windowEvent); + } + } + }; + + TaskEngine.getInstance().schedule(task, 250); + } + }); + } + +} + + + diff --git a/core/src/main/java/org/jivesoftware/spark/Workspace.java b/core/src/main/java/org/jivesoftware/spark/Workspace.java new file mode 100644 index 000000000..c60075629 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/Workspace.java @@ -0,0 +1,497 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark; + +import java.awt.CardLayout; +import java.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.util.TimerTask; + +import javax.swing.AbstractAction; +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; + +import org.jivesoftware.MainWindow; +import org.jivesoftware.MainWindowListener; +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Default; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.StanzaListener; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smack.filter.StanzaFilter; +import org.jivesoftware.smack.filter.StanzaTypeFilter; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smackx.debugger.EnhancedDebuggerWindow; +import org.jivesoftware.smackx.delay.packet.DelayInformation; +import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; +import org.jivesoftware.smackx.muc.packet.GroupChatInvitation; +import org.jivesoftware.smackx.vcardtemp.packet.VCard; +import org.jivesoftware.spark.component.tabbedPane.SparkTabbedPane; +import org.jivesoftware.spark.filetransfer.SparkTransferManager; +import org.jivesoftware.spark.search.SearchManager; +import org.jivesoftware.spark.ui.ChatContainer; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomNotFoundException; +import org.jivesoftware.spark.ui.CommandPanel; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.spark.ui.ContactList; +import org.jivesoftware.spark.ui.conferences.ConferenceServices; +import org.jivesoftware.spark.ui.status.StatusBar; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.UIComponentRegistry; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.alerts.BroadcastPlugin; +import org.jivesoftware.sparkimpl.plugin.bookmarks.BookmarkPlugin; +import org.jivesoftware.sparkimpl.plugin.gateways.GatewayPlugin; +import org.jivesoftware.sparkimpl.plugin.transcripts.ChatTranscriptPlugin; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.parts.Localpart; + +/** + * The inner Container for Spark. + * The Workspace is the container for all plugins into the Spark installation. + * Plugins would use this for the following: + *

    + *

      + *
    • Add own tab to the main tabbed pane. e.g. + *
      + * Workspace workspace = SparkManager.getWorkspace();
      + * JButton button = new JButton("HELLO SPARK USERS");
      + * workspace.getWorkspacePane().addTab("MyPlugin", button);
      + * 
      + *
    • Retrieve the ContactList. + */ +public class Workspace extends JPanel implements StanzaListener { + + private static final long serialVersionUID = 7076407890063933765L; + private final SparkTabbedPane workspacePane; + private final StatusBar statusBox; + + private ContactList contactList; + private ConferenceServices conferences; + private GatewayPlugin gatewayPlugin; + private BookmarkPlugin bookmarkPlugin; + private ChatTranscriptPlugin transcriptPlugin; + private BroadcastPlugin broadcastPlugin; + + private static Workspace singleton; + private static final Object LOCK = new Object(); + + private final JPanel cardPanel; + private final CardLayout cardLayout; + + public static final String WORKSPACE_PANE = "WORKSPACE_PANE"; + + + /** + * Returns the singleton instance of Workspace, creating it if necessary. + */ + public static Workspace getInstance() { + // Synchronize on LOCK to ensure that we don't end up creating two singletons. + synchronized (LOCK) { + if (null == singleton) { + Workspace controller = new Workspace(); + singleton = controller; + return controller; + } + } + return singleton; + } + + + /** + * Creates the instance of the SupportChatWorkspace. + */ + private Workspace() { + final MainWindow mainWindow = SparkManager.getMainWindow(); + // Add MainWindow listener + mainWindow.addMainWindowListener(new MainWindowListener() { + @Override + public void shutdown() { + final ChatContainer container = SparkManager.getChatManager().getChatContainer(); + // Close all Chats. + for (ChatRoom chatRoom : container.getChatRooms()) { + // Leave the ChatRoom + container.leaveChatRoom(chatRoom); + } + conferences.shutdown(); + gatewayPlugin.shutdown(); + bookmarkPlugin.shutdown(); + broadcastPlugin.shutdown(); + } + + @Override + public void mainWindowActivated() { + } + + @Override + public void mainWindowDeactivated() { + } + } + ); + + // Initialize the workspace pane, defaulting the tabs to the bottom. + boolean top = Default.getBoolean(Default.TABS_PLACEMENT_TOP); + workspacePane = UIComponentRegistry.createWorkspaceTabPanel(top ? JTabbedPane.TOP : JTabbedPane.BOTTOM); + workspacePane.setBorder(BorderFactory.createEmptyBorder()); + // Add Panels. + cardLayout = new CardLayout(); + cardPanel = new JPanel(cardLayout); + cardPanel.setOpaque(false); + cardPanel.add(WORKSPACE_PANE, this); + + statusBox = UIComponentRegistry.createStatusBar(); + + // Build default workspace + this.setLayout(new GridBagLayout()); + add(workspacePane, new GridBagConstraints(0, 9, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); + add(statusBox, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + + + this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("F12"), "showDebugger"); + this.getActionMap().put("showDebugger", new AbstractAction("showDebugger") { + @Override + public void actionPerformed(ActionEvent evt) { + EnhancedDebuggerWindow window = EnhancedDebuggerWindow.getInstance(); + window.setVisible(true); + } + }); + + // Set background + setBackground(new Color(235, 239, 254)); + } + + /** + * Builds the Workspace layout. + */ + public void buildLayout() { + // Moved this to LoginDialog class + // new Enterprise(); + // Initialize Contact List + contactList = UIComponentRegistry.createContactList(); + conferences = UIComponentRegistry.createConferenceServices(); + // Init contact list. + contactList.initialize(); + // Load VCard information for status box + statusBox.loadVCard(); + // Initialise TransferManager + SparkTransferManager.getInstance(); + } + + /** + * Starts the Loading of all Spark Plugins. + */ + public void loadPlugins() { + Log.debug("Start loading plugins"); + // Send Available status + SparkManager.getSessionManager().changePresence(statusBox.getPresence()); + // Add presence and message listeners. + // We listen for these to force to open a 1-1 peer chat window from other operators if one isn't already open + StanzaFilter workspaceMessageFilter = new StanzaTypeFilter(Message.class); + // Add the packetListener to this instance + SparkManager.getSessionManager().getConnection().addAsyncStanzaListener(this, workspaceMessageFilter); + // Make presence available to anonymous requests, if from anonymous user in the system. + StanzaListener workspacePresenceListener = stanza -> { + Presence presence = (Presence)stanza; + JivePropertiesExtension extension = presence.getExtension(JivePropertiesExtension.class); + if (extension != null && extension.getProperty("anonymous") != null) { + boolean isAvailable = statusBox.getPresence().getMode() == Presence.Mode.available; + Presence reply = StanzaBuilder.buildPresence() + .ofType(isAvailable ? Presence.Type.available : Presence.Type.unavailable) + .to(presence.getFrom()) + .build(); + try + { + SparkManager.getSessionManager().getConnection().sendStanza(reply); + } + catch ( SmackException.NotConnectedException e ) + { + Log.warning( "Unable to send presence reply to " + reply.getTo(), e ); + } + } + }; + + SparkManager.getSessionManager().getConnection().addAsyncStanzaListener(workspacePresenceListener, new StanzaTypeFilter(Presence.class)); + + // Until we have better plugin management, will init after presence updates. + Log.debug("Manual init of gateway plugin"); + gatewayPlugin = new GatewayPlugin(); + gatewayPlugin.initialize(); + + // Load all non-presence related items. + Log.debug("Manual init of conference bookmarks"); + conferences.loadConferenceBookmarks(); + SearchManager.getInstance(); + Log.debug("Manual init of ChatTranscriptPlugin"); + transcriptPlugin = new ChatTranscriptPlugin(); + + // Load Broadcast Plugin + Log.debug("Manual init of BroadcastPlugin"); + broadcastPlugin = new BroadcastPlugin(); + broadcastPlugin.initialize(); + + // Load BookmarkPlugin + Log.debug("Manual init of BookmarkPlugin"); + bookmarkPlugin = new BookmarkPlugin(); + bookmarkPlugin.initialize(); + + Log.debug("Done with manual plugin inits"); + + // Schedule the loading of the plugins after two seconds. + TaskEngine.getInstance().schedule(new TimerTask() { + @Override + public void run() { + Log.debug("Initializing plugin manager"); + final PluginManager pluginManager = PluginManager.getInstance(); + Log.debug("Add main window listener"); + SparkManager.getMainWindow().addMainWindowListener(pluginManager); + Log.debug("Initializing plugins"); + pluginManager.initializePlugins(); + // Subscriptions are always manual + Log.debug("Set roster mode"); + Roster roster = SparkManager.getRoster(); + roster.setSubscriptionMode(Roster.SubscriptionMode.manual); + } + }, 2000); + + // Check URI Mappings + SparkManager.getUriManager().handleURIMapping(Spark.ARGUMENTS, true); + } + + + /** + * Returns the status box for the User. + */ + public StatusBar getStatusBar() { + return statusBox; + } + + /** + * This is to handle agent-to-agent conversations. + * + * @param stanza the smack packet to process. + */ + @Override + public void processStanza(final Stanza stanza) { + SwingUtilities.invokeLater( () -> { + try + { + handleIncomingPacket(stanza); + } + catch ( Throwable e ) + { + Log.warning( "Unable to handle incoming stanza: " + stanza , e ); + } + } ); + } + + + private void handleIncomingPacket(Stanza stanza) throws SmackException.NotConnectedException, InterruptedException + { + // We only handle message packets here. + if (!(stanza instanceof Message)) { + return; + } + final Message message = (Message)stanza; + boolean isGroupChat = message.getType() == Message.Type.groupchat; + // Check if Conference invite. If so, do not handle here. + if (message.hasExtension(GroupChatInvitation.class)) { + return; + } + + final String body = message.getBody(); + final JivePropertiesExtension extension = message.getExtension( JivePropertiesExtension.class ); + final boolean broadcast = extension != null && extension.getProperty( "broadcast" ) != null; + + // Handle offline message. + DelayInformation offlineInformation = message.getExtension(DelayInformation.class); + if (offlineInformation != null && (Message.Type.chat == message.getType() || + Message.Type.normal == message.getType())) { + handleOfflineMessage(message); + } + + if (body == null || + isGroupChat || + broadcast || + message.getType() == Message.Type.normal || + message.getType() == Message.Type.headline || + message.getType() == Message.Type.error) { + return; + } + // Create a new chat room for Agent Invite. + final Jid from = stanza.getFrom(); + final DomainBareJid host = SparkManager.getSessionManager().getServerAddress(); + // Don't allow workgroup notifications to come through here. + final BareJid bareJID = from.asBareJid(); + if (host.equals(from)) { + return; + } + + ChatRoom room = null; + try { + room = SparkManager.getChatManager().getChatContainer().getChatRoom(bareJID); + } + catch (ChatRoomNotFoundException ignored) { + } + // Check for non-existent rooms. + if (room == null) { + EntityBareJid entityBareJid = bareJID.asEntityBareJidIfPossible(); + if (entityBareJid != null) { + createOneToOneRoom(entityBareJid, message); + } + } + } + + /** + * Creates a new room if necessary and inserts an offline message. + * + * @param message The Offline message. + */ + private void handleOfflineMessage(Message message) throws SmackException.NotConnectedException, InterruptedException + { + if(!ModelUtil.hasLength(message.getBody())){ + return; + } + + EntityBareJid bareJID = message.getFrom().asEntityBareJidIfPossible(); + if (bareJID == null) { + return; + } + + String nickname = null; + ContactItem contact = contactList.getContactItemByJID(bareJID); + if (contact != null) { + nickname = contact.getDisplayName(); + } else { + Localpart localpart = bareJID.getLocalpartOrNull(); + if (localpart != null) { + nickname = localpart.toString(); + } + } + // Create the room if it does not exist.; + ChatRoom room = SparkManager.getChatManager().createChatRoom(bareJID, nickname, nickname); + if (!SparkManager.getChatManager().getChatContainer().getChatFrame().isVisible()) { + SparkManager.getChatManager().getChatContainer().getChatFrame().setVisible(true); + } + // Insert offline message + room.getTranscriptWindow().insertMessage(nickname, message, ChatManager.FROM_COLOR); + room.addToTranscript(message, true); + // Save the message to history immediately. + SparkManager.getWorkspace().getTranscriptPlugin().persistChatRoom(room); + // Send display and notified message back. + SparkManager.getMessageEventManager().sendDeliveredNotification(message.getFrom(), message.getStanzaId()); + SparkManager.getMessageEventManager().sendDisplayedNotification(message.getFrom(), message.getStanzaId()); + } + + /** + * Creates a new room based on an anonymous user. + * + * @param bareJID the bare JID of the anonymous user. + * @param message the message from the anonymous user. + */ + private void createOneToOneRoom(EntityBareJid bareJID, Message message) { + String nickname = null; + ContactItem contact = contactList.getContactItemByJID(bareJID); + if (contact != null) { + nickname = contact.getDisplayName(); + } else { + Localpart localpart = bareJID.getLocalpartOrNull(); + if (localpart != null) { + nickname = localpart.toString(); + } + } + if (nickname == null) { + // Attempt to load VCard from users who we are not subscribed to. + VCard vCard = SparkManager.getVCardManager().getVCard(bareJID); + if (vCard != null && vCard.getError() == null) { + String fullName = vCard.getField("FN"); + String userNickname = vCard.getNickName(); + if (ModelUtil.hasLength(userNickname)) { + nickname = userNickname; + } + else if (ModelUtil.hasLength(fullName)) { + nickname = fullName; + } + } + } + + SparkManager.getChatManager().createChatRoom(bareJID, nickname, nickname); + try { + insertMessage(bareJID, message); + } + catch (ChatRoomNotFoundException e) { + Log.error("Could not find chat room.", e); + } + } + + + private void insertMessage(final BareJid bareJID, final Message message) throws ChatRoomNotFoundException { + ChatRoom chatRoom = SparkManager.getChatManager().getChatContainer().getChatRoom(bareJID); + chatRoom.insertMessage(message); + int chatLength = chatRoom.getTranscriptWindow().getDocument().getLength(); + chatRoom.getTranscriptWindow().setCaretPosition(chatLength); + chatRoom.getChatInputEditor().requestFocusInWindow(); + } + + + /** + * Returns the Workspace TabbedPane. If you wish to add your + * component, simply use addTab(name, icon, component) call. + */ + public SparkTabbedPane getWorkspacePane() { + return workspacePane; + } + + /** + * Returns the ContactList associated with this workspace. + */ + public ContactList getContactList() { + return contactList; + } + + public void changeCardLayout(String layout) { + cardLayout.show(cardPanel, layout); + } + + public JPanel getCardPanel() { + return cardPanel; + } + + /** + * Returns the CommandPanel of this Workspace. + */ + public CommandPanel getCommandPanel() { + return statusBox.getCommandPanel(); + } + + public ChatTranscriptPlugin getTranscriptPlugin() { + return transcriptPlugin; + } +} diff --git a/src/java/org/jivesoftware/spark/component/AutoCompleteDocument.java b/core/src/main/java/org/jivesoftware/spark/component/AutoCompleteDocument.java similarity index 89% rename from src/java/org/jivesoftware/spark/component/AutoCompleteDocument.java rename to core/src/main/java/org/jivesoftware/spark/component/AutoCompleteDocument.java index 621a6c73c..6bc0fe3cd 100644 --- a/src/java/org/jivesoftware/spark/component/AutoCompleteDocument.java +++ b/core/src/main/java/org/jivesoftware/spark/component/AutoCompleteDocument.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,8 +29,8 @@ public class AutoCompleteDocument extends PlainDocument { private static final long serialVersionUID = -6198560336890706214L; - private List dictionary = new ArrayList<>(); - private JTextComponent comp; + private final List dictionary = new ArrayList<>(); + private final JTextComponent comp; public AutoCompleteDocument(JTextComponent field, String[] aDictionary) { comp = field; @@ -45,7 +41,8 @@ public void addDictionaryEntry(String item) { dictionary.add(item); } - public void insertString(int offs, String str, AttributeSet a) + @Override + public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { super.insertString(offs, str, a); String word = autoComplete(getText(0, getLength())); @@ -57,8 +54,7 @@ public void insertString(int offs, String str, AttributeSet a) } public String autoComplete(String text) { - for (Object aDictionary : dictionary) { - String word = (String) aDictionary; + for (String word : dictionary) { if (word.startsWith(text)) { return word.substring(text.length()); } @@ -81,7 +77,7 @@ public static JTextField createAutoCompleteTextField(String[] dictionary) { return field; } - public static void main(String args[]) { + public static void main(String[] args) { javax.swing.JFrame frame = new javax.swing.JFrame("foo"); frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE); String[] dict = {"auto", "automobile", "autocrat", "graduation"}; @@ -94,4 +90,4 @@ public static void main(String args[]) { frame.getContentPane().add(field); frame.setVisible(true); } -} \ No newline at end of file +} diff --git a/src/java/org/jivesoftware/spark/component/BackgroundPanel.java b/core/src/main/java/org/jivesoftware/spark/component/BackgroundPanel.java similarity index 94% rename from src/java/org/jivesoftware/spark/component/BackgroundPanel.java rename to core/src/main/java/org/jivesoftware/spark/component/BackgroundPanel.java index 545d91f8c..cf4f43526 100644 --- a/src/java/org/jivesoftware/spark/component/BackgroundPanel.java +++ b/core/src/main/java/org/jivesoftware/spark/component/BackgroundPanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -44,7 +40,8 @@ public BackgroundPanel() { } - public void paintComponent(Graphics g) { + @Override + public void paintComponent(Graphics g) { final Image backgroundImage = Default.getImageIcon(Default.TOP_BOTTOM_BACKGROUND_IMAGE).getImage(); double scaleX = getWidth() / (double)backgroundImage.getWidth(null); double scaleY = getHeight() / (double)backgroundImage.getHeight(null); diff --git a/src/java/org/jivesoftware/spark/component/CheckBoxList.java b/core/src/main/java/org/jivesoftware/spark/component/CheckBoxList.java similarity index 92% rename from src/java/org/jivesoftware/spark/component/CheckBoxList.java rename to core/src/main/java/org/jivesoftware/spark/component/CheckBoxList.java index 418db771a..0841be55d 100644 --- a/src/java/org/jivesoftware/spark/component/CheckBoxList.java +++ b/core/src/main/java/org/jivesoftware/spark/component/CheckBoxList.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,8 +32,8 @@ */ public class CheckBoxList extends JPanel { private static final long serialVersionUID = 4145933151755357313L; - private Map valueMap = new HashMap<>(); - private JPanel internalPanel = new JPanel(); + private final Map valueMap = new HashMap<>(); + private final JPanel internalPanel = new JPanel(); /** * Create the CheckBoxList UI. diff --git a/src/java/org/jivesoftware/spark/component/CheckNode.java b/core/src/main/java/org/jivesoftware/spark/component/CheckNode.java similarity index 94% rename from src/java/org/jivesoftware/spark/component/CheckNode.java rename to core/src/main/java/org/jivesoftware/spark/component/CheckNode.java index c04dcb7c2..dcd47020d 100644 --- a/src/java/org/jivesoftware/spark/component/CheckNode.java +++ b/core/src/main/java/org/jivesoftware/spark/component/CheckNode.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -137,9 +133,9 @@ public void setSelected(boolean isSelected) { if (selectionMode == DIG_IN_SELECTION && children != null) { - Enumeration nodeEnum = children.elements(); + Enumeration nodeEnum = children.elements(); while (nodeEnum.hasMoreElements()) { - CheckNode node = nodeEnum.nextElement(); + CheckNode node = (CheckNode) nodeEnum.nextElement(); node.setSelected(isSelected); } } @@ -159,7 +155,8 @@ public boolean isSelected() { * * @return the associated object. */ - public Object getAssociatedObject() { + @Override + public Object getAssociatedObject() { return associatedObject; } @@ -168,7 +165,8 @@ public Object getAssociatedObject() { * * @param associatedObject the associated object set. */ - public void setAssociatedObject(Object associatedObject) { + @Override + public void setAssociatedObject(Object associatedObject) { this.associatedObject = associatedObject; } } diff --git a/src/java/org/jivesoftware/spark/component/CheckRenderer.java b/core/src/main/java/org/jivesoftware/spark/component/CheckRenderer.java similarity index 89% rename from src/java/org/jivesoftware/spark/component/CheckRenderer.java rename to core/src/main/java/org/jivesoftware/spark/component/CheckRenderer.java index c4fbdbd00..b941b4949 100644 --- a/src/java/org/jivesoftware/spark/component/CheckRenderer.java +++ b/core/src/main/java/org/jivesoftware/spark/component/CheckRenderer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,8 +37,8 @@ */ public class CheckRenderer extends JPanel implements TreeCellRenderer { private static final long serialVersionUID = 687507314190933733L; - private JCheckBox check; - private TreeLabel label; + private final JCheckBox check; + private final TreeLabel label; /** * Create new CheckRenderer. @@ -55,7 +51,8 @@ public CheckRenderer() { label.setForeground(UIManager.getColor("Tree.textForeground")); } - public Component getTreeCellRendererComponent(JTree tree, Object value, + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row, boolean hasFocus) { String stringValue = tree.convertValueToText(value, isSelected, @@ -79,14 +76,15 @@ else if (expanded) { return this; } - public Dimension getPreferredSize() { + @Override + public Dimension getPreferredSize() { Dimension d_check = new Dimension(30, 30); Dimension d_label = label.getPreferredSize(); - return new Dimension(d_check.width + d_label.width, - d_check.height < d_label.height ? d_label.height : d_check.height); + return new Dimension(d_check.width + d_label.width, Math.max(d_check.height, d_label.height)); } - public void doLayout() { + @Override + public void doLayout() { Dimension d_check = check.getPreferredSize(); Dimension d_label = label.getPreferredSize(); int y_check = 0; @@ -104,7 +102,8 @@ public void doLayout() { } - public void setBackground(Color color) { + @Override + public void setBackground(Color color) { if (color instanceof ColorUIResource) color = null; super.setBackground(color); @@ -114,7 +113,7 @@ public void setBackground(Color color) { /** * Represents one UI node for the checkbox node. */ - public class TreeLabel extends JLabel { + public static class TreeLabel extends JLabel { private static final long serialVersionUID = -6367572474576692556L; boolean isSelected; boolean hasFocus; @@ -125,13 +124,15 @@ public class TreeLabel extends JLabel { public TreeLabel() { } - public void setBackground(Color color) { + @Override + public void setBackground(Color color) { if (color instanceof ColorUIResource) color = null; super.setBackground(color); } - public void paint(Graphics g) { + @Override + public void paint(Graphics g) { String str; if ((str = getText()) != null) { if (0 < str.length()) { @@ -157,7 +158,8 @@ public void paint(Graphics g) { super.paint(g); } - public Dimension getPreferredSize() { + @Override + public Dimension getPreferredSize() { Dimension retDimension = super.getPreferredSize(); if (retDimension != null) { retDimension = new Dimension(retDimension.width + 3, diff --git a/src/java/org/jivesoftware/spark/component/CheckTree.java b/core/src/main/java/org/jivesoftware/spark/component/CheckTree.java similarity index 79% rename from src/java/org/jivesoftware/spark/component/CheckTree.java rename to core/src/main/java/org/jivesoftware/spark/component/CheckTree.java index 4bc955079..646289b05 100644 --- a/src/java/org/jivesoftware/spark/component/CheckTree.java +++ b/core/src/main/java/org/jivesoftware/spark/component/CheckTree.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,7 +37,7 @@ */ public class CheckTree extends JPanel { private static final long serialVersionUID = 8452107824029515678L; - private JTree tree; + private final JTree tree; /** * Constructs a new CheckBox tree. @@ -62,14 +58,15 @@ public CheckTree(CheckNode rootNode) { } - class NodeSelectionListener extends MouseAdapter { - JTree tree; + static class NodeSelectionListener extends MouseAdapter { + private final JTree tree; NodeSelectionListener(JTree tree) { this.tree = tree; } - public void mouseClicked(MouseEvent e) { + @Override + public void mouseClicked(MouseEvent e) { int x = e.getX(); int y = e.getY(); int row = tree.getRowForLocation(x, y); @@ -78,44 +75,28 @@ public void mouseClicked(MouseEvent e) { CheckNode node = (CheckNode)path.getLastPathComponent(); boolean isSelected = !node.isSelected(); node.setSelected(isSelected); - if (node.getSelectionMode() == CheckNode.DIG_IN_SELECTION) { - if (isSelected) { - //tree.expandPath(path); - } - else { - //tree.collapsePath(path); - } - } ((DefaultTreeModel)tree.getModel()).nodeChanged(node); // I need revalidate if node is root. but why? - tree.revalidate(); tree.repaint(); - } } } - /** - * Closes the CheckTree. - */ - public void close() { - } - - - class ButtonActionListener implements ActionListener { - CheckNode root; - JTextArea textArea; + static class ButtonActionListener implements ActionListener { + private final CheckNode root; + private final JTextArea textArea; ButtonActionListener(CheckNode root, JTextArea textArea) { this.root = root; this.textArea = textArea; } - public void actionPerformed(ActionEvent e) { - Enumeration nodeEnum = root.breadthFirstEnumeration(); + @Override + public void actionPerformed(ActionEvent e) { + Enumeration nodeEnum = root.breadthFirstEnumeration(); while (nodeEnum.hasMoreElements()) { - CheckNode node = nodeEnum.nextElement(); + CheckNode node = (CheckNode) nodeEnum.nextElement(); if (node.isSelected()) { TreeNode[] nodes = node.getPath(); textArea.append("\n" + nodes[0].toString()); diff --git a/src/java/org/jivesoftware/spark/component/ConfirmDialog.java b/core/src/main/java/org/jivesoftware/spark/component/ConfirmDialog.java similarity index 93% rename from src/java/org/jivesoftware/spark/component/ConfirmDialog.java rename to core/src/main/java/org/jivesoftware/spark/component/ConfirmDialog.java index eb861fc25..d127ba977 100644 --- a/src/java/org/jivesoftware/spark/component/ConfirmDialog.java +++ b/core/src/main/java/org/jivesoftware/spark/component/ConfirmDialog.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -42,10 +38,10 @@ */ public class ConfirmDialog extends BackgroundPanel { private static final long serialVersionUID = -441250586899776207L; - private JLabel message; - private JLabel iconLabel; - private JButton yesButton; - private JButton noButton; + private final JLabel message; + private final JLabel iconLabel; + private final JButton yesButton; + private final JButton noButton; private ConfirmListener listener = null; private JDialog dialog; @@ -87,7 +83,7 @@ public ConfirmDialog() { * @param text the main text to display. * @param yesText the text to use on the OK or Yes button. * @param noText the text to use on the No button. - * @param icon the icon to use for graphical represenation. + * @param icon the icon to use for graphical representation. */ public void showConfirmDialog(JFrame parent, String title, String text, String yesText, String noText, Icon icon) { message.setText("" + text + ""); @@ -104,7 +100,8 @@ public void showConfirmDialog(JFrame parent, String title, String text, String y dialog.setVisible(true); dialog.addWindowListener(new WindowAdapter() { - public void windowClosed(WindowEvent windowEvent) { + @Override + public void windowClosed(WindowEvent windowEvent) { if (listener != null) { listener.noOption(); } diff --git a/src/java/org/jivesoftware/spark/component/DroppableFrame.java b/core/src/main/java/org/jivesoftware/spark/component/DroppableFrame.java similarity index 75% rename from src/java/org/jivesoftware/spark/component/DroppableFrame.java rename to core/src/main/java/org/jivesoftware/spark/component/DroppableFrame.java index 16b3fc3ff..2cb680df8 100644 --- a/src/java/org/jivesoftware/spark/component/DroppableFrame.java +++ b/core/src/main/java/org/jivesoftware/spark/component/DroppableFrame.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -55,48 +51,57 @@ protected DroppableFrame() { dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this); } - public void dragDropEnd(DragSourceDropEvent DragSourceDropEvent) { + @Override + public void dragDropEnd(DragSourceDropEvent DragSourceDropEvent) { } - public void dragEnter(DragSourceDragEvent DragSourceDragEvent) { + @Override + public void dragEnter(DragSourceDragEvent DragSourceDragEvent) { } - public void dragExit(DragSourceEvent DragSourceEvent) { + @Override + public void dragExit(DragSourceEvent DragSourceEvent) { } - public void dragOver(DragSourceDragEvent DragSourceDragEvent) { + @Override + public void dragOver(DragSourceDragEvent DragSourceDragEvent) { } - public void dropActionChanged(DragSourceDragEvent DragSourceDragEvent) { + @Override + public void dropActionChanged(DragSourceDragEvent DragSourceDragEvent) { } - public void dragEnter(DropTargetDragEvent dropTargetDragEvent) { + @Override + public void dragEnter(DropTargetDragEvent dropTargetDragEvent) { dropTargetDragEvent.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE); } - public void dragExit(DropTargetEvent dropTargetEvent) { + @Override + public void dragExit(DropTargetEvent dropTargetEvent) { } - public void dragOver(DropTargetDragEvent dropTargetDragEvent) { + @Override + public void dragOver(DropTargetDragEvent dropTargetDragEvent) { } - public void dropActionChanged(DropTargetDragEvent dropTargetDragEvent) { + @Override + public void dropActionChanged(DropTargetDragEvent dropTargetDragEvent) { } - public void drop(DropTargetDropEvent dropTargetDropEvent) { + @Override + public void drop(DropTargetDropEvent dropTargetDropEvent) { try { Transferable transferable = dropTargetDropEvent.getTransferable(); if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { dropTargetDropEvent.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); List fileList = (List) transferable.getTransferData(DataFlavor.javaFileListFlavor); for (File aFileList : fileList) { - File file = aFileList; - if (file.isFile()) { - fileDropped(file); + if (aFileList.isFile()) { + fileDropped(aFileList); } - if (file.isDirectory()) { - directoryDropped(file); + if (aFileList.isDirectory()) { + directoryDropped(aFileList); } } dropTargetDropEvent.getDropTargetContext().dropComplete(true); @@ -112,7 +117,8 @@ public void drop(DropTargetDropEvent dropTargetDropEvent) { } - public void dragGestureRecognized(DragGestureEvent dragGestureEvent) { + @Override + public void dragGestureRecognized(DragGestureEvent dragGestureEvent) { } @@ -129,4 +135,4 @@ public void dragGestureRecognized(DragGestureEvent dragGestureEvent) { * @param file the directory that has been dropped. */ public abstract void directoryDropped(File file); -} \ No newline at end of file +} diff --git a/src/java/org/jivesoftware/spark/component/FileDragLabel.java b/core/src/main/java/org/jivesoftware/spark/component/FileDragLabel.java similarity index 76% rename from src/java/org/jivesoftware/spark/component/FileDragLabel.java rename to core/src/main/java/org/jivesoftware/spark/component/FileDragLabel.java index 3e0062feb..95c7d0e09 100644 --- a/src/java/org/jivesoftware/spark/component/FileDragLabel.java +++ b/core/src/main/java/org/jivesoftware/spark/component/FileDragLabel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,7 +33,6 @@ import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.io.File; -import java.io.IOException; import java.io.StringReader; import java.util.Vector; @@ -61,35 +56,45 @@ public void setFile(File file) { this.file = file; } - public void dragDropEnd(DragSourceDropEvent DragSourceDropEvent) { + @Override + public void dragDropEnd(DragSourceDropEvent DragSourceDropEvent) { } - public void dragEnter(DragSourceDragEvent DragSourceDragEvent) { + @Override + public void dragEnter(DragSourceDragEvent DragSourceDragEvent) { } - public void dragExit(DragSourceEvent DragSourceEvent) { + @Override + public void dragExit(DragSourceEvent DragSourceEvent) { } - public void dragOver(DragSourceDragEvent DragSourceDragEvent) { + @Override + public void dragOver(DragSourceDragEvent DragSourceDragEvent) { } - public void dropActionChanged(DragSourceDragEvent DragSourceDragEvent) { + @Override + public void dropActionChanged(DragSourceDragEvent DragSourceDragEvent) { } - public void dragEnter(DropTargetDragEvent dropTargetDragEvent) { + @Override + public void dragEnter(DropTargetDragEvent dropTargetDragEvent) { dropTargetDragEvent.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE); } - public void dragExit(DropTargetEvent dropTargetEvent) { + @Override + public void dragExit(DropTargetEvent dropTargetEvent) { } - public void dragOver(DropTargetDragEvent dropTargetDragEvent) { + @Override + public void dragOver(DropTargetDragEvent dropTargetDragEvent) { } - public void dropActionChanged(DropTargetDragEvent dropTargetDragEvent) { + @Override + public void dropActionChanged(DropTargetDragEvent dropTargetDragEvent) { } - public synchronized void drop(DropTargetDropEvent dropTargetDropEvent) { + @Override + public synchronized void drop(DropTargetDropEvent dropTargetDropEvent) { try { final Transferable transferable = dropTargetDropEvent.getTransferable(); if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { @@ -106,7 +111,8 @@ public synchronized void drop(DropTargetDropEvent dropTargetDropEvent) { } } - public void dragGestureRecognized(DragGestureEvent dragGestureEvent) { + @Override + public void dragGestureRecognized(DragGestureEvent dragGestureEvent) { if (file == null) { // Nothing selected, nothing to drag getToolkit().beep(); @@ -122,7 +128,8 @@ private class FileSelection extends Vector implements Transferable { private final static int FILE = 0; private final static int STRING = 1; private final static int PLAIN = 2; - DataFlavor flavors[] = {DataFlavor.javaFileListFlavor, + private final DataFlavor[] flavors = { + DataFlavor.javaFileListFlavor, DataFlavor.stringFlavor, DataFlavor.getTextPlainUnicodeFlavor()}; @@ -131,12 +138,14 @@ public FileSelection(File file) { } - public synchronized DataFlavor[] getTransferDataFlavors() { + @Override + public synchronized DataFlavor[] getTransferDataFlavors() { return flavors; } - public boolean isDataFlavorSupported(DataFlavor flavor) { + @Override + public boolean isDataFlavorSupported(DataFlavor flavor) { boolean b = false; b = b | flavor.equals(flavors[FILE]); b |= flavor.equals(flavors[STRING]); @@ -145,8 +154,9 @@ public boolean isDataFlavorSupported(DataFlavor flavor) { } - public synchronized Object getTransferData(DataFlavor flavor) - throws UnsupportedFlavorException, IOException { + @Override + public synchronized Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException { if (flavor.equals(flavors[FILE])) { return this; } @@ -162,7 +172,7 @@ else if (flavor.equals(flavors[STRING])) { } } - public static void main(String args[]) { + public static void main(String[] args) { JFrame f = new JFrame(); FileDragLabel p = new FileDragLabel(); f.add(p); diff --git a/src/java/org/jivesoftware/spark/component/HTMLViewer.java b/core/src/main/java/org/jivesoftware/spark/component/HTMLViewer.java similarity index 96% rename from src/java/org/jivesoftware/spark/component/HTMLViewer.java rename to core/src/main/java/org/jivesoftware/spark/component/HTMLViewer.java index 9d810631e..9a89d34a4 100644 --- a/src/java/org/jivesoftware/spark/component/HTMLViewer.java +++ b/core/src/main/java/org/jivesoftware/spark/component/HTMLViewer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,7 +35,7 @@ */ public class HTMLViewer extends JPanel { private static final long serialVersionUID = 4938398130343609958L; - private JEditorPane browser; + private final JEditorPane browser; /** @@ -98,7 +94,8 @@ public String getSelectedText() { * * @return the preferred dimension */ - public Dimension getPreferredSize() { + @Override + public Dimension getPreferredSize() { final Dimension size = super.getPreferredSize(); size.width = 0; return size; diff --git a/src/java/org/jivesoftware/spark/component/IconTextField.java b/core/src/main/java/org/jivesoftware/spark/component/IconTextField.java similarity index 76% rename from src/java/org/jivesoftware/spark/component/IconTextField.java rename to core/src/main/java/org/jivesoftware/spark/component/IconTextField.java index 13843a5dc..7a05d44d8 100644 --- a/src/java/org/jivesoftware/spark/component/IconTextField.java +++ b/core/src/main/java/org/jivesoftware/spark/component/IconTextField.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,27 +17,24 @@ import org.jivesoftware.resource.SparkRes; -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.UIManager; +import javax.swing.*; import java.awt.Color; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; +import javax.swing.plaf.basic.BasicTextFieldUI; /** - * Creates a Firefox Search type box that allows for icons inside of a textfield. This - * could be used to build out your own search objects. + * Creates a Firefox Search type box that allows for icons inside of a + * textfield. This could be used to build out your own search objects. */ public class IconTextField extends JPanel { + private static final long serialVersionUID = -7000758637988415370L; - private JTextField textField; - private JLabel imageComponent; - private JLabel downOption; + private final JTextField textField; + private final JLabel imageComponent; + private final JLabel downOption; /** * Creates a new IconTextField with Icon. @@ -50,16 +43,17 @@ public class IconTextField extends JPanel { */ public IconTextField(Icon icon) { setLayout(new GridBagLayout()); - setBackground((Color)UIManager.get("TextField.background")); + setBackground((Color) UIManager.get("TextField.background")); textField = new JTextField(); - textField.setBorder(null); - setBorder(new JTextField().getBorder()); - + textField.setUI(new BasicTextFieldUI()); + textField.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); + //setBorder(new JTextField().getBorder()); + this.setBorder(BorderFactory.createLineBorder(Color.lightGray)); imageComponent = new JLabel(icon); - downOption = new JLabel(SparkRes.getImageIcon(SparkRes.DOWN_OPTION_IMAGE)); + downOption = new JLabel(SparkRes.getImageIcon(SparkRes.Icon.DOWN_OPTION_IMAGE)); - add(downOption, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTHEAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + add(downOption, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); add(imageComponent, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); add(textField, new GridBagConstraints(2, 0, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 5, 0, 0), 0, 0)); @@ -123,10 +117,8 @@ public JComponent getImageComponent() { public JTextField getTextComponent() { return textField; } -} - - - - - + public JLabel getDownOption() { + return downOption; + } +} diff --git a/src/java/org/jivesoftware/spark/component/ImageTitlePanel.java b/core/src/main/java/org/jivesoftware/spark/component/ImageTitlePanel.java similarity index 97% rename from src/java/org/jivesoftware/spark/component/ImageTitlePanel.java rename to core/src/main/java/org/jivesoftware/spark/component/ImageTitlePanel.java index 09e46021c..f1e8029ad 100644 --- a/src/java/org/jivesoftware/spark/component/ImageTitlePanel.java +++ b/core/src/main/java/org/jivesoftware/spark/component/ImageTitlePanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,7 +37,7 @@ */ public class ImageTitlePanel extends JPanel { private static final long serialVersionUID = -4942953711496567252L; - private Image backgroundImage; + private final Image backgroundImage; private final JLabel titleLabel = new JLabel(); private final JLabel iconLabel = new JLabel(); private final GridBagLayout gridBagLayout = new GridBagLayout(); @@ -74,7 +70,8 @@ public ImageTitlePanel() { titleLabel.setFont(new Font("Dialog", Font.BOLD, 11)); } - public void paintComponent(Graphics g) { + @Override + public void paintComponent(Graphics g) { double scaleX = getWidth() / (double)backgroundImage.getWidth(null); double scaleY = getHeight() / (double)backgroundImage.getHeight(null); AffineTransform xform = AffineTransform.getScaleInstance(scaleX, scaleY); @@ -169,4 +166,4 @@ public void setIcon(ImageIcon icon) { new GridBagConstraints(2, 0, 1, 1, 1.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); } -} \ No newline at end of file +} diff --git a/src/java/org/jivesoftware/spark/component/InputDialog.java b/core/src/main/java/org/jivesoftware/spark/component/InputDialog.java similarity index 93% rename from src/java/org/jivesoftware/spark/component/InputDialog.java rename to core/src/main/java/org/jivesoftware/spark/component/InputDialog.java index f35164c05..468b8e2fe 100644 --- a/src/java/org/jivesoftware/spark/component/InputDialog.java +++ b/core/src/main/java/org/jivesoftware/spark/component/InputDialog.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -117,7 +113,8 @@ public String getInput(String title, String description, Icon icon, Component pa // Add Key Listener to Send Field textArea.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { + @Override + public void keyPressed(KeyEvent e) { if (e.getKeyChar() == KeyEvent.VK_TAB) { optionPane.requestFocus(); } @@ -141,6 +138,7 @@ else if (e.getKeyChar() == KeyEvent.VK_ESCAPE) { public Action nextFocusAction = new AbstractAction("Move Focus Forwards") { private static final long serialVersionUID = 1L; + @Override public void actionPerformed(ActionEvent evt) { ((Component)evt.getSource()).transferFocus(); } @@ -152,26 +150,25 @@ public void actionPerformed(ActionEvent evt) { public Action prevFocusAction = new AbstractAction("Move Focus Backwards") { private static final long serialVersionUID = 1L; + @Override public void actionPerformed(ActionEvent evt) { ((Component)evt.getSource()).transferFocusBackward(); } }; - public void propertyChange(PropertyChangeEvent e) { + @Override + public void propertyChange(PropertyChangeEvent e) { String value = (String)optionPane.getValue(); if (Res.getString("cancel").equals(value)) { stringValue = null; dialog.setVisible(false); } else if (Res.getString("ok").equals(value)) { - stringValue = textArea.getText(); - if (stringValue.trim().length() == 0) { + stringValue = textArea.getText().trim(); + if (stringValue.isEmpty()) { stringValue = null; } - else { - stringValue = stringValue.trim(); - } dialog.setVisible(false); } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jivesoftware/spark/component/JContactItemField.java b/core/src/main/java/org/jivesoftware/spark/component/JContactItemField.java new file mode 100644 index 000000000..209e92a09 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/component/JContactItemField.java @@ -0,0 +1,328 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.component; + +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.spark.util.ModelUtil; +import static org.jivesoftware.spark.util.StringUtils.replaceSpecialLetters; + +import javax.swing.DefaultListModel; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.JWindow; +import javax.swing.ListCellRenderer; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Point; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; + +/** + * Implementation of a popup field from a TextField. + * + * @author Derek DeMoro + */ +public class JContactItemField extends JPanel { + + private static final long serialVersionUID = -8556694682789891531L; + private final JTextField textField = new JTextField(); + private final DefaultListModel model = new DefaultListModel<>(); + private final JList list; + private final JWindow popup; + private List items; + + public JContactItemField(List items) { + setLayout(new BorderLayout()); + list = new JList(model) { + private static final long serialVersionUID = -9031169221430835595L; + + @Override + public String getToolTipText(MouseEvent e) { + int row = locationToIndex(e.getPoint()); + if (row >= 0) + { + final ContactItem item = getModel().getElementAt(row); + if (item != null) { + return item.getJid().toString(); + } + } + return null; + } + }; + + this.items = items; + + add(textField, BorderLayout.CENTER); + + + textField.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent keyEvent) { + char ch = keyEvent.getKeyChar(); + if (validateChar(ch)) { + showPopupMenu(); + } + + if (keyEvent.getKeyCode() == KeyEvent.VK_ENTER) { + int index = list.getSelectedIndex(); + if (index >= 0) { + ContactItem selection = list.getSelectedValue(); + textField.setText(selection.getDisplayName()); + popup.setVisible(false); + } + } + + if (keyEvent.getKeyCode() == KeyEvent.VK_ESCAPE) { + popup.setVisible(false); + } + dispatchEvent(keyEvent); + } + + @Override + public void keyPressed(KeyEvent e) { + if (isArrowKey(e)) { + list.dispatchEvent(e); + } + + } + }); + + + textField.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + } + + @Override + public void focusLost(FocusEvent e) { + textField.requestFocusInWindow(); + } + }); + + + popup = new JWindow(); + + + popup.getContentPane().add(new JScrollPane(list)); + popup.setAlwaysOnTop(true); + + + list.setCellRenderer(new PopupRenderer()); + list.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + int index = list.getSelectedIndex(); + if (index >= 0) { + ContactItem selection = list.getSelectedValue(); + textField.setText(selection.getDisplayName()); + popup.setVisible(false); + } + } + } + }); + } + + public void dispose() { + popup.dispose(); + } + + public void setItems(List list) { + this.items = list; + } + + public JList getList() { + return list; + } + + private void showPopupMenu() { + model.removeAllElements(); + + String typedItem = replaceSpecialLetters(textField.getText()); + + final List validItems = new ArrayList<>(); + for (ContactItem contactItem : items) { + String nickname = replaceSpecialLetters(contactItem.getDisplayName().toLowerCase()); + if (nickname.startsWith(typedItem.toLowerCase())) { + validItems.add(contactItem); + } else if (typedItem.length() > 2 && nickname.contains(typedItem.toLowerCase())) { + validItems.add(contactItem); + } + } + + + if (validItems.size() > 0) { + for (final ContactItem label : validItems) { + model.addElement(label); + } + } + + if (validItems.size() != 0) { + popup.pack(); + if(validItems.size()*16<=SparkManager.getContactList().getHeight()-SparkManager.getSearchManager().getSearchServiceUI().getHeight()-14){ + popup.setSize(textField.getWidth(), validItems.size()*16+5); + }else{ + popup.setSize(textField.getWidth(), SparkManager.getContactList().getHeight()-SparkManager.getSearchManager().getSearchServiceUI().getHeight()-14); + } + Point pt = textField.getLocationOnScreen(); + pt.translate(0, textField.getHeight()); + popup.setLocation(pt); + popup.toFront(); + popup.setVisible(true); + } + + // set initial selection + if (validItems.size() > 0) { + list.setSelectedIndex(0); + } + + } + + /** + * Validate the given text - to pass it must contain letters, digits, '@', '-', '_', '.', ',' + * or a space character. + * + * @param text the text to check + * @return true if the given text is valid, false otherwise. + */ + public boolean validateChars(String text) { + if (!ModelUtil.hasLength(text)) { + return false; + } + + for (int i = 0; i < text.length(); i++) { + char ch = text.charAt(i); + if (!Character.isLetterOrDigit(ch) && ch != '@' && ch != '-' && ch != '_' + && ch != '.' && ch != ',' && ch != ' ') { + return false; + } + } + + + return true; + } + + /** + * Validate the given text - to pass it must contain letters, digits, '@', '-', '_', '.', ',' + * or a space character. + * + * @param ch the character + * @return true if the given text is valid, false otherwise. + */ + public boolean validateChar(char ch) { + return Character.isLetterOrDigit(ch) || ch == '@' || ch == '-' || ch == '_' + || ch == '.' || ch == ',' || ch == ' ' || ch == KeyEvent.VK_BACK_SPACE || ch == KeyEvent.CTRL_DOWN_MASK + || ch == KeyEvent.CTRL_MASK; + } + + public boolean isArrowKey(KeyEvent e) { + return e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN; + } + + public String getText() { + return textField.getText(); + } + + public ContactItem getSelectedContactItem() { + return list.getSelectedValue(); + } + + public void setText(String text) { + textField.setText(text); + } + + public void focus() { + textField.requestFocus(); + } + + public JTextField getTextField() { + return textField; + } + + public JWindow getPopup() { + return popup; + } + + static class PopupRenderer extends JLabel implements ListCellRenderer { + private static final long serialVersionUID = 239608430590852355L; + + /** + * Construct Default JLabelIconRenderer. + */ + public PopupRenderer() { + setOpaque(true); + this.setHorizontalTextPosition(JLabel.RIGHT); + this.setHorizontalAlignment(JLabel.LEFT); + } + + @Override + public Component getListCellRendererComponent(JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus) { + if (isSelected) { + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + } + else { + setBackground(list.getBackground()); + setForeground(list.getForeground()); + } + + + ContactItem contactItem = (ContactItem)value; + setText(contactItem.getDisplayName()); + if (contactItem.getIcon() == null) { + setIcon(SparkRes.getImageIcon(SparkRes.Icon.CLEAR_BALL_ICON)); + } + else { + setIcon(contactItem.getIcon()); + } + setFont(contactItem.getNicknameLabel().getFont()); + setForeground(contactItem.getForeground()); + + return this; + } + } + + public boolean canClose() { + return !textField.hasFocus(); + } + + /** + * sets the selected Index using the Point of a given {@link MouseEvent} + * @param mouseevent - {@link MouseEvent} to get The {@link Point} from + */ + public void setSelectetIndex(MouseEvent mouseevent) + { + list.setSelectedIndex(list.locationToIndex(mouseevent.getPoint())); + } + + +} diff --git a/src/java/org/jivesoftware/spark/component/JMultilineLabel.java b/core/src/main/java/org/jivesoftware/spark/component/JMultilineLabel.java similarity index 93% rename from src/java/org/jivesoftware/spark/component/JMultilineLabel.java rename to core/src/main/java/org/jivesoftware/spark/component/JMultilineLabel.java index c49538df5..d6b65f863 100644 --- a/src/java/org/jivesoftware/spark/component/JMultilineLabel.java +++ b/core/src/main/java/org/jivesoftware/spark/component/JMultilineLabel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,11 +27,12 @@ import java.awt.font.TextLayout; import java.text.AttributedCharacterIterator; import java.text.AttributedString; +import java.util.Objects; public class JMultilineLabel extends JComponent { private static final long serialVersionUID = 3061233171993075054L; private String text; - private Insets margin = new Insets(1, 1, 1, 1); + private final Insets margin = new Insets(1, 1, 1, 1); private int maxWidth = Integer.MAX_VALUE; private boolean justify; private final FontRenderContext frc = new FontRenderContext(null, false, false); @@ -53,7 +50,7 @@ public void setText(String text) { String old = this.text; this.text = text; firePropertyChange("text", old, this.text); - if ((old == null) ? text != null : !old.equals(text)) + if (!Objects.equals(old, text)) morph(); } @@ -83,15 +80,18 @@ public void setJustified(boolean justify) { repaint(); } - public Dimension getPreferredSize() { + @Override + public Dimension getPreferredSize() { return paintOrGetSize(null, getMaxWidth()); } - public Dimension getMinimumSize() { + @Override + public Dimension getMinimumSize() { return getPreferredSize(); } - protected void paintComponent(Graphics g) { + @Override + protected void paintComponent(Graphics g) { super.paintComponent(g); paintOrGetSize((Graphics2D)g, getWidth()); } diff --git a/src/java/org/jivesoftware/spark/component/JiveSortableTable.java b/core/src/main/java/org/jivesoftware/spark/component/JiveSortableTable.java similarity index 82% rename from src/java/org/jivesoftware/spark/component/JiveSortableTable.java rename to core/src/main/java/org/jivesoftware/spark/component/JiveSortableTable.java index 6e156bca4..b1e8974fa 100644 --- a/src/java/org/jivesoftware/spark/component/JiveSortableTable.java +++ b/core/src/main/java/org/jivesoftware/spark/component/JiveSortableTable.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -73,7 +69,8 @@ public abstract class JiveSortableTable extends Table { protected JiveSortableTable() { } - public String getToolTipText(MouseEvent e) { + @Override + public String getToolTipText(MouseEvent e) { int r = rowAtPoint(e.getPoint()); int c = columnAtPoint(e.getPoint()); Object value; @@ -106,7 +103,8 @@ else if (tooltipValue == null) { } // Handle image rendering correctly - public TableCellRenderer getCellRenderer(int row, int column) { + @Override + public TableCellRenderer getCellRenderer(int row, int column) { Object o = getValueAt(row, column); if (o != null) { if (o instanceof JLabel) { @@ -134,17 +132,20 @@ protected JiveSortableTable(String[] headers) { setSelectionMode(ListSelectionModel.SINGLE_SELECTION); this.addKeyListener(new KeyListener() { - public void keyPressed(KeyEvent e) { + @Override + public void keyPressed(KeyEvent e) { if (e.getKeyChar() == KeyEvent.VK_ENTER) { e.consume(); enterPressed(); } } - public void keyReleased(KeyEvent e) { + @Override + public void keyReleased(KeyEvent e) { } - public void keyTyped(KeyEvent e) { + @Override + public void keyTyped(KeyEvent e) { } }); @@ -155,7 +156,8 @@ public void keyTyped(KeyEvent e) { * * @param list the list to add to the model. */ - public void add(List list) { + @Override + public void add(List list) { for (Object aList : list) { Object[] newRow = (Object[]) aList; tableModel.addRow(newRow); @@ -167,7 +169,8 @@ public void add(List list) { * * @return the object array of a row. */ - public Object[] getSelectedRowObject() { + @Override + public Object[] getSelectedRowObject() { return getRowObject(getSelectedRow()); } @@ -177,7 +180,8 @@ public Object[] getSelectedRowObject() { * @param selectedRow the row to retrieve. * @return the object[] of a row. */ - public Object[] getRowObject(int selectedRow) { + @Override + public Object[] getRowObject(int selectedRow) { if (selectedRow < 0) { return null; } @@ -195,7 +199,8 @@ public Object[] getRowObject(int selectedRow) { /** * Removes all columns and rows from table. */ - public void clearTable() { + @Override + public void clearTable() { int rowCount = getRowCount(); for (int i = 0; i < rowCount; i++) { getTableModel().removeRow(0); @@ -207,7 +212,7 @@ public void clearTable() { */ public static class JiveTableModel extends DefaultTableModel { private static final long serialVersionUID = -8112392992589859403L; - private boolean isEditable; + private final boolean isEditable; /** * Use the JiveTableModel in order to better handle the table. This allows @@ -229,7 +234,8 @@ public JiveTableModel(Object[] columnNames, int numRows, boolean isEditable) { * @param column the column to check. * @return true if the cell is editable. */ - public boolean isCellEditable(int row, int column) { + @Override + public boolean isCellEditable(int row, int column) { return isEditable; } } @@ -237,11 +243,11 @@ public boolean isCellEditable(int row, int column) { /** * A swing renderer used to display labels within a table. */ - public class JLabelRenderer extends JLabel implements TableCellRenderer { - private static final long serialVersionUID = 8670248883432881619L; - Border unselectedBorder; - Border selectedBorder; - boolean isBordered = true; + public static class JLabelRenderer extends JLabel implements TableCellRenderer { + private static final long serialVersionUID = 8670248883432881619L; + private Border unselectedBorder; + private Border selectedBorder; + final boolean isBordered; /** * JLabelConstructor to build ui. @@ -253,7 +259,8 @@ public JLabelRenderer(boolean isBordered) { this.isBordered = isBordered; } - public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { + @Override + public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { final String text = ((JLabel)color).getText(); if (text != null) { setText(" " + text); @@ -268,9 +275,6 @@ public Component getTableCellRendererComponent(JTable table, Object color, boole else { setForeground(Color.black); setBackground(Color.white); - if (row % 2 == 0) { - //setBackground( new Color( 156, 207, 255 ) ); - } } if (isBordered) { @@ -296,8 +300,8 @@ public Component getTableCellRendererComponent(JTable table, Object color, boole /** * A swing renderer to dispaly Textareas within a table. */ - public class TextAreaCellRenderer extends JTextArea implements TableCellRenderer { - private static final long serialVersionUID = -1704445909682732833L; + public static class TextAreaCellRenderer extends JTextArea implements TableCellRenderer { + private static final long serialVersionUID = -1704445909682732833L; /** * Create new renderer with font. @@ -310,7 +314,8 @@ public TextAreaCellRenderer(Font font) { setFont(font); } - public Component getTableCellRendererComponent(JTable jTable, Object obj, boolean isSelected, boolean hasFocus, + @Override + public Component getTableCellRendererComponent(JTable jTable, Object obj, boolean isSelected, boolean hasFocus, int row, int column) { // set color & border here setText(obj == null ? "" : obj.toString()); @@ -326,11 +331,11 @@ public Component getTableCellRendererComponent(JTable jTable, Object obj, boolea /** * A swing renderer used to display Buttons within a table. */ - public class JButtonRenderer extends JButton implements TableCellRenderer { - private static final long serialVersionUID = -1847536957519732935L; - Border unselectedBorder; - Border selectedBorder; - boolean isBordered = true; + public static class JButtonRenderer extends JButton implements TableCellRenderer { + private static final long serialVersionUID = -1847536957519732935L; + private Border unselectedBorder; + private Border selectedBorder; + final boolean isBordered = true; /** * Empty Constructor. @@ -339,7 +344,8 @@ public JButtonRenderer() { } - public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { + @Override + public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { final String text = ((JButton)color).getText(); setText(text); @@ -353,9 +359,6 @@ public Component getTableCellRendererComponent(JTable table, Object color, boole else { setForeground(Color.black); setBackground(Color.white); - if (row % 2 == 0) { - //setBackground( new Color( 156, 207, 255 ) ); - } } if (isBordered) { @@ -378,7 +381,7 @@ public Component getTableCellRendererComponent(JTable table, Object color, boole } } - public class ComboBoxRenderer extends JComboBox implements TableCellRenderer { + public static class ComboBoxRenderer extends JComboBox implements TableCellRenderer { private static final long serialVersionUID = 5892858463680797611L; public ComboBoxRenderer() { @@ -389,7 +392,8 @@ public ComboBoxRenderer(String[] items) { super(items); } - public Component getTableCellRendererComponent(JTable table, Object value, + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if (isSelected) { setForeground(table.getSelectionForeground()); @@ -406,11 +410,11 @@ public Component getTableCellRendererComponent(JTable table, Object value, } } - public class MyComboBoxEditor extends DefaultCellEditor { + public static class MyComboBoxEditor extends DefaultCellEditor { private static final long serialVersionUID = 1003726653998005772L; public MyComboBoxEditor(String[] items) { - super(new JComboBox(items)); + super(new JComboBox<>(items)); } } @@ -419,14 +423,16 @@ public MyComboBoxEditor(String[] items) { * * @return the table model. */ - public Table.JiveTableModel getTableModel() { + @Override + public Table.JiveTableModel getTableModel() { return tableModel; } /** * Clears all objects from map. */ - public void clearObjectMap() { + @Override + public void clearObjectMap() { objectMap.clear(); } @@ -436,7 +442,8 @@ public void clearObjectMap() { * @param row - the current row * @param object - the object to associate with the row. */ - public void addObject(int row, Object object) { + @Override + public void addObject(int row, Object object) { objectMap.put(row, object); } @@ -446,14 +453,8 @@ public void addObject(int row, Object object) { * @param row - the row associated with the object. * @return The object associated with the row. */ - public Object getObject(int row) { + @Override + public Object getObject(int row) { return objectMap.get(row); } - - /** - * Override to handle when enter is pressed. - */ - public void enterPressed() { - } - -} \ No newline at end of file +} diff --git a/src/java/org/jivesoftware/spark/component/JiveTable.java b/core/src/main/java/org/jivesoftware/spark/component/JiveTable.java similarity index 80% rename from src/java/org/jivesoftware/spark/component/JiveTable.java rename to core/src/main/java/org/jivesoftware/spark/component/JiveTable.java index 0d8315400..b47c080db 100644 --- a/src/java/org/jivesoftware/spark/component/JiveTable.java +++ b/core/src/main/java/org/jivesoftware/spark/component/JiveTable.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,11 +37,11 @@ */ public class JiveTable extends JTable { private static final long serialVersionUID = -7140811933957438525L; - private JiveTable.JiveTableModel tableModel; + private final JiveTable.JiveTableModel tableModel; public JiveTable(String[] headers, Integer[] columnsToUseRenderer) { - tableModel = new JiveTable.JiveTableModel(headers, 0, false); + tableModel = new JiveTableModel(headers, 0, false); this.setModel(tableModel); getTableHeader().setReorderingAllowed(false); @@ -59,12 +55,13 @@ public JiveTable(String[] headers, Integer[] columnsToUseRenderer) { } - public TableCellRenderer getCellRenderer(int row, int column) { + @Override + public TableCellRenderer getCellRenderer(int row, int column) { if (column == 3 || column == 4) { - return new JiveTable.JButtonRenderer(false); + return new JButtonRenderer(false); } else if (column == 1) { - return new JiveTable.JLabelRenderer(false); + return new JLabelRenderer(false); } else { return super.getCellRenderer(row, column); @@ -95,9 +92,9 @@ public Object[] getSelectedObject() { return obj; } - public class JiveTableModel extends DefaultTableModel { + public static class JiveTableModel extends DefaultTableModel { private static final long serialVersionUID = -2072664365332767844L; - private boolean _isEditable; + private final boolean _isEditable; /** * Use the JiveTableModel in order to better handle the table. This allows @@ -115,22 +112,24 @@ public JiveTableModel(Object[] columnNames, int numRows, boolean isEditable) { /** * Returns true if cell is editable. */ - public boolean isCellEditable(int row, int column) { + @Override + public boolean isCellEditable(int row, int column) { return _isEditable; } } - class JLabelRenderer extends JLabel implements TableCellRenderer { - private static final long serialVersionUID = 4387574944818048720L; - Border unselectedBorder = null; - Border selectedBorder = null; - boolean isBordered = true; + static class JLabelRenderer extends JLabel implements TableCellRenderer { + private static final long serialVersionUID = 4387574944818048720L; + private Border unselectedBorder = null; + private Border selectedBorder = null; + final boolean isBordered = true; public JLabelRenderer(boolean isBordered) { super(); } - public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { + @Override + public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { final String text = ((JLabel)color).getText(); setText(text); @@ -144,9 +143,6 @@ public Component getTableCellRendererComponent(JTable table, Object color, boole else { setForeground(Color.black); setBackground(Color.white); - if (row % 2 == 0) { - //setBackground( new Color( 156, 207, 255 ) ); - } } if (isBordered) { @@ -170,12 +166,12 @@ public Component getTableCellRendererComponent(JTable table, Object color, boole } - class JButtonRenderer extends JButton implements TableCellRenderer { + static class JButtonRenderer extends JButton implements TableCellRenderer { - private static final long serialVersionUID = -5287214156125954342L; - Border unselectedBorder = null; - Border selectedBorder = null; - boolean isBordered = true; + private static final long serialVersionUID = -5287214156125954342L; + private Border unselectedBorder = null; + private Border selectedBorder = null; + private final boolean isBordered = true; public JButtonRenderer(boolean isBordered) { super(); @@ -183,7 +179,8 @@ public JButtonRenderer(boolean isBordered) { //setOpaque(true); //MUST do this for background to show up. } - public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { + @Override + public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { final String text = ((JButton)color).getText(); setText(text); @@ -197,9 +194,6 @@ public Component getTableCellRendererComponent(JTable table, Object color, boole else { setForeground(Color.black); setBackground(Color.white); - if (row % 2 == 0) { - //setBackground( new Color( 156, 207, 255 ) ); - } } if (isBordered) { @@ -226,4 +220,4 @@ public JiveTable.JiveTableModel getTableModel() { return tableModel; } -} \ No newline at end of file +} diff --git a/src/java/org/jivesoftware/spark/component/JiveTreeCellRenderer.java b/core/src/main/java/org/jivesoftware/spark/component/JiveTreeCellRenderer.java similarity index 83% rename from src/java/org/jivesoftware/spark/component/JiveTreeCellRenderer.java rename to core/src/main/java/org/jivesoftware/spark/component/JiveTreeCellRenderer.java index 1526f92e3..12e7f35af 100644 --- a/src/java/org/jivesoftware/spark/component/JiveTreeCellRenderer.java +++ b/core/src/main/java/org/jivesoftware/spark/component/JiveTreeCellRenderer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -43,7 +39,8 @@ public class JiveTreeCellRenderer extends DefaultTreeCellRenderer { public JiveTreeCellRenderer() { } - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { this.value = value; final Component c = super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); @@ -76,27 +73,33 @@ private Icon getCustomIcon() { return null; } - public Icon getClosedIcon() { + @Override + public Icon getClosedIcon() { return getCustomIcon(); } - public Icon getDefaultClosedIcon() { + @Override + public Icon getDefaultClosedIcon() { return getCustomIcon(); } - public Icon getDefaultLeafIcon() { + @Override + public Icon getDefaultLeafIcon() { return getCustomIcon(); } - public Icon getDefaultOpenIcon() { + @Override + public Icon getDefaultOpenIcon() { return getCustomIcon(); } - public Icon getLeafIcon() { + @Override + public Icon getLeafIcon() { return getCustomIcon(); } - public Icon getOpenIcon() { + @Override + public Icon getOpenIcon() { return getCustomIcon(); } diff --git a/src/java/org/jivesoftware/spark/component/JiveTreeNode.java b/core/src/main/java/org/jivesoftware/spark/component/JiveTreeNode.java similarity index 87% rename from src/java/org/jivesoftware/spark/component/JiveTreeNode.java rename to core/src/main/java/org/jivesoftware/spark/component/JiveTreeNode.java index 89a472f2d..ea825533d 100644 --- a/src/java/org/jivesoftware/spark/component/JiveTreeNode.java +++ b/core/src/main/java/org/jivesoftware/spark/component/JiveTreeNode.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,13 +17,12 @@ import org.jivesoftware.resource.SparkRes; -import javax.swing.Icon; +import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; -import java.io.IOException; /** * JiveTreeNode class is a better implementation than using the @@ -56,8 +51,8 @@ public class JiveTreeNode extends DefaultMutableTreeNode implements Transferable */ public JiveTreeNode(TreeFolder folder) { super(folder.getDisplayName(), true); - closedImage = SparkRes.getImageIcon(SparkRes.FOLDER_CLOSED); - openImage = SparkRes.getImageIcon(SparkRes.FOLDER); + closedImage = SparkRes.getImageIcon(SparkRes.Icon.FOLDER_CLOSED); + openImage = SparkRes.getImageIcon(SparkRes.Icon.FOLDER); associatedObject = folder; } @@ -70,8 +65,8 @@ public JiveTreeNode(TreeFolder folder) { public JiveTreeNode(String name, boolean allowsChildren) { super(name, allowsChildren); if (allowsChildren) { - closedImage = SparkRes.getImageIcon(SparkRes.FOLDER_CLOSED); - openImage = SparkRes.getImageIcon(SparkRes.FOLDER); + closedImage = SparkRes.getImageIcon(SparkRes.Icon.FOLDER_CLOSED); + openImage = SparkRes.getImageIcon(SparkRes.Icon.FOLDER); } } @@ -203,34 +198,33 @@ public void setAssociatedObject(Object o) { */ public final boolean hasParent(String parentName) { JiveTreeNode parent = (JiveTreeNode)getParent(); - while (true) { - if (parent.getAssociatedObject() == null) { - break; - } - final TreeFolder folder = (TreeFolder)parent.getAssociatedObject(); + while (parent.getAssociatedObject() != null) { + final TreeFolder folder = (TreeFolder) parent.getAssociatedObject(); if (folder.getDisplayName().equals(parentName)) { return true; } - parent = (JiveTreeNode)parent.getParent(); + parent = (JiveTreeNode) parent.getParent(); } return false; } - /** * Transferable implementation */ - public DataFlavor[] getTransferDataFlavors() { + @Override + public DataFlavor[] getTransferDataFlavors() { return DATA_FLAVORS; } - public boolean isDataFlavorSupported(DataFlavor flavor) { + @Override + public boolean isDataFlavorSupported(DataFlavor flavor) { return flavor == DATA_FLAVORS[0]; } - public Object getTransferData(DataFlavor flavor) - throws UnsupportedFlavorException, IOException { + @Override + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException { if (this.isDataFlavorSupported(flavor)) { return this; } diff --git a/src/java/org/jivesoftware/spark/component/LinkLabel.java b/core/src/main/java/org/jivesoftware/spark/component/LinkLabel.java similarity index 83% rename from src/java/org/jivesoftware/spark/component/LinkLabel.java rename to core/src/main/java/org/jivesoftware/spark/component/LinkLabel.java index 904b379dd..9580cd4bd 100644 --- a/src/java/org/jivesoftware/spark/component/LinkLabel.java +++ b/core/src/main/java/org/jivesoftware/spark/component/LinkLabel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,11 +36,11 @@ final public class LinkLabel extends JLabel implements MouseListener { private static final long serialVersionUID = 454820993140807217L; // cursors used in url-link related displays and default display - private Cursor DEFAULT_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR); - private Cursor LINK_CURSOR = new Cursor(Cursor.HAND_CURSOR); - private Color rolloverTextColor; - private Color foregroundTextColor; - private String labelURL; + private final Cursor DEFAULT_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR); + private final Cursor LINK_CURSOR = new Cursor(Cursor.HAND_CURSOR); + private final Color rolloverTextColor; + private final Color foregroundTextColor; + private final String labelURL; private boolean invokeBrowser; @@ -79,7 +75,8 @@ public void setInvokeBrowser(boolean invoke) { * * @param me the MouseEvent. */ - public void mouseClicked(MouseEvent me) { + @Override + public void mouseClicked(MouseEvent me) { if (invokeBrowser) { try { BrowserLauncher.openURL(labelURL); @@ -90,18 +87,22 @@ public void mouseClicked(MouseEvent me) { } } - public void mousePressed(MouseEvent me) { + @Override + public void mousePressed(MouseEvent me) { } - public void mouseReleased(MouseEvent me) { + @Override + public void mouseReleased(MouseEvent me) { } - public void mouseEntered(MouseEvent me) { + @Override + public void mouseEntered(MouseEvent me) { this.setForeground(rolloverTextColor); this.setCursor(LINK_CURSOR); } - public void mouseExited(MouseEvent me) { + @Override + public void mouseExited(MouseEvent me) { this.setForeground(foregroundTextColor); this.setCursor(DEFAULT_CURSOR); } diff --git a/core/src/main/java/org/jivesoftware/spark/component/MessageDialog.java b/core/src/main/java/org/jivesoftware/spark/component/MessageDialog.java new file mode 100644 index 000000000..0ca2595d8 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/component/MessageDialog.java @@ -0,0 +1,381 @@ +/* + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.component; + +import org.jivesoftware.MainWindow; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.SparkManager; + +import javax.swing.*; +import java.awt.*; +import java.beans.PropertyChangeListener; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; + +/** + * MessageDialog class is used to easily display the most commonly used dialogs. + */ +public final class MessageDialog +{ + /** + * Display a dialog with an exception. + * + * The dialog's owner (to which the dialog is positioned relative to) is the Spark "Main Window". + * + * @param throwable the throwable object to display. + */ + public static void showErrorDialog( final Throwable throwable ) + { + showErrorDialog( SparkManager.getMainWindow(), null, throwable ); + } + + /** + * Display a dialog with an exception. + * + * @param owner The owner of the dialog, to which the dialog is positioned relative to. + * @param throwable the throwable object to display. + */ + public static void showErrorDialog( final JFrame owner, final Throwable throwable ) + { + showErrorDialog( owner, null, throwable ); + } + + /** + * Display a dialog with an exception. + * + * The dialog's owner (to which the dialog is positioned relative to) is the Spark "Main Window". + * + * @param description Human readable text (can be null or empty). + * @param throwable the throwable object to display. + */ + public static void showErrorDialog( final String description, final Throwable throwable ) + { + showErrorDialog( SparkManager.getMainWindow(), description, throwable ); + } + /** + * Display a dialog with an exception. + * + * @param owner The owner of the dialog, to which the dialog is positioned relative to. + * @param description Human readable text (can be null or empty). + * @param throwable the throwable object to display. + */ + public static void showErrorDialog( final JFrame owner, final String description, final Throwable throwable ) + { + EventQueue.invokeLater( () -> + { + // Create the title panel for this dialog + final String desc = description == null || description.trim().isEmpty() ? null : description.trim(); + final TitlePanel titlePanel = new TitlePanel(Res.getString("message.default.error"), desc, SparkRes.getImageIcon(SparkRes.Icon.SMALL_DELETE), true); + + final JLabel titleLabel = new JLabel( Res.getString( "message.default.error" ) ); + titleLabel.setFont(new Font("dialog", Font.BOLD, 11 ) ); + + final JLabel descriptionLabel = new JLabel(desc); + descriptionLabel.setFont(new Font("dialog", Font.PLAIN, 10 ) ); + + // The stacktrace content. + final JTextArea textPane = new JTextArea(); + textPane.setFont( new Font( "Dialog", Font.PLAIN, 12 ) ); + textPane.setEditable( false ); + textPane.setText( getStackTrace( throwable ) ); + textPane.setCaretPosition( 0 ); // scroll to top + final JScrollPane scrollPane = new JScrollPane( textPane ); + scrollPane.setPreferredSize( new Dimension( 600, 400 ) ); + scrollPane.setVisible( false ); + + // Construct main panel w/ layout. + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout( new BorderLayout() ); + + mainPanel.add( titleLabel, BorderLayout.NORTH ); + if ( description != null && !description.trim().isEmpty() ) + { + mainPanel.add( descriptionLabel, BorderLayout.CENTER ); + } + mainPanel.add( scrollPane, BorderLayout.SOUTH ); + + // The user should only be able to close this dialog. + final Object[] options = { Res.getString( "details" ), Res.getString( "close" ) }; + final JOptionPane pane = new JOptionPane( mainPanel, JOptionPane.ERROR_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[ 1 ] ); + + final JDialog dlg = new JDialog( owner, Res.getString( "title.error" ), false ); + dlg.setContentPane( pane ); + + pane.addPropertyChangeListener( "value", evt -> + { + if ( dlg.isVisible() && evt.getSource() == pane ) + { + String value = (String) pane.getValue(); + if ( Res.getString( "close" ).equals( value ) ) + { + dlg.setVisible( false ); + } + if ( Res.getString( "details" ).equals( value ) ) + { + scrollPane.setVisible( !scrollPane.isVisible() ); + dlg.pack(); + dlg.setLocationRelativeTo( owner ); + pane.setValue( null ); // reset the value, otherwise the value change listener won't fire again! + } + } + } ); + + dlg.pack(); + dlg.setLocationRelativeTo( owner ); + + // By setting the preferred size to whatever is the size after packaging, the size of these components is + // unlikely to be modified by the expanding/collapsing of the stack trace pane. + titleLabel.setPreferredSize( titleLabel.getSize() ); + descriptionLabel.setPreferredSize( descriptionLabel.getSize() ); + + dlg.setVisible( true ); + dlg.toFront(); + dlg.requestFocus(); + } ); + } + + /** + * Display an alert dialog. + * + * @param message the message to display. + * @param header the header/title of the dialog. + * @param title the title to display. + * @param icon the icon for the alert dialog. + */ + public static void showAlert( final String message, final String header, final String title, final Icon icon ) + { + EventQueue.invokeLater( () -> { + JTextPane textPane; + final JOptionPane pane; + final JDialog dlg; + + TitlePanel titlePanel; + + textPane = new JTextPane(); + textPane.setFont( new Font( "Dialog", Font.PLAIN, 12 ) ); + textPane.setEditable( false ); + textPane.setText( message ); + textPane.setBackground( Color.white ); + + // Create the title panel for this dialog + titlePanel = new TitlePanel( header, null, icon, true ); + + // Construct main panel w/ layout. + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout( new BorderLayout() ); + mainPanel.add( titlePanel, BorderLayout.NORTH ); + + // The user should only be able to close this dialog. + Object[] options = { Res.getString( "close" ) }; + pane = new JOptionPane( new JScrollPane( textPane ), JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[ 0 ] ); + + mainPanel.add( pane, BorderLayout.CENTER ); + + MainWindow mainWindow = SparkManager.getMainWindow(); + dlg = new JDialog( mainWindow, title, false ); + dlg.pack(); + dlg.setSize( 300, 300 ); + dlg.setContentPane( mainPanel ); + dlg.setLocationRelativeTo( SparkManager.getMainWindow() ); + + PropertyChangeListener changeListener = e -> + { + String value = (String) pane.getValue(); + if ( Res.getString( "close" ).equals( value ) ) + { + dlg.setVisible( false ); + } + }; + + pane.addPropertyChangeListener( changeListener ); + + dlg.setVisible( true ); + dlg.toFront(); + dlg.requestFocus(); + } ); + } + + /** + * Creates, but does not display, a dialog with a specified component. + * + * @param title the title of the dialog. + * @param description the description to display. + * @param icon the icon. + * @param comp the component to display. + * @param parent the parent of this dialog. + * @param modal true if it is modal. + * @return the JDialog created. + */ + public static JDialog createComponent( String title, String description, Icon icon, JComponent comp, Component parent, boolean modal ) + { + final JOptionPane pane; + final JDialog dlg; + + TitlePanel titlePanel; + + // Create the title panel for this dialog + titlePanel = new TitlePanel( title, description, icon, true ); + + // Construct main panel w/ layout. + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout( new BorderLayout() ); + mainPanel.add( titlePanel, BorderLayout.NORTH ); + + // The user should only be able to close this dialog. + Object[] options = { Res.getString( "close" ) }; + pane = new JOptionPane( comp, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[ 0 ] ); + + mainPanel.add( pane, BorderLayout.CENTER ); + + JOptionPane p = new JOptionPane(); + dlg = p.createDialog( parent, title ); + dlg.setModal( modal ); + + dlg.pack(); + dlg.setResizable( true ); + dlg.setContentPane( mainPanel ); + + PropertyChangeListener changeListener = e -> { + String value; + try + { + value = (String) pane.getValue(); + if ( Res.getString( "close" ).equals( value ) ) + { + dlg.setVisible( false ); + } + } + catch ( Exception ex ) + { + // probably pressed ;-) + } + + }; + + pane.addPropertyChangeListener( changeListener ); + + return dlg; + } + + /** + * Display a dialog with a specified component. + * + * @param title the title of the dialog. + * @param description the description to display. + * @param icon the icon. + * @param comp the component to display. + * @param parent the parent of this dialog. + * @param width the width of this dialog. + * @param height the height of this dialog. + * @param modal true if it is modal. + * @return the JDialog created. + */ + public static JDialog showComponent( String title, String description, Icon icon, JComponent comp, Component parent, int width, int height, boolean modal ) + { + final JOptionPane pane; + final JDialog dlg; + + TitlePanel titlePanel; + + // Create the title panel for this dialog + titlePanel = new TitlePanel( title, description, icon, true ); + + // Construct main panel w/ layout. + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout( new BorderLayout() ); + mainPanel.add( titlePanel, BorderLayout.NORTH ); + + // The user should only be able to close this dialog. + Object[] options = { Res.getString( "close" ) }; + pane = new JOptionPane( comp, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[ 0 ] ); + + mainPanel.add( pane, BorderLayout.CENTER ); + + JOptionPane p = new JOptionPane(); + dlg = p.createDialog( parent, title ); + dlg.setModal( modal ); + + dlg.pack(); + dlg.setSize( width, height ); + dlg.setResizable( true ); + dlg.setContentPane( mainPanel ); + dlg.setLocationRelativeTo( parent ); + + PropertyChangeListener changeListener = e -> { + String value; + try + { + value = (String) pane.getValue(); + if ( Res.getString( "close" ).equals( value ) ) + { + dlg.setVisible( false ); + } + } + catch ( Exception ex ) + { + // probably pressed ;-) + } + }; + + pane.addPropertyChangeListener( changeListener ); + + dlg.setVisible( true ); + dlg.toFront(); + dlg.requestFocus(); + return dlg; + } + + /** + * Returns the String representation of a StackTrace. + * + * @param aThrowable the throwable object. + * @return the string. + */ + public static String getStackTrace( Throwable aThrowable ) + { + final Writer result = new StringWriter(); + final PrintWriter printWriter = new PrintWriter( result ); + aThrowable.printStackTrace( printWriter ); + return result.toString(); + } + + /** + * Defines a custom format for the stack trace as String. + * + * @param heading the title of the stack trace. + * @param aThrowable the throwable object. + * @return the string. + */ + public static String getCustomStackTrace( String heading, Throwable aThrowable ) + { + //add the class name and any message passed to constructor + final StringBuilder result = new StringBuilder( heading ); + result.append( aThrowable.toString() ); + final String lineSeperator = System.getProperty( "line.separator" ); + result.append( lineSeperator ); + + //add each element of the stack trace + StackTraceElement[] stackTrace = aThrowable.getStackTrace(); + for ( StackTraceElement traceElement : stackTrace) + { + result.append( traceElement ); + result.append( lineSeperator ); + } + return result.toString(); + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/component/PasswordDialog.java b/core/src/main/java/org/jivesoftware/spark/component/PasswordDialog.java new file mode 100644 index 000000000..376618cc3 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/component/PasswordDialog.java @@ -0,0 +1,204 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.component; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.SparkManager; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.GridBagLayout; +import java.awt.GridBagConstraints; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JLabel; +import javax.swing.JCheckBox; + +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + + +/** + * PasswordDialog class is used to retrieve information from a user. + * + * @author Derek DeMoro + */ +public final class PasswordDialog implements PropertyChangeListener { + private JPasswordField passwordField; + private JOptionPane optionPane; + private JDialog dialog; + + private final JCheckBox _savePasswordBox = new JCheckBox(); + private String stringValue; + private int width = 400; + private int height = 200; + private String password; + + public void setPasswordField(String password) { + this.password = password; + } + + public boolean isCheckboxSelected() { + return _savePasswordBox.isSelected(); + } + + public void savePassword(String roomName, String password) { + try { + SettingsManager.getLocalPreferences().setGroupChatPassword(roomName, password); + } catch (Exception e) { + Log.error("Error storing encrypted password.", e); + } + } + + /** + * Empty Constructor. + */ + public PasswordDialog() { + } + + /** + * Returns the input from a user. + * + * @param title the title of the dialog. + * @param description the dialog description. + * @param icon the icon to use. + * @param width the dialog width + * @param height the dialog height + * @return the users input. + */ + public String getInput(String title, String description, Icon icon, int width, int height) { + this.width = width; + this.height = height; + + return getPassword(title, description, icon, SparkManager.getMainWindow()); + } + + /** + * Prompt and return input. + * + * @param title the title of the dialog. + * @param description the dialog description. + * @param icon the icon to use. + * @param parent the parent to use. + * @return the user input. + */ + public String getPassword(String title, String description, Icon icon, Component parent) { + passwordField = new JPasswordField(); + passwordField.setText(password); + + TitlePanel titlePanel = new TitlePanel(title, description, icon, true); + + // Construct main panel with layout. + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BorderLayout()); + mainPanel.add(titlePanel, BorderLayout.NORTH); + + final JPanel passwordPanel = new JPanel(new GridBagLayout()); + JLabel passwordLabel = new JLabel(Res.getString("label.enter.password") + ":"); + passwordPanel.add(passwordLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + passwordPanel.add(passwordField, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + // User should be able to close this dialog (with an option to save room's password) + passwordPanel.add(_savePasswordBox, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + ResourceUtils.resButton(_savePasswordBox, Res.getString("checkbox.save.password")); + final Object[] options = {Res.getString("ok"), Res.getString("cancel"),}; + optionPane = new JOptionPane(passwordPanel, JOptionPane.PLAIN_MESSAGE, + JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); + + mainPanel.add(optionPane, BorderLayout.CENTER); + + // Let's make sure that the dialog is modal. + // Cannot risk people losing this dialog. + JOptionPane p = new JOptionPane(); + dialog = p.createDialog(parent, title); + dialog.setModal(true); + dialog.pack(); + dialog.setSize(width, height); + dialog.setContentPane(mainPanel); + dialog.setLocationRelativeTo(parent); + optionPane.addPropertyChangeListener(this); + + // Add Key Listener to Send Field + passwordField.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyChar() == KeyEvent.VK_TAB) { + optionPane.requestFocus(); + } else if (e.getKeyChar() == KeyEvent.VK_ESCAPE) { + dialog.dispose(); + } + } + }); + + passwordField.requestFocus(); + + dialog.setVisible(true); + return stringValue; + } + + /** + * Move to focus forward action. + */ + public Action nextFocusAction = new AbstractAction(Res.getString("label.move.focus.forwards")) { + private static final long serialVersionUID = 6465350147231073505L; + + @Override + public void actionPerformed(ActionEvent evt) { + ((Component) evt.getSource()).transferFocus(); + } + }; + + /** + * Moves the focus backwards in the dialog. + */ + public Action prevFocusAction = new AbstractAction(Res.getString("label.move.focus.backwards")) { + private static final long serialVersionUID = -91177056113094990L; + + @Override + public void actionPerformed(ActionEvent evt) { + ((Component) evt.getSource()).transferFocusBackward(); + } + }; + + @Override + public void propertyChange(PropertyChangeEvent e) { + String value = (String) optionPane.getValue(); + // Sets password and closes the dialog based on input + if (Res.getString("cancel").equals(value)) { + stringValue = null; + dialog.setVisible(false); + } else if (Res.getString("ok").equals(value)) { + stringValue = String.valueOf(passwordField.getPassword()).trim(); + if (stringValue.isEmpty()) { + stringValue = null; + } + dialog.setVisible(false); + } + } +} diff --git a/src/java/org/jivesoftware/spark/component/ProgressIcon.java b/core/src/main/java/org/jivesoftware/spark/component/ProgressIcon.java similarity index 86% rename from src/java/org/jivesoftware/spark/component/ProgressIcon.java rename to core/src/main/java/org/jivesoftware/spark/component/ProgressIcon.java index 756ed8d02..aa8cc885a 100644 --- a/src/java/org/jivesoftware/spark/component/ProgressIcon.java +++ b/core/src/main/java/org/jivesoftware/spark/component/ProgressIcon.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,7 +27,7 @@ * @author Derek DeMoro */ public class ProgressIcon implements Icon { - private int percent; + private final int percent; /** * Create new ProgressIcon. @@ -42,15 +38,18 @@ public ProgressIcon(int percent) { this.percent = percent; } - public int getIconHeight() { + @Override + public int getIconHeight() { return 10; } - public int getIconWidth() { + @Override + public int getIconWidth() { return percent; } - public void paintIcon(Component c, Graphics g, int x, int y) { + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { g.setColor(Color.blue); g.fillRect(x, y, getIconWidth(), getIconHeight());//To change body of implemented methods use File | Settings | File Templates. } diff --git a/src/java/org/jivesoftware/spark/component/RolloverButton.java b/core/src/main/java/org/jivesoftware/spark/component/RolloverButton.java similarity index 94% rename from src/java/org/jivesoftware/spark/component/RolloverButton.java rename to core/src/main/java/org/jivesoftware/spark/component/RolloverButton.java index 7ddeb803e..2a6f7a50f 100644 --- a/src/java/org/jivesoftware/spark/component/RolloverButton.java +++ b/core/src/main/java/org/jivesoftware/spark/component/RolloverButton.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -88,7 +84,8 @@ protected void decorate() { setMargin(new Insets(1, 1, 1, 1)); addMouseListener(new MouseAdapter() { - public void mouseEntered(MouseEvent e) { + @Override + public void mouseEntered(MouseEvent e) { if (isEnabled()) { setBorderPainted(true); @@ -99,7 +96,8 @@ public void mouseEntered(MouseEvent e) { } } - public void mouseExited(MouseEvent e) { + @Override + public void mouseExited(MouseEvent e) { setBorderPainted(false); setContentAreaFilled(false); } diff --git a/src/java/org/jivesoftware/spark/component/RosterTree.java b/core/src/main/java/org/jivesoftware/spark/component/RosterTree.java similarity index 87% rename from src/java/org/jivesoftware/spark/component/RosterTree.java rename to core/src/main/java/org/jivesoftware/spark/component/RosterTree.java index 3e023cf02..cb2c5909f 100644 --- a/src/java/org/jivesoftware/spark/component/RosterTree.java +++ b/core/src/main/java/org/jivesoftware/spark/component/RosterTree.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,6 +23,7 @@ import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.spark.PresenceManager; import org.jivesoftware.spark.SparkManager; +import org.jxmpp.jid.Jid; import javax.swing.BorderFactory; import javax.swing.JPanel; @@ -80,37 +77,42 @@ private void changePresence(String user, Presence presence){ final String nodeUser = addressMap.get(node); if (user.startsWith(nodeUser)) { if (!presence.isAvailable()) { - node.setIcon(SparkRes.getImageIcon(SparkRes.CLEAR_BALL_ICON)); + node.setIcon(SparkRes.getImageIcon(SparkRes.Icon.CLEAR_BALL_ICON)); } else { - node.setIcon(SparkRes.getImageIcon(SparkRes.GREEN_BALL)); + node.setIcon(SparkRes.getImageIcon(SparkRes.Icon.GREEN_BALL)); } } } } private void buildFromRoster() { - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); + final Roster roster = SparkManager.getRoster(); roster.addRosterListener(new RosterListener() { - public void entriesAdded(Collection addresses) { + @Override + public void entriesAdded(Collection addresses) { } - public void entriesUpdated(Collection addresses) { + @Override + public void entriesUpdated(Collection addresses) { } - public void entriesDeleted(Collection addresses) { + @Override + public void entriesDeleted(Collection addresses) { } - public void presenceChanged(Presence presence) { + @Override + public void presenceChanged(Presence presence) { //changePresence(presence.getFrom(), presence.getMode() == Presence.Mode.available); } }); + for (RosterGroup group : roster.getGroups()) { final JiveTreeNode groupNode = new JiveTreeNode(group.getName(), true); groupNode.setAllowsChildren(true); @@ -121,13 +123,13 @@ public void presenceChanged(Presence presence) { for (RosterEntry entry : group.getEntries()) { String name = entry.getName(); if (name == null) { - name = entry.getUser(); + name = entry.getJid().toString(); } final JiveTreeNode entryNode = new JiveTreeNode(name, false); - final Presence usersPresence = PresenceManager.getPresence(entry.getUser()); - addressMap.put(entryNode, entry.getUser()); + final Presence usersPresence = PresenceManager.getPresence(entry.getJid()); + addressMap.put(entryNode, entry.getJid().toString()); boolean showUnavailableAgents = true; if (usersPresence.isAvailable() && !usersPresence.isAway()) { groupNode.add(entryNode); @@ -136,7 +138,7 @@ else if ( showUnavailableAgents ) { groupNode.add(entryNode); } - changePresence(entry.getUser(), usersPresence); + changePresence(entry.getJid().toString(), usersPresence); final DefaultTreeModel model = (DefaultTreeModel)rosterTree.getModel(); model.nodeStructureChanged(groupNode); } @@ -162,7 +164,8 @@ public String getJID(JiveTreeNode node) { return addressMap.get(node); } - public String toString() { + @Override + public String toString() { return "Roster"; } } diff --git a/src/java/org/jivesoftware/spark/component/ScrollPaneWatermark.java b/core/src/main/java/org/jivesoftware/spark/component/ScrollPaneWatermark.java similarity index 95% rename from src/java/org/jivesoftware/spark/component/ScrollPaneWatermark.java rename to core/src/main/java/org/jivesoftware/spark/component/ScrollPaneWatermark.java index 1bd1a49a9..7f02b7908 100644 --- a/src/java/org/jivesoftware/spark/component/ScrollPaneWatermark.java +++ b/core/src/main/java/org/jivesoftware/spark/component/ScrollPaneWatermark.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -52,7 +48,8 @@ public void setForegroundImage(Image image) { this.foregroundImage = image; } - public void paintComponent(Graphics g) { + @Override + public void paintComponent(Graphics g) { super.paintComponent(g); if(foregroundImage != null){ diff --git a/src/java/org/jivesoftware/spark/component/Table.java b/core/src/main/java/org/jivesoftware/spark/component/Table.java similarity index 88% rename from src/java/org/jivesoftware/spark/component/Table.java rename to core/src/main/java/org/jivesoftware/spark/component/Table.java index c17634677..ba6e16783 100644 --- a/src/java/org/jivesoftware/spark/component/Table.java +++ b/core/src/main/java/org/jivesoftware/spark/component/Table.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -77,7 +73,8 @@ public abstract class Table extends JXTable { protected Table() { } - public String getToolTipText(MouseEvent e) { + @Override + public String getToolTipText(MouseEvent e) { int r = rowAtPoint(e.getPoint()); int c = columnAtPoint(e.getPoint()); Object value; @@ -110,7 +107,8 @@ else if (tooltipValue == null) { } // Handle image rendering correctly - public TableCellRenderer getCellRenderer(int row, int column) { + @Override + public TableCellRenderer getCellRenderer(int row, int column) { Object o = getValueAt(row, column); if (o != null) { if (o instanceof JLabel) { @@ -145,23 +143,27 @@ protected Table(String[] headers) { setSelectionMode(ListSelectionModel.SINGLE_SELECTION); this.addKeyListener(new KeyListener() { - public void keyPressed(KeyEvent e) { + @Override + public void keyPressed(KeyEvent e) { if (e.getKeyChar() == KeyEvent.VK_ENTER) { e.consume(); enterPressed(); } } - public void keyReleased(KeyEvent e) { + @Override + public void keyReleased(KeyEvent e) { } - public void keyTyped(KeyEvent e) { + @Override + public void keyTyped(KeyEvent e) { } }); } - public Component prepareRenderer(TableCellRenderer renderer, + @Override + public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, int vColIndex) { Component c = super.prepareRenderer(renderer, rowIndex, vColIndex); if (rowIndex % 2 == 0 && !isCellSelected(rowIndex, vColIndex)) { @@ -238,7 +240,7 @@ public void clearTable() { public static class JiveTableModel extends DefaultTableModel { private static final long serialVersionUID = 2256144012470569949L; - private boolean isEditable; + private final boolean isEditable; /** * Use the JiveTableModel in order to better handle the table. This allows @@ -260,7 +262,8 @@ public JiveTableModel(Object[] columnNames, int numRows, boolean isEditable) { * @param column the column to check. * @return true if the cell is editable. */ - public boolean isCellEditable(int row, int column) { + @Override + public boolean isCellEditable(int row, int column) { return isEditable; } } @@ -268,12 +271,12 @@ public boolean isCellEditable(int row, int column) { /** * A swing renderer used to display labels within a table. */ - public class JLabelRenderer extends JLabel implements TableCellRenderer { + public static class JLabelRenderer extends JLabel implements TableCellRenderer { private static final long serialVersionUID = 4433780600297455731L; - Border unselectedBorder; - Border selectedBorder; - boolean isBordered = true; + private Border unselectedBorder; + private Border selectedBorder; + private final boolean isBordered; /** * JLabelConstructor to build ui. @@ -285,7 +288,8 @@ public JLabelRenderer(boolean isBordered) { this.isBordered = isBordered; } - public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { + @Override + public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { final String text = ((JLabel)color).getText(); if (text != null) { setText(" " + text); @@ -300,9 +304,6 @@ public Component getTableCellRendererComponent(JTable table, Object color, boole else { setForeground(Color.black); setBackground(Color.white); - if (row % 2 == 0) { - //setBackground( new Color( 156, 207, 255 ) ); - } } if (isBordered) { @@ -328,7 +329,7 @@ public Component getTableCellRendererComponent(JTable table, Object color, boole /** * A swing renderer to dispaly Textareas within a table. */ - public class TextAreaCellRenderer extends JTextArea implements TableCellRenderer { + public static class TextAreaCellRenderer extends JTextArea implements TableCellRenderer { private static final long serialVersionUID = -8533968851464831361L; @@ -343,7 +344,8 @@ public TextAreaCellRenderer(Font font) { setFont(font); } - public Component getTableCellRendererComponent(JTable jTable, Object obj, boolean isSelected, boolean hasFocus, + @Override + public Component getTableCellRendererComponent(JTable jTable, Object obj, boolean isSelected, boolean hasFocus, int row, int column) { // set color & border here setText(obj == null ? "" : obj.toString()); @@ -359,12 +361,12 @@ public Component getTableCellRendererComponent(JTable jTable, Object obj, boolea /** * A swing renderer used to display Buttons within a table. */ - public class JButtonRenderer extends JButton implements TableCellRenderer { + public static class JButtonRenderer extends JButton implements TableCellRenderer { private static final long serialVersionUID = 1268514163461994738L; - Border unselectedBorder; - Border selectedBorder; - boolean isBordered = true; + private Border unselectedBorder; + private Border selectedBorder; + private final boolean isBordered = true; /** * Empty Constructor. @@ -373,7 +375,8 @@ public JButtonRenderer() { } - public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { + @Override + public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { final String text = ((JButton)color).getText(); setText(text); @@ -387,9 +390,6 @@ public Component getTableCellRendererComponent(JTable table, Object color, boole else { setForeground(Color.black); setBackground(Color.white); - if (row % 2 == 0) { - //setBackground( new Color( 156, 207, 255 ) ); - } } if (isBordered) { @@ -412,7 +412,7 @@ public Component getTableCellRendererComponent(JTable table, Object color, boole } } - public class ComboBoxRenderer extends JComboBox implements TableCellRenderer { + public static class ComboBoxRenderer extends JComboBox implements TableCellRenderer { private static final long serialVersionUID = -545496178928790522L; @@ -424,7 +424,8 @@ public ComboBoxRenderer(String[] items) { super(items); } - public Component getTableCellRendererComponent(JTable table, Object value, + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if (isSelected) { setForeground(table.getSelectionForeground()); @@ -441,12 +442,12 @@ public Component getTableCellRendererComponent(JTable table, Object value, } } - public class MyComboBoxEditor extends DefaultCellEditor { + public static class MyComboBoxEditor extends DefaultCellEditor { private static final long serialVersionUID = 6097118754932234992L; public MyComboBoxEditor(String[] items) { - super(new JComboBox(items)); + super(new JComboBox<>(items)); } } @@ -491,5 +492,4 @@ public Object getObject(int row) { */ public void enterPressed() { } - -} \ No newline at end of file +} diff --git a/src/java/org/jivesoftware/spark/component/TimeTrackingLabel.java b/core/src/main/java/org/jivesoftware/spark/component/TimeTrackingLabel.java similarity index 96% rename from src/java/org/jivesoftware/spark/component/TimeTrackingLabel.java rename to core/src/main/java/org/jivesoftware/spark/component/TimeTrackingLabel.java index db31e31ca..0e5291094 100644 --- a/src/java/org/jivesoftware/spark/component/TimeTrackingLabel.java +++ b/core/src/main/java/org/jivesoftware/spark/component/TimeTrackingLabel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,7 +28,7 @@ public class TimeTrackingLabel extends JLabel { private static final long serialVersionUID = 6640616146941699107L; private Date startTime; - private JComponent parentComponent; + private final JComponent parentComponent; private final String HOURS = "h"; private final String MINUTES = "min"; @@ -116,9 +112,10 @@ public void stopTimer() { timer.stop(); } - public String toString() { + @Override + public String toString() { return getText(); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jivesoftware/spark/component/TitlePanel.java b/core/src/main/java/org/jivesoftware/spark/component/TitlePanel.java new file mode 100644 index 000000000..7ddcf0ad0 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/component/TitlePanel.java @@ -0,0 +1,123 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.component; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JLabel; +import javax.swing.JPanel; + +/** + * TitlePanel class is the top panel displayed in this application. + * This should be used to identify the application to users using a title, brief + * description, and the company's logo. + * + * @author Derek DeMoro + */ +public final class TitlePanel extends JPanel { + + private static final long serialVersionUID = -967166058268240672L; + private final JLabel titleLabel = new JLabel(); + private final JLabel descriptionLabel = new JLabel(); + + /** + * Create a new TitlePanel. + * + * @param title the title to use with the panel. + * @param description the panel description. + * @param icon the icon to use with the panel. + * @param showDescription true if the description should be shown. + */ + public TitlePanel(String title, String description, Icon icon, boolean showDescription) { + + // Set the icon + JLabel iconLabel = new JLabel(); + iconLabel.setIcon(icon); + + // Set the title + setTitle(title); + + // Set the description + setDescription(description); + + GridBagLayout gridBagLayout = new GridBagLayout(); + setLayout(gridBagLayout); + + descriptionLabel.setBackground(Color.white); + + if (showDescription) { + add(iconLabel, new GridBagConstraints(2, 0, 1, 2, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(descriptionLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 9, 5, 5), 0, 0)); + add(titleLabel, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + setBackground(Color.white); + + titleLabel.setFont(new Font("dialog", Font.BOLD, 11)); + descriptionLabel.setFont(new Font("dialog", Font.PLAIN, 10)); + } else { + final JPanel panel = new JPanel(); + panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + panel.setBackground(Color.gray.brighter()); + panel.setLayout(new GridBagLayout()); + panel.add(titleLabel, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0)); + panel.add(iconLabel, new GridBagConstraints(2, 0, 1, 2, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); + + titleLabel.setVerticalTextPosition(JLabel.CENTER); + titleLabel.setFont(new Font("dialog", Font.BOLD, 14)); + titleLabel.setForeground(Color.black); + descriptionLabel.setFont(new Font("dialog", Font.PLAIN, 10)); + add(panel, new GridBagConstraints(0, 0, 1, 0, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 2, 2, 2), 0, 0)); + } + + } + + /** + * Set the icon for the panel. + * + * @param icon - the relative icon based on classpath. ex. + * /com/jivesoftware/images/Foo.gif. + */ + public final void setIcon(Icon icon) { + titleLabel.setIcon(icon); + } + + /** + * Set the main title for this panel. + * + * @param title - main title. + */ + public final void setTitle(String title) { + titleLabel.setText(title); + } + + /** + * Set a brief description which will be displayed below the main title. + * + * @param desc - brief description + */ + public final void setDescription(String desc) { + if (desc != null) { + desc = "" + desc + ""; + } + descriptionLabel.setText(desc); + } + +} diff --git a/src/java/org/jivesoftware/spark/component/Tree.java b/core/src/main/java/org/jivesoftware/spark/component/Tree.java similarity index 94% rename from src/java/org/jivesoftware/spark/component/Tree.java rename to core/src/main/java/org/jivesoftware/spark/component/Tree.java index 522adeaaa..89566622b 100644 --- a/src/java/org/jivesoftware/spark/component/Tree.java +++ b/core/src/main/java/org/jivesoftware/spark/component/Tree.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -59,7 +55,8 @@ public Tree(DefaultMutableTreeNode node) { * * @param e - the TreeSelectionEvent notifying of a valueChange. */ - public void valueChanged(TreeSelectionEvent e) { + @Override + public void valueChanged(TreeSelectionEvent e) { JiveTreeNode node = (JiveTreeNode)getLastSelectedPathComponent(); if (node == null) return; @@ -84,7 +81,8 @@ public JiveTreeNode getTreeNode() { * * @param e - the mousedragged event to handle drag and drop from. */ - public void mouseDragged(MouseEvent e) { + @Override + public void mouseDragged(MouseEvent e) { final JComponent c = (JComponent)e.getSource(); JiveTreeNode node = (JiveTreeNode)getLastSelectedPathComponent(); if (node == null) { @@ -140,7 +138,7 @@ private TreePath find2(Tree tree, TreePath parent, Object[] nodes, int depth, bo // Traverse children if (node.getChildCount() >= 0) { - for (Enumeration e = node.children(); e.hasMoreElements();) { + for (Enumeration e = node.children(); e.hasMoreElements();) { TreeNode n = e.nextElement(); TreePath path = parent.pathByAddingChild(n); TreePath result = find2(tree, path, nodes, depth + 1, byName); @@ -156,7 +154,8 @@ private TreePath find2(Tree tree, TreePath parent, Object[] nodes, int depth, bo return null; } - public void mouseMoved(MouseEvent e) { + @Override + public void mouseMoved(MouseEvent e) { } /** diff --git a/src/java/org/jivesoftware/spark/component/TreeFolder.java b/core/src/main/java/org/jivesoftware/spark/component/TreeFolder.java similarity index 92% rename from src/java/org/jivesoftware/spark/component/TreeFolder.java rename to core/src/main/java/org/jivesoftware/spark/component/TreeFolder.java index d3777ef1f..936096f57 100644 --- a/src/java/org/jivesoftware/spark/component/TreeFolder.java +++ b/core/src/main/java/org/jivesoftware/spark/component/TreeFolder.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,15 +24,15 @@ public class TreeFolder implements Serializable { private static final long serialVersionUID = 2692119297116147123L; - private Set subFolders = new HashSet<>(); - private Set paletteItems = new HashSet<>(); + private final Set subFolders = new HashSet<>(); + private final Set paletteItems = new HashSet<>(); private String displayName; private String description; private String icon; private ContextMenuListener listener; public TreeFolder() { - // Allow user the flexibilty to create + // Allow user the flexibility to create } public TreeFolder(String displayName, String description, String icon) { diff --git a/src/java/org/jivesoftware/spark/component/TreeItem.java b/core/src/main/java/org/jivesoftware/spark/component/TreeItem.java similarity index 97% rename from src/java/org/jivesoftware/spark/component/TreeItem.java rename to core/src/main/java/org/jivesoftware/spark/component/TreeItem.java index 82343a55b..cd32c961d 100644 --- a/src/java/org/jivesoftware/spark/component/TreeItem.java +++ b/core/src/main/java/org/jivesoftware/spark/component/TreeItem.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/spark/component/VerticalFlowLayout.java b/core/src/main/java/org/jivesoftware/spark/component/VerticalFlowLayout.java similarity index 96% rename from src/java/org/jivesoftware/spark/component/VerticalFlowLayout.java rename to core/src/main/java/org/jivesoftware/spark/component/VerticalFlowLayout.java index 0eb296e1d..fbafa8686 100644 --- a/src/java/org/jivesoftware/spark/component/VerticalFlowLayout.java +++ b/core/src/main/java/org/jivesoftware/spark/component/VerticalFlowLayout.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -54,10 +50,10 @@ public class VerticalFlowLayout extends FlowLayout { */ public static final int BOTTOM = 2; - int hgap; - int vgap; - boolean hfill; - boolean vfill; + private final int hgap; + private final int vgap; + private boolean hfill; + private boolean vfill; /** * Construct a new VerticalFlowLayout with a middle alignment, and @@ -122,7 +118,8 @@ public VerticalFlowLayout(int align, * * @param target the component to lay out */ - public Dimension preferredLayoutSize(Container target) { + @Override + public Dimension preferredLayoutSize(Container target) { Dimension tarsiz = new Dimension(0, 0); for (int i = 0; i < target.getComponentCount(); i++) { @@ -148,7 +145,8 @@ public Dimension preferredLayoutSize(Container target) { * @param target the component to lay out. * @return the minimum layout dimension. */ - public Dimension minimumLayoutSize(Container target) { + @Override + public Dimension minimumLayoutSize(Container target) { Dimension tarsiz = new Dimension(0, 0); for (int i = 0; i < target.getComponentCount(); i++) { @@ -240,7 +238,8 @@ private void placethem(Container target, int x, int y, int width, int height, * * @param target the container to lay out. */ - public void layoutContainer(Container target) { + @Override + public void layoutContainer(Container target) { Insets insets = target.getInsets(); int maxheight = target.getSize().height - (insets.top + insets.bottom + vgap * 2); int maxwidth = target.getSize().width - (insets.left + insets.right + hgap * 2); diff --git a/src/java/org/jivesoftware/spark/component/WrappedLabel.java b/core/src/main/java/org/jivesoftware/spark/component/WrappedLabel.java similarity index 93% rename from src/java/org/jivesoftware/spark/component/WrappedLabel.java rename to core/src/main/java/org/jivesoftware/spark/component/WrappedLabel.java index 48a380d97..0df928869 100644 --- a/src/java/org/jivesoftware/spark/component/WrappedLabel.java +++ b/core/src/main/java/org/jivesoftware/spark/component/WrappedLabel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,7 +37,8 @@ public WrappedLabel() { this.setOpaque(false); } - public Dimension getPreferredSize() { + @Override + public Dimension getPreferredSize() { final Dimension size = super.getPreferredSize(); size.width = 0; return size; diff --git a/src/java/org/jivesoftware/spark/component/borders/ComponentTitledBorder.java b/core/src/main/java/org/jivesoftware/spark/component/borders/ComponentTitledBorder.java similarity index 80% rename from src/java/org/jivesoftware/spark/component/borders/ComponentTitledBorder.java rename to core/src/main/java/org/jivesoftware/spark/component/borders/ComponentTitledBorder.java index 1aa7a0686..b74c428c3 100644 --- a/src/java/org/jivesoftware/spark/component/borders/ComponentTitledBorder.java +++ b/core/src/main/java/org/jivesoftware/spark/component/borders/ComponentTitledBorder.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,12 +31,12 @@ import java.awt.event.MouseListener; public class ComponentTitledBorder implements Border, MouseListener, SwingConstants { - int offset = 5; + private final int offset = 5; - Component comp; - JComponent container; - Rectangle rect; - Border border; + private final Component comp; + private final JComponent container; + private final Border border; + private Rectangle rect; public ComponentTitledBorder(Component comp, JComponent container, Border border) { this.comp = comp; @@ -49,11 +45,13 @@ public ComponentTitledBorder(Component comp, JComponent container, Border border container.addMouseListener(this); } - public boolean isBorderOpaque() { + @Override + public boolean isBorderOpaque() { return true; } - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { Insets borderInsets = border.getBorderInsets(c); Insets insets = getBorderInsets(c); int temp = (insets.top - borderInsets.top) / 2; @@ -63,7 +61,8 @@ public void paintBorder(Component c, Graphics g, int x, int y, int width, int he SwingUtilities.paintComponent(g, comp, (Container)c, rect); } - public Insets getBorderInsets(Component c) { + @Override + public Insets getBorderInsets(Component c) { Dimension size = comp.getPreferredSize(); Insets insets = border.getBorderInsets(c); insets.top = Math.max(insets.top, size.height); @@ -84,23 +83,28 @@ private void dispatchEvent(MouseEvent me) { } } - public void mouseClicked(MouseEvent me) { + @Override + public void mouseClicked(MouseEvent me) { dispatchEvent(me); } - public void mouseEntered(MouseEvent me) { + @Override + public void mouseEntered(MouseEvent me) { dispatchEvent(me); } - public void mouseExited(MouseEvent me) { + @Override + public void mouseExited(MouseEvent me) { dispatchEvent(me); } - public void mousePressed(MouseEvent me) { + @Override + public void mousePressed(MouseEvent me) { dispatchEvent(me); } - public void mouseReleased(MouseEvent me) { + @Override + public void mouseReleased(MouseEvent me) { dispatchEvent(me); } -} \ No newline at end of file +} diff --git a/src/java/org/jivesoftware/spark/component/borders/PartialLineBorder.java b/core/src/main/java/org/jivesoftware/spark/component/borders/PartialLineBorder.java similarity index 82% rename from src/java/org/jivesoftware/spark/component/borders/PartialLineBorder.java rename to core/src/main/java/org/jivesoftware/spark/component/borders/PartialLineBorder.java index fdf930603..2ca6e4c12 100644 --- a/src/java/org/jivesoftware/spark/component/borders/PartialLineBorder.java +++ b/core/src/main/java/org/jivesoftware/spark/component/borders/PartialLineBorder.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,13 +31,13 @@ */ public class PartialLineBorder extends AbstractBorder { private static final long serialVersionUID = -5125856347919451956L; - private Color color; - private int thickness; + private final Color color; + private final int thickness; - boolean top, - left, - bottom, - right; + final boolean top; + final boolean left; + final boolean bottom; + final boolean right; public PartialLineBorder(Color color, int thickness) { top = true; @@ -51,15 +47,15 @@ public PartialLineBorder(Color color, int thickness) { this.color = color; this.thickness = thickness; - - } - public boolean isBorderOpaque() { + @Override + public boolean isBorderOpaque() { return true; } - public Insets getBorderInsets(Component component) { + @Override + public Insets getBorderInsets(Component component) { return new Insets(2, 2, 2, 2); } @@ -67,12 +63,12 @@ public int getThickness() { return thickness; } - public void paintBorder(Component component, Graphics g, int x, int y, int width, int height) { + @Override + public void paintBorder(Component component, Graphics g, int x, int y, int width, int height) { Graphics2D g2 = (Graphics2D)g; g2.setStroke(new BasicStroke(1.0f)); g2.setColor(color); - if (top) { g2.drawLine(x, y, x + width, y); } @@ -86,4 +82,4 @@ public void paintBorder(Component component, Graphics g, int x, int y, int width g2.drawLine(x + width, y, x + width, y + height); } } -} \ No newline at end of file +} diff --git a/src/java/org/jivesoftware/spark/component/browser/BrowserFactory.java b/core/src/main/java/org/jivesoftware/spark/component/browser/BrowserFactory.java similarity index 94% rename from src/java/org/jivesoftware/spark/component/browser/BrowserFactory.java rename to core/src/main/java/org/jivesoftware/spark/component/browser/BrowserFactory.java index ae889ed3c..c7715c587 100644 --- a/src/java/org/jivesoftware/spark/component/browser/BrowserFactory.java +++ b/core/src/main/java/org/jivesoftware/spark/component/browser/BrowserFactory.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,7 +36,6 @@ private BrowserFactory() { * Returns the Browser UI to use for system Spark is currently running on. * * @return the BrowserViewer. - * @see NativeBrowserViewer * @see HTMLViewer */ public static BrowserViewer getBrowser() { diff --git a/src/java/org/jivesoftware/spark/component/browser/BrowserListener.java b/core/src/main/java/org/jivesoftware/spark/component/browser/BrowserListener.java similarity index 95% rename from src/java/org/jivesoftware/spark/component/browser/BrowserListener.java rename to core/src/main/java/org/jivesoftware/spark/component/browser/BrowserListener.java index 1d64c6614..539448000 100644 --- a/src/java/org/jivesoftware/spark/component/browser/BrowserListener.java +++ b/core/src/main/java/org/jivesoftware/spark/component/browser/BrowserListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/src/main/java/org/jivesoftware/spark/component/browser/BrowserViewer.java b/core/src/main/java/org/jivesoftware/spark/component/browser/BrowserViewer.java new file mode 100644 index 000000000..162c5e015 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/component/browser/BrowserViewer.java @@ -0,0 +1,92 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.component.browser; + +import org.jivesoftware.spark.util.log.Log; + +import javax.swing.*; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Abstract class describing a particular type of component capable of rendering html. + * + * @author Derek DeMoro + */ +public abstract class BrowserViewer extends JPanel { + private static final long serialVersionUID = -5389246902135069702L; + private final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList<>(); + + /** + * Add a BrowserListener. + * + * @param listener the listener. + */ + public void addBrowserListener(BrowserListener listener) { + listeners.addIfAbsent(listener); + } + + /** + * Remove a BrowserListener. + * + * @param listener the listener. + */ + public void removeBrowserListener(BrowserListener listener) { + listeners.remove(listener); + } + + /** + * Fire all BrowserListeners. + * + * @param document the document that has been downloaded. + */ + public void fireBrowserListeners( String document ) + { + for ( BrowserListener listener : listeners ) + { + try + { + listener.documentLoaded( document ); + } + catch ( Exception e ) + { + Log.error( "A BrowserListener (" + listener + ") threw an exception while processing a 'downloaded' event for document: " + document, e ); + } + } + } + + + public void documentLoaded(String document) { + fireBrowserListeners(document); + } + + /** + * Should create the UI necessary to display html. + */ + public abstract void initializeBrowser(); + + /** + * Should load the given url. + * + * @param url the url to load. + */ + public abstract void loadURL(String url); + + /** + * Should go back in history one page. + */ + public abstract void goBack(); + +} diff --git a/core/src/main/java/org/jivesoftware/spark/component/browser/EmbeddedBrowserViewer.java b/core/src/main/java/org/jivesoftware/spark/component/browser/EmbeddedBrowserViewer.java new file mode 100644 index 000000000..7fcb0e857 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/component/browser/EmbeddedBrowserViewer.java @@ -0,0 +1,102 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.component.browser; + +import java.awt.BorderLayout; +import java.net.MalformedURLException; + +import javax.swing.JFrame; +import javax.swing.LookAndFeel; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +//import org.lobobrowser.gui.ContentEvent; +//import org.lobobrowser.gui.ContentListener; +//import org.lobobrowser.gui.FramePanel; + +//FIXME SPARK-2388 The LoboBrowser doesn't work anymore and should be replaced +public class EmbeddedBrowserViewer extends BrowserViewer { + + private static final long serialVersionUID = -8055149462713514766L; + // private final FramePanel browser; + + /** + * Constructs a new LobobrowserViewer + */ + public EmbeddedBrowserViewer() { + LookAndFeel laf = UIManager.getLookAndFeel(); + +// browser = new FramePanel(); + //substance look and feel + try { + UIManager.setLookAndFeel(laf); + } + catch (UnsupportedLookAndFeelException e) { + e.printStackTrace(); + } +// browser.addContentListener(this); + } + + /** + * Implementation of "Back"-button + */ + public void goBack() { +// browser.back(); + } + + /** + * Initialization of the BrowserViewer + */ + public void initializeBrowser() { + this.setLayout(new BorderLayout()); +// this.add(browser, BorderLayout.CENTER); + } + + /** + * Load the given URL + */ + public void loadURL(String url) { +// try { +// browser.navigate(url); +// } catch (MalformedURLException e) { +// e.printStackTrace(); +// } + } + + /** + * React to an event by updating the address bar + */ +// public void contentSet(ContentEvent event) { +// if (browser == null || browser.getCurrentNavigationEntry() == null) { +// return; +// } +// String url = browser.getCurrentNavigationEntry().getUrl().toExternalForm(); +// documentLoaded(url); +// } + + public static void main(String[] args) { + EmbeddedBrowserViewer viewer = new EmbeddedBrowserViewer(); + viewer.initializeBrowser(); + JFrame frame = new JFrame("Test"); + + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(viewer, BorderLayout.CENTER); + frame.setVisible(true); + frame.pack(); + frame.setSize(600, 400); + viewer.loadURL("http://igniterealtime.org"); + } +} diff --git a/src/java/org/jivesoftware/spark/component/browser/package.html b/core/src/main/java/org/jivesoftware/spark/component/browser/package.html similarity index 100% rename from src/java/org/jivesoftware/spark/component/browser/package.html rename to core/src/main/java/org/jivesoftware/spark/component/browser/package.html diff --git a/src/java/org/jivesoftware/spark/component/focus/SpecifiedOrderFocusTraversalPolicy.java b/core/src/main/java/org/jivesoftware/spark/component/focus/SpecifiedOrderFocusTraversalPolicy.java similarity index 93% rename from src/java/org/jivesoftware/spark/component/focus/SpecifiedOrderFocusTraversalPolicy.java rename to core/src/main/java/org/jivesoftware/spark/component/focus/SpecifiedOrderFocusTraversalPolicy.java index d7be855d8..3766b0afb 100644 --- a/src/java/org/jivesoftware/spark/component/focus/SpecifiedOrderFocusTraversalPolicy.java +++ b/core/src/main/java/org/jivesoftware/spark/component/focus/SpecifiedOrderFocusTraversalPolicy.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,8 +23,8 @@ public class SpecifiedOrderFocusTraversalPolicy extends FocusTraversalPolicy { - private List list; - private Component[] order; + private final List list; + private final Component[] order; public SpecifiedOrderFocusTraversalPolicy(Component[] order) { @@ -36,14 +32,17 @@ public SpecifiedOrderFocusTraversalPolicy(Component[] order) list = Arrays.asList(order); } + @Override public Component getFirstComponent(Container focusCycleRoot) { return null; } + @Override public Component getLastComponent(Container focusCycleRoot) { return null; } + @Override public Component getComponentAfter(Container focusCycleRoot, Component aComponent) { int index = list.indexOf(aComponent); @@ -54,6 +53,7 @@ public Component getComponentAfter(Container focusCycleRoot, return order[index + 1]; } + @Override public Component getComponentBefore(Container focusCycleRoot, Component aComponent) { int index = list.indexOf(aComponent); @@ -62,6 +62,7 @@ public Component getComponentBefore(Container focusCycleRoot, return order[index - 1]; } + @Override public Component getDefaultComponent(Container focusCycleRoot) { return order[0]; } diff --git a/src/java/org/jivesoftware/spark/component/package.html b/core/src/main/java/org/jivesoftware/spark/component/package.html similarity index 100% rename from src/java/org/jivesoftware/spark/component/package.html rename to core/src/main/java/org/jivesoftware/spark/component/package.html diff --git a/src/java/org/jivesoftware/spark/component/panes/BaseCollapsibleTitlePane.java b/core/src/main/java/org/jivesoftware/spark/component/panes/BaseCollapsibleTitlePane.java similarity index 94% rename from src/java/org/jivesoftware/spark/component/panes/BaseCollapsibleTitlePane.java rename to core/src/main/java/org/jivesoftware/spark/component/panes/BaseCollapsibleTitlePane.java index aa347111a..589411ff3 100644 --- a/src/java/org/jivesoftware/spark/component/panes/BaseCollapsibleTitlePane.java +++ b/core/src/main/java/org/jivesoftware/spark/component/panes/BaseCollapsibleTitlePane.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2011 eZuce Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/src/main/java/org/jivesoftware/spark/component/panes/CollapsiblePane.java b/core/src/main/java/org/jivesoftware/spark/component/panes/CollapsiblePane.java new file mode 100644 index 000000000..a582c59e6 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/component/panes/CollapsiblePane.java @@ -0,0 +1,172 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.component.panes; + +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.log.Log; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.Iterator; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * CollapsiblePane provides a component which can collapse or expand its content area + * with animation and fade in/fade out effects. It also acts as a standard container for + * other Swing components. + * + * @author Derek DeMoro + */ +/** + */ +public class CollapsiblePane extends JPanel { + + private static final long serialVersionUID = -6770924580102536726L; + private BaseCollapsibleTitlePane titlePane; + private final JPanel mainPanel; + + private final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList<>(); + + private boolean subPane; + + public CollapsiblePane() { + setLayout(new BorderLayout()); + + titlePane = new CollapsibleTitlePane(); + mainPanel = new JPanel(); + + + add(titlePane, BorderLayout.NORTH); + add(mainPanel, BorderLayout.CENTER); + + mainPanel.setLayout(new BorderLayout()); + + titlePane.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.isPopupTrigger()) { + return; + } + boolean isCollapsed = titlePane.isCollapsed(); + setCollapsed(!isCollapsed); + } + }); + } + + /** + * Creates a CollapsiblePane. + * @param title the title to use. + */ + public CollapsiblePane(String title) { + this(); + setTitle(title); + } + + /** + * Set the title of the Collapsible Pane. + * @param title the collapsible pane title. + */ + public void setTitle(String title) { + titlePane.setTitle(title); + } + + public void setIcon(Icon icon) { + titlePane.setIcon(icon); + } + + public void setCollapsed(boolean collapsed) { + titlePane.setCollapsed(collapsed); + mainPanel.setVisible(!collapsed); + + if (collapsed) { + firePaneCollapsed(); + } + else { + firePaneExpanded(); + } + } + + public void setContentPane(Component comp) { + mainPanel.add(comp); + } + + public void addCollapsiblePaneListener(CollapsiblePaneListener listener) { + listeners.addIfAbsent(listener); + } + + public void removeCollapsiblePaneListener(CollapsiblePaneListener listener) { + listeners.remove(listener); + } + + private void firePaneExpanded() + { + final Iterator iter = ModelUtil.reverseListIterator( listeners.listIterator() ); + while ( iter.hasNext() ) + { + final CollapsiblePaneListener listener = iter.next(); + try + { + listener.paneExpanded(); + } + catch ( Exception e ) + { + Log.error( "A CollapsiblePaneListener(" + listener + ") threw an exception while processing an 'expanded' event.", e ); + } + } + } + + private void firePaneCollapsed() + { + final Iterator iter = ModelUtil.reverseListIterator( listeners.listIterator() ); + while ( iter.hasNext() ) + { + final CollapsiblePaneListener listener = iter.next(); + try + { + listener.paneCollapsed(); + } + catch ( Exception e ) + { + Log.error( "A CollapsiblePaneListener (" + listener + ") threw an exception while processing a 'collapsed' event.", e ); + } + } + } + + + public BaseCollapsibleTitlePane getTitlePane() { + return titlePane; + } + + protected void setTitlePane(BaseCollapsibleTitlePane titlePane) { + this.titlePane = titlePane; + } + + public boolean isCollapsed() { + return titlePane.isCollapsed(); + } + + public boolean isSubPane() { + return subPane; + } + + public void setSubPane(boolean subPane) { + this.subPane = subPane; + + titlePane.setSubPane(subPane); + } +} diff --git a/src/java/org/jivesoftware/spark/component/panes/CollapsiblePaneListener.java b/core/src/main/java/org/jivesoftware/spark/component/panes/CollapsiblePaneListener.java similarity index 94% rename from src/java/org/jivesoftware/spark/component/panes/CollapsiblePaneListener.java rename to core/src/main/java/org/jivesoftware/spark/component/panes/CollapsiblePaneListener.java index 26fa94e15..b37755c4b 100644 --- a/src/java/org/jivesoftware/spark/component/panes/CollapsiblePaneListener.java +++ b/core/src/main/java/org/jivesoftware/spark/component/panes/CollapsiblePaneListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,5 +25,6 @@ public interface CollapsiblePaneListener { void paneExpanded(); + @SuppressWarnings("EmptyMethod") void paneCollapsed(); } diff --git a/src/java/org/jivesoftware/spark/component/panes/CollapsibleTitlePane.java b/core/src/main/java/org/jivesoftware/spark/component/panes/CollapsibleTitlePane.java similarity index 80% rename from src/java/org/jivesoftware/spark/component/panes/CollapsibleTitlePane.java rename to core/src/main/java/org/jivesoftware/spark/component/panes/CollapsibleTitlePane.java index b06fb6c99..0e332fb93 100644 --- a/src/java/org/jivesoftware/spark/component/panes/CollapsibleTitlePane.java +++ b/core/src/main/java/org/jivesoftware/spark/component/panes/CollapsibleTitlePane.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,6 +19,7 @@ import org.jivesoftware.spark.util.ColorUtil; import org.jivesoftware.spark.util.GraphicUtils; import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; import java.awt.Color; import java.awt.Font; @@ -38,9 +35,7 @@ import java.awt.geom.AffineTransform; import java.util.StringTokenizer; -import javax.swing.Icon; -import javax.swing.JLabel; -import javax.swing.UIManager; +import javax.swing.*; /** * Internal implementation of the Title pane in the northern region of a CollapsiblePane. @@ -49,31 +44,29 @@ */ public class CollapsibleTitlePane extends BaseCollapsibleTitlePane { private static final long serialVersionUID = 2528585101535037612L; - private JLabel titleLabel; - private JLabel iconLabel; + private final JLabel titleLabel; + private final JLabel iconLabel; - private JLabel preIconLabel; + private final JLabel preIconLabel; private boolean collapsed; - private Color startColor; - private Color endColor; - - private Color titleColor; - private boolean subPane; private Image backgroundImage; + private final int fontSize; + + private static final Color COLOR_TITLE_PANE_TEXT = new Color(33, 93, 198); + private static final Color COLOR_TITLE_PANE_GRADIENT_START = new Color(238,242,253); + private static final Color COLOR_TITLE_PANE_GRADIENT_END = Color.white; + public CollapsibleTitlePane() { setLayout(new GridBagLayout()); - titleColor = new Color(33, 93, 198); - Font titleFont = new Font("Dialog", Font.BOLD, 11); + fontSize = SettingsManager.getLocalPreferences().getContactListFontSize(); + Font titleFont = new Font("Dialog", Font.BOLD, fontSize); - // Initialize color - startColor = new Color(238,242,253); - endColor = Color.white; titleLabel = new JLabel(); iconLabel = new JLabel(); @@ -90,17 +83,19 @@ public CollapsibleTitlePane() { titleLabel.setForeground(customTitleColor); } else { - titleLabel.setForeground(titleColor); + titleLabel.setForeground(COLOR_TITLE_PANE_TEXT); } titleLabel.setFont(titleFont); addMouseListener(new MouseAdapter() { - public void mouseEntered(MouseEvent e) { + @Override + public void mouseEntered(MouseEvent e) { setCursor(GraphicUtils.HAND_CURSOR); } - public void mouseExited(MouseEvent e) { + @Override + public void mouseExited(MouseEvent e) { setCursor(GraphicUtils.DEFAULT_CURSOR); } }); @@ -113,66 +108,49 @@ public void mouseExited(MouseEvent e) { // startColor = getColor(start); // endColor = getColor(end); // } - - } - public void setStartColor(Color color) { - // Initialize color - startColor = color; - } - - public void setEndColor(Color color) { - endColor = color; - } - - public void setIcon(Icon icon) { + @Override + public void setIcon(Icon icon) { titleLabel.setIcon(icon); } - public void setTitle(String title) { + @Override + public void setTitle(String title) { titleLabel.setText(title); } - public boolean isCollapsed() { + @Override + public boolean isCollapsed() { return collapsed; } - public void setCollapsed(boolean collapsed) { + @Override + public void setCollapsed(boolean collapsed) { this.collapsed = collapsed; if (!isSubPane()) { if (!collapsed) { - preIconLabel.setIcon(SparkRes.getImageIcon(SparkRes.PANE_DOWN_ARROW_IMAGE)); + preIconLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PANE_DOWN_ARROW_IMAGE)); } else { - preIconLabel.setIcon(SparkRes.getImageIcon(SparkRes.PANE_UP_ARROW_IMAGE)); + preIconLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PANE_UP_ARROW_IMAGE)); } } else { iconLabel.setIcon(null); if (collapsed) { - preIconLabel.setIcon(SparkRes.getImageIcon(SparkRes.PLUS_SIGN)); + preIconLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PLUS_SIGN)); } else { - preIconLabel.setIcon(SparkRes.getImageIcon(SparkRes.MINUS_SIGN)); + preIconLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.MINUS_SIGN)); } } } - public void setTitleColor(Color color) { - titleColor = color; - - titleLabel.setForeground(color); - } - - public Color getTitleColor() { - return titleColor; - } - - - public void paintComponent(Graphics g) { + @Override + public void paintComponent(Graphics g) { if (backgroundImage != null) { double scaleX = getWidth() / (double)backgroundImage.getWidth(null); double scaleY = getHeight() / (double)backgroundImage.getHeight(null); @@ -181,8 +159,8 @@ public void paintComponent(Graphics g) { return; } - Color stopColor = endColor; - Color starterColor = startColor; + Color stopColor = COLOR_TITLE_PANE_GRADIENT_END; + Color starterColor = COLOR_TITLE_PANE_GRADIENT_START; Color customStartColor = (Color)UIManager.get("CollapsiblePane.startColor"); Color customEndColor = (Color)UIManager.get("CollapsiblePane.endColor"); diff --git a/src/java/org/jivesoftware/spark/component/panes/ICollapsibleTitlePane.java b/core/src/main/java/org/jivesoftware/spark/component/panes/ICollapsibleTitlePane.java similarity index 94% rename from src/java/org/jivesoftware/spark/component/panes/ICollapsibleTitlePane.java rename to core/src/main/java/org/jivesoftware/spark/component/panes/ICollapsibleTitlePane.java index 123e3b36e..fc84f1471 100644 --- a/src/java/org/jivesoftware/spark/component/panes/ICollapsibleTitlePane.java +++ b/core/src/main/java/org/jivesoftware/spark/component/panes/ICollapsibleTitlePane.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2011 eZuce Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/spark/component/renderer/JContactItemRenderer.java b/core/src/main/java/org/jivesoftware/spark/component/renderer/JContactItemRenderer.java similarity index 92% rename from src/java/org/jivesoftware/spark/component/renderer/JContactItemRenderer.java rename to core/src/main/java/org/jivesoftware/spark/component/renderer/JContactItemRenderer.java index 23f2c8850..605c83b9c 100644 --- a/src/java/org/jivesoftware/spark/component/renderer/JContactItemRenderer.java +++ b/core/src/main/java/org/jivesoftware/spark/component/renderer/JContactItemRenderer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2013 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,11 +27,11 @@ * extend JPanel here directly and customize here. * */ -public class JContactItemRenderer extends ContactItem implements ListCellRenderer { - JPanelRenderer basicPanelRenderer; +public class JContactItemRenderer extends ContactItem implements ListCellRenderer { + private final JPanelRenderer basicPanelRenderer; public JContactItemRenderer() { - super("", "", ""); + super("", "", null); setOpaque(true); basicPanelRenderer = new JPanelRenderer(); } @@ -49,7 +45,7 @@ public Component getListCellRendererComponent(JList list, Object value, int inde setFocusable(false); setNickname(renderItem.getNickname()); setAlias(renderItem.getAlias()); - if (this.getDisplayName().trim().isEmpty()) { + if (this.getDisplayName().isEmpty()) { // Fallback hack to show something other than empty string. // JID can't be set after object creation, so alias is reset. setAlias(renderItem.getDisplayName()); diff --git a/core/src/main/java/org/jivesoftware/spark/component/renderer/JLabelIconRenderer.java b/core/src/main/java/org/jivesoftware/spark/component/renderer/JLabelIconRenderer.java new file mode 100644 index 000000000..a2a02955b --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/component/renderer/JLabelIconRenderer.java @@ -0,0 +1,115 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.component.renderer; + +import java.awt.Color; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.ListCellRenderer; + +import java.awt.Component; +import java.awt.Point; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.border.EmptyBorder; + +/** + * The JLabelIconRenderer is the an implementation of + * ListCellRenderer to add icons w/ associated text in JComboBox and JList. + * + * @author Derek DeMoro + */ +public class JLabelIconRenderer extends JLabel implements ListCellRenderer { + + private static final long serialVersionUID = -694803906607554443L; + private int mindex = -1; + + /** + * Construct Default JLabelIconRenderer. + */ + public JLabelIconRenderer() { + setOpaque(true); + this.setVerticalTextPosition(JLabel.CENTER); + this.setHorizontalTextPosition(JLabel.RIGHT); + this.setHorizontalAlignment(JLabel.LEFT); + } + + @Override + public Component getListCellRendererComponent(JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus) { + + this.setVerticalTextPosition(JLabel.CENTER); + this.setHorizontalTextPosition(JLabel.RIGHT); + + list.addMouseMotionListener(new MouseAdapter() { + public void mouseMoved(MouseEvent me) { + Point p = new Point(me.getX(), me.getY()); + int index = list.locationToIndex(p); + if (index != mindex) { + mindex = index; + list.repaint(); + } + } + }); + Color backgroundColor = mindex == index ? list.getSelectionBackground() : list.getBackground(); + + list.addMouseListener(new MouseAdapter() { + @Override + public void mouseExited(MouseEvent e) { + mindex = -1; + if (isSelected) { + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + } else { + setBackground(backgroundColor); + setForeground(list.getForeground()); + } + list.repaint(); + } + + @Override + public void mouseEntered(MouseEvent e) { + + if (isSelected) { + setBackground(list.getSelectionBackground().darker()); + setForeground(list.getSelectionForeground()); + } else { + setBackground(backgroundColor); + setForeground(list.getForeground()); + } + } + + }); + + if (isSelected) { + setBackground(list.getSelectionBackground().darker()); + setForeground(list.getSelectionForeground()); + } else { + setBackground(backgroundColor); + setForeground(list.getForeground()); + } + JLabel label = (JLabel) value; + setIcon(label.getIcon()); + setText(label.getText()); + setBorder(new EmptyBorder(0, 15, 0, 15)); + setIconTextGap(5); + + return this; + } +} diff --git a/src/java/org/jivesoftware/spark/component/renderer/JPanelRenderer.java b/core/src/main/java/org/jivesoftware/spark/component/renderer/JPanelRenderer.java similarity index 95% rename from src/java/org/jivesoftware/spark/component/renderer/JPanelRenderer.java rename to core/src/main/java/org/jivesoftware/spark/component/renderer/JPanelRenderer.java index 3eaab1d2b..873c38838 100644 --- a/src/java/org/jivesoftware/spark/component/renderer/JPanelRenderer.java +++ b/core/src/main/java/org/jivesoftware/spark/component/renderer/JPanelRenderer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,7 +31,7 @@ * * @author Derek DeMoro */ -public class JPanelRenderer extends JPanel implements ListCellRenderer { +public class JPanelRenderer extends JPanel implements ListCellRenderer { private static final long serialVersionUID = -8968866073878932932L; /** @@ -45,7 +41,8 @@ public JPanelRenderer() { setOpaque(true); } - public Component getListCellRendererComponent(JList list, + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, diff --git a/src/java/org/jivesoftware/spark/component/renderer/ListIconRenderer.java b/core/src/main/java/org/jivesoftware/spark/component/renderer/ListIconRenderer.java similarity index 94% rename from src/java/org/jivesoftware/spark/component/renderer/ListIconRenderer.java rename to core/src/main/java/org/jivesoftware/spark/component/renderer/ListIconRenderer.java index ca2b34c27..950517f29 100644 --- a/src/java/org/jivesoftware/spark/component/renderer/ListIconRenderer.java +++ b/core/src/main/java/org/jivesoftware/spark/component/renderer/ListIconRenderer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,7 +30,7 @@ * * @author Derek DeMoro */ -public class ListIconRenderer extends JLabel implements ListCellRenderer { +public class ListIconRenderer extends JLabel implements ListCellRenderer { private static final long serialVersionUID = -1440360116105487085L; /** @@ -46,7 +42,8 @@ public ListIconRenderer() { setVerticalAlignment(CENTER); } - public Component getListCellRendererComponent(JList list, + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, diff --git a/core/src/main/java/org/jivesoftware/spark/component/tabbedPane/SparkTab.java b/core/src/main/java/org/jivesoftware/spark/component/tabbedPane/SparkTab.java new file mode 100644 index 000000000..c79f96beb --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/component/tabbedPane/SparkTab.java @@ -0,0 +1,88 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.component.tabbedPane; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; + +import javax.swing.Icon; +import javax.swing.JPanel; + +public class SparkTab extends JPanel { + + private static final long serialVersionUID = 2027267184472260195L; + private final SparkTabbedPane pane; + private final Component component; + + public SparkTab(SparkTabbedPane pane, Component comp) { + this.pane = pane; + this.component = comp; + this.setLayout(new BorderLayout()); + add(comp); + } + + public void setTabTitle(String title) { + pane.setTitleAt(pane.getTabPosition(this), title); + } + + public void setIcon(Icon icon) { + pane.setIconAt(pane.getTabPosition(this), icon); + } + + public Component getComponent() { + return component; + } + + public String getTitleLabel() { + return pane.getTitleAt(pane.getTabPosition(this)); + } + + public String getActualText() { + return pane.getTitleAt(pane.getTabPosition(this)); + } + + public void setTitleColor(Color color) { + pane.setTitleColorAt(pane.getTabPosition(this), color); + } + + public Color getTitleColor() { + return pane.getTitleColorAt(pane.getTabPosition(this)); + } + + public void setTabBold(boolean bold) { + pane.setTitleBoldAt(pane.getTabPosition(this), bold); + } + + public Font getDefaultFont() { + return pane.getDefaultFontAt(pane.getTabPosition(this)); + } + + public void setTabFont(Font font) { + pane.setTitleFontAt(pane.getTabPosition(this), font); + } + + public void setShowUnreadMessageIcon(boolean show, int unreadCount) { + pane.showUnreadMessageIndicator(pane.getTabbedPane(), show, unreadCount); + } + + public void validateTab() { + invalidate(); + validate(); + repaint(); + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/component/tabbedPane/SparkTabbedPane.java b/core/src/main/java/org/jivesoftware/spark/component/tabbedPane/SparkTabbedPane.java new file mode 100644 index 000000000..016b97265 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/component/tabbedPane/SparkTabbedPane.java @@ -0,0 +1,652 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.component.tabbedPane; + +import org.jivesoftware.Spark; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.ChatRoomNotFoundException; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import javax.swing.*; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.Iterator; +import java.util.concurrent.CopyOnWriteArrayList; + +public class SparkTabbedPane extends JPanel { + + private static final long serialVersionUID = -9007068462231539973L; + private static final String NAME = "SparkTabbedPane"; + private final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList<>(); + private final JTabbedPane pane; + private final Icon closeInactiveButtonIcon; + private final Icon closeActiveButtonIcon; + private boolean closeEnabled = false; + private int dragTabIndex = -1; + + /** + * The default Hand cursor. + */ + public static final Cursor HAND_CURSOR = new Cursor(Cursor.HAND_CURSOR); + + /** + * The default Text Cursor. + */ + public static final Cursor DEFAULT_CURSOR = new Cursor( + Cursor.DEFAULT_CURSOR); + + public SparkTabbedPane() { + this(JTabbedPane.TOP); + } + + public SparkTabbedPane(final Integer type) { + this(type.intValue()); + } + + public SparkTabbedPane(final int type) { + + pane = buildTabbedPane(type); + pane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); + setLayout(new BorderLayout()); + add(pane); + ChangeListener changeListener = changeEvent -> { + JTabbedPane sourceTabbedPane = (JTabbedPane) changeEvent.getSource(); + int index = sourceTabbedPane.getSelectedIndex(); + if (index >= 0) { + fireTabSelected(getTabAt(index), getTabAt(index).getComponent(), index); + } + }; + pane.addChangeListener(changeListener); + + closeInactiveButtonIcon = SparkRes.getImageIcon(SparkRes.Icon.CLOSE_WHITE_X_IMAGE); + closeActiveButtonIcon = SparkRes.getImageIcon(SparkRes.Icon.CLOSE_RED_X_IMAGE); + + } + + public void showUnreadMessageIndicator(JTabbedPane pane, boolean show, int unreadCount) { + //if tab style = wrap + if(!SettingsManager.getLocalPreferences().isTabsScroll()){ + return; + } + JToolBar tb = new JToolBar(); + tb.setFloatable(false); + tb.setBorder(null); + JLabel lbl = new JLabel("[" + unreadCount + "] ", SparkRes.getImageIcon(SparkRes.Icon.NEW_MESSAGE), JLabel.TRAILING); + + lbl.setForeground(Color.red); + lbl.setVerticalAlignment(JLabel.CENTER); + lbl.setVerticalTextPosition(JLabel.CENTER); + tb.add(lbl); + + if (show) { + pane.putClientProperty("JTabbedPane.trailingComponent", tb); + } else if (unreadCount == 0 || show == false) { + pane.putClientProperty("JTabbedPane.trailingComponent", null); + + } + } + + public SparkTab getTabContainingComponent(Component component) { + for (Component comp : pane.getComponents()) { + if (comp instanceof SparkTab) { + SparkTab tab = (SparkTab) comp; + if (tab.getComponent() == component) { + return tab; + } + } + } + return null; + } + + public SparkTab addTab(String title, Icon icon, final Component component) { + return addTab(title, icon, component, null); + } + + public SparkTab addTab(String title, Icon icon, final Component component, + String tip) { + final SparkTab sparktab = new SparkTab(this, component); + + TabPanel tabpanel = new TabPanel(sparktab, title, icon); + pane.addTab(title, null, sparktab, tip); + + pane.setTabComponentAt(pane.getTabCount() - 1, tabpanel); + fireTabAdded(sparktab, component, getTabPosition(sparktab)); + + return sparktab; + } + + public SparkTab getTabAt(int index) { + return ((SparkTab) pane.getComponentAt(index)); + } + + public int getTabPosition(SparkTab tab) { + return pane.indexOfComponent(tab); + } + + public Component getComponentInTab(SparkTab tab) { + return tab.getComponent(); + } + + public void setIconAt(int index, Icon icon) { + Component com = pane.getTabComponentAt(index); + if (com instanceof TabPanel) { + TabPanel panel = (TabPanel) com; + panel.setIcon(icon); + } + } + + public void setTitleAt(int index, String title) { + // k33ptoo commented out to allow first tab to show x number of unread messages + //if (index > 0) { + Component com = pane.getTabComponentAt(index); + if (com instanceof TabPanel) { + TabPanel panel = (TabPanel) com; + panel.setTitle(title); + pane.setTitleAt(index, title); + } + //} + } + + public void setTitleColorAt(int index, Color color) { + + Component com = pane.getTabComponentAt(index); + if (com instanceof TabPanel) { + TabPanel panel = (TabPanel) com; + panel.setTitleColor(color); + } + } + + public Color getTitleColorAt(int index) { + Color c = Color.black; + Component com = pane.getTabComponentAt(index); + if (com instanceof TabPanel) { + TabPanel panel = (TabPanel) com; + c = panel.getTitleColor(); + } + return c; + } + + /* + * Updates the tab colors for unread,active and inactive tabs + */ + public void updateActiveTab() { + for (int i = 0; i < pane.getTabCount(); ++i) { + Component com = pane.getTabComponentAt(i); + TabPanel panel = (TabPanel) com; + Font oldFont = panel.getFont(); + try { + if (SparkManager.getChatManager().getChatContainer().getChatRoom(i).getUnreadMessageCount() == 0) { + if (i == getSelectedIndex()) { + panel.setTitleFont(new Font(oldFont.getFontName(), Font.BOLD, + oldFont.getSize())); + panel.setTitleColor((Color) UIManager.get("Chat.activeTabColor")); + } else { + panel.setTitleFont(new Font(oldFont.getFontName(), Font.PLAIN, + oldFont.getSize())); + panel.setTitleColor((Color) UIManager.get("Chat.inactiveTabColor")); + } + } + + } catch (ChatRoomNotFoundException e) { + //Do nothing + } + + } + + } + + public void setTitleBoldAt(int index, boolean bold) { + Component com = pane.getTabComponentAt(index); + if (com instanceof TabPanel) { + TabPanel panel = (TabPanel) com; + panel.setTitleBold(bold); + } + } + + public void setTitleFontAt(int index, Font font) { + Component com = pane.getTabComponentAt(index); + if (com instanceof TabPanel) { + TabPanel panel = (TabPanel) com; + panel.setTitleFont(font); + } + } + + public Font getDefaultFontAt(int index) { + Component com = pane.getTabComponentAt(index); + if (com instanceof TabPanel) { + TabPanel panel = (TabPanel) com; + return panel.getDefaultFont(); + } + return null; + } + + public String getTitleAt(int index) { + return pane.getTitleAt(index); + } + + public int getTabCount() { + return pane.getTabCount(); + } + + public void setSelectedIndex(int index) { + pane.setSelectedIndex(index); + } + + public int indexOfComponent(Component component) { + for (Component comp : pane.getComponents()) { + if (comp instanceof SparkTab) { + SparkTab tab = (SparkTab) comp; + if (tab.getComponent() == component) { + return pane.indexOfComponent(tab); + } + } + } + return -1; + } + + public Component getComponentAt(int index) { + return ((SparkTab) pane.getComponentAt(index)).getComponent(); + } + + public Component getTabComponentAt(int index) { + return pane.getTabComponentAt(index); + } + + public Component getTabComponentAt(SparkTab tab) { + return pane.getTabComponentAt(indexOfComponent(tab)); + } + + public Component getSelectedComponent() { + if (pane.getSelectedComponent() instanceof SparkTab) { + SparkTab tab = (SparkTab) pane.getSelectedComponent(); + return tab.getComponent(); + } + return null; + } + + public void removeTabAt(int index) { + pane.remove(index); + } + + public int getSelectedIndex() { + return pane.getSelectedIndex(); + } + + public void setCloseButtonEnabled(boolean enable) { + closeEnabled = enable; + } + + public void addSparkTabbedPaneListener(SparkTabbedPaneListener listener) { + listeners.addIfAbsent(listener); + } + + public void removeSparkTabbedPaneListener(SparkTabbedPaneListener listener) { + listeners.remove(listener); + } + + protected void fireTabAdded(SparkTab tab, Component component, int index) { + final Iterator list = ModelUtil.reverseListIterator(listeners.listIterator()); + while (list.hasNext()) { + final SparkTabbedPaneListener listener = list.next(); + try { + listener.tabAdded(tab, component, index); + } catch (Exception e) { + Log.error("A SparkTabbedPaneListener (" + listener + ") threw an exception while processing a 'tabAdded' event (tab: '" + tab + "', component: '" + component + "', index: '" + index + "').", e); + } + } + } + + public JPanel getMainPanel() { + return this; + } + + public void removeComponent(Component comp) { + int index = indexOfComponent(comp); + if (index != -1) { + removeTabAt(index); + } + } + + protected void fireTabRemoved(SparkTab tab, Component component, int index) { + final Iterator list = ModelUtil.reverseListIterator(listeners.listIterator()); + while (list.hasNext()) { + final SparkTabbedPaneListener listener = list.next(); + try { + listener.tabRemoved(tab, component, index); + } catch (Exception e) { + Log.error("A SparkTabbedPaneListener (" + listener + ") threw an exception while processing a 'tabRemoved' event (tab: '" + tab + "', component: '" + component + "', index: '" + index + "').", e); + } + } + } + + protected void fireTabSelected(SparkTab tab, Component component, int index) { + final Iterator list = ModelUtil.reverseListIterator(listeners.listIterator()); + while (list.hasNext()) { + final SparkTabbedPaneListener listener = list.next(); + try { + listener.tabSelected(tab, component, index); + } catch (Exception e) { + Log.error("A SparkTabbedPaneListener (" + listener + ") threw an exception while processing a 'tabSelected' event (tab: '" + tab + "', component: '" + component + "', index: '" + index + "').", e); + } + } + } + + protected void allTabsClosed() { + final Iterator list = ModelUtil.reverseListIterator(listeners + .listIterator()); + while (list.hasNext()) { + list.next().allTabsRemoved(); + } + } + + public void close(SparkTab sparktab) { + int closeTabNumber = pane.indexOfComponent(sparktab); + pane.removeTabAt(closeTabNumber); + fireTabRemoved(sparktab, sparktab.getComponent(), closeTabNumber); + + if (pane.getTabCount() == 0) { + allTabsClosed(); + } + } + + private class TabPanel extends JPanel { + + private static final long serialVersionUID = -8249981130816404360L; + private final BorderLayout layout = new BorderLayout(5, 5); + private final Font defaultFontPlain = new Font("Dialog", Font.PLAIN, 11); + private final Font defaultFontBold = new Font("Dialog", Font.BOLD, 11); + private JLabel iconLabel; + private final JLabel titleLabel; + private final JLabel tabCloseButton = new JLabel(closeInactiveButtonIcon); + + public TabPanel(final SparkTab sparktab, String title, Icon icon) { + setOpaque(false); + this.setLayout(layout); + titleLabel = new JLabel(title); + + titleLabel.setFont(closeEnabled ? defaultFontBold + : defaultFontPlain); + if (icon != null) { + iconLabel = new JLabel(icon); + add(iconLabel, BorderLayout.WEST); + } + + add(titleLabel, BorderLayout.CENTER); + if (closeEnabled) { + tabCloseButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent mouseEvent) { + if (Spark.isWindows()) { + tabCloseButton.setIcon(closeActiveButtonIcon); + } + setCursor(HAND_CURSOR); + } + + @Override + public void mouseExited(MouseEvent mouseEvent) { + if (Spark.isWindows()) { + tabCloseButton.setIcon(closeInactiveButtonIcon); + } + setCursor(DEFAULT_CURSOR); + } + + @Override + public void mousePressed(MouseEvent mouseEvent) { + final SwingWorker closeTimerThread = new SwingWorker() { + @Override + public Object construct() { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + Log.error(e); + } + return true; + } + + @Override + public void finished() { + close(sparktab); + //reset counter + if (SparkManager.getChatManager().getChatContainer().getTotalNumberOfUnreadMessages() == 0) { + showUnreadMessageIndicator(SparkManager.getChatManager().getChatContainer().getTabbedPane(), false, SparkManager.getChatManager().getChatContainer().getTotalNumberOfUnreadMessages()); + } else { + showUnreadMessageIndicator(SparkManager.getChatManager().getChatContainer().getTabbedPane(), true, SparkManager.getChatManager().getChatContainer().getTotalNumberOfUnreadMessages()); + } + } + }; + closeTimerThread.start(); + } + }); + add(tabCloseButton, BorderLayout.EAST); + } + } + + @Override + public Dimension getPreferredSize() { + Dimension dim = super.getPreferredSize(); + + if (closeEnabled && titleLabel.getText() != null && titleLabel.getText().length() < 6 + && dim.getWidth() < 80) { + return new Dimension(80, dim.height); + + } else { + return dim; + } + + } + + public Font getDefaultFont() { + return defaultFontPlain; + } + + public void setIcon(Icon icon) { + iconLabel.setIcon(icon); + } + + public void setTitle(String title) { + titleLabel.setText(title); + } + + public Color getTitleColor() { + return titleLabel.getForeground(); + } + + public void setTitleColor(Color color) { + titleLabel.setForeground(color); + titleLabel.validate(); + titleLabel.repaint(); + } + + public void setTitleBold(boolean bold) { + Font oldFont = titleLabel.getFont(); + Font newFont; + if (bold) { + newFont = new Font(oldFont.getFontName(), Font.BOLD, + oldFont.getSize()); + } else { + newFont = new Font(oldFont.getFontName(), Font.PLAIN, + oldFont.getSize()); + } + + titleLabel.setFont(newFont); + titleLabel.validate(); + titleLabel.repaint(); + titleLabel.revalidate(); + } + + public void setTitleFont(Font font) { + titleLabel.setFont(font); + titleLabel.validate(); + titleLabel.repaint(); + titleLabel.revalidate(); + } + + } + + /** + * Drag and Drop + */ + public void enableDragAndDrop() { + final DragSourceListener dsl = new DragSourceListener() { + + @Override + public void dragDropEnd(DragSourceDropEvent event) { + dragTabIndex = -1; + } + + @Override + public void dragEnter(DragSourceDragEvent event) { + event.getDragSourceContext().setCursor(DragSource.DefaultMoveDrop); + } + + @Override + public void dragExit(DragSourceEvent event) { + } + + @Override + public void dragOver(DragSourceDragEvent event) { + } + + @Override + public void dropActionChanged(DragSourceDragEvent event) { + } + + }; + + final Transferable t = new Transferable() { + private final DataFlavor FLAVOR = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType, NAME); + + @Override + public Object getTransferData(DataFlavor flavor) { + return pane; + } + + @Override + public DataFlavor[] getTransferDataFlavors() { + DataFlavor[] f = new DataFlavor[1]; + f[0] = this.FLAVOR; + return f; + } + + @Override + public boolean isDataFlavorSupported(DataFlavor flavor) { + return flavor.getHumanPresentableName().equals(NAME); + } + + }; + + final DragGestureListener dgl = event -> { + dragTabIndex = pane.indexAtLocation(event.getDragOrigin().x, event.getDragOrigin().y); + try { + event.startDrag(DragSource.DefaultMoveDrop, t, dsl); + } catch (Exception idoe) { + Log.error(idoe); + } + }; + + final DropTargetListener dtl = new DropTargetListener() { + + @Override + public void dragEnter(DropTargetDragEvent event) { + } + + @Override + public void dragExit(DropTargetEvent event) { + } + + @Override + public void dragOver(DropTargetDragEvent event) { + } + + @Override + public void drop(DropTargetDropEvent event) { + int dropTabIndex = getTargetTabIndex(event.getLocation()); + moveTab(dragTabIndex, dropTabIndex); + } + + @Override + public void dropActionChanged(DropTargetDragEvent event) { + } + + }; + + new DropTarget(pane, DnDConstants.ACTION_COPY_OR_MOVE, dtl, true); + new DragSource().createDefaultDragGestureRecognizer(pane, DnDConstants.ACTION_COPY_OR_MOVE, dgl); + } + + private void moveTab(int prev, int next) { + if (next < 0 || prev == next) { + return; + } + Component cmp = pane.getComponentAt(prev); + Component tab = pane.getTabComponentAt(prev); + String str = pane.getTitleAt(prev); + Icon icon = pane.getIconAt(prev); + String tip = pane.getToolTipTextAt(prev); + boolean flg = pane.isEnabledAt(prev); + int tgtindex = prev > next ? next : next - 1; + pane.remove(prev); + pane.insertTab(str, icon, cmp, tip, tgtindex); + pane.setEnabledAt(tgtindex, flg); + + if (flg) { + pane.setSelectedIndex(tgtindex); + } + + pane.setTabComponentAt(tgtindex, tab); + } + + private int getTargetTabIndex(Point point) { + Point tabPt = SwingUtilities.convertPoint(pane, point, pane); + boolean isTB = pane.getTabPlacement() == JTabbedPane.TOP || pane.getTabPlacement() == JTabbedPane.BOTTOM; + for (int i = 0; i < getTabCount(); i++) { + Rectangle r = pane.getBoundsAt(i); + if (isTB) { + r.setRect(r.x - (r.width >> 1), r.y, r.width, r.height); + } else { + r.setRect(r.x, r.y - (r.height >> 1), r.width, r.height); + } + if (r.contains(tabPt)) { + return i; + } + } + Rectangle r = pane.getBoundsAt(getTabCount() - 1); + if (isTB) { + r.setRect(r.x + (r.width >> 1), r.y, r.width, r.height); + } else { + r.setRect(r.x, r.y + (r.height >> 1), r.width, r.height); + } + return r.contains(tabPt) ? getTabCount() : -1; + } + + protected JTabbedPane buildTabbedPane(final int type) { + return new JTabbedPane(type); + } + + protected JTabbedPane getTabbedPane() { + return pane; + } + +} diff --git a/src/java/org/jivesoftware/spark/component/tabbedPane/SparkTabbedPaneListener.java b/core/src/main/java/org/jivesoftware/spark/component/tabbedPane/SparkTabbedPaneListener.java similarity index 97% rename from src/java/org/jivesoftware/spark/component/tabbedPane/SparkTabbedPaneListener.java rename to core/src/main/java/org/jivesoftware/spark/component/tabbedPane/SparkTabbedPaneListener.java index e88f9681c..26ccc20da 100644 --- a/src/java/org/jivesoftware/spark/component/tabbedPane/SparkTabbedPaneListener.java +++ b/core/src/main/java/org/jivesoftware/spark/component/tabbedPane/SparkTabbedPaneListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/src/main/java/org/jivesoftware/spark/decorator/DefaultTabHandler.java b/core/src/main/java/org/jivesoftware/spark/decorator/DefaultTabHandler.java new file mode 100644 index 000000000..72893093d --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/decorator/DefaultTabHandler.java @@ -0,0 +1,117 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.decorator; + +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.tabbedPane.SparkTab; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.SparkTabHandler; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jxmpp.jid.EntityBareJid; + +import java.awt.Color; +import java.awt.Component; + +import javax.swing.*; + +/** + */ +public class DefaultTabHandler extends SparkTabHandler { + + public DefaultTabHandler() { + + } + + @Override + public boolean isTabHandled(SparkTab tab, Component component, boolean isSelectedTab, boolean chatFrameFocused) { + + if (component instanceof ChatRoom) { + ChatRoom room = (ChatRoom) component; + + boolean isStaleRoom = SparkManager.getChatManager().isStaleRoom(room); + + boolean isTyping = SparkManager.getChatManager().containsTypingNotification((ChatRoom) component); + + // Check if is typing. + if (isTyping) { + tab.setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_MESSAGE_EDIT_IMAGE)); + } else if (room instanceof ChatRoomImpl && !isStaleRoom) { + // User is not typing, therefore show default presence icon. + if (SparkManager.getConnection().isConnected()) { + EntityBareJid participantJID = ((ChatRoomImpl) room).getParticipantJID(); + Presence presence = PresenceManager.getPresence(participantJID); + Icon icon = PresenceManager.getIconFromPresence(presence); + tab.setIcon(icon); + } else { + tab.setIcon(SparkRes.getImageIcon(SparkRes.Icon.CLEAR_BALL_ICON)); + } + } + + if (!chatFrameFocused || !isSelectedTab) { + // Handle unread message count. + int unreadMessageCount = room.getUnreadMessageCount(); + + if (unreadMessageCount > 0) { + // Make tab red. + tab.setTitleColor((Color) UIManager.get("Chat.unreadMessageColor")); + tab.setTabBold(true); + tab.setShowUnreadMessageIcon(true, SparkManager.getChatManager().getChatContainer().getTotalNumberOfUnreadMessages()); + tab.setTabTitle(room.getTabTitle() + " (" + unreadMessageCount + ")"); + } + + } + + if (chatFrameFocused && isSelectedTab) { + tab.setTitleColor(Color.black); + + // tab.setTabFont(tab.getDefaultFont()); + tab.setTabTitle(room.getTabTitle()); + // Clear unread message count. + room.clearUnreadMessageCount(); + //handle other tabs with unread messages, still show the icon unread + if (SparkManager.getChatManager().getChatContainer().getTotalNumberOfUnreadMessages() == 0) { + tab.setShowUnreadMessageIcon(false, SparkManager.getChatManager().getChatContainer().getTotalNumberOfUnreadMessages()); + } else { + tab.setShowUnreadMessageIcon(true, SparkManager.getChatManager().getChatContainer().getTotalNumberOfUnreadMessages()); + } + } + + // Check if the room is stale. + if (isStaleRoom && component instanceof ChatRoomImpl) { + decorateStaleTab(tab, (ChatRoom) component); + } // Should only set the icon to default if the frame is in focus + // and the tab is the selected component. + + } + else { + if (!chatFrameFocused || !isSelectedTab) { + // Make tab red. + tab.setTitleColor((Color) UIManager.get("Chat.unreadMessageColor")); + tab.setTabBold(true); + } + if (isSelectedTab && chatFrameFocused) { + tab.setTitleColor(Color.black); + tab.setTabFont(tab.getDefaultFont()); + } + } + + return true; + } + +} diff --git a/src/java/org/jivesoftware/spark/filetransfer/ChatRoomTransferDecorator.java b/core/src/main/java/org/jivesoftware/spark/filetransfer/ChatRoomTransferDecorator.java similarity index 80% rename from src/java/org/jivesoftware/spark/filetransfer/ChatRoomTransferDecorator.java rename to core/src/main/java/org/jivesoftware/spark/filetransfer/ChatRoomTransferDecorator.java index 8636788ab..b2ec6bbfd 100644 --- a/src/java/org/jivesoftware/spark/filetransfer/ChatRoomTransferDecorator.java +++ b/core/src/main/java/org/jivesoftware/spark/filetransfer/ChatRoomTransferDecorator.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -49,35 +45,36 @@ */ public class ChatRoomTransferDecorator implements KeyListener, FileDropListener, ChatRoomClosingListener, ActionListener { - private ChatRoom chatRoom; - private ChatRoomButton sendFileButton; - private ChatRoomButton sendScreenShotButton; + private final ChatRoom chatRoom; + private final ChatRoomButton sendFileButton; + private final ChatRoomButton sendScreenShotButton; public ChatRoomTransferDecorator(final ChatRoom chatRoom) { - this.chatRoom = chatRoom; - - chatRoom.addFileDropListener(this); - chatRoom.getChatInputEditor().addKeyListener(this); - chatRoom.addClosingListener(this); + this.chatRoom = chatRoom; + chatRoom.addFileDropListener(this); + chatRoom.getChatInputEditor().addKeyListener(this); + chatRoom.addClosingListener(this); - sendFileButton = UIComponentRegistry.getButtonFactory().createSendFileButton(); - sendFileButton.setToolTipText(Res.getString("message.send.file.to.user")); + sendFileButton = UIComponentRegistry.getButtonFactory().createSendFileButton(); + sendFileButton.setToolTipText(Res.getString("message.send.file.to.user")); - chatRoom.addChatRoomButton(sendFileButton); + chatRoom.addChatRoomButton(sendFileButton); + sendFileButton.addActionListener(this); - sendScreenShotButton = UIComponentRegistry.getButtonFactory().createScreenshotButton(); - sendScreenShotButton.setToolTipText(Res.getString("message.send.picture")); - chatRoom.addChatRoomButton(sendScreenShotButton); + sendScreenShotButton = UIComponentRegistry.getButtonFactory().createScreenshotButton(); + sendScreenShotButton.setToolTipText(Res.getString("message.send.picture")); - sendFileButton.addActionListener(this); - sendScreenShotButton.addActionListener(this); + chatRoom.addChatRoomButton(sendScreenShotButton); + sendScreenShotButton.addActionListener(this); } - public void keyTyped(KeyEvent e) { + @Override + public void keyTyped(KeyEvent e) { } - public void keyPressed(KeyEvent ke) { + @Override + public void keyPressed(KeyEvent ke) { if (ke.getKeyCode() == KeyEvent.VK_V) { int i = ke.getModifiers(); if ((i & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) { @@ -92,7 +89,8 @@ public void keyPressed(KeyEvent ke) { } } - public void keyReleased(KeyEvent e) { + @Override + public void keyReleased(KeyEvent e) { } @Override @@ -111,7 +109,8 @@ public void filesDropped(Collection files, Component component) { } - public void actionPerformed(ActionEvent e) { + @Override + public void actionPerformed(ActionEvent e) { if (e.getSource() == sendScreenShotButton) { SparkManager.getTransferManager().sendScreenshot(sendScreenShotButton, chatRoom); } @@ -122,7 +121,8 @@ public void actionPerformed(ActionEvent e) { private void showFilePicker() { SwingWorker worker = new SwingWorker() { - public Object construct() { + @Override + public Object construct() { try { Thread.sleep(10); } @@ -132,7 +132,8 @@ public Object construct() { return true; } - public void finished() { + @Override + public void finished() { FileDialog fileChooser = SparkManager.getTransferManager().getFileChooser(SparkManager.getChatManager().getChatContainer().getChatFrame(), Res.getString("title.select.file.to.send")); if (SparkManager.getTransferManager().getDefaultDirectory() != null) { @@ -158,7 +159,8 @@ public void finished() { worker.start(); } - public void closing() { + @Override + public void closing() { chatRoom.removeFileDropListener(this); chatRoom.getChatInputEditor().removeKeyListener(this); chatRoom.removeClosingListener(this); diff --git a/src/java/org/jivesoftware/spark/filetransfer/FileTransferListener.java b/core/src/main/java/org/jivesoftware/spark/filetransfer/FileTransferListener.java similarity index 96% rename from src/java/org/jivesoftware/spark/filetransfer/FileTransferListener.java rename to core/src/main/java/org/jivesoftware/spark/filetransfer/FileTransferListener.java index 41b3b82cf..0c615108f 100644 --- a/src/java/org/jivesoftware/spark/filetransfer/FileTransferListener.java +++ b/core/src/main/java/org/jivesoftware/spark/filetransfer/FileTransferListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/src/main/java/org/jivesoftware/spark/filetransfer/HttpDownloader.java b/core/src/main/java/org/jivesoftware/spark/filetransfer/HttpDownloader.java new file mode 100644 index 000000000..8b2d6cec2 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/filetransfer/HttpDownloader.java @@ -0,0 +1,97 @@ +package org.jivesoftware.spark.filetransfer; + +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; +import org.jivesoftware.smack.SmackConfiguration; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.updater.AcceptAllCertsConnectionManager; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.util.concurrent.TimeUnit; + +public class HttpDownloader { + + private static final long MAX_FILE_SIZE = 1_048_576; // 1MB in bytes + + public static byte[] downloadContent(URI uri) { + Log.debug("Start downloading " + uri.toString()); + try (final CloseableHttpClient httpClient = + HttpClients.custom().useSystemProperties() + .setConnectionManager(AcceptAllCertsConnectionManager.getInstance()) // FIXME: do not use acceptallcdertsconnectionmanager! It is unsafe. Only use trusted certificates! + .setDefaultRequestConfig(RequestConfig.custom().setResponseTimeout(SmackConfiguration.getDefaultReplyTimeout() / 10, TimeUnit.MILLISECONDS).build()) + .build() + ) { + // First, make a pre-flight HEAD request to check the file size. + // This also helps avoid calls to unsecure API that use GET method (e.g. routers cgi-bin scripts) + final ClassicHttpRequest headRequest = ClassicRequestBuilder.head(uri) + .setHeader("Accept", "image/*") + .setHeader("User-Agent", "Spark HttpFileUpload") + .build(); + + Boolean sizeCheck = httpClient.execute(headRequest, response -> { + if (response.getCode() != 200) { + // ok, that image is probably removed (404), forbidden (403), or this wasn't an image link but an API. + return false; + } + // Check the Content-Length + Header contentLengthHeader = response.getFirstHeader("Content-Length"); + if (contentLengthHeader == null) { + return false; + } + long contentLength = Long.parseLong(contentLengthHeader.getValue()); + if (contentLength > MAX_FILE_SIZE || contentLength <= 0) { + Log.debug("File size " + contentLength + " bytes exceeds maximum limit of " + MAX_FILE_SIZE + " bytes for " + uri); + return false; + } + return true; + }); + + if (!sizeCheck) { + Log.debug("File size check failed for " + uri); + return null; + } + + // Proceed with the GET request to download the file + final ClassicHttpRequest request = ClassicRequestBuilder.get(uri) + .setHeader("Accept", "image/*") + .setHeader("User-Agent", "Spark HttpFileUpload") + .build(); + + byte[] contentBytes = httpClient.execute(request, response -> { + if (response.getCode() != 200 || response.getEntity() == null) { + return null; + } + // double-check for the content length + long contentLength = response.getEntity().getContentLength(); + if (contentLength > MAX_FILE_SIZE || contentLength <= 0) { + Log.debug("File size " + contentLength + " bytes exceeds maximum limit of " + MAX_FILE_SIZE + " bytes for " + uri); + return null; + } + byte[] content; + try { + // First, read the content fully to avoid broken images + content = EntityUtils.toByteArray(response.getEntity()); + return content; + } catch (IOException e) { + Log.warning("Network error while loading picture from " + uri, e); + return null; + } finally { + // if the connection is "prematurely closed," clean up the local resources + EntityUtils.consumeQuietly(response.getEntity()); + } + }); + return contentBytes; + } catch (Exception e) { + Log.warning("Unable to download content from " + uri + ": " + e); + return null; + } + } +} diff --git a/src/java/org/jivesoftware/spark/filetransfer/SparkTransferManager.java b/core/src/main/java/org/jivesoftware/spark/filetransfer/SparkTransferManager.java similarity index 84% rename from src/java/org/jivesoftware/spark/filetransfer/SparkTransferManager.java rename to core/src/main/java/org/jivesoftware/spark/filetransfer/SparkTransferManager.java index d97e80b62..fa89878f6 100644 --- a/src/java/org/jivesoftware/spark/filetransfer/SparkTransferManager.java +++ b/core/src/main/java/org/jivesoftware/spark/filetransfer/SparkTransferManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -47,8 +43,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; -import java.util.List; import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; import javax.imageio.ImageIO; import javax.swing.JMenu; @@ -66,9 +62,11 @@ import org.jivesoftware.smack.filter.AndFilter; import org.jivesoftware.smack.filter.FromMatchesFilter; import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager; import org.jivesoftware.smackx.filetransfer.FileTransferManager; import org.jivesoftware.smackx.filetransfer.FileTransferRequest; import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer; @@ -77,14 +75,7 @@ import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.filetransfer.preferences.FileTransferPreference; import org.jivesoftware.spark.preference.PreferenceManager; -import org.jivesoftware.spark.ui.ChatFrame; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomButton; -import org.jivesoftware.spark.ui.ChatRoomListenerAdapter; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.ui.ImageSelectionPanel; -import org.jivesoftware.spark.ui.TranscriptWindow; +import org.jivesoftware.spark.ui.*; import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; import org.jivesoftware.spark.util.ResourceUtils; import org.jivesoftware.spark.util.SwingWorker; @@ -94,7 +85,10 @@ import org.jivesoftware.sparkimpl.plugin.filetransfer.transfer.ui.SendFileTransfer; import org.jivesoftware.sparkimpl.plugin.filetransfer.transfer.ui.TransferUtils; import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; -import org.jxmpp.util.XmppStringUtils; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.EntityFullJid; +import org.jxmpp.jid.Jid; /** * Responsible for the handling of File Transfer within Spark. You would use the SparkManager @@ -104,17 +98,18 @@ */ public class SparkTransferManager { - private List listeners = new ArrayList<>(); + private final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList<>(); private File defaultDirectory; private static SparkTransferManager singleton; private static final Object LOCK = new Object(); private FileTransferManager transferManager; - private Map> waitMap = new HashMap<>(); + private final Map> waitMap = new HashMap<>(); private BufferedImage bufferedImage; private ImageSelectionPanel selectionPanel; private Robot robot; + private InBandBytestreamManager ibbmanager; /** @@ -138,65 +133,56 @@ public static SparkTransferManager getInstance() { } private SparkTransferManager() { - boolean enabled = Enterprise.containsFeature(Enterprise.FILE_TRANSFER_FEATURE); - if (!enabled) { - return; - } + + // See if we should disable the option to transfer files and images + if (Default.getBoolean(Default.DISABLE_FILE_TRANSFER) || !Enterprise.containsFeature(Enterprise.FILE_TRANSFER_FEATURE)) return; SparkManager.getConnection().addConnectionListener(new ConnectionListener() { @Override public void connected( XMPPConnection xmppConnection ) { - } @Override public void authenticated( XMPPConnection xmppConnection, boolean b ) { transferManager = FileTransferManager.getInstanceFor( SparkManager.getConnection() ); - - final ContactList contactList = SparkManager.getWorkspace().getContactList(); - - // Create the listener - transferManager.addFileTransferListener( request -> SwingUtilities.invokeLater( () -> handleTransferRequest(request, contactList) ) ); - - // Add Send File to Chat Room - addSendFileButton(); - - contactList.addFileDropListener( ( files, component ) -> { - if (component instanceof ContactItem) { - ContactItem item = (ContactItem)component; - - ChatRoom chatRoom = null; - for (File file : files) { - chatRoom = sendFile(file, item.getJID()); - } - - if (chatRoom != null) { - SparkManager.getChatManager().getChatContainer().activateChatRoom(chatRoom); - } - } - } ); - } - public void connectionClosed() { + @Override + public void connectionClosed() { } - public void connectionClosedOnError(Exception e) { + @Override + public void connectionClosedOnError(Exception e) { } + }); - public void reconnectingIn(int seconds) { - } + final ContactList contactList = SparkManager.getWorkspace().getContactList(); - public void reconnectionSuccessful() { - // Re-create transfer manager. - transferManager = FileTransferManager.getInstanceFor( SparkManager.getConnection() ); - } + // Create the listener + transferManager = FileTransferManager.getInstanceFor( SparkManager.getConnection() ); + transferManager.addFileTransferListener( request -> SwingUtilities.invokeLater( () -> handleTransferRequest(request, contactList) ) ); + //SPARK-1869 + ibbmanager = InBandBytestreamManager.getByteStreamManager( SparkManager.getConnection()); + ibbmanager.setDefaultBlockSize(61440); + // Add Send File to Chat Room + addSendFileButton(); + + contactList.addFileDropListener( ( files, component ) -> { + if (component instanceof ContactItem) { + ContactItem item = (ContactItem)component; + + ChatRoom chatRoom = null; + for (File file : files) { + chatRoom = sendFile(file, item.getJid()); + } - public void reconnectionFailed(Exception e) { + if (chatRoom != null) { + SparkManager.getChatManager().getChatContainer().activateChatRoom(chatRoom); + } } - }); + } ); try { robot = new Robot(); @@ -211,7 +197,7 @@ public void reconnectionFailed(Exception e) { prefManager.addPreference(new FileTransferPreference()); final JMenu actionsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions")); - JMenuItem downloadsMenu = new JMenuItem("", SparkRes.getImageIcon(SparkRes.DOWNLOAD_16x16)); + JMenuItem downloadsMenu = new JMenuItem("", SparkRes.getImageIcon(SparkRes.Icon.DOWNLOAD_16x16)); ResourceUtils.resButton(downloadsMenu, Res.getString("menuitem.view.downloads")); actionsMenu.addSeparator(); actionsMenu.add(downloadsMenu); @@ -226,7 +212,7 @@ public void reconnectionFailed(Exception e) { // // Add View Downloads to Command Panel // final JPanel commandPanel = SparkManager.getWorkspace().getCommandPanel(); // -// RolloverButton viewDownloads = new RolloverButton(SparkRes.getImageIcon(SparkRes.DOWNLOAD_16x16)); +// RolloverButton viewDownloads = new RolloverButton(SparkRes.getImageIcon(SparkRes.Icons.DOWNLOAD_16x16)); // viewDownloads.setToolTipText(Res.getString("menuitem.view.downloads")); // commandPanel.add(viewDownloads); // viewDownloads.addActionListener(new ActionListener() { @@ -257,9 +243,7 @@ private static URI getFileURI(String filePath) { filePath = filePath.replaceAll(" ", "%20"); URL url = new URL(filePath); uri = url.toURI(); - } catch (MalformedURLException ex) { - ex.printStackTrace(); - } catch (URISyntaxException ex) { + } catch (MalformedURLException | URISyntaxException ex) { ex.printStackTrace(); } } else { @@ -275,8 +259,8 @@ private void handleTransferRequest(FileTransferRequest request, ContactList cont return; } - String requestor = request.getRequestor(); - String bareJID = XmppStringUtils.parseBareJid(requestor); + Jid requestor = request.getRequestor(); + EntityBareJid bareJID = requestor.asEntityBareJidOrThrow(); String fileName = request.getFileName(); @@ -293,10 +277,10 @@ private void handleTransferRequest(FileTransferRequest request, ContactList cont TranscriptWindow transcriptWindow = chatRoom.getTranscriptWindow(); transcriptWindow.insertCustomText(Res.getString("message.file.transfer.chat.window"), true, false, Color.BLACK); - final ReceiveFileTransfer receivingMessageUI = new ReceiveFileTransfer(); + final ReceiveFileTransfer receivingMessageUI = new ReceiveFileTransfer(chatRoom); receivingMessageUI.acceptFileTransfer(request); - chatRoom.addClosingListener( () -> receivingMessageUI.cancelTransfer() ); + chatRoom.addClosingListener(receivingMessageUI::cancelTransfer); transcriptWindow.addComponent(receivingMessageUI); @@ -327,30 +311,23 @@ public void sendFileTo(ContactItem item) { if (file.exists()) { defaultDirectory = file.getParentFile(); - sendFile( file, item.getJID() ); + sendFile( file, item.getJid() ); } } private void addSendFileButton() { final ChatManager chatManager = SparkManager.getChatManager(); - chatManager.addChatRoomListener(new ChatRoomListenerAdapter() { - - public void chatRoomOpened(final ChatRoom room) { + chatManager.addChatRoomListener(new ChatRoomListener() { + @Override + public void chatRoomOpened(final ChatRoom room) { if (!(room instanceof ChatRoomImpl)) { return; } - // Otherwise, new ChatRoomTransferDecorator(room); } - - public void chatRoomClosed(ChatRoom room) { - - } }); - - } public void sendScreenshot(final ChatRoomButton button, final ChatRoom room) { @@ -371,7 +348,8 @@ public void sendScreenshot(final ChatRoomButton button, final ChatRoom room) { } final SwingWorker worker = new SwingWorker() { - public Object construct() { + @Override + public Object construct() { try { Thread.sleep(1000); Rectangle area = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()); @@ -392,7 +370,8 @@ public Object construct() { return null; } - public void finished() { + @Override + public void finished() { bufferedImage = (BufferedImage)get(); if (bufferedImage == null) { UIManager.put("OptionPane.okButtonText", Res.getString("ok")); @@ -406,7 +385,8 @@ public void finished() { selectionPanel.setImage(bufferedImage); selectionPanel.validate(); selectionPanel.addMouseListener(new MouseAdapter() { - public void mouseReleased(MouseEvent e) { + @Override + public void mouseReleased(MouseEvent e) { Rectangle clip = selectionPanel.getClip(); BufferedImage newImage = null; try { @@ -438,7 +418,8 @@ public void mouseReleased(MouseEvent e) { }); frame.addKeyListener(new KeyAdapter() { - public void keyReleased(KeyEvent e) { + @Override + public void keyReleased(KeyEvent e) { if (e.getKeyChar() == KeyEvent.VK_ESCAPE) { frame.dispose(); frame.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); @@ -479,23 +460,19 @@ private void addPresenceListener() { SparkManager.getConnection().addAsyncStanzaListener( stanza -> { Presence presence = (Presence)stanza; if (presence.isAvailable()) { - String bareJID = XmppStringUtils.parseBareJid(presence.getFrom()); + BareJid bareJID = presence.getFrom().asBareJid(); // Iterate through map. ArrayList list = waitMap.get(bareJID); if (list != null) { // Iterate through list and send. - Iterator iter = list.iterator(); ChatRoom room = null; - while (iter.hasNext()) { - File file = iter.next(); + for (File file : list) { room = sendFile(file, bareJID); } if (room != null) { - Message message = new Message(); - message.setBody(Res.getString("message.sent.offline.files")); - room.sendMessage(message); + room.sendMessage(Res.getString("message.sent.offline.files")); } } @@ -512,7 +489,7 @@ private void addPresenceListener() { * @param jid the jid of the user to send the file to. * @return the ChatRoom of the user. */ - public ChatRoom sendFile(File file, String jid) { + public ChatRoom sendFile(File file, Jid jid) { long maxsize = Long.parseLong(Default.getString(Default.FILE_TRANSFER_MAXIMUM_SIZE)); long warningsize = Long.parseLong(Default.getString(Default.FILE_TRANSFER_WARNING_SIZE)); @@ -539,25 +516,26 @@ public ChatRoom sendFile(File file, String jid) { } final ContactList contactList = SparkManager.getWorkspace().getContactList(); - String bareJID = XmppStringUtils.parseBareJid(jid); - String fullJID = PresenceManager.getFullyQualifiedJID(jid); + EntityFullJid fullJID = PresenceManager.getFullyQualifiedJID(jid.asBareJid()); + EntityBareJid bareJid = fullJID.asEntityBareJid(); + - if (!PresenceManager.isOnline(jid)) { + if (!PresenceManager.isOnline(bareJid)) { ArrayList list = waitMap.get(jid); if (list == null) { list = new ArrayList<>(); } list.add(file); - waitMap.put(jid, list); + waitMap.put(bareJid, list); ChatRoom chatRoom; ContactItem contactItem = contactList.getContactItemByJID(jid); if (contactItem != null) { - chatRoom = SparkManager.getChatManager().createChatRoom(jid, contactItem.getDisplayName(), contactItem.getDisplayName()); + chatRoom = SparkManager.getChatManager().createChatRoom(bareJid, contactItem.getDisplayName(), contactItem.getDisplayName()); } else { - chatRoom = SparkManager.getChatManager().createChatRoom(jid, jid, jid); + chatRoom = SparkManager.getChatManager().createChatRoom(bareJid, jid, jid); } chatRoom.getTranscriptWindow().insertNotificationMessage("The user is offline. Will auto-send \"" + file.getName() + "\" when user comes back online.", ChatManager.ERROR_COLOR); @@ -568,20 +546,20 @@ public ChatRoom sendFile(File file, String jid) { final OutgoingFileTransfer transfer = transferManager.createOutgoingFileTransfer(fullJID); - ContactItem contactItem = contactList.getContactItemByJID(bareJID); + ContactItem contactItem = contactList.getContactItemByJID(bareJid); ChatRoom chatRoom; if (contactItem != null) { - chatRoom = SparkManager.getChatManager().createChatRoom(bareJID, contactItem.getDisplayName(), contactItem.getDisplayName()); + chatRoom = SparkManager.getChatManager().createChatRoom(bareJid, contactItem.getDisplayName(), contactItem.getDisplayName()); } else { - chatRoom = SparkManager.getChatManager().createChatRoom(bareJID, bareJID, bareJID); + chatRoom = SparkManager.getChatManager().createChatRoom(bareJid, bareJid.toString(), bareJid.toString()); } TranscriptWindow transcriptWindow = chatRoom.getTranscriptWindow(); - SendFileTransfer sendingUI = new SendFileTransfer(); + SendFileTransfer sendingUI = new SendFileTransfer(chatRoom); try { transfer.sendFile(file, "Sending file"); } @@ -590,7 +568,7 @@ public ChatRoom sendFile(File file, String jid) { } // Add listener to cancel transfer is sending file to user who just went offline. - AndFilter presenceFilter = new AndFilter(new StanzaTypeFilter(Presence.class), FromMatchesFilter.createBare(bareJID)); + AndFilter presenceFilter = new AndFilter(new StanzaTypeFilter(Presence.class), FromMatchesFilter.createBare(bareJid)); final StanzaListener packetListener = stanza -> { Presence presence = (Presence)stanza; if (!presence.isAvailable()) { @@ -641,7 +619,8 @@ public void sendImage(final BufferedImage image, final ChatRoom room) { room.setCursor(new Cursor(Cursor.WAIT_CURSOR)); SwingWorker writeImageThread = new SwingWorker() { - public Object construct() { + @Override + public Object construct() { try { // Write out file in separate thread. ImageIO.write(image, "png", imageFile); @@ -652,7 +631,8 @@ public Object construct() { return true; } - public void finished() { + @Override + public void finished() { ChatRoomImpl roomImpl = (ChatRoomImpl)room; sendFile(imageFile, roomImpl.getParticipantJID()); SparkManager.getChatManager().getChatContainer().activateChatRoom(room); @@ -675,10 +655,7 @@ public static BufferedImage getClipboard() { return (BufferedImage)t.getTransferData(DataFlavor.imageFlavor); } } - catch (UnsupportedFlavorException e) { - // Nothing to do - } - catch (IOException e) { + catch (UnsupportedFlavorException | IOException e) { // Nothing to do } return null; @@ -692,7 +669,7 @@ public static BufferedImage getClipboard() { * @param listener the listener */ public void addTransferListener(FileTransferListener listener) { - listeners.add(listener); + listeners.addIfAbsent(listener); } /** @@ -705,7 +682,7 @@ public void removeTransferListener(FileTransferListener listener) { } private boolean fireTransferListeners(FileTransferRequest request) { - for (FileTransferListener listener : new ArrayList<>( listeners )) { + for (FileTransferListener listener : listeners) { boolean accepted = listener.handleTransfer(request); if (accepted) { return true; diff --git a/src/java/org/jivesoftware/spark/filetransfer/package.html b/core/src/main/java/org/jivesoftware/spark/filetransfer/package.html similarity index 100% rename from src/java/org/jivesoftware/spark/filetransfer/package.html rename to core/src/main/java/org/jivesoftware/spark/filetransfer/package.html diff --git a/core/src/main/java/org/jivesoftware/spark/filetransfer/preferences/FileTransferPreference.java b/core/src/main/java/org/jivesoftware/spark/filetransfer/preferences/FileTransferPreference.java new file mode 100644 index 000000000..2eecfe498 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/filetransfer/preferences/FileTransferPreference.java @@ -0,0 +1,132 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.filetransfer.preferences; + +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.resource.Res; +import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer; +import org.jivesoftware.spark.preference.Preference; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import javax.swing.*; + +/** + */ +public class FileTransferPreference implements Preference { + + private final FileTransferPreferencePanel ui; + private final LocalPreferences localPreferences; + + public FileTransferPreference() { + localPreferences = SettingsManager.getLocalPreferences(); + int timeout = localPreferences.getFileTransferTimeout(); + + timeout = timeout * 60 * 1000; + + OutgoingFileTransfer.setResponseTimeout(timeout); + + ui = new FileTransferPreferencePanel(); + } + + @Override + public String getTitle() { + return Res.getString("title.file.transfer.preferences"); + } + + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.SEND_FILE_ICON); + } + + @Override + public String getTooltip() { + return Res.getString("tooltip.file.transfer"); + } + + @Override + public String getListName() { + return Res.getString("title.file.transfer"); + } + + @Override + public String getNamespace() { + return "FILE_TRANSFER"; + } + + @Override + public JComponent getGUI() { + return ui; + } + + @Override + public void load() { + boolean ibb = localPreferences.isFileTransferIbbOnly(); + int timeout = localPreferences.getFileTransferTimeout(); + boolean auto = localPreferences.isAutoAcceptFileTransferFromContacts(); + ui.setDownloadDirectory(localPreferences.getDownloadDir()); + ui.setTimeout(Integer.toString(timeout)); + ui.setIbbOnly(ibb); + ui.setAutoAccept(auto); + } + + @Override + public void commit() { + LocalPreferences pref = SettingsManager.getLocalPreferences(); + pref.setFileTransferIbbOnly(ui.getIbbOnly()); + pref.setAutoAcceptFileTransferFromContacts(ui.getAutoAccept()); + String downloadDir = ui.getDownloadDirectory(); + if (ModelUtil.hasLength(downloadDir)) { + pref.setDownloadDir(downloadDir); + } + + String timeout = ui.getTimeout(); + if (ModelUtil.hasLength(timeout)) { + int tout = 1; + try { + tout = Integer.parseInt(timeout); + } catch (NumberFormatException e) { + // Nothing to do + } + + pref.setFileTransferTimeout(tout); + + final int timeOutMs = tout * (60 * 1000); + OutgoingFileTransfer.setResponseTimeout(timeOutMs); + } + } + + @Override + public boolean isDataValid() { + return true; + } + + @Override + public String getErrorMessage() { + return null; + } + + @Override + public Object getData() { + return null; + } + + @Override + public void shutdown() { + commit(); + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/filetransfer/preferences/FileTransferPreferencePanel.java b/core/src/main/java/org/jivesoftware/spark/filetransfer/preferences/FileTransferPreferencePanel.java new file mode 100644 index 000000000..e02db8973 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/filetransfer/preferences/FileTransferPreferencePanel.java @@ -0,0 +1,124 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.filetransfer.preferences; + +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.WindowsFileSystemView; + +import javax.swing.*; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.io.File; + +/** + * FileTransferPreferencePanel is the UI for handling File Transfer Preferences. + * + * @author Derek DeMoro + */ +public class FileTransferPreferencePanel extends JPanel { + + private static final long serialVersionUID = -2404221882867691253L; + private final JTextField timeoutField; + private final JTextField downloadDirectoryField; + private final JCheckBox ibbOnly; + private final JCheckBox autoAccept; + + private JFileChooser fc; + + + public FileTransferPreferencePanel() { + setLayout(new GridBagLayout()); + setBorder(BorderFactory.createTitledBorder(Res.getString("title.file.transfer.preferences"))); + + timeoutField = new JTextField(); + downloadDirectoryField = new JTextField(); + ibbOnly = new JCheckBox(); + autoAccept = new JCheckBox(); + + JLabel timeoutLabel = new JLabel(); + JLabel downloadDirectoryLabel = new JLabel(); + final JButton downloadButton = new JButton(); + + ResourceUtils.resLabel(timeoutLabel, timeoutField, Res.getString("label.transfer.timeout")); + ResourceUtils.resLabel(downloadDirectoryLabel, downloadDirectoryField, Res.getString("label.transfer.download.directory")); + ResourceUtils.resButton(ibbOnly, Res.getString("checkbox.filetransfer.ibb.only")); + ResourceUtils.resButton(autoAccept, Res.getString("checkbox.filetransfer.autoaccept.presence")); + ResourceUtils.resButton(downloadButton, Res.getString("button.browse")); + + add(ibbOnly, new GridBagConstraints(0, 0, 3, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + + add(autoAccept, new GridBagConstraints(0, 1, 3, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + + add(timeoutLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(timeoutField, new GridBagConstraints(1, 2, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 100, 0)); + + add(downloadDirectoryLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(downloadDirectoryField, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + add(downloadButton, new GridBagConstraints(2, 3, 1, 1, 0.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + + downloadButton.addActionListener( e -> pickFile(Res.getString("title.choose.directory"), downloadDirectoryField) ); + } + + public void setTimeout(String minutes) { + timeoutField.setText(minutes); + } + + public String getTimeout() { + return timeoutField.getText(); + } + + public void setDownloadDirectory(String dir) { + downloadDirectoryField.setText(dir); + } + + public String getDownloadDirectory() { + return downloadDirectoryField.getText(); + } + + public void setIbbOnly(boolean enable) { + ibbOnly.setSelected(enable); + } + + public boolean getIbbOnly() { return ibbOnly.isSelected(); } + + public void setAutoAccept(boolean enable) { + autoAccept.setSelected(enable); + } + + public boolean getAutoAccept() { return autoAccept.isSelected(); } + + private void pickFile(String title, JTextField field) { + if (fc == null) { + fc = new JFileChooser(); + fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + if (Spark.isWindows()) { + fc.setFileSystemView(new WindowsFileSystemView()); + } + } + fc.setDialogTitle(title); + int returnVal = fc.showOpenDialog(this); + + if (returnVal == JFileChooser.APPROVE_OPTION) { + File file = fc.getSelectedFile(); + field.setText(file.getAbsolutePath()); + } + } + +} diff --git a/src/java/org/jivesoftware/spark/package.html b/core/src/main/java/org/jivesoftware/spark/package.html similarity index 100% rename from src/java/org/jivesoftware/spark/package.html rename to core/src/main/java/org/jivesoftware/spark/package.html diff --git a/src/java/org/jivesoftware/spark/plugin/ContextMenuListener.java b/core/src/main/java/org/jivesoftware/spark/plugin/ContextMenuListener.java similarity index 97% rename from src/java/org/jivesoftware/spark/plugin/ContextMenuListener.java rename to core/src/main/java/org/jivesoftware/spark/plugin/ContextMenuListener.java index 840b5eb2e..89023fc50 100644 --- a/src/java/org/jivesoftware/spark/plugin/ContextMenuListener.java +++ b/core/src/main/java/org/jivesoftware/spark/plugin/ContextMenuListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/spark/plugin/Invokable.java b/core/src/main/java/org/jivesoftware/spark/plugin/Invokable.java similarity index 95% rename from src/java/org/jivesoftware/spark/plugin/Invokable.java rename to core/src/main/java/org/jivesoftware/spark/plugin/Invokable.java index 4b9ca8833..733ed80a5 100644 --- a/src/java/org/jivesoftware/spark/plugin/Invokable.java +++ b/core/src/main/java/org/jivesoftware/spark/plugin/Invokable.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/spark/plugin/MetadataListener.java b/core/src/main/java/org/jivesoftware/spark/plugin/MetadataListener.java similarity index 94% rename from src/java/org/jivesoftware/spark/plugin/MetadataListener.java rename to core/src/main/java/org/jivesoftware/spark/plugin/MetadataListener.java index e3ac6829b..8e757accf 100644 --- a/src/java/org/jivesoftware/spark/plugin/MetadataListener.java +++ b/core/src/main/java/org/jivesoftware/spark/plugin/MetadataListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +20,6 @@ import java.util.Map; /** - * */ public interface MetadataListener { diff --git a/src/java/org/jivesoftware/spark/plugin/Plugin.java b/core/src/main/java/org/jivesoftware/spark/plugin/Plugin.java similarity index 95% rename from src/java/org/jivesoftware/spark/plugin/Plugin.java rename to core/src/main/java/org/jivesoftware/spark/plugin/Plugin.java index 64451c5e6..846ff2c98 100644 --- a/src/java/org/jivesoftware/spark/plugin/Plugin.java +++ b/core/src/main/java/org/jivesoftware/spark/plugin/Plugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,7 +37,7 @@ public interface Plugin { * * @see org.jivesoftware.spark.PluginManager */ - public void initialize(); + void initialize(); /** * This method is invoked by the PluginManager when Spark @@ -52,7 +48,7 @@ public interface Plugin { * be called, but on normal terminations of Spark, this method will be * invoked. */ - public void shutdown(); + void shutdown(); /** * This method is invoked by the PluginManager before Spark @@ -66,7 +62,7 @@ public interface Plugin { * * @return true if the plugin can shut currently. */ - public boolean canShutDown(); + boolean canShutDown(); /** @@ -75,6 +71,6 @@ public interface Plugin { * will need to release all your in-memory resources in the #shutdown method. This * method should be used to remove on disk resources such as files, images, etc. */ - public void uninstall(); + void uninstall(); -} \ No newline at end of file +} diff --git a/src/java/org/jivesoftware/spark/plugin/PluginClassLoader.java b/core/src/main/java/org/jivesoftware/spark/plugin/PluginClassLoader.java similarity index 90% rename from src/java/org/jivesoftware/spark/plugin/PluginClassLoader.java rename to core/src/main/java/org/jivesoftware/spark/plugin/PluginClassLoader.java index b2423ea78..62dc5be45 100644 --- a/src/java/org/jivesoftware/spark/plugin/PluginClassLoader.java +++ b/core/src/main/java/org/jivesoftware/spark/plugin/PluginClassLoader.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,15 +18,18 @@ import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.provider.ExtensionElementProvider; -import org.jivesoftware.smack.provider.IQProvider; +import org.jivesoftware.smack.provider.IqProvider; import org.jivesoftware.smack.provider.ProviderManager; +import org.jivesoftware.smack.xml.SmackXmlParser; +import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.spark.util.URLFileSystem; import org.jivesoftware.spark.util.log.Log; -import org.xmlpull.mxp1.MXParser; -import org.xmlpull.v1.XmlPullParser; +import java.io.BufferedReader; import java.io.File; import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; @@ -38,6 +37,8 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import static java.nio.charset.StandardCharsets.UTF_8; + /** * A simple classloader to extend the classpath to * include all jars in a lib directory.

      @@ -87,7 +88,7 @@ else if (smallName.endsWith(".zip")) { for (File jar : jars) { if (jar.isFile()) { - final URL url = jar.toURL(); + final URL url = jar.toURI().toURL(); addURL(url); try { checkForSmackProviders(url); @@ -114,13 +115,12 @@ private void loadSmackProvider(InputStream providerStream) throws Exception { // Get an array of class loaders to try loading the providers files from. + Reader reader = new BufferedReader(new InputStreamReader(providerStream, UTF_8)); try { - XmlPullParser parser = new MXParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput(providerStream, "UTF-8"); - int eventType = parser.getEventType(); + final XmlPullParser parser = SmackXmlParser.newXmlParser(reader); + XmlPullParser.Event eventType = parser.getEventType(); do { - if (eventType == XmlPullParser.START_TAG) { + if (eventType == XmlPullParser.Event.START_ELEMENT) { if (parser.getName().equals("iqProvider")) { parser.next(); parser.next(); @@ -141,7 +141,7 @@ private void loadSmackProvider(InputStream providerStream) throws Exception { try { // Add the provider to the map. Class provider = this.loadClass(className); - if (IQProvider.class.isAssignableFrom(provider)) { + if (IqProvider.class.isAssignableFrom(provider)) { ProviderManager.addIQProvider(elementName, namespace, provider.newInstance()); } else if (IQ.class.isAssignableFrom(provider)) { @@ -189,7 +189,7 @@ else if (ExtensionElement.class.isAssignableFrom( } eventType = parser.next(); } - while (eventType != XmlPullParser.END_DOCUMENT); + while (eventType != XmlPullParser.Event.END_DOCUMENT); } finally { try { diff --git a/core/src/main/java/org/jivesoftware/spark/plugin/PluginDependency.java b/core/src/main/java/org/jivesoftware/spark/plugin/PluginDependency.java new file mode 100644 index 000000000..a083a519d --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/plugin/PluginDependency.java @@ -0,0 +1,71 @@ +package org.jivesoftware.spark.plugin; + +import org.jivesoftware.spark.util.log.Log; + +public class PluginDependency +{ + private String name; + private String version; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public boolean compareVersion(String version) { + + if(version != null && getVersion() != null) { + String[] checkVersion = version.split("\\."); + String[] originalVersion = getVersion().split("\\."); + int maxlength = Math.max(originalVersion.length, checkVersion.length); + + + // go through all Version-parts + for(int i= 0; i < maxlength; i++) { + // if the checked version is too short + if ( checkVersion.length <= i + && originalVersion[i].equals("0")) + return true; + else if (checkVersion.length <= i) + return false; + // if the original version is long enough + if(originalVersion.length > i) { + + // convert to integer + try { + int originalVersNumber = Integer.parseInt(originalVersion[i]); + int checkVersNumber = Integer.parseInt(checkVersion[i]); + + // check the numbers + if(checkVersNumber > originalVersNumber) { + return true; + } + else if(checkVersNumber < originalVersNumber) { + return false; + } + } + catch(Exception e) { + Log.error("Version " + version + " contains letters.", e); + return false; + } + } + else { + return true; + } + } + return true; + } + return false; + } +} diff --git a/src/java/org/jivesoftware/spark/plugin/PublicPlugin.java b/core/src/main/java/org/jivesoftware/spark/plugin/PublicPlugin.java similarity index 92% rename from src/java/org/jivesoftware/spark/plugin/PublicPlugin.java rename to core/src/main/java/org/jivesoftware/spark/plugin/PublicPlugin.java index aa4d91ecf..70321f27c 100644 --- a/src/java/org/jivesoftware/spark/plugin/PublicPlugin.java +++ b/core/src/main/java/org/jivesoftware/spark/plugin/PublicPlugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,8 +34,17 @@ public class PublicPlugin { private boolean largeIconAvailable; private String minVersion; private File pluginDir; - private List dependencies = new ArrayList<>(); - + private final List dependencies = new ArrayList<>(); + + public PublicPlugin() { + } + + public PublicPlugin(String name, String pluginClass, String version) { + this.name = name; + this.pluginClass = pluginClass; + this.version = version; + } + public String getName() { return name; } diff --git a/core/src/main/java/org/jivesoftware/spark/plugin/package.html b/core/src/main/java/org/jivesoftware/spark/plugin/package.html new file mode 100644 index 000000000..612ecd575 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/plugin/package.html @@ -0,0 +1 @@ +Provides the API for creating and registering Plugins. diff --git a/src/java/org/jivesoftware/spark/preference/Preference.java b/core/src/main/java/org/jivesoftware/spark/preference/Preference.java similarity index 98% rename from src/java/org/jivesoftware/spark/preference/Preference.java rename to core/src/main/java/org/jivesoftware/spark/preference/Preference.java index af2bda8d9..1e93dd4c6 100644 --- a/src/java/org/jivesoftware/spark/preference/Preference.java +++ b/core/src/main/java/org/jivesoftware/spark/preference/Preference.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/spark/preference/PreferenceManager.java b/core/src/main/java/org/jivesoftware/spark/preference/PreferenceManager.java similarity index 76% rename from src/java/org/jivesoftware/spark/preference/PreferenceManager.java rename to core/src/main/java/org/jivesoftware/spark/preference/PreferenceManager.java index c18f9fc22..42b9a6643 100644 --- a/src/java/org/jivesoftware/spark/preference/PreferenceManager.java +++ b/core/src/main/java/org/jivesoftware/spark/preference/PreferenceManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,31 +15,27 @@ */ package org.jivesoftware.spark.preference; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import javax.swing.JDialog; - import org.jivesoftware.MainWindowListener; import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.util.log.Log; import org.jivesoftware.sparkimpl.plugin.privacy.ui.PrivacyPreferences; import org.jivesoftware.sparkimpl.preference.PreferenceDialog; import org.jivesoftware.sparkimpl.preference.PreferencesPanel; import org.jivesoftware.sparkimpl.preference.chat.ChatPreference; import org.jivesoftware.sparkimpl.preference.groupchat.GroupChatPreference; -import org.jivesoftware.sparkimpl.preference.media.MediaPreference; +//import org.jivesoftware.sparkimpl.preference.media.MediaPreference; import org.jivesoftware.sparkimpl.settings.local.LocalPreference; +import javax.swing.*; +import java.util.*; + /** * Usage of the PreferenceManager to handle loading of preferences within Spark. * * @author Derek DeMoro */ public class PreferenceManager { - private Map map = new LinkedHashMap<>(); + private final Map map = new LinkedHashMap<>(); private PreferenceDialog preferenceDialog; public PreferenceManager() { @@ -56,9 +48,9 @@ public PreferenceManager() { addPreference(groupChatPreferences); groupChatPreferences.load(); - MediaPreference preferenes = new MediaPreference(); - addPreference(preferenes); - preferenes.load(); +// MediaPreference preferences = new MediaPreference(); +// addPreference(preferences); +// preferences.load(); PrivacyPreferences privacy = new PrivacyPreferences(); addPreference(privacy); @@ -68,18 +60,19 @@ public PreferenceManager() { addPreference(localPreferences); localPreferences.load(); - getPreferences(); - SparkManager.getMainWindow().addMainWindowListener(new MainWindowListener() { - public void shutdown() { + @Override + public void shutdown() { fireShutdown(); } - public void mainWindowActivated() { + @Override + public void mainWindowActivated() { } - public void mainWindowDeactivated() { + @Override + public void mainWindowDeactivated() { } }); @@ -120,19 +113,22 @@ public Object getPreferenceData(String namespace) { return getPreference(namespace).getData(); } - public Iterator getPreferences() { - final List returnList = new ArrayList<>(); - for (String namespace : map.keySet()) { - returnList.add(map.get(namespace)); - } - return returnList.iterator(); - + public Collection getPreferences() { + return map.values(); } - private void fireShutdown() { - for (String namespace : map.keySet()) { - final Preference preference = map.get(namespace); - preference.shutdown(); + private void fireShutdown() + { + for ( final Preference preference : map.values() ) + { + try + { + preference.shutdown(); + } + catch ( Exception e ) + { + Log.error( "An exception occurred while trying to shutdown preference: " + preference, e ); + } } } diff --git a/src/java/org/jivesoftware/spark/preference/package.html b/core/src/main/java/org/jivesoftware/spark/preference/package.html similarity index 100% rename from src/java/org/jivesoftware/spark/preference/package.html rename to core/src/main/java/org/jivesoftware/spark/preference/package.html diff --git a/core/src/main/java/org/jivesoftware/spark/sasl/SASLGSSAPIv3CompatMechanism.java b/core/src/main/java/org/jivesoftware/spark/sasl/SASLGSSAPIv3CompatMechanism.java new file mode 100644 index 000000000..78d1022f0 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/sasl/SASLGSSAPIv3CompatMechanism.java @@ -0,0 +1,22 @@ +package org.jivesoftware.spark.sasl; + +import org.jivesoftware.smack.sasl.javax.SASLGSSAPIMechanism; + +/** + * This is an implementation of a SASL GSS-API mechanisms, that uses the XMPP domain name, instead of the fully + * qualified domain name of the XMPP server that is being connected to. + * + * This implementation reverts the GSS-API SASL mechanism behavior back to what it was in Smack 3, which can facilitate + * running Smack-3- and Smack-4-based clients on the same Openfire instance (Openfire will be configured to require + * either the XMPP domain name, or the FQDN). + * + * @author Guus der Kinderen, guus.der.kinderen@gmail.com + */ +public class SASLGSSAPIv3CompatMechanism extends SASLGSSAPIMechanism +{ + @Override + protected String getServerName() + { + return super.serviceName.toString(); + } +} diff --git a/src/java/org/jivesoftware/spark/search/SearchManager.java b/core/src/main/java/org/jivesoftware/spark/search/SearchManager.java similarity index 88% rename from src/java/org/jivesoftware/spark/search/SearchManager.java rename to core/src/main/java/org/jivesoftware/spark/search/SearchManager.java index 9565d78c9..e116d1d7b 100644 --- a/src/java/org/jivesoftware/spark/search/SearchManager.java +++ b/core/src/main/java/org/jivesoftware/spark/search/SearchManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +17,7 @@ import org.jivesoftware.spark.util.SwingWorker; import org.jivesoftware.sparkimpl.search.users.UserSearchService; +import org.jxmpp.jid.DomainBareJid; import java.util.ArrayList; import java.util.Collection; @@ -32,9 +29,9 @@ * find area of the bottom of Spark. */ public class SearchManager { - private List searchServices = new ArrayList<>(); - private SearchService ui; - private Collection _searchservicesHosts; + private final List searchServices = new ArrayList<>(); + private final SearchService ui; + private Collection _searchservicesHosts; private static SearchManager singleton; private static final Object LOCK = new Object(); @@ -65,12 +62,14 @@ private SearchManager() { // By default, the user search is first. SwingWorker worker = new SwingWorker() { UserSearchService searchWizard; - public Object construct() { + @Override + public Object construct() { searchWizard = new UserSearchService(); return searchWizard; } - public void finished() { + @Override + public void finished() { if (searchWizard.getSearchServices() != null) { ui.setActiveSearchService(searchWizard); addSearchService(searchWizard); @@ -121,19 +120,14 @@ public Collection getSearchServices() { * * @return the collection of search services. */ - public Collection getSearchServicesAsString() + public Collection getSearchServicesAsJid() { return _searchservicesHosts; } private void checkSearchService() { Collection searchables = getSearchServices(); - if (searchables.size() <= 1) { - ui.getFindField().enableDropdown(false); - } - else { - ui.getFindField().enableDropdown(true); - } + ui.getFindField().enableDropdown(searchables.size() > 1); } public SearchService getSearchServiceUI() { diff --git a/src/java/org/jivesoftware/spark/search/SearchService.java b/core/src/main/java/org/jivesoftware/spark/search/SearchService.java similarity index 76% rename from src/java/org/jivesoftware/spark/search/SearchService.java rename to core/src/main/java/org/jivesoftware/spark/search/SearchService.java index 932f2fb3e..4637c10a1 100644 --- a/src/java/org/jivesoftware/spark/search/SearchService.java +++ b/core/src/main/java/org/jivesoftware/spark/search/SearchService.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.jivesoftware.spark.search; import org.jivesoftware.Spark; @@ -28,14 +24,9 @@ import org.jivesoftware.spark.component.IconTextField; import org.jivesoftware.spark.util.ResourceUtils; import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.Icon; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.UIManager; +import javax.swing.*; import java.awt.Color; import java.awt.Graphics; @@ -53,10 +44,12 @@ import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.util.Collection; +import javax.swing.plaf.basic.BasicPanelUI; public class SearchService extends JPanel { + private static final long serialVersionUID = 6407801290193187867L; - private IconTextField findField; + private final IconTextField findField; private Image backgroundImage; private boolean newSearch; @@ -64,81 +57,69 @@ public class SearchService extends JPanel { public SearchService() { setLayout(new GridBagLayout()); - findField = new IconTextField(SparkRes.getImageIcon(SparkRes.SEARCH_USER_16x16)); + findField = new IconTextField(SparkRes.getImageIcon(SparkRes.Icon.SEARCH_USER_16x16)); backgroundImage = Default.getImageIcon(Default.TOP_BOTTOM_BACKGROUND_IMAGE).getImage(); + this.setUI(new BasicPanelUI()); final JLabel findLabel = new JLabel(); ResourceUtils.resLabel(findLabel, findField, Res.getString("label.find")); // add(findLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - boolean hide = Default.getBoolean(Default.HIDE_PERSON_SEARCH_FIELD); - if (!hide) { - if (Spark.isMac()) { - add(findField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 30), 0, 0)); - } - else { - add(findField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - } - } - - // Check for secure connection - if (SparkManager.getConnection().isSecureConnection()) { - final JLabel lockLabel = new JLabel(); - lockLabel.setHorizontalTextPosition(JLabel.LEFT); - lockLabel.setIcon(SparkRes.getImageIcon(SparkRes.LOCK_16x16)); - if (!hide) { - if (Spark.isMac()) { - add(lockLabel, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 0, 5, 15), 0, 0)); - - } - else { - add(lockLabel, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 0, 5, 5), 0, 0)); + boolean showPersonSearchField = (!Default.getBoolean(Default.HIDE_PERSON_SEARCH_FIELD) && Enterprise.containsFeature(Enterprise.PERSON_SEARCH_FEATURE)); - } + if (showPersonSearchField) { + if (Spark.isMac()) { + add(findField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 30), 0, 0)); + } else { + add(findField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); } - lockLabel.setToolTipText(Res.getString("message.spark.secure")); } findField.setToolTipText(Res.getString("message.search.for.contacts")); findField.getTextComponent().addKeyListener(new KeyListener() { + @Override public void keyTyped(KeyEvent e) { } + @Override public void keyPressed(KeyEvent e) { if (e.getKeyChar() == KeyEvent.VK_ENTER) { final Icon previousIcon = findField.getIcon(); - findField.setIcon(SparkRes.getImageIcon(SparkRes.BUSY_IMAGE)); + findField.setIcon(SparkRes.getImageIcon(SparkRes.Icon.BUSY_IMAGE)); findField.validate(); findField.repaint(); SwingWorker worker = new SwingWorker() { + @Override public Object construct() { activeSearchable.search(findField.getText()); return true; } + @Override public void finished() { findField.setIcon(previousIcon); findField.setText(""); } }; - worker.start(); } } + @Override public void keyReleased(KeyEvent e) { } }); findField.getTextComponent().addMouseListener(new MouseAdapter() { + @Override public void mouseClicked(MouseEvent e) { if (newSearch) { findField.setText(""); @@ -148,15 +129,14 @@ public void mouseClicked(MouseEvent e) { } }); - Workspace workspace = SparkManager.getWorkspace(); - workspace.add(this, new GridBagConstraints(0, 10, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + workspace.add(this, new GridBagConstraints(0, 7, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); workspace.invalidate(); workspace.validate(); workspace.repaint(); - - findField.getImageComponent().addMouseListener(new MouseAdapter() { + findField.getDownOption().addMouseListener(new MouseAdapter() { + @Override public void mouseClicked(MouseEvent e) { Collection searchables = SparkManager.getSearchManager().getSearchServices(); if (searchables.size() <= 1) { @@ -167,9 +147,10 @@ public void mouseClicked(MouseEvent e) { final JPopupMenu popup = new JPopupMenu(); for (final Searchable searchable : searchables) { Action action = new AbstractAction() { - private static final long serialVersionUID = 1289193809077193703L; + private static final long serialVersionUID = 1289193809077193703L; - public void actionPerformed(ActionEvent e) { + @Override + public void actionPerformed(ActionEvent e) { setActiveSearchService(searchable); } }; @@ -196,10 +177,12 @@ public void setActiveSearchService(final Searchable searchable) { findField.setToolTipText(searchable.getToolTip()); findField.getTextComponent().addFocusListener(new FocusListener() { + @Override public void focusGained(FocusEvent e) { findField.setText(""); } + @Override public void focusLost(FocusEvent e) { findField.getTextComponent().setForeground((Color) UIManager.get("TextField.lightforeground")); findField.setText(searchable.getDefaultText()); @@ -207,6 +190,7 @@ public void focusLost(FocusEvent e) { }); } + @Override public void paintComponent(Graphics g) { double scaleX = getWidth() / (double) backgroundImage.getWidth(null); double scaleY = getHeight() / (double) backgroundImage.getHeight(null); @@ -222,5 +206,4 @@ public void setBackgroundImage(Image image) { this.backgroundImage = image; } - } diff --git a/src/java/org/jivesoftware/spark/search/Searchable.java b/core/src/main/java/org/jivesoftware/spark/search/Searchable.java similarity index 97% rename from src/java/org/jivesoftware/spark/search/Searchable.java rename to core/src/main/java/org/jivesoftware/spark/search/Searchable.java index cdf14bf8d..974ee4a0e 100644 --- a/src/java/org/jivesoftware/spark/search/Searchable.java +++ b/core/src/main/java/org/jivesoftware/spark/search/Searchable.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/spark/search/package.html b/core/src/main/java/org/jivesoftware/spark/search/package.html similarity index 100% rename from src/java/org/jivesoftware/spark/search/package.html rename to core/src/main/java/org/jivesoftware/spark/search/package.html diff --git a/core/src/main/java/org/jivesoftware/spark/ui/BroadcastHistoryFrame.java b/core/src/main/java/org/jivesoftware/spark/ui/BroadcastHistoryFrame.java new file mode 100644 index 000000000..e43706405 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/BroadcastHistoryFrame.java @@ -0,0 +1,166 @@ +package org.jivesoftware.spark.ui; +import java.awt.*; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.text.Format; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettingsManager; + +/** + * @author ps + */ +public class BroadcastHistoryFrame extends javax.swing.JFrame { + + /** + * Creates new form NewJFrame + */ + public BroadcastHistoryFrame() { + BroadcastHistoryArea = new javax.swing.JTextArea(); + BroadcastHistoryArea.setEditable(false); + BroadcastHistoryArea.setLineWrap(true); + BroadcastHistoryArea.setWrapStyleWord(true); + initComponents(); + } + + public void readFromFile(String date) throws IOException { + String fileLocation = Spark.getSparkUserHome() + File.separator + "user" + File.separator + SparkManager.getSessionManager().getUsername() + "@" + SparkManager.getSessionManager().getServerAddress() + File.separator + "transcripts" + File.separator + "broadcast_history." + date + ".txt"; + File myfile = new File(fileLocation); + if (!myfile.exists()) { + return; + } + FileInputStream fis = new FileInputStream(myfile); + BufferedReader br = new BufferedReader(new InputStreamReader(fis)); + + String line; + while ((line = br.readLine()) != null) { + BroadcastHistoryArea.append(line + "\n"); + } + br.close(); + } + + private void initComponents() { + SearchButton = new javax.swing.JToggleButton(); + DateField = new javax.swing.JFormattedTextField(); + SearchDate = new javax.swing.JLabel(); + Date date=new Date(); + Format formatter = new SimpleDateFormat("yyy-MM"); + String myDate = formatter.format(date); + DateField.setValue(myDate); + setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + JScrollPane panelPane = new JScrollPane(BroadcastHistoryArea); + SearchDate.setText(Res.getString("label.broadcast.history.search.date")); + setTitle(Res.getString("title.broadcast.history")); + + try { + readFromFile(myDate); + } catch (IOException ex) { + Log.error("Couldn't read from file", ex); + } + + SearchButton.setText((Res.getString("button.search"))); + SearchButton.addMouseListener(new java.awt.event.MouseAdapter() { + @Override + public void mouseClicked(java.awt.event.MouseEvent evt) { + SearchButtonMouseClicked(evt); + } + }); + + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(panelPane, javax.swing.GroupLayout.DEFAULT_SIZE, 533, javax.swing.GroupLayout.DEFAULT_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 20, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(SearchDate) + .addComponent(SearchButton) + .addComponent(DateField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(22, 22, 22)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(15, 15, 15) + .addComponent(panelPane, javax.swing.GroupLayout.DEFAULT_SIZE, 350, javax.swing.GroupLayout.DEFAULT_SIZE)) + .addGroup(layout.createSequentialGroup() + .addGap(15, 15, 15) + .addComponent(SearchDate) + .addGap(10, 10, 10) + .addComponent(DateField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(10, 10, 10) + .addComponent(SearchButton))) + .addContainerGap(15, Short.MAX_VALUE)) + ); + + pack(); + + final Rectangle bounds = LayoutSettingsManager.getLayoutSettings().getBroadcastHistoryBounds(); + if ( bounds == null || bounds.width <= 0 || bounds.height <= 0 ) + { + // Use default settings. + setLocationRelativeTo( null ); + } + else + { + setBounds( bounds ); + } + + addComponentListener( new ComponentAdapter() + { + @Override + public void componentResized( ComponentEvent e ) + { + LayoutSettingsManager.getLayoutSettings().setBroadcastHistoryBounds( getBounds() ); + } + + @Override + public void componentMoved( ComponentEvent e ) + { + LayoutSettingsManager.getLayoutSettings().setBroadcastHistoryBounds( getBounds() ); + } + } ); + } + + + private void SearchButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_SearchButtonMouseClicked + BroadcastHistoryArea.setText(""); + try { + readFromFile(DateField.getText()); + } catch (IOException ex) { + Log.error("Couldn't read from file", ex); + } + }//GEN-LAST:event_SearchButtonMouseClicked + + public void run() { + java.awt.EventQueue.invokeLater(() -> { + BroadcastHistoryFrame frame= new BroadcastHistoryFrame(); + frame.setVisible(true); + frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); + }); +} + + private javax.swing.JFormattedTextField DateField; + // Variables declaration - do not modify//GEN-BEGIN:variables + private final javax.swing.JTextArea BroadcastHistoryArea; + private javax.swing.JLabel SearchDate; + private javax.swing.JToggleButton SearchButton; + // End of variables declaration//GEN-END:variables +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ChatArea.java b/core/src/main/java/org/jivesoftware/spark/ui/ChatArea.java new file mode 100644 index 000000000..eeda07114 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/ChatArea.java @@ -0,0 +1,428 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.ContextMenuListener; +import org.jivesoftware.spark.ui.conferences.ConferenceUtils; +import org.jivesoftware.spark.uri.UriManager; +import org.jivesoftware.spark.util.BrowserLauncher; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.emoticons.EmoticonManager; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.util.JidUtil; + +import javax.swing.*; +import javax.swing.text.*; +import java.awt.*; +import java.awt.event.*; +import java.net.URI; +import java.util.*; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * The ChatArea class handles proper chat text formatting such as url handling. Use ChatArea for proper + * formatting of bold, italics, underlined and urls. + */ +public class ChatArea extends JTextPane implements MouseListener, MouseMotionListener, ActionListener { + + /** + * The default Hand cursor. + */ + public static final Cursor HAND_CURSOR = new Cursor(Cursor.HAND_CURSOR); + + /** + * The default Text Cursor. + */ + public static final Cursor DEFAULT_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR); + + /** + * The currently selected Font Size to use. + */ + private final int fontSize = SettingsManager.getLocalPreferences().getChatRoomFontSize(); + private final CopyOnWriteArrayList contextMenuListeners = new CopyOnWriteArrayList<>(); + + private JPopupMenu popup; + + private final JMenuItem cutMenu; + private final JMenuItem copyMenu; + private final JMenuItem pasteMenu; + private final JMenuItem selectAll; + + private final CopyOnWriteArrayList interceptors = new CopyOnWriteArrayList<>(); + + protected final EmoticonManager emoticonManager; + + protected Boolean forceEmoticons = false; + + protected Boolean emoticonsAvailable = true; + + /** + * ChatArea Constructor. + */ + public ChatArea() { + emoticonManager = EmoticonManager.getInstance(); + + Collection emoticonPacks; + emoticonPacks = emoticonManager.getEmoticonPacks(); + + if(emoticonPacks == null) { + emoticonsAvailable = false; + } + + cutMenu = new JMenuItem(Res.getString("action.cut")); + cutMenu.addActionListener(this); + + copyMenu = new JMenuItem(Res.getString("action.copy")); + copyMenu.addActionListener(this); + + pasteMenu = new JMenuItem(Res.getString("action.paste")); + pasteMenu.addActionListener(this); + + selectAll = new JMenuItem(Res.getString("action.select.all")); + selectAll.addActionListener(this); + + // Set Default Font + setFont(new Font("Dialog", Font.PLAIN, fontSize)); + + + getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ctrl x"), "cut"); + + getActionMap().put("cut", new AbstractAction("cut") { + private static final long serialVersionUID = 9117190151545566922L; + + @Override + public void actionPerformed(ActionEvent evt) { + cutAction(); + } + }); + + getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ctrl c"), "copy"); + + getActionMap().put("copy", new AbstractAction("copy") { + private static final long serialVersionUID = 4949716854440264528L; + + @Override + public void actionPerformed(ActionEvent evt) { + SparkManager.setClipboard(getSelectedText()); + } + }); + + getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("ctrl v"), "paste"); + + getActionMap().put("paste", new AbstractAction("paste") { + private static final long serialVersionUID = -8767763580660683678L; + + @Override + public void actionPerformed(ActionEvent evt) { + pasteAction(); + } + }); + + setEditorKit( new WrapEditorKit() ); // SPARK-1613 Ensure that long text wraps. + } + + /** + * setText is a core JTextPane method that can beused to inject a different Document type + * for instance HTMLDocument (setText("") + * We should keep the functionality - it is useful when we want to inject a different Document type + * instead of StyleDocument + * @param content + */ + public void setInitialContent(String content) { + super.setText(content); + } + + + /** + * Removes the last appearance of word from the TextArea + * @param word + */ + public void removeLastWord(String word) + { + select(getText().lastIndexOf(word),getText().length()); + replaceSelection(""); + } + + /** + * Removes everything in between begin and end + * @param begin + * @param end + */ + public void removeWordInBetween(int begin, int end){ + select(begin, end); + replaceSelection(""); + } + + /** + * Clear the current document. This will remove all text and element + * attributes such as bold, italics, and underlining. Note that the font family and + * font size will be persisted. + */ + public void clear() { + super.setText(""); + } + + @Override + public void mouseClicked(MouseEvent e) { + try { + final int pos = viewToModel(e.getPoint()); + final Element element = getStyledDocument().getCharacterElement(pos); + + if (element != null) { + final AttributeSet as = element.getAttributes(); + final String url = (String) as.getAttribute("link"); + + if (url != null) { + try { + boolean handled = fireLinkInterceptors(e, url); + if (!handled) { + if(e.getButton() == MouseEvent.BUTTON1) { + if (url.startsWith("xmpp:")) { + // eg: xmpp:open_chat@conference.igniterealtime.org?join;password=somesecret + SparkManager.getUriManager().handleURIMapping(url, false); + } else { + BrowserLauncher.openURL(url); + } + } + else if (e.getButton() == MouseEvent.BUTTON3) { + JPopupMenu popupmenu = new JPopupMenu(); + JMenuItem linkcopy = new JMenuItem( + Res.getString("action.copy")); + linkcopy.addActionListener( e1 -> SparkManager.setClipboard(url) ); + linkcopy.setEnabled(true); + popupmenu.add(linkcopy); + popupmenu.show(this, e.getX(), e.getY()); + } + } + } + catch (Exception ioe) { + Log.error("Error launching browser:", ioe); + } + } + } + } + catch (Exception ex) { + Log.error("Visible Error", ex); + } + } + + @Override + public void mousePressed(MouseEvent e) { + if (e.isPopupTrigger()) { + handlePopup(e); + } + } + + /** + * This launches the BrowserLauncher with the URL + * located in ChatArea. Note that the url will + * automatically be clickable when added to ChatArea + * + * @param e - the MouseReleased event + */ + @Override + public void mouseReleased(MouseEvent e) { + if (e.isPopupTrigger()) { + handlePopup(e); + } + + + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + @Override + public void mouseDragged(MouseEvent e) { + } + + /** + * Checks to see if the mouse is located over a browseable + * link. + * + * @param e - the current MouseEvent. + */ + @Override + public void mouseMoved(MouseEvent e) { + checkForLink(e); + } + + /** + * Checks to see if the mouse is located over a browseable + * link. + * + * @param e - the current MouseEvent. + */ + private void checkForLink(MouseEvent e) { + try { + final int pos = viewToModel(e.getPoint()); + final Element element = getStyledDocument().getCharacterElement(pos); + + if (element != null) { + final AttributeSet as = element.getAttributes(); + final Object o = as.getAttribute("link"); + + if (o != null) { + setCursor(HAND_CURSOR); + } + else { + setCursor(DEFAULT_CURSOR); + } + } + } + catch (Exception ex) { + Log.error("Error in CheckLink:", ex); + } + } + + private void handlePopup(MouseEvent e) { + popup = new JPopupMenu(); + popup.add(cutMenu); + popup.add(copyMenu); + popup.add(pasteMenu); + fireContextMenuListeners(); + popup.addSeparator(); + popup.add(selectAll); + + // Handle enable + boolean textSelected = ModelUtil.hasLength(getSelectedText()); + String clipboard = SparkManager.getClipboard(); + cutMenu.setEnabled(textSelected && isEditable()); + copyMenu.setEnabled(textSelected); + pasteMenu.setEnabled(ModelUtil.hasLength(clipboard) && isEditable()); + + popup.show(this, e.getX(), e.getY()); + } + + /** + * Adds a ContextMenuListener to ChatArea. + * + * @param listener the ContextMenuListener. + */ + public void addContextMenuListener(ContextMenuListener listener) { + contextMenuListeners.addIfAbsent(listener); + } + + /** + * Remove a ContextMenuListener to ChatArea. + * + * @param listener the ContextMenuListener. + */ + public void removeContextMenuListener(ContextMenuListener listener) { + contextMenuListeners.remove(listener); + } + + private void fireContextMenuListeners() + { + for ( final ContextMenuListener listener : contextMenuListeners ) + { + try + { + listener.poppingUp( this, popup ); + } + catch ( Exception e ) + { + Log.error( "A ContextMenuListener (" + listener + ") threw an exception while processing a 'poppingUp' event. ChatArea: '" + this + "', popup: '" + popup + "'.", e ); + } + } + } + + public void addLinkInterceptor(LinkInterceptor interceptor) { + interceptors.addIfAbsent(interceptor); + } + + public void removeLinkInterceptor(LinkInterceptor interceptor) { + interceptors.remove(interceptor); + } + + public boolean fireLinkInterceptors( MouseEvent event, String link ) + { + for ( final LinkInterceptor interceptor : interceptors ) + { + try + { + final boolean handled = interceptor.handleLink( event, link ); + if ( handled ) + { + return true; + } + } + catch ( Exception e ) + { + Log.error( "A LinkInterceptor (" + interceptor + ") threw an exception while processing link: '" + link + "', event: '" + event + "'.", e ); + } + } + + return false; + } + + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource() == cutMenu) { + cutAction(); + } + else if (e.getSource() == copyMenu) { + SparkManager.setClipboard(getSelectedText()); + } + else if (e.getSource() == pasteMenu) { + pasteAction(); + } + else if (e.getSource() == selectAll) { + requestFocus(); + selectAll(); + } + } + + private void cutAction() { + String selectedText = getSelectedText(); + replaceSelection(""); + SparkManager.setClipboard(selectedText); + } + + private void pasteAction() { + String text = SparkManager.getClipboard(); + if (text != null) { + replaceSelection(text); + } + } + + protected void releaseResources() { + getActionMap().remove("copy"); + getActionMap().remove("cut"); + getActionMap().remove("paste"); + } + + public Boolean getForceEmoticons() { + return forceEmoticons; + } + + public void setForceEmoticons(Boolean forceEmoticons) { + this.forceEmoticons = forceEmoticons; + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ChatContainer.java b/core/src/main/java/org/jivesoftware/spark/ui/ChatContainer.java new file mode 100644 index 000000000..d94b8f377 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/ChatContainer.java @@ -0,0 +1,1439 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.MainWindow; +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.StanzaListener; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.filter.AndFilter; +import org.jivesoftware.smack.filter.FromMatchesFilter; +import org.jivesoftware.smack.filter.StanzaTypeFilter; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smackx.muc.MultiUserChatManager; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.tabbedPane.SparkTab; +import org.jivesoftware.spark.component.tabbedPane.SparkTabbedPane; +import org.jivesoftware.spark.component.tabbedPane.SparkTabbedPaneListener; +import org.jivesoftware.spark.ui.conferences.GroupChatRoomListener; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jivesoftware.spark.util.SwingTimerTask; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.*; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Resourcepart; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.regex.Pattern; + +import static org.jivesoftware.spark.util.StringUtils.keyStroke2String; + +/** + * Contains all ChatRoom objects within Spark. + * + * @author Derek DeMoro + */ +public class ChatContainer extends SparkTabbedPane implements MessageListener, ChangeListener, KeyListener { + + /** + * List of all ChatRoom Listeners. + */ + private final CopyOnWriteArrayList chatRoomListeners = new CopyOnWriteArrayList<>(); + private final List chatRoomList = new ArrayList<>(); + private final Map presenceMap = new HashMap<>(); + private final String WELCOME_TITLE = SparkRes.getString(SparkRes.WELCOME); + private ChatFrame chatFrame; + private final TimerTask focusTask; + private static List domainMUC; + private final LocalPreferences pref = SettingsManager.getLocalPreferences(); + + /** + * Creates the ChatContainer to hold all ChatRooms. + */ + public ChatContainer() { + // Assign location + super(SettingsManager.getLocalPreferences().isTabTopPosition() ? JTabbedPane.TOP : JTabbedPane.BOTTOM); + + // Set minimum size + setMinimumSize(new Dimension(400, 200)); + // Don't allow tabs to shrink and allow scrolling. + + enableDragAndDrop(); + //add Group chat room listener + addChatRoomListener(new GroupChatRoomListener()); + addSparkTabbedPaneListener(new SparkTabbedPaneListener() { + @Override + public void tabRemoved(SparkTab tab, Component component, int index) { + stateChanged(null); + if (component instanceof ChatRoom) { + cleanupChatRoom((ChatRoom) component); + } else if (component instanceof ContainerComponent) { + ((ContainerComponent) component).closing(); + } + } + + @Override + public void tabAdded(SparkTab tab, Component component, int index) { + stateChanged(null); + } + + @Override + public void tabSelected(SparkTab tab, Component component, int index) { + stateChanged(null); + + // Notify ChatRoomListeners that the tab has been activated. + if (component instanceof ChatRoom) { + fireChatRoomActivated((ChatRoom) component); + } + } + + @Override + public void allTabsRemoved() { + + if (chatFrame != null) { + chatFrame.setTitle(""); + chatFrame.setVisible(false); + chatFrame = null; + } + + } + + @Override + public boolean canTabClose(SparkTab tab, Component component) { + return true; + } + }); + + setCloseButtonEnabled(true); + + // Add Key Navigation + addKeyNavigation(); + + this.setFocusable(false); + + setOpaque(true); + + setBackground(Color.white); + + // Create task for focusing chat. + focusTask = new SwingTimerTask() { + @Override + public void doRun() { + try { + //chatFrame.requestFocus(); + ChatRoom chatRoom = getActiveChatRoom(); + chatRoom.getChatInputEditor().requestFocusInWindow(); + updateActiveTab(); + + } catch (ChatRoomNotFoundException e1) { + // Ignore. There may legitamtly not be a chat room. + } + } + }; + + } + + /** + * Adds navigation capability to chat rooms. Users can navigate using the + * alt-left or right arrow keys. + */ + private void addKeyNavigation() { + KeyStroke leftStroke = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0); + String leftStrokeString = keyStroke2String(leftStroke); + + // Handle Left Arrow + this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("alt " + leftStrokeString), "navigateLeft"); + this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("alt " + leftStrokeString), "navigateLeft"); + this.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("alt " + leftStrokeString), "navigateLeft"); + this.getActionMap().put("navigateLeft", new AbstractAction("navigateLeft") { + @Override + public void actionPerformed(ActionEvent evt) { + navigateLeft(); + } + }); + + KeyStroke rightStroke = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0); + String rightStrokeString = keyStroke2String(rightStroke); + + // Handle Right Arrow + this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("alt " + rightStrokeString), "navigateRight"); + this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("alt " + rightStrokeString), "navigateRight"); + this.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("alt " + rightStrokeString), "navigateRight"); + + this.getActionMap().put("navigateRight", new AbstractAction("navigateRight") { + @Override + public void actionPerformed(ActionEvent evt) { + navigateRight(); + } + }); + + this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("ESCAPE"), "escape"); + this.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("ESCAPE"), "escape"); + + this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("Ctrl W"), "escape"); + this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "escape"); + + this.getActionMap().put("escape", new AbstractAction("escape") { + @Override + public void actionPerformed(ActionEvent evt) { + closeActiveRoom(); + } + }); + + this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | InputEvent.SHIFT_MASK), "shiftCmdW"); + this.getActionMap().put("shiftCmdW", new AbstractAction("shiftCmdW") { + @Override + public void actionPerformed(ActionEvent evt) { + closeAllChatRooms(); + } + }); + + // Add KeyMappings + getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "searchContacts"); + getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("control F"), "searchContacts"); + getActionMap().put("searchContacts", new AbstractAction("searchContacts") { + + @Override + public void actionPerformed(ActionEvent evt) { + SwingWorker worker = new SwingWorker() { + + @Override + public Object construct() { + return 42; + } + + @Override + public void finished() { + SparkManager.getUserManager() + .searchContacts("", SparkManager.getChatManager() + .getChatContainer().getChatFrame()); + } + }; + worker.start(); + } + }); + } + + /** + * Adds a new ChatRoom to Spark. + * + * @param room the ChatRoom to add. + */ + public synchronized void addChatRoom(final ChatRoom room) { + createFrameIfNeeded(); + + room.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.LIGHT_GRAY)); + AndFilter presenceFilter = new AndFilter(new StanzaTypeFilter(Presence.class), FromMatchesFilter.createBare(room.getBareJid())); + + // Next, create a packet listener. We use an anonymous inner class for brevity. + StanzaListener myListener = stanza -> SwingUtilities.invokeLater(() -> { + try { + handleRoomPresence((Presence) stanza); + } catch (Throwable t) { + Log.warning("Unable to handle incoming stanza (room presence): " + stanza, t); + } + }); + + room.registeredToFrame(chatFrame); + + SparkManager.getConnection().addAsyncStanzaListener(myListener, presenceFilter); + + // Add to PresenceMap + presenceMap.put(room.getJid(), myListener); + + String tooltip; + if (room instanceof ChatRoomImpl) { + tooltip = room.getJid().toString(); + String nickname = SparkManager.getUserManager().getUserNicknameFromJID(((ChatRoomImpl) room).getParticipantJID()); + + tooltip = "Contact: " + nickname + "
      JID: " + tooltip; + } else { + tooltip = room.getBareJid().toString(); + } + + // Create ChatRoom UI and dock + SparkTab tab = addTab(room.getTabTitle(), room.getTabIcon(), room, tooltip); + tab.addMouseListener(new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent e) { + checkTabPopup(e); + } + + @Override + public void mousePressed(MouseEvent e) { + checkTabPopup(e); + } + }); + + room.addMessageListener(this); + + // Remove brand panel + final String title = getTabAt(0).getActualText(); + if (title.equals(WELCOME_TITLE)) { + chatFrame.setTitle(room.getRoomTitle()); + } + + final TimerTask visibleTask = new SwingTimerTask() { + @Override + public void doRun() { + checkVisibility(room); + } + }; + + TaskEngine.getInstance().schedule(visibleTask, 100); + + // Add to ChatRoomList + chatRoomList.add(room); + + // Notify users that the chat room has been opened. + fireChatRoomOpened(room); + + // Focus Chat + focusChat(); + + // Add Room listeners to override issue with input maps and keybinding on the mac. + if (Spark.isMac()) { + room.getChatInputEditor().addKeyListener(this); + } + } + + public void addContainerComponent(ContainerComponent comp) { + createFrameIfNeeded(); + + addTab(comp.getTabTitle(), comp.getTabIcon(), comp.getGUI(), comp.getToolTipDescription()); + chatFrame.setTitle(comp.getFrameTitle()); + checkVisibility(comp.getGUI()); + + if (getSelectedComponent() != comp) { + // Notify Decorators + SparkManager.getChatManager().notifySparkTabHandlers(comp.getGUI()); + } + } + + /** + * Handles the presence of a one to one chat room. + * + * @param p the presence to handle. + */ + private void handleRoomPresence(final Presence p) { + final EntityBareJid roomname = p.getFrom().asEntityBareJidIfPossible(); + ChatRoom chatRoom; + try { + chatRoom = getChatRoom(roomname); + } catch (ChatRoomNotFoundException e1) { + Log.debug("Could not locate chat room " + roomname); + return; + } + + final Resourcepart userid = p.getFrom().getResourceOrNull(); + if (p.getType() == Presence.Type.unavailable) { + fireUserHasLeft(chatRoom, userid); + } else if (p.getType() == Presence.Type.available) { + fireUserHasJoined(chatRoom, userid); + } + + // Change tab icon + if (chatRoom instanceof ChatRoomImpl) { + // Notify state change. + int tabLoc = indexOfComponent(chatRoom); + if (tabLoc != -1) { + SparkManager.getChatManager().notifySparkTabHandlers(chatRoom); + } + } + } + + private void checkVisibility(Component component) { + if (!chatFrame.isVisible() && SparkManager.getMainWindow().isFocusOwner()) { + chatFrame.setState(Frame.NORMAL); + chatFrame.setVisible(true); + } else if (chatFrame.isVisible() && !chatFrame.isInFocus()) { + startFlashing(component, false, null, null); + } else if (chatFrame.isVisible() && chatFrame.getState() == Frame.ICONIFIED) { + // Set to new tab. + int tabLocation = indexOfComponent(component); + setSelectedIndex(tabLocation); + + // If the ContactList is in the tray, we need better notification by flashing + // the chatframe. + startFlashing(component, false, null, null); + } // Handle when chat frame is visible but the Contact List is not. + else if (chatFrame.isVisible() && !SparkManager.getMainWindow().isVisible()) { + startFlashing(component, false, null, null); + } else if (!chatFrame.isVisible()) { + // Set to new tab. + int tabLocation = indexOfComponent(component); + setSelectedIndex(tabLocation); + + if (Spark.isWindows()) { + chatFrame.setFocusableWindowState(false); + chatFrame.setState(Frame.ICONIFIED); + } + chatFrame.setFocusableWindowState(true); + + // If the ContactList is in the tray, we need better notification by flashing + // the chatframe. + if (!SparkManager.getMainWindow().isVisible()) { + startFlashing(component, false, null, null); + } else if (chatFrame.getState() == Frame.ICONIFIED) { + startFlashing(component, false, null, null); + } + + if (component instanceof ChatRoom) { + chatFrame.setTitle(((ChatRoom) component).getRoomTitle()); + } + } + } + + private void handleMessageNotification(final ChatRoom chatRoom, boolean customMsg, String customMsgText, String customMsgTitle) { + ChatRoom activeChatRoom = null; + boolean groupMessageChecked = false; + try { + activeChatRoom = getActiveChatRoom(); + } catch (ChatRoomNotFoundException e1) { + Log.error(e1); + } + + if (chatFrame.isVisible() && (chatFrame.getState() == Frame.ICONIFIED || chatFrame.getInactiveTime() > 20000)) { + int tabLocation = indexOfComponent(chatRoom); + //setSelectedIndex(tabLocation); + groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); + return; + } + if (chatFrame.isVisible() && chatFrame.getState() == Frame.NORMAL) { + groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); + groupMessageChecked = true; + } + + if (!chatFrame.isVisible() && SparkManager.getMainWindow().isFocusOwner()) { + chatFrame.setState(Frame.NORMAL); + chatFrame.setVisible(true); + } else if (chatFrame.isVisible() && !chatFrame.isInFocus()) { + if (!groupMessageChecked) { + groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); + } + } else if (chatFrame.isVisible() && chatFrame.getState() == Frame.ICONIFIED) { + // Set to new tab. + int tabLocation = indexOfComponent(chatRoom); + setSelectedIndex(tabLocation); + + // If the ContactList is in the tray, we need better notification by flashing + // the chatframe. + if (!groupMessageChecked) { + groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); + } + } // Handle when chat frame is visible but the Contact List is not. + else if (chatFrame.isVisible() && !SparkManager.getMainWindow().isVisible() && !chatFrame.isInFocus()) { + if (!groupMessageChecked) { + groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); + } + } else if (!chatFrame.isVisible()) { + // Set to new tab. + int tabLocation = indexOfComponent(chatRoom); + setSelectedIndex(tabLocation); + + if (Spark.isWindows()) { + chatFrame.setExtendedState(Frame.ICONIFIED); + } + chatFrame.setVisible(true); + + // If the ContactList is in the tray, we need better notification by flashing + // the chatframe. + if (!SparkManager.getMainWindow().isVisible()) { + if (!groupMessageChecked) { + groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); + } + } else if (chatFrame.getState() == Frame.ICONIFIED) { + if (!groupMessageChecked) { + groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); + } + } + + chatFrame.setTitle(chatRoom.getRoomTitle()); + } else if (chatRoom != activeChatRoom) { + if (!groupMessageChecked) { + groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); + } + } + } + + /** + * Removes the ChatRoom resources. + * + * @param room the room to remove. + */ + private synchronized void cleanupChatRoom(ChatRoom room) { + if (room.isActive()) { + room.leaveChatRoom(); + room.closeChatRoom(); + } + + final StanzaListener listener = presenceMap.get(room.getJid()); + if (listener != null) { + SparkManager.getConnection().removeAsyncStanzaListener(listener); + } + + fireChatRoomClosed(room); + room.removeMessageListener(this); + + // Remove mappings + presenceMap.remove(room.getJid()); + + chatRoomList.remove(room); + + room.getChatInputEditor().removeKeyListener(this); + + // Clear all Text :) + room.getTranscriptWindow().cleanup(); + } + + /** + * Close all chat rooms. + */ + public void closeAllChatRooms() { + if (MainWindow.getInstance().isDocked() || !pref.isAutoCloseChatRoomsEnabled()) { + return; + } + + // copy room list to avoid concurrent modification during iterations and removing + List allChatRooms = new ArrayList<>(chatRoomList); + for (ChatRoom chatRoom : allChatRooms) { + chatRoom.closeChatRoom(); + } + + // close in reverse order + for (int i = getTabCount() - 1; i >= 0; i--) { + Component comp = getComponentAt(i); + if (comp instanceof ContainerComponent) { + ((ContainerComponent) comp).closing(); + } + closeTab(comp); + } + } + + /** + * Leaves a ChatRoom. Leaving a chat room does everything but close the room + * itself. + * + * @param room the room to leave. + */ + public void leaveChatRoom(ChatRoom room) { + // Notify that the chatroom has been left. + fireChatRoomLeft(room); + room.leaveChatRoom(); + + final StanzaListener listener = presenceMap.get(room.getJid()); + if (listener != null && SparkManager.getConnection().isConnected()) { + SparkManager.getConnection().removeAsyncStanzaListener(listener); + } + } + + /** + * Returns a ChatRoom by name. + * + * @param roomName the name of the ChatRoom. + * @return the ChatRoom + * @throws ChatRoomNotFoundException if the room was not found. + */ + public ChatRoom getChatRoom(CharSequence roomName) throws ChatRoomNotFoundException { + EntityBareJid roomAddress = JidCreate.entityBareFromOrThrowUnchecked(roomName); + return getChatRoom(roomAddress); + } + + /** + * Returns a ChatRoom by name. + * + * @param jid the name of the ChatRoom. + * @return the ChatRoom + * @throws ChatRoomNotFoundException if the room was not found. + */ + public ChatRoom getChatRoom(EntityJid jid) throws ChatRoomNotFoundException { + for (int i = 0; i < getTabCount(); i++) { + ChatRoom room = null; + try { + room = getChatRoom(i); + } catch (ChatRoomNotFoundException e1) { + // Ignore + } + + if (jid instanceof EntityBareJid) { + + if (room != null && room.getJid().equals(jid) && isMUC(jid) && room.isActive()) { + return room; + } + + if (room != null && room.getBareJid().equals(jid) && !isMUC(jid) && room.isActive()) { + return room; + } + } else { + if (room != null && room.getJid().equals(jid) && room.isActive()) { + return room; + } + } + } + throw new ChatRoomNotFoundException(jid + " not found."); + } + + + private static boolean isMUC(EntityJid jid){ + + if(domainMUC == null){ + try { + MultiUserChatManager mucManager = SparkManager.getMucManager(); + domainMUC = mucManager.getMucServiceDomains(); + }catch (XMPPException | SmackException | InterruptedException e) { + Log.error("Unable to load MUC Service Names.", e); + } + } + + if(domainMUC != null && jid.hasNoResource()){ + for(DomainBareJid domain : domainMUC){ + if(jid.getDomain().equals(domain.getDomain())){ + return true; + } + } + } + return false; + } + + /** + * Returns a ChatRoom in the specified tab location. + * + * @param location the tab location. + * @return the ChatRoom found. + * @throws ChatRoomNotFoundException thrown if the room is not found. + */ + public ChatRoom getChatRoom(int location) throws ChatRoomNotFoundException { + if (getTabCount() < location) { + throw new ChatRoomNotFoundException(); + } + try { + Component comp = getComponentAt(location); + if (comp instanceof ChatRoom) { + return (ChatRoom) comp; + } + } catch (ArrayIndexOutOfBoundsException outOfBoundsEx) { + Log.error("Error getting Chat Room", outOfBoundsEx); + } + + throw new ChatRoomNotFoundException(); + } + + /** + * Returns the Active ChatRoom. + * + * @return the ChatRoom active in the tabbed pane. + * @throws ChatRoomNotFoundException is thrown if no chat room is found. + */ + public ChatRoom getActiveChatRoom() throws ChatRoomNotFoundException { + int location = getSelectedIndex(); + if (location != -1) { + return getChatRoom(location); + } + throw new ChatRoomNotFoundException(); + } + + /** + * Returns the Active Component. + * + * @return the Component active in the tabbed pane. + */ + public Component getActiveRoom() { + int location = getSelectedIndex(); + if (location != -1) { + return getComponentAt(location); + } + + return null; + } + + /** + * Activates the specified ChatRoom. + * + * @param room the ChatRoom to activate. + */ + public void activateChatRoom(ChatRoom room) { + int tabLocation = indexOfComponent(room); + setSelectedIndex(tabLocation); + + chatFrame.bringFrameIntoFocus(); + focusChat(); + } + + /** + * Activates the component in tabbed pane. + * + * @param component the component contained within the tab to activate. + */ + public void activateComponent(Component component) { + int tabLocation = indexOfComponent(component); + if (tabLocation != -1) { + setSelectedIndex(tabLocation); + } + + chatFrame.bringFrameIntoFocus(); + focusChat(); + } + + /** + * Used for Tray Notifications. + * + * @param room the ChatRoom where the message was received. + * @param message the message received. + */ + @Override + public void messageReceived(ChatRoom room, Message message) { + room.increaseUnreadMessageCount(); + SparkManager.getWorkspace().getTranscriptPlugin().persistChatRoom(room); + fireNotifyOnMessage(room, false, null, null); + ChatManager.getInstance().fireMessageReceived(message); + } + + /** + * Used for Tray Notifications. + * + * @param chatRoom the ChatRoom where the message was received. + */ + public void fireNotifyOnMessage(final ChatRoom chatRoom, final boolean customMsg, final String customMsgText, final String customMsgTitle) { + SwingUtilities.invokeLater(() -> handleMessageNotification(chatRoom, customMsg, customMsgText, customMsgTitle)); + } + + @Override + public void messageSent(ChatRoom room, Message message) { + fireChatRoomStateUpdated(room); + } + + /** + * Notification that the tab pane has been modified. + * Generally by changing of the tabs. + */ + @Override + public void stateChanged(ChangeEvent e) { + // Stop the flashing only if the chat frame is in focus. + if (chatFrame.isInFocus()) { + stopFlashing(); + } + + final Object o = getSelectedComponent(); + if (o instanceof ChatRoom) { + final ChatRoom room = (ChatRoom) o; + focusChat(); + + // Set the title of the room. + chatFrame.setTitle(room.getRoomTitle()); + chatFrame.setIconImage(SparkManager.getMainWindow().getIconImage()); + } else if (o instanceof ContainerComponent) { + final ContainerComponent comp = (ContainerComponent) o; + chatFrame.setTitle(comp.getFrameTitle()); + chatFrame.setIconImage(comp.getTabIcon().getImage()); + + SparkManager.getChatManager().notifySparkTabHandlers(comp.getGUI()); + } + } + + private void stopFlashing() { + try { + // Get current tab + int selectedIndex = getSelectedIndex(); + if (selectedIndex != -1) { + Component comp = getComponentAt(selectedIndex); + if (comp != null) { + stopFlashing(comp); + } + } + } catch (Exception e) { + Log.error(e); + } + } + + /** + * Closes a tab of a room. + * + * @param component the component inside of the tab to close. + */ + public void closeTab(Component component) { + int location = indexOfComponent(component); + if (location == -1) { + return; + } + + if (getTabCount() == 0) { + chatFrame.setTitle(""); + } + + this.close(this.getTabAt(location)); + } + + public void closeActiveRoom() { + ChatRoom room; + try { + room = getActiveChatRoom(); + } catch (ChatRoomNotFoundException e1) { + Component comp = getActiveRoom(); + if (comp != null) { + boolean canClose = ((ContainerComponent) comp).closing(); + if (canClose) { + closeTab(comp); + } + } + return; + } + + // Confirm end session + boolean isGroupChat = room.getChatType() == Message.Type.groupchat; + if (isGroupChat) { + final int ok = JOptionPane.showConfirmDialog(chatFrame, Res.getString("message.end.conversation"), + Res.getString("title.confirmation"), JOptionPane.YES_NO_OPTION); + if (ok == JOptionPane.OK_OPTION) { + room.closeChatRoom(); + } + } else { + room.closeChatRoom(); + } + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + for (ChatRoom room : chatRoomList) { + buf.append("Roomname=").append(room.getBareJid()).append("\n"); + } + return buf.toString(); + } + + /** + * Returns true if there are any Rooms present. + * + * @return true if Rooms are present, otherwise false. + */ + public boolean hasRooms() { + int count = getSelectedIndex(); + return count != -1; + } + + /** + * Adds a ChatRoom listener to ChatRooms. The listener will be called when + * either a ChatRoom has been added, removed, or activated. + * + * @param listener the ChatRoomListener to register + */ + public void addChatRoomListener(ChatRoomListener listener) { + chatRoomListeners.addIfAbsent(listener); + } + + /** + * Removes the specified ChatRoomListener. + * + * @param listener the ChatRoomListener to remove + */ + public void removeChatRoomListener(ChatRoomListener listener) { + chatRoomListeners.remove(listener); + } + + /** + * Notifies users that a ChatRoom has been opened. + * + * @param room - the ChatRoom that has been opened. + */ + protected void fireChatRoomOpened(ChatRoom room) { + for (final ChatRoomListener listener : chatRoomListeners) { + try { + listener.chatRoomOpened(room); + } catch (Exception e) { + Log.error("A ChatRoomListener (" + listener + ") threw an exception while processing a 'opened' event for room: " + room, e); + } + } + } + + /** + * Notifies users that a ChatRoom has been left. + * + * @param room - the ChatRoom that has been left + */ + protected void fireChatRoomLeft(ChatRoom room) { + for (final ChatRoomListener listener : chatRoomListeners) { + try { + listener.chatRoomLeft(room); + } catch (Exception e) { + Log.error("A ChatRoomListener (" + listener + ") threw an exception while processing a 'left' event for room: " + room, e); + } + } + } + + /** + * Notifies users that a ChatRoom has been closed. + * + * @param room - the ChatRoom that has been closed. + */ + protected void fireChatRoomClosed(ChatRoom room) { + for (final ChatRoomListener listener : chatRoomListeners) { + try { + listener.chatRoomClosed(room); + } catch (Exception e) { + Log.error("A ChatRoomListener (" + listener + ") threw an exception while processing a 'closed' event for room: " + room, e); + } + } + } + + /** + * Notifies users that a ChatRoom has been activated. + * + * @param room - the ChatRoom that has been activated. + */ + protected void fireChatRoomActivated(ChatRoom room) { + for (final ChatRoomListener listener : chatRoomListeners) { + try { + listener.chatRoomActivated(room); + } catch (Exception e) { + Log.error("A ChatRoomListener (" + listener + ") threw an exception while processing a 'activated' event for room: " + room, e); + } + } + } + + /** + * Notifies users that a user has joined a ChatRoom. + * + * @param room - the ChatRoom that a user has joined. + * @param userid - the userid of the person. + */ + protected void fireUserHasJoined(final ChatRoom room, final Resourcepart userid) { + SwingUtilities.invokeLater(() + -> { + for (final ChatRoomListener listener : chatRoomListeners) { + try { + if (userid != null) { + listener.userHasJoined(room, userid.toString()); + } + } catch (Exception e) { + Log.error("A ChatRoomListener (" + listener + ") threw an exception while processing a 'user joined' event for user '" + userid + "' in room: " + room, e); + } + } + }); + } + + /** + * Notifies users that a user has left a ChatRoom. + * + * @param room - the ChatRoom that a user has left. + * @param userid - the userid of the person. + */ + protected void fireUserHasLeft(final ChatRoom room, final Resourcepart userid) { + SwingUtilities.invokeLater(() + -> { + for (final ChatRoomListener listener : chatRoomListeners) { + try { + listener.userHasLeft(room, userid.toString()); + } catch (Exception e) { + Log.error("A ChatRoomListener (" + listener + ") threw an exception while processing a 'user left' event for user '" + userid + "' in room: " + room, e); + } + } + }); + } + + /** + * Starts flashing of MainWindow. + * + * @param comp the Component to check if a message has been inserted but the + * room is not the selected room. + */ + public void startFlashing(final Component comp, final boolean customMsg, + final String customMsgText, final String customMsgTitle) { + + SwingUtilities.invokeLater(() -> { + try { + final int index = indexOfComponent(comp); + if (index != -1) { + // Check notifications. + if (pref.isChatRoomNotificationsOn() || !(comp instanceof GroupChatRoom)) { + if (comp instanceof ChatRoom) { + if (comp instanceof GroupChatRoom) { + GroupChatRoom groupChatRoom = (GroupChatRoom) comp; + if (groupChatRoom.getLastMessage() != null) { + EntityFullJid lastMessageFrom = groupChatRoom.getLastMessage().getFrom().asEntityFullJidIfPossible(); + if (!groupChatRoom.isBlocked(lastMessageFrom)) { + checkNotificationPreferences(groupChatRoom, customMsg, customMsgText, customMsgTitle); + } + } + } else { + checkNotificationPreferences((ChatRoom) comp, customMsg, customMsgText, customMsgTitle); + } + } + } + // Notify decorators + SparkManager.getChatManager().notifySparkTabHandlers(comp); + } + + boolean flashAllowed = pref.isChatRoomNotificationsOn() + || !(comp instanceof GroupChatRoom); + + if (!chatFrame.isInFocus() && flashAllowed) { + SparkManager.getNativeManager().flashWindow(chatFrame); + } + } catch (Exception ex) { + Log.error("Issue in ChatRooms with tab location.", ex); + } + }); + } + + public void fireChatRoomStateUpdated(final ChatRoom room) { + final int index = indexOfComponent(room); + if (index != -1) { + SparkManager.getChatManager().notifySparkTabHandlers(room); + } + } + + /** + * Checks to see if the ChatFrame should stop flashing. + * + * @param component the component that should be notified. + */ + public void stopFlashing(final Component component) { + SwingUtilities.invokeLater(() -> { + try { + // Stop the flashing + SparkManager.getNativeManager().stopFlashing(chatFrame); + // Notify decorators + SparkManager.getChatManager().notifySparkTabHandlers(component); + } catch (Exception ex) { + Log.error("Could not stop flashing because " + ex.getMessage(), ex); + } + }); + } + + /** + * Handles Notification preferences for incoming messages and rooms. + */ + private void checkNotificationPreferences(final ChatRoom room, boolean customMsg, String customMsgText, String customMsgTitle) { + if (pref.getWindowTakesFocus()) { + chatFrame.setState(Frame.NORMAL); + chatFrame.setVisible(true); + } + + if (pref.getShowToasterPopup()) { + SparkToaster toaster = new SparkToaster(); + toaster.setCustomAction(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + chatFrame.setState(Frame.NORMAL); + chatFrame.setVisible(true); + int tabLocation = indexOfComponent(room); + if (tabLocation != -1) { + setSelectedIndex(tabLocation); + } + } + }); + + toaster.setDisplayTime(5000); + toaster.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); + + String nickname = room.getRoomTitle(); + + toaster.setToasterHeight(150); + toaster.setToasterWidth(200); + + int size = room.getTranscripts().size(); + if (customMsg) { + toaster.setTitle(customMsgTitle); + toaster.showToaster(room.getTabIcon(), customMsgText); + } else { + toaster.setTitle(nickname); + if (size > 0) { + Message lastChatMessage = room.getTranscripts().get(size - 1); + toaster.showToaster(room.getTabIcon(), lastChatMessage.getBody()); + } + } + } + } + + /** + * Performs several group chat checks + * + * chatRoom the chat room that needs to be passed customMsg whether or not + * this is a custom message customMsgText if any custom message should + * appear in the popup customMsgTitle whether or not the toaster should have + * any popup + */ + private void groupChatMessageCheck(ChatRoom chatRoom, boolean customMsg, String customMsgText, String customMsgTitle) { + // predefine if this is a group chat message or not + boolean isGroupChat = chatRoom.getChatType() == Message.Type.groupchat; + int size = chatRoom.getTranscripts().size(); + + // is this a group chat message and is my name in it? + if (isGroupChat) { + // is a group chat, perform some functions + String fromNickName = ""; + Message lastChatMessage; + Jid mucNickNameT; + String finalRoomName = ""; + if (size > 0) { + finalRoomName = chatRoom.getRoomTitle(); + lastChatMessage = chatRoom.getTranscripts().get(size - 1); + mucNickNameT = lastChatMessage.getFrom(); + if (mucNickNameT == null) { + fromNickName = finalRoomName; + } else { + String[] mucNickName = mucNickNameT.toString().split("/"); + if (mucNickName.length < 2) { // We have no name after "/" in mucNickNameT (must be like: test@conference.jabber.kg/kos) + fromNickName = finalRoomName; //Res.getString("label.message"); + } else { + fromNickName = mucNickName[1]; + } + } + } else { + lastChatMessage = StanzaBuilder.buildMessage().build(); + } + String myNickName = chatRoom.getNickname().toString(); + if (!myNickName.equals(fromNickName)) { + final String lastMessageBody = lastChatMessage.getBody(); + if (lastMessageBody != null && !lastMessageBody.isEmpty() && pref.isMucHighToastEnabled()) { + // allowed to check for new messages containing name + String myUserName = SparkManager.getSessionManager().getUsername(); + Pattern usernameMatch = Pattern.compile(myUserName, Pattern.CASE_INSENSITIVE); + Pattern nicknameMatch = Pattern.compile(myNickName, Pattern.CASE_INSENSITIVE); + if (usernameMatch.matcher(lastMessageBody).find() || nicknameMatch.matcher(lastMessageBody).find()) { + // match, send new message + String customMsgTextS = Res.getString("group.chat.name.match") + " " + finalRoomName + " by " + fromNickName + " (" + lastMessageBody + ")"; + String customMsgTitleS = Res.getString("group.chat.name.notification"); + startFlashing(chatRoom, true, customMsgTextS, customMsgTitleS); + } else { + // regular group message + String customMsgTextS = fromNickName + " says: " + lastMessageBody; + startFlashing(chatRoom, true, customMsgTextS, finalRoomName); + } + } else { + // regular group message + String customMsgTextS = fromNickName + " says: " + lastMessageBody; + startFlashing(chatRoom, true, customMsgTextS, finalRoomName); + } + } + } else if (customMsg) { + // probably a file transfer request + startFlashing(chatRoom, true, customMsgText, customMsgTitle); + } else { + // normal personal chat + Message lastChatMessage = null; + if (size > 0) { + lastChatMessage = chatRoom.getTranscripts().get(size - 1); + } + String finalRoomName = chatRoom.getRoomTitle(); + String customMsgTextS = ""; + if (lastChatMessage != null) { + customMsgTextS = lastChatMessage.getBody(); + } + startFlashing(chatRoom, true, customMsgTextS, finalRoomName); + } + } + + public void setChatRoomTitle(ChatRoom room, String title) { + int index = indexOfComponent(room); + if (index != -1) { + SparkTab tab = getTabAt(index); + fireChatRoomStateUpdated(room); + tab.setTabTitle(room.getTabTitle()); + } + } + + private void createFrameIfNeeded() { + if (chatFrame != null) { + return; + } + + if (pref.isDockingEnabled()) { + chatFrame = MainWindow.getInstance(); + } else { + chatFrame = new ChatFrame(); + } + + if (SparkManager.getMainWindow().isActive() || pref.getWindowTakesFocus()) { + chatFrame.setState(Frame.NORMAL); + } else { + chatFrame.setAutoRequestFocus(false); + chatFrame.setState(Frame.ICONIFIED); + } + + chatFrame.setVisible(true); + chatFrame.addWindowListener(new WindowAdapter() { + @Override + public void windowActivated(WindowEvent windowEvent) { + stopFlashing(); + int sel = getSelectedIndex(); + if (sel == -1) { + return; + } + final ChatRoom room; + try { + room = getChatRoom(sel); + focusChat(); + + // Set the title of the room. + chatFrame.setTitle(room.getRoomTitle()); + } catch (ChatRoomNotFoundException e1) { + // Nothing to do + } + + } + + @Override + public void windowClosing(WindowEvent windowEvent) { + ChatContainer chatContainer = SparkManager.getChatManager().getChatContainer(); + if (chatContainer.getTotalNumberOfUnreadMessages() > 0 && + pref.isCloseUnreadMessage()) { + final int selectedOption = JOptionPane.showConfirmDialog(null, + Res.getString("message.close.unread.window"), + Res.getString("title.alert"), + JOptionPane.YES_NO_OPTION); + if (selectedOption == JOptionPane.YES_OPTION) { + chatContainer.closeAllChatRooms(); + } + } else { + chatContainer.closeAllChatRooms(); + } + } + }); + + // Start timer + handleStaleChats(); + } + + /** + * Brings the chat into focus. + */ + public void focusChat() { + + TaskEngine.getInstance().schedule(focusTask, 50); + } + + public Collection getChatRooms() { + return new ArrayList<>(chatRoomList); + } + + public ChatFrame getChatFrame() { + return chatFrame; + } + + public void blinkFrameIfNecessary(final JFrame frame) { + final MainWindow mainWindow = SparkManager.getMainWindow(); + if (mainWindow.isFocusOwner()) { + frame.setVisible(true); + } else { + // Set to new tab. + if (Spark.isWindows()) { + frame.setState(Frame.ICONIFIED); + SparkManager.getNativeManager().flashWindow(frame); + frame.setVisible(true); + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowActivated(WindowEvent e) { + SparkManager.getNativeManager().stopFlashing(frame); + } + }); + } + } + } + + private void checkTabPopup(MouseEvent e) { + final SparkTab tab = (SparkTab) e.getSource(); + if (!e.isPopupTrigger()) { + return; + } + + final JPopupMenu popup = new JPopupMenu(); + + // Handle closing this room. + Action closeThisAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + ChatRoom chatRoom = (ChatRoom) getComponentInTab(tab); + if (chatRoom != null) { + closeTab(chatRoom); + } + } + }; + closeThisAction.putValue(Action.NAME, Res.getString("message.close.this.chat")); + popup.add(closeThisAction); + + if (getChatRooms().size() > 1) { + // Handle closing other rooms. + Action closeOthersAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + ChatRoom chatRoom = (ChatRoom) getComponentInTab(tab); + if (chatRoom != null) { + for (ChatRoom cRoom : getChatRooms()) { + if (chatRoom != cRoom) { + closeTab(cRoom); + } + } + } + } + }; + + closeOthersAction.putValue(Action.NAME, Res.getString("message.close.other.chats")); + popup.add(closeOthersAction); + + Action closeOldAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + for (ChatRoom rooms : getStaleChatRooms()) { + closeTab(rooms); + } + } + }; + closeOldAction.putValue(Action.NAME, Res.getString("message.close.stale.chats")); + popup.add(closeOldAction); + + } + + popup.show(tab, e.getX(), e.getY()); + } + + /** + * Returns a Collection of stale chat rooms. + * + * @return a collection of stale chat rooms. + */ + public Collection getStaleChatRooms() { + final List staleRooms = new ArrayList<>(); + for (ChatRoom chatRoom : getChatRooms()) { + long lastActivity = chatRoom.getLastActivity(); + long currentTime = System.currentTimeMillis(); + long diff = currentTime - lastActivity; + int minutes = (int) (diff / (60 * 1000F)); + int timeoutMinutes = pref.getChatLengthDefaultTimeout(); + int unreadCount = chatRoom.getUnreadMessageCount(); + if (timeoutMinutes <= minutes && unreadCount == 0) { + staleRooms.add(chatRoom); + } + } + return staleRooms; + } + + /** + * Checks every room every 30 seconds to see if it's timed out. + */ + private void handleStaleChats() { + int delay = 1000; // delay for 1 second. + int period = 60000; // repeat every minute. + + final TimerTask task = new SwingTimerTask() { + @Override + public void doRun() { + for (ChatRoom chatRoom : getStaleChatRooms()) { + // Notify decorators + SparkManager.getChatManager().notifySparkTabHandlers(chatRoom); + } + } + }; + + TaskEngine.getInstance().scheduleAtFixedRate(task, delay, period); + } + + private void navigateRight() { + int selectedIndex = getSelectedIndex(); + if (selectedIndex > -1) { + int count = getTabCount(); + if (selectedIndex == (count - 1)) { + setSelectedIndex(0); + } else { + setSelectedIndex(selectedIndex + 1); + } + } + } + + private void navigateLeft() { + int selectedIndex = getSelectedIndex(); + if (selectedIndex > 0) { + setSelectedIndex(selectedIndex - 1); + } else { + setSelectedIndex(getTabCount() - 1); + } + } + + // Handle key listener events for mac only :) + @Override + public void keyTyped(KeyEvent keyEvent) { + // Nothing to do. + } + + @Override + public void keyPressed(KeyEvent keyEvent) { + if (keyEvent.isMetaDown()) { + if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) { + navigateRight(); + } else if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) { + navigateLeft(); + } + + } + } + + @Override + public void keyReleased(KeyEvent keyEvent) { + // Nothing to do. + } + + /** + * Returns the total number of unread messages in Spark. + * + * @return the total number of unread messages in Spark. + */ + public int getTotalNumberOfUnreadMessages() { + int messageCount = 0; + for (ChatRoom chatRoom : chatRoomList) { + messageCount += chatRoom.getUnreadMessageCount(); + } + + return messageCount; + } + + public void closeAllGroupChatRooms() { + for (ChatRoom chatRoom : chatRoomList) { + boolean isGroup = chatRoom.getChatType() == Message.Type.groupchat; + if (isGroup) { + closeTab(chatRoom); + chatRoom.closeChatRoom(); + } + } + } + + public boolean hasGroupChatRooms() { + for (ChatRoom chatRoom : chatRoomList) { + boolean isGroup = chatRoom.getChatType() == Message.Type.groupchat; + if (isGroup) { + return true; + } + } + return false; + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ChatFrame.java b/core/src/main/java/org/jivesoftware/spark/ui/ChatFrame.java new file mode 100644 index 000000000..6cfbf0ffe --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/ChatFrame.java @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.MainWindow; +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettingsManager; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * The Window used to display the ChatRoom container. + */ +public class ChatFrame extends JFrame implements WindowFocusListener { + + private static final long serialVersionUID = -7789413067818105293L; + private long inactiveTime; + private boolean focused; + private final JCheckBox alwaysOnTopItem; + private final ChatFrame chatFrame = this; + private final CopyOnWriteArrayList _windowToFrontListeners = new CopyOnWriteArrayList<>(); + + /** + * Creates default ChatFrame. + */ + public ChatFrame() { + this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + + + + alwaysOnTopItem = new JCheckBox(); + alwaysOnTopItem.setToolTipText(Res.getString("menuitem.always.on.top")); + LocalPreferences pref = SettingsManager.getLocalPreferences(); + alwaysOnTopItem.addActionListener(actionEvent -> { + if (alwaysOnTopItem.isSelected()) + { + pref.setChatWindowAlwaysOnTop(true); + chatFrame.setAlwaysOnTop(true); + } + else + { + pref.setChatWindowAlwaysOnTop(false); + chatFrame.setAlwaysOnTop(false); + } + } ); + + if (pref.isChatWindowAlwaysOnTop()) + { + alwaysOnTopItem.setSelected(true); + chatFrame.setAlwaysOnTop(true); + } + + + + + setIconImage(SparkManager.getApplicationImage().getImage()); + + getContentPane().setLayout(new BorderLayout()); + getContentPane().add(SparkManager.getChatManager().getChatContainer(), BorderLayout.CENTER); + + setMinimumSize( new Dimension( 300, 300 ) ); + final Rectangle chatFrameBounds = LayoutSettingsManager.getLayoutSettings().getChatFrameBounds(); + if (chatFrameBounds == null || chatFrameBounds.width <= 0 || chatFrameBounds.height <= 0) + { + // Use default settings. + setSize(500, 400); + GraphicUtils.centerWindowOnScreen(this); + } + else + { + setBounds( chatFrameBounds ); + } + + addComponentListener( new ComponentAdapter() + { + @Override + public void componentResized( ComponentEvent e ) + { + // Don't do this for subclasses. + if ( e.getComponent().getClass().getSimpleName().equalsIgnoreCase( "ChatFrame" ) ) + { + LayoutSettingsManager.getLayoutSettings().setChatFrameBounds( getBounds() ); + } + } + + @Override + public void componentMoved( ComponentEvent e ) + { + // Don't do this for subclasses. + if ( e.getComponent().getClass().getSimpleName().equalsIgnoreCase( "ChatFrame" ) ) + { + LayoutSettingsManager.getLayoutSettings().setChatFrameBounds( getBounds() ); + } + } + } ); + + addWindowFocusListener(this); + + // Setup WindowListener to be the proxy to the actual window listener + // which cannot normally be used outside of the Window component because + // of protected access. + addWindowListener(new WindowAdapter() { + + /** + * This event fires when the window has become active. + * + * @param e WindowEvent is not used. + */ + @Override + public void windowActivated(WindowEvent e) { + inactiveTime = 0; + if (Spark.isMac()) { + setJMenuBar(MainWindow.getInstance().getMenu()); + } + } + + /** + * Invoked when a window is de-activated. + */ + @Override + public void windowDeactivated(WindowEvent e) { + inactiveTime = System.currentTimeMillis(); + } + + /** + * This event fires whenever a user minimizes the window + * from the toolbar. + * + * @param e WindowEvent is not used. + */ + @Override + public void windowIconified(WindowEvent e) { + } + + @Override + public void windowDeiconified(WindowEvent e) { + setFocusableWindowState(true); + } + }); + + // Adding a Resize Listener to validate component sizes in a Chat Room. + addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + try { + ChatRoom chatRoom = SparkManager.getChatManager().getChatContainer().getActiveChatRoom(); + chatRoom.getVerticalSlipPane().setDividerLocation(-1); + } + catch (ChatRoomNotFoundException e1) { + // Ignore, because I don't care if it's not a chat room. + } + } + }); + + + } + + + + + @Override + public void windowGainedFocus(WindowEvent e) { + focused = true; + + if(this instanceof MainWindow){ + return; + } + + + SparkManager.getChatManager().getChatContainer().focusChat(); + } + + @Override + public void windowLostFocus(WindowEvent e) { + focused = false; + } + + /** + * Returns true if the frame is in focus, otherwise returns false. + * + * @return true if the frame is in focus, otherwise returns false. + */ + public boolean isInFocus() { + return focused; + } + + /** + * Returns time the ChatFrame has not been in focus. + * + * @return the time in milliseconds. + */ + public long getInactiveTime() { + if (inactiveTime == 0) { + return 0; + } + + return System.currentTimeMillis() - inactiveTime; + } + + /** + * Brings the ChatFrame into focus on the desktop. + */ + public void bringFrameIntoFocus() { + if (!isVisible()) { + setVisible(true); + } + + if (getState() == Frame.ICONIFIED) { + setState(Frame.NORMAL); + } + + toFront(); + requestFocus(); + } + + /** + * Shake it, come on now, shake that frame. + */ + public void buzz() { + ShakeWindow d = new ShakeWindow(this); + d.startShake(); + } + + + /** + * set if the chatFrame should always stay on top + * @param active + */ + public void setWindowAlwaysOnTop(boolean active) { + SettingsManager.getLocalPreferences().setChatWindowAlwaysOnTop(active); + chatFrame.setAlwaysOnTop(active); + this.fireWindowOnTopListeners(active); + } + + + private void fireWindowOnTopListeners( boolean active ) + { + for ( ChatFrameToFrontListener listener : _windowToFrontListeners ) + { + try + { + listener.updateStatus( active ); + } + catch ( Exception e ) + { + Log.error( "A ChatFrameToFrontListener (" + listener + ") threw an exception while processing a 'updateStatus' event with status: " + active, e ); + } + } + } + + /** + * removes the Window to Front Listener for specified {@link ChatRoom} + * @param chatRoom + */ + public void removeWindowToFrontListener(ChatRoom chatRoom) { + _windowToFrontListeners.remove(chatRoom); + } + + /** + * Remove listeners from the "window-alway-on-top" information + * @param chatRoom + */ + public void addWindowToFronListener(ChatRoom chatRoom) { + _windowToFrontListeners.addIfAbsent(chatRoom); + fireWindowOnTopListeners(chatFrame.isAlwaysOnTop()); + } + +} diff --git a/src/java/org/jivesoftware/spark/ui/ChatFrameToFrontListener.java b/core/src/main/java/org/jivesoftware/spark/ui/ChatFrameToFrontListener.java similarity index 100% rename from src/java/org/jivesoftware/spark/ui/ChatFrameToFrontListener.java rename to core/src/main/java/org/jivesoftware/spark/ui/ChatFrameToFrontListener.java diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ChatInputEditor.java b/core/src/main/java/org/jivesoftware/spark/ui/ChatInputEditor.java new file mode 100644 index 000000000..83873615c --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/ChatInputEditor.java @@ -0,0 +1,213 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JComponent; +import javax.swing.KeyStroke; +import javax.swing.UIManager; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.undo.CannotUndoException; +import javax.swing.undo.UndoManager; + +import org.jivesoftware.spark.SparkManager; + +/** + * This is implementation of ChatArea that should be used as the sendField + * in any chat room implementation. + */ +public class ChatInputEditor extends ChatArea implements DocumentListener { + private static final long serialVersionUID = -3085035737908538581L; + private final UndoManager undoManager; + private final KeyStroke undoKeyStroke; + private final KeyStroke ctrlbackspaceKeyStroke; + private final KeyStroke escapeKeyStroke; + + /** + * Creates a new Default ChatSendField. + */ + public ChatInputEditor() { + undoManager = new UndoManager(); + + this.setDragEnabled(true); + this.getDocument().addUndoableEditListener(undoManager); + Action undo = new AbstractAction() { + private static final long serialVersionUID = -8897769620508545403L; + @Override + public void actionPerformed(ActionEvent e) { + try { + undoManager.undo(); + } catch (CannotUndoException cue) { + // no more undoing for you + } + } + }; + + Action escape = new AbstractAction() { + private static final long serialVersionUID = -2973535045376312313L; + @Override + public void actionPerformed(ActionEvent e) { + SparkManager.getChatManager().getChatContainer().closeActiveRoom(); + } + }; + + Action ctrlbackspace = new AbstractAction() { + private static final long serialVersionUID = -2973535045376312313L; + + @Override + public void actionPerformed(ActionEvent e) { + + // We have Text selected, remove it + if (getSelectedText() != null && getSelectedText().length() > 0) { + ChatInputEditor.this.removeWordInBetween(getSelectionStart(), + getSelectionEnd()); + + // We are somewhere in betwee 0 and str.length + } else if (getCaretPosition() < getText().length()) { + + String preCaret = getText() + .substring(0, getCaretPosition()); + + int lastSpace = preCaret.lastIndexOf(" ") != -1 ? preCaret + .lastIndexOf(" ") : 0; + + if (lastSpace != -1 && lastSpace!=0) + { + // Do we have anymore spaces before the current one? + for (int i = lastSpace; getText().charAt(i) == ' '; --i) { + lastSpace--; + } + lastSpace++; + } + ChatInputEditor.this.removeWordInBetween(lastSpace, + getCaretPosition()); + + setCaretPosition(Math.min(lastSpace, getText().length())); + + // We are at the end and will remove until the next SPACE + } else if (getText().contains(" ")) { + int untilhere = getText().lastIndexOf(" "); + + // Do we have anymore spaces before the last one? + for (int i = untilhere; getText().charAt(i) == ' '; --i) { + untilhere--; + } + untilhere++; + ChatInputEditor.this.removeLastWord(getText().substring( + untilhere)); + } else { + ChatInputEditor.this.removeLastWord(getText()); + } + } + }; + + undoKeyStroke = KeyStroke.getKeyStroke('z', InputEvent.CTRL_MASK); + ctrlbackspaceKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, KeyEvent.CTRL_MASK); + escapeKeyStroke = KeyStroke.getKeyStroke("ESCAPE"); + + getInputMap().put(ctrlbackspaceKeyStroke, "ctrlbackspace"); + getInputMap().put(undoKeyStroke, "undo"); + getInputMap().put(escapeKeyStroke, "escape"); + getInputMap().put(KeyStroke.getKeyStroke("ctrl W"), "escape"); + + registerKeyboardAction(undo, KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_MASK), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + registerKeyboardAction(ctrlbackspace, KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, KeyEvent.CTRL_MASK), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + registerKeyboardAction(escape, KeyStroke.getKeyStroke("ESCAPE"), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + + getDocument().addDocumentListener(this); + + addMouseListener(this); + } + + @Override + public void insertUpdate(DocumentEvent e) { + // this.setCaretPosition(e.getOffset()); + this.requestFocusInWindow(); + } + + /** + * Appends the Text at the end + */ + public void appendText(String str) { + super.setText( super.getText() + str); + } + + @Override + public void removeUpdate(DocumentEvent e) { + } + + @Override + public void changedUpdate(DocumentEvent e) { + } + + /** + * Remove dependices when no longer in use. + */ + public void close() { + getDocument().removeDocumentListener(this); + getDocument().removeUndoableEditListener(undoManager); + removeMouseListener(this); + getInputMap().remove(undoKeyStroke); + getInputMap().remove(ctrlbackspaceKeyStroke); + getInputMap().remove(escapeKeyStroke); + getInputMap().remove(KeyStroke.getKeyStroke("ctrl W")); + } + + /** + * Disables the Chat Editor, rendering it to the system default + * color. + */ + public void showAsDisabled() { + this.setEditable(false); + this.setEnabled(false); + + clear(); + + final Color disabledColor = (Color)UIManager.get("Button.disabled"); + + this.setBackground(disabledColor); + } + + /** + * Enable the Chat Editor. + */ + public void showEnabled() { + this.setEditable(true); + this.setEnabled(true); + + this.setBackground(Color.white); + } + + /** + * Inserts text into the current document at the current caret position. + * + * @param text the text to insert + * @throws BadLocationException if the location is not available for insertion. + */ + public void insertText(String text) throws BadLocationException { + final Document doc = getDocument(); + doc.insertString(this.getCaret().getDot(), text, null); + } +} diff --git a/src/java/org/jivesoftware/spark/ui/ChatPrinter.java b/core/src/main/java/org/jivesoftware/spark/ui/ChatPrinter.java similarity index 98% rename from src/java/org/jivesoftware/spark/ui/ChatPrinter.java rename to core/src/main/java/org/jivesoftware/spark/ui/ChatPrinter.java index 8137f6ba3..01dd5bb9b 100644 --- a/src/java/org/jivesoftware/spark/ui/ChatPrinter.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/ChatPrinter.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -84,7 +80,7 @@ of this class without using its print dialog by creating an instance of pFormat object, the print method gets its PageFormat as an argument. */ private PageFormat pFormat; - private PrinterJob pJob; + private final PrinterJob pJob; /** * The constructor initializes the pFormat and PJob variables. @@ -180,7 +176,8 @@ public void pageDialog() { * @param pageIndex the page to print. * @return the page number printed. */ - public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) { + @Override + public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) { double scale = 1.0; Graphics2D graphics2D; View rootView; diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ChatRoom.java b/core/src/main/java/org/jivesoftware/spark/ui/ChatRoom.java new file mode 100644 index 000000000..d133cb47a --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/ChatRoom.java @@ -0,0 +1,1289 @@ +/* + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.ConnectionListener; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.StanzaListener; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smack.roster.RosterEntry; +import org.jivesoftware.smackx.chatstates.ChatState; +import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; +import org.jivesoftware.spark.ChatAreaSendField; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.BackgroundPanel; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.plugin.ContextMenuListener; +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.UIComponentRegistry; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.EntityFullJid; +import org.jxmpp.jid.EntityJid; +import org.jxmpp.jid.parts.Resourcepart; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import java.awt.*; +import java.awt.event.*; +import java.io.File; +import java.time.Instant; +import java.util.*; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import static org.apache.commons.lang3.StringUtils.startsWithIgnoreCase; + +/** + * The base implementation of all ChatRoom conversations. You would implement + * this class to have most types of Chat. + */ +public abstract class ChatRoom extends BackgroundPanel implements ActionListener, StanzaListener, DocumentListener, ConnectionListener, FocusListener, ContextMenuListener, ChatFrameToFrontListener { + private final LocalPreferences pref = SettingsManager.getLocalPreferences(); + + private final JPanel chatPanel; + private final JSplitPane splitPane; + private final JSplitPane verticalSplit; + + private final JLabel notificationLabel; + private final TranscriptWindow transcriptWindow; + private final ChatAreaSendField chatAreaButton; + private final ChatToolBar toolbar; + private final JScrollPane textScroller; + private final JPanel bottomPanel; + + private final JPanel editorWrapperBar; + private final JPanel editorBarRight; + private final JPanel editorBarLeft; + private final JPanel chatWindowPanel; + + private int unreadMessageCount; + + private boolean mousePressed; + + private final CopyOnWriteArrayList closingListeners = new CopyOnWriteArrayList<>(); + + private ChatRoomTransferHandler transferHandler; + + private final List packetIDList; + private final CopyOnWriteArrayList messageListeners; + private final List transcript; + private final CopyOnWriteArrayList fileDropListeners; + + private final MouseAdapter transcriptWindowMouseListener; + + private final KeyAdapter chatEditorKeyListener; + private ChatFrame _chatFrame; + private final RolloverButton _alwaysOnTopItem; + private boolean _isAlwaysOnTopActive; + + // Chat state + private TimerTask typingTimerTask; + private long lastNotificationSentTime; + private ChatState lastNotificationSent; + private final long pauseTimePeriod = 2000; + private final long inactiveTimePeriod = 120000; + + private static final Color COLOR_BOTTOM_PANEL_BORDER = new Color(197, 213, 230); + + /** + * Initializes the base layout and base background color. + */ + protected ChatRoom() { + chatPanel = new JPanel(new GridBagLayout()); + transcriptWindow = UIComponentRegistry.createTranscriptWindow(); + splitPane = new JSplitPane(); + packetIDList = new ArrayList<>(); + notificationLabel = new JLabel(); + toolbar = new ChatToolBar(); + bottomPanel = new JPanel(); + + messageListeners = new CopyOnWriteArrayList<>(); + transcript = new ArrayList<>(); + + editorWrapperBar = new JPanel(new BorderLayout()); + editorBarLeft = new JPanel(new FlowLayout(FlowLayout.LEFT, 1, 1)); + editorBarRight = new JPanel(new FlowLayout(FlowLayout.RIGHT, 1, 1)); + editorWrapperBar.add(editorBarLeft, BorderLayout.WEST); + editorWrapperBar.add(editorBarRight, BorderLayout.EAST); + fileDropListeners = new CopyOnWriteArrayList<>(); + + transcriptWindowMouseListener = new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + + if (e.getClickCount() != 2) { + getChatInputEditor().requestFocus(); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + mousePressed = false; + if (transcriptWindow.getSelectedText() == null) { + getChatInputEditor().requestFocus(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + mousePressed = true; + } + }; + + transcriptWindow.addMouseListener(transcriptWindowMouseListener); + + chatAreaButton = new ChatAreaSendField(Res.getString("button.send")); + textScroller = new JScrollPane(transcriptWindow); + textScroller.setBackground(transcriptWindow.getBackground()); + textScroller.getViewport().setBackground(Color.white); + transcriptWindow.setBackground(Color.white); + + getChatInputEditor().setSelectedTextColor((Color) UIManager.get("ChatInput.SelectedTextColor")); + getChatInputEditor().setSelectionColor((Color) UIManager.get("ChatInput.SelectionColor")); + + setLayout(new GridBagLayout()); + + // Remove Default Beveled Borders + splitPane.setBorder(null); + splitPane.setOneTouchExpandable(false); + + // Add Vertical Split Pane + verticalSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + add(verticalSplit, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); + + verticalSplit.setBorder(null); + verticalSplit.setOneTouchExpandable(false); + + verticalSplit.setTopComponent(splitPane); + + textScroller.setAutoscrolls(true); + + // For the first 5*150ms we wait for transcript to load and move + // scrollpane to max postion if size of scrollpane changed + textScroller.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() { + + private boolean scrollAtStart = false; + + @Override + public void adjustmentValueChanged(AdjustmentEvent e) { + + if (!scrollAtStart) { + scrollAtStart = true; + SwingWorker thread = new SwingWorker() { + + @Override + public Object construct() { + int start = textScroller.getVerticalScrollBar().getMaximum(); + int second; + int i = 0; + do { + try { + + Thread.sleep(150); + second = textScroller.getVerticalScrollBar().getMaximum(); + if (start == second) { + ++i; + } else { + scrollToBottom(); + getTranscriptWindow().repaint(); + } + start = second; + } catch (InterruptedException e) { + e.printStackTrace(); + } + } while (i < 5); + return null; + } + }; + thread.start(); + } + } + }); + + // Speed up scrolling. It was way too slow. + textScroller.getVerticalScrollBar().setBlockIncrement(200); + textScroller.getVerticalScrollBar().setUnitIncrement(20); + + chatWindowPanel = new JPanel(); + chatWindowPanel.setLayout(new GridBagLayout()); + chatWindowPanel.add(textScroller, new GridBagConstraints(0, 10, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); + chatWindowPanel.setOpaque(false); + + // Layout Components + chatPanel.add(chatWindowPanel, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, + GridBagConstraints.BOTH, getChatPanelInsets(), 0, 0)); + + // Add Chat Panel to Split Pane + splitPane.setLeftComponent(chatPanel); + + // Add edit buttons to Chat Room + editorBarLeft.setOpaque(false); + chatPanel.setOpaque(false); + + bottomPanel.setOpaque(false); + splitPane.setOpaque(false); + bottomPanel.setLayout(new GridBagLayout()); + bottomPanel.add(chatAreaButton, new GridBagConstraints(0, 1, 5, 1, 1.0, 1.0, GridBagConstraints.WEST, + GridBagConstraints.BOTH, getChatAreaInsets(), 0, 35)); + bottomPanel.add(editorWrapperBar, new GridBagConstraints(0, 0, 5, 1, 0.0, 0.0, GridBagConstraints.WEST, + GridBagConstraints.HORIZONTAL, getEditorWrapperInsets(), 0, 0)); + + // Set bottom panel border + bottomPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, COLOR_BOTTOM_PANEL_BORDER)); + verticalSplit.setOpaque(false); + + verticalSplit.setBottomComponent(bottomPanel); + verticalSplit.setResizeWeight(1.0); + verticalSplit.setDividerSize(2); + + // Add listener to send button + chatAreaButton.getButton().addActionListener(this); + + // Add Key Listener to Send Field + getChatInputEditor().getDocument().addDocumentListener(this); + + // Add Key Listener to Send Field + chatEditorKeyListener = new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + checkForEnter(e); + } + }; + + getChatInputEditor().addKeyListener(chatEditorKeyListener); + + getChatInputEditor().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ctrl F4"), "closeTheRoom"); + getChatInputEditor().getActionMap().put("closeTheRoom", new AbstractAction("closeTheRoom") { + @Override + public void actionPerformed(ActionEvent evt) { + // Leave this chat. + closeChatRoom(); + } + }); + + getChatInputEditor().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ctrl SPACE"), "handleCompletion"); + getChatInputEditor().getActionMap().put("handleCompletion", new AbstractAction("handleCompletion") { + @Override + public void actionPerformed(ActionEvent evt) { + // handle name completion. + try { + handleNickNameCompletion(); + } catch (ChatRoomNotFoundException e) { + Log.error("ctlr-space nickname find", e); + } + } + }); + + _isAlwaysOnTopActive = pref.isChatWindowAlwaysOnTop(); + _alwaysOnTopItem = UIComponentRegistry.getButtonFactory().createAlwaysOnTop(_isAlwaysOnTopActive); + + _alwaysOnTopItem.addActionListener(actionEvent -> { + if (!_isAlwaysOnTopActive) { + pref.setChatWindowAlwaysOnTop(true); + _chatFrame.setWindowAlwaysOnTop(true); + _isAlwaysOnTopActive = true; + _alwaysOnTopItem.setIcon(SparkRes.getImageIcon(SparkRes.Icon.FRAME_ALWAYS_ON_TOP_ACTIVE)); + + } else { + pref.setChatWindowAlwaysOnTop(false); + _chatFrame.setWindowAlwaysOnTop(false); + _isAlwaysOnTopActive = false; + _alwaysOnTopItem.setIcon(SparkRes.getImageIcon(SparkRes.Icon.FRAME_ALWAYS_ON_TOP_DEACTIVE)); + } + }); + + editorBarRight.add(_alwaysOnTopItem); + + // Initially, set the right pane to null to keep it empty. + getSplitPane().setRightComponent(null); + + notificationLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.BLANK_IMAGE)); + + getTranscriptWindow().addContextMenuListener(this); + + transferHandler = new ChatRoomTransferHandler(this); + + getTranscriptWindow().setTransferHandler(transferHandler); + getChatInputEditor().setTransferHandler(transferHandler); + + addToolbar(); + + // Add Connection Listener + SparkManager.getConnection().addConnectionListener(this); + + // Add Focus Listener + addFocusListener(this); + + setChatState(ChatState.active); + createChatStateTimerTask(); + + scrollToBottom(); + } + + protected void createChatStateTimerTask() { + typingTimerTask = new TimerTask() { + @Override + public void run() { + final long lastUpdate = System.currentTimeMillis() - lastNotificationSentTime; + switch (lastNotificationSent) { + case paused: + case active: + if (lastUpdate > inactiveTimePeriod) { + setChatState(ChatState.inactive); + } + break; + + case composing: + if (lastUpdate > pauseTimePeriod) { + setChatState(ChatState.paused); + } + break; + } + } + }; + TaskEngine.getInstance().scheduleAtFixedRate(typingTimerTask, pauseTimePeriod / 2, pauseTimePeriod / 2); + } + + /** + * Sends a chat state to all peers. + * + * @param state the chat state. + * @throws InterruptedException + */ + protected abstract void sendChatState(ChatState state) throws SmackException.NotConnectedException, InterruptedException; + + /** + * Sets the chat state, causing an update to be sent to all peers if the new + * state warrants an update. + * + * @param state the chat state (never null). + */ + public final void setChatState(ChatState state) { + Objects.requireNonNull(state); + + // Only sent out a chat state notification when it is different from the last one that was transmitted... + final boolean isDifferentState = lastNotificationSent != state; + + // ... unless it's 'composing' - that can be repeated every so many seconds. + final boolean isStillComposing = state == ChatState.composing && System.currentTimeMillis() - lastNotificationSentTime > 2000; + + final long now = System.currentTimeMillis(); + if (isDifferentState || isStillComposing) { + try { + sendChatState(state); + } catch (SmackException.NotConnectedException | InterruptedException e) { + Log.warning("Unable to update the chat state to " + state, e); + } + lastNotificationSent = state; + lastNotificationSentTime = now; + } + } + + /** + * Handles the Nickname Completion dialog, when Pressing CTRL + SPACE
      + * it searches for matches in the current GroupchatList and also in the + * Roster + * + * @throws ChatRoomNotFoundException when for some reason the GroupChatRoom + * cannot be found, this should not happen, since we retrieve it from + * the ActiveWindowTab and thus can be ignored + */ + private void handleNickNameCompletion() throws ChatRoomNotFoundException { + // Search for a name that starts with the same word as the last word in the chat input editor. + final String text = getChatInputEditor().getText(); + if (text == null || text.isEmpty()) { + return; + } + + final int lastSpaceCharacterIndex = text.lastIndexOf(' '); // -1 when space does not occur. + final String needle = text.substring(lastSpaceCharacterIndex + 1); + + final Set matches = new TreeSet<>(String::compareToIgnoreCase); + + if (SparkManager.getChatManager().getChatContainer().getActiveChatRoom() instanceof GroupChatRoom) { + final GroupChatRoom activeChatRoom = (GroupChatRoom) SparkManager.getChatManager().getChatContainer().getActiveChatRoom(); + for (EntityFullJid participant : activeChatRoom.getParticipants()) { + String nickname = participant.getResourcepart().toString(); + if (startsWithIgnoreCase(nickname, needle)) { + matches.add(nickname); + } + } + } else { + Roster roster = SparkManager.getRoster(); + for (RosterEntry re : roster.getEntries()) { + // Use the name if available, otherwise the localpart of the JID. + final String username; + if (re.getName() != null) { + username = re.getName(); + } else { + username = re.getJid().toString().substring(0, re.getJid().toString().indexOf('@')); +//TODO username = re.getJid().getLocalpartOrNull().asUnescapedString(); + } + + if (startsWithIgnoreCase(username, needle)) { + matches.add(username); + } + } + } + + if (matches.size() == 1) { + // If we only have 1 match, that match can be used immediately. + getChatInputEditor().appendText(matches.iterator().next().substring(needle.length())); + } else { + // More than one match: create Popupmenu and let the user select one. + final JPopupMenu popup = new JPopupMenu(); + for (final String match : matches) { + final JMenuItem menuItem = new JMenuItem(match); + popup.add(menuItem); + menuItem.addActionListener(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + getChatInputEditor().appendText(match.substring(needle.length())); + popup.setVisible(false); + } + }); + } + + popup.show(SparkManager.getChatManager().getChatContainer(), + getChatInputEditor().getCaret().getMagicCaretPosition().x, + SparkManager.getChatManager().getChatContainer().getHeight() - 20); + } + } + + // I would normally use the command pattern, but + // have no real use when dealing with just a couple options. + @Override + public void actionPerformed(ActionEvent e) { + sendMessage(); + // Clear send field and disable send button + getChatInputEditor().clear(); + chatAreaButton.getButton().setEnabled(false); + } + + /** + * Creates and sends a message object from the text in the Send Field, using + * the default nickname specified in your Chat Preferences. + */ + protected abstract void sendMessage(); + + /** + * Creates a Message object from the given text and delegates to the room + * for sending. + * + * @param text the text to send. + */ + public abstract void sendMessage(String text); + + /** + * Sends the current message. + * + * @param messageBuilder - the message to send. + */ + public abstract void sendMessage(MessageBuilder messageBuilder); + + /** + * Returns the nickname of the current agent as specified in Chat Preferences. + */ + public Resourcepart getNickname() { + return pref.getNickname(); + } + + /** + * The main entry point when receiving any messages. This will either handle + * a message from a customer or delegate itself as an agent handler. + * + * @param message - the message received. + * @return message modified by {@link ChatManager#filterIncomingMessage} + */ + public Message insertMessage(Message message) { + Objects.requireNonNull(message); + // Fire Message + MessageBuilder messageBuilder = MessageBuilder.buildMessageFrom(message, message.getStanzaId()); + SparkManager.getChatManager().filterIncomingMessage(this, messageBuilder); + message = messageBuilder.build(); + SparkManager.getChatManager().fireGlobalMessageReceivedListeners(this, message); + + addToTranscript(message, true); + fireMessageReceived(message); + SparkManager.getWorkspace().getTranscriptPlugin().persistChatRoom(this); + return message; + } + + /** + * Add a ChatResponse to the current discussion chat area. + * + * @param message the message to add to the transcript list + * @param updateDate true if you wish the date label to be updated with the + * date and time the message was received. + */ + public void addToTranscript(Message message, boolean updateDate) { + // Create a message to persist. + final Map properties = new HashMap<>(1); + properties.put("date", new Date()); + Message newMessage = StanzaBuilder.buildMessageFrom(message, message.getStanzaId()) + .addExtension(new JivePropertiesExtension(properties)) + .build(); + transcript.add(newMessage); + // Add current date if this is the current agent + if (updateDate) { + Instant lastMessageDate = transcriptWindow.getLastUpdated(); + if (lastMessageDate != null) { + // Set new label date + notificationLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_ABOUT_IMAGE)); + notificationLabel.setText(Res.getString("message.last.message.received", SparkManager.DATE_SECOND_FORMATTER.format(Date.from(lastMessageDate)))); + } + } + scrollToBottom(); + } + + /** + * Scrolls the chat window to the bottom. + */ + public void scrollToBottom() { + if (mousePressed) { + return; + } + + int lengthOfChat = transcriptWindow.getDocument().getLength(); + transcriptWindow.setCaretPosition(lengthOfChat); + + try { + final JScrollBar scrollBar = textScroller.getVerticalScrollBar(); + EventQueue.invokeLater(() -> scrollBar.setValue(scrollBar.getMaximum())); + + } catch (Exception e) { + Log.error(e); + } + } + + /** + * Checks to see if the Send button should be enabled. + * + * @param e - the documentevent to react to. + */ + protected void checkForText(DocumentEvent e) { + final int length = e.getDocument().getLength(); + chatAreaButton.getButton().setEnabled(length > 0); + } + + /** + * Requests valid focus to the SendField. + */ + public void positionCursor() { + getChatInputEditor().setCaretPosition(getChatInputEditor().getCaretPosition()); + chatAreaButton.getChatInputArea().requestFocusInWindow(); + } + + /** + * Disable the chat room. This is called when a chat has been either + * transfered over or the customer has left the chat room. + */ + public abstract void leaveChatRoom(); + + /** + * Returns the SendField component. + * + * @return the SendField ChatSendField. + */ + public ChatInputEditor getChatInputEditor() { + return chatAreaButton.getChatInputArea(); + } + + /** + * Returns the chatWindow components. + * + * @return the ChatWindow component. + */ + public TranscriptWindow getTranscriptWindow() { + return transcriptWindow; + } + + /** + * Checks to see if enter was pressed and validates room. + * + * @param e the KeyEvent + */ + private void checkForEnter(KeyEvent e) { + final KeyStroke keyStroke = KeyStroke.getKeyStroke(e.getKeyCode(), e.getModifiers()); + if (!keyStroke.equals(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.SHIFT_DOWN_MASK)) + && e.getKeyChar() == KeyEvent.VK_ENTER) { + e.consume(); + sendMessage(); + getChatInputEditor().setText(""); + getChatInputEditor().setCaretPosition(0); + + SparkManager.getWorkspace().getTranscriptPlugin().persistChatRoom(this); + } else if (keyStroke.equals(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.SHIFT_DOWN_MASK))) { + final Document document = getChatInputEditor().getDocument(); + try { + document.insertString(getChatInputEditor().getCaretPosition(), "\n", null); + getChatInputEditor().requestFocusInWindow(); + chatAreaButton.getButton().setEnabled(true); + } catch (BadLocationException badLoc) { + Log.error("Error when checking for enter:", badLoc); + } + } + } + + /** + * Add a {@link MessageListener} to the current ChatRoom. + * + * @param listener - the MessageListener to add to the current ChatRoom. + */ + public void addMessageListener(MessageListener listener) { + messageListeners.addIfAbsent(listener); + } + + /** + * Remove the specified {@link MessageListener } from the current ChatRoom. + * + * @param listener - the MessageListener to remove from the current + * ChatRoom. + */ + public void removeMessageListener(MessageListener listener) { + messageListeners.remove(listener); + } + + /** + * Notifies all message listeners that + * + * @param message the message received. + */ + private void fireMessageReceived(Message message) { + for (MessageListener listener : messageListeners) { + try { + listener.messageReceived(this, message); + } catch (Exception e) { + Log.error("A MessageListener (" + listener + ") threw an exception while processing a 'message received' event for message: " + message, e); + } + } + } + + /** + * Notifies all MessageListener that a message has been sent. + * + * @param message the message sent. + */ + protected void fireMessageSent(Message message) { + for (MessageListener listener : messageListeners) { + try { + listener.messageSent(this, message); + } catch (Exception e) { + Log.error("A MessageListener (" + listener + ") threw an exception while processing a 'message sent' event for message: " + message, e); + } + } + } + + /** + * Returns a map of the current Chat Transcript which is a list of all + * ChatResponses and their order. You should retrieve this map to get any + * current chat transcript state. + * + * @return - the map of current chat responses. + */ + public List getTranscripts() { + return transcript; + } + + /** + * Disables the ChatRoom toolbar. + */ + public void disableToolbar() { + final int count = editorBarLeft.getComponentCount(); + for (int i = 0; i < count; i++) { + final Object o = editorBarLeft.getComponent(i); + if (o instanceof RolloverButton) { + final RolloverButton rb = (RolloverButton) o; + rb.setEnabled(false); + } + } + } + + /** + * Enable the ChatRoom toolbar. + */ + public void enableToolbar() { + final int count = editorBarLeft.getComponentCount(); + for (int i = 0; i < count; i++) { + final Object o = editorBarLeft.getComponent(i); + if (o instanceof RolloverButton) { + final RolloverButton rb = (RolloverButton) o; + rb.setEnabled(true); + } + } + } + + /** + * Checks to see if the Send Button should be enabled depending on the + * current update in SendField. + * + * @param event the DocumentEvent from the sendField. + */ + @Override + public void removeUpdate(DocumentEvent event) { + checkForText(event); + } + + /** + * Checks to see if the Send button should be enabled. + * + * @param docEvent the document event. + */ + @Override + public void changedUpdate(DocumentEvent docEvent) { + // Do nothing. + } + + /** + * Return the splitpane used in this chat room. + * + * @return the splitpane used in this chat room. + */ + public JSplitPane getSplitPane() { + return splitPane; + } + + /** + * Returns the ChatPanel that contains the ChatWindow and SendField. + * + * @return the ChatPanel. + */ + public JPanel getChatPanel() { + return chatPanel; + } + + /** + * Close the ChatRoom. + */ + public void closeChatRoom() { + fireClosingListeners(); + + setChatState(ChatState.gone); + + if (typingTimerTask != null) { + TaskEngine.getInstance().cancelScheduledTask(typingTimerTask); + typingTimerTask = null; + } + + getTranscriptWindow().removeContextMenuListener(this); + getTranscriptWindow().removeMouseListener(transcriptWindowMouseListener); + getChatInputEditor().removeKeyListener(chatEditorKeyListener); + this.removeAll(); + + textScroller.getViewport().remove(transcriptWindow); + + // Remove Connection Listener + SparkManager.getConnection().removeConnectionListener(this); + getTranscriptWindow().setTransferHandler(null); + getChatInputEditor().setTransferHandler(null); + + transferHandler = null; + + packetIDList.clear(); + messageListeners.clear(); + fileDropListeners.clear(); + getChatInputEditor().close(); + + getChatInputEditor().getActionMap().remove("closeTheRoom"); + chatAreaButton.getButton().removeActionListener(this); + bottomPanel.remove(chatAreaButton); + // TODO: We are seeing NPEs in the next line. Find out why _chatFrame is null. + _chatFrame.removeWindowToFrontListener(this); + } + + /** + * Get the Icon to be used in the tab holding this ChatRoom. + * + * @return - Icon to use + */ + public abstract Icon getTabIcon(); + + /** + * Get the XMPP address of this room. + * + * @return the XMPP address of this room + */ + public abstract EntityBareJid getBareJid(); + + public abstract EntityJid getJid(); + + /** + * Get the title to use in the tab holding this ChatRoom. + * + * @return - the title to use. + */ + public abstract String getTabTitle(); + + /** + * Returns the title of this room to use. The title will be used in the + * title bar of the ChatRoom. + * + * @return - the title of this ChatRoom. + */ + public abstract String getRoomTitle(); + + /** + * Returns the Message.Type specific to this chat room. + * GroupChat is Message.Type.groupchat Normal Chat is Message.TYPE.NORMAL + * + * @return the ChatRooms Message.TYPE + */ + public abstract Message.Type getChatType(); + + /** + * Returns whether or not this ChatRoom is active. Note: carrying a + * conversation rather than being disabled, as it would be transcript mode. + * + * @return true if the chat room is active. + */ + public abstract boolean isActive(); + + /** + * Returns the notification label. The notification label notifies the user + * of chat room activity, such as the date of the last message and typing + * notifications. + * + * @return the notification label. + */ + public JLabel getNotificationLabel() { + return notificationLabel; + } + + /** + * Adds a packetID to the packedIDList. The packetIDLlist keeps track of all + * messages coming into the chatroom. + * + * @param packetID the packetID to add. + */ + public void addPacketID(String packetID) { + packetIDList.add(packetID); + } + + /** + * Checks if the packetID has already been used. + * + * @param packetID the packetID to check for. + * @return true if the packetID already exists. + */ + public boolean packetIDExists(String packetID) { + return packetIDList.contains(packetID); + } + + /** + * Returns this instance of the chatroom. + * + * @return the current ChatRoom instance. + */ + public ChatRoom getChatRoom() { + return this; + } + + /** + * Returns the toolbar used on top of the chat room. + * + * @return the toolbar used on top of this chat room. + */ + public ChatToolBar getToolBar() { + return toolbar; + } + + protected void addToolbar() { + add(toolbar, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + } + + @Override + public void insertUpdate(DocumentEvent e) { + // Meant to be overridden + checkForText(e); + setChatState(ChatState.composing); + } + + /** + * Override to save the transcript in the preferred room style. + */ + public void saveTranscript() { + getTranscriptWindow().saveTranscript(getTabTitle() + ".html", getTranscripts(), null); + } + + /** + * Used for the top toolbar. + */ + public static class ChatToolBar extends JPanel { + + private final JPanel buttonPanel; + + /** + * Default Constructor. + */ + public ChatToolBar() { + buttonPanel = new JPanel(); + buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 2, 0)); + + // Set Layout + setLayout(new GridBagLayout()); + + buttonPanel.setOpaque(false); + add(buttonPanel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + setOpaque(false); + } + + /** + * Adds a new ChatRoomButton the CommandBar. + * + * @param button the button. + */ + public void addChatRoomButton(ChatRoomButton button) { + buttonPanel.add(button); + buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); + + // Make all JButtons the same size + Component[] comps = buttonPanel.getComponents(); + final int no = comps != null ? comps.length : 0; + + final List buttons = new ArrayList<>(); + for (int i = 0; i < no; i++) { + try { + Component component = comps[i]; + if (component instanceof JButton) { + buttons.add(component); + } + } catch (NullPointerException e) { + Log.error(e); + } + } + + GraphicUtils.makeSameSize(buttons.toArray(new Component[0])); + } + + /** + * Removes the ChatRoomButton from the CommandBar. + * + * @param button the button. + */ + public void removeChatRoomButton(ChatRoomButton button) { + buttonPanel.remove(button); + } + } + + /** + * Returns the number of unread messages in this ChatRoom. + * + * @return the number of unread messages. + */ + public int getUnreadMessageCount() { + return unreadMessageCount; + } + + /** + * Increases the number of unread messages by 1. + */ + public void increaseUnreadMessageCount() { + unreadMessageCount++; + } + + + /** + * Resets the number of unread messages. + */ + public void clearUnreadMessageCount() { + unreadMessageCount = 0; + } + + /** + * Returns the bottom panel used in the ChatRoom. + * + * @return the bottomPane; + */ + public JPanel getBottomPanel() { + return bottomPanel; + } + + /** + * Returns the Container which holds the ChatWindow. + * + * @return the Container. + */ + public JPanel getChatWindowPanel() { + return chatWindowPanel; + } + + /** + * Adds a new FileDropListener to allow for Drag and Drop + * notifications of objects onto the ChatWindow. + * + * @param listener the listener. + */ + public void addFileDropListener(FileDropListener listener) { + fileDropListeners.addIfAbsent(listener); + } + + /** + * Remove the FileDropListener from ChatRoom. + * + * @param listener the listener. + */ + public void removeFileDropListener(FileDropListener listener) { + fileDropListeners.remove(listener); + } + + /** + * Notify all users that a collection of files has been dropped onto the + * ChatRoom. + * + * @param files the files dropped. + */ + public void fireFileDropListeners(Collection files) { + for (FileDropListener listener : fileDropListeners) { + try { + listener.filesDropped(files, this); + } catch (Exception e) { + Log.error("A FileDropListener (" + listener + ") threw an exception while processing a 'files dropped' event.", e); + } + } + } + + /** + * Returns the panel which contains the toolbar items, such as spell + * checker. + * + * @return the panel which contains the lower toolbar items. + */ + public JPanel getEditorBar() { + return editorBarLeft; + } + + /** + * Returns the panel next to the editor bar
      + * for use with system buttons, like room controlling or toggle stay-on-top + * + * @return + */ + public JPanel getRoomControllerBar() { + return editorBarRight; + } + + /** + * Adds a ChatRoomClosingListener to this ChatRoom. A + * ChatRoomClosingListener is notified whenever this room is closing. + * + * @param listener the ChatRoomClosingListener. + */ + public void addClosingListener(ChatRoomClosingListener listener) { + closingListeners.addIfAbsent(listener); + } + + /** + * Removes a ChatRoomClosingListener from this ChatRoom. + * + * @param listener the ChatRoomClosingListener. + */ + public void removeClosingListener(ChatRoomClosingListener listener) { + closingListeners.remove(listener); + } + + /** + * Notifies all ChatRoomClosingListener that this ChatRoom is + * closing. + */ + private void fireClosingListeners() { + for (final ChatRoomClosingListener listener : closingListeners) + { + try { + listener.closing(); + } catch (Exception e) { + Log.error("A ChatRoomClosingListener (" + listener + ") threw an exception while processing a 'closing' event.", e); + } + } + closingListeners.clear(); + } + + /** + * Returns the ScrollPane that contains the TranscriptWindow. + * + * @return the TranscriptWindow ScrollPane. + */ + public JScrollPane getScrollPaneForTranscriptWindow() { + return textScroller; + } + + /** + * Return the "Send" button. + * + * @return the send button. + */ + public JButton getSendButton() { + return chatAreaButton.getButton(); + } + + /** + * Returns the VerticalSplitPane used in this ChatRoom. + * + * @return the VerticalSplitPane. + */ + public JSplitPane getVerticalSlipPane() { + return verticalSplit; + } + + @Override + public void focusGained(FocusEvent focusEvent) { + validate(); + invalidate(); + repaint(); + + if (focusEvent.getComponent().equals(getChatInputEditor())) { + setChatState(ChatState.active); + } + + } + + @Override + public void poppingUp(Object component, JPopupMenu popup) { + Action saveAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + saveTranscript(); + } + }; + saveAction.putValue(Action.NAME, Res.getString("action.save")); + saveAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SAVE_AS_16x16)); + + popup.add(saveAction); + } + + @Override + public void poppingDown(JPopupMenu popup) { + + } + + @Override + public boolean handleDefaultAction(MouseEvent e) { + return false; + } + + @Override + public void focusLost(FocusEvent focusEvent) { + if (focusEvent.getComponent().equals(getChatInputEditor())) { + setChatState(ChatState.inactive); + } + } + + /** + * Implementation of this method should return the last time this chat room + * sent or recieved a message. + * + * @return the last time (in system milliseconds) that the room last + * recieved a message. + */ + public abstract long getLastActivity(); + + @Override + public void connectionClosed() { + } + + @Override + public void connectionClosedOnError(Exception e) { + } + + @Override + public void updateStatus(boolean active) { + _alwaysOnTopItem.setSelected(active); + } + + @Override + public void registeredToFrame(ChatFrame chatframe) { + this._chatFrame = chatframe; + _chatFrame.addWindowToFronListener(this); + } + + protected JPanel getEditorWrapperBar() { + return editorWrapperBar; + } + + protected JPanel getEditorBarRight() { + return editorBarRight; + } + + protected JPanel getEditorBarLeft() { + return editorBarLeft; + } + + protected JScrollPane getTextScroller() { + return textScroller; + } + + protected Insets getChatPanelInsets() { + return new Insets(0, 5, 0, 5); + } + + protected Insets getChatAreaInsets() { + return new Insets(0, 5, 5, 5); + } + + protected Insets getEditorWrapperInsets() { + return new Insets(0, 5, 0, 5); + } + + public void addChatRoomComponent(JComponent component) { + editorBarLeft.add(component); + } + + public void addChatRoomButton(ChatRoomButton button) { + addChatRoomButton(button, false); + } + + public void addChatRoomButton(ChatRoomButton button, boolean forceRepaint) { + toolbar.addChatRoomButton(button); + if (forceRepaint) { + toolbar.invalidate(); + toolbar.repaint(); + } + } + + public void showToolbar() { + toolbar.setVisible(true); + } + + public void hideToolbar() { + toolbar.setVisible(false); + } + + public void addEditorComponent(JComponent component) { + editorBarLeft.add(component); + } + + public void removeEditorComponent(JComponent component) { + editorBarLeft.remove(component); + } + + public void addControllerButton(RolloverButton button) { + editorBarRight.add(button, 0); + } +} diff --git a/src/java/org/jivesoftware/spark/ui/ChatRoomButton.java b/core/src/main/java/org/jivesoftware/spark/ui/ChatRoomButton.java similarity index 97% rename from src/java/org/jivesoftware/spark/ui/ChatRoomButton.java rename to core/src/main/java/org/jivesoftware/spark/ui/ChatRoomButton.java index ba35765d1..c07bb556a 100644 --- a/src/java/org/jivesoftware/spark/ui/ChatRoomButton.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/ChatRoomButton.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/spark/ui/ChatRoomClosingListener.java b/core/src/main/java/org/jivesoftware/spark/ui/ChatRoomClosingListener.java similarity index 94% rename from src/java/org/jivesoftware/spark/ui/ChatRoomClosingListener.java rename to core/src/main/java/org/jivesoftware/spark/ui/ChatRoomClosingListener.java index 2bd0e8cfd..96614b281 100644 --- a/src/java/org/jivesoftware/spark/ui/ChatRoomClosingListener.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/ChatRoomClosingListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ChatRoomListener.java b/core/src/main/java/org/jivesoftware/spark/ui/ChatRoomListener.java new file mode 100644 index 000000000..c7e0cc339 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/ChatRoomListener.java @@ -0,0 +1,95 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +/** + * The ChatRoomListener interface is one of the interfaces extension + * writers use to add functionality to Spark. + *

      + * Chat Room events let you track when a room is opened, closed, joined, left and activated. + *

      + * The methods in this class are empty. This class exists as + * a convenience for creating listener objects. + * In general, you implement this interface in order to listen + * for ChatRoom activity, such as a ChatRoom opening, closing, or being + * activated. + *

      + * This abstract class defines null methods for them + * all, so you can only have to define methods for events you care about.) + *

      + * Create a listener object using the interface and then register it with + * the ChatManager's addChatRoomListener method. + * + * @author Derek DeMoro + */ +public interface ChatRoomListener { + + /** + * Invoked by ChatRooms when a new ChatRoom has been opened. + * + * @param room - the ChatRoom that has been opened. + * @see ChatContainer + */ + default void chatRoomOpened(ChatRoom room) { + } + + /** + * Invoked by ChatRooms when a ChatRoom has been left, but not + * closed. + * + * @param room - the ChatRoom that has been left. + * @see ChatContainer + */ + default void chatRoomLeft(ChatRoom room) { + } + + /** + * Invoke by ChatRooms when a ChatRoom has been closed. + * + * @param room - the ChatRoom that has been closed. + */ + default void chatRoomClosed(ChatRoom room) { + } + + /** + * Invoked by ChatRooms when a ChatRoom has been activated. + * i.e. it has already been opened, but was deactivated when the user + * selected a new chat room, but now has selected the old one. + * + * @param room - the ChatRoom that has been selected. + */ + default void chatRoomActivated(ChatRoom room) { + } + + /** + * Invoked by ChatRooms when a person has joined a chat room. + * + * @param room - the chat room the person has joined + * @param userid - the userid of the person who has joined + */ + default void userHasJoined(ChatRoom room, String userid) { + } + + /** + * Invoked by ChatRooms when a person has left a chat room. + * + * @param room - the chat room the person has left + * @param userid - the userid of the person who has left + */ + default void userHasLeft(ChatRoom room, String userid) { + } + +} diff --git a/src/java/org/jivesoftware/spark/ui/ChatRoomNotFoundException.java b/core/src/main/java/org/jivesoftware/spark/ui/ChatRoomNotFoundException.java similarity index 95% rename from src/java/org/jivesoftware/spark/ui/ChatRoomNotFoundException.java rename to core/src/main/java/org/jivesoftware/spark/ui/ChatRoomNotFoundException.java index 681eb3c38..bee56dc61 100644 --- a/src/java/org/jivesoftware/spark/ui/ChatRoomNotFoundException.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/ChatRoomNotFoundException.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/spark/ui/ChatRoomPlugin.java b/core/src/main/java/org/jivesoftware/spark/ui/ChatRoomPlugin.java similarity index 97% rename from src/java/org/jivesoftware/spark/ui/ChatRoomPlugin.java rename to core/src/main/java/org/jivesoftware/spark/ui/ChatRoomPlugin.java index dd1c7f292..037e12774 100644 --- a/src/java/org/jivesoftware/spark/ui/ChatRoomPlugin.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/ChatRoomPlugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ChatRoomTransferHandler.java b/core/src/main/java/org/jivesoftware/spark/ui/ChatRoomTransferHandler.java new file mode 100644 index 000000000..fa77d3659 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/ChatRoomTransferHandler.java @@ -0,0 +1,133 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.File; +import java.io.IOException; +import java.util.Collection; + +import javax.swing.JComponent; +import javax.swing.TransferHandler; + +import org.jivesoftware.spark.util.log.Log; + +/** + * Handler for drag and dropping of files unto a ChatWindow. + */ +public class ChatRoomTransferHandler extends TransferHandler { + private static final long serialVersionUID = 6941570710627039031L; + private final ChatRoom chatRoom; + + private static final DataFlavor[] flavors = {DataFlavor.javaFileListFlavor, DataFlavor.stringFlavor}; + + public ChatRoomTransferHandler(ChatRoom chatRoom) { + this.chatRoom = chatRoom; + } + + @Override + public int getSourceActions(JComponent c) { + return TransferHandler.COPY_OR_MOVE; + } + + + @Override + public boolean canImport(JComponent comp, DataFlavor[] flavor) { + for (DataFlavor dataFlavor : flavor) { + for (DataFlavor value : flavors) { + if (dataFlavor.equals(value)) { + return true; + } + } + } + return false; + } + + @Override + public Transferable createTransferable(JComponent comp) { + if (comp instanceof TranscriptWindow) { + return new TranscriptWindowTransferable((TranscriptWindow) comp); + } + + return null; + } + + @Override + public boolean importData(JComponent comp, Transferable t) { + if (t.isDataFlavorSupported(flavors[0])) { + try { + Object o = t.getTransferData(flavors[0]); + if (o instanceof Collection) { + Collection files = (Collection)o; + + // Otherwise fire files dropped event. + chatRoom.fireFileDropListeners(files); + return true; + } + } + catch (UnsupportedFlavorException | IOException e) { + Log.error(e); + } + } + else if (t.isDataFlavorSupported(flavors[1])) { + try { + Object o = t.getTransferData(flavors[1]); + if (o instanceof String) { + // Otherwise fire files dropped event. + chatRoom.getChatInputEditor().insertText((String)o); + return true; + } + } + catch (Exception e) { + Log.error(e); + } + + } + return false; + } + + public static class TranscriptWindowTransferable implements Transferable { + + private final TranscriptWindow item; + + public TranscriptWindowTransferable(TranscriptWindow item) { + this.item = item; + } + + // Returns supported flavors + @Override + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[]{DataFlavor.stringFlavor}; + } + + // Returns true if flavor is supported + @Override + public boolean isDataFlavorSupported(DataFlavor flavor) { + return DataFlavor.stringFlavor.equals(flavor); + } + + // Returns Selected Text + @Override + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { + if (!DataFlavor.stringFlavor.equals(flavor)) { + throw new UnsupportedFlavorException(flavor); + } + return item.getSelectedText(); + } + } +} diff --git a/src/java/org/jivesoftware/spark/ui/ChatStatePanel.java b/core/src/main/java/org/jivesoftware/spark/ui/ChatStatePanel.java similarity index 88% rename from src/java/org/jivesoftware/spark/ui/ChatStatePanel.java rename to core/src/main/java/org/jivesoftware/spark/ui/ChatStatePanel.java index 4627d4d43..47f3003e2 100644 --- a/src/java/org/jivesoftware/spark/ui/ChatStatePanel.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/ChatStatePanel.java @@ -12,9 +12,9 @@ public class ChatStatePanel extends JPanel{ - public ChatStatePanel(ChatState state, String nickname) { + public ChatStatePanel(ChatState state, CharSequence nickname) { setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1)); - JLabel label = new JLabel( Res.getString( state.name(), nickname ) ); + JLabel label = new JLabel( Res.getString( state.name(), nickname.toString() ) ); label.setFont(new Font("Courier New", Font.PLAIN, 9)); label.setForeground(Color.gray); label.setHorizontalTextPosition(JLabel.LEFT); diff --git a/src/java/org/jivesoftware/spark/ui/CommandPanel.java b/core/src/main/java/org/jivesoftware/spark/ui/CommandPanel.java similarity index 97% rename from src/java/org/jivesoftware/spark/ui/CommandPanel.java rename to core/src/main/java/org/jivesoftware/spark/ui/CommandPanel.java index d07f4a8c1..9aa7c675c 100644 --- a/src/java/org/jivesoftware/spark/ui/CommandPanel.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/CommandPanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,7 +22,6 @@ import org.jivesoftware.Spark; /** - * */ public class CommandPanel extends JPanel { diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ContactGroup.java b/core/src/main/java/org/jivesoftware/spark/ui/ContactGroup.java new file mode 100644 index 000000000..7053b9830 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/ContactGroup.java @@ -0,0 +1,1077 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.Workspace; +import org.jivesoftware.spark.component.VerticalFlowLayout; +import org.jivesoftware.spark.component.panes.CollapsiblePane; +import org.jivesoftware.spark.component.renderer.JContactItemRenderer; +import org.jivesoftware.spark.util.*; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.BareJid; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import static org.jivesoftware.spark.ui.ContactItem.CONTACT_ITEM_COMPARATOR; + +/** + * Container representing a RosterGroup within the Contact List. + */ +public class ContactGroup extends CollapsiblePane implements MouseListener { + private static final long serialVersionUID = 6578057848913010799L; + private final List contactItems = new ArrayList<>(); + private final List contactGroups = new ArrayList<>(); + private final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList<>(); + private final List offlineContacts = new ArrayList<>(); + + private final int fontSize; + + private String groupName; + private final DefaultListModel model; + private final JList contactItemList; + private boolean sharedGroup; + private final JPanel listPanel; + + // Used to display no contacts in list. + private final ContactItem noContacts = UIComponentRegistry.createContactItem( + Res.getString("group.empty"), null, null); + + private final ListMotionListener motionListener = new ListMotionListener(); + + private boolean canShowPopup; + + private boolean mouseDragged = false; + + private final LocalPreferences preferences; + + private ContactList contactList = Workspace.getInstance().getContactList(); + + private DisplayWindowTask timerTask = null; + + /** + * Create a new ContactGroup. + * + * @param groupName the name of the new ContactGroup. + */ + public ContactGroup(String groupName) { + // Initialize Model and UI + model = new DefaultListModel<>(); + contactItemList = new JList<>(model); + + preferences = SettingsManager.getLocalPreferences(); + + setTitle(getGroupTitle(groupName)); + + fontSize = preferences.getContactListFontSize(); + + // Use JPanel Renderer + contactItemList.setCellRenderer(new JContactItemRenderer()); + + this.groupName = groupName; + + listPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); + listPanel.add(contactItemList, listPanel); + this.setContentPane(listPanel); + + if (!isOfflineGroup()) { + contactItemList.setDragEnabled(true); + contactItemList.setTransferHandler(new ContactGroupTransferHandler()); + } + + // Allow for mouse events to take place on the title bar + getTitlePane().addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + checkPopup(e); + + } + + @Override + public void mouseReleased(MouseEvent e) { + checkPopup(e); + } + + @Override + public void mouseClicked(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON1) { + contactList = Workspace.getInstance().getContactList(); + contactList.saveState(); + } + } + + public void checkPopup(MouseEvent e) { + if (e.isPopupTrigger()) { + e.consume(); + fireContactGroupPopupEvent(e); + } + } + }); + + // Items should have selection listener + contactItemList.addMouseListener(this); + + contactItemList.addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent keyEvent) { + + } + + @Override + public void keyPressed(KeyEvent keyEvent) { + if (keyEvent.getKeyChar() == KeyEvent.VK_ENTER) { + ContactItem item = contactItemList.getSelectedValue(); + fireContactItemDoubleClicked(item); + } + + ContactList.activeKeyEvent = keyEvent; + } + + @Override + public void keyReleased(KeyEvent keyEvent) { + ContactList.activeKeyEvent = null; + } + }); + + noContacts.getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, fontSize)); + noContacts.getNicknameLabel().setForeground(Color.GRAY); + model.addElement(noContacts); + + // Add Popup Window + addPopupWindow(); + + + } + + /** + * Adds a new offline contact. + * + * @param alias the alias of the offline contact. + * @param nickname the nickname of the offline contact. + * @param jid the jid of the offline contact. + * @param status the current status of the offline contact. + */ + public void addOfflineContactItem(final String alias, final String nickname, final BareJid jid, final String status) { + if (EventQueue.isDispatchThread()) { + // Build new ContactItem + final ContactItem offlineItem = UIComponentRegistry.createContactItem(alias, nickname, jid); + offlineItem.setGroupName(getGroupName()); + + final Presence offlinePresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .build(); + offlineItem.setPresence(offlinePresence); + + // set offline icon + offlineItem.setIcon(PresenceManager.getIconFromPresence(offlinePresence)); + + // Set status if applicable. + if (ModelUtil.hasLength(status)) { + offlineItem.setStatusText(status); + } + // Add to offline contacts. + offlineContacts.add(offlineItem); + + insertOfflineContactItem(offlineItem); + } else { + try { + // invokeAndWait, because the contacts must be added before they can moved to offline group + EventQueue.invokeAndWait(() -> { + // Build new ContactItem + final ContactItem offlineItem = UIComponentRegistry.createContactItem(alias, nickname, jid); + offlineItem.setGroupName(getGroupName()); + + final Presence offlinePresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .build(); + offlineItem.setPresence(offlinePresence); + + // set offline icon + offlineItem.setIcon(PresenceManager.getIconFromPresence(offlinePresence)); + + // Set status if applicable. + if (ModelUtil.hasLength(status)) { + offlineItem.setStatusText(status); + } + // Add to offline contacts. + offlineContacts.add(offlineItem); + + insertOfflineContactItem(offlineItem); + }); + } catch (Exception ex) { + Log.error(ex); + } + } + } + + /** + * Inserts a new offline ContactItem into the ui model. + * + * @param offlineItem the ContactItem to add. + */ + public void insertOfflineContactItem(ContactItem offlineItem) { + if (model.contains(offlineItem)) { + return; + } + + if (!preferences.isOfflineGroupVisible()) { + offlineContacts.sort(CONTACT_ITEM_COMPARATOR); + int index = offlineContacts.indexOf(offlineItem); + + int totalListSize = contactItems.size(); + int newPos = totalListSize + index; + + if (newPos > model.size()) { + newPos = model.size(); + } + + model.insertElementAt(offlineItem, newPos); + + if (model.contains(noContacts)) { + model.removeElement(noContacts); + } + } + } + + /** + * Removes an offline ContactItem from the Offline contact + * model and ui. + * + * @param item the offline contact item to remove. + */ + public void removeOfflineContactItem(ContactItem item) { + offlineContacts.remove(item); + //removeContactItem(item); + } + + /** + * Removes an offline ContactItem from the offline contact model and ui. + * + * @param jid the offline contact item to remove. + */ + public void removeOfflineContactItem(BareJid jid) { + final List items = new ArrayList<>(offlineContacts); + for (ContactItem item : items) { + if (item.getJid().equals(jid)) { + removeOfflineContactItem(item); + } + } + } + + /** + * Toggles the visibility of Offline Contacts. + * + * @param show true if offline contacts should be shown, otherwise false. + */ + public void toggleOfflineVisibility(boolean show) { + final List items = new ArrayList<>(offlineContacts); + for (ContactItem item : items) { + if (show) { + insertOfflineContactItem(item); + } else { + model.removeElement(item); + } + } + if (model.getSize() == 0) { + model.addElement(noContacts); + } + } + + + /** + * Adds a ContactItem to the ContactGroup. + * + * @param item the ContactItem. + */ + public void addContactItem(ContactItem item) { + // Remove from offline group if it exists + removeOfflineContactItem(item.getJid()); + + if (model.contains(noContacts)) { + model.remove(0); + } + + if (Res.getString("group.offline").equals(groupName)) { + setOfflineGroupNameFont(item); + } + + item.setGroupName(getGroupName()); + contactItems.add(item); + + List tempItems = getContactItems(); + int index = tempItems.indexOf(item); + + + Object[] objs = contactItemList.getSelectedValuesList().toArray(); + + model.insertElementAt(item, index); + + int[] intList = new int[objs.length]; + for (int i = 0; i < objs.length; i++) { + ContactItem contact = (ContactItem) objs[i]; + intList[i] = model.indexOf(contact); + } + + if (intList.length > 0) { + contactItemList.setSelectedIndices(intList); + } + + fireContactItemAdded(item); + } + + protected void setOfflineGroupNameFont(ContactItem item) { + item.getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, item.getFontSize())); + item.getNicknameLabel().setForeground(Color.GRAY); + } + + /** + * Call whenever the UI needs to be updated. + */ + public void fireContactGroupUpdated() { + contactItemList.validate(); + contactItemList.repaint(); + updateTitle(); + } + + /** + * Adds a sub group to this Contact group. + * + * @param contactGroup + * that should be the new subgroup + */ + public void addContactGroup(ContactGroup contactGroup) { + final JPanel panel = new JPanel(new GridBagLayout()); + panel.add(contactGroup, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2, 15, 0, 0), 0, 0)); + panel.setBackground(Color.white); + contactGroup.setSubPane(true); + + // contactGroup.setStyle(CollapsiblePane.TREE_STYLE); + contactGroups.add(contactGroup); + contactGroups.sort(ContactList.GROUP_COMPARATOR); + listPanel.add(panel, contactGroups.indexOf(contactGroup)); + } + + /** + * Removes a child ContactGroup. + * + * @param contactGroup the contact group to remove. + */ + public void removeContactGroup(ContactGroup contactGroup) { + Component[] comps = listPanel.getComponents(); + for (Component comp : comps) { + if (comp instanceof JPanel) { + JPanel panel = (JPanel) comp; + ContactGroup group = (ContactGroup) panel.getComponent(0); + if (group == contactGroup) { + listPanel.remove(panel); + break; + } + } + } + + + contactGroups.remove(contactGroup); + } + + public void setPanelBackground(Color color) { + Component[] comps = listPanel.getComponents(); + for (Component comp : comps) { + if (comp instanceof JPanel) { + JPanel panel = (JPanel) comp; + panel.setBackground(color); + } + } + + } + + /** + * Returns a ContactGroup based on it's name. + * + * @param groupName the name of the group. + * @return the ContactGroup. + */ + public ContactGroup getContactGroup(String groupName) { + for (ContactGroup group : new ArrayList<>(contactGroups)) { + if (group.getGroupName().equals(groupName)) { + return group; + } + } + + return null; + } + + /** + * Removes a ContactItem. + * + * @param item the ContactItem to remove. + */ + public void removeContactItem(ContactItem item) { + contactItems.remove(item); + if (contactItems.isEmpty()) { + removeContactGroup(this); + } + + model.removeElement(item); + updateTitle(); + + fireContactItemRemoved(item); + } + + /** + * Returns a ContactItem by the displayed name the user has been assigned. + * + * @param displayName the displayed name of the user. + * @return the ContactItem. + */ + public ContactItem getContactItemByDisplayName(CharSequence displayName) { + for (ContactItem item : new ArrayList<>(contactItems)) { + if (item.getDisplayName().equals(displayName.toString())) { + return item; + } + } + return null; + } + + /** + * Returns a ContactItem from offlineContacts by the displayed name the user has been assigned. + * + * @param displayName the displayed name of the user. + * @return the ContactItem. + */ + public ContactItem getOfflineContactItemByDisplayName(String displayName) { + for (ContactItem item : new ArrayList<>(offlineContacts)) { + if (item.getDisplayName().equals(displayName)) { + return item; + } + } + return null; + } + + /** + * Returns a ContactItem by the displayed name the user has been assigned. + * + * @param displayName the displayed name of the user. + * @param searchInOffline should we search ContactItem in offline contacts + * @return the ContactItem. + */ + public ContactItem getContactItemByDisplayName(String displayName, boolean searchInOffline) { + if (searchInOffline) { + ContactItem item = getContactItemByDisplayName(displayName); + if (item == null) { + item = getOfflineContactItemByDisplayName(displayName); + } + return item; + } + return getContactItemByDisplayName(displayName); + } + + /** + * Returns a ContactItem by the users bare bareJID. + * + * @param bareJID the bareJID of the user. + * @return the ContactItem. + */ + public ContactItem getContactItemByJID(BareJid bareJID) { + for (ContactItem item : new ArrayList<>(contactItems)) { + if (item != null && item.getJid().equals(bareJID)) { + return item; + } + } + return null; + } + + /** + * Returns a ContactItem from offlineContacts by the users bare bareJID. + * + * @param bareJID the bareJID of the user. + * @return the ContactItem. + */ + public ContactItem getOfflineContactItemByJID(BareJid bareJID) { + for (ContactItem item : new ArrayList<>(offlineContacts)) { + if (item.getJid().equals(bareJID)) { + return item; + } + } + return null; + } + + /** + * Returns a ContactItem by the users bare bareJID. + * + * @param bareJID the bareJID of the user. + * @param searchInOffline should we search ContactItem in offline contacts + * @return the ContactItem. + */ + public ContactItem getContactItemByJID(BareJid bareJID, boolean searchInOffline) { + if (searchInOffline) { + ContactItem item = getContactItemByJID(bareJID); + if (item == null) { + item = getOfflineContactItemByJID(bareJID); + } + return item; + } + return getContactItemByJID(bareJID); + } + + /** + * Returns all ContactItems in the ContactGroup. + * + * @return all ContactItems. + */ + public List getContactItems() { + final List list = new ArrayList<>(contactItems); + list.sort(CONTACT_ITEM_COMPARATOR); + return list; + } + + /** + * Returns the name of the ContactGroup. + * + * @return the name of the ContactGroup. + */ + public String getGroupName() { + return groupName; + } + + + @Override + public void mouseClicked(MouseEvent e) { + ContactItem item = contactItemList.getSelectedValue(); + if (item == null) { + return; + } + + if (e.getClickCount() == 2) { + fireContactItemDoubleClicked(item); + } else if (e.getClickCount() == 1) { + fireContactItemClicked(item); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + int loc = contactItemList.locationToIndex(e.getPoint()); + + Object o = model.getElementAt(loc); + if (!(o instanceof ContactItem)) { + return; + } + + contactItemList.setCursor(GraphicUtils.HAND_CURSOR); + } + + @Override + public void mouseExited(MouseEvent e) { + Object o; + try { + int loc = contactItemList.locationToIndex(e.getPoint()); + if (loc == -1) { + return; + } + + o = model.getElementAt(loc); + if (!(o instanceof ContactItem)) { + UIComponentRegistry.getContactInfoWindow().dispose(); + return; + } + } catch (Exception e1) { + Log.error(e1); + return; + } + + contactItemList.setCursor(GraphicUtils.DEFAULT_CURSOR); + + } + + @Override + public void mousePressed(MouseEvent e) { + checkPopup(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + checkPopup(e); + } + + private void checkPopup(MouseEvent e) { + if (e.isPopupTrigger()) { + // Otherwise, handle single selection + int index = contactItemList.locationToIndex(e.getPoint()); + if (index != -1) { + int[] indexes = contactItemList.getSelectedIndices(); + boolean selected = false; + for (int o : indexes) { + if (index == o) { + selected = true; + break; + } + } + + if (!selected) { + contactItemList.setSelectedIndex(index); + fireContactItemClicked(contactItemList.getSelectedValue()); + } + } + + + final Collection selectedItems = SparkManager.getChatManager().getSelectedContactItems(); + if (selectedItems.size() > 1) { + firePopupEvent(e, selectedItems); + } else if (selectedItems.size() == 1) { + final ContactItem contactItem = selectedItems.iterator().next(); + firePopupEvent(e, contactItem); + } + } + } + + /** + * Add a ContactGroupListener. + * + * @param listener the ContactGroupListener. + */ + public void addContactGroupListener(ContactGroupListener listener) { + listeners.addIfAbsent(listener); + } + + /** + * Removes a ContactGroupListener. + * + * @param listener the ContactGroupListener. + */ + public void removeContactGroupListener(ContactGroupListener listener) { + listeners.remove(listener); + } + + private void fireContactItemClicked(ContactItem item) { + for (final ContactGroupListener listener : listeners) { + try { + listener.contactItemClicked(item); + } catch (Exception e) { + Log.error("A ContactGroupListener (" + listener + ") threw an exception while processing a 'contactItemClicked' event for item: " + item, e); + } + } + } + + private void fireContactItemDoubleClicked(ContactItem item) { + if(item.getJid().equals("dummy@dummy.example")){ + return; + } + for (final ContactGroupListener listener : listeners) { + try { + listener.contactItemDoubleClicked(item); + } catch (Exception e) { + Log.error("A ContactGroupListener (" + listener + ") threw an exception while processing a 'contactItemDoubleClicked' event for item: " + item, e); + } + } + } + + private void firePopupEvent(MouseEvent event, ContactItem item) { + for (final ContactGroupListener listener : listeners) { + try { + listener.showPopup(event, item); + } catch (Exception e) { + Log.error("A ContactGroupListener (" + listener + ") threw an exception while processing a 'showPopup' event for item: " + item + ", event: " + event, e); + } + } + } + + private void firePopupEvent(MouseEvent event, Collection items) { + for (final ContactGroupListener listener : listeners) { + try { + listener.showPopup(event, items); + } catch (Exception e) { + Log.error("A ContactGroupListener (" + listener + ") threw an exception while processing a 'showPopup' event for items: " + items + ", event: " + event, e); + } + } + } + + private void fireContactGroupPopupEvent(MouseEvent event) { + for (final ContactGroupListener listener : listeners) { + try { + listener.contactGroupPopup(event, this); + } catch (Exception e) { + Log.error("A ContactGroupListener (" + listener + ") threw an exception while processing a 'contactGroupPopup' event: " + event, e); + } + } + } + + private void fireContactItemAdded(ContactItem item) { + for (final ContactGroupListener listener : listeners) { + try { + listener.contactItemAdded(item); + } catch (Exception e) { + Log.error("A ContactGroupListener (" + listener + ") threw an exception while processing a 'contactItemAdded' event for item: " + item, e); + } + } + } + + private void fireContactItemRemoved(ContactItem item) { + for (final ContactGroupListener listener : listeners) { + try { + listener.contactItemRemoved(item); + } catch (Exception e) { + Log.error("A ContactGroupListener (" + listener + ") threw an exception while processing a 'contactItemRemoved' event for item: " + item, e); + } + } + } + + private void updateTitle() { + if (Res.getString("group.offline").equals(groupName)) { + setTitle(Res.getString("group.offline")); + return; + } + + int count = 0; + for (ContactItem it : getContactItems()) { + if (it.isAvailable()) { + count++; + } + } + + setTitle(getGroupTitle(groupName) + " (" + count + " " + Res.getString("online") + ")"); + + + if (model.getSize() == 0) { + model.addElement(noContacts); + } + } + + /** + * Returns the containing JList of the ContactGroup. + * + * @return the JList. + */ + public JList getList() { + return contactItemList; + } + + /** + * Clears all selections within this group. + */ + public void clearSelection() { + contactItemList.clearSelection(); + } + + public void removeAllContacts() { + // Remove all users from online group. + for (ContactItem item : getContactItems()) { + removeContactItem(item); + } + + // Remove all users from offline group. + for (ContactItem item : getOfflineContacts()) { + removeOfflineContactItem(item); + } + } + + /** + * Returns true if the ContactGroup contains available users. + * + * @return true if the ContactGroup contains available users. + */ + public boolean hasAvailableContacts() { + for (ContactGroup group : contactGroups) { + if (group.hasAvailableContacts()) { + return true; + } + } + + for (ContactItem item : getContactItems()) { + if (item.getPresence() != null) { + return true; + } + } + return false; + } + + public Collection getOfflineContacts() { + final List list = new ArrayList<>(offlineContacts); + list.sort(CONTACT_ITEM_COMPARATOR); + return list; + } + + /** + * Returns true if this ContactGroup is the Offline Group. + * + * @return true if OfflineGroup. + */ + public boolean isOfflineGroup() { + return Res.getString("group.offline").equals(getGroupName()); + } + + /** + * Returns true if this ContactGroup is the Unfiled Group. + * + * @return true if UnfiledGroup. + */ + public boolean isUnfiledGroup() { + //TODO: Don't identify the unfiled group by name, because the user + //could have a custom group of that name. + + return Res.getString("unfiled").equals(getGroupName()); + } + + @Override + public String toString() { + return getGroupName(); + } + + /** + * Returns true if ContactGroup is a Shared Group. + * + * @return true if Shared Group. + */ + public boolean isSharedGroup() { + return sharedGroup; + } + + /** + * Set to true if this ContactGroup is a shared Group. + * + * @param sharedGroup true if shared group. + */ + protected void setSharedGroup(boolean sharedGroup) { + this.sharedGroup = sharedGroup; + if (sharedGroup) { + setToolTipText(Res.getString("message.is.shared.group", getGroupName())); + } + } + + /** + * Returns all Selected Contacts within the ContactGroup. + * + * @return all selected ContactItems. + */ + public List getSelectedContacts() { + final List items = new ArrayList<>(); + Object[] selections = contactItemList.getSelectedValuesList().toArray(); + for (Object selection : selections) { + try { + ContactItem item = (ContactItem) selection; + items.add(item); + } catch (NullPointerException e) { + // TODO: Evaluate if we should do something here. + } + } + return items; + } + + public JPanel getContainerPanel() { + return listPanel; + } + + public Collection getContactGroups() { + return contactGroups; + } + + /** + * Lets make sure that the panel doesn't stretch past the + * scrollpane view pane. + * + * @return the preferred dimension + */ + @Override + public Dimension getPreferredSize() { + final Dimension size = super.getPreferredSize(); + size.width = 0; + return size; + } + + /** + * Sets the name of group. + * + * @param groupName the contact group name. + */ + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + /** + * Returns the "pretty" title of the ContactGroup. + * + * @param title the title. + * @return the new title. + */ + public String getGroupTitle(String title) { + int lastIndex = title.lastIndexOf("::"); + if (lastIndex != -1) { + title = title.substring(lastIndex + 2); + } + + return title; + } + + /** + * Returns true if the group is nested. + * + * @param groupName the name of the group. + * @return true if the group is nested. + */ + public boolean isSubGroup(String groupName) { + return groupName.contains("::"); + } + + /** + * Returns true if this group is nested. + * + * @return true if nested. + */ + public boolean isSubGroup() { + return isSubGroup(getGroupName()); + } + + /** + * Returns the underlying container for the JList. + * + * @return the underlying container of the JList. + */ + public JPanel getListPanel() { + return listPanel; + } + + /** + * Adds an internal popup listesner. + */ + private void addPopupWindow() { + contactItemList.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent mouseEvent) { + canShowPopup = true; + timerTask = new DisplayWindowTask(mouseEvent); + TaskEngine.getInstance().schedule(timerTask, 500, 1000); + } + + @Override + public void mouseExited(MouseEvent mouseEvent) { + if (timerTask != null) { + TaskEngine.getInstance().cancelScheduledTask(timerTask); + } + canShowPopup = false; + UIComponentRegistry.getContactInfoWindow().dispose(); + } + }); + + + contactItemList.addMouseMotionListener(motionListener); + } + + private class DisplayWindowTask extends SwingTimerTask { + private MouseEvent event; + private boolean newPopupShown = false; + + public DisplayWindowTask(MouseEvent e) { + event = e; + } + + @Override + public void doRun() { + if (canShowPopup) { + if (!newPopupShown && !mouseDragged) { + displayWindow(event); + newPopupShown = true; + } + } + } + + public void setEvent(MouseEvent event) { + this.event = event; + } + + public void setNewPopupShown(boolean popupChanged) { + this.newPopupShown = popupChanged; + } + + public boolean isNewPopupShown() { + return newPopupShown; + } + } + + private class ListMotionListener extends MouseMotionAdapter { + + @Override + public void mouseMoved(MouseEvent e) { + if (!canShowPopup) { + return; + } + + if (e == null) { + return; + } + timerTask.setEvent(e); + if (needToChangePopup(e) && timerTask.isNewPopupShown()) { + UIComponentRegistry.getContactInfoWindow().dispose(); + timerTask.setNewPopupShown(false); + } + mouseDragged = false; + } + + @Override + public void mouseDragged(MouseEvent e) { + if (timerTask.isNewPopupShown()) { + UIComponentRegistry.getContactInfoWindow().dispose(); + } + mouseDragged = true; + } + } + + + /** + * Displays the ContactInfoWindow. + * + * @param e the mouseEvent that triggered this event. + */ + private void displayWindow(MouseEvent e) { + if (preferences.areVCardsVisible()) { + final ContactGroup parent = this; + final SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + UIComponentRegistry.getContactInfoWindow().display(parent, e); + return null; + } + }; + worker.start(); + + } + } + + private boolean needToChangePopup(MouseEvent e) { + ContactInfoWindow contact = UIComponentRegistry.getContactInfoWindow(); + int loc = getList().locationToIndex(e.getPoint()); + ContactItem item = getList().getModel().getElementAt(loc); + return (item == null || contact == null || contact.getContactItem() == null) || !contact.getContactItem().getJid().equals(item.getJid()); + } + + protected DefaultListModel getModel() { + return model; + } + + protected JList getContactItemList() { + return contactItemList; + } +} diff --git a/src/java/org/jivesoftware/spark/ui/ContactGroupListener.java b/core/src/main/java/org/jivesoftware/spark/ui/ContactGroupListener.java similarity index 84% rename from src/java/org/jivesoftware/spark/ui/ContactGroupListener.java rename to core/src/main/java/org/jivesoftware/spark/ui/ContactGroupListener.java index 7388d3058..f26dc70fe 100644 --- a/src/java/org/jivesoftware/spark/ui/ContactGroupListener.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/ContactGroupListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,28 +33,28 @@ public interface ContactGroupListener { * * @param item the ContactItem. */ - public void contactItemAdded(ContactItem item); + void contactItemAdded(ContactItem item); /** * Notifies the user that a ContactItem has been removed from a ContactGroup. * * @param item the ContactItem removed. */ - public void contactItemRemoved(ContactItem item); + void contactItemRemoved(ContactItem item); /** * Notifies the user that a ContactItem within the ContactGroup has been double-clicked. * * @param item the ContactItem double clicked. */ - public void contactItemDoubleClicked(ContactItem item); + void contactItemDoubleClicked(ContactItem item); /** * Notifies the user that a ContactItem within the ContactGroup has been clicked. * * @param item the ContactItem clicked. */ - public void contactItemClicked(ContactItem item); + void contactItemClicked(ContactItem item); /** * Notifies the user that a popup call has occured on the ContactGroup. @@ -67,7 +63,7 @@ public interface ContactGroupListener { * @param item the ContactItem clicked within the ContactGroup. * @deprecated see {@link ContextMenuListener} */ - public void showPopup(MouseEvent e, ContactItem item); + void showPopup(MouseEvent e, ContactItem item); /** * Notifies the user that a popup call has occured on the ContactGroup. @@ -76,7 +72,7 @@ public interface ContactGroupListener { * @param items the ContactItems within the ContactGroup. * @deprecated see ContextMenuListener */ - public void showPopup(MouseEvent e, Collection items); + void showPopup(MouseEvent e, Collection items); /** * Notifies the user that a Popup event has occured on the ContactGroup title @@ -85,5 +81,5 @@ public interface ContactGroupListener { * @param e the MouseEvent that triggered the event. * @param group the ContactGroup. */ - public void contactGroupPopup(MouseEvent e, ContactGroup group); + void contactGroupPopup(MouseEvent e, ContactGroup group); } diff --git a/src/java/org/jivesoftware/spark/ui/ContactGroupTransferHandler.java b/core/src/main/java/org/jivesoftware/spark/ui/ContactGroupTransferHandler.java similarity index 78% rename from src/java/org/jivesoftware/spark/ui/ContactGroupTransferHandler.java rename to core/src/main/java/org/jivesoftware/spark/ui/ContactGroupTransferHandler.java index b817fc1c3..7b6ddc7ab 100644 --- a/src/java/org/jivesoftware/spark/ui/ContactGroupTransferHandler.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/ContactGroupTransferHandler.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -45,21 +41,23 @@ public class ContactGroupTransferHandler extends TransferHandler { private static final long serialVersionUID = -1229773343301542259L; - private static final DataFlavor flavors[] = {DataFlavor.imageFlavor, DataFlavor.javaFileListFlavor}; + private static final DataFlavor[] flavors = {DataFlavor.imageFlavor, DataFlavor.javaFileListFlavor}; - public int getSourceActions(JComponent c) { + @Override + public int getSourceActions(JComponent c) { return TransferHandler.MOVE; } - public boolean canImport(JComponent comp, DataFlavor flavor[]) { + @Override + public boolean canImport(JComponent comp, DataFlavor[] flavor) { if (!(comp instanceof JList)) { return false; } - JList list = (JList)comp; + JList list = (JList)comp; ContactGroup group = getContactGroup(list); if(group == null){ return false; @@ -68,9 +66,9 @@ public boolean canImport(JComponent comp, DataFlavor flavor[]) { return false; } - for (int i = 0, n = flavor.length; i < n; i++) { - for (int j = 0, m = flavors.length; j < m; j++) { - if (flavor[i].equals(flavors[j])) { + for (DataFlavor dataFlavor : flavor) { + for (DataFlavor value : flavors) { + if (dataFlavor.equals(value)) { return true; } } @@ -78,32 +76,30 @@ public boolean canImport(JComponent comp, DataFlavor flavor[]) { return false; } - protected void exportDone(JComponent c, Transferable data, int action) { - } - - - public Transferable createTransferable(JComponent comp) { + @Override + public Transferable createTransferable(JComponent comp) { if (comp instanceof JList) { - JList list = (JList)comp; + JList list = (JList) comp; ContactItem source = (ContactItem)list.getSelectedValue(); return new ContactItemTransferable(source); } return null; } - public boolean importData(JComponent comp, Transferable t) { + @Override + public boolean importData(JComponent comp, Transferable t) { if (comp instanceof JList) { - JList list = (JList)comp; + JList list = (JList) comp; ContactGroup group = getContactGroup(list); if (t.isDataFlavorSupported(flavors[0])) { try { ContactItem item = (ContactItem)t.getTransferData(flavors[0]); - DefaultListModel model = (DefaultListModel)list.getModel(); + DefaultListModel model = (DefaultListModel) list.getModel(); int size = model.getSize(); for (int i = 0; i < size; i++) { - ContactItem it = (ContactItem)model.getElementAt(i); + ContactItem it = (ContactItem) model.getElementAt(i); if (it.getDisplayName().equals(item.getDisplayName())) { return false; } @@ -112,9 +108,7 @@ public boolean importData(JComponent comp, Transferable t) { addContactItem(group, item); return true; } - catch (UnsupportedFlavorException ignored) { - } - catch (IOException ignored) { + catch (UnsupportedFlavorException | IOException ignored) { } } else if (t.isDataFlavorSupported(flavors[1])) { @@ -123,7 +117,7 @@ else if (t.isDataFlavorSupported(flavors[1])) { if (o instanceof java.util.Collection) { Collection files = (Collection)o; ContactItem source = (ContactItem)list.getSelectedValue(); - if (source == null || source.getJID() == null) { + if (source == null || source.getJid() == null) { return false; } @@ -131,10 +125,7 @@ else if (t.isDataFlavorSupported(flavors[1])) { SparkManager.getWorkspace().getContactList().fireFilesDropped(files, source); } } - catch (UnsupportedFlavorException e) { - Log.error(e); - } - catch (IOException e) { + catch (UnsupportedFlavorException | IOException e) { Log.error(e); } } @@ -142,26 +133,29 @@ else if (t.isDataFlavorSupported(flavors[1])) { return false; } - public class ContactItemTransferable implements Transferable { + public static class ContactItemTransferable implements Transferable { - private ContactItem item; + private final ContactItem item; public ContactItemTransferable(ContactItem item) { this.item = item; } // Returns supported flavors - public DataFlavor[] getTransferDataFlavors() { + @Override + public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[]{DataFlavor.imageFlavor}; } // Returns true if flavor is supported - public boolean isDataFlavorSupported(DataFlavor flavor) { + @Override + public boolean isDataFlavorSupported(DataFlavor flavor) { return DataFlavor.imageFlavor.equals(flavor); } // Returns image - public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { + @Override + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { if (!DataFlavor.imageFlavor.equals(flavor)) { throw new UnsupportedFlavorException(flavor); } @@ -169,7 +163,7 @@ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorExcepti } } - private ContactGroup getContactGroup(JList list) { + private ContactGroup getContactGroup(JList list) { ContactList contactList = SparkManager.getWorkspace().getContactList(); for (ContactGroup group : contactList.getContactGroups()) { if (group.getList() == list) { @@ -184,7 +178,7 @@ private ContactGroup getContactGroup(JList list) { return null; } - private ContactGroup getSubContactGroup(ContactGroup group, JList list) { + private ContactGroup getSubContactGroup(ContactGroup group, JList list) { for (ContactGroup g : group.getContactGroups()) { if (g.getList() == list) { return g; @@ -212,8 +206,8 @@ private void addContactItem(final ContactGroup contactGroup, final ContactItem i newContact.setIcon(item.getIcon()); newContact.getNicknameLabel().setFont(item.getNicknameLabel().getFont()); - if (!PresenceManager.isOnline(item.getJID())) { - contactGroup.addOfflineContactItem(item.getAlias(), item.getNickname(), item.getJID(), null); + if (!PresenceManager.isOnline(item.getJid().asBareJid())) { + contactGroup.addOfflineContactItem(item.getAlias(), item.getNickname(), item.getJid(), null); } else { contactGroup.addContactItem(newContact); @@ -224,9 +218,10 @@ private void addContactItem(final ContactGroup contactGroup, final ContactItem i final ContactGroup oldGroup = getContactGroup(item.getGroupName()); SwingWorker worker = new SwingWorker() { - public Object construct() { - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - RosterEntry entry = roster.getEntry(item.getJID()); + @Override + public Object construct() { + Roster roster = SparkManager.getRoster(); + RosterEntry entry = roster.getEntry(item.getJid().asBareJid()); RosterGroup groupFound = null; @@ -236,7 +231,7 @@ public Object construct() { groupFound = group; group.addEntry(entry); } - catch (XMPPException | SmackException e1) { + catch (XMPPException | SmackException | InterruptedException e1) { Log.error(e1); return false; } @@ -249,14 +244,15 @@ public Object construct() { try { groupFound.addEntry(entry); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error(e); } } return true; } - public void finished() { + @Override + public void finished() { if ((Boolean)get()) { // Now try and remove the group from the old one. removeContactItem(oldGroup, item); @@ -281,8 +277,8 @@ public boolean removeContactItem(ContactGroup contactGroup, ContactItem item) { } // Remove entry from Roster Group - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - RosterEntry entry = roster.getEntry(item.getJID()); + Roster roster = SparkManager.getRoster(); + RosterEntry entry = roster.getEntry(item.getJid().asBareJid()); RosterGroup rosterGroup = null; @@ -292,7 +288,7 @@ public boolean removeContactItem(ContactGroup contactGroup, ContactItem item) { rosterGroup = group; group.removeEntry(entry); } - catch (XMPPException | SmackException e1) { + catch (XMPPException | SmackException | InterruptedException e1) { return false; } } diff --git a/src/java/org/jivesoftware/spark/ui/ContactInfoHandler.java b/core/src/main/java/org/jivesoftware/spark/ui/ContactInfoHandler.java similarity index 95% rename from src/java/org/jivesoftware/spark/ui/ContactInfoHandler.java rename to core/src/main/java/org/jivesoftware/spark/ui/ContactInfoHandler.java index b6657b025..bfa0052f7 100644 --- a/src/java/org/jivesoftware/spark/ui/ContactInfoHandler.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/ContactInfoHandler.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/spark/ui/ContactInfoWindow.java b/core/src/main/java/org/jivesoftware/spark/ui/ContactInfoWindow.java similarity index 80% rename from src/java/org/jivesoftware/spark/ui/ContactInfoWindow.java rename to core/src/main/java/org/jivesoftware/spark/ui/ContactInfoWindow.java index 8ba9c9c28..e0c7afb93 100644 --- a/src/java/org/jivesoftware/spark/ui/ContactInfoWindow.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/ContactInfoWindow.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,16 +16,9 @@ package org.jivesoftware.spark.ui; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.Point; -import java.awt.Toolkit; +import java.awt.*; import java.awt.event.MouseEvent; -import java.net.MalformedURLException; + import java.net.URL; import javax.swing.BorderFactory; @@ -41,18 +30,20 @@ import org.jivesoftware.resource.Res; import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaError.Condition; import org.jivesoftware.smackx.vcardtemp.packet.VCard; import org.jivesoftware.smackx.iqlast.packet.LastActivity; import org.jivesoftware.smackx.iqlast.LastActivityManager; import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.ui.ContactItem; import org.jivesoftware.spark.util.GraphicUtils; import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.spark.util.log.Log; import org.jivesoftware.sparkimpl.plugin.gateways.transports.Transport; import org.jivesoftware.sparkimpl.plugin.gateways.transports.TransportUtils; -import org.jxmpp.util.XmppStringUtils; +import org.jivesoftware.sparkimpl.settings.Sizes; +import org.jxmpp.jid.Jid; import java.text.SimpleDateFormat; import java.util.Date; @@ -74,7 +65,7 @@ public class ContactInfoWindow extends JPanel { private ContactItem contactItem; - private JWindow window = new JWindow(); + private final JWindow window = new JWindow(); private static ContactInfoWindow singleton; private static final Object LOCK = new Object(); @@ -142,25 +133,31 @@ protected ContactInfoWindow(boolean populate) { final ContactList contactList = SparkManager.getWorkspace().getContactList(); contactList.addContactListListener(new ContactListListener() { - public void contactItemAdded(ContactItem item) { + @Override + public void contactItemAdded(ContactItem item) { } - public void contactItemRemoved(ContactItem item) { + @Override + public void contactItemRemoved(ContactItem item) { } - public void contactGroupAdded(ContactGroup group) { + @Override + public void contactGroupAdded(ContactGroup group) { } - public void contactGroupRemoved(ContactGroup group) { + @Override + public void contactGroupRemoved(ContactGroup group) { } - public void contactItemClicked(ContactItem item) { + @Override + public void contactItemClicked(ContactItem item) { if (window != null) { window.dispose(); } } - public void contactItemDoubleClicked(ContactItem item) { + @Override + public void contactItemDoubleClicked(ContactItem item) { if (window != null) { window.dispose(); } @@ -172,8 +169,8 @@ public void display(ContactGroup group, MouseEvent e) { int loc = group.getList().locationToIndex(e.getPoint()); - ContactItem item = (ContactItem)group.getList().getModel().getElementAt(loc); - if (item == null || item.getJID() == null) { + ContactItem item = group.getList().getModel().getElementAt(loc); + if (item == null || item.getJid() == null || item.getJid().toString().equals("dummy@dummy.example")) { return; } @@ -214,6 +211,10 @@ public void setWindowLocation(int x, int y) { if (actualY + getHeight() > screenSize.height - 64) { actualY -= actualY + getHeight() - screenSize.height + 64; } + // if width Spark Main Windows > width 0.9*screenSize we should put a window inside + if(SparkManager.getMainWindow().getWidth() > screenSize.getWidth()*0.9){ + actualX = x-310; + } window.setLocation(actualX, actualY); } @@ -235,17 +236,11 @@ public void customizeUI(ContactItem contactItem) { } if (status.equals(Res.getString("offline")) || contactItem.getPresence().isAway()) { //If user is offline or away, try to see last activity + try { - String client = ""; - if (!status.equals(Res.getString("offline"))) { - //If user is away (not offline), last activity request is sent to client - client = contactItem.getPresence().getFrom(); - if ((client != null) && (client.lastIndexOf("/") != -1)) { - client = client.substring(client.lastIndexOf("/")); - } else client = "/"; - } - - LastActivity activity = LastActivityManager.getInstanceFor( SparkManager.getConnection() ).getLastActivity( contactItem.getJID()+client); + //If user is away (not offline), last activity request is sent to client + Jid client = status.equals(Res.getString("offline")) ? contactItem.getJid() : contactItem.getPresence().getFrom(); + LastActivity activity = LastActivityManager.getInstanceFor( SparkManager.getConnection() ).getLastActivity(client); long idleTime = (activity.getIdleTime() * 1000); @@ -261,28 +256,31 @@ public void customizeUI(ContactItem contactItem) { } else { format = new SimpleDateFormat("EEE M/d/yy h:mm a"); } - status += (" since " + format.format(l)); + status += (" " + Res.getString("time.since")+ " " + format.format(l)); } else if (contactItem.getPresence().isAway()) { status += "\n"; String time = ModelUtil.getTimeFromLong(idleTime); status += Res.getString("message.idle.for", time); } } - } catch (Exception e1) { - } + } catch (XMPPException.XMPPErrorException e) { + Condition condition = e.getStanzaError().getCondition(); + if (condition != Condition.feature_not_implemented && condition != Condition.service_unavailable && condition != Condition.subscription_required) { + Log.warning("Unable to get Last Activity from: " + contactItem, e); + } + } catch (Exception e) { + Log.warning("Unable to get Last Activity from: " + contactItem, e); + } } statusLabel.setText(status); - Transport transport = TransportUtils.getTransport( XmppStringUtils.parseDomain(contactItem.getJID())); + Transport transport = TransportUtils.getTransport(contactItem.getJid().asDomainBareJid()); if (transport != null) { fullJIDLabel.setIcon(transport.getIcon()); - String name = XmppStringUtils.parseLocalpart(contactItem.getJID()); - name = XmppStringUtils.unescapeLocalpart(name); - fullJIDLabel.setText(transport.getName() + " - " + name); + fullJIDLabel.setText(transport.getName() + " - " + contactItem.getJid().getLocalpartOrThrow().asUnescapedString()); } else { - String name = XmppStringUtils.unescapeLocalpart(contactItem.getJID()); - fullJIDLabel.setText(name); + fullJIDLabel.setText(contactItem.getJid().getLocalpartOrThrow().asUnescapedString()); fullJIDLabel.setIcon(null); } @@ -296,23 +294,23 @@ public void customizeUI(ContactItem contactItem) { } if (icon != null && icon.getIconHeight() > 1) { - icon = GraphicUtils.scaleImageIcon(icon, 96, 96); + icon = GraphicUtils.scaleImageIcon(icon, Sizes.Avatar.PROFILE, Sizes.Avatar.PROFILE); avatarLabel.setIcon(icon); } else { - icon = SparkRes.getImageIcon(SparkRes.DEFAULT_AVATAR_64x64_IMAGE); + icon = SparkRes.getImageIcon(SparkRes.Icon.DEFAULT_AVATAR_64x64_IMAGE); avatarLabel.setIcon(icon); } - avatarLabel.setBorder(BorderFactory.createBevelBorder(0, Color.white, Color.lightGray)); + avatarLabel.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); } - catch (MalformedURLException e) { - Log.error(e); + catch (Exception e) { + Log.warning("Unable to update avatar in contact info window", e); } // Get VCard from memory (if available) String title = ""; String phone = ""; - VCard vcard = SparkManager.getVCardManager().getVCardFromMemory(XmppStringUtils.parseBareJid(contactItem.getJID())); + VCard vcard = SparkManager.getVCardManager().getVCardFromMemory(contactItem.getJid().asBareJid()); if (vcard != null) { title = vcard.getField("TITLE"); phone = vcard.getPhoneWork("VOICE"); @@ -345,16 +343,14 @@ public void dispose() { } - public Dimension getPreferredSize() { + @Override + public Dimension getPreferredSize() { final Dimension size = super.getPreferredSize(); size.width = 300; size.height = 125; return size; } - public void mouseEntered(MouseEvent e) { - } - public void mouseExited(MouseEvent e) { Point point = e.getPoint(); diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ContactItem.java b/core/src/main/java/org/jivesoftware/spark/ui/ContactItem.java new file mode 100644 index 000000000..95cc4f488 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/ContactItem.java @@ -0,0 +1,625 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Comparator; + +import javax.swing.*; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smack.roster.RosterEntry; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.roster.packet.RosterPacket; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettings; +import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettingsManager; +import org.jivesoftware.sparkimpl.profile.ext.VCardUpdateExtension; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.BareJid; +import org.jxmpp.util.XmppStringUtils; + +import static org.apache.commons.lang3.StringUtils.trimToEmpty; + +/** + * Represent a single contact within the ContactList. + */ +public class ContactItem extends JPanel { + + public final static Comparator CONTACT_ITEM_COMPARATOR = Comparator.comparing(ContactItem::getDisplayName, String.CASE_INSENSITIVE_ORDER); + + private final JLabel imageLabel; + private final JLabel displayNameLabel; + private final JLabel descriptionLabel; + private final JLabel specialImageLabel; + private final JLabel sideIcon; + + private String nickname; + private String alias; + private final BareJid jid; + private Icon icon; + private String status; + private String groupName; + private boolean available; + private Presence presence; + private String hash = ""; + private final File contactsDir; + private final int fontSize; + private final int iconSize; + private final boolean avatarsShowing; + + private static final Color COLOR_USER_ONLINE_NICKNAME = new Color(255, 128, 0); + + public ContactItem(String alias, String nickname, BareJid fullyQualifiedJID) { + this(alias, nickname, fullyQualifiedJID, true); + } + + /** + * Creates a new instance of a contact. + * + * @param alias the alias of the contact + * @param nickname the nickname of the contact. + * @param jid the fully-qualified jid of the contact (ex. derek@jivesoftware.com) + */ + public ContactItem(String alias, String nickname, BareJid jid, boolean initUi) { + setLayout(new GridBagLayout()); + + // Set Default Font + final LocalPreferences pref = SettingsManager.getLocalPreferences(); + fontSize = pref.getContactListFontSize(); + iconSize = pref.getContactListIconSize(); + avatarsShowing = pref.areAvatarsVisible(); + + // Set default presence + presence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .build(); + + contactsDir = new File(SparkManager.getUserDirectory(), "contacts"); + + this.alias = trimToEmpty(alias); + this.nickname = trimToEmpty(nickname); + this.jid = jid; + + if (initUi) { + displayNameLabel = new JLabel(); + descriptionLabel = new JLabel(); + imageLabel = new JLabel(); + specialImageLabel = new JLabel(); + sideIcon = new JLabel(); + if (avatarsShowing) { + sideIcon.setMinimumSize(new Dimension(iconSize, iconSize)); + sideIcon.setMaximumSize(new Dimension(iconSize, iconSize)); + sideIcon.setPreferredSize(new Dimension(iconSize, iconSize)); + } + + displayNameLabel.setHorizontalTextPosition(JLabel.LEFT); + displayNameLabel.setHorizontalAlignment(JLabel.LEFT); + //displayNameLabel.setText(nickname); + + descriptionLabel.setFont(new Font("Dialog", Font.PLAIN, fontSize)); + descriptionLabel.setForeground((Color) UIManager.get("ContactItemDescription.foreground")); + descriptionLabel.setHorizontalTextPosition(JLabel.LEFT); + descriptionLabel.setHorizontalAlignment(JLabel.LEFT); + + this.setOpaque(true); + + add(imageLabel, new GridBagConstraints(0, 0, 1, 2, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 15, 0, 0), 0, 0)); + add(displayNameLabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 0, 0), 0, 0)); + add(descriptionLabel, new GridBagConstraints(2, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 2, 0), 0, 0)); + add(specialImageLabel, new GridBagConstraints(3, 0, 1, 2, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 0, 0), 0, 0)); + add(sideIcon, new GridBagConstraints(4, 0, 1, 2, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 0, 0), 0, 0)); + + setDisplayName(); + } + else { + imageLabel = null; + displayNameLabel = null; + descriptionLabel = null; + specialImageLabel = null; + sideIcon = null; + } + } + + /** + * Returns the name that should be displayed to represent the the contact. + * If an alias has been set, this alias will be returned. If no alias has + * been set, the nickname will be returned. If that hasn't been set either, + * the JID will be returned. + * + * @return a name suitable to be displayed + */ + public String getDisplayName() { + String displayName = null; + if (!alias.isEmpty()) { + return alias; + } + if (!nickname.isEmpty()) { + return nickname; + } + BareJid bareJid = getJid(); + if (bareJid != null) { + displayName = bareJid.toString(); + } + if (displayName != null) { + return displayName; + } + return ""; // weird, but happens. + } + + /** + * Returns the nickname of the contact. Note that for typical user-interface + * related tasks, you probably should use {@link #getDisplayName()} instead. + * + * @return the contact nickname. + */ + public String getNickname() { + return nickname; + } + + /** + * Sets the nickname of the contact. + * + * @param nickname the contact nickname. + */ + public void setNickname(String nickname) { + this.nickname = trimToEmpty(nickname); + if (alias.isEmpty()) { + setDisplayName(); + } + } + + /** + * Returns the alias of the contact. Note that for typical user-interface + * related tasks, you probably should use {@link #getDisplayName()} instead. + * + * @return the contact alias. + */ + public String getAlias() { + return alias; + } + + /** + * Sets the alias of the contact. + * + * @param alias the contact alias. + */ + public void setAlias(String alias) { + this.alias = trimToEmpty(alias); + setDisplayName(); + } + + /** + * Updates the displayed name for the contact. This method tries to use an + * alias first. If that's not set, the nickname will be used instead. If + * that's not set either, the JID of the user will be used. + */ + protected void setDisplayName() { + final String displayName = getDisplayName(); + + int nickLength = displayName.length(); + + LayoutSettings settings = LayoutSettingsManager.getLayoutSettings(); + int windowWidth = settings.getMainWindowBounds() != null ? settings.getMainWindowBounds().width : 50; + + if (nickLength > windowWidth) { // FIXME comparing pixel-width with character count - that can't be good. + displayNameLabel.setText(XmppStringUtils.unescapeLocalpart(displayName).substring(0, windowWidth) + "..."); + } else { + displayNameLabel.setText(XmppStringUtils.unescapeLocalpart(displayName)); + } + } + + /** + * Return the XMPP address, aka. JID< of this contact item. + * + * @return the XMPP address of this item. + */ + public BareJid getJid() { + return jid; + } + + /** + * Returns the icon showing the contacts current state or presence. + * + * @return the icon. + */ + public Icon getIcon() { + return icon; + } + + /** + * Sets the current icon to use. + * + * @param icon the current icon to use. + */ + public void setIcon(Icon icon) { + this.icon = icon; + imageLabel.setIcon(icon); + } + + /** + * Returns the contacts current status based on their presence. + * + * @return the contacts current status. + */ + public String getStatus() { + return status; + } + + /** + * Sets the contacts current status. + * + * @param status the contacts current status. + */ + public void setStatus(String status) { + this.status = status; + } + + /** + * Returns the name of the ContactGroup that this contact belongs to. + * + * @return the name of the ContactGroup. + */ + public String getGroupName() { + return groupName; + } + + /** + * Sets the name of the ContactGrouop that this contact belongs to. + * + * @param groupName the name of the ContactGroup. + */ + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + public boolean isAvailable() { + return available; + } + + public void setAvailable(boolean available) { + this.available = available; + } + + /** + * Returns the JLabel showing the users nickname. + * + * @return the nickname label. + */ + public JLabel getNicknameLabel() { + return displayNameLabel; + } + + /** + * Returns the JLabel representing the description. + * + * @return the description label. + */ + public JLabel getDescriptionLabel() { + return descriptionLabel; + } + + /** + * Returns the current presence of the contact. + * + * @return the users current presence. + */ + public Presence getPresence() { + return presence; + } + + /** + * Sets the current presence on this contact item. + * + * @param presence the presence. + */ + public void setPresence(Presence presence) { + this.presence = presence; + final VCardUpdateExtension extension = presence.getExtension(VCardUpdateExtension.class); + // Handle vCard update packet. + if (extension != null) { + String hash = extension.getPhotoHash(); + if (hash != null) { + this.hash = hash; + if (!hashExists(hash)) { + updateAvatar(); + updateAvatarInSideIcon(); + } + } + } + updatePresenceIcon(presence); + } + + /** + * Checks to see if the hash already exists. + * + * @param hash the hash. + * @return true if the hash exists, otherwise false. + */ + private boolean hashExists(String hash) { + contactsDir.mkdirs(); + + final File imageFile = new File(contactsDir, hash); + return imageFile.exists(); + } + + /** + * Returns the url of the avatar belonging to this contact. + * + * @return the url of the avatar. + * @throws MalformedURLException thrown if the address is invalid. + */ + public URL getAvatarURL() throws MalformedURLException { + contactsDir.mkdirs(); + + if (ModelUtil.hasLength(hash)) { + final File imageFile = new File(contactsDir, hash); + if (imageFile.exists()) { + return imageFile.toURI().toURL(); + } + } + + return SparkManager.getVCardManager().getAvatarURLIfAvailable(getJid()); + } + + public int getFontSize() { + return fontSize; + } + + /** + * Persists the avatar locally based on the new hash. + */ + private void updateAvatar() { + SparkManager.getVCardManager().addToQueue(getJid().asBareJid()); + } + + @Override + public String toString() { + return displayNameLabel.getText(); + } + + + /** + * Updates the icon of the user based on their presence. + * + * @param presence the users presence. + */ + public void updatePresenceIcon(Presence presence) { + ChatManager chatManager = SparkManager.getChatManager(); + boolean handled = chatManager.fireContactItemPresenceChanged(this, presence); + if (handled) { + return; + } + + String status = presence.getStatus(); + Icon statusIcon = SparkRes.getImageIcon(SparkRes.Icon.GREEN_BALL); + boolean isAvailable = false; + if (status == null && presence.isAvailable()) { + Presence.Mode mode = presence.getMode(); + if (mode == Presence.Mode.available) { + status = Res.getString("status.online"); + isAvailable = true; + } + else if (mode == Presence.Mode.away) { + status = Res.getString("status.away"); + statusIcon = SparkRes.getImageIcon(SparkRes.Icon.IM_AWAY); + } + else if (mode == Presence.Mode.chat) { + status = Res.getString("status.free.to.chat"); + } + else if (mode == Presence.Mode.dnd) { + status = Res.getString("status.do.not.disturb"); + statusIcon = SparkRes.getImageIcon(SparkRes.Icon.IM_AWAY); + } + else if (mode == Presence.Mode.xa) { + status = Res.getString("status.extended.away"); + statusIcon = SparkRes.getImageIcon(SparkRes.Icon.IM_XA); + } + } + + // Sets status icon and text based on presence + if (presence.isAway()) { + statusIcon = SparkRes.getImageIcon(SparkRes.Icon.IM_AWAY); + } + else if (presence.isAvailable()) { + isAvailable = true; + } + else { + getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, fontSize)); + getNicknameLabel().setForeground((Color)UIManager.get("ContactItemOffline.color")); + + Roster roster = SparkManager.getRoster(); + RosterEntry entry = roster.getEntry(getJid()); + if (entry != null && (entry.getType() == RosterPacket.ItemType.none || entry.getType() == RosterPacket.ItemType.from) + && entry.isSubscriptionPending()) { + // Do not move out of group. + setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_QUESTION)); + getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, fontSize)); + setStatusText(Res.getString("status.pending")); + } + else { + //We should keep the offline bullet (not available) instead of putting icon null. + setIcon(SparkRes.getImageIcon(SparkRes.Icon.CLEAR_BALL_ICON)); + setFont(new Font("Dialog", Font.PLAIN, fontSize)); + getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, fontSize)); + setAvailable(false); + if (ModelUtil.hasLength(status)) { + setStatusText(status); + } + else { + setStatusText(""); + } + } + + sideIcon.setIcon(null); + setAvailable(false); + return; + } + + Icon sIcon = PresenceManager.getIconFromPresence(presence); + if (sIcon != null) { + setIcon(sIcon); + } + else { + setIcon(statusIcon); + } + if (status != null) { + setStatus(status); + } + + if (PresenceManager.isOnPhone(presence)) { + statusIcon = SparkRes.getImageIcon(SparkRes.Icon.ON_PHONE_IMAGE); + setIcon(statusIcon); + } + + // Always change nickname label to black. + getNicknameLabel().setForeground((Color)UIManager.get("ContactItemNickname.foreground")); + + + if (isAvailable) { + getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, fontSize)); + if (Res.getString("status.online").equals(status) || Res.getString("available").equalsIgnoreCase(status)) { + setStatusText(""); + } + else { + setStatusText(status); + } + } + else if (presence.isAvailable()) { + LocalPreferences pref = SettingsManager.getLocalPreferences(); + if(pref.isGrayingOutEnabled()) + { + getNicknameLabel().setFont(new Font("Dialog", Font.ITALIC, fontSize)); + getNicknameLabel().setForeground(Color.gray); + } + else + { + getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, fontSize)); + getNicknameLabel().setForeground(Color.black); + } + if (status != null) { + setStatusText(status); + } + } + + setAvailable(true); + } + + /** + * Sets the status label text based on the users status. + * + * @param status the users status. + */ + public void setStatusText(String status) { + setStatus(status); + + if (ModelUtil.hasLength(status)) { + getDescriptionLabel().setText(" - " + status); + } + else { + getDescriptionLabel().setText(""); + } + } + + /** + * The icon should only be used to display avatars in contact list. if you want to add an icon + * to indicated that this contact is a transport e.g you should use setSpecialIcon() + * + * @param icon the icon to use. + */ + public void setSideIcon(Icon icon) { + sideIcon.setIcon(icon); + } + + + /** + * The icon to use to show extra information about this contact. An example would be to + * represent that this user is from a 3rd party transport. + * + * @param icon the icon to use. + */ + public void setSpecialIcon(Icon icon) + { + specialImageLabel.setIcon(icon); + } + + /** + * Shows that the user is coming online. + */ + public void showUserComingOnline() { + // Change Font + getNicknameLabel().setFont(new Font("Dialog", Font.BOLD, fontSize)); + getNicknameLabel().setForeground(COLOR_USER_ONLINE_NICKNAME); + } + + /** + * Shows that the user is going offline. + */ + public void showUserGoingOfflineOnline() { + // Change Font + getNicknameLabel().setFont(new Font("Dialog", Font.BOLD, fontSize)); + getNicknameLabel().setForeground(Color.red); + } + + /** + * Update avatar icon. + */ + public void updateAvatarInSideIcon() { + try { + final URL url = getAvatarURL(); + if (url != null) { + if (!avatarsShowing) { + setSideIcon(null); + } else { + ImageIcon icon = new ImageIcon(url); + icon = GraphicUtils.scale(icon, iconSize, iconSize); + setSideIcon(icon); + } + } + } catch (Exception e) { + Log.warning("Unable to update avatar in side icon", e); + } + } + + protected JLabel getDisplayNameLabel() { + return displayNameLabel; + } + + public JLabel getSpecialImageLabel() { + return specialImageLabel; + } + + public JLabel getSideIcon() { + return sideIcon; + } +} diff --git a/src/java/org/jivesoftware/spark/ui/ContactItemHandler.java b/core/src/main/java/org/jivesoftware/spark/ui/ContactItemHandler.java similarity index 75% rename from src/java/org/jivesoftware/spark/ui/ContactItemHandler.java rename to core/src/main/java/org/jivesoftware/spark/ui/ContactItemHandler.java index 395d9ea69..d19185dc4 100644 --- a/src/java/org/jivesoftware/spark/ui/ContactItemHandler.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/ContactItemHandler.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +16,7 @@ package org.jivesoftware.spark.ui; import org.jivesoftware.smack.packet.Presence; +import org.jxmpp.jid.BareJid; import javax.swing.Icon; @@ -30,21 +27,25 @@ public interface ContactItemHandler { /** - * The users presence has been changed. + * The user's presence has been changed. * * @param item the contact item. - * @param presence the users new presence. + * @param presence the user's new presence. * @return true if the presence was handled. */ - boolean handlePresence(ContactItem item, Presence presence); + default boolean handlePresence(ContactItem item, Presence presence) { + return false; + } /** - * Return the icon used for particular presence. + * Return the icon used for the particular presence. * * @param jid the users jid. * @return the icon, if any. null may be returned. */ - Icon getIcon(String jid); + default Icon getIcon(BareJid jid) { + return null; + } /** * Return the icon to use on the chat room tab. @@ -52,8 +53,9 @@ public interface ContactItemHandler { * @param presence the presence of the user. * @return the icon to use. */ - Icon getTabIcon(Presence presence); - + default Icon getTabIcon(Presence presence) { + return null; + } /** * The ContactItem has been double-clicked by the user. @@ -61,5 +63,7 @@ public interface ContactItemHandler { * @param item the ContactItem to handle. * @return true if you wish to handle the double-click event. */ - boolean handleDoubleClick(ContactItem item); + default boolean handleDoubleClick(ContactItem item) { + return false; + } } diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ContactList.java b/core/src/main/java/org/jivesoftware/spark/ui/ContactList.java new file mode 100644 index 000000000..bb9ec0b20 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/ContactList.java @@ -0,0 +1,2543 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.MainWindowListener; +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.*; +import org.jivesoftware.smack.XMPPException.XMPPErrorException; +import org.jivesoftware.smack.filter.StanzaTypeFilter; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smack.packet.StanzaError; +import org.jivesoftware.smack.packet.StanzaError.Condition; +import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smack.roster.RosterEntry; +import org.jivesoftware.smack.roster.RosterGroup; +import org.jivesoftware.smack.roster.RosterListener; +import org.jivesoftware.smack.roster.packet.RosterPacket; +import org.jivesoftware.smackx.iqlast.LastActivityManager; +import org.jivesoftware.smackx.iqlast.packet.LastActivity; +import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; +import org.jivesoftware.smackx.sharedgroups.SharedGroupManager; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.Workspace; +import org.jivesoftware.spark.component.InputDialog; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.component.VerticalFlowLayout; +import org.jivesoftware.spark.plugin.ContextMenuListener; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.util.*; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; +import org.jivesoftware.sparkimpl.profile.VCardManager; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.time.Duration; +import java.time.Instant; +import java.util.*; +import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CopyOnWriteArrayList; + + +public class ContactList extends JPanel implements ActionListener, + ContactGroupListener, Plugin, RosterListener, ConnectionListener, ReconnectionListener { + + private static final long serialVersionUID = -4391111935248627078L; + private static final String GROUP_DELIMITER = "::"; + private final JPanel mainPanel = new JPanel(); + private final JScrollPane contactListScrollPane; + private final List groupList = new ArrayList<>(); + private final RolloverButton addingGroupButton; + + private ContactItem activeItem; + private ContactGroup activeGroup; + private ContactGroup unfiledGroup; + + + // Create Menus + private final JMenuItem addContactMenu; + private final JMenuItem addContactGroupMenu; + private final JMenuItem removeContactFromGroupMenu; + private final JMenuItem chatMenu; + private final JMenuItem renameMenu; + + private final ContactGroup offlineGroup; + private final JCheckBoxMenuItem showHideMenu = new JCheckBoxMenuItem(); + private final JCheckBoxMenuItem showOfflineGroupMenu = new JCheckBoxMenuItem(); + private final JCheckBoxMenuItem showOfflineUsersMenu = new JCheckBoxMenuItem(); + + private List sharedGroups = new ArrayList<>(); + + private final CopyOnWriteArrayList contextListeners = new CopyOnWriteArrayList<>(); + + private final CopyOnWriteArrayList dndListeners = new CopyOnWriteArrayList<>(); + private final CopyOnWriteArrayList contactListListeners = new CopyOnWriteArrayList<>(); + private final Properties props; + private final File propertiesFile; + + private final LocalPreferences localPreferences; + + private ContactItem contactItem; + + private String name; + private BareJid user; + + + public static final String RETRY_PANEL = "RETRY_PANEL"; + + + private final ReconnectPanel _reconnectPanel; + private final ReconnectPanelSmall _reconnectpanelsmall; + private final ReconnectPanelIcon _reconnectpanelicon; + + private final Workspace workspace; + + public static KeyEvent activeKeyEvent; + + /** + * Creates a new instance of ContactList. + */ + public ContactList() { + // Load Local Preferences + localPreferences = SettingsManager.getLocalPreferences(); + + offlineGroup = UIComponentRegistry.createContactGroup(Res.getString("group.offline")); + unfiledGroup = getUnfiledGroup(); + + JToolBar toolbar = new JToolBar(); + toolbar.setFloatable(false); + addContactMenu = new JMenuItem(Res.getString("menuitem.add.contact"), SparkRes.getImageIcon(SparkRes.Icon.USER1_ADD_16x16)); + addContactGroupMenu = new JMenuItem(Res.getString("menuitem.add.contact.group"), SparkRes.getImageIcon(SparkRes.Icon.SMALL_ADD_IMAGE)); + + removeContactFromGroupMenu = new JMenuItem(Res.getString("menuitem.remove.from.group"), SparkRes.getImageIcon(SparkRes.Icon.SMALL_DELETE)); + chatMenu = new JMenuItem(Res.getString("menuitem.start.a.chat"), SparkRes.getImageIcon(SparkRes.Icon.SMALL_MESSAGE_IMAGE)); + renameMenu = new JMenuItem(Res.getString("menuitem.rename"), SparkRes.getImageIcon(SparkRes.Icon.DESKTOP_IMAGE)); + + addContactMenu.addActionListener(this); + removeContactFromGroupMenu.addActionListener(this); + chatMenu.addActionListener(this); + renameMenu.addActionListener(this); + + + setLayout(new BorderLayout()); + + addingGroupButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.Icon.ADD_CONTACT_IMAGE)); + + RolloverButton groupChatButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.Icon.JOIN_GROUPCHAT_IMAGE)); + toolbar.add(addingGroupButton); + toolbar.add(groupChatButton); + + addingGroupButton.addActionListener(this); + + mainPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); + mainPanel.setBackground((Color) UIManager.get("ContactItem.background")); + contactListScrollPane = new JScrollPane(mainPanel); + contactListScrollPane.setAutoscrolls(true); + + contactListScrollPane.setBorder(BorderFactory.createEmptyBorder()); + contactListScrollPane.getVerticalScrollBar().setBlockIncrement(200); + contactListScrollPane.getVerticalScrollBar().setUnitIncrement(20); + + _reconnectPanel = new ReconnectPanel(); + + _reconnectpanelsmall = new ReconnectPanelSmall(Res.getString("button.reconnect2")); + + _reconnectpanelicon = new ReconnectPanelIcon(); + + workspace = SparkManager.getWorkspace(); + + workspace.getCardPanel().add(RETRY_PANEL, _reconnectPanel); + + + add(contactListScrollPane, BorderLayout.CENTER); + + + // Load Properties file + props = new Properties(); + // Save to a properties file. + propertiesFile = new File(Spark.getSparkUserHome(), "/groups.properties"); + try { + props.load(new FileInputStream(propertiesFile)); + } catch (IOException e) { + // File does not exist. + } + + // Add ActionListener(s) to menus + addContactGroup(unfiledGroup); + addContactGroup(offlineGroup); + + showHideMenu.setSelected(false); + + // Add KeyMappings + SparkManager.getMainWindow().getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control F"), "searchContacts"); + SparkManager.getMainWindow().getRootPane().getActionMap().put("searchContacts", new AbstractAction("searchContacts") { + private static final long serialVersionUID = -5956142123453578689L; + + @Override + public void actionPerformed(ActionEvent evt) { + SparkManager.getUserManager().searchContacts("", SparkManager.getMainWindow()); + } + }); + + // Handle Command-F on Macs + SparkManager.getMainWindow().getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "appleStrokeF"); + SparkManager.getMainWindow().getRootPane().getActionMap().put("appleStrokeF", new AbstractAction("appleStrokeF") { + private static final long serialVersionUID = 7883006402414136652L; + + @Override + public void actionPerformed(ActionEvent evt) { + SparkManager.getUserManager().searchContacts("", SparkManager.getMainWindow()); + } + }); + + // Save state on shutdown. + final ContactList instance = this; + SparkManager.getMainWindow().addMainWindowListener(new MainWindowListener() { + @Override + public void shutdown() { + saveState(); + SparkManager.getConnection().removeConnectionListener(instance); + } + + @Override + public void mainWindowActivated() { + + } + + @Override + public void mainWindowDeactivated() { + + } + }); + + SparkManager.getConnection().addConnectionListener(this); + ReconnectionManager.getInstanceFor(SparkManager.getConnection()).addReconnectionListener(this); + // Get a command panel and add View Online/Offline, Add Contact +// StatusBar statusBar = SparkManager.getWorkspace().getStatusBar(); + +// final JPanel commandPanel = SparkManager.getWorkspace().getCommandPanel(); +// +// +// final RolloverButton addContactButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.Icons.USER1_ADD_16x16)); +// if (!Default.getBoolean(Default.ADD_CONTACT_DISABLED)) { +// commandPanel.add(addContactButton); +// } +// addContactButton.setToolTipText(Res.getString("message.add.a.contact")); +// addContactButton.addActionListener(new ActionListener() { +// public void actionPerformed(ActionEvent e) { +// new RosterDialog().showRosterDialog(); +// } +// }); + + } + + /** + * Switches all users to Offline and Creates a Reconnection Group + */ + private synchronized void switchAllUserOffline(final boolean onError) { + SwingWorker worker = new SwingWorker() { + + @Override + public Object construct() { + mainPanel.add(_reconnectpanelsmall, 0); + Roster roster = SparkManager.getRoster(); + final Collection rosterEntries = roster.getEntries(); + + for (RosterEntry r : rosterEntries) { + Presence p = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .build(); + moveToOfflineGroup(p, r.getJid()); + } + return true; + } + }; + worker.start(); + } + + /** + * Switches all Users to Offline and Creates an Icon in the CommandBar + */ + private synchronized void switchAllUserOfflineNoGroupEntry(final boolean onError) { + SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + _reconnectpanelicon.getPanel().add(_reconnectpanelicon.getButton(), 0); + _reconnectpanelicon.getPanel().revalidate(); + Roster roster = SparkManager.getRoster(); + Collection rosterEntries = roster.getEntries(); + for (RosterEntry r : rosterEntries) { + Presence p = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .build(); + moveToOfflineGroup(p, r.getJid()); + } + return true; + } + }; + worker.start(); + } + + /** + * Updates the user's presence. + * + * @param presence the user to update. + */ + private synchronized void updateUserPresence(Presence presence) { + if (presence.getError() != null) { + // We ignore this. + return; + } + if (presence.getFrom() == null) { + return; + } + + final Roster roster = SparkManager.getRoster(); + + final BareJid bareJID = presence.getFrom().asBareJid(); + + RosterEntry entry = roster.getEntry(bareJID); + boolean isPending = entry != null && (entry.getType() == RosterPacket.ItemType.none || entry.getType() == RosterPacket.ItemType.from) + && entry.isSubscriptionPending(); + + // If online, check to see if they are in the offline group. + // If so, remove from an offline group and add to all groups they belong to. + if (presence.getType() == Presence.Type.available && offlineGroup.getContactItemByJID(bareJID) != null || (presence.getFrom().toString().contains("workgroup."))) { + changeOfflineToOnline(bareJID, entry, presence); + } else if (presence.getType() == Presence.Type.available) { + updateContactItemsPresence(presence, entry, bareJID); + } else if (presence.getType() == Presence.Type.unavailable && !isPending) { + // If not available, move to an offline group. + Presence rosterPresence = PresenceManager.getPresence(bareJID); + if (!rosterPresence.isAvailable()) { + moveToOfflineGroup(presence, bareJID); + } else { + updateContactItemsPresence(rosterPresence, entry, bareJID); + } + } + + } + + /** + * Updates the presence of one individual based on their JID. + * + * @param presence the user's presence. + * @param entry the roster entry being updated. + * @param bareJID the bare jid of the user. + */ + private void updateContactItemsPresence(Presence presence, RosterEntry entry, BareJid bareJID) { + for (ContactGroup group : groupList) { + ContactItem item = group.getContactItemByJID(bareJID); + if (item != null) { + if (group == offlineGroup) { + changeOfflineToOnline(bareJID, entry, presence); + continue; + } + item.setPresence(presence); + group.fireContactGroupUpdated(); + } + } + } + + /** + * Moves every ContactItem associated with the given bareJID to offline. + * + * @param presence the user's presence. + * @param bareJID the bareJID of the user. + */ + private void moveToOfflineGroup(final Presence presence, final BareJid bareJID) { + for (ContactGroup grpItem : new ArrayList<>(groupList)) { + final ContactGroup group = grpItem; + final ContactItem item = group.getContactItemByJID(bareJID); + if (item != null) { + int numberOfMillisecondsInTheFuture = 3000; + Date timeToRun = new Date(System.currentTimeMillis() + numberOfMillisecondsInTheFuture); + + // Only run through if the user's presence was online before. + if (item.getPresence().isAvailable()) { + item.showUserGoingOfflineOnline(); + item.setIcon(SparkRes.getImageIcon(SparkRes.Icon.CLEAR_BALL_ICON)); + group.fireContactGroupUpdated(); + + TaskEngine.getInstance().schedule(new SwingTimerTask() { + @Override + public void doRun() { + item.setPresence(presence); + + // Check for ContactItemHandler. + group.removeContactItem(item); + checkGroup(group); + + if (offlineGroup.getContactItemByJID(item.getJid()) == null) { + moveToOffline(item); + offlineGroup.fireContactGroupUpdated(); + } + } + }, timeToRun); + } + } else { + final ContactItem offlineItem = offlineGroup.getContactItemByJID(bareJID); + if (offlineItem != null) { + offlineItem.setPresence(presence); + } + } + } + } + + /** + * Moves a user to each group they belong to. + * + * @param bareJID the bareJID of the user to show as online. + * @param entry the RosterEntry of the user. + * @param presence the user's presence. + */ + private void changeOfflineToOnline(BareJid bareJID, final RosterEntry entry, Presence presence) { + // Move out of an offline group. Add to all groups. + final ContactItem offlineItem = offlineGroup.getContactItemByJID(bareJID); + + if (offlineItem == null) { + return; + } + offlineGroup.removeContactItem(offlineItem); + + // Add To all groups it belongs to. + boolean isFiled = false; + + for (RosterGroup rosterGroup : entry.getGroups()) { + isFiled = true; + ContactGroup contactGroup = getContactGroup(rosterGroup.getName()); + if (contactGroup == null) { + // Create Contact Group + contactGroup = addContactGroup(rosterGroup.getName()); + } + + if (contactGroup != null) { + ContactItem changeContactItem; + if (contactGroup.getContactItemByJID(entry.getJid()) == null) { + ContactItem offlineCurrentItem = contactGroup.getOfflineContactItemByJID(bareJID); + //prevents from duplicating roster contacts when users going offline and online with Offline Group invisible + contactGroup.removeContactItem(offlineCurrentItem); + + // If we are reconnecting, we have to check if we are on the + // dispatch thread + if (EventQueue.isDispatchThread()) { + + changeContactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getJid()); + contactGroup.addContactItem(changeContactItem); + changeContactItem.setAvailable(true); + changeContactItem.setPresence(presence); + changeContactItem.updateAvatarInSideIcon(); + changeContactItem.showUserComingOnline(); + changeContactItem.setSpecialIcon(offlineItem.getSpecialImageLabel().getIcon()); + //contactItem.updatePresenceIcon(contactItem.getPresence()); + toggleGroupVisibility(contactGroup.getGroupName(), true); + //contactGroup.fireContactGroupUpdated(); + + int numberOfMillisecondsInTheFuture = 5000; + Date timeToRun = new Date(System.currentTimeMillis() + + numberOfMillisecondsInTheFuture); + + final ContactItem staticItem = changeContactItem; + final ContactGroup staticGroup = contactGroup; + TaskEngine.getInstance().schedule(new SwingTimerTask() { + @Override + public void doRun() { + staticItem.updatePresenceIcon(staticItem.getPresence()); + staticGroup.fireContactGroupUpdated(); + } + }, timeToRun); + + } else { + + final ContactGroup staticContactGroup = contactGroup; + final Presence staticItemPresence = presence; + + //Reconnection and not in dispatch Thread -> Add to EVentQueue + EventQueue.invokeLater(() -> { + + final ContactItem changeContact = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getJid()); + staticContactGroup.addContactItem(changeContact); + changeContact.setPresence(staticItemPresence); + changeContact.setAvailable(true); + changeContact.updateAvatarInSideIcon(); + changeContact.showUserComingOnline(); + changeContact.setSpecialIcon(offlineItem.getSpecialImageLabel().getIcon()); + changeContact.updatePresenceIcon(changeContact.getPresence()); + toggleGroupVisibility(staticContactGroup.getGroupName(), true); + staticContactGroup.fireContactGroupUpdated(); + + }); + } + } + } + } + + if (!isFiled) { + + + if (unfiledGroup.getContactItemByJID(entry.getJid()) == null) { + // If we are reconnecting, we have to check if we are on the + // dispatch thread + if (EventQueue.isDispatchThread()) { + + contactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getJid()); + ContactGroup unfiledGrp = getUnfiledGroup(); + unfiledGrp.addContactItem(contactItem); + contactItem.setPresence(presence); + contactItem.setAvailable(true); + unfiledGrp.setVisible(true); + unfiledGrp.fireContactGroupUpdated(); + + + } else { + final Presence staticItemPresence = presence; + EventQueue.invokeLater(() -> { + contactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getJid()); + ContactGroup unfiledGrp = getUnfiledGroup(); + + contactItem.setPresence(staticItemPresence); + contactItem.setAvailable(true); + unfiledGrp.addContactItem(contactItem); + contactItem.updatePresenceIcon(contactItem.getPresence()); + unfiledGrp.fireContactGroupUpdated(); + + + }); + + } + + } + } + } + + /** + * Called to build the initial ContactList. + */ + private void buildContactList() { + Log.debug("Building contact list"); + final Roster roster = SparkManager.getRoster(); + + roster.addRosterListener(this); + + // Add All Groups to List + Log.debug("... adding all groups to list"); + for (RosterGroup group : roster.getGroups()) { + Instant start = Instant.now(); + addContactGroup(group.getName()); + Log.debug("... adding group " + group.getName() + " took " + Duration.between(start, Instant.now())); + } + + Log.debug("... iterating over all groups"); + for (RosterGroup group : roster.getGroups()) { + Instant start = Instant.now(); + if (group.getName() == null || Objects.equals(group.getName(), "")) { + for (RosterEntry entry : group.getEntries()) { + + ContactItem buildContactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getJid()); + moveToOffline(buildContactItem); + } + } else { + + ContactGroup contactGroup = getContactGroup(group.getName()); + if (contactGroup == null) { + contactGroup = getUnfiledGroup(); + } + + for (RosterEntry entry : group.getEntries()) { + contactItem = null; + name = entry.getName(); + user = entry.getJid(); + // in case of a connection lost, the creation must be done in the event queue + if (EventQueue.isDispatchThread()) { + contactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getJid()); + } else { + try { + EventQueue.invokeAndWait(() -> contactItem = UIComponentRegistry.createContactItem(name, null, user)); + } catch (Exception ex) { + Log.error("createContactItem error: ", ex); + } + } + + // if there was something wrong, try another + if (contactItem == null) + continue; + + Presence p = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .build(); + contactItem.setPresence(p); + if ((entry.getType() == RosterPacket.ItemType.none || entry.getType() == RosterPacket.ItemType.from) + && entry.isSubscriptionPending()) { + // Add to a contact group. + contactGroup.addContactItem(contactItem); + contactGroup.setVisible(true); + } else { + if (offlineGroup.getContactItemByJID(entry.getJid()) == null) { + moveToOffline(contactItem); + } + } + } + } + + Log.debug("... iterating over group " + group.getName() + " took " + Duration.between(start, Instant.now())); + } + + if (EventQueue.isDispatchThread()) { + // Add Unfiled Group + for (RosterEntry entry : roster.getUnfiledEntries()) { + ContactItem moveToOfflineContactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getJid()); + moveToOffline(moveToOfflineContactItem); + } + } else { + try { + EventQueue.invokeAndWait(() -> { + for (RosterEntry entry : roster.getUnfiledEntries()) { + ContactItem moveToOfflineContactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getJid()); + moveToOffline(moveToOfflineContactItem); + } + }); + } catch (Exception e) { + Log.error("moveToOffline", e); + } + } + Log.debug("Done with contact list"); + } + + private void updateContactList(ContactGroup group) { + if (group != null) { + for (ContactItem item : group.getContactItems()) { + updateUserPresence(PresenceManager.getPresence(item.getJid())); + } + } + + Collection subGroups = group != null ? group.getContactGroups() : this.getContactGroups(); + + for (ContactGroup subGroup : subGroups) { + updateContactList(subGroup); + } + } + + /** + * Called when NEW entries are added. + * + * @param addresses the address added. + */ + @Override + public void entriesAdded(final Collection addresses) { + SwingUtilities.invokeLater(() -> { + Roster roster = SparkManager.getRoster(); + + for (Jid jid : addresses) { + RosterEntry entry = roster.getEntry(jid.asBareJid()); + addUser(entry); + } + }); + } + + /** + * Adds a single user to the ContactList. + * + * @param entry the RosterEntry of the user. + */ + private void addUser(RosterEntry entry) { + ContactItem newContactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getJid()); + + if (entry.getType() == RosterPacket.ItemType.none || entry.getType() == RosterPacket.ItemType.from) { + // Ignore, since the new user is pending to be added. + for (RosterGroup group : entry.getGroups()) { + ContactGroup contactGroup = getContactGroup(group.getName()); + if (contactGroup == null) { + contactGroup = addContactGroup(group.getName()); + } + + boolean isPending = entry.getType() == RosterPacket.ItemType.none || entry.getType() == RosterPacket.ItemType.from + && entry.isSubscriptionPending(); + if (isPending) { + contactGroup.setVisible(true); + } + contactGroup.addContactItem(newContactItem); + + } + return; + } else { + moveToOffline(newContactItem); + } + + // Update user's icon + Presence presence = SparkManager.getRoster().getPresence(entry.getJid()); + try { + updateUserPresence(presence); + } catch (Exception e) { + Log.error(e); + } + } + + /** + * Handle when the Roster changes based on subscription notices. + * + * @param addresses List of entries that were updated. + */ + @Override + public void entriesUpdated(final Collection addresses) { + handleEntriesUpdated(addresses); + } + + /** + * Called when users are removed from the roster. + * + * @param addresses the addresses removed from the roster. + */ + @Override + public void entriesDeleted(final Collection addresses) { + SwingUtilities.invokeLater(() -> { + for (Jid jid : addresses) { + removeContactItem(jid.asBareJid()); + } + }); + + } + + /** + * Handles any presence modifications of a user(s). + * + * @param addresses the Collection of addresses that have been modified within the Roster. + */ + private synchronized void handleEntriesUpdated(final Collection addresses) { + SwingUtilities.invokeLater(() -> { + Roster roster = SparkManager.getRoster(); + + Iterator jids = addresses.iterator(); + while (jids.hasNext()) { + Jid jid = jids.next(); + RosterEntry rosterEntry = roster.getEntry(jid.asBareJid()); + if (rosterEntry != null) { + // Check for new Roster Groups and add them if they do not exist. + boolean isUnfiled = true; + for (RosterGroup group : rosterEntry.getGroups()) { + isUnfiled = false; + + // Handle if this is a new Entry in a new Group. + if (getContactGroup(group.getName()) == null) { + // Create a group. + ContactGroup contactGroup = addContactGroup(group.getName()); + contactGroup.setVisible(false); + contactGroup = getContactGroup(group.getName()); + ContactItem contactItem1 = UIComponentRegistry.createContactItem(rosterEntry.getName(), null, rosterEntry.getJid()); + contactGroup.addContactItem(contactItem1); + Presence presence = PresenceManager.getPresence(jid.asBareJid()); + contactItem1.setPresence(presence); + if (presence.isAvailable()) { + contactGroup.setVisible(true); + } + } else { + ContactGroup contactGroup = getContactGroup(group.getName()); + ContactItem item = offlineGroup.getContactItemByJID(jid.asBareJid()); + if (item == null) { + item = contactGroup.getContactItemByJID(jid.asBareJid()); + } + // Check to see if this entry is new to a pre-existing group. + if (item == null) { + item = UIComponentRegistry.createContactItem(rosterEntry.getName(), null, rosterEntry.getJid()); + Presence presence = PresenceManager.getPresence(jid.asBareJid()); + item.setPresence(presence); + if (presence.isAvailable()) { + contactGroup.addContactItem(item); + contactGroup.fireContactGroupUpdated(); + } else { + moveToOffline(item); + offlineGroup.fireContactGroupUpdated(); + } + } + + // If not, just update their presence. + else { + RosterEntry entry = roster.getEntry(jid.asBareJid()); + Presence presence = PresenceManager.getPresence(jid.asBareJid()); + item.setPresence(presence); + try { + updateUserPresence(presence); + } catch (Exception e) { + Log.error(e); + } + + if (entry != null && (entry.getType() == RosterPacket.ItemType.none || entry.getType() == RosterPacket.ItemType.from) + && entry.isSubscriptionPending()) { + contactGroup.setVisible(true); + + } + contactGroup.fireContactGroupUpdated(); + } + } + } + + // Now check to see if groups have been modified or removed. This is used + // to check if Contact Groups have been renamed or removed. + final Set userGroupSet = new HashSet<>(); + jids = addresses.iterator(); + while (jids.hasNext()) { + jid = jids.next(); + rosterEntry = roster.getEntry(jid.asBareJid()); + + boolean unfiled = true; + for (RosterGroup g : rosterEntry.getGroups()) { + userGroupSet.add(g.getName()); + unfiled = false; + } + + for (ContactGroup group : new ArrayList<>(getContactGroups())) { + ContactItem itemFound = group.getContactItemByJID(jid.asBareJid()); + if (itemFound != null && !unfiled && group != getUnfiledGroup() && group != offlineGroup) { + if (!userGroupSet.contains(group.getGroupName())) { + if (group.getContactItems().isEmpty()) { + removeContactGroup(group); + } else { + group.removeContactItem(itemFound); + } + } + } + + } + } + + + if (!isUnfiled) { + return; + } + + ContactGroup unfiledGrp = getUnfiledGroup(); + ContactItem unfiledItem = unfiledGrp.getContactItemByJID(jid.asBareJid()); + if (unfiledItem == null) { + ContactItem offlineItem = offlineGroup.getContactItemByJID(jid.asBareJid()); + if (offlineItem != null) { + if ((rosterEntry.getType() == RosterPacket.ItemType.none || rosterEntry.getType() == RosterPacket.ItemType.from) + && rosterEntry.isSubscriptionPending()) { + // Remove from offlineItem and add to unfiledItem. + offlineGroup.removeContactItem(offlineItem); + unfiledGrp.addContactItem(offlineItem); + unfiledGrp.fireContactGroupUpdated(); + unfiledGrp.setVisible(true); + } + } + } + } + } + }); + } + + @Override + public void presenceChanged(Presence presence) { + + } + + public ContactItem getContactItemByJID(CharSequence jid) { + BareJid bareJid = JidCreate.bareFromOrThrowUnchecked(jid); + return getContactItemByJID(bareJid); + } + + /** + * Retrieve the ContactItem by its jid. + * + * @param jid the JID of the user. + * @return the "first" contact item found. + */ + public ContactItem getContactItemByJID(BareJid jid) { + for (ContactGroup group : getContactGroups()) { + ContactItem item = group.getContactItemByJID(jid); + if (item != null) { + return item; + } + } + return null; + } + + /** + * Returns a Collection of ContactItems in a ContactList. + * + * @param jid the users JID. + * @return a Collection of ContactItem items. + */ + public Collection getContactItemsByJID(Jid jid) { + final BareJid bareJid = jid.asBareJid(); + final List list = new ArrayList<>(); + for (ContactGroup group : getContactGroups()) { + ContactItem item = group.getContactItemByJID(bareJid); + if (item != null) { + list.add(item); + } + } + // We have to search ContactItems into offline contacts. + // Standard getContactItemByJID() method search ContactItems only in OfflineGroup or into inline contacts + for (ContactGroup group : getContactGroups()) { + for (ContactItem offlineItem : group.getOfflineContacts()) { + if (offlineItem != null && offlineItem.getJid().equals(bareJid)) { + if (!list.contains(offlineItem)) { + list.add(offlineItem); + } + } + } + } + + return list; + } + + /** + * Set an Icon for all ContactItems that match the given jid. + * + * @param jid the users jid. + * @param icon the icon to use. + */ + public void setIconFor(Jid jid, Icon icon) { + for (ContactGroup group : getContactGroups()) { + ContactItem item = group.getContactItemByJID(jid.asBareJid()); + if (item != null) { + item.setIcon(icon); + group.fireContactGroupUpdated(); + } + } + } + + /** + * Sets the default settings for a ContactItem. + * + * @param jid the users jid. + */ + public void useDefaults(Jid jid) { + for (ContactGroup group : getContactGroups()) { + ContactItem item = group.getContactItemByJID(jid.asBareJid()); + if (item != null) { + item.updatePresenceIcon(item.getPresence()); + group.fireContactGroupUpdated(); + } + } + } + + + /** + * Retrieve the ContactItem by their displayed name (either alias, nickname or username). + * + * @param displayName the users nickname in the contact list. + * @return the "first" contact item found. + */ + public ContactItem getContactItemByDisplayName(CharSequence displayName) { + for (ContactGroup contactGroup : getContactGroups()) { + ContactItem item = contactGroup.getContactItemByDisplayName(displayName); + if (item != null) { + return item; + } + } + return null; + } + + /** + * Adds a new ContactGroup to the ContactList. + * + * @param group the group to add. + */ + private void addContactGroup(ContactGroup group) { + groupList.add(group); + + groupList.sort(GROUP_COMPARATOR); + + try { + mainPanel.add(group, groupList.indexOf(group)); + } catch (Exception e) { + Log.error(e); + } + + group.addContactGroupListener(this); + + fireContactGroupAdded(group); + + // Check state + String prop = props.getProperty(group.getGroupName()); + if (prop != null) { + boolean isCollapsed = Boolean.parseBoolean(prop); + group.setCollapsed(isCollapsed); + } + } + + /** + * Creates and adds a new ContactGroup to the ContactList. + * + * @param groupName the name of the ContactGroup to add. + * @return the newly created ContactGroup. + */ + private ContactGroup addContactGroup(String groupName) { + StringTokenizer tkn = new StringTokenizer(groupName, GROUP_DELIMITER); + + ContactGroup rootGroup = null; + ContactGroup lastGroup = null; + StringBuilder buf = new StringBuilder(); + + boolean groupAdded = false; + while (tkn.hasMoreTokens()) { + String group = tkn.nextToken(); + buf.append(group); + if (tkn.hasMoreTokens()) { + buf.append("::"); + } + + String name = buf.toString(); + if (name.endsWith("::")) { + name = name.substring(0, name.length() - 2); + } + + ContactGroup newContactGroup = getContactGroup(name); + + + if (newContactGroup == null) { + newContactGroup = UIComponentRegistry.createContactGroup(group); + + String realGroupName = buf.toString(); + if (realGroupName.endsWith("::")) { + realGroupName = realGroupName.substring(0, realGroupName.length() - 2); + } + + newContactGroup.setGroupName(realGroupName); + } else { + if (newContactGroup != offlineGroup && newContactGroup != getUnfiledGroup()) { + rootGroup = newContactGroup; + continue; + } + } + + + if (lastGroup != null) { + lastGroup.addContactGroup(newContactGroup); + groupList.add(newContactGroup); + } else if (rootGroup != null) { + rootGroup.addContactGroup(newContactGroup); + groupList.add(newContactGroup); + } else { + rootGroup = newContactGroup; + } + + lastGroup = newContactGroup; + + + newContactGroup.addContactGroupListener(this); + + if (sharedGroups != null) { + boolean isSharedGroup = sharedGroups.contains(newContactGroup.getGroupName()); + newContactGroup.setSharedGroup(isSharedGroup); + } + + fireContactGroupAdded(newContactGroup); + + // Check state + + String prop = props.getProperty(newContactGroup.getGroupName()); + if (prop != null) { + boolean isCollapsed = Boolean.parseBoolean(prop); + newContactGroup.setCollapsed(isCollapsed); + } + + + groupAdded = true; + } + + if (!groupAdded) { + return getContactGroup(groupName); + } + + + final List tempList = new ArrayList<>(); + final Component[] comps = mainPanel.getComponents(); + for (Component c : comps) { + if (c instanceof ContactGroup && c != offlineGroup) { + tempList.add((ContactGroup) c); + } + } + tempList.add(rootGroup); + + + groupList.add(rootGroup); + + tempList.sort(GROUP_COMPARATOR); + + int loc = tempList.indexOf(rootGroup); + + + try { + mainPanel.add(rootGroup, loc); + } catch (Exception e) { + Log.error(e); + } + + // Check if I should show groups with no users online + if (null != getContactGroup(groupName) && !getContactGroup(groupName).hasAvailableContacts()) { + showEmptyGroups(localPreferences.isEmptyGroupsShown()); + } + + + return getContactGroup(groupName); + + } + + /** + * Removes a ContactGroup from the group model and ContactList. + * + * @param contactGroup the ContactGroup to remove. + */ + private void removeContactGroup(ContactGroup contactGroup) { + contactGroup.removeContactGroupListener(this); + groupList.remove(contactGroup); + mainPanel.remove(contactGroup); + + ContactGroup parent = getParentGroup(contactGroup.getGroupName()); + if (parent != null) { + parent.removeContactGroup(contactGroup); + } + + contactListScrollPane.validate(); + mainPanel.invalidate(); + mainPanel.repaint(); + + fireContactGroupRemoved(contactGroup); + } + + + /** + * Returns a ContactGroup based on its name. + * + * @param groupName the name of the ContactGroup. + * @return the ContactGroup. If no ContactGroup is found, null is returned. + */ + public ContactGroup getContactGroup(String groupName) { + ContactGroup cGroup = null; + + for (ContactGroup contactGroup : groupList) { + if (contactGroup.getGroupName().equals(groupName)) { + cGroup = contactGroup; + break; + } else { + cGroup = getSubContactGroup(contactGroup, groupName); + if (cGroup != null) { + break; + } + } + } + + return cGroup; + } + + /** + * For traversing of a nested group. Allows users to find the owning parent of a given contact group. + * + * @param groupName the name of the nested contact group. + * @return the parent ContactGroup. If no parent, null will be returned. + */ + public ContactGroup getParentGroup(String groupName) { + // Check if there is even a parent group + if (!groupName.contains("::")) { + return null; + } + + final ContactGroup group = getContactGroup(groupName); + if (group == null) { + return null; + } + + // Otherwise, find the parent + int index = groupName.lastIndexOf("::"); + String parentGroupName = groupName.substring(0, index); + return getContactGroup(parentGroupName); + } + + /** + * Returns the nested ContactGroup of a given ContactGroup with an associated name. + * + * @param group the parent ContactGroup. + * @param groupName the name of the nested group. + * @return the nested ContactGroup. If not found, null will be returned. + */ + private ContactGroup getSubContactGroup(ContactGroup group, String groupName) { + ContactGroup grp = null; + + for (ContactGroup contactGroup : group.getContactGroups()) { + if (contactGroup.getGroupName().equals(groupName)) { + grp = contactGroup; + break; + } else if (!contactGroup.getContactGroups().isEmpty()) { + grp = getSubContactGroup(contactGroup, groupName); + if (grp != null) { + break; + } + } + + } + return grp; + } + + /** + * Toggles the visibility of a ContactGroup. + * + * @param groupName the name of the ContactGroup. + * @param visible true to show, otherwise false. + */ + public void toggleGroupVisibility(String groupName, boolean visible) { + StringTokenizer tkn = new StringTokenizer(groupName, GROUP_DELIMITER); + while (tkn.hasMoreTokens()) { + String group = tkn.nextToken(); + ContactGroup contactGroup = getContactGroup(group); + if (contactGroup != null) { + contactGroup.setVisible(visible); + } + } + + ContactGroup group = getContactGroup(groupName); + if (group != null) { + group.setVisible(visible); + } + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource() == addingGroupButton) { + new RosterDialog().showRosterDialog(); + } else if (e.getSource() == chatMenu) { + if (activeItem != null) { + SparkManager.getChatManager().activateChat(activeItem.getJid(), activeItem.getDisplayName()); + } + } else if (e.getSource() == addContactMenu) { + RosterDialog rosterDialog = new RosterDialog(); + if (activeGroup != null) { + rosterDialog.setDefaultGroup(activeGroup); + } + rosterDialog.showRosterDialog(); + } else if (e.getSource() == removeContactFromGroupMenu) { + if (activeItem != null) { + removeContactFromGroup(activeItem); + } + } else if (e.getSource() == renameMenu) { + if (activeItem == null) { + return; + } + + String oldAlias = activeItem.getAlias(); + String newAlias = JOptionPane.showInputDialog(this, Res.getString("label.rename.to") + ":", oldAlias); + + // if the user pressed 'cancel', the output will be null. + // if the user removed alias, the output will be an empty String. + if (newAlias != null) { + if (!ModelUtil.hasLength(newAlias)) { + newAlias = null; // allows you to remove an alias. + } + + BareJid address = activeItem.getJid().asBareJid(); + ContactGroup contactGroup = getContactGroup(activeItem.getGroupName()); + ContactItem contactItem = contactGroup.getContactItemByDisplayName(activeItem.getDisplayName()); + contactItem.setAlias(newAlias); + + final Roster roster = SparkManager.getRoster(); + RosterEntry entry = roster.getEntry(address); + try { + entry.setName(newAlias); + + final BareJid user = address.asBareJid(); + for (ContactGroup cg : groupList) { + ContactItem ci = cg.getContactItemByJID(user); + if (ci != null) { + ci.setAlias(newAlias); + } + } + } catch (XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException | InterruptedException e1) { + Log.warning("Unable to set new alias '" + newAlias + "' for roster entry " + address, e1); + } + } + } + } + + + /** + * Removes a contact item from the group. + * + * @param item the ContactItem to remove. + */ + private void removeContactFromGroup(ContactItem item) { + String groupName = item.getGroupName(); + ContactGroup contactGroup = getContactGroup(groupName); + Roster roster = SparkManager.getRoster(); + RosterEntry entry = roster.getEntry(item.getJid().asBareJid()); + if (entry != null && contactGroup != offlineGroup) { + try { + RosterGroup rosterGroup = roster.getGroup(groupName); + if (rosterGroup != null) { + RosterEntry rosterEntry = rosterGroup.getEntry(entry.getJid()); + if (rosterEntry != null) { + rosterGroup.removeEntry(rosterEntry); + } + } + contactGroup.removeContactItem(contactGroup.getContactItemByJID(item.getJid())); + checkGroup(contactGroup); + } catch (Exception e) { + Log.error("Error removing user from contact list.", e); + } + } + } + + private void removeContactFromRoster(ContactItem item) { + Roster roster = SparkManager.getRoster(); + RosterEntry entry = roster.getEntry(item.getJid().asBareJid()); + if (entry != null) { + try { + roster.removeEntry(entry); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.warning("Unable to remove roster entry.", e); + } + } + } + + private void removeContactItem(BareJid jid) { + for (ContactGroup group : new ArrayList<>(getContactGroups())) { + ContactItem item = group.getContactItemByJID(jid); + group.removeOfflineContactItem(jid); + if (item != null) { + group.removeContactItem(item); + checkGroup(group); + } + } + } + + @Override + public void contactItemClicked(ContactItem item) { + activeItem = item; + + if (activeKeyEvent == null || ((activeKeyEvent.getModifiers() & KeyEvent.CTRL_MASK) == 0)) { + clearSelectionList(item); + } + + + fireContactItemClicked(item); + activeKeyEvent = null; + } + + @Override + public void contactItemDoubleClicked(ContactItem item) { + activeItem = item; + + ChatManager chatManager = SparkManager.getChatManager(); + boolean handled = chatManager.fireContactItemDoubleClicked(item); + + if (!handled) { + chatManager.activateChat(item.getJid().asUnescapedString(), item.getDisplayName()); + } + + clearSelectionList(item); + + fireContactItemDoubleClicked(item); + } + + @Override + public void contactGroupPopup(MouseEvent e, final ContactGroup group) { + // Do nothing with an offline group + if (group == offlineGroup || group == getUnfiledGroup()) { + return; + } + + + final JPopupMenu popup = new JPopupMenu(); + if (!Default.getBoolean(Default.ADD_CONTACT_DISABLED) && Enterprise.containsFeature(Enterprise.ADD_CONTACTS_FEATURE)) + popup.add(addContactMenu); + + if (!Default.getBoolean(Default.ADD_CONTACT_GROUP_DISABLED) && Enterprise.containsFeature(Enterprise.ADD_GROUPS_FEATURE)) + popup.add(addContactGroupMenu); + + popup.addSeparator(); + + fireContextMenuListenerPopup(popup, group); + + JMenuItem delete = new JMenuItem(Res.getString("menuitem.delete")); + JMenuItem rename = new JMenuItem(Res.getString("menuitem.rename")); + JMenuItem expand = new JMenuItem(Res.getString("menuitem.expand.all.groups")); + JMenuItem collapse = new JMenuItem(Res.getString("menuitem.collapse.all.groups")); + + if (!group.isSharedGroup()) { + popup.addSeparator(); + + // See if we should disable the "Delete" menu option + if (!Default.getBoolean(Default.DISABLE_REMOVALS) && Enterprise.containsFeature(Enterprise.REMOVALS_FEATURE)) + popup.add(delete); + + // See if we should disable the "Rename" menu option + if (!Default.getBoolean(Default.DISABLE_RENAMES) && Enterprise.containsFeature(Enterprise.RENAMES_FEATURE)) + popup.add(rename); + } + + // Only display a horizontal separator if at least one of those options is present + final boolean allowRemovals = (!Default.getBoolean(Default.DISABLE_REMOVALS) && Enterprise.containsFeature(Enterprise.REMOVALS_FEATURE)); + final boolean allowRenames = (!Default.getBoolean(Default.DISABLE_RENAMES) && Enterprise.containsFeature(Enterprise.RENAMES_FEATURE)); + if (allowRemovals || allowRenames) popup.addSeparator(); + + popup.add(expand); + popup.add(collapse); + + delete.addActionListener(e1 -> { + UIManager.put("OptionPane.yesButtonText", Res.getString("yes")); + UIManager.put("OptionPane.noButtonText", Res.getString("no")); + UIManager.put("OptionPane.cancelButtonText", Res.getString("cancel")); + int ok = JOptionPane.showConfirmDialog(group, Res.getString("message.delete.confirmation", group.getGroupName()), Res.getString("title.confirmation"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + if (ok == JOptionPane.YES_OPTION) { + String groupName = group.getGroupName(); + Roster roster = SparkManager.getRoster(); + + RosterGroup rosterGroup = roster.getGroup(groupName); + if (rosterGroup != null) { + for (RosterEntry entry : rosterGroup.getEntries()) { + try { + rosterGroup.removeEntry(entry); + } catch (XMPPException | SmackException | InterruptedException ex) { + Log.error("Error removing entry", ex); + } + } + } + + // Remove from UI + removeContactGroup(group); + invalidate(); + repaint(); + } + + }); + + + rename.addActionListener(e1 -> { + String newName = JOptionPane.showInputDialog(group, Res.getString("label.rename.to") + ":", Res.getString("title.rename.roster.group"), JOptionPane.QUESTION_MESSAGE); + if (!ModelUtil.hasLength(newName)) { + return; + } + String groupName = group.getGroupName(); + Roster roster = SparkManager.getRoster(); + + RosterGroup rosterGroup = roster.getGroup(groupName); + //Do not remove ContactGroup if the name entered was the same + if (rosterGroup != null && !groupName.equals(newName)) { + try { + rosterGroup.setName(newName); + removeContactGroup(group); + addContactGroup(newName); + toggleGroupVisibility(newName, true); + getContactGroup(newName).setCollapsed(group.isCollapsed()); + } catch (XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException | InterruptedException ex) { + Log.warning("Unable to set new name '" + newName + "' for roster group" + groupName, ex); + } + } + + }); + expand.addActionListener(e1 -> { + Collection groups = getContactGroups(); + for (ContactGroup group1 : groups) { + group1.setCollapsed(false); + } + }); + + collapse.addActionListener(e1 -> { + Collection groups = getContactGroups(); + for (ContactGroup group1 : groups) { + group1.setCollapsed(true); + } + }); + + // popup.add(inviteFirstAcceptor); + popup.show(group, e.getX(), e.getY()); + + activeGroup = group; + } + + + @Override + public void showPopup(MouseEvent e, final ContactItem item) { + showPopup(null, e, item); + } + + /** + * Shows a popup for right-clicking of ContactItem. + * + * @param e the MouseEvent + * @param item the ContactItem + * @param component the owning component + */ + public void showPopup(Component component, MouseEvent e, final ContactItem item) { + if (item.getJid() == null) { + return; + } + + activeItem = item; + + final JPopupMenu popup = new JPopupMenu(); + + // Add Start Chat Menu + popup.add(chatMenu); + + // Add Send File Action + Action sendAction = new AbstractAction() { + private static final long serialVersionUID = -7519717310558205566L; + + @Override + public void actionPerformed(ActionEvent actionEvent) { + SparkManager.getTransferManager().sendFileTo(item); + } + }; + + // See if we should disable the option to transfer files and images + if (!Default.getBoolean(Default.DISABLE_FILE_TRANSFER) && Enterprise.containsFeature(Enterprise.FILE_TRANSFER_FEATURE)) { + sendAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.DOCUMENT_16x16)); + sendAction.putValue(Action.NAME, Res.getString("menuitem.send.a.file")); + if (item.getPresence() != null) popup.add(sendAction); + } + + popup.addSeparator(); + + String groupName = item.getGroupName(); + ContactGroup contactGroup = getContactGroup(groupName); + if (contactGroup == null) { + Log.error("Unable to get contact group for " + groupName); + } + + // Only show "Remove Contact From Group" if the user belongs to more than one group. + if (contactGroup != null && !contactGroup.isSharedGroup() && !contactGroup.isOfflineGroup() && contactGroup != getUnfiledGroup()) { + Roster roster = SparkManager.getRoster(); + RosterEntry entry = roster.getEntry(item.getJid().asBareJid()); + if (entry != null) { + int groupCount = entry.getGroups().size(); + + //todo: It should be possible to remove a user from the only group they're in + // which would put them into the unfiled group. + if (groupCount > 1) { + popup.add(removeContactFromGroupMenu); + } + + } + } + + // Define remove entry action + Action removeAction = new AbstractAction() { + private static final long serialVersionUID = -2565914214685979320L; + + @Override + public void actionPerformed(ActionEvent e) { + removeContactFromRoster(item); + } + }; + + removeAction.putValue(Action.NAME, Res.getString("menuitem.remove.from.roster")); + removeAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_CIRCLE_DELETE)); + + // Check if a user is in a shared group. + boolean isInSharedGroup = false; + for (ContactGroup cGroup : new ArrayList<>(getContactGroups())) { + if (cGroup.isSharedGroup()) { + ContactItem it = cGroup.getContactItemByJID(item.getJid().asBareJid()); + if (it != null) { + isInSharedGroup = true; + } + } + } + + // See if we should disable the option to remove a contact + if (!Default.getBoolean(Default.DISABLE_REMOVALS) && Enterprise.containsFeature(Enterprise.REMOVALS_FEATURE)) { + if (contactGroup != null && !contactGroup.isSharedGroup() && !isInSharedGroup) { + popup.add(removeAction); + } + } + + // See if we should disable the option to rename a contact + if (!Default.getBoolean(Default.DISABLE_RENAMES) && Enterprise.containsFeature(Enterprise.RENAMES_FEATURE)) + popup.add(renameMenu); + + Action viewProfile = new AbstractAction() { + private static final long serialVersionUID = -2562731455090634805L; + + @Override + public void actionPerformed(ActionEvent e) { + VCardManager vcardSupport = SparkManager.getVCardManager(); + BareJid jid = item.getJid().asBareJid(); + vcardSupport.viewProfile(jid, SparkManager.getWorkspace()); + } + }; + viewProfile.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.PROFILE_IMAGE_16x16)); + viewProfile.putValue(Action.NAME, Res.getString("menuitem.view.profile")); + + popup.add(viewProfile); + + + popup.addSeparator(); + + Action lastActivityAction = new AbstractAction() { + private static final long serialVersionUID = -4884230635430933060L; + + @Override + public void actionPerformed(ActionEvent actionEvent) { + try { + String client = ""; + if (item.getPresence().getType() != Presence.Type.unavailable) { + client = item.getPresence().getFrom().toString(); + if ((client != null) && (client.lastIndexOf("/") != -1)) { + client = client.substring(client.lastIndexOf("/")); + } else client = "/"; + } + + Jid jid = JidCreate.from(item.getJid().toString() + client); + LastActivity activity = LastActivityManager.getInstanceFor(SparkManager.getConnection()).getLastActivity(jid); + long idleTime = (activity.getIdleTime() * 1000); + String time = ModelUtil.getTimeFromLong(idleTime); + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(getGUI(), Res.getString("message.idle.for", time), Res.getString("title.last.activity"), JOptionPane.INFORMATION_MESSAGE); + } catch (Exception e1) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(getGUI(), Res.getString("message.unable.to.retrieve.last.activity", item.getJid()), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + } + + } + }; + + lastActivityAction.putValue(Action.NAME, Res.getString("menuitem.view.last.activity")); + lastActivityAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.HISTORY_16x16)); + + if (contactGroup == offlineGroup || item.getPresence().isAway() || (item.getPresence().getType() == Presence.Type.unavailable) || (item.getPresence().getType() == null)) { + popup.add(lastActivityAction); + } + + Action subscribeAction = new AbstractAction() { + private static final long serialVersionUID = -7754905015338902300L; + + @Override + public void actionPerformed(ActionEvent e) { + BareJid jid = item.getJid(); + Presence response = StanzaBuilder.buildPresence() + .ofType(Presence.Type.subscribe) + .build(); + response.setTo(jid); + + try { + SparkManager.getConnection().sendStanza(response); + } catch (SmackException.NotConnectedException | InterruptedException e1) { + Log.warning("Unable to send subscribe to " + jid, e1); + } + } + }; + + subscribeAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_USER1_INFORMATION)); + subscribeAction.putValue(Action.NAME, Res.getString("menuitem.subscribe.to")); + + Roster roster = SparkManager.getRoster(); + RosterEntry entry = roster.getEntry(item.getJid().asBareJid()); + if (entry != null && entry.getType() == RosterPacket.ItemType.from) { + popup.add(subscribeAction); + } else if (entry != null && entry.getType() != RosterPacket.ItemType.both && entry.isSubscriptionPending()) { + popup.add(subscribeAction); + } + + // Fire Context Menu Listener + fireContextMenuListenerPopup(popup, item); + + ContactGroup group = getContactGroup(item.getGroupName()); + if (component == null) { + popup.show(group.getList(), e.getX(), e.getY()); + } else { + popup.show(component, e.getX(), e.getY()); + popup.requestFocus(); + } + } + + @Override + public void showPopup(MouseEvent e, final Collection items) { + ContactGroup group = null; + for (ContactItem item : items) { + group = getContactGroup(item.getGroupName()); + break; + } + + + final JPopupMenu popup = new JPopupMenu(); + final JMenuItem sendMessagesMenu = new JMenuItem(Res.getString("menuitem.send.a.message"), SparkRes.getImageIcon(SparkRes.Icon.SMALL_MESSAGE_IMAGE)); + + fireContextMenuListenerPopup(popup, items); + + // See if we should disable all "Broadcast" menu items + if (!Default.getBoolean(Default.DISABLE_BROADCAST_MENU_ITEM) && Enterprise.containsFeature(Enterprise.BROADCAST_FEATURE)) + popup.add(sendMessagesMenu); + + sendMessagesMenu.addActionListener(e1 -> sendMessages(items)); + + try { + popup.show(group.getList(), e.getX(), e.getY()); + } catch (NullPointerException ee) { + // Nothing we can do here + } + } + + private void clearSelectionList(ContactItem selectedItem) { + // Check for null. In certain cases the event triggering the model might + // not find the selected object. + if (selectedItem == null) { + return; + } + + final ContactGroup owner = getContactGroup(selectedItem.getGroupName()); + for (ContactGroup contactGroup : new ArrayList<>(groupList)) { + if (owner != contactGroup) { + contactGroup.clearSelection(); + } + } + } + + + private void sendMessages(Collection items) { + InputDialog dialog = new InputDialog(); + final String messageText = dialog.getInput(Res.getString("title.broadcast.message"), Res.getString("message.enter.broadcast.message"), SparkRes.getImageIcon(SparkRes.Icon.BLANK_IMAGE), SparkManager.getMainWindow()); + if (!ModelUtil.hasLength(messageText)) { + return; + } + StringBuilder buf = new StringBuilder(); + final Map broadcastMessages = new HashMap<>(); + for (ContactItem item : items) { + MessageBuilder messageBuilder = StanzaBuilder.buildMessage(); + final Map properties = new HashMap<>(); + properties.put("broadcast", true); + messageBuilder.addExtension(new JivePropertiesExtension(properties)); + messageBuilder.setBody(messageText); + + Message message = messageBuilder.build(); + message.setTo(item.getJid()); + if (broadcastMessages.putIfAbsent(item.getJid().toString(), message) == null) { + buf.append(item.getDisplayName()).append('\n'); + } + } + + for (Message message : broadcastMessages.values()) { + try { + SparkManager.getConnection().sendStanza(message); + } catch (SmackException.NotConnectedException | InterruptedException e) { + Log.warning("Unable to send broadcast to " + message.getTo(), e); + } + } + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(SparkManager.getMainWindow(), Res.getString("message.hasbeenbroadcast.to", buf.toString()), Res.getString("title.notification"), JOptionPane.INFORMATION_MESSAGE); + } + + // For plugin use only + + @Override + public void initialize() { + Log.debug("Initializing contact list"); + this.setBorder(BorderFactory.createEmptyBorder()); + + // Add Contact List + addContactListToWorkspace(); + + // Hide the top toolbar + SparkManager.getMainWindow().getTopToolBar().setVisible(false); + + final Runnable sharedGroupLoader = () -> { + // Retrieve shared group list. + try { + sharedGroups = SharedGroupManager.getSharedGroups(SparkManager.getConnection()); + } catch (XMPPErrorException e) { + StanzaError stanzaError = e.getStanzaError(); + if (stanzaError.getCondition() == Condition.service_unavailable) { + // Server does not support shared groups. + return; + } + Log.error("Unable to contact shared group info.", e); + } catch (SmackException | InterruptedException e) { + Log.error("Unable to contact shared group info.", e); + } + }; + + SwingUtilities.invokeLater(this::loadContactList); + TaskEngine.getInstance().submit(sharedGroupLoader); + } + + private void loadContactList() { + + // Build the initial contact list. + buildContactList(); + + boolean show = localPreferences.isEmptyGroupsShown(); + + // Hide all groups initially + showEmptyGroups(show); + + // Hide all Offline Users + showOfflineUsers(localPreferences.isOfflineUsersShown()); + + // Add a subscription listener. + addSubscriptionListener(); + + // Load all plugins + SparkManager.getWorkspace().loadPlugins(); + + } + + public void addSubscriptionListener() { + // Sometimes, presence changes happen in rapid succession (for instance, when initially connecting). To avoid + // having a lot of UI-updates (which are costly), this queue is used to create a short buffer, allowing us to + // group UI updates in batches. + final ConcurrentLinkedQueue presenceBuffer = new ConcurrentLinkedQueue<>(); + final long bufferTimeMS = 500; + + final StanzaListener subscribeListener = stanza -> + { + final Presence presence = (Presence) stanza; + final Roster roster = SparkManager.getRoster(); + final RosterEntry entry = roster.getEntry(presence.getFrom().asBareJid()); + + switch (presence.getType()) { + case subscribe: + // Someone else wants to subscribe to our presence. Ask user for approval + SwingUtilities.invokeLater(() -> + { + try { + subscriptionRequest(presence.getFrom().asBareJid()); + } catch (SmackException.NotConnectedException | InterruptedException e) { + Log.warning("Unable to process subscription request from: " + presence.getFrom(), e); + } + }); + break; + + case unsubscribe: + // Someone else is removing their subscription to our presence (we're removed from their roster). + if (entry != null) { + try { + removeContactItem(presence.getFrom().asBareJid()); + roster.removeEntry(entry); + } catch (XMPPException | SmackException e) { + Presence unsub = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unsubscribed) + .build(); + unsub.setTo(presence.getFrom()); + try { + SparkManager.getConnection().sendStanza(unsub); + } catch (SmackException.NotConnectedException e1) { + Log.warning("Unable to unsubscribe from " + unsub.getTo(), e1); + } + Log.error(e); + } + } + break; + + case subscribed: + // Someone else approved our request to be subscribed to their presence information. + final BareJid jid = presence.getFrom().asBareJid(); + final ContactItem item = getContactItemByJID(jid.toString()); + + // If an item is not in the Contact List, add them. + if (item == null && entry != null) { + final ContactItem newItem = UIComponentRegistry.createContactItem(entry.getName(), null, jid); + moveToOffline(newItem); + offlineGroup.fireContactGroupUpdated(); + } + break; + + case unsubscribed: + // Someone is telling us that we're no longer subscribed to their presence information. + SwingUtilities.invokeLater(() -> + { + if (entry != null) { + try { + removeContactItem(presence.getFrom().asBareJid()); + roster.removeEntry(entry); + } catch (Throwable e) { + Log.error("Unable to process 'unsubscribed'", e); + } + } + removeContactItem(presence.getFrom().asBareJid().asBareJid()); + }); + break; + + default: + // Any other presence updates. These are likely regular presence changes, not subscription-state changes. + presenceBuffer.add(presence); + + TaskEngine.getInstance().schedule(new TimerTask() { + @Override + public void run() { + SwingUtilities.invokeLater(() -> + { + final Iterator iterator = presenceBuffer.iterator(); + while (iterator.hasNext()) { + final Presence presence = iterator.next(); + try { + updateUserPresence(presence); + } catch (Exception e) { + Log.warning("Unable to process this presence update that was received: " + presence, e); + } finally { + iterator.remove(); + } + } + }); + } + }, bufferTimeMS); + break; + } + }; + + SparkManager.getConnection().addAsyncStanzaListener(subscribeListener, new StanzaTypeFilter(Presence.class)); + } + + + @Override + public void shutdown() { + saveState(); + } + + @Override + public boolean canShutDown() { + return true; + } + + private void addContactListToWorkspace() { + Workspace workspace = SparkManager.getWorkspace(); + workspace.getWorkspacePane().addTab(Res.getString("tab.contacts"), SparkRes.getImageIcon(SparkRes.Icon.SMALL_ALL_CHATS_IMAGE), this); + // Add To Contacts Menu + final JMenu contactsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.contacts")); + JMenuItem addContactsMenu = new JMenuItem("", SparkRes.getImageIcon(SparkRes.Icon.USER1_ADD_16x16)); + ResourceUtils.resButton(addContactsMenu, Res.getString("menuitem.add.contact")); + ResourceUtils.resButton(addContactGroupMenu, Res.getString("menuitem.add.contact.group")); + + if (!Default.getBoolean(Default.ADD_CONTACT_DISABLED) && Enterprise.containsFeature(Enterprise.ADD_CONTACTS_FEATURE)) + contactsMenu.add(addContactsMenu); + + if (!Default.getBoolean(Default.ADD_CONTACT_GROUP_DISABLED) && Enterprise.containsFeature(Enterprise.ADD_GROUPS_FEATURE)) + contactsMenu.add(addContactGroupMenu); + + addContactsMenu.addActionListener(e -> new RosterDialog().showRosterDialog()); + + addContactGroupMenu.addActionListener(e -> { + String groupName = JOptionPane.showInputDialog(getGUI(), Res.getString("message.name.of.group") + ":", Res.getString("title.add.new.group"), JOptionPane.QUESTION_MESSAGE); + if (ModelUtil.hasLength(groupName)) { + ContactGroup contactGroup = getContactGroup(groupName); + if (contactGroup == null) { + contactGroup = addContactGroup(groupName); + contactGroup.setVisible(true); + //validateTree(); + repaint(); + } + } + }); + + // Add Toggle Contacts Menu + ResourceUtils.resButton(showHideMenu, Res.getString("menuitem.show.empty.groups")); + contactsMenu.add(showHideMenu); + + showHideMenu.addActionListener(e -> showEmptyGroups(showHideMenu.isSelected())); + + ResourceUtils.resButton(showOfflineGroupMenu, Res.getString("menuitem.show.offline.group")); + contactsMenu.add(showOfflineGroupMenu); + + showOfflineGroupMenu.addActionListener(actionEvent -> showOfflineGroup(showOfflineGroupMenu.isSelected())); + + ResourceUtils.resButton(showOfflineUsersMenu, Res.getString("menuitem.show.offline.users")); + contactsMenu.add(showOfflineUsersMenu); + + showOfflineUsersMenu.addActionListener(actionEvent -> showOfflineUsers(showOfflineUsersMenu.isSelected())); + + // Show or Hide Offline Group + showOfflineGroupMenu.setSelected(localPreferences.isOfflineGroupVisible()); + showOfflineGroup(localPreferences.isOfflineGroupVisible()); + + // sets showOfflineUsersMenu selected or not selected + showOfflineUsersMenu.setSelected(localPreferences.isOfflineUsersShown()); + + // Initialize vcard support + SparkManager.getVCardManager(); + } + + /** + * Toggles the visibility of empty groups. + * + * @param show true to display empty contact groups within the ContactList, otherwise false. + */ + private void showEmptyGroups(boolean show) { + for (ContactGroup group : getContactGroups()) { + if (group != offlineGroup) { + if (show) { + group.setVisible(true); + } else { + // Never hide an offline group. + group.setVisible(group.hasAvailableContacts()); + } + } + } + + localPreferences.setEmptyGroupsShown(show); + showHideMenu.setSelected(show); + } + + private void showOfflineUsers(boolean show) { + for (ContactGroup group : getContactGroups()) { + if (group != offlineGroup) { + group.toggleOfflineVisibility(show); + } + + if (group == offlineGroup) { + if (show) { + group.setVisible(true); + showOfflineGroupMenu.setEnabled(true); + showOfflineGroupMenu.setSelected(localPreferences.isOfflineGroupVisible()); + showOfflineGroup(showOfflineGroupMenu.isSelected()); + } else { + group.setVisible(false); + showOfflineGroupMenu.setEnabled(false); + } + } + } + localPreferences.setOfflineUsersShown(show); + } + + /** + * Toggles the visibility of the Offline Group. + * + * @param show true to display the offline group, otherwise false. + */ + private void showOfflineGroup(boolean show) { + // Save in preferences + localPreferences.setOfflineGroupVisible(show); + // Toggle Visibility of Offline Group. + offlineGroup.setVisible(show); + + if (show) { + // Remove offline items from all groups. + for (ContactGroup group : getContactGroups()) { + group.toggleOfflineVisibility(false); + } + } else { + // Remove offline items from all groups. + for (ContactGroup group : getContactGroups()) { + group.toggleOfflineVisibility(true); + } + } + } + + + /** + * Sorts ContactGroups + */ + public static final Comparator GROUP_COMPARATOR = (group1, group2) -> { + // Make sure that an offline group is always on the bottom. + if (group2.isOfflineGroup()) { + return -1; + } + + return group1.getGroupName().trim().compareToIgnoreCase(group2.getGroupName().trim()); + }; + + public JPanel getMainPanel() { + return mainPanel; + } + + public List getContactGroups() { + final List gList = new ArrayList<>(groupList); + gList.sort(GROUP_COMPARATOR); + return gList; + } + + private void subscriptionRequest(final BareJid jid) throws SmackException.NotConnectedException, InterruptedException { + final SubscriptionDialog subscriptionDialog = new SubscriptionDialog(); + subscriptionDialog.invoke(jid); + } + + public void addContextMenuListener(ContextMenuListener listener) { + contextListeners.addIfAbsent(listener); + } + + public void removeContextMenuListener(ContextMenuListener listener) { + contextListeners.remove(listener); + } + + public void fireContextMenuListenerPopup(JPopupMenu popup, Object object) { + for (final ContextMenuListener listener : contextListeners) { + try { + listener.poppingUp(object, popup); + } catch (Exception e) { + Log.error("A ContextMenuListener (" + listener + ") threw an exception while processing a 'popingUp' event for object: " + object, e); + } + } + } + + public JComponent getGUI() { + return this; + } + + public ContactGroup getActiveGroup() { + return activeGroup; + } + + public Collection getSelectedUsers() { + final List list = new ArrayList<>(); + + for (ContactGroup group : getContactGroups()) { + list.addAll(group.getSelectedContacts()); + } + return list; + } + + /** + * Selects the first user found with a specified jid + * @param jid, the Users JID + */ + public void setSelectedUser(BareJid jid) { + for (ContactGroup group : getContactGroups()) { + if (group.getContactItemByJID(jid) != null) { + + ContactItem item = group.getContactItemByJID(jid); + group.getList().setSelectedValue(item, false); + return; + } + } + } + + private void checkGroup(final ContactGroup group) { + try { + EventQueue.invokeLater(() -> { + if (!group.hasAvailableContacts() && group != offlineGroup && group != getUnfiledGroup() && !showHideMenu.isSelected()) { + group.setVisible(false); + } + }); + } catch (Exception e) { + Log.error("checkGroup error: ", e); + } + + } + + public void addFileDropListener(FileDropListener listener) { + dndListeners.addIfAbsent(listener); + } + + public void removeFileDropListener(FileDropListener listener) { + dndListeners.remove(listener); + } + + public void fireFilesDropped(Collection files, ContactItem item) { + for (final FileDropListener listener : dndListeners) { + try { + listener.filesDropped(files, item); + } catch (Exception e) { + Log.error("A FileDropListener (" + listener + ") threw an exception while processing a 'filedDropped' event for: " + item, e); + } + } + } + + @Override + public void contactItemAdded(ContactItem item) { + fireContactItemAdded(item); + } + + @Override + public void contactItemRemoved(ContactItem item) { + fireContactItemRemoved(item); + } + + /* + Adding ContactListListener support. + */ + + public void addContactListListener(ContactListListener listener) { + contactListListeners.addIfAbsent(listener); + } + + public void removeContactListListener(ContactListListener listener) { + contactListListeners.remove(listener); + } + + public void fireContactItemAdded(ContactItem item) { + for (final ContactListListener listener : contactListListeners) { + try { + listener.contactItemAdded(item); + } catch (Exception e) { + Log.error("A ContactListListener (" + listener + ") threw an exception while processing a 'contactItemAdded' event for: " + item, e); + } + } + } + + public void fireContactItemRemoved(ContactItem item) { + for (final ContactListListener listener : contactListListeners) { + try { + listener.contactItemRemoved(item); + } catch (Exception e) { + Log.error("A ContactListListener (" + listener + ") threw an exception while processing a 'contactItemRemoved' event for: " + item, e); + } + } + } + + public void fireContactGroupAdded(ContactGroup group) { + for (final ContactListListener listener : contactListListeners) { + try { + listener.contactGroupAdded(group); + } catch (Exception e) { + Log.error("A ContactListListener (" + listener + ") threw an exception while processing a 'contactGroupAdded' event for: " + group, e); + } + } + } + + public void fireContactGroupRemoved(ContactGroup group) { + for (final ContactListListener listener : contactListListeners) { + try { + listener.contactGroupRemoved(group); + } catch (Exception e) { + Log.error("A ContactListListener (" + listener + ") threw an exception while processing a 'contactGroupRemoved' event for: " + group, e); + } + } + } + + public void fireContactItemClicked(ContactItem item) { + for (final ContactListListener listener : contactListListeners) { + try { + listener.contactItemClicked(item); + } catch (Exception e) { + Log.error("A ContactListListener (" + listener + ") threw an exception while processing a 'contactItemClicked' event for: " + item, e); + } + } + } + + public void fireContactItemDoubleClicked(ContactItem item) { + for (final ContactListListener listener : contactListListeners) { + try { + listener.contactItemDoubleClicked(item); + } catch (Exception e) { + Log.error("A ContactListListener (" + listener + ") threw an exception while processing a 'contactItemDoubleClicked' event for: " + item, e); + } + } + } + + + @Override + public void uninstall() { + // Do nothing. + } + + public void saveState() { + if (props == null) { + return; + } + for (ContactGroup contactGroup : getContactGroups()) { + props.put(contactGroup.getGroupName(), Boolean.toString(contactGroup.isCollapsed())); + } + + try { + props.store(new FileOutputStream(propertiesFile), "Tracks the state of groups."); + } catch (IOException e) { + Log.error("Unable to save group properties.", e); + } + + } + + + @Override + public void connected(XMPPConnection xmppConnection) { + + } + + @Override + public void authenticated(XMPPConnection xmppConnection, boolean b) { + clientReconnected(); + } + + @Override + public void connectionClosed() { + // No reason to reconnect. + + // Show MainWindow + SparkManager.getMainWindow().setVisible(true); + + // Flash That Window. + SparkManager.getNativeManager().flashWindowStopOnFocus( + SparkManager.getMainWindow()); + + String errorMessage = Res.getString("message.disconnected.error"); + + switch (localPreferences.getReconnectPanelType()) { + case 0: + _reconnectPanel.setDisconnectReason(errorMessage); + removeAllUsers(); + workspace.changeCardLayout(RETRY_PANEL); + break; + case 1: + switchAllUserOffline(false); + _reconnectpanelsmall.setReconnectText(errorMessage); + break; + + case 2: + switchAllUserOfflineNoGroupEntry(false); + _reconnectpanelicon.setReconnectText(errorMessage); + break; + } + + } + + + /** + * Reconnect using the Panel with Message + * @param message + */ + private void reconnect(final String message) { + // Show MainWindow + SparkManager.getMainWindow().setVisible(true); + + // Flash That Window. + SparkManager.getNativeManager().flashWindowStopOnFocus( + SparkManager.getMainWindow()); + + switch (localPreferences.getReconnectPanelType()) { + case 0: + workspace.changeCardLayout(RETRY_PANEL); + _reconnectPanel.setDisconnectReason(message); + break; + case 1: + switchAllUserOffline(true); + break; + case 2: + switchAllUserOfflineNoGroupEntry(true); + break; + default: + workspace.changeCardLayout(RETRY_PANEL); + } + + removeAllUsers(); + } + + public void clientReconnected() { + + switch (localPreferences.getReconnectPanelType()) { + case 0: + workspace.changeCardLayout(Workspace.WORKSPACE_PANE); + break; + case 1: + mainPanel.remove(_reconnectpanelsmall); + break; + + case 2: + SwingWorker sw = new SwingWorker() { + @Override + public Object construct() { + _reconnectpanelicon.remove(); + _reconnectpanelicon.getPanel().revalidate(); + return 42; + } + }; + sw.start(); + break; + } + + offlineGroup.fireContactGroupUpdated(); + + try { + updateContactList(null); + } + catch (Exception e) { + Log.error(e); + } + + final Presence myPresence = SparkManager.getWorkspace().getStatusBar() + .getPresence(); + SparkManager.getSessionManager().changePresence(myPresence); + + } + + @Override + public void connectionClosedOnError(final Exception ex) { + String errorMessage = Res.getString("message.disconnected.error"); + + if (ex instanceof XMPPException.StreamErrorException) { + XMPPException.StreamErrorException xmppEx = (XMPPException.StreamErrorException) ex; + switch (xmppEx.getStreamError().getCondition()) { + case conflict: + errorMessage = Res.getString("message.disconnected.conflict.error"); + break; + + case system_shutdown: + errorMessage = Res.getString("message.disconnected.shutdown"); + break; + + default: + errorMessage = Res.getString("message.general.error", xmppEx.getStreamError().getConditionText()); + break; + } + } + + switch (localPreferences.getReconnectPanelType()) { + case 0: + final String message = errorMessage; + SwingUtilities.invokeLater(() -> reconnect(message)); + break; + case 1: + switchAllUserOffline(true); + _reconnectpanelsmall.setReconnectText(errorMessage); + break; + + case 2: + switchAllUserOfflineNoGroupEntry(true); + _reconnectpanelicon.setReconnectText(errorMessage); + break; + + } + } + + private void removeAllUsers() { + // Behind the scenes, move everyone to the offline group. + for (ContactGroup contactGroup : new ArrayList<>(getContactGroups())) { + contactGroup.removeAllContacts(); + } + + } + + @Override + public void reconnectingIn(int i) { + + switch (localPreferences.getReconnectPanelType()) { + case 0: + if (i == 0) { + _reconnectPanel.setReconnectText(Res + .getString("message.reconnect.attempting")); + } else { + _reconnectPanel.setReconnectText(Res.getString( + "message.reconnect.wait", i)); + } + break; + + case 1: + if (i == 0) { + _reconnectpanelsmall.setReconnectText(Res + .getString("message.reconnect.attempting")); + } else { + _reconnectpanelsmall.setReconnectText(Res.getString( + "message.reconnect.wait", i)); + } + break; + + case 2: + if (i == 0) { + _reconnectpanelicon.setReconnectText(Res + .getString("message.reconnect.attempting")); + } else { + _reconnectpanelicon.setReconnectText(Res.getString( + "message.reconnect.wait", i)); + } + break; + } + + } + + @Override + public void reconnectionFailed(Exception exception) { + + switch (localPreferences.getReconnectPanelType()) { + + case 0: + _reconnectPanel.setReconnectText(Res + .getString("message.reconnect.failed")); + break; + case 1: + _reconnectpanelsmall.setReconnectText(Res + .getString("message.reconnect.failed")); + break; + case 2: + _reconnectpanelicon.setReconnectText(Res + .getString("message.reconnect.failed")); + break; + } + + } + + /** + * Moves a ContactItem to an offline state. + * + * @param contactItem the ContactItem. + */ + private void moveToOffline(ContactItem contactItem) { + offlineGroup.addContactItem(contactItem); + + BareJid jid = contactItem.getJid().asBareJid(); + boolean isFiled = false; + + final Roster roster = SparkManager.getRoster(); + for (RosterGroup group : roster.getEntry(jid).getGroups()) { + ContactGroup contactGroup = getContactGroup(group.getName()); + if (contactGroup == null && !Objects.equals(group.getName(), "")) { + contactGroup = addContactGroup(group.getName()); + } + if (contactGroup != null) { + isFiled = true; + contactGroup.addOfflineContactItem(contactItem.getAlias(), contactItem.getNickname(), contactItem.getJid(), contactItem.getStatus()); + } + } + if (!isFiled) { + getUnfiledGroup().addOfflineContactItem(contactItem.getAlias(), contactItem.getNickname(), contactItem.getJid(), contactItem.getStatus()); + } + + if (!localPreferences.isOfflineUsersShown()) { + for (ContactGroup group : getContactGroups()) { + if (group != offlineGroup) { + group.toggleOfflineVisibility(false); + } + } + } + } + + private ContactGroup getUnfiledGroup() { + if (unfiledGroup == null) { + // Add Unfiled Group + if (EventQueue.isDispatchThread()) { + unfiledGroup = UIComponentRegistry.createContactGroup(Res.getString("unfiled")); + // Only show the "Unfiled" group if it is not empty + if (unfiledGroup.hasAvailableContacts()) addContactGroup(unfiledGroup); + } else { + try { + EventQueue.invokeAndWait(() -> { + unfiledGroup = UIComponentRegistry.createContactGroup(Res.getString("unfiled")); + addContactGroup(unfiledGroup); + }); + } catch (Exception ex) { + Log.error("checkGroup error: ", ex); + } + } + } + return unfiledGroup; + } + + public void showAddContact(String contact) { + addContactMenu.doClick(); + } + + public ContactItem getActiveItem() { + return activeItem; + } +} diff --git a/src/java/org/jivesoftware/spark/ui/ContactListListener.java b/core/src/main/java/org/jivesoftware/spark/ui/ContactListListener.java similarity index 95% rename from src/java/org/jivesoftware/spark/ui/ContactListListener.java rename to core/src/main/java/org/jivesoftware/spark/ui/ContactListListener.java index ba349f7ff..1e3db7d00 100644 --- a/src/java/org/jivesoftware/spark/ui/ContactListListener.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/ContactListListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,6 +35,7 @@ public interface ContactListListener { * * @param item the ContactItem removed. */ + @SuppressWarnings("EmptyMethod") void contactItemRemoved(ContactItem item); /** @@ -46,6 +43,7 @@ public interface ContactListListener { * * @param group the ContactGroup. */ + @SuppressWarnings("EmptyMethod") void contactGroupAdded(ContactGroup group); /** @@ -53,6 +51,7 @@ public interface ContactListListener { * * @param group the ContactGroup. */ + @SuppressWarnings("EmptyMethod") void contactGroupRemoved(ContactGroup group); /** diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ContainerComponent.java b/core/src/main/java/org/jivesoftware/spark/ui/ContainerComponent.java new file mode 100644 index 000000000..927aebd80 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/ContainerComponent.java @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import javax.swing.ImageIcon; +import javax.swing.JComponent; + +/** + */ +public interface ContainerComponent { + + String getTabTitle(); + + String getFrameTitle(); + + ImageIcon getTabIcon(); + + JComponent getGUI(); + + String getToolTipDescription(); + + boolean closing(); +} diff --git a/src/java/org/jivesoftware/spark/ui/CustomPainter.java b/core/src/main/java/org/jivesoftware/spark/ui/CustomPainter.java similarity index 98% rename from src/java/org/jivesoftware/spark/ui/CustomPainter.java rename to core/src/main/java/org/jivesoftware/spark/ui/CustomPainter.java index edd53ac22..01e241d70 100644 --- a/src/java/org/jivesoftware/spark/ui/CustomPainter.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/CustomPainter.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/src/main/java/org/jivesoftware/spark/ui/CustomTextEntry.java b/core/src/main/java/org/jivesoftware/spark/ui/CustomTextEntry.java new file mode 100644 index 000000000..b18c17f19 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/CustomTextEntry.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2017 Ignite Realtime Foundation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import javax.swing.text.*; +import java.awt.*; +import java.time.ZonedDateTime; + +/** + * Represents a custom text, which is rendered as a line of text in a particular style. + * + * Typical examples are notifications that someone is joining or leaving a multi-user chatroom. + * + * @author Guus der Kinderen, guus.der.kinderen@gmail.com + */ +public class CustomTextEntry extends TimeStampedEntry +{ + private final String message; + private final Color textColor; + private final boolean bold; + private final boolean italic; + private final boolean underline; + private final boolean strikeThrough; + + protected CustomTextEntry( ZonedDateTime timestamp, String message, Color textColor, boolean bold, boolean italic, boolean underline, boolean strikeThrough ) + { + super( timestamp, false ); + this.message = message; + this.textColor = textColor; + this.bold = bold; + this.italic = italic; + this.underline = underline; + this.strikeThrough = strikeThrough; + } + + protected CustomTextEntry( ZonedDateTime timestamp, String message, Color textColor ) + { + this( timestamp, message, textColor, false, false, false, false ); + } + + protected AttributeSet getStyle() + { + final MutableAttributeSet style = new SimpleAttributeSet(); + StyleConstants.setFontFamily( style, "Dialog" ); + StyleConstants.setFontSize( style, SettingsManager.getLocalPreferences().getChatRoomFontSize() ); + StyleConstants.setForeground( style, textColor ); + StyleConstants.setBold( style, bold ); + StyleConstants.setItalic( style, italic ); + StyleConstants.setUnderline( style, underline ); + StyleConstants.setStrikeThrough( style, strikeThrough ); + return style; + } + + @Override + protected void addTo( ChatArea chatArea ) throws BadLocationException + { + final Document doc = chatArea.getDocument(); + + doc.insertString( doc.getLength(), getFormattedTimestamp() + message + "\n", getStyle() ); + // Enabling the 'setCaretPosition' line below causes Spark to freeze (often, not always) when trying to print the subject of a chatroom that's just being loaded. + // chatArea.setCaretPosition( doc.getLength() ); + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/DataFormUI.java b/core/src/main/java/org/jivesoftware/spark/ui/DataFormUI.java new file mode 100644 index 000000000..4d7876aa8 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/DataFormUI.java @@ -0,0 +1,216 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.smackx.xdata.*; +import org.jivesoftware.smackx.xdata.form.FillableForm; +import org.jivesoftware.smackx.xdata.packet.DataForm; +import org.jivesoftware.spark.component.CheckBoxList; + +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import static java.awt.GridBagConstraints.*; +import static java.awt.GridBagConstraints.NONE; + +/** + * Builds the UI for any DataForm (JEP-0004: Data Forms), and allow for creation + * of an answer form to send back the server. + */ +public class DataFormUI extends JPanel { + private static final long serialVersionUID = -6313707846021436765L; + private final Map valueMap = new HashMap<>(); + private final DataForm form; + private int row = 5; + + /** + * Creates a new DataFormUI + * + * @param form the DataForm to build a UI with. + */ + public DataFormUI(DataForm form) { + this.setLayout(new GridBagLayout()); + this.form = form; + buildUI(); + Insets insets = new Insets(0, 0, 0, 0); + this.add(new JLabel(), new GridBagConstraints(0, row, 3, 1, 0, 1, CENTER, NONE, insets, 0, 0)); + } + + + private void buildUI() { + // Add default answers to the form to submit + for (final FormField field : form.getFields()) { + String variable = field.getFieldName(); + String label = field.getLabel(); + FormField.Type type = field.getType(); + List valueList = field.getValues(); + switch (type) { + case bool: { + BooleanFormField booleanField = field.ifPossibleAsOrThrow(BooleanFormField.class); + boolean isSelected = booleanField.getValueAsBoolean(); + JCheckBox box = new JCheckBox(label); + box.setSelected(isSelected); + addField(label, box, variable); + break; + } + case text_single: + case jid_single: { + String v = ""; + if (!valueList.isEmpty()) { + v = valueList.get(0).toString(); + } + addField(label, new JTextField(v), variable); + break; + } + case text_multi: + case jid_multi: { + String text = String.join(",", valueList); + addField(label, new JTextArea(text), variable); + break; + } + case text_private: { + String v = ""; + if (!valueList.isEmpty()) { + v = valueList.get(0).toString(); + } + addField(label, new JPasswordField(v), variable); + break; + } + case list_single: { + ListSingleFormField listSingleFormField = field.ifPossibleAsOrThrow(ListSingleFormField.class); + JComboBox box = new JComboBox<>(); + for (FormField.Option option : listSingleFormField.getOptions()) { + box.addItem(option.getValueString()); + } + if (!valueList.isEmpty()) { + String defaultValue = valueList.get(0).toString(); + box.setSelectedItem(defaultValue); + } + addField(label, box, variable); + break; + } + case list_multi: { + ListMultiFormField listMultiFormField = field.ifPossibleAsOrThrow(ListMultiFormField.class); + CheckBoxList checkBoxList = new CheckBoxList(); + for (FormField.Option option : listMultiFormField.getOptions()) { + String optionLabel = option.getLabel(); + String optionValue = option.getValueString(); + boolean isSelected = valueList.contains(optionValue); + checkBoxList.addCheckBox(new JCheckBox(optionLabel, isSelected), optionValue); + } + addField(label, checkBoxList, variable); + break; + } + case fixed: { + if (!valueList.isEmpty()) { + String v = valueList.get(0).toString(); + addField(label, new JLabel(v), variable); + } + break; + } + case hidden: { + // nothing to render + break; + } + } + } + } + + /** + * Returns the answered DataForm. + */ + public FillableForm getFilledForm() { + // Now submit all information + FillableForm answerForm = new FillableForm(form); + for (Map.Entry entry : valueMap.entrySet()) { + String answer = entry.getKey(); + JComponent o = entry.getValue(); + // Extract form values from components; populates submit form + if (o instanceof JCheckBox) { + boolean isSelected = ((JCheckBox) o).isSelected(); + answerForm.setAnswer(answer, isSelected); + } else if (o instanceof JTextArea) { + List list = new ArrayList<>(); + String value = ((JTextArea) o).getText(); + StringTokenizer tokenizer = new StringTokenizer(value, ",", false); + while (tokenizer.hasMoreTokens()) { + list.add(tokenizer.nextToken().trim()); + } + // an empty list is not allowed + if (!list.isEmpty()) { + answerForm.setAnswer(answer, list); + } + } else if (o instanceof JTextField) { + String value = ((JTextField) o).getText(); + answerForm.setAnswer(answer, value); + } else if (o instanceof JComboBox) { + String value = (String) ((JComboBox) o).getSelectedItem(); + answerForm.setAnswer(answer, value); + } else if (o instanceof CheckBoxList) { + List list = ((CheckBoxList) o).getSelectedValues(); + // an empty list is not allowed + if (!list.isEmpty()) { + answerForm.setAnswer(answer, list); + } + } + } + + return answerForm; + } + + + /** + * Add labeled component to form and map variable to the component + */ + private void addField(String label, JComponent comp, String variable) { + Insets insets = new Insets(5, 5, 5, 5); + if (!(comp instanceof JCheckBox)) { + this.add(new JLabel(label), new GridBagConstraints(0, row, 1, 1, 1, 0, WEST, HORIZONTAL, insets, 0, 0)); + } + if (comp instanceof JTextArea) { + this.add(new JScrollPane(comp), new GridBagConstraints(1, row, 1, 1, 1, 0, WEST, HORIZONTAL, insets, 100, 50)); + } else if (comp instanceof JCheckBox) { + this.add(comp, new GridBagConstraints(0, row, 1, 1, 0, 0, WEST, HORIZONTAL, insets, 0, 0)); + } else if (comp instanceof CheckBoxList) { + this.add(comp, new GridBagConstraints(1, row, 1, 1, 0, 0, WEST, HORIZONTAL, insets, 0, 50)); + } else { + this.add(comp, new GridBagConstraints(1, row, 1, 1, 1, 0, WEST, HORIZONTAL, insets, 0, 0)); + } + valueMap.put(variable, comp); + row++; + } + + public JComponent getComponent(String variable) { + return valueMap.get(variable); + } +} + diff --git a/src/java/org/jivesoftware/spark/ui/FileDropListener.java b/core/src/main/java/org/jivesoftware/spark/ui/FileDropListener.java similarity index 96% rename from src/java/org/jivesoftware/spark/ui/FileDropListener.java rename to core/src/main/java/org/jivesoftware/spark/ui/FileDropListener.java index 33b95b2f0..6d8724402 100644 --- a/src/java/org/jivesoftware/spark/ui/FileDropListener.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/FileDropListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/spark/ui/GlobalMessageListener.java b/core/src/main/java/org/jivesoftware/spark/ui/GlobalMessageListener.java similarity index 94% rename from src/java/org/jivesoftware/spark/ui/GlobalMessageListener.java rename to core/src/main/java/org/jivesoftware/spark/ui/GlobalMessageListener.java index 0b295a513..fc683f62d 100644 --- a/src/java/org/jivesoftware/spark/ui/GlobalMessageListener.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/GlobalMessageListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/src/main/java/org/jivesoftware/spark/ui/GroupChatRoomTransferHandler.java b/core/src/main/java/org/jivesoftware/spark/ui/GroupChatRoomTransferHandler.java new file mode 100644 index 000000000..7dbf5ab65 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/GroupChatRoomTransferHandler.java @@ -0,0 +1,89 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.BareJid; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; + +import javax.swing.JComponent; +import javax.swing.TransferHandler; + +/** + * Handler for drag and dropping of files unto a ChatWindow. + */ +public class GroupChatRoomTransferHandler extends TransferHandler { + private static final long serialVersionUID = -192689038331188379L; + private final GroupChatRoom groupChatRoom; + private static final DataFlavor[] flavors = {DataFlavor.imageFlavor}; + + /** + * Creates a transfer handler for the given GroupChatRoom + * + * @param chatRoom the GroupChatRoom. + */ + public GroupChatRoomTransferHandler(GroupChatRoom chatRoom) { + this.groupChatRoom = chatRoom; + } + + @Override + public int getSourceActions(JComponent c) { + return TransferHandler.COPY; + } + + + @Override + public boolean canImport(JComponent comp, DataFlavor[] flavor) { + for (DataFlavor dataFlavor : flavor) { + for (DataFlavor value : flavors) { + if (dataFlavor.equals(value)) { + return true; + } + } + } + return false; + } + + @Override + public Transferable createTransferable(JComponent comp) { + return null; + } + + @Override + public boolean importData(JComponent comp, Transferable t) { + if (t.isDataFlavorSupported(flavors[0])) { + try { + final Object o = t.getTransferData(flavors[0]); + if (o instanceof ContactItem) { + // Invite User + final ContactItem contactItem = (ContactItem)o; + BareJid jid = contactItem.getJid(); + groupChatRoom.inviteUser(jid.asEntityBareJidOrThrow(), "Please join the conference room."); + + return true; + } + } + catch (Exception e) { + Log.error(e); + } + } + + return false; + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/HorizontalLineEntry.java b/core/src/main/java/org/jivesoftware/spark/ui/HorizontalLineEntry.java new file mode 100644 index 000000000..ee19493fe --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/HorizontalLineEntry.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2017 Ignite Realtime Foundation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import javax.swing.*; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import java.time.ZonedDateTime; + +/** + * A entry that is displayed as a horizontal line. + * + * @author Guus der Kinderen, guus.der.kinderen@gmail.com + */ +public class HorizontalLineEntry extends TranscriptWindowEntry +{ + public HorizontalLineEntry() + { + super( ZonedDateTime.now() ); + } + + public HorizontalLineEntry( ZonedDateTime timestamp ) + { + super( timestamp ); + } + + @Override + protected void addTo( ChatArea chatArea ) throws BadLocationException + { + final Document doc = chatArea.getDocument(); + + chatArea.insertComponent( new JSeparator() ); + doc.insertString(doc.getLength(), "\n", null ); + // Enabling the 'setCaretPosition' line below causes Spark to freeze (often, not always) when trying to print the subject of a chatroom that's just being loaded. + // chatArea.setCaretPosition( doc.getLength() ); + } +} diff --git a/src/java/org/jivesoftware/spark/ui/ImageSelectionPanel.java b/core/src/main/java/org/jivesoftware/spark/ui/ImageSelectionPanel.java similarity index 88% rename from src/java/org/jivesoftware/spark/ui/ImageSelectionPanel.java rename to core/src/main/java/org/jivesoftware/spark/ui/ImageSelectionPanel.java index ec1c36d57..c5dc9f399 100644 --- a/src/java/org/jivesoftware/spark/ui/ImageSelectionPanel.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/ImageSelectionPanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -53,7 +49,8 @@ public void setImage(BufferedImage image) { addMouseMotionListener(selector); } - protected void paintComponent(Graphics g) { + @Override + protected void paintComponent(Graphics g) { if (image == null) { return; } @@ -79,7 +76,8 @@ public void setClipFrame(Point start, Point end) { repaint(); } - public Dimension getPreferredSize() { + @Override + public Dimension getPreferredSize() { return new Dimension(image.getWidth(), image.getHeight()); } @@ -94,10 +92,10 @@ public void clear() { } class Selector extends MouseInputAdapter { - ImageSelectionPanel selectionPanel; - Point start; - boolean dragging, - isClipSet; + private final ImageSelectionPanel selectionPanel; + private Point start; + private boolean dragging; + private boolean isClipSet; public Selector(ImageSelectionPanel isp) { selectionPanel = isp; @@ -105,7 +103,8 @@ public Selector(ImageSelectionPanel isp) { isClipSet = false; } - public void mousePressed(MouseEvent e) { + @Override + public void mousePressed(MouseEvent e) { if (isClipSet) // clear existing clip { selectionPanel.setClipFrame(start, start); @@ -119,11 +118,13 @@ public void mousePressed(MouseEvent e) { } } - public void mouseReleased(MouseEvent e) { + @Override + public void mouseReleased(MouseEvent e) { dragging = false; } - public void mouseDragged(MouseEvent e) { + @Override + public void mouseDragged(MouseEvent e) { if (dragging) selectionPanel.setClipFrame(start, e.getPoint()); } diff --git a/src/java/org/jivesoftware/spark/ui/LinkInterceptor.java b/core/src/main/java/org/jivesoftware/spark/ui/LinkInterceptor.java similarity index 90% rename from src/java/org/jivesoftware/spark/ui/LinkInterceptor.java rename to core/src/main/java/org/jivesoftware/spark/ui/LinkInterceptor.java index 6c55d8626..ee699998b 100644 --- a/src/java/org/jivesoftware/spark/ui/LinkInterceptor.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/LinkInterceptor.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,5 +30,5 @@ public interface LinkInterceptor { * @param link the link that was clicked. * @return true if the user wishes to handle the link. */ - public boolean handleLink(MouseEvent mouseEvent, String link); + boolean handleLink(MouseEvent mouseEvent, String link); } diff --git a/core/src/main/java/org/jivesoftware/spark/ui/MessageEntry.java b/core/src/main/java/org/jivesoftware/spark/ui/MessageEntry.java new file mode 100644 index 000000000..ef2637e88 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/MessageEntry.java @@ -0,0 +1,458 @@ +/* + * Copyright (C) 2017 Ignite Realtime Foundation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.emoticons.EmoticonManager; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import javax.swing.*; +import javax.swing.text.*; +import java.awt.*; +import java.time.ZonedDateTime; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.function.Predicate; +import java.util.regex.Pattern; + +import static javax.swing.text.StyleConstants.Foreground; +import static org.jivesoftware.spark.ui.preview.ImagePreview.insertPicture; +import static org.jivesoftware.spark.ui.preview.LinkPreview.insertLink; +import static org.jivesoftware.spark.ui.preview.NetworkAddressPreview.insertAddress; + +/** + * An entry that represents a single (chat) message. + * + * An entry is displayed in this format: (timestamp) prefix: message, + * for example: (10:03) Guus: Hello everyone! + * + * Messages are formatted according to XEP-0393: Message Styling + * + * @author Guus der Kinderen, guus.der.kinderen@gmail.com + */ +public class MessageEntry extends TimeStampedEntry +{ + public static final String DIRECTIVE_CHARS = "*_~`#["; + private static final Predicate CUSTOM_STYLE_NAME_MATCHER = Pattern.compile("_?[a-zA-Z]((-|_)?[a-zA-Z0-9]+)*").asMatchPredicate(); + private static final SimpleAttributeSet DEFAULT_HIGHLIGHT_STYLE = new SimpleAttributeSet(); + static { + StyleConstants.setBackground(DEFAULT_HIGHLIGHT_STYLE, Color.YELLOW); + } + /** + * Default background color (white/transparent) + */ + private static final Color COLOR_MSG_BG = new Color(255, 255, 255, 0); + protected final String prefix; + protected final Color prefixColor; + protected final String message; + protected final Color messageColor; + protected final Color backgroundColor; + protected final Map customStyles; + + /** + * Creates a new entry using the default background color (white/transparent). + * + * @param timestamp The timestamp of the entry (cannot be null). + * @param prefix The prefix of the message (typically, the name of the author of the message. + * @param prefixColor The color to be used for the timestamp and prefix text. + * @param message The message text itself. + * @param messageColor The color to be used for the message text. + */ + public MessageEntry( ZonedDateTime timestamp, String prefix, Color prefixColor, String message, Color messageColor ) + { + this( timestamp, false, prefix, prefixColor, message, messageColor, null ); + } + + /** + * Creates a new entry using the default background color (white/transparent). + * + * @param timestamp The timestamp of the entry (cannot be null). + * @param isDelayed Set true if entry contain delayed delivery, historic timestamp. + * @param prefix The prefix of the message (typically, the name of the author of the message. + * @param prefixColor The color to be used for the timestamp and prefix text. + * @param message The message text itself. + * @param messageColor The color to be used for the message text. + */ + public MessageEntry( ZonedDateTime timestamp, boolean isDelayed, String prefix, Color prefixColor, String message, Color messageColor ) + { + this( timestamp, isDelayed, prefix, prefixColor, message, messageColor, null ); + } + + /** + * Creates a new entry using the default background color (white/transparent). + * + * @param timestamp The timestamp of the entry (cannot be null). + * @param prefix The prefix of the message (typically, the name of the author of the message. + * @param prefixColor The color to be used for the timestamp and prefix text. + * @param message The message text itself. + * @param messageColor The color to be used for the message text. + * @param backgroundColor The color to be used for the entire entry (prefix as well ass message text). + */ + public MessageEntry( ZonedDateTime timestamp, String prefix, Color prefixColor, String message, Color messageColor, Color backgroundColor ) + { + this( timestamp, false, prefix, prefixColor, message, messageColor,backgroundColor ); + + } + + /** + * Creates a new entry using a given background color (default is white/transparent). + * + * @param timestamp The timestamp of the entry (cannot be null). + * @param isDelayed Set true if entry contain delayed delivery, historic timestamp. + * @param prefix The prefix of the message (typically, the name of the author of the message. + * @param prefixColor The color to be used for the timestamp and prefix text. + * @param message The message text itself. + * @param messageColor The color to be used for the message text. + * @param backgroundColor The color to be used for the entire entry (prefix as well ass message text). + */ + public MessageEntry( ZonedDateTime timestamp, boolean isDelayed, String prefix, Color prefixColor, String message, Color messageColor, Color backgroundColor ) + { + this(timestamp, isDelayed, prefix, prefixColor, message, messageColor, backgroundColor, Map.of()); + } + + /** + * Creates a new entry using a given background color and optional custom styles to be applied like + * * Asciidoc Custom Inline Styles: + * *

      {@code [.style-name]#my styled text#} will have the effect of applying the style corresponding to {@code style-name} in {@code customStyles} parameter, to the text between {@code #} characters. + * + * @param timestamp The timestamp of the entry (cannot be null). + * @param isDelayed Set true if entry contain delayed delivery, historic timestamp. + * @param prefix The prefix of the message (typically, the name of the author of the message. + * @param prefixColor The color to be used for the timestamp and prefix text. + * @param message The message text itself. + * @param messageColor The color to be used for the message text. + * @param customStyles custom styles to be applied to specific parts of the message in the same manner as Asciidoc custom inline styles. + */ + public MessageEntry( ZonedDateTime timestamp, boolean isDelayed, String prefix, Color prefixColor, String message, Color messageColor, Color backgroundColor, Map customStyles ) + { + super( timestamp, isDelayed ); + this.prefix = prefix == null ? "" : prefix; + this.prefixColor = prefixColor; + this.message = message; + this.messageColor = messageColor; + this.backgroundColor = backgroundColor != null ? backgroundColor : COLOR_MSG_BG; + if(customStyles.keySet().stream().anyMatch(styleName -> !CUSTOM_STYLE_NAME_MATCHER.test(styleName))) { + throw new IllegalArgumentException("One of the input custom style names is invalid: " + customStyles.keySet()); + } + this.customStyles = customStyles; + } + + protected MutableAttributeSet getPrefixStyle() + { + final MutableAttributeSet style = new SimpleAttributeSet(); + StyleConstants.setFontFamily( style, "Dialog" ); + StyleConstants.setFontSize( style, SettingsManager.getLocalPreferences().getChatRoomFontSize() ); + StyleConstants.setForeground( style, prefixColor ); + StyleConstants.setBackground( style, backgroundColor ); + return style; + } + + protected MutableAttributeSet getMessageStyle() + { + final MutableAttributeSet style = new SimpleAttributeSet(); + StyleConstants.setFontFamily( style, "Dialog" ); + StyleConstants.setFontSize( style, SettingsManager.getLocalPreferences().getChatRoomFontSize() ); + StyleConstants.setForeground( style, messageColor ); + StyleConstants.setBackground( style, backgroundColor ); + return style; + } + + @Override + protected void addTo( ChatArea chatArea ) throws BadLocationException + { + final MutableAttributeSet prefixStyle = getPrefixStyle(); + final MutableAttributeSet messageStyle = getMessageStyle(); + + // First, add the message prefix. + final Document doc = chatArea.getDocument(); + doc.insertString( doc.getLength(), getFormattedTimestamp() + prefix + ": ", prefixStyle ); + + final MutableAttributeSet directiveStyle = applyMessageStyle( 'K', messageStyle ); // Special style used on the directives themselves. + + // Next, process the message, bit by bit. + for ( final Block block : asBlocks( message ) ) + { + if ( block.isPreformattedCodeBlock() ) + { + final MutableAttributeSet style = applyMessageStyle( '`', messageStyle ); + + for ( final String line : block.lines ) + { + boolean codeBlockLine = line.trim().startsWith("```"); + doc.insertString(doc.getLength(), line, codeBlockLine ? directiveStyle : style ); + } + + doc.insertString( doc.getLength(), "\n", messageStyle ); + } + else + { + // for now, we'll not visually differentiate between quotes and non-quotes. + for ( final String line : block.lines) + { + if (line.isEmpty()) { + continue; + } + int to = 0; + do + { + int from = to; + + // Handle whitespace + if (Character.isWhitespace(line.charAt(to))) { + while (++to < line.length()) { + if (!Character.isWhitespace(line.charAt(to))) break; + } + doc.insertString(doc.getLength(), line.substring(from, to), messageStyle); + continue; + } + + // Handle directives + char charAtFrom = line.charAt(from); + if (DIRECTIVE_CHARS.indexOf(charAtFrom) != -1) { + char directive = charAtFrom; + /* + If the matched directive char is [, check whether this is '[.style-name]#sometext#', where style-name is one of the names in customStyles, in which case apply that custom inline style (Asciidoc-like) + */ + final AttributeSet fragmentSpecificStyle; + if(directive == '[') { + if(line.charAt(from+1) == '.') { + // style-name is at least one character, therefore look for ] from 'from+3' position + final int closingSquareBracketIndex = line.indexOf(']', from + 3); + if (closingSquareBracketIndex != -1 && line.charAt(closingSquareBracketIndex + 1) == '#') { + final String appliedStyleName = line.substring(from + 2, closingSquareBracketIndex); + if (!customStyles.containsKey(appliedStyleName)) { + Log.error("The message text is using a custom inline style named '" + appliedStyleName + "' but no such style has been defined. Ignoring."); + fragmentSpecificStyle = null; + } else { + fragmentSpecificStyle = customStyles.get(appliedStyleName); + directive = '#'; + from = closingSquareBracketIndex + 1; + Log.debug("Applying custom inline style '" + appliedStyleName + "' to the text between #"); + } + } else { + fragmentSpecificStyle = null; + } + } else { + fragmentSpecificStyle = null; + } + } else if(directive == '#') { + /* + If the matched directive char is #, highlight (in yellow) the text between # (no custom inline style here, as it was already handled in previous case above). + */ + fragmentSpecificStyle = DEFAULT_HIGHLIGHT_STYLE; + } else { + fragmentSpecificStyle = applyMessageStyle(directive, messageStyle); + } + if(fragmentSpecificStyle != null) { + to = line.indexOf(directive, from + 1); // directive closing + if (to != -1 && !Character.isWhitespace(line.charAt(to - 1)) && (to - from) > 1) { + String fragment = line.substring(from + 1, to++); + insertFragment(chatArea, fragment, applyMessageStyle(directive, messageStyle)); + continue; + } + } + } + + // Handle quoted text ("", not >) + if (charAtFrom == '\"') { + to = line.indexOf('\"', from + 1); // quote closing + if (to != -1) { + doc.insertString(doc.getLength(), "\"", messageStyle); + insertFragment(chatArea, line.substring(from + 1, to++), messageStyle); + doc.insertString(doc.getLength(), "\"", messageStyle); + continue; + } + } + + to = from; + while (++to < line.length()) { + if (Character.isWhitespace(line.charAt(to))) break; + } + insertFragment(chatArea, line.substring(from, to), messageStyle); + } + while (to < line.length()); + } + doc.insertString( doc.getLength(), "\n", messageStyle ); + } + } + + // Enabling the 'setCaretPosition' line below causes Spark to freeze (often, not always) when trying to print the subject of a chatroom that's just being loaded. + // chatArea.setCaretPosition( doc.getLength() ); + } + + protected void insertFragment(ChatArea chatArea, String fragment, AttributeSet style) throws BadLocationException { + if (insertPicture(chatArea, fragment, style)) return; + if (insertLink(chatArea.getDocument(), fragment, style)) return; + if (insertAddress(chatArea.getDocument(), fragment, style)) return; + if (insertEmoticon(chatArea, fragment)) return; + chatArea.getDocument().insertString(chatArea.getDocument().getLength(), fragment, style); + } + + /** + * Splits the provided text into a sequence of blocks. + * + * @param text The text to be parsed + * @return the + */ + protected java.util.List asBlocks( String text ) + { + final java.util.List result = new ArrayList<>(); + + // Process the text line-by-line + final StringTokenizer tokenizer = new StringTokenizer(text, "\n", true); + Block block = null; + while ( tokenizer.hasMoreTokens() ) + { + final String line = tokenizer.nextToken(); + + if ( block == null ) + { + block = new Block(line); + } + else if ( !block.tryAppend( line ) ) + { + // If this line does not belong to the block that's already being constructed, then that block is + // done. Add it to the result, and create a new one. + result.add( block ); + block = new Block(line); + } + } + + if (block != null) + { + result.add( block ); + } + + return result; + } + + /** + * A block is any chunk of text that can be parsed unambiguously in one pass. + * + *

        + *
      • A single line of text comprising one or more spans
      • + *
      • A block quotation
      • + *
      • A preformatted code block
      • + *
      + */ + static class Block + { + final java.util.Deque lines = new ArrayDeque<>(); + + Block( String line ) + { + lines.add( line ); + } + + boolean isBlockQuotation() { + return !lines.isEmpty() && lines.getFirst().startsWith( ">" ); + } + + boolean isPreformattedCodeBlock() { + return !lines.isEmpty() && lines.getFirst().startsWith( "```" ); + } + + boolean tryAppend( String line ) + { + if ( isBlockQuotation() && line.startsWith( ">" ) ) + { + // Only add when this is a new line in the same block quote. + if ( !line.startsWith( ">" ) ) + { + return false; + } + + lines.add( line ); + return true; + } + + if ( isPreformattedCodeBlock() ) + { + // Only add if the code block was not already closed. + if ( lines.size() > 1 && lines.getLast().trim().endsWith( "```" ) ) + { + return false; + } + + lines.add( line ); + return true; + } + + if ( line.startsWith( ">" ) || line.startsWith( "```" )) + { + // Start a new block! + return false; + } + lines.add( line ); + return true; + } + } + + public MutableAttributeSet applyMessageStyle( char directive, MutableAttributeSet messageStyle ) + { + final MutableAttributeSet style = new SimpleAttributeSet( messageStyle.copyAttributes() ); + switch ( directive ) + { + case '*': + StyleConstants.setBold( style, true ); + break; + case '_': + StyleConstants.setItalic( style, true ); + break; + case '~': + StyleConstants.setStrikeThrough( style, true ); + break; + case '`': + StyleConstants.setFontFamily( style, "Monospaced" ); + break; + case 'K': // Keyword + StyleConstants.setForeground( style, ((Color) messageStyle.getAttribute( Foreground )).brighter().brighter().brighter() ); + break; + + default: + Log.warning( "Cannot apply message style for unrecognized directive: " + directive ); + } + return style; + } + + /** + * Inserts an emotion icon into the current document. + * + * @param imageKey - the smiley representation of the image.( ex. :) ) + * @return true if the image was found, otherwise false. + */ + public boolean insertEmoticon(ChatArea chatArea, String imageKey ) + { + if ( !chatArea.getForceEmoticons() && !SettingsManager.getLocalPreferences().areEmoticonsEnabled() || !chatArea.emoticonsAvailable ) + { + return false; + } + + final Icon emotion = EmoticonManager.getInstance().getEmoticonImage( imageKey ); + if ( emotion == null ) + { + return false; + } + + final Document doc = chatArea.getDocument(); + chatArea.select( doc.getLength(), doc.getLength() ); + + chatArea.insertIcon( emotion ); + return true; + } +} diff --git a/src/java/org/jivesoftware/spark/ui/MessageEventListener.java b/core/src/main/java/org/jivesoftware/spark/ui/MessageEventListener.java similarity index 81% rename from src/java/org/jivesoftware/spark/ui/MessageEventListener.java rename to core/src/main/java/org/jivesoftware/spark/ui/MessageEventListener.java index 8e3738f66..4dc23ea30 100644 --- a/src/java/org/jivesoftware/spark/ui/MessageEventListener.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/MessageEventListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +15,7 @@ */ package org.jivesoftware.spark.ui; -import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; /** * Listen for the sending and receiving of messages. @@ -28,7 +24,7 @@ */ public interface MessageEventListener { - void sendingMessage(Message message); + void sendingMessage(MessageBuilder msgBuilder); - void receivingMessage(Message message); + void receivingMessage(MessageBuilder msgBuilder); } diff --git a/src/java/org/jivesoftware/spark/ui/MessageFilter.java b/core/src/main/java/org/jivesoftware/spark/ui/MessageFilter.java similarity index 82% rename from src/java/org/jivesoftware/spark/ui/MessageFilter.java rename to core/src/main/java/org/jivesoftware/spark/ui/MessageFilter.java index c5108f19a..b24018923 100644 --- a/src/java/org/jivesoftware/spark/ui/MessageFilter.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/MessageFilter.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +16,7 @@ package org.jivesoftware.spark.ui; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; /** * The MessageFilter interface is one of the interfaces extension @@ -38,17 +35,17 @@ public interface MessageFilter { * Update the body of an outgoing message. * * @param room Room the message is attached to. - * @param message the message to update. + * @param messageBuilder the message to update. */ - void filterOutgoing(ChatRoom room, Message message); + void filterOutgoing(ChatRoom room, MessageBuilder messageBuilder); /** * Updates the body of an incoming message. * * @param room Room the message is attached to. - * @param message the message to update. + * @param messageBuilder the message to update. */ - void filterIncoming(ChatRoom room, Message message); + void filterIncoming(ChatRoom room, MessageBuilder messageBuilder); } diff --git a/src/java/org/jivesoftware/spark/ui/MessageListener.java b/core/src/main/java/org/jivesoftware/spark/ui/MessageListener.java similarity index 97% rename from src/java/org/jivesoftware/spark/ui/MessageListener.java rename to core/src/main/java/org/jivesoftware/spark/ui/MessageListener.java index f26de1a65..391cfe279 100644 --- a/src/java/org/jivesoftware/spark/ui/MessageListener.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/MessageListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/spark/ui/PresenceListener.java b/core/src/main/java/org/jivesoftware/spark/ui/PresenceListener.java similarity index 90% rename from src/java/org/jivesoftware/spark/ui/PresenceListener.java rename to core/src/main/java/org/jivesoftware/spark/ui/PresenceListener.java index b0bbcd0a8..1471e9a97 100644 --- a/src/java/org/jivesoftware/spark/ui/PresenceListener.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/PresenceListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,6 +19,7 @@ /** * The PresenceListener is used to listen for Personal Presence changes within the system. + * It allows other parts of the application to react to presence updates (e.g., updating UI elements like status icons). *

      * Presence listeners can be registered using the {@link org.jivesoftware.spark.SessionManager} */ diff --git a/core/src/main/java/org/jivesoftware/spark/ui/RawPacketSender.java b/core/src/main/java/org/jivesoftware/spark/ui/RawPacketSender.java new file mode 100644 index 000000000..b86bba55c --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/RawPacketSender.java @@ -0,0 +1,179 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.GridLayout; + +import javax.swing.*; + +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.filter.StanzaFilter; +import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.packet.id.StandardStanzaIdSource; +import org.jivesoftware.smack.util.XmlUtil; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.MessageDialog; + +/** + * Class to Send Raw packets useful when debugging + * + * @author wolf.posdorfer + */ +public class RawPacketSender { + + private static final String[] STANZA_SAMPLES = { + "\n" + + "\n" + + "\n" + + "\n" + + "", + "\n" + + "\n" + + "", + "\n" + + "\n" + + "", + "\n" + + "\n" + + "", + "\n" + + "\n" + + "" + }; + private final JFrame _mainFrame; + private final JPanel _mainPanel; + + private final JScrollPane _textScroller; + + private final JTextArea _textAreaLog; + private final JTextArea _inputArea; + private final JButton _btnSend; + private final JButton _btnClearLog; + private final JComboBox _cbStanzas; + + public RawPacketSender() { + _mainFrame = new JFrame("Send Raw Packets"); + _mainFrame.setIconImage(SparkRes.getImageIcon(SparkRes.Icon.MAIN_IMAGE).getImage()); + _mainPanel = new JPanel(); + _mainPanel.setLayout(new GridLayout(2, 1)); + _textAreaLog = new JTextArea(); + _inputArea = new JTextArea(); + _inputArea.setToolTipText("Leave the stanza id attribute empty to generate a new id"); + _textScroller = new JScrollPane(_textAreaLog); + _btnSend = new JButton("Send", SparkRes.getImageIcon(SparkRes.Icon.SMALL_CHECK)); + _btnSend.addActionListener(e -> onBtnSendClick()); + _btnClearLog = new JButton("Clear", SparkRes.getImageIcon(SparkRes.Icon.SMALL_DELETE)); + _btnClearLog.addActionListener(e -> onBtnClearLogClick()); + _cbStanzas = new JComboBox<>(new String[] { + "Presence", + "Message", + "IQ", + "Discovery Info", + "Get version", + }); + _cbStanzas.addActionListener(e -> _inputArea.setText(STANZA_SAMPLES[_cbStanzas.getSelectedIndex()])); + + JPanel southPanel = new JPanel(new BorderLayout()); + southPanel.add(_inputArea, BorderLayout.CENTER); + + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + buttonPanel.add(_cbStanzas); + buttonPanel.add(_btnClearLog); + buttonPanel.add(_btnSend); + southPanel.add(buttonPanel, BorderLayout.SOUTH); + + _textAreaLog.setBackground(Color.LIGHT_GRAY); + _mainPanel.add(_textScroller); + _mainPanel.add(southPanel); + + _mainFrame.add(_mainPanel); + _mainFrame.setSize(500, 500); + _mainFrame.setLocationRelativeTo(null); + _mainFrame.setVisible(true); + // handle request and responses with the debugging it "id-X" + StanzaFilter debugPacketFilter = stanza -> stanza.getStanzaId() != null && stanza.getStanzaId().endsWith("-X"); + SparkManager.getConnection().addAsyncStanzaListener(this::addRespToLog, debugPacketFilter); + } + + private void addRespToLog(Stanza stanza) { + SwingUtilities.invokeLater(() -> { + _textAreaLog.append("\n" + XmlUtil.prettyFormatXml(stanza.toXML())); + }); + } + + private void onBtnSendClick() { + String reqText = _inputArea.getText(); + if (reqText.isBlank()) { + return; + } + String debugStanzaId = StandardStanzaIdSource.DEFAULT.getNewStanzaId() + "-X"; + // replace empty id with generated id + String rawXml = reqText.replace("id=\"\"", "id=\"" + debugStanzaId + "\""); + AdHocPacket packetToSend = new AdHocPacket(rawXml); + try { + SparkManager.getConnection().sendStanza(packetToSend); + _textAreaLog.append("\n" + XmlUtil.prettyFormatXml(rawXml)); + } catch (Exception exc) { + MessageDialog.showErrorDialog(_mainFrame, exc); + } + } + + private void onBtnClearLogClick() { + _textAreaLog.setText(""); + } + + /** + * An ad-hoc stanza is like any regular stanza but with the exception that it's intention is + * to be used only to send packets.

      + *

      + * The whole text to send must be passed to the constructor. This implies that the client of + * this class is responsible for sending a valid text to the constructor. + */ + private static final class AdHocPacket extends Stanza { + + private final String text; + + /** + * Create a new AdHocPacket with the text to send. The passed text must be a valid text to + * send to the server, no validation will be done on the passed text. + * + * @param text the whole text of the stanza to send + */ + private AdHocPacket(String text) { + this.text = text; + } + + @Override + public String toXML(XmlEnvironment enclosingNamespace) { + return text; + } + + @Override + public String toString() { + return toXML((XmlEnvironment) null); + } + + @Override + public String getElementName() { + return null; + } + } + +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ReconnectPanel.java b/core/src/main/java/org/jivesoftware/spark/ui/ReconnectPanel.java new file mode 100644 index 000000000..ada3be2ab --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/ReconnectPanel.java @@ -0,0 +1,166 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import java.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.*; +import javax.swing.text.html.HTMLEditorKit; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.ConnectionListener; +import org.jivesoftware.smack.ReconnectionListener; +import org.jivesoftware.smack.ReconnectionManager; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.util.ModelUtil; + +/** + * RetryPanel is the UI/Function class to handle reconnection logic. This allows for a simple card layout to replace the current + * roster when the connection has been lost. + * + * @author Derek DeMoro + */ +public class ReconnectPanel extends JPanel implements ConnectionListener, ReconnectionListener { + private static final long serialVersionUID = -7099075581561760774L; + private final JEditorPane pane; + private final JLabel _icon; + + private final JButton _button; + + /** + * Construct the RetryPanel. + */ + public ReconnectPanel() { + setLayout(new GridBagLayout()); + + // Init Components + pane = new JEditorPane(); + pane.setBackground(Color.white); + pane.setEditorKit(new HTMLEditorKit()); + pane.setEditable(false); + + _icon = new JLabel(SparkRes.getImageIcon(SparkRes.Icon.BUSY_IMAGE)); + _button = new JButton(Res.getString("button.reconnect2")); + _button.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + final int selectedOption = JOptionPane.showConfirmDialog(null, + Res.getString("message.restart.required"), + Res.getString("title.alert"), + JOptionPane.YES_NO_OPTION); + if (selectedOption == JOptionPane.YES_OPTION) { + SparkManager.getMainWindow().logout(false); + } + } + }); + layoutComponents(); + + setBackground(Color.white); + + _icon.setText(Res.getString("button.reconnect2")); + + SparkManager.getConnection().addConnectionListener(this); + + ReconnectionManager.getInstanceFor(SparkManager.getConnection()).addReconnectionListener(this); + } + + + /** + * Sets the reason the user was disconnected from the server. + * + * @param reason the reason the user was disconnected from the server. + */ + public void setDisconnectReason(String reason) { + if (!ModelUtil.hasLength(reason)) { + reason = Res.getString("message.generic.reconnect.message"); + } + + String builder = "
      " + + "" + + reason + + "" + + "
      "; + + pane.setText( builder ); + } + + private void layoutComponents() { + add(pane, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); + add(_icon, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(_button, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + } + + /** + * Starts the countdown to the next retry attempt. The retry attemp is set for every 45 seconds or what is set + * as the default in preferences. + * + * @param text the text to display on the reconnect button. + */ + protected void setReconnectText(String text) { + _icon.setVisible(true); + _icon.setText(text); + } + + /** + * Changes the UI to handle when a conflict occurs on the server. + */ + public void showConflict() { + _icon.setVisible(false); + } + + @Override + public void connected( XMPPConnection xmppConnection ) + { + _icon.setVisible(false); + _icon.setEnabled(true); + } + + @Override + public void authenticated( XMPPConnection xmppConnection, boolean b ) + { + _icon.setVisible(false); + _icon.setEnabled(true); + } + + @Override + public void connectionClosed() { + _icon.setVisible(true); + _icon.setEnabled(true); + } + + @Override + public void connectionClosedOnError(Exception e) { + _icon.setVisible(true); + _icon.setEnabled(true); + } + + @Override + public void reconnectingIn(int seconds) { + } + + @Override + public void reconnectionFailed(Exception e) { + _icon.setVisible(true); + _icon.setEnabled(true); + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ReconnectPanelIcon.java b/core/src/main/java/org/jivesoftware/spark/ui/ReconnectPanelIcon.java new file mode 100644 index 000000000..9f291f989 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/ReconnectPanelIcon.java @@ -0,0 +1,110 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import javax.swing.*; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.ConnectionListener; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.util.SwingWorker; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * Used for silent reconnecting
      + * Displays a little Icon at first position in commandpanel + * + * @author wolf.posdorfer + * + */ +public class ReconnectPanelIcon implements ConnectionListener { + + private static final long serialVersionUID = 437696141257704105L; + private final JButton _icon; + private final JPanel _commandpanel; + + /** + * creates a new Panel + */ + public ReconnectPanelIcon() { + + _commandpanel = SparkManager.getWorkspace().getCommandPanel(); + + _icon = new JButton(SparkRes.getImageIcon(SparkRes.Icon.BUSY_IMAGE)); + _icon.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + final int selectedOption = JOptionPane.showConfirmDialog(null, + Res.getString("message.restart.required"), + Res.getString("title.alert"), + JOptionPane.YES_NO_OPTION); + if (selectedOption == JOptionPane.YES_OPTION) { + SparkManager.getMainWindow().logout(false); + } + } + }); + + } + + public JPanel getPanel() { + return _commandpanel; + } + + public JButton getButton() { + return _icon; + } + + public void setReconnectText(String text) { + _icon.setToolTipText(text); + } + + public void remove() { + SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + return 42; + } + + @Override + public void finished() { + _commandpanel.remove(_icon); + } + }; + worker.start(); + + } + + @Override + public void connected( XMPPConnection xmppConnection ) { + } + + @Override + public void authenticated( XMPPConnection xmppConnection, boolean b ) { + } + + @Override + public void connectionClosed() { + } + + @Override + public void connectionClosedOnError(Exception e) { + } + +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/ReconnectPanelSmall.java b/core/src/main/java/org/jivesoftware/spark/ui/ReconnectPanelSmall.java new file mode 100644 index 000000000..f705eddcf --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/ReconnectPanelSmall.java @@ -0,0 +1,88 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import javax.swing.*; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.ConnectionListener; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.spark.SparkManager; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * Used for silent reconnecting
      + * Displays a reconnection dialog as a ContactGroup at the Top + * + * @author wolf.posdorfer + * + */ +public class ReconnectPanelSmall extends ContactGroup implements + ConnectionListener { + + private static final long serialVersionUID = 437696141257704105L; + private final JButton _reconnectionlabel = new JButton( + Res.getString("message.reconnect.attempting")); + + + /** + * creates a new Panel + * + * @param groupName + */ + public ReconnectPanelSmall(String groupName) { + super(groupName); + this.add(_reconnectionlabel); + this.setIcon(SparkRes.getImageIcon(SparkRes.Icon.BUSY_IMAGE)); + _reconnectionlabel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + final int selectedOption = JOptionPane.showConfirmDialog(null, + Res.getString("message.restart.required"), + Res.getString("title.alert"), + JOptionPane.YES_NO_OPTION); + if (selectedOption == JOptionPane.YES_OPTION) { + SparkManager.getMainWindow().logout(false); + } + } + }); + } + + public void setReconnectText(String text) { + String s = "" + text + ""; + _reconnectionlabel.setText(s); + } + + @Override + public void connected( XMPPConnection xmppConnection ) { + } + + @Override + public void authenticated( XMPPConnection xmppConnection, boolean b ) { + } + + @Override + public void connectionClosed() { + } + + @Override + public void connectionClosedOnError(Exception e) { + } + +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/RequestFocusListener.java b/core/src/main/java/org/jivesoftware/spark/ui/RequestFocusListener.java new file mode 100644 index 000000000..e901d89ac --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/RequestFocusListener.java @@ -0,0 +1,65 @@ +package org.jivesoftware.spark.ui; + +import javax.swing.JComponent; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; + +/** + * Convenience class to request focus on a component. + * + * When the component is added to a realized Window then component will + * request focus immediately, since the ancestorAdded event is fired + * immediately. + * + * When the component is added to a non realized Window, then the focus + * request will be made once the window is realized, since the + * ancestorAdded event will not be fired until then. + * + * Using the default constructor will cause the listener to be removed + * from the component once the AncestorEvent is generated. A second constructor + * allows you to specify a boolean value of false to prevent the + * AncestorListener from being removed when the event is generated. This will + * allow you to reuse the listener each time the event is generated. + * + * @author Rob Camick + */ + +public class RequestFocusListener implements AncestorListener { + private final boolean removeListener; + + /* + * Convenience constructor. The listener is only used once and then it is + * removed from the component. + */ + + public RequestFocusListener() { + this(true); + } + + /* + * Constructor that controls whether this listen can be used once or + * multiple times. + * + * @param removeListener when true this listener is only invoked once + * otherwise it can be invoked multiple times. + */ + + public RequestFocusListener(boolean removeListener) { + this.removeListener = removeListener; + } + + @Override + public void ancestorAdded(AncestorEvent e) { + JComponent component = e.getComponent(); + component.requestFocusInWindow(); + + if (removeListener) + component.removeAncestorListener( this ); + } + + @Override + public void ancestorMoved(AncestorEvent e) {} + + @Override + public void ancestorRemoved(AncestorEvent e) {} +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/RosterDialog.java b/core/src/main/java/org/jivesoftware/spark/ui/RosterDialog.java new file mode 100644 index 000000000..ca1ff4660 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/RosterDialog.java @@ -0,0 +1,679 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Vector; + +import javax.swing.*; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smack.roster.RosterEntry; +import org.jivesoftware.smack.roster.RosterGroup; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.vcardtemp.VCardManager; +import org.jivesoftware.smackx.xdata.form.FillableForm; +import org.jivesoftware.smackx.xdata.packet.DataForm; +import org.jivesoftware.smackx.search.ReportedData; +import org.jivesoftware.smackx.vcardtemp.packet.VCard; +import org.jivesoftware.smackx.search.UserSearchManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.UserManager; +import org.jivesoftware.spark.component.TitlePanel; +import org.jivesoftware.spark.component.borders.ComponentTitledBorder; +import org.jivesoftware.spark.component.renderer.JPanelRenderer; +import org.jivesoftware.spark.search.SearchManager; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.gateways.Gateway; +import org.jivesoftware.sparkimpl.plugin.gateways.transports.Transport; +import org.jivesoftware.sparkimpl.plugin.gateways.transports.TransportUtils; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; +import org.jxmpp.util.XmppStringUtils; + + +/** + * The RosterDialog is used to add new users to the users XMPP Roster. + */ +public class RosterDialog implements ActionListener { + private final JPanel panel; + private final JTextField jidField; + private final JTextField nicknameField; + private final Vector groupModel = new Vector<>(); + + private final JComboBox groupBox; + private final JComboBox accounts; + private JDialog dialog; + private final ContactList contactList; + private final JCheckBox publicBox; + private final JButton _searchForName ; + private final Collection _usersearchservice; + + /** + * Create a new instance of RosterDialog. + */ + public RosterDialog() { + contactList = SparkManager.getWorkspace().getContactList(); + + _usersearchservice = SearchManager.getInstance().getSearchServicesAsJid(); + + panel = new JPanel(); + JLabel contactIDLabel = new JLabel(); + jidField = new JTextField(); + JLabel nicknameLabel = new JLabel(); + nicknameField = new JTextField(); + JLabel groupLabel = new JLabel(); + groupBox = new JComboBox<>(groupModel); + + JButton newGroupButton = new JButton(); + + JLabel accountsLabel = new JLabel(); + accounts = new JComboBox<>(); + publicBox = new JCheckBox(Res.getString("label.user.on.public.network")); + + ResourceUtils.resLabel(accountsLabel, publicBox, Res.getString("label.network")); + + _searchForName = new JButton(); + _searchForName.setIcon(SparkRes.getImageIcon(SparkRes.Icon.TRANSFER_IMAGE_24x24)); + + _searchForName.addMouseListener(new MouseListener() { + @Override + public void mouseClicked(MouseEvent e) { + try { + searchForContact(jidField.getText(), e); + } catch (XMPPException | SmackException | InterruptedException e1) { + Log.error("search contact", e1); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + }); + + dialog = null; + panel.setLayout(new GridBagLayout()); + panel.add(contactIDLabel, new GridBagConstraints(0, 0, 1, 1, 0.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); + panel.add(jidField , new GridBagConstraints(1, 0, 1, 1, 1.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); + panel.add(_searchForName, new GridBagConstraints(2, 0, 1, 1, 0.0D, 0.0D, 17, 0, new Insets(5, 5, 5, 5), 0, 0)); + + + panel.add(nicknameLabel, new GridBagConstraints(0, 1, 1, 1, 0.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); + panel.add(nicknameField, new GridBagConstraints(1, 1, 1, 1, 1.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); + + + JPanel networkPanel = new JPanel( new GridBagLayout() ); + ComponentTitledBorder componentBorder = new ComponentTitledBorder(publicBox, networkPanel + , BorderFactory.createEtchedBorder()); + + + networkPanel.add(accountsLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); + networkPanel.add(accounts, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); + + networkPanel.setBorder(componentBorder); + + networkPanel.setVisible(false); + accounts.setEnabled(false); + + + panel.add(groupLabel, new GridBagConstraints(0, 4, 1, 1, 0.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); + + panel.add(groupBox, new GridBagConstraints(1, 4, 1, 1, 1.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); + + if (!Default.getBoolean(Default.ADD_CONTACT_GROUP_DISABLED) && Enterprise.containsFeature(Enterprise.ADD_GROUPS_FEATURE)) { + panel.add(newGroupButton, new GridBagConstraints(2, 4, 1, 1, 0.0D, 0.0D, 17, 1, new Insets(5, 5, 5, 5), 0, 0)); + } + newGroupButton.addActionListener(this); + + panel.add( networkPanel, new GridBagConstraints(0, 5, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + + ResourceUtils.resLabel(contactIDLabel, jidField, Res.getString("label.username") + ":"); + ResourceUtils.resLabel(nicknameLabel, nicknameField, Res.getString("label.nickname") + ":"); + ResourceUtils.resLabel(groupLabel, groupBox, Res.getString("label.group") + ":"); + ResourceUtils.resButton(newGroupButton, Res.getString("button.new")); + + accounts.setRenderer(new JPanelRenderer()); + + for (ContactGroup group : contactList.getContactGroups()) { + if (!group.isOfflineGroup() && !Res.getString("unfiled").equalsIgnoreCase(group.getGroupName()) && !group.isSharedGroup()) { + groupModel.add(group.getGroupName()); + } + } + + + groupBox.setEditable(true); + + if (groupModel.isEmpty()) { + groupBox.addItem("Friends"); + } + groupBox.setSelectedIndex(0); + + jidField.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + + } + + @Override + public void focusLost(FocusEvent e) { + String jid = getJID(); + String vcardNickname = null; + + if (!publicBox.isSelected()) { + // This is not a transport. + String fullJID = getJID(); + if ( !fullJID.contains( "@" ) ) { + fullJID = fullJID + "@" + SparkManager.getConnection().getXMPPServiceDomain(); + } + + if (!fullJID.startsWith( "@" )) + { + BareJid bareJid = JidCreate.bareFromOrThrowUnchecked(fullJID); + vcardNickname = SparkManager.getUserManager().getNickname( bareJid ); + } + } + + String nickname = nicknameField.getText(); + if (!ModelUtil.hasLength(nickname) && ModelUtil.hasLength(jid)) { + nickname = XmppStringUtils.parseLocalpart(jid); + if (!ModelUtil.hasLength(nickname)) { + nickname = jid; + } + + nicknameField.setText(vcardNickname != null ? vcardNickname : nickname); + } + } + }); + + final List accountCol = getAccounts(); + for (AccountItem item : accountCol) { + accounts.addItem(item); + } + + if (!accountCol.isEmpty()) { + accountsLabel.setVisible(true); + accounts.setVisible(true); + publicBox.setVisible(true); + networkPanel.setVisible(true); + } + + publicBox.addActionListener( actionEvent -> accounts.setEnabled(publicBox.isSelected()) ); + + + } + + /** + * Sets the default ContactGroup to display in the combo box. + * + * @param contactGroup the default ContactGroup. + */ + public void setDefaultGroup(ContactGroup contactGroup) { + String groupName = contactGroup.getGroupName(); + if (groupModel.contains(groupName)) { + groupBox.setSelectedItem(groupName); + } + else { + groupBox.addItem(groupName); + groupBox.setSelectedItem(groupName); + } + } + + /** + * Sets the default jid to show in the jid field. + * + * @param jid the jid. + */ + public void setDefaultJID(String jid) { + jidField.setText(jid); + } + + /** + * Sets the default nickname to show in the nickname field. + * + * @param nickname the nickname. + */ + public void setDefaultNickname(String nickname) { + nicknameField.setText(nickname); + } + + + @Override + public void actionPerformed(ActionEvent e) { + String group = JOptionPane.showInputDialog(dialog, Res.getString("label.enter.group.name") + ":", Res.getString("title.new.roster.group"), JOptionPane.QUESTION_MESSAGE); + if (group != null && !group.isEmpty() && !groupModel.contains(group)) { + SparkManager.getRoster().createGroup(group); + groupModel.add(group); + int size = groupModel.size(); + groupBox.setSelectedIndex(size - 1); + } + } + + /** + * Display the RosterDialog using a parent container. + * + * @param parent the parent Frame. + */ + public void showRosterDialog(JFrame parent) { + TitlePanel titlePanel = new TitlePanel(Res.getString("title.add.contact"), Res.getString("message.add.contact.to.list"), null, true); + + + JPanel mainPanel = new JPanel() { + private static final long serialVersionUID = -7489967438182277375L; + + @Override + public Dimension getPreferredSize() { + final Dimension size = super.getPreferredSize(); + size.width = 450; + return size; + } + }; + + mainPanel.setLayout(new BorderLayout()); + mainPanel.add(titlePanel, BorderLayout.NORTH); + mainPanel.add(panel, BorderLayout.CENTER); + + JButton buttonAdd = new JButton(Res.getString("add")); + + buttonAdd.addActionListener( e -> addContactButton() ); + + JButton buttonCancel = new JButton(Res.getString("cancel")); + buttonCancel.addActionListener( e -> dialog.dispose() ); + + + JPanel panelButtons = new JPanel(new FlowLayout()); + panelButtons.add(buttonAdd); + panelButtons.add(buttonCancel); + mainPanel.add(panelButtons, BorderLayout.SOUTH); + + dialog = new JDialog(parent, Res.getString("title.add.contact"), false); + dialog.setContentPane(mainPanel); + dialog.pack(); + + dialog.setLocationRelativeTo(parent); + + dialog.setVisible(true); + dialog.toFront(); + dialog.requestFocus(); + + jidField.requestFocus(); + } + + /** + * Display the RosterDialog using the MainWindow as the parent. + */ + public void showRosterDialog() { + showRosterDialog(SparkManager.getMainWindow()); + } + + private void addEntry() { + Transport transport = null; + AccountItem item; + if (publicBox.isSelected()) { + item = (AccountItem)accounts.getSelectedItem(); + transport = item.getTransport(); + } + if (transport == null) { + String jid = getJID(); + if ( !jid.contains( "@" ) ) { + jid = jid + "@" + SparkManager.getConnection().getXMPPServiceDomain(); + } + String nickname = nicknameField.getText(); + String group = (String)groupBox.getSelectedItem(); + + jid = UserManager.escapeJID(jid); + BareJid bareJid = JidCreate.bareFromOrThrowUnchecked(jid); + // Add as a new entry + addRosterEntry(bareJid, nickname, group); + } + else { + String jid = getJID(); + try { + jid = Gateway.getJID(transport.getXMPPServiceDomain(), jid); + } + catch (Exception e) { + Log.error(e); + } + + String nickname = nicknameField.getText(); + String group = (String)groupBox.getSelectedItem(); + BareJid bareJid = JidCreate.bareFromOrThrowUnchecked(jid); + addRosterEntry(bareJid, nickname, group); + } + } + + /** + * Returns the trimmed version of the JID. + * + * @return the trimmed version. + */ + private String getJID() { + return jidField.getText().trim(); + } + + private void addRosterEntry(final BareJid jid, final String nickname, final String group) { + final SwingWorker rosterEntryThread = new SwingWorker() { + @Override + public Object construct() { + return addEntry(jid, nickname, group); + } + + @Override + public void finished() { + if (get() == null) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(dialog, Res.getString("label.unable.to.add.contact"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + } + } + + }; + + rosterEntryThread.start(); + } + + /** + * Creates a PopupDialog above the Search Button displaying matching Contacts + * + * @param byname the Search name, at least 5 chars long + * @param event the MouseEvent which triggered it + * @throws XMPPException + * @throws InterruptedException + */ + public void searchForContact(String byname, MouseEvent event) + throws XMPPException, SmackException.NotConnectedException, SmackException.NoResponseException, InterruptedException + { + + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + + if (byname.contains("@")) { + byname = byname.substring(0, byname.indexOf("@")); + } + + if (byname.length() <= 1) { + JOptionPane.showMessageDialog(jidField, + Res.getString("message.search.input.short"), + Res.getString("title.notification"), + JOptionPane.ERROR_MESSAGE); + + } else { + + JPopupMenu popup = new JPopupMenu(); + JMenuItem header = new JMenuItem( + Res.getString("group.search.results") + ":"); + header.setBackground(UIManager.getColor("List.selectionBackground")); + header.setForeground(Color.red); + popup.add(header); + + for (DomainBareJid search : _usersearchservice) { + + ReportedData data; + UserSearchManager usersearchManager = UserSearchManager.getInstanceFor( + SparkManager.getConnection()); + + DataForm f = usersearchManager.getSearchForm(search).getDataForm(); + + FillableForm answer = new FillableForm(f); + answer.setAnswer("Name", true); + answer.setAnswer("Email", true); + answer.setAnswer("Username", true); + answer.setAnswer("search", byname); + + data = usersearchManager.sendSimpleSearchForm(answer.getDataFormToSubmit(), search); + + ArrayList columnnames = new ArrayList<>(); + for ( ReportedData.Column column : data.getColumns() ) { + String label = column.getLabel(); + columnnames.add(label); + } + + for (ReportedData.Row row : data.getRows() ) { + if (!row.getValues(columnnames.get(0)).isEmpty()) { + String s = row.getValues(columnnames.get(0)) + .get(0).toString(); + final JMenuItem item = new JMenuItem(s); + popup.add(item); + item.addActionListener( e -> { + jidField.setText(item.getText()); + nicknameField.setText(XmppStringUtils + .parseLocalpart(item.getText())); + } ); + } + + } + } + + if (popup.getComponentCount() > 2) { + popup.setVisible(true); + popup.show(_searchForName, event.getX(), event.getY()); + } else if (popup.getComponentCount() == 2) { + jidField.setText(((JMenuItem) popup.getComponent(1)).getText()); + nicknameField.setText(XmppStringUtils.parseLocalpart(((JMenuItem) popup + .getComponent(1)).getText())); + } else { + JOptionPane.showMessageDialog(jidField, + Res.getString("message.no.results.found"), + Res.getString("title.notification"), + JOptionPane.ERROR_MESSAGE); + } + } + } + + + /** + * Adds a new entry to the users Roster. + * + * @param jid the jid. + * @param nickname the nickname. + * @param group the contact group. + * @return the new RosterEntry. + */ + public RosterEntry addEntry(BareJid jid, String nickname, String group) { + String[] groups = {group}; + + Roster roster = SparkManager.getRoster(); + RosterEntry userEntry = roster.getEntry(jid); + + boolean isSubscribed = true; + if (userEntry != null) { + isSubscribed = userEntry.getGroups().isEmpty(); + } + + if (isSubscribed) { + try { + roster.createItemAndRequestSubscription(jid, nickname, new String[]{group}); + } + catch (XMPPException | SmackException | InterruptedException e) { + Log.error("Unable to add new entry " + jid, e); + } + return roster.getEntry(jid); + } + + + try { + RosterGroup rosterGroup = roster.getGroup(group); + if (rosterGroup == null) { + rosterGroup = roster.createGroup(group); + } + + if (userEntry == null) { + roster.createItemAndRequestSubscription(jid, nickname, groups); + userEntry = roster.getEntry(jid); + } + else { + userEntry.setName(nickname); + rosterGroup.addEntry(userEntry); + } + + userEntry = roster.getEntry(jid); + } + catch (XMPPException | SmackException | InterruptedException ex) { + Log.error(ex); + } + return userEntry; + } + + public List getAccounts() { + List list = new ArrayList<>(); + + for (Transport transport : TransportUtils.getTransports()) { + if (TransportUtils.isRegistered(SparkManager.getConnection(), transport)) { + AccountItem item = new AccountItem(transport.getIcon(), transport.getName(), transport); + list.add(item); + } + } + + return list; + } + + /** + * Method to handle the Add-Button + */ + private void addContactButton() { + String errorMessage = Res.getString("title.error"); + String jid = getJID(); + + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + + if (jid.isEmpty()) { + JOptionPane.showMessageDialog(dialog, Res.getString("message.invalid.jid.error"), + Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + return; + } + + String contact = UserManager.escapeJID(jid); + String nickname = nicknameField.getText(); + String group = (String) groupBox.getSelectedItem(); + + Transport transport = null; + if (publicBox.isSelected()) { + AccountItem item = (AccountItem) accounts.getSelectedItem(); + transport = item.getTransport(); + } + + if (transport == null) { + if (!contact.contains("@")) { + contact = contact + "@" + + SparkManager.getConnection().getXMPPServiceDomain(); + } + } else { + if (!contact.contains("@")) { + contact = contact + "@" + transport.getXMPPServiceDomain(); + } + } + + if (!ModelUtil.hasLength(nickname) && ModelUtil.hasLength(contact)) { + // Try to load nickname from VCard + try { + EntityBareJid contactJid = JidCreate.entityBareFrom(contact); + final VCard vcard = VCardManager.getInstanceFor(SparkManager.getConnection()).loadVCard(contactJid); + nickname = vcard.getNickName(); + } catch (XMPPException | SmackException | XmppStringprepException | InterruptedException e1) { + Log.error(e1); + } + // If no nickname, use first name. + if (!ModelUtil.hasLength(nickname)) { + nickname = XmppStringUtils.parseLocalpart(contact); + } + nicknameField.setText(nickname); + } + + ContactGroup contactGroup = contactList.getContactGroup(group); + boolean isSharedGroup = contactGroup != null && contactGroup.isSharedGroup(); + + if (isSharedGroup) { + errorMessage = Res.getString("message.cannot.add.contact.to.shared.group"); + } else if (!ModelUtil.hasLength(contact)) { + errorMessage = Res.getString("message.specify.contact.jid"); + } else if (!XmppStringUtils.parseBareJid(contact).contains("@")) { + errorMessage = Res.getString("message.invalid.jid.error"); + } else if (!ModelUtil.hasLength(group)) { + errorMessage = Res.getString("message.specify.group"); + } + + if (ModelUtil.hasLength(contact) && ModelUtil.hasLength(group) && !isSharedGroup) { + addEntry(); + dialog.setVisible(false); + } else { + JOptionPane.showMessageDialog(dialog, errorMessage,Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + } + } + + static class AccountItem extends JPanel { + private static final long serialVersionUID = -7657731912529801653L; + private final Transport transport; + + public AccountItem(Icon icon, String name, Transport transport) { + setLayout(new GridBagLayout()); + this.transport = transport; + + JLabel iconLabel = new JLabel(); + iconLabel.setIcon(icon); + + JLabel label = new JLabel(); + label.setText(name); + label.setFont(new Font("Dialog", Font.PLAIN, 11)); + label.setHorizontalTextPosition(JLabel.CENTER); + + add(iconLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + add(label, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 10, 0, 0), 0, 0)); + + setBackground(Color.white); + } + + public Transport getTransport() { + return transport; + } + } +} diff --git a/src/java/org/jivesoftware/spark/ui/RosterNode.java b/core/src/main/java/org/jivesoftware/spark/ui/RosterNode.java similarity index 91% rename from src/java/org/jivesoftware/spark/ui/RosterNode.java rename to core/src/main/java/org/jivesoftware/spark/ui/RosterNode.java index c72825df2..0e9bc2e57 100644 --- a/src/java/org/jivesoftware/spark/ui/RosterNode.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/RosterNode.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,11 +18,10 @@ import org.jivesoftware.resource.SparkRes; import org.jivesoftware.smack.packet.Presence; -import javax.swing.Icon; +import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; /** - * */ public class RosterNode extends DefaultMutableTreeNode { private static final long serialVersionUID = -3043224462615651820L; @@ -50,12 +45,13 @@ public RosterNode(String name, boolean isGroup) { this.isGroup = isGroup; if (isGroup) { - openIcon = SparkRes.getImageIcon(SparkRes.MINUS_SIGN); - closedIcon = SparkRes.getImageIcon(SparkRes.PLUS_SIGN); + openIcon = SparkRes.getImageIcon(SparkRes.Icon.MINUS_SIGN); + closedIcon = SparkRes.getImageIcon(SparkRes.Icon.PLUS_SIGN); } } - public Object getUserObject() { + @Override + public Object getUserObject() { return name + " " + getChildCount(); } diff --git a/src/java/org/jivesoftware/spark/ui/RosterPickList.java b/core/src/main/java/org/jivesoftware/spark/ui/RosterPickList.java similarity index 81% rename from src/java/org/jivesoftware/spark/ui/RosterPickList.java rename to core/src/main/java/org/jivesoftware/spark/ui/RosterPickList.java index 2734e210a..833bd4815 100644 --- a/src/java/org/jivesoftware/spark/ui/RosterPickList.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/RosterPickList.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -44,8 +40,8 @@ */ public class RosterPickList extends JPanel { private static final long serialVersionUID = -7725304880236329893L; - private DefaultListModel model = new DefaultListModel(); - private JList rosterList = new JList(model); + private final DefaultListModel model = new DefaultListModel<>(); + private final JList rosterList = new JList<>(model); /** * Creates a new instance of the RosterBrowser. @@ -72,18 +68,18 @@ public Collection showRoster(JDialog parent) { final List userList = new ArrayList<>(); // Populate Invite Panel with Available users. - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); + final Roster roster = SparkManager.getRoster(); for (RosterEntry entry : roster.getEntries()) { - Presence presence = PresenceManager.getPresence(entry.getUser()); + Presence presence = PresenceManager.getPresence(entry.getJid()); if (presence.isAvailable()) { - ContactItem item = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getUser()); + ContactItem item = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getJid()); item.setPresence(presence); userList.add(item); } } // Sort Users - Collections.sort(userList, itemComparator); + userList.sort(ContactItem.CONTACT_ITEM_COMPARATOR); for (ContactItem item : userList) { model.addElement(item); @@ -95,7 +91,7 @@ public Collection showRoster(JDialog parent) { TitlePanel titlePanel; // Create the title panel for this dialog - titlePanel = new TitlePanel(Res.getString("title.roster"), Res.getString("message.select.one.or.more"), SparkRes.getImageIcon(SparkRes.BLANK_IMAGE), true); + titlePanel = new TitlePanel(Res.getString("title.roster"), Res.getString("message.select.one.or.more"), SparkRes.getImageIcon(SparkRes.Icon.BLANK_IMAGE), true); // Construct main panel w/ layout. final JPanel mainPanel = new JPanel(); @@ -140,34 +136,16 @@ else if (Res.getString("ok").equals(value)) { List selectedContacts = new ArrayList<>(); - Object[] values = rosterList.getSelectedValues(); - final int no = values != null ? values.length : 0; - for (int i = 0; i < no; i++) { + Object[] values = rosterList.getSelectedValuesList().toArray(); + for (Object value : values) { try { - ContactItem item = (ContactItem)values[i]; - selectedContacts.add(item.getJID()); - } - catch (NullPointerException e) { + ContactItem item = (ContactItem) value; + selectedContacts.add(item.getJid().toString()); + } catch (NullPointerException e) { Log.error(e); } } - return selectedContacts; } - - /** - * Sorts ContactItems. - */ - final Comparator itemComparator = ( item1, item2 ) -> { - String nickname1 = item1.getDisplayName(); - String nickname2 = item2.getDisplayName(); - if (nickname1 == null || nickname2 == null) { - return 0; - } - - return nickname1.toLowerCase().compareTo(nickname2.toLowerCase()); - - }; - } diff --git a/src/java/org/jivesoftware/spark/ui/RosterTreeCellRenderer.java b/core/src/main/java/org/jivesoftware/spark/ui/RosterTreeCellRenderer.java similarity index 87% rename from src/java/org/jivesoftware/spark/ui/RosterTreeCellRenderer.java rename to core/src/main/java/org/jivesoftware/spark/ui/RosterTreeCellRenderer.java index bfaa1e60c..f26280c0b 100644 --- a/src/java/org/jivesoftware/spark/ui/RosterTreeCellRenderer.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/RosterTreeCellRenderer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,7 +27,6 @@ import java.awt.Font; /** - * */ public class RosterTreeCellRenderer extends DefaultTreeCellRenderer { private static final long serialVersionUID = 4645070076041138834L; @@ -44,7 +39,8 @@ public class RosterTreeCellRenderer extends DefaultTreeCellRenderer { public RosterTreeCellRenderer() { } - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { this.value = value; final Component c = super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); @@ -101,27 +97,33 @@ private Icon getCustomIcon() { return null; } - public Icon getClosedIcon() { + @Override + public Icon getClosedIcon() { return getCustomIcon(); } - public Icon getDefaultClosedIcon() { + @Override + public Icon getDefaultClosedIcon() { return getCustomIcon(); } - public Icon getDefaultLeafIcon() { + @Override + public Icon getDefaultLeafIcon() { return getCustomIcon(); } - public Icon getDefaultOpenIcon() { + @Override + public Icon getDefaultOpenIcon() { return getCustomIcon(); } - public Icon getLeafIcon() { + @Override + public Icon getLeafIcon() { return getCustomIcon(); } - public Icon getOpenIcon() { + @Override + public Icon getOpenIcon() { return getCustomIcon(); } } diff --git a/src/java/org/jivesoftware/spark/ui/ShakeWindow.java b/core/src/main/java/org/jivesoftware/spark/ui/ShakeWindow.java similarity index 98% rename from src/java/org/jivesoftware/spark/ui/ShakeWindow.java rename to core/src/main/java/org/jivesoftware/spark/ui/ShakeWindow.java index 9595a04d7..2bb973df9 100644 --- a/src/java/org/jivesoftware/spark/ui/ShakeWindow.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/ShakeWindow.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,7 +33,7 @@ public class ShakeWindow { public static final int SHAKE_DURATION = 1000; public static final int SHAKE_UPDATE = 5; - private Window window; + private final Window window; private Point naturalLocation; private long startTime; private Timer shakeTimer; diff --git a/core/src/main/java/org/jivesoftware/spark/ui/SparkTabHandler.java b/core/src/main/java/org/jivesoftware/spark/ui/SparkTabHandler.java new file mode 100644 index 000000000..ce5b7e58d --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/SparkTabHandler.java @@ -0,0 +1,74 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.tabbedPane.SparkTab; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jxmpp.jid.EntityBareJid; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.resource.SparkRes; + +import java.awt.Component; +import java.awt.Color; + +/** + * Allows users to control the decoration of a SparkTab component within the ChatContainer. + */ +public abstract class SparkTabHandler { + + public abstract boolean isTabHandled(SparkTab tab, Component component, boolean isSelectedTab, boolean chatFrameFocused); + + /** + * Updates the SparkTab to show it is in a stale state. + * + * @param tab the SparkTab. + * @param chatRoom the ChatRoom of the SparkTab. + */ + protected void decorateStaleTab(SparkTab tab, ChatRoom chatRoom) { + tab.setTitleColor(Color.gray); + tab.setTabFont(tab.getDefaultFont()); + + EntityBareJid jid = ((ChatRoomImpl)chatRoom).getParticipantJID(); + Presence presence = PresenceManager.getPresence(jid); + + if (!presence.isAvailable() || !SparkManager.getConnection().isConnected()) { + tab.setIcon(SparkRes.getImageIcon(SparkRes.Icon.IM_UNAVAILABLE_STALE_IMAGE)); + } + else { + Presence.Mode mode = presence.getMode(); + if (mode == Presence.Mode.available || mode == null) { + tab.setIcon(SparkRes.getImageIcon(SparkRes.Icon.IM_AVAILABLE_STALE_IMAGE)); + } + else if (mode == Presence.Mode.away) { + tab.setIcon(SparkRes.getImageIcon(SparkRes.Icon.IM_AWAY_STALE_IMAGE)); + } + else if (mode == Presence.Mode.chat) { + tab.setIcon(SparkRes.getImageIcon(SparkRes.Icon.IM_FREE_CHAT_STALE_IMAGE)); + } + else if (mode == Presence.Mode.dnd) { + tab.setIcon(SparkRes.getImageIcon(SparkRes.Icon.IM_DND_STALE_IMAGE)); + } + else if (mode == Presence.Mode.xa) { + tab.setIcon(SparkRes.getImageIcon(SparkRes.Icon.IM_XA_STALE_IMAGE)); + } + } + + tab.validateTab(); + } + +} diff --git a/src/java/org/jivesoftware/spark/ui/Sparkler.java b/core/src/main/java/org/jivesoftware/spark/ui/Sparkler.java similarity index 94% rename from src/java/org/jivesoftware/spark/ui/Sparkler.java rename to core/src/main/java/org/jivesoftware/spark/ui/Sparkler.java index f2fe0a50b..db6e243c4 100644 --- a/src/java/org/jivesoftware/spark/ui/Sparkler.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/Sparkler.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/spark/ui/SparklerDecorator.java b/core/src/main/java/org/jivesoftware/spark/ui/SparklerDecorator.java similarity index 87% rename from src/java/org/jivesoftware/spark/ui/SparklerDecorator.java rename to core/src/main/java/org/jivesoftware/spark/ui/SparklerDecorator.java index 83891d8c7..437cfd2be 100644 --- a/src/java/org/jivesoftware/spark/ui/SparklerDecorator.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/SparklerDecorator.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,8 +22,8 @@ public class SparklerDecorator { - private Map urls = new HashMap<>(); - private Map popups = new HashMap<>(); + private final Map urls = new HashMap<>(); + private final Map popups = new HashMap<>(); public void setURL(String matchedText, String url) { diff --git a/core/src/main/java/org/jivesoftware/spark/ui/StartOfDayEntry.java b/core/src/main/java/org/jivesoftware/spark/ui/StartOfDayEntry.java new file mode 100644 index 000000000..f4f58691a --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/StartOfDayEntry.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2017 Ignite Realtime Foundation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import javax.swing.text.*; +import java.awt.*; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +/** + * A text entry that denotes the start of a (new) day. + * + * @author Guus der Kinderen, guus.der.kinderen@gmail.com + */ +public class StartOfDayEntry extends TranscriptWindowEntry +{ + private static final MutableAttributeSet STYLE; + + private static final DateTimeFormatter FORMAT = DateTimeFormatter.ofPattern( "EEEE, dd MMMM yyyy" ); + + static + { + STYLE = new SimpleAttributeSet(); + StyleConstants.setFontFamily( STYLE, "Dialog" ); + StyleConstants.setFontSize( STYLE, SettingsManager.getLocalPreferences().getChatRoomFontSize() ); + StyleConstants.setBold( STYLE, true ); + StyleConstants.setUnderline( STYLE, true ); + StyleConstants.setForeground( STYLE, Color.BLACK ); + } + + protected StartOfDayEntry( ZonedDateTime timestamp ) + { + //delay here is true because StartOfDayEntry can appear among MessageEntries with delay + super( timestamp,true ); + } + + @Override + protected void addTo( ChatArea chatArea ) throws BadLocationException + { + // Get the instant that represents the start of the day in the local time-zone. + final LocalDateTime startOfDay = getTimestamp().withZoneSameInstant( ZoneId.systemDefault() ).toLocalDate().atStartOfDay(); + + final String startOfDayMessage = FORMAT.format( startOfDay ); + + final Document doc = chatArea.getDocument(); + doc.insertString(doc.getLength(), startOfDayMessage + '\n', STYLE ); + // Enabling the 'setCaretPosition' line below causes Spark to freeze (often, not always) when trying to print the subject of a chatroom that's just being loaded. + // chatArea.setCaretPosition( doc.getLength() ); + } +} diff --git a/src/java/org/jivesoftware/spark/ui/StringTransferHandler.java b/core/src/main/java/org/jivesoftware/spark/ui/StringTransferHandler.java similarity index 79% rename from src/java/org/jivesoftware/spark/ui/StringTransferHandler.java rename to core/src/main/java/org/jivesoftware/spark/ui/StringTransferHandler.java index b27fc4bcf..db1e921a5 100644 --- a/src/java/org/jivesoftware/spark/ui/StringTransferHandler.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/StringTransferHandler.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,36 +36,38 @@ public abstract class StringTransferHandler extends TransferHandler { protected abstract void cleanup(JComponent c, boolean remove); - protected Transferable createTransferable(JComponent c) { + @Override + protected Transferable createTransferable(JComponent c) { return new StringSelection(exportString(c)); } - public int getSourceActions(JComponent c) { + @Override + public int getSourceActions(JComponent c) { return COPY_OR_MOVE; } - public boolean importData(JComponent c, Transferable t) { + @Override + public boolean importData(JComponent c, Transferable t) { if (canImport(c, t.getTransferDataFlavors())) { try { String str = (String)t.getTransferData(DataFlavor.stringFlavor); importString(c, str); return true; } - catch (UnsupportedFlavorException ufe) { - // Nothing to do - } - catch (IOException ioe) { + catch (UnsupportedFlavorException | IOException ufe) { // Nothing to do } } return false; } - protected void exportDone(JComponent c, Transferable data, int action) { + @Override + protected void exportDone(JComponent c, Transferable data, int action) { cleanup(c, action == MOVE); } - public boolean canImport(JComponent c, DataFlavor[] flavors) { + @Override + public boolean canImport(JComponent c, DataFlavor[] flavors) { for (DataFlavor flavor : flavors) { if (DataFlavor.stringFlavor.equals(flavor)) { return true; @@ -77,4 +75,4 @@ public boolean canImport(JComponent c, DataFlavor[] flavors) { } return false; } -} \ No newline at end of file +} diff --git a/src/java/org/jivesoftware/spark/ui/SubscriptionDialog.java b/core/src/main/java/org/jivesoftware/spark/ui/SubscriptionDialog.java similarity index 87% rename from src/java/org/jivesoftware/spark/ui/SubscriptionDialog.java rename to core/src/main/java/org/jivesoftware/spark/ui/SubscriptionDialog.java index a1de64686..eebb1a36c 100644 --- a/src/java/org/jivesoftware/spark/ui/SubscriptionDialog.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/SubscriptionDialog.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,6 +18,7 @@ import org.jivesoftware.Spark; import org.jivesoftware.resource.Res; import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.roster.Roster; import org.jivesoftware.smack.roster.RosterEntry; import org.jivesoftware.smack.roster.RosterGroup; @@ -38,6 +35,7 @@ import org.jivesoftware.spark.util.log.Log; import org.jivesoftware.sparkimpl.plugin.gateways.transports.Transport; import org.jivesoftware.sparkimpl.plugin.gateways.transports.TransportUtils; +import org.jxmpp.jid.BareJid; import org.jxmpp.util.XmppStringUtils; import javax.swing.BorderFactory; @@ -78,13 +76,13 @@ public class SubscriptionDialog { private final JTextField nicknameField = new JTextField(); - private final JComboBox groupBox = new JComboBox(); + private final JComboBox groupBox = new JComboBox<>(); - private JLabel usernameLabelValue = new JLabel(); + private final JLabel usernameLabelValue = new JLabel(); private JFrame dialog; - private String jid; + private BareJid jid; public SubscriptionDialog() { @@ -161,24 +159,26 @@ public SubscriptionDialog() { } } - public void invoke(final String jid) throws SmackException.NotConnectedException + public void invoke(final BareJid jid) throws SmackException.NotConnectedException, InterruptedException { this.jid = jid; - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); + final Roster roster = SparkManager.getRoster(); // If User is already in roster, do not show. RosterEntry entry = roster.getEntry(jid); if (entry != null && entry.getType() == RosterPacket.ItemType.to) { - Presence response = new Presence(Presence.Type.subscribed); + Presence response = StanzaBuilder.buildPresence() + .ofType(Presence.Type.subscribed) + .build(); response.setTo(jid); SparkManager.getConnection().sendStanza(response); return; } - String message = Res.getString("message.approve.subscription", UserManager.unescapeJID(jid)); - Transport transport = TransportUtils.getTransport( XmppStringUtils.parseDomain(jid)); + String message = Res.getString("message.approve.subscription", jid.asUnescapedString()); + Transport transport = TransportUtils.getTransport( jid.asDomainBareJid() ); Icon icon = null; if (transport != null) { icon = transport.getIcon(); @@ -191,20 +191,22 @@ public void invoke(final String jid) throws SmackException.NotConnectedException UserManager userManager = SparkManager.getUserManager(); - String username = userManager.getNickname(userManager.getFullJID(jid)); - username = username == null ? XmppStringUtils.parseLocalpart(UserManager.unescapeJID(jid)) : username; - usernameLabelValue.setText(UserManager.unescapeJID(jid)); + String username = userManager.getNickname(jid); + username = username == null ? XmppStringUtils.parseLocalpart(jid.asUnescapedString()) : username; + usernameLabelValue.setText(jid.asUnescapedString()); nicknameField.setText(username); acceptButton.addActionListener( e -> { if (!rosterBox.isSelected()) { - Presence response = new Presence(Presence.Type.subscribed); + Presence response = StanzaBuilder.buildPresence() + .ofType(Presence.Type.subscribed) + .build(); response.setTo(jid); try { SparkManager.getConnection().sendStanza(response); } - catch ( SmackException.NotConnectedException e1 ) + catch ( SmackException.NotConnectedException | InterruptedException e1 ) { Log.warning( "Unable to send stanza accepting subscription from " + jid, e1 ); } @@ -214,13 +216,15 @@ public void invoke(final String jid) throws SmackException.NotConnectedException boolean addEntry = addEntry(); if (addEntry) { - Presence response = new Presence(Presence.Type.subscribed); + Presence response = StanzaBuilder.buildPresence() + .ofType(Presence.Type.subscribed) + .build(); response.setTo(jid); try { SparkManager.getConnection().sendStanza(response); } - catch ( SmackException.NotConnectedException e1 ) + catch ( SmackException.NotConnectedException | InterruptedException e1 ) { Log.warning( "Unable to send stanza accepting subscription from " + jid, e1 ); } @@ -240,6 +244,7 @@ public void invoke(final String jid) throws SmackException.NotConnectedException dialog = new JFrame(Res.getString("title.subscription.request")){ private static final long serialVersionUID = 5713933518069623228L; + @Override public Dimension getPreferredSize() { final Dimension dim = super.getPreferredSize(); dim.width = 400; @@ -281,13 +286,15 @@ else if (!SparkManager.getMainWindow().isVisible() || !SparkManager.getMainWindo private void unsubscribeAndClose() { - Presence response = new Presence(Presence.Type.unsubscribe); + Presence response = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unsubscribe) + .build(); response.setTo(jid); try { SparkManager.getConnection().sendStanza(response); } - catch ( SmackException.NotConnectedException e ) + catch ( SmackException.NotConnectedException | InterruptedException e ) { Log.warning( "Unable to send stanza unsubscribing from " + jid, e ); } @@ -331,10 +338,10 @@ else if (ModelUtil.hasLength(nickname) && ModelUtil.hasLength(group) && !isShare * @param group the contact group. * @return the new RosterEntry. */ - public RosterEntry addEntry(String jid, String nickname, String group) { + public RosterEntry addEntry(BareJid jid, String nickname, String group) { String[] groups = {group}; - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); + Roster roster = SparkManager.getRoster(); RosterEntry userEntry = roster.getEntry(jid); boolean isSubscribed = true; @@ -344,9 +351,9 @@ public RosterEntry addEntry(String jid, String nickname, String group) { if (isSubscribed) { try { - roster.createEntry(jid, nickname, new String[]{group}); + roster.preApproveAndCreateEntry(jid, nickname, new String[]{group}); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error("Unable to add new entry " + jid, e); } return roster.getEntry(jid); @@ -360,7 +367,7 @@ public RosterEntry addEntry(String jid, String nickname, String group) { } if (userEntry == null) { - roster.createEntry(jid, nickname, groups); + roster.preApproveAndCreateEntry(jid, nickname, groups); userEntry = roster.getEntry(jid); } else { @@ -370,7 +377,7 @@ public RosterEntry addEntry(String jid, String nickname, String group) { userEntry = roster.getEntry(jid); } - catch (XMPPException | SmackException ex) { + catch (XMPPException | SmackException | InterruptedException ex) { Log.error(ex); } return userEntry; diff --git a/core/src/main/java/org/jivesoftware/spark/ui/TimeStampedEntry.java b/core/src/main/java/org/jivesoftware/spark/ui/TimeStampedEntry.java new file mode 100644 index 000000000..c5855cdaa --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/TimeStampedEntry.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2017 Ignite Realtime Foundation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +/** + * An entry that is prefixed with a time stamp. + * + * @author Guus der Kinderen, guus.der.kinderen@gmail.com + */ +public abstract class TimeStampedEntry extends TranscriptWindowEntry +{ + private final DateTimeFormatter format; + + protected TimeStampedEntry( ZonedDateTime timestamp, boolean isDelayed ) + { + super( timestamp, isDelayed ); + format = DateTimeFormatter.ofPattern( SettingsManager.getLocalPreferences().getTimeFormat() ); + } + + protected String getFormattedTimestamp() + { + // Convert the zoned timestamp to a timestamp in the local zone. + final LocalDateTime localDateTime = getTimestamp().withZoneSameInstant( ZoneId.systemDefault() ).toLocalDateTime(); + + // Use the local timestamp to format a message that will be displayed to the end-user. + return "(" + format.format( localDateTime ) + ") "; + } +} diff --git a/src/java/org/jivesoftware/spark/ui/TranscriptAlert.java b/core/src/main/java/org/jivesoftware/spark/ui/TranscriptAlert.java similarity index 91% rename from src/java/org/jivesoftware/spark/ui/TranscriptAlert.java rename to core/src/main/java/org/jivesoftware/spark/ui/TranscriptAlert.java index 8225cfaf3..7faf55c29 100644 --- a/src/java/org/jivesoftware/spark/ui/TranscriptAlert.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/TranscriptAlert.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,10 +30,10 @@ public class TranscriptAlert extends JPanel { private static final long serialVersionUID = -4882289773265904417L; - private JLabel imageLabel = new JLabel(); - private JLabel titleLabel = new JLabel(); - private RolloverButton yesButton = new RolloverButton(); - private RolloverButton cancelButton = new RolloverButton(); + private final JLabel imageLabel = new JLabel(); + private final JLabel titleLabel = new JLabel(); + private final RolloverButton yesButton = new RolloverButton(); + private final RolloverButton cancelButton = new RolloverButton(); public TranscriptAlert() { setLayout(new GridBagLayout()); diff --git a/core/src/main/java/org/jivesoftware/spark/ui/TranscriptWindow.java b/core/src/main/java/org/jivesoftware/spark/ui/TranscriptWindow.java new file mode 100644 index 000000000..d24734672 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/TranscriptWindow.java @@ -0,0 +1,630 @@ +/* + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smackx.delay.packet.DelayInformation; +import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.ContextMenuListener; +import org.jivesoftware.spark.ui.history.HistoryWindow; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; +import org.jivesoftware.sparkimpl.plugin.emoticons.EmoticonManager; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.util.XmppStringUtils; + +import javax.swing.*; +import javax.swing.text.*; +import java.awt.*; +import java.awt.datatransfer.StringSelection; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.util.*; +import java.util.List; + +/** + * Provides a window in which a chat is presented to the end user, by listing all chat messages in order. This + * implementation is usable for both one-on-one chats, as well as multi-user chats. + * + * The class primary responsibility is to maintain an (time-based) ordered list of entries, and provides various methods + * to add new entries. Responsibility for the visual representation of each entry is delegated to the implementation of + * that entry. + * + * @author Guus der Kinderen, guus.der.kinderen@gmail.com + */ +public class TranscriptWindow extends ChatArea implements ContextMenuListener +{ + /** + * Unless specifically documented otherwise, content is stored in an in-memory cache of {@link TranscriptWindowEntry}s. + * This cache is used to recompose the UI when needed (which typically occurs when entries are added out-of-order). + */ + private final LinkedList entries = new LinkedList<>(); + + /** + * Creates a default instance of TranscriptWindow. + */ + public TranscriptWindow() + { + setEditable( false ); + + Collection emoticonPacks; + emoticonPacks = EmoticonManager.getInstance().getEmoticonPacks(); + + if ( emoticonPacks == null ) + { + emoticonsAvailable = false; + } + + addMouseListener( this ); + addMouseMotionListener( this ); + setDragEnabled( true ); + addContextMenuListener( this ); + + // Make sure ctrl-c works + getInputMap( JComponent.WHEN_IN_FOCUSED_WINDOW ).put( KeyStroke.getKeyStroke( "ctrl c" ), "copy" ); + + getActionMap().put( "copy", new AbstractAction( "copy" ) + { + @Override + public void actionPerformed( ActionEvent evt ) + { + StringSelection stringSelection = new StringSelection( getSelectedText() ); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents( stringSelection, null ); + } + } ); + + } + + // Guarded by 'this' + boolean isReordingScheduled = false; + + private synchronized void reOrder() { + // Clear and refill the UI component. + try + { + entries.sort( Comparator.comparing(TranscriptWindowEntry::isDelayed).thenComparing( TranscriptWindowEntry::getTimestamp ) ); + clear(); + for ( TranscriptWindowEntry e : entries ) + { + e.addTo( this ); + } + } + catch ( BadLocationException ex ) + { + Log.error( "An exception prevented chat content to be redrawn in the user interface!", ex ); + } + finally + { + isReordingScheduled = false; + } + } + + protected synchronized void add( TranscriptWindowEntry entry ) + { + if ( !entries.isEmpty() ) + { + if ( entry.getTimestamp().isBefore( entries.getLast().getTimestamp() ) && !(entries.getLast() instanceof CustomTextEntry) ) + { + Log.debug( "A chat entry appears to have been delivered out of order. The transcript window must be reordered!" ); + if (!isReordingScheduled) { + Log.warning( "Scheduling new re-ordering of entries in the transcript window." ); + isReordingScheduled = true; + TaskEngine.getInstance().schedule(new TimerTask() + { + @Override + + public void run() + { + SwingUtilities.invokeLater(() -> reOrder()); + } + }, 250); + } + } + if ( !entry.getTimestamp().withZoneSameInstant( ZoneId.systemDefault() ).toLocalDate().isEqual( entries.getLast().getTimestamp().withZoneSameInstant( ZoneId.systemDefault() ).toLocalDate() ) ) + { + // The date appeared to have rolled over, since the last entry. Add a 'start-of-day' entry before we add + // the new entry, unless we're already in the process of adding exactly that 'start-of-day' entry. + final StartOfDayEntry startOfDayEntry = new StartOfDayEntry( entry.getTimestamp() ); + if ( !entry.equals( startOfDayEntry ) ) + { + add( startOfDayEntry ); + } + } + } + + entries.add( entry ); + + try + { + entry.addTo( this ); + } + catch ( BadLocationException ex ) + { + Log.error( "An exception prevented chat content to be displayed in the user interface!", ex ); + } + } + + + /** + * Inserts a component into the transcript window. + * + * @param component the component to insert. + */ + public void addComponent( Component component ) + { + final StyledDocument doc = (StyledDocument) getDocument(); + + // The image must first be wrapped in a style + Style style = doc.addStyle( "StyleName", null ); + + + StyleConstants.setComponent( style, component ); + + // Insert the image at the end of the text + try + { + doc.insertString( doc.getLength(), "ignored text", style ); + doc.insertString( doc.getLength(), "\n", null ); + } + catch ( BadLocationException e ) + { + Log.error( e ); + } + } + + /** + * Adds a text message this transcript window. + * + * Unless the provided message defines a timestamp (for instance, when a 'delay' extension is present), the message + * timestamp is assumed to be 'now'. + * + * @param nickname the nickname of the author of the message. + * @param message the message to insert. + * @param foreground the color to use for the nickname (excluding the message text) foreground. + */ + public void insertMessage( CharSequence nickname, Message message, Color foreground ) + { + insertMessage( nickname, message, foreground, null ); + } + + /** + * Adds a text message this transcript window. + * + * @param nickname the nickname of the author of the message. + * @param message the message to insert. + * @param foreground the color to use for the nickname (excluding the message text) foreground. + * @param background the color to use for the entire background (eg, to highlight). + */ + public void insertMessage( CharSequence nickname, Message message, Color foreground, Color background ) + { + String nicknameStr = nickname.toString(); + for ( TranscriptWindowInterceptor interceptor : SparkManager.getChatManager().getTranscriptWindowInterceptors() ) + { + try + { + boolean handled = interceptor.isMessageIntercepted( this, nicknameStr, message ); + if ( handled ) + { + // Do nothing. + return; + } + } + catch ( Exception e ) + { + Log.error( "A TranscriptWindowInterceptor ('" + interceptor + "') threw an exception while processing a chat message (current user: '" + nickname + "').", e ); + } + } + + // Verify the timestamp of this message. Determine if it is a 'live' message, or one that was sent earlier. + final DelayInformation inf = message.getExtension(DelayInformation.class); + final ZonedDateTime sentDate; + final boolean isDelayed; + if ( inf != null ) + { + sentDate = inf.getStamp().toInstant().atZone( ZoneOffset.UTC ); + isDelayed = true; + } + else + { + sentDate = ZonedDateTime.now(); + isDelayed = false; + } + + String body = getMessageBodyByLang(message); + if (body == null) { + return; + } + add( new MessageEntry( sentDate, isDelayed, nicknameStr, foreground, body, (Color) UIManager.get( "Message.foreground" ), background ) ); + } + + private static String getMessageBodyByLang(Message message) { + String preferredLocale = Locale.getDefault().getLanguage(); + String body = message.getBody(preferredLocale); + if (body == null) { + // return default body (no language) + body = message.getBody(); + } + return body; + } + + + /** + * Adds a notification message this transcript window. A notification message generally is a presence update, but + * can be used for most anything related to the room. + * + * The message timestamp is assumed to be 'now'. + * + * @param message the information message to insert. + * @param foregroundColor the foreground color to use. + */ + public synchronized void insertNotificationMessage( String message, Color foregroundColor ) + { + add( new CustomTextEntry( ZonedDateTime.now(), message, foregroundColor ) ); + } + + /** + * Adds a custom text message this transcript window. + * + * The message timestamp is assumed to be 'now'. + * + * @param text the text to insert. + * @param bold true to use bold text. + * @param underline true to have text underlined. + * @param foreground the foreground color. + */ + public synchronized void insertCustomText( String text, boolean bold, boolean underline, Color foreground ) + { + add( new CustomTextEntry( ZonedDateTime.now(), text, foreground, bold, false, underline, false ) ); + } + + /** + * Adds a custom text message this transcript window. + * + * The message timestamp is assumed to be 'now'. + * + * @param text the text to insert. + * @param bold true to use bold text. + * @param italic true to use italic text. + * @param underline true to have text underlined. + * @param strikeThrough true to have text strike through. + * @param foreground the foreground color. + */ + public synchronized void insertCustomText( String text, boolean bold, boolean italic, boolean underline, boolean strikeThrough, Color foreground ) + { + add( new CustomTextEntry( ZonedDateTime.now(), text, foreground, bold, italic, underline, strikeThrough ) ); + } + + /** + * Return the timestamp of the last entry that was added to this transcript window. + * + * If there is no entries in this window, the null is returned. + * + * @return the timestamp of the last entry in this window, or null when there are no entries. + */ + public Instant getLastUpdated() + { + if ( entries.isEmpty() ) + { + return null; + } + return entries.getLast().getTimestamp().toInstant(); + } + + /** + * Adds a historic text message to this transcript window. These typically are messages that were added to a chat + * before the local user joined the chat. + * + * @param userid the userid of the sender. + * @param message the message to insert. + * @param date the timestamp of the message. + */ + public void insertHistoryMessage( String userid, Message message, Date date ) + { + for ( TranscriptWindowInterceptor interceptor : SparkManager.getChatManager().getTranscriptWindowInterceptors() ) + { + try + { + boolean handled = interceptor.isHistoryMessageIntercepted( this, userid, message, date ); + if ( handled ) + { + // Do nothing. + return; + } + } + catch ( Exception e ) + { + Log.error( "A TranscriptWindowInterceptor ('" + interceptor + "') threw an exception while processing a chat history message (current user: '" + userid + "').", e ); + } + } + + final ZonedDateTime sentDate = date.toInstant().atZone( ZoneOffset.UTC ); + final Color historyColor = (Color) UIManager.get( "History.foreground" ); + + add(new MessageEntry(sentDate, true, userid, historyColor, message.getBody(), historyColor, null)); + } + + /** + * Adds a historic text message to this transcript window. These typically are messages that were added to a chat before the local user joined the chat. + * + * @param userid the userid of the sender. + * @param message the message to insert. + * @param date the timestamp of the message. + */ + public void insertHistoryMessage( String userid, String message, Date date) + { + insertHistoryMessage(userid, message, date, Map.of()); + } + + /** + * Adds a tagged historic text message to this transcript window. This is the same as {@link #insertHistoryMessage(String, Message, Date)}, except custom style(s) can be applied to specific part(s) of the message using Asciidoc-like + * Custom Inline Styles: + *

      {@code [.style-name]#my styled text#} will have the effect of applying the style corresponding to {@code style-name} in {@code customStyles} parameter, to the text between {@code #} characters. + * + * @param userid the userid of the sender. + * @param message the message to insert. + * @param date the timestamp of the message. + * @param customStyles custom styles to be applied to the parts of the message between {@code #} and following {@code [.style-name]} where {@code style-name} is the key identifying the style attributes in this parameter. + */ + public void insertHistoryMessage( String userid, String message, Date date, Map customStyles) + { + final ZonedDateTime sentDate = date.toInstant().atZone( ZoneOffset.UTC ); + final Color historyColor = (Color) UIManager.get( "History.foreground" ); + + add(new MessageEntry(sentDate, true, userid, historyColor, message, historyColor, null)); + } + + public void insertHorizontalLine() + { + add( new HorizontalLineEntry() ); + } + + /** + * Disable the entire TranscriptWindow and visually represent + * it as disabled. + */ + public void showWindowDisabled() + { + final Document document = getDocument(); + final SimpleAttributeSet attrs = new SimpleAttributeSet(); + StyleConstants.setForeground( attrs, Color.LIGHT_GRAY ); + + final int length = document.getLength(); + StyledDocument styledDocument = getStyledDocument(); + styledDocument.setCharacterAttributes( 0, length, attrs, false ); + } + + /** + * Persist a current transcript. + * + * @param fileName the name of the file to save the transcript as. Note: This can be modified by the user. + * @param transcript the collection of transcript. + * @param headerData the string to prepend to the transcript. + * @see ChatRoom#getTranscripts() + */ + public void saveTranscript( String fileName, List transcript, String headerData ) + { + final LocalPreferences pref = SettingsManager.getLocalPreferences(); + + try + { + SimpleDateFormat formatter; + + File defaultSaveFile = new File(Spark.getSparkUserHome(), fileName); + final JFileChooser fileChooser = new JFileChooser( defaultSaveFile ); + fileChooser.setSelectedFile( defaultSaveFile ); + + // Show save dialog; this method does not return until the dialog is closed + int result = fileChooser.showSaveDialog( this ); + final File selFile = fileChooser.getSelectedFile(); + + if ( selFile != null && result == JFileChooser.APPROVE_OPTION ) + { + final StringBuilder buf = new StringBuilder(); + final Iterator transcripts = transcript.iterator(); + buf.append( "" ); + if ( headerData != null ) + { + buf.append( headerData ); + } + + buf.append( "" ); + while ( transcripts.hasNext() ) + { + final Message message = transcripts.next(); + String from = null; + if (message.getFrom() != null) { + from = message.getFrom().toString(); + } + if ( from == null ) + { + from = pref.getNickname().toString(); + } + + if ( Message.Type.groupchat == message.getType() ) + { + if ( ModelUtil.hasLength( XmppStringUtils.parseResource( from ) ) ) + { + from = XmppStringUtils.parseResource( from ); + } + } + + final String body = message.getBody(); + + final JivePropertiesExtension extension = message.getExtension(JivePropertiesExtension.class); + Date insertionDate = null; + if ( extension != null ) + { + insertionDate = (Date) extension.getProperty( "insertionDate" ); + } + + formatter = new SimpleDateFormat( "hh:mm:ss" ); + + String value = ""; + if ( insertionDate != null ) + { + value = "(" + formatter.format( insertionDate ) + ") "; + } + buf.append( "" ); + + } + buf.append( "
      " ).append( value ).append( "" ).append( from ).append( ": " ).append( body ).append( "
      " ); + final BufferedWriter writer = new BufferedWriter( new FileWriter( selFile ) ); + writer.write( buf.toString() ); + writer.close(); + UIManager.put( "OptionPane.okButtonText", Res.getString( "ok" ) ); + JOptionPane.showMessageDialog( SparkManager.getMainWindow(), "Chat transcript has been saved.", + "Chat Transcript Saved", JOptionPane.INFORMATION_MESSAGE ); + } + } + catch ( Exception ex ) + { + Log.error( "Unable to save chat transcript.", ex ); + UIManager.put( "OptionPane.okButtonText", Res.getString( "ok" ) ); + JOptionPane.showMessageDialog( SparkManager.getMainWindow(), "Could not save transcript.", "Error", JOptionPane.ERROR_MESSAGE ); + } + + } + + public void cleanup() + { + super.releaseResources(); + + clear(); + + removeMouseListener( this ); + removeMouseMotionListener( this ); + + removeContextMenuListener( this ); + getActionMap().remove( "copy" ); + } + + /** + * Adds Print and Clear actions. + * + * @param object the TransferWindow + * @param popup the popup menu to add to. + */ + @Override + public void poppingUp( final Object object, JPopupMenu popup ) + { + popup.addSeparator(); + + popup.add(new AbstractAction(Res.getString("action.print"), SparkRes.getImageIcon(SparkRes.Icon.PRINTER_IMAGE_16x16)) + { + @Override + public void actionPerformed( ActionEvent actionEvent ) + { + SparkManager.printChatTranscript( (TranscriptWindow) object ); + } + } ); + + if (!Default.getBoolean(Default.HIDE_HISTORY_SETTINGS) && Enterprise.containsFeature(Enterprise.HISTORY_SETTINGS_FEATURE) + && !Default.getBoolean(Default.HISTORY_DISABLED) && Enterprise.containsFeature(Enterprise.HISTORY_TRANSCRIPTS_FEATURE)) { + popup.add(new AbstractAction(Res.getString("action.clear"), SparkRes.getImageIcon(SparkRes.Icon.ERASER_IMAGE)) + { + @Override + public void actionPerformed( ActionEvent actionEvent ) + { + String user = null; + try + { + ChatManager manager = SparkManager.getChatManager(); + ChatRoom room = manager.getChatContainer().getActiveChatRoom(); + user = room.getBareJid().toString(); + + int ok = JOptionPane.showConfirmDialog( (TranscriptWindow) object, + Res.getString( "delete.permanently" ), + Res.getString( "delete.log.permanently" ), + JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE ); + if ( ok == JOptionPane.YES_OPTION ) + { + // This actions must be move into Transcript Plugin! + File transcriptDir = new File( SparkManager.getUserDirectory(), "transcripts" ); + File transcriptFile = new File( transcriptDir, user + ".xml" ); + transcriptFile.delete(); + transcriptFile = new File( transcriptDir, user + "_current.xml" ); + transcriptFile.delete(); + clear(); + } + } + catch ( Exception ex ) + { + Log.error( "An exception occurred while trying to clear history for a chat room " + user, ex ); + } + } + } ); + } + ChatRoom room = null; + try{ + room = SparkManager.getChatManager().getChatContainer().getActiveChatRoom(); + }catch (Exception e){ + Log.error( "An exception occurred while trying to get active chat room " + room, e ); + } + + + // History window + if (!Default.getBoolean(Default.HISTORY_DISABLED) && Enterprise.containsFeature(Enterprise.HISTORY_TRANSCRIPTS_FEATURE)) { + if(room != null && room.getChatType() == Message.Type.chat){ + ChatRoom finalRoom = room; + popup.add(new AbstractAction( Res.getString( "action.viewlog" ) ) + { + @Override + public void actionPerformed( ActionEvent e ) + { + try + { + HistoryWindow hw = new HistoryWindow( SparkManager.getUserDirectory(), finalRoom.getJid().toString() ); + hw.showWindow(); + } + catch ( Exception ex ) + { + Log.error( "An exception occurred while trying to open history window for room " + finalRoom, ex ); + } + } + } ); + } + } + } + + @Override + public void poppingDown( JPopupMenu popup ) + { + } + + @Override + public boolean handleDefaultAction( MouseEvent e ) + { + return false; + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/TranscriptWindowEntry.java b/core/src/main/java/org/jivesoftware/spark/ui/TranscriptWindowEntry.java new file mode 100644 index 000000000..94a38a40b --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/TranscriptWindowEntry.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2017 Ignite Realtime Foundation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import javax.swing.text.BadLocationException; +import java.time.ZonedDateTime; +import java.util.Objects; + +/** + * One entry in a transcript window (typically a line of text). + * + * This class and its descendants represent an entry of content displayed in a transcript window, including its + * formatting. + * + * @author Guus der Kinderen, guus.der.kinderen@gmail.com. + */ +public abstract class TranscriptWindowEntry +{ + private final ZonedDateTime timestamp; + protected final boolean isDelayed; + + /** + * Constructs a new entry. + * + * When displayed in context of a conversation, chat entries are ordered by time. This is why the time component + * of an entry is non-optional. Note that multiple entries can exist that have the same time component. + * + * @param timestamp The timestamp of the entry (cannot be null). + */ + protected TranscriptWindowEntry( ZonedDateTime timestamp ){ + this(timestamp, false); + } + /** + * Constructs a new entry. + * + * When displayed in context of a conversation, chat entries are ordered by time. This is why the time component + * of an entry is non-optional. Note that multiple entries can exist that have the same time component. + * + * @param timestamp The timestamp of the entry (cannot be null). + * @param isDelayed Set true if contain delayed, historic timestamp. + */ + protected TranscriptWindowEntry( ZonedDateTime timestamp, boolean isDelayed ) + { + Objects.requireNonNull(timestamp); + this.timestamp = timestamp; + this.isDelayed = isDelayed; + } + + /** + * The timestamp of the entry. + * + * @return A (zoned) timestamp (never null). + */ + public ZonedDateTime getTimestamp() + { + return timestamp; + } + + /** + * Adds this entry to the provided chat area. + * + * This method is intended to be overridden by subclasses, which allows each subclass to decorate its content + * appropriately. + * + * @param chatArea the ChatArea to which content is to be added (cannot be null). + */ + protected abstract void addTo( ChatArea chatArea ) throws BadLocationException; + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + + TranscriptWindowEntry that = (TranscriptWindowEntry) o; + + return timestamp.toInstant().equals( that.timestamp.toInstant() ); + } + + @Override + public int hashCode() + { + return timestamp.toInstant().hashCode(); + } + + /** + * Is it delayed message. + * @return True if message contain historic, delayed delivery timestamp. + */ + public boolean isDelayed() { + return isDelayed; + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/TranscriptWindowInterceptor.java b/core/src/main/java/org/jivesoftware/spark/ui/TranscriptWindowInterceptor.java new file mode 100644 index 000000000..650f03ecb --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/TranscriptWindowInterceptor.java @@ -0,0 +1,54 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import org.jivesoftware.smack.packet.Message; + +import java.util.Date; + +/** + * Allows users to intercept messages before they are inserted into the TranscriptWindow. + * + * @see TranscriptWindow + * @see org.jivesoftware.spark.ChatManager + */ +public interface TranscriptWindowInterceptor { + + /** + * Is called before a message by this user is inserted into the TranscriptWindow. + * + * @param window the TranscriptWindow. + * @param userid the userid. + * @param message the message to be inserted. + * @return true if it should be handled by a custom interceptor. + */ + boolean isMessageIntercepted(TranscriptWindow window, String userid, Message message); + + /** + * Is called before a historic text message by this user is inserted into the TranscriptWindow. + * History messages are typically messages that were added to a chat before the local user joined the chat. + * + * @param window the TranscriptWindow. + * @param userid the userid. + * @param message the message to be inserted. + * @param date the timestamp of the message + * @return true if it should be handled by a custom interceptor. + */ + default boolean isHistoryMessageIntercepted(TranscriptWindow window, String userid, Message message, Date date) + { + return false; + } +} diff --git a/src/java/org/jivesoftware/spark/ui/VCardPanel.java b/core/src/main/java/org/jivesoftware/spark/ui/VCardPanel.java similarity index 75% rename from src/java/org/jivesoftware/spark/ui/VCardPanel.java rename to core/src/main/java/org/jivesoftware/spark/ui/VCardPanel.java index 3136cbfc3..2f2561c66 100644 --- a/src/java/org/jivesoftware/spark/ui/VCardPanel.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/VCardPanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,21 +29,17 @@ import java.net.URI; import java.net.URISyntaxException; -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JWindow; -import javax.swing.Timer; +import javax.swing.*; import org.jivesoftware.resource.SparkRes; import org.jivesoftware.smackx.vcardtemp.packet.VCard; import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.UserManager; import org.jivesoftware.spark.util.GraphicUtils; import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.Sizes; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.impl.JidCreate; /** * UI to display VCard Information in Wizards, Dialogs, Chat Rooms and any other container. @@ -57,11 +49,11 @@ public class VCardPanel extends JPanel { private static final long serialVersionUID = -5810110243694315630L; - private Cursor DEFAULT_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR); - private Cursor LINK_CURSOR = new Cursor(Cursor.HAND_CURSOR); + private final Cursor DEFAULT_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR); + private final Cursor LINK_CURSOR = new Cursor(Cursor.HAND_CURSOR); - private JWindow _avatarHoverWindow = new JWindow(); - private final String jid; + private final JWindow _avatarHoverWindow = new JWindow(); + private final BareJid jid; private final JLabel avatarImage; private String emailAddress = ""; @@ -71,7 +63,7 @@ public class VCardPanel extends JPanel { * * @param jid the jid to use when retrieving the vcard information. */ - public VCardPanel(final String jid) { + public VCardPanel(final BareJid jid) { setLayout(new GridBagLayout()); setOpaque(false); @@ -80,12 +72,15 @@ public VCardPanel(final String jid) { add(avatarImage, new GridBagConstraints(0, 0, 1, 3, 0.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 0, 5, 0), 0, 0)); buildAvatarHover(); - Image aImage = SparkRes.getImageIcon(SparkRes.BLANK_24x24).getImage(); - aImage = aImage.getScaledInstance(-1, 64, Image.SCALE_SMOOTH); - ImageIcon ico = new ImageIcon(aImage); - - avatarImage.setIcon(ico); + try { + Image aImage = SparkRes.getImageIcon(SparkRes.Icon.BLANK_24x24).getImage(); + aImage = aImage.getScaledInstance(-1, 64, Image.SCALE_SMOOTH); + ImageIcon ico = new ImageIcon(aImage); + avatarImage.setIcon(ico); + } catch (Exception e) { + Log.error("Unable to process image in vcard!", e); + } VCard vcard = SparkManager.getVCardManager().getVCard(jid); @@ -102,22 +97,22 @@ public VCardPanel(final String jid) { try { icon = new ImageIcon(bytes); Image newImage = icon.getImage(); - if (icon.getIconHeight() > 48 || icon.getIconWidth() > 48) { - newImage = newImage.getScaledInstance(-1, 48, Image.SCALE_SMOOTH); + if (icon.getIconHeight() > Sizes.Avatar.VCARD || icon.getIconWidth() > Sizes.Avatar.VCARD) { + newImage = newImage.getScaledInstance(-1, Sizes.Avatar.VCARD, Image.SCALE_SMOOTH); } icon = new ImageIcon(newImage); } catch (Exception e) { - Log.error(e); + Log.error("Unable to fetch image in vcard!", e); } } else { - icon = SparkRes.getImageIcon(SparkRes.DEFAULT_AVATAR_32x32_IMAGE); + icon = SparkRes.getImageIcon(SparkRes.Icon.DEFAULT_AVATAR_32x32_IMAGE); } if (icon != null && icon.getIconWidth() > 0) { avatarImage.setIcon(icon); - avatarImage.setBorder(BorderFactory.createBevelBorder(0, Color.white, Color.lightGray)); + avatarImage.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); } vcard.setJabberId(jid); @@ -127,10 +122,11 @@ public VCardPanel(final String jid) { private void buildAvatarHover() { _avatarHoverWindow.addMouseListener(new MouseAdapter() { - public void mouseExited(MouseEvent e) { + @Override + public void mouseExited(MouseEvent e) { showAvatarBig(false, null); - }; + } }); } @@ -149,17 +145,17 @@ private void showAvatarBig(boolean bool, VCard vcard) { try { icon = new ImageIcon(bytes); newImage = icon.getImage(); - if (icon.getIconHeight() > 128 || icon.getIconWidth() > 128) { - newImage = newImage.getScaledInstance(-1, 128, Image.SCALE_SMOOTH); + if (icon.getIconHeight() > Sizes.Avatar.HOVER_BIG || icon.getIconWidth() > Sizes.Avatar.HOVER_BIG) { + newImage = newImage.getScaledInstance(-1, Sizes.Avatar.HOVER_BIG, Image.SCALE_SMOOTH); } icon = new ImageIcon(newImage); } catch (Exception e1) { - Log.error(e1); + Log.error("Unable to process vcard avatar", e1); } } else { - icon = SparkRes.getImageIcon(SparkRes.DEFAULT_AVATAR_32x32_IMAGE); + icon = SparkRes.getImageIcon(SparkRes.Icon.DEFAULT_AVATAR_32x32_IMAGE); } label.setIcon(icon); @@ -178,9 +174,11 @@ private void showAvatarBig(boolean bool, VCard vcard) { private void buildUI(final VCard vcard) { avatarImage.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent mouseEvent) { + @Override + public void mouseClicked(MouseEvent mouseEvent) { if (mouseEvent.getClickCount() == 2) { - SparkManager.getVCardManager().viewProfile(vcard.getJabberId(), avatarImage); + BareJid bareJid = JidCreate.bareFromOrThrowUnchecked(vcard.getJabberId()); + SparkManager.getVCardManager().viewProfile(bareJid, avatarImage); } } @@ -200,28 +198,19 @@ public void mouseExited(MouseEvent e) { }); - String firstName = vcard.getFirstName(); - if (firstName == null) { - firstName = ""; - } - - String lastName = vcard.getLastName(); - if (lastName == null) { - lastName = ""; - } - + String fullName = vcard.getField("FN"); final JLabel usernameLabel = new JLabel(); usernameLabel.setHorizontalTextPosition(JLabel.LEFT); usernameLabel.setFont(new Font("Dialog", Font.BOLD, 15)); usernameLabel.setForeground(Color.GRAY); - if (ModelUtil.hasLength(firstName) && ModelUtil.hasLength(lastName)) { - usernameLabel.setText(firstName + " " + lastName); + if (ModelUtil.hasLength(fullName)) { + usernameLabel.setText(fullName); } else { String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid); - usernameLabel.setText(UserManager.unescapeJID(nickname)); + usernameLabel.setText(nickname); } @@ -249,17 +238,20 @@ public void mouseExited(MouseEvent e) { final String hoverText = "" + emailAddress + ""; final JLabel emailTime = new JLabel(unselectedText); emailTime.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { + @Override + public void mouseClicked(MouseEvent e) { startEmailClient(emailAddress); } - public void mouseEntered(MouseEvent e) { + @Override + public void mouseEntered(MouseEvent e) { emailTime.setText(hoverText); setCursor(LINK_CURSOR); } - public void mouseExited(MouseEvent e) { + @Override + public void mouseExited(MouseEvent e) { emailTime.setText(unselectedText); setCursor(DEFAULT_CURSOR); } diff --git a/core/src/main/java/org/jivesoftware/spark/ui/VCardViewer.java b/core/src/main/java/org/jivesoftware/spark/ui/VCardViewer.java new file mode 100644 index 000000000..0f6cbc7df --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/VCardViewer.java @@ -0,0 +1,264 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Desktop; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Image; +import java.awt.Insets; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import javax.swing.*; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smackx.vcardtemp.packet.VCard; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.UserManager; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.Sizes; +import org.jxmpp.jid.BareJid; + +/** + * UI to display VCard Information in Wizards, Dialogs, Chat Rooms and any other container. + * + * @author Derek DeMoro + */ +public class VCardViewer extends JPanel { + + private static final long serialVersionUID = -5642099937626355102L; + private final Cursor DEFAULT_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR); + private final Cursor LINK_CURSOR = new Cursor(Cursor.HAND_CURSOR); + + private final BareJid jid; + private final JLabel avatarImage; + + private String emailAddress = ""; + + /** + * Generate a VCard Panel using the specified jid. + * + * @param jid the jid to use when retrieving the vcard information. + */ + public VCardViewer(final BareJid jid) { + setLayout(new GridBagLayout()); + setOpaque(false); + + this.jid = jid; + avatarImage = new JLabel(); + add(avatarImage, new GridBagConstraints(0, 0, 1, 3, 0.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 0, 5, 0), 0, 0)); + + try { + Image aImage = SparkRes.getImageIcon(SparkRes.Icon.BLANK_24x24).getImage(); + aImage = aImage.getScaledInstance(-1, Sizes.Avatar.VCARD_VIEW, Image.SCALE_SMOOTH); + ImageIcon ico = new ImageIcon(aImage); + + avatarImage.setIcon(ico); + + final SwingWorker vcardLoader = new SwingWorker() + { + VCard vcard = null; + + @Override + public Object construct() + { + vcard = SparkManager.getVCardManager().getVCard(jid); + return vcard; + } + + @Override + public void finished() + { + if (vcard == null) { + // Do nothing. + return; + } + + ImageIcon icon = null; + + byte[] bytes = vcard.getAvatar(); + if (bytes != null && bytes.length > 0) { + try { + icon = new ImageIcon(bytes); + Image aImage = icon.getImage(); + aImage = aImage.getScaledInstance(-1, Sizes.Avatar.VCARD, Image.SCALE_SMOOTH); + icon = new ImageIcon(aImage); + } catch (Exception e) { + Log.warning("Unable to get scaled avatar from vcard.", e); + } + } else { + icon = SparkRes.getImageIcon(SparkRes.Icon.DEFAULT_AVATAR_32x32_IMAGE); + } + + if (icon != null && icon.getIconWidth() > 0) { + avatarImage.setIcon(icon); + avatarImage.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); + } + + vcard.setJabberId(jid); + buildUI(vcard); + } + }; + vcardLoader.start(); + } catch (Exception e) { + Log.warning("Unable to get avatar from vcard.", e); + } + } + + private void buildUI(final VCard vcard) { + String fullName = vcard.getField("FN"); + + final JLabel usernameLabel = new JLabel(); + usernameLabel.setHorizontalTextPosition(JLabel.LEFT); + usernameLabel.setFont(new Font(Font.DIALOG, Font.BOLD, 15)); + + usernameLabel.setForeground(Color.GRAY); + if (ModelUtil.hasLength(fullName)) { + usernameLabel.setText(fullName); + } + else { + String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid); + usernameLabel.setText(nickname); + } + + + final Icon icon = SparkManager.getChatManager().getIconForContactHandler(vcard.getJabberId()); + if (icon != null) { + usernameLabel.setIcon(icon); + } + + + add(usernameLabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 0), 0, 0)); + + String title = vcard.getField("TITLE"); + if (ModelUtil.hasLength(title)) { + final JLabel titleLabel = new JLabel(title); + titleLabel.setFont(new Font(Font.DIALOG, Font.PLAIN, 11)); + add(titleLabel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 0, 0), 0, 0)); + } + + + if (ModelUtil.hasLength(vcard.getEmailHome())) { + emailAddress = vcard.getEmailHome(); + } + + final Color linkColor = new Color(49, 89, 151); + final String unselectedText = "" + emailAddress + ""; + final String hoverText = "" + emailAddress + ""; + final JLabel emailTime = new JLabel(unselectedText); + emailTime.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + startEmailClient(emailAddress); + } + + @Override + public void mouseEntered(MouseEvent e) { + emailTime.setText(hoverText); + setCursor(LINK_CURSOR); + + } + + @Override + public void mouseExited(MouseEvent e) { + emailTime.setText(unselectedText); + setCursor(DEFAULT_CURSOR); + } + }); + + + add(emailTime, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 10, 0), 0, 0)); + + // Add JID Label + final String jid = UserManager.unescapeJID(vcard.getJabberId()); + final JLabel jidLabel = new JLabel("JID: " + jid + ""); + jidLabel.setToolTipText("Click to copy jid to clipboard."); + jidLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent mouseEvent) { + jidLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent mouseEvent) { + jidLabel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + + } + + @Override + public void mouseClicked(MouseEvent mouseEvent) { + SparkManager.setClipboard(jid); + } + }); + + add(jidLabel, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 2, 0), 0, 0)); + + // Add Home Phone + String homeNumber = vcard.getPhoneHome("VOICE"); + if (!ModelUtil.hasLength(homeNumber)) { + homeNumber = Res.getString("label.na"); + } + final JLabel homePhoneLabel = new JLabel(Res.getString("label.home").replace("&", "") + ": " + homeNumber); + add(homePhoneLabel, new GridBagConstraints(1, 4, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 2, 0), 0, 0)); + + // Add Work Phone + String workNumber = vcard.getPhoneWork("VOICE"); + if (!ModelUtil.hasLength(workNumber)) { + workNumber = Res.getString("label.na"); + } + final JLabel workPhoneLabel = new JLabel(Res.getString("label.work").replace("&", "") + ": " + workNumber); + add(workPhoneLabel, new GridBagConstraints(1, 5, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 2, 0), 0, 0)); + + // Add Cell Phone + String cellNumber = vcard.getPhoneWork("CELL"); + if (!ModelUtil.hasLength(cellNumber)) { + cellNumber = Res.getString("label.na"); + } + + final JLabel cellPhoneLabel = new JLabel(Res.getString("label.cell").replace("&", "") + ": " + cellNumber); + add(cellPhoneLabel, new GridBagConstraints(1, 6, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 2, 0), 0, 0)); + + // Add Company + String company = vcard.getOrganization(); + final JLabel orgLabel = new JLabel(Res.getString("label.company").replace("&", "") + ": " + company); + add(orgLabel, new GridBagConstraints(1, 7, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 2, 0), 0, 0)); + + } + + + private void startEmailClient(String emailAddress) { + try { + Desktop.getDesktop().mail(new URI("mailto:" + emailAddress)); + } catch (IOException e) { + Log.error("Can't open Mailer", e); + } catch (URISyntaxException e) { + Log.error("URI Wrong", e); + } + } + + +} diff --git a/src/java/org/jivesoftware/spark/ui/WrapColumnFactory.java b/core/src/main/java/org/jivesoftware/spark/ui/WrapColumnFactory.java similarity index 95% rename from src/java/org/jivesoftware/spark/ui/WrapColumnFactory.java rename to core/src/main/java/org/jivesoftware/spark/ui/WrapColumnFactory.java index c73639116..d96e1c530 100644 --- a/src/java/org/jivesoftware/spark/ui/WrapColumnFactory.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/WrapColumnFactory.java @@ -10,7 +10,8 @@ */ public class WrapColumnFactory implements ViewFactory { - public View create( Element elem ) + @Override + public View create( Element elem ) { String kind = elem.getName(); if ( kind != null ) diff --git a/src/java/org/jivesoftware/spark/ui/WrapEditorKit.java b/core/src/main/java/org/jivesoftware/spark/ui/WrapEditorKit.java similarity index 91% rename from src/java/org/jivesoftware/spark/ui/WrapEditorKit.java rename to core/src/main/java/org/jivesoftware/spark/ui/WrapEditorKit.java index c50bf6c16..eda4eb385 100644 --- a/src/java/org/jivesoftware/spark/ui/WrapEditorKit.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/WrapEditorKit.java @@ -13,7 +13,8 @@ public class WrapEditorKit extends StyledEditorKit { private final ViewFactory defaultFactory = new WrapColumnFactory(); - public ViewFactory getViewFactory() + @Override + public ViewFactory getViewFactory() { return defaultFactory; } diff --git a/src/java/org/jivesoftware/spark/ui/WrapLabelView.java b/core/src/main/java/org/jivesoftware/spark/ui/WrapLabelView.java similarity index 93% rename from src/java/org/jivesoftware/spark/ui/WrapLabelView.java rename to core/src/main/java/org/jivesoftware/spark/ui/WrapLabelView.java index 0ecc22347..3e4f4cf16 100644 --- a/src/java/org/jivesoftware/spark/ui/WrapLabelView.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/WrapLabelView.java @@ -17,7 +17,8 @@ public WrapLabelView( Element elem ) super( elem ); } - public float getMinimumSpan( int axis ) + @Override + public float getMinimumSpan( int axis ) { switch ( axis ) { diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/AnswerFormDialog.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/AnswerFormDialog.java new file mode 100644 index 000000000..5dd47f3ea --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/AnswerFormDialog.java @@ -0,0 +1,113 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.conferences; + +import java.awt.*; +import javax.swing.*; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.xdata.form.FillableForm; +import org.jivesoftware.smackx.xdata.packet.DataForm; +import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.DataFormUI; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jxmpp.jid.parts.Resourcepart; + +import static org.apache.commons.lang3.StringUtils.isBlank; +import static org.jivesoftware.spark.ChatManager.ERROR_COLOR; +import static org.jivesoftware.spark.ChatManager.NOTIFICATION_COLOR; +import static org.jivesoftware.sparkimpl.settings.local.SettingsManager.getLocalPreferences; + +/** + * Answer Form Dialog. + * Used for registration in the room. + * + * @author wolf.posdorfer + */ +public class AnswerFormDialog { + private final DataFormUI dataFormUI; + private final JDialog dialog; + + public AnswerFormDialog(JFrame parent, final MultiUserChat chat, final DataForm form) { + this.dataFormUI = new DataFormUI(form); + preFillForm(); + dialog = new JDialog(parent, true); + dialog.setTitle(Res.getString("button.register").replace("&", "")); + dialog.setLayout(new GridBagLayout()); + + JButton updateButton = new JButton(); + ResourceUtils.resButton(updateButton, Res.getString("apply")); + updateButton.addActionListener(e -> { + dialog.dispose(); + sendAnswerForm(chat); + }); + + JButton cancelButton = new JButton(); + ResourceUtils.resButton(cancelButton, Res.getString("button.cancel")); + cancelButton.addActionListener(actionEvent -> dialog.dispose()); + + JPanel bottomPanel = new JPanel(); + bottomPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)); + bottomPanel.add(updateButton); + bottomPanel.add(cancelButton); + + dialog.getContentPane().setLayout(new BorderLayout()); + dialog.getContentPane().add(dataFormUI, BorderLayout.CENTER); + dialog.getContentPane().add(bottomPanel, BorderLayout.SOUTH); + + dialog.pack(); +// dialog.setSize(600, 400); + GraphicUtils.centerWindowOnScreen(dialog); + dialog.setVisible(true); + } + + private void preFillForm() { + Resourcepart defaultNickname = getLocalPreferences().getNickname(); + JComponent nicknameField = dataFormUI.getComponent("muc#register_roomnick"); + if (nicknameField instanceof JTextField && isBlank(((JTextField)nicknameField).getText())) { + ((JTextField)nicknameField).setText(defaultNickname.toString()); + } + JComponent firstNameField = dataFormUI.getComponent("muc#register_first"); + if (firstNameField instanceof JTextField && isBlank(((JTextField)firstNameField).getText())) { + ((JTextField)firstNameField).setText(defaultNickname.toString()); //TODO get First Name + } + JComponent lastNameField = dataFormUI.getComponent("muc#register_last"); + if (lastNameField instanceof JTextField && isBlank(((JTextField)lastNameField).getText())) { + ((JTextField)lastNameField).setText(defaultNickname.toString()); //TODO get Last Name + } + } + + /** + * Sends the Answer Form + */ + private void sendAnswerForm(MultiUserChat chat) { + ChatRoom room = SparkManager.getChatManager().getChatRoom(chat.getRoom()); + FillableForm filledForm = dataFormUI.getFilledForm(); + try { + chat.sendRegistrationForm(filledForm); + String reg = Res.getString("message.groupchat.registered.member", chat.getRoom()); + room.getTranscriptWindow().insertNotificationMessage(reg, NOTIFICATION_COLOR); + } catch (XMPPException | SmackException | InterruptedException e) { + room.getTranscriptWindow().insertNotificationMessage(e.getMessage(), ERROR_COLOR); + } + } + +} diff --git a/src/java/org/jivesoftware/spark/ui/conferences/BannedUsers.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/BannedUsers.java similarity index 77% rename from src/java/org/jivesoftware/spark/ui/conferences/BannedUsers.java rename to core/src/main/java/org/jivesoftware/spark/ui/conferences/BannedUsers.java index 794bbeee2..336ba91ac 100644 --- a/src/java/org/jivesoftware/spark/ui/conferences/BannedUsers.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/BannedUsers.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.jivesoftware.spark.ui.conferences; import org.jivesoftware.resource.SparkRes; @@ -29,6 +25,9 @@ import org.jivesoftware.spark.ui.ChatRoom; import org.jivesoftware.spark.ui.rooms.GroupChatRoom; import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; import javax.swing.DefaultListModel; import javax.swing.ImageIcon; @@ -47,57 +46,54 @@ * Handles unbanning banned users in Chat Rooms. */ public class BannedUsers extends JPanel { - private static final long serialVersionUID = 6422162361752646645L; - private MultiUserChat chat; - private DefaultListModel listModel = new DefaultListModel(); - private JList list = new JList(listModel); - private JMenuItem unBanMenuItem = new JMenuItem(Res.getString("menuitem.unban")); + private final DefaultListModel listModel = new DefaultListModel<>(); + private final JList list = new JList<>(listModel); + private final JMenuItem unBanMenuItem = new JMenuItem(Res.getString("menuitem.unban")); - /** - * Construct UI - */ public BannedUsers() { setLayout(new BorderLayout()); list.setCellRenderer(new ListIconRenderer()); add(list, BorderLayout.CENTER); // Respond to Double-Click in Agent List to start a chat list.addMouseListener(new MouseAdapter() { + @Override public void mousePressed(MouseEvent evt) { if (evt.isPopupTrigger()) { int index = list.locationToIndex(evt.getPoint()); list.setSelectedIndex(index); - ImageIcon icon = (ImageIcon)list.getModel().getElementAt(index); + ImageIcon icon = list.getModel().getElementAt(index); String jid = icon.getDescription(); showPopup(evt, jid); } } + @Override public void mouseReleased(MouseEvent evt) { if (evt.isPopupTrigger()) { int index = list.locationToIndex(evt.getPoint()); list.setSelectedIndex(index); - ImageIcon icon = (ImageIcon)list.getModel().getElementAt(index); + ImageIcon icon = list.getModel().getElementAt(index); String jid = icon.getDescription(); showPopup(evt, jid); } } }); - unBanMenuItem.addActionListener( e -> { + unBanMenuItem.addActionListener(e -> { int index = list.getSelectedIndex(); - ImageIcon icon = (ImageIcon)list.getModel().getElementAt(index); - String jid = icon.getDescription(); + ImageIcon icon = list.getModel().getElementAt(index); + String jidString = icon.getDescription(); try { + BareJid jid = JidCreate.fromUnescaped(jidString).asBareJid(); chat.grantMembership(jid); - } - catch (XMPPException | SmackException memEx) { + } catch (XMPPException | SmackException | XmppStringprepException | InterruptedException memEx) { Log.error("Error granting membership", memEx); } listModel.removeElementAt(index); - } ); + }); } /** @@ -120,15 +116,14 @@ public void loadAllBannedUsers() { Iterator bannedUsers = null; try { bannedUsers = chat.getOutcasts().iterator(); - } - catch (XMPPException | SmackException e) { + } catch (XMPPException | SmackException | InterruptedException e) { Log.error("Error loading all banned users", e); } while (bannedUsers != null && bannedUsers.hasNext()) { Affiliate bannedUser = bannedUsers.next(); - ImageIcon icon = SparkRes.getImageIcon(SparkRes.STAR_RED_IMAGE); - icon.setDescription(bannedUser.getJid()); + ImageIcon icon = SparkRes.getImageIcon(SparkRes.Icon.STAR_RED_IMAGE); + icon.setDescription(bannedUser.getJid().toString()); listModel.addElement(icon); } } diff --git a/src/java/org/jivesoftware/spark/ui/conferences/BookmarksListener.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/BookmarksListener.java similarity index 96% rename from src/java/org/jivesoftware/spark/ui/conferences/BookmarksListener.java rename to core/src/main/java/org/jivesoftware/spark/ui/conferences/BookmarksListener.java index d1e544261..b9eedca8d 100644 --- a/src/java/org/jivesoftware/spark/ui/conferences/BookmarksListener.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/BookmarksListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +18,6 @@ import org.jivesoftware.sparkimpl.plugin.bookmarks.BookmarkUI; /** - * * @author kos */ public interface BookmarksListener { diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/BookmarksUI.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/BookmarksUI.java new file mode 100644 index 000000000..702ab9fb7 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/BookmarksUI.java @@ -0,0 +1,653 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.conferences; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.bookmarks.BookmarkManager; +import org.jivesoftware.smackx.bookmarks.BookmarkedConference; +import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; +import org.jivesoftware.smackx.disco.packet.DiscoverInfo; +import org.jivesoftware.smackx.disco.packet.DiscoverItems; +import org.jivesoftware.smackx.muc.MultiUserChatConstants; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.JiveTreeCellRenderer; +import org.jivesoftware.spark.component.JiveTreeNode; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.component.Tree; +import org.jivesoftware.spark.plugin.ContextMenuListener; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; + +import javax.swing.*; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * BookmarkedConferences is used to display the UI for all bookmarked conference rooms. + */ +public class BookmarksUI extends JPanel { + /** + * Tree used to display bookmarks. + */ + private Tree tree; + private JiveTreeNode rootNode; + private List mucServices; + private final Set autoJoinRooms = new HashSet<>(); + private final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList<>(); + + private final CopyOnWriteArrayList bookmarkListeners = new CopyOnWriteArrayList<>(); + + private BookmarkManager manager; + + public BookmarksUI() { + } + + /** + * Initialize Conference UI. + */ + public void loadUI() { + setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY)); + setLayout(new GridBagLayout()); + add(getServicePanel(), new GridBagConstraints(0, 0, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + rootNode = new JiveTreeNode("Conference Services"); + tree = new Tree(rootNode) { + @Override + protected void setExpandedState(TreePath path, boolean state) { + // Ignore all collapse requests; collapse events will not be fired + if (state) { + super.setExpandedState(path, state); + } + } + }; + + tree.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent mouseEvent) { + tree.setCursor(GraphicUtils.HAND_CURSOR); + } + + @Override + public void mouseExited(MouseEvent mouseEvent) { + tree.setCursor(GraphicUtils.DEFAULT_CURSOR); + } + }); + + JScrollPane scrollPane = new JScrollPane(tree); + add(scrollPane, new GridBagConstraints(0, 2, 2, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); + + // Add all registered services. + addRegisteredServices(); + + tree.setCellRenderer(new JiveTreeCellRenderer()); + tree.putClientProperty("JTree.lineStyle", "None"); + tree.setRootVisible(false); + tree.addMouseListener( + new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent mouseEvent) { + // Handle double click event to join conference room + if (mouseEvent.getClickCount() != 2) { + return; + } + TreePath path = tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY()); + if (path == null) { + return; + } + JiveTreeNode node = (JiveTreeNode) path.getLastPathComponent(); + if (node != null && node.getAllowsChildren()) { + browseRooms((String) node.getUserObject()); + } else if (node != null) { + final String roomName = node.getUserObject().toString(); + final Jid roomJid = (Jid) node.getAssociatedObject(); // Has a resource part if a nickname is desired. + ConferenceUtils.joinConferenceOnSeparateThread(roomName, roomJid.asEntityBareJidOrThrow(), roomJid.getResourceOrNull(), null); + } + } + + @Override + public void mouseReleased(MouseEvent mouseEvent) { + checkPopup(mouseEvent); + } + + @Override + public void mousePressed(MouseEvent mouseEvent) { + checkPopup(mouseEvent); + } + } + ); + setBackground(Color.white); + + manager = BookmarkManager.getBookmarkManager(SparkManager.getConnection()); + } + + private void checkPopup(MouseEvent mouseEvent) { + // Handle no path for x y coordinates + if (tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY()) == null) { + return; + } + + final JiveTreeNode node = (JiveTreeNode) tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY()).getLastPathComponent(); + + if (mouseEvent.isPopupTrigger() && node != null) { + JPopupMenu popupMenu = new JPopupMenu(); + + // Define service actions + Action browseAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + browseRooms(node.toString()); + } + }; + browseAction.putValue(Action.NAME, Res.getString("menuitem.browse.service")); + browseAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_DATA_FIND_IMAGE)); + + Action removeServiceAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel(); + treeModel.removeNodeFromParent(node); + } + }; + removeServiceAction.putValue(Action.NAME, Res.getString("menuitem.remove.service")); + removeServiceAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_DELETE)); + + JMenuItem browseServiceMenu = new JMenuItem(browseAction); + JMenuItem removeServiceMenu = new JMenuItem(removeServiceAction); + + // Define room actions + Action joinRoomAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + final String roomName = node.getUserObject().toString(); + final Jid roomJid = (Jid) node.getAssociatedObject(); // Has a resource part if a nickname is desired. + ConferenceUtils.joinConferenceOnSeparateThread(roomName, roomJid.asEntityBareJidOrThrow(), roomJid.getResourceOrNull(), null); + } + }; + + joinRoomAction.putValue(Action.NAME, Res.getString("menuitem.join.room")); + joinRoomAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_USER_ENTER)); + + Action removeRoomAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel(); + treeModel.removeNodeFromParent(node); + final Jid roomJid = (Jid) node.getAssociatedObject(); + autoJoinRooms.remove(roomJid.asEntityBareJidOrThrow()); + removeBookmark(roomJid.asEntityBareJidOrThrow()); + } + }; + removeRoomAction.putValue(Action.NAME, Res.getString("menuitem.remove.bookmark")); + removeRoomAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.DELETE_BOOKMARK_ICON)); + + + JMenuItem joinRoomMenu = new JMenuItem(joinRoomAction); + JMenuItem removeRoomMenu = new JMenuItem(removeRoomAction); + + // Add context menu items based on node type + if (node.getAllowsChildren()) { + popupMenu.add(browseServiceMenu); + popupMenu.add(removeServiceMenu); + } else { + popupMenu.add(joinRoomMenu); + popupMenu.add(removeRoomMenu); + popupMenu.addSeparator(); + + Action autoJoin = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + final EntityBareJid roomJID = ((Jid) node.getAssociatedObject()).asEntityBareJidOrThrow(); + if (autoJoinRooms.contains(roomJID)) { + autoJoinRooms.remove(roomJID); + } else { + autoJoinRooms.add(roomJID); + } + + String name = node.getUserObject().toString(); + addBookmark(name, roomJID, autoJoinRooms.contains(roomJID)); + } + }; + + autoJoin.putValue(Action.NAME, Res.getString("menuitem.join.on.startup")); + + JCheckBoxMenuItem item = new JCheckBoxMenuItem(autoJoin); + EntityBareJid roomJID = ((Jid) node.getAssociatedObject()).asEntityBareJidOrThrow(); + item.setSelected(autoJoinRooms.contains(roomJID)); + popupMenu.add(item); + + // Define service actions + Action roomInfoAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + EntityBareJid roomJID = ((Jid) node.getAssociatedObject()).asEntityBareJidOrThrow(); + RoomBrowser roomBrowser = new RoomBrowser(); + roomBrowser.displayRoomInformation(roomJID); + } + }; + + roomInfoAction.putValue(Action.NAME, Res.getString("menuitem.view.room.info")); + roomInfoAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_DATA_FIND_IMAGE)); + popupMenu.add(roomInfoAction); + + Action copyUriGroupChat = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + final String rooJid = node.getAssociatedObject().toString(); + SparkManager.setClipboard("xmpp:" + rooJid + "?join"); + } + }; + + copyUriGroupChat.putValue(Action.NAME, Res.getString("button.copy.to.clipboard")); + copyUriGroupChat.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.COPY_16x16)); + popupMenu.add(copyUriGroupChat); + + } + // Fire menu listeners + fireContextMenuListeners(popupMenu, node); + // Display popup menu. + popupMenu.show(tree, mouseEvent.getX(), mouseEvent.getY()); + } + } + + public void browseRooms(String serviceNameString) { + DomainBareJid serviceName = JidCreate.domainBareFromOrThrowUnchecked(serviceNameString); + browseRooms(serviceName); + } + + public void browseRooms(DomainBareJid serviceName) { + ConferenceRoomBrowser rooms = new ConferenceRoomBrowser(this, serviceName); + rooms.invoke(); + } + + private void addRegisteredServices() { + SwingWorker worker = new SwingWorker() { + + @Override + public Object construct() { + try { + if (SparkManager.getConnection().isConnected()) { + mucServices = SparkManager.getMucManager().getMucServiceDomains(); + } + } catch (XMPPException | SmackException | InterruptedException e) { + Log.error("Unable to load MUC Service Names.", e); + } + return mucServices; + } + + @Override + public void finished() { + if (mucServices == null) { + return; + } + for (DomainBareJid service : mucServices) { + if (!hasService(service)) { + addServiceToList(service); + } + } + } + }; + + worker.start(); + } + + /** + * Adds a new service (ex. conferences@jabber.org) to the services list. + * + * @param service the new service. + * @return the new service node created. + */ + public JiveTreeNode addServiceToList(DomainBareJid service) { + final JiveTreeNode serviceNode = new JiveTreeNode(service.toString(), true, SparkRes.getImageIcon(SparkRes.Icon.SERVER_ICON)); + rootNode.add(serviceNode); + final DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); + model.nodeStructureChanged(rootNode); + // expand the tree for displaying + for (int i = 0; i <= tree.getRowCount(); i++) { + tree.expandPath(tree.getPathForRow(i)); + } + return serviceNode; + } + + /** + * Adds a new bookmark to a particular service node. + * + * @param serviceNode the service node. + * @param roomName the name of the room to bookmark. + * @param roomJidNick the jid of the room. Optionally contains a nickname in the resource + * @return the new bookmark created. + */ + private JiveTreeNode addBookmark(JiveTreeNode serviceNode, String roomName, Jid roomJidNick) { + JiveTreeNode roomNode = new JiveTreeNode(roomName, false, SparkRes.getImageIcon(SparkRes.Icon.BOOKMARK_ICON)); + roomNode.setAssociatedObject(roomJidNick); + serviceNode.add(roomNode); + final DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); + model.nodeStructureChanged(serviceNode); + return roomNode; + } + + public void addBookmark(String roomName, EntityBareJid roomJID, boolean autoJoin) { + try { + if (autoJoin) { + autoJoinRooms.add(roomJID); + } + manager.addBookmarkedConference(roomName, roomJID, autoJoin, null, null); + fireBookmarksAdded(roomJID); //fire bookmark event + } catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + } + } + + public void removeBookmark(EntityBareJid roomJID) { + try { + autoJoinRooms.remove(roomJID); + manager.removeBookmarkedConference(roomJID); + fireBookmarksRemoved(roomJID); // fire bookmark remove event + } catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + } + } + + + /** + * Build panel for adding conference service + */ + private JPanel getServicePanel() { + final JPanel servicePanel = new JPanel(); + servicePanel.setOpaque(false); + servicePanel.setLayout(new GridBagLayout()); + + final JLabel serviceLabel = new JLabel(); + final RolloverButton addButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.Icon.SMALL_ADD_IMAGE)); + addButton.setToolTipText(Res.getString("message.add.conference.service")); + + final JTextField serviceField = new JTextField(); + servicePanel.add(serviceLabel, new GridBagConstraints(0, 0, 2, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 2, 5), 0, 0)); + servicePanel.add(serviceField, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 2, 5), 0, 0)); + servicePanel.add(addButton, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 2, 5), 0, 0)); + + // Add resource utils + ResourceUtils.resLabel(serviceLabel, serviceField, Res.getString("label.add.conference.service")); + + final Action conferenceAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + final String conferenceService = serviceField.getText(); + if (hasService(conferenceService)) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(null, Res.getString("message.service.already.exists"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + serviceField.setText(""); + } else { + final List serviceList = new ArrayList<>(); + serviceField.setText(Res.getString("message.searching.please.wait")); + serviceField.setEnabled(false); + addButton.setEnabled(false); + SwingWorker worker = new SwingWorker() { + DiscoverInfo discoInfo; + + @Override + public Object construct() { + ServiceDiscoveryManager discoManager = SparkManager.getDiscoManager(); + try { + DomainBareJid conferenceServiceJid = JidCreate.domainBareFrom(conferenceService); + discoInfo = discoManager.discoverInfo(conferenceServiceJid); + for (DiscoverInfo.Identity identity : discoInfo.getIdentities()) { + if ("conference".equals(identity.getCategory())) { + serviceList.add(conferenceServiceJid); + break; + } else if ("server".equals(identity.getCategory())) { + try { + Collection services = getConferenceServices(conferenceServiceJid); + serviceList.addAll(services); + } catch (Exception e1) { + Log.error("Unable to load conference services in server.", e1); + } + } + } + } catch (XMPPException | SmackException | XmppStringprepException | InterruptedException e1) { + Log.error("Error in conferences discovery.", e1); + } + return true; + } + + @Override + public void finished() { + if (discoInfo != null) { + for (DomainBareJid aServiceList : serviceList) { + if (!hasService(aServiceList)) { + addServiceToList(aServiceList); + } + } + } else { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(SparkManager.getMainWindow(), Res.getString("message.conference.service.error"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + } + serviceField.setText(""); + serviceField.setEnabled(true); + addButton.setEnabled(true); + } + }; + worker.start(); + } + } + }; + addButton.addActionListener(conferenceAction); + + serviceField.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyChar() == KeyEvent.VK_ENTER) { + conferenceAction.actionPerformed(null); + } + } + }); + + return servicePanel; + } + + private Collection getConferenceServices(DomainBareJid server) throws Exception { + List answer = new ArrayList<>(); + ServiceDiscoveryManager discoManager = SparkManager.getDiscoManager(); + DiscoverItems items = discoManager.discoverItems(server); + for (DiscoverItems.Item item : items.getItems()) { + DomainBareJid entityID = item.getEntityID().asDomainBareJid(); + // TODO: We should not simply assume that this is MUC service just because it starts with a given prefix. + if (entityID.toString().startsWith("conference") || entityID.toString().startsWith("private")) { + answer.add(entityID); + } else { + try { + DiscoverInfo info = discoManager.discoverInfo(item.getEntityID()); + if (info.containsFeature(MultiUserChatConstants.NAMESPACE)) { + answer.add(entityID); + } + } catch (XMPPException | SmackException e) { + Log.error("Problem when loading conference service.", e); + } + } + } + return answer; + } + + private boolean hasService(CharSequence service) { + TreePath path = tree.findByName(tree, new String[]{rootNode.getUserObject().toString(), service.toString()}); + return path != null; + } + + public void loadBookmarks() { + try { + List bc = manager.getBookmarkedConferences(); + setBookmarks(bc); + } catch (XMPPException | SmackException | InterruptedException error) { + Log.error(error); + } + } + + /** + * Sets the current bookmarks used with this account. + */ + public void setBookmarks(Collection bookmarks) { + // Iterate bookmarks; join if auotojoin and add to the tree + for (BookmarkedConference bookmark : bookmarks) { + DomainBareJid serviceName = bookmark.getJid().asDomainBareJid(); + String roomName = bookmark.getName() != null && !bookmark.getName().isEmpty() ? bookmark.getName() : bookmark.getJid().getLocalpart().asUnescapedString(); + + if (bookmark.isAutoJoin()) { + ConferenceUtils.joinConferenceOnSeparateThread(roomName, bookmark.getJid(), bookmark.getNickname(), bookmark.getPassword()); + ConferenceUtils.addUnclosableChatRoom(bookmark.getJid()); + autoJoinRooms.add(bookmark.getJid()); + } + + // Get Service Node + String rootNodeStr = rootNode.getUserObject().toString(); + TreePath path = tree.findByName(tree, new String[]{rootNodeStr, serviceName.toString()}); + JiveTreeNode serviceNode; + if (path == null) { + serviceNode = addServiceToList(serviceName); + path = tree.findByName(tree, new String[]{rootNodeStr, serviceName.toString()}); + } else { + serviceNode = (JiveTreeNode) path.getLastPathComponent(); + } + + Jid roomJidNick = bookmark.getNickname() != null ? JidCreate.fullFrom(bookmark.getJid(), bookmark.getNickname()) : bookmark.getJid(); + addBookmark(serviceNode, roomName, roomJidNick); + tree.expandPath(path); + } + } + + /** + * Returns all MUC services available. + */ + public List getMucServices() { + return mucServices; + } + + /** + * Adds a new ContextMenuListener. + * + * @param listener the listener. + */ + public void addContextMenuListener(ContextMenuListener listener) { + listeners.addIfAbsent(listener); + } + + /** + * Removes a ContextMenuListener. + */ + public void removeContextMenuListener(ContextMenuListener listener) { + listeners.remove(listener); + } + + private void fireContextMenuListeners(JPopupMenu popup, JiveTreeNode node) { + for (final ContextMenuListener listener : listeners) { + try { + listener.poppingUp(node, popup); + } catch (Exception e) { + Log.error("A ContextMenuListener (" + listener + ") threw an exception while processing a 'poppingUp' event for node: " + node, e); + } + } + } + + /** + * Adds a new BookmarksListener. + */ + public void addBookmarksListener(BookmarksListener bookmarkListener) { + bookmarkListeners.addIfAbsent(bookmarkListener); + } + + /** + * Removes a BookmarksListener. + */ + public void removeBookmarksListener(BookmarksListener bookmarkListener) { + bookmarkListeners.remove(bookmarkListener); + } + + private void fireBookmarksAdded(EntityBareJid roomJID) { + for (final BookmarksListener listener : bookmarkListeners) { + try { + listener.bookmarkAdded(roomJID.toString()); + } catch (Exception e) { + Log.error("A BookmarksListener (" + listener + ") threw an exception while processing a 'bookmarkAdded' event for: " + roomJID, e); + } + } + } + + private void fireBookmarksRemoved(EntityBareJid roomJID) { + for (final BookmarksListener listener : bookmarkListeners) { + try { + listener.bookmarkRemoved(roomJID.toString()); + } catch (Exception e) { + Log.error("A BookmarksListener (" + listener + ") threw an exception while processing a 'bookmarkRemoved' event for: " + roomJID, e); + } + } + } + + /** + * Returns a list of bookmarks. + */ + public List getBookmarks() { + try { + return manager.getBookmarkedConferences(); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + } + return List.of(); + } + + void addOrRemoveNode(DomainBareJid serviceName, boolean isBookmarked, String roomName, EntityBareJid roomJID) { + if (roomName == null) { + roomName = roomJID.getLocalpart().asUnescapedString(); + } + JiveTreeNode rootNode = (JiveTreeNode) tree.getModel().getRoot(); + TreePath rootPath = tree.findByName(tree, new String[]{rootNode.toString(), serviceName.toString()}); + if (!isBookmarked) { + JiveTreeNode node = (JiveTreeNode) tree.getLastSelectedPathComponent(); + if (node == null) { + String defaultServiceName = ConferenceServices.getDefaultServiceName().toString(); + TreePath path = tree.findByName(tree, new String[]{rootNode.toString(), defaultServiceName}); + node = (JiveTreeNode) path.getLastPathComponent(); + } + JiveTreeNode roomNode = new JiveTreeNode(roomName, false, SparkRes.getImageIcon(SparkRes.Icon.BOOKMARK_ICON)); + roomNode.setAssociatedObject(roomJID); + node.add(roomNode); + DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); + model.nodeStructureChanged(node); + tree.expandPath(rootPath); + addBookmark(roomName, roomJID, false); + } else { + // Remove bookmark + TreePath path = tree.findByName(tree, new String[]{rootNode.toString(), serviceName.toString(), roomName}); + JiveTreeNode node = (JiveTreeNode) path.getLastPathComponent(); + DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); + model.removeNodeFromParent(node); + EntityBareJid jid = ((Jid) node.getAssociatedObject()).asEntityBareJidOrThrow(); + removeBookmark(jid); + } + } +} diff --git a/src/java/org/jivesoftware/spark/ui/conferences/ConferenceItem.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/ConferenceItem.java similarity index 81% rename from src/java/org/jivesoftware/spark/ui/conferences/ConferenceItem.java rename to core/src/main/java/org/jivesoftware/spark/ui/conferences/ConferenceItem.java index fae131e49..a90b67d4c 100644 --- a/src/java/org/jivesoftware/spark/ui/conferences/ConferenceItem.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/ConferenceItem.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2011 eZuce Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +18,7 @@ import org.jivesoftware.smackx.bookmarks.BookmarkedConference; public class ConferenceItem { - private BookmarkedConference bookmarkedConf; + private final BookmarkedConference bookmarkedConf; public ConferenceItem(BookmarkedConference bookmarkedConf) { this.bookmarkedConf = bookmarkedConf; @@ -30,7 +26,7 @@ public ConferenceItem(BookmarkedConference bookmarkedConf) { @Override public String toString() { - return bookmarkedConf.getName(); + return bookmarkedConf.getName() != null && !bookmarkedConf.getName().isEmpty() ? bookmarkedConf.getName() : bookmarkedConf.getJid().getLocalpart().asUnescapedString(); } public BookmarkedConference getBookmarkedConf() { diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/ConferenceRoomBrowser.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/ConferenceRoomBrowser.java new file mode 100644 index 000000000..a14e49d64 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/ConferenceRoomBrowser.java @@ -0,0 +1,843 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.conferences; + +import java.awt.*; +import java.awt.event.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.*; +import java.util.List; + +import javax.swing.*; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; + + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.StanzaError; +import org.jivesoftware.smackx.muc.MultiUserChatManager; +import org.jivesoftware.smackx.xdata.form.FillableForm; +import org.jivesoftware.smackx.bookmarks.BookmarkedConference; +import org.jivesoftware.smackx.muc.HostedRoom; +import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jivesoftware.smackx.muc.RoomInfo; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.component.TitlePanel; +import org.jivesoftware.spark.ui.ChatRoomNotFoundException; +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jivesoftware.spark.util.ImageCombiner; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.UIComponentRegistry; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettingsManager; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Localpart; +import org.jxmpp.jid.parts.Resourcepart; + +import static java.awt.BorderLayout.*; +import static org.jivesoftware.smackx.muc.MucConfigFormManager.*; + +/** + * A UI that handles all Group Rooms contained in an XMPP Messenger server. This + * handles creation and joining of rooms for group chat discussions as well as + * the listing of the creation times, number of occupants in a room, and the + * room name itself. + */ +public class ConferenceRoomBrowser extends JPanel implements ActionListener, ComponentListener { + private final RoomList roomsTable; + private final RolloverButton createButton = new RolloverButton("", + SparkRes.getImageIcon(SparkRes.Icon.SMALL_USER1_NEW)); + private final RolloverButton joinRoomButton = new RolloverButton("", + SparkRes.getImageIcon(SparkRes.Icon.DOOR_IMAGE)); + private final RolloverButton refreshButton = new RolloverButton("", + SparkRes.getImageIcon(SparkRes.Icon.REFRESH_IMAGE)); + private final RolloverButton addRoomButton = new RolloverButton("", + SparkRes.getImageIcon(SparkRes.Icon.ADD_BOOKMARK_ICON)); + + private final RolloverButton showHiddenButtons = new RolloverButton( + SparkRes.getImageIcon(SparkRes.Icon.PANE_UP_ARROW_IMAGE)); + + private final JMenuItem joinRoomItem; + private final JMenuItem addRoomItem; + private final JMenuItem createItem; + private final JMenuItem refreshItem; + + private final ChatManager chatManager; + + private JDialog dlg; + + private final BookmarksUI conferences; + private final DomainBareJid serviceName; + + private int allButtonWidth; + private int threeButtonWidth; + private int twoButtonWidth; + private int oneButtonWidth; + + private final JPopupMenu popup; + + final TableRowSorter sorter; + private final Map roomInfos = new HashMap<>(); + private final LocalPreferences pref = SettingsManager.getLocalPreferences(); + + /** + * Creates a new instance of ConferenceRooms. + * + * @param conferences the conference ui. + * @param serviceName the name of the conference service. + */ + public ConferenceRoomBrowser(BookmarksUI conferences, DomainBareJid serviceName) { + this.setLayout(new BorderLayout()); + + this.conferences = conferences; + this.serviceName = serviceName; + + popup = new JPopupMenu(); + + joinRoomItem = new JMenuItem(Res.getString("menuitem.join.room")); + addRoomItem = new JMenuItem(Res.getString("menuitem.bookmark.room")); + createItem = new JMenuItem(Res.getString("menuitem.create.room")); + refreshItem = new JMenuItem(Res.getString("menuitem.refresh")); + + joinRoomItem.setIcon(SparkRes.getImageIcon(SparkRes.Icon.DOOR_IMAGE)); + addRoomItem.setIcon(SparkRes.getImageIcon(SparkRes.Icon.ADD_BOOKMARK_ICON)); + createItem.setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_USER1_NEW)); + refreshItem.setIcon(SparkRes.getImageIcon(SparkRes.Icon.REFRESH_IMAGE)); + + popup.add(joinRoomItem); + popup.add(addRoomItem); + popup.add(createItem); + popup.add(refreshItem); + + // Add Toolbar + final JPanel mainPanel = new JPanel(new BorderLayout()); + JPanel toolbar = new JPanel(new FlowLayout(FlowLayout.LEFT)); + JPanel pane_hiddenButtons = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + toolbar.add(joinRoomButton); + toolbar.add(addRoomButton); + toolbar.add(createButton); + toolbar.add(refreshButton); + pane_hiddenButtons.add(showHiddenButtons); + + mainPanel.add(toolbar, WEST); + mainPanel.add(pane_hiddenButtons, EAST); + this.add(mainPanel, NORTH); + + JLabel labelFilter = new JLabel(Res.getString("label.search")); + JTextField txtFilter = new JTextField(20); + txtFilter.setMinimumSize(new Dimension(50, 20)); + + //add fields for filter + final JPanel filterPanel = new JPanel(new BorderLayout()); + JPanel toolbarFilter = new JPanel(new FlowLayout(FlowLayout.LEFT)); + toolbarFilter.add(labelFilter); + toolbarFilter.add(txtFilter); + + filterPanel.add(toolbarFilter); + this.add(filterPanel, SOUTH); + + createButton.addActionListener(this); + createItem.addActionListener(this); + joinRoomButton.addActionListener(this); + refreshButton.addActionListener(this); + + ResourceUtils.resButton(createButton, Res.getString("button.create.room")); + ResourceUtils.resButton(joinRoomButton, Res.getString("button.join.room")); + ResourceUtils.resButton(refreshButton, Res.getString("button.refresh")); + ResourceUtils.resButton(addRoomButton, Res.getString("button.bookmark.room")); + + refreshButton.setToolTipText(Res.getString("message.update.room.list")); + joinRoomButton.setToolTipText(Res.getString("message.join.conference.room")); + createButton.setToolTipText(Res.getString("message.create.or.join.room")); + + // Add Group Chat Table + roomsTable = new RoomList(); + roomsTable.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + enterRoom(); + } + } + }); + + //build model for roomsTable, ignoring the 1st column + sorter = new TableRowSorter<>(roomsTable.getModel()); + sorter.setComparator(3, Comparator.comparing((String o) -> !o.isEmpty() ? Long.parseLong(o) : 0)); + roomsTable.setRowSorter(sorter); + roomsTable.setComponentPopupMenu(roomEntryPopupMenu()); + + final JScrollPane pane = new JScrollPane(roomsTable); + pane.setBackground(Color.white); + pane.setForeground(Color.white); + this.setBackground(Color.white); + this.setForeground(Color.white); + pane.getViewport().setBackground(Color.white); + this.add(pane, CENTER); + + chatManager = SparkManager.getChatManager(); + + txtFilter.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + JTextField textField = (JTextField) e.getSource(); + String text = textField.getText(); + List> filters = new ArrayList<>(3); + filters.add(RowFilter.regexFilter(text, 1)); + filters.add(RowFilter.regexFilter(text, 2)); + filters.add(RowFilter.regexFilter(text, 3)); + RowFilter af = RowFilter.orFilter(filters); + sorter.setRowFilter(af); + } + }); + joinRoomButton.addActionListener(actionEvent -> joinSelectedRoom()); + addRoomButton.addActionListener(actionEvent -> bookmarkRoom(serviceName)); + refreshButton.addActionListener(actionEvent -> refreshRoomList(serviceName)); + joinRoomItem.addActionListener(actionEvent -> joinSelectedRoom()); + addRoomItem.addActionListener(actionEvent -> bookmarkRoom(serviceName)); + refreshItem.addActionListener(actionEvent -> refreshRoomList(serviceName)); + showHiddenButtons.addActionListener(actionEvent -> popup.show(showHiddenButtons, 0, showHiddenButtons.getHeight())); + + joinRoomButton.setEnabled(false); + addRoomButton.setEnabled(false); + joinRoomItem.setEnabled(false); + addRoomItem.setEnabled(false); + + addTableListener(); + } + + private RoomInfo selectedRoomInfo() { + final int selectedRow = roomsTable.getSelectedRow(); + if (selectedRow == -1) { + return null; + } + Localpart roomNamePart = Localpart.formUnescapedOrNull(roomsTable.getValueAt(selectedRow, 2).toString()); + EntityBareJid roomJID = JidCreate.entityBareFrom(roomNamePart, serviceName); + RoomInfo roomInfo = roomInfos.get(roomJID); + return roomInfo; + } + + private JPopupMenu roomEntryPopupMenu() { + JPopupMenu popupMenu = new JPopupMenu(); + + JMenuItem itemRoomInfo = new JMenuItem(Res.getString("menuitem.view.room.info")); + itemRoomInfo.setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_DATA_FIND_IMAGE)); + itemRoomInfo.addActionListener(e -> { + RoomInfo roomInfo = selectedRoomInfo(); + if (roomInfo == null) { + return; + } + RoomBrowser roomBrowser = new RoomBrowser(); + roomBrowser.displayRoomInformation(roomInfo.getRoom()); + }); + popupMenu.add(itemRoomInfo); + + JMenuItem itemCopyUri = new JMenuItem(Res.getString("button.copy.to.clipboard")); + itemCopyUri.setIcon(SparkRes.getImageIcon(SparkRes.Icon.COPY_16x16)); + itemCopyUri.addActionListener(e -> { + RoomInfo roomInfo = selectedRoomInfo(); + if (roomInfo == null) { + return; + } + String roomJIDString = roomInfo.getRoom().toString(); + SparkManager.setClipboard("xmpp:" + roomJIDString + "?join"); + }); + popupMenu.add(itemCopyUri); + + // Select the row where the use made their right-clicked + popupMenu.addPopupMenuListener(new PopupMenuListener() { + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + SwingUtilities.invokeLater(() -> { + Point point = SwingUtilities.convertPoint(popupMenu, new Point(0, 0), roomsTable); + int rowAtPoint = roomsTable.rowAtPoint(point); + if (rowAtPoint <= -1) { + return; + } + roomsTable.setRowSelectionInterval(rowAtPoint, rowAtPoint); + }); + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + } + + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + } + }); + + return popupMenu; + } + + private void startLoadingImg() { + SwingWorker startLoading = new SwingWorker() { + + @Override + public Object construct() { + return null; + } + + @Override + public void finished() { + refreshButton.setIcon(SparkRes.getImageIcon(SparkRes.Icon.BUSY_IMAGE)); + refreshButton.validate(); + refreshButton.repaint(); + refreshItem.setIcon(SparkRes.getImageIcon(SparkRes.Icon.BUSY_IMAGE)); + refreshItem.validate(); + refreshItem.repaint(); + } + }; + startLoading.start(); + } + + private void stopLoadingImg() { + SwingWorker stopLoading = new SwingWorker() { + + @Override + public Object construct() { + return null; + } + + @Override + public void finished() { + refreshButton.setIcon(SparkRes.getImageIcon(SparkRes.Icon.REFRESH_IMAGE)); + refreshButton.validate(); + refreshButton.repaint(); + refreshItem.setIcon(SparkRes.getImageIcon(SparkRes.Icon.REFRESH_IMAGE)); + refreshItem.validate(); + refreshItem.repaint(); + } + }; + stopLoading.start(); + } + + private void clearTable() { + SwingWorker clearTable = new SwingWorker() { + + @Override + public Object construct() { + return null; + } + + @Override + public void finished() { + roomsTable.clearTable(); + } + }; + clearTable.start(); + } + + private void refreshRoomList(final DomainBareJid serviceName) { + TimerTask refreshTask = new TimerTask() { + + @Override + public void run() { + roomInfos.clear(); + clearTable(); + startLoadingImg(); + String errorMsg = null; + try { + MultiUserChatManager mucManager = SparkManager.getMucManager(); + Map rooms = mucManager.getRoomsHostedBy(serviceName); + for (Map.Entry entry : rooms.entrySet()) { + HostedRoom room = entry.getValue(); + try { + RoomInfo roomInfo = mucManager.getRoomInfo(room.getJid()); + addRoomToTable(roomInfo); + } catch (Exception e) { + Log.warning("Unable to get room info " + room.getName() + ": " + e.getMessage()); + } + } + } catch (XMPPException.XMPPErrorException e) { + StanzaError.Condition condition = e.getStanzaError().getCondition(); + if (condition == StanzaError.Condition.feature_not_implemented || condition == StanzaError.Condition.service_unavailable) { + errorMsg = Res.getString("message.conference.rooms.unsupported"); + } else { + Log.error("Unable to retrieve list of rooms from " + serviceName + ": " + e); + errorMsg = e.getMessage(); + } + } catch (Exception e) { + Log.error("Unable to retrieve list of rooms from " + serviceName, e); + errorMsg = e.getMessage(); + } finally { + stopLoadingImg(); + } + // If there was an error, show it to a user + if (errorMsg != null) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(conferences, + Res.getString("message.conference.info.error") + "\n" + errorMsg, + Res.getString("title.error"), + JOptionPane.ERROR_MESSAGE); + if (dlg != null) { + dlg.dispose(); + } + return; + } + roomsTable.setSortable(true); + } + }; + TaskEngine.getInstance().submit(refreshTask); + } + + private void bookmarkRoom(DomainBareJid serviceName) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + RoomInfo roomInfo = selectedRoomInfo(); + if (roomInfo == null) { + JOptionPane.showMessageDialog(dlg, Res.getString("message.select.add.room.to.add"), Res.getString("title.group.chat"), JOptionPane.INFORMATION_MESSAGE); + return; + } + + // Check to see what type of room this is. + if (!roomInfo.isPersistent()) { + JOptionPane.showMessageDialog(dlg, Res.getString("message.bookmark.temporary.room.error"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + return; + } + + boolean isBookmarked = isBookmarked(roomInfo.getRoom()); + String roomName = roomInfo.getName() != null ? roomInfo.getName() : roomInfo.getRoom().getLocalpart().toString(); + conferences.addOrRemoveNode(serviceName, isBookmarked, roomName, roomInfo.getRoom()); + int selectedRow = roomsTable.getSelectedRow(); + ImageIcon bookmarkIcon = isBookmarked ? SparkRes.getImageIcon(SparkRes.Icon.BLANK_IMAGE) : SparkRes.getImageIcon(SparkRes.Icon.BOOKMARK_ICON); + roomsTable.getTableModel().setValueAt(new JLabel(bookmarkIcon), selectedRow, 0); + addBookmarkUI(!isBookmarked); + } + + + private void joinSelectedRoom() { + RoomInfo roomInfo = selectedRoomInfo(); + if (roomInfo == null) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(dlg, + Res.getString("message.select.room.to.join"), + Res.getString("title.group.chat"), + JOptionPane.INFORMATION_MESSAGE); + return; + } + enterRoom(); + } + + private void addTableListener() { + roomsTable.getSelectionModel().addListSelectionListener( + e -> { + if (e.getValueIsAdjusting()) { + return; + } + RoomInfo roomInfo = selectedRoomInfo(); + if (roomInfo != null) { + joinRoomButton.setEnabled(true); + joinRoomItem.setEnabled(true); + addRoomButton.setEnabled(true); + addRoomItem.setEnabled(true); + addBookmarkUI(!isBookmarked(roomInfo.getRoom())); + } else { + joinRoomButton.setEnabled(false); + addRoomButton.setEnabled(false); + joinRoomItem.setEnabled(false); + addRoomItem.setEnabled(false); + addBookmarkUI(true); + } + }); + } + + /** + * Displays the ConferenceRoomBrowser. + */ + public void invoke() { + // Create the title panel for this dialog + TitlePanel titlePanel = new TitlePanel( + Res.getString("title.create.or.bookmark.room"), + Res.getString("message.add.favorite.room"), + SparkRes.getImageIcon(SparkRes.Icon.BLANK_IMAGE), true); + + // Construct main panel w/ layout. + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BorderLayout()); + mainPanel.add(titlePanel, NORTH); + + // The user should only be able to close this dialog. + Object[] options = {Res.getString("close")}; + final JOptionPane pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, + JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); + mainPanel.add(pane, CENTER); + final JOptionPane p = new JOptionPane(); + + dlg = p.createDialog(SparkManager.getMainWindow(), + Res.getString("title.browse.room.service", serviceName)); + dlg.setModal(false); + dlg.addComponentListener(this); + + dlg.setResizable(true); + dlg.setContentPane(mainPanel); + dlg.setLocationRelativeTo(SparkManager.getMainWindow()); + + PropertyChangeListener changeListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent e) { + String value = (String) pane.getValue(); + if (Res.getString("close").equals(value)) { + pane.removePropertyChangeListener(this); + dlg.dispose(); + } else if (Res.getString("close").equals(value)) { + pane.setValue(JOptionPane.UNINITIALIZED_VALUE); + } + } + }; + + pane.addPropertyChangeListener(changeListener); + + dlg.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyChar() == KeyEvent.VK_ESCAPE) { + dlg.dispose(); + } + } + }); + + // will need that when the window is smaller than the buttons width... + setButtonsWidth(); + + showHiddenButtons.setVisible(false); + dlg.pack(); + + final Rectangle bounds = LayoutSettingsManager.getLayoutSettings().getConferenceRoomBrowserBounds(); + if (bounds == null || bounds.width <= 0 || bounds.height <= 0) { + // Use default settings. + dlg.setSize(700, 400); + } else { + dlg.setBounds(bounds); + } + + dlg.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + LayoutSettingsManager.getLayoutSettings().setConferenceRoomBrowserBounds(dlg.getBounds()); + } + + @Override + public void componentMoved(ComponentEvent e) { + LayoutSettingsManager.getLayoutSettings().setConferenceRoomBrowserBounds(dlg.getBounds()); + } + }); + + dlg.setVisible(true); + dlg.toFront(); + dlg.requestFocus(); + refreshRoomList(serviceName); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource() == createButton || e.getSource() == createItem) { + createRoom(); + } + } + + private void enterRoom() { + RoomInfo roomInfo = selectedRoomInfo(); + if (roomInfo == null) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(dlg, + Res.getString("message.select.room.to.enter"), + Res.getString("title.group.chat"), + JOptionPane.INFORMATION_MESSAGE); + return; + } + + try { + chatManager.getChatContainer().getChatRoom(roomInfo.getRoom()); + } catch (ChatRoomNotFoundException e1) { + ConferenceUtils.joinConferenceOnSeparateThread(roomInfo.getName(), + roomInfo.getRoom(), null, null); + } + } + + /** + * Create a new room based on room table selection. + */ + private void createRoom() { + RoomCreationDialog mucRoomDialog = new RoomCreationDialog(); + final MultiUserChat groupChat = mucRoomDialog.createGroupChat(SparkManager.getMainWindow(), serviceName); + if (groupChat == null) { + return; + } + // Join Room + try { + GroupChatRoom room = UIComponentRegistry.createGroupChatRoom(groupChat); + Resourcepart nickname = pref.getNickname(); + groupChat.create(nickname); + chatManager.getChatContainer().addChatRoom(room); + chatManager.getChatContainer().activateChatRoom(room); + + // Send Form + FillableForm form = groupChat.getConfigurationForm().getFillableForm(); + if (mucRoomDialog.isPasswordProtected()) { + String password = mucRoomDialog.getPassword(); + room.setPassword(password); + if (form.hasField(MUC_ROOMCONFIG_PASSWORDPROTECTEDROOM)) { + form.setAnswer(MUC_ROOMCONFIG_PASSWORDPROTECTEDROOM, true); + } + form.setAnswer(MUC_ROOMCONFIG_ROOMSECRET, password); + } + form.setAnswer(MUC_ROOMCONFIG_ROOMNAME, mucRoomDialog.getRoomName()); + form.setAnswer("muc#roomconfig_roomdesc", mucRoomDialog.getRoomTopic()); + + if (mucRoomDialog.isPublicRoom()) { + if (form.hasField(MUC_ROOMCONFIG_PUBLICLYSEARCHABLEROOM)) { + form.setAnswer(MUC_ROOMCONFIG_PUBLICLYSEARCHABLEROOM, true); + } + } + if (mucRoomDialog.isPermanent()) { + form.setAnswer("muc#roomconfig_persistentroom", true); + } + groupChat.sendConfigurationForm(form); + MultiUserChatManager mucManager = SparkManager.getMucManager(); + RoomInfo roomInfo = mucManager.getRoomInfo(groupChat.getRoom()); + addRoomToTable(roomInfo); + } catch (XMPPException | SmackException | InterruptedException e1) { + Log.error("Error creating new room.", e1); + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(this, + Res.getString("message.room.creation.error"), + Res.getString("title.error"), + JOptionPane.ERROR_MESSAGE); + } + } + + /** + * Adds a room to the room table. + */ + private void addRoomToTable(RoomInfo room) { + roomInfos.put(room.getRoom(), room); + SwingWorker addRoomThread = new SwingWorker() { + + @Override + public Object construct() { + JLabel iconLabel = new JLabel(); + iconLabel.setAlignmentX(JLabel.RIGHT_ALIGNMENT); + boolean isBookmark = false; + boolean isPassword = false; + + ImageIcon bookmarkIcon = SparkRes.getImageIcon(SparkRes.Icon.BOOKMARK_ICON); + ImageIcon passwordIcon = SparkRes.getImageIcon(SparkRes.Icon.LOCK_16x16); + + if (isBookmarked(room.getRoom())) { + isBookmark = true; + iconLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.BOOKMARK_ICON)); + } + if (room.isPasswordProtected() || room.isMembersOnly()) { + isPassword = true; + } + + // Set icon based on bookmark and password status + if (isBookmark && isPassword) { + try { + Image img = ImageCombiner.combine(bookmarkIcon, passwordIcon); + if (img != null) { + iconLabel.setIcon(new ImageIcon(img)); + } + } catch (Exception e) { + Log.warning("Unable to set icon for bookmarked & password-protected room " + room.getRoom(), e); + } + } else if (isBookmark) { + iconLabel.setIcon(bookmarkIcon); + } else if (isPassword) { + try { + if (passwordIcon != null) { + Image img = ImageCombiner.returnTransparentImage( + passwordIcon.getIconWidth(), passwordIcon.getIconHeight()); + Image combined = ImageCombiner.combine(new ImageIcon(img), passwordIcon); + if (combined != null) { + iconLabel.setIcon(new ImageIcon(combined)); + } + } + } catch (Exception e) { + Log.warning("Unable to set icon for password-protected room " + room.getRoom(), e); + } + } + + String occupants = room.getOccupantsCount() != -1 ? String.valueOf(room.getOccupantsCount()) : ""; + Localpart roomLocalpart = room.getRoom().getLocalpart(); + String roomAddress = roomLocalpart.toString(); + String roomTitle = room.getName() != null ? room.getName() : roomLocalpart.asUnescapedString(); + return new Object[]{iconLabel, roomTitle, roomAddress, occupants, room.getLang(), room.getDescription()}; + } + + @Override + public void finished() { + Object[] insertRoom = (Object[]) get(); + roomsTable.getTableModel().addRow(insertRoom); + } + }; + addRoomThread.start(); + } + + /** + * Returns true if the room specified is bookmarked. + * + * @param roomJID the jid of the room to check. + * @return true if the room is bookmarked. + */ + private boolean isBookmarked(EntityBareJid roomJID) { + for (BookmarkedConference bk : conferences.getBookmarks()) { + if (roomJID.equals(bk.getJid())) { + return true; + } + } + return false; + } + + /** + * Toggles the bookmark room button depending on it's state. + * + * @param addBookmark true if the button should display itself as bookmarkable :) + */ + private void addBookmarkUI(boolean addBookmark) { + if (!addBookmark) { + addRoomButton.setText(Res.getString("button.remove.bookmark")); + addRoomButton.setIcon(SparkRes.getImageIcon(SparkRes.Icon.DELETE_BOOKMARK_ICON)); + } else { + ResourceUtils.resButton(addRoomButton, Res.getString("button.bookmark.room")); + addRoomButton.setIcon(SparkRes.getImageIcon(SparkRes.Icon.ADD_BOOKMARK_ICON)); + } + } + + /** + * Center the text + */ + static class CenterRenderer extends DefaultTableCellRenderer { + + public CenterRenderer() { + setHorizontalAlignment(CENTER); + } + + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, boolean isSelected, boolean hasFocus, int row, + int column) { + super.getTableCellRendererComponent(table, value, isSelected, + hasFocus, row, column); + return this; + } + } + + @Override + public void componentHidden(ComponentEvent e) { + } + + @Override + public void componentMoved(ComponentEvent e) { + } + + @Override + public void componentResized(ComponentEvent e) { + if (this.getWidth() <= (oneButtonWidth + 19)) { + joinRoomButton.setVisible(false); + addRoomButton.setVisible(false); + createButton.setVisible(false); + refreshButton.setVisible(false); + + joinRoomItem.setVisible(true); + addRoomItem.setVisible(true); + createItem.setVisible(true); + refreshItem.setVisible(true); + + showHiddenButtons.setVisible(true); + } else if (this.getWidth() <= (twoButtonWidth + 19)) { + joinRoomButton.setVisible(true); + addRoomButton.setVisible(false); + createButton.setVisible(false); + refreshButton.setVisible(false); + + joinRoomItem.setVisible(false); + addRoomItem.setVisible(true); + createItem.setVisible(true); + refreshItem.setVisible(true); + + showHiddenButtons.setVisible(true); + } else if (this.getWidth() <= (threeButtonWidth + 19)) { + joinRoomButton.setVisible(true); + addRoomButton.setVisible(true); + createButton.setVisible(false); + refreshButton.setVisible(false); + + joinRoomItem.setVisible(false); + addRoomItem.setVisible(false); + createItem.setVisible(true); + refreshItem.setVisible(true); + + showHiddenButtons.setVisible(true); + } else if (this.getWidth() <= (allButtonWidth + 19)) { + joinRoomButton.setVisible(true); + addRoomButton.setVisible(true); + createButton.setVisible(true); + refreshButton.setVisible(false); + + joinRoomItem.setVisible(false); + addRoomItem.setVisible(false); + createItem.setVisible(false); + refreshItem.setVisible(true); + + showHiddenButtons.setVisible(true); + } else if (this.getWidth() > (allButtonWidth + 19)) { + joinRoomButton.setVisible(true); + addRoomButton.setVisible(true); + createButton.setVisible(true); + refreshButton.setVisible(true); + + joinRoomItem.setVisible(false); + addRoomItem.setVisible(false); + createItem.setVisible(false); + refreshItem.setVisible(false); + + showHiddenButtons.setVisible(false); + } + } + + @Override + public void componentShown(ComponentEvent e) { + } + + // will need that, when the window is smaller than the buttons width... + private void setButtonsWidth() { + allButtonWidth = createButton.getWidth() + refreshButton.getWidth() + + addRoomButton.getWidth() + joinRoomButton.getWidth(); + threeButtonWidth = createButton.getWidth() + addRoomButton.getWidth() + + joinRoomButton.getWidth() + showHiddenButtons.getWidth(); + twoButtonWidth = addRoomButton.getWidth() + joinRoomButton.getWidth() + + showHiddenButtons.getWidth(); + oneButtonWidth = joinRoomButton.getWidth() + + showHiddenButtons.getWidth(); + } + +} diff --git a/src/java/org/jivesoftware/spark/ui/conferences/ConferenceServiceBrowser.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/ConferenceServiceBrowser.java similarity index 86% rename from src/java/org/jivesoftware/spark/ui/conferences/ConferenceServiceBrowser.java rename to core/src/main/java/org/jivesoftware/spark/ui/conferences/ConferenceServiceBrowser.java index c286be155..aaa739584 100644 --- a/src/java/org/jivesoftware/spark/ui/conferences/ConferenceServiceBrowser.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/ConferenceServiceBrowser.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,12 +22,15 @@ import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.packet.DiscoverInfo; import org.jivesoftware.smackx.disco.packet.DiscoverItems; +import org.jivesoftware.smackx.muc.MultiUserChatConstants; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.component.RolloverButton; import org.jivesoftware.spark.component.TitlePanel; import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.spark.util.ResourceUtils; import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; @@ -73,8 +72,8 @@ public String getSelectedService() { mainPanel.add(new JLabel("ex. jivesoftware.com"), new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); // Add Empty CheckBox List - final DefaultListModel model = new DefaultListModel(); - final JList list = new JList(model); + final DefaultListModel model = new DefaultListModel<>(); + final JList list = new JList<>(model); list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JScrollPane scrollPane = new JScrollPane(list); scrollPane.setBorder(BorderFactory.createTitledBorder(Res.getString("group.conferences.found"))); @@ -87,8 +86,7 @@ public String getSelectedService() { try { Collection col = getConferenceServices(address); for (String aCol : col) { - String service = aCol; - model.addElement(service); + model.addElement(aCol); } } catch (Exception e1) { @@ -104,7 +102,7 @@ public String getSelectedService() { JPanel topPanel = new JPanel(); topPanel.setLayout(new BorderLayout()); - TitlePanel titlePanel = new TitlePanel(Res.getString("title.browse.conference.services"), Res.getString("message.find.conference.services"), SparkRes.getImageIcon(SparkRes.BLANK_IMAGE), true); + TitlePanel titlePanel = new TitlePanel(Res.getString("title.browse.conference.services"), Res.getString("message.find.conference.services"), SparkRes.getImageIcon(SparkRes.Icon.BLANK_IMAGE), true); topPanel.add(titlePanel, BorderLayout.NORTH); topPanel.add(pane, BorderLayout.CENTER); @@ -120,7 +118,8 @@ public String getSelectedService() { dlg.setLocationRelativeTo(SparkManager.getMainWindow()); PropertyChangeListener changeListener = new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent e) { + @Override + public void propertyChange(PropertyChangeEvent e) { String value = (String)pane.getValue(); if ("Close".equals(value)) { list.clearSelection(); @@ -140,22 +139,23 @@ else if ("Ok".equals(value)) { dlg.toFront(); - return (String)list.getSelectedValue(); + return list.getSelectedValue(); } - public Collection getConferenceServices(String server) throws Exception { + public Collection getConferenceServices(String serverString) throws Exception { + Jid server = JidCreate.from(serverString); List answer = new ArrayList<>(); - ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(SparkManager.getConnection()); + ServiceDiscoveryManager discoManager = SparkManager.getDiscoManager(); DiscoverItems items = discoManager.discoverItems(server); for (DiscoverItems.Item item : items.getItems() ) { - if (item.getEntityID().startsWith("conference") || item.getEntityID().startsWith("private")) { - answer.add(item.getEntityID()); + if (item.getEntityID().toString().startsWith("conference") || item.getEntityID().toString().startsWith("private")) { + answer.add(item.getEntityID().toString()); } else { try { DiscoverInfo info = discoManager.discoverInfo(item.getEntityID()); - if (info.containsFeature("http://jabber.org/protocol/muc")) { - answer.add(item.getEntityID()); + if (info.containsFeature(MultiUserChatConstants.NAMESPACE)) { + answer.add(item.getEntityID().toString()); } } catch (XMPPException | SmackException e) { diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/ConferenceServices.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/ConferenceServices.java new file mode 100644 index 000000000..282236736 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/ConferenceServices.java @@ -0,0 +1,439 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.conferences; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smackx.bookmarks.BookmarkedConference; +import org.jivesoftware.smackx.muc.InvitationListener; +import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jivesoftware.smackx.muc.MultiUserChatManager; +import org.jivesoftware.smackx.muc.packet.MUCUser; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.Workspace; +import org.jivesoftware.spark.plugin.ContextMenuListener; +import org.jivesoftware.spark.ui.*; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.UIComponentRegistry; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.EntityJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Localpart; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.TimerTask; + +/** + * Conference plugin is responsible for the initial loading of Multi User Chat support. + */ +public class ConferenceServices implements InvitationListener { + private static final BookmarksUI bookmarksUI = new BookmarksUI(); + private final LocalPreferences pref = SettingsManager.getLocalPreferences(); + + public ConferenceServices() { + addInvitationListener(); + addChatRoomListener(); + addPopupListeners(); + + // Add Join Conference Button to ActionMenu + final JMenu actionsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions")); + JMenuItem actionMenuItem = new JMenuItem(Res.getString("message.join.conference.room"), SparkRes.getImageIcon(SparkRes.Icon.CONFERENCE_IMAGE_16x16)); + actionsMenu.add(actionMenuItem, 1); + actionMenuItem.addActionListener(e -> { + ConferenceRoomBrowser rooms = new ConferenceRoomBrowser(bookmarksUI, getDefaultServiceName()); + rooms.invoke(); + }); + + // Add Presence Listener to send directed presence to Group Chat Rooms. + PresenceListener presenceListener = presence -> SwingUtilities.invokeLater(() -> { + for (ChatRoom room : SparkManager.getChatManager().getChatContainer().getChatRooms()) { + if (room instanceof GroupChatRoom) { + GroupChatRoom groupChatRoom = (GroupChatRoom) room; + EntityBareJid jid = groupChatRoom.getMultiUserChat().getRoom(); + int priority = presence.getPriority(); + //Sometimes priority is not set in the presence packet received. Make sure priority is in valid range + priority = (priority < -128 || priority > 128) ? 1 : priority; + final Presence p = StanzaBuilder.buildPresence() + .ofType(presence.getType()) + .setStatus(presence.getStatus()) + .setPriority(priority) + .setMode(presence.getMode()) + .to(jid) + .build(); + try { + SparkManager.getConnection().sendStanza(p); + } catch (SmackException.NotConnectedException | InterruptedException e) { + Log.warning("Unable to send stanza to " + p.getTo(), e); + } + } + } + }); + SparkManager.getSessionManager().addPresenceListener(presenceListener); + } + + /** + * Adds an invitation listener to check for any MUC invites. + */ + private void addInvitationListener() { + SparkManager.getMucManager().addInvitationListener(this); + } + + /** + * Persists bookmarked data, if any. + */ + @SuppressWarnings("EmptyMethod") + public void shutdown() { + } + + /** + * Load all bookmarked data. + */ + public void loadConferenceBookmarks() { + final TimerTask bookmarkLoader = new TimerTask() { + @Override + public void run() { + try { + bookmarksUI.loadUI(); + bookmarksUI.loadBookmarks(); + addBookmarksUI(); + } catch (Exception e) { + Log.error(e); + } + } + }; + TaskEngine.getInstance().schedule(bookmarkLoader, 500); + } + + /** + * Add Bookmarks UI Tab "Conferences" to the workspace + */ + protected void addBookmarksUI() { + EventQueue.invokeLater(() -> { + final Workspace workspace = SparkManager.getWorkspace(); + final boolean useTab = pref.isShowConferenceTab(); + if (useTab) { + String title = Res.getString("tab.conferences"); + ImageIcon icon = SparkRes.getImageIcon(SparkRes.Icon.CONFERENCE_IMAGE_16x16); + workspace.getWorkspacePane().addTab(title, icon, bookmarksUI); + } + }); + } + + private void addChatRoomListener() { + ChatManager chatManager = SparkManager.getChatManager(); + chatManager.addChatRoomListener(new ChatRoomListener() { + @Override + public void chatRoomOpened(final ChatRoom room) { + if (room instanceof ChatRoomImpl) { + final ChatRoomDecorator decorator = new ChatRoomDecorator(room); + decorator.decorate(); + } + } + }); + } + + + public boolean canShutDown() { + return true; + } + + public static DomainBareJid getDefaultServiceName() { + return bookmarksUI.getMucServices() != null ? bookmarksUI.getMucServices().get(0) : null; + } + + private void addPopupListeners() { + final ContactList contactList = SparkManager.getWorkspace().getContactList(); + + // Add ContactList items. + final Action inviteAllAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + Collection contacts = contactList.getActiveGroup().getContactItems(); + startConference(contacts); + } + }; + + inviteAllAction.putValue(Action.NAME, Res.getString("menuitem.invite.group.to.conference")); + inviteAllAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.CONFERENCE_IMAGE_16x16)); + final Action conferenceAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + Collection contacts = contactList.getSelectedUsers(); + startConference(contacts); + } + }; + + conferenceAction.putValue(Action.NAME, Res.getString("menuitem.start.a.conference")); + conferenceAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_WORKGROUP_QUEUE_IMAGE)); + + + contactList.addContextMenuListener(new ContextMenuListener() { + @Override + public void poppingUp(Object component, JPopupMenu popup) { + Collection col = contactList.getSelectedUsers(); + if (component instanceof ContactGroup) { + popup.add(inviteAllAction); + } else if (component instanceof Collection && !col.isEmpty()) { + popup.add(conferenceAction); + } + } + + @Override + public void poppingDown(JPopupMenu popup) { + } + + @Override + public boolean handleDefaultAction(MouseEvent e) { + return false; + } + }); + + // Add to Actions Menu + final JMenu actionsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions")); + actionsMenu.add(conferenceAction); + } + + private void startConference(Collection items) { + DomainBareJid serviceName = getDefaultServiceName(); + if (serviceName == null) { + return; + } + final ContactList contactList = SparkManager.getWorkspace().getContactList(); + List jids = new ArrayList<>(items.size()); + for (ContactItem item : items) { + ContactGroup contactGroup = contactList.getContactGroup(item.getGroupName()); + contactGroup.clearSelection(); + if (item.isAvailable()) { + jids.add(item.getJid()); + } + } + String userName = SparkManager.getSessionManager().getJID().getLocalpart().toString(); + final Localpart roomName = Localpart.fromUnescapedOrThrowUnchecked(userName + "_" + StringUtils.randomString(3)); + EntityBareJid room = JidCreate.entityBareFrom(roomName, serviceName); + ConferenceUtils.inviteUsersToRoom(serviceName, room, jids, true); + } + + protected BookmarkedConference getDefaultBookmark() { + BookmarkedConference bookmarkedConference = null; + try { + List bookmarkedConfs = ConferenceUtils.retrieveBookmarkedConferences(); + EntityBareJid implicitBookmarkedJID = pref.getDefaultBookmarkedConf(); + if (bookmarkedConfs != null && !bookmarkedConfs.isEmpty()) { + // check if the "default" bookmarked conference is still in the bookmarks list: + if (implicitBookmarkedJID != null) { + for (BookmarkedConference bc : bookmarkedConfs) { + if (implicitBookmarkedJID.equals(bc.getJid())) { + bookmarkedConference = bc; + break; + } + } + } + // If no match was found, or no "default" bookmark could be retrieved-use the first bookmark: + if (bookmarkedConference == null) { + bookmarkedConference = bookmarkedConfs.iterator().next(); + } + } + return bookmarkedConference; + } catch (XMPPException | SmackException | InterruptedException ex) { + Log.warning("No default bookmark can be retrieved"); + } + return null; + } + + /** + * Returns the UI for the addition and removal of Conference bookmarks. + */ + public static BookmarksUI getBookmarkedConferences() { + return bookmarksUI; + } + + private class ChatRoomDecorator implements ActionListener, ChatRoomClosingListener { + private final ChatRoom chatRoom; + private ChatRoomButton inviteButton; + + public ChatRoomDecorator(ChatRoom room) { + this.chatRoom = room; + chatRoom.addClosingListener(this); + } + + public void decorate() { + // Add Conference Invite Button. + inviteButton = UIComponentRegistry.getButtonFactory().createInviteConferenceButton(); + inviteButton.setToolTipText(Res.getString("title.invite.to.conference")); + chatRoom.addChatRoomButton(inviteButton); + inviteButton.addActionListener(this); + } + + @Override + public void closing() { + inviteButton.removeActionListener(this); + chatRoom.removeClosingListener(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + Localpart userName = SparkManager.getSessionManager().getJID().getLocalpart(); + final String roomName = userName + "_" + StringUtils.randomString(3); + final List jids = new ArrayList<>(); + jids.add(((ChatRoomImpl) chatRoom).getParticipantJID()); + final DomainBareJid serviceName = getDefaultServiceName(); + if (serviceName == null) { + return; + } + // Creates private conference in background thread + SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + try { + Thread.sleep(25); + } catch (InterruptedException e1) { + Log.error(e1); + } + return "ok"; + } + + @Override + public void finished() { + try { + BookmarkedConference selectedBookmarkedConf = pref.isUseAdHocRoom() ? null : getDefaultBookmark(); + if (selectedBookmarkedConf == null) { + ConferenceUtils.createPrivateConference(serviceName, + Res.getString("message.please.join.in.conference"), roomName, jids); + } else { + ConferenceUtils.joinConferenceOnSeparateThread(selectedBookmarkedConf.getName(), + selectedBookmarkedConf.getJid(), selectedBookmarkedConf.getNickname(), selectedBookmarkedConf.getPassword(), + Res.getString("message.please.join.in.conference"), jids); + } + } catch (SmackException | InterruptedException ex) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(chatRoom, "An error occurred.", Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + } + } + }; + worker.start(); + } + } + + @Override + public void invitationReceived(final XMPPConnection conn, final MultiUserChat room, final EntityJid inviterEntity, final String reason, + final String password, final Message message, MUCUser.Invite invitation) { + EntityBareJid inviter = inviterEntity.asEntityBareJid(); + SwingUtilities.invokeLater(() -> { + for (RoomInvitationListener listener : SparkManager.getChatManager().getInvitationListeners()) { + boolean handle = listener.handleInvitation(conn, room, inviter, reason, password, message); + if (handle) { + return; + } + } + // Make sure the user is not already in the room. + ChatContainer chatContainer = SparkManager.getChatManager().getChatContainer(); + try { + chatContainer.getChatRoom(room.getRoom()); + return; + } catch (ChatRoomNotFoundException ignored) { + } + + final GroupChatInvitationUI invitationUI = new GroupChatInvitationUI(room.getRoom(), inviter, password, reason); + String message1 = Res.getString("message.invite.to.groupchat", inviter); + String title = Res.getString("title.group.chat"); + EntityBareJid bareJID = inviter.asEntityBareJid(); + + if (pref.isAutoAcceptMucInvite()) { + ConferenceUtils.enterRoomOnSameThread(room.getRoom().getLocalpart().toString(), room.getRoom(), password); + MultiUserChatManager mucManager = SparkManager.getMucManager(); + GroupChatRoom chat = UIComponentRegistry.createGroupChatRoom(mucManager.getMultiUserChat(room.getRoom())); + showToaster(message1, title, chat); + return; + // Nothing to do here, we want to join the room, and stuff + } + try { + ChatRoom chatRoom = chatContainer.getChatRoom(bareJID); + // If the ChatRoom exists, add an invitationUI. + chatRoom.getTranscriptWindow().addComponent(invitationUI); + // Notify user of incoming invitation. + chatRoom.increaseUnreadMessageCount(); + chatRoom.scrollToBottom(); + chatContainer.fireNotifyOnMessage(chatRoom, true, message1, title); + } catch (ChatRoomNotFoundException e) { + // If it doesn't exist, create a new Group Chat Room + final MultiUserChatManager mucManager = SparkManager.getMucManager(); + final GroupChatRoom groupChatRoom = UIComponentRegistry.createGroupChatRoom(mucManager.getMultiUserChat(room.getRoom())); + showToaster(message1, title, groupChatRoom); + + groupChatRoom.getSplitPane().setDividerSize(5); + groupChatRoom.getVerticalSlipPane().setDividerLocation(0.6); + groupChatRoom.getSplitPane().setDividerLocation(0.6); + Localpart roomName = room.getRoom().getLocalpart(); + groupChatRoom.setTabTitle(roomName); + groupChatRoom.getToolBar().setVisible(true); + chatContainer.addChatRoom(groupChatRoom); + groupChatRoom.getTranscriptWindow().addComponent(invitationUI); + // Notify user of incoming invitation. + groupChatRoom.increaseUnreadMessageCount(); + groupChatRoom.scrollToBottom(); + chatContainer.fireNotifyOnMessage(groupChatRoom, true, message1, title); + } + // If no listeners handled the invitation default to generic invite. + // new ConversationInvitation(conn, room, inviter, reason, password, message); + }); + } + + private void showToaster(String message, String title, GroupChatRoom groupChatRoom) { + if (!pref.getShowToasterPopup()) { + return; + } + SparkToaster toaster = new SparkToaster(); + toaster.setCustomAction(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + ChatFrame chatFrame = SparkManager.getChatManager().getChatContainer().getChatFrame(); + chatFrame.setState(Frame.NORMAL); + chatFrame.setVisible(true); + } + }); + toaster.setDisplayTime(5000); + toaster.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); + toaster.setToasterHeight(150); + toaster.setToasterWidth(200); + toaster.setTitle(title); + toaster.showToaster(groupChatRoom.getTabIcon(), message); + } + +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/ConferenceUtils.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/ConferenceUtils.java new file mode 100644 index 000000000..79e361034 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/ConferenceUtils.java @@ -0,0 +1,286 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.conferences; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaError; +import org.jivesoftware.smackx.bookmarks.BookmarkManager; +import org.jivesoftware.smackx.bookmarks.BookmarkedConference; +import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jivesoftware.smackx.muc.MultiUserChatManager; +import org.jivesoftware.smackx.muc.RoomInfo; +import org.jivesoftware.smackx.xdata.form.FillableForm; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.ChatRoomNotFoundException; +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jivesoftware.spark.util.UIComponentRegistry; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.privacy.PrivacyManager; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Localpart; +import org.jxmpp.jid.parts.Resourcepart; + +import javax.swing.*; +import java.awt.*; +import java.util.*; +import java.util.List; + +import static org.jivesoftware.smackx.muc.MucConfigFormManager.*; + +/** + * ConferenceUtils allow for basic joining and inviting of users. + */ +public class ConferenceUtils { + private static final LocalPreferences pref = SettingsManager.getLocalPreferences(); + + private ConferenceUtils() { + } + + /** + * Enters a GroupChatRoom on the event thread. + * + * @param roomName the name of the room. + * @param roomJID the jid of the room. + * @param password the rooms password (if any). + * @return the GroupChatRoom created. + */ + public static GroupChatRoom enterRoomOnSameThread(final CharSequence roomName, EntityBareJid roomJID, String password ) + { + final JoinRoomSwingWorker worker = new JoinRoomSwingWorker( roomJID, null, password, roomName.toString() ); + worker.start(); + return (GroupChatRoom) worker.get(); // blocks until completed. + } + + public static void joinConferenceOnSeparateThread(final CharSequence roomName, EntityBareJid roomJID, final Resourcepart nickname, String password) { + joinConferenceOnSeparateThread(roomName, roomJID, nickname, password, null, null); + } + + /** + * Joins a conference room using another thread. This allows for a smoother opening of rooms. + * + * @param roomName the name of the room. + * @param roomJID the jid of the room. + * @param nickname THe nickname that the user joining will be using (optional). + * @param password the rooms password if required. + */ + public static void joinConferenceOnSeparateThread(final CharSequence roomName, EntityBareJid roomJID, final Resourcepart nickname, String password, final String inviteMessage, final Collection invites) { + String tabTitle = roomName != null ? roomName.toString() : roomJID.getLocalpart().asUnescapedString(); + final JoinRoomSwingWorker worker = new JoinRoomSwingWorker( roomJID, nickname, password, tabTitle); + if ( invites != null && !invites.isEmpty() ) + { + final InviteSwingWorker inviteSwingWorker = new InviteSwingWorker( roomJID, invites, inviteMessage ); + worker.setFollowUp( inviteSwingWorker ); + } + worker.start(); + } + + /** + * Presents the user with a dialog pre-filled with the room name and the jid. + * + * @param roomInfo the info of the room. + * @param roomJID the rooms jid. + */ + public static void joinConferenceRoom(RoomInfo roomInfo, EntityBareJid roomJID) { + JoinConferenceRoomDialog joinDialog = new JoinConferenceRoomDialog(); + joinDialog.joinRoom(roomJID, roomInfo); + changePresenceToAvailableIfInvisible(); + } + + /** + * Invites users to an existing room. + * + * @param chat The room to invite people into. + * @param jids a collection of the users to invite. + */ + public static void inviteUsersToRoom(MultiUserChat chat, Collection jids, boolean randomName ) { + inviteUsersToRoom(chat.getRoom().asDomainBareJid(), chat.getRoom(), jids, randomName ); + } + + /** + * Invites users to an existing room. + * + * @param serviceName the service name to use. + * @param roomName the name of the room. + * @param jids a collection of the users to invite. + */ + public static void inviteUsersToRoom(DomainBareJid serviceName, EntityBareJid roomName, Collection jids, boolean randomName) { + boolean useTextField = pref.isUseAdHocRoom(); + List rooms = null; + if (!useTextField) { + try { + rooms = retrieveBookmarkedConferences(); + } catch (Exception ex) { + Log.error(ex); + } + useTextField = !randomName || (rooms == null || rooms.isEmpty()); + } + InvitationDialog inviteDialog = new InvitationDialog(useTextField); + inviteDialog.inviteUsersToRoom(serviceName, rooms, roomName, jids); + } + + public static List retrieveBookmarkedConferences() throws XMPPException, SmackException, InterruptedException + { + BookmarkManager manager = BookmarkManager.getBookmarkManager(SparkManager.getConnection()); + return manager.getBookmarkedConferences(); + } + + /** + * Creates a private conference. + * + * @param serviceName the service name to use for the private conference. + * @param message the message sent to each individual invitee. + * @param roomName the name of the room to create. + * @param jids a collection of the user JIDs to invite. + * @throws SmackException thrown if an error occurs during room creation. + * @throws InterruptedException + */ + public static void createPrivateConference(DomainBareJid serviceName, String message, String roomName, Collection jids) throws SmackException, InterruptedException + { + Localpart roomNamePart = Localpart.fromUnescapedOrThrowUnchecked(roomName); + EntityBareJid roomJID = JidCreate.entityBareFrom(roomNamePart, serviceName); + MultiUserChatManager mucManager = SparkManager.getMucManager(); + MultiUserChat multiUserChat = mucManager.getMultiUserChat(roomJID); + final GroupChatRoom room = UIComponentRegistry.createGroupChatRoom(multiUserChat); + try { + // Attempt to create room. + multiUserChat.create(pref.getNickname()); + } + catch (XMPPException e) { + // TODO: Simply let this method throw XMPPException, instead of wrapping it here. + throw new SmackException.SmackWrappedException(e); + } + + try { + // Since this is a private room, make the room not public and set user as owner of the room. + FillableForm submitForm = multiUserChat.getConfigurationForm().getFillableForm(); + submitForm.setAnswer(MUC_ROOMCONFIG_PUBLICLYSEARCHABLEROOM, false); + submitForm.setAnswer(MUC_ROOMCONFIG_ROOMNAME, roomName); + + multiUserChat.sendConfigurationForm(submitForm); + } + catch (XMPPException | SmackException e1) { + Log.error("Unable to send conference room chat configuration form.", e1); + } + + ChatManager chatManager = SparkManager.getChatManager(); + // Check if the room already is opened + try { + chatManager.getChatContainer().getChatRoom(room.getBareJid()); + } + catch (ChatRoomNotFoundException e) { + chatManager.getChatContainer().addChatRoom(room); + chatManager.getChatContainer().activateChatRoom(room); + } + + for (EntityBareJid jid : jids) { + multiUserChat.invite(jid, message); + room.getTranscriptWindow().insertNotificationMessage(Res.getString("message.waiting.for.user.to.join",jid), ChatManager.NOTIFICATION_COLOR); + } + } + + /** + * Returns an explanation for the exception. + * + * @param error The XMPP error + * @return the reason for the exception. + * @see XEP-0045 Error Conditions + */ + public static String getReason(StanzaError error) { + if (error == null) { + return Res.getString("message.error.no.response"); + } + + switch ( error.getCondition() ) + { + case conflict: + return Res.getString("message.error.nickname.in.use"); + case forbidden: + return Res.getString("message.you.have.been.banned"); + case remote_server_not_found: + case item_not_found: + return Res.getString("message.error.room.not.exist"); + case not_acceptable: + return Res.getString("message.error.must.use.reserved.nick"); + case not_allowed: + return Res.getString("message.error.no.permission.create.room"); + case not_authorized: + return Res.getString("message.error.room.password.incorrect"); + case registration_required: + return Res.getString("message.error.not.member"); + default: + String reason = error.getDescriptiveText() == null ? error.getCondition().toString() : error.getDescriptiveText(); + return Res.getString("message.default.error") + ": " + reason; + } + + } + + final static List unclosableChatRooms = new ArrayList<>(); + public synchronized static void addUnclosableChatRoom(EntityBareJid jid) { + unclosableChatRooms.add(jid); + } + + public static boolean isChatRoomClosable(Component c) { + if (c instanceof GroupChatRoom) { + GroupChatRoom groupChatRoom = (GroupChatRoom) c; + EntityBareJid roomName = groupChatRoom.getChatRoom().getBareJid(); + return !unclosableChatRooms.contains(roomName); + } else { + return true; + } + } + + public static boolean confirmToRevealVisibility() { + Presence currentPresence = SparkManager.getWorkspace().getStatusBar().getPresence(); + + if (!PresenceManager.isInvisible(currentPresence)) + return true; + + int reply = JOptionPane.showConfirmDialog(null, + Res.getString("dialog.confirm.to.reveal.visibility.msg"), + Res.getString("dialog.confirm.to.reveal.visibility.title"), + JOptionPane.YES_NO_OPTION); + return reply == JOptionPane.YES_OPTION; + } + + /** + * If the current present is 'invisible' then this method change it to + * 'Online'. Decided 'invisibility' is a kind of private thing. So if user + * would like to go to the conference then the user reveal him/herself. i.e. + * if current presence is invisible then we should go to visible. Otherwise + * all 'invisible' users will be shown as 'Offline' on the conference + * participant list which is confusing. This method mostly is used in + * ConferenceUtils. Usually it is called after user is joined to a room. + */ + public static void changePresenceToAvailableIfInvisible() { + Presence currentPresence = SparkManager.getWorkspace().getStatusBar().getPresence(); + if (PresenceManager.isInvisible(currentPresence)) { + PrivacyManager.getInstance().goToVisible(); + SparkManager.getSessionManager().changePresence(PresenceManager.getAvailablePresence()); + } + } + +} + diff --git a/src/java/org/jivesoftware/spark/ui/conferences/ConversationInvitation.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/ConversationInvitation.java similarity index 80% rename from src/java/org/jivesoftware/spark/ui/conferences/ConversationInvitation.java rename to core/src/main/java/org/jivesoftware/spark/ui/conferences/ConversationInvitation.java index fcfe1df2c..97f813477 100644 --- a/src/java/org/jivesoftware/spark/ui/conferences/ConversationInvitation.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/ConversationInvitation.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.jivesoftware.spark.ui.conferences; import org.jivesoftware.resource.Res; @@ -29,7 +25,8 @@ import org.jivesoftware.spark.ui.ContainerComponent; import org.jivesoftware.spark.util.ResourceUtils; import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.parts.Localpart; import java.awt.Color; import java.awt.FlowLayout; @@ -55,17 +52,15 @@ * @author Derek DeMoro */ public class ConversationInvitation extends JPanel implements ContainerComponent, ActionListener { - private static final long serialVersionUID = -5830187619047598274L; - - private JButton joinButton; + private final JButton joinButton; - private String roomName; - private String password; - private String inviter; + private final EntityBareJid roomName; + private final String password; + private final EntityBareJid inviter; - private String tabTitle; - private String frameTitle; - private String descriptionText; + private final String tabTitle; + private final String frameTitle; + private final String descriptionText; /** * Builds a new Conference Invitation UI. @@ -75,7 +70,7 @@ public class ConversationInvitation extends JPanel implements ContainerComponent * @param reason the reason they want to talk. * @param password the password of the room if any. */ - public ConversationInvitation( final String roomName, final String inviter, String reason, final String password ) { + public ConversationInvitation(EntityBareJid roomName, EntityBareJid inviter, String reason, final String password) { this.roomName = roomName; this.password = password; this.inviter = inviter; @@ -91,20 +86,14 @@ public ConversationInvitation( final String roomName, final String inviter, Stri final JLabel dateLabel = new JLabel(); final JLabel dateLabelValue = new JLabel(); - - String nickname = SparkManager.getUserManager().getUserNicknameFromJID(inviter); - - + String nickname = SparkManager.getUserManager().getUserNicknameFromJID(this.inviter); add(titleLabel, new GridBagConstraints(0, 0, 4, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(2, 5, 2, 5), 0, 0)); - add(description, new GridBagConstraints(0, 1, 4, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 9, 2, 5), 0, 0)); - - add(dateLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(2, 5, 2, 5), 0, 0)); add(dateLabelValue, new GridBagConstraints(1, 3, 3, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(2, 5, 2, 5), 0, 0)); titleLabel.setFont(new Font("dialog", Font.BOLD, 12)); - description.setFont(new Font("dialog", 0, 12)); + description.setFont(new Font("dialog", Font.PLAIN, 12)); titleLabel.setText(Res.getString("title.conference.invitation")); description.setText(nickname + " has invited you to chat in " + roomName + ". " + nickname + " writes \"" + reason + "\""); @@ -116,8 +105,8 @@ public ConversationInvitation( final String roomName, final String inviter, Stri // Set Date Label dateLabel.setFont(new Font("dialog", Font.BOLD, 12)); dateLabel.setText(Res.getString("date") + ":"); - String invitationDateFormat = ( (SimpleDateFormat) SimpleDateFormat.getTimeInstance( SimpleDateFormat.MEDIUM ) ).toPattern(); - final SimpleDateFormat formatter = new SimpleDateFormat( invitationDateFormat ); + String invitationDateFormat = ((SimpleDateFormat) SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM)).toPattern(); + final SimpleDateFormat formatter = new SimpleDateFormat(invitationDateFormat); final String date = formatter.format(new Date()); dateLabelValue.setText(date); dateLabelValue.setFont(new Font("dialog", Font.PLAIN, 12)); @@ -151,20 +140,18 @@ public ConversationInvitation( final String roomName, final String inviter, Stri } + @Override public void actionPerformed(ActionEvent actionEvent) { final Object obj = actionEvent.getSource(); if (obj == joinButton) { - String name = XmppStringUtils.parseLocalpart(roomName); - ConferenceUtils.enterRoomOnSameThread(name, roomName, password); - } - else { - try - { - MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).decline( roomName, inviter, "No thank you"); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "unable to decline invatation from " + inviter + " to join room " + roomName, e ); + Localpart name = roomName.getLocalpart(); + ConferenceUtils.enterRoomOnSameThread(name.toString(), roomName, password); + } else { + try { + MultiUserChatManager mucManager = SparkManager.getMucManager(); + mucManager.decline(roomName, inviter, "No thank you"); + } catch (SmackException.NotConnectedException | InterruptedException e) { + Log.warning("unable to decline invitation from " + inviter + " to join room " + roomName, e); } } @@ -174,26 +161,32 @@ public void actionPerformed(ActionEvent actionEvent) { } + @Override public String getTabTitle() { return tabTitle; } + @Override public String getFrameTitle() { return frameTitle; } + @Override public ImageIcon getTabIcon() { - return SparkRes.getImageIcon(SparkRes.CONFERENCE_IMAGE_16x16); + return SparkRes.getImageIcon(SparkRes.Icon.CONFERENCE_IMAGE_16x16); } + @Override public JComponent getGUI() { return this; } + @Override public String getToolTipDescription() { return descriptionText; } + @Override public boolean closing() { return true; } diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/DataFormDialog.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/DataFormDialog.java new file mode 100644 index 000000000..92d01bdc3 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/DataFormDialog.java @@ -0,0 +1,125 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.conferences; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.GridBagLayout; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.muc.MultiUserChatManager; +import org.jivesoftware.smackx.xdata.form.FillableForm; +import org.jivesoftware.smackx.xdata.form.Form; +import org.jivesoftware.smackx.bookmarks.BookmarkManager; +import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jivesoftware.smackx.muc.RoomInfo; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.MessageDialog; +import org.jivesoftware.spark.ui.ChatFrame; +import org.jivesoftware.spark.ui.DataFormUI; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.log.Log; + +/** + * Configure chat room + */ +public class DataFormDialog extends JPanel { + private final DataFormUI dataFormUI; + private final JDialog dialog; + + public static void openDataFormDialog(MultiUserChat chat) { + ChatFrame chatFrame = SparkManager.getChatManager().getChatContainer().getChatFrame(); + Form form; + // Create the room + try { + form = chat.getConfigurationForm(); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + MessageDialog.showErrorDialog(Res.getString("group.send_config.error"), e); + return; + } + new DataFormDialog(chatFrame, chat, form); + } + + public DataFormDialog(JFrame parent, MultiUserChat chat, Form form) { + dialog = new JDialog(parent, true); + dialog.setTitle(Res.getString("title.configure.chat.room")); + + this.setLayout(new GridBagLayout()); + + this.dataFormUI = new DataFormUI(form.getDataForm()); + this.add(dataFormUI); + + JButton button = new JButton(); + ResourceUtils.resButton(button, Res.getString("button.update")); + button.addActionListener(e -> { + dialog.dispose(); + // Now submit all information + updateRoomConfiguration(chat); + }); + + final JScrollPane pane = new JScrollPane(this); + pane.getVerticalScrollBar().setBlockIncrement(200); + pane.getVerticalScrollBar().setUnitIncrement(20); + + dialog.getContentPane().setLayout(new BorderLayout()); + dialog.getContentPane().add(pane, BorderLayout.CENTER); + + JPanel bottomPanel = new JPanel(); + bottomPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)); + bottomPanel.add(button); + + JButton cancelButton = new JButton(); + ResourceUtils.resButton(cancelButton, Res.getString("button.cancel")); + cancelButton.addActionListener(actionEvent -> dialog.dispose()); + + bottomPanel.add(cancelButton); + + dialog.getContentPane().add(bottomPanel, BorderLayout.SOUTH); + + dialog.pack(); + dialog.setSize(800, 600); + GraphicUtils.centerWindowOnScreen(dialog); + dialog.setVisible(true); + } + + private void updateRoomConfiguration(MultiUserChat chat) { + FillableForm submitForm = dataFormUI.getFilledForm(); + try { + chat.sendConfigurationForm(submitForm); + // Now recheck the new settings and update bookmark + MultiUserChatManager mucManager = SparkManager.getMucManager(); + RoomInfo info = mucManager.getRoomInfo(chat.getRoom()); + // Remove bookmark if any for a non-persistent room + if (!info.isPersistent()) { + BookmarkManager.getBookmarkManager(SparkManager.getConnection()).removeBookmarkedConference(info.getRoom()); + } + //TODO update bookmark password if it was set + } catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + MessageDialog.showErrorDialog(Res.getString("group.send_config.error"), e); + } + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/GroupChatInvitationUI.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/GroupChatInvitationUI.java new file mode 100644 index 000000000..29e88f2f0 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/GroupChatInvitationUI.java @@ -0,0 +1,181 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.conferences; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smackx.muc.MultiUserChatManager; +import org.jivesoftware.spark.ChatNotFoundException; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.SwingTimerTask; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.parts.Localpart; + +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextPane; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; + +import java.awt.Color; +import java.awt.Container; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimerTask; + +/** + * Conference Invitation UI. + * + * @author Derek DeMoro + */ +public class GroupChatInvitationUI extends JPanel implements ActionListener { + private final RolloverButton acceptButton; + + private final EntityBareJid room; + private final EntityBareJid inviter; + private final String password; + + public GroupChatInvitationUI(EntityBareJid room, EntityBareJid inviter, String password, String reason) { + setLayout(new GridBagLayout()); + setBackground(new Color(230, 239, 249)); + + this.room = room; + this.inviter = inviter; + this.password = password; + + // Build invitation time label. + final Date now = new Date(); + String invitationDateFormat = ((SimpleDateFormat) SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM)).toPattern(); + final SimpleDateFormat dateFormatter = new SimpleDateFormat(invitationDateFormat); + final String invitationTime = dateFormatter.format(now); + // Get users nickname, if there is one. + String nickname = SparkManager.getUserManager().getUserNicknameFromJID(inviter); + + JLabel iconLabel = new JLabel(SparkRes.getImageIcon(SparkRes.Icon.CONFERENCE_IMAGE_48x48)); + + JTextPane titleLabel = new JTextPane(); + titleLabel.setOpaque(false); + titleLabel.setEditable(false); + titleLabel.setBackground(new Color(230, 239, 249)); + + acceptButton = new RolloverButton(Res.getString("button.accept").replace("&", ""), SparkRes.getImageIcon(SparkRes.Icon.ACCEPT_INVITE_IMAGE)); + acceptButton.setForeground(new Color(63, 158, 61)); + + RolloverButton rejectButton = new RolloverButton(Res.getString("button.reject"), SparkRes.getImageIcon(SparkRes.Icon.REJECT_INVITE_IMAGE)); + rejectButton.setForeground(new Color(185, 33, 33)); + + add(iconLabel, new GridBagConstraints(0, 0, 1, 2, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); + add(titleLabel, new GridBagConstraints(1, 0, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0)); + + add(acceptButton, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 2, 2, 2), 0, 0)); + add(rejectButton, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 2, 2, 2), 0, 0)); + + final SimpleAttributeSet styles = new SimpleAttributeSet(); + StyleConstants.setForeground(styles, new Color(13, 104, 196)); + + Document document = titleLabel.getDocument(); + try { + document.insertString(0, "[" + invitationTime + "] ", styles); + StyleConstants.setBold(styles, true); + document.insertString(document.getLength(), Res.getString("message.invite.to.groupchat", nickname), styles); + + if (ModelUtil.hasLength(reason)) { + StyleConstants.setBold(styles, false); + document.insertString(document.getLength(), "\nMessage: " + reason, styles); + } + } catch (BadLocationException e) { + Log.error(e); + } + + acceptButton.addActionListener(this); + rejectButton.addActionListener(this); + } + + @Override + public void actionPerformed(ActionEvent event) { + if (event.getSource() == acceptButton) { + acceptInvitation(); + } else { + rejectInvitation(); + } + } + + /** + * Action taking when a user clicks on the accept button. + */ + private void acceptInvitation() { + setVisible(false); + Localpart name = room.getLocalpart(); + ConferenceUtils.enterRoomOnSameThread(name.toString(), room, password); + final TimerTask removeUITask = new SwingTimerTask() { + @Override + public void doRun() { + removeUI(); + } + }; + TaskEngine.getInstance().schedule(removeUITask, 2000); + } + + /** + * Action taking when a user clicks on the reject button. + */ + private void rejectInvitation() { + removeUI(); + // Close unjoined room + try { + GroupChatRoom chatRoom = SparkManager.getChatManager().getGroupChat(room); + if (chatRoom != null) { + if (!chatRoom.getMultiUserChat().isJoined()) { + chatRoom.closeChatRoom(); + } + } + } catch (ChatNotFoundException ignored) { + } + + try { + MultiUserChatManager mucManager = SparkManager.getMucManager(); + mucManager.decline(room, inviter, "No thank you"); + } catch (SmackException.NotConnectedException | InterruptedException e) { + Log.warning("Unable to decline invitation from " + inviter + " to join room " + room, e); + } + } + + /** + * Removes this interface from its parent. + */ + private void removeUI() { + final Container par = getParent(); + if (par != null) { + par.remove(this); + par.invalidate(); + par.validate(); + par.repaint(); + } + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/GroupChatParticipantList.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/GroupChatParticipantList.java new file mode 100644 index 000000000..806a33c52 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/GroupChatParticipantList.java @@ -0,0 +1,1099 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.conferences; + +import org.jdesktop.swingx.JXList; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.PresenceListener; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaError; +import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; +import org.jivesoftware.smackx.disco.packet.DiscoverInfo; +import org.jivesoftware.smackx.muc.*; +import org.jivesoftware.smackx.muc.packet.MUCItem; +import org.jivesoftware.smackx.muc.packet.MUCUser; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.UserManager; +import org.jivesoftware.spark.component.ImageTitlePanel; +import org.jivesoftware.spark.ui.ChatContainer; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomNotFoundException; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.EntityFullJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Resourcepart; +import org.jxmpp.stringprep.XmppStringprepException; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.List; +import java.util.*; + +import static org.apache.commons.lang3.StringUtils.isBlank; +import static org.jivesoftware.spark.ChatManager.ERROR_COLOR; +import static org.jivesoftware.spark.ChatManager.NOTIFICATION_COLOR; + +/** + * Display a room information, such as agents and room information. + */ +public class GroupChatParticipantList extends JPanel { + private GroupChatRoom groupChatRoom; + private final ImageTitlePanel agentInfoPanel; + private final ChatManager chatManager; + private MultiUserChat chat; + private final LocalPreferences pref = SettingsManager.getLocalPreferences(); + + /** + * Map of participants displayName and JID + */ + private final Map userMap = new HashMap<>(); + + private final UserManager userManager = SparkManager.getUserManager(); + + private final DefaultListModel model = new DefaultListModel<>(); + + private final JXList participantsList; + + private PresenceListener listener = null; + + private final Map invitees = new HashMap<>(); + + private boolean allowNicknameChange = true; + + private DiscoverInfo roomInformation; + + private final List users = new ArrayList<>(); + + private final Map usersToRoles = new HashMap<>(); + private final Map usersToAffiliation = new HashMap<>(); + + public GroupChatParticipantList() { + setLayout(new GridBagLayout()); + chatManager = SparkManager.getChatManager(); + + agentInfoPanel = new ImageTitlePanel(Res.getString("message.participants.in.room")); + participantsList = new JXList(model); + participantsList.setCellRenderer(new ParticipantRenderer()); + + // Set the room to track + this.setOpaque(false); + this.setBackground(Color.white); + + // Respond to Double-Click in Agent List to start a chat + participantsList.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent evt) { + if (evt.getClickCount() != 2) { + return; + } + String selectedUser = getSelectedUser(); + if (selectedUser == null) { + return; + } + startChat(groupChatRoom, userMap.get(Resourcepart.fromOrThrowUnchecked(selectedUser))); + } + + @Override + public void mouseReleased(final MouseEvent evt) { + if (evt.isPopupTrigger()) { + checkPopup(evt); + } + } + + @Override + public void mousePressed(final MouseEvent evt) { + if (evt.isPopupTrigger()) { + checkPopup(evt); + } + } + }); + + JScrollPane scroller = new JScrollPane(participantsList); + scroller.setPreferredSize(new Dimension(200, getHeight())); + + // Speed up scrolling. It was way too slow. + scroller.getVerticalScrollBar().setBlockIncrement(200); + scroller.getVerticalScrollBar().setUnitIncrement(20); + scroller.setBackground(Color.white); + scroller.getViewport().setBackground(Color.white); + + add(scroller, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); + } + + public void setChatRoom(final ChatRoom chatRoom) { + this.groupChatRoom = (GroupChatRoom) chatRoom; + chat = groupChatRoom.getMultiUserChat(); + chat.addInvitationRejectionListener((jid1, reason, message, rejection) -> { + String displayName = userManager.getUserNicknameFromJID(jid1); + userHasLeft(displayName); + chatRoom.getTranscriptWindow().insertNotificationMessage( + displayName + " has rejected the invitation." + " " + reason, + NOTIFICATION_COLOR); + }); + + listener = p -> SwingUtilities.invokeLater(() -> { + if (p.getError() != null) { + if (p.getError().getCondition() == StanzaError.Condition.conflict) { + return; + } + } + final EntityFullJid userid = p.getFrom().asEntityFullJidOrThrow(); + + Resourcepart displayName = userid.getResourcepart(); + userMap.put(displayName, userid); + if (p.getType() == Presence.Type.available) { + addParticipant(userid, p); + agentInfoPanel.setVisible(true); + groupChatRoom.validate(); + } else { + removeUser(displayName); + } + + // When joining a room, check if the current user is an owner/admin. If so, the UI should allow the current + // user to change settings of this MUC. + final MUCUser mucUserEx = p.getExtension(MUCUser.class); + // 110 = Inform user that presence refers to itself + if (mucUserEx != null && mucUserEx.getStatus().contains(MUCUser.Status.create(110))) { + final MUCItem item = mucUserEx.getItem(); + if (item != null) { + if (item.getAffiliation() == MUCAffiliation.admin || item.getAffiliation() == MUCAffiliation.owner) { + groupChatRoom.notifySettingsAccessRight(); + } + } + } + }); + + chat.addParticipantListener(listener); + ServiceDiscoveryManager discoManager = SparkManager.getDiscoManager(); + try { + roomInformation = discoManager.discoverInfo(chat.getRoom()); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.debug("Unable to retrieve room information for " + chat.getRoom()); + } + } + + public void addInvitee(EntityBareJid jid, String message) { + // So the problem with this is that I have no idea what the users actual + // jid is in most cases. + final UserManager userManager = SparkManager.getUserManager(); + String displayName = userManager.getUserNicknameFromJID(jid); + + groupChatRoom.getTranscriptWindow().insertNotificationMessage( + displayName + " has been invited to join this room.", + NOTIFICATION_COLOR); + if (roomInformation != null + && !roomInformation.containsFeature(MucFeature.NonAnonymous.getName())) { + return; + } + final ImageIcon inviteIcon = SparkRes.getImageIcon(SparkRes.Icon.USER1_BACK_16x16); + addUser(inviteIcon, Resourcepart.fromOrThrowUnchecked(displayName)); + invitees.put(displayName, message); + } + + protected ImageIcon getImageIcon(EntityFullJid participantJID) { + Resourcepart displayName = participantJID.getResourcepart(); + ImageIcon icon = SparkRes.getImageIcon(SparkRes.Icon.GREEN_BALL); + icon.setDescription(displayName.toString()); + return icon; + } + + protected void addParticipant(final EntityFullJid participantJID, Presence presence) { + // Remove reference to invitees + for (CharSequence displayName : invitees.keySet()) { + EntityFullJid jid = SparkManager.getUserManager().getJIDFromDisplayName(displayName); + Occupant occ = chat.getOccupant(jid); + if (occ != null) { + Jid actualJID = occ.getJid(); + if (actualJID.equals(jid)) { + removeUser(displayName); + } + } + } + + Resourcepart nickname = participantJID.getResourcepart(); + MUCAffiliation affiliation = null; + MUCRole role = null; + final MUCUser extension = presence.getExtension(MUCUser.class); + if (extension != null && extension.getItem() != null) { + affiliation = extension.getItem().getAffiliation(); + role = extension.getItem().getRole(); + } + + if (affiliation == null) { + affiliation = MUCAffiliation.none; + } + if (role == null) { + role = MUCRole.none; + } + + usersToRoles.put(participantJID, role); + usersToAffiliation.put(participantJID, affiliation); + + Icon icon; + if (pref.isShowingRoleIcons()) { + icon = getIconForRole(role, affiliation); + } else { + icon = PresenceManager.getIconFromPresence(presence); + if (icon == null) { + icon = SparkRes.getImageIcon(SparkRes.Icon.GREEN_BALL); + } + } + + if (!exists(nickname)) { + addUser(icon, nickname); + } else { + int index = getIndex(nickname); + if (index != -1) { + final JLabel userLabel = new JLabel(nickname.toString(), icon, SwingConstants.CENTER); + userLabel.setForeground(groupChatRoom.getUserColor(nickname)); + model.setElementAt(userLabel, index); + } + } + } + + /** + * Returns corresponding Icons for each MUC-Role + * icons are:
      + * Owner = Gold Star
      + * Admin = Silver Star
      + * Moderator = Bronze Star
      + * Member = Yellow
      + * Participant = Green
      + * Visitor = Blue
      + * N/A = Grey
      + */ + private Icon getIconForRole(MUCRole role, MUCAffiliation affiliation) { + switch (affiliation) { + case owner: + return SparkRes.getImageIcon(SparkRes.Icon.STAR_OWNER); + case admin: + return SparkRes.getImageIcon(SparkRes.Icon.STAR_ADMIN); + case member: + if (role == MUCRole.moderator) { + return SparkRes.getImageIcon(SparkRes.Icon.STAR_MODERATOR); + } else { + return SparkRes.getImageIcon(SparkRes.Icon.STAR_YELLOW_IMAGE); + } + default: + switch (role) { + case participant: + return SparkRes.getImageIcon(SparkRes.Icon.STAR_GREEN_IMAGE); + case moderator: + return SparkRes.getImageIcon(SparkRes.Icon.STAR_MODERATOR); + case visitor: + return SparkRes.getImageIcon(SparkRes.Icon.STAR_BLUE_IMAGE); + default: + return SparkRes.getImageIcon(SparkRes.Icon.STAR_GREY_IMAGE); + } + } + } + + public void userHasLeft(CharSequence displayName) { + int index = getIndex(displayName); + if (index != -1) { + removeUser(displayName); + userMap.remove(displayName); + } + } + + protected boolean exists(Resourcepart nickname) { + String nicknameString = nickname.toString(); + // Check if nickname exists in UI user list + for (int i = 0; i < model.getSize(); i++) { + final JLabel userLabel = model.getElementAt(i); + if (userLabel.getText().equals(nicknameString)) { + return true; + } + } + return false; + } + + protected String getSelectedUser() { + JLabel label = (JLabel) participantsList.getSelectedValue(); + if (label != null) { + return label.getText(); + } + return null; + } + + protected void startChat(ChatRoom groupChat, EntityFullJid groupJID) { + Resourcepart userNickname = groupJID.getResourcepart(); + String roomTitle = userNickname + " - " + groupChat.getBareJid(); + // TODO: Remove duplicate variable userNickname and nicknameOfUser. + Resourcepart nickname = groupChat.getNickname(); + if (userNickname.equals(nickname)) { + return; + } + ChatContainer chatContainer = chatManager.getChatContainer(); + ChatRoom chatRoom; + try { + chatRoom = chatContainer.getChatRoom(groupJID); + } catch (ChatRoomNotFoundException e) { + Log.debug("Could not find chat room - " + groupJID); + // Create a new room + chatRoom = new ChatRoomImpl(groupJID, userNickname, roomTitle); + chatContainer.addChatRoom(chatRoom); + } + chatContainer.activateChatRoom(chatRoom); + } + + public String getTabTitle() { + return Res.getString("title.room.information"); + } + + public Icon getTabIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.SMALL_BUSINESS_MAN_VIEW); + } + + public String getTabToolTip() { + return Res.getString("title.room.information"); + } + + public JComponent getGUI() { + return this; + } + + protected void kickUser(Resourcepart nickname) { + try { + chat.kickParticipant(nickname, Res.getString("message.you.have.been.kicked")); + } catch (XMPPException | SmackException | InterruptedException e) { + groupChatRoom.insertText(Res.getString("message.kicked.error", nickname)); + } + } + + protected void banUser(Resourcepart displayName) { + try { + EntityFullJid entityFullJid = userMap.get(displayName); + Occupant occupant = chat.getOccupant(entityFullJid); + if (occupant != null) { + EntityBareJid bareJID = occupant.getJid().asEntityBareJidOrThrow(); + chat.banUser(bareJID, Res.getString("message.you.have.been.banned")); + } + } catch (XMPPException | SmackException | InterruptedException | IllegalStateException e) { + groupChatRoom.getTranscriptWindow(). + insertNotificationMessage("No can do " + e.getMessage(), ERROR_COLOR); + } + } + + protected void unbanUser(String jidString) { + try { + BareJid jid = JidCreate.bareFrom(jidString); + chat.grantMembership(jid); + } catch (XMPPException | SmackException | XmppStringprepException | InterruptedException e) { + groupChatRoom.getTranscriptWindow(). + insertNotificationMessage("No can do " + e.getMessage(), ERROR_COLOR); + } + } + + protected void grantVoice(Resourcepart nickname) { + try { + chat.grantVoice(nickname); + } catch (XMPPException | SmackException | InterruptedException e) { + groupChatRoom.getTranscriptWindow(). + insertNotificationMessage("No can do " + e.getMessage(), ERROR_COLOR); + } + } + + protected void revokeVoice(Resourcepart nickname) { + try { + chat.revokeVoice(nickname); + } catch (XMPPException | SmackException | InterruptedException e) { + groupChatRoom.getTranscriptWindow(). + insertNotificationMessage("No can do " + e.getMessage(), ERROR_COLOR); + } + } + + protected void grantModerator(Resourcepart nickname) { + try { + chat.grantModerator(nickname); + } catch (XMPPException | SmackException | InterruptedException e) { + groupChatRoom.getTranscriptWindow().insertNotificationMessage( + "No can do " + e.getMessage(), ERROR_COLOR); + } + } + + protected void revokeModerator(Resourcepart nickname) { + try { + chat.revokeModerator(nickname); + } catch (XMPPException | SmackException | InterruptedException e) { + groupChatRoom.getTranscriptWindow().insertNotificationMessage( + "No can do " + e.getMessage(), ERROR_COLOR); + } + } + + protected void grantMember(Resourcepart nickname) { + try { + Occupant o = userManager.getOccupant(groupChatRoom, nickname); + BareJid bareJid = o.getJid().asBareJid(); + chat.grantMembership(bareJid); + } catch (XMPPException | SmackException | InterruptedException e) { + groupChatRoom.getTranscriptWindow().insertNotificationMessage( + "No can do " + e.getMessage(), ERROR_COLOR); + } + } + + protected void revokeMember(Resourcepart nickname) { + try { + Occupant o = userManager.getOccupant(groupChatRoom, nickname); + BareJid bareJid = o.getJid().asBareJid(); + chat.revokeMembership(bareJid); + } catch (XMPPException | SmackException | InterruptedException e) { + groupChatRoom.getTranscriptWindow().insertNotificationMessage( + "No can do " + e.getMessage(), ERROR_COLOR); + } + } + + protected void grantAdmin(Resourcepart nickname) { + try { + Occupant o = userManager.getOccupant(groupChatRoom, nickname); + BareJid bareJid = o.getJid().asBareJid(); + chat.grantAdmin(bareJid); + } catch (XMPPException | SmackException | InterruptedException e) { + groupChatRoom.getTranscriptWindow().insertNotificationMessage( + "No can do " + e.getMessage(), ERROR_COLOR); + } + } + + protected void revokeAdmin(Resourcepart nickname) { + try { + Occupant o = userManager.getOccupant(groupChatRoom, nickname); + BareJid bareJid = o.getJid().asBareJid(); + chat.revokeAdmin(bareJid); + } catch (XMPPException | SmackException | InterruptedException e) { + groupChatRoom.getTranscriptWindow().insertNotificationMessage( + "No can do " + e.getMessage(), ERROR_COLOR); + } + } + + protected void grantOwner(Resourcepart nickname) { + try { + Occupant o = userManager.getOccupant(groupChatRoom, nickname); + BareJid bareJid = o.getJid().asBareJid(); + chat.grantOwnership(bareJid); + } catch (XMPPException | SmackException | InterruptedException e) { + groupChatRoom.getTranscriptWindow().insertNotificationMessage( + "No can do " + e.getMessage(), ERROR_COLOR); + } + } + + protected void revokeOwner(Resourcepart nickname) { + try { + Occupant o = userManager.getOccupant(groupChatRoom, nickname); + BareJid bareJid = o.getJid().asBareJid(); + chat.revokeOwnership(bareJid); + } catch (XMPPException | SmackException | InterruptedException e) { + groupChatRoom.getTranscriptWindow().insertNotificationMessage( + "No can do " + e.getMessage(), ERROR_COLOR); + } + } + + protected void checkPopup(MouseEvent evt) { + Point p = evt.getPoint(); + final int index = participantsList.locationToIndex(p); + final JPopupMenu popup = new JPopupMenu(); + if (index != -1) { + participantsList.setSelectedIndex(index); + final JLabel userLabel = model.getElementAt(index); + final Resourcepart selectedUser = Resourcepart.fromOrThrowUnchecked(userLabel.getText()); + final EntityFullJid groupJID = userMap.get(selectedUser); + final Resourcepart groupJIDNickname = groupJID.getResourcepart(); + final Resourcepart nickname = groupChatRoom.getNickname(); + final Occupant occupant = userManager.getOccupant(groupChatRoom, selectedUser); + final boolean iamAdmin = SparkManager.getUserManager().isAdmin(groupChatRoom, chat.getNickname()); + final boolean iamOwner = SparkManager.getUserManager().isOwner(groupChatRoom, chat.getNickname()); + final boolean iamAdminOrOwner = iamAdmin || iamOwner; + final boolean iamModerator = SparkManager.getUserManager().isModerator(groupChatRoom, chat.getNickname()); + final boolean userIsMember = SparkManager.getUserManager().isMember(occupant); + final boolean userIsAdmin = userManager.isAdmin(groupChatRoom, occupant.getNick()); + final boolean userIsOwner = userManager.isOwner(occupant); + final boolean userIsModerator = userManager.isModerator(occupant); + boolean selectedMyself = nickname.equals(groupJIDNickname); + + // Handle invites + if (groupJIDNickname == null) { + Action inviteAgainAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + String message = invitees.get(selectedUser); + EntityFullJid jid = userManager.getJIDFromDisplayName(selectedUser); + try { + chat.invite(jid.asEntityBareJid(), message); + } catch (SmackException.NotConnectedException | InterruptedException e) { + Log.warning("Unable to send stanza to " + jid, e); + } + } + }; + + inviteAgainAction.putValue(Action.NAME, Res.getString("menuitem.invite.again")); + popup.add(inviteAgainAction); + + Action removeInvite = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + int index = getIndex(selectedUser); + if (index != -1) { + model.removeElementAt(index); + } + } + }; + removeInvite.putValue(Action.NAME, Res.getString("menuitem.remove")); + popup.add(removeInvite); + + popup.show(participantsList, evt.getX(), evt.getY()); + return; + } + + if (selectedMyself) { + Action changeNicknameAction = new ChangeNicknameAction(); + changeNicknameAction.putValue(Action.NAME, Res.getString("menuitem.change.nickname")); + changeNicknameAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.TYPING_TRAY)); + if (allowNicknameChange) { + popup.add(changeNicknameAction); + } + } + + Action chatAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + String selectedUser = getSelectedUser(); + if (selectedUser == null) { + return; + } + startChat(groupChatRoom, userMap.get(Resourcepart.fromOrThrowUnchecked(selectedUser))); + } + }; + + chatAction.putValue(Action.NAME, Res.getString("menuitem.start.a.chat")); + chatAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_MESSAGE_IMAGE)); + if (!selectedMyself) { + popup.add(chatAction); + } + + Action blockAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + String user = getSelectedUser(); + ImageIcon icon; + if (groupChatRoom.isBlocked(groupJID)) { + groupChatRoom.removeBlockedUser(groupJID); + icon = getImageIcon(groupJID); + } else { + groupChatRoom.addBlockedUser(groupJID); + icon = SparkRes.getImageIcon(SparkRes.Icon.BRICKWALL_IMAGE); + } + + JLabel label = new JLabel(user, icon, SwingConstants.CENTER); + model.setElementAt(label, index); + } + }; + + blockAction.putValue(Action.NAME, Res.getString("menuitem.block.user")); + blockAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.BRICKWALL_IMAGE)); + if (!selectedMyself) { + if (groupChatRoom.isBlocked(groupJID)) { + blockAction.putValue(Action.NAME, Res.getString("menuitem.unblock.user")); + } + popup.add(blockAction); + } + + Action kickAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + kickUser(selectedUser); + } + }; + + kickAction.putValue(Action.NAME, Res.getString("menuitem.kick.user")); + kickAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_DELETE)); + if (iamModerator && !userIsAdmin && !selectedMyself) { + popup.add(kickAction); + } + + // Handle Voice Operations + Action voiceAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + if (userManager.hasVoice(groupChatRoom, selectedUser)) { + revokeVoice(selectedUser); + } else { + grantVoice(selectedUser); + } + users.sort(labelComp); + } + }; + + voiceAction.putValue(Action.NAME, Res.getString("menuitem.voice")); + voiceAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.MEGAPHONE_16x16)); + if (iamModerator && !userIsModerator && !selectedMyself) { + if (userManager.hasVoice(groupChatRoom, selectedUser)) { + voiceAction.putValue(Action.NAME, Res.getString("menuitem.revoke.voice")); + } else { + voiceAction.putValue(Action.NAME, Res.getString("menuitem.grant.voice")); + } + popup.add(voiceAction); + } + + Action banAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + banUser(selectedUser); + } + }; + banAction.putValue(Action.NAME, Res.getString("menuitem.ban.user")); + banAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.RED_FLAG_16x16)); + if (iamAdminOrOwner && !userIsModerator && !selectedMyself) { + popup.add(banAction); + } + + JMenu affiliationMenu = new JMenu(Res.getString("menuitem.affiliation")); + affiliationMenu.setIcon(SparkRes.getImageIcon(SparkRes.Icon.MODERATOR_IMAGE)); + + Action memberAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + if (!userIsMember) { + grantMember(selectedUser); + } else { + revokeMember(selectedUser); + } + users.sort(labelComp); + } + }; + memberAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.STAR_YELLOW_IMAGE)); + if (iamAdminOrOwner && !userIsMember) { + memberAction.putValue(Action.NAME, Res.getString("menuitem.grant.member")); + affiliationMenu.add(memberAction); + } else if (iamAdminOrOwner && userIsMember && !selectedMyself) { + memberAction.putValue(Action.NAME, Res.getString("menuitem.revoke.member")); + affiliationMenu.add(memberAction); + } + + + Action moderatorAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + if (!userIsModerator) { + grantModerator(selectedUser); + } else { + revokeModerator(selectedUser); + } + users.sort(labelComp); + } + }; + + moderatorAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.STAR_MODERATOR)); + + if (iamAdminOrOwner && !userIsModerator && !userIsAdmin && !userIsOwner) { + moderatorAction.putValue(Action.NAME, Res.getString("menuitem.grant.moderator")); + affiliationMenu.add(moderatorAction); + } else if (iamAdminOrOwner && userIsModerator && !selectedMyself) { + moderatorAction.putValue(Action.NAME, Res.getString("menuitem.revoke.moderator")); + affiliationMenu.add(moderatorAction); + } + + Action adminAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + if (!userIsAdmin) { + grantAdmin(selectedUser); + } else { + revokeAdmin(selectedUser); + } + users.sort(labelComp); + } + }; + adminAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.STAR_ADMIN)); + if (iamAdminOrOwner && !userIsAdmin && !userIsOwner) { + adminAction.putValue(Action.NAME, Res.getString("menuitem.grant.admin")); + affiliationMenu.add(adminAction); + } else if (iamAdminOrOwner && !selectedMyself) { + adminAction.putValue(Action.NAME, Res.getString("menuitem.revoke.admin")); + affiliationMenu.add(adminAction); + } + + + Action ownerAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + if (!userIsOwner) { + grantOwner(selectedUser); + } else { + revokeOwner(selectedUser); + } + users.sort(labelComp); + } + }; + ownerAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.STAR_OWNER)); + + if (iamOwner && !userIsOwner) { + ownerAction.putValue(Action.NAME, Res.getString("menuitem.grant.owner")); + affiliationMenu.add(ownerAction); + } else if (iamOwner && !selectedMyself) { + ownerAction.putValue(Action.NAME, Res.getString("menuitem.revoke.owner")); + affiliationMenu.add(ownerAction); + } + + if (affiliationMenu.getItemCount() > 0) { + popup.add(affiliationMenu); + } + + // Handle Unbanning of users. + Action unbanAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + String jid = ((JMenuItem) actionEvent.getSource()).getText(); + unbanUser(jid); + } + }; + + if (iamAdmin || iamOwner) { + JMenu unbanMenu = new JMenu(Res.getString("menuitem.unban")); + List bannedUsers = List.of(); + try { + bannedUsers = chat.getOutcasts(); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.error("Error loading all banned users", e); + } + + for (Affiliate bannedUser : bannedUsers) { + ImageIcon icon = SparkRes.getImageIcon(SparkRes.Icon.RED_BALL); + JMenuItem bannedItem = new JMenuItem(bannedUser.getJid().toString(), icon); + unbanMenu.add(bannedItem); + bannedItem.addActionListener(unbanAction); + } + if (unbanMenu.getMenuComponentCount() > 0) { + popup.add(unbanMenu); + } + } + } + + Action inviteAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + ConferenceUtils.inviteUsersToRoom(groupChatRoom.getMultiUserChat(), null, false); + } + }; + + inviteAction.putValue(Action.NAME, Res.getString("menuitem.invite.users")); + inviteAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.CONFERENCE_IMAGE_16x16)); + + if (index != -1) { + popup.addSeparator(); + } + popup.add(inviteAction); + + Action copyUriGroupChat = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + SparkManager.setClipboard("xmpp:" + chat.getRoom() + "?join"); + } + }; + + copyUriGroupChat.putValue(Action.NAME, Res.getString("button.copy.to.clipboard")); + copyUriGroupChat.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.COPY_16x16)); + popup.add(copyUriGroupChat); + + popup.show(participantsList, evt.getX(), evt.getY()); + } + + public void setNicknameChangeAllowed(boolean allowed) { + allowNicknameChange = allowed; + } + + public int getIndex(CharSequence name) { + for (int i = 0; i < model.getSize(); i++) { + JLabel label = model.getElementAt(i); + if (label.getText().equals(name.toString())) { + return i; + } + } + return -1; + } + + /** + * Removes a user from the participant list based on their displayed name. + * + * @param displayName the users displayed name to remove. + */ + public synchronized void removeUser(CharSequence displayName) { + try { + for (int i = 0; i < users.size(); i++) { + JLabel label = users.get(i); + if (label.getText().equals(displayName.toString())) { + users.remove(label); + model.removeElement(label); + } + } + + for (int i = 0; i < model.size(); i++) { + JLabel label = model.getElementAt(i); + if (label.getText().equals(displayName.toString())) { + users.remove(label); + model.removeElement(label); + } + } + } catch (Exception e) { + Log.error(e); + } + } + + /** + * Adds a new user to the participant list. + * + * @param userIcon the icon to use initially. + * @param nickname the users nickname. + */ + public synchronized void addUser(Icon userIcon, Resourcepart nickname) { + try { + final JLabel user = new JLabel(nickname.toString(), userIcon, SwingConstants.CENTER); + user.setForeground(groupChatRoom.getUserColor(nickname)); + users.add(user); + // Sort users alpha. + users.sort(labelComp); + // Add to the correct position in the model. + final int index = users.indexOf(user); + model.insertElementAt(user, index); + } catch (Exception e) { + Log.error(e); + } + } + + /** + * Sorts ContactItems. + */ + final Comparator labelComp = new Comparator<>() { + @Override + public int compare(JLabel item1, JLabel item2) { + if (pref.isShowingRoleIcons()) { + return compareWithRole(item1, item2); + } else { + return compareWithoutRole(item1.getText(), item2.getText()); + } + } + + private int compareWithoutRole(String s1, String s2) { + return s1.compareToIgnoreCase(s2); + } + + /** + * Compares 2 items by their Role and Affiliation
      + * affiliation > role
      + * owner > admin > moderator > member > participant > visitor + * + * @return -1, 0 or 1 + */ + private int compareWithRole(JLabel item1, JLabel item2) { + int user1 = 100; + int user2 = 100; + try { + // append Room-JID to UserLabel + Resourcepart nick1 = Resourcepart.from(item1.getText()); + Resourcepart nick2 = Resourcepart.from(item2.getText()); + EntityFullJid jid1 = JidCreate.entityFullFrom(chat.getRoom(), nick1); + EntityFullJid jid2 = JidCreate.entityFullFrom(chat.getRoom(), nick2); + user1 = getCompareValue(jid1); + user2 = getCompareValue(jid2); + } catch (Exception e) { + //FIXME Sometimes there is no Occupant with that jid, dunno why + } + + int result = 0; + if (user1 == user2) { + result = compareWithoutRole(item1.getText(), item2.getText()); + } else { + // a=owner,b=admin, m=moderator, n=member , p=participant, v=visitor + // a < b < m < n < p < v + if (user1 < user2) + result = -1; + if (user1 > user2) + result = 1; + } + return result; + } + }; + + /** + * check if we have an affiliation to this room
      + * and map it to an integer
      + * 0=owner,1=admin.....5=visitor
      + */ + private int getCompareValue(EntityFullJid jid) { + MUCRole role = usersToRoles.get(jid); + MUCAffiliation affiliation = usersToAffiliation.get(jid); + switch (affiliation) { + case owner: + return 0; + case admin: + return 1; + case member: + return (role == MUCRole.moderator ? 2 : 3); + case none: + switch (role) { + case moderator: + return 2; + case participant: + return 4; + case visitor: + return 5; + default: + return 100; + } + default: + return 100; + } + } + + /** + * The ParticipantRenderer is an implementation of + * ListCellRenderer to add icons w/ associated text in JComboBox and JList. + */ + public static class ParticipantRenderer extends JLabel implements ListCellRenderer { + public ParticipantRenderer() { + setOpaque(true); + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) { + JLabel label = (JLabel) value; + if (isSelected) { + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + } else { + setBackground(label.getBackground()); + setForeground(label.getForeground()); + } + setText(label.getText()); + setIcon(label.getIcon()); + return this; + } + } + + protected GroupChatRoom getGroupChatRoom() { + return groupChatRoom; + } + + protected ImageTitlePanel getAgentInfoPanel() { + return agentInfoPanel; + } + + protected MultiUserChat getChat() { + return chat; + } + + protected Map getUserMap() { + return userMap; + } + + protected DefaultListModel getModel() { + return model; + } + + protected JXList getParticipantsList() { + return participantsList; + } + + protected PresenceListener getListener() { + return listener; + } + + protected Map getInvitees() { + return invitees; + } + + protected boolean isAllowNicknameChange() { + return allowNicknameChange; + } + + protected DiscoverInfo getRoomInformation() { + return roomInformation; + } + + protected List getUsers() { + return users; + } + + protected Comparator getLabelComp() { + return labelComp; + } + + private class ChangeNicknameAction extends AbstractAction { + @Override + public void actionPerformed(ActionEvent actionEvent) { + // retry to change nickname + while (true) { + String newNickname = JOptionPane.showInputDialog(groupChatRoom, + Res.getString("label.new.nickname") + ":", + Res.getString("title.change.nickname"), + JOptionPane.QUESTION_MESSAGE); + if (isBlank(newNickname)) { + return; + } + newNickname = newNickname.trim(); + Resourcepart newNicknameResourcepart = Resourcepart.fromOrNull(newNickname); + if (newNicknameResourcepart == null) { + // retry + continue; + } + String nick = chat.getNickname().toString(); + try { + chat.changeNickname(newNicknameResourcepart); + return; + } catch (XMPPException.XMPPErrorException xmppError) { + switch (xmppError.getStanzaError().getCondition()) { + case not_acceptable: + // handle deny changing nick. + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(groupChatRoom, + Res.getString("message.nickname.not.acceptable"), + Res.getString("title.change.nickname"), + JOptionPane.ERROR_MESSAGE); + return; + case conflict: + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(groupChatRoom, + Res.getString("message.nickname.in.use"), + Res.getString("title.change.nickname"), + JOptionPane.ERROR_MESSAGE); + break; + default: + Log.error("Error changing nickname", xmppError); + return; + } + } catch (SmackException | InterruptedException e1) { + Log.error("Error changing nickname", e1); + return; + } + } + } + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/GroupChatRoomListener.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/GroupChatRoomListener.java new file mode 100644 index 000000000..bb5e08134 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/GroupChatRoomListener.java @@ -0,0 +1,75 @@ +/** + * Copyright (C) 2004-2013 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.conferences; + +import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jivesoftware.smackx.muc.UserStatusListener; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomListener; +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jxmpp.jid.Jid; + +/** + * This listener is notified for every group chat room. + * The affected chat room is sent as parameter in every method. + * Keeping such listener tied to a group chat room instance + * is wrong because all listeners will be notified when someone joins a particular chat room for example + */ +public class GroupChatRoomListener implements ChatRoomListener { + @Override + public void chatRoomOpened(ChatRoom room) { + if (!(room instanceof GroupChatRoom)) { + return; + } + GroupChatRoom groupChatRoom = (GroupChatRoom) room; + MultiUserChat chat = groupChatRoom.getMultiUserChat(); + chat.addUserStatusListener(new UserStatusListener() { + }); + } + + @Override + public void chatRoomLeft(ChatRoom room) { + if (!(room instanceof GroupChatRoom)) { + return; + } + GroupChatRoom groupChatRoom = (GroupChatRoom) room; + groupChatRoom.getConferenceRoomInfo().getAgentInfoPanel().setVisible(false); + } + + @Override + public void chatRoomClosed(ChatRoom room) { + if (!(room instanceof GroupChatRoom)) { + return; + } + GroupChatRoom groupChatRoom = (GroupChatRoom) room; + MultiUserChat chat = groupChatRoom.getMultiUserChat(); + chat.removeParticipantListener(groupChatRoom.getConferenceRoomInfo().getListener()); + } + + @Override + public void userHasLeft(ChatRoom room, String userid) { + if (!(room instanceof GroupChatRoom)) { + return; + } + GroupChatRoom groupChatRoom = (GroupChatRoom) room; + int index = groupChatRoom.getConferenceRoomInfo().getIndex(userid); + if (index != -1) { + groupChatRoom.getConferenceRoomInfo().removeUser(userid); + groupChatRoom.getConferenceRoomInfo().getUserMap().remove(userid); + } + } + +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/InvitationDialog.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/InvitationDialog.java new file mode 100644 index 000000000..d0c5683c4 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/InvitationDialog.java @@ -0,0 +1,396 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.conferences; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smackx.bookmarks.BookmarkedConference; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.ChatNotFoundException; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.TitlePanel; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.RosterPickList; +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; +import org.jxmpp.util.XmppStringUtils; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.UIManager; + +import java.awt.BorderLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Invite To conference dialog + */ +final class InvitationDialog extends JPanel { + private JTextField textRoomsField; + private JComboBox comboRoomsField; + + private final JTextField messageField = new JTextField(); + private final DefaultListModel invitedUsers = new DefaultListModel<>(); + private final JList invitedUserList = new JList<>(invitedUsers); + private final LocalPreferences pref = SettingsManager.getLocalPreferences(); + + private JDialog dlg; + + public InvitationDialog(boolean adhoc) { + JComponent roomsField; + if (adhoc) { + roomsField = new JTextField(); + textRoomsField = (JTextField) roomsField; + } else { + roomsField = new JComboBox<>(); + comboRoomsField = (JComboBox) roomsField; + comboRoomsField.setEditable(true); + comboRoomsField.addActionListener(e -> { + // get selected bookmark and persist it: + ConferenceItem bookmarkedConfItem = (ConferenceItem) comboRoomsField.getSelectedItem(); + if (bookmarkedConfItem != null) { + BookmarkedConference bookmarkedConf = bookmarkedConfItem.getBookmarkedConf(); + pref.setDefaultBookmarkedConf(bookmarkedConf.getJid()); + } + }); + } + GridBagLayout gridBagLayout1 = new GridBagLayout(); + setLayout(gridBagLayout1); + + JLabel roomsLabel = new JLabel(); + add(roomsLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(roomsField, new GridBagConstraints(1, 0, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + JLabel messageLabel = new JLabel(); + add(messageLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(messageField, new GridBagConstraints(1, 1, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + JLabel jidLabel = new JLabel(); + final JTextField jidField = new JTextField(); + JButton addJIDButton = new JButton(); + JButton browseButton = new JButton(); + ResourceUtils.resButton(addJIDButton, Res.getString("button.add")); + ResourceUtils.resButton(browseButton, Res.getString("button.roster")); + ResourceUtils.resLabel(jidLabel, jidField, Res.getString("label.add.jid")); + + add(jidLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + add(jidField, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + add(addJIDButton, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(browseButton, new GridBagConstraints(3, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + + addJIDButton.addActionListener(actionEvent -> { + String jid = jidField.getText(); + String server = XmppStringUtils.parseBareJid(jid); + if (server == null || !server.contains("@")) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(dlg, Res.getString("message.enter.valid.jid"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + jidField.setText(""); + jidField.requestFocus(); + } else { + if (!invitedUsers.contains(jid)) { + invitedUsers.addElement(jid); + } + jidField.setText(""); + } + }); + + browseButton.addActionListener(actionEvent -> { + RosterPickList browser = new RosterPickList(); + Collection col = browser.showRoster(dlg); + for (String aCol : col) { + if (!invitedUsers.contains(aCol)) { + invitedUsers.addElement(aCol); + } + } + }); + + JLabel inviteLabel = new JLabel(); + add(inviteLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + add(new JScrollPane(invitedUserList), new GridBagConstraints(1, 3, 3, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); + + // Add Resource Utils + ResourceUtils.resLabel(messageLabel, messageField, Res.getString("label.message") + ":"); + ResourceUtils.resLabel(roomsLabel, roomsField, Res.getString("label.room") + ":"); + inviteLabel.setText(Res.getString("label.invited.users")); + + messageField.setText(Res.getString("message.please.join.in.conference")); + + // Add Listener to list + invitedUserList.addMouseListener(new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent mouseEvent) { + if (!mouseEvent.isPopupTrigger()) { + return; + } + showPopup(mouseEvent); + } + + @Override + public void mousePressed(MouseEvent mouseEvent) { + if (!mouseEvent.isPopupTrigger()) { + return; + } + showPopup(mouseEvent); + } + }); + } + + private void showPopup(MouseEvent e) { + final JPopupMenu popup = new JPopupMenu(); + final int index = invitedUserList.locationToIndex(e.getPoint()); + + Action removeAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + invitedUsers.remove(index); + } + }; + + removeAction.putValue(Action.NAME, Res.getString("menuitem.remove")); + removeAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_DELETE)); + + popup.add(removeAction); + popup.show(invitedUserList, e.getX(), e.getY()); + } + + private void fillRoomsUI(List rooms, EntityBareJid adHocRoomName) { + if (textRoomsField != null) { + textRoomsField.setText(adHocRoomName.toString()); + } + if (comboRoomsField != null) { + // comboRoomsField.setSelectedIndex(-1); + ConferenceItem bookmarkedConf = null; + final EntityBareJid bookmarkedConfJid = pref.getDefaultBookmarkedConf(); + + // Add conference rooms to the combobox + for (BookmarkedConference room : rooms) { + final ConferenceItem ci = new ConferenceItem(room); + if (bookmarkedConfJid != null && bookmarkedConfJid.equals(ci.getBookmarkedConf().getJid())) { + bookmarkedConf = ci; + } + comboRoomsField.addItem(ci); + } + if (bookmarkedConf != null) { + comboRoomsField.setSelectedItem(bookmarkedConf); + } + } + } + + /** + * Return selected room name from text or combo box + */ + private String getSelectedRoomName() { + String roomTitle = null; + if (textRoomsField != null) { + roomTitle = textRoomsField.getText(); + } + if (comboRoomsField != null) { + roomTitle = comboRoomsField.getSelectedItem().toString(); + } + return roomTitle; + } + + private BookmarkedConference getSelectedBookmarkedConference() { + if (comboRoomsField != null) { + ConferenceItem bookmarkedConfItem = (ConferenceItem) comboRoomsField.getSelectedItem(); + if (bookmarkedConfItem != null) { + return bookmarkedConfItem.getBookmarkedConf(); + } + } + return null; + } + + public void inviteUsersToRoom(final DomainBareJid serviceName, List rooms, EntityBareJid adHocRoomName, Collection jids) { + fillRoomsUI(rooms, adHocRoomName); + JFrame parent = SparkManager.getChatManager().getChatContainer().getChatFrame(); + if (parent == null || !parent.isVisible()) { + parent = SparkManager.getMainWindow(); + } + + // Add jids to user list + if (jids != null) { + for (Jid jid : jids) { + invitedUsers.addElement(jid.toString()); + } + } + + // Create the title panel for this dialog + TitlePanel titlePanel = new TitlePanel(Res.getString("title.invite.to.conference"), Res.getString("message.invite.users.to.conference"), SparkRes.getImageIcon(SparkRes.Icon.BLANK_IMAGE), true); + + // Construct main panel w/ layout. + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BorderLayout()); + mainPanel.add(titlePanel, BorderLayout.NORTH); + + // The user should only be able to close this dialog. + Object[] options = {Res.getString("invite"), Res.getString("cancel")}; + final JOptionPane pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); + mainPanel.add(pane, BorderLayout.CENTER); + + final JOptionPane p = new JOptionPane(); + dlg = p.createDialog(parent, Res.getString("title.conference.rooms")); + dlg.setModal(false); + + dlg.pack(); + dlg.setSize(500, 450); + dlg.setResizable(true); + dlg.setContentPane(mainPanel); + dlg.setLocationRelativeTo(parent); + + PropertyChangeListener changeListener = e -> { + String value = (String) pane.getValue(); + if (Res.getString("cancel").equals(value)) { + pane.setValue(JOptionPane.UNINITIALIZED_VALUE); + dlg.dispose(); + } else if (Res.getString("invite").equals(value)) { + final String roomTitle = getSelectedRoomName(); + final BookmarkedConference selectedBookmarkedConf = getSelectedBookmarkedConference(); + int size = invitedUserList.getModel().getSize(); + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + if (size == 0) { + JOptionPane.showMessageDialog(dlg, Res.getString("message.specify.users.to.join.conference"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + pane.setValue(JOptionPane.UNINITIALIZED_VALUE); + return; + } + if (!ModelUtil.hasLength(roomTitle)) { + JOptionPane.showMessageDialog(dlg, Res.getString("message.no.room.to.join.error"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + pane.setValue(JOptionPane.UNINITIALIZED_VALUE); + return; + } + EntityBareJid roomName = null; + + // Add all rooms the user is in to list. + ChatManager chatManager = SparkManager.getChatManager(); + for (ChatRoom chatRoom : chatManager.getChatContainer().getChatRooms()) { + if (chatRoom instanceof GroupChatRoom) { + GroupChatRoom groupRoom = (GroupChatRoom) chatRoom; + if (groupRoom.getBareJid().equals(roomTitle)) { + roomName = groupRoom.getMultiUserChat().getRoom(); + break; + } + } + } + String message = messageField.getText(); + final String messageText = message != null ? message : Res.getString("message.please.join.in.conference"); + if (invitedUsers.getSize() > 0) { + invitedUserList.setSelectionInterval(0, invitedUsers.getSize() - 1); + } + + GroupChatRoom chatRoom; + try { + chatRoom = SparkManager.getChatManager().getGroupChat(roomName); + } catch (ChatNotFoundException e1) { + dlg.setVisible(false); + final List jidList = new ArrayList<>(); + for (String entityBareJidString : invitedUserList.getSelectedValuesList()) { + try { + EntityBareJid entityBareJid = JidCreate.entityBareFromUnescaped(entityBareJidString); + jidList.add(entityBareJid); + } catch (NullPointerException | XmppStringprepException ee) { + Log.error(ee); + } + } + + SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + try { + Thread.sleep(15); + } catch (InterruptedException ignored) { + } + return "ok"; + } + + @Override + public void finished() { + try { + if (selectedBookmarkedConf == null) { + ConferenceUtils.createPrivateConference(serviceName, messageText, roomTitle, jidList); + } else { + ConferenceUtils.joinConferenceOnSeparateThread( + selectedBookmarkedConf.getName(), selectedBookmarkedConf.getJid(), + selectedBookmarkedConf.getNickname(), selectedBookmarkedConf.getPassword(), + messageText, jidList); + } + } catch (SmackException | InterruptedException ex) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(pane, "An error occurred.", Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + } + } + }; + + worker.start(); + pane.setValue(JOptionPane.UNINITIALIZED_VALUE); + return; + } + + pane.setValue(JOptionPane.UNINITIALIZED_VALUE); + dlg.dispose(); + + Object[] values = invitedUserList.getSelectedValuesList().toArray(); + for (Object o : values) { + String jidString = (String) o; + try { + EntityBareJid jid = JidCreate.entityBareFromUnescaped(jidString); + chatRoom.getMultiUserChat().invite(jid, message != null ? message : Res.getString("message.please.join.in.conference")); + String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid); + chatRoom.getTranscriptWindow().insertNotificationMessage("Invited " + nickname, ChatManager.NOTIFICATION_COLOR); + } catch (SmackException.NotConnectedException | XmppStringprepException | InterruptedException e1) { + Log.warning("Unable to send stanza to " + jidString, e1); + } + } + } + }; + pane.addPropertyChangeListener(changeListener); + + dlg.setVisible(true); + dlg.toFront(); + dlg.requestFocus(); + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/InviteSwingWorker.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/InviteSwingWorker.java new file mode 100644 index 000000000..bdaf0bd98 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/InviteSwingWorker.java @@ -0,0 +1,81 @@ +package org.jivesoftware.spark.ui.conferences; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jivesoftware.smackx.muc.MultiUserChatManager; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomNotFoundException; +import org.jivesoftware.spark.ui.TranscriptWindow; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.EntityBareJid; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * An executable that causes invitations to be sent, asking JIDs to join a chat room. + * + * @author Guus der Kinderen, guus.der.kinderen@gmail.com + */ +public class InviteSwingWorker extends SwingWorker +{ + private final EntityBareJid roomJID; + private final Collection invitees; + private final String invitation; + + public InviteSwingWorker( EntityBareJid roomJID, Collection invitees, String invitation ) + { + this.roomJID = roomJID; + this.invitees = ( invitees == null ? Collections.emptySet() : invitees); + this.invitation = invitation; + } + + @Override + public Object construct() + { + final Set invitedJIDs = new HashSet<>(invitees.size()); + MultiUserChatManager mucManager = SparkManager.getMucManager(); + MultiUserChat groupChat = mucManager.getMultiUserChat(roomJID); + // Send invitations + for ( final EntityBareJid jid : invitees) + { + try + { + if (invitedJIDs.add(jid)) { + groupChat.invite(jid, invitation); + } + } + catch ( SmackException.NotConnectedException | InterruptedException e ) + { + Log.warning( "Unable to invite " + jid + " to " + roomJID, e ); + } + } + return invitedJIDs; + } + + @Override + public void finished() + { + final EntityBareJid roomName = roomJID; + try + { + final ChatRoom room = SparkManager.getChatManager().getChatContainer().getChatRoom( roomName ); + final TranscriptWindow transcriptWindow = room.getTranscriptWindow(); + for ( final EntityBareJid jid : (Set) getValue() ) + { + final String notification = Res.getString( "message.waiting.for.user.to.join", jid ); + transcriptWindow.insertNotificationMessage( notification, ChatManager.NOTIFICATION_COLOR ); + } + } + catch ( ChatRoomNotFoundException e ) + { + Log.error( "Unable to identify chat room tab by name: " + roomName ); + } + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/JoinConferenceRoomDialog.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/JoinConferenceRoomDialog.java new file mode 100644 index 000000000..4f9f10e9e --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/JoinConferenceRoomDialog.java @@ -0,0 +1,118 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.conferences; + +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.resource.Res; +import org.jivesoftware.smackx.muc.RoomInfo; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.TitlePanel; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.EntityBareJid; + +import java.awt.BorderLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.beans.PropertyChangeListener; + +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JTextField; + +final class JoinConferenceRoomDialog extends JPanel { + private final JLabel passwordLabel = new JLabel(); + private final JPasswordField passwordField = new JPasswordField(); + private final JTextField nicknameField = new JTextField(); + private final JLabel roomNameDescription = new JLabel(); + private final LocalPreferences pref = SettingsManager.getLocalPreferences(); + + public JoinConferenceRoomDialog() { + GridBagLayout gridBagLayout1 = new GridBagLayout(); + setLayout(gridBagLayout1); + add(nicknameField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + add(passwordField, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + add(passwordLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + JLabel nicknameLabel = new JLabel(); + add(nicknameLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + JLabel roomNameLabel = new JLabel(); + add(roomNameLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(roomNameDescription, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + add(new JLabel(), new GridBagConstraints(0, 3, 2, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.VERTICAL, new Insets(5, 5, 5, 5), 0, 0)); + + // Add Resource Utils + ResourceUtils.resLabel(nicknameLabel, nicknameField, Res.getString("label.nickname") + ":"); + ResourceUtils.resLabel(passwordLabel, passwordField, Res.getString("label.password") + ":"); + + roomNameLabel.setText(Res.getString("room.name") + ":"); + } + + public void joinRoom(EntityBareJid roomJID, RoomInfo roomInfo) { + // Set default nickname + nicknameField.setText(pref.getNickname().toString()); + // Enable the password field if a password is required + boolean requiresPassword = roomInfo.isPasswordProtected(); + passwordField.setVisible(requiresPassword); + passwordLabel.setVisible(requiresPassword); + String roomName = roomInfo.getName() != null ? roomInfo.getName() : roomJID.getLocalpart().asUnescapedString(); + roomNameDescription.setText(roomName); + + // Create the title panel for this dialog + TitlePanel titlePanel = new TitlePanel(Res.getString("title.join.conference.room"), Res.getString("message.specify.information.for.conference"), SparkRes.getImageIcon(SparkRes.Icon.BLANK_IMAGE), true); + + // Construct main panel w/ layout. + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BorderLayout()); + mainPanel.add(titlePanel, BorderLayout.NORTH); + + // The user should only be able to close this dialog. + Object[] options = {Res.getString("join"), Res.getString("cancel")}; + final JOptionPane pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); + mainPanel.add(pane, BorderLayout.CENTER); + final JOptionPane p = new JOptionPane(); + + final JDialog dlg = p.createDialog(SparkManager.getMainWindow(), Res.getString("title.conference.rooms")); + dlg.setModal(false); + + dlg.pack(); + dlg.setSize(350, 250); + dlg.setResizable(true); + dlg.setContentPane(mainPanel); + dlg.setLocationRelativeTo(SparkManager.getMainWindow()); + + PropertyChangeListener changeListener = e -> { + String value = (String) pane.getValue(); + if (Res.getString("cancel").equals(value)) { + pane.setValue(JOptionPane.UNINITIALIZED_VALUE); + dlg.dispose(); + } else if (Res.getString("join").equals(value)) { + pane.setValue(JOptionPane.UNINITIALIZED_VALUE); + dlg.dispose(); + ConferenceUtils.joinConferenceOnSeparateThread(roomName, roomJID, null, null); + } + }; + pane.addPropertyChangeListener(changeListener); + + dlg.setVisible(true); + dlg.toFront(); + dlg.requestFocus(); + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/JoinRoomSwingWorker.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/JoinRoomSwingWorker.java new file mode 100644 index 000000000..3f7bcbedd --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/JoinRoomSwingWorker.java @@ -0,0 +1,258 @@ +package org.jivesoftware.spark.ui.conferences; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.SmackConfiguration; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.PresenceBuilder; +import org.jivesoftware.smack.packet.StandardExtensionElement; +import org.jivesoftware.smack.packet.StanzaError; +import org.jivesoftware.smackx.muc.MucEnterConfiguration; +import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jivesoftware.smackx.muc.MultiUserChatManager; +import org.jivesoftware.smackx.muc.RoomInfo; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.ChatContainer; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomNotFoundException; +import org.jivesoftware.spark.ui.RequestFocusListener; +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.UIComponentRegistry; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.profile.VCardManager; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.parts.Resourcepart; +import org.jxmpp.stringprep.XmppStringprepException; + +import javax.swing.*; +import java.awt.*; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +/** + * An executable that makes the user join a room. + * + * When no password is provided, and the room to be joined is determined to be password protected, a password dialog + * will be presented. + * + * The user will join the room using the nickname as saved in the local preferences, unless explicitly overridden in + * the constructor. + * + * An optional 'follow-up' action can be registered. When such a follow-up is registered, it shall be executed, + * asynchronously, after the room was successfully joined. + * + * @author Guus der Kinderen, guus.der.kinderen@gmail.com + */ +public class JoinRoomSwingWorker extends SwingWorker +{ + private final List errors = new ArrayList<>(); + private final EntityBareJid roomJID; + private Resourcepart nickname; + private String password; + private final String tabTitle; + private MultiUserChat groupChat; + private SwingWorker followUp; + private final LocalPreferences pref = SettingsManager.getLocalPreferences(); + + public JoinRoomSwingWorker( EntityBareJid roomJID, Resourcepart nickname, String password, String tabTitle ) + { + this.roomJID = roomJID; + this.nickname = nickname; + this.password = password; + this.tabTitle = tabTitle; + } + + /** + * Set a follow-up action, to be executed upon successful join of the room. + * + * Not that a follow-up must be set, before this instance of JoinRoomSwingWorker is started. + * + * @param followUp a follow-up action (can be null). + */ + public void setFollowUp( SwingWorker followUp ) + { + this.followUp = followUp; + } + + @Override + public Object construct() + { + // A SwingWorker by definition is to be used to offload operations from the Event Dispatcher Thread. + if (SmackConfiguration.DEBUG && EventQueue.isDispatchThread()) { + throw new IllegalStateException("Must NOT be called on the Event Dispatcher Thread (but was)"); + } + + try + { + Log.debug("Joining chat room " + roomJID); + MultiUserChatManager mucManager = SparkManager.getMucManager(); + groupChat = mucManager.getMultiUserChat( roomJID ); + RoomInfo roomInfo = mucManager.getRoomInfo(roomJID); + Log.debug("... got groupchat for " + roomJID); + boolean passwordRequired = roomInfo.isPasswordProtected(); + Log.debug("... password required for " + roomJID + ": " + passwordRequired); + + // Use the default nickname, if none has been provided. + if ( nickname == null ) + { + nickname = pref.getNickname(); + } + + AtomicReference roomUIObject = new AtomicReference<>(); + // Create a UI component, if one was not yet created. It is important that this happens before the MUC is + // joined server-side, as the UI component needs to be able to display data that is sent by the server upon + // joining the room. + ChatRoom room; + try { + room = SparkManager.getChatManager().getChatContainer().getChatRoom(groupChat.getRoom()); + } catch (ChatRoomNotFoundException e) { + room = UIComponentRegistry.createGroupChatRoom(groupChat); + ((GroupChatRoom) room).setPassword(password); + ((GroupChatRoom) room).setTabTitle(tabTitle); + } + roomUIObject.set(room); + Log.debug("... created UI object for " + roomJID); + if ( !groupChat.isJoined() ) { + // Join the MUC server-sided, if we're not already in. + if (password == null && passwordRequired) { + EventQueue.invokeAndWait(() -> { + JLabel label = new JLabel(Res.getString("message.enter.room.password")); + JPasswordField passwordField = new JPasswordField(); + passwordField.addAncestorListener(new RequestFocusListener()); + JOptionPane.showConfirmDialog(null, new Object[]{label, passwordField}, Res.getString("title.password.required"), JOptionPane.OK_CANCEL_OPTION); + password = new String(passwordField.getPassword()); + }); + + if (!ModelUtil.hasLength(password)) { + return null; + } + } + AtomicBoolean wontJoin = new AtomicBoolean(false); + EventQueue.invokeLater(() -> { + if (!ConferenceUtils.confirmToRevealVisibility()) { + wontJoin.set(true); + } + }); + if (wontJoin.get()) { + return null; + } + } + if ( !groupChat.isJoined() ) { + Log.debug("Start server-sided join of chat room " + roomJID); + groupChat.join(getMucEnterConfiguration(groupChat, nickname, password)); + Log.debug("Joined chat room " + roomJID + " on the server."); + } + return roomUIObject.get(); + } + catch ( XMPPException | SmackException | InterruptedException | InvocationTargetException ex ) + { + Log.error( "An exception occurred while trying to join room '" + roomJID + "'.", ex ); + StanzaError error = null; + if ( ex instanceof XMPPException.XMPPErrorException ) + { + error = ( (XMPPException.XMPPErrorException) ex ).getStanzaError(); + AtomicReference retryAttemptResult = new AtomicReference<>(); + if (StanzaError.Condition.conflict == error.getCondition()) + { + try { + EventQueue.invokeAndWait(() -> { + final Object userInput = JOptionPane.showInputDialog( + SparkManager.getMainWindow(), + Res.getString( "message.nickname.in.use" ), + Res.getString( "title.change.nickname" ), + JOptionPane.WARNING_MESSAGE, + null, + null, // null selection values implies text field. + nickname + ); + + if ( userInput != null ) + { + Log.debug( "Retry joining room '" + roomJID + "', using nickname: " + userInput ); + this.nickname = Resourcepart.fromOrThrowUnchecked((String) userInput); + retryAttemptResult.set(construct()); + } + }); + } catch (InterruptedException | InvocationTargetException e) { + Log.error( "An exception occurred while trying to join room '" + roomJID + "' in the retry attempt. Giving up.", ex ); + } + return retryAttemptResult; + } + } + + final String errorText = ConferenceUtils.getReason( error ); + errors.add( errorText ); + return null; + } + } + + public static MucEnterConfiguration getMucEnterConfiguration(final MultiUserChat groupChat, final Resourcepart nickname, final String password) + { + final MucEnterConfiguration.Builder builder = groupChat.getEnterConfigurationBuilder(nickname); + if ( ModelUtil.hasLength( password ) ) + { + builder.withPassword(password); + } + + if (SparkManager.getVCardManager().getVCard() != null && SparkManager.getVCardManager().getVCard().getAvatarHash() != null) { + final String hash = SparkManager.getVCardManager().getVCard().getAvatarHash(); + builder.withPresence( presenceBuilder -> presenceBuilder + .addExtension( + StandardExtensionElement.builder("x", "vcard-temp:x:update") + .addElement("photo", hash) + .build() + ) + .addExtension( + StandardExtensionElement.builder("x", "jabber:x:avatar") + .addElement("hash", hash) + .build() + ) + ); + } + return builder.build(); + } + + @Override + public void finished() + { + UIManager.put( "OptionPane.okButtonText", Res.getString( "ok" ) ); + if (!errors.isEmpty()) + { + String error = errors.get( 0 ); + final String style = "width: 300px;"; + String body = "

      "+ roomJID + ": " + Res.getString("message.error.unable.join.room") +"

      " + error + "

      "; + JOptionPane.showMessageDialog( SparkManager.getMainWindow(), body, Res.getString("message.error.unable.join.room"), JOptionPane.ERROR_MESSAGE ); + } + else if ( groupChat.isJoined() && getValue() != null ) + { + Log.debug("Activating chat room that we just joined"); + final ChatRoom room = (ChatRoom) getValue(); + ConferenceUtils.changePresenceToAvailableIfInvisible(); + final ChatContainer container = SparkManager.getChatManager().getChatContainer(); + if ( !container.getChatRooms().contains( room ) ) + { + container.addChatRoom( room ); + } + container.activateChatRoom( room ); + Log.debug("Activated chat room that we just joined"); + + if ( followUp != null ) + { + Log.debug("Starting chat room join follow-up"); + followUp.start(); + } + } + else + { + JOptionPane.showMessageDialog( SparkManager.getMainWindow(), Res.getString("message.error.unable.join.room"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE ); + } + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/RoomBrowser.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/RoomBrowser.java new file mode 100644 index 000000000..31d39aaee --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/RoomBrowser.java @@ -0,0 +1,181 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.conferences; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; +import org.jivesoftware.smackx.muc.MultiUserChatManager; +import org.jivesoftware.smackx.muc.RoomInfo; +import org.jivesoftware.smackx.disco.packet.DiscoverItems; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.JiveTreeCellRenderer; +import org.jivesoftware.spark.component.JiveTreeNode; +import org.jivesoftware.spark.component.TitlePanel; +import org.jivesoftware.spark.component.Tree; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; + +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.beans.PropertyChangeListener; + +/** + * View room information dialog + */ +public class RoomBrowser extends JPanel { + private final JLabel descriptionValue = new JLabel(); + private final JLabel subjectValue = new JLabel(); + private final JLabel occupantsValue = new JLabel(); + private final JLabel roomNameValue = new JLabel(); + + private final JiveTreeNode rootNode; + private final Tree tree; + + public RoomBrowser() { + JLabel descriptionLabel = new JLabel(); + descriptionLabel.setText(Res.getString("description") + ":"); + JLabel subjectLabel = new JLabel(); + subjectLabel.setText(Res.getString("subject") + ":"); + JLabel occupantsLabel = new JLabel(); + occupantsLabel.setText(Res.getString("occupants") + ":"); + JLabel roomNameLabel = new JLabel(); + roomNameLabel.setText(Res.getString("room.name") + ":"); + + // Add labels to UI + setLayout(new GridBagLayout()); + add(descriptionLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(descriptionValue, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + add(subjectLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(subjectValue, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + add(occupantsLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(occupantsValue, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + add(roomNameLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(roomNameValue, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + rootNode = new JiveTreeNode(Res.getString("tree.users.in.room"), true); + tree = new Tree(rootNode); + + add(tree, new GridBagConstraints(0, 4, 2, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); + setBackground(Color.white); + tree.setCellRenderer(new JiveTreeCellRenderer()); + } + + public void displayRoomInformation(final EntityBareJid roomJID) { + SwingWorker worker = new SwingWorker() { + RoomInfo roomInfo = null; + DiscoverItems items = null; + + @Override + public Object construct() { + try { + MultiUserChatManager mucManager = SparkManager.getMucManager(); + roomInfo = mucManager.getRoomInfo(roomJID); + ServiceDiscoveryManager discoManager = SparkManager.getDiscoManager(); + items = discoManager.discoverItems(roomJID); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + } + return "ok"; + } + + @Override + public void finished() { + setupRoomInformationUI(roomJID, roomInfo, items); + } + }; + + worker.start(); + } + + private void setupRoomInformationUI(EntityBareJid roomJID, final RoomInfo roomInfo, final DiscoverItems items) { + descriptionValue.setText(Res.getString("message.no.description.available")); + subjectValue.setText(Res.getString("message.no.subject.available")); + occupantsValue.setText(""); + roomNameValue.setText(""); + try { + descriptionValue.setText(roomInfo.getDescription()); + subjectValue.setText(roomInfo.getSubject()); + + if (roomInfo.getOccupantsCount() == -1) { + occupantsValue.setText(""); + } else { + occupantsValue.setText(Integer.toString(roomInfo.getOccupantsCount())); + } + roomNameValue.setText(roomInfo.getRoom().toString()); + + for (DiscoverItems.Item item : items.getItems()) { + Jid jid = item.getEntityID(); + rootNode.add(new JiveTreeNode(jid.toString(), false, SparkRes.getImageIcon(SparkRes.Icon.SMALL_USER1_INFORMATION))); + } + tree.expandRow(0); + } catch (Exception e) { + Log.error(e); + } + + // Create the title panel for this dialog + TitlePanel titlePanel = new TitlePanel(Res.getString("title.view.room.information"), Res.getString("message.room.information.for", roomJID), SparkRes.getImageIcon(SparkRes.Icon.BLANK_IMAGE), true); + + // Construct main panel w/ layout. + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BorderLayout()); + mainPanel.add(titlePanel, BorderLayout.NORTH); + + // The user should only be able to close this dialog. + Object[] options = {Res.getString("close")}; + final JOptionPane pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); + mainPanel.add(pane, BorderLayout.CENTER); + final JOptionPane p = new JOptionPane(); + final JDialog dlg = p.createDialog(SparkManager.getMainWindow(), Res.getString("title.view.room.information")); + dlg.setModal(false); + + dlg.pack(); + dlg.setSize(450, 400); + dlg.setResizable(true); + dlg.setContentPane(mainPanel); + dlg.setLocationRelativeTo(SparkManager.getMainWindow()); + + PropertyChangeListener changeListener = e -> { + String value = (String) pane.getValue(); + if (Res.getString("close").equals(value)) { + pane.setValue(JOptionPane.UNINITIALIZED_VALUE); + dlg.dispose(); + } + }; + + pane.addPropertyChangeListener(changeListener); + + dlg.setVisible(true); + dlg.toFront(); + dlg.requestFocus(); + } + +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/RoomCreationDialog.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/RoomCreationDialog.java new file mode 100644 index 000000000..fe49f9c47 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/RoomCreationDialog.java @@ -0,0 +1,275 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.conferences; + +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jivesoftware.smackx.muc.MultiUserChatManager; +import org.jivesoftware.smackx.muc.RoomInfo; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.TitlePanel; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Localpart; + +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JTextField; +import javax.swing.UIManager; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import static java.awt.GridBagConstraints.*; + +public class RoomCreationDialog extends JPanel { + private final GridBagLayout gridBagLayout1 = new GridBagLayout(); + private final JLabel nameLabel = new JLabel(); + private final JTextField nameField = new JTextField(); + private final JLabel topicLabel = new JLabel(); + private final JTextField topicField = new JTextField(); + private final JCheckBox permanentCheckBox = new JCheckBox(); + private final JCheckBox isPublicCheckBox = new JCheckBox(); + private final JCheckBox hasPasswordCheckbox = new JCheckBox(); + private final JLabel passwordLabel = new JLabel(); + private final JPasswordField passwordField = new JPasswordField(); + private final JLabel confirmPasswordLabel = new JLabel(); + private final JPasswordField confirmPasswordField = new JPasswordField(); + private MultiUserChat groupChat = null; + private JOptionPane pane; + + public RoomCreationDialog() { + try { + jbInit(); + } catch (Exception e) { + Log.error(e); + } + } + + private void jbInit() { + this.setLayout(gridBagLayout1); + Insets insets = new Insets(5, 5, 5, 5); + this.add(nameLabel, new GridBagConstraints(0, 0, 1, 1, 0, 0, WEST, NONE, insets, 0, 0)); + this.add(nameField, new GridBagConstraints(1, 0, 1, 1, 1, 0, WEST, HORIZONTAL, insets, 0, 0)); + this.add(topicLabel, new GridBagConstraints(0, 1, 1, 1, 0, 0, WEST, NONE, insets, 5, 0)); + this.add(topicField, new GridBagConstraints(1, 1, 1, 1, 1, 0, WEST, HORIZONTAL, insets, 0, 0)); + this.add(permanentCheckBox, new GridBagConstraints(0, 2, 1, 1, 0, 0, WEST, NONE, insets, 0, 0)); + this.add(isPublicCheckBox, new GridBagConstraints(0, 3, 1, 1, 0, 0, WEST, NONE, insets, 0, 0)); + this.add(hasPasswordCheckbox, new GridBagConstraints(0, 4, 1, 1, 0, 1, NORTHWEST, NONE, insets, 0, 0)); + this.add(passwordLabel, new GridBagConstraints(0, 5, 1, 1, 0, 0, WEST, NONE, insets, 0, 0)); + this.add(passwordField, new GridBagConstraints(1, 5, 1, 1, 1, 0, WEST, HORIZONTAL, insets, 0, 0)); + this.add(confirmPasswordLabel, new GridBagConstraints(0, 6, 1, 1, 0, 0, WEST, NONE, insets, 0, 0)); + this.add(confirmPasswordField, new GridBagConstraints(1, 6, 1, 1, 1, 1, WEST, HORIZONTAL, insets, 0, 0)); + + ResourceUtils.resLabel(nameLabel, nameField, Res.getString("label.room.name")); + ResourceUtils.resLabel(topicLabel, topicField, Res.getString("label.room.topic") + ":"); + ResourceUtils.resButton(permanentCheckBox, Res.getString("checkbox.permanent")); + ResourceUtils.resButton(isPublicCheckBox, Res.getString("room.config.public")); + isPublicCheckBox.setToolTipText(Res.getString("room.config.public.hint")); + ResourceUtils.resButton(hasPasswordCheckbox, Res.getString("checkbox.private.room")); + ResourceUtils.resLabel(passwordLabel, passwordField, Res.getString("label.password") + ":"); + ResourceUtils.resLabel(confirmPasswordLabel, confirmPasswordField, Res.getString("label.confirm.password") + ":"); + + isPublicCheckBox.setSelected(true); + permanentCheckBox.setSelected(true); + + passwordLabel.setVisible(false); + passwordField.setVisible(false); + confirmPasswordLabel.setVisible(false); + confirmPasswordField.setVisible(false); + + hasPasswordCheckbox.addActionListener(changeEvent -> { + boolean hasPassword = hasPasswordCheckbox.isSelected(); + passwordLabel.setVisible(hasPassword); + passwordField.setVisible(hasPassword); + confirmPasswordLabel.setVisible(hasPassword); + confirmPasswordField.setVisible(hasPassword); + }); + } + + public MultiUserChat createGroupChat(Component parent, final DomainBareJid serviceName) { + // Create the title panel for this dialog + TitlePanel titlePanel = new TitlePanel( + Res.getString("title.create.room"), + Res.getString("message.create.or.join.room"), + SparkRes.getImageIcon(SparkRes.Icon.BLANK_24x24), + true); + + // Construct main panel w/ layout. + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BorderLayout()); + mainPanel.add(titlePanel, BorderLayout.NORTH); + + // The user should only be able to close this dialog. + Object[] options = {Res.getString("create"), Res.getString("close")}; + pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); + + mainPanel.add(pane, BorderLayout.CENTER); + + JOptionPane p = new JOptionPane(); + final JDialog dlg = p.createDialog(parent, Res.getString("title.conference.rooms")); + dlg.pack(); + dlg.setSize(500, 400); + dlg.setContentPane(mainPanel); + dlg.setLocationRelativeTo(parent); + + + PropertyChangeListener changeListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent e) { + Object o = pane.getValue(); + if (o instanceof Integer) { + dlg.setVisible(false); + return; + } + + String value = (String) pane.getValue(); + // Closes dialog or creates group chat based on input + if (Res.getString("close").equals(value)) { + dlg.setVisible(false); + } else if (Res.getString("create").equals(value)) { + createRoom(); + } + } + + private void createRoom() { + MultiUserChatManager mucManager = SparkManager.getMucManager(); + boolean isValid = validatePanel(); + if (isValid) { + String newRoomName = nameField.getText().replaceAll(" ", "_"); + Localpart newRoomNamePart = Localpart.fromOrThrowUnchecked(newRoomName); + EntityBareJid newRoomJid = JidCreate.entityBareFrom(newRoomNamePart, serviceName); + try { + RoomInfo roomInfo = mucManager.getRoomInfo(newRoomJid); + //JOptionPane.showMessageDialog(dlg, "Room already exists. Please specify a unique room name.", "Room Exists", JOptionPane.ERROR_MESSAGE); + //pane.setValue(JOptionPane.UNINITIALIZED_VALUE); + pane.removePropertyChangeListener(this); + dlg.setVisible(false); + ConferenceUtils.joinConferenceRoom(roomInfo, newRoomJid); + return; + } catch (XMPPException | SmackException | InterruptedException ignored) { + } + + // Create a group chat with valid information + groupChat = mucManager.getMultiUserChat(newRoomJid); + if (groupChat == null) { + showError("Could not join chat " + nameField.getText()); + pane.setValue(JOptionPane.UNINITIALIZED_VALUE); + } else { + pane.removePropertyChangeListener(this); + dlg.setVisible(false); + } + } else { + pane.setValue(JOptionPane.UNINITIALIZED_VALUE); + } + } + }; + + pane.addPropertyChangeListener(changeListener); + nameField.requestFocusInWindow(); + + dlg.setVisible(true); + dlg.toFront(); + dlg.requestFocus(); + + return groupChat; + } + + private boolean validatePanel() { + String roomName = nameField.getText(); + String password = new String(passwordField.getPassword()); + String confirmPassword = new String(confirmPasswordField.getPassword()); + boolean hasPassword = hasPasswordCheckbox.isSelected(); + + // Check for valid information + if (!ModelUtil.hasLength(roomName)) { + showError(Res.getString("message.specify.name.error")); + nameField.requestFocus(); + return false; + } + + if (hasPassword) { + if (!ModelUtil.hasLength(password)) { + showError(Res.getString("message.password.private.room.error")); + passwordField.requestFocus(); + return false; + } + if (!ModelUtil.hasLength(confirmPassword)) { + showError(Res.getString("message.confirmation.password.error")); + confirmPasswordField.requestFocus(); + return false; + } + if (!password.equals(confirmPassword)) { + showError(Res.getString("message.passwords.no.match")); + passwordField.requestFocus(); + return false; + } + } + return true; + } + + private void showError(String errorMessage) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(this, errorMessage, Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + } + + public boolean isPublicRoom() { + return isPublicCheckBox.isSelected(); + } + + public boolean isPermanent() { + return permanentCheckBox.isSelected(); + } + + public boolean isPasswordProtected() { + return passwordField.getPassword().length > 0; + } + + public String getPassword() { + return new String(confirmPasswordField.getPassword()); + } + + /** + * Returns the Room name of the RoomCreationDialog + */ + public String getRoomName() { + return nameField.getText(); + } + + /** + * Returns the Rooms Topic of the RoomCreationDialog + */ + public String getRoomTopic() { + return topicField.getText(); + } + +} diff --git a/src/java/org/jivesoftware/spark/ui/conferences/RoomInvitationListener.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/RoomInvitationListener.java similarity index 90% rename from src/java/org/jivesoftware/spark/ui/conferences/RoomInvitationListener.java rename to core/src/main/java/org/jivesoftware/spark/ui/conferences/RoomInvitationListener.java index f08468b1d..1ba5a28cd 100644 --- a/src/java/org/jivesoftware/spark/ui/conferences/RoomInvitationListener.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/RoomInvitationListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,6 +18,7 @@ import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jxmpp.jid.EntityBareJid; /** @@ -40,5 +37,5 @@ public interface RoomInvitationListener { * @param message the appened message. * @return true if you wish to intercept this invitation. */ - boolean handleInvitation( final XMPPConnection connection, final MultiUserChat room, final String inviter, final String reason, final String password, final Message message); + boolean handleInvitation( final XMPPConnection connection, final MultiUserChat room, final EntityBareJid inviter, final String reason, final String password, final Message message); } diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/RoomList.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/RoomList.java new file mode 100644 index 000000000..7259abd97 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/RoomList.java @@ -0,0 +1,46 @@ +package org.jivesoftware.spark.ui.conferences; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.component.Table; + +import javax.swing.*; +import javax.swing.table.TableCellRenderer; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +final class RoomList extends Table { + public RoomList() { + super(new String[]{ + " ", + Res.getString("title.name"), + Res.getString("title.address"), + Res.getString("title.occupants"), + Res.getString("menuitem.languages"), + Res.getString("description"), + }); + getColumnModel().setColumnMargin(0); + getColumnModel().getColumn(0).setMaxWidth(30); + getColumnModel().getColumn(3).setMaxWidth(80); + getColumnModel().getColumn(4).setMaxWidth(120); + + setSelectionBackground(Table.SELECTION_COLOR); + setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + setRowSelectionAllowed(true); + // setSortable(true); + } + + // Handle image rendering correctly + @Override + public TableCellRenderer getCellRenderer(int row, int column) { + Object o = getValueAt(row, column); + if (o != null) { + if (o instanceof JLabel) { + return new JLabelRenderer(false); + } + } + if (column == 3) { + return new ConferenceRoomBrowser.CenterRenderer(); + } + return super.getCellRenderer(row, column); + } +} diff --git a/src/java/org/jivesoftware/spark/ui/conferences/package.html b/core/src/main/java/org/jivesoftware/spark/ui/conferences/package.html similarity index 100% rename from src/java/org/jivesoftware/spark/ui/conferences/package.html rename to core/src/main/java/org/jivesoftware/spark/ui/conferences/package.html diff --git a/src/java/org/jivesoftware/spark/ui/history/AbstractHistoryFile.java b/core/src/main/java/org/jivesoftware/spark/ui/history/AbstractHistoryFile.java similarity index 96% rename from src/java/org/jivesoftware/spark/ui/history/AbstractHistoryFile.java rename to core/src/main/java/org/jivesoftware/spark/ui/history/AbstractHistoryFile.java index 12cae309e..71ee76069 100644 --- a/src/java/org/jivesoftware/spark/ui/history/AbstractHistoryFile.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/history/AbstractHistoryFile.java @@ -1,5 +1,4 @@ /** - * */ package org.jivesoftware.spark.ui.history; @@ -8,7 +7,6 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; @@ -107,7 +105,7 @@ protected List toList(Map months) { entries.add(historyEntry.getValue()); } - Collections.sort(entries, ( o1, o2 ) -> o2.getDate().compareTo(o1.getDate()) ); + entries.sort((o1, o2) -> o2.getDate().compareTo(o1.getDate())); return entries; } diff --git a/src/java/org/jivesoftware/spark/ui/history/HistoryEntry.java b/core/src/main/java/org/jivesoftware/spark/ui/history/HistoryEntry.java similarity index 87% rename from src/java/org/jivesoftware/spark/ui/history/HistoryEntry.java rename to core/src/main/java/org/jivesoftware/spark/ui/history/HistoryEntry.java index ed70e27f9..4f54037b2 100644 --- a/src/java/org/jivesoftware/spark/ui/history/HistoryEntry.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/history/HistoryEntry.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Objects; /** * @author Vyacheslav Durin (nixspirit@gmail.com) @@ -21,13 +22,11 @@ public HistoryEntry() { } public HistoryEntry(HistoryEntry orig) { - if (orig == null) - throw new IllegalArgumentException("Orig cannob be null"); - setDate(orig.getDate()); - setName(orig.getName()); - for (HistoryMessage msg : orig.getMessages()) { - getMessages().add(new HistoryMessage(msg)); - } + Objects.requireNonNull(orig); + date = orig.getDate(); + name = orig.getName(); + entries = new ArrayList<>(orig.getEntries()); + messages = new ArrayList<>(orig.getMessages()); } /** @@ -96,9 +95,9 @@ public Date getDate() { public void setDate(Date date) { this.date = date; - }; + } - /** + /** * {@inheritDoc} */ @Override diff --git a/core/src/main/java/org/jivesoftware/spark/ui/history/HistoryMessage.java b/core/src/main/java/org/jivesoftware/spark/ui/history/HistoryMessage.java new file mode 100644 index 000000000..1cc626123 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/history/HistoryMessage.java @@ -0,0 +1,191 @@ +package org.jivesoftware.spark.ui.history; + +import java.text.MessageFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.Objects; + +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +/** + * @author Vyacheslav Durin (nixspirit@gmail.com) + * + * Apr 17, 2013 + * @version 0.1 + */ +public class HistoryMessage { + + private static final String EMPTY = ""; + private static final SimpleDateFormat dateFormat = new SimpleDateFormat( + "yyyy-MM-dd HH:mm:ss.S z"); + private static final SimpleDateFormat fromDateFormat = new SimpleDateFormat( + "hh:mm:ss a"); + private static final MessageFormat contentFormat = new MessageFormat( + "({0}) {1}: {2}
      "); + private Element messageElement; + private String to; + private String from; + private String body; + private Date date; + + public HistoryMessage(Element messageEl) { + this.messageElement = messageEl; + + String to = getElementValue(this.messageElement, "to"); + String from = getElementValue(this.messageElement, "from"); + String body = getElementValue(this.messageElement, "body"); + String date = getElementValue(this.messageElement, "date"); + + setTo(to); + setFrom(from); + setBody(body); + setDate(date); + } + + public HistoryMessage() { + } + + public HistoryMessage(HistoryMessage orig) { + Objects.requireNonNull(orig); + setTo(orig.getTo()); + setFrom(orig.getFrom()); + setBody(orig.getBody()); + setDate(orig.getDate()); + messageElement = orig.getXML(); + } + + /** + * @param to + * the to to set + */ + public void setTo(String to) { + this.to = to; + } + + /** + * @param from + * the from to set + */ + public void setFrom(String from) { + this.from = from; + } + + /** + * @param body + * the body to set + */ + public void setBody(String body) { + this.body = body; + } + + /** + * @param date + * the date to set + */ + public void setDate(Date date) { + this.date = date; + } + + /** + * @param date + * the date to set + */ + public void setDate(String date) { + this.date = parseHistoryDate(date); + } + + /** + * @return the messageElement + */ + public Element getXML() { + return messageElement; + } + + /** + * @return the to + */ + public String getTo() { + return to; + } + + /** + * @return the from + */ + public String getFrom() { + return from; + } + + /** + * @return the body + */ + public String getBody() { + return body; + } + + /** + * @return the date + */ + public Date getDate() { + return date; + } + + public Date getNormalizedDate() { + Calendar cal = normalizeDate(getDate()); + return cal.getTime(); + } + + public Date getNormalizedMonth() { + Calendar cal = normalizeDate(getDate()); + cal.set(Calendar.DATE, 1); + return cal.getTime(); + } + + public String getContent() { + return contentFormat.format(new String[] { fromDateFormat.format(date), + from, body }); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return "HistoryMessage to=" + to + ", from=" + from + ", body=" + body + + ", date=" + date + "]"; + } + + private static Date parseHistoryDate(String dateToParse) { + try { + return dateFormat.parse(dateToParse); + } catch (Exception e) { + e.printStackTrace(); + } + return Calendar.getInstance().getTime(); + } + + private static Calendar normalizeDate(Date d) { + Calendar cal = Calendar.getInstance(); + cal.setTime(d); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + return cal; + } + + private static String getElementValue(Element element, String tag) { + if (element == null || tag == null || EMPTY.equals(tag)) + return EMPTY; + + NodeList to = element.getElementsByTagName(tag); + if (to.getLength() < 1) + return EMPTY; + Element el = (Element) to.item(0); + if (el == null) + return EMPTY; + return el.getFirstChild().getNodeValue(); + } + +} diff --git a/src/java/org/jivesoftware/spark/ui/history/HistoryTreeNode.java b/core/src/main/java/org/jivesoftware/spark/ui/history/HistoryTreeNode.java similarity index 100% rename from src/java/org/jivesoftware/spark/ui/history/HistoryTreeNode.java rename to core/src/main/java/org/jivesoftware/spark/ui/history/HistoryTreeNode.java diff --git a/src/java/org/jivesoftware/spark/ui/history/HistoryWindow.java b/core/src/main/java/org/jivesoftware/spark/ui/history/HistoryWindow.java similarity index 90% rename from src/java/org/jivesoftware/spark/ui/history/HistoryWindow.java rename to core/src/main/java/org/jivesoftware/spark/ui/history/HistoryWindow.java index 6f359f234..61c62d05e 100644 --- a/src/java/org/jivesoftware/spark/ui/history/HistoryWindow.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/history/HistoryWindow.java @@ -1,5 +1,7 @@ package org.jivesoftware.spark.ui.history; +import org.jivesoftware.resource.Res; + import java.awt.Color; import java.awt.Component; import java.awt.Dimension; @@ -44,23 +46,19 @@ public class HistoryWindow extends JFrame { private static final String CONTENT_TYPE = "text/html"; private static final String EMPTY = ""; - private static final String LABEL_SIZE = "Size:"; - private static final String BTN_FIND = "Find"; - private static final String BTN_CLOSE = "Close"; private static final Dimension SIZE = new Dimension(700, 400); private static final Point LOCATION = new Point(400, 150); private static final MessageFormat TITLE_FORMAT = new MessageFormat("{0}"); private static final MessageFormat LABEL_FORMAT = new MessageFormat("{0}"); private static final MessageFormat HISTORY_FILE_FORMAT = new MessageFormat( "transcripts/{0}.xml"); - private static final Font LABEL_FONT = new Font("Droid Sans", Font.BOLD, 16); - private static final Font SIZE_TEXT_FONT = new Font("Droid Sans", + private static final Font LABEL_FONT = new Font("Droid Sans", Font.PLAIN, 14); private static final Font TEXT_FONT = new Font("Droid Sans", Font.PLAIN, 13); private static final Dimension SIZE_FIND_FIELD = new Dimension(100, 25); - private String roomName; - private InputStream historyStream; + private final String roomName; + private final InputStream historyStream; private JButton btnClose; private JTextPane historyContentText; private JScrollPane historyContentTextScrollPane; @@ -103,10 +101,10 @@ private void initComponents() { historyFile = new XMLHistoryFile(historyStream); sizeText = historyFile.getFormatSize(); - btnClose = createJButton(BTN_CLOSE); + btnClose = createJButton(Res.getString("button.close")); btnClose.setFont(TEXT_FONT); - btnFind = createJButton(BTN_FIND); + btnFind = createJButton(Res.getString("button.find")); btnFind.setFont(TEXT_FONT); HistoryTreeNode historyTreeTopNode = buildHistoryTree( historyFile, roomName ); @@ -178,14 +176,9 @@ private void initLayout() { private Component getSizePanel() { JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT)); - JLabel label = createJLabel(LABEL_SIZE); + JLabel label = createJLabel(Res.getString("message.file.size",sizeText)); label.setFont(LABEL_FONT); panel.add(label); - - JLabel sizeTextLabel = createJLabel(EMPTY); - sizeTextLabel.setFont(SIZE_TEXT_FONT); - sizeTextLabel.setText(sizeText); - panel.add(sizeTextLabel); return panel; } @@ -272,15 +265,14 @@ private ActionListener onCloseBtnClick() { private ActionListener onFindBtnClick() { return e -> { - String searchText = findTextField.getText().toString().trim(); + String searchText = findTextField.getText().trim(); if (EMPTY.equals(searchText)) { historyTree.setModel(historyOriginalModel); selectVeryFirstLeaf(); return; } - List results = historyFile.search(findTextField - .getText().toString()); + List results = historyFile.search(findTextField.getText()); HistoryTreeNode top = new HistoryTreeNode(searchText); @@ -334,22 +326,18 @@ private static JButton createJButton(String title) { } private static JTextField createJTextField() { - JTextField field = new JTextField(); - return field; + return new JTextField(); } private static JTree createJTree(DefaultMutableTreeNode top) { - JTree tree = new JTree(top); - return tree; + return new JTree(top); } private static JTextPane createJTextPane() { - JTextPane pane = new JTextPane(); - return pane; + return new JTextPane(); } private static JLabel createJLabel(String title) { - JLabel label = new JLabel(title); - return label; + return new JLabel(title); } } diff --git a/src/java/org/jivesoftware/spark/ui/history/XMLHistoryFile.java b/core/src/main/java/org/jivesoftware/spark/ui/history/XMLHistoryFile.java similarity index 83% rename from src/java/org/jivesoftware/spark/ui/history/XMLHistoryFile.java rename to core/src/main/java/org/jivesoftware/spark/ui/history/XMLHistoryFile.java index 28e5842a3..905cabdcf 100644 --- a/src/java/org/jivesoftware/spark/ui/history/XMLHistoryFile.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/history/XMLHistoryFile.java @@ -2,11 +2,7 @@ import java.io.IOException; import java.io.InputStream; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -26,16 +22,13 @@ public class XMLHistoryFile extends AbstractHistoryFile { private static final String MESSAGE_TAG = "message"; - private InputStream roomFileStream; + private final InputStream roomFileStream; /** - * @param roomFileStream + * @param fileStream */ public XMLHistoryFile(InputStream fileStream) { - - if (fileStream == null) - throw new IllegalArgumentException("History Stream cannot be null"); - + Objects.requireNonNull(fileStream); roomFileStream = fileStream; } @@ -43,8 +36,7 @@ public XMLHistoryFile(InputStream fileStream) { protected long getSize() { try { return roomFileStream.available() / SIZE_MULTIPLICATOR; - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException ignored) { } return 0; } @@ -105,13 +97,9 @@ private Document read() { roomFileStream.close(); doc.getDocumentElement().normalize(); return doc; - } catch (ParserConfigurationException e) { - e.printStackTrace(); - } catch (SAXException e) { - e.printStackTrace(); - } catch (IOException e) { + } catch (ParserConfigurationException | SAXException | IOException e) { e.printStackTrace(); } - return null; + return null; } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/login/CertificateDialog.java b/core/src/main/java/org/jivesoftware/spark/ui/login/CertificateDialog.java new file mode 100644 index 000000000..40583fe4f --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/login/CertificateDialog.java @@ -0,0 +1,400 @@ +package org.jivesoftware.spark.ui.login; + +import static java.awt.GridBagConstraints.BOTH; +import static java.awt.GridBagConstraints.CENTER; +import static java.awt.GridBagConstraints.EAST; +import static java.awt.GridBagConstraints.HORIZONTAL; +import static java.awt.GridBagConstraints.NONE; +import static java.awt.GridBagConstraints.WEST; + +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.HeadlessException; +import java.awt.Insets; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.security.KeyStoreException; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; + +import javax.naming.InvalidNameException; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingUtilities; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.certificates.CertManager; +import org.jivesoftware.sparkimpl.certificates.CertificateController; +import org.jivesoftware.sparkimpl.certificates.CertificateDialogReason; +import org.jivesoftware.sparkimpl.certificates.CertificateModel; +import org.jivesoftware.sparkimpl.certificates.OIDTranslator; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; + +/** + * This class show to user all fields of certificate as well as options to check it's validity and set trust toward it. + * When certificate is invalid then setting radio button on trust will put certificate to exceptions list. When + * certificate is valid and radio button is set on distrust then it will be put on distrusted list. In other situations + * trust will work according to validity + * + * @author Pawel Scibiorski + */ +public class CertificateDialog extends JDialog implements ActionListener { + + private final static Insets DEFAULT_INSETS = new Insets(5, 5, 5, 5); + private final CertificateModel certModel; + private final CertManager certControll; + private boolean addCert = false; + + private final JScrollPane scrollPane; + private final JPanel panel = new JPanel(); + public boolean isAddCert() { + return addCert; + } + + private final JPanel buttonPanel = new JPanel(); + private final JPanel certStatusPanel = new JPanel(); + + private final JTextArea versionField = new JTextArea(); + private final JTextArea serialNumberField = new JTextArea(); + private final JTextArea signatureValueField = new JTextArea(); + private final JTextArea signatureAlgorithmField = new JTextArea(); + private final JTextArea issuerField = new JTextArea(); + private final JTextArea subjectField = new JTextArea(); + private final JTextArea notBeforeField = new JTextArea(); + private final JTextArea notAfterField = new JTextArea(); + private final JTextArea publicKeyField = new JTextArea(); + private final JTextArea publicKeyAlgorithmField = new JTextArea(); + private final JTextArea issuerUniqueIDField = new JTextArea(); + private final JTextArea subjectUniqueIDField = new JTextArea(); + private final JTextArea unsupportedExtensionsArea = new JTextArea(); + private final JTextArea certStatusArea = new JTextArea(); + + private final JLabel infoLabel = new JLabel(); + private final JLabel versionLabel = new JLabel(); + private final JLabel serialNumberLabel = new JLabel(); + private final JLabel signatureValueLabel = new JLabel(); + private final JLabel signatureAlgorithmLabel = new JLabel(); + private final JLabel issuerLabel = new JLabel(); + private final JLabel subjectLabel = new JLabel(); + private final JLabel notBeforeLabel = new JLabel(); + private final JLabel notAfterLabel = new JLabel(); + private final JLabel publicKeyLabel = new JLabel(); + private final JLabel publicKeyAlgorithmLabel = new JLabel(); + private final JLabel issuerUniqueIDLabel = new JLabel(); + private final JLabel subjectUniqueIDLabel = new JLabel(); + private final JLabel unsupportedExtensionsLabel = new JLabel(); + private final JLabel extensionsLabel = new JLabel(); + + private final JCheckBox exceptionBox = new JCheckBox(); + private final JButton checkValidity = new JButton(); + private final JButton okButton = new JButton(); + private final JButton cancelButton = new JButton(); + private final List certUnsupportedCriticalExtensions; + private final List certUnsupportedNonCriticalExtensions; + private final HashMap certExtensions; + private final JButton deleteButton = new JButton(); + + + public CertificateDialog(LocalPreferences localPreferences, CertificateModel certModel, + CertManager certificateController, CertificateDialogReason reason) { + Objects.requireNonNull(localPreferences); + Objects.requireNonNull(certModel); + + certControll = certificateController; + this.certModel = certModel; + this.certExtensions = certModel.getExtensions(); + this.certUnsupportedCriticalExtensions = certModel.getUnsupportedCriticalExtensions(); + this.certUnsupportedNonCriticalExtensions = certModel.getUnsupportedNonCriticalExtensions(); + setTitle(Res.getString("title.certificate")); + setSize(500, 600); + setLayout(new GridBagLayout()); + Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize(); + setLocation(dimension.width / 2 - this.getWidth(), dimension.height / 2 - this.getHeight() / 2); + setModal(true); + setLayout(new GridBagLayout()); + setResizable(false); + + setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + + versionField.setText(Integer.toString(certModel.getVersion())); + serialNumberField.setText(certModel.getSerialNumber()); + signatureValueField.setText(certModel.getSignatureValue()); + signatureAlgorithmField.setText(certModel.getSignatureAlgorithm()); + issuerField.setText(certModel.getIssuer()); + subjectField.setText(certModel.getSubject()); + notBeforeField.setText(certModel.getNotBefore()); + notAfterField.setText(certModel.getNotAfter()); + publicKeyField.setText(certModel.getPublicKey()); + publicKeyAlgorithmField.setText(certModel.getPublicKeyAlgorithm()); + issuerUniqueIDField.setText(certModel.getIssuerUniqueID()); + subjectUniqueIDField.setText(certModel.getSubjectUniqueID()); + extensionsLabel.setText(Res.getString("cert.extensions")); + certStatusArea.setText(certModel.getCertStatusAll()); + + certStatusArea.setEditable(false); + + versionField.setLineWrap(true); + serialNumberField.setLineWrap(true); + signatureValueField.setLineWrap(true); + signatureAlgorithmField.setLineWrap(true); + issuerField.setLineWrap(true); + subjectField.setLineWrap(true); + notBeforeField.setLineWrap(true); + notAfterField.setLineWrap(true); + publicKeyField.setLineWrap(true); + publicKeyAlgorithmField.setLineWrap(true); + issuerUniqueIDField.setLineWrap(true); + subjectUniqueIDField.setLineWrap(true); + unsupportedExtensionsArea.setLineWrap(true); + certStatusArea.setLineWrap(true); + + versionField.setEditable(false); + serialNumberField.setEditable(false); + signatureValueField.setEditable(false); + signatureAlgorithmField.setEditable(false); + issuerField.setEditable(false); + subjectField.setEditable(false); + notBeforeField.setEditable(false); + notAfterField.setEditable(false); + publicKeyField.setEditable(false); + publicKeyAlgorithmField.setEditable(false); + issuerUniqueIDField.setEditable(false); + subjectUniqueIDField.setEditable(false); + unsupportedExtensionsArea.setEditable(false); + certStatusArea.setEditable(false); + + + okButton.addActionListener(this); + cancelButton.addActionListener(this); + deleteButton.addActionListener(this); + checkValidity.addActionListener(this); + exceptionBox.addActionListener(this); + + ResourceUtils.resLabel(versionLabel, versionField, Res.getString("label.certificate.version")); + ResourceUtils.resLabel(serialNumberLabel, serialNumberField, Res.getString("label.certificate.serial.number")); + ResourceUtils.resLabel(signatureValueLabel, signatureValueField, + Res.getString("label.certificate.signature.value")); + ResourceUtils.resLabel(signatureAlgorithmLabel, signatureAlgorithmField, + Res.getString("label.certificate.signature.algorithm")); + ResourceUtils.resLabel(issuerLabel, issuerField, Res.getString("label.certificate.issuer")); + ResourceUtils.resLabel(subjectLabel, subjectField, Res.getString("label.certificate.subject")); + ResourceUtils.resLabel(notBeforeLabel, notBeforeField, Res.getString("label.certificate.not.before")); + ResourceUtils.resLabel(notAfterLabel, notAfterField, Res.getString("label.certificate.not.after")); + ResourceUtils.resLabel(publicKeyLabel, publicKeyField, Res.getString("label.certificate.public.key")); + ResourceUtils.resLabel(publicKeyAlgorithmLabel, publicKeyAlgorithmField, + Res.getString("label.certificate.public.key.algorithm")); + ResourceUtils.resLabel(issuerUniqueIDLabel, issuerUniqueIDField, + Res.getString("label.certificate.issuer.unique.id")); + ResourceUtils.resLabel(subjectUniqueIDLabel, subjectUniqueIDField, + Res.getString("label.certificate.subject.unique.id")); + ResourceUtils.resLabel(unsupportedExtensionsLabel, unsupportedExtensionsArea, + Res.getString("cert.extensions.unsupported")); + ResourceUtils.resButton(exceptionBox, Res.getString("checkbox.on.exception.list")); + ResourceUtils.resButton(checkValidity, Res.getString("button.check.validity")); + ResourceUtils.resButton(okButton, Res.getString("ok")); + ResourceUtils.resButton(cancelButton, Res.getString("cancel")); + ResourceUtils.resButton(deleteButton, Res.getString("delete")); + if (reason == CertificateDialogReason.ADD_CERTIFICATE) { + infoLabel.setText(Res.getString("dialog.certificate.show")); + }else if (reason == CertificateDialogReason.ADD_ID_CERTIFICATE){ + infoLabel.setText(Res.getString("dialog.id.certificate.show")); + } else if (reason == CertificateDialogReason.ADD_CERTIFICATE_FROM_CONNECTION){ + infoLabel.setText(Res.getString("dialog.certificate.add.from.connection")); + } + + panel.setLayout(new GridBagLayout()); + buttonPanel.setLayout(new GridBagLayout()); + + panel.add(versionLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(serialNumberLabel, + new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(signatureValueLabel, + new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(signatureAlgorithmLabel, + new GridBagConstraints(0, 3, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(issuerLabel, new GridBagConstraints(0, 4, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(subjectLabel, new GridBagConstraints(0, 5, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(notBeforeLabel, new GridBagConstraints(0, 6, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(notAfterLabel, new GridBagConstraints(0, 7, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(publicKeyLabel, new GridBagConstraints(0, 8, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(publicKeyAlgorithmLabel, + new GridBagConstraints(0, 9, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(issuerUniqueIDLabel, + new GridBagConstraints(0, 10, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(subjectUniqueIDLabel, + new GridBagConstraints(0, 11, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + + panel.add(versionField, + new GridBagConstraints(2, 0, 12, 1, 0.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(serialNumberField, + new GridBagConstraints(2, 1, 6, 1, 0.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(signatureValueField, + new GridBagConstraints(2, 2, 6, 1, 0.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(signatureAlgorithmField, + new GridBagConstraints(2, 3, 6, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(issuerField, new GridBagConstraints(2, 4, 6, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(subjectField, new GridBagConstraints(2, 5, 6, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(notBeforeField, new GridBagConstraints(2, 6, 6, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(notAfterField, new GridBagConstraints(2, 7, 6, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(publicKeyField, new GridBagConstraints(2, 8, 6, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(publicKeyAlgorithmField, + new GridBagConstraints(2, 9, 6, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(issuerUniqueIDField, + new GridBagConstraints(2, 10, 6, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(subjectUniqueIDField, + new GridBagConstraints(2, 11, 6, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + certStatusPanel.setLayout(new GridBagLayout()); + certStatusPanel.add(certStatusArea, new GridBagConstraints(0, 0, 1, 1, 1, 1, CENTER, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + certStatusPanel.setBorder( + BorderFactory.createTitledBorder(Res.getString("label.certificate.status"))); + + + // extensions + panel.add(extensionsLabel, new GridBagConstraints(2, 12, 6, 1, 1.0, 0.0, EAST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + int i =13; //place extensions in next rows + for(HashMap.Entry entry : certExtensions.entrySet()) { + String oid = entry.getKey(); + String value = entry.getValue(); + JTextArea extensionArea = new JTextArea(); + extensionArea.setLineWrap(true); + extensionArea.setText(value); + extensionArea.setEditable(false); + JLabel extensionLabel = new JLabel(); + ResourceUtils.resLabel(extensionLabel, extensionArea, OIDTranslator.getDescription(oid)); + + panel.add(extensionLabel, + new GridBagConstraints(0, i, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(extensionArea, + new GridBagConstraints(2, i, 6, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + i++; + } + for (String extension : certUnsupportedCriticalExtensions) { + unsupportedExtensionsArea.append(Res.getString("cert.critical") + "\n" + extension + ": " + + OIDTranslator.getDescription(extension) + '\n'); + } + for (String extension : certUnsupportedNonCriticalExtensions) { + unsupportedExtensionsArea.append(Res.getString("cert.not.critical") + "\n" + extension + ": " + + OIDTranslator.getDescription(extension) + '\n'); + } + + panel.add(unsupportedExtensionsLabel, new GridBagConstraints(0, i, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + panel.add(unsupportedExtensionsArea, new GridBagConstraints(2, i, 6, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + if(reason == CertificateDialogReason.SHOW_CERTIFICATE || reason == CertificateDialogReason.ADD_CERTIFICATE_FROM_CONNECTION){ + + buttonPanel.add(exceptionBox, new GridBagConstraints(0, 0, 1, 1, 0.2, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + if (reason == CertificateDialogReason.SHOW_CERTIFICATE) { + exceptionBox.setSelected(certificateController.isOnExceptionList(certModel)); + } else if (reason == CertificateDialogReason.ADD_CERTIFICATE_FROM_CONNECTION) { + exceptionBox.setSelected(true); + } + + } + + buttonPanel.add(certStatusPanel, new GridBagConstraints(2, 0, 3, 2, 0.2, 0.0, CENTER, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + buttonPanel.add(checkValidity, new GridBagConstraints(0, 1, 2, 1, 0.0, 0.0, WEST, NONE, DEFAULT_INSETS, 0, 0)); + buttonPanel.add(okButton, new GridBagConstraints(2, 2, 1, 1, 0.2, 0.0, CENTER, HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + if (reason == CertificateDialogReason.ADD_CERTIFICATE || reason == CertificateDialogReason.ADD_ID_CERTIFICATE + || reason == CertificateDialogReason.ADD_CERTIFICATE_FROM_CONNECTION) { + buttonPanel.add(cancelButton, + new GridBagConstraints(3, 2, 1, 1, 0.2, 0.0, CENTER, HORIZONTAL, new Insets(5, 5, 5, 100), 0, 0)); + } + if (reason == CertificateDialogReason.SHOW_CERTIFICATE || reason == CertificateDialogReason.SHOW_ID_CERTIFICATE) { + buttonPanel.add(cancelButton, + new GridBagConstraints(3, 2, 1, 1, 0.2, 0.0, CENTER, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + buttonPanel.add(deleteButton, + new GridBagConstraints(4, 2, 1, 1, 0.2, 0.0, CENTER, HORIZONTAL, new Insets(5, 5, 5, 0), 0, 0)); + } + + scrollPane = new JScrollPane(panel); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + + if (reason == CertificateDialogReason.ADD_CERTIFICATE || reason == CertificateDialogReason.ADD_ID_CERTIFICATE + || reason == CertificateDialogReason.ADD_CERTIFICATE_FROM_CONNECTION) { + add(infoLabel, new GridBagConstraints(0, 0, 4, 1, 1.0, 0.0, WEST, BOTH, DEFAULT_INSETS, 0, 0)); + } + + add(scrollPane, new GridBagConstraints(0, 1, 4, 1, 1.0, 1.0, WEST, BOTH, DEFAULT_INSETS, 0, 0)); + add(buttonPanel, new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + SwingUtilities.invokeLater(() -> { + //scrolls scrollPane to top + panel.scrollRectToVisible(versionField.getBounds()); + + // info that certificate is distrusted + if (( reason == CertificateDialogReason.ADD_CERTIFICATE + || reason == CertificateDialogReason.ADD_ID_CERTIFICATE + || reason == CertificateDialogReason.ADD_CERTIFICATE_FROM_CONNECTION) && !certModel.isValid()) { + JOptionPane.showMessageDialog(null, Res.getString("dialog.certificate.is.distrusted")); + } + }); + + setVisible(true); + + } + + @Override + public void actionPerformed(ActionEvent e) { + if(e.getSource() == okButton){ + //controller should be passed to this class only if there is need to modification content of Keystore. + if (certControll != null) { + addCert= true; + if (certControll instanceof CertificateController && !certControll.isOnExceptionList(certModel) && exceptionBox.isSelected()) { + + CertificateController crtCtrl = (CertificateController)certControll; + try { + crtCtrl.addCertificateAsExempted(certModel); + } catch (HeadlessException | InvalidNameException | KeyStoreException e1) { + Log.error(e1); + } + } + } + this.dispose(); + }else if(e.getSource() == cancelButton){ + if (certControll != null) { + certControll.setAddToKeystore(false); + } + this.dispose(); + }else if(e.getSource() == deleteButton){ + try { + certControll.deleteEntry(certModel.getAlias()); + this.dispose(); + } catch (KeyStoreException ex) { + Log.error("Couldn't delete the certificate", ex); + } + + } else if (e.getSource() == exceptionBox) { + certControll.addOrRemoveFromExceptionList(exceptionBox.isSelected()); + } else if (e.getSource() == checkValidity) { + checkValidity(); + } + } + + private void checkValidity() { + if (certControll.checkRevocation(certModel.getCertificate())) { + certStatusArea.setText(certModel.getCertStatusAll()); + try { + certControll.addCertificateToBlackList(certModel.getCertificate()); + } catch (HeadlessException | KeyStoreException + | InvalidNameException ex) { + Log.warning("Couldn't add certificate to the blacklist", ex); + } + certStatusArea.updateUI(); + } + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/login/CertificatesManagerSettingsPanel.java b/core/src/main/java/org/jivesoftware/spark/ui/login/CertificatesManagerSettingsPanel.java new file mode 100644 index 000000000..8f5de1428 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/login/CertificatesManagerSettingsPanel.java @@ -0,0 +1,321 @@ +package org.jivesoftware.spark.ui.login; + +import static java.awt.GridBagConstraints.HORIZONTAL; +import static java.awt.GridBagConstraints.WEST; + +import java.awt.Color; +import java.awt.Component; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.io.File; +import java.io.IOException; +import java.security.KeyStoreException; +import java.security.cert.CertificateException; + +import javax.naming.InvalidNameException; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableModel; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.certificates.CertificateController; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +/** + * This class serve as visual in implementation of manageable list of + * certificates. Together with CertificateController and CertificateModel + * Classes this apply MVC pattern. + * + * @author Paweł Ścibiorski + * + */ +public class CertificatesManagerSettingsPanel extends JPanel implements ActionListener, MouseListener, TableModelListener { + + private final static Insets DEFAULT_INSETS = new Insets(5, 5, 5, 5); + private final LocalPreferences localPreferences; + + //table with certificates + private final CertificateController certControll; + private static JTable certTable; + private final JButton showCert = new JButton(); + + private JScrollPane scrollPane; + + //add certificate utilities + private final JFileChooser fileChooser = new JFileChooser(); + private final JButton fileButton = new JButton(); + private final JPanel filePanel = new JPanel(); + private final FileNameExtensionFilter certFilter = new FileNameExtensionFilter( + Res.getString("menuitem.certificate.files.filter"), "cer", "crt", "der", "pem"); + + //checboxes with options + private final JCheckBox acceptExpired = new JCheckBox(); + private final JCheckBox acceptRevoked = new JCheckBox(); + private final JCheckBox acceptSelfSigned = new JCheckBox(); + private final JCheckBox checkCRL = new JCheckBox(); + private final JCheckBox checkOCSP = new JCheckBox(); + private final JCheckBox allowSoftFail = new JCheckBox(); + private final JCheckBox acceptNotValidYet = new JCheckBox(); + + public CertificatesManagerSettingsPanel(LocalPreferences localPreferences, JDialog optionsDialog) { + + this.localPreferences = localPreferences; + + certControll = new CertificateController(localPreferences); + setLayout(new GridBagLayout()); + + addCertTableToPanel(); + + ResourceUtils.resButton(acceptExpired, Res.getString("checkbox.accept.expired")); + ResourceUtils.resButton(acceptNotValidYet, Res.getString("checkbox.accept.not.valid.yet")); + ResourceUtils.resButton(acceptRevoked, Res.getString("checkbox.accept.revoked")); + ResourceUtils.resButton(acceptSelfSigned, Res.getString("checkbox.accept.self.signed")); + ResourceUtils.resButton(checkCRL, Res.getString("checkbox.check.crl")); + ResourceUtils.resButton(checkOCSP, Res.getString("checkbox.check.ocsp")); + ResourceUtils.resButton(allowSoftFail, Res.getString("checkbox.allow.soft.fail")); + ResourceUtils.resButton(showCert, Res.getString("button.show.certificate")); + ResourceUtils.resButton(fileButton, Res.getString("label.choose.file")); + + acceptSelfSigned.setSelected(localPreferences.isAcceptSelfSigned()); + acceptExpired.setSelected(localPreferences.isAcceptExpired()); + acceptNotValidYet.setSelected(localPreferences.isAcceptNotValidYet()); + acceptRevoked.setSelected(localPreferences.isAcceptRevoked()); + checkCRL.setSelected(localPreferences.isCheckCRL()); + checkOCSP.setSelected(localPreferences.isCheckOCSP()); + allowSoftFail.setSelected(localPreferences.isAllowSoftFail()); + + certTable.addMouseListener(this); + certTable.getModel().addTableModelListener(this); + showCert.setEnabled(false); + showCert.addActionListener(this); + fileButton.addActionListener(this); + checkCRL.addActionListener(this); + checkOCSP.addActionListener(this); + acceptRevoked.addActionListener(this); + + checkCRL.setEnabled(!acceptRevoked.isSelected()); + checkOCSP.setEnabled(checkCRL.isSelected()); + allowSoftFail.setEnabled(checkOCSP.isSelected()); + filePanel.setLayout(new GridBagLayout()); + filePanel.add(fileButton, new GridBagConstraints(0, 0, 2, 1, 1.0, 1.0, WEST, HORIZONTAL, DEFAULT_INSETS, 40, 0)); + filePanel.setBorder( + BorderFactory.createTitledBorder(Res.getString("label.certificate.add.certificate.to.truststore"))); + + add(scrollPane, new GridBagConstraints(0, 0, 6, 1, 1.0, 0.8, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + add(acceptSelfSigned, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.1, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + add(acceptExpired, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.1, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + add(acceptNotValidYet, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.1, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + add(acceptRevoked, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.1, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + add(checkCRL, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.1, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + add(checkOCSP, new GridBagConstraints(3, 1, 1, 1, 0.0, 0.1, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + add(allowSoftFail, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.1, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + add(showCert, new GridBagConstraints(4, 1, 2, 1, 0.0, 0.1, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + add(filePanel, new GridBagConstraints(4, 2, 2, 4, 0.0, 0.1, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + } + + public void addCertTableToPanel() { + certControll.loadKeyStores(); + certControll.createTableModel(); + certTable = new JTable(certControll.getTableModel()) { + + @Override + public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, + int columnIndex) { + JComponent component = (JComponent) super.prepareRenderer(renderer, rowIndex, columnIndex); + if (isRowSelected(rowIndex)) { + component.setBackground(getBackground()); + component.setForeground(Color.black); + } + Object value = getModel().getValueAt(convertRowIndexToModel(rowIndex), columnIndex); + + DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer(); + + centerRenderer.setHorizontalAlignment(JLabel.CENTER); + this.getColumnModel().getColumn(1).setCellRenderer(centerRenderer); + + if (value.equals(Res.getString("cert.valid"))) { + component.setBackground(Color.green); + } else if (value.equals(Res.getString("cert.expired")) || value + .equals(Res.getString("cert.not.valid.yet")) || value.equals(Res.getString("cert.revoked"))) { + component.setBackground(Color.red); + } else { + component.setBackground(Color.white); + } + return component; + } + + }; + + scrollPane = new JScrollPane(certTable); + certTable.setFillsViewportHeight(true); + certTable.setAutoCreateRowSorter(true); + + certControll.resizeColumnWidth(certTable); + certTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); + + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource() == showCert) { + certControll.showCertificate(); + + } else if (e.getSource() == fileButton) { + addCertificate(); + + } else if (e.getSource() == checkCRL) { + + if (checkCRL.isSelected()) { + + checkOCSP.setEnabled(true); + allowSoftFail.setEnabled(true); + } else if (!checkCRL.isSelected()) { + + checkOCSP.setSelected(false); + checkOCSP.setEnabled(false); + allowSoftFail.setEnabled(false); + allowSoftFail.setSelected(false); + } + + } else if (e.getSource() == acceptRevoked) { + if (acceptRevoked.isSelected()) { + + checkCRL.setSelected(false); + checkOCSP.setSelected(false); + allowSoftFail.setSelected(false); + + checkCRL.setEnabled(false); + checkOCSP.setEnabled(false); + allowSoftFail.setEnabled(false); + } else if (!acceptRevoked.isSelected()) { + checkCRL.setEnabled(true); + } + } + } + + @Override + public void mouseClicked(MouseEvent e) { + + } + + @Override + public void mouseEntered(MouseEvent e) { + + } + + @Override + public void mouseExited(MouseEvent e) { + + } + + @Override + public void mousePressed(MouseEvent e) { + if (e.getClickCount() == 2) { + JTable source = (JTable) e.getSource(); + if (e.getSource() == certTable && source.getSelectedColumn() != 2) { + certControll.showCertificate(); + } + } + if (e.getSource() == certTable) { + showCert.setEnabled(true); + } + } + + @Override + public void tableChanged(TableModelEvent e) { + int row = e.getFirstRow(); + int column = e.getColumn(); + if (column == 2) { + TableModel model = (TableModel) e.getSource(); + Boolean checked = (Boolean) model.getValueAt(row, column); + certControll.addOrRemoveFromExceptionList(checked); + } + } + + private void addCertificate() { + fileChooser.setAcceptAllFileFilterUsed(false); + fileChooser.addChoosableFileFilter(certFilter); + fileChooser.setFileFilter(certFilter); + + int retVal = fileChooser.showOpenDialog(this); + if (retVal == JFileChooser.APPROVE_OPTION) { + + File file = fileChooser.getSelectedFile(); + try { + certControll.addEntryFileToKeyStore(file); + } catch (CertificateException e) { + JOptionPane.showMessageDialog(null, Res.getString("dialog.cannot.upload.certificate.might.be.ill.formatted")); + Log.error("Cannot upload certificate file", e); + } catch (KeyStoreException | InvalidNameException | IOException e) { + JOptionPane.showMessageDialog(null, "dialog.cannot.upload.certificate"); + Log.error("Cannot upload certificate file", e); + } + } + } + + @Override + public void mouseReleased(MouseEvent arg0) { + + } + + public static JTable getCertTable() { + return certTable; + } + + public void useDefault() { + acceptExpired.setSelected(Default.getBoolean(Default.ACCEPT_EXPIRED)); + acceptNotValidYet.setSelected(Default.getBoolean(Default.ACCEPT_NOT_VALID_YET)); + acceptSelfSigned.setSelected(Default.getBoolean(Default.ACCEPT_SELF_SIGNED)); + acceptRevoked.setSelected(Default.getBoolean(Default.ACCEPT_REVOKED)); + checkCRL.setSelected(Default.getBoolean(Default.CHECK_CRL)); + checkOCSP.setSelected(Default.getBoolean(Default.CHECK_OCSP)); + allowSoftFail.setSelected(Default.getBoolean(Default.ALLOW_SOFT_FAIL)); + + acceptExpired.setEnabled(true); + acceptNotValidYet.setEnabled(true); + acceptSelfSigned.setEnabled(true); + acceptRevoked.setEnabled(true); + checkCRL.setEnabled(true); + checkOCSP.setEnabled(true); + allowSoftFail.setEnabled(true); + } + + public void saveSettings() { + localPreferences.setAcceptExpired(acceptExpired.isSelected()); + localPreferences.setAcceptNotValidYet(acceptNotValidYet.isSelected()); + localPreferences.setAcceptSelfSigned(acceptSelfSigned.isSelected()); + localPreferences.setAcceptRevoked(acceptRevoked.isSelected()); + localPreferences.setCheckCRL(checkCRL.isSelected()); + localPreferences.setCheckOCSP(checkOCSP.isSelected()); + localPreferences.setAllowSoftFail(allowSoftFail.isSelected()); + certControll.overWriteKeyStores(); + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/login/GSSAPIConfiguration.java b/core/src/main/java/org/jivesoftware/spark/ui/login/GSSAPIConfiguration.java new file mode 100644 index 000000000..126cdf67f --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/login/GSSAPIConfiguration.java @@ -0,0 +1,89 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.spark.ui.login; + +import javax.security.auth.login.AppConfigurationEntry; +import javax.security.auth.login.Configuration; +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; + + +public class GSSAPIConfiguration extends Configuration +{ + Map> configs; + + public GSSAPIConfiguration() + { + super(); + init( true ); + } + + public GSSAPIConfiguration( boolean config_from_file ) + { + super(); + init( config_from_file ); + } + + private void init( boolean config_from_file ) + { + configs = new HashMap<>(); + + //The structure of the options is not well documented in terms of + //data types. Since the file version of the Configuration object + //puts things in quotes, String is assumed. But boolean options + //do not have quotes, and my represent different types internally. + HashMap c_options = new HashMap<>(); + + //If Kerberos config is not from a file, it's not possible to (re-)read the config file. + //So don't set refreshKrb5Config + if ( config_from_file ) + { + c_options.put( "refreshKrb5Config", "true" ); + } + c_options.put( "doNotPrompt", "true" ); + c_options.put( "useTicketCache", "true" ); + c_options.put( "debug", "true" ); + + putAppConfigurationEntry( "com.sun.security.jgss.initiate", "com.sun.security.auth.module.Krb5LoginModule", AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, c_options ); + putAppConfigurationEntry( "com.sun.security.jgss.krb5.initiate", "com.sun.security.auth.module.Krb5LoginModule", AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, c_options ); + } + + @Override + public AppConfigurationEntry[] getAppConfigurationEntry( String name ) + { + AppConfigurationEntry[] a = new AppConfigurationEntry[ 1 ]; + Vector v = configs.get( name ); + if ( v != null ) + { + a = v.toArray( a ); + return a; + } + else + { + return null; + } + } + + public boolean putAppConfigurationEntry( String name, String module, AppConfigurationEntry.LoginModuleControlFlag controlFlag, Map options ) + { + Vector v = configs.computeIfAbsent(name, k -> new Vector<>()); + + return v.add( new AppConfigurationEntry( module, controlFlag, options ) ); + } + +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/login/GeneralLoginSettingsPanel.java b/core/src/main/java/org/jivesoftware/spark/ui/login/GeneralLoginSettingsPanel.java new file mode 100644 index 000000000..98dcd558d --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/login/GeneralLoginSettingsPanel.java @@ -0,0 +1,250 @@ +package org.jivesoftware.spark.ui.login; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.sparkimpl.settings.JiveInfo; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.net.InetAddress; +import java.net.UnknownHostException; + +import static java.awt.GridBagConstraints.*; + +/** + * Internal class to set General settings + */ +class GeneralLoginSettingsPanel extends JPanel implements ActionListener +{ + private final static Insets DEFAULT_INSETS = new Insets( 5, 5, 5, 5 ); + private final LocalPreferences localPreferences; + private final JDialog optionsDialog; + private final JCheckBox autoDiscoverBox = new JCheckBox(); + private final JTextField portField = new JTextField(); + private final JTextField xmppHostField = new JTextField(); + private final JTextField timeOutField = new JTextField(); + private final JTextField resourceField = new JTextField(); + private final JCheckBox useHostnameAsResourceBox = new JCheckBox(); + private final JCheckBox useVersionAsResourceBox = new JCheckBox(); + private final JCheckBox compressionBox = new JCheckBox(); + private final JCheckBox debuggerBox = new JCheckBox(); + + public GeneralLoginSettingsPanel( LocalPreferences localPreferences, JDialog optionsDialog ) + { + this.localPreferences = localPreferences; + this.optionsDialog = optionsDialog; + JLabel portLabel = new JLabel(); + ResourceUtils.resLabel( portLabel, portField, Res.getString( "label.port" ) ); + JLabel timeOutLabel = new JLabel(); + ResourceUtils.resLabel( timeOutLabel, timeOutField, Res.getString( "label.response.timeout" ) ); + JCheckBox autoLoginBox = new JCheckBox(); + ResourceUtils.resButton( autoLoginBox, Res.getString( "label.auto.login" ) ); + JLabel xmppHostLabel = new JLabel(); + ResourceUtils.resLabel( xmppHostLabel, xmppHostField, Res.getString( "label.host" ) ); + ResourceUtils.resButton( autoDiscoverBox, Res.getString( "checkbox.auto.discover.port" ) ); + JLabel resourceLabel = new JLabel(); + ResourceUtils.resLabel( resourceLabel, resourceField, Res.getString( "label.resource" ) ); + ResourceUtils.resButton( useHostnameAsResourceBox, Res.getString( "checkbox.use.hostname.as.resource" ) ); + ResourceUtils.resButton( useVersionAsResourceBox, Res.getString( "checkbox.use.version.as.resource" ) ); + ResourceUtils.resButton( compressionBox, Res.getString( "checkbox.use.compression" ) ); + ResourceUtils.resButton( debuggerBox, Res.getString( "checkbox.use.debugger.on.startup" ) ); + portField.setText( Integer.toString( localPreferences.getXmppPort() ) ); + timeOutField.setText( Integer.toString( localPreferences.getTimeOut() ) ); + autoLoginBox.setSelected( localPreferences.isAutoLogin() ); + xmppHostField.setText( localPreferences.getXmppHost() ); + resourceField.setText( localPreferences.getResource() ); + + useHostnameAsResourceBox.addActionListener( this ); + useHostnameAsResourceBox.setSelected( localPreferences.isUseHostnameAsResource() ); + updateResourceHostname(); + + useVersionAsResourceBox.addActionListener( this ); + useVersionAsResourceBox.setSelected( localPreferences.isUseVersionAsResource() ); + updateResourceVersion(); + + resourceField.setEnabled(!(useHostnameAsResourceBox.isSelected() || useVersionAsResourceBox.isSelected())); + + autoDiscoverBox.addActionListener( this ); + + autoDiscoverBox.setSelected( !localPreferences.isHostAndPortConfigured() ); + updateAutoDiscovery(); + + compressionBox.setSelected( localPreferences.isCompressionEnabled() ); + + debuggerBox.setSelected( localPreferences.isDebuggerEnabled() ); + + final JPanel connectionPanel = new JPanel(); + connectionPanel.setLayout( new GridBagLayout() ); + connectionPanel.setBorder( BorderFactory.createTitledBorder( Res.getString( "group.connection" ) ) ); + + setLayout( new GridBagLayout() ); + + add( autoDiscoverBox, new GridBagConstraints( 0, 0, 2, 1, 1.0, 0.0, WEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + + connectionPanel.add( xmppHostLabel, new GridBagConstraints( 0, 0, 1, 1, 0.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + connectionPanel.add( xmppHostField, new GridBagConstraints( 1, 0, 1, 1, 1.0, 0.0, WEST, NONE, DEFAULT_INSETS, 200, 0 ) ); + connectionPanel.add( portLabel, new GridBagConstraints( 0, 1, 1, 1, 0.0, 0.0, WEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + connectionPanel.add( portField, new GridBagConstraints( 1, 1, 1, 1, 1.0, 0.0, WEST, NONE, DEFAULT_INSETS, 50, 0 ) ); + + add( connectionPanel, new GridBagConstraints( 0, 1, 3, 1, 1.0, 0.0, NORTHWEST, BOTH, DEFAULT_INSETS, 0, 0 ) ); + + if ( Default.getBoolean( Default.USE_HOSTNAME_AS_RESOURCE ) == Default.getBoolean( Default.USE_VERSION_AS_RESOURCE ) ) + { + add( resourceLabel, new GridBagConstraints( 0, 2, 1, 1, 0.0, 0.0, WEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + add( resourceField, new GridBagConstraints( 1, 2, 1, 1, 0.0, 0.0, WEST, NONE, DEFAULT_INSETS, 100, 0 ) ); + add( useHostnameAsResourceBox, new GridBagConstraints( 0, 3, 2, 1, 0.0, 0.0, WEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + add( useVersionAsResourceBox, new GridBagConstraints( 0, 4, 2, 1, 0.0, 0.0, WEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + } + add( timeOutLabel, new GridBagConstraints( 0, 5, 1, 1, 0.0, 0.0, WEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + add( timeOutField, new GridBagConstraints( 1, 5, 1, 1, 0.0, 0.0, WEST, NONE, DEFAULT_INSETS, 50, 0 ) ); + add( compressionBox, new GridBagConstraints( 0, 6, 2, 1, 0.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + add( debuggerBox, new GridBagConstraints( 0, 7, 2, 1, 0.0, 1.0, NORTHWEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + } + + /** + * Updates local preferences with auto discovery settings. + */ + private void updateAutoDiscovery() + { + boolean isSelected = autoDiscoverBox.isSelected(); + xmppHostField.setEnabled( !isSelected ); + portField.setEnabled( !isSelected ); + localPreferences.setHostAndPortConfigured( !isSelected ); + } + + /** + * Updates resource settings. + */ + private void updateResourceHostname() + { + boolean isSelected = useHostnameAsResourceBox.isSelected(); + try + { + if ( isSelected ) + { + String resource = InetAddress.getLocalHost().getHostName(); + resourceField.setText( resource ); + useVersionAsResourceBox.setSelected( false ); + } + resourceField.setEnabled( !isSelected ); + } + catch ( UnknownHostException e ) + { + UIManager.put( "OptionPane.okButtonText", Res.getString( "ok" ) ); + JOptionPane.showMessageDialog( optionsDialog, + Res.getString( "message.unable.to.use.hostname.as.resource" ), + Res.getString( "title.error" ), + JOptionPane.ERROR_MESSAGE ); + } + //localPreferences.setHostAndPortConfigured(!isSelected); + } + + private void updateResourceVersion() + { + boolean isSelected = useVersionAsResourceBox.isSelected(); + if ( isSelected ) + { + String resource = JiveInfo.getName() + " " + JiveInfo.getVersion(); + resourceField.setText( resource ); + useHostnameAsResourceBox.setSelected( false ); + } + resourceField.setEnabled( !isSelected ); + //localPreferences.setHostAndPortConfigured(!isSelected); + } + + @Override + public void actionPerformed( ActionEvent e ) + { + if ( e.getSource() == autoDiscoverBox ) + { + updateAutoDiscovery(); + } + else if ( e.getSource() == useHostnameAsResourceBox ) + { + updateResourceHostname(); + } + else if ( e.getSource() == useVersionAsResourceBox ) + { + updateResourceVersion(); + } + } + + public boolean validate_settings() + { + String timeOut = timeOutField.getText(); + String port = portField.getText(); + String resource = resourceField.getText(); + + boolean valid = true; + UIManager.put( "OptionPane.okButtonText", Res.getString( "ok" ) ); + + try + { + Integer.valueOf( timeOut ); + } + catch ( NumberFormatException numberFormatException ) + { + JOptionPane.showMessageDialog( optionsDialog, + Res.getString( "message.supply.valid.timeout" ), + Res.getString( "title.error" ), + JOptionPane.ERROR_MESSAGE ); + timeOutField.requestFocus(); + valid = false; + } + + try + { + Integer.valueOf( port ); + } + catch ( NumberFormatException numberFormatException ) + { + JOptionPane.showMessageDialog( optionsDialog, + Res.getString( "message.supply.valid.port" ), + Res.getString( "title.error" ), + JOptionPane.ERROR_MESSAGE ); + portField.requestFocus(); + valid = false; + } + + if ( !ModelUtil.hasLength( resource ) ) + { + JOptionPane.showMessageDialog( optionsDialog, + Res.getString( "message.supply.resource" ), + Res.getString( "title.error" ), + JOptionPane.ERROR_MESSAGE ); + resourceField.requestFocus(); + valid = false; + } + + return valid; + } + + public void useDefault(){ + autoDiscoverBox.setSelected(!Default.getBoolean(Default.HOST_AND_PORT_CONFIGURED)); + useHostnameAsResourceBox.setSelected(Default.getBoolean(Default.USE_HOSTNAME_AS_RESOURCE)); + useVersionAsResourceBox.setSelected(Default.getBoolean(Default.USE_VERSION_AS_RESOURCE)); + compressionBox.setSelected(Default.getBoolean(Default.COMPRESSION_ENABLED)); + debuggerBox.setSelected(Default.getBoolean(Default.DEBUGGER_ENABLED)); + portField.setText(Default.getString(Default.XMPP_PORT)); + resourceField.setText(Default.getString(Default.SHORT_NAME)); + timeOutField.setText(Default.getString(Default.TIME_OUT)); + } + + public void saveSettings() + { + localPreferences.setTimeOut( Integer.parseInt( timeOutField.getText() ) ); + localPreferences.setXmppPort( Integer.parseInt( portField.getText() ) ); + localPreferences.setXmppHost( xmppHostField.getText() ); + localPreferences.setCompressionEnabled( compressionBox.isSelected() ); + localPreferences.setDebuggerEnabled( debuggerBox.isSelected() ); + localPreferences.setResource( resourceField.getText() ); + localPreferences.setUseHostnameAsResource( useHostnameAsResourceBox.isSelected() ); + localPreferences.setUseVersionAsResource( useVersionAsResourceBox.isSelected() ); + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/login/LoginSettingDialog.java b/core/src/main/java/org/jivesoftware/spark/ui/login/LoginSettingDialog.java new file mode 100644 index 000000000..b5b8c2a0b --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/login/LoginSettingDialog.java @@ -0,0 +1,188 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.login; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.component.TitlePanel; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import javax.swing.*; +import java.awt.*; +import java.awt.Dialog.ModalityType; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * Allows users to configure startup options. + * + * @author Derek DeMoro + * @author Jay Kline + */ +public class LoginSettingDialog implements PropertyChangeListener +{ + private JDialog optionsDialog; + private JOptionPane optionPane; + + private final JTabbedPane tabbedPane = new JTabbedPane(); + + private final GeneralLoginSettingsPanel generalPanel; + private final SecurityLoginSettingsPanel securityPanel; + private final ProxyLoginSettingsPanel proxyPanel; + private final SsoLoginSettingsPanel ssoPanel; + private final CertificatesManagerSettingsPanel certManagerPanel; + private final MutualAuthenticationSettingsPanel mutAuthPanel; + + /** + * Empty Constructor. + */ + public LoginSettingDialog() + { + LocalPreferences localPreferences = SettingsManager.getLocalPreferences(); + generalPanel = new GeneralLoginSettingsPanel( localPreferences, optionsDialog ); + proxyPanel = new ProxyLoginSettingsPanel( localPreferences, optionsDialog ); + securityPanel = new SecurityLoginSettingsPanel( localPreferences, optionsDialog ); + ssoPanel = new SsoLoginSettingsPanel( localPreferences, optionsDialog ); + certManagerPanel = new CertificatesManagerSettingsPanel(localPreferences, optionsDialog); + mutAuthPanel = new MutualAuthenticationSettingsPanel(localPreferences, optionsDialog); + } + + /** + * Invokes the OptionsDialog. + * + * @param owner the parent owner of this dialog. This is used for correct + * parenting. + * @return true if the options have been changed. + */ + public boolean invoke( JFrame owner ) + { + TitlePanel titlePanel; + + // Create the title panel for this dialog + titlePanel = new TitlePanel(Res.getString("title.advanced.connection.preferences"), "", SparkRes.getImageIcon(SparkRes.Icon.BLANK_24x24), true); + tabbedPane.addTab( Res.getString( "tab.general" ), generalPanel ); + tabbedPane.addTab( Res.getString( "tab.security" ), securityPanel ); + if ( !Default.getBoolean( Default.PROXY_DISABLED ) ) + { + tabbedPane.addTab( Res.getString( "tab.proxy" ), proxyPanel ); + } + if ( !Default.getBoolean( Default.SSO_DISABLED ) ) + { + tabbedPane.addTab( Res.getString( "tab.sso" ), ssoPanel ); + } + if ( !Default.getBoolean(Default.CERTIFICATES_MANAGER_DISABLED)) + { + tabbedPane.addTab( Res.getString( "tab.certificates" ), certManagerPanel ); + } + if ( !Default.getBoolean( Default.MUTUAL_AUTH_DISABLED)){ + tabbedPane.addTab( Res.getString("tab.mutual.auth"), mutAuthPanel); + } + // Construct main panel w/ layout. + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout( new BorderLayout() ); + mainPanel.add( titlePanel, BorderLayout.NORTH ); + + // The user should only be able to close this dialog. + Object[] options = { Res.getString( "ok" ), Res.getString( "cancel" ), Res.getString( "use.default" ) }; + optionPane = new JOptionPane( tabbedPane, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[ 0 ] ); + + mainPanel.add( optionPane, BorderLayout.CENTER ); + + optionsDialog = new JDialog( owner, Res.getString( "title.preferences" ), true ); + optionsDialog.setModalityType(ModalityType.DOCUMENT_MODAL); + optionsDialog.setContentPane( mainPanel ); + optionsDialog.pack(); + + optionsDialog.setLocationRelativeTo( owner ); + optionPane.addPropertyChangeListener( this ); + + optionsDialog.setResizable( false ); + optionsDialog.setVisible( true ); + optionsDialog.toFront(); + optionsDialog.requestFocus(); + + return true; + } + + /** + * PropertyChangeEvent is called when the user either clicks the Cancel or + * OK button. + * + * @param e the property change event. + */ + @Override + public void propertyChange( PropertyChangeEvent e ) + { + // The event is fired to often - for example when disposing a dialog, after settings have already been saved. + // This causes settings to, again, be saved based on the configuration of the options dialog (which by this time + // are outdated). A work-around is provided below, to only process changes on events that were fired while the + // dialog was actually still visible. See SPARK-2079 + if (!optionsDialog.isVisible()) { + return; + } + String value = (String) optionPane.getValue(); + if ( Res.getString( "cancel" ).equals( value ) ) + { + optionsDialog.setVisible( false ); + } + else if ( Res.getString( "ok" ).equals( value ) ) + { + boolean valid = generalPanel.validate_settings(); + valid = valid && securityPanel.validate_settings(); + valid = valid && proxyPanel.validate_settings(); + valid = valid && ssoPanel.validate_settings(); + + if ( valid ) + { + generalPanel.saveSettings(); + securityPanel.saveSettings(); + proxyPanel.saveSettings(); + ssoPanel.saveSettings(); + certManagerPanel.saveSettings(); + mutAuthPanel.saveSettings(); + optionsDialog.setVisible( false ); + } + else + { + optionPane.removePropertyChangeListener( this ); + optionPane.setValue( JOptionPane.UNINITIALIZED_VALUE ); + optionPane.addPropertyChangeListener( this ); + } + } else if (Res.getString("use.default").equals(value)) { + if (tabbedPane.getSelectedComponent().equals(generalPanel)) { + generalPanel.useDefault(); + } else if (tabbedPane.getSelectedComponent().equals(securityPanel)) { + securityPanel.useDefault(); + } else if (tabbedPane.getSelectedComponent().equals(proxyPanel)) { + proxyPanel.useDefault(); + } else if (tabbedPane.getSelectedComponent().equals(ssoPanel)) { + ssoPanel.useDefault(); + } else if (tabbedPane.getSelectedComponent().equals(certManagerPanel)) { + certManagerPanel.useDefault(); + } + + optionPane.removePropertyChangeListener( this ); + optionPane.setValue( JOptionPane.UNINITIALIZED_VALUE ); + optionPane.addPropertyChangeListener( this ); + + } else { + // Some unknown operation happened + optionPane.setValue( JOptionPane.UNINITIALIZED_VALUE ); + } + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/login/MutualAuthenticationSettingsPanel.java b/core/src/main/java/org/jivesoftware/spark/ui/login/MutualAuthenticationSettingsPanel.java new file mode 100644 index 000000000..13c4efdfa --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/login/MutualAuthenticationSettingsPanel.java @@ -0,0 +1,288 @@ +package org.jivesoftware.spark.ui.login; + +import static java.awt.GridBagConstraints.HORIZONTAL; +import static java.awt.GridBagConstraints.WEST; + +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.HeadlessException; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.io.File; +import java.io.IOException; +import java.security.KeyPair; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; + +import javax.naming.InvalidNameException; +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.ScrollPaneConstants; +import javax.swing.filechooser.FileNameExtensionFilter; + +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.certificates.IdentityController; +import org.jivesoftware.sparkimpl.certificates.PemHelper; +import org.jivesoftware.sparkimpl.certificates.PemHelper.PemBuilder; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +public class MutualAuthenticationSettingsPanel extends JPanel implements ActionListener, MouseListener { + private final static Insets DEFAULT_INSETS = new Insets(5, 5, 5, 5); + + private final IdentityController idControll; + + private static JTable idTable; + private static JScrollPane scrollPane; + + private final JFileChooser fileChooser = new JFileChooser(); + private final JButton addCertButton = new JButton(); + private final JButton showCert = new JButton(); + + private final JPanel uploadCertificatePanel = new JPanel(); + private final JPanel creationPanel = new JPanel(); + + private final JRadioButton selfSignedCertificate = new JRadioButton(); + private final JRadioButton certificateSigningRequest = new JRadioButton(); + private final JCheckBox saveCertToFile = new JCheckBox(); + private final JButton createButton = new JButton(); + + private final JTextField commonNameField = new JTextField(); + private final JTextField organizationUnitField = new JTextField(); + private final JTextField organizationField = new JTextField(); + private final JTextField countryField = new JTextField(); + private final JTextField cityField = new JTextField(); + + private final JLabel commonNameLabel = new JLabel(); + private final JLabel organizationUnitLabel = new JLabel(); + private final JLabel organizationLabel = new JLabel(); + private final JLabel countryLabel = new JLabel(); + private final JLabel cityLabel = new JLabel(); + private final ButtonGroup radioGroup = new ButtonGroup(); + //current Spark version support only .pem format of RSA private key with certificate + private final FileNameExtensionFilter certFilter = new FileNameExtensionFilter(Res.getString("menuitem.certificate.files.filter"),"pem"); + + public MutualAuthenticationSettingsPanel(LocalPreferences localPreferences, JDialog optionsDialog) { + setLayout(new GridBagLayout()); + + idControll = new IdentityController(localPreferences); + idTable = new JTable(idControll.getTableModel()); + idTable.addMouseListener(this); + idTable.setPreferredSize(new Dimension(50, 50)); + idTable.setPreferredScrollableViewportSize(idTable.getPreferredSize()); + idTable.setFillsViewportHeight(true); + scrollPane = new JScrollPane(idTable); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + + ResourceUtils.resButton(addCertButton, Res.getString("label.choose.file")); + + ResourceUtils.resButton(selfSignedCertificate, Res.getString("cert.self.signed")); + ResourceUtils.resButton(certificateSigningRequest, Res.getString("cert.sign.request")); + ResourceUtils.resButton(saveCertToFile, Res.getString("cert.self.signed.save.to.file")); + + ResourceUtils.resLabel( commonNameLabel, commonNameField, Res.getString("cert.common.name")); + ResourceUtils.resLabel( organizationUnitLabel, organizationUnitField, Res.getString("cert.organization.unit")); + ResourceUtils.resLabel( organizationLabel, organizationField, Res.getString("cert.organization")); + ResourceUtils.resLabel( countryLabel, countryField, Res.getString("cert.country")); + ResourceUtils.resLabel( cityLabel, cityField, Res.getString("cert.city")); + + ResourceUtils.resButton(createButton, Res.getString("create")); + ResourceUtils.resButton(showCert, Res.getString("button.show.certificate")); + + + uploadCertificatePanel.setLayout(new GridBagLayout()); + uploadCertificatePanel.setBorder(BorderFactory.createTitledBorder(Res.getString("label.certificate.add.certificate.to.identitystore"))); + uploadCertificatePanel.add(addCertButton, new GridBagConstraints(0, 0, 1, 1, 0.05, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + radioGroup.add(selfSignedCertificate); + radioGroup.add(certificateSigningRequest); + + selfSignedCertificate.addActionListener(this); + certificateSigningRequest.addActionListener(this); + + certificateSigningRequest.setSelected(true); + saveCertToFile.setEnabled(false); + + creationPanel.setLayout(new GridBagLayout()); + + creationPanel.add(certificateSigningRequest, new GridBagConstraints(0, 0, 1, 1, 0.3, 1.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + creationPanel.add(selfSignedCertificate, new GridBagConstraints(1, 0, 1, 1, 0.3, 1.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + creationPanel.add(saveCertToFile, new GridBagConstraints(2, 0, 1, 1, 0.4, 1.0, WEST, HORIZONTAL, DEFAULT_INSETS, 200, 0)); + + creationPanel.add(commonNameLabel, new GridBagConstraints(0, 1, 1, 1, 0.05, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + creationPanel.add(organizationUnitLabel, new GridBagConstraints(0, 2, 1, 1, 0.05, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + creationPanel.add(organizationLabel, new GridBagConstraints(0, 3, 1, 1, 0.05, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + creationPanel.add(countryLabel, new GridBagConstraints(0, 4, 1, 1, 0.05, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + creationPanel.add(cityLabel, new GridBagConstraints(0, 5, 1, 1, 0.05, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + creationPanel.add(createButton, new GridBagConstraints(0, 6, 1, 1, 0.05, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + creationPanel.add(commonNameField, new GridBagConstraints(1, 1, 2, 1, 0.95, 1.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + creationPanel.add(organizationUnitField, new GridBagConstraints(1, 2, 2, 1, 0.95, 1.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + creationPanel.add(organizationField, new GridBagConstraints(1, 3, 2, 1, 0.95, 1.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + creationPanel.add(countryField, new GridBagConstraints(1, 4, 2, 1, 0.95, 1.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + creationPanel.add(cityField, new GridBagConstraints(1, 5, 2, 1, 0.95, 1.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + + add(scrollPane, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.3, WEST, GridBagConstraints.BOTH, DEFAULT_INSETS, 0, 0)); + add(uploadCertificatePanel, new GridBagConstraints(0, 1, 1, 1, 0.2, 0.2, WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 400), 0, 0)); + add(showCert, new GridBagConstraints(0, 2, 1, 1, 0.2, 0.2, WEST, HORIZONTAL, new Insets(5, 5, 5, 400), 0, 0)); + add(creationPanel, new GridBagConstraints(0, 3, 1, 6, 1.0, 0.5, WEST, GridBagConstraints.BOTH, DEFAULT_INSETS, 0, 0)); + + showCert.setEnabled(false); + showCert.addActionListener(this); + addCertButton.addActionListener(this); + createButton.addActionListener(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + if(e.getSource() == addCertButton){ + addCertificateByChoosingFile(); + } + if(e.getSource() == idTable){ + showCert.setEnabled(true); + } + if(e.getSource() == showCert){ + idControll.showCertificate(); + } + if (e.getSource() == certificateSigningRequest) { + saveCertToFile.setEnabled(false); + } + if (e.getSource() == selfSignedCertificate) { + saveCertToFile.setEnabled(true); + } + if (e.getSource() == createButton) { + if (certificateSigningRequest.isSelected()) { + createCertificateSignRequest(); + } else if (selfSignedCertificate.isSelected()) { + createSelfSignedCertificate(); + } + } + } + + private void createCertificateSignRequest() { + idControll.setUpData(commonNameField.getText(), organizationUnitField.getText(), organizationField.getText(), countryField.getText(), + cityField.getText()); + try { + KeyPair keyPair = idControll.createKeyPair(); + + PKCS10CertificationRequest request = idControll.createCSR(keyPair); + PemHelper.saveToPemFile(keyPair, IdentityController.KEY_FILE); + PemHelper.saveToPemFile(request, IdentityController.CSR_FILE); + JOptionPane.showMessageDialog(null, + Res.getString("dialog.certificate.request.has.been.created") + IdentityController.SECURITY_DIRECTORY.toString()); + } catch (OperatorCreationException | NoSuchAlgorithmException | IOException | NoSuchProviderException e1) { + Log.error("Couldn't create Certificate Signing Request", e1); + } + } + + private void createSelfSignedCertificate() { + idControll.setUpData(commonNameField.getText(), organizationUnitField.getText(), organizationField.getText(), countryField.getText(), + cityField.getText()); + try { + KeyPair keyPair = idControll.createKeyPair(); + + X509Certificate cert = idControll.createSelfSignedCertificate(keyPair); + if (saveCertToFile.isSelected()) { + PemBuilder pemBuilder = new PemBuilder(); + pemBuilder.add(keyPair.getPrivate()); + pemBuilder.add(cert); + pemBuilder.saveToPemFile(IdentityController.CERT_FILE); + JOptionPane.showMessageDialog(null, + Res.getString("dialog.self.signed.certificate.has.been.created") + IdentityController.SECURITY_DIRECTORY.toString()); + } else { + try { + idControll.addEntryToKeyStore(cert, keyPair.getPrivate()); + } catch (HeadlessException | InvalidNameException | KeyStoreException e) { + Log.error("Couldn't save entry to IdentityStore", e); + } + } + } catch (NoSuchAlgorithmException | NoSuchProviderException | IOException | OperatorCreationException | CertificateException e1) { + Log.error("Couldn't create Self Signed Certificate", e1); + } + } + + public static JTable getIdTable() { + return idTable; + } + + @Override + public void mouseClicked(MouseEvent e) { + // TODO Auto-generated method stub + } + + @Override + public void mouseEntered(MouseEvent e) { + // TODO Auto-generated method stub + } + + @Override + public void mouseExited(MouseEvent e) { + // TODO Auto-generated method stub + } + + @Override + public void mousePressed(MouseEvent e) { + if (e.getClickCount() == 2) { + if (e.getSource() == idTable) { + idControll.showCertificate(); + } + } + if (e.getSource() == idTable) { + showCert.setEnabled(true); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + + } + + private void addCertificateByChoosingFile() { + fileChooser.setAcceptAllFileFilterUsed(false); + fileChooser.addChoosableFileFilter(certFilter); + fileChooser.setFileFilter(certFilter); + + int retVal = fileChooser.showOpenDialog(this); + if (retVal == JFileChooser.APPROVE_OPTION) { + File file = fileChooser.getSelectedFile(); + try { + idControll.addEntryFileToKeyStore(file); + } catch (CertificateException e) { + JOptionPane.showMessageDialog(null, Res.getString("dialog.cannot.upload.certificate.might.be.ill.formatted")); + Log.error("Cannot upload certificate file", e); + } catch (InvalidKeySpecException | NoSuchAlgorithmException | KeyStoreException | InvalidNameException + | IOException e) { + JOptionPane.showMessageDialog(null, Res.getString("dialog.cannot.upload.certificate")); + Log.error("Cannot upload certificate file", e); + } + } + } + + public void saveSettings() { + idControll.overWriteKeyStores(); + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/login/ProxyLoginSettingsPanel.java b/core/src/main/java/org/jivesoftware/spark/ui/login/ProxyLoginSettingsPanel.java new file mode 100644 index 000000000..5a9ba406b --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/login/ProxyLoginSettingsPanel.java @@ -0,0 +1,313 @@ +package org.jivesoftware.spark.ui.login; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; + +import javax.swing.*; +import java.awt.*; +import java.util.Properties; + +import static java.awt.GridBagConstraints.*; + +/** + * Internal class to allow setting of proxies within Spark. + */ +class ProxyLoginSettingsPanel extends JPanel +{ + private final static Insets DEFAULT_INSETS = new Insets( 5, 5, 5, 5 ); + private final LocalPreferences localPreferences; + private final JCheckBox useProxyBox = new JCheckBox(); + private final JComboBox protocolBox = new JComboBox<>(); + private final JTextField hostField = new JTextField(); + private final JTextField portField = new JTextField(); + private final JTextField usernameField = new JTextField(); + private final JPasswordField passwordField = new JPasswordField(); + private final JDialog optionsDialog; + + public ProxyLoginSettingsPanel( LocalPreferences localPreferences, JDialog optionsDialog ) + { + this.localPreferences = localPreferences; + this.optionsDialog = optionsDialog; + final JLabel protocolLabel = new JLabel(); + final JLabel hostLabel = new JLabel(); + final JLabel portLabel = new JLabel(); + final JLabel usernameLabel = new JLabel(); + final JLabel passwordLabel = new JLabel(); + + protocolBox.addItem( "SOCKS" ); + protocolBox.addItem( "HTTP" ); + + ResourceUtils.resButton( useProxyBox, Res.getString( "checkbox.use.proxy.server" ) ); + ResourceUtils.resLabel( protocolLabel, protocolBox, Res.getString( "label.protocol" ) ); + ResourceUtils.resLabel( hostLabel, hostField, Res.getString( "label.host" ) ); + ResourceUtils.resLabel( portLabel, portField, Res.getString( "label.port" ) ); + ResourceUtils.resLabel( usernameLabel, usernameField, Res.getString( "label.username" ) ); + ResourceUtils.resLabel( passwordLabel, passwordField, Res.getString( "label.password" ) ); + + setLayout( new GridBagLayout() ); + add( useProxyBox, new GridBagConstraints( 0, 0, 2, 1, 1.0, 0.0, NORTHWEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + add( protocolLabel, new GridBagConstraints( 0, 1, 1, 1, 0.0, 0.0, NORTHWEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + add( protocolBox, new GridBagConstraints( 1, 1, 1, 1, 1.0, 0.0, NORTHWEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + add( hostLabel, new GridBagConstraints( 0, 2, 1, 1, 0.0, 0.0, NORTHWEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + add( hostField, new GridBagConstraints( 1, 2, 1, 1, 1.0, 0.0, NORTHWEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + add( portLabel, new GridBagConstraints( 0, 3, 1, 1, 0.0, 0.0, NORTHWEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + add( portField, new GridBagConstraints( 1, 3, 1, 1, 1.0, 0.0, NORTHWEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + add( usernameLabel, new GridBagConstraints( 0, 4, 1, 1, 0.0, 0.0, NORTHWEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + add( usernameField, new GridBagConstraints( 1, 4, 1, 1, 1.0, 0.0, NORTHWEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + add( passwordLabel, new GridBagConstraints( 0, 5, 1, 1, 0.0, 0.0, NORTHWEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + add( passwordField, new GridBagConstraints( 1, 5, 1, 1, 1.0, 1.0, NORTHWEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + + useProxyBox.addActionListener( e -> enableFields( useProxyBox.isSelected() ) ); + + // Check localSettings + if ( localPreferences.isProxyEnabled() ) + { + useProxyBox.setSelected( true ); + } + + enableFields( useProxyBox.isSelected() ); + + if ( ModelUtil.hasLength( localPreferences.getHost() ) ) + { + hostField.setText( localPreferences.getHost() ); + } + + if ( ModelUtil.hasLength( localPreferences.getPort() ) ) + { + portField.setText( localPreferences.getPort() ); + } + + if ( ModelUtil.hasLength( localPreferences.getProxyPassword() ) ) + { + passwordField.setText( localPreferences.getProxyPassword() ); + } + + if ( ModelUtil.hasLength( localPreferences.getProxyUsername() ) ) + { + usernameField.setText( localPreferences.getProxyUsername() ); + } + + if ( ModelUtil.hasLength( localPreferences.getProtocol() ) ) + { + protocolBox.setSelectedItem( localPreferences.getProtocol() ); + } + + if ( Default.getString( Default.PROXY_PROTOCOL ).length() > 0 ) + { + protocolBox.setSelectedItem( Default.getString( Default.PROXY_PROTOCOL ) ); + protocolBox.setEnabled( false ); + useProxyBox.setSelected( true ); + useProxyBox.setVisible( false ); + } + if ( Default.getString( Default.PROXY_HOST ).length() > 0 ) + { + hostField.setText( Default.getString( Default.PROXY_HOST ) ); + hostField.setEnabled( false ); + useProxyBox.setSelected( true ); + useProxyBox.setVisible( false ); + } + if ( Default.getString( Default.PROXY_PORT ).length() > 0 ) + { + portField.setText( Default.getString( Default.PROXY_PORT ) ); + portField.setEnabled( false ); + } + + } + + /** + * Enables the fields of the proxy panel. + * + * @param enable true if all fields should be enabled, otherwise false. + */ + private void enableFields( boolean enable ) + { + Component[] comps = getComponents(); + for ( Component comp1 : comps ) + { + if ( comp1 instanceof JTextField || comp1 instanceof JComboBox ) + { + JComponent comp = (JComponent) comp1; + comp.setEnabled( enable ); + } + } + } + + /** + * Returns the protocol to use for this proxy. + * + * @return the protocol. + */ + public String getProtocol() + { + return (String) protocolBox.getSelectedItem(); + } + + /** + * Returns the host to use for this proxy. + * + * @return the host. + */ + public String getHost() + { + return hostField.getText(); + } + + /** + * Returns the port to use with this proxy. + * + * @return the port to use. + */ + public String getPort() + { + return portField.getText(); + } + + /** + * Returns the username to use with this proxy. + * + * @return the username. + */ + public String getUsername() + { + return usernameField.getText(); + } + + /** + * Returns the password to use with this proxy. + * + * @return the password. + */ + public String getPassword() + { + return new String( passwordField.getPassword() ); + } + + public boolean validate_settings() + { + boolean valid = true; + + UIManager.put( "OptionPane.okButtonText", Res.getString( "ok" ) ); + + if ( useProxyBox.isSelected() ) + { + try + { + Integer.valueOf( portField.getText() ); + } + catch ( NumberFormatException numberFormatException ) + { + JOptionPane.showMessageDialog( optionsDialog, + Res.getString( "message.supply.valid.port" ), + Res.getString( "title.error" ), + JOptionPane.ERROR_MESSAGE ); + portField.requestFocus(); + valid = false; + } + + if ( !ModelUtil.hasLength( hostField.getText() ) ) + { + JOptionPane.showMessageDialog( optionsDialog, + Res.getString( "message.supply.valid.host" ), + Res.getString( "title.error" ), + JOptionPane.ERROR_MESSAGE ); + hostField.requestFocus(); + valid = false; + } + } + return valid; + } + + public void useDefault() { + useProxyBox.setSelected(Default.getBoolean(Default.PROXY_ENABLED)); + enableFields(useProxyBox.isSelected()); + } + + /** + * Persist the proxy settings to local preferences. + */ + public void saveSettings() + { + localPreferences.setProxyEnabled( useProxyBox.isSelected() ); + + if ( ModelUtil.hasLength( getProtocol() ) ) + { + localPreferences.setProtocol( getProtocol() ); + } + + if ( ModelUtil.hasLength( getHost() ) ) + { + localPreferences.setHost( getHost() ); + } + + if ( ModelUtil.hasLength( getPort() ) ) + { + localPreferences.setPort( getPort() ); + } + + if ( getUsername().equals( "" ) || getUsername() == null ) + { + localPreferences.setProxyUsername( "" ); + } + + if ( ModelUtil.hasLength( getUsername() ) ) + { + localPreferences.setProxyUsername( getUsername() ); + } + + if ( getPassword().equals( "" ) || getPassword() == null ) + { + localPreferences.setProxyPassword( "" ); + } + + if ( ModelUtil.hasLength( getPassword() ) ) + { + localPreferences.setProxyPassword( getPassword() ); + } + + if ( !localPreferences.isProxyEnabled() ) + { + Properties props = System.getProperties(); + props.remove( "socksProxyHost" ); + props.remove( "socksProxyPort" ); + props.remove( "http.proxyHost" ); + props.remove( "http.proxyPort" ); + props.remove( "http.proxySet" ); + } + else + { + String host = localPreferences.getHost(); + String port = localPreferences.getPort(); + String protocol = localPreferences.getProtocol(); + + boolean isValid = ModelUtil.hasLength( host ) && ModelUtil.hasLength( port ); + + if ( isValid ) + { + if ( protocol.equals( "SOCKS" ) ) + { + System.setProperty( "socksProxyHost", host ); + System.setProperty( "socksProxyPort", port ); + } + else + { + System.setProperty( "http.proxySet", "true" ); + + // Set https settings + System.setProperty( "https.proxyHost", host ); + System.setProperty( "https.proxyPort", port ); + + // Set http settings + System.setProperty( "http.proxyHost", host ); + System.setProperty( "http.proxyPort", port ); + } + } + else + { + localPreferences.setProxyEnabled( false ); + } + } + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/login/SecurityLoginSettingsPanel.java b/core/src/main/java/org/jivesoftware/spark/ui/login/SecurityLoginSettingsPanel.java new file mode 100644 index 000000000..5e6aa24e9 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/login/SecurityLoginSettingsPanel.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2017 Ignite Realtime Foundation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.spark.ui.login; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.ConnectionConfiguration; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import javax.swing.*; +import java.awt.*; + +import static java.awt.GridBagConstraints.*; + +/** + * Allows users to configure security-related settings. + * + * @author Guus der Kinderen, guus.der.kinderen@gmail.com + */ +public class SecurityLoginSettingsPanel extends JPanel +{ + private final static Insets DEFAULT_INSETS = new Insets( 5, 5, 5, 5 ); + + private final JDialog optionsDialog; + private final LocalPreferences localPreferences; + + // Radio buttons that configure the 'mode' of encryption. + private final JRadioButton modeRequiredRadio; + private final JRadioButton modeIfPossibleRadio; + private final JRadioButton modeDisabledRadio; + + // Checkbox that toggles between 'old' style Direct TLS (socket encryption, typically on port 5223), or STARTTLS. A check indicates 'old' behavior. + private final JCheckBox useDirectTlsBox; + + private final JCheckBox disableHostnameVerificationBox; + private final JCheckBox allowClientSideAuthentication; + + private final JButton deleteSavedPasswords; + + public SecurityLoginSettingsPanel( LocalPreferences localPreferences, JDialog optionsDialog ) + { + this.localPreferences = localPreferences; + this.optionsDialog = optionsDialog; + + setLayout( new GridBagLayout() ); + + // The titled-border panel labeled 'encryption mode' + final JPanel encryptionModePanel = new JPanel(); + encryptionModePanel.setLayout( new GridBagLayout() ); + encryptionModePanel.setBorder( BorderFactory.createTitledBorder( Res.getString( "group.encryption_mode" ) ) ); + + // The radio buttons that config the 'encryption mode' + modeRequiredRadio = new JRadioButton(); + modeRequiredRadio.setToolTipText( Res.getString( "tooltip.encryptionmode.required" ) ); + modeIfPossibleRadio = new JRadioButton(); + modeIfPossibleRadio.setToolTipText( Res.getString( "tooltip.encryptionmode.ifpossible" ) ); + modeDisabledRadio = new JRadioButton(); + modeDisabledRadio.setToolTipText( Res.getString( "tooltip.encryptionmode.disabled" ) ); + + useDirectTlsBox = new JCheckBox(); + disableHostnameVerificationBox = new JCheckBox(); + allowClientSideAuthentication = new JCheckBox(); + + deleteSavedPasswords = new JButton(); + deleteSavedPasswords.setEnabled( localPreferences.hasStoredPasswords() ); + + // .. Set labels/text for all the components. + ResourceUtils.resButton( modeRequiredRadio, Res.getString( "radio.encryptionmode.required" ) ); + ResourceUtils.resButton( modeIfPossibleRadio, Res.getString( "radio.encryptionmode.ifpossible" ) ); + ResourceUtils.resButton( modeDisabledRadio, Res.getString( "radio.encryptionmode.disabled" ) ); + ResourceUtils.resButton( useDirectTlsBox, Res.getString( "label.old.ssl" ) ); + ResourceUtils.resButton( disableHostnameVerificationBox, Res.getString( "checkbox.disable.hostname.verification" ) ); + ResourceUtils.resButton( allowClientSideAuthentication, Res.getString( "checkbox.allow.client.side.authentication" ) ); + ResourceUtils.resButton( deleteSavedPasswords, Res.getString( "button.delete.saved.passwords" ) ); + + // ... add the radio buttons to a group to make them interdependent. + final ButtonGroup modeGroup = new ButtonGroup(); + modeGroup.add( modeRequiredRadio ); + modeGroup.add( modeIfPossibleRadio ); + modeGroup.add( modeDisabledRadio ); + + // ... add event handler that disables the UI of encryption-related config, when encryption itself is disabled. + modeDisabledRadio.addChangeListener( e -> { + final boolean encryptionPossible = !modeDisabledRadio.isSelected(); + useDirectTlsBox.setEnabled( encryptionPossible ); + disableHostnameVerificationBox.setEnabled( encryptionPossible ); + allowClientSideAuthentication.setEnabled( encryptionPossible ); + } ); + + // ... apply the correct state, either based on saves settings, or defaults. + modeRequiredRadio.setSelected( localPreferences.getSecurityMode() == ConnectionConfiguration.SecurityMode.required ); + modeIfPossibleRadio.setSelected( localPreferences.getSecurityMode() == ConnectionConfiguration.SecurityMode.ifpossible ); + modeDisabledRadio.setSelected( localPreferences.getSecurityMode() == ConnectionConfiguration.SecurityMode.disabled ); + useDirectTlsBox.setSelected( localPreferences.isDirectTls() ); + disableHostnameVerificationBox.setSelected( localPreferences.isDisableHostnameVerification() ); + allowClientSideAuthentication.setSelected(true); + + // ... register click-handler that deletes stored passwords. + deleteSavedPasswords.addActionListener(actionEvent -> { + SettingsManager.getLocalPreferences().clearPasswordForAllUsers(); + deleteSavedPasswords.setEnabled(false); + }); + + // ... place the components on the titled-border panel. + encryptionModePanel.add( modeRequiredRadio, new GridBagConstraints( 0, 0, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + encryptionModePanel.add( modeIfPossibleRadio, new GridBagConstraints( 0, 1, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + encryptionModePanel.add( modeDisabledRadio, new GridBagConstraints( 0, 2, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + encryptionModePanel.add( useDirectTlsBox, new GridBagConstraints( 0, 3, 2, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + + // ... place the titled-border panel on the global panel. + add( encryptionModePanel, new GridBagConstraints( 0, 0, 1, 1, 1.0, 0.0, NORTHWEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + + // ... place the other components under the titled-border panel. + add( disableHostnameVerificationBox, new GridBagConstraints( 0, 1, 1, 1, 0.0, 0.0, NORTHWEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + add( allowClientSideAuthentication, new GridBagConstraints( 0, 2, 1, 1, 0.0, 0.0, NORTHWEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + add( deleteSavedPasswords, new GridBagConstraints( 0, 3, 1, 1, 0.0, 1.0, NORTHWEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + } + + public boolean validate_settings() + { + return true; + } + + public void useDefault() { + modeRequiredRadio.setSelected(Default.getString(Default.SECURITY_MODE).equals("required")); + modeIfPossibleRadio.setSelected(Default.getString(Default.SECURITY_MODE).equals("ifpossible")); + modeDisabledRadio.setSelected(Default.getString(Default.SECURITY_MODE).equals("disabled")); + disableHostnameVerificationBox.setSelected(Default.getBoolean(Default.DISABLE_HOSTNAME_VERIFICATION)); + allowClientSideAuthentication.setSelected(Default.getBoolean(Default.ALLOW_CLIENT_SIDE_AUTH)); + useDirectTlsBox.setSelected(Default.getBoolean(Default.OLD_SSL_ENABLED)); + } + + public void saveSettings() + { + if ( modeRequiredRadio.isSelected() ) + { + localPreferences.setSecurityMode( ConnectionConfiguration.SecurityMode.required ); + } + if ( modeIfPossibleRadio.isSelected() ) + { + localPreferences.setSecurityMode( ConnectionConfiguration.SecurityMode.ifpossible ); + } + if ( modeDisabledRadio.isSelected() ) + { + localPreferences.setSecurityMode( ConnectionConfiguration.SecurityMode.disabled ); + } + localPreferences.setDirectTls( useDirectTlsBox.isSelected() ); + localPreferences.setDisableHostnameVerification( disableHostnameVerificationBox.isSelected() ); + localPreferences.setAllowClientSideAuthentication( allowClientSideAuthentication.isSelected() ); + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/login/SsoLoginSettingsPanel.java b/core/src/main/java/org/jivesoftware/spark/ui/login/SsoLoginSettingsPanel.java new file mode 100644 index 000000000..9d17bbd55 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/login/SsoLoginSettingsPanel.java @@ -0,0 +1,266 @@ +package org.jivesoftware.spark.ui.login; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.component.WrappedLabel; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; + +import javax.security.auth.Subject; +import javax.security.auth.login.Configuration; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.security.Principal; + +import static java.awt.GridBagConstraints.*; + +/** + * Internal class to set SSO settings + */ +class SsoLoginSettingsPanel extends JPanel implements ActionListener +{ + private final static Insets DEFAULT_INSETS = new Insets( 5, 5, 5, 5 ); + private final LocalPreferences localPreferences; + private final JCheckBox useSSOBox = new JCheckBox(); + private final JTextField realmField = new JTextField(); + private final JTextField kdcField = new JTextField(); + private final JRadioButton methodFileRadio = new JRadioButton(); + private final JRadioButton methodDNSRadio = new JRadioButton(); + private final JRadioButton methodManualRadio = new JRadioButton(); + private final JCheckBox useSaslGssapiSmack3compatBox = new JCheckBox(); + private final JDialog optionsDialog; + + public SsoLoginSettingsPanel( LocalPreferences localPreferences, JDialog optionsDialog ) + { + this.localPreferences = localPreferences; + this.optionsDialog = optionsDialog; + + ResourceUtils.resButton( useSSOBox, Res.getString( "title.advanced.connection.usesso" ) ); + useSSOBox.addActionListener( this ); + ResourceUtils.resButton( useSaslGssapiSmack3compatBox, Res.getString( "title.advanced.connection.sso.smack3compat" ) ); + useSaslGssapiSmack3compatBox.addActionListener( this ); + + final WrappedLabel wrappedLabel = new WrappedLabel(); + String principalName = null; + try + { + principalName = getPrincipalName(); + } + catch ( Exception e ) + { + // Ignore + } + + if ( ModelUtil.hasLength( principalName ) ) + { + wrappedLabel.setText( Res.getString( "title.advanced.connection.sso.account", principalName ) ); + } + else + { + wrappedLabel.setForeground( Color.RED ); + wrappedLabel.setText( Res.getString( "title.advanced.connection.sso.noprincipal" ) ); + } + wrappedLabel.setBackground( Color.lightGray ); + + final String method = localPreferences.getSSOMethod(); + if ( ModelUtil.hasLength( method ) ) + { + switch ( method ) + { + case "dns": + methodDNSRadio.setSelected( true ); + break; + case "manual": + methodManualRadio.setSelected( true ); + break; + case "file": + default: + methodFileRadio.setSelected( true ); + break; + } + } + else + { + methodFileRadio.setSelected( true ); + } + + if ( ModelUtil.hasLength( localPreferences.getSSORealm() ) ) + { + realmField.setText( localPreferences.getSSORealm() ); + } + if ( ModelUtil.hasLength( localPreferences.getSSOKDC() ) ) + { + kdcField.setText( localPreferences.getSSOKDC() ); + } + + final JLabel methodFileLabel = new JLabel(); + final JLabel methodDNSLabel = new JLabel(); + final JLabel methodManualLabel = new JLabel(); + final JLabel realmLabel = new JLabel(); + final JLabel kdcLabel = new JLabel(); + + ResourceUtils.resLabel( methodFileLabel, methodFileRadio, Res.getString( "checkbox.use.krbconf" ) ); + ResourceUtils.resLabel( methodDNSLabel, methodDNSRadio, Res.getString( "checkbox.use.krb.dns" ) ); + ResourceUtils.resLabel( methodManualLabel, methodManualRadio, Res.getString( "checkbox.use.specify.below" ) ); + ResourceUtils.resLabel( realmLabel, realmField, Res.getString( "label.krb.realm" ) ); + ResourceUtils.resLabel( kdcLabel, kdcField, Res.getString( "label.krb.kdc" ) ); + + final ButtonGroup ssoMethodRadio = new ButtonGroup(); + ssoMethodRadio.add( methodFileRadio ); + ssoMethodRadio.add( methodDNSRadio ); + ssoMethodRadio.add( methodManualRadio ); + + setLayout( new GridBagLayout() ); + add( wrappedLabel, new GridBagConstraints( 0, 0, 3, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 10 ) ); + add( useSSOBox, new GridBagConstraints( 0, 1, 3, 1, 1.0, 0.0, WEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + add( methodFileRadio, new GridBagConstraints( 0, 2, 1, 1, 0.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + add( methodFileLabel, new GridBagConstraints( 1, 2, 2, 1, 1.0, 0.0, WEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + add( methodDNSRadio, new GridBagConstraints( 0, 3, 1, 1, 0.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + add( methodDNSLabel, new GridBagConstraints( 1, 3, 2, 1, 1.0, 0.0, WEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + add( methodManualRadio, new GridBagConstraints( 0, 4, 1, 1, 0.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + add( methodManualLabel, new GridBagConstraints( 1, 4, 2, 1, 1.0, 0.0, WEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + add( realmLabel, new GridBagConstraints( 1, 5, 1, 1, 0.0, 0.0, WEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + add( realmField, new GridBagConstraints( 2, 5, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + add( kdcLabel, new GridBagConstraints( 1, 6, 1, 1, 0.0, 0.0, WEST, NONE, DEFAULT_INSETS, 0, 0 ) ); + add( kdcField, new GridBagConstraints( 2, 6, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + add( useSaslGssapiSmack3compatBox, new GridBagConstraints( 0, 7, 3, 1, 1.0, 1.0, NORTHWEST, HORIZONTAL, DEFAULT_INSETS, 0, 0 ) ); + + useSSOBox.setSelected( localPreferences.isSSOEnabled() ); + useSaslGssapiSmack3compatBox.setSelected( localPreferences.isSaslGssapiSmack3Compatible() ); + + setFormEnabled( useSSOBox.isSelected() ); + } + + /** + * Returns the principal name if one exists. + * + * @return the name (ex. derek) of the principal. + */ + private String getPrincipalName() { + if ( localPreferences.getDebug() ) + { + System.setProperty( "java.security.krb5.debug", "true" ); + } + System.setProperty( "javax.security.auth.useSubjectCredsOnly", "false" ); + GSSAPIConfiguration config = new GSSAPIConfiguration( false ); + Configuration.setConfiguration( config ); + + LoginContext lc; + try + { + lc = new LoginContext( "com.sun.security.jgss.krb5.initiate" ); + lc.login(); + } + catch ( LoginException le ) + { + Log.debug( le.getMessage() ); + return null; + } + + Subject mySubject = lc.getSubject(); + + for ( Principal p : mySubject.getPrincipals() ) + { + String name = p.getName(); + int indexOne = name.indexOf( "@" ); + if ( indexOne != -1 ) + { + return name; + } + } + return null; + } + + @Override + public void actionPerformed( ActionEvent e ) + { + if ( e.getSource() == useSSOBox ) + { + setFormEnabled( useSSOBox.isSelected() ); + } + } + + private void setFormEnabled( boolean enabled ) + { + methodFileRadio.setEnabled( enabled ); + methodDNSRadio.setEnabled( enabled ); + methodManualRadio.setEnabled( enabled ); + realmField.setEnabled( enabled ); + kdcField.setEnabled( enabled ); + useSaslGssapiSmack3compatBox.setEnabled( enabled ); + } + + public boolean validate_settings() + { + boolean valid = true; + UIManager.put( "OptionPane.okButtonText", Res.getString( "ok" ) ); + + if ( useSSOBox.isSelected() ) + { + if ( methodManualRadio.isSelected() ) + { + if ( !ModelUtil.hasLength( realmField.getText() ) ) + { + JOptionPane.showMessageDialog( optionsDialog, + "You must specify a realm", + Res.getString( "title.error" ), + JOptionPane.ERROR_MESSAGE ); + realmField.requestFocus(); + valid = false; + } + if ( !ModelUtil.hasLength( kdcField.getText() ) ) + { + JOptionPane.showMessageDialog( optionsDialog, + "You must specify a KDC", + Res.getString( "title.error" ), + JOptionPane.ERROR_MESSAGE ); + kdcField.requestFocus(); + valid = false; + } + } + } + + return valid; + } + + public void useDefault(){ + useSSOBox.setSelected(Default.getBoolean(Default.USE_SSO)); + methodFileRadio.setSelected(Default.getString(Default.SSO_METHOD).equals("file")); + methodDNSRadio.setSelected(Default.getString(Default.SSO_METHOD).equals("dns")); + methodManualRadio.setSelected(Default.getString(Default.SSO_METHOD).equals("manual")); + setFormEnabled(useSSOBox.isSelected()); + useSaslGssapiSmack3compatBox.setSelected(Default.getBoolean(Default.USE_SASL_GSS_API_SMACK_3_COMPATIBLE)); + + + } + + public void saveSettings() + { + localPreferences.setSSOEnabled( useSSOBox.isSelected() ); + if ( methodFileRadio.isSelected() ) + { + localPreferences.setSSOMethod( "file" ); + } + else if ( methodDNSRadio.isSelected() ) + { + localPreferences.setSSOMethod( "dns" ); + } + else if ( methodManualRadio.isSelected() ) + { + localPreferences.setSSOMethod( "manual" ); + localPreferences.setSSORealm( realmField.getText() ); + localPreferences.setSSOKDC( kdcField.getText() ); + } + else + { + localPreferences.setSSOMethod( "file" ); + } + localPreferences.setSaslGssapiSmack3Compatible( useSaslGssapiSmack3compatBox.isSelected() ); + } +} diff --git a/src/java/org/jivesoftware/spark/ui/package.html b/core/src/main/java/org/jivesoftware/spark/ui/package.html similarity index 100% rename from src/java/org/jivesoftware/spark/ui/package.html rename to core/src/main/java/org/jivesoftware/spark/ui/package.html diff --git a/core/src/main/java/org/jivesoftware/spark/ui/preview/ImagePreview.java b/core/src/main/java/org/jivesoftware/spark/ui/preview/ImagePreview.java new file mode 100644 index 000000000..f0dc1b665 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/preview/ImagePreview.java @@ -0,0 +1,126 @@ +package org.jivesoftware.spark.ui.preview; + +import org.jivesoftware.spark.filetransfer.HttpDownloader; +import org.jivesoftware.spark.ui.ChatArea; +import org.jivesoftware.spark.util.log.Log; + +import javax.imageio.ImageIO; +import javax.swing.*; +import javax.swing.text.*; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.net.URI; +import java.net.URLConnection; + +import static org.jivesoftware.spark.ui.preview.LinkPreview.addLink; + +public class ImagePreview { + + /** + * Inserts a picture into the current document. + * + * @param url - the link to the content to insert e.g., https://example.org/hello.gif + * @throws BadLocationException if the location is not available for insertion. + */ + public static boolean insertPicture(ChatArea chatArea, String url, AttributeSet messageStyle) { + // TODO: instead of operating on message text content, operate on message stanza metadata. + // TODO: do not download each time. Cache downloaded data. + // TODO: make resized image clickable (open in unresized size). + if (url.startsWith("https://") || url.startsWith("http://")) { + // url with #anchor is definitely not an image + if (url.contains("#")) { + return false; + } + URI uri; + try { + uri = URI.create(url); + } catch (IllegalArgumentException ignored) { + Log.debug("Bad url " + url); + return false; + } + // check if this is a file + String path = uri.getPath(); + if (path == null || path.isEmpty()) { + return false; + } + // Check if the file extension is a known image type + String mimeType = URLConnection.getFileNameMap().getContentTypeFor(path); + if (mimeType == null || !mimeType.startsWith("image/")) { + return false; + } + + byte[] content = HttpDownloader.downloadContent(uri); + if (content == null) { + return false; + } + BufferedImage img; + try { + img = ImageIO.read(new java.io.ByteArrayInputStream(content)); + } catch (Exception e) { + Log.warning("Unable to load picture from " + url, e); + return false; + } + try { + if (img != null) { + SimpleAttributeSet center = new SimpleAttributeSet(); + StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER); + SimpleAttributeSet left = new SimpleAttributeSet(); + StyleConstants.setAlignment(left, StyleConstants.ALIGN_LEFT); + + final StyledDocument doc = (StyledDocument) chatArea.getDocument(); + + doc.insertString(doc.getLength(), "\n", messageStyle); + + final int width = Math.max(60, Math.round(chatArea.getParent().getWidth() * 0.70f)); + final int height = Math.max(60, Math.round(chatArea.getParent().getHeight() * 0.40f)); + ImageIcon image = scaleImage(new ImageIcon(img), width, height); + + int start = doc.getLength(); + + MutableAttributeSet inputAttributes = chatArea.getInputAttributes(); + inputAttributes.removeAttributes(inputAttributes); + StyleConstants.setIcon(inputAttributes, image); + chatArea.getDocument().insertString(doc.getLength(), " ", chatArea.getInputAttributes()); + inputAttributes.removeAttributes(inputAttributes); + doc.insertString(doc.getLength(), "\n", messageStyle); + + final MutableAttributeSet linkStyle = new SimpleAttributeSet(messageStyle.copyAttributes()); + addLink(doc, url, linkStyle); + int end = doc.getLength(); + final int length = end - start + 1; + doc.setParagraphAttributes(start, length, center, false); + + // No longer center. + //System.out.println("text: " + doc.getText(start, length)); + doc.setParagraphAttributes(doc.getLength() + 2, 0, left, false); + return true; + } + } catch (Throwable e) { + Log.warning("Unable to download content from " + url, e); + return false; + } + } + + return false; + } + + public static ImageIcon scaleImage(ImageIcon icon, int w, int h) { + try { + int nw = icon.getIconWidth(); + int nh = icon.getIconHeight(); + if (icon.getIconWidth() > w) { + nw = w; + nh = (nw * icon.getIconHeight()) / icon.getIconWidth(); + } + if (nh > h) { + nh = h; + nw = (icon.getIconWidth() * nh) / icon.getIconHeight(); + } + return new ImageIcon(icon.getImage().getScaledInstance(nw, nh, Image.SCALE_DEFAULT)); + } catch (Exception e) { + Log.warning("Unable to scale an image", e); + return null; + } + } + +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/preview/LinkPreview.java b/core/src/main/java/org/jivesoftware/spark/ui/preview/LinkPreview.java new file mode 100644 index 000000000..47f55376a --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/preview/LinkPreview.java @@ -0,0 +1,41 @@ +package org.jivesoftware.spark.ui.preview; + +import javax.swing.*; +import javax.swing.text.*; +import java.awt.*; + +public class LinkPreview { + + /** + * Inserts a link into the current document. + * + * @param link - the link to insert e.g., https://example.org/ + * @throws BadLocationException if the location is not available for insertion. + */ + public static boolean insertLink(Document doc, String link, AttributeSet style) + { + if ((link.startsWith("https://") || link.startsWith("http://") || + link.startsWith("ftp://") || + link.startsWith("www.") || + (link.startsWith("xmpp:") && link.contains("?join")) || + link.startsWith("file:/")) + && link.indexOf(".") > 1) { + + addLink(doc, link, style); + return true; + } + else { return false; } + } + + static void addLink(Document doc, String link, AttributeSet style) { + // Create a new style, based on the style used for generic text, for the link. + final MutableAttributeSet linkStyle = new SimpleAttributeSet(style.copyAttributes()); + StyleConstants.setForeground(linkStyle, (Color) UIManager.get("Link.foreground")); + StyleConstants.setUnderline(linkStyle, true); + linkStyle.addAttribute("link", link); + try { + doc.insertString(doc.getLength(), link, linkStyle); + } catch (BadLocationException ignored) { + } + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/preview/NetworkAddressPreview.java b/core/src/main/java/org/jivesoftware/spark/ui/preview/NetworkAddressPreview.java new file mode 100644 index 000000000..a37675fbf --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/preview/NetworkAddressPreview.java @@ -0,0 +1,33 @@ +package org.jivesoftware.spark.ui.preview; + +import javax.swing.*; +import javax.swing.text.*; +import java.awt.*; + +public class NetworkAddressPreview { + + /** + * Inserts a network address into the current document. + * + * @param address - the address to insert( ex. \superpc\etc\file\ OR http://localhost/ ) + * @throws BadLocationException if the location is not available for insertion. + */ + public static Boolean insertAddress(Document doc, String address, AttributeSet style) + { + if (address.startsWith("\\\\") || + (address.indexOf("://") > 0 && address.indexOf(".") < 1)) { + + // Create a new style, based on the style used for generic text, for the address. + final MutableAttributeSet addressStyle = new SimpleAttributeSet(style.copyAttributes()); + StyleConstants.setForeground(addressStyle, (Color) UIManager.get("Address.foreground")); + StyleConstants.setUnderline(addressStyle, true); + addressStyle.addAttribute("link", address); + try { + doc.insertString(doc.getLength(), address, addressStyle); + } catch (BadLocationException ignored) { + } + return true; + } + else { return false; } + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/preview/package.html b/core/src/main/java/org/jivesoftware/spark/ui/preview/package.html new file mode 100644 index 000000000..fbddae4f2 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/preview/package.html @@ -0,0 +1 @@ +Download and preview links in messages. diff --git a/core/src/main/java/org/jivesoftware/spark/ui/rooms/ChatRoomImpl.java b/core/src/main/java/org/jivesoftware/spark/ui/rooms/ChatRoomImpl.java new file mode 100644 index 000000000..c5c68252f --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/rooms/ChatRoomImpl.java @@ -0,0 +1,901 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.rooms; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.filter.*; +import org.jivesoftware.smack.packet.*; +import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smack.roster.RosterEntry; +import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smackx.carbons.packet.CarbonExtension; +import org.jivesoftware.smackx.chatstates.ChatState; +import org.jivesoftware.smackx.chatstates.packet.ChatStateExtension; +import org.jivesoftware.smackx.delay.packet.DelayInformation; +import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; +import org.jivesoftware.smackx.muc.packet.MUCUser; +import org.jivesoftware.smackx.xevent.MessageEventManager; +import org.jivesoftware.smackx.xevent.packet.MessageEvent; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.*; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; +import org.jivesoftware.sparkimpl.plugin.transcripts.ChatTranscript; +import org.jivesoftware.sparkimpl.plugin.transcripts.ChatTranscripts; +import org.jivesoftware.sparkimpl.plugin.transcripts.HistoryMessage; +import org.jivesoftware.sparkimpl.profile.VCardManager; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.*; +import org.jxmpp.jid.parts.Localpart; +import org.jxmpp.jid.parts.Resourcepart; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.text.DateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * This is the Person to Person implementation of ChatRoom + * This room only allows for 1 to 1 conversations. + */ +public class ChatRoomImpl extends ChatRoom { + private final CopyOnWriteArrayList messageEventListeners = new CopyOnWriteArrayList<>(); + private EntityBareJid roomname; + private Icon tabIcon; + private String roomTitle; + private String tabTitle; + + /** + * The participants XMPP address, can be a full or bare JID. + */ + private EntityJid participantJID; + + private final Resourcepart participantNickname; + + private Presence presence; + + private boolean offlineSent; + + private String threadID; + + private long lastActivity; + + private boolean active; + + // True if this is a one-on-one with a participant of a multi-user chatroom. + private final boolean privateChat; + + // Information button + private ChatRoomButton infoButton; + + private final ChatRoomButton addToRosterButton; + private VCardPanel vcardPanel; + + private JComponent chatStatePanel; + + public ChatRoomImpl(final EntityJid participantJID, Resourcepart participantNickname, CharSequence title) { + this(participantJID, participantNickname, title, true); + } + + /** + * Constructs a 1-to-1 ChatRoom. + * + * Note that the participantJID value can be a bare JID, or a full JID. In regular one-on-one chats, a bare JID is + * expected. This instance will then display relevant data sent by any of the (full) JIDs associated to the bare JID. + * When this instance is created to reflect a private message in MUC context, a full JID is expected to be provided + * as the participantJID value (room@service/nick). In such case, only data sent from that full JID is displayed. + * + * @param participantJID the participants jid to chat with. + * @param participantNickname the nickname of the participant. + * @param title the title of the room. + */ + public ChatRoomImpl(final EntityJid participantJID, Resourcepart participantNickname, CharSequence title, boolean initUi) { + Log.debug("Loading chat room impl: " + title); + this.active = true; + //activateNotificationTime = System.currentTimeMillis(); + setParticipantJID(participantJID); + this.participantNickname = participantNickname; + + // Loads the current history for this user. + SwingUtilities.invokeLater(this::loadHistory); + + // Register StanzaListeners + final StanzaFilter directFilter = new AndFilter( + FromMatchesFilter.create( participantJID ), + new OrFilter( new StanzaTypeFilter( Presence.class ), + new StanzaTypeFilter( Message.class ) ) + ); + + final StanzaFilter carbonFilter = new AndFilter( + FromMatchesFilter.create( SparkManager.getSessionManager().getUserBareAddress() ), // Security Consideration, see https://xmpp.org/extensions/xep-0280.html#security + new StanzaTypeFilter( Message.class ), + new OrFilter( + new StanzaExtensionFilter( "sent", CarbonExtension.NAMESPACE ), + new StanzaExtensionFilter( "received", CarbonExtension.NAMESPACE ) + ) + ); + + SparkManager.getConnection().addSyncStanzaListener( this, new OrFilter( directFilter, carbonFilter ) ); + + // Use the agents username as the Tab Title + this.tabTitle = title.toString(); + + // The name of the room will be the node of the user jid + conversation. + this.roomTitle = participantNickname.toString(); + + // Add RoomInfo + this.getSplitPane().setRightComponent(null); + getSplitPane().setDividerSize(0); + + + presence = PresenceManager.getPresence(participantJID.asBareJid()); + + Roster roster = SparkManager.getRoster(); + + RosterEntry entry = roster.getEntry(participantJID.asBareJid()); + + tabIcon = PresenceManager.getIconFromPresence(presence); + + if (initUi) { + // Create toolbar buttons. + infoButton = new ChatRoomButton("", SparkRes.getImageIcon(SparkRes.Icon.PROFILE_IMAGE_24x24)); + infoButton.setToolTipText(Res.getString("message.view.information.about.this.user")); + // Create basic toolbar. + addChatRoomButton(infoButton); + // Show VCard. + infoButton.addActionListener(this); + } + + // If this is a private chat from a group chat room, do not show toolbar. + privateChat = participantNickname.equals(participantJID.getResourceOrNull()); + if ( privateChat ) { + getToolBar().setVisible(false); + } + + // If the user is not in the roster, then allow user to add them. + addToRosterButton = new ChatRoomButton("", SparkRes.getImageIcon(SparkRes.Icon.ADD_IMAGE_24x24)); + if (entry == null && !privateChat) { + addToRosterButton.setToolTipText(Res.getString("message.add.this.user.to.your.roster")); + if (!Default.getBoolean(Default.ADD_CONTACT_DISABLED) && Enterprise.containsFeature(Enterprise.ADD_CONTACTS_FEATURE)) addChatRoomButton(addToRosterButton); + addToRosterButton.addActionListener(this); + } + + lastActivity = System.currentTimeMillis(); + Log.debug("Loaded chat room impl: " + title); + } + + /** + * Set the XMPP address of the participant. + * + * @param jid the XMPP address + */ + private void setParticipantJID(Jid jid) { + if (!jid.isEntityJid()) { + return; + } + participantJID = jid.asEntityJidOrThrow(); + roomname = participantJID.asEntityBareJid(); + } + + /** + * Returns true if this is a private chat from a group chat room. + * + * @return true if this this is a PM-based chat with one MUC participant, otherwise false. + */ + public boolean isPrivateChat() + { + return privateChat; + } + + @Override + public void closeChatRoom() { + // If already closed, don't bother. + if (!active) { + return; + } + + super.closeChatRoom(); + + removeListeners(); + + SparkManager.getChatManager().removeChat(this); + + SparkManager.getConnection().removeAsyncStanzaListener(this); + + active = false; + vcardPanel = null; + + this.removeAll(); + } + + protected void removeListeners() { + // Remove info listener + infoButton.removeActionListener(this); + addToRosterButton.removeActionListener(this); + SparkManager.getConnection().removeSyncStanzaListener(this); + } + + @Override + public void sendMessage() { + String text = getChatInputEditor().getText(); + sendMessage(text); + } + + @Override + public void sendMessage(String text) { + // Remove control characters + text = text.replaceAll("[\\u0001-\\u0008\\u000B-\\u001F]", ""); + // If the body is empty, just return and do nothing + if (!ModelUtil.hasLength(text)) { + return; + } + MessageBuilder messageBuilder = StanzaBuilder.buildMessage() + .setBody(text); + + if (threadID == null) { + threadID = StringUtils.randomString(6); + } + messageBuilder.setThread(threadID); + + if ( privateChat ) + { + // XEP-0045: 7.5 Sending a Private Message + messageBuilder.addExtension( new MUCUser() ); + } + + // Fire Message Filters + SparkManager.getChatManager().filterOutgoingMessage(this, messageBuilder); + + // Fire Global Filters + Message message = messageBuilder.build(); + SparkManager.getChatManager().fireGlobalMessageSentListeners(this, message); + + sendMessage(messageBuilder); + } + + /** + * Sends a message to the appropriate jid. The message is automatically added to the transcript. + * + * @param messageBuilder the message to send. + */ + @Override + public void sendMessage(MessageBuilder messageBuilder) { + //Before sending message, let's add our full jid for full verification + //Set message attributes before insertMessage is called - this is useful when transcript window is extended + //more information will be available to be displayed for the chat area Document + messageBuilder.ofType(Message.Type.chat); + // Set chat state to 'active' + messageBuilder.addExtension( new ChatStateExtension( ChatState.active ) ); + messageBuilder.to(participantJID); + messageBuilder.from(SparkManager.getSessionManager().getJID()); + Message message = messageBuilder.build(); + + displaySendMessage( message ); + + // No need to request displayed or delivered as we aren't doing anything with this + // information. + MessageEventManager.addNotificationsRequests(message, true, false, false, true); + + // Send the message that contains the notifications request + try { + fireOutgoingMessageSending(messageBuilder); + // rebuild message after all alterations + Message msgToSend = messageBuilder.build(); + SparkManager.getConnection().sendStanza(msgToSend); + } + catch (Exception ex) { + Log.error("Error sending message", ex); + } + } + + /** + * Adds a message that is to be sent to the transcript window. + * + * @param message The message to be displayed. + */ + private void displaySendMessage( Message message ) + { + lastActivity = System.currentTimeMillis(); + + try { + getTranscriptWindow().insertMessage( getNickname(), message, ChatManager.TO_COLOR); + getChatInputEditor().selectAll(); + + getTranscriptWindow().validate(); + getTranscriptWindow().repaint(); + getChatInputEditor().clear(); + } + catch (Exception ex) { + Log.error( "Error sending message", ex); + } + + // Notify users that message has been sent + fireMessageSent(message); + + addToTranscript(message, false); + + getChatInputEditor().setCaretPosition(0); + getChatInputEditor().requestFocusInWindow(); + scrollToBottom(); + } + + @Override + public EntityBareJid getBareJid() { + return roomname; + } + + + @Override + public Icon getTabIcon() { + return tabIcon; + } + + public void setTabIcon(Icon icon) { + this.tabIcon = icon; + } + + @Override + public String getTabTitle() { + return tabTitle; + } + + public void setTabTitle(String tabTitle) { + this.tabTitle = tabTitle; + } + + public void setRoomTitle(String roomTitle) { + this.roomTitle = roomTitle; + } + + @Override + public String getRoomTitle() { + return roomTitle; + } + + @Override + public Message.Type getChatType() { + return Message.Type.chat; + } + + @Override + public void leaveChatRoom() { + // There really is no such thing in Agent to Agent + } + + @Override + public boolean isActive() { + return true; + } + + /** + * Returns the Bare-Participant JID + * + * user@server.com
      + * for retrieving the full Jid use ChatRoomImpl.getJID() + * + * @return + */ + public EntityBareJid getParticipantJID() { + return participantJID.asEntityBareJid(); + } + + /** + * Returns the users full jid (ex. macbeth@jivesoftware.com/spark) or null if user is offline. + * + * @return the users Full JID. + */ + public EntityFullJid getJidOnline() { + presence = PresenceManager.getPresence(getParticipantJID()); + return presence.getFrom().asEntityFullJidIfPossible(); + } + + @Override + public EntityJid getJid() { + return participantJID; + } + + /** + * Process incoming packets. + * + * @param stanza - the packet to process + */ + @Override + public void processStanza(final Stanza stanza) { + final Runnable runnable = () -> { + try + { + if ( stanza instanceof Presence ) + { + + Presence.Type oldType = presence.getType(); + + presence = (Presence) stanza; + + final Presence presence1 = (Presence) stanza; + + ContactList list = SparkManager.getWorkspace().getContactList(); + ContactItem contactItem = list.getContactItemByJID( getParticipantJID() ); + + String time = DateFormat.getTimeInstance( DateFormat.SHORT ).format( new Date() ); + + if ( presence1.getType() == Presence.Type.unavailable && contactItem != null ) + { + getTranscriptWindow().insertNotificationMessage( "*** " + Res.getString( "message.went.offline", participantNickname, time ), ChatManager.NOTIFICATION_COLOR ); + } + else if ( oldType == Presence.Type.unavailable && presence1.getType() == Presence.Type.available ) + { + getTranscriptWindow().insertNotificationMessage( "*** " + Res.getString( "message.came.online", participantNickname, time ), ChatManager.NOTIFICATION_COLOR ); + } + } + else if ( stanza instanceof Message ) + { + lastActivity = System.currentTimeMillis(); + + + // Do something with the incoming packet here. + MessageBuilder msgBuilder = MessageBuilder.buildMessageFrom((Message) stanza, stanza.getStanzaId()); + fireReceivingIncomingMessage(msgBuilder); + Message message = msgBuilder.build(); + if ( message.getError() != null ) + { + if ( message.getError().getCondition() == StanzaError.Condition.item_not_found ) + { + Roster roster = SparkManager.getRoster(); + // Check to see if the user is online to recieve this message. + RosterEntry entry = roster.getEntry( participantJID.asBareJid() ); + if ( !presence.isAvailable() && !offlineSent && entry != null ) + { + getTranscriptWindow().insertNotificationMessage( Res.getString( "message.offline.error" ), ChatManager.ERROR_COLOR ); + offlineSent = true; + } + } + else + { + // Show a generic error if something went wrong: SPARK-1895. + getTranscriptWindow().insertNotificationMessage( Res.getString( "message.default.error" ) + ": " + message.getError().getCondition(), ChatManager.ERROR_COLOR ); + } + return; + } + + // Check to see if the user is online to recieve this message. + Roster roster = SparkManager.getRoster(); + RosterEntry entry = roster.getEntry( participantJID.asBareJid() ); + if ( !presence.isAvailable() && !offlineSent && entry != null ) + { + getTranscriptWindow().insertNotificationMessage( Res.getString( "message.offline" ), ChatManager.ERROR_COLOR ); + offlineSent = true; + } + + if ( threadID == null ) + { + threadID = message.getThread(); + if ( threadID == null ) + { + threadID = StringUtils.randomString( 6 ); + } + } + + final JivePropertiesExtension extension = message.getExtension(JivePropertiesExtension.class); + final boolean broadcast = extension != null && extension.getProperty( "broadcast" ) != null; + + // If this is a group chat message, discard + if ( message.getType() == Message.Type.groupchat || broadcast || message.getType() == Message.Type.normal || + message.getType() == Message.Type.headline ) + { + return; + } + + // Do not accept Administrative messages. + final DomainBareJid host = SparkManager.getSessionManager().getServerAddress(); + if ( host.equals( message.getFrom() ) ) + { + return; + } + + // Do not Handle offline messages. Offline messages are handling by Workspace. + if (message.hasExtension(DelayInformation.class) && + (message.getType() == Message.Type.chat || + message.getType() == Message.Type.normal)) { + return; + } + + final CarbonExtension carbon = CarbonExtension.from(message); + if ( carbon != null ) + { + // Is this a carbon copy? + final Message forwardedStanza = carbon.getForwarded().getForwardedStanza(); + if ( forwardedStanza.getBody() != null ) + { + if ( carbon.getDirection() == CarbonExtension.Direction.received ) + { + Jid forwardedStanzaJid = forwardedStanza.getFrom(); + if ((privateChat && forwardedStanzaJid.equals(getJid())) || //private chat from MUC, match the full JID + (!privateChat && forwardedStanzaJid.asBareJid().equals(getJid().asBareJid()))) // person-to-person chat, match bare jids + { + // This is a stanza that we received from someone on one of our other clients. + setParticipantJID(forwardedStanzaJid); + insertMessage( forwardedStanza ); + } + + } + else + { + Jid forwardedStanzaJid = forwardedStanza.getTo(); + if ((privateChat && forwardedStanzaJid.equals(getJid())) || //private chat from MUC, match full JID + (!privateChat && forwardedStanzaJid.asBareJid().equals(getJid().asBareJid()))) // person-to-person chat, match bare jids + { + // This is a stanza that one of our own clients sent. + setParticipantJID(forwardedStanzaJid); + displaySendMessage( forwardedStanza ); + } + + } + showTyping( false ); + } + } + else if ( message.getBody() != null ) + { + // If the message is not from the current agent. Append to chat. + setParticipantJID(message.getFrom()); + insertMessage( message ); + + showTyping( false ); + } + } + } + catch ( Exception e ) + { + Log.error( "An exception occurred while processing this incoming stanza: " + stanza, e ); + } + }; + SwingUtilities.invokeLater(runnable); + } + + /** + * Returns the nickname of the user chatting with. + * + * @return the nickname of the chatting user. + */ + public Resourcepart getParticipantNickname() { + return participantNickname; + } + + + /** + * The current SendField has been updated somehow. + * + * @param e - the DocumentEvent to respond to. + */ + @Override + public void insertUpdate(DocumentEvent e) { + super.insertUpdate( e ); + } + + @Override + public Message insertMessage(Message message) { + message = super.insertMessage(message); + MessageEvent messageEvent = message.getExtension(MessageEvent.class); + if (messageEvent != null) { + checkEvents(message.getFrom(), message.getStanzaId(), messageEvent); + } + + getTranscriptWindow().insertMessage(participantNickname, message, ChatManager.FROM_COLOR); + + // Set the participant jid to their full JID. + setParticipantJID(message.getFrom()); + return message; + } + + private void checkEvents(Jid from, String packetID, MessageEvent messageEvent) { + if (messageEvent.isDelivered() || messageEvent.isDisplayed()) { + // Create the message to send + MessageBuilder messageBuilder = StanzaBuilder.buildMessage(); + // Create a MessageEvent Package and add it to the message + MessageEvent event = new MessageEvent(); + if (messageEvent.isDelivered()) { + event.setDelivered(true); + } + if (messageEvent.isDisplayed()) { + event.setDisplayed(true); + } + event.setStanzaId(packetID); + messageBuilder.addExtension(event); + messageBuilder.from(from); + Message msg = messageBuilder.build(); + // Send the packet + try + { + SparkManager.getConnection().sendStanza(msg); + } + catch ( SmackException.NotConnectedException | InterruptedException e ) + { + Log.warning( "Unable to send message to " + msg.getTo(), e ); + } + } + } + + public void addMessageEventListener(MessageEventListener listener) { + messageEventListeners.addIfAbsent(listener); + } + + public void removeMessageEventListener(MessageEventListener listener) { + messageEventListeners.remove(listener); + } + + public Collection getMessageEventListeners() { + return messageEventListeners; + } + + public void fireOutgoingMessageSending(MessageBuilder message) + { + for ( final MessageEventListener listener : messageEventListeners ) + { + try + { + listener.sendingMessage( message ); + } + catch ( Exception e ) + { + Log.error( "A MessageEventListener ('" + listener + "') threw an exception while processing an outgoing message (to '" + message.getTo() + "').", e ); + } + } + } + + public void fireReceivingIncomingMessage(MessageBuilder message) + { + for ( final MessageEventListener listener : messageEventListeners ) + { + try + { + listener.receivingMessage( message ); + } + catch ( Exception e ) + { + Log.error( "A MessageEventListener ('" + listener + "') threw an exception while processing an incoming message (from '" + message.getFrom() + "').", e ); + } + } + } + + + /** + * Show the typing notification. + * + * @param typing true if the typing notification should show, otherwise hide it. + */ + public void showTyping(boolean typing) { + if (typing) { + String isTypingText = Res.getString("message.is.typing.a.message", participantNickname); + getNotificationLabel().setText(isTypingText); + getNotificationLabel().setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_MESSAGE_EDIT_IMAGE)); + } + else { + // Remove is typing text. + getNotificationLabel().setText(""); + getNotificationLabel().setIcon(SparkRes.getImageIcon(SparkRes.Icon.BLANK_IMAGE)); + } + + } + + /** + * The last time this chat room sent or received a message. + * + * @return the last time this chat room sent or receieved a message.sendChatState + */ + @Override + public long getLastActivity() { + return lastActivity; + } + + /** + * Returns the current presence of the client this room was created for. + * + * @return the presence + */ + public Presence getPresence() { + return presence; + } + + + @Override + public void connected( XMPPConnection xmppConnection ) + { + + } + + @Override + public void authenticated( XMPPConnection xmppConnection, boolean b ) + { + reconnectionSuccessful(); + } + + @Override + public void connectionClosed() { + handleDisconnect(); + + String message = Res.getString("message.disconnected.error"); + getTranscriptWindow().insertNotificationMessage(message, ChatManager.ERROR_COLOR); + } + + @Override + public void connectionClosedOnError(Exception ex) { + handleDisconnect(); + + String message = Res.getString("message.disconnected.error"); + + if (ex instanceof XMPPException.StreamErrorException && ((XMPPException.StreamErrorException) ex).getStreamError().getCondition() == StreamError.Condition.conflict ) + { + message = Res.getString("message.disconnected.conflict.error"); + } + + getTranscriptWindow().insertNotificationMessage(message, ChatManager.ERROR_COLOR); + } + + public void reconnectionSuccessful() { + Presence usersPresence = PresenceManager.getPresence(getParticipantJID()); + if (usersPresence.isAvailable()) { + presence = usersPresence; + } + + SparkManager.getChatManager().getChatContainer().fireChatRoomStateUpdated(this); + getChatInputEditor().setEnabled(true); + getSendButton().setEnabled(true); + } + + private void handleDisconnect() { + presence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .build(); + getChatInputEditor().setEnabled(false); + getSendButton().setEnabled(false); + SparkManager.getChatManager().getChatContainer().fireChatRoomStateUpdated(this); + } + + + protected void loadHistory() { + // Add VCard Panel + vcardPanel = new VCardPanel(participantJID.asBareJid()); + getToolBar().add(vcardPanel, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 2, 0, 2), 0, 0)); + + if (!Default.getBoolean(Default.HISTORY_DISABLED) && Enterprise.containsFeature(Enterprise.HISTORY_TRANSCRIPTS_FEATURE)) { + final LocalPreferences localPreferences = SettingsManager.getLocalPreferences(); + if (!localPreferences.isChatHistoryEnabled()) { + return; + } + + if (!localPreferences.isPrevChatHistoryEnabled()) { + return; + } + + final ChatTranscript chatTranscript = ChatTranscripts.getCurrentChatTranscript(getJid()); + final String personalNickname = SparkManager.getUserManager().getNickname(); + final boolean privateChat = participantNickname.equals(participantJID.getResourceOrNull()); + + for (HistoryMessage message : chatTranscript.getMessages()) { + String nickname = SparkManager.getUserManager().getUserNicknameFromJID(message.getFrom().asBareJid()); + String messageBody = message.getBody(); + if (nickname.equals(message.getFrom().toString()) || nickname.equals(message.getFrom().asBareJid().toString())) { + BareJid otherJID = message.getFrom().asBareJid(); + EntityBareJid myJID = SparkManager.getSessionManager().getUserBareAddress(); + + if (otherJID.equals(myJID)) { + nickname = personalNickname; + } + else { + Resourcepart resourcepart = message.getFrom().getResourceOrNull(); + Localpart localpart = message.getFrom().getLocalpartOrNull(); + if (resourcepart == null) { + if (localpart != null) { + nickname = localpart.toString(); + } + } else { + if(privateChat){ + nickname = resourcepart.toString(); + } else { + if(localpart != null){ + nickname = localpart.toString(); + } + } + } + } + } + + if (ModelUtil.hasLength(messageBody) && messageBody.startsWith("/me ")) { + messageBody = messageBody.replaceFirst("/me", nickname); + } + + final Date messageDate = message.getDate(); + getTranscriptWindow().insertHistoryMessage(nickname, messageBody, messageDate); + } + if ( 0 < chatTranscript.getMessages().size() ) { // Check if we have history mesages + getTranscriptWindow().insertHorizontalLine(); + } + chatTranscript.release(); + } + } + + private boolean isOnline() { + Roster roster = SparkManager.getRoster(); + Presence presence = roster.getPresence(participantJID.asBareJid()); + return presence.isAvailable(); + } + + + // I would normally use the command pattern, but + // have no real use when dealing with just a couple options. + @Override + public void actionPerformed(ActionEvent e) { + + if (e.getSource() == infoButton) { + VCardManager vcard = SparkManager.getVCardManager(); + vcard.viewProfile(participantJID.asBareJid(), SparkManager.getChatManager().getChatContainer()); + } + else if (e.getSource() == addToRosterButton) { + RosterDialog rosterDialog = new RosterDialog(); + rosterDialog.setDefaultJID(participantJID.asBareJid().toString()); + rosterDialog.setDefaultNickname(getParticipantNickname().toString()); + rosterDialog.showRosterDialog(SparkManager.getChatManager().getChatContainer().getChatFrame()); + } else { + super.actionPerformed(e); + } + } + + public void notifyChatStateChange(ChatState state) { + if (chatStatePanel != null) { + getEditorWrapperBar().remove(chatStatePanel); + } + + chatStatePanel = new ChatStatePanel(state, getParticipantNickname()); + getEditorWrapperBar().add(chatStatePanel, BorderLayout.SOUTH); + getEditorWrapperBar().revalidate(); + getEditorWrapperBar().repaint(); + } + + @Override + protected void sendChatState(ChatState state) throws SmackException.NotConnectedException, InterruptedException + { + if ( !active ) + { + return; + } + + MessageBuilder messageBuilder = StanzaBuilder.buildMessage() + .ofType( Message.Type.chat ); + + if (threadID == null) { + threadID = StringUtils.randomString(6); + } + messageBuilder.setThread(threadID); + messageBuilder.addExtension( new ChatStateExtension( state ) ); + messageBuilder.to(participantJID); + messageBuilder.from(SparkManager.getSessionManager().getJID()); + + Message message = messageBuilder.build(); + SparkManager.getConnection().sendStanza( message ); + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/rooms/GroupChatRoom.java b/core/src/main/java/org/jivesoftware/spark/ui/rooms/GroupChatRoom.java new file mode 100644 index 000000000..5714b6964 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/rooms/GroupChatRoom.java @@ -0,0 +1,1017 @@ +/** + *

      + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.rooms; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.filter.*; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smack.packet.StanzaError; +import org.jivesoftware.smackx.chatstates.ChatState; +import org.jivesoftware.smackx.delay.packet.DelayInformation; +import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jivesoftware.smackx.muc.ParticipantStatusListener; +import org.jivesoftware.smackx.muc.UserStatusListener; +import org.jivesoftware.smackx.muc.packet.Destroy; +import org.jivesoftware.smackx.muc.packet.MUCUser; +import org.jivesoftware.smackx.xdata.form.Form; +import org.jivesoftware.smackx.xevent.MessageEventManager; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.plugin.ContextMenuListener; +import org.jivesoftware.spark.ui.*; +import org.jivesoftware.spark.ui.conferences.AnswerFormDialog; +import org.jivesoftware.spark.ui.conferences.ConferenceUtils; +import org.jivesoftware.spark.ui.conferences.DataFormDialog; +import org.jivesoftware.spark.ui.conferences.GroupChatParticipantList; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.UIComponentRegistry; +import org.jivesoftware.spark.util.XEP0392Utils; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.*; +import org.jxmpp.jid.parts.Resourcepart; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.util.*; +import java.util.List; +import java.util.regex.Pattern; + +import static java.awt.GridBagConstraints.HORIZONTAL; +import static java.awt.GridBagConstraints.NORTHWEST; +import static java.util.regex.Pattern.CASE_INSENSITIVE; + +/** + * GroupChatRoom is the conference chat room UI used to have Multi-User Chats. + */ +public class GroupChatRoom extends ChatRoom { + private static final Color COLOR_HIGHLIGHT_MINE_BG = new Color(244, 248, 255); + private static final Color COLOR_HIGHLIGHT_MENTION_BG = new Color(255, 255, 153); + private static final Color COLOR_ALPHA = new Color(0, 0, 0, 0); + + private final LocalPreferences pref = SettingsManager.getLocalPreferences(); + private final MultiUserChat chat; + private final SubjectPanel subjectPanel; + private final List currentUserList = new ArrayList<>(); + private final Map participantColors = new HashMap<>(); + private final List blockedUsers = new ArrayList<>(); + private final GroupChatParticipantList roomInfo; + private final RolloverButton settings; + /** compiled regexp by Nick and JID for {@link #getMessageBackground} */ + private Pattern myNicknameMatch; + private Icon tabIcon = SparkRes.getImageIcon(SparkRes.Icon.CONFERENCE_IMAGE_16x16); + private String password = null; + private String tabTitle; + private boolean isActive = true; + private long lastActivity; + private Message lastMessage; + private boolean chatStatEnabled; + + public GroupChatRoom(final MultiUserChat chat) { + Log.debug("Loading Group Chat Room for " + chat.getRoom()); + this.chat = chat; + + // Create the filter and register with the current connection, making sure to filter by room + final StanzaFilter fromFilter = FromMatchesFilter.createBare(chat.getRoom()); + final StanzaFilter orFilter = new OrFilter(new StanzaTypeFilter(Presence.class), new StanzaTypeFilter(Message.class)); + final StanzaFilter andFilter = new AndFilter(orFilter, fromFilter); + + // Add packet Listener. + SparkManager.getConnection().addAsyncStanzaListener(this, andFilter); + // We are just using a generic Group Chat. + tabTitle = chat.getRoom().getLocalpart().asUnescapedString(); + // Room Information + roomInfo = UIComponentRegistry.createGroupChatParticipantList(); + getSplitPane().setRightComponent(roomInfo.getGUI()); + getSplitPane().setResizeWeight(0.8); + + roomInfo.setChatRoom(this); + + setupListeners(); + + subjectPanel = new SubjectPanel(this); + + // Do not show the top toolbar + getToolBar().add(subjectPanel, + new GridBagConstraints(0, 1, 1, 1, 1, 0, + NORTHWEST, HORIZONTAL, new Insets(0, 2, 0, 2), 0, 0)); + + // Add ContextMenuListener + getTranscriptWindow().addContextMenuListener(new ContextMenuListener() { + @Override + public void poppingUp(Object component, JPopupMenu popup) { + popup.addSeparator(); + Action inviteAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + ConferenceUtils.inviteUsersToRoom(chat, null, false); + } + }; + + inviteAction.putValue(Action.NAME, Res.getString("menuitem.invite.users")); + inviteAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_MESSAGE_IMAGE)); + + popup.add(inviteAction); + + Action copyUriGroupChat = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + SparkManager.setClipboard("xmpp:" + chat.getRoom() + "?join"); + } + }; + + copyUriGroupChat.putValue(Action.NAME, Res.getString("button.copy.to.clipboard")); + copyUriGroupChat.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.COPY_16x16)); + popup.add(copyUriGroupChat); + + Action configureAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + DataFormDialog.openDataFormDialog(chat); + } + }; + + configureAction.putValue(Action.NAME, Res.getString("title.configure.room")); + configureAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SETTINGS_IMAGE_16x16)); + if (SparkManager.getUserManager().isOwner((GroupChatRoom) getChatRoom(), getNickname())) { + popup.add(configureAction); + } + + Action subjectChangeAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + String newSubject = JOptionPane.showInputDialog( + getChatRoom(), + Res.getString("message.enter.new.subject") + ":", + Res.getString("title.change.subject"), + JOptionPane.QUESTION_MESSAGE); + if (ModelUtil.hasLength(newSubject)) { + try { + chat.changeSubject(newSubject); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + } + } + } + }; + + subjectChangeAction.putValue(Action.NAME, Res.getString("menuitem.change.subject")); + subjectChangeAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_MESSAGE_EDIT_IMAGE)); + popup.add(subjectChangeAction); + + // Define actions to modify/view room information + Action destroyRoomAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + int ok = JOptionPane.showConfirmDialog( + getChatRoom(), + Res.getString("message.confirm.destruction.of.room"), + Res.getString("title.confirmation"), + JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE); + if (ok == JOptionPane.NO_OPTION) { + return; + } + + String reason = JOptionPane.showInputDialog( + getChatRoom(), + Res.getString("message.room.destruction.reason"), + Res.getString("title.enter.reason"), + JOptionPane.QUESTION_MESSAGE); + if (ModelUtil.hasLength(reason)) { + try { + chat.destroy(reason, null); + getChatRoom().leaveChatRoom(); + } catch (XMPPException | SmackException | InterruptedException e1) { + Log.warning("Unable to destroy room", e1); + } + } + } + }; + + destroyRoomAction.putValue(Action.NAME, Res.getString("menuitem.destroy.room")); + destroyRoomAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_DELETE)); + if (SparkManager.getUserManager().isOwner((GroupChatRoom) getChatRoom(), getNickname())) { + popup.add(destroyRoomAction); + } + + } + + @Override + public void poppingDown(JPopupMenu popup) { + } + + @Override + public boolean handleDefaultAction(MouseEvent e) { + return false; + } + }); + + // set the last activity to be right now + lastActivity = System.currentTimeMillis(); + + final GroupChatRoomTransferHandler transferHandler = new GroupChatRoomTransferHandler(this); + getTranscriptWindow().setTransferHandler(transferHandler); + + // Adds the Settings and Subject Button to the right Toolbar + settings = UIComponentRegistry.getButtonFactory().createSettingsButton(); + settings.setVisible(false); + final RolloverButton thema = UIComponentRegistry.getButtonFactory().createTemaButton(); + final RolloverButton register = UIComponentRegistry.getButtonFactory().createRegisterButton(); + + addControllerButton(settings); + addControllerButton(thema); + addControllerButton(register); + + settings.addActionListener(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent event) { + DataFormDialog.openDataFormDialog(chat); + } + }); + + thema.addActionListener(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + final String newSubject = JOptionPane.showInputDialog(getChatRoom(), + Res.getString("message.enter.new.subject") + ":", + Res.getString("title.change.subject"), + JOptionPane.QUESTION_MESSAGE); + if (ModelUtil.hasLength(newSubject)) { + try { + chat.changeSubject(newSubject); + } catch (XMPPException | SmackException | InterruptedException xmpee) { + getTranscriptWindow().insertNotificationMessage(xmpee.getMessage(), ChatManager.ERROR_COLOR); + scrollToBottom(); + } + } + } + }); + + register.addActionListener(event -> { + try { + final Form form = chat.getRegistrationForm(); + if (form != null) { + final ChatFrame chatFrame = SparkManager.getChatManager().getChatContainer().getChatFrame(); + new AnswerFormDialog(chatFrame, chat, form.getDataForm()); + } else { + getTranscriptWindow().insertNotificationMessage("Registration is not needed", ChatManager.ERROR_COLOR); + } + } catch (XMPPException | SmackException | InterruptedException xmpe) { + getTranscriptWindow().insertNotificationMessage(xmpe.getMessage(), ChatManager.ERROR_COLOR); + scrollToBottom(); + } + }); + Log.debug("Loaded Group Chat Room for " + chat.getRoom()); + } + + private Pattern compileMyNicknameMatch() { + String myUserName = SparkManager.getSessionManager().getUsername(); + return Pattern.compile(Pattern.quote(myUserName) + "|" + Pattern.quote(getNickname().toString()), CASE_INSENSITIVE); + } + + public Message getLastMessage() { + return lastMessage; + } + + /** + * Have the user leave this chat room and then close it. + */ + @Override + public void closeChatRoom() { + // Specify the end time. + super.closeChatRoom(); + // Remove Listener + SparkManager.getConnection().removeAsyncStanzaListener(this); + final ChatContainer container = SparkManager.getChatManager().getChatContainer(); + container.leaveChatRoom(this); + container.closeTab(this); + } + + /** + * Determines the background color to use for messages. + * + * @param nickname Nickname associated with the message. + * @param body Body of the message to scan for reasons to highlight. + * @return Color of message background. + */ + private Color getMessageBackground(Resourcepart nickname, String body) { + final Resourcepart myNickName = getNickname(); + if (myNicknameMatch == null) { + // TODO recalculate on nick change + myNicknameMatch = compileMyNicknameMatch(); + } + // Should we even highlight this packet? + if (pref.isMucHighNameEnabled() && myNickName.equals(nickname)) { + return COLOR_HIGHLIGHT_MINE_BG; + } else if (pref.isMucHighTextEnabled() && myNicknameMatch.matcher(body).find()) { + return COLOR_HIGHLIGHT_MENTION_BG; + } else { + return COLOR_ALPHA; + } + } + + /** + * Sends a message. + * + * @param messageBuilder - the message to send. + */ + @Override + public void sendMessage(MessageBuilder messageBuilder) { + messageBuilder.ofType(Message.Type.groupchat); + messageBuilder.to(chat.getRoom()); + Message message = messageBuilder.build(); + try { + MessageEventManager.addNotificationsRequests(message, true, true, true, true); + addPacketID(message.getStanzaId()); + + SparkManager.getChatManager().filterOutgoingMessage(this, messageBuilder); + SparkManager.getChatManager().fireGlobalMessageSentListeners(this, message); + + chat.sendMessage(messageBuilder); + } catch (Exception ex) { + Log.error("Unable to send message in conference chat.", ex); + } + + // Notify users that the message has been sent. + fireMessageSent(message); + addToTranscript(message, false); + + getChatInputEditor().clear(); + getTranscriptWindow().validate(); + getTranscriptWindow().repaint(); + + getChatInputEditor().setCaretPosition(0); + getChatInputEditor().requestFocusInWindow(); + scrollToBottom(); + + lastActivity = System.currentTimeMillis(); + } + + @Override + public EntityBareJid getBareJid() { + return chat.getRoom(); + } + + @Override + public EntityJid getJid() { + return chat.getRoom(); + } + + /** + * Retrieve the nickname of the user in this groupchat. + */ + @Override + public Resourcepart getNickname() { + return chat.getNickname(); + } + + /** + * Return the Icon that should be used in the tab of this GroupChat Pane. + */ + @Override + public Icon getTabIcon() { + return tabIcon; + } + + /** + * Sets the icon that should be used in the tab of this GroupChat Pane. + */ + public void setTabIcon(ImageIcon tabIcon) { + this.tabIcon = tabIcon; + } + + /** + * Return the title that should be used in the tab. + */ + @Override + public String getTabTitle() { + return tabTitle; + } + + /** + * Sets the title to use on the tab describing the Conference room. + */ + public void setTabTitle(CharSequence tabTitle) { + this.tabTitle = tabTitle.toString(); + } + + /** + * Return the title of this room. + */ + @Override + public String getRoomTitle() { + return getTabTitle(); + } + + /** + * Return the type of chat we are in. + */ + @Override + public Message.Type getChatType() { + return Message.Type.groupchat; + } + + /** + * Implementation of leaveChatRoom. + */ + @Override + public void leaveChatRoom() { + if (!isActive) { + return; + } + SparkManager.getConnection().removeAsyncStanzaListener(this); + getChatInputEditor().showAsDisabled(); + // Do not allow other to try and invite or transfer chat + disableToolbar(); + getToolBar().setVisible(false); + // Update Room Notice To Inform Agent that he has left the chat. + getTranscriptWindow().insertNotificationMessage(Res.getString("message.user.left.room", getNickname()), ChatManager.NOTIFICATION_COLOR); + SwingUtilities.invokeLater(() -> { + try { + chat.leave(); + } catch (Exception e) { + Log.error("Closing Group Chat Room error.", e); + } + }); + // Set the window as greyed out. + getTranscriptWindow().showWindowDisabled(); + // Update Notification Label + getNotificationLabel().setText(Res.getString("message.chat.session.ended", SparkManager.DATE_SECOND_FORMATTER.format(new java.util.Date()))); + getNotificationLabel().setIcon(null); + getNotificationLabel().setEnabled(false); + + getSplitPane().setRightComponent(null); + getSplitPane().setDividerSize(0); + isActive = false; + } + + /** + * Returns whether or not this ChatRoom is active. To be active means to + * have the agent still engaged in a conversation with a customer. + * + * @return true if the ChatRoom is active. + */ + @Override + public boolean isActive() { + return isActive; + } + + /** + * Implementation of processPacket to handle muc related packets. + * + * @param stanza the packet. + */ + @Override + public void processStanza(final Stanza stanza) { + if (stanza instanceof Presence) { + SwingUtilities.invokeLater(() -> handlePresencePacket(stanza)); + } + if (stanza instanceof Message) { + SwingUtilities.invokeLater(() -> { + handleMessagePacket(stanza); + // Set last activity + lastActivity = System.currentTimeMillis(); + }); + } + } + + /** + * Handle all MUC related packets. + */ + private void handleMessagePacket(Stanza stanza) { + // Do something with the incoming packet here. + final Message message = (Message) stanza; + lastMessage = message; + if (message.getType() == Message.Type.groupchat) { + final DelayInformation inf = message.getExtension(DelayInformation.class); + final Date sentDate = inf != null ? inf.getStamp() : new Date(); + // Do not accept Administrative messages. + final DomainBareJid host = SparkManager.getSessionManager().getServerAddress(); + if (host.equals(message.getFrom())) { + return; + } + if (ModelUtil.hasLength(message.getBody())) { + final Resourcepart from = message.getFrom().getResourceOrEmpty(); + if (inf != null) { + // This is part of the MUC history. No need to add it to the transcript again. + // Add to the UI component that shows the chat. + getTranscriptWindow().insertHistoryMessage(from.toString(), message.getBody(), sentDate); + } else { + // A 'regular' chat message. + if (isBlocked(message.getFrom().asEntityFullJidIfPossible())) { + return; + } + final boolean isFromRoomOccupant = message.getFrom().hasResource(); + if (isFromRoomOccupant && SparkManager.getUserManager().getOccupant(this, from) == null) { + return; + } + // Update transcript + insertMessage(message); + } + } + } else if (message.getType() == Message.Type.chat) { + try { + SparkManager.getChatManager().getChatContainer().getChatRoom(message.getFrom().asEntityJidOrThrow()); + } catch (ChatRoomNotFoundException e) { + final Resourcepart userNickname = message.getFrom().getResourceOrEmpty(); + final String roomTitle = userNickname + " - " + getBareJid(); + // Check to see if this is a message notification. + if (message.getBody() != null) { + // Create the new room + ChatRoom chatRoom = new ChatRoomImpl(message.getFrom().asEntityJidOrThrow(), userNickname, roomTitle); + SparkManager.getChatManager().getChatContainer().addChatRoom(chatRoom); + chatRoom.insertMessage(message); + } + } + } else if (message.getError() != null) { + String errorMessage = ""; + if (message.getError().getCondition() == StanzaError.Condition.forbidden && message.getSubject() != null) { + errorMessage = Res.getString("message.subject.change.error"); + } else if (message.getError().getCondition() == StanzaError.Condition.forbidden) { + errorMessage = Res.getString("message.forbidden.error"); + } + if (ModelUtil.hasLength(errorMessage)) { + getTranscriptWindow().insertNotificationMessage(errorMessage, ChatManager.ERROR_COLOR); + } + } + // Scroll To bottom every time a message is received + scrollToBottom(); + } + + @Override + public Message insertMessage(Message message) { + message = super.insertMessage(message); + final Resourcepart from = message.getFrom().getResourceOrThrow(); + // Add to the UI component that shows the chat. + getTranscriptWindow().insertMessage(from, message, getColor(from), getMessageBackground(from, message.getBody())); + return message; + } + + /** + * Handle all presence packets being sent to this Group Chat Room. + */ + private void handlePresencePacket(Stanza stanza) { + final Presence presence = (Presence) stanza; + if (presence.getError() != null) { + return; + } + final EntityFullJid from = presence.getFrom().asEntityFullJidIfPossible(); + if (from == null) { + return; + } + + final Resourcepart nickname = from.getResourcepart(); + final MUCUser mucUser = stanza.getExtension(MUCUser.class); + Set status = null; + if (mucUser != null) { + status = mucUser.getStatus(); + final Destroy destroy = mucUser.getDestroy(); + if (destroy != null) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(this, + (destroy.getReason() != null ? Res.getString("message.room.destroyed", destroy.getReason()) : Res.getString("message.room.destroyed.no.reason")), + Res.getString("title.room.destroyed"), + JOptionPane.INFORMATION_MESSAGE); + leaveChatRoom(); + return; + } + } + + if (presence.getType() == Presence.Type.unavailable && status != null && !status.contains(MUCUser.Status.NEW_NICKNAME_303)) { + synchronized (currentUserList) { + if (currentUserList.contains(from)) { + if (pref.isShowJoinLeaveMessagesEnabled()) { + getTranscriptWindow().insertNotificationMessage(Res.getString("message.user.left.room", nickname), ChatManager.NOTIFICATION_COLOR); + scrollToBottom(); + } + currentUserList.remove(from); + synchronized (participantColors) { + participantColors.remove(from.getResourcepart()); + } + } + } + } else { + synchronized (currentUserList) { + if (!currentUserList.contains(from)) { + currentUserList.add(from); + getChatInputEditor().setEnabled(true); + if (pref.isShowJoinLeaveMessagesEnabled()) { + getTranscriptWindow().insertNotificationMessage( + Res.getString("message.user.joined.room", nickname), + ChatManager.NOTIFICATION_COLOR); + scrollToBottom(); + } + } + } + } + } + + /** + * Set up the participant listeners and status change listeners. + */ + private void setupListeners() { + chat.addParticipantStatusListener(new ParticipantStatusListener() { + @Override + public void kicked(EntityFullJid participant, Jid actor, String reason) { + if (reason == null || reason.isEmpty()) { + insertText(Res.getString("message.user.kicked.from.room.no.reason", participant.getResourcepart(), actor)); + } else { + insertText(Res.getString("message.user.kicked.from.room", participant.getResourcepart(), actor, reason)); + } + } + + @Override + public void voiceGranted(EntityFullJid participant) { + insertText(Res.getString("message.user.given.voice", participant.getResourcepart())); + } + + @Override + public void voiceRevoked(EntityFullJid participant) { + insertText(Res.getString("message.user.voice.revoked", participant.getResourcepart())); + } + + @Override + public void banned(EntityFullJid participant, Jid actor, String reason) { + if (reason == null || reason.isEmpty()) { + insertText(Res.getString("message.user.banned.no.reason", participant.getResourcepart())); + } else { + insertText(Res.getString("message.user.banned", participant.getResourcepart(), reason)); + } + } + + @Override + public void membershipGranted(EntityFullJid participant) { + insertText(Res.getString("message.user.granted.membership", participant.getResourcepart())); + } + + @Override + public void membershipRevoked(EntityFullJid participant) { + insertText(Res.getString("message.user.revoked.membership", participant.getResourcepart())); + } + + @Override + public void moderatorGranted(EntityFullJid participant) { + insertText(Res.getString("message.user.granted.moderator", participant.getResourcepart())); + } + + @Override + public void moderatorRevoked(EntityFullJid participant) { + insertText(Res.getString("message.user.revoked.moderator", participant.getResourcepart())); + } + + @Override + public void ownershipGranted(EntityFullJid participant) { + insertText(Res.getString("message.user.granted.owner", participant.getResourcepart())); + } + + @Override + public void ownershipRevoked(EntityFullJid participant) { + insertText(Res.getString("message.user.revoked.owner", participant.getResourcepart())); + } + + @Override + public void adminGranted(EntityFullJid participant) { + insertText(Res.getString("message.user.granted.admin", participant.getResourcepart())); + } + + @Override + public void adminRevoked(EntityFullJid participant) { + insertText(Res.getString("message.user.revoked.admin", participant.getResourcepart())); + } + + @Override + public void nicknameChanged(EntityFullJid participant, Resourcepart nickname) { + insertText(Res.getString("message.user.nickname.changed", participant.getResourcepart(), nickname)); + } + }); + + chat.addUserStatusListener(new UserStatusListener() { + @Override + public void kicked(Jid s, String reason) { + if (ModelUtil.hasLength(reason)) { + insertText(reason); + } else { + insertText(Res.getString("message.your.kicked", s)); + } + + getChatInputEditor().setEnabled(false); + getSplitPane().setRightComponent(null); + leaveChatRoom(); + } + + @Override + public void voiceGranted() { + insertText(Res.getString("message.your.voice.granted")); + getChatInputEditor().setEnabled(true); + } + + @Override + public void voiceRevoked() { + insertText(Res.getString("message.your.voice.revoked")); + getChatInputEditor().setEnabled(false); + } + + @Override + public void banned(Jid s, String reason) { + insertText(Res.getString("message.your.banned")); + } + + @Override + public void membershipGranted() { + insertText(Res.getString("message.your.membership.granted")); + } + + @Override + public void membershipRevoked() { + insertText(Res.getString("message.your.membership.revoked")); + } + + @Override + public void moderatorGranted() { + insertText(Res.getString("message.your.moderator.granted")); + } + + @Override + public void moderatorRevoked() { + insertText(Res.getString("message.your.moderator.revoked")); + } + + @Override + public void ownershipGranted() { + insertText(Res.getString("message.your.ownership.granted")); + } + + @Override + public void ownershipRevoked() { + insertText(Res.getString("message.your.ownership.revoked")); + } + + @Override + public void adminGranted() { + insertText(Res.getString("message.your.admin.granted")); + } + + @Override + public void adminRevoked() { + insertText(Res.getString("message.your.revoked.granted")); + } + }); + + chat.addSubjectUpdatedListener((subject, by) -> { + subjectPanel.setSubject(subject); + if (subject.isEmpty()) { + return; + } + Resourcepart nickname = Resourcepart.EMPTY; + if (by != null) { + nickname = by.getResourcepart(); + } + final String insertMessage = Res.getString("message.subject.has.been.changed.to", subject, nickname); + getTranscriptWindow().insertNotificationMessage(insertMessage, ChatManager.NOTIFICATION_COLOR); + }); + } + + /** + * Changes the label that is displayed for this room. Does not send an update to the XMPP server (UI only). + */ + public void setRoomLabel(String label) { + subjectPanel.setRoomLabel(label); + } + + /** + * Inserts a notification message within the TranscriptWindow. + * + * @param text the text to insert. + */ + public void insertText(String text) { + getTranscriptWindow().insertNotificationMessage(text, ChatManager.NOTIFICATION_COLOR); + } + + /** + * Returns the user format (e.g. darkcave@macbeth.shakespeare.lit/thirdwitch) of each user in the room. + */ + public Collection getParticipants() { + synchronized (currentUserList) { + return new ArrayList<>(currentUserList); + } + } + + /** + * Sends the message that is currently in the Send field. + */ + @Override + public void sendMessage() { + sendMessage(getChatInputEditor().getText()); + } + + @Override + public void sendMessage(String text) { + // Remove control characters + text = text.replaceAll("[\\u0001-\\u0008\\u000B-\\u001F]", ""); + // If the body is empty, just return and do nothing + if (!ModelUtil.hasLength(text)) { + return; + } + + MessageBuilder messageBuilder = StanzaBuilder.buildMessage() + .setBody(text); + + sendMessage(messageBuilder); + } + + /** + * Returns a MultiUserChat object associated with this room. + */ + public MultiUserChat getMultiUserChat() { + return chat; + } + + /** + * Adds a user to the blocked user list. + * Blocked users are NOT a MUC-related item, + * but rather used by the client to not display messages from certain people. + * + * @param userJid the room jid of the user (ex.spark@conference.jivesoftware.com/Dan) + */ + public void addBlockedUser(EntityFullJid userJid) { + blockedUsers.add(userJid); + } + + /** + * Removes a user from the blocked user list. + * + * @param usersJID the jid of the user (ex. spark@conference.jivesoftware.com/Dan) + */ + public void removeBlockedUser(EntityFullJid usersJID) { + blockedUsers.remove(usersJID); + } + + /** + * Returns true if the user is in the blocked user list. + * + * @param userJid the jid of the user (ex. spark@conference.jivesoftware.com/Dan) + */ + public boolean isBlocked(EntityFullJid userJid) { + return blockedUsers.contains(userJid); + } + + /** + * Invite a user to this conference room. + * + * @param jid the jid of the user to invite. + * @param message the message to send with the invitation. + */ + public void inviteUser(EntityBareJid jid, String message) { + message = message != null && !message.isEmpty() ? message : Res.getString("message.please.join.in.conference"); + try { + getMultiUserChat().invite(jid, message); + roomInfo.addInvitee(jid, message); + } catch (SmackException.NotConnectedException | InterruptedException e) { + Log.warning("Unable to invite " + jid + " to room " + getBareJid(), e); + } + } + + /** + * Returns the {@link GroupChatParticipantList} which displays all users within a conference room. + */ + public GroupChatParticipantList getConferenceRoomInfo() { + return roomInfo; + } + + @Override + public long getLastActivity() { + return lastActivity; + } + + @Override + public void authenticated(XMPPConnection xmppConnection, boolean b) { + final EntityBareJid roomJID = chat.getRoom(); + final String roomName = tabTitle; + final Resourcepart nickname = getNickname(); + final String password = this.password; + try { + chat.leave(); + } catch (Exception e) { + Log.error(e); + } + + isActive = false; + EventQueue.invokeLater(() -> { + closeChatRoom(); + ConferenceUtils.joinConferenceOnSeparateThread(roomName, roomJID, nickname, password); + }); + } + + @Override + public void connectionClosed() { + handleDisconnect(); + } + + @Override + public void connectionClosedOnError(Exception ex) { + handleDisconnect(); + + getTranscriptWindow().showWindowDisabled(); + getSplitPane().setRightComponent(null); + getTranscriptWindow().insertNotificationMessage(Res.getString("message.disconnected.group.chat.error"), ChatManager.ERROR_COLOR); + } + + /** + * Sets the Password for this GroupChat if available, to rejoin the chat after a reconnection without prompting the user + */ + public void setPassword(String password) { + this.password = password; + } + + /** + * Is called whenever Spark was unexpectedly disconnected. + */ + private void handleDisconnect() { + getChatInputEditor().setEnabled(false); + getSendButton().setEnabled(false); + SparkManager.getChatManager().getChatContainer().fireChatRoomStateUpdated(this); + } + + /** + * Returns the Color to use. Use Color.blue for yourself + */ + public Color getColor(Resourcepart nickname) { + if (nickname.equals(this.getNickname())) { + return ChatManager.TO_COLOR; + } else { + return getUserColor(nickname); + } + } + + public Color getUserColor(Resourcepart nickname) { + if (!pref.isMucRandomColors()) { + return ChatManager.FROM_COLOR; + } + synchronized (participantColors) { + Color userColor = participantColors.computeIfAbsent(nickname, XEP0392Utils::colorOfMucParticipant); + return userColor; + } + } + + public void notifySettingsAccessRight() { + if (SparkManager.getUserManager().isOwner((GroupChatRoom) getChatRoom(), getNickname())) { + settings.setVisible(true); + } + } + + public boolean isChatStatEnabled() { + return chatStatEnabled; + } + + public void setChatStatEnabled(boolean chatStatEnabled) { + this.chatStatEnabled = chatStatEnabled; + } + + @Override + protected void sendChatState(ChatState state) throws SmackException.NotConnectedException, InterruptedException { + if (!chatStatEnabled || !SparkManager.getConnection().isConnected()) { + return; + } + + // XEP-0085: SHOULD NOT send 'gone' in a MUC. + if (state == ChatState.gone) { + return; + } + + final Resourcepart myNickname = getNickname(); + // Send composing notifications to all other occupants + for (final EntityFullJid occupant : chat.getOccupants()) { + final Resourcepart occupantNickname = occupant.getResourcepart(); + if (occupantNickname != null && !occupantNickname.equals(myNickname)) { + SparkManager.getMessageEventManager().sendComposingNotification(occupant, "djn"); + } + } + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/rooms/SubjectPanel.java b/core/src/main/java/org/jivesoftware/spark/ui/rooms/SubjectPanel.java new file mode 100644 index 000000000..0d95112c5 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/rooms/SubjectPanel.java @@ -0,0 +1,54 @@ +package org.jivesoftware.spark.ui.rooms; + +import org.jivesoftware.spark.util.XEP0392Utils; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.EntityBareJid; + +import javax.swing.*; +import java.awt.*; + +/** + * A UI implementation for display subjects within the conference room. + */ +public class SubjectPanel extends JPanel +{ + private final JLabel roomJIDLabel; + private final JLabel subjectLabel; + + public SubjectPanel( GroupChatRoom groupChatRoom ) + { + setLayout( new GridBagLayout() ); + EntityBareJid roomJid = groupChatRoom.getBareJid(); + roomJIDLabel = new JLabel( "<" + roomJid + ">" ); + roomJIDLabel.setFont( roomJIDLabel.getFont().deriveFont( Font.BOLD ) ); + if (SettingsManager.getLocalPreferences().isMucRandomColors()) { + roomJIDLabel.setForeground(XEP0392Utils.colorOfMuc(roomJid)); + } + + subjectLabel = new JLabel( groupChatRoom.getMultiUserChat().getSubject() ); + + add( roomJIDLabel, + new GridBagConstraints( 1, 0, 1, 1, 1.0, 0.0, + GridBagConstraints.NORTHWEST, + GridBagConstraints.HORIZONTAL, new Insets( 2, 2, 0, + 2 ), 0, 0 ) ); + add( subjectLabel, + new GridBagConstraints( 1, 1, 1, 1, 1.0, 0.0, + GridBagConstraints.NORTHWEST, + GridBagConstraints.HORIZONTAL, new Insets( 0, 2, 0, + 2 ), 0, 0 ) ); + + setOpaque( false ); + } + + public void setSubject( String subject ) + { + subjectLabel.setText( subject ); + this.setToolTipText( subject ); + } + + public void setRoomLabel( String label ) + { + roomJIDLabel.setText( label ); + } +} diff --git a/src/java/org/jivesoftware/spark/ui/rooms/package.html b/core/src/main/java/org/jivesoftware/spark/ui/rooms/package.html similarity index 100% rename from src/java/org/jivesoftware/spark/ui/rooms/package.html rename to core/src/main/java/org/jivesoftware/spark/ui/rooms/package.html diff --git a/src/java/org/jivesoftware/spark/ui/status/CustomMessages.java b/core/src/main/java/org/jivesoftware/spark/ui/status/CustomMessages.java similarity index 88% rename from src/java/org/jivesoftware/spark/ui/status/CustomMessages.java rename to core/src/main/java/org/jivesoftware/spark/ui/status/CustomMessages.java index 7f6c82cbd..3215ac347 100644 --- a/src/java/org/jivesoftware/spark/ui/status/CustomMessages.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/status/CustomMessages.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,7 +27,6 @@ import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -52,6 +47,7 @@ import org.jivesoftware.resource.Res; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.spark.PresenceManager; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.component.JiveTreeCellRenderer; @@ -65,14 +61,15 @@ import com.thoughtworks.xstream.XStream; public class CustomMessages { - private static File customMessages = new File(SparkManager.getUserDirectory(), "custom_messages.xml"); - private static XStream xstream = new XStream(); + private static final File customMessages = new File(SparkManager.getUserDirectory(), "custom_messages.xml"); + private static final XStream xstream = new XStream(); private CustomMessages() { } static { + xstream.allowTypes(new Class[]{CustomStatusItem.class}); xstream.alias("custom-items", List.class); xstream.alias("custom-status", CustomStatusItem.class); } @@ -103,7 +100,7 @@ public static List load() { } // Sort Custom Messages - Collections.sort( list, ( a, b ) -> ( a.getStatus().compareToIgnoreCase( b.getStatus() ) ) ); + list.sort((a, b) -> (a.getStatus().compareToIgnoreCase(b.getStatus()))); return list; } @@ -133,9 +130,7 @@ public static void editCustomMessages() { final List customItems = load(); final StatusBar statusBar = SparkManager.getWorkspace().getStatusBar(); - Iterator statusItems = statusBar.getStatusList().iterator(); - while (statusItems.hasNext()) { - StatusItem item = statusItems.next(); + for (StatusItem item : statusBar.getStatusList()) { JiveTreeNode node = new JiveTreeNode(item.getText(), false, item.getIcon()); Iterator cMessages = customItems.iterator(); @@ -146,13 +141,9 @@ public static void editCustomMessages() { if (csi.getType().equals(item.getText())) { JiveTreeNode subNode = new JiveTreeNode(csi.getStatus(), false); node.add(subNode); - } } - - rootNode.add(node); - } final JScrollPane pane = new JScrollPane(tree); @@ -182,11 +173,13 @@ public static void editCustomMessages() { } tree.addMouseListener(new MouseAdapter() { - public void mousePressed(MouseEvent mouseEvent) { + @Override + public void mousePressed(MouseEvent mouseEvent) { checkPopup(mouseEvent); } - public void mouseReleased(MouseEvent mouseEvent) { + @Override + public void mouseReleased(MouseEvent mouseEvent) { checkPopup(mouseEvent); } @@ -210,6 +203,7 @@ else if (selectedNode.getParent() == rootNode) { Action addAction = new AbstractAction() { private static final long serialVersionUID = 2187174931315380754L; + @Override public void actionPerformed(ActionEvent actionEvent) { CustomStatus status = new CustomStatus(); String type = (String)selectedNode.getUserObject(); @@ -234,17 +228,13 @@ public void actionPerformed(ActionEvent actionEvent) { Action deleteAction = new AbstractAction() { private static final long serialVersionUID = -4421868467918912876L; + @Override public void actionPerformed(ActionEvent actionEvent) { List list = new ArrayList<>(); //Refresh customItems list List customItems = load(); - Iterator iter = customItems.iterator(); - while (iter.hasNext()) { - CustomStatusItem item = iter.next(); - if (item.getType().equals(messageType) && item.getStatus().equals(messageStatus)) { - - } - else { + for (CustomStatusItem item : customItems) { + if (!item.getType().equals(messageType) || !item.getStatus().equals(messageStatus)) { list.add(item); } } @@ -262,11 +252,10 @@ public void actionPerformed(ActionEvent actionEvent) { Action editAction = new AbstractAction() { private static final long serialVersionUID = 39916149252596354L; + @Override public void actionPerformed(ActionEvent actionEvent) { List newItems = load(); - Iterator iter = newItems.iterator(); - while (iter.hasNext()) { - CustomStatusItem item = iter.next(); + for (CustomStatusItem item : newItems) { if (item.getType().equals(messageType) && item.getStatus().equals(messageStatus)) { CustomStatus customStatus = new CustomStatus(); customStatus.showEditDialog(item); @@ -275,9 +264,7 @@ public void actionPerformed(ActionEvent actionEvent) { reloadTree(rootNode, tree); break; } - } - } }; @@ -296,9 +283,7 @@ public void actionPerformed(ActionEvent actionEvent) { private static void reloadTree(JiveTreeNode rootNode, Tree tree) { StatusBar statusBar = SparkManager.getWorkspace().getStatusBar(); rootNode.removeAllChildren(); - Iterator statusItems = statusBar.getStatusList().iterator(); - while (statusItems.hasNext()) { - StatusItem statusItem = statusItems.next(); + for (StatusItem statusItem : statusBar.getStatusList()) { JiveTreeNode node = new JiveTreeNode(statusItem.getText(), false, statusItem.getIcon()); List newItems = load(); @@ -311,11 +296,8 @@ private static void reloadTree(JiveTreeNode rootNode, Tree tree) { if (csi.getType().equals(statusItem.getText())) { JiveTreeNode subNode = new JiveTreeNode(csi.getStatus(), false); node.add(subNode); - } } - - rootNode.add(node); } @@ -326,16 +308,16 @@ private static void reloadTree(JiveTreeNode rootNode, Tree tree) { private static class CustomStatus extends JPanel { private static final long serialVersionUID = 1117350001209641469L; - private JLabel typeLabel = new JLabel(); - private JComboBox typeBox = new JComboBox(); + private final JLabel typeLabel = new JLabel(); + private final JComboBox typeBox = new JComboBox<>(); - private JLabel statusLabel = new JLabel(); - private JTextField statusField = new JTextField(); + private final JLabel statusLabel = new JLabel(); + private final JTextField statusField = new JTextField(); - private JLabel priorityLabel = new JLabel(); - private JTextField priorityField = new JTextField(); + private final JLabel priorityLabel = new JLabel(); + private final JTextField priorityField = new JTextField(); - private JCheckBox persistBox = new JCheckBox(); + private final JCheckBox persistBox = new JCheckBox(); public CustomStatus() { StatusBar statusBar = SparkManager.getWorkspace().getStatusBar(); @@ -362,26 +344,27 @@ public CustomStatus() { typeBox.setRenderer(new ListIconRenderer()); // Add Types - Iterator statusIterator = statusBar.getStatusList().iterator(); - while (statusIterator.hasNext()) { - final StatusItem statusItem = statusIterator.next(); + for (StatusItem statusItem : statusBar.getStatusList()) { if (!PresenceManager.isOnPhone(statusItem.getPresence())) { - ImageIcon icon = (ImageIcon)statusItem.getIcon(); + try { + ImageIcon icon = (ImageIcon) statusItem.getIcon(); - ImageIcon newIcon = new ImageIcon(icon.getImage()); - newIcon.setDescription(statusItem.getText()); + ImageIcon newIcon = new ImageIcon(icon.getImage()); + newIcon.setDescription(statusItem.getText()); - typeBox.addItem(newIcon); + typeBox.addItem(newIcon); + } catch (Exception e) { + Log.warning("Unable to update icon on custom status bar", e); + } } } priorityField.setText("1"); statusField.setText(Res.getString("status.online")); - } public String getType() { - ImageIcon icon = (ImageIcon)typeBox.getSelectedItem(); + ImageIcon icon = (ImageIcon) typeBox.getSelectedItem(); return icon.getDescription(); } @@ -422,7 +405,7 @@ public void showEditDialog(final CustomStatusItem item) { String type = item.getType(); int count = typeBox.getItemCount(); for (int i = 0; i < count; i++) { - ImageIcon icon = (ImageIcon)typeBox.getItemAt(i); + ImageIcon icon = typeBox.getItemAt(i); if (icon.getDescription().equals(type)) { typeBox.setSelectedIndex(i); break; @@ -507,7 +490,7 @@ public void invoke(String selectedType) { if (selectedType != null) { int count = typeBox.getItemCount(); for (int i = 0; i < count; i++) { - ImageIcon icon = (ImageIcon)typeBox.getItemAt(i); + ImageIcon icon = typeBox.getItemAt(i); if (icon.getDescription().equals(selectedType)) { typeBox.setSelectedIndex(i); break; @@ -537,9 +520,12 @@ else if (Res.getString("ok").equals(value)) { StatusItem item = statusBar.getStatusItem(getType()); Presence oldPresence = item.getPresence(); - Presence presence = StatusBar.copyPresence(oldPresence); - presence.setStatus(getStatus()); - presence.setPriority(getPriority()); + Presence presence = StanzaBuilder.buildPresence() + .ofType(oldPresence.getType()) + .setStatus(getStatus()) + .setPriority(getPriority()) + .setMode(oldPresence.getMode()) + .build(); SparkManager.getSessionManager().changePresence(presence); statusBar.setStatus(getStatus()); @@ -575,9 +561,12 @@ else if (Res.getString("ok").equals(value)) { // Update current status. StatusItem item = statusBar.getStatusItem(getType()); Presence oldPresence = item.getPresence(); - Presence presence = StatusBar.copyPresence(oldPresence); - presence.setStatus(getStatus()); - presence.setPriority(getPriority()); + Presence presence = StanzaBuilder.buildPresence() + .ofType(oldPresence.getType()) + .setStatus(getStatus()) + .setPriority(getPriority()) + .setMode(oldPresence.getMode()) + .build(); SparkManager.getSessionManager().changePresence(presence); statusBar.setStatus(getStatus()); @@ -596,4 +585,4 @@ else if (Res.getString("ok").equals(value)) { } -} \ No newline at end of file +} diff --git a/src/java/org/jivesoftware/spark/ui/status/CustomStatusItem.java b/core/src/main/java/org/jivesoftware/spark/ui/status/CustomStatusItem.java similarity index 96% rename from src/java/org/jivesoftware/spark/ui/status/CustomStatusItem.java rename to core/src/main/java/org/jivesoftware/spark/ui/status/CustomStatusItem.java index 21efb6748..2434cbb1e 100644 --- a/src/java/org/jivesoftware/spark/ui/status/CustomStatusItem.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/status/CustomStatusItem.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/src/main/java/org/jivesoftware/spark/ui/status/StatusBar.java b/core/src/main/java/org/jivesoftware/spark/ui/status/StatusBar.java new file mode 100644 index 000000000..1451f5727 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/status/StatusBar.java @@ -0,0 +1,745 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.status; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Image; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.geom.AffineTransform; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.TimerTask; + +import javax.swing.*; +import javax.swing.border.Border; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smackx.vcardtemp.packet.VCard; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.CommandPanel; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.ImageCombiner; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.StringUtils; +import org.jivesoftware.spark.util.SwingTimerTask; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.UIComponentRegistry; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; +import org.jivesoftware.sparkimpl.plugin.privacy.PrivacyManager; +import org.jivesoftware.sparkimpl.plugin.privacy.list.SparkPrivacyList; +import org.jivesoftware.sparkimpl.profile.VCardEditor; +import org.jivesoftware.sparkimpl.profile.VCardListener; +import org.jivesoftware.sparkimpl.profile.VCardManager; +import org.jivesoftware.sparkimpl.profile.ext.VCardUpdateExtension; +import org.jivesoftware.sparkimpl.settings.Sizes; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +//TODO: I need to remove the presence logic from this class. +public class StatusBar extends JPanel implements VCardListener { + + private final List statusList = new ArrayList<>(); + + private final JLabel imageLabel = new JLabel(); + private final JLabel descriptiveLabel = new JLabel(); + private final JLabel nicknameLabel = new JLabel(); + private final StatusPanel statusPanel = new StatusPanel(); + + private final CommandPanel commandPanel; + private Image backgroundImage; + private final Runnable changePresenceRunnable; + + private Presence currentPresence; + + private static final Color COLOR_STATUS_BACKGROUND = new Color(207, 207, 207); + + public StatusBar() { + this(true); + } + + public StatusBar(boolean doLayout) { + + commandPanel = UIComponentRegistry.createCommandPanel(); + + if (doLayout) { + setLayout(new GridBagLayout()); + + backgroundImage = Default.getImageIcon(Default.TOP_BOTTOM_BACKGROUND_IMAGE).getImage(); + + ImageIcon brandedImage = Default.getImageIcon(Default.BRANDED_IMAGE); + if (brandedImage != null && brandedImage.getIconWidth() > 1) { + final JLabel brandedLabel = new JLabel(brandedImage); + add(brandedLabel, new GridBagConstraints(3, 0, 1, 3, 1.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); + } + + add(imageLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(2, 8, 2, 2), 0, 0)); + allowProfileEditing(); + + add(nicknameLabel, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(2, 12, 0, 0), 0, 0)); + add(statusPanel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 7, 0, 0), 0, 0)); + add(commandPanel, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTHWEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 0), 0, 0)); + nicknameLabel.setToolTipText(SparkManager.getConnection().getUser().toString()); + nicknameLabel.setFont(new Font(Font.DIALOG, Font.BOLD, 12)); + setStatus(Res.getString("status.online")); + } + + buildStatusItemList(); + + // SPARK-1521, if we log in as invisible, default status should be "Invisible" + currentPresence = getPresenceOnStart(); + + updatePresence(); + + //setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230), 1)); + SparkManager.getSessionManager().addPresenceListener(presence -> { + Presence statusPresence = StanzaBuilder.buildPresence() + .ofType(presence.getType()) + .setStatus(StringUtils.modifyWildcards(presence.getStatus())) + .setPriority(presence.getPriority()) + .setMode(presence.getMode()) + .build(); + changeAvailability(statusPresence); + + // SPARK-1524: + // after reconnected if we had the 'invisible' presence + // we should re-send it + if (PresenceManager.isInvisible(currentPresence)) { + TimerTask task = new SwingTimerTask() { + @Override + public void doRun() { + PrivacyManager.getInstance().goToInvisible(); + } + }; + TaskEngine.getInstance().schedule(task, 500); + } + }); + + final TimerTask task = new SwingTimerTask() { + @Override + public void doRun() { + SparkManager.getVCardManager().addVCardListener(SparkManager.getWorkspace().getStatusBar()); + } + }; + + TaskEngine.getInstance().schedule(task, 3000); + changePresenceRunnable = this::updatePresence; + + } + + public void setAvatar(Icon icon) { + try { + if (icon == null) { + imageLabel.setIcon(null); + } else { + Image image = ImageCombiner.iconToImage(icon); + if (icon.getIconHeight() > Sizes.Avatar.STATUS || icon.getIconWidth() > Sizes.Avatar.STATUS) { + imageLabel.setIcon(new ImageIcon(image.getScaledInstance(-1, Sizes.Avatar.STATUS, Image.SCALE_SMOOTH))); + } else { + imageLabel.setIcon(icon); + } + } + imageLabel.setBorder(null); + revalidate(); + } catch (Exception e) { + Log.warning("Unable to set avatar", e); + } + } + + public CommandPanel getCommandPanel() { + return commandPanel; + } + + public void setNickname(String nickname) { + nicknameLabel.setText(nickname); + } + + /** + * Sets the current status text in the Status Manager. + * + * @param status the status to set. + */ + public void setStatus(String status) { + statusPanel.setStatus(status); + } + + protected void updatePresence() { + setStatus(currentPresence.getStatus()); + final Icon icon = PresenceManager.getIconFromPresence(currentPresence); + if (icon != null) { + statusPanel.setIcon(icon); + } + } + + public void showPopup(MouseEvent e, JLabel lblStatus) { + final JPopupMenu popup = new JPopupMenu(); + + List custom = CustomMessages.load(); + if (custom == null) { + custom = new ArrayList<>(); + } + + // Sort Custom Messages + custom.sort((a, b) -> (a.getStatus().compareToIgnoreCase(b.getStatus()))); + + // Build menu from StatusList + for (final StatusItem statusItem : statusList) { + final Action statusAction = new AbstractAction() { + private static final long serialVersionUID = -192865863435381702L; + + @Override + public void actionPerformed(ActionEvent actionEvent) { + final String text = statusItem.getText(); + final StatusItem si = getStatusItem(text); + if (si == null) { + // Custom status + Log.error("Unable to find status item for status - " + text); + return; + } + + SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + return changePresence(si.getPresence()); + } + + @Override + public void finished() { + setStatus((String) getValue()); + } + }; + worker.start(); + lblStatus.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PANE_DOWN_ARROW_IMAGE)); + + } + }; + + statusAction.putValue(Action.NAME, statusItem.getText()); + statusAction.putValue(Action.SMALL_ICON, statusItem.getIcon()); + + // Has Children + boolean hasChildren = false; + for (Object aCustom : custom) { + final CustomStatusItem cItem = (CustomStatusItem) aCustom; + String type = cItem.getType(); + if (type.equals(statusItem.getText())) { + hasChildren = true; + } + } + + if (!hasChildren) { + // Add as Menu Item + popup.add(statusAction); + } else { + + final JMenu mainStatusItem = new JMenu(statusAction); + + popup.add(mainStatusItem); + + // Add Custom Messages + for (Object aCustom : custom) { + final CustomStatusItem customItem = (CustomStatusItem) aCustom; + String type = customItem.getType(); + final String customStatus = customItem.getStatus(); + if (type.equals(statusItem.getText())) { + // Add Child Menu + Action action = new AbstractAction() { + private static final long serialVersionUID = -1264239704492879742L; + + @Override + public void actionPerformed(ActionEvent actionEvent) { + final String text = mainStatusItem.getText(); + final StatusItem si = getStatusItem(text); + if (si == null) { + // Custom status + Log.error("Unable to find status item for status - " + text); + return; + } + + SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + Presence presence = StanzaBuilder.buildPresence() + .ofType(si.getPresence().getType()) + .setStatus(customStatus) + .setPriority(customItem.getPriority()) + .setMode(si.getPresence().getMode()) + .build(); + return changePresence(presence); + } + + @Override + public void finished() { + setStatus((String) getValue()); + } + }; + worker.start(); + } + }; + action.putValue(Action.NAME, customItem.getStatus()); + action.putValue(Action.SMALL_ICON, statusItem.getIcon()); + mainStatusItem.add(action); + } + } + + // If menu has children, allow it to still be clickable. + mainStatusItem.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent mouseEvent) { + statusAction.actionPerformed(null); + popup.setVisible(false); + } + }); + } + } + + //SPARK-1521. Add privacy menu if Privacy Manager is active and have any visible lists + final PrivacyManager pmanager = PrivacyManager.getInstance(); + if (pmanager.isPrivacyActive() && pmanager.getPrivacyLists().size() > 0) { + + JMenu privMenu = new JMenu(Res.getString("privacy.status.menu.entry")); + privMenu.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_ICON_SMALL)); + + for (SparkPrivacyList plist : pmanager.getPrivacyLists()) { + JMenuItem it = new JMenuItem(plist.getListName()); + privMenu.add(it); + if (plist.isActive()) { + it.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_LIGHTNING)); + } else { + it.setIcon(null); + } + final SparkPrivacyList finalList = plist; + it.addActionListener(e1 -> PrivacyManager.getInstance().setListAsActive(finalList.getListName())); + } + + if (pmanager.hasActiveList()) { + JMenuItem remMenu = new JMenuItem(Res.getString("privacy.menuitem.deactivate.current.list", pmanager.getActiveList().getListName()), + SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_DEACTIVATE_LIST)); + remMenu.addActionListener(e1 -> pmanager.declineActiveList()); + privMenu.addSeparator(); + privMenu.add(remMenu); + } + + popup.add(privMenu); + } + + // Add change message + final JMenuItem changeStatusMenu = new JMenuItem(Res.getString("menuitem.set.status.message"), SparkRes.getImageIcon(SparkRes.Icon.BLANK_IMAGE)); + popup.addSeparator(); + + popup.add(changeStatusMenu); + changeStatusMenu.addActionListener(e1 -> CustomMessages.addCustomMessage()); + + Action editMessagesAction = new AbstractAction() { + private static final long serialVersionUID = 7148051050075679995L; + + @Override + public void actionPerformed(ActionEvent actionEvent) { + CustomMessages.editCustomMessages(); + } + }; + + editMessagesAction.putValue(Action.NAME, Res.getString("menuitem.edit.status.message")); + popup.add(editMessagesAction); + + final JPanel panel = getStatusPanel(); + popup.show(panel, 0, panel.getHeight()); + lblStatus.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PANE_UP_ARROW_IMAGE)); + + + } + + protected JPanel getStatusPanel() { + return statusPanel; + } + + public void changeAvailability(final Presence presence) { + // SPARK-1524: if we were reconnected because of the error + // then we get presence with the mode == null. + if (presence.getMode() == null) { + return; + } + + if ((presence.getMode() == currentPresence.getMode()) && (presence.getType() == currentPresence.getType()) && (presence.getStatus().equals(currentPresence.getStatus()))) { + if (presence.hasExtension(VCardUpdateExtension.class)) { + // Update VCard + loadVCard(); + } + return; + } + currentPresence = presence; + + SwingUtilities.invokeLater(changePresenceRunnable); + } + + /** + * Populates the current Dnd List. + */ + private void buildStatusItemList() { + for (Presence presence : PresenceManager.getPresences()) { + Icon icon = PresenceManager.getIconFromPresence(presence); + StatusItem item = new StatusItem(presence, icon); + statusList.add(item); + } + + final Presence availablePresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .build(); + final Icon availableIcon = PresenceManager.getIconFromPresence(availablePresence); + + // Set default presence icon (Available) + statusPanel.setIcon(availableIcon); + } + + public Collection getStatusList() { + return statusList; + } + + public Collection getCustomStatusList() { + List custom = CustomMessages.load(); + if (custom == null) { + custom = new ArrayList<>(); + } + + // Sort Custom Messages + custom.sort((a, b) -> (a.getStatus().compareToIgnoreCase(b.getStatus()))); + + return custom; + } + + public Presence getPresence() { + return currentPresence; + } + + public StatusItem getStatusItem(String label) { + for (StatusItem aStatusList : statusList) { + if (aStatusList.getText().equals(label)) { + return aStatusList; + } + } + return null; + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + if (backgroundImage != null) { + double scaleX = getWidth() / (double) backgroundImage.getWidth(null); + double scaleY = getHeight() / (double) backgroundImage.getHeight(null); + AffineTransform xform = AffineTransform.getScaleInstance(scaleX, scaleY); + ((Graphics2D) g).drawImage(backgroundImage, xform, this); + } + } + + public void loadVCard() { + final Runnable loadVCard = () -> { + VCard vcard = SparkManager.getVCardManager().getVCard(); + updateVCardInformation(vcard); + }; + + TaskEngine.getInstance().submit(loadVCard); + } + + protected void updateVCardInformation(final VCard vCard) { + SwingUtilities.invokeLater(() -> { + if (vCard.getError() == null) { + String fullName = vCard.getField("FN"); + String nickname = vCard.getNickName(); + if (ModelUtil.hasLength(fullName)) { + setNickname(fullName); + } else if (ModelUtil.hasLength(nickname)) { + setNickname(nickname); + } else { + nickname = SparkManager.getSessionManager().getUsername(); + setNickname(nickname); + } + } else { + String nickname = SparkManager.getSessionManager().getUsername(); + setNickname(nickname); + return; + } + + byte[] avatarBytes = null; + try { + avatarBytes = vCard.getAvatar(); + } catch (Exception e) { + Log.error("Cannot retrieve avatar bytes.", e); + } + + if (avatarBytes != null && avatarBytes.length > 0) { + try { + ImageIcon avatarIcon = new ImageIcon(avatarBytes); + avatarIcon = VCardManager.scale(avatarIcon); + setAvatar(avatarIcon); + imageLabel.invalidate(); + imageLabel.validate(); + imageLabel.repaint(); + } catch (Exception e) { + Log.warning("Unable to update vcard viewer with avatar data", e); + } + } else { + imageLabel.setIcon(null); + imageLabel.setBorder(null); + imageLabel.invalidate(); + imageLabel.validate(); + imageLabel.repaint(); + } + }); + + } + + /** + * Return the nickname Component used to display the users profile name. + * + * @return the label. + */ + public JLabel getNicknameLabel() { + return nicknameLabel; + } + + public void setStatusPanelEnabled(Boolean enabled) { + getStatusPanel().setEnabled(enabled); + } + + private class StatusPanel extends JPanel { + + private static final long serialVersionUID = -5086334443225239032L; + private final JLabel iconLabel; + private final JLabel statusLabel; + + public StatusPanel() { + super(); + + //setOpaque(false); + + iconLabel = new JLabel(); + statusLabel = new JLabel(); + + setLayout(new GridBagLayout()); + + // Remove padding from icon label + iconLabel.setIconTextGap(0); + + add(iconLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + add(statusLabel, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 2, 0, 0), 0, 0)); + + statusLabel.setFont(new Font(Font.DIALOG, Font.PLAIN, 11)); + + // See if we should disable ability to change presence status + if (!Default.getBoolean(Default.DISABLE_PRESENCE_STATUS_CHANGE) && Enterprise.containsFeature(Enterprise.PRESENCE_STATUS_FEATURE)) { + statusLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PANE_DOWN_ARROW_IMAGE)); + } + + statusLabel.setHorizontalTextPosition(JLabel.LEFT); + + //setOpaque(false); + setBackground(Color.white); + + final Border border = BorderFactory.createEmptyBorder(2, 2, 2, 2); + setBorder(border); + + // See if we should disable ability to change presence status + if (!Default.getBoolean(Default.DISABLE_PRESENCE_STATUS_CHANGE) && Enterprise.containsFeature(Enterprise.PRESENCE_STATUS_FEATURE)) { + statusLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent e) { + if (!isEnabled()) { + return; + } + showPopup(e, statusLabel); + } + + @Override + public void mouseEntered(MouseEvent e) { + if (!isEnabled()) { + return; + } + setCursor(GraphicUtils.HAND_CURSOR); + setBackground(COLOR_STATUS_BACKGROUND); + //setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); + } + + @Override + public void mouseExited(MouseEvent e) { + setCursor(GraphicUtils.DEFAULT_CURSOR); + //setBorder(border); + setBackground(Color.white); + } + + @Override + public void mousePressed(MouseEvent e) { + if (!isEnabled()) { + return; + } + setBackground(new Color(221,221,221)); + //setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); + } + + }); + } + + } + + public void setStatus(String status) { + int length = status.length(); + String visualStatus = status; + if (length > 30) { + visualStatus = status.substring(0, 27) + "..."; + } + + statusLabel.setText(visualStatus); + statusLabel.setToolTipText(status); + } + + public void setIcon(Icon icon) { + iconLabel.setIcon(icon); + } + } + + public void setBackgroundImage(Image image) { + this.backgroundImage = image; + } + + public void setDescriptiveText(String text) { + descriptiveLabel.setText(text); + } + + @Override + public Dimension getPreferredSize() { + Dimension dim = super.getPreferredSize(); + dim.width = 0; + return dim; + } + + @Override + public void vcardChanged(VCard vcard) { + updateVCardInformation(vcard); + } + + protected Runnable getChangePresenceRunnable() { + return changePresenceRunnable; + } + + protected Presence getCurrentPresence() { + return currentPresence; + } + + private String changePresence(Presence presence) { + // SPARK-1521. Other clients can see "Invisible" status while we are disappearing. + // So we send "Offline" instead of "Invisible" for them. + boolean isNewPresenceInvisible = PresenceManager + .isInvisible(presence); + if (isNewPresenceInvisible && !PrivacyManager.getInstance().isPrivacyActive()) { + JOptionPane.showMessageDialog(null, Res.getString("dialog.invisible.privacy.lists.not.supported")); + } + + Presence copyPresence = StanzaBuilder.buildPresence() + .ofType(presence.getType()) + .setStatus(isNewPresenceInvisible ? null : presence.getStatus()) + .setPriority(presence.getPriority()) + .setMode(presence.getMode()) + .build(); + if (PresenceManager.areEqual(getCurrentPresence(), copyPresence)) { + return presence.getStatus(); + } + + // ask user to confirm that all group chat rooms will be closed if + // he/she goes to invisible. + if (isNewPresenceInvisible + && SparkManager.getChatManager().getChatContainer() + .hasGroupChatRooms()) { + int reply = JOptionPane + .showConfirmDialog( + null, + Res.getString("dialog.confirm.close.all.conferences.if.invisible.msg"), + Res.getString("dialog.confirm.to.reveal.visibility.title"), + JOptionPane.YES_NO_OPTION); + if (reply == JOptionPane.NO_OPTION) { + return getCurrentPresence().getStatus(); + } + } + + // If we go visible then we should send "Available" first. + if (!isNewPresenceInvisible + && PresenceManager.isInvisible(getCurrentPresence())) { + PrivacyManager.getInstance().goToVisible(); + } + + // Then set the current status. + SparkManager.getSessionManager().changePresence(copyPresence); + + // If we go invisible we should activate the "globally invisible list" + // and send "Available" after "Unavailable" presence. + if (isNewPresenceInvisible) { + SparkManager.getChatManager().getChatContainer() + .closeAllGroupChatRooms(); + PrivacyManager.getInstance().goToInvisible(); + } + + return presence.getStatus(); + } + + protected Presence getPresenceOnStart() { + return SettingsManager.getLocalPreferences().isLoginAsInvisible() + ? PresenceManager.getUnavailablePresence() + : PresenceManager.getAvailablePresence(); + } + + public void allowProfileEditing() { + // Allow profile editing ONLY if both client-side and server-side settings permit it + if (Default.getBoolean(Default.DISABLE_EDIT_PROFILE) || !Enterprise.containsFeature(Enterprise.VCARD_FEATURE)) { + return; + } + + // Go ahead and show the profile when clicking on the Avatar image + imageLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent mouseEvent) { + if (mouseEvent.getClickCount() == 1) { + VCardManager vcardManager = SparkManager.getVCardManager(); + VCardEditor editor = new VCardEditor(); + editor.editProfile(vcardManager.getVCard(), SparkManager.getWorkspace()); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + imageLabel.setCursor(GraphicUtils.HAND_CURSOR); + } + + @Override + public void mouseExited(MouseEvent e) { + imageLabel.setCursor(GraphicUtils.DEFAULT_CURSOR); + } + }); + } + +} diff --git a/src/java/org/jivesoftware/spark/ui/status/StatusItem.java b/core/src/main/java/org/jivesoftware/spark/ui/status/StatusItem.java similarity index 94% rename from src/java/org/jivesoftware/spark/ui/status/StatusItem.java rename to core/src/main/java/org/jivesoftware/spark/ui/status/StatusItem.java index d4ed2c5ed..3c1bea6a0 100644 --- a/src/java/org/jivesoftware/spark/ui/status/StatusItem.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/status/StatusItem.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,7 +25,7 @@ */ public class StatusItem extends JLabel { private static final long serialVersionUID = 725324886254656704L; - private Presence presence; + private final Presence presence; /** * Creates a single StatusItem UI object. diff --git a/src/java/org/jivesoftware/spark/ui/status/package.html b/core/src/main/java/org/jivesoftware/spark/ui/status/package.html similarity index 100% rename from src/java/org/jivesoftware/spark/ui/status/package.html rename to core/src/main/java/org/jivesoftware/spark/ui/status/package.html diff --git a/src/java/org/jivesoftware/spark/ui/themes/ColorPreferencePanel.java b/core/src/main/java/org/jivesoftware/spark/ui/themes/ColorPreferencePanel.java similarity index 87% rename from src/java/org/jivesoftware/spark/ui/themes/ColorPreferencePanel.java rename to core/src/main/java/org/jivesoftware/spark/ui/themes/ColorPreferencePanel.java index d2c629a3d..c5e68386c 100644 --- a/src/java/org/jivesoftware/spark/ui/themes/ColorPreferencePanel.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/themes/ColorPreferencePanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -51,7 +47,7 @@ public class ColorPreferencePanel extends SparkTabbedPane { private static final long serialVersionUID = -3594152276094474130L; - private JList _colorliste; + private JList colorList; private ColorSettings _colorsettings; private JLabel _errorlabel; @@ -67,13 +63,9 @@ private void createUI() { _colorsettings = ColorSettingManager.getColorSettings(); Set sets = _colorsettings.getKeys(); - - - Vector keys= new Vector<>(); - for(String s : sets) - { - keys.add(s); - } + + + Vector keys = new Vector<>(sets); sortList(keys); JPanel rightpanel = new JPanel(new GridBagLayout()); @@ -96,17 +88,17 @@ private void createUI() { rightpanel.add(_errorlabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0 , GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - _colorliste = new JList(keys); - JScrollPane _jScrollPane = new JScrollPane( _colorliste ); + colorList = new JList<>(keys); + JScrollPane _jScrollPane = new JScrollPane(colorList); setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); add( _jScrollPane ); add(rightpanel); - _colorliste.addListSelectionListener( e -> { + colorList.addListSelectionListener(e -> { - String v = (String) _colorliste.getSelectedValue(); + String v = colorList.getSelectedValue(); Color c = _colorsettings.getColorFromProperty(v); @@ -114,7 +106,7 @@ private void createUI() { _errorlabel.setText(""); } ); - savebutton.addActionListener( e -> savebuttonaction(e) ); + savebutton.addActionListener(this::savebuttonaction); restoreDefaults.addActionListener( e -> { ColorSettingManager.restoreDefault(); @@ -133,9 +125,9 @@ private void savebuttonaction(ActionEvent e) { Color c = _colorpick.getColor(); _colorsettings.setColorForProperty( - (String) _colorliste.getSelectedValue(), c); + colorList.getSelectedValue(), c); - UIManager.put( _colorliste.getSelectedValue(), c); + UIManager.put( colorList.getSelectedValue(), c); _errorlabel.setText(Res.getString("lookandfeel.color.saved")); diff --git a/core/src/main/java/org/jivesoftware/spark/ui/themes/ColorSettingManager.java b/core/src/main/java/org/jivesoftware/spark/ui/themes/ColorSettingManager.java new file mode 100644 index 000000000..f018da988 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/themes/ColorSettingManager.java @@ -0,0 +1,147 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.themes; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Default; +import org.jivesoftware.spark.util.log.Log; + +public class ColorSettingManager { + + private static Map colorSettings = new HashMap<>(0); + + private ColorSettingManager() { + } + + /** + * Returns the ColorSettings + */ + public static ColorSettings getColorSettings() { + return loadSettings(getSettingsFile()); + } + + /** + * Returns the file or creates it + */ + private static File getSettingsFile() { + File path = Spark.getSparkUserHome(); + if (!path.exists()) { + path.mkdirs(); + } + File f = new File(path, "color.settings"); + return f; + } + + /** + * Save all settings + */ + public static void saveColorSettings() { + // Safe only those settings that are different from a default + Map defaultColors = getDefaultColors(); + final Properties props = new Properties(); + for (Map.Entry setting : colorSettings.entrySet()) { + String defaultSettingVal = defaultColors.get(setting.getKey()); + if (defaultSettingVal == null || !defaultSettingVal.equals(setting.getValue())) { + props.put(setting.getKey(), setting.getValue()); + } + } + // if there are no properties left, and they are all default, delete the settings file + File settingsFile = getSettingsFile(); + if (props.isEmpty() && settingsFile.exists()) { + settingsFile.delete(); + return; + } + try { + props.store(Files.newOutputStream(settingsFile.toPath()), null); + } catch (Exception e) { + Log.error("Error saving settings.", e); + } + } + + /** + * load the Settings file + */ + private static ColorSettings loadSettings(File file) { + loadSettingsToMap(file); + Map defaultColors = getDefaultColors(); + + // Loads defaults if empty; reconciles against defaults otherwise + if (colorSettings.isEmpty()) { + colorSettings = defaultColors; + } else if (colorSettings.size() != defaultColors.size()) { + // add missing settings from defaults + defaultColors.forEach(colorSettings::putIfAbsent); + } + return new ColorSettings(colorSettings); + } + + /** + * loads all Properties into a HashMap from the File specified + */ + private static void loadSettingsToMap(File file) { + if (!file.exists()) { + return; + } + Properties props = new Properties(); + try { + props.load(Files.newInputStream(file.toPath())); + } catch (IOException e) { + Log.error("Error loading color settings.", e); + return; + } + Enumeration enume = props.keys(); + while (enume.hasMoreElements()) { + String propName = (String) enume.nextElement(); + colorSettings.put(propName, props.getProperty(propName)); + } + } + + /** + * Gets colors from default.properties + */ + private static HashMap getDefaultColors() { + Matcher colorPatternMatcher = Pattern.compile("[0-9]*,[0-9]*,[0-9]*,[0-9]*").matcher(""); + HashMap hashmap = new HashMap<>(40); + Enumeration enu = Default.getAllKeys(); + while (enu.hasMoreElements()) { + String s = enu.nextElement(); + String propValue = Default.getString(s).replace(" ", ""); + colorPatternMatcher.reset(propValue); + if (colorPatternMatcher.matches()) { + hashmap.put(s, propValue); + } + } + return hashmap; + } + + /** + * Restores the Default Settings + */ + public static void restoreDefault() { + colorSettings = getDefaultColors(); + saveColorSettings(); + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/themes/ColorSettings.java b/core/src/main/java/org/jivesoftware/spark/ui/themes/ColorSettings.java new file mode 100644 index 000000000..b6730ead6 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/themes/ColorSettings.java @@ -0,0 +1,58 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.themes; + +import java.awt.Color; +import java.util.Map; +import java.util.Set; + +public class ColorSettings { + + private final Map _hashmap; + + public ColorSettings(Map settingMap) { + _hashmap = settingMap; + } + + public void setColorForProperty(String propertyName, Color color) { + int r = color.getRed(); + int g = color.getGreen(); + int b = color.getBlue(); + int a = color.getAlpha(); + String c = r + "," + g + "," + b + "," + a; + _hashmap.put(propertyName, c); + } + + public Color getColorFromProperty(String propertyName) { + String colorValue = _hashmap.get(propertyName).replaceAll(" ", ""); + colorValue = colorValue.replaceAll("[a-zA-Z]", ""); + String[] items = colorValue.split(","); + return new Color( + Integer.parseInt(items[0]), + Integer.parseInt(items[1]), + Integer.parseInt(items[2]), + Integer.parseInt(items[3])); + } + + /** + * Returns all the PropertyNames + */ + public Set getKeys() { + return _hashmap.keySet(); + } +} + + diff --git a/src/java/org/jivesoftware/spark/ui/themes/EmoticonPanel.java b/core/src/main/java/org/jivesoftware/spark/ui/themes/EmoticonPanel.java similarity index 95% rename from src/java/org/jivesoftware/spark/ui/themes/EmoticonPanel.java rename to core/src/main/java/org/jivesoftware/spark/ui/themes/EmoticonPanel.java index 1c85afbd6..3c33827b5 100644 --- a/src/java/org/jivesoftware/spark/ui/themes/EmoticonPanel.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/themes/EmoticonPanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,7 +33,7 @@ public class EmoticonPanel extends JPanel { private static final long serialVersionUID = 4884193790861293275L; private int _spalte=0; private int _zeile=0; - private int _numberInRow; + private final int _numberInRow; /** * Creates a new EmotionPanel diff --git a/core/src/main/java/org/jivesoftware/spark/ui/themes/LookAndFeelManager.java b/core/src/main/java/org/jivesoftware/spark/ui/themes/LookAndFeelManager.java new file mode 100644 index 000000000..189da68f3 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/themes/LookAndFeelManager.java @@ -0,0 +1,176 @@ +package org.jivesoftware.spark.ui.themes; + +import com.formdev.flatlaf.FlatLaf; +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Default; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import javax.swing.*; +import java.awt.*; +import java.util.*; + +/** + * Manages the Look and Feel instances that can be used by Spark. + * + * @author Guus der Kinderen, guus.der.kinderen@gmail.com + */ +public class LookAndFeelManager { + + /** + * All non-system provided look and feel implementations that are available. + */ + public static final Class lafs[] = new Class[]{ + //flatlaf + org.jivesoftware.spark.ui.themes.lafs.SparkLightLaf.class, + org.jivesoftware.spark.ui.themes.lafs.SparkIntelliJLaf.class, + org.jivesoftware.spark.ui.themes.lafs.SparkMacLightLaf.class +}; + + static { + // Add all additional look and feels to the UIManager. + for (Class laf : lafs) { + String name; + try { + name = laf.newInstance().getName(); + } catch (InstantiationException | IllegalAccessException e) { + name = laf.getTypeName(); + } + UIManager.installLookAndFeel(name, laf.getName()); + + } + } + + private static transient Map lookAndFeelClassByName = null; + + /** + * Gets the (human readable) name of a Look and Feel, based on its class + * name. + * + * @param className A class name (eg: + * com.jtattoo.plaf.luna.LunaLookAndFeel). + * @return a human readable name, or null if the class name is not + * recognized. + */ + public static String getName(String className) { + final Map lookAndFeelClassByName = getLookAndFeelClassByName(); + for (final Map.Entry entry : lookAndFeelClassByName.entrySet()) { + if (entry.getValue().equalsIgnoreCase(className)) { + return entry.getKey(); + } + } + + return null; + } + + /** + * Gets the class name of a Look and Feel, based on its (human readable) + * name. + * + * @param name a human readable name (eg: "Luna") + * @return A class name (eg: com.jtattoo.plaf.luna.LunaLookAndFeel) or null + * if the class name is not recognized + */ + public static String getClassName(String name) { + return getLookAndFeelClassByName().get(name); + } + + /** + * Determines if setting the look and feel as identified by it's human + * readable name requires a Spark restart. + * + * @param name The (human readable name (eg: "Luna"). + * @return true when Spark must be restarted to apply this Look And Feel. + */ + public static boolean requiresRestart(String name) { + // TODO: the original code required a restart for the java-provided LaFs and Synthetica, but perhaps that's no longer needed? + return false; + } + + private synchronized static Map getLookAndFeelClassByName() { + // Lazy loading of the ordered collection. + if (lookAndFeelClassByName == null) { + final UIManager.LookAndFeelInfo[] lafis = UIManager.getInstalledLookAndFeels(); + + lookAndFeelClassByName = new TreeMap<>(String::compareToIgnoreCase); + for (final UIManager.LookAndFeelInfo lafi : lafis) { + //Add only custom Laf, drop system Laf + if(lafi.getClassName().contains("org.jivesoftware.spark.ui.themes.lafs.")){ + lookAndFeelClassByName.put(lafi.getName(), lafi.getClassName()); + } + } + } + return lookAndFeelClassByName; + } + + private static String getLookandFeel(LocalPreferences preferences) { + String result; + + String whereToLook = Spark.isMac() ? Default.DEFAULT_LOOK_AND_FEEL_MAC : Default.DEFAULT_LOOK_AND_FEEL; + + if (!Default.getBoolean(Default.LOOK_AND_FEEL_DISABLED)) { + result = preferences.getLookAndFeel(); + } else if (Default.getString(whereToLook).length() > 0) { + result = Default.getString(whereToLook); + } else { + result = UIManager.getSystemLookAndFeelClassName(); + } + + return result; + } + + /** + * Handles the Loading of the Look And Feel, as defined as the prefered Look + * And Feel in the local settings. + */ + public static void loadPreferredLookAndFeel() { + final LocalPreferences preferences = SettingsManager.getLocalPreferences(); + final String laf = getLookandFeel(preferences); + + if (laf.toLowerCase().contains("substance")) { + EventQueue.invokeLater(() -> doSetLookAndFeel(laf)); + } else { + doSetLookAndFeel(laf); + } + } + + private static void doSetLookAndFeel(String laf) { + try { + if (Spark.isWindows()) { + JFrame.setDefaultLookAndFeelDecorated(true); + JDialog.setDefaultLookAndFeelDecorated(true); + } + //skip loading from preference and use flatlaf as default + + if(SettingsManager.getLocalPreferences().isTabsScroll()){ + UIManager.put( "TabbedPane.tabLayoutPolicy", "scroll" ); + } else { + UIManager.put( "TabbedPane.tabLayoutPolicy", "wrap" ); + } + UIManager.put("TabbedPane.showTabSeparators", true); + UIManager.put("TabbedPane.hasFullBorder", true); + UIManager.put("TabbedPane.underlineColor", new Color(242, 159, 97)); + UIManager.put("TitlePane.unifiedBackground",false); + // Add "eye" button to show password for all passwordField + UIManager.put("PasswordField.showRevealButton",true); + if(!laf.contains("org.jivesoftware.spark.ui.themes.lafs.")){ + laf = Default.getString(Spark.isMac() ? Default.DEFAULT_LOOK_AND_FEEL_MAC : Default.DEFAULT_LOOK_AND_FEEL); + SettingsManager.getLocalPreferences().setLookAndFeel(laf); + } + UIManager.setLookAndFeel(laf); + FlatLaf.updateUILater(); + } catch (Exception e) { + Log.error("An exception occurred while trying to load the look and feel.", e); + } + } + + /** + * Returns the human readable name of all available Look And Feels. + * + * @return An array of names, never null. + */ + public static String[] getLookAndFeelNames() { + return getLookAndFeelClassByName().keySet().toArray(new String[0]); + } +} diff --git a/src/java/org/jivesoftware/spark/ui/themes/MainThemePanel.java b/core/src/main/java/org/jivesoftware/spark/ui/themes/MainThemePanel.java similarity index 82% rename from src/java/org/jivesoftware/spark/ui/themes/MainThemePanel.java rename to core/src/main/java/org/jivesoftware/spark/ui/themes/MainThemePanel.java index 8a4715089..1a5526c2f 100644 --- a/src/java/org/jivesoftware/spark/ui/themes/MainThemePanel.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/themes/MainThemePanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,8 +34,8 @@ public class MainThemePanel extends JPanel { private static final long serialVersionUID = 6014253744953992190L; - private ThemePanel _themepanel; - private ColorPreferencePanel _colorpanel; + private final ThemePanel _themepanel; + private final ColorPreferencePanel _colorpanel; public MainThemePanel() { @@ -49,11 +45,11 @@ public MainThemePanel() _colorpanel = new ColorPreferencePanel(); JTabbedPane tabs = new JTabbedPane(); - ImageIcon appe = new ImageIcon(SparkRes.getImageIcon(SparkRes.PALETTE_24x24_IMAGE).getImage().getScaledInstance(16, 16, Image.SCALE_SMOOTH)); - ImageIcon color = new ImageIcon(SparkRes.getImageIcon(SparkRes.COLOR_ICON).getImage().getScaledInstance(16, 16, Image.SCALE_SMOOTH)); + ImageIcon appe = new ImageIcon(SparkRes.getImageIcon(SparkRes.Icon.PALETTE_24x24_IMAGE).getImage().getScaledInstance(16, 16, Image.SCALE_SMOOTH)); + ImageIcon color = new ImageIcon(SparkRes.getImageIcon(SparkRes.Icon.COLOR_ICON).getImage().getScaledInstance(16, 16, Image.SCALE_SMOOTH)); tabs.addTab(Res.getString("title.appearance.preferences"),appe, _themepanel); - if(!Default.getBoolean("CHANGE_COLORS_DISABLED")){ + if(!Default.getBoolean(Default.CHANGE_COLORS_DISABLED)){ tabs.addTab(Res.getString("lookandfeel.color.label"),color,_colorpanel); } add(tabs); diff --git a/core/src/main/java/org/jivesoftware/spark/ui/themes/ThemePanel.java b/core/src/main/java/org/jivesoftware/spark/ui/themes/ThemePanel.java new file mode 100644 index 000000000..557be5e14 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/themes/ThemePanel.java @@ -0,0 +1,551 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.themes; + +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.TranscriptWindow; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.WindowsFileSystemView; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.emoticons.Emoticon; +import org.jivesoftware.sparkimpl.plugin.emoticons.EmoticonManager; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import javax.swing.*; +import java.awt.*; +import java.io.File; +import java.util.Objects; + +/** + * ThemePanel is used for the setting of TranscriptWindows and Emoticon packs. + */ +public class ThemePanel extends JPanel { + + private static final long serialVersionUID = 2943854311454590459L; + + private final JComboBox messageStyleBox; + + private final JComboBox emoticonBox; + + private final JButton addEmoticonButton; + + private final JTextField contactListFontField; + private final JLabel contactListFontLabel; + + private final JTextField chatRoomFontField; + private final JLabel chatRoomFontLabel; + + private final JTextField maxCurrentHistorySizeField; + private final JLabel maxCurrentHistorySizeLabel; + + private final JCheckBox emoticonCheckBox; + private JFileChooser fc; + + private final JCheckBox showAvatarsBox; + private final JCheckBox showVCards; + private final JLabel avatarSizeLabel; + private final JComboBox avatarSizeField; + + private final JCheckBox disableGrayingIdleContacts; + + private final JLabel _lookandfeelLabel; + private final JComboBox _lookandfeel; + private final JButton _lookandfeelpreview; + private final JCheckBox _useTabsForTransports; + private final JCheckBox _useTabsForConference; + + private final JComboBox _showReconnectBox; + + private final LocalPreferences pref = SettingsManager.getLocalPreferences(); + + private final JScrollPane emoticonscrollpane; + + private JPanel emoticonspanel; + + /** + * Construct UI + */ + public ThemePanel() { + setLayout(new GridBagLayout()); + + _lookandfeel = new JComboBox<>(LookAndFeelManager.getLookAndFeelNames()); + + if (Default.getBoolean(Default.LOOK_AND_FEEL_DISABLED)) { + _lookandfeel.setEnabled(false); + } + _lookandfeelLabel = new JLabel(Res.getString("lookandfeel.select")); + _lookandfeelpreview = new JButton(Res.getString("lookandfeel.change.now")); + + _lookandfeel.addActionListener(e + -> { + final boolean requiresRestart = LookAndFeelManager.requiresRestart((String) _lookandfeel.getSelectedItem()); + if (requiresRestart) { + _lookandfeelpreview.setEnabled(false); + _lookandfeelpreview.setToolTipText(Res.getString("lookandfeel.tooltip.restart.yes")); + } else { + _lookandfeelpreview.setEnabled(true); + _lookandfeelpreview.setToolTipText(Res.getString("lookandfeel.tooltip.restart.no")); + } + _lookandfeelpreview.revalidate(); + }); + + _lookandfeelpreview.addActionListener(e + -> { + SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + return 42; + } + + private void setNewLaF() { + final String selectedName = (String) _lookandfeel.getSelectedItem(); + try { + final String className = LookAndFeelManager.getClassName(selectedName); + UIManager.setLookAndFeel(className); + } catch (Exception e) { + Log.error("An unexpected exception occurred while trying to update Look and Feel to '" + selectedName + "'.", e); + } + } + + private void updateAllComponentsLaF(final Window window) { + for (Window childWindow : window.getOwnedWindows()) { + updateAllComponentsLaF(childWindow); + } + SwingUtilities.updateComponentTreeUI(window); + } + + @Override + public void finished() { + UIManager.put("OptionPane.yesButtonText", Res.getString("yes")); + UIManager.put("OptionPane.noButtonText", Res.getString("no")); + + // substance is a PITA! If the current laf is substance, and the new laf is not, we need to + // refresh all components, but since substance is very stubborn, we must restart. + final String currentName = UIManager.getLookAndFeel().getName().toLowerCase(); + final String selectedName = ((String) _lookandfeel.getSelectedItem()); + final String selectedClass = LookAndFeelManager.getClassName(selectedName); + if (currentName.contains("substance") && !selectedName.toLowerCase().contains("substance")) { + final int selectedOption = JOptionPane.showConfirmDialog(SparkManager.getPreferenceManager().getPreferenceDialog(), + Res.getString("message.restart.required"), + Res.getString("title.alert"), + JOptionPane.YES_NO_OPTION); + if (selectedOption == JOptionPane.YES_OPTION) { + setNewLaF(); + SettingsManager.getLocalPreferences().setLookAndFeel(selectedClass); + SparkManager.getMainWindow().logout(false); + } + } else { + // otherwise we're ok to just refresh all components + setNewLaF(); + for (Frame frame : Frame.getFrames()) { + updateAllComponentsLaF(frame); + } + JFrame.setDefaultLookAndFeelDecorated(true); + JDialog.setDefaultLookAndFeelDecorated(true); + SettingsManager.getLocalPreferences().setLookAndFeel(selectedClass); + } + } + }; + worker.start(); + }); + + _useTabsForTransports = new JCheckBox(""); + _useTabsForConference = new JCheckBox(""); + + JLabel messageStyleLabel = new JLabel(); + messageStyleBox = new JComboBox<>(); + + emoticonspanel = new EmoticonPanel(10); + emoticonscrollpane = new JScrollPane(emoticonspanel); + emoticonscrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + emoticonscrollpane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + + emoticonBox = new JComboBox<>(); + + emoticonCheckBox = new JCheckBox(); + + JButton addThemeButton = new JButton(); + addEmoticonButton = new JButton(); + + TranscriptWindow emoticonpreviewtranscript = new TranscriptWindow(); + emoticonpreviewtranscript.setForceEmoticons(true); + + showAvatarsBox = new JCheckBox(); + avatarSizeLabel = new JLabel(); + String[] sizeChoices = {"16", "24", "32", "48", "96", "120"}; + avatarSizeField = new JComboBox<>(sizeChoices); + + contactListFontField = new JTextField(); + contactListFontLabel = new JLabel(); + + chatRoomFontField = new JTextField(); + chatRoomFontLabel = new JLabel(); + + maxCurrentHistorySizeField = new JTextField(); + maxCurrentHistorySizeLabel = new JLabel(); + + + String[] r = { + Res.getString("checkbox.reconnect.panel.big"), + Res.getString("checkbox.reconnect.panel.small"), + Res.getString("checkbox.reconnect.panel.icon") + }; + _showReconnectBox = new JComboBox<>(r); + + _showReconnectBox.setSelectedIndex(pref.getReconnectPanelType()); + + _showReconnectBox.addActionListener(e + -> { + if (_showReconnectBox.getSelectedIndex() != -1) { + setShowReconnectPanel(_showReconnectBox.getSelectedIndex()); + } + }); + + showVCards = new JCheckBox(); + + disableGrayingIdleContacts = new JCheckBox(Res.getString("checkbox.graying.out")); + + // Set ResourceUtils + ResourceUtils.resLabel(messageStyleLabel, messageStyleBox, Res.getString("label.message.style") + ":"); +// ResourceUtils.resLabel(emoticonsLabel, emoticonBox, Res.getString("label.emoticons") + ":"); + ResourceUtils.resButton(emoticonCheckBox, Res.getString("checkbox.enable.emoticons")); + + ResourceUtils.resButton(addThemeButton, Res.getString("button.add")); + ResourceUtils.resButton(addEmoticonButton, Res.getString("button.add")); + + ResourceUtils.resLabel(contactListFontLabel, contactListFontField, Res.getString("label.contactlist.fontsize")); + ResourceUtils.resLabel(chatRoomFontLabel, chatRoomFontField, Res.getString("label.chatroom.fontsize")); + ResourceUtils.resLabel(maxCurrentHistorySizeLabel, maxCurrentHistorySizeField, Res.getString("label.chatroom.maxcurrenthistorysize")); + ResourceUtils.resButton(showAvatarsBox, Res.getString("checkbox.show.avatars.in.contactlist")); + ResourceUtils.resLabel(avatarSizeLabel, avatarSizeField, Res.getString("label.contactlist.avatarsize")); + ResourceUtils.resButton(showVCards, Res.getString("title.appearance.showVCards")); + _useTabsForTransports.setText(Res.getString("checkbox.transport.tab.setting")); + _useTabsForConference.setText(Res.getString("checkbox.conference.tab.setting")); + + // Build UI + buildUI(); + } + + public String getSelectedLookAndFeelName() { + return (String) this._lookandfeel.getSelectedItem(); + } + + public String getSelectedLookAndFeelClassName() { + return LookAndFeelManager.getClassName(getSelectedLookAndFeelName()); + } + + /** + * Builds the UI. + */ + private void buildUI() { + // Add Viewer +// add(new JScrollPane(transcript), new GridBagConstraints(0, 0, 3, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); + add(emoticonscrollpane, new GridBagConstraints(0, 1, 3, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); + + add(emoticonBox, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + add(addEmoticonButton, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(emoticonCheckBox, new GridBagConstraints(0, 2, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + + add( _lookandfeelLabel, new GridBagConstraints( 0, 4, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 50, 0 ) ); + add( _lookandfeel, new GridBagConstraints( 1, 4, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets( 5, 5, 5, 5 ), 50, 0 ) ); + add( _lookandfeelpreview, new GridBagConstraints( 2, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 0, 0 ) ); + add(chatRoomFontLabel, new GridBagConstraints(0, 5, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(chatRoomFontField, new GridBagConstraints(1, 5, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); + add(contactListFontLabel, new GridBagConstraints(0, 6, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(contactListFontField, new GridBagConstraints(1, 6, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); + add(maxCurrentHistorySizeLabel, new GridBagConstraints(0, 7, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(maxCurrentHistorySizeField, new GridBagConstraints(1, 7, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); + add(showAvatarsBox, new GridBagConstraints(0, 8, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(avatarSizeLabel, new GridBagConstraints(0, 9, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(avatarSizeField, new GridBagConstraints(1, 9, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); + add(showVCards, new GridBagConstraints(0, 10, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); + add(disableGrayingIdleContacts, new GridBagConstraints(0, 11, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); + add(_useTabsForTransports, new GridBagConstraints(0, 12, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); + add(_useTabsForConference, new GridBagConstraints(0, 13, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); + + JLabel reconnectionlabel = new JLabel(Res.getString("checkbox.reconnect.info")); + add(reconnectionlabel, new GridBagConstraints(0, 14, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); + add(_showReconnectBox, new GridBagConstraints(1, 14, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); + + // Activate live one. + _useTabsForTransports.setSelected(pref.getShowTransportTab()); + _useTabsForTransports.addActionListener(e -> SettingsManager.getLocalPreferences().setShowTransportTab(_useTabsForTransports.isSelected())); + _useTabsForConference.setSelected(pref.isShowConferenceTab()); + _useTabsForConference.addActionListener(e -> SettingsManager.getLocalPreferences().setShowConferenceTab( + _useTabsForConference.isSelected())); + + _useTabsForConference.setSelected(pref.isShowConferenceTab()); + _useTabsForConference.addActionListener(e -> SettingsManager.getLocalPreferences().setShowConferenceTab(_useTabsForConference.isSelected())); + + final EmoticonManager emoticonManager = EmoticonManager.getInstance(); + if (emoticonManager.getEmoticonPacks() != null) { + for (String pack : emoticonManager.getEmoticonPacks()) { + emoticonBox.addItem(pack); + } + } + + final String activePack = pref.getEmoticonPack(); + emoticonBox.setSelectedItem(activePack); + + emoticonBox.addActionListener(e + -> { + emoticonManager.addEmoticonPack((String) emoticonBox.getSelectedItem()); + emoticonManager.setActivePack((String) emoticonBox.getSelectedItem()); + showSelectedEmoticon(); + }); + + addEmoticonButton.addActionListener(e -> addEmoticonPack()); + + showSelectedEmoticon(); + + emoticonCheckBox.setSelected(pref.areEmoticonsEnabled()); + + final String className = pref.getLookAndFeel(); + final String name = LookAndFeelManager.getName(className); + _lookandfeel.setSelectedItem(name); + + showVCards.setSelected(pref.areVCardsVisible()); + + showAvatarsBox.setSelected(pref.areAvatarsVisible()); + + disableGrayingIdleContacts.setSelected(pref.isGrayingOutEnabled()); + + String contactListIconSizeItem = String.valueOf(pref.getContactListIconSize()); + avatarSizeField.setSelectedItem(contactListIconSizeItem); + // if there wasn't such size then add and select it + if (!Objects.equals(avatarSizeField.getSelectedItem(), contactListIconSizeItem)) { + avatarSizeField.addItem(contactListIconSizeItem); + avatarSizeField.setSelectedItem(contactListIconSizeItem); + } + + try { + int chatRoomFontSize = pref.getChatRoomFontSize(); + int contactListFontSize = pref.getContactListFontSize(); + int maxCurrentHistorySize = pref.getMaxCurrentHistorySize(); + + chatRoomFontField.setText(Integer.toString(chatRoomFontSize)); + contactListFontField.setText(Integer.toString(contactListFontSize)); + maxCurrentHistorySizeField.setText(Integer.toString(maxCurrentHistorySize)); + } catch (Exception e) { + Log.error(e); + } + } + + /** + * Displays the active emoticon pack. + */ + protected void showSelectedEmoticon() { + EmoticonManager emoticonManager = EmoticonManager.getInstance(); + + int i = emoticonManager.getActiveEmoticonSet().size(); + if (i == 0) { + emoticonspanel = new EmoticonPanel(1); + JLabel label = new JLabel(SparkRes.getImageIcon(SparkRes.Icon.SMALL_DELETE)); + emoticonspanel.add(label); + } else if (i < 25) { + emoticonspanel = new EmoticonPanel(i); + } else { + emoticonspanel = new EmoticonPanel(10); + } + for (Emoticon emoticon : emoticonManager.getActiveEmoticonSet()) { + ImageIcon ico = new ImageIcon(emoticonManager.getEmoticonURL(emoticon)); + JLabel label = new JLabel(ico); + emoticonspanel.add(label); + } + + int rows = Math.min(((EmoticonPanel) emoticonspanel).getNumRows() * 45, 300); + emoticonscrollpane.setPreferredSize(new Dimension(300, rows)); + emoticonscrollpane.setViewportView(emoticonspanel); + this.revalidate(); + } + + /** + * Returns the name of the theme selected. + * + * @return the name of the selected theme. + */ + public String getSelectedTheme() { + return messageStyleBox.getItemAt(messageStyleBox.getSelectedIndex()); + } + + /** + * Returns the name of the selected emoticon pack. + * + * @return the name of the emoticon pack. + */ + public String getSelectedEmoticonPack() { + return (String) emoticonBox.getSelectedItem(); + } + + public void setEmoticonsEnabled(boolean enabled) { + emoticonCheckBox.setSelected(enabled); + } + + public boolean areEmoticonsEnabled() { + return emoticonCheckBox.isSelected(); + } + + public boolean isGrayingOutEnabled() { + return disableGrayingIdleContacts.isSelected(); + } + + /** + * Adds a new Emoticon pack to Spark. + */ + private void addEmoticonPack() { + if (fc == null) { + fc = new JFileChooser(); + if (Spark.isWindows()) { + fc.setFileSystemView(new WindowsFileSystemView()); + } + } + fc.setDialogTitle("Add Emoticon Pack"); + + fc.addChoosableFileFilter(new ZipFilter()); + + int returnVal = fc.showOpenDialog(this); + + if (returnVal == JFileChooser.APPROVE_OPTION) { + File pack = fc.getSelectedFile(); + try { + EmoticonManager emoticonManager = EmoticonManager.getInstance(); + String name = emoticonManager.installPack(pack); + + if (name == null) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(this, "Not a valid emoticon pack.", "Error", JOptionPane.ERROR_MESSAGE); + return; + } + + // If the name does not exists, add it to the message box. + for (int i = 0; i < emoticonBox.getItemCount(); i++) { + String n = emoticonBox.getItemAt(i); + if (name.equals(n)) { + return; + } + } + + emoticonBox.addItem(name); + + // Set Selected + emoticonBox.setSelectedItem(name); + } catch (Exception e) { + Log.error(e); + } + } + } + + /** + * The ZipFilter class is used by the emoticon file picker to filter out all + * other files besides *.zip files. + */ + private static class ZipFilter extends javax.swing.filechooser.FileFilter { + + @Override + public boolean accept(File file) { + String filename = file.getName(); + if (file.isDirectory()) { + return true; + } + return filename.endsWith(".zip"); + } + + @Override + public String getDescription() { + return "*.zip"; + } + } + + public String getChatRoomFontSize() { + return chatRoomFontField.getText(); + } + + public String getContactListFontSize() { + return contactListFontField.getText(); + } + + public String getMaxCurrentHistorySize() { + return maxCurrentHistorySizeField.getText(); + } + + public int getContactListIconSize() { + String selectedSize = (String) avatarSizeField.getSelectedItem(); + if (selectedSize == null) { + return 32; + } + return Integer.parseInt(selectedSize); + } + + public boolean areAvatarsVisible() { + return showAvatarsBox.isSelected(); + } + + public boolean areVCardsVisible() { + return showVCards.isSelected(); + } + + /** + * Return 0,1,2 + * + * @return + */ + public int getReconnectPanelType() { + return _showReconnectBox.getSelectedIndex(); + } + + /** + * set 0,1,2 + * + * @param reconnect + */ + public void setShowReconnectPanel(int reconnect) { + _showReconnectBox.setSelectedIndex(reconnect); + } + + protected JLabel getLookandfeelLabel() { + return _lookandfeelLabel; + } + + protected JComboBox getLookandfeel() { + return _lookandfeel; + } + + protected JButton getLookandfeelpreview() { + return _lookandfeelpreview; + } + + protected JCheckBox getUseTabsForConference() { + return _useTabsForConference; + } + + protected JCheckBox getShowAvatarsBox() { + return showAvatarsBox; + } + + protected JLabel getAvatarSizeLabel() { + return avatarSizeLabel; + } + + protected JComboBox getAvatarSizeField() { + return avatarSizeField; + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/themes/ThemePreference.java b/core/src/main/java/org/jivesoftware/spark/ui/themes/ThemePreference.java new file mode 100644 index 000000000..7eae83d0b --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/themes/ThemePreference.java @@ -0,0 +1,124 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.ui.themes; + +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.preference.Preference; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import javax.swing.*; + +/** + */ +public class ThemePreference implements Preference { + + private MainThemePanel panel; + + public static final String NAMESPACE = "themes"; + + public ThemePreference() {} + + @Override + public String getTitle() { + return Res.getString("title.appearance.preferences"); + } + + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.PALETTE_24x24_IMAGE); + } + + @Override + public String getTooltip() { + return Res.getString("tooltip.appearance"); + } + + @Override + public String getListName() { + return Res.getString("title.appearance"); + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public JComponent getGUI() { + panel = new MainThemePanel(); + return panel; + } + + @Override + public void load() {} + + @Override + public boolean isDataValid() { + return true; + } + + @Override + public String getErrorMessage() { + return null; + } + + @Override + public Object getData() { + return null; + } + + @Override + public void commit() { + final String pack = panel.getThemePanel().getSelectedEmoticonPack(); + boolean emotEnabled = panel.getThemePanel().areEmoticonsEnabled(); + boolean grayingOutEnabled = panel.getThemePanel().isGrayingOutEnabled(); + LocalPreferences pref = SettingsManager.getLocalPreferences(); + if(pack != null){ + pref.setEmoticonPack(pack); + } + pref.setEmoticonsEnabled(emotEnabled); + pref.setLookAndFeel(panel.getThemePanel().getSelectedLookAndFeelClassName()); + pref.setAvatarVisible(panel.getThemePanel().areAvatarsVisible()); + pref.setContactListIconSize(panel.getThemePanel().getContactListIconSize()); + pref.setVCardsVisible(panel.getThemePanel().areVCardsVisible()); + pref.setGrayingOutEnabled(grayingOutEnabled); + pref.setReconnectPanelType(panel.getThemePanel().getReconnectPanelType()); + + try { + String chatRoomFontSize = panel.getThemePanel().getChatRoomFontSize(); + String contactListFontSize = panel.getThemePanel().getContactListFontSize(); + String maxCurrentHistorySize = panel.getThemePanel().getMaxCurrentHistorySize(); + + pref.setChatRoomFontSize(Integer.parseInt(chatRoomFontSize)); + pref.setContactListFontSize(Integer.parseInt(contactListFontSize)); + pref.setMaxCurrentHistorySize(Integer.parseInt(maxCurrentHistorySize)); + } + catch (NumberFormatException e) { + Log.error(e); + } + + + ColorSettingManager.saveColorSettings(); + } + + @Override + public void shutdown() {} +} + + diff --git a/core/src/main/java/org/jivesoftware/spark/ui/themes/lafs/SparkIntelliJLaf.java b/core/src/main/java/org/jivesoftware/spark/ui/themes/lafs/SparkIntelliJLaf.java new file mode 100644 index 000000000..08471cf2b --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/themes/lafs/SparkIntelliJLaf.java @@ -0,0 +1,19 @@ +package org.jivesoftware.spark.ui.themes.lafs; + +import com.formdev.flatlaf.FlatIntelliJLaf; + +public class SparkIntelliJLaf extends FlatIntelliJLaf { + + public static boolean setup() { + return setup(new SparkIntelliJLaf()); + } + @Override + public String getName() { + return "SparkIntelliJLaf"; + } + + @Override + public String getDescription() { + return "SparkIntelliJLaf Look and Feel"; + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/themes/lafs/SparkLightLaf.java b/core/src/main/java/org/jivesoftware/spark/ui/themes/lafs/SparkLightLaf.java new file mode 100644 index 000000000..44cbe154b --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/themes/lafs/SparkLightLaf.java @@ -0,0 +1,30 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.jivesoftware.spark.ui.themes.lafs; + +import com.formdev.flatlaf.FlatLightLaf; + + +/** + * + * @author KeepToo + */ +public class SparkLightLaf extends FlatLightLaf { + + public static boolean setup() { + return setup(new SparkLightLaf()); + } + + @Override + public String getName() { + return "SparkLightLaf"; + } + + @Override + public String getDescription() { + return "SparkLightLaf Look and Feel"; + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/themes/lafs/SparkLightLaf.properties b/core/src/main/java/org/jivesoftware/spark/ui/themes/lafs/SparkLightLaf.properties new file mode 100644 index 000000000..bf5447839 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/themes/lafs/SparkLightLaf.properties @@ -0,0 +1,335 @@ +# +# Copyright 2019 FormDev Software GmbH +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Colors and style mostly based on IntelliJ theme from IntelliJ IDEA Community Edition, +# which is licensed under the Apache 2.0 license. Copyright 2000-2019 JetBrains s.r.o. +# See: https://github.com/JetBrains/intellij-community/ + +#Modified by k33ptoo 2020 + +#---- variables ---- + +@background=#ffffff +@foreground=#000000 +@selectionBackground=#EC6F12 +@selectionForeground=#ffffff +@selectionInactiveBackground=#d4d4d4 +@selectionInactiveForeground=@foreground +@disabledText=#8C8C8C +@textComponentBackground=#ffffff +@menuBackground=#fff +@menuHoverBackground=darken(@menuBackground,10%,derived) +@menuCheckBackground=darken(@menuBackground,10%,derived) +@menuCheckHoverBackground=darken(@menuBackground,20%,derived) +@cellFocusColor=#000000 +@icon=#afafaf + +# Drop (use lazy colors for IntelliJ platform themes, which usually do not specify these colors) +@dropCellBackground=lighten(List.selectionBackground,10%,lazy) +@dropCellForeground=lazy(List.selectionForeground) +@dropLineColor=lighten(List.selectionBackground,20%,lazy) +@dropLineShortColor=darken(List.selectionBackground,20%,lazy) + + +#---- globals ---- + +*.background=@background +*.foreground=@foreground +*.textBackground=#cccccc +*.textForeground=@foreground +*.caretForeground=@foreground +*.inactiveBackground=@background +*.inactiveForeground=@disabledText +*.selectionBackground=@selectionBackground +*.selectionForeground=@selectionForeground +*.disabledBackground=@background +*.disabledForeground=@disabledText +*.disabledText=@disabledText +*.acceleratorForeground=lighten(@foreground,30%) +*.acceleratorSelectionForeground=@selectionForeground + + +#---- system colors ---- + +activeCaption=#F6BF95 +inactiveCaption=#F9D4B8 +controlHighlight=#e3e3e3 +controlLtHighlight=#fff +controlDkShadow=darken($controlShadow,15%) + + +#---- Button ---- + +Button.background=#F1F1F1 +Button.focusedBackground=$Button.background +Button.hoverBackground=#D1D1D3 +Button.pressedBackground=darken($Button.background,10%,derived) + +Button.borderColor=@background +Button.disabledBorderColor=$Component.disabledBorderColor +Button.focusedBorderColor=$Component.focusedBorderColor +Button.hoverBorderColor=@background + +Button.default.background=$Button.background +Button.default.foreground=@foreground +Button.default.focusedBackground=$Button.focusedBackground +Button.default.hoverBackground=$Button.hoverBackground +Button.default.pressedBackground=$Button.pressedBackground +Button.default.borderColor=@background +Button.default.hoverBorderColor=@background +Button.default.focusedBorderColor=@background +Button.default.focusColor=$Button.background +Button.default.borderWidth=0 + +Button.toolbar.hoverBackground=darken($Button.background,12%,derived) +Button.toolbar.pressedBackground=darken($Button.background,15%,derived) + + +#---- CheckBox ---- + +# enabled +CheckBox.icon.borderColor=#b0b0b0 +CheckBox.icon.background=#FFFFFF +CheckBox.icon.selectedBorderColor=$CheckBox.icon.borderColor +CheckBox.icon.selectedBackground=$CheckBox.icon.background +CheckBox.icon.checkmarkColor=#F29F61 + +# disabled +CheckBox.icon.disabledBorderColor=#BDBDBD +CheckBox.icon.disabledBackground=@background +CheckBox.icon.disabledCheckmarkColor=#ABABAB + +# focused +CheckBox.icon.focusedBorderColor=#F29F61 +CheckBox.icon.focusedBackground=$Button.focusedBackground + +# hover +CheckBox.icon.hoverBorderColor=$CheckBox.icon.focusedBorderColor +CheckBox.icon.hoverBackground=$Button.hoverBackground + +# pressed +CheckBox.icon.pressedBackground=$Button.pressedBackground + + +# used if CheckBox.icon.style=filled +# enabled +CheckBox.icon[filled].selectedBorderColor=#F29F61 +CheckBox.icon[filled].selectedBackground=#F29F61 +CheckBox.icon[filled].checkmarkColor=#FFFFFF +# focused +CheckBox.icon[filled].selectedFocusedBorderColor=#E8995D +CheckBox.icon[filled].selectedFocusedBackground=$CheckBox.icon[filled].selectedBackground +CheckBox.icon[filled].selectedFocusedCheckmarkColor=$CheckBox.icon.focusedBackground +# hover +CheckBox.icon[filled].selectedHoverBackground=#D28A54 +# pressed +CheckBox.icon[filled].selectedPressedBackground=#CA8550 + + +#---- ComboBox ---- + +ComboBox.background=@textComponentBackground +ComboBox.buttonBackground=@textComponentBackground +ComboBox.buttonEditableBackground=#fafafa +ComboBox.buttonArrowColor=#666666 +ComboBox.buttonDisabledArrowColor=#ABABAB +ComboBox.buttonHoverArrowColor=#999999 + + +#---- Component ---- + +Component.borderColor=#c4c4c4 +Component.disabledBorderColor=#cfcfcf +Component.focusedBorderColor=#c4c4c4 +Component.focusColor=#E8995D +Component.linkColor=#EC6F12 +Component.grayFilter=25,-25,100 + +Component.error.borderColor=lighten(desaturate($Component.error.focusedBorderColor,20%),25%) +Component.error.focusedBorderColor=#e53e4d +Component.warning.borderColor=lighten(saturate($Component.warning.focusedBorderColor,25%),20%) +Component.warning.focusedBorderColor=#e2a53a +Component.custom.borderColor=lighten(desaturate(#f00,20%,derived noAutoInverse),25%,derived noAutoInverse) + + +#---- Desktop ---- + +Desktop.background=#E6EBF0 + + +#---- DesktopIcon ---- + +DesktopIcon.background=darken($Desktop.background,10%) + + +#---- HelpButton ---- + +HelpButton.questionMarkColor=#F29F61 + + +#---- InternalFrame ---- + +InternalFrame.activeTitleBackground=#fff +InternalFrame.activeTitleForeground=@foreground +InternalFrame.inactiveTitleBackground=#fafafa +InternalFrame.inactiveTitleForeground=@disabledText + +InternalFrame.activeBorderColor=darken($Component.borderColor,20%) +InternalFrame.inactiveBorderColor=$Component.borderColor + +InternalFrame.buttonHoverBackground=darken($InternalFrame.activeTitleBackground,10%,derived) +InternalFrame.buttonPressedBackground=darken($InternalFrame.activeTitleBackground,20%,derived) +InternalFrame.closeHoverBackground=lazy(Actions.Red) +InternalFrame.closePressedBackground=darken(Actions.Red,10%,lazy) +InternalFrame.closeHoverForeground=#fff +InternalFrame.closePressedForeground=#fff + +InternalFrame.activeDropShadowOpacity=0.25 +InternalFrame.inactiveDropShadowOpacity=0.5 + + +#---- List ---- + +List.background=@textComponentBackground + + +#---- Menu ---- + +Menu.icon.arrowColor=#666666 +Menu.icon.disabledArrowColor=#ABABAB + + +#---- MenuBar ---- + +MenuBar.borderColor=#cdcdcd +MenuBar.hoverBackground=@menuHoverBackground + + +#---- MenuItemCheckBox ---- + +MenuItemCheckBox.icon.checkmarkColor=#F29F61 +MenuItemCheckBox.icon.disabledCheckmarkColor=#ABABAB + + +#---- PasswordField ---- + +PasswordField.capsLockIconColor=#00000064 + + +#---- Popup ---- + +Popup.dropShadowColor=#000 +Popup.dropShadowOpacity=0.15 + + +#---- PopupMenu ---- + +PopupMenu.borderColor=#adadad + + +#---- ProgressBar ---- + +ProgressBar.background=#D1D1D1 +ProgressBar.foreground=#EC6F12 +ProgressBar.selectionForeground=@textComponentBackground +ProgressBar.selectionBackground=@foreground + + +#---- RadioButton ---- + +RadioButton.icon[filled].centerDiameter=5 + + +#---- ScrollBar ---- + +ScrollBar.track=lighten(@background,1%,derived noAutoInverse) +ScrollBar.thumb=darken($ScrollBar.track,10%,derived noAutoInverse) +ScrollBar.hoverTrackColor=darken($ScrollBar.track,3%,derived noAutoInverse) +ScrollBar.hoverThumbColor=darken($ScrollBar.thumb,10%,derived noAutoInverse) +ScrollBar.pressedThumbColor=darken($ScrollBar.thumb,20%,derived noAutoInverse) +ScrollBar.hoverButtonBackground=darken(@background,5%,derived noAutoInverse) +ScrollBar.pressedButtonBackground=darken(@background,10%,derived noAutoInverse) + + +#---- Separator ---- + +Separator.foreground=#d1d1d1 + + +#---- Slider ---- + +Slider.trackColor=#c4c4c4 +Slider.thumbColor=#6e6e6e +Slider.tickColor=#888888 +Slider.hoverColor=lighten($Slider.thumbColor,15%,derived) +Slider.disabledForeground=#c0c0c0 + + +#---- SplitPane ---- + +SplitPaneDivider.draggingColor=#c4c4c4 +SplitPaneDivider.oneTouchHoverArrowColor=#333333 + + +#---- TabbedPane ---- + +TabbedPane.disabledForeground=@disabledText +TabbedPane.underlineColor=#EC6F12 +TabbedPane.disabledUnderlineColor=#ababab +TabbedPane.hoverColor=#d9d9d9 +TabbedPane.focusColor=#dae4ed +TabbedPane.contentAreaColor=#bfbfbf + + +#---- Table ---- + +Table.background=@textComponentBackground +Table.gridColor=darken($Table.background,3%) + + +#---- TableHeader ---- + +TableHeader.background=@textComponentBackground +TableHeader.separatorColor=darken($TableHeader.background,10%) +TableHeader.bottomSeparatorColor=$TableHeader.separatorColor + + +#---- TitlePane ---- + +TitlePane.embeddedForeground=lighten($TitlePane.foreground,35%) +TitlePane.buttonHoverBackground=darken($TitlePane.background,10%,derived) +TitlePane.buttonPressedBackground=darken($TitlePane.background,20%,derived) + + +#---- ToggleButton ---- + +ToggleButton.selectedBackground=darken($ToggleButton.background,20%,derived) +ToggleButton.selectedForeground=@foreground +ToggleButton.disabledSelectedBackground=darken($ToggleButton.background,13%,derived) + +ToggleButton.toolbar.selectedBackground=$ToggleButton.selectedBackground + + +#---- ToolTip ---- + +ToolTip.border=4,6,4,6,$InternalFrame.activeBorderColor +ToolTip.background=#fafafa + + +#---- Tree ---- + +Tree.background=@textComponentBackground +Tree.hash=#E6E6E6 diff --git a/core/src/main/java/org/jivesoftware/spark/ui/themes/lafs/SparkMacLightLaf.java b/core/src/main/java/org/jivesoftware/spark/ui/themes/lafs/SparkMacLightLaf.java new file mode 100644 index 000000000..0c6a366ac --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/themes/lafs/SparkMacLightLaf.java @@ -0,0 +1,19 @@ +package org.jivesoftware.spark.ui.themes.lafs; + +import com.formdev.flatlaf.themes.FlatMacLightLaf; + +public class SparkMacLightLaf extends FlatMacLightLaf { + public static boolean setup() { + return setup(new SparkMacLightLaf()); + } + + @Override + public String getName() { + return "SparkMacLightLaf"; + } + + @Override + public String getDescription() { + return "SparkMacLightLaf Look and Feel"; + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/uri/UriManager.java b/core/src/main/java/org/jivesoftware/spark/uri/UriManager.java new file mode 100644 index 000000000..427f0bcfa --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/uri/UriManager.java @@ -0,0 +1,374 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.uri; + +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; + +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smack.roster.RosterEntry; +import org.jivesoftware.smack.roster.RosterGroup; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.UserManager; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.conferences.ConferenceUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; + +import static org.jivesoftware.spark.util.StringUtils.unescapeFromXML; + +/** + * Class to handle URI-Mappings defined by
      + * XEP-0147: XMPP URI Scheme Query Components + * + * @author wolf.posdorfer + */ +public class UriManager { + + public enum uritypes { + message, + join, + unsubscribe, + subscribe, + roster, + remove; + } + + /** + * Handles XMPP URI Mappings. + * E.g.: xmpp:open_chat@conference.igniterealtime.org?join;password=somesecret + * See XMPP URI/IRI Querytypes + * + * @param xmppUri the XMPP URI passed into Spark or received in a chat message. + * @param isCommand the XMPP URI passed into Spark or received in a chat message. + */ + public void handleURIMapping(String xmppUri, boolean isCommand) { + if (xmppUri == null) { + return; + } + if (!xmppUri.startsWith("xmpp")) { + return; + } + + Log.debug("Handling URI mapping for: " + xmppUri); + URI uri; + try { + uri = parseXmppUri(xmppUri); + } catch (URISyntaxException e) { + Log.error("error parsing uri: " + xmppUri, e); + return; + } + + String query = uri.getQuery(); + if (query == null) { + // No query string, so assume the URI is xmpp:JID + Jid jid = retrieveJID(uri); + if (jid == null) { + return; + } + EntityBareJid bareJid = jid.asEntityBareJidOrThrow(); + UserManager userManager = SparkManager.getUserManager(); + String nickname = userManager.getUserNicknameFromJID(bareJid); + ChatManager chatManager = SparkManager.getChatManager(); + ChatRoom chatRoom = chatManager.createChatRoom(bareJid, nickname, nickname); + chatManager.getChatContainer().activateChatRoom(chatRoom); + } else { + // extract the command from the query string i.e. "join" from "?join;password=somesecret" + String command = query; + int cmdEndPos = query.indexOf(';'); + if (cmdEndPos > 0) { + command = query.substring(0, cmdEndPos); + } + UriManager.uritypes commandUriType; + try { + commandUriType = UriManager.uritypes.valueOf(command.toLowerCase()); + } catch (IllegalArgumentException e) { + Log.error("Unknown XMPP URI command " + xmppUri); + return; + } + // For URI received in a chat it's allowed only the ?join command + if (!isCommand && commandUriType != uritypes.join) { + return; + } + + // Route URI to handler based on command + switch (commandUriType) { + case message: + try { + handleMessage(uri); + } catch (Exception e) { + Log.error("error with ?message URI", e); + } + break; + case join: + try { + handleConference(uri); + } catch (Exception e) { + Log.error("error with ?join URI", e); + } + break; + case subscribe: + try { + handleSubscribe(uri); + } catch (Exception e) { + Log.error("error with ?subscribe URI", e); + } + break; + case unsubscribe: + try { + handleUnsubscribe(uri); + } catch (Exception e) { + Log.error("error with ?unsubscribe URI", e); + } + break; + case roster: + try { + handleRoster(uri); + } catch (Exception e) { + Log.error("error with ?roster URI", e); + } + break; + case remove: + try { + handleRemove(uri); + } catch (Exception e) { + Log.error("error with ?remove URI", e); + } + break; + } + } + } + + URI parseXmppUri(String xmppUri) throws URISyntaxException { + URI uri; + /* + Java's URI class distinguishes between two types of URIs: + * Hierarchical URIs: Like http://example.com/path?query. These have a / after the scheme and colon. + * Opaque URIs: Like mailto:user@example.com or xmpp:user@domain. These do not have a / immediately following the scheme. + For opaque URIs, the URI class does not automatically parse the string into components like host, path, or query. + Instead, it treats everything after the colon as the Scheme Specific Part. + To reuse Java's built-in query parsing, we'll use the "Fake Hierarchical" Trick: + We temporarily transform the xmpp: URI into a hierarchical one (i.e. http:) just for parsing. + */ + uri = new URI(xmppUri.replaceFirst("xmpp:", "http://")); + return uri; + } + + /** + * handles the ?message URI + * + * @param uri + * the decoded uri + */ + public void handleMessage(URI uri) { + Jid jid = retrieveJID(uri); + if (jid == null) { + return; + } + // Find body + String body = retrieveParam(uri, "body"); + body = unescapeFromXML(body); + + UserManager userManager = SparkManager.getUserManager(); + String nickname = userManager.getUserNicknameFromJID(jid.asBareJid()); + ChatManager chatManager = SparkManager.getChatManager(); + ChatRoom chatRoom = chatManager.createChatRoom(jid.asEntityJidOrThrow(), nickname, nickname); + if (body != null && !body.isEmpty()) { + MessageBuilder messageBuilder = StanzaBuilder.buildMessage() + .setBody(body); + chatRoom.sendMessage(messageBuilder); + } + + chatManager.getChatContainer().activateChatRoom(chatRoom); + } + + /** + * Handles the ?join URI + * + * @param uri + * the decoded uri + */ + public void handleConference(URI uri) { + Jid jid = retrieveJID(uri); + if (jid == null) { + return; + } + String password = retrieveParam(uri, "password"); + ConferenceUtils.joinConferenceOnSeparateThread(jid, jid.asEntityBareJidOrThrow(), null, password); + } + + /** + * Handles the ?subscribe URI + * + * @param uri + * the decoded uri + * @throws Exception + */ + public void handleSubscribe(URI uri) throws Exception { + // xmpp:romeo@montague.net?subscribe + // Send contact add request + Jid jid = retrieveJID(uri); + if (jid == null) { + return; + } + XMPPConnection connection = SparkManager.getConnection(); + Presence response = connection.getStanzaFactory() + .buildPresenceStanza() + .ofType(Presence.Type.subscribe) + .to(jid) + .build(); + connection.sendStanza(response); + } + + /** + * Handles the ?unsubscribe URI + * + * @param uri + * the decoded uri + */ + public void handleUnsubscribe(URI uri) throws SmackException.NotConnectedException { + Jid jid = retrieveJID(uri); + if (jid == null) { + return; + } + + Presence response = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unsubscribe) + .build(); + response.setTo(jid); + try { + SparkManager.getConnection().sendStanza(response); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } + } + + /*** + * Handles the ?roster URI
      + * with name= and group= + * + * @param uri + * the decoded uri + * @throws Exception + */ + public void handleRoster(URI uri) throws Exception { + // xmpp:romeo@montague.net?roster + // xmpp:romeo@montague.net?roster;name=Romeo%20Montague + // xmpp:romeo@montague.net?roster;group=Friends + // xmpp:romeo@montague.net?roster;name=Romeo%20Montague;group=Friends + Jid jid = retrieveJID(uri); + if (jid == null) { + return; + } + BareJid bareJid = jid.asBareJid(); + + String name = retrieveParam(uri, "name"); + String group = retrieveParam(uri, "group"); + + Roster roster = SparkManager.getRoster(); + RosterEntry userEntry = roster.getEntry(bareJid); + + roster.preApproveAndCreateEntry(bareJid, name, new String[]{group}); + + RosterGroup rosterGroup = roster.getGroup(group); + if (rosterGroup == null) { + rosterGroup = roster.createGroup(group); + } + + if (userEntry == null) { + roster.preApproveAndCreateEntry(bareJid, name, new String[]{group}); + } else { + userEntry.setName(name); + rosterGroup.addEntry(userEntry); + } + } + + /** + * Handles the ?remove URI + * + * @param uri + * the decoded uri + * @throws Exception + */ + public void handleRemove(URI uri) throws Exception { + // xmpp:romeo@montague.net?remove + Jid jid = retrieveJID(uri); + if (jid == null) { + return; + } + BareJid bareJid = jid.asBareJid(); + + Roster roster = SparkManager.getRoster(); + RosterEntry entry = roster.getEntry(bareJid); + roster.removeEntry(entry); + } + + /** + * Gets JID from URI. Returns the full jid including resource romeo@montague.net/balcony + */ + public Jid retrieveJID(URI uri) { + if (uri.getHost() == null || uri.getUserInfo() == null) { + return null; + } + String jidString = ""; + if (uri.getUserInfo() != null) { + jidString += uri.getUserInfo(); + jidString += '@'; + } + jidString += uri.getHost(); + // Resource contains the leading / + String resource = uri.getPath(); + if (resource != null && !resource.isEmpty() && !resource.equals("/")) { + jidString += resource; + } + return JidCreate.fromOrNull(jidString); + } + + /** + * Extracts password from URI if present e.g., xmpp:open_chat@conference.igniterealtime.org?join;password=somesecret + */ + public String retrieveParam(URI uri, String param) { + String query = uri.getRawSchemeSpecificPart(); + int index = query.indexOf(";" + param + "="); + if (index == -1) { + return null; + } + int paramStart = index + (";" + param + "=").length(); + int paramEndPos = query.indexOf('&', paramStart); + if (paramEndPos == -1) { + paramEndPos = query.indexOf(';', paramStart); + if (paramEndPos == -1) { + paramEndPos = query.length(); + } + } + String result = query.substring(paramStart, paramEndPos); + if (result.isEmpty()) { + return null; + } + return URLDecoder.decode(result, StandardCharsets.UTF_8); + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/util/BrowserLauncher.java b/core/src/main/java/org/jivesoftware/spark/util/BrowserLauncher.java new file mode 100644 index 000000000..a7cb655b1 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/util/BrowserLauncher.java @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.util; + +import java.awt.Desktop; +import java.io.File; +import java.net.URI; + +public class BrowserLauncher { + + public static void openURL(String url) throws Exception { + if (url.startsWith("http") || url.startsWith("ftp") || url.startsWith("file") || url.startsWith("www")) { + if (url.startsWith("file") && url.contains(" ")) { + url = url.replace(" ", "%20"); + } + if (url.startsWith("www")) { + url = "http://" + url; + } + try { + Desktop.getDesktop().browse(new URI(url)); + } catch (Exception ex) { + // fallback on Linux + Runtime.getRuntime().exec("xdg-open " + url); + } + } else { + File f = new File(url); + if (f.exists() && Desktop.isDesktopSupported()) { + try { + Desktop.getDesktop().open(f); + } catch (Exception ex) { + if (!url.startsWith("//")) { + url = "//" + url; + } + Desktop.getDesktop().browse(new URI("http:" + url)); + } + } + } + } +} diff --git a/src/java/org/jivesoftware/spark/util/ByteFormat.java b/core/src/main/java/org/jivesoftware/spark/util/ByteFormat.java similarity index 98% rename from src/java/org/jivesoftware/spark/util/ByteFormat.java rename to core/src/main/java/org/jivesoftware/spark/util/ByteFormat.java index f9a2d6e26..ed44b5009 100644 --- a/src/java/org/jivesoftware/spark/util/ByteFormat.java +++ b/core/src/main/java/org/jivesoftware/spark/util/ByteFormat.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -63,6 +59,7 @@ public String formatKB(long kilobytes) { * @param pos field position. * @return A formatted string representing the given bytes in more human-readable form. */ + @Override public StringBuffer format(Object obj, StringBuffer buf, FieldPosition pos) { if (obj instanceof Long) { long numBytes = (Long) obj; @@ -93,6 +90,7 @@ else if (numBytes < 1024 * 1024 * 1024) { * @param pos Position to parse from. * @return returns null in this implementation. */ + @Override public Object parseObject(String source, ParsePosition pos) { return null; } diff --git a/src/java/org/jivesoftware/spark/util/ColorPick.java b/core/src/main/java/org/jivesoftware/spark/util/ColorPick.java similarity index 96% rename from src/java/org/jivesoftware/spark/util/ColorPick.java rename to core/src/main/java/org/jivesoftware/spark/util/ColorPick.java index d11bfba5f..8b7d52f46 100644 --- a/src/java/org/jivesoftware/spark/util/ColorPick.java +++ b/core/src/main/java/org/jivesoftware/spark/util/ColorPick.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -42,8 +38,8 @@ public class ColorPick extends JPanel implements ChangeListener { private static final long serialVersionUID = 2709297435120012839L; - private JSlider[] _sliderarray; - private JLabel _preview; + private final JSlider[] _sliderarray; + private final JLabel _preview; /** @@ -186,4 +182,10 @@ public void stateChanged(ChangeEvent e) { } } + @Override + public void setEnabled(boolean enabled) { + for(JSlider s : _sliderarray){ + s.setEnabled(enabled); + } + } } diff --git a/src/java/org/jivesoftware/spark/util/ColorUtil.java b/core/src/main/java/org/jivesoftware/spark/util/ColorUtil.java similarity index 97% rename from src/java/org/jivesoftware/spark/util/ColorUtil.java rename to core/src/main/java/org/jivesoftware/spark/util/ColorUtil.java index c3179eac3..e6bfa10d6 100644 --- a/src/java/org/jivesoftware/spark/util/ColorUtil.java +++ b/core/src/main/java/org/jivesoftware/spark/util/ColorUtil.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,8 +31,8 @@ public static Color blend(Color color1, Color color2, double ratio) { float r = (float)ratio; float ir = (float)1.0 - r; - float rgb1[] = new float[3]; - float rgb2[] = new float[3]; + float[] rgb1 = new float[3]; + float[] rgb2 = new float[3]; color1.getColorComponents(rgb1); color2.getColorComponents(rgb2); @@ -174,8 +170,8 @@ public static double colorDistance(double[] color1, double[] color2) { * @return Distance between colors. */ public static double colorDistance(Color color1, Color color2) { - float rgb1[] = new float[3]; - float rgb2[] = new float[3]; + float[] rgb1 = new float[3]; + float[] rgb2 = new float[3]; color1.getColorComponents(rgb1); color2.getColorComponents(rgb2); diff --git a/core/src/main/java/org/jivesoftware/spark/util/Encryptor.java b/core/src/main/java/org/jivesoftware/spark/util/Encryptor.java new file mode 100644 index 000000000..161132e82 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/util/Encryptor.java @@ -0,0 +1,62 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.util; + +import org.jasypt.util.text.AES256TextEncryptor; +import org.jivesoftware.resource.Res; + +import javax.swing.*; + +/** + * Encrypts and Decrypts text using AES256 key derived from user-defined password (PBKDF2). + * + * @author Derek DeMoro + */ +public class Encryptor { + + private static final IllegalArgumentException UNDEFINED_MASTER_PASSWORD_EXCEPTION = new IllegalArgumentException("No master password provided"); + public static final AES256TextEncryptor AES256_INSTANCE = new AES256TextEncryptor(); + private static boolean MASTER_PASSWORD_SET = false; + + /** + * Set the Master password for PBKDF + * @param isNew first time the master password is set (nothing encrypted before) + */ + public static void setMasterPassword(boolean isNew) { + if(MASTER_PASSWORD_SET) { + return; + } + + final JPasswordField passwordField = new JPasswordField(70); + final int option = JOptionPane.showConfirmDialog(null, passwordField, Res.getString(isNew? "dialog.title.master.password.prompt.new": "dialog.title.master.password.prompt.old"), JOptionPane.OK_CANCEL_OPTION); + if(option != JOptionPane.OK_OPTION) // pressing OK button + { + throw UNDEFINED_MASTER_PASSWORD_EXCEPTION; + } + + AES256_INSTANCE.setPasswordCharArray(passwordField.getPassword()); + MASTER_PASSWORD_SET = true; + } + + public static void setMasterPassword(String password) { + if(password == null) { + throw UNDEFINED_MASTER_PASSWORD_EXCEPTION; + } + + AES256_INSTANCE.setPassword(password); + MASTER_PASSWORD_SET = true; + } +} diff --git a/src/java/org/jivesoftware/spark/util/GraphicUtils.java b/core/src/main/java/org/jivesoftware/spark/util/GraphicUtils.java similarity index 78% rename from src/java/org/jivesoftware/spark/util/GraphicUtils.java rename to core/src/main/java/org/jivesoftware/spark/util/GraphicUtils.java index ece155d7b..6626fe7d2 100644 --- a/src/java/org/jivesoftware/spark/util/GraphicUtils.java +++ b/core/src/main/java/org/jivesoftware/spark/util/GraphicUtils.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -45,15 +41,11 @@ import java.io.FileInputStream; import java.io.IOException; import java.net.URL; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JComponent; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JPopupMenu; +import javax.swing.*; import org.jivesoftware.resource.SparkRes; import org.jivesoftware.spark.util.log.Log; @@ -73,7 +65,7 @@ public final class GraphicUtils { }; protected final static MediaTracker tracker = new MediaTracker(component); - private static Map imageCache = new HashMap<>(); + private static final Map imageCache = new HashMap<>(); /** * The default Hand cursor. @@ -224,35 +216,33 @@ public static Point getPopupMenuShowPoint(JPopupMenu popup, MouseEvent event) { * coordinates */ public static Point getPopupMenuShowPoint(JPopupMenu popup, int x, int y) { - Dimension sizeMenu = popup.getPreferredSize(); - Point bottomRightMenu = new Point(x + sizeMenu.width, y - + sizeMenu.height); - - Rectangle[] screensBounds = getScreenBounds(); - int n = screensBounds.length; - for (int i = 0; i < n; i++) { - Rectangle screenBounds = screensBounds[i]; - if (screenBounds.x <= x - && x <= (screenBounds.x + screenBounds.width)) { - Dimension sizeScreen = screenBounds.getSize(); - sizeScreen.height -= 32; // Hack to help prevent menu being - // clipped by Windows/Linux/Solaris - // Taskbar. - - int xOffset = 0; - if (bottomRightMenu.x > (screenBounds.x + sizeScreen.width)) - xOffset = -sizeMenu.width; - - int yOffset = 0; - if (bottomRightMenu.y > (screenBounds.y + sizeScreen.height)) - yOffset = sizeScreen.height - bottomRightMenu.y; - - return new Point(x + xOffset, y + yOffset); - } - } - - return new Point(x, y); // ? that would mean that the top left point was - // not on any screen. + Dimension sizeMenu = popup.getPreferredSize(); + Point bottomRightMenu = new Point(x + sizeMenu.width, y + + sizeMenu.height); + + Rectangle[] screensBounds = getScreenBounds(); + for (Rectangle screenBounds : screensBounds) { + if (screenBounds.x <= x + && x <= (screenBounds.x + screenBounds.width)) { + Dimension sizeScreen = screenBounds.getSize(); + sizeScreen.height -= 32; // Hack to help prevent menu being + // clipped by Windows/Linux/Solaris + // Taskbar. + + int xOffset = 0; + if (bottomRightMenu.x > (screenBounds.x + sizeScreen.width)) + xOffset = -sizeMenu.width; + + int yOffset = 0; + if (bottomRightMenu.y > (screenBounds.y + sizeScreen.height)) + yOffset = sizeScreen.height - bottomRightMenu.y; + + return new Point(x + xOffset, y + yOffset); + } + } + + return new Point(x, y); // ? that would mean that the top left point was + // not on any screen. } /** @@ -491,19 +481,19 @@ public static Rectangle[] getScreenBounds() { * * @param comps */ - public static void makeSameSize(JComponent... comps) { + public static void makeSameSize(Component... comps) { if (comps.length == 0) { return; } int max = 0; - for (JComponent comp1 : comps) { + for (Component comp1 : comps) { int w = comp1.getPreferredSize().width; - max = w > max ? w : max; + max = Math.max(w, max); } Dimension dim = new Dimension(max, comps[0].getPreferredSize().height); - for (JComponent comp : comps) { + for (Component comp : comps) { comp.setPreferredSize(dim); } } @@ -644,17 +634,14 @@ public static Image toImage(BufferedImage bufferedImage) { } /** - * * @param size * @return */ private static ConvolveOp getBlurOp(int size) { - float[] data = new float[size * size]; - float value = 1 / (float) (size * size); - for (int i = 0; i < data.length; i++) { - data[i] = value; - } - return new ConvolveOp(new Kernel(size, size, data)); + float[] data = new float[size * size]; + float value = 1 / (float) (size * size); + Arrays.fill(data, value); + return new ConvolveOp(new Kernel(size, size, data)); } /** @@ -663,18 +650,16 @@ private static ConvolveOp getBlurOp(int size) { * * @param im * @return {@link BufferedImage} - * @throws InterruptedException * @throws {@link IOException} */ - public static BufferedImage convert(Image im) throws InterruptedException, - IOException { - //load(im); - BufferedImage bi = new BufferedImage(im.getWidth(null), - im.getHeight(null), BufferedImage.TYPE_INT_ARGB_PRE); - Graphics bg = bi.getGraphics(); - bg.drawImage(im, 0, 0, null); - bg.dispose(); - return bi; + public static BufferedImage convert(Image im) { + //load(im); + BufferedImage bi = new BufferedImage(im.getWidth(null), + im.getHeight(null), BufferedImage.TYPE_INT_ARGB_PRE); + Graphics bg = bi.getGraphics(); + bg.drawImage(im, 0, 0, null); + bg.dispose(); + return bi; } /** @@ -702,30 +687,20 @@ public static void load(Image image) throws InterruptedException, * @return byte[] */ public static byte[] getBytesFromImage(File file) { - FileInputStream fileInputStream = null; - try { - fileInputStream = new FileInputStream(file); + try (FileInputStream fileInputStream = new FileInputStream(file)) { byte[] data = new byte[(int) file.length()]; - fileInputStream.read(data); - fileInputStream.close(); - return data; - } catch (IOException e) { - if (fileInputStream != null) { - try { - fileInputStream.close(); - } catch (IOException e1) { - } - } - return null; - } - - + fileInputStream.read(data); + return data; + } catch (Exception e) { + Log.warning("Unable to read image", e); + return null; + } } /** * Returns a scaled down image if the height or width is smaller than the * image size. - * + * * @param icon * the image icon. * @param newHeight @@ -734,21 +709,26 @@ public static byte[] getBytesFromImage(File file) { * the preferred width. * @return the icon. */ - public static ImageIcon scaleImageIcon(ImageIcon icon, int newHeight, - int newWidth) { - Image img = icon.getImage(); - int height = icon.getIconHeight(); - int width = icon.getIconWidth(); - - if (height > newHeight) { - height = newHeight; - } - - if (width > newWidth) { - width = newWidth; - } - img = img.getScaledInstance(width, height, Image.SCALE_SMOOTH); - return new ImageIcon(img); + public static ImageIcon scaleImageIcon(ImageIcon icon, int newHeight, int newWidth) + { + try { + Image img = icon.getImage(); + int height = icon.getIconHeight(); + int width = icon.getIconWidth(); + + if (height > newHeight) { + height = newHeight; + } + + if (width > newWidth) { + width = newWidth; + } + img = img.getScaledInstance(width, height, Image.SCALE_SMOOTH); + return new ImageIcon(img); + } catch (Exception e) { + Log.warning("Unable to scale image", e); + return null; + } } /** @@ -763,38 +743,44 @@ public static ImageIcon scaleImageIcon(ImageIcon icon, int newHeight, * the preferred width. * @return the icon. */ - public static ImageIcon scale(ImageIcon icon, int newHeight, int newWidth) { - Image img = icon.getImage(); - int height = icon.getIconHeight(); - int width = icon.getIconWidth(); - boolean scaleHeight = height * newWidth > width * newHeight; - if (height > newHeight) { - // Too tall - if (width <= newWidth || scaleHeight) { - // Width is okay or height is limiting factor due to aspect - // ratio - height = newHeight; - width = -1; - } else { - // Width is limiting factor due to aspect ratio - height = -1; - width = newWidth; - } - } else if (width > newWidth) { - // Too wide and height is okay - height = -1; - width = newWidth; - } else if (scaleHeight) { - // Height is limiting factor due to aspect ratio - height = newHeight; - width = -1; - } else { - // Width is limiting factor due to aspect ratio - height = -1; - width = newWidth; - } - img = img.getScaledInstance(width, height, Image.SCALE_SMOOTH); - return new ImageIcon(img); + public static ImageIcon scale(ImageIcon icon, int newHeight, int newWidth) + { + try { + Image img = icon.getImage(); + int height = icon.getIconHeight(); + int width = icon.getIconWidth(); + boolean scaleHeight = height * newWidth > width * newHeight; + if (height > newHeight) { + // Too tall + if (width <= newWidth || scaleHeight) { + // Width is okay or height is limiting factor due to aspect + // ratio + height = newHeight; + width = -1; + } else { + // Width is limiting factor due to aspect ratio + height = -1; + width = newWidth; + } + } else if (width > newWidth) { + // Too wide and height is okay + height = -1; + width = newWidth; + } else if (scaleHeight) { + // Height is limiting factor due to aspect ratio + height = newHeight; + width = -1; + } else { + // Width is limiting factor due to aspect ratio + height = -1; + width = newWidth; + } + img = img.getScaledInstance(width, height, Image.SCALE_SMOOTH); + return new ImageIcon(img); + } catch (Exception e) { + Log.warning("Unable to scale image", e); + return null; + } } /** @@ -806,21 +792,13 @@ public static ImageIcon scale(ImageIcon icon, int newHeight, int newWidth) { * @return the native icon, otherwise default document icon. */ public static Icon getIcon(File file) { - try { - sun.awt.shell.ShellFolder sf = sun.awt.shell.ShellFolder - .getShellFolder(file); - - // Get large icon - return new ImageIcon(sf.getIcon(true), sf.getFolderType()); - } catch (Exception e) { - try { - return new JFileChooser().getIcon(file); - } catch (Exception e1) { - // Do nothing. - } - } + try { + return new JFileChooser().getIcon(file); + } catch (Exception e) { + Log.warning("unable to get icon", e); + } - return SparkRes.getImageIcon(SparkRes.DOCUMENT_INFO_32x32); + return SparkRes.getImageIcon(SparkRes.Icon.DOCUMENT_INFO_32x32); } /** @@ -831,19 +809,18 @@ public static Icon getIcon(File file) { * @return {@link BufferedImage} */ public static BufferedImage getBufferedImage(File file) { - // Why wasn't this using it's code that pulled from the file? Hrm. - Icon icon = SparkRes.getImageIcon(SparkRes.DOCUMENT_INFO_32x32); - - BufferedImage bi = new BufferedImage(icon.getIconWidth(), - icon.getIconHeight(), BufferedImage.OPAQUE); - Graphics bg = bi.getGraphics(); - - ImageIcon i = (ImageIcon) icon; - - bg.drawImage(i.getImage(), 0, 0, null); - bg.dispose(); - - return bi; + // Why wasn't this using it's code that pulled from the file? Hrm. + ImageIcon icon = SparkRes.getImageIcon(SparkRes.Icon.DOCUMENT_INFO_32x32); + + BufferedImage bi = null; + if (icon != null) { + bi = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.OPAQUE); + Graphics bg = bi.getGraphics(); + + bg.drawImage(icon.getImage(), 0, 0, null); + bg.dispose(); + } + return bi; } /** @@ -855,27 +832,32 @@ public static BufferedImage getBufferedImage(File file) { * @return */ public static ImageIcon fitToSquare(ImageIcon icon, int newSize) { - if (newSize <= 0) { - return icon; - } - - final int oldWidth = icon.getIconWidth(); - final int oldHeight = icon.getIconHeight(); - int newWidth; - int newHeight; - - if (oldHeight >= oldWidth) { - newWidth = (int) ((float) oldWidth * newSize / oldHeight); - newHeight = newSize; - } else { - newWidth = newSize; - newHeight = (int) ((float) oldHeight * newSize / oldWidth); - } - - final Image img = icon.getImage().getScaledInstance(newWidth, - newHeight, Image.SCALE_SMOOTH); - - return new ImageIcon(img); + try { + if (newSize <= 0) { + return icon; + } + + final int oldWidth = icon.getIconWidth(); + final int oldHeight = icon.getIconHeight(); + int newWidth; + int newHeight; + + if (oldHeight >= oldWidth) { + newWidth = (int) ((float) oldWidth * newSize / oldHeight); + newHeight = newSize; + } else { + newWidth = newSize; + newHeight = (int) ((float) oldHeight * newSize / oldWidth); + } + + final Image img = icon.getImage().getScaledInstance(newWidth, + newHeight, Image.SCALE_SMOOTH); + + return new ImageIcon(img); + } catch (Exception e) { + Log.warning("Unable to fit image to square", e); + return null; + } } // public static void centerWindowOnScreen(Runnable runnable) { diff --git a/core/src/main/java/org/jivesoftware/spark/util/ImageCombiner.java b/core/src/main/java/org/jivesoftware/spark/util/ImageCombiner.java new file mode 100644 index 000000000..ad0b85e83 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/util/ImageCombiner.java @@ -0,0 +1,115 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.util; + +import org.jivesoftware.spark.util.log.Log; + +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.awt.image.ImageObserver; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JComponent; + +/** + * ImageCombiner + * + * @author wolf.posdorfer + */ +public class ImageCombiner { + + /** + * Combines two images into one + * + * @param image1 + * left image + * @param image2 + * right image + * @return combined Image + */ + public static Image combine(Image image1, Image image2) + { + return combine(new ImageIcon(image1), new ImageIcon(image2)); + } + + /** + * Combines two images into one + * + * @param image1 + * left image + * @param image2 + * right image + * @return combined Image + */ + public static Image combine(ImageIcon image1, ImageIcon image2) { + try { + ImageObserver comp = new JComponent() + { + private static final long serialVersionUID = 1L; + }; + + int w = image1.getIconWidth() + image2.getIconWidth(); + int h = Math.max(image1.getIconHeight(), image2.getIconHeight()); + + BufferedImage image = new BufferedImage(w, h, + BufferedImage.TYPE_INT_ARGB); + + Graphics2D g2 = image.createGraphics(); + + g2.drawImage(image1.getImage(), 0, 0, comp); + g2.drawImage(image2.getImage(), image1.getIconWidth(), 0, comp); + g2.dispose(); + + return image; + } catch (Exception e) { + Log.warning("Unable to combine two images", e); + return null; + } + } + + public static Image returnTransparentImage(int w, int h) { + return new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + } + + /** + * Creates an Image from the specified Icon + * + * @param icon + * that should be converted to an image + * @return the new image + */ + public static Image iconToImage(Icon icon) { + if (icon instanceof ImageIcon) { + return ((ImageIcon) icon).getImage(); + } else { + int w = icon.getIconWidth(); + int h = icon.getIconHeight(); + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice gd = ge.getDefaultScreenDevice(); + GraphicsConfiguration gc = gd.getDefaultConfiguration(); + BufferedImage image = gc.createCompatibleImage(w, h); + Graphics2D g = image.createGraphics(); + icon.paintIcon(null, g, 0, 0); + g.dispose(); + return image; + } + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/util/ModelUtil.java b/core/src/main/java/org/jivesoftware/spark/util/ModelUtil.java new file mode 100644 index 000000000..d11c50079 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/util/ModelUtil.java @@ -0,0 +1,132 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.util; + + +import org.jivesoftware.resource.Res; + +import java.util.Iterator; +import java.util.ListIterator; + +import static org.apache.commons.lang3.StringUtils.isNotBlank; + +/** + * Utility methods frequently used by data classes and design-time + * classes. + */ +public final class ModelUtil { + + private ModelUtil() { + // Prevent instantiation. + } + + + /** + * Returns true if the specified {@link String} is not + * null and has a length greater than zero. This is + * a very frequently occurring check. + * + * @param s String to check + * @return True if string is null or empty + */ + public static boolean hasLength(CharSequence s) { + return isNotBlank(s); + } + + + /** + * Returns a formatted String from time. + * + * @param diff the amount of elapsed time. + * @return the formatted String. + */ + public static String getTimeFromLong(long diff) { + final String DAYS = Res.getString("time.days"); + final String HOURS = Res.getString("time.hours"); + final String MINUTES = Res.getString("time.minutes"); + final String LESS_THAN_ONE_MINUTE = Res.getString("time.less.than.one.minute"); + + final long MS_IN_A_DAY = 1000 * 60 * 60 * 24; + final long MS_IN_AN_HOUR = 1000 * 60 * 60; + final long MS_IN_A_MINUTE = 1000 * 60; + long numDays = diff / MS_IN_A_DAY; + diff = diff % MS_IN_A_DAY; + long numHours = diff / MS_IN_AN_HOUR; + diff = diff % MS_IN_AN_HOUR; + long numMinutes = diff / MS_IN_A_MINUTE; + if (numDays == 0 && numHours == 0 && numMinutes == 0) { + return LESS_THAN_ONE_MINUTE; + } + + StringBuilder buf = new StringBuilder(40); + if(numDays > 0){ + buf.append(numDays).append(' ').append(DAYS).append(", "); + } + if (numHours > 0) { + buf.append(numHours).append(' ').append(HOURS).append(", "); + } + buf.append(numMinutes).append(' ').append(MINUTES); + return buf.toString(); + } + + + /** + * Creates an Iterator that is the reverse of a ListIterator. + * + * @param i Iterator of a list. + * @return Reversed iterator. + */ + public static Iterator reverseListIterator(ListIterator i) { + return new ReverseListIterator<>( i ); + } +} + +/** + * An Iterator that is the reverse of a ListIterator. + */ +class ReverseListIterator implements Iterator { + private final ListIterator _i; + + public ReverseListIterator(ListIterator i) { + _i = i; + while (_i.hasNext()) _i.next(); + } + + @Override + public boolean hasNext() { + return _i.hasPrevious(); + } + + @Override + public T next() { + return _i.previous(); + } + + @Override + public void remove() { + _i.remove(); + } +} + + + + + + + + + + diff --git a/src/java/org/jivesoftware/spark/util/ResourceUtils.java b/core/src/main/java/org/jivesoftware/spark/util/ResourceUtils.java similarity index 97% rename from src/java/org/jivesoftware/spark/util/ResourceUtils.java rename to core/src/main/java/org/jivesoftware/spark/util/ResourceUtils.java index 20878ee08..5f7d894bd 100644 --- a/src/java/org/jivesoftware/spark/util/ResourceUtils.java +++ b/core/src/main/java/org/jivesoftware/spark/util/ResourceUtils.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -122,7 +118,7 @@ public static String stripMnemonic(String label) { public static int getMnemonicKeyCode(String mnemonic) { int mindex = mnemonic.indexOf("&"); if (mindex > -1) { - return (int)mnemonic.toUpperCase().charAt(mindex + 1); + return mnemonic.toUpperCase().charAt(mindex + 1); } return 0; } diff --git a/src/java/org/jivesoftware/spark/util/StringUtils.java b/core/src/main/java/org/jivesoftware/spark/util/StringUtils.java similarity index 85% rename from src/java/org/jivesoftware/spark/util/StringUtils.java rename to core/src/main/java/org/jivesoftware/spark/util/StringUtils.java index 0262a6769..57334ee5f 100644 --- a/src/java/org/jivesoftware/spark/util/StringUtils.java +++ b/core/src/main/java/org/jivesoftware/spark/util/StringUtils.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,6 +23,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.BreakIterator; @@ -53,11 +50,11 @@ public class StringUtils { private static final char[] GT_ENCODE = ">".toCharArray(); // patterns for the email address checks - private static Pattern basicAddressPattern; - private static Pattern validUserPattern; - private static Pattern domainPattern; - private static Pattern ipDomainPattern; - private static Pattern tldPattern; + private static final Pattern basicAddressPattern; + private static final Pattern validUserPattern; + private static final Pattern domainPattern; + private static final Pattern ipDomainPattern; + private static final Pattern tldPattern; // prepare the patterns static { @@ -285,52 +282,50 @@ public static String stripTags(String in) { /** * This method takes a string and strips out all tags while still leaving * the tag body intact. - * - * @param in - * the text to be converted. - * @param stripBRTag - * Remove BR tags. + * + * @param in the text to be converted. + * @param stripBRTag Remove BR tags. * @return the input string with all tags removed. */ public static String stripTags(String in, boolean stripBRTag) { - if (in == null) { - return null; - } - - char ch; - int i = 0; - int last = 0; - char[] input = in.toCharArray(); - int len = input.length; - StringBuilder out = new StringBuilder((int) (len * 1.3)); - for (; i < len; i++) { - ch = input[i]; - if (ch > '>') { - // Nothing to do - } else if (ch == '<') { - if (!stripBRTag && i + 3 < len && input[i + 1] == 'b' - && input[i + 2] == 'r' && input[i + 3] == '>') { - i += 3; - continue; - } - if (i > last) { - if (last > 0) { - out.append(" "); - } - out.append(input, last, i - last); - } - last = i + 1; - } else if (ch == '>') { - last = i + 1; - } - } - if (last == 0) { - return in; - } - if (i > last) { - out.append(input, last, i - last); - } - return out.toString(); + if (in == null) { + return null; + } + + char ch; + int i = 0; + int last = 0; + char[] input = in.toCharArray(); + int len = input.length; + StringBuilder out = new StringBuilder((int) (len * 1.3)); + for (; i < len; i++) { + ch = input[i]; + if (ch <= '>') { + if (ch == '<') { + if (!stripBRTag && i + 3 < len && input[i + 1] == 'b' + && input[i + 2] == 'r' && input[i + 3] == '>') { + i += 3; + continue; + } + if (i > last) { + if (last > 0) { + out.append(" "); + } + out.append(input, last, i - last); + } + last = i + 1; + } else if (ch == '>') { + last = i + 1; + } + } + } + if (last == 0) { + return in; + } + if (i > last) { + out.append(input, last, i - last); + } + return out.toString(); } /** @@ -344,46 +339,46 @@ public static String stripTags(String in, boolean stripBRTag) { * with their HTML escape sequences. */ public static String escapeHTMLTags(String in) { - if (in == null) { - return null; - } - char ch; - int i = 0; - int last = 0; - char[] input = in.toCharArray(); - int len = input.length; - StringBuilder out = new StringBuilder((int) (len * 1.3)); - for (; i < len; i++) { - ch = input[i]; - if (ch > '>') { - // Nothing to do - } else if (ch == '<') { - if (i > last) { - out.append(input, last, i - last); - } - last = i + 1; - out.append(LT_ENCODE); - } else if (ch == '>') { - if (i > last) { - out.append(input, last, i - last); - } - last = i + 1; - out.append(GT_ENCODE); - } else if (ch == '"') { - if (i > last) { - out.append(input, last, i - last); - } - last = i + 1; - out.append(QUOTE_ENCODE); - } - } - if (last == 0) { - return in; - } - if (i > last) { - out.append(input, last, i - last); - } - return out.toString(); + if (in == null) { + return null; + } + char ch; + int i = 0; + int last = 0; + char[] input = in.toCharArray(); + int len = input.length; + StringBuilder out = new StringBuilder((int) (len * 1.3)); + for (; i < len; i++) { + ch = input[i]; + if (ch <= '>') { + if (ch == '<') { + if (i > last) { + out.append(input, last, i - last); + } + last = i + 1; + out.append(LT_ENCODE); + } else if (ch == '>') { + if (i > last) { + out.append(input, last, i - last); + } + last = i + 1; + out.append(GT_ENCODE); + } else if (ch == '"') { + if (i > last) { + out.append(input, last, i - last); + } + last = i + 1; + out.append(QUOTE_ENCODE); + } + } + } + if (last == 0) { + return in; + } + if (i > last) { + out.append(input, last, i - last); + } + return out.toString(); } /** @@ -424,12 +419,8 @@ public synchronized static String hash(String data) { } } // Now, compute hash. - try { - digest.update(data.getBytes("utf-8")); - } catch (UnsupportedEncodingException e) { - // Nothing to do - } - return encodeHex(digest.digest()); + digest.update(data.getBytes(StandardCharsets.UTF_8)); + return encodeHex(digest.digest()); } public synchronized static String hash(byte[] data) { @@ -535,131 +526,6 @@ private static byte hexCharToByte(char ch) { return 0x00; } - // ********************************************************************* - // * Base64 - a simple base64 encoder and decoder. - // * - // * Copyright (c) 1999, Bob Withers - bwit@pobox.com - // * - // * This code may be freely used for any purpose, either personal - // * or commercial, provided the authors copyright notice remains - // * intact. - // ********************************************************************* - - /** - * Encodes a String as a base64 String. - * - * @param data - * a String to encode. - * @return a base64 encoded String. - */ - public static String encodeBase64(String data) { - byte[] bytes = null; - try { - bytes = data.getBytes("ISO-8859-1"); - } catch (UnsupportedEncodingException uee) { - // Nothing to do - } - return encodeBase64(bytes); - } - - /** - * Encodes a byte array into a base64 String. - * - * @param data - * a byte array to encode. - * @return a base64 encode String. - */ - public static String encodeBase64(byte[] data) { - int c; - int len = data.length; - StringBuilder ret = new StringBuilder(((len / 3) + 1) * 4); - for (int i = 0; i < len; ++i) { - c = (data[i] >> 2) & 0x3f; - ret.append(cvt.charAt(c)); - c = (data[i] << 4) & 0x3f; - if (++i < len) - c |= (data[i] >> 4) & 0x0f; - - ret.append(cvt.charAt(c)); - if (i < len) { - c = (data[i] << 2) & 0x3f; - if (++i < len) - c |= (data[i] >> 6) & 0x03; - - ret.append(cvt.charAt(c)); - } else { - ++i; - ret.append((char) fillchar); - } - - if (i < len) { - c = data[i] & 0x3f; - ret.append(cvt.charAt(c)); - } else { - ret.append((char) fillchar); - } - } - return ret.toString(); - } - - /** - * Decodes a base64 String. - * - * @param data - * a base64 encoded String to decode. - * @return the decoded String. - */ - - public static String decodeBase64(String data) { - byte[] bytes = null; - try { - bytes = data.getBytes("ISO-8859-1"); - } catch (UnsupportedEncodingException uee) { - // Nothing to do - } - return decodeBase64(bytes); - } - - /** - * Decodes a base64 aray of bytes. - * - * @param data - * a base64 encode byte array to decode. - * @return the decoded String. - */ - public static String decodeBase64(byte[] data) { - int c, c1; - int len = data.length; - StringBuilder ret = new StringBuilder((len * 3) / 4); - for (int i = 0; i < len; ++i) { - c = cvt.indexOf(data[i]); - ++i; - c1 = cvt.indexOf(data[i]); - c = ((c << 2) | ((c1 >> 4) & 0x3)); - ret.append((char) c); - if (++i < len) { - c = data[i]; - if (fillchar == c) - break; - - c = cvt.indexOf(c); - c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf); - ret.append((char) c1); - } - - if (++i < len) { - c1 = data[i]; - if (fillchar == c1) - break; - - c1 = cvt.indexOf(c1); - c = ((c << 6) & 0xc0) | c1; - ret.append((char) c); - } - } - return ret.toString(); - } - /** * The method below is under the following license *

      @@ -884,7 +750,7 @@ public static String[] toLowerCaseWordArray(String text) { wordList.add(tmp); } } - return wordList.toArray(new String[wordList.size()]); + return wordList.toArray(new String[0]); } /** @@ -892,7 +758,7 @@ public static String[] toLowerCaseWordArray(String text) { * Random class is not considered to be cryptographically secure, so only * use these random Strings for low to medium security applications. */ - private static Random randGen = new Random(); + private static final Random randGen = new Random(); /** * Array of numbers and letters of mixed case. Numbers appear in the list @@ -900,7 +766,7 @@ public static String[] toLowerCaseWordArray(String text) { * We can use the array to get a random number or letter by picking a random * array index. */ - private static char[] numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz" + private static final char[] numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz" + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray(); /** @@ -1141,8 +1007,7 @@ public static String chopAtWordsAround(String input, String[] wordList, return input.substring(beginIdx, endIdx); } } - return input.substring(0, - (input.length() >= 200) ? 200 : input.length()); + return input.substring(0, Math.min(input.length(), 200)); } /** @@ -1281,58 +1146,57 @@ public static String highlightWords(String string, String[] words, * @return the string with appropriate characters escaped. */ public static String escapeForXML(String string) { - if (string == null) { - return null; - } - char ch; - int i = 0; - int last = 0; - char[] input = string.toCharArray(); - int len = input.length; - StringBuilder out = new StringBuilder((int) (len * 1.3)); - for (; i < len; i++) { - ch = input[i]; - - if (ch > '>') { - // Nothing to do - } else if (ch == '<') { - if (i > last) { - out.append(input, last, i - last); - } - last = i + 1; - out.append(LT_ENCODE); - } else if (ch == '&') { - if (i > last) { - out.append(input, last, i - last); - } - last = i + 1; - out.append(AMP_ENCODE); - } else if (ch == '"') { - if (i > last) { - out.append(input, last, i - last); - } - last = i + 1; - out.append(QUOTE_ENCODE); - } else if (ch == 10 || ch == 13 || ch == 9) { - // Nothing to do - } else if (ch < 32) { - // Disallow all ASCII control characters, except space, - // enter characters and tabs: - if (i > last) { - out.append(input, last, i - last); - } - last = i + 1; - } - } - if (last == 0) { - // Return after escaping end sequence "]]>" - return string.replace("]]>", "]]&gt;"); - } - if (i > last) { - out.append(input, last, i - last); - } - // Return after escaping end sequence "]]>" - return out.toString().replace("]]>", "]]&gt;"); + if (string == null) { + return null; + } + char ch; + int i = 0; + int last = 0; + char[] input = string.toCharArray(); + int len = input.length; + StringBuilder out = new StringBuilder((int) (len * 1.3)); + for (; i < len; i++) { + ch = input[i]; + if (ch <= '>') { + if (ch == '<') { + if (i > last) { + out.append(input, last, i - last); + } + last = i + 1; + out.append(LT_ENCODE); + } else if (ch == '&') { + if (i > last) { + out.append(input, last, i - last); + } + last = i + 1; + out.append(AMP_ENCODE); + } else if (ch == '"') { + if (i > last) { + out.append(input, last, i - last); + } + last = i + 1; + out.append(QUOTE_ENCODE); + } else if (ch != 10 && ch != 13 && ch != 9) { + // Disallow all ASCII control characters, except space, + // enter characters and tabs: + if (ch < 32) { + if (i > last) { + out.append(input, last, i - last); + } + last = i + 1; + } + } + } + } + if (last == 0) { + // Return after escaping end sequence "]]>" + return string.replace("]]>", "]]&gt;"); + } + if (i > last) { + out.append(input, last, i - last); + } + // Return after escaping end sequence "]]>" + return out.toString().replace("]]>", "]]&gt;"); } /** @@ -1411,61 +1275,58 @@ public static String dateToMillis(Date date) { * @return true if the address is valid, false otherwise */ public static boolean isValidEmailAddress(String addr) { - if (addr == null) { - return false; - } - - addr = addr.trim(); - - if (addr.length() == 0) { - return false; - } - // basic address check - Matcher matcher = basicAddressPattern.matcher(addr); - if (!matcher.matches()) { - return false; - } - String userPart = matcher.group(1); - String domainPart = matcher.group(2); - // user address check - matcher = validUserPattern.matcher(userPart); - if (!matcher.matches()) { - return false; - } - // ip domain check - matcher = ipDomainPattern.matcher(domainPart); - if (matcher.matches()) { - // if the pattern matched, check to make sure that the ip range is - // valid - for (int i = 1; i < 5; i++) { - String num = matcher.group(i); - - if (num == null) { - return false; - } - - if (Integer.parseInt(num) > 254) { - return false; - } - } - return true; - } - // symbolic domain check - matcher = domainPattern.matcher(domainPart); - if (matcher.matches()) { - String tld = matcher.group(matcher.groupCount()); - // Permit top-level-domains of 3 (includes dot separator) because - // these could be - // country codes which we are not going to check for. - matcher = tldPattern.matcher(tld); - if (tld.length() != 3 && !matcher.matches()) { - return false; - } - } else { - return false; - } - // all tests passed - return true; + if (addr == null) { + return false; + } + + addr = addr.trim(); + + if (addr.length() == 0) { + return false; + } + // basic address check + Matcher matcher = basicAddressPattern.matcher(addr); + if (!matcher.matches()) { + return false; + } + String userPart = matcher.group(1); + String domainPart = matcher.group(2); + // user address check + matcher = validUserPattern.matcher(userPart); + if (!matcher.matches()) { + return false; + } + // ip domain check + matcher = ipDomainPattern.matcher(domainPart); + if (matcher.matches()) { + // if the pattern matched, check to make sure that the ip range is + // valid + for (int i = 1; i < 5; i++) { + String num = matcher.group(i); + + if (num == null) { + return false; + } + + if (Integer.parseInt(num) > 254) { + return false; + } + } + return true; + } + // symbolic domain check + matcher = domainPattern.matcher(domainPart); + if (matcher.matches()) { + String tld = matcher.group(matcher.groupCount()); + // Permit top-level-domains of 3 (includes dot separator) because + // these could be + // country codes which we are not going to check for. + matcher = tldPattern.matcher(tld); + return tld.length() == 3 || matcher.matches(); + } else { + return false; + } + // all tests passed } // Testing method @@ -1919,12 +1780,13 @@ public static String getKeyText(int keyCode) { } /** - * Converts the first Character of a String to its Uppercase Instance
      + * Converts the first Character of a CharSequence to its Uppercase Instance
      * test -> Test - * @param word + * @param cs * @return String, with first char uppercased */ - public static String makeFirstWordCaptial(String word) { + public static String makeFirstWordCaptial(CharSequence cs) { + String word = cs.toString(); if (word.length() < 2) { return word; } @@ -1990,12 +1852,12 @@ public static String modifyWildcards(String resource) { * @throws Exception */ public static String getMD5Checksum(String filepath) throws NoSuchAlgorithmException, IOException { - byte[] b = createChecksum(filepath); - String result = ""; - for (int i = 0; i < b.length; i++) { - result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1); - } - return result; + byte[] b = createChecksum(filepath); + StringBuilder result = new StringBuilder(); + for (byte value : b) { + result.append(Integer.toString((value & 0xff) + 0x100, 16).substring(1)); + } + return result.toString(); } /** @@ -2037,4 +1899,58 @@ public static int countNumberOfOccurences(String string, char c) { } return result; } -} \ No newline at end of file + + /** + * Returns the value of the major/feature element of the version number. + * + * @param version A java version String + * @return The major + */ + public static int getJavaMajorVersion( String version ) { + if (version.startsWith("1.")) { + int dot = version.indexOf('.', 2); + if ( dot == -1 ) { + version = version.substring( 2 ); + } else { + version = version.substring( 2, dot ); + } + } else { + int dot = version.indexOf('.'); + if (dot != -1) { + version = version.substring(0, dot); + } + int hyphen = version.indexOf('-'); + if (hyphen != -1) { + version = version.substring(0, hyphen); + } + } + return Integer.parseInt(version); + } + + /** + * Returns the string with replaced special letter + * Allow to search contacts without special letters interfering + * + * @param text A input string + * @return String with replaced special letter + */ + public static String replaceSpecialLetters(String text){ + return text + .replaceAll("á|â|à|Ã¥|ã|ä", "a") + .replaceAll("Ã|Â|À|Ã…|Ã|Ä", "A") + .replaceAll("é|ê|è|ë", "e") + .replaceAll("É|Ê|È|Ë", "E") + .replaceAll("í|î|ì|Ñ–", "i") + .replaceAll("Ã|ÃŽ|ÃŒ|І", "I") + .replaceAll("ó|ô|ò|õ|ö", "o") + .replaceAll("Ó|Ô|Ã’|Õ|Ö", "O") + .replaceAll("ú|û|ù|ü", "u") + .replaceAll("Ú|Û|Ù|Ü", "U") + .replaceAll("ñ", "n") + .replaceAll("Ñ", "N") + .replaceAll("ý", "y") + .replaceAll("Ã", "Y") + .replaceAll("Ñ‘", "е") + .replaceAll("Ð", "Е"); + } +} diff --git a/src/java/org/jivesoftware/spark/util/SwingTimerTask.java b/core/src/main/java/org/jivesoftware/spark/util/SwingTimerTask.java similarity index 93% rename from src/java/org/jivesoftware/spark/util/SwingTimerTask.java rename to core/src/main/java/org/jivesoftware/spark/util/SwingTimerTask.java index d91a8147b..cf17ec9a4 100644 --- a/src/java/org/jivesoftware/spark/util/SwingTimerTask.java +++ b/core/src/main/java/org/jivesoftware/spark/util/SwingTimerTask.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,7 +23,8 @@ public abstract class SwingTimerTask extends java.util.TimerTask { public abstract void doRun(); - public void run() { + @Override + public void run() { if (!EventQueue.isDispatchThread()) { EventQueue.invokeLater(this); } diff --git a/src/java/org/jivesoftware/spark/util/SwingWorker.java b/core/src/main/java/org/jivesoftware/spark/util/SwingWorker.java similarity index 86% rename from src/java/org/jivesoftware/spark/util/SwingWorker.java rename to core/src/main/java/org/jivesoftware/spark/util/SwingWorker.java index c3e8822a7..26fd2f316 100644 --- a/src/java/org/jivesoftware/spark/util/SwingWorker.java +++ b/core/src/main/java/org/jivesoftware/spark/util/SwingWorker.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,16 +17,18 @@ +import org.jivesoftware.spark.util.log.Log; + import javax.swing.SwingUtilities; /** - * Improvement version of the javax SwingWorker class to avoid deadlocks. This gives user - * multi-threaded abilities within their swing apps. + * Improvement version of the {@link javax.swing.SwingWorker} class to avoid deadlocks. + * This gives the user multithreaded abilities within their swing apps. * * @author Derek DeMoro */ public abstract class SwingWorker { - private Object value; // see getValue(), setValue() + private volatile Object value; // see getValue(), setValue() /** * Class to maintain reference to current worker thread @@ -60,7 +58,7 @@ synchronized void clear() { * * @return Object produced by worker thread. */ - protected synchronized Object getValue() { + protected Object getValue() { return value; } @@ -69,7 +67,7 @@ protected synchronized Object getValue() { * * @param x Sets value for worker thread. */ - private synchronized void setValue(Object x) { + private void setValue(Object x) { value = x; } @@ -129,21 +127,17 @@ public Object get() { * and then exit. */ public SwingWorker() { - new Runnable() { - public void run() { - finished(); - } - }; - Runnable doConstruct = () -> { try { - setValue(construct()); + setValue(construct()); + } + catch (Exception e) { + Log.error("SwingWorker exception while async constructing value", e); } finally { threadVar.clear(); } - SwingUtilities.invokeLater( () -> finished() ); - + SwingUtilities.invokeLater(this::finished); }; Thread t = new Thread(doConstruct); diff --git a/src/java/org/jivesoftware/spark/util/TaskEngine.java b/core/src/main/java/org/jivesoftware/spark/util/TaskEngine.java similarity index 98% rename from src/java/org/jivesoftware/spark/util/TaskEngine.java rename to core/src/main/java/org/jivesoftware/spark/util/TaskEngine.java index 12ae03edc..4142dbb86 100644 --- a/src/java/org/jivesoftware/spark/util/TaskEngine.java +++ b/core/src/main/java/org/jivesoftware/spark/util/TaskEngine.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -44,7 +40,7 @@ */ public class TaskEngine { - private static TaskEngine instance = new TaskEngine(); + private static final TaskEngine instance = new TaskEngine(); /** * Returns a task engine instance (singleton). @@ -57,7 +53,7 @@ public static TaskEngine getInstance() { private Timer timer; private ExecutorService executor; - private Map wrappedTasks = new ConcurrentHashMap<>(); + private final Map wrappedTasks = new ConcurrentHashMap<>(); /** * Constructs a new task engine. @@ -68,6 +64,7 @@ private TaskEngine() { final AtomicInteger threadNumber = new AtomicInteger(1); + @Override public Thread newThread(Runnable runnable) { // Use our own naming scheme for the threads. Thread thread = new Thread(Thread.currentThread().getThreadGroup(), runnable, @@ -315,14 +312,15 @@ public void shutdown() { */ private class TimerTaskWrapper extends TimerTask { - private TimerTask task; + private final TimerTask task; public TimerTaskWrapper(TimerTask task) { this.task = task; } - public void run() { + @Override + public void run() { executor.submit(task); } } -} \ No newline at end of file +} diff --git a/src/java/org/jivesoftware/spark/util/UIComponentRegistry.java b/core/src/main/java/org/jivesoftware/spark/util/UIComponentRegistry.java similarity index 91% rename from src/java/org/jivesoftware/spark/util/UIComponentRegistry.java rename to core/src/main/java/org/jivesoftware/spark/util/UIComponentRegistry.java index d496893b3..d2511595b 100644 --- a/src/java/org/jivesoftware/spark/util/UIComponentRegistry.java +++ b/core/src/main/java/org/jivesoftware/spark/util/UIComponentRegistry.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2011 eZuce Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,8 +17,12 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.time.Duration; +import java.time.Instant; import java.util.Arrays; -import org.jivesoftware.LoginDialog; + +import org.apache.commons.lang3.reflect.ConstructorUtils; +import org.jivesoftware.gui.LoginUIPanel; import org.jivesoftware.smackx.muc.MultiUserChat; import org.jivesoftware.spark.ButtonFactory; import org.jivesoftware.spark.component.tabbedPane.SparkTabbedPane; @@ -41,6 +41,10 @@ import org.jivesoftware.spark.ui.status.StatusBar; import org.jivesoftware.spark.ui.themes.ThemePanel; import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.EntityJid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Resourcepart; /** * This is a registry for components that may be replaced by plugins. Also @@ -57,7 +61,7 @@ public final class UIComponentRegistry { private static Class statusBarClass = StatusBar.class; private static Class commandPanelClass = CommandPanel.class; private static Class workspaceTabPaneClass = SparkTabbedPane.class; - private static Class loginDialogClass = LoginDialog.class; + private static Class loginDialogClass = LoginUIPanel.class; private static Class themePanelClass = ThemePanel.class; private static Class conferenceServicesClass = ConferenceServices.class; private static Class transcriptWindowClass = TranscriptWindow.class; @@ -78,7 +82,7 @@ private UIComponentRegistry() { * * @param clazz */ - public static void registerLoginDialog(Class clazz) { + public static void registerLoginDialog(Class clazz) { if (loginDialogClass != clazz) { Log.debug("Registering new contract item class: " + clazz.getName()); @@ -305,10 +309,10 @@ public static void registerButtonFactory(Class clazz) { * @return A new instance of the class currently registered as contact item. */ public static ContactItem createContactItem(String alias, String nickname, - String fullyQualifiedJID) { + BareJid fullyQualifiedJID) { // null breaks instantiation by reflection final String nick = nickname != null ? nickname : ""; - final String jid = fullyQualifiedJID != null ? fullyQualifiedJID : ""; + final BareJid jid = fullyQualifiedJID != null ? fullyQualifiedJID : JidCreate.bareFromOrThrowUnchecked("dummy@dummy.example"); final String aliass = alias != null ? alias : ""; return instantiate(contactItemClass, aliass, nick, jid); @@ -352,8 +356,6 @@ public static ContactGroup createContactGroup(String name) { /** * Creates a new contact group object * - * @param name - * * @return A new instance of the class currently registered as status bar. */ public static StatusBar createStatusBar() { @@ -363,8 +365,6 @@ public static StatusBar createStatusBar() { /** * Creates a new command panel object * - * @param name - * * @return A new instance of the class currently registered as status bar. */ public static CommandPanel createCommandPanel() { @@ -374,22 +374,18 @@ public static CommandPanel createCommandPanel() { /** * Creates a new workspace tab panel object * - * @param name - * - * @return + * @return A new instance of the class currently registered as workspace tab pane */ public static SparkTabbedPane createWorkspaceTabPanel(int tabPosition) { - return instantiate(workspaceTabPaneClass, new Integer(tabPosition)); + return instantiate(workspaceTabPaneClass, tabPosition); } /** * Creates a new login dialog panel object * - * @param name - * - * @return + * @return A new instance of the class currently registered as login dialog */ - public static LoginDialog createLoginDialog() { + public static LoginUIPanel createLoginDialog() { return instantiate(loginDialogClass); } @@ -436,7 +432,7 @@ public static TranscriptWindow createTranscriptWindow() { * * @return A new instance of the class currently registered as chat room. */ - public static ChatRoom createChatRoom(String participantJID, String participantNickname, String title) { + public static ChatRoom createChatRoom(EntityJid participantJID, Resourcepart participantNickname, CharSequence title) { return instantiate(chatRoomClass, participantJID, participantNickname, title); } @@ -490,25 +486,21 @@ public static ButtonFactory getButtonFactory() { private static T instantiate(Class currentClass, Object... args) { T instance = null; - Log.debug("Args: " + Arrays.toString(args)); + Instant start = Instant.now(); + Class[] classes = new Class[args.length]; try { - if (args != null) { - Class[] classes = new Class[args.length]; - for (int i = 0; i < args.length; i++) { - classes[i] = args[i].getClass(); - } - final Constructor ctor = currentClass.getDeclaredConstructor(classes); - instance = ctor.newInstance(args); - } else { - final Constructor ctor = currentClass.getDeclaredConstructor(); - instance = ctor.newInstance(); + for (int i = 0; i < args.length; i++) { + classes[i] = args[i].getClass(); } + final Constructor ctor = ConstructorUtils.getMatchingAccessibleConstructor(currentClass, classes); + instance = ctor.newInstance(args); + Log.debug("Instantiated " + currentClass.getName() + " with args: " + Arrays.toString(args) + " in " + Duration.between(start, Instant.now())); } catch (final Exception e) { // not pretty but we're catching several exceptions we can do little // about - Log.error("Error calling constructor for " + currentClass.getName(), e); + Log.error("Error calling constructor for " + currentClass.getName() + " with arguments " + Arrays.toString(classes), e); } return instance; } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jivesoftware/spark/util/URLFileSystem.java b/core/src/main/java/org/jivesoftware/spark/util/URLFileSystem.java new file mode 100644 index 000000000..23b01faae --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/util/URLFileSystem.java @@ -0,0 +1,505 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.channels.FileChannel; + +/** + * URLFileSystem class handles some of the most common + * functionallity when working with URLs. + * + * @version 1.0, 03/12/14 + */ + +public class URLFileSystem { + public static String getContents(URL url) { + try { + return getContents(url.openStream()); + } + catch (IOException e) { + return null; + } + } + + public static String getContents(InputStream is) { + byte[] buffer = new byte[2048]; + int length; + StringBuilder sb = new StringBuilder(); + try { + while ((length = is.read(buffer)) != -1) { + sb.append(new String(buffer, 0, length)); + } + return sb.toString(); + } + catch (IOException e) { + return null; + } + } + + public static String getContents(File file) { + try { + return getContents(file.toURI().toURL()); + } + catch (MalformedURLException e) { + return ""; + } + } + + /** + * Copies the contents at src to dst. + * + * @param src URL to copy to local file. + * @param dst File to pull information from to copy to. + * @throws IOException if there is an error during copy. + */ + public static void copy(URL src, File dst) throws IOException { + try (InputStream in = src.openStream(); + OutputStream out = new FileOutputStream(dst)) { + dst.mkdirs(); + copy(in, out); + } + } + + /** + * Common code for copy routines. By convention, the streams are + * closed in the same method in which they were opened. Thus, + * this method does not close the streams when the copying is done. + * + * @param in Source stream + * @param out Destination stream + * @throws IOException if there is an error during copy. + */ + public static void copy(InputStream in, OutputStream out) throws IOException { + final byte[] buffer = new byte[4096]; + while (true) { + final int bytesRead = in.read(buffer); + if (bytesRead < 0) { + break; + } + out.write(buffer, 0, bytesRead); + } + + out.flush(); + } + + //-------------------------------------------------------------------------- + // URLFileSystemHelper public API... + //-------------------------------------------------------------------------- + + /** + * Returns a canonical form of the {@link URL}, if one is available. + *

      + *

      + * The default implementation just returns the specified {@link URL} + * as-is. + * + * @param url URL to convert. + * @return Convert url. + */ + public URL canonicalize(URL url) { + return url; + } + + /** + * Tests whether the application can read the resource at the + * specified {@link URL}. + * + * @return true if and only if the specified + * {@link URL} points to a resource that exists and can be + * read by the application; false otherwise. + * + * @param url URL to check if we can read from it. + */ + public boolean canRead(URL url) { + try { + final URLConnection urlConnection = url.openConnection(); + return urlConnection.getDoInput(); + } + catch (Exception e) { + return false; + } + } + + + /** + * Tests whether the application can modify the resource at the + * specified {@link URL}. + * + * @return true if and only if the specified + * {@link URL} points to a file that exists and the + * application is allowed to write to the file; false + * otherwise. + * + * @param url URL to check if we can write to. + */ + public boolean canWrite(URL url) { + try { + final URLConnection urlConnection = url.openConnection(); + return urlConnection.getDoOutput(); + } + catch (Exception e) { + return false; + } + } + + /** + * Tests whether the application can create the resource at the specified + * {@link URL}. + * + * @return true if the resource at the specified {@link URL} + * exists or can be created; false otherwise. + * + * @param url URL to check if we can create things at. + */ + public boolean canCreate(URL url) { + return true; + } + + /** + * Tests whether the specified {@link URL} is valid. If the resource + * pointed by the {@link URL} exists the method returns true. + * If the resource does not exist, the method tests that all components + * of the path can be created. + * + * @return true if the {@link URL} is valid. + * + * @param url URL to check for validity. + */ + public boolean isValid(URL url) { + if (exists(url)) { + return true; + } + + return canCreate(url); + } + + /** + * Returns true if the specified {@link URL} points to a + * resource that currently exists; returns false + * otherwise.

      + *

      + * The default implementation simply returns false + * without doing anything. + * + * @param url URL to test for existance + * @return True if url exists + */ + public static boolean exists(URL url) { + return url2File(url).exists(); + } + + public static boolean mkdirs(URL url) { + final File file = url2File(url); + if (!file.exists()) { + return file.mkdirs(); + } + return true; + } + + + /** + * Returns the name of the file contained by the {@link URL}, not + * including any protocol, hostname authentication, directory path, + * anchor, or query. This simply returns the simple filename. For + * example, if you pass in an {@link URL} whose string representation + * is: + *

      + *

      + * protocol://host:1010/dir1/dir2/file.ext#anchor?query + *
      + *

      + * the returned value is "file.ext" (without the + * quotes).

      + *

      + * The returned file name should only be used for display purposes + * and not for opening streams or otherwise trying to locate the + * resource indicated by the {@link URL}. + * + * @param url URL of resource to get filename of + * @return File name determined + */ + public static String getFileName(URL url) { + if (url == null) { + return ""; + } + + final String path = url.getPath(); + if (path.equals("/")) { + return "/"; + } + final int lastSep = path.lastIndexOf('/'); + if (lastSep == path.length() - 1) { + final int lastSep2 = path.lastIndexOf('/', lastSep - 1); + return path.substring(lastSep2 + 1, lastSep); + } + else { + return path.substring(lastSep + 1); + } + } + + + /** + * Returns the number of bytes contained in the resource that the + * specified {@link URL} points to. If the length cannot be + * determined, -1 is returned.

      + *

      + * The default implementation attempts to get the content length from + * the {@link URLConnection} associated with the {@link URL}. If that + * fails for some reason (e.g. the resource does not exist, there was + * some other an I/O exception, etc.), -1 is returned. + * + * @see URLConnection + * @param url URL to get length of resource of + * @return Content length + */ + public long getLength(URL url) { + try { + final URLConnection urlConnection = url.openConnection(); + return urlConnection.getContentLength(); + } + catch (Exception e) { + return -1; + } + } + + + /** + * Returns the name of the file contained by the {@link URL}, not + * including any protocol, hostname authentication, directory path, + * anchor, or query. This simply returns the simple filename. For + * example, if you pass in an {@link URL} whose string representation + * is: + *

      + *

      + * protocol://host:1010/dir1/dir2/file.ext1.ext2#anchor?query + *
      + *

      + * the returned value is "file" (without the quotes).

      + *

      + * The returned file name should only be used for display purposes + * and not for opening streams or otherwise trying to locate the + * resource indicated by the {@link URL}.

      + *

      + * The default implementation first calls {@link #getFileName(URL)} to + * get the file name part. Then all characters starting with the + * first occurrence of '.' are removed. The remaining string is then + * returned. + * + * @param url URL of resource + * @return Name for URL + */ + public static String getName(URL url) { + final String fileName = getFileName(url); + final int firstDot = fileName.lastIndexOf('.'); + return firstDot > 0 ? fileName.substring(0, firstDot) : fileName; + } + + + /** + * Returns the path part of the {@link URL}. + *

      + * The default implementation delegates to {@link URL#getPath()}. + * + * @param url URL of resource + * @return Path of URL + */ + public String getPath(URL url) { + return url.getPath(); + } + + + /** + * Returns the path part of the {@link URL} without the last file + * extension. To clarify, the following examples demonstrate the + * different cases that come up: + *

      + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
      Path part of input {@link URL}
      Output {@link String} + *
      /dir/file.ext/dir/file
      /dir/file.ext1.ext2/dir/file.ext1
      /dir1.ext1/dir2.ext2/file.ext1.ext2/dir1.ext1/dir2.ext2/file.ext1
      /file.ext/file
      /dir.ext/file/dir.ext/file
      /dir/file/dir/file
      /file/file
      /.ext/
      + *

      + * The default implementation gets the path from {@link + * #getPath(URL)} and then trims off all of the characters beginning + * with the last "." in the path, if and only if the last "." comes + * after the last "/" in the path. If the last "." comes before + * the last "/" or if there is no "." at all, then the entire path + * is returned. + * + * @param url URL of resource + * @return Path without extension + */ + public String getPathNoExt(URL url) { + final String path = getPath(url); + final int lastSlash = path.lastIndexOf("/"); + final int lastDot = path.lastIndexOf("."); + if (lastDot <= lastSlash) { + // When the lastDot < lastSlash, it means that one of the + // directories has an extension, but the filename itself has + // no extension. In this case, returning the whole path is + // the correct behavior. + // + // The only time that lastDot and lastSlash can be equal occurs + // when both of them are -1. In that case, returning the whole + // path is the correct behavior. + return path; + } + // At this point, we know that lastDot must be non-negative, so + // we can return the whole path string up to the last dot. + return path.substring(0, lastDot); + } + + + /** + * Returns the platform-dependent String representation of the + * {@link URL}; the returned string should be considered acceptable + * for users to read. In general, the returned string should omit + * as many parts of the {@link URL} as possible. For the "file" + * protocol, therefore, the platform pathname should just be the + * pathname alone (no protocol) using the appropriate file separator + * character for the current platform. For other protocols, it may + * be necessary to reformat the {@link URL} string into a more + * human-readable form. That decision is left to each + * URLFileSystemHelper implementor. + *

      + * The default implementation returns url.toString(). + * If the {@link URL} is null, the empty string is + * returned. + * + * @return The path portion of the specified {@link URL} in + * platform-dependent notation. This value should only be used for + * display purposes and not for opening streams or otherwise trying + * to locate the document. + * + * @param url URL of resource + */ + public String getPlatformPathName(URL url) { + return url != null ? url.toString() : ""; + } + + /** + * This "sanitizes" the specified string path by converting all + * {@link File#separatorChar} characters to forward slash ('/'). + * Also, a leading forward slash is prepended if the path does + * not begin with one. + * + * @param path Path to sanitize + * @return Sanitized path + */ + private static String sanitizePath(String path) { + if (File.separatorChar != '/') { + path = path.replace(File.separatorChar, '/'); + } + if (!path.startsWith("/")) { + path = "/" + path; + } + return path; + } + + public static File url2File(URL url) { + final String path = url.getPath(); + return new File(path); + } + + public static URL getParent(URL url) { + final File file = url2File(url); + final File parentFile = file.getParentFile(); + if (parentFile != null && !file.equals(parentFile)) { + try { + return parentFile.toURI().toURL(); + } + catch (Exception ex) { + return null; + } + } + return null; + } + + /** + * Allows for the copying of entire directories/sub-dirs and their files. + * + * @param src the root directory to copy. + * @param dst the destination directory. + * @throws IOException thrown if there is an issue copying over the files. + */ + public static void copyDir(File src, File dst) throws IOException { + // Create the destination directory + dst.mkdirs(); + + // Loop through the files and directories in the source directory and copy them + File[] files = src.listFiles(); + for (File file : files) { + if (file.isFile()) { + copyFile(file, new File(dst, file.getName())); + } else if (file.isDirectory()) { + copyDir(file, new File(dst, file.getName())); + } + } + } + + private static void copyFile(File src, File dst) throws IOException { + FileChannel in = new FileInputStream(src).getChannel(); + FileChannel out = new FileOutputStream(dst).getChannel(); + + // Fast and efficient way to copy a file + in.transferTo(0, in.size(), out); + + in.close(); + out.close(); + } +} diff --git a/src/java/org/jivesoftware/spark/util/WindowsFileSystemView.java b/core/src/main/java/org/jivesoftware/spark/util/WindowsFileSystemView.java similarity index 87% rename from src/java/org/jivesoftware/spark/util/WindowsFileSystemView.java rename to core/src/main/java/org/jivesoftware/spark/util/WindowsFileSystemView.java index 0fe88119d..9d398490b 100644 --- a/src/java/org/jivesoftware/spark/util/WindowsFileSystemView.java +++ b/core/src/main/java/org/jivesoftware/spark/util/WindowsFileSystemView.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +16,6 @@ package org.jivesoftware.spark.util; import java.io.File; -import java.io.IOException; import javax.swing.filechooser.FileSystemView; @@ -54,7 +49,8 @@ public WindowsFileSystemView() { * @param value0 * @return boolean */ - public boolean isRoot(File value0) { + @Override + public boolean isRoot(File value0) { return false; // } // isRoot() @@ -62,10 +58,10 @@ public boolean isRoot(File value0) { * createNewFolder * * @param value0 - * @throws IOException * @return File */ - public File createNewFolder(File value0) throws IOException { + @Override + public File createNewFolder(File value0) { return null; // } // createNewFolder() @@ -75,7 +71,8 @@ public File createNewFolder(File value0) throws IOException { * @param value0 * @return boolean */ - public boolean isHiddenFile(File value0) { + @Override + public boolean isHiddenFile(File value0) { return false; // } // isHiddenFile() @@ -84,7 +81,8 @@ public boolean isHiddenFile(File value0) { * * @return File[] */ - public File[] getRoots() { + @Override + public File[] getRoots() { return null; // } // getRoots() diff --git a/core/src/main/java/org/jivesoftware/spark/util/XEP0392Utils.java b/core/src/main/java/org/jivesoftware/spark/util/XEP0392Utils.java new file mode 100644 index 000000000..ca2203e52 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/util/XEP0392Utils.java @@ -0,0 +1,26 @@ +package org.jivesoftware.spark.util; + +import org.jivesoftware.smackx.colors.ConsistentColor; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.parts.Resourcepart; + +import java.awt.*; + +public class XEP0392Utils { + + public static Color colorOfMucParticipant(Resourcepart userNickname) { + return toColor(ConsistentColor.RGBFrom(userNickname)); + } + + public static Color colorOfMuc(EntityBareJid mucJid) { + return toColor(ConsistentColor.RGBFrom(mucJid)); + } + + private static Color toColor(float[] rgb) { + // avoid negative values + rgb[0] = Math.max(0, rgb[0]); + rgb[1] = Math.max(0, rgb[1]); + rgb[2] = Math.max(0, rgb[2]); + return new Color(rgb[0], rgb[1], rgb[2]); + } +} diff --git a/core/src/main/java/org/jivesoftware/spark/util/log/Log.java b/core/src/main/java/org/jivesoftware/spark/util/log/Log.java new file mode 100644 index 000000000..98ba78f0b --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/util/log/Log.java @@ -0,0 +1,154 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.util.log; + +import org.jivesoftware.Spark; + +import java.io.File; +import java.io.IOException; +import java.util.logging.FileHandler; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; + +/** + * Creates and writes out messages to a a log file. This should be used for all + * error handling within the Agent application. + */ +public class Log { + private final java.util.logging.Logger ERROR_LOGGER; + private final Logger WARNING_LOGGER; + private static final boolean debugEnabled = System.getProperty("debug.mode") != null; + + private volatile static Log singleton = null; + + private static Log getInstance() { + if (singleton == null) { + synchronized (Log.class) { + if (singleton == null) { + singleton = new Log(); + } + } + } + return singleton; + } + + private Log() { + if (!Spark.getLogDirectory().exists()) { + Spark.getLogDirectory().mkdirs(); + } + ERROR_LOGGER = java.util.logging.Logger.getAnonymousLogger(); + WARNING_LOGGER = java.util.logging.Logger.getAnonymousLogger(); + + File ERROR_LOG_FILE = new File(Spark.getLogDirectory(), "errors.log"); + File WARNING_LOG_FILE = new File(Spark.getLogDirectory(), "warn.log"); + + try { + // Create an appending file handler + boolean append = true; + FileHandler errorHandler = new FileHandler( + ERROR_LOG_FILE.getCanonicalPath(), 1000000, 10, append); + errorHandler.setFormatter(new SimpleFormatter()); + + FileHandler warnHandler = new FileHandler( + WARNING_LOG_FILE.getCanonicalPath(), 1000000, 10, append); + warnHandler.setFormatter(new SimpleFormatter()); + + // Add to the desired logger + ERROR_LOGGER.addHandler(errorHandler); + WARNING_LOGGER.addHandler(warnHandler); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Adds a handler to the error logger + * + * @param h the handler to add + */ + public synchronized static void addErrorHandler(Handler h) { + getInstance().ERROR_LOGGER.addHandler(h); + } + + /** + * Adds a handler to the error logger + * + * @param h the handler to add + */ + public synchronized static void addWarningHandler(Handler h) { + getInstance().WARNING_LOGGER.addHandler(h); + } + + /** + * Logs all error messages to default error logger. + * + * @param message + * a message to append to log file. + * @param ex the exception being thrown. + */ + public static void error(String message, Throwable ex) { + getInstance().ERROR_LOGGER.log(Level.SEVERE, message, ex); + } + + /** + * Logs all error messages to default error logger. + * + * @param ex the exception being thrown. + */ + public static void error(Throwable ex) { + getInstance().ERROR_LOGGER.log(Level.SEVERE, "", ex); + } + + /** + * Log a warning message to the default logger. + * + * @param message the message to log. + * @param ex the exception. + */ + public static void warning(String message, Throwable ex) { + getInstance().WARNING_LOGGER.log(Level.WARNING, message, ex); + } + + public static void warning(String message) { + getInstance().WARNING_LOGGER.log(Level.WARNING, message); + } + + /** + * Logs all error messages to default error logger. + * + * @param message a message to append to log file. + */ + public static void error(String message) { + getInstance().ERROR_LOGGER.log(Level.SEVERE, message); + } + + /** + * Logs all messages to standard errout for debugging purposes. To use, pass + * in the VM Parameters debug.mode=true. + *

      + * ex. (-Ddebug.mode=true) + * + * @param message the message to print out. + */ + public static void debug(String message) { + if (debugEnabled) { + System.err.println(message); + } + } + +} diff --git a/src/java/org/jivesoftware/spark/util/log/package.html b/core/src/main/java/org/jivesoftware/spark/util/log/package.html similarity index 100% rename from src/java/org/jivesoftware/spark/util/log/package.html rename to core/src/main/java/org/jivesoftware/spark/util/log/package.html diff --git a/src/java/org/jivesoftware/spark/util/package.html b/core/src/main/java/org/jivesoftware/spark/util/package.html similarity index 100% rename from src/java/org/jivesoftware/spark/util/package.html rename to core/src/main/java/org/jivesoftware/spark/util/package.html diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/certificates/CertManager.java b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/CertManager.java new file mode 100644 index 000000000..98fdfc124 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/CertManager.java @@ -0,0 +1,290 @@ +package org.jivesoftware.sparkimpl.certificates; + +import java.awt.HeadlessException; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; +import java.util.Base64; +import java.util.Collection; +import java.util.Enumeration; +import java.util.LinkedList; +import java.util.List; + +import javax.naming.InvalidNameException; +import javax.naming.ldap.LdapName; +import javax.naming.ldap.Rdn; +import javax.swing.JOptionPane; +import javax.swing.table.DefaultTableModel; + +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.ui.login.CertificateDialog; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; + +/** + * This class contains some methods and fields that are common for CertificateController and IdentityController classes. + * According to MVC, it stands as Controller behind CertificatesManagerSettingsPanel and + * MutualAuthenticationSettingsPanel which are Views. + * + * @author Paweł Ścibiorski + */ +public abstract class CertManager { + + protected LocalPreferences localPreferences; + public final static char[] passwd = "changeit".toCharArray(); + protected boolean addToKeystore; + + public final static File SECURITY_DIRECTORY = new File(Spark.getSparkUserHome(), "security"); + + /** + * BLACKLIST is a KeyStore with revoked certificates. It isn't directly displayed, but when other + * KeyStores content is added, then it is compared with this list and information about revocation + * is added to certificate status + */ + public final static File BLACKLIST = new File(SECURITY_DIRECTORY, "blacklist"); + + /** + * Contain all certificates, used for help in managing certificates, but isn't directly displayed on the certificate table + */ + protected KeyStore blackListStore; + + protected final List allCertificates = new LinkedList<>(); + + /** + * Contains only revoked certificates + */ + protected final List blackListedCertificates = new LinkedList<>(); + + protected DefaultTableModel tableModel; + + public abstract void deleteEntry(String alias) throws KeyStoreException; + + public abstract void addOrRemoveFromExceptionList(boolean checked); + + public abstract boolean isOnExceptionList(CertificateModel cert); + + public abstract void createTableModel(); + + protected abstract void refreshCertTable(); + + public abstract void addEntryFileToKeyStore(File file) + throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, HeadlessException, + InvalidNameException, InvalidKeySpecException; + + /** + * Check if there is a certificate entry in KeyStore with the same alias. + * + * @param alias which is checked if it already exist in keystore + */ + protected abstract boolean checkForSameAlias(String alias) throws HeadlessException, KeyStoreException; + + /** + * Save the KeyStores. + */ + public abstract void loadKeyStores(); + + public abstract void overWriteKeyStores(); + + public void setAddToKeystore(boolean addToKeystore) { + this.addToKeystore = addToKeystore; + } + + public boolean isAddToKeystore() { + return addToKeystore; + } + + /** + * Check if this certificate already exists in TrustStore. + * + * @param addedCert the certificate for which it method look in the model list + * @return true if KeyStore already have this certificate. + */ + protected boolean checkForSameCertificate(X509Certificate addedCert) { + // check if this certificate isn't already added to TrustStore + for (CertificateModel model : allCertificates) { + X509Certificate certificateCheck = model.getCertificate(); + String signature = Base64.getEncoder().encodeToString(certificateCheck.getSignature()); + String addedSignature = Base64.getEncoder().encodeToString(addedCert.getSignature()); + if (addedSignature.equals(signature)) { + JOptionPane.showMessageDialog(null, Res.getString("dialog.certificate.cannot.have.copy")); + return true; + } + } + return false; + } + + /** + * Check if a given certificate is revoked looking on it's CRL (if exist). + * + * @param cert which is validated + * @return true if the certificate is revoked, false if it isn't or CRL cannot be accessed (because it might not exist). + */ + public boolean checkRevocation(X509Certificate cert) { + boolean revoked = false; + try { + SparkTrustManager man = new SparkTrustManager(); + Collection crls = man.loadCRL(new X509Certificate[]{cert}); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + for (X509CRL crl : crls) { + if (crl.isRevoked(cert)) { + revoked = true; + break; + } + } + } catch (Exception e) { + Log.warning("Cannot check validity", e); + } + return revoked; + } + + /** + * This method adds certificate to blackList + * + * @param cert the certificate to be added to the blacklist + */ + public void addCertificateToBlackList(X509Certificate cert) throws KeyStoreException, + HeadlessException, InvalidNameException { + blackListStore.setCertificateEntry(useCommonNameAsAlias(cert), cert); + blackListedCertificates.add(new CertificateModel(cert)); + } + + + /** + * Extract from the certificate its Common Name ("CN") and return it to use as certificates name. + * This method also assures that it will not add the second same alias to TrustStore by adding a number to alias. + * In case when a Common Name cannot be extracted, the method will return "cert{number}". + * + * @param cert Certificate which Common Name is meant to use + * @return String Common Name of the certificate + */ + protected String useCommonNameAsAlias(X509Certificate cert) throws InvalidNameException, HeadlessException, KeyStoreException { + String alias = null; + String dn = cert.getSubjectX500Principal().getName(); + LdapName ldapDN = new LdapName(dn); + for (Rdn rdn : ldapDN.getRdns()) { + if (rdn.getType().equals("CN")) { + alias = rdn.getValue().toString(); + int i = 1; + while (checkForSameAlias(alias)) { + alias = alias + i; + i++; + } + break; + } + } + // Certificate subject doesn't have easy distinguishable common name then generate alias as cert{integer} + if (alias == null) { + alias = "cert"; + int i = 1; + while (checkForSameAlias(alias)) { + alias = alias + i; + i++; + } + } + return alias; + } + + /** + * Open dialog with certificate. + */ + public abstract void showCertificate(); + + /** + * Open dialog with certificate. + * + * @param certModel Model of the certificate which details are meant to be shown. + * @param reason The reason for the Certificate dialog to be shown. + */ + public CertificateDialog showCertificate(CertificateModel certModel, CertificateDialogReason reason) { + return new CertificateDialog(localPreferences, certModel, this, reason); + } + + protected KeyStore openKeyStore(File file) { + KeyStore keyStore = null; + try { + keyStore = KeyStore.getInstance("JKS"); + // checking if length >0 prevents EOFExceptions + if (file.exists() && !file.isDirectory() && file.length() > 0) { + try (InputStream inputStream = Files.newInputStream(file.toPath())) { + keyStore.load(inputStream, passwd); + } catch (IOException | NoSuchAlgorithmException | CertificateException e) { + // try to open without a password + try (InputStream inputStream = Files.newInputStream(file.toPath())) { + keyStore.load(inputStream, "".toCharArray()); + } catch (IOException | NoSuchAlgorithmException | CertificateException e2) { + Log.error("Unable to access KeyStore " + file, e2); + } + } + } else { + keyStore.load(null, passwd); // if cannot open KeyStore then new empty one will be created + } + } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) { + Log.warning("Cannot create exceptions KeyStore", e); + } + return keyStore; + } + + /** + * Add certificates from keyStore to the list. Useful for displaying in the certificate table. + * + * @param keyStore source keystore. + * @param list list which will be filled with certificate models. + */ + protected List fillTableListWithKeyStoreContent(KeyStore keyStore, List list) { + if (keyStore != null) { + try { + Enumeration store = keyStore.aliases(); + while (store.hasMoreElements()) { + String alias = store.nextElement(); + X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias); + CertificateModel certModel = new CertificateModel(certificate, alias); + certModel.setRevoked(blackListStore.getCertificateAlias(certificate) != null); + if (list != null) { + list.add(certModel); + } + allCertificates.add(certModel); + } + } catch (KeyStoreException e) { + Log.error("Cannot read KeyStore", e); + } + } + return list; + } + + protected void saveKeyStore(KeyStore keyStore, File file) { + if (keyStore == null) { + return; + } + boolean isEmpty; + try { + isEmpty = keyStore.size() == 0; + } catch (KeyStoreException ignored) { + return; + } + if (isEmpty) { + file.delete(); + return; + } + try (OutputStream outputStream = Files.newOutputStream(file.toPath())) { + keyStore.store(outputStream, passwd); + } catch (Exception e) { + Log.error("Couldn't save KeyStore", e); + } + } + + public DefaultTableModel getTableModel() { + return tableModel; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/certificates/CertificateController.java b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/CertificateController.java new file mode 100644 index 000000000..241be84dd --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/CertificateController.java @@ -0,0 +1,623 @@ +package org.jivesoftware.sparkimpl.certificates; + +import java.awt.HeadlessException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; + +import javax.naming.InvalidNameException; +import javax.swing.JOptionPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableColumnModel; + +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.ui.login.CertificateDialog; +import org.jivesoftware.spark.ui.login.CertificatesManagerSettingsPanel; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; + +/** + * This class serve to extract certificates, storage them during runtime and format them and support management of them. + * Together with CertificateManagerSettingsPanel and CertificateModel Classes this applies an MVC pattern. + * + * @author Paweł Ścibiorski + */ +public class CertificateController extends CertManager { + + /** + * TRUSTED contains user's trusted certificates + */ + public final static File TRUSTED = new File(SECURITY_DIRECTORY, "truststore"); + + /** + * EXCEPTIONS contains user's certificates that are added to exceptions (their validity isn't checked) + */ + public final static File EXCEPTIONS = new File(SECURITY_DIRECTORY, "exceptions"); + + /** + * DISTRUSTED_CACERTS when a user removes JRE certificate then really copy of this is created in this KeyStore + */ + public final static File DISTRUSTED_CACERTS = new File(SECURITY_DIRECTORY, "distrusted_cacerts"); + + /** + * CACERTS_EXCEPTIONS used for JRE certificates that are added to exceptions (their validity isn't checked) + */ + public final static File CACERTS_EXCEPTIONS = new File(SECURITY_DIRECTORY, "cacerts_exceptions"); + + /** + * DISPLAYED_CACERTS isn't used de facto as a file as it is never saved, but this object helps in keystore management. + * It contains CACERTS - (DISTRUSTED_CACERTS + CACERTSEXCEPTIONS) + */ + public final static File DISPLAYED_CACERTS = new File(SECURITY_DIRECTORY, "displayed_cacerts"); + + /** + * CACERTS contain only JRE default certificates, data is only read from it, never saved to this file. + * CACERTS should be used only for read. + */ + public final static File CACERTS = new File(System.getProperty("java.home") + File.separator + "lib" + File.separator + "security" + File.separator + "cacerts"); + + private KeyStore trustStore, exceptionsStore, displayCaStore, distrustedCaStore, exceptionsCaStore; + + /** + * Contains certificates which aren't revoked or exempted + */ + private List trustedCertificates = new LinkedList<>(); + + /** + * Contains only certificates from a list of exempted + */ + private List exemptedCertificates = new LinkedList<>(); + + /** + * Contains only exempted cacerts certificates + */ + private List exemptedCacerts = new LinkedList<>(); + + /** + * Contains cacerts displayed certificates that aren't exempted + */ + private List displayCaCertificates = new LinkedList<>(); + + private static final String[] COLUMN_NAMES = { + Res.getString("table.column.certificate.subject"), + Res.getString("table.column.certificate.validity"), + Res.getString("table.column.certificate.exempted") + }; + private static final int NUMBER_OF_COLUMNS = COLUMN_NAMES.length; + + private static final Class[] COLUMN_TYPES = { + String.class, + String.class, + Boolean.class + }; + + + public CertificateController(LocalPreferences localPreferences) { + Objects.requireNonNull(localPreferences); + this.localPreferences = localPreferences; + } + + /** + * Load KeyStores files. + */ + @Override + public void loadKeyStores() { + blackListStore = openKeyStore(BLACKLIST); + trustStore = openKeyStore(TRUSTED); + exceptionsStore = openKeyStore(EXCEPTIONS); + distrustedCaStore = openKeyStore(DISTRUSTED_CACERTS); + exceptionsCaStore = openKeyStore(CACERTS_EXCEPTIONS); + displayCaStore = openCacertsKeyStore(); + + trustedCertificates = fillTableListWithKeyStoreContent(trustStore, trustedCertificates); + exemptedCertificates = fillTableListWithKeyStoreContent(exceptionsStore, exemptedCertificates); + displayCaCertificates = fillTableListWithKeyStoreContent(displayCaStore, displayCaCertificates); + exemptedCacerts = fillTableListWithKeyStoreContent(exceptionsCaStore, exemptedCacerts); + } + + public KeyStore openCacertsKeyStore() { + KeyStore caStore = openKeyStore(CACERTS); + KeyStore distrustedCaStore = openKeyStore(DISTRUSTED_CACERTS); + KeyStore exceptionsCaStore = openKeyStore(CACERTS_EXCEPTIONS); + KeyStore displayCerts = null; // displayCerts keyStore is meant to contain certificates that are in cacerts and aren't distrusted + try { + displayCerts = KeyStore.getInstance("JKS"); + displayCerts.load(null, passwd); + if (caStore != null) { + Enumeration store = caStore.aliases(); + while (store.hasMoreElements()) { + String alias = store.nextElement(); + X509Certificate certificate = (X509Certificate) caStore.getCertificate(alias); + // if getCertificateAlias return null then entry doesn't exist in distrustedCaStore (Java's default). + if (distrustedCaStore.getCertificateAlias(certificate) == null) { + displayCerts.setCertificateEntry(alias, certificate); + } + } + } + } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) { + Log.error("Cannot read KeyStore", e); + + } + return displayCerts; + } + + @Override + public void overWriteKeyStores() { + saveKeyStore(trustStore, TRUSTED); + saveKeyStore(exceptionsStore, EXCEPTIONS); + saveKeyStore(blackListStore, BLACKLIST); + saveKeyStore(distrustedCaStore, DISTRUSTED_CACERTS); + saveKeyStore(exceptionsCaStore, CACERTS_EXCEPTIONS); + } + + @Override + public void createTableModel() { + tableModel = new DefaultTableModel() { + // return adequate classes for columns so last column is Boolean displayed as checkbox + @Override + public Class getColumnClass(int column) { + return COLUMN_TYPES[column]; + } + + @Override + public boolean isCellEditable(int row, int column) { + return column == 2; + } + }; + + tableModel.setColumnIdentifiers(COLUMN_NAMES); + Object[] certEntry = new Object[NUMBER_OF_COLUMNS]; + addRowsToTableModel(trustedCertificates, certEntry); + addRowsToTableModel(displayCaCertificates, certEntry); + } + + /** + * Adds a list to the certificate table so it is displayed in the table. + * + * @param certList is list with CertificateModel object that are added to the + * @param certEntry serves as a table row model. Each element of that array is corresponding to the column in table + */ + private void addRowsToTableModel(List certList, Object[] certEntry) { + if (certList == null) { + return; + } + // put certificate from arrayList into rows with chosen columns + for (CertificateModel cert : certList) { + tableModel.addRow(fillTableWithList(certEntry, cert)); + } + } + + /** + * Create a certificate entry, which can be added in row of the certificate table. + * + * @param certEntry serves as a table row model. Each element of that array is corresponding to the column in table + * @param cert is CertificateModel for which this class will return object representing table's row + * @return certificate entry which is array of objects which values depends on this method. Elements are: [0] String [1] String [2] boolean + */ + private Object[] fillTableWithList(Object[] certEntry, CertificateModel cert) { + if (cert.getSubjectCommonName() != null) { + certEntry[0] = cert.getSubjectCommonName(); + } else { + certEntry[0] = cert.getSubject(); + } + certEntry[1] = cert.getValidityStatus(); + certEntry[2] = isOnExceptionList(cert); + return certEntry; + } + + /** + * Adds certificate with given entry to exceptions KeyStore + * + * @param alias of the certificate, assuming that certificate is in TrustStore + */ + public void addCertToExceptions(String alias) { + try { + X509Certificate cert = (X509Certificate) trustStore.getCertificate(alias); + exceptionsStore.setCertificateEntry(alias, cert); + } catch (KeyStoreException ex) { + Log.error("Error at moving certificate from trusted list to the exceptions list", ex); + } + } + + /** + * Removes a certificate with the given alias from the exceptions list + * + * @param alias of the certificate + */ + private void removeCertFromExceptions(String alias) { + try { + X509Certificate cert = (X509Certificate) trustStore.getCertificate(alias); + exceptionsStore.deleteEntry(alias); + } catch (KeyStoreException ex) { + Log.error("Error at moving certificate from exceptions list to trusted list", ex); + } + } + + /** + * Adds CA certificate with the given entry to CA exceptions KeyStore + * + * @param alias of the certificate + */ + private void addCaCertToExceptions(String alias) { + + try { + X509Certificate cert = (X509Certificate) displayCaStore.getCertificate(alias); + exceptionsCaStore.setCertificateEntry(alias, cert); + } catch (KeyStoreException ex) { + Log.error("Error at moving certificate from trusted list to the exception list", ex); + } + } + + /** + * Removes CA certificate with the given alias from the exceptions list + * + * @param alias of the certificate + */ + private void removeCaCertFromExceptions(String alias) { + try { + X509Certificate cert = (X509Certificate) displayCaStore.getCertificate(alias); + exceptionsCaStore.deleteEntry(alias); + } catch (KeyStoreException ex) { + Log.error("Error at moving certificate from exceptions list to trusted list", ex); + } + } + + /** + * If argument is true then move certificate to the exceptions Keystore, if false, then move to the trusted Keystore. + * Useful for checkboxes where its selected value indicates where the certificate should be moved. + * + * @param checked should it be moved? + */ + @Override + public void addOrRemoveFromExceptionList(boolean checked) { + String alias = allCertificates.get(getTranslatedRow()).getAlias(); + if (getAliasKeyStorePath(alias).equals(TRUSTED)) { + if (checked) { + addCertToExceptions(alias); + } else { + removeCertFromExceptions(alias); + } + } else if (getAliasKeyStorePath(alias).equals(DISPLAYED_CACERTS)) { + if (checked) { + addCaCertToExceptions(alias); + } else { + removeCaCertFromExceptions(alias); + } + } + } + + public boolean isInTrustStore(CertificateModel cert) { + try { + if (trustStore.getCertificateAlias(cert.getCertificate()) != null) { + return true; + } else { + return displayCaStore.getCertificateAlias(cert.getCertificate()) != null; + } + } catch (KeyStoreException e) { + return false; + } + } + + /** + * Return information if certificate is on the list of exception. + * + * @param cert the model entry + */ + @Override + public boolean isOnExceptionList(CertificateModel cert) { + try { + if (exceptionsStore.getCertificateAlias(cert.getCertificate()) != null) { + return true; + } else { + return exceptionsCaStore.getCertificateAlias(cert.getCertificate()) != null; + } + } catch (KeyStoreException e) { + return false; + } + } + + /** + * Return information if certificate is on blacklist (revoked). + * + * @param cert Model entry + */ + public boolean isOnBlackList(CertificateModel cert) { + return blackListedCertificates.contains(cert); + } + + /** + * Return file path which contains certificate with given alias; + * + * @param alias of the certificate + * @return File path of KeyStore with certificate + */ + private KeyStore getAliasKeyStore(String alias) { + try { + if (exceptionsStore.containsAlias(alias)) { + return exceptionsStore; + } + if (exceptionsCaStore.containsAlias(alias)) { + return exceptionsCaStore; + } + if (blackListStore.containsAlias(alias)) { + return blackListStore; + } + if (trustStore.containsAlias(alias)) { + return trustStore; + } + if (displayCaStore.containsAlias(alias)) { + return displayCaStore; + } + } catch (KeyStoreException e) { + Log.error(e); + return null; + } + return null; + } + + /** + * Return file path which contains certificate with given alias; + * + * @param alias of the certificate + * @return File path of KeyStore with certificate + */ + private File getAliasKeyStorePath(String alias) { + try { + if (exceptionsStore.containsAlias(alias)) { + return EXCEPTIONS; + } + if (exceptionsCaStore.containsAlias(alias)) { + return CACERTS_EXCEPTIONS; + } + if (blackListStore.containsAlias(alias)) { + return BLACKLIST; + } + if (trustStore.containsAlias(alias)) { + return TRUSTED; + } + if (displayCaStore.containsAlias(alias)) { + return DISPLAYED_CACERTS; + } + } catch (KeyStoreException e) { + Log.error(e); + return null; + } + return null; + } + + + /** + * This method deletes certificate with provided alias from the Truststore + * + * @param alias Alias of the certificate to delete + */ + @Override + public void deleteEntry(String alias) throws KeyStoreException { + int dialogButton = JOptionPane.YES_NO_OPTION; + int dialogValue = JOptionPane.showConfirmDialog(null, Res.getString("dialog.certificate.sure.to.delete"), null, + dialogButton); + if (dialogValue == JOptionPane.YES_OPTION) { + KeyStore store = getAliasKeyStore(alias); + + if (store.equals(displayCaStore) || store.equals(exceptionsCaStore)) { + // adds entry do distrusted store so it will be not displayed next time + distrustedCaStore.setCertificateEntry(alias, store.getCertificate(alias)); + } + store.deleteEntry(alias); + if (store.equals(trustStore)) { + removeCertFromExceptions(alias); + } + JOptionPane.showMessageDialog(null, Res.getString("dialog.certificate.has.been.deleted")); + CertificateModel model = null; + for (CertificateModel certModel : allCertificates) { + if (certModel.getAlias().equals(alias)) { + model = certModel; + break; + } + } + exemptedCertificates.remove(model); + trustedCertificates.remove(model); + blackListedCertificates.remove(model); + displayCaCertificates.remove(model); + exemptedCacerts.remove(model); + + allCertificates.remove(model); + } + refreshCertTable(); + } + + /** + * Refresh the certificate table to make visible changes in it's model + */ + @Override + public void refreshCertTable() { + createTableModel(); + SwingUtilities.invokeLater(() -> { + resizeColumnWidth(CertificatesManagerSettingsPanel.getCertTable()); + CertificatesManagerSettingsPanel.getCertTable().setModel(tableModel); + tableModel.fireTableDataChanged(); + }); + } + + + /** + * Resizes certificate table to preferred width. + */ + public void resizeColumnWidth(JTable table) { + SwingUtilities.invokeLater(() -> { + final TableColumnModel columnModel = table.getColumnModel(); + final int maxWidth = table.getParent().getWidth(); + columnModel.getColumn(1).setPreferredWidth(80); + columnModel.getColumn(2).setPreferredWidth(60); + columnModel.getColumn(0).setPreferredWidth(maxWidth - 140); + }); + } + + public void addEntryToKeyStore(X509Certificate cert, boolean exempted) throws HeadlessException, InvalidNameException, KeyStoreException { + Objects.requireNonNull(cert); + addEntryToKeyStoreImpl(new CertificateModel(cert), exempted); + } + + /** + * This method adds certificate entry to the TrustStore. + * + * @param cert Certificate which is added. + */ + public void addEntryToKeyStore(X509Certificate cert, CertificateDialogReason reason) throws HeadlessException, InvalidNameException, KeyStoreException { + Objects.requireNonNull(cert); + if (reason != null) { + addEntryToKeyStoreImpl(cert, reason); + } else { + addEntryToKeyStoreImpl(new CertificateModel(cert), false); + } + } + + /** + * This method adds a certificate from the file (*.cer), (*.crt), (*.der), (*.pem) to TrustStore. + * + * @param file File with a certificate that is added + */ + @Override + public void addEntryFileToKeyStore(File file) throws IOException, CertificateException, + KeyStoreException, HeadlessException, InvalidNameException { + Objects.requireNonNull(file); + X509Certificate addedCert = certificateFromFile(file); + addEntryToKeyStoreImpl(addedCert, CertificateDialogReason.ADD_CERTIFICATE); + } + + /** + * Opens a new dialog which will ask to add certificates from a chain + */ + public void addChain(X509Certificate[] chain) { + try { + final KeyStore caCertsStore = openCacertsKeyStore(); + for (X509Certificate cert : chain) { + if ((trustStore.getCertificateAlias(cert) == null) + && (caCertsStore.getCertificateAlias(cert) == null)) { + addEntryToKeyStore(cert, true); + } + } + overWriteKeyStores(); + } catch (Exception e) { + Log.error("An exception occurred while trying to add a certificate chain to the trust stores", e); + } + } + + public void addCertificateAsExempted(CertificateModel certModel) throws HeadlessException, InvalidNameException, KeyStoreException { + addEntryToKeyStoreImpl(certModel, true); + } + + /** + * This method adds a certificate to the KeyStore. If it is invalid, revoked or self-signed, it will be added as an exempted certificate. + * It can be added as exempted also on purpose by setting on true exempted. + * + * @param certModel CertificateModel + * @param exempted if it is set on true then certificate will be also added to exempted certificates + */ + private void addEntryToKeyStoreImpl(CertificateModel certModel, boolean exempted) throws HeadlessException, InvalidNameException, KeyStoreException { + String alias = useCommonNameAsAlias(certModel.getCertificate()); + //if certificate is invalid in some way then it is added to exceptions, also it can be intentionally set as exempted + if (!certModel.isValid() || checkRevocation(certModel.getCertificate()) || certModel.isSelfSigned() || exempted) { + exceptionsStore.setCertificateEntry(alias, certModel.getCertificate()); + exemptedCertificates.add(certModel); + } + trustStore.setCertificateEntry(alias, certModel.getCertificate()); + trustedCertificates.add(certModel); + + if (tableModel != null) { + refreshCertTable(); + } + } + + /** + * This method takes certificate and add it to the TrustStore + * + * @param addedCert certificate which is added + * @param reason changes displayed text in certificate dialog + */ + private void addEntryToKeyStoreImpl(X509Certificate addedCert, CertificateDialogReason reason) throws HeadlessException, InvalidNameException, KeyStoreException { + CertificateModel certModel = new CertificateModel(addedCert); + CertificateDialog certDialog = null; + if (!checkForSameCertificate(addedCert)) { + certDialog = showCertificate(certModel, reason); + } + if (certDialog != null && certDialog.isAddCert()) { + addEntryToKeyStoreImpl(certModel, false); + JOptionPane.showMessageDialog(null, Res.getString("dialog.certificate.has.been.added")); + } + } + + /** + * Takes a file with certificate and return X509Representation of the certificate. + * + * @param file with certificate + * @return X509Certificate from the file + */ + private X509Certificate certificateFromFile(File file) throws IOException, CertificateException { + X509Certificate cert; + try (InputStream inputStream = Files.newInputStream(file.toPath())) { + CertificateFactory cf = CertificateFactory.getInstance("X509"); + cert = (X509Certificate) cf.generateCertificate(inputStream); + } + return cert; + } + + /** + * Check if there is certificate entry in Truststore with the same alias. + * + * @param alias Alias of the certificate which is looked for in the model list + * @return True if KeyStore contain the same alias. + */ + @Override + protected boolean checkForSameAlias(String alias) throws HeadlessException { + for (CertificateModel model : allCertificates) { + if (model.getAlias().equals(alias)) { + return true; + } + } + return false; + } + + /** + * Open dialog with certificate. + */ + @Override + public void showCertificate() { + CertificateDialog certDialog = new CertificateDialog(localPreferences, + allCertificates.get(getTranslatedRow()), this, CertificateDialogReason.SHOW_CERTIFICATE); + } + + /** + * Gets index of an element in the table model in the selected row of table after sorting. + * + * @return index of row + */ + private int getTranslatedRow() { + int selectedRow = CertificatesManagerSettingsPanel.getCertTable().getSelectedRow(); + return CertificatesManagerSettingsPanel.getCertTable().convertRowIndexToModel(selectedRow); + } + + public List getAllCertificates() { + return allCertificates; + } + + public void setTableModel(DefaultTableModel tableModel) { + this.tableModel = tableModel; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/certificates/CertificateDialogReason.java b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/CertificateDialogReason.java new file mode 100644 index 000000000..82bc2cfdb --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/CertificateDialogReason.java @@ -0,0 +1,9 @@ +package org.jivesoftware.sparkimpl.certificates; + +public enum CertificateDialogReason { + ADD_CERTIFICATE, + SHOW_CERTIFICATE, + SHOW_ID_CERTIFICATE, + ADD_ID_CERTIFICATE, + ADD_CERTIFICATE_FROM_CONNECTION +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/certificates/CertificateModel.java b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/CertificateModel.java new file mode 100644 index 000000000..d6adb6a64 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/CertificateModel.java @@ -0,0 +1,468 @@ +package org.jivesoftware.sparkimpl.certificates; + +import java.io.IOException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.util.*; + +import javax.naming.InvalidNameException; +import javax.naming.ldap.LdapName; +import javax.naming.ldap.Rdn; + +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier; +import org.bouncycastle.asn1.x509.BasicConstraints; +import org.bouncycastle.asn1.x509.CRLDistPoint; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.asn1.x509.GeneralSubtree; +import org.bouncycastle.asn1.x509.NameConstraints; +import org.bouncycastle.asn1.x509.PolicyConstraints; +import org.bouncycastle.asn1.x509.SubjectDirectoryAttributes; +import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; +import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; +import org.bouncycastle.util.encoders.Hex; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.util.log.Log; + +/** + * Model that keep certificate fields as String values.Together with CertificateController and + * CertificateManagerSettingsPanel classes this apply MVC pattern. + */ +public class CertificateModel { + + private final X509Certificate certificate; + private String alias; + private String subjectCommonName; + private String issuerCommonName; + private final int version; + private final String serialNumber; + private final String signatureValue; + private final String signatureAlgorithm; + private final String issuer; + private final String subject; + private final String notBefore; + private final String notAfter; + private final String publicKey; + private final String publicKeyAlgorithm; + private String issuerUniqueID; + private String subjectUniqueID; + + private final boolean valid; + private boolean revoked; + private Set criticalExtensionSet; + private Set nonCriticalExtensionSet; + private final HashMap extensions = new HashMap<>(); + private final ArrayList unsupportedCriticalExtensions = new ArrayList<>(); + private final ArrayList unsupportedNonCriticalExtensions = new ArrayList<>(); + + public CertificateModel(X509Certificate certificate, String alias) { + this(certificate); + this.alias = alias; + } + + public CertificateModel(X509Certificate certificate) { + Objects.requireNonNull(certificate); + this.certificate = certificate; + this.version = certificate.getVersion(); + this.serialNumber = certificate.getSerialNumber().toString(); + this.signatureValue = Base64.getEncoder().encodeToString(certificate.getSignature()); + this.signatureAlgorithm = certificate.getSigAlgName(); + this.issuer = certificate.getIssuerX500Principal().getName(); + this.subject = certificate.getSubjectX500Principal().getName(); + this.notBefore = certificate.getNotBefore().toString(); + this.notAfter = certificate.getNotAfter().toString(); + this.publicKey = certificate.getPublicKey().toString(); + this.publicKeyAlgorithm = certificate.getPublicKey().getAlgorithm(); + // rfc5280 in section 4.1.2.8. Unique Identifiers + // "CAs conforming to this profile MUST NOT generate certificates with unique identifiers." + // "These fields MUST NOT appear if the version is 1." + if (version != 1 && ((certificate.getKeyUsage() != null && !certificate.getKeyUsage()[5]) + || certificate.getBasicConstraints() == -1)) { + try { + this.issuerUniqueID = Arrays.toString(certificate.getIssuerUniqueID()); + } catch (NullPointerException e) { + Log.warning("Certificate doesn't have issuerUniqueID: " + issuer, e); + } + try { + this.subjectUniqueID = Arrays.toString(certificate.getIssuerUniqueID()); + } catch (NullPointerException e) { + Log.warning("Certificate doesn't have subjectUniqueID: " + subject, e); + } + } + try { + this.subjectCommonName = extractCommonName(subject); + } catch (InvalidNameException e) { + Log.warning("Couldn't extract subject Common Name (CN)", e); + } + + try { + this.issuerCommonName = extractCommonName(issuer); + } catch (InvalidNameException e) { + Log.warning("Couldn't extract issuer Common Name (CN)", e); + } + this.valid = checkValidity(); + + setupExtensions(certificate); + + } + + private void setupExtensions(X509Certificate cert) { + + criticalExtensionSet = cert.getCriticalExtensionOIDs(); + nonCriticalExtensionSet = cert.getNonCriticalExtensionOIDs(); + if (criticalExtensionSet != null) { + for (String oid : criticalExtensionSet) { + extensionExtractHandler(cert, oid, true); + } + } + if (nonCriticalExtensionSet != null) { + for (String oid : nonCriticalExtensionSet) { + extensionExtractHandler(cert, oid, false); + } + } + } + + /** + * Get values of the extension and format them into readable Strings. + * + * @param cert + * @param oid + */ + private void extensionExtractHandler(X509Certificate cert, String oid, boolean critical) { + try { + ASN1Primitive primitive = JcaX509ExtensionUtils.parseExtensionValue(cert.getExtensionValue(oid)); + String value = Res.getString("cert.is.critical") + critical + "\n"; + boolean isSupported = true; + + if (oid.equals(Extension.subjectDirectoryAttributes.toString())) { + value += subjectDirectoryAttributesExtractor(primitive); + + } else if (oid.equals(Extension.subjectKeyIdentifier.toString())) { + value += subjectKeyIdentifierExtractor(primitive); + + } else if (oid.equals(Extension.keyUsage.toString())) { + value += keyUsageExtractor(cert); + + } else if (oid.equals(Extension.subjectAlternativeName.toString())) { + value += alternativeNameExtractor(cert.getSubjectAlternativeNames()); + + } else if (oid.equals(Extension.issuerAlternativeName.toString())) { + value += alternativeNameExtractor(cert.getIssuerAlternativeNames()); + + } else if (oid.equals(Extension.basicConstraints.toString())) { + value += basicConstraintsExtractor(primitive); + + } else if (oid.equals(Extension.nameConstraints.toString())) { + value += NameConstraintsExtractor(primitive); + + } else if (oid.equals(Extension.cRLDistributionPoints.toString())) { + value += CRLPointsExtractor(primitive); + + } else if (oid.equals(Extension.policyMappings.toString())) { + value += policyMappingsExtractor(cert); + + } else if (oid.equals(Extension.authorityKeyIdentifier.toString())) { + value += authorityKeyIdentifierExtractor(primitive); + + } else if (oid.equals(Extension.policyConstraints.toString())) { + value += policyConstraintsExtractor(primitive); + + } else if (oid.equals(Extension.extendedKeyUsage.toString())) { + value += extendedKeyUsageExtractor(cert); + + } else { + addToUnsupported(critical, oid); + isSupported = false; + } + if (isSupported) { + extensions.put(oid, value); + } + } catch (NullPointerException | IOException | CertificateParsingException e) { + Log.error("Couldn't extract " + oid + ": " + OIDTranslator.getDescription(oid) + "extension.", e); + addToUnsupported(critical, oid); + } + } + + private String subjectDirectoryAttributesExtractor(ASN1Primitive primitive) { + SubjectDirectoryAttributes sub = SubjectDirectoryAttributes.getInstance(primitive); + return sub.toString(); + } + + private String extendedKeyUsageExtractor(X509Certificate cert) throws CertificateParsingException { + StringBuilder value = new StringBuilder(); + List extKeyUsage = cert.getExtendedKeyUsage(); + for (String use : extKeyUsage) { + value.append(use).append(": ").append(OIDTranslator.getDescription(use)).append("\n"); + } + return value.toString(); + } + + private String policyConstraintsExtractor(ASN1Primitive primitive) { + PolicyConstraints pc = PolicyConstraints.getInstance(primitive); + String value = ""; + if (pc.getInhibitPolicyMapping() != null) { + value += Res.getString("cert.extension.policy.constraints.inhibit.policy.mapping") + ": " + + pc.getInhibitPolicyMapping() + "\n"; + } + if (pc.getRequireExplicitPolicyMapping() != null) { + value += Res.getString("cert.extension.policy.constraints.require.explicit.policy.mapping") + ": " + + pc.getRequireExplicitPolicyMapping(); + } + return value; + } + + private String authorityKeyIdentifierExtractor(ASN1Primitive primitive) { + AuthorityKeyIdentifier authorityKeyIdentifier = AuthorityKeyIdentifier.getInstance(primitive); + return Hex.toHexString(authorityKeyIdentifier.getKeyIdentifier()); + } + + private String subjectKeyIdentifierExtractor(ASN1Primitive primitive) { + SubjectKeyIdentifier subjectKeyIdentifier = SubjectKeyIdentifier.getInstance(primitive); + return Hex.toHexString(subjectKeyIdentifier.getKeyIdentifier()); + } + + private String policyMappingsExtractor(X509Certificate cert) { + ASN1OctetString oct = ASN1OctetString.getInstance(cert.getExtensionValue(Extension.policyMappings.toString())); + return oct.toString(); + } + + private String CRLPointsExtractor(ASN1Primitive primitive) { + CRLDistPoint point = CRLDistPoint.getInstance(primitive); + return point.toString(); + } + + private String NameConstraintsExtractor(ASN1Primitive primitive) { + NameConstraints nc = NameConstraints.getInstance(primitive); + StringBuilder value = new StringBuilder(); + if (nc.getPermittedSubtrees() != null) { + value.append(Res.getString("cert.extension.name.constraints.permitted.subtrees")).append(": \n"); + for (GeneralSubtree subtree : nc.getPermittedSubtrees()) { + value.append(subtree.toString()).append("\n"); + } + } + if (nc.getExcludedSubtrees() != null) { + value.append(Res.getString("cert.extension.name.constraints.excluded.subtrees")).append(": \n"); + for (GeneralSubtree subtree : nc.getExcludedSubtrees()) { + value.append(subtree.toString()).append("\n"); + } + } + return value.toString(); + } + + private String basicConstraintsExtractor(ASN1Primitive primitive) { + BasicConstraints bc = BasicConstraints.getInstance(primitive); + String value = Res.getString("cert.extension.basic.constraints.is.ca") + ": " + bc.isCA(); + if (bc.getPathLenConstraint() != null) { + value += "\n" + Res.getString("cert.extension.basic.constraints.path.length") + ": " + + bc.getPathLenConstraint(); + } + return value; + } + + private String alternativeNameExtractor(Collection> rootNames) { + StringBuilder value = new StringBuilder(); + if (rootNames != null) { + for (List names : rootNames) { + if (names != null) { + for (Object name : names) { + value.append(name.toString()).append("\n"); + } + } + } + } + return value.toString(); + } + + + private String keyUsageExtractor(X509Certificate cert){ + String value; + value = Res.getString("cert.extension.extended.usage.digital.signature") + ": " + cert.getKeyUsage()[0] + + "\n"; + value += Res.getString("cert.extension.extended.usage.non.repudiation") + ": " + cert.getKeyUsage()[1] + + "\n"; + value += Res.getString("cert.extension.extended.usage.key.encipherment") + ": " + cert.getKeyUsage()[2] + + "\n"; + value += Res.getString("cert.extension.extended.usage.data.encipherment") + ": " + cert.getKeyUsage()[3] + + "\n"; + value += Res.getString("cert.extension.extended.usage.key.agreement") + ": " + cert.getKeyUsage()[4] + + "\n"; + value += Res.getString("cert.extension.extended.usage.key.cert.sign") + ": " + cert.getKeyUsage()[5] + + "\n"; + value += Res.getString("cert.extension.extended.usage.crl.sign") + ": " + cert.getKeyUsage()[6] + + "\n"; + value += Res.getString("cert.extension.extended.usage.encipher.only") + ": " + cert.getKeyUsage()[7] + + "\n"; + value += Res.getString("cert.extension.extended.usage.decipher.only") + ": " + cert.getKeyUsage()[8]; + + return value; + } + + private void addToUnsupported(boolean critical, String oid){ + if (critical) { + unsupportedCriticalExtensions.add(oid); + } else { + unsupportedNonCriticalExtensions.add(oid); + } + } + + private String extractCommonName(String certName) throws InvalidNameException { + String name = null; + LdapName ldapDN = new LdapName(certName); + for (Rdn rdn : ldapDN.getRdns()) { + if (rdn.getType().equals("CN")) { + name = rdn.getValue().toString(); + } + } + return name; + } + + public String getValidityStatus() { + if (isRevoked()) { + return Res.getString("cert.revoked"); + + } else if (isAfterNotAfter()) { + return Res.getString("cert.expired"); + + } else if (isBeforeNotBefore()) { + return "cert.not.valid.yet"; + + } else { + return Res.getString("cert.valid"); + } + } + + public String getCertStatusAll() { + String status = ""; + if (isRevoked()) { + status += Res.getString("cert.revoked") + "\n"; + } + if (isAfterNotAfter()) { + status += Res.getString("cert.expired") + "\n"; + } + if (isBeforeNotBefore()) { + status += Res.getString("cert.not.valid.yet") + "\n"; + } + if (!isRevoked() && !isAfterNotAfter() && !isBeforeNotBefore()) { + status += Res.getString("cert.valid") + "\n"; + } + if (isSelfSigned()) { + status += Res.getString("cert.self.signed") + "\n"; + } + return status; + } + + public boolean isSelfSigned(){ + return subject.equals(issuer); + } + + /** + * Check validity of the certificate. + * @return True if certificate isn't expired, isn't not valid yet and isn't revoked. + */ + private boolean checkValidity() { + return !isAfterNotAfter() && !isBeforeNotBefore() && !isRevoked(); + } + + private boolean isBeforeNotBefore() { + Date today = new Date(); + return today.before(certificate.getNotBefore()); + } + + private boolean isAfterNotAfter() { + Date today = new Date(); + return today.after(certificate.getNotAfter()); + } + + public X509Certificate getCertificate() { + return certificate; + } + + public String getAlias() { + return alias; + } + + public int getVersion() { + return version; + } + + public String getSerialNumber() { + return serialNumber; + } + + public String getSignatureValue() { + return signatureValue; + } + + public String getSignatureAlgorithm() { + return signatureAlgorithm; + } + + public String getIssuer() { + return issuer; + } + + public String getSubject() { + return subject; + } + + public String getNotBefore() { + return notBefore; + } + + public String getNotAfter() { + return notAfter; + } + + public String getPublicKey() { + return publicKey; + } + + public String getPublicKeyAlgorithm() { + return publicKeyAlgorithm; + } + + public String getIssuerUniqueID() { + return issuerUniqueID; + } + + public String getSubjectUniqueID() { + return subjectUniqueID; + } + + public boolean isValid() { + return valid; + } + + public String getSubjectCommonName() { + return subjectCommonName; + } + + public boolean isRevoked() { + return revoked; + } + + public void setRevoked(boolean revoked) { + this.revoked = revoked; + } + + public String getIssuerCommonName() { + return issuerCommonName; + } + + public Set getCriticalExtensionSet() { + return criticalExtensionSet; + } + + public HashMap getExtensions() { + return extensions; + } + + public ArrayList getUnsupportedCriticalExtensions() { + return unsupportedCriticalExtensions; + } + + public ArrayList getUnsupportedNonCriticalExtensions() { + return unsupportedNonCriticalExtensions; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/certificates/GeneralTrustManager.java b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/GeneralTrustManager.java new file mode 100644 index 000000000..62a1ccb47 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/GeneralTrustManager.java @@ -0,0 +1,98 @@ +package org.jivesoftware.sparkimpl.certificates; + +import java.awt.HeadlessException; +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; + +import javax.naming.InvalidNameException; +import javax.net.ssl.X509TrustManager; + +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +/** + * This class contain some of the methods and variables that are common for Spark's TrustManagers + * @author Pawel Scibiorski + */ +public abstract class GeneralTrustManager implements X509TrustManager { + protected final LocalPreferences localPref = SettingsManager.getLocalPreferences(); + protected final CertificateController certControll = new CertificateController(localPref); + protected KeyStore allStore; + protected abstract void loadKeyStores(); + + /** + * Adds content of the keystore to allStore which should contain all certificates from accepted issuers. + * @param keyStore + * @throws KeyStoreException + * @throws HeadlessException + * @throws InvalidNameException + */ + protected void addKeyStoreContentToAllStore(KeyStore keyStore) + throws KeyStoreException, HeadlessException, InvalidNameException { + + Enumeration aliases = keyStore.aliases(); + // Retrieve all the certificates out of the KeyStore using aliases + while (aliases.hasMoreElements()) { + String alias = aliases.nextElement(); + X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias); + allStore.setCertificateEntry(certControll.useCommonNameAsAlias(certificate), certificate); + } + } + + protected void loadAllStore() { + try { + allStore = KeyStore.getInstance("JKS"); + allStore.load(null, CertificateController.passwd); + } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException | HeadlessException e) { + Log.error("Cannot create allStore KeyStore", e); + } + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + X509Certificate[] X509Certs; + try { + // See how many certificates are in the keystore. + int numberOfEntry = allStore.size(); + // Create an array of X509Certificates + X509Certs = new X509Certificate[numberOfEntry]; + // If there are any certificates in the keystore. + if (numberOfEntry > 0) { + // Get all the certificate alias out of the keystore. + Enumeration aliases = allStore.aliases(); + // Retrieve all the certificates out of the keystore + // via the alias name. + int i = 0; + while (aliases.hasMoreElements()) { + X509Certs[i] = (X509Certificate) allStore.getCertificate(aliases.nextElement()); + i++; + } + } + } catch (KeyStoreException e) { + Log.error("Cannot create accepted issuers list", e); + X509Certs = null; + } + return X509Certs; + } + + /** + * Checks if certificate order in chain is end entity certificate for first certificate in the chain and root CA is last in the chain + * @param chain with certificates + * @return true if first certificate in chain is end entity + */ + protected boolean isOrderFromSubjectToIssuer(X509Certificate[] chain){ + boolean order = true; + for (int i = 0; i < chain.length - 1; i++) { + if(!chain[i].getIssuerX500Principal().getName().equals(chain[i + 1].getSubjectX500Principal().getName())){ + order = false; + } + } + return order; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/certificates/IdentityController.java b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/IdentityController.java new file mode 100644 index 000000000..b41fefc53 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/IdentityController.java @@ -0,0 +1,294 @@ +package org.jivesoftware.sparkimpl.certificates; + +import java.awt.HeadlessException; +import java.io.File; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.file.Files; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.security.Security; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; +import java.util.Date; +import java.util.Objects; + +import javax.naming.InvalidNameException; +import javax.net.ssl.KeyManagerFactory; +import javax.security.auth.x500.X500Principal; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import javax.swing.table.DefaultTableModel; + +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.BasicConstraints; +import org.bouncycastle.asn1.x509.ExtendedKeyUsage; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.asn1.x509.KeyPurposeId; +import org.bouncycastle.asn1.x509.KeyUsage; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.cert.CertIOException; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMException; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder; +import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder; +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.ui.login.CertificateDialog; +import org.jivesoftware.spark.ui.login.MutualAuthenticationSettingsPanel; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; + +/** + * This class is used for creating certificate signing request and self-signed certificates. + */ +public class IdentityController extends CertManager { + private static String commonName, organizationUnit, organization, city, country; + + public final static File IDENTITY = new File(SECURITY_DIRECTORY, "identitystore"); + public static File CSR_FILE = new File(SECURITY_DIRECTORY, commonName + "_csr.pem"); + public static File KEY_FILE = new File(SECURITY_DIRECTORY, commonName + "_key.pem"); + public static File CERT_FILE = new File(SECURITY_DIRECTORY, commonName + "_cert.pem"); + + private KeyStore idStore; + + private final static String[] COLUMN_NAMES = {"Identity certificates"}; + private final static int NUMBER_OF_COLUMNS = COLUMN_NAMES.length; + KeyPair keyPair; + + public IdentityController(LocalPreferences localPreferences) { + Security.addProvider(new BouncyCastleProvider()); + loadKeyStores(); + Objects.requireNonNull(localPreferences); + this.localPreferences = localPreferences; + createTableModel(); + } + + @Override + public void loadKeyStores() { + idStore = openKeyStore(IDENTITY); + blackListStore = openKeyStore(BLACKLIST); + fillTableListWithKeyStoreContent(idStore, null); + } + + @Override + public void overWriteKeyStores() { + saveKeyStore(idStore, IDENTITY); + } + + public KeyManagerFactory initKeyManagerFactory() + throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException, NoSuchProviderException { + loadKeyStores(); + KeyManagerFactory keyManFact = KeyManagerFactory.getInstance("SunX509", "SunJSSE"); + keyManFact.init(idStore, IdentityController.passwd); + return keyManFact; + } + + public void setUpData(String commonName, String organizationUnit, String organization, String country, + String city) { + IdentityController.commonName = commonName; + IdentityController.organizationUnit = organizationUnit; + IdentityController.organization = organization; + IdentityController.country = country; + IdentityController.city = city; + CSR_FILE = new File(SECURITY_DIRECTORY, commonName + "_csr.pem"); + KEY_FILE = new File(SECURITY_DIRECTORY, commonName + "_key.pem"); + CERT_FILE = new File(SECURITY_DIRECTORY, commonName + "_cert.pem"); + } + + @Override + public void createTableModel() { + tableModel = new DefaultTableModel(); + tableModel.setColumnIdentifiers(COLUMN_NAMES); + Object[] certEntry = new Object[NUMBER_OF_COLUMNS]; + for (CertificateModel cert : allCertificates) { + if (cert.getSubjectCommonName() != null) { + certEntry[0] = cert.getSubjectCommonName(); + } else { + certEntry[0] = cert.getSubject(); + } + tableModel.addRow(certEntry); + } + } + + @Override + public void showCertificate() { + new CertificateDialog(localPreferences, + allCertificates.get(MutualAuthenticationSettingsPanel.getIdTable().getSelectedRow()), this, + CertificateDialogReason.SHOW_ID_CERTIFICATE); + } + + /** + * Creates Certificate Signing Request. + */ + public PKCS10CertificationRequest createCSR(KeyPair keyPair) throws OperatorCreationException { + X500Principal principal = new X500Principal(createX500NameString()); + PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder(principal, keyPair.getPublic()); + JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder("SHA256withRSA"); + ContentSigner signer = csBuilder.build(keyPair.getPrivate()); + return p10Builder.build(signer); + } + + /** + * Create string representation of the X500Principal name with fields as Common Name, Organization Unit, Organization, Location and Country. + * + * @return String X500Name + */ + private String createX500NameString() { + if (commonName == null || commonName.isEmpty()) { + throw new IllegalArgumentException("Common Name cannot be empty"); + } + String sb = "CN=" + commonName; + if (organizationUnit != null && !organizationUnit.isEmpty()) { + sb += ", OU=" + organizationUnit; + } + if (organization != null && !organization.isEmpty()) { + sb += ", O=" + organization; + } + if (city != null && !city.isEmpty()) { + sb += ", L=" + city; + } + if (country != null && !country.isEmpty()) { + sb += ", C=" + country; + } + return sb; + } + + /** + * This method adds certificate from file (*.pem) to Identity Store. + */ + @Override + public void deleteEntry(String alias) throws KeyStoreException { + int dialogButton = JOptionPane.YES_NO_OPTION; + int dialogValue = JOptionPane.showConfirmDialog(null, Res.getString("dialog.certificate.sure.to.delete"), null, dialogButton); + if (dialogValue == JOptionPane.YES_OPTION) { + idStore.deleteEntry(alias); + JOptionPane.showMessageDialog(null, Res.getString("dialog.certificate.has.been.deleted")); + CertificateModel model = null; + for (CertificateModel certModel : allCertificates) { + if (certModel.getAlias().equals(alias)) { + model = certModel; + break; + } + } + allCertificates.remove(model); + } + refreshCertTable(); + } + + @Override + public void addOrRemoveFromExceptionList(boolean checked) { + } + + @Override + public boolean isOnExceptionList(CertificateModel cert) { + return false; + } + + /** + * Refresh the certificate table to make visible changes in its model + */ + @Override + public void refreshCertTable() { + createTableModel(); + SwingUtilities.invokeLater(() -> { + MutualAuthenticationSettingsPanel.getIdTable().setModel(tableModel); + tableModel.fireTableDataChanged(); + }); + } + + /** + * This method extracts a key and certificate from the file (*.pem) and adds it to the Identity Store. + * + * @param file with a certificate that is added and private key entry + */ + @Override + public void addEntryFileToKeyStore(File file) + throws IOException, CertificateException, InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, InvalidNameException { + + byte[] certAndKey = Files.readAllBytes(file.toPath()); + X509Certificate addedCert = parseCertificate(certAndKey); + PrivateKey key = parseKey(certAndKey); + addEntryToKeyStore(addedCert, key); + } + + public PrivateKey parseKey(byte[] certAndKey) throws PEMException, InvalidKeySpecException, NoSuchAlgorithmException { + String beginDelimiter = PemHelper.knowDelimeter(certAndKey, PemHelper.typeOfDelimeter.KEY_BEGIN); + String endDelimiter = PemHelper.knowDelimeter(certAndKey, PemHelper.typeOfDelimeter.KEY_END); + byte[] keyBytes = PemHelper.parseDERFromPEM(certAndKey, beginDelimiter, endDelimiter); + return PemHelper.generatePrivateKeyFromDER(keyBytes); + } + + public X509Certificate parseCertificate(byte[] certAndKey) throws PEMException, CertificateException { + String beginDelimiter = PemHelper.knowDelimeter(certAndKey, PemHelper.typeOfDelimeter.CERT_BEGIN); + String endDelimiter = PemHelper.knowDelimeter(certAndKey, PemHelper.typeOfDelimeter.CERT_END); + byte[] certBytes = PemHelper.parseDERFromPEM(certAndKey, beginDelimiter, endDelimiter); + return PemHelper.generateCertificateFromDER(certBytes); + } + + public void addEntryToKeyStore(X509Certificate addedCert, PrivateKey key) throws HeadlessException, InvalidNameException, KeyStoreException { + CertificateModel certModel = new CertificateModel(addedCert); + CertificateDialog certDialog = null; + if (!checkForSameCertificate(addedCert)) { + certDialog = showCertificate(certModel, CertificateDialogReason.ADD_ID_CERTIFICATE); + } + // Adds certificate to keystore if user approves + if (certDialog != null && certDialog.isAddCert()) { + String alias = useCommonNameAsAlias(addedCert); + X509Certificate[] chain = {addedCert}; + idStore.setKeyEntry(alias, key, passwd, chain); + allCertificates.add(new CertificateModel(addedCert)); + refreshCertTable(); + JOptionPane.showMessageDialog(null, Res.getString("dialog.certificate.has.been.added.to.identity.store")); + } + } + + @Override + protected boolean checkForSameAlias(String alias) throws HeadlessException, KeyStoreException { + return idStore.containsAlias(alias); + } + + public KeyPair createKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException { + KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC"); + generator.initialize(2048, new SecureRandom()); + keyPair = generator.generateKeyPair(); + return keyPair; + } + + public X509Certificate createSelfSignedCertificate(KeyPair keyPair) throws CertIOException, OperatorCreationException, CertificateException { + + long serial = System.currentTimeMillis(); + SubjectPublicKeyInfo keyInfo = SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded()); + X500Name name = new X500Name(createX500NameString()); + X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(name, + BigInteger.valueOf(serial), + new Date(System.currentTimeMillis() - 1000000000), + new Date(System.currentTimeMillis() + 1000000000), + name, + keyInfo + ); + certBuilder.addExtension(Extension.basicConstraints, true, new BasicConstraints(true)); + certBuilder.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment)); + certBuilder.addExtension(Extension.extendedKeyUsage, true, new ExtendedKeyUsage(KeyPurposeId.id_kp_clientAuth)); + + JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder("SHA256withRSA"); + ContentSigner signer = csBuilder.build(keyPair.getPrivate()); + X509CertificateHolder certHolder = certBuilder.build(signer); + + return new JcaX509CertificateConverter().getCertificate(certHolder); + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/certificates/OIDTranslator.java b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/OIDTranslator.java new file mode 100644 index 000000000..b6ca69103 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/OIDTranslator.java @@ -0,0 +1,115 @@ +package org.jivesoftware.sparkimpl.certificates; + +import java.util.HashMap; +import java.util.Map; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.util.log.Log; + +public final class OIDTranslator { + + private static final Map OIDtoDescriptionMap = new HashMap<>(); + static { + OIDtoDescriptionMap.put("2.5.29.1", Res.getString("2.5.29.1")); + OIDtoDescriptionMap.put("2.5.29.2", Res.getString("2.5.29.2")); + OIDtoDescriptionMap.put("2.5.29.3", Res.getString("2.5.29.3")); + OIDtoDescriptionMap.put("2.5.29.4", Res.getString("2.5.29.4")); + OIDtoDescriptionMap.put("2.5.29.5", Res.getString("2.5.29.5")); + OIDtoDescriptionMap.put("2.5.29.6", Res.getString("2.5.29.6")); + OIDtoDescriptionMap.put("2.5.29.7", Res.getString("2.5.29.7")); + OIDtoDescriptionMap.put("2.5.29.8", Res.getString("2.5.29.8")); + OIDtoDescriptionMap.put("2.5.29.9", Res.getString("2.5.29.9")); + OIDtoDescriptionMap.put("2.5.29.10", Res.getString("2.5.29.10")); + OIDtoDescriptionMap.put("2.5.29.11", Res.getString("2.5.29.11")); + OIDtoDescriptionMap.put("2.5.29.12", Res.getString("2.5.29.12")); + OIDtoDescriptionMap.put("2.5.29.13", Res.getString("2.5.29.13")); + OIDtoDescriptionMap.put("2.5.29.14", Res.getString("2.5.29.14")); + OIDtoDescriptionMap.put("2.5.29.15", Res.getString("2.5.29.15")); + OIDtoDescriptionMap.put("2.5.29.16", Res.getString("2.5.29.16")); + OIDtoDescriptionMap.put("2.5.29.17", Res.getString("2.5.29.17")); + OIDtoDescriptionMap.put("2.5.29.18", Res.getString("2.5.29.18")); + OIDtoDescriptionMap.put("2.5.29.19", Res.getString("2.5.29.19")); + OIDtoDescriptionMap.put("2.5.29.20", Res.getString("2.5.29.20")); + OIDtoDescriptionMap.put("2.5.29.21", Res.getString("2.5.29.21")); + OIDtoDescriptionMap.put("2.5.29.22", Res.getString("2.5.29.22")); + OIDtoDescriptionMap.put("2.5.29.23", Res.getString("2.5.29.23")); + OIDtoDescriptionMap.put("2.5.29.24", Res.getString("2.5.29.24")); + OIDtoDescriptionMap.put("2.5.29.25", Res.getString("2.5.29.25")); + OIDtoDescriptionMap.put("2.5.29.26", Res.getString("2.5.29.26")); + OIDtoDescriptionMap.put("2.5.29.27", Res.getString("2.5.29.27")); + OIDtoDescriptionMap.put("2.5.29.28", Res.getString("2.5.29.28")); + OIDtoDescriptionMap.put("2.5.29.29", Res.getString("2.5.29.29")); + OIDtoDescriptionMap.put("2.5.29.30", Res.getString("2.5.29.30")); + OIDtoDescriptionMap.put("2.5.29.31", Res.getString("2.5.29.31")); + OIDtoDescriptionMap.put("2.5.29.32", Res.getString("2.5.29.32")); + OIDtoDescriptionMap.put("2.5.29.33", Res.getString("2.5.29.33")); + OIDtoDescriptionMap.put("2.5.29.34", Res.getString("2.5.29.34")); + OIDtoDescriptionMap.put("2.5.29.35", Res.getString("2.5.29.35")); + OIDtoDescriptionMap.put("2.5.29.36", Res.getString("2.5.29.36")); + OIDtoDescriptionMap.put("2.5.29.37", Res.getString("2.5.29.37")); + OIDtoDescriptionMap.put("2.5.29.38", Res.getString("2.5.29.38")); + OIDtoDescriptionMap.put("2.5.29.39", Res.getString("2.5.29.39")); + OIDtoDescriptionMap.put("2.5.29.40", Res.getString("2.5.29.40")); + OIDtoDescriptionMap.put("2.5.29.41", Res.getString("2.5.29.41")); + OIDtoDescriptionMap.put("2.5.29.42", Res.getString("2.5.29.42")); + OIDtoDescriptionMap.put("2.5.29.43", Res.getString("2.5.29.43")); + OIDtoDescriptionMap.put("2.5.29.44", Res.getString("2.5.29.44")); + OIDtoDescriptionMap.put("2.5.29.45", Res.getString("2.5.29.45")); + OIDtoDescriptionMap.put("2.5.29.46", Res.getString("2.5.29.46")); + OIDtoDescriptionMap.put("2.5.29.47", Res.getString("2.5.29.47")); + OIDtoDescriptionMap.put("2.5.29.48", Res.getString("2.5.29.48")); + OIDtoDescriptionMap.put("2.5.29.49", Res.getString("2.5.29.49")); + OIDtoDescriptionMap.put("2.5.29.50", Res.getString("2.5.29.50")); + OIDtoDescriptionMap.put("2.5.29.51", Res.getString("2.5.29.51")); + OIDtoDescriptionMap.put("2.5.29.52", Res.getString("2.5.29.52")); + OIDtoDescriptionMap.put("2.5.29.53", Res.getString("2.5.29.53")); + OIDtoDescriptionMap.put("2.5.29.54", Res.getString("2.5.29.54")); + OIDtoDescriptionMap.put("2.5.29.55", Res.getString("2.5.29.55")); + OIDtoDescriptionMap.put("2.5.29.56", Res.getString("2.5.29.56")); + OIDtoDescriptionMap.put("2.5.29.57", Res.getString("2.5.29.57")); + OIDtoDescriptionMap.put("2.5.29.58", Res.getString("2.5.29.58")); + OIDtoDescriptionMap.put("2.5.29.59", Res.getString("2.5.29.59")); + OIDtoDescriptionMap.put("2.5.29.60", Res.getString("2.5.29.60")); + OIDtoDescriptionMap.put("2.5.29.61", Res.getString("2.5.29.61")); + OIDtoDescriptionMap.put("2.5.29.62", Res.getString("2.5.29.62")); + OIDtoDescriptionMap.put("2.5.29.63", Res.getString("2.5.29.63")); + OIDtoDescriptionMap.put("2.5.29.64", Res.getString("2.5.29.64")); + OIDtoDescriptionMap.put("2.5.29.65", Res.getString("2.5.29.65")); + OIDtoDescriptionMap.put("2.5.29.66", Res.getString("2.5.29.66")); + OIDtoDescriptionMap.put("2.5.29.67", Res.getString("2.5.29.67")); + OIDtoDescriptionMap.put("2.5.29.68", Res.getString("2.5.29.68")); + OIDtoDescriptionMap.put("2.5.29.69", Res.getString("2.5.29.69")); + + OIDtoDescriptionMap.put("2.16.840.1.113730.1.1", Res.getString("2.16.840.1.113730.1.1")); + OIDtoDescriptionMap.put("1.3.6.1.4.1.311.20.2", Res.getString("1.3.6.1.4.1.311.20.2")); + OIDtoDescriptionMap.put("1.3.6.1.4.1.311.21.1", Res.getString("1.3.6.1.4.1.311.21.1")); + OIDtoDescriptionMap.put("1.3.6.1.5.5.7.3.2", Res.getString("1.3.6.1.5.5.7.3.2")); + OIDtoDescriptionMap.put("1.2.840.113533.7.65.0", Res.getString("1.2.840.113533.7.65.0")); + OIDtoDescriptionMap.put("1.3.6.1.5.5.7.1.1", Res.getString("1.3.6.1.5.5.7.1.1")); + OIDtoDescriptionMap.put("1.3.6.1.5.5.7.1.12", Res.getString("1.3.6.1.5.5.7.1.12")); + OIDtoDescriptionMap.put("1.3.6.1.5.5.7.3.1", Res.getString("1.3.6.1.5.5.7.3.1")); + OIDtoDescriptionMap.put("1.3.6.1.5.5.7.3.3", Res.getString("1.3.6.1.5.5.7.3.3")); + OIDtoDescriptionMap.put("1.3.6.1.5.5.7.3.4", Res.getString("1.3.6.1.5.5.7.3.4")); + OIDtoDescriptionMap.put("1.3.6.1.5.5.7.3.5", Res.getString("1.3.6.1.5.5.7.3.5")); + OIDtoDescriptionMap.put("1.3.6.1.5.5.7.3.6", Res.getString("1.3.6.1.5.5.7.3.6")); + OIDtoDescriptionMap.put("1.3.6.1.5.5.7.3.7", Res.getString("1.3.6.1.5.5.7.3.7")); + OIDtoDescriptionMap.put("1.3.6.1.5.5.7.3.8", Res.getString("1.3.6.1.5.5.7.3.8")); + OIDtoDescriptionMap.put("1.3.6.1.5.5.7.3.9", Res.getString("1.3.6.1.5.5.7.3.9")); + OIDtoDescriptionMap.put("1.3.6.1.5.5.7.3.10", Res.getString("1.3.6.1.5.5.7.3.10")); + OIDtoDescriptionMap.put("1.3.6.1.5.5.7.3.11", Res.getString("1.3.6.1.5.5.7.3.11")); + OIDtoDescriptionMap.put("1.3.6.1.5.5.7.3.12", Res.getString("1.3.6.1.5.5.7.3.12")); + OIDtoDescriptionMap.put("1.3.6.1.5.5.7.3.13", Res.getString("1.3.6.1.5.5.7.3.13")); + OIDtoDescriptionMap.put("1.3.6.1.4.1.311.10.3.4", Res.getString("1.3.6.1.4.1.311.10.3.4")); + OIDtoDescriptionMap.put("2.23.42.7.0", Res.getString("2.23.42.7.0")); + } + + public static String getDescription(String oid) { + String description = OIDtoDescriptionMap.get(oid); + if (description != null) { + return description; + } else { + Log.warning("Unknown description for Object ID (OID: " + oid + ")"); + return Res.getString("cert.unknown.oid"); + } + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/certificates/PemHelper.java b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/PemHelper.java new file mode 100644 index 000000000..70a6a61e5 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/PemHelper.java @@ -0,0 +1,154 @@ +package org.jivesoftware.sparkimpl.certificates; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.Security; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.DatatypeConverter; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMException; +import org.bouncycastle.openssl.jcajce.JcaPEMWriter; + +public class PemHelper { + + public enum typeOfDelimeter { + KEY_BEGIN, KEY_END, CERT_BEGIN, CERT_END + } + + + //sometimes key some delimeters might be a bit customized like "RSA PRIVATE KEY" vs "PRIVATE KEY" + private static final String[] keyBeginDelimeters = { "-----BEGIN RSA PRIVATE KEY-----", + "-----BEGIN PRIVATE KEY-----", + }; + private static final String[] keyEndDelimeters = { "-----END RSA PRIVATE KEY-----", + "-----END PRIVATE KEY-----" + }; + + private static final String[] certBeginDelimeters = { "-----BEGIN CERTIFICATE-----", + "-----BEGIN X509 CERTIFICATE-----", + "-----BEGIN TRUSTED CERTIFICATE-----" + }; + + private static final String[] certEndDelimeters = { "-----END CERTIFICATE-----", + "-----END X509 CERTIFICATE-----", + "-----END TRUSTED CERTIFICATE-----" + }; + + + protected static byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter) + throws PEMException { + String data = new String(pem); + if(!data.contains(beginDelimiter) || !data.contains(endDelimiter)){ + throw new PEMException("File doesn't contains begin delimeter: " +beginDelimiter + "or end delimeter: " +endDelimiter ); + } + String[] tokens = data.split(beginDelimiter); + tokens = tokens[1].split(endDelimiter); + return DatatypeConverter.parseBase64Binary(tokens[0]); + } + + protected static RSAPrivateKey generatePrivateKeyFromDER(byte[] keyBytes) throws InvalidKeySpecException, NoSuchAlgorithmException { + // here Bouncy Castle provider is important as KeyFactory might not work + Security.addProvider(new BouncyCastleProvider()); + + PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); + KeyFactory factory = KeyFactory.getInstance("RSA"); + + return (RSAPrivateKey)factory.generatePrivate(spec); + } + + /** + * + * @param pem it's byte array representation of pem file + * @param type + * @return + * @throws PEMException + * @throws Exception + */ + protected static String knowDelimeter(byte[] pem, typeOfDelimeter type) throws PEMException { + if(!(type instanceof typeOfDelimeter)){ + throw new IllegalArgumentException(); + } + String header = new String(pem); + String knownDelimeter = null; + String[] deliArray = null; + if(type.equals(typeOfDelimeter.KEY_BEGIN)){ + deliArray = keyBeginDelimeters; + } + if(type.equals(typeOfDelimeter.KEY_END)){ + deliArray = keyEndDelimeters; + } + if(type.equals(typeOfDelimeter.CERT_BEGIN)){ + deliArray = certBeginDelimeters; + } + if(type.equals(typeOfDelimeter.CERT_END)){ + deliArray = certEndDelimeters; + } + for (String delimeter : deliArray) { + if (header.contains(delimeter)) { + knownDelimeter = delimeter; + } + } + if(knownDelimeter == null){ + throw new PEMException("Pem file doesn't include: "+ type.toString() + " kind of delimeter"); + } + return knownDelimeter; + + } + + protected static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException { + CertificateFactory factory = CertificateFactory.getInstance("X.509"); + + return (X509Certificate)factory.generateCertificate(new ByteArrayInputStream(certBytes)); + } + + /** + * Saves object to PEM file + * + * @param object meant to be saved + * @param file to which object should be saved + * @throws FileNotFoundException + * @throws IOException + */ + public static void saveToPemFile(Object object, File file) throws FileNotFoundException, IOException{ + try (JcaPEMWriter pem = new JcaPEMWriter(new OutputStreamWriter(new FileOutputStream(file)))) { + pem.writeObject(object); + } + } + + /** + * This class can be used to write few object into one PEM file. + * @author Paweł Ścibiorski + * + */ + public static class PemBuilder { + private final List buildList = new ArrayList<>(); + + public void add(Object object) { + buildList.add(object); + } + + public void saveToPemFile(File file) throws IOException { + try (JcaPEMWriter pem = new JcaPEMWriter(new OutputStreamWriter(new FileOutputStream(file)))) { + for (Object object : buildList) { + pem.writeObject(object); + } + } + } + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/certificates/SparkExceptionsTrustManager.java b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/SparkExceptionsTrustManager.java new file mode 100644 index 000000000..d0eb3ca84 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/SparkExceptionsTrustManager.java @@ -0,0 +1,157 @@ +package org.jivesoftware.sparkimpl.certificates; + +import java.awt.HeadlessException; +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.*; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import javax.naming.InvalidNameException; +import javax.net.ssl.X509TrustManager; + +import org.jivesoftware.spark.util.log.Log; + +/** + * This TrustManager serves for purpose of accepting certificates from exceptions lists. + * The only check it does is check if certification path can be built. + * It doesn't do any checks against time of expiration or revocation. + * + * @author Pawel Scibiorski + */ +public class SparkExceptionsTrustManager extends GeneralTrustManager implements X509TrustManager { + + KeyStore exceptionsStore, cacertsExceptionsStore; + + public SparkExceptionsTrustManager() { + loadKeyStores(); + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) { + throw new UnsupportedOperationException("This implementation cannot be used to validate client-provided certificate chains."); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + // if end entity certificate is on the exception list then pass checks + try { + if (!isFirstCertExempted(chain)) { + // else exempted certificate can be higher in chain, in this case certificate list have to be build + validatePath(chain); + } + } catch (NoSuchAlgorithmException | KeyStoreException | InvalidAlgorithmParameterException + | CertPathValidatorException | IllegalArgumentException e) { + Log.warning("Cannot build certificate chain", e); + throw new CertificateException("Cannot build certificate chain"); + } + } + + /** + * Validate certificate path. + * As it is exception, no checks against revocation or time validity are done. + * But the path still have to be validated in order to find connection between + * certificate presented by server and root CA in KeyStore + * + * @throws NoSuchAlgorithmException + * @throws KeyStoreException + * @throws InvalidAlgorithmParameterException + * @throws CertPathValidatorException + * @throws CertificateException + * @throws IllegalArgumentException + */ + private void validatePath(X509Certificate[] chain) + throws NoSuchAlgorithmException, KeyStoreException, InvalidAlgorithmParameterException, + CertPathValidatorException, CertificateException,IllegalArgumentException { + + if (SparkTrustManager.isSelfSigned(chain)) { + throw new IllegalArgumentException("Method cannot be used with self-signed certificate."); + } + + // The certificate representing the {@link TrustAnchor} should not be included in the certification path. + // If it does, certain validation (like OCSP) might give unexpected results/fail. SPARK-2188 + final List certificates = Arrays.stream(chain) + .filter( cert -> !SparkTrustManager.isRootCACertificate(cert)) + .collect(Collectors.toList()); + + // Construct a certPath entity that represents the chain that is to be validated. Does not include the trust anchor. + final CertPath certPath = CertificateFactory.getInstance("X.509").generateCertPath(certificates); + + // SPARK-2185: Ensure that what we validate is not empty. + if ( certPath.getCertificates().isEmpty() ) { + throw new CertificateException("Unable to build a certificate path from the provided chain."); + } + + // PKIX algorithm is defined in rfc3280 + CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX"); + + // Selects the target to be validated. This is the end-entity/leaf certificate, typically the first in the chain. + X509CertSelector toBeValidated = new X509CertSelector(); + toBeValidated.setCertificate((X509Certificate) certPath.getCertificates().get(0)); + + // create parameters using trustStore as source of Trust Anchors and using X509CertSelector + PKIXBuilderParameters parameters = new PKIXBuilderParameters(allStore, toBeValidated); + + // no checks against revocation as this is the 'exception' trust manager. + parameters.setRevocationEnabled(false); + + try { + PKIXCertPathValidatorResult validationResult = (PKIXCertPathValidatorResult) certPathValidator + .validate(certPath, parameters); + X509Certificate trustAnchor = validationResult.getTrustAnchor().getTrustedCert(); + if (trustAnchor == null) { + throw new CertificateException("certificate path failed: Trusted CA is NULL"); + } + } catch (CertPathValidatorException e) { + // This exception trust manager ignores the expiration dates + if ( e.getReason() == CertPathValidatorException.BasicReason.EXPIRED) { + Log.debug("Chain validation detected expiry, but this 'exception' trust manager allows this Not failing validation."); + } else if ( e.getReason() == CertPathValidatorException.BasicReason.NOT_YET_VALID) { + Log.debug("Chain validation detected not-yet-valid, but this 'exception' trust manager allows this Not failing validation."); + } else { + throw e; + } + } + } + + /** + * Check if the first certificate in chain is exempted + * + * @param chain contain certificates from server + * @return true if the first certificate is in exceptionsStore + * @throws KeyStoreException + */ + private boolean isFirstCertExempted(X509Certificate[] chain) throws KeyStoreException { + if (isOrderFromSubjectToIssuer(chain)) { + return exceptionsStore.getCertificateAlias(chain[0]) != null; + } else { + return exceptionsStore.getCertificateAlias(chain[chain.length - 1]) != null; + } + } + + /** + * Load KeyStores and add it's content to the allStore + */ + @Override + protected void loadKeyStores() { + exceptionsStore = certControll.openKeyStore(CertificateController.EXCEPTIONS); + cacertsExceptionsStore = certControll.openKeyStore(CertificateController.CACERTS_EXCEPTIONS); + loadAllStore(); + + try { + addKeyStoreContentToAllStore(exceptionsStore); + } catch (HeadlessException | KeyStoreException | InvalidNameException e) { + Log.error("Cannot add exceptionStore content to allStore", e); + } + try { + addKeyStoreContentToAllStore(cacertsExceptionsStore); + } catch (HeadlessException | KeyStoreException | InvalidNameException e) { + Log.error("Cannot add cacertsExceptionsStore to allStore", e); + } + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/certificates/SparkSSLContextCreator.java b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/SparkSSLContextCreator.java new file mode 100644 index 000000000..4defd2799 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/SparkSSLContextCreator.java @@ -0,0 +1,49 @@ +package org.jivesoftware.sparkimpl.certificates; + +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SecureRandom; +import java.security.UnrecoverableKeyException; + +import javax.net.ssl.SSLContext; + +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +public class SparkSSLContextCreator { + + /** + * ClientSide is authentication by + */ + public enum Options { + BOTH, ONLY_CLIENT_SIDE, ONLY_SERVER_SIDE + } + + /** + * Create SSLContext and initialize it + * + * @return initialized SSL context + * @throws KeyManagementException + * @throws NoSuchAlgorithmException + * @throws KeyStoreException + * @throws UnrecoverableKeyException + * @throws NoSuchProviderException + */ + public static SSLContext setUpContext(Options options) + throws KeyManagementException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, NoSuchProviderException { + SSLContext context = SSLContext.getInstance("TLS"); + if (options == Options.ONLY_SERVER_SIDE) { + context.init(null, SparkTrustManager.getTrustManagerList(), new SecureRandom()); + } else if (options == Options.BOTH) { + IdentityController identityController = new IdentityController(SettingsManager.getLocalPreferences()); + context.init(identityController.initKeyManagerFactory().getKeyManagers(), SparkTrustManager.getTrustManagerList(), new SecureRandom()); + + } else if (options == Options.ONLY_CLIENT_SIDE) { + IdentityController identityController = new IdentityController(SettingsManager.getLocalPreferences()); + context.init(identityController.initKeyManagerFactory().getKeyManagers(), null, new SecureRandom()); + + } + return context; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/certificates/SparkSSLSocketFactory.java b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/SparkSSLSocketFactory.java new file mode 100644 index 000000000..e6532fcf7 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/SparkSSLSocketFactory.java @@ -0,0 +1,92 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.certificates; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.UnrecoverableKeyException; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; + +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.certificates.SparkSSLContextCreator.Options; + +/** + * An SSL socket factory that will let any certifacte past, even if it's expired or not singed by a root CA. + */ +public class SparkSSLSocketFactory extends SSLSocketFactory { + + private SSLSocketFactory factory; + + public SparkSSLSocketFactory(Options options) { + + SSLContext sslcontent; + try { + sslcontent = SparkSSLContextCreator.setUpContext(options); + factory = sslcontent.getSocketFactory(); + } catch (KeyManagementException | UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException + | NoSuchProviderException e) { + Log.error("Couldn't create SSLSocketFactory", e); + } + + } + + @Override + public Socket createSocket(Socket socket, String s, int i, boolean flag) throws IOException { + return factory.createSocket(socket, s, i, flag); + } + + @Override + public Socket createSocket(InetAddress inaddr, int i, InetAddress inaddr2, int j) throws IOException { + return factory.createSocket(inaddr, i, inaddr2, j); + } + + @Override + public Socket createSocket(InetAddress inaddr, int i) throws IOException { + return factory.createSocket(inaddr, i); + } + + @Override + public Socket createSocket(String s, int i, InetAddress inaddr, int j) throws IOException { + return factory.createSocket(s, i, inaddr, j); + } + + @Override + public Socket createSocket(String s, int i) throws IOException { + return factory.createSocket(s, i); + } + + @Override + public Socket createSocket() throws IOException { + return factory.createSocket(); + } + + @Override + public String[] getDefaultCipherSuites() { + return factory.getSupportedCipherSuites(); + } + + @Override + public String[] getSupportedCipherSuites() { + return factory.getSupportedCipherSuites(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/certificates/SparkTrustManager.java b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/SparkTrustManager.java new file mode 100644 index 000000000..70398dac8 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/SparkTrustManager.java @@ -0,0 +1,463 @@ +package org.jivesoftware.sparkimpl.certificates; + +import java.awt.HeadlessException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumSet; +import java.util.List; +import java.util.stream.Collectors; + +import javax.naming.InvalidNameException; +import javax.net.ssl.X509TrustManager; + +import org.apache.commons.lang3.ArrayUtils; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.x509.CRLDistPoint; +import org.bouncycastle.asn1.x509.DistributionPoint; +import org.bouncycastle.asn1.x509.DistributionPointName; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.GeneralNames; +import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; +import org.jivesoftware.spark.util.log.Log; + +/** + * This trust manager wrap around SparkExceptionsTrustManager. + * In case when SparkExceptionsTrustManager fail then this + * TrustManager will provide certificates from TRUSTED KeyStore which are checked against data validity, revocation, + * acceptance of self-signed certificates and basic constraints. + * + * @author Pawel Scibiorsk + */ +public class SparkTrustManager extends GeneralTrustManager implements X509TrustManager { + + static X509Certificate[] lastFailedChain; + + private final boolean checkCRL; + private final boolean checkOCSP; + private final boolean acceptExpired; + private final boolean acceptNotValidYet; + private final boolean acceptRevoked; + private final boolean acceptSelfSigned; + private final boolean allowSoftFail; + + private CertStore crlStore; + private final X509TrustManager exceptionsTrustManager; + private KeyStore trustStore; + private KeyStore displayedCaCerts; + private final Collection crlCollection = new ArrayList<>(); + + public SparkTrustManager() { + exceptionsTrustManager = new SparkExceptionsTrustManager(); + checkCRL = localPref.isCheckCRL(); + checkOCSP = localPref.isCheckOCSP(); + acceptExpired = localPref.isAcceptExpired(); + acceptNotValidYet = localPref.isAcceptNotValidYet(); + acceptRevoked = localPref.isAcceptRevoked(); + acceptSelfSigned = localPref.isAcceptSelfSigned(); + allowSoftFail = localPref.isAllowSoftFail(); + + loadKeyStores(); + } + + public static X509TrustManager[] getTrustManagerList() { + return new X509TrustManager[] { new SparkTrustManager() }; + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) { + throw new UnsupportedOperationException("This implementation cannot be used to validate client-provided certificate chains."); + } + + public static X509Certificate[] getLastFailedChain() + { + return lastFailedChain; + } + + public void addChain( X509Certificate[] chain ) { + certControll.addChain(chain); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + try { + doTheChecks(chain, authType); + lastFailedChain = null; + } catch (CertPathValidatorException e) { + lastFailedChain = chain; + throw new CertificateException(e); + } + } + + /** + * Do chain validity checks + * @param chain with certificates from server + * @param authType "RSA" etc. + * @throws CertificateException + * @throws CertPathValidatorException + */ + private void doTheChecks(X509Certificate[] chain, String authType) throws CertificateException, CertPathValidatorException { + try { + // first check if certificate is accepted as a certificate from exceptions list, exceptionsTrustManager + // will make use of chain provided by exceptions KeyStore + exceptionsTrustManager.checkServerTrusted(chain, authType); + } catch (CertificateException ex) { + // in case when certificate isn't on exceptions list then make use of this Trust Manager + // validate chain by date (expired/not valid yet) + checkDateValidity(chain); + + // check if certificate isn't self signed, self signed certificate still have to be in TrustStore to be + // accepted + if (!isSelfSigned(chain)) { + // validate certificate path + try { + validatePath(chain); + } catch (NoSuchAlgorithmException | KeyStoreException | InvalidAlgorithmParameterException | CertPathValidatorException e) { + Log.error("Validating path failed", e); + throw new CertPathValidatorException("Certificate path validation failed", e); + } + } else if (isSelfSigned(chain) && !acceptSelfSigned) { + // Self Signed certificate while it isn't accepted + throw new CertificateException("Self Signed certificate"); + } else if (isSelfSigned(chain) && acceptSelfSigned) { + // check if certificate is in Keystore and check CRL, but do not validate path as certificate is Self + // Signed important reminder: hostname validation must be also turned off to accept self signed + // certificate + if (!ArrayUtils.contains(getAcceptedIssuers(), chain[0])) { + throw new CertPathValidatorException("Certificate not in the TrustStore"); + } + try { + loadCRL(chain); + for (X509CRL crl : crlCollection) { + if (crl.isRevoked(chain[0])) { + throw new CertificateException("Certificate is revoked"); + } + } + } catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException | CRLException | IOException e) { + Log.warning("Couldn't load CRL"); + } + } else { + throw new CertificateException("Certificate chain cannot be trusted"); + } + } + } + + /** + * Return true if the certificate chain contain only one Self Signed certificate + */ + public static boolean isSelfSigned(X509Certificate[] chain) { + return chain[0].getIssuerX500Principal().getName().equals(chain[0].getSubjectX500Principal().getName()) + && chain.length == 1; + } + + /** + * Returns true if a certificate is a 'root' certificate, by verifying that its issuer matches its subject, and the + * subject of the certificate is a CA (by checking the Basic Constraints). + * + * @param cert The certificate to check + * @return 'true' if the certificate is a root certificate, otherwise false. + */ + public static boolean isRootCACertificate( final X509Certificate cert ) { + return cert.getIssuerX500Principal().getName().equals(cert.getSubjectX500Principal().getName()) && cert.getBasicConstraints() > -1; + } + + /** + * Verifies if Spark's trust stores recognize the issuer of at least one of the certificates in the chain. + * + * @param chain The chain to verify + * @return false if none of the issuers are present in any of the trust stores of Spark. + */ + public boolean containsTrustAnchorFor(X509Certificate[] chain) { + final Collection allAcceptedIssuers = Arrays.stream(getAcceptedIssuers()) + .map(x509Certificate -> x509Certificate.getSubjectDN().getName()) + .collect(Collectors.toSet()); + return Arrays.stream(chain).anyMatch( cert -> allAcceptedIssuers.contains( cert.getIssuerDN().getName()) ); + } + + /** + * Validate certificate path + * + * Note that the provided chain cannot be a self-signed certificate. This method assumes a CA-signed chain is + * provided. + * + * @throws NoSuchAlgorithmException + * @throws KeyStoreException + * @throws InvalidAlgorithmParameterException + * @throws CertPathValidatorException + * @throws CertificateException + */ + private void validatePath(X509Certificate[] chain) + throws NoSuchAlgorithmException, KeyStoreException, InvalidAlgorithmParameterException, + CertPathValidatorException, CertificateException + { + if (isSelfSigned(chain)) { + throw new IllegalArgumentException("Method cannot be used with self-signed certificate."); + } + + // The certificate representing the {@link TrustAnchor TrustAnchor} should not be included in the certification + // path. If it does, certain validation (like OCSP) might give unexpected results/fail. SPARK-2188 + final List certificates = Arrays.stream(chain) + .filter( cert -> !isRootCACertificate(cert)) + .collect(Collectors.toList()); + + // Construct a certPath entity that represents the chain that is to be validated. Does not include the trust anchor. + final CertPath certPath = CertificateFactory.getInstance("X.509").generateCertPath(certificates); + + // SPARK-2185: Ensure that what we validate is not empty. + if ( certPath.getCertificates().isEmpty() ) { + throw new CertificateException("Unable to build a certificate path from the provided chain."); + } + + // PKIX algorithm is defined in rfc3280 + CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX"); + CertPathBuilder certPathBuilder = CertPathBuilder.getInstance("PKIX"); + + // Selects the target to be validated. This is the end-entity/leaf certificate, typically the first in the chain. + X509CertSelector toBeValidated = new X509CertSelector(); + toBeValidated.setCertificate((X509Certificate) certPath.getCertificates().get(0)); + + // create parameters using trustStore as source of Trust Anchors and using X509CertSelector + PKIXBuilderParameters parameters = new PKIXBuilderParameters(allStore, toBeValidated); + + // will use PKIXRevocationChecker (or nothing if revocation mechanisms are + // disabled) instead of the default revocation checker + parameters.setRevocationEnabled(false); + + // if revoked certificates aren't accepted, but no revocation checks then only + // certificates from blacklist will be rejected + if (!acceptRevoked) { + // OCSP checking is done according to Java PKI Programmer's Guide, PKIXRevocationChecker was added in Java 8: + // https://docs.oracle.com/javase/8/docs/technotes/guides/security/certpath/CertPathProgGuide.html#PKIXRevocationChecker + PKIXRevocationChecker checker = (PKIXRevocationChecker) certPathBuilder.getRevocationChecker(); + + EnumSet checkerOptions = EnumSet.noneOf(PKIXRevocationChecker.Option.class); + // if soft fail isn't enabled then OCSP or CRL must pass validation, in case + // when any of them cannot be validated verification will fail, if soft fail + // is enabled then in case of network issues revocation checking is omitted + if (allowSoftFail) { + checkerOptions.add(PKIXRevocationChecker.Option.SOFT_FAIL); + } + // check OCSP, CRL serve as backup + if (checkOCSP && checkCRL) { + checker.setOptions(checkerOptions); + parameters.addCertPathChecker(checker); + } else if (!checkOCSP && checkCRL) { + // check only CRL, if CRL fail then there is no fallback to OCSP + checkerOptions.add(PKIXRevocationChecker.Option.PREFER_CRLS); + checkerOptions.add(PKIXRevocationChecker.Option.NO_FALLBACK); + checker.setOptions(checkerOptions); + parameters.addCertPathChecker(checker); + } + } + + try { + PKIXCertPathValidatorResult validationResult = (PKIXCertPathValidatorResult) certPathValidator + .validate(certPath, parameters); + X509Certificate trustAnchor = validationResult.getTrustAnchor().getTrustedCert(); + if (trustAnchor == null) { + throw new CertificateException("certificate path failed: Trusted CA is NULL"); + } + checkBasicConstraints(certPath, trustAnchor); + } catch (CertificateRevokedException e) { + Log.warning("Certificate was revoked", e); + for (Certificate c : certPath.getCertificates()) { + X509Certificate cert = (X509Certificate) c; + for (X509CRL crl : crlCollection) { + if (crl.isRevoked(cert)) { + try { + addToBlackList(cert); + } catch (HeadlessException | InvalidNameException e1) { + Log.error("Couldn't move to the blacklist", e1); + } + break; + } + } + } + throw new CertificateException("Certificate was revoked"); + } catch (CertPathValidatorException e) { + String no_OCSP_Responder_error = "Certificate does not specify OCSP responder"; + // Spark can be configured to disregard some of the issues that can pop up through validation. + if ( e.getReason() == CertPathValidatorException.BasicReason.EXPIRED && acceptExpired ) { + Log.debug("Chain validation detected expiry, but Spark is configured to allow this. Not failing validation."); + } else if ( e.getReason() == CertPathValidatorException.BasicReason.NOT_YET_VALID && acceptNotValidYet ) { + Log.debug("Chain validation detected not-yet-valid, but Spark is configured to allow this. Not failing validation."); + } else if (e.getReason() == CertPathValidatorException.BasicReason.UNSPECIFIED && e.getMessage().equals(no_OCSP_Responder_error)) { + Log.debug(no_OCSP_Responder_error); + } else { + // When Spark is not configured to ignore the validation issue, rethrow the original exception. + throw e; + } + } + } + + /** + * check time date validity of certificates + * + * @throws CertificateException + */ + private void checkDateValidity(X509Certificate[] chain) throws CertificateException { + for (X509Certificate cert : chain) { + // expiration check + try { + cert.checkValidity(); + } catch (CertificateExpiredException e) { + Log.warning("Certificate is expired " + cert.getSubjectX500Principal().getName(), e); + if (!acceptExpired) { + throw new CertificateException("Certificate is expired"); + } + } catch (CertificateNotYetValidException e) { + Log.warning("Certificate is not valid yet " + cert.getSubjectX500Principal().getName(), e); + if (!acceptNotValidYet) { + throw new CertificateException("Certificate is not valid yet"); + } + } + } + } + + /** + * Checks the validity of the BasicConstraints extension of each certificate in the chain. + * + * Each certificate is assumed to have a BasicConstraints extension, with the exception of the leaf (end-entity) + * certificate, which _can_ have a certificate. + * + * All non-leaf certificates must have the cA field set to 'true'. + * + * The pathLen is valid: it defines the maximum amount of intermediate certificates between the CA and the leaf + * certificate. The leaf certificate itself is not included in the count (eg: a value of 'one' would allow for a + * chain length of three: the leaf, one intermediate, and the root (where the value of 'one' is defined). + * + * This method assumes that the provided chain is in order, where the first chain is the end-entity / leaf certificate. + * + * The trust anchor / root CA should not be part of the certPath chain. + * + * @param chain The certificate chain, possibly incomplete. + * @param trustAnchor the root CA certificate. + * @throws CertificateException When the BasicConstraint verification fails. + */ + private void checkBasicConstraints(CertPath chain, X509Certificate trustAnchor) throws CertificateException { + // Intentionally skipping over the first certificate, which is the end-entity certificate. + for (int i = 1; i pathLenConstraint) { + throw new CertificateException("Certificate number " + i + " in the chain failed the BasicConstraints check: " + + (pathLenConstraint == -1 ? "CA flag not set" : "pathLenConstraint to small (was: " +pathLenConstraint+ " needed:" + certsSeparatingThisCertFromEndEntity+")")); + } + } + + // Explicitly check the trustAnchor (as it should not be in the chain) + final int pathLenConstraint = trustAnchor.getBasicConstraints(); + final int certsSeparatingThisCertFromEndEntity = chain.getCertificates().size() - 1; + if (certsSeparatingThisCertFromEndEntity > pathLenConstraint) { + throw new CertificateException("Trust anchor of the chain failed the BasicConstraints check: " + + (pathLenConstraint == -1 ? "CA flag not set" : "pathLenConstraint to small (was: " + pathLenConstraint + " needed:" + certsSeparatingThisCertFromEndEntity + ")")); + } + } + + /** + * loads trust stores and potentially (depending on settings) blacklist + */ + @Override + protected void loadKeyStores() { + certControll.loadKeyStores(); + trustStore = certControll.openKeyStore(CertificateController.TRUSTED); + displayedCaCerts = certControll.openCacertsKeyStore(); + + loadAllStore(); + + try { + addKeyStoreContentToAllStore(trustStore); + } catch (HeadlessException | KeyStoreException | InvalidNameException e) { + Log.error("Cannot add trustStore content to allStore", e); + } + try { + addKeyStoreContentToAllStore(displayedCaCerts); + } catch (HeadlessException | KeyStoreException | InvalidNameException e) { + Log.error("Cannot add displayedCaCerts to the allStore", e); + } + } + + + public Collection loadCRL(X509Certificate[] chain) throws IOException, InvalidAlgorithmParameterException, + NoSuchAlgorithmException, CRLException { + + // for each certificate in chain + for (X509Certificate cert : chain) { + if (cert.getExtensionValue(Extension.cRLDistributionPoints.getId()) != null) { + ASN1Primitive primitive = JcaX509ExtensionUtils + .parseExtensionValue(cert.getExtensionValue(Extension.cRLDistributionPoints.getId())); + // extract distribution point extension + CRLDistPoint distPoint = CRLDistPoint.getInstance(primitive); + DistributionPoint[] dp = distPoint.getDistributionPoints(); + // each distribution point extension can hold number of distribution points + for (DistributionPoint d : dp) { + DistributionPointName dpName = d.getDistributionPoint(); + // Look for URIs in fullName + if (dpName != null && dpName.getType() == DistributionPointName.FULL_NAME) { + GeneralName[] genNames = GeneralNames.getInstance(dpName.getName()).getNames(); + // Look for an URI + for (GeneralName genName : genNames) { + // extract url + URL url = new URL(genName.getName().toString()); + try { + // download from Internet to the collection + crlCollection.add(downloadCRL(url)); + } catch (CertificateException | CRLException e) { + throw new CRLException("Couldn't download CRL"); + } + } + } + } + } else { + Log.warning("Certificate " + cert.getSubjectX500Principal().getName() + " have no CRLs"); + } + // parameters for cert store is collection type, using collection with crl create parameters + CollectionCertStoreParameters params = new CollectionCertStoreParameters(crlCollection); + // this parameters are next used for creation of certificate store with crls + crlStore = CertStore.getInstance("Collection", params); + } + return crlCollection; + } + + /** + * Move certificate to the blacklist of the revoked certificates. + * + * @param cert certificate which is meant to move into blacklist + * @throws KeyStoreException + * @throws InvalidNameException + * @throws HeadlessException + */ + private void addToBlackList(X509Certificate cert) throws KeyStoreException, + HeadlessException, InvalidNameException { + certControll.addCertificateToBlackList(cert); + } + + /** + * Downloads a CRL from given URL + * + * @param url the web address with given CRL + * @throws IOException + * @throws CertificateException + * @throws CRLException + */ + private X509CRL downloadCRL(URL url) throws IOException, CertificateException, CRLException { + try (InputStream crlStream = url.openStream()) { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + return (X509CRL) cf.generateCRL(crlStream); + } + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/certificates/UnrecognizedServerCertificatePanel.java b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/UnrecognizedServerCertificatePanel.java new file mode 100644 index 000000000..0b36646f7 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/certificates/UnrecognizedServerCertificatePanel.java @@ -0,0 +1,62 @@ +package org.jivesoftware.sparkimpl.certificates; + +import org.jivesoftware.resource.Res; + +import javax.swing.*; +import java.awt.*; +import java.util.Objects; + +import static java.awt.GridBagConstraints.LINE_END; +import static java.awt.GridBagConstraints.LINE_START; + +public class UnrecognizedServerCertificatePanel extends JPanel { + private final static Insets DEFAULT_INSETS = new Insets(5, 5, 5, 5); + + private final CertificateModel certModel; + + public UnrecognizedServerCertificatePanel( CertificateModel certModel) { + Objects.requireNonNull(certModel); + this.certModel = certModel; + + setLayout(new GridBagLayout()); + add( new JLabel(Res.getString("dialog.certificate.unrecognized.server.certificate")), new GridBagConstraints(0, 0, 2, 1, 1, 0, LINE_START, GridBagConstraints.HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + final JLabel subjectLabel = new JLabel( Res.getString("label.certificate.subject") ); + subjectLabel.setHorizontalAlignment(SwingConstants.RIGHT ); + add( subjectLabel, new GridBagConstraints(0, 1, 1, 1, 0.1, 0, LINE_END, GridBagConstraints.HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + final JTextField subjectNameField = new JTextField(); + subjectNameField.setEditable(false); + subjectNameField.setText( certModel.getSubjectCommonName() != null ? certModel.getSubjectCommonName() : certModel.getSubject() ); + add( subjectNameField, new GridBagConstraints(1, 1, 1, 1, 1, 0, LINE_START, GridBagConstraints.HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + final JLabel issuerLabel = new JLabel( Res.getString("label.certificate.issuer") ); + issuerLabel.setHorizontalAlignment( SwingConstants.RIGHT ); + add( issuerLabel, new GridBagConstraints(0, 2, 1, 1, 0.1, 0, LINE_END, GridBagConstraints.HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + final JTextField issuerNameField = new JTextField(); + issuerNameField.setEditable(false); + issuerNameField.setText( certModel.getIssuerCommonName() != null ? certModel.getIssuerCommonName() : certModel.getIssuer() ); + add( issuerNameField, new GridBagConstraints(1, 2, 1, 1, 1, 0, LINE_START, GridBagConstraints.HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + final JLabel validityFromLabel = new JLabel( Res.getString("label.certificate.not.before") ); + validityFromLabel.setHorizontalAlignment( SwingConstants.RIGHT ); + add( validityFromLabel, new GridBagConstraints(0, 3, 1, 1, 0.1, 0, LINE_END, GridBagConstraints.HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + final JTextField validityFromField = new JTextField(); + validityFromField.setEditable(false); + validityFromField.setText( certModel.getNotBefore() ); + add( validityFromField, new GridBagConstraints(1, 3, 1, 1, 1, 0, LINE_START, GridBagConstraints.HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + final JLabel validityUntilLabel = new JLabel( Res.getString("label.certificate.not.after") ); + validityUntilLabel.setHorizontalAlignment( SwingConstants.RIGHT ); + add( validityUntilLabel, new GridBagConstraints(0, 4, 1, 1, 0.1, 0, LINE_END, GridBagConstraints.HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + final JTextField validityUntilField = new JTextField(); + validityUntilField.setEditable(false); + validityUntilField.setText( certModel.getNotAfter() ); + add( validityUntilField, new GridBagConstraints(1, 4, 1, 1, 1, 0, LINE_START, GridBagConstraints.HORIZONTAL, DEFAULT_INSETS, 0, 0)); + + add( new JLabel(Res.getString("dialog.certificate.add.unrecognized.server.certificate")), new GridBagConstraints(0, 5, 2, 1, 1, 0, LINE_START, GridBagConstraints.HORIZONTAL, DEFAULT_INSETS, 0, 0)); + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/InternalPlugins.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/InternalPlugins.java new file mode 100644 index 000000000..40ac492e6 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/InternalPlugins.java @@ -0,0 +1,34 @@ +package org.jivesoftware.sparkimpl.plugin; + +import org.jivesoftware.spark.plugin.PublicPlugin; + +import java.util.List; + +public class InternalPlugins { + + public static List getInternalPlugins() { + return List.of( + new PublicPlugin("Jabber Browser", "org.jivesoftware.sparkimpl.plugin.jabber.JabberBrowser", "1.1"), +// new PublicPlugin("Asterisks Phone Plugin", "org.jivesoftware.sparkimpl.plugin.phone.PhonePlugin", "1.1"), + new PublicPlugin("Jabber Version", "org.jivesoftware.sparkimpl.plugin.jabber.JabberVersion", "1.1"), + new PublicPlugin("Sounds Plugin", "org.jivesoftware.sparkimpl.preference.sounds.SoundPlugin", "1.1"), + new PublicPlugin("Layout Plugin", "org.jivesoftware.sparkimpl.plugin.layout.LayoutPlugin", "1.1"), + new PublicPlugin("Chat Post Loader", "org.jivesoftware.sparkimpl.plugin.chat.ChatArgumentsPlugin", "1.1"), + new PublicPlugin("Presence Change Plugin", "org.jivesoftware.sparkimpl.plugin.chat.PresenceChangePlugin", "1.1"), + new PublicPlugin("Plugin Viewer Plugin", "org.jivesoftware.sparkimpl.plugin.viewer.PluginViewer", "1.1"), + new PublicPlugin("Emoticon Plugin", "org.jivesoftware.sparkimpl.plugin.emoticons.EmoticonPlugin", "1.1"), + new PublicPlugin("Sparklers Plugin", "org.jivesoftware.sparkimpl.plugin.sparklers.SparklersPlugin", "1.1"), + new PublicPlugin("Notes Plugin", "org.jivesoftware.sparkimpl.plugin.scratchpad.ScratchPadPlugin", "1.1"), + new PublicPlugin("Buzz Plugin", "org.jivesoftware.sparkimpl.plugin.alerts.BuzzPlugin", "1.1"), + new PublicPlugin("Notifications Plugin", "org.jivesoftware.sparkimpl.preference.notifications.NotificationPlugin", "1.1"), + new PublicPlugin("Shortcut Plugin", "org.jivesoftware.sparkimpl.plugin.chat.ShortcutPlugin", "1.1"), + new PublicPlugin("History Plugin", "org.jivesoftware.sparkimpl.plugin.history.ConversationHistoryPlugin", "1.1"), + new PublicPlugin("Contact List Assistant", "org.jivesoftware.sparkimpl.plugin.chat.ContactListAssistantPlugin", "1.1"), + new PublicPlugin("My Favorites", "org.jivesoftware.sparkimpl.plugin.history.FrequentContactsPlugin", "1.1"), + new PublicPlugin("Language Plugin", "org.jivesoftware.sparkimpl.plugin.language.LanguagePlugin", "1.1"), + new PublicPlugin("SystemTray", "org.jivesoftware.sparkimpl.plugin.systray.SysTrayPlugin", "1.1"), + new PublicPlugin("UserIdle", "org.jivesoftware.sparkimpl.plugin.idle.UserIdlePlugin", "1.1"), + new PublicPlugin("Privacy Lists", "org.jivesoftware.sparkimpl.plugin.privacy.PrivacyPlugin", "2.1") + ); + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/BroadcastDialog.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/BroadcastDialog.java new file mode 100644 index 000000000..b17fb58bd --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/BroadcastDialog.java @@ -0,0 +1,417 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.alerts; + +import java.awt.*; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.List; +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.UIManager; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import org.jivesoftware.Spark; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.CheckNode; +import org.jivesoftware.spark.component.CheckTree; +import org.jivesoftware.spark.component.TitlePanel; +import org.jivesoftware.spark.ui.ChatInputEditor; +import org.jivesoftware.spark.ui.ContactGroup; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.spark.ui.ContactList; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettingsManager; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.impl.JidCreate; + +/** + * Allows for better selective broadcasting. + * + * @author Derek DeMoro + */ +public class BroadcastDialog extends JPanel { + + private static final long serialVersionUID = -8998994627855985137L; + private final ChatInputEditor messageBox; + private final JCheckBox OfflineUsers = new JCheckBox(Res.getString("checkbox.broadcast.hide.offline.user")); + private final JRadioButton normalMessageButton; + + private final ArrayList> NodesGroups = new ArrayList<>(); + private final List nodes = new ArrayList<>(); + private final List groupNodes = new ArrayList<>(); + private final CheckNode rosterNode; + private final CheckTree checkTree; + private Integer OfflineGroup; + + public BroadcastDialog() { + setLayout(new GridBagLayout()); + rosterNode = new CheckNode(Res.getString("title.roster")); + checkTree = new CheckTree(rosterNode); + final ContactList contactList = SparkManager.getWorkspace().getContactList(); + + // creates the List for the Online Users + String groupName = Res.getString("status.online"); + CheckNode groupNode = new CheckNode(groupName); + groupNodes.add(groupNode); + rosterNode.add(groupNode); + List onlineJIDs = new ArrayList<>(); + //ContactGroup groupp; + for(ContactGroup group : contactList.getContactGroups()) + for (ContactItem item : group.getContactItems()) + { + if(item.isAvailable() && !onlineJIDs.contains(item.getJid().toString())) + { + CheckNode itemNode = new CheckNode(item.getDisplayName(), false, item.getIcon()); + itemNode.setAssociatedObject(item.getJid().toString()); + groupNode.add(itemNode); + nodes.add(itemNode); + onlineJIDs.add(item.getJid().toString()); + } + } + + // Build out from Roster + + for (ContactGroup group : contactList.getContactGroups()) { + groupName = group.getGroupName(); + if (!group.hasAvailableContacts()) { + continue; + } + groupNode = new CheckNode(groupName); + groupNodes.add(groupNode); + rosterNode.add(groupNode); + + // Now add contact items from contact group. + for (ContactItem item : group.getContactItems()) { + CheckNode itemNode = new CheckNode(item.getDisplayName(), false, item.getIcon()); + itemNode.setAssociatedObject(item.getJid().toString()); + groupNode.add(itemNode); + nodes.add(itemNode); + } + + for (ContactItem item : group.getOfflineContacts()) { + CheckNode itemNode = new CheckNode(item.getDisplayName(), false, item.getIcon()); + itemNode.setAssociatedObject(item.getJid().toString()); + groupNode.add(itemNode); + nodes.add(itemNode); + } + } + + messageBox = new ChatInputEditor(); + normalMessageButton = new JRadioButton(Res.getString("message.normal")); + JRadioButton alertMessageButton = new JRadioButton(Res.getString("message.alert.notify")); + + ButtonGroup group = new ButtonGroup(); + group.add(normalMessageButton); + group.add(alertMessageButton); + + final JScrollPane pane = new JScrollPane(messageBox); + pane.setBorder(BorderFactory.createTitledBorder(Res.getString("label.message").replace("&", ""))); + + final JScrollPane treePane = new JScrollPane(checkTree); + treePane.setBorder(BorderFactory.createTitledBorder(Res.getString("message.send.to.these.people"))); + treePane.getVerticalScrollBar().setBlockIncrement(200); + treePane.getVerticalScrollBar().setUnitIncrement(20); + // Add to UI + add(pane, new GridBagConstraints(0, 0, 1, 1, 0.5, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); + add(normalMessageButton, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(alertMessageButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 5, 2, 5), 0, 0)); + add(treePane, new GridBagConstraints(1, 0, 1, 3, 0.5, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, 5, 2, 5), 0, 0)); + add(OfflineUsers, new GridBagConstraints(1, 3, 1, 0, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, 5, 2, 5), 0, 0)); + + OfflineUsers.addActionListener( e -> hideOfflineUsers() ); + + normalMessageButton.setSelected(true); + checkTree.expandTree(); + + // get list of selected users + java.util.Collection selectedUsers = contactList.getSelectedUsers(); + // if selected users is 1 or less, + // don't per-select in dialog window (see SPARK-1088) + if (selectedUsers.size() > 1) { + // Iterate through selected users. + for (ContactItem item : selectedUsers) { + for (CheckNode node : nodes) { + if (node.getAssociatedObject().toString().equals(item.getJid().toString())) { + node.setSelected(true); + } + } + } + } + } + + public void invokeDialog(ContactGroup group) { + for (CheckNode node : groupNodes) { + if (node.getUserObject().toString().equals(group.getGroupName())) { + node.setSelected(true); + } + } + + invokeDialog(); + } + + /** + * Displays the broadcast dialog. + */ + public void invokeDialog() { + final JDialog dlg; + + TitlePanel titlePanel; + + // Create the title panel for this dialog + titlePanel = new TitlePanel(Res.getString("title.broadcast.message"), Res.getString("message.enter.broadcast.message"), null, true); + + // Construct main panel w/ layout. + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BorderLayout()); + mainPanel.add(titlePanel, BorderLayout.NORTH); + + // The user should only be able to close this dialog. + JButton okButton = new JButton(Res.getString("ok")); + JButton closeButton = new JButton(Res.getString("close")); + + mainPanel.add(this,BorderLayout.CENTER); + + JPanel buttonpanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + buttonpanel.add(okButton); + buttonpanel.add(closeButton); + + mainPanel.add(buttonpanel,BorderLayout.SOUTH); + + dlg = new JDialog(SparkManager.getMainWindow(), Res.getString("broadcast")); + dlg.setContentPane(mainPanel); + dlg.pack(); + + + final Rectangle bounds = LayoutSettingsManager.getLayoutSettings().getBroadcastMessageBounds(); + if ( bounds == null || bounds.width <= 0 || bounds.height <= 0 ) + { + // Use default settings. + dlg.setSize( 800, 600 ); + dlg.setLocationRelativeTo( null ); + } + else + { + dlg.setBounds( bounds ); + } + + dlg.addComponentListener( new ComponentAdapter() + { + @Override + public void componentResized( ComponentEvent e ) + { + LayoutSettingsManager.getLayoutSettings().setBroadcastMessageBounds( dlg.getBounds() ); + } + + @Override + public void componentMoved( ComponentEvent e ) + { + LayoutSettingsManager.getLayoutSettings().setBroadcastMessageBounds( dlg.getBounds() ); + } + } ); + + dlg.setResizable(false); + + // Add listener + okButton.addActionListener( e -> { +try +{ +if (sendBroadcasts(dlg)) { +dlg.setVisible(false); +} +} +catch ( SmackException.NotConnectedException e1 ) +{ +Log.warning( "Unable to broadcast.", e1 ); +} + +} ); + + closeButton.addActionListener( e -> dlg.setVisible(false) ); + + dlg.setVisible(true); + dlg.toFront(); + dlg.requestFocus(); + + messageBox.requestFocus(); + + } + + private void hideOfflineUsers() { + + int i; + if (OfflineUsers.isSelected()) { + final ContactList contactList = SparkManager.getWorkspace() + .getContactList(); + i = 0; + for (CheckNode node : nodes) { + if (contactList.getContactItemByDisplayName(node.toString()) + .getPresence().getType() == Presence.Type.unavailable) { + if (node.getParent() != null) { + TreeNode parent = node.getParent(); + TreeNode[] path = ((DefaultTreeModel) checkTree + .getTree().getModel()).getPathToRoot(parent); + ((DefaultTreeModel) checkTree.getTree().getModel()) + .removeNodeFromParent(node); + checkTree.getTree() + .setSelectionPath(new TreePath(path)); + NodesGroups.add( new ArrayList<>()); + NodesGroups.get(i).add(parent); + NodesGroups.get(i).add(node); + i++; + } + } + } + for (int x = 0; x < groupNodes.size(); x++) { + if (groupNodes.get(x).toString() + .equals(Res.getString("group.offline"))) { + OfflineGroup = x; + TreeNode parent = groupNodes.get(x).getParent(); + TreeNode[] path = ((DefaultTreeModel) checkTree.getTree() + .getModel()).getPathToRoot(parent); + ((DefaultTreeModel) checkTree.getTree().getModel()) + .removeNodeFromParent(groupNodes.get(x)); + checkTree.getTree().setSelectionPath(new TreePath(path)); + } + } + } else { + i = 0; + DefaultMutableTreeNode child = groupNodes.get(OfflineGroup); + ((DefaultTreeModel) checkTree.getTree().getModel()).insertNodeInto( + child, rosterNode, rosterNode.getChildCount()); + TreeNode[] path = ((DefaultTreeModel) checkTree.getTree() + .getModel()).getPathToRoot(rosterNode); + checkTree.getTree().expandPath(new TreePath(path)); + checkTree.expandTree(); + for (CheckNode node : nodes) { + if (node.getParent() == null) { + child = (CheckNode) NodesGroups.get(i).get(1); + ((DefaultTreeModel) checkTree.getTree().getModel()) + .insertNodeInto(child, ((CheckNode) NodesGroups + .get(i).get(0)), ((CheckNode) NodesGroups + .get(i).get(0)).getChildCount()); + path = ((DefaultTreeModel) checkTree.getTree().getModel()) + .getPathToRoot(node); + checkTree.getTree().expandPath(new TreePath(path)); + checkTree.expandTree(); + i++; + } + } + } + } + + /** + * Sends a broadcast message to all users selected. + */ + private boolean sendBroadcasts(JDialog dlg) throws SmackException.NotConnectedException + { + Set jids = new HashSet<>(); + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + for (CheckNode node : nodes) { + if (node.isSelected()) { + String jid = (String)node.getAssociatedObject(); + jids.add(JidCreate.bareFromOrThrowUnchecked(jid)); + } + } + if (jids.isEmpty()) + { + JOptionPane.showMessageDialog(dlg, Res.getString("message.broadcast.no.user.selected"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + return false; + } + String text = messageBox.getText(); + if (!ModelUtil.hasLength(text)) { + JOptionPane.showMessageDialog(dlg, Res.getString("message.broadcast.no.text"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + return false; + } + List recipients = new ArrayList<>(jids.size()); + for (BareJid jid : jids) { + MessageBuilder messageBuilder = StanzaBuilder.buildMessage() + .ofType(normalMessageButton.isSelected() ? Message.Type.normal : Message.Type.headline) + .to(jid) + .setBody(text); + Message message = messageBuilder.build(); + + try { + SparkManager.getConnection().sendStanza(message); + } catch (InterruptedException e) { + Log.error("Error sending broadcast message to " + jid, e); + break; + } + String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid); + recipients.add(nickname); + } + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"+" - "+"HH:mm"); + Date date = new Date(); + String out=dateFormat.format(date)+" ("+String.join(", ", recipients)+"): "+text+"\n"; + try { + addDataToFile(out); + } catch (IOException ex) { + Log.error("Couldn't add data to file", ex); + } + return true; + } + + private void addDataToFile(String data) throws IOException + { + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM"); + Date date = new Date(); + String fileName="broadcast_history."+dateFormat.format(date)+".txt"; + String filePath=Spark.getSparkUserHome()+File.separator+"user"+File.separator+SparkManager.getSessionManager().getUsername()+"@"+SparkManager.getSessionManager().getServerAddress()+File.separator+"transcripts"; + File fileDirectory = new File(filePath); + if(!fileDirectory.exists()) + { + fileDirectory.mkdir(); + } + String fileLocation=filePath+File.separator+fileName; + + + File file = new File(fileLocation); + + if(!file.exists()) + { + file.createNewFile(); + } + FileWriter fileWritter = new FileWriter(file.getPath(),true); + BufferedWriter out = new BufferedWriter(fileWritter); + out.write(data); + out.close(); + + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/BroadcastPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/BroadcastPlugin.java new file mode 100644 index 000000000..b781bf754 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/BroadcastPlugin.java @@ -0,0 +1,504 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.alerts; + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import javax.swing.*; +import javax.swing.event.HyperlinkEvent; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.StanzaListener; +import org.jivesoftware.smack.filter.StanzaFilter; +import org.jivesoftware.smack.filter.StanzaTypeFilter; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.Message.Type; +import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smackx.delay.packet.DelayInformation; +import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.component.tabbedPane.SparkTab; +import org.jivesoftware.spark.plugin.ContextMenuListener; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.ChatContainer; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomNotFoundException; +import org.jivesoftware.spark.ui.ContactGroup; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.spark.ui.ContactList; +import org.jivesoftware.spark.ui.MessageListener; +import org.jivesoftware.spark.ui.SparkTabHandler; +import org.jivesoftware.spark.ui.TranscriptWindow; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.ui.status.StatusBar; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Localpart; +import org.jxmpp.jid.parts.Resourcepart; +import org.jxmpp.util.XmppStringUtils; +import org.jivesoftware.spark.ui.BroadcastHistoryFrame; + +import static org.apache.commons.lang3.StringUtils.*; +import static org.jivesoftware.spark.Event.MSG_INCOMING; +import static org.jivesoftware.spark.util.StringUtils.*; + +/** + * Handles broadcasts from a server and allows for roster wide broadcasts. + */ +public class BroadcastPlugin extends SparkTabHandler implements Plugin, StanzaListener { + + private final Set broadcastRooms = new HashSet<>(); + + @Override + public void initialize() { + // See if we should disable all "Broadcast" menu items + if (Default.getBoolean(Default.DISABLE_BROADCAST_MENU_ITEM) || !Enterprise.containsFeature(Enterprise.BROADCAST_FEATURE)) { + return; + } + + // Add as ContainerDecorator + SparkManager.getChatManager().addSparkTabHandler(this); + + StanzaFilter serverFilter = new StanzaTypeFilter(Message.class); + SparkManager.getConnection().addAsyncStanzaListener(this, serverFilter); + + // Register with action menu + final JMenu actionsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions")); + JMenuItem broadcastHistoryMenu = new JMenuItem(Res.getString("title.broadcast.history"), SparkRes.getImageIcon(SparkRes.Icon.HISTORY_16x16)); + JMenuItem broadcastMenu = new JMenuItem(Res.getString("title.broadcast.message"), SparkRes.getImageIcon(SparkRes.Icon.MEGAPHONE_16x16)); + ResourceUtils.resButton(broadcastMenu, Res.getString("title.broadcast.message")); + actionsMenu.add(broadcastHistoryMenu); + actionsMenu.add(broadcastMenu); + + broadcastMenu.addActionListener(e -> broadcastToRoster()); + broadcastHistoryMenu.addActionListener(e -> new BroadcastHistoryFrame().run()); + // Register with action menu + JMenuItem startConversationMenu = new JMenuItem("", SparkRes.getImageIcon(SparkRes.Icon.SMALL_MESSAGE_IMAGE)); + ResourceUtils.resButton(startConversationMenu, Res.getString("menuitem.start.a.chat")); + if (!Default.getBoolean(Default.HIDE_START_A_CHAT) && Enterprise.containsFeature(Enterprise.START_A_CHAT_FEATURE)) { + actionsMenu.add(startConversationMenu, 0); + } + // Start chat with user entered in dialog + startConversationMenu.addActionListener(e -> { + ContactList contactList = SparkManager.getWorkspace().getContactList(); + Collection selectedUsers = contactList.getSelectedUsers(); + String selectedUser = ""; + Iterator selectedUsersIterator = selectedUsers.iterator(); + if (selectedUsersIterator.hasNext()) { + ContactItem contactItem = selectedUsersIterator.next(); + selectedUser = contactItem.getJid().toString(); + } + + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + UIManager.put("OptionPane.cancelButtonText", Res.getString("cancel")); + + String jid = (String) JOptionPane.showInputDialog(SparkManager.getMainWindow(), Res.getString("label.enter.address"), Res.getString("title.start.chat"), JOptionPane.QUESTION_MESSAGE, null, null, selectedUser); + if (ModelUtil.hasLength(jid) && ModelUtil.hasLength(XmppStringUtils.parseDomain(jid))) { + if (ModelUtil.hasLength(jid) && jid.indexOf('@') == -1) { + // Append server address + jid = jid + "@" + SparkManager.getConnection().getXMPPServiceDomain(); + } + EntityBareJid entityBareJid = JidCreate.entityBareFromUnescapedOrThrowUnchecked(jid); + String nickname = SparkManager.getUserManager().getUserNicknameFromJID(entityBareJid); + ChatRoom chatRoom = SparkManager.getChatManager().createChatRoom(entityBareJid, nickname, nickname); + SparkManager.getChatManager().getChatContainer().activateChatRoom(chatRoom); + } + }); + + // Add Send to selected users. + final ContactList contactList = SparkManager.getWorkspace().getContactList(); + contactList.addContextMenuListener(new ContextMenuListener() { + @Override + public void poppingUp(Object component, JPopupMenu popup) { + if (component instanceof ContactGroup) { + final ContactGroup group = (ContactGroup) component; + Action broadcastMessageAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + broadcastToGroup(group); + } + }; + + broadcastMessageAction.putValue(Action.NAME, Res.getString("menuitem.broadcast.to.group")); + broadcastMessageAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.MEGAPHONE_16x16)); + + popup.add(broadcastMessageAction); + } + } + + @Override + public void poppingDown(JPopupMenu popup) { + } + + @Override + public boolean handleDefaultAction(MouseEvent e) { + return false; + } + }); + + // Add Broadcast to roaster + StatusBar statusBar = SparkManager.getWorkspace().getStatusBar(); + + RolloverButton broadcastToRosterButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.Icon.MEGAPHONE_16x16)); + broadcastToRosterButton.setToolTipText(Res.getString("message.send.a.broadcast")); + + statusBar.invalidate(); + statusBar.validate(); + statusBar.repaint(); + + broadcastToRosterButton.addActionListener(e -> broadcastToRoster()); + } + + @Override + public void shutdown() { + } + + @Override + public boolean canShutDown() { + return false; + } + + @Override + public void processStanza(final Stanza stanza) { + SwingUtilities.invokeLater(() -> { + try { + final Message message = (Message) stanza; + // Do not handle errors or offline messages + if (message.hasExtension(DelayInformation.class) || message.getError() != null) { + return; + } + + final JivePropertiesExtension extension = message.getExtension(JivePropertiesExtension.class); + final boolean broadcast = extension != null && extension.getProperty("broadcast") != null; + // Shows alert if broadcast or normal/headline message + if ((broadcast || message.getType() == Type.normal + || message.getType() == Type.headline) && message.getBody() != null) { + showAlert((Message) stanza); + } else { + DomainBareJid host = SparkManager.getSessionManager().getServerAddress(); + Jid from = stanza.getFrom(); + if (host.equals(from)) { + showAlert((Message) stanza); + } + } + } catch (Exception e) { + Log.error(e); + } + }); + } + + /** + * Show Server Alert. + * + * @param message the message to show. + */ + private void showAlert(Message message) { + Type type = message.getType(); + // Do not show alert if the message is an error. + if (message.getError() != null) { + return; + } + + final String body = message.getBody(); + String subject = message.getSubject(); + + StringBuilder buf = new StringBuilder(); + if (subject != null) { + buf.append(Res.getString("subject")).append(": ").append(subject); + buf.append("\n\n"); + } + buf.append(body); + + Jid from = message.getFrom(); + + final TranscriptWindow window = new TranscriptWindow(); + window.insertNotificationMessage(buf.toString(), ChatManager.TO_COLOR); + + JPanel p = new JPanel(); + p.setLayout(new BorderLayout()); + p.add(window, BorderLayout.CENTER); + p.setBorder(BorderFactory.createLineBorder(Color.lightGray)); + + // Count the number of linebreaks
      and \n + String s = message.getBody(); + s = s.replace("
      ", "\n"); + s = s.replace("
      ", "\n"); + int linebreaks = countNumberOfOccurences(s, '\n'); + + // If the message is blank, then it should not be displayed. + if (isBlank(s)) { + return; + } + + // Currently Server Broadcasts don't contain Subjects, so this might be a MOTD message + boolean mightbeMOTD = message.getSubject() != null; + + if (!from.hasLocalpart()) { + // if there's no "@" it means the message came from the server + if (Default.getBoolean(Default.BROADCAST_IN_CHAT_WINDOW) + || linebreaks > 20 || message.getBody().length() > 1000 || mightbeMOTD) { + // If the message has more than 20 linebreaks or is longer than 1000 characters + // we should broadcast in a normal chat window. + broadcastInChat(message); + } else { + broadcastWithPanel(message); + } + } else if (message.getFrom() != null) { + userToUserBroadcast(message, type, from); + } + } + + /** + * Handles Broadcasts made from a user to another user + * + * @param message the message + * @param type the message type + * @param from the sender + */ + private void userToUserBroadcast(Message message, Type type, Jid from) { + EntityBareJid jid = from.asEntityBareJidOrThrow(); + Resourcepart nickname = SparkManager.getUserManager().getUserNicknameAsResourcepartFromJID(jid); + ChatManager chatManager = SparkManager.getChatManager(); + ChatContainer container = chatManager.getChatContainer(); + + ChatRoomImpl chatRoom; + try { + chatRoom = (ChatRoomImpl) container.getChatRoom(jid); + } catch (ChatRoomNotFoundException e) { + chatRoom = new ChatRoomImpl(jid, nickname, nickname); + SparkManager.getChatManager().getChatContainer().addChatRoom(chatRoom); + } + + Message m = StanzaBuilder.buildMessage() + .setBody(message.getBody()) + .to(message.getTo()) + .from(message.getFrom()) + .build(); + + String broadcastType = type == Message.Type.normal ? Res.getString("broadcast") : Res.getString("message.alert.notify"); + + chatRoom.getTranscriptWindow().insertMessage((nickname + " - " + broadcastType), message, ChatManager.FROM_COLOR); + chatRoom.addToTranscript(m, true); + chatRoom.increaseUnreadMessageCount(); + broadcastRooms.add(chatRoom); + + showToaster(message, nickname, broadcastType); + + SparkManager.getChatManager().fireGlobalMessageReceivedListeners(chatRoom, message); + + if (message.hasExtension(DelayInformation.class)) { + SparkManager.getSoundManager().playClip(MSG_INCOMING); + } + + chatRoom.addMessageListener(new MessageListener() { + boolean waiting = true; + + @Override + public void messageReceived(ChatRoom room, Message message) { + removeAsBroadcast(room); + } + + @Override + public void messageSent(ChatRoom room, Message message) { + removeAsBroadcast(room); + } + + private void removeAsBroadcast(ChatRoom room) { + if (waiting) { + broadcastRooms.remove(room); + // Notify decorators + SparkManager.getChatManager().notifySparkTabHandlers(room); + waiting = false; + } + } + }); + } + + private static void showToaster(Message message, Resourcepart nickname, String broadcastType) { + LocalPreferences pref = SettingsManager.getLocalPreferences(); + if (pref.getShowToasterPopup()) { + SparkToaster toaster = new SparkToaster(); + toaster.setDisplayTime(30000); + toaster.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); + toaster.setTitle(nickname + " - " + broadcastType); + toaster.showToaster(message.getBody()); + } + } + + /** + * Broadcasts a message to all in the roster. + */ + private void broadcastToRoster() { + final BroadcastDialog broadcastDialog = new BroadcastDialog(); + broadcastDialog.invokeDialog(); + } + + /** + * Broadcasts a message to all selected users. + * + * @param group the Contact Group to send the messages to. + */ + private void broadcastToGroup(ContactGroup group) { + final BroadcastDialog broadcastDialog = new BroadcastDialog(); + broadcastDialog.invokeDialog(group); + } + + @Override + public void uninstall() { + } + + @Override + public boolean isTabHandled(SparkTab tab, Component component, boolean isSelectedTab, boolean chatFrameFocused) { + if (component instanceof ChatRoom) { + ChatRoom chatroom = (ChatRoom) component; + if (broadcastRooms.contains(chatroom)) { + final ChatRoomImpl room = (ChatRoomImpl) component; + tab.setIcon(SparkRes.getImageIcon(SparkRes.Icon.INFORMATION_IMAGE)); + String nickname = room.getTabTitle(); + nickname = Res.getString("message.broadcast.from", nickname); + tab.setTabTitle(nickname); + + if ((!chatFrameFocused || !isSelectedTab) && room.getUnreadMessageCount() > 0) { + // Make tab red. + tab.setTitleColor(Color.red); + tab.setTabBold(true); + } else { + tab.setTitleColor(Color.black); + tab.setTabFont(tab.getDefaultFont()); + room.clearUnreadMessageCount(); + } + return true; + } + } + return false; + } + + /** + * Displays the Serverbroadcast like all other messages in its on + * chat container with transcript history + */ + private void broadcastInChat(Message message) { + String windowtitle = message.getSubject() != null ? message.getSubject() : Res.getString("administrator"); + Localpart serverAlertPart = Localpart.fromOrThrowUnchecked("serveralert"); + EntityBareJid jid = JidCreate.entityBareFrom(serverAlertPart, message.getFrom().asDomainBareJid()); + Resourcepart resourcepart = Resourcepart.fromOrThrowUnchecked(Res.getString("broadcast")); + ChatRoomImpl chatRoom = new ChatRoomImpl(jid, resourcepart, windowtitle); + chatRoom.getBottomPanel().setVisible(false); + chatRoom.hideToolbar(); + SparkManager.getChatManager().getChatContainer().addChatRoom(chatRoom); + + chatRoom.getTranscriptWindow().insertNotificationMessage(message.getBody(), ChatManager.NOTIFICATION_COLOR); + broadcastRooms.add(chatRoom); + } + + private String linkCreator(String message) { + message = message.replace("\n", "
      "); + String[] lines = message.split("\\s+"); + StringBuilder html = new StringBuilder(); + for (String line : lines) { + if (line.startsWith("www")) { + line = "http://" + line; + } + if (line.startsWith("http:") || line.startsWith("https:")) { + line = "" + line + ""; + // final JLabel label = new JLabel(" click "); + } + html.append(" ").append(line); + } + return html.toString(); + } + + /** + * Displays a Server Broadcast within a JFrame
      + * Messages can contain html-tags + */ + private void broadcastWithPanel(Message message) { + + String title = Res.getString("message.broadcast.from", + Res.getString("administrator")); + final JFrame alert = new JFrame(title); + + alert.setLayout(new GridBagLayout()); + alert.setIconImage(SparkRes.getImageIcon(SparkRes.Icon.MAIN_IMAGE).getImage()); + String mylink = linkCreator(message.getBody()); + JLabel icon = new JLabel(SparkRes.getImageIcon(SparkRes.Icon.ALERT)); + JButton close = new JButton(Res.getString("close")); + + close.addActionListener(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + alert.setVisible(false); + alert.dispose(); + } + }); + final JEditorPane textPane = new JEditorPane(); + textPane.setEditable(false); + textPane.setContentType("text/html"); + textPane.setText(mylink); + + textPane.addHyperlinkListener(e -> { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + try { + Log.warning("Open the URL in default browser" + e.getURL()); + Desktop.getDesktop().browse(e.getURL().toURI()); + } catch (IOException | URISyntaxException ex) { + Log.error(ex.getCause()); + } + } + }); + JScrollPane scrollPane = new JScrollPane(textPane); + scrollPane.setBorder(BorderFactory.createEmptyBorder()); + textPane.setCaretPosition(0); + + alert.add(icon, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + alert.add(scrollPane, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); + alert.add(close, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + + alert.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + alert.setVisible(true); + + alert.setMinimumSize(new Dimension(340, 200)); + alert.setPreferredSize(new Dimension(340, 200)); + alert.pack(); + Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); + int x = (dim.width - alert.getSize().width) / 2; + int y = (dim.height - alert.getSize().height) / 2; + alert.setLocation(x, y); + alert.toFront(); + alert.requestFocus(); + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/BuzzPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/BuzzPlugin.java new file mode 100644 index 000000000..e449a8816 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/BuzzPlugin.java @@ -0,0 +1,157 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.alerts; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.filter.AndFilter; +import org.jivesoftware.smack.filter.StanzaTypeFilter; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smackx.attention.packet.AttentionExtension; +import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; +import org.jivesoftware.smackx.disco.packet.DiscoverInfo; +import org.jivesoftware.spark.Event; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.spark.SoundManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.*; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.util.SwingTimerTask; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.EntityFullJid; + +import java.util.TimerTask; + +import javax.swing.SwingUtilities; + +import static org.jivesoftware.spark.ChatManager.NOTIFICATION_COLOR; + +/** + * Allows users to shake a user's frame to attract their attention and play a buzz sound. + * It's kind of "call" to get an immediate answer. + * Such a notification may be shown even in DND status. + * A user may disable the buzz feature in the settings, but anyway it will see the buzz as a regular message. + * @see XEP-0224 Attention. + */ +public class BuzzPlugin implements Plugin { + + @Override + public void initialize() { + // Add Attention to a discovered items list. + SparkManager.addFeature(AttentionExtension.NAMESPACE); + SparkManager.getConnection() + .addAsyncStanzaListener( + stanza -> SwingUtilities.invokeLater(() -> shakeWindow((Message) stanza)), + new AndFilter(StanzaTypeFilter.MESSAGE, s -> s.hasExtension(AttentionExtension.ELEMENT_NAME, AttentionExtension.NAMESPACE)) + ); + + SparkManager.getChatManager().addChatRoomListener( + new ChatRoomListener() { + @Override + public void chatRoomOpened(final ChatRoom room) { + TimerTask task = new SwingTimerTask() { + @Override + public void doRun() { + addBuzzFeatureToChatRoom(room); + } + }; + + TaskEngine.getInstance().schedule(task, 100); + } + }); + } + + private void addBuzzFeatureToChatRoom(final ChatRoom room) { + if (room instanceof ChatRoomImpl) { + SwingUtilities.invokeLater(() -> { + boolean hasAttentionSupport = clientOfContactSupportsAttentions(room); + if (!hasAttentionSupport) { + return; + } + // Add the button to the toolbar + new BuzzRoomDecorator(room); + }); + } + } + + /** + * Determine via service discovery if the contact's client supports attentions + */ + private static boolean clientOfContactSupportsAttentions(ChatRoom room) { + EntityFullJid fullJID = PresenceManager.getFullyQualifiedJID(room.getBareJid()); + boolean hasAttentionSupport = true; + ServiceDiscoveryManager discoManager = SparkManager.getDiscoManager(); + try { + DiscoverInfo discoverInfo = discoManager.discoverInfo(fullJID); + hasAttentionSupport = discoverInfo.containsFeature(AttentionExtension.NAMESPACE); + } catch (Exception e) { + Log.warning(e.getMessage()); + } + return hasAttentionSupport; + } + + private void shakeWindow(Message message) { + EntityBareJid bareJID = message.getFrom().asEntityBareJidOrThrow(); + String nickname; + ContactItem contact = SparkManager.getWorkspace().getContactList().getContactItemByJID(bareJID); + if (contact != null) { + nickname = contact.getDisplayName(); + } else { + nickname = bareJID.getLocalpart().asUnescapedString(); + } + + ChatContainer chatContainer = SparkManager.getChatManager().getChatContainer(); + ChatRoom room; + try { + room = chatContainer.getChatRoom(bareJID); + } catch (ChatRoomNotFoundException e) { + // Create the room if it does not exist. + room = SparkManager.getChatManager().createChatRoom(bareJID, + nickname, nickname); + } + + ChatFrame chatFrame = chatContainer.getChatFrame(); + if (chatFrame != null) { + if (SettingsManager.getLocalPreferences().isBuzzEnabled()) { + chatFrame.buzz(); + chatContainer.activateChatRoom(room); +//TODO SparkManager.getSoundManager().playClip(Event.ATTENTION_BUZZ); + } + } + + // Insert offline message + room.getTranscriptWindow().insertNotificationMessage( + Res.getString("message.buzz.message", nickname), + NOTIFICATION_COLOR); + room.scrollToBottom(); + } + + @Override + public void shutdown() { + } + + @Override + public boolean canShutDown() { + return true; + } + + @Override + public void uninstall() { + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/BuzzRoomDecorator.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/BuzzRoomDecorator.java new file mode 100644 index 000000000..bb510334b --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/BuzzRoomDecorator.java @@ -0,0 +1,108 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.alerts; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.TimerTask; + +import javax.swing.JButton; +import javax.swing.JLabel; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smackx.attention.packet.AttentionExtension; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.util.SwingTimerTask; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.UIComponentRegistry; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.Jid; + +import static org.jivesoftware.spark.ChatManager.NOTIFICATION_COLOR; + +/** + * Adds a simple buzz operation button the each newly created ChatRoom. + * + * @author Derek DeMoro + */ +public class BuzzRoomDecorator implements ActionListener { + + private final ChatRoom chatRoom; + private final JButton buzzButton; + + + public BuzzRoomDecorator(ChatRoom chatRoom) { + this.chatRoom = chatRoom; + + buzzButton = UIComponentRegistry.getButtonFactory().createBuzzButton(); + buzzButton.setToolTipText(Res + .getString("message.buzz.alert.notification")); + buzzButton.addActionListener(this); + + final JLabel dividerLabel = UIComponentRegistry.getButtonFactory().createDivider(); + if (dividerLabel != null) { + chatRoom.addEditorComponent(dividerLabel); + } + chatRoom.addEditorComponent(buzzButton); + } + + public void addBuzzButton(BuzzRoomDecorator buzzer) + { + final JLabel dividerLabel = new JLabel(SparkRes.getImageIcon(SparkRes.Icon.DIVIDER_IMAGE)); + chatRoom.addEditorComponent(dividerLabel); + chatRoom.addEditorComponent(buzzer.buzzButton); + } + + @Override + public void actionPerformed(ActionEvent e) { + Jid jid = ((ChatRoomImpl) chatRoom).getParticipantJID(); + + XMPPConnection connection = SparkManager.getConnection(); + Message message = connection.getStanzaFactory() + .buildMessageStanza() + .ofType(Message.Type.headline) // avoid offline storage + .to(jid) + .addExtension(new AttentionExtension()) + .build(); + + try + { + connection.sendStanza(message); + } + catch ( SmackException.NotConnectedException | InterruptedException e1 ) + { + Log.warning( "Unable to send stanza to " + jid, e1 ); + } + + chatRoom.getTranscriptWindow().insertNotificationMessage(Res.getString("message.buzz.sent"), NOTIFICATION_COLOR); + buzzButton.setEnabled(false); + + // Enable the button after 30 seconds to prevent abuse. + final TimerTask enableTask = new SwingTimerTask() { + @Override + public void doRun() { + buzzButton.setEnabled(true); + } + }; + TaskEngine.getInstance().schedule(enableTask, 30_000); + } +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/alerts/InputTextAreaDialog.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/InputTextAreaDialog.java similarity index 94% rename from src/java/org/jivesoftware/sparkimpl/plugin/alerts/InputTextAreaDialog.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/InputTextAreaDialog.java index cb9862a69..599b2faf9 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/alerts/InputTextAreaDialog.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/InputTextAreaDialog.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -120,7 +116,8 @@ public String getInput(String title, String description, Icon icon, Component pa // Add Key Listener to Send Field textArea.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { + @Override + public void keyPressed(KeyEvent e) { if (e.getKeyChar() == KeyEvent.VK_TAB) { optionPane.requestFocus(); } @@ -143,6 +140,7 @@ else if (e.getKeyChar() == KeyEvent.VK_ESCAPE) { public Action nextFocusAction = new AbstractAction("Move Focus Forwards") { private static final long serialVersionUID = 1238373124060258519L; + @Override public void actionPerformed(ActionEvent evt) { ((Component)evt.getSource()).transferFocus(); } @@ -154,26 +152,25 @@ public void actionPerformed(ActionEvent evt) { public Action prevFocusAction = new AbstractAction("Move Focus Backwards") { private static final long serialVersionUID = 7927553016576134725L; + @Override public void actionPerformed(ActionEvent evt) { ((Component)evt.getSource()).transferFocusBackward(); } }; - public void propertyChange(PropertyChangeEvent e) { + @Override + public void propertyChange(PropertyChangeEvent e) { String value = (String)optionPane.getValue(); if (Res.getString("cancel").equals(value)) { stringValue = null; dialog.setVisible(false); } else if (Res.getString("ok").equals(value)) { - stringValue = textArea.getText(); - if (stringValue.trim().length() == 0) { + stringValue = textArea.getText().trim(); + if (stringValue.isEmpty()) { stringValue = ""; } - else { - stringValue = stringValue.trim(); - } dialog.setVisible(false); } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/SparkToaster.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/SparkToaster.java new file mode 100644 index 000000000..3930452e9 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/alerts/SparkToaster.java @@ -0,0 +1,686 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.alerts; + +/** + * SparkToaster is an improvement of Java Toaster which is a java utility class for your swing applications + * that show an animate box coming from the bottom of your screen + * with a notification message and/or an associated image + * (like msn online/offline notifications). + * + * Toaster panel in windows system follow the taskbar; So if + * the taskbar is into the bottom the panel coming from the bottom + * and if the taskbar is on the top then the panel coming from the top. + * + * This is a simple example of utilization: + * + * import com.nitido.utils.toaster.*; + * import javax.swing.*; + * + */ + + +import java.awt.Color; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.EventQueue; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsEnvironment; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Image; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.geom.AffineTransform; + +import javax.swing.*; +import javax.swing.border.Border; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.util.ImageCombiner; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.Sizes; + +import static java.awt.GridBagConstraints.BOTH; +import static java.awt.GridBagConstraints.EAST; +import static java.awt.GridBagConstraints.HORIZONTAL; +import static java.awt.GridBagConstraints.NONE; +import static java.awt.GridBagConstraints.NORTHWEST; +import static java.awt.GridBagConstraints.WEST; + +/** + * Class to show toasters in multiplatform + * + * @author daniele piras + */ +public class SparkToaster { + + /** + * The default Hand cursor. + */ + public static final Cursor HAND_CURSOR = new Cursor(Cursor.HAND_CURSOR); + + /** + * The default Text Cursor. + */ + public static final Cursor DEFAULT_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR); + + // Width of the toaster + private int toasterWidth = 200; + + // Height of the toaster + private int toasterHeight = 150; + + // Step for the toaster + private int step = 20; + + // Step time + private int stepTime = 20; + + // Show time + private int displayTime = 3000; + + // Current number of toasters... + private int currentNumberOfToaster = 0; + + // Last opened toaster + private int maxToaster = 0; + + // Font used to display a message + private Font font; + + // Color for a border + private Color borderColor; + + // Color for toaster + private Color toasterColor; + + // Set message color + private Color messageColor; + + // Set the margin + int margin; + + private String title; + private Border border; + + private Action customAction; + private Window window; + private final JPanel mainPanel = new JPanel(); + private TitleLabel titleLabel; + private boolean hideable = true; + + private static final Color COLOR_TOASTER_TITLE = new Color(87, 166, 211); + private static final Color COLOR_TOASTER_BORDER = new Color(245, 153, 15); + private static final Color COLOR_ME_SAYS = Color.MAGENTA; + + public SparkToaster() { + // Set default font... + font = new Font("Dialog", Font.PLAIN, 11); + + // Border color + borderColor = COLOR_TOASTER_BORDER; + toasterColor = Color.WHITE; + messageColor = Color.BLACK; + } + + class SingleToaster extends javax.swing.JWindow { + // Text area for the message + private final JTextArea message = new JTextArea(); + + public SingleToaster() { + initComponents(); + } + + private void initComponents() { + message.setFont(getToasterMessageFont()); + + mainPanel.setBackground(Color.white); + message.setOpaque(false); + mainPanel.setLayout(new GridBagLayout()); + message.setMargin(new Insets(2, 2, 2, 2)); + message.setLineWrap(true); + message.setWrapStyleWord(true); + + message.setForeground(getMessageColor()); + titleLabel = new TitleLabel(getTitle(), true); + titleLabel.setForeground(COLOR_TOASTER_TITLE); + titleLabel.setFont(new Font("Dialog", Font.BOLD, 13)); + + mainPanel.add(titleLabel, new GridBagConstraints(0, 0, 3, 1, 1.0, 0.0, NORTHWEST, HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + + titleLabel.getCloseButton().addActionListener( e -> { + setVisible(false); + dispose(); + } ); + + if (border != null) { + mainPanel.setBorder(border); + } + + message.setForeground(Color.BLACK); + + message.setOpaque(false); + + getContentPane().add(mainPanel); + + + mainPanel.addMouseListener(new PaneMouseListener()); + message.addMouseListener(new PaneMouseListener()); + + pack(); + setSize(toasterWidth, toasterHeight); + mainPanel.setBorder(BorderFactory.createLineBorder(Color.lightGray)); + } + + + /** + * Start toaster animation... + */ + public void animate() { + (new Animation(this)).start(); + } + + private class PaneMouseListener extends MouseAdapter { + + @Override + public void mouseClicked(MouseEvent e) { + if (customAction != null) { + customAction.actionPerformed(null); + } + + if (hideable) { + setVisible(false); + dispose(); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + message.setCursor(HAND_CURSOR); + setCursor(HAND_CURSOR); + } + + @Override + public void mouseExited(MouseEvent e) { + message.setCursor(DEFAULT_CURSOR); + setCursor(DEFAULT_CURSOR); + } + } + } + + + /** + * Class that manage the animation + */ + class Animation extends Thread { + private final SingleToaster toaster; + + public Animation(SingleToaster toaster) { + this.toaster = toaster; + } + + + /** + * Animate vertically the toaster. The toaster could be moved from bottom + * to upper or to upper to bottom + * + * @param posx X position for toaster. + * @param fromY Y from position + * @param toY Y to position + * @throws InterruptedException if animation is interrupted + */ + protected void animateVertically(int posx, int fromY, int toY) throws InterruptedException { + toaster.setLocation(posx, fromY); + if (toY < fromY) { + for (int i = fromY; i > toY; i -= step) { + toaster.setLocation(posx, i); + Thread.sleep(stepTime); + } + } + else { + for (int i = fromY; i < toY; i += step) { + toaster.setLocation(posx, i); + Thread.sleep(stepTime); + } + } + toaster.setLocation(posx, toY); + toaster.invalidate(); + toaster.validate(); + toaster.repaint(); + } + + @Override + public void run() { + try { + boolean animateFromBottom = true; + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + Rectangle screenRect = ge.getMaximumWindowBounds(); + int screenHeight = screenRect.height; + int startYPosition; + int stopYPosition; + if (screenRect.y > 0) { + animateFromBottom = false; // Animate from top! + } + int maxToasterInScreen = screenHeight / toasterHeight; + int posX = screenRect.width - toasterWidth - 1; + toaster.setLocation(posX, screenHeight); + try { + EventQueue.invokeAndWait( () -> toaster.setVisible(true) ); + } + catch(Exception e) + { + Log.error(e); + } + toaster.setAlwaysOnTop(true); + + if (animateFromBottom) { + startYPosition = screenHeight; + stopYPosition = startYPosition - toasterHeight - 1; + if (currentNumberOfToaster > 0) { + stopYPosition = stopYPosition - (maxToaster % maxToasterInScreen * toasterHeight); + } + else { + maxToaster = 0; + } + } + else { + startYPosition = screenRect.y - toasterHeight; + stopYPosition = screenRect.y; + + if (currentNumberOfToaster > 0) { + stopYPosition = stopYPosition + (maxToaster % maxToasterInScreen * toasterHeight); + } + else { + maxToaster = 0; + } + } + + currentNumberOfToaster++; + maxToaster++; + + animateVertically(posX, startYPosition, stopYPosition); + Thread.sleep(displayTime); + animateVertically(posX, stopYPosition, startYPosition); + + currentNumberOfToaster--; + toaster.setVisible(false); + toaster.dispose(); + } + catch (Exception e) { + Log.error(e); + } + } + } + + + /** + * Show a toaster with the specified message and the associated icon. + */ + public void showToaster(Icon icon, String msg) { + SingleToaster singleToaster = new SingleToaster(); + final JScrollPane pane = new JScrollPane(singleToaster.message); + pane.setOpaque(false); + pane.setBorder(BorderFactory.createEmptyBorder()); + pane.getViewport().setBackground(Color.white); + mainPanel.add(pane, new GridBagConstraints(1, 2, 3, 1, 1.0, 1.0, WEST, BOTH, new Insets(2, 5, 2, 5), 0, 0)); + + if (icon != null) { + titleLabel.setIcon(icon); + } + if (ModelUtil.hasLength(msg) && msg.startsWith("/me ")) { + msg = msg.replaceFirst("/me", getTitle()); + singleToaster.message.setForeground(COLOR_ME_SAYS); + } + singleToaster.message.setText(msg); + singleToaster.message.setCaretPosition(0); + singleToaster.animate(); + window = singleToaster; + } + + /** + * Show a toaster with the specified message and the associated icon. + * + * @param title Title to use in toaster popup + * @param comp Component to add to toaster popup + */ + public void showToaster(final String title, final Component comp) { + SingleToaster singleToaster = new SingleToaster(); + mainPanel.add(comp, new GridBagConstraints(1, 2, 3, 1, 1.0, 1.0, WEST, BOTH, new Insets(2, 0, 0, 0), 0, 0)); + + titleLabel.setTitle(title); + singleToaster.animate(); + window = singleToaster; + } + + public void showToaster(Icon icon) { + SingleToaster singleToaster = new SingleToaster(); + if (icon != null) { + titleLabel.setIcon(icon); + } + singleToaster.animate(); + window = singleToaster; + } + + public void showToaster() { + SingleToaster singleToaster = new SingleToaster(); + singleToaster.animate(); + window = singleToaster; + } + + /** + * Show a toaster with the specified message. + * + * @param msg Message to display. + */ + public void showToaster(String msg) { + showToaster(null, msg); + } + + /** + * @return Returns the font + */ + public Font getToasterMessageFont() { + return font; + } + + /** + * Set the font for the message + * + * @param f Font to set on toaster messages. + */ + public void setToasterMessageFont(Font f) { + font = f; + } + + + /** + * @return Returns the borderColor. + */ + public Color getBorderColor() { + return borderColor; + } + + + /** + * @param borderColor The borderColor to set. + */ + public void setBorderColor(Color borderColor) { + this.borderColor = borderColor; + } + + + /** + * @return Returns the displayTime. + */ + public int getDisplayTime() { + return displayTime; + } + + + /** + * @param displayTime The displayTime to set. + */ + public void setDisplayTime(int displayTime) { + this.displayTime = displayTime; + } + + + /** + * @return Returns the margin. + */ + public int getMargin() { + return margin; + } + + + /** + * @param margin The margin to set. + */ + public void setMargin(int margin) { + this.margin = margin; + } + + + /** + * @return Returns the messageColor. + */ + public Color getMessageColor() { + return messageColor; + } + + + /** + * @param messageColor The messageColor to set. + */ + public void setMessageColor(Color messageColor) { + this.messageColor = messageColor; + } + + + /** + * @return Returns the step. + */ + public int getStep() { + return step; + } + + + /** + * @param step The step to set. + */ + public void setStep(int step) { + this.step = step; + } + + + /** + * @return Returns the stepTime. + */ + public int getStepTime() { + return stepTime; + } + + + /** + * @param stepTime The stepTime to set. + */ + public void setStepTime(int stepTime) { + this.stepTime = stepTime; + } + + + /** + * @return Returns the toasterColor. + */ + public Color getToasterColor() { + return toasterColor; + } + + + /** + * @param toasterColor The toasterColor to set. + */ + public void setToasterColor(Color toasterColor) { + this.toasterColor = toasterColor; + } + + + /** + * @return Returns the toasterHeight. + */ + public int getToasterHeight() { + return toasterHeight; + } + + + /** + * @param toasterHeight The toasterHeight to set. + */ + public void setToasterHeight(int toasterHeight) { + this.toasterHeight = toasterHeight; + } + + + /** + * @return Returns the toasterWidth. + */ + public int getToasterWidth() { + return toasterWidth; + } + + + /** + * @param toasterWidth The toasterWidth to set. + */ + public void setToasterWidth(int toasterWidth) { + this.toasterWidth = toasterWidth; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Border getBorder() { + return border; + } + + public void setBorder(Border border) { + this.border = border; + } + + public void setCustomAction(Action action) { + this.customAction = action; + } + + public void setComponent(Component comp) { + mainPanel.add(comp, new GridBagConstraints(1, 2, 3, 1, 1.0, 1.0, WEST, BOTH, new Insets(2, 5, 2, 5), 0, 0)); + } + + public void close() { + if (window != null) { + window.dispose(); + } + } + + public Window getWindow() { + return window; + } + + public void hideTitle() { + titleLabel.setVisible(false); + } + + + static class TitleLabel extends JPanel { + private final JLabel label; + private final RolloverButton closeButton; + + public TitleLabel(String text, final boolean showCloseIcon) { + setLayout(new GridBagLayout()); + label = new JLabel(text); + label.setFont(new Font("Dialog", Font.BOLD, 11)); + label.setHorizontalTextPosition(JLabel.RIGHT); + label.setHorizontalAlignment(JLabel.LEFT); + + add(label, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, WEST, HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + closeButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.Icon.CLOSE_IMAGE)); + + if (showCloseIcon) { + add(closeButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, EAST, NONE, new Insets(5, 5, 5, 5), 0, 0)); + } + + setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.lightGray)); + } + + public void setIcon(Icon icon) { + if (icon.getIconHeight() > Sizes.Toaster.ICON || icon.getIconWidth() > Sizes.Toaster.ICON) { + Image image = ImageCombiner.iconToImage(icon); + label.setIcon(new ImageIcon(image.getScaledInstance(-1, Sizes.Toaster.ICON, Image.SCALE_SMOOTH))); + } else + { + label.setIcon(icon); + } + } + + public RolloverButton getCloseButton() { + return closeButton; + } + + public void setTitle(String title) { + label.setText(title); + } + + public JLabel getLabel() + { + return label; + } + + @Override + public void paintComponent(Graphics g) { + final Image backgroundImage = Default.getImageIcon(Default.TOP_BOTTOM_BACKGROUND_IMAGE).getImage(); + double scaleX = getWidth() / (double)backgroundImage.getWidth(null); + double scaleY = getHeight() / (double)backgroundImage.getHeight(null); + AffineTransform xform = AffineTransform.getScaleInstance(scaleX, scaleY); + ((Graphics2D)g).drawImage(backgroundImage, xform, this); + } + } + + public void setHidable(boolean hideable) { + this.hideable = hideable; + } + + /** + * Simple Example... + * + * @param args Command line args. + */ + public static void main(String[] args) { + SparkToaster toaster = new SparkToaster(); + toaster.setDisplayTime(30000); + toaster.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); + toaster.setTitle(Res.getString("title.notification")); + + JButton button = new JButton("DDD"); + toaster.hideTitle(); + toaster.showToaster("HELLO", button); + + } + + public void setTitleAlert(Font font, Presence presence) { + final Icon presenceIcon = PresenceManager.getIconFromPresence(presence); + titleLabel.setIcon(presenceIcon); + titleLabel.getLabel().setFont(font); + } + +} + diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkItem.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkItem.java similarity index 85% rename from src/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkItem.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkItem.java index 0aff15d19..b14d98ab1 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkItem.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkItem.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,14 +37,13 @@ import org.jivesoftware.spark.util.log.Log; /** - * */ public class BookmarkItem extends JPanel { private static final long serialVersionUID = -3120765894005887305L; - private JLabel imageLabel; - private JLabel nameLabel; - private JLabel descriptionLabel; + private final JLabel imageLabel; + private final JLabel nameLabel; + private final JLabel descriptionLabel; public Action action; @@ -74,7 +69,7 @@ public BookmarkItem() { } public void addURL(final BookmarkedURL bookmark) { - imageLabel.setIcon(SparkRes.getImageIcon(SparkRes.LINK_16x16)); + imageLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.LINK_16x16)); nameLabel.setText(bookmark.getName()); descriptionLabel.setText(bookmark.getURL()); @@ -94,9 +89,9 @@ public void actionPerformed(ActionEvent e) { } public void addConferenceRoom(final BookmarkedConference bookmark) { - imageLabel.setIcon(SparkRes.getImageIcon(SparkRes.CONFERENCE_IMAGE_16x16)); - nameLabel.setText(bookmark.getName()); - descriptionLabel.setText(bookmark.getJid()); + imageLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.CONFERENCE_IMAGE_16x16)); + nameLabel.setText(bookmark.getName() != null && !bookmark.getName().isEmpty() ? bookmark.getName() : bookmark.getJid().getLocalpart().asUnescapedString()); + descriptionLabel.setText(bookmark.getJid().toString()); action = new AbstractAction() { private static final long serialVersionUID = 4324785627112595384L; @@ -116,7 +111,7 @@ public Object construct() { @Override public void finished() { - ConferenceUtils.joinConferenceOnSeperateThread(bookmark.getName(), bookmark.getJid(), bookmark.getPassword()); + ConferenceUtils.joinConferenceOnSeparateThread(bookmark.getName(), bookmark.getJid(), bookmark.getNickname(), bookmark.getPassword()); } }; worker.start(); diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkPlugin.java similarity index 82% rename from src/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkPlugin.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkPlugin.java index 7b6028823..f390ad3a6 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkPlugin.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkPlugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,8 +16,10 @@ package org.jivesoftware.sparkimpl.plugin.bookmarks; import java.awt.event.ActionEvent; -import java.util.Collection; +import java.util.Comparator; +import java.util.List; import java.util.TimerTask; +import java.util.stream.Collectors; import javax.swing.AbstractAction; import javax.swing.Action; @@ -74,7 +72,6 @@ public void finished() { } /** - * */ public void initialize() { final JMenu bookmarkMenu = new JMenu(Res.getString("menuitem.bookmarks")); @@ -126,7 +123,7 @@ public void rescan(JMenu bookmarkMenu) { SparkManager.getMainWindow().getMenu().invalidate(); SparkManager.getMainWindow().getMenu().validate(); SparkManager.getMainWindow().getMenu().repaint(); - } catch (XMPPException | SmackException ex) { + } catch (XMPPException | SmackException | InterruptedException ex) { Log.error(ex); } } @@ -139,7 +136,7 @@ public void rescan(JMenu bookmarkMenu) { public void createMenu(JMenu bookmarkMenu) { try { setBookmarks(bookmarkMenu); - } catch (XMPPException | SmackException ex) { + } catch (XMPPException | SmackException | InterruptedException ex) { Log.error(ex); } } @@ -148,18 +145,23 @@ public void createMenu(JMenu bookmarkMenu) { * loading menu items and setting bookmarks listeners * * @param bookmarkMenu menu Jmenu + * @throws InterruptedException */ - public void setBookmarks(JMenu bookmarkMenu) throws XMPPException, SmackException + public void setBookmarks(JMenu bookmarkMenu) throws XMPPException, SmackException, InterruptedException { BookmarkManager manager = BookmarkManager.getBookmarkManager(SparkManager.getConnection()); if (manager != null) { - Collection bookmarkedConferences = manager.getBookmarkedConferences(); - final Collection bookmarkedLinks = manager.getBookmarkedURLs(); + final List bookmarkedConferences = manager.getBookmarkedConferences() + .stream().sorted(Comparator.comparing(BookmarkedConference::getName, Comparator.nullsFirst(Comparator.naturalOrder()))) + .collect(Collectors.toList()); + final List bookmarkedLinks = manager.getBookmarkedURLs() + .stream().sorted(Comparator.comparing(BookmarkedURL::getName, Comparator.nullsFirst(Comparator.naturalOrder()))) + .collect(Collectors.toList()); - for (Object bookmarkedLink : bookmarkedLinks) { - final BookmarkedURL link = (BookmarkedURL) bookmarkedLink; + for (BookmarkedURL bookmarkedLink : bookmarkedLinks) { + final BookmarkedURL link = bookmarkedLink; Action urlAction = new AbstractAction() { @@ -176,13 +178,13 @@ public void actionPerformed(ActionEvent actionEvent) { }; urlAction.putValue(Action.NAME, link.getName()); - urlAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.LINK_16x16)); + urlAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.LINK_16x16)); bookmarkMenu.add(urlAction); } - - for (Object bookmarkedConference : bookmarkedConferences) { - final BookmarkedConference conferences = (BookmarkedConference) bookmarkedConference; + bookmarkMenu.addSeparator(); + for (BookmarkedConference bookmarkedConference : bookmarkedConferences) { + final BookmarkedConference conferences = bookmarkedConference; Action conferenceAction = new AbstractAction() { @@ -194,7 +196,7 @@ public void actionPerformed(ActionEvent actionEvent) { @Override public void doRun() { - ConferenceUtils.joinConferenceOnSeperateThread(conferences.getName(), conferences.getJid(), conferences.getPassword()); + ConferenceUtils.joinConferenceOnSeparateThread(conferences.getName(), conferences.getJid(), conferences.getNickname(), conferences.getPassword()); } }; @@ -202,8 +204,8 @@ public void doRun() { } }; - conferenceAction.putValue(Action.NAME, conferences.getName()); - conferenceAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.CONFERENCE_IMAGE_16x16)); + conferenceAction.putValue(Action.NAME, conferences.getName() != null && !conferences.getName().isEmpty() ? conferences.getName() : conferences.getJid().getLocalpart().asUnescapedString()); + conferenceAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.CONFERENCE_IMAGE_16x16)); bookmarkMenu.add(conferenceAction); } } diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkUI.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkUI.java similarity index 91% rename from src/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkUI.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkUI.java index b18485ab3..b7b585cf3 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkUI.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/bookmarks/BookmarkUI.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,12 +31,11 @@ import java.awt.event.MouseEvent; /** - * */ public class BookmarkUI extends JPanel { private static final long serialVersionUID = 2724141541874364121L; - private DefaultListModel model; - private JList list; + private final DefaultListModel model; + private final JList list; public BookmarkUI() { @@ -48,8 +43,8 @@ public BookmarkUI() { CollapsiblePane pane = new CollapsiblePane(); pane.setTitle(Res.getString("title.bookmarks")); - model = new DefaultListModel(); - list = new JList(model); + model = new DefaultListModel<>(); + list = new JList<>(model); add(pane, BorderLayout.CENTER); pane.setContentPane(list); @@ -59,7 +54,7 @@ public BookmarkUI() { @Override public void mouseClicked(MouseEvent mouseEvent) { if (mouseEvent.getClickCount() == 2) { - BookmarkItem item = (BookmarkItem)list.getSelectedValue(); + BookmarkItem item = list.getSelectedValue(); item.invokeAction(); } } diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/chat/ChatArgumentsPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/chat/ChatArgumentsPlugin.java new file mode 100644 index 000000000..7f0c25093 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/chat/ChatArgumentsPlugin.java @@ -0,0 +1,68 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.chat; + +import org.jivesoftware.Spark; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.conferences.ConferenceUtils; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Localpart; + +import java.util.Objects; + +/** + * Chat Post Loader. + * Allows users to specify command-line arguments to control Spark on startup. + * + * @author Derek DeMoro + */ +public class ChatArgumentsPlugin implements Plugin { + + @Override + public void initialize() { + String value; + EntityBareJid start_chat_jid = (value = Spark.getArgumentValue("start_chat_jid")) == null ? null + : JidCreate.entityBareFromUnescapedOrThrowUnchecked(Objects.requireNonNull(value)); + EntityBareJid start_chat_muc = (value = Spark.getArgumentValue("start_chat_muc")) == null ? null + : JidCreate.entityBareFromUnescapedOrThrowUnchecked(Objects.requireNonNull(value)); + + if (start_chat_jid != null) { + Localpart nickname = start_chat_jid.getLocalpart(); + SparkManager.getChatManager().createChatRoom(start_chat_jid, nickname.toString(), start_chat_jid.toString()); + } + + if (start_chat_muc != null) { + ConferenceUtils.joinConferenceOnSeparateThread(start_chat_muc, start_chat_muc, null, null); + } + } + + @Override + public void shutdown() { + + } + + @Override + public boolean canShutDown() { + return false; + } + + @Override + public void uninstall() { + // Do nothing. + } +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/chat/ContactListAssistantPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/chat/ContactListAssistantPlugin.java similarity index 81% rename from src/java/org/jivesoftware/sparkimpl/plugin/chat/ContactListAssistantPlugin.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/chat/ContactListAssistantPlugin.java index da620ea51..fece42226 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/chat/ContactListAssistantPlugin.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/chat/ContactListAssistantPlugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +16,7 @@ package org.jivesoftware.sparkimpl.plugin.chat; import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.Default; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.roster.Roster; import org.jivesoftware.smack.roster.RosterEntry; @@ -35,6 +32,7 @@ import org.jivesoftware.spark.util.SwingWorker; import org.jivesoftware.spark.util.UIComponentRegistry; import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; import org.jivesoftware.sparkimpl.settings.local.SettingsManager; @@ -53,7 +51,8 @@ import java.util.List; /** - * Adds extra functionallity to the ContactList. This includes copying and moving of ContactItem. + * Adds extra functionallity to the ContactList. + * This includes copying and moving of ContactItem. */ public class ContactListAssistantPlugin implements Plugin { @@ -75,7 +74,7 @@ public void poppingUp(Object object, final JPopupMenu popup) { final Collection contactItems = Collections.unmodifiableCollection(contactList.getSelectedUsers()); if (!contactItems.isEmpty()) { final List contactGroups = contactList.getContactGroups(); - Collections.sort(contactGroups, ContactList.GROUP_COMPARATOR); + contactGroups.sort(ContactList.GROUP_COMPARATOR); for (final ContactGroup group : contactGroups) { if (group.isUnfiledGroup() || group.isOfflineGroup()) { @@ -130,28 +129,38 @@ public void popupMenuCanceled(PopupMenuEvent popupMenuEvent) { }); int index = -1; - for (int i = 0; i < popup.getComponentCount(); i++) { - Object o = popup.getComponent(i); - if (o instanceof JMenuItem && ((JMenuItem)o).getText().equals(Res.getString("menuitem.rename"))) { - index = i; - break; - } - } + if (!Default.getBoolean(Default.DISABLE_RENAMES) && Enterprise.containsFeature(Enterprise.RENAMES_FEATURE)) { + for (int i = 0; i < popup.getComponentCount(); i++) { + Object o = popup.getComponent(i); + if (o instanceof JMenuItem && ((JMenuItem)o).getText().equals(Res.getString("menuitem.rename"))) { + index = i; + break; + } + } + + } else index = 3; + if (contactItems.size() == 1) { - // Add right after the rename item. + // Add MOVE/COPY options right after the RENAME option or in it's place if it doesn't exist. if (index != -1) { - popup.add(moveToMenu, index + 1); - popup.add(copyToMenu, index + 2); + // See if we should disable the "Move to" and "Copy to" menu options + if (!Default.getBoolean(Default.DISABLE_MOVE_AND_COPY) && Enterprise.containsFeature(Enterprise.MOVE_COPY_FEATURE)) { + popup.add(moveToMenu, index + 1); + popup.add(copyToMenu, index + 2); + } } } else if (contactItems.size() > 1) { - popup.addSeparator(); - popup.add(moveToMenu); - popup.add(copyToMenu); - popup.addSeparator(); + // See if we should disable the "Move to" and "Copy to" menu options + if (!Default.getBoolean(Default.DISABLE_MOVE_AND_COPY) && Enterprise.containsFeature(Enterprise.MOVE_COPY_FEATURE)) { + popup.addSeparator(); + popup.add(moveToMenu); + popup.add(copyToMenu); + } + + // Clean up the extra separator if "Broadcast" menu items are disabled + if (!Default.getBoolean(Default.DISABLE_BROADCAST_MENU_ITEM) && Enterprise.containsFeature(Enterprise.BROADCAST_FEATURE)) popup.addSeparator(); } - - } } @@ -174,7 +183,7 @@ public boolean handleDefaultAction(MouseEvent e) { private boolean isContactItemInGroup(Collection contactItems, ContactGroup group) { boolean contactInGroup = false; for (ContactItem ci : contactItems) { - if (group.getContactItemByJID(ci.getJID(), true) != null) { + if (group.getContactItemByJID(ci.getJid(), true) != null) { contactInGroup = true; break; } @@ -251,19 +260,19 @@ private void updateAvatarsInContactList() { * @param move true if the ContactItem should be moved, otherwise false. */ private void addContactItem(final ContactGroup contactGroup, final ContactItem item, final boolean move) { - ContactItem newContact = UIComponentRegistry.createContactItem(item.getAlias(), item.getNickname(), item.getJID()); + ContactItem newContact = UIComponentRegistry.createContactItem(item.getAlias(), item.getNickname(), item.getJid()); newContact.setPresence(item.getPresence()); newContact.setIcon(item.getIcon()); newContact.getNicknameLabel().setFont(item.getNicknameLabel().getFont()); boolean groupHadAvailableContacts = false; // Do not copy/move a contact item only if it is not already in the Group. - if (contactGroup.getContactItemByJID(item.getJID(), true) != null) { + if (contactGroup.getContactItemByJID(item.getJid().asBareJid(), true) != null) { return; } - if (!PresenceManager.isOnline(item.getJID())) { - contactGroup.addOfflineContactItem(item.getAlias(), item.getNickname(), item.getJID(), null); + if (!PresenceManager.isOnline(item.getJid().asBareJid())) { + contactGroup.addOfflineContactItem(item.getAlias(), item.getNickname(), item.getJid(), null); } else { groupHadAvailableContacts = contactGroup.hasAvailableContacts(); @@ -279,8 +288,8 @@ private void addContactItem(final ContactGroup contactGroup, final ContactItem i SwingWorker worker = new SwingWorker() { @Override public Object construct() { - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - RosterEntry entry = roster.getEntry(item.getJID()); + Roster roster = SparkManager.getRoster(); + RosterEntry entry = roster.getEntry(item.getJid().asBareJid()); RosterGroup groupFound = null; @@ -294,7 +303,7 @@ public Object construct() { } group.addEntry(entry); } - catch (XMPPException | SmackException e1) { + catch (XMPPException | SmackException | InterruptedException e1) { Log.error(e1); return false; } @@ -311,7 +320,7 @@ public Object construct() { SparkManager.getContactList().toggleGroupVisibility(groupFound.getName(), true); } } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error(e); } } @@ -350,8 +359,8 @@ public boolean removeContactItem(ContactGroup contactGroup, ContactItem item) { } // Remove entry from Roster Group - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - RosterEntry entry = roster.getEntry(item.getJID()); + Roster roster = SparkManager.getRoster(); + RosterEntry entry = roster.getEntry(item.getJid().asBareJid()); RosterGroup rosterGroup = null; @@ -361,7 +370,7 @@ public boolean removeContactItem(ContactGroup contactGroup, ContactItem item) { rosterGroup = group; group.removeEntry(entry); } - catch (XMPPException | SmackException e1) { + catch (XMPPException | SmackException | InterruptedException e1) { return false; } } diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/chat/PresenceChangePlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/chat/PresenceChangePlugin.java new file mode 100644 index 000000000..fe5c542e4 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/chat/PresenceChangePlugin.java @@ -0,0 +1,208 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.chat; + +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.util.*; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.JPopupMenu; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.filter.StanzaTypeFilter; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.ContextMenuListener; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.spark.ui.ContactList; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; + +/** + * Presence Change Plugin. + * Tracks users presenences during the runtime of Spark. + * Allows users to place activity listeners on individual users. + * This class notifies users when other users come from away or offline to available. + * + * @author Derek DeMoro + */ +public class PresenceChangePlugin implements Plugin { + + private final Set sparkContacts = new HashSet<>(); + private final LocalPreferences localPref = SettingsManager.getLocalPreferences(); + + @Override + public void initialize() { + // Listen for right-clicks on ContactItem + ContactList contactList = SparkManager.getWorkspace().getContactList(); + Action listenAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + for (ContactItem item : contactList.getSelectedUsers()) { + BareJid bareAddress = item.getJid().asBareJid(); + sparkContacts.add(bareAddress); + } + } + }; + + listenAction.putValue(Action.NAME, Res.getString("menuitem.alert.when.online")); + listenAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_ALARM_CLOCK)); + + Action removeAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + for (ContactItem item : contactList.getSelectedUsers()) { + BareJid bareAddress = item.getJid().asBareJid(); + sparkContacts.remove(bareAddress); + } + } + }; + + removeAction.putValue(Action.NAME, Res.getString("menuitem.remove.alert.when.online")); + removeAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_DELETE)); + contactList.addContextMenuListener(new ContextMenuListener() { + @Override + public void poppingUp(Object object, JPopupMenu popup) { + if (!(object instanceof ContactItem)) { + return; + } + ContactItem item = (ContactItem) object; + BareJid bareAddress = item.getJid(); + // Add actions to the popup based on contact availability + if (!item.getPresence().isAvailable() || item.getPresence().isAway()) { + if (sparkContacts.contains(bareAddress)) { + popup.add(removeAction); + } else { + popup.add(listenAction); + } + } + } + + @Override + public void poppingDown(JPopupMenu popup) { + } + + @Override + public boolean handleDefaultAction(MouseEvent e) { + return false; + } + }); + + // Check presence changes + SparkManager.getConnection().addAsyncStanzaListener(stanza -> { + try { + Presence presence = (Presence) stanza; + if (!presence.isAvailable() || presence.isAway()) { + return; + } + BareJid from = presence.getFrom().asBareJid(); + List removeLater = new ArrayList<>(); + for (BareJid jid : sparkContacts) { + if (!jid.equals(from)) { + continue; + } + removeLater.add(jid); + // sparkContacts.remove(jid); + String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid); + String time = SparkManager.DATE_SECOND_FORMATTER.format(new Date()); + String infoText = Res.getString("message.user.now.available.to.chat", nickname, time); + if (localPref.getShowToasterPopup()) { + EventQueue.invokeLater(() -> + { + showToaster(nickname, infoText, jid.asEntityBareJidOrThrow()); + }); + } + + ChatRoom room = SparkManager.getChatManager().getChatRoom(jid.asEntityBareJidOrThrow()); + if (localPref.getWindowTakesFocus()) { + EventQueue.invokeLater(() -> SparkManager.getChatManager().activateChat(jid, nickname)); + } + EventQueue.invokeLater(() -> room.getTranscriptWindow().insertNotificationMessage(infoText, ChatManager.NOTIFICATION_COLOR)); + } + for (BareJid s : removeLater) { + sparkContacts.remove(s); + } + } catch (Exception ex) { + Log.error(ex); + } + }, new StanzaTypeFilter(Presence.class)); + } + + /** + * Show contact status change via popup notification + */ + private static void showToaster(String nickname, String infoText, EntityBareJid chatRoomJid) { + SparkToaster toaster = new SparkToaster(); + toaster.setDisplayTime(5000); + toaster.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); + + toaster.setToasterHeight(150); + toaster.setToasterWidth(200); + + toaster.setTitle(nickname); + toaster.showToaster(null, infoText); + + toaster.setCustomAction(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + SparkManager.getChatManager().getChatRoom(chatRoomJid); + } + }); + } + + @Override + public void shutdown() { + } + + @Override + public boolean canShutDown() { + return true; + } + + @Override + public void uninstall() { + } + + public void addWatch(Jid user) { + BareJid bareAddress = user.asBareJid(); + sparkContacts.add(bareAddress); + } + + public void removeWatch(Jid user) { + BareJid bareAddress = user.asBareJid(); + sparkContacts.remove(bareAddress); + } + + public boolean getWatched(Jid user) { + BareJid bareAddress = user.asBareJid(); + return sparkContacts.contains(bareAddress); + } + +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/chat/ShortcutPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/chat/ShortcutPlugin.java similarity index 82% rename from src/java/org/jivesoftware/sparkimpl/plugin/chat/ShortcutPlugin.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/chat/ShortcutPlugin.java index 9d7efa8ad..36c50c056 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/chat/ShortcutPlugin.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/chat/ShortcutPlugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,28 +25,33 @@ import java.awt.Color; /** - * The ShortcutPlugin is used to handle IRC-style shortcuts. + * Adds simple IRC style shortcuts. */ public class ShortcutPlugin implements Plugin, TranscriptWindowInterceptor { - public void initialize() { + @Override + public void initialize() { // Add TranscriptWindowInterceptor SparkManager.getChatManager().addTranscriptWindowInterceptor(this); } - public void shutdown() { + @Override + public void shutdown() { } - public boolean canShutDown() { + @Override + public boolean canShutDown() { return false; } - public void uninstall() { + @Override + public void uninstall() { } - public boolean isMessageIntercepted(TranscriptWindow window, String userid, Message message) { + @Override + public boolean isMessageIntercepted(TranscriptWindow window, String userid, Message message) { String body = message.getBody(); if (ModelUtil.hasLength(body) && body.startsWith("/me ")) { body = body.replaceFirst("/me", userid); diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/emoticons/Emoticon.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/emoticons/Emoticon.java similarity index 93% rename from src/java/org/jivesoftware/sparkimpl/plugin/emoticons/Emoticon.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/emoticons/Emoticon.java index c107817a8..3470e311d 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/emoticons/Emoticon.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/emoticons/Emoticon.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +15,6 @@ */ package org.jivesoftware.sparkimpl.plugin.emoticons; -import java.util.ArrayList; import java.util.List; import java.io.File; @@ -32,8 +27,8 @@ public class Emoticon { private String imageName; private String emoticonName; - private File emoticonDirectory; - private List equivalants = new ArrayList<>(); + private final File emoticonDirectory; + private final List equivalants; /** diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonManager.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonManager.java new file mode 100644 index 000000000..fd0b5ac42 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonManager.java @@ -0,0 +1,574 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.emoticons; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Node; +import org.dom4j.io.SAXReader; +import org.jivesoftware.Spark; +import org.jivesoftware.spark.util.StringUtils; +import org.jivesoftware.spark.util.URLFileSystem; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.xml.sax.SAXException; + +import javax.swing.ImageIcon; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.*; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.zip.ZipFile; + +import static java.util.Arrays.asList; + +/** + * Responsible for the handling of all Emoticon packs. Using the + * EmoticonManager, you can specify any defined Emoticon Pack, retrieve any + * emoticon based on its text equivalent, and retrieve its associated image url. + * + * @author Derek DeMoro + */ +public class EmoticonManager { + private static EmoticonManager singleton; + private static final Object LOCK = new Object(); + + // Mapped by pack name, then by 'equivalent' key. + private final Map> emoticonMap = new HashMap<>(); + private final Map imageMap = new HashMap<>(); + + /** + * The root emoticon directory. + */ + public static File EMOTICON_DIRECTORY; + + private final LocalPreferences pref = SettingsManager.getLocalPreferences(); + + /** + * Returns the singleton instance of EmoticonManager. + */ + public static EmoticonManager getInstance() { + // Synchronize on LOCK to ensure that we don't end up creating + // two singletons. + synchronized (LOCK) { + if (null == singleton) { + EmoticonManager controller = new EmoticonManager(); + singleton = controller; + return controller; + } + } + return singleton; + } + + /** + * Initialize the EmoticonManager + */ + private EmoticonManager() { + EMOTICON_DIRECTORY = new File(Spark.getBinDirectory().getParent(), + "xtra/emoticons").getAbsoluteFile(); + + File[] files; + files = EMOTICON_DIRECTORY.listFiles(); + + // If files in this directory, copy these files into the Spark User Home + // Directory + if (files != null) { + // Copy over to allow for non-admins to extract. + copyFiles(); + String emoticonPack = pref.getEmoticonPack(); + try { + addEmoticonPack(emoticonPack); + } catch (Exception e) { + Log.error(e); + } + } + } + + /** + * Copy the files directly over to an accepted permissions directory. + */ + private void copyFiles() { + // Current Plugin directory + File newEmoticonDir = new File(Spark.getLogDirectory().getParentFile(), + "xtra/emoticons").getAbsoluteFile(); + newEmoticonDir.mkdirs(); + deleteOldEmoticons(newEmoticonDir); + + File[] files = EMOTICON_DIRECTORY.listFiles(); + for (File file : files) { + if (file.isFile()) { + try { + // Copy over + File newFile = new File(newEmoticonDir, file.getName()); + + // Check timestamps + long installerFile = file.lastModified(); + long copiedFile = newFile.lastModified(); + if (installerFile > copiedFile) { + // Check if File is Zip-File + int endIndex = file.getName().indexOf(".zip"); + if (endIndex > 0) { + String unzipURL = file.getName().substring(0, endIndex); + File unzipFile = new File(newEmoticonDir, unzipURL); + + if (!unzipFile.exists() || !checkIfSameFile(file, newFile)) { + // Copy over and expand :) + URLFileSystem.copy(file.toURI().toURL(), newFile); + expandNewPack(newFile, newEmoticonDir); + } + } + } + } catch (IOException e) { + Log.error(e); + } + } + } + EMOTICON_DIRECTORY = newEmoticonDir; + } + + private boolean checkIfSameFile(File oldZip, File newZip) { + boolean result = true; + + ZipFile oldZipFile = null; + ZipFile newZipFile = null; + try { + oldZipFile = new JarFile(oldZip); + newZipFile = new JarFile(newZip); + if (oldZipFile.size() == newZipFile.size()) { + for (Enumeration e = newZipFile.entries(); e.hasMoreElements(); ) { + JarEntry entry = (JarEntry) e.nextElement(); + if (oldZipFile.getEntry(entry.getName()) == null || + entry.hashCode() != oldZipFile.getEntry(entry.getName()).hashCode()) { + result = false; + break; + } + } + } else { + result = false; + } + } catch (IOException e) { + Log.error(e); + } + closeFile(newZipFile); + closeFile(oldZipFile); + return result; + } + + private void closeFile(ZipFile zipFile) { + try { + if (zipFile != null) { + zipFile.close(); + } + } catch (IOException e) { + Log.error(e); + } + } + + /** + * Returns the active emoticon set within Spark. + */ + public Collection getActiveEmoticonSet() { + String emoticonPack = pref.getEmoticonPack(); + // If EmoticonPack is set + //When no emoticon set is available, return an empty list + if (emoticonPack != null) { + Map emoticons = emoticonMap.get(emoticonPack); + Collection empty = List.of(); + return emoticons == null ? empty : new LinkedHashSet<>(emoticons.values()); + } + return Collections.emptyList(); + } + + /** + * Returns the name of the active emoticon set. + */ + public String getActiveEmoticonSetName() { + return pref.getEmoticonPack(); + } + + /** + * Sets the active emoticon set. + * + * @param pack the archive containing the emoticon pack. + */ + public void setActivePack(String pack) { + pref.setEmoticonPack(pack); + imageMap.clear(); + } + + /** + * Installs a new Adium style emoticon pack into Spark. + * + * @param pack the emoticon pack (contains Emotiocons.plist) + * @return the name of the newly installed emoticon set. + */ + public String installPack(File pack) { + if (!containsEmoticonPList(pack)) { + return null; + } + + String name; + // Copy to the emoticon area + try { + File dst = new File(EMOTICON_DIRECTORY, pack.getName()); + URLFileSystem.copy(pack.toURI().toURL(), dst); + + File rootDirectory = unzipPack(pack, EMOTICON_DIRECTORY); + name = URLFileSystem.getName(rootDirectory.toURI().toURL()); + addEmoticonPack(name); + } catch (IOException e) { + Log.error(e); + return null; + } + return name; + } + + /** + * Loads an emoticon set. + * + * @param packName the name of the pack. + */ + public void addEmoticonPack(String packName) { + File emoticonSet = new File(EMOTICON_DIRECTORY, packName + ".adiumemoticonset"); + if (!emoticonSet.exists()) { + emoticonSet = new File(EMOTICON_DIRECTORY, packName + ".AdiumEmoticonset"); + } + + if (!emoticonSet.exists()) { + emoticonSet = new File(EMOTICON_DIRECTORY, "Default.adiumemoticonset"); + packName = "Default"; + setActivePack("Default"); + } + + final File plist = new File(emoticonSet, "Emoticons.plist"); + if (!plist.exists()) { + Log.error("Emoticons.plist not found in " + emoticonSet.getAbsolutePath()); + return; + } + Map emoticons = new LinkedHashMap<>(); + + // Create SaxReader and set to non-validating parser. + // This will allow for non-http problems to not break spark :) + final SAXReader saxParser = SAXReader.createDefault(); + saxParser.setValidation(false); + try { + saxParser.setFeature("http://xml.org/sax/features/validation", false); + saxParser.setFeature("http://xml.org/sax/features/namespaces", false); + saxParser.setFeature("http://apache.org/xml/features/validation/schema", false); + saxParser.setFeature("http://apache.org/xml/features/validation/schema-full-checking", false); + saxParser.setFeature("http://apache.org/xml/features/validation/dynamic", false); + saxParser.setFeature("http://apache.org/xml/features/allow-java-encodings", true); + saxParser.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true); + saxParser.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false); + } catch (SAXException e) { + Log.error(e); + return; + } + + Document emoticonFile; + try { + emoticonFile = saxParser.read(plist); + } catch (DocumentException e) { + Log.error(e); + return; + } + + Node root = emoticonFile.selectSingleNode("/plist/dict/dict"); + List keyList = root.selectNodes("key"); + List dictonaryList = root.selectNodes("dict"); + Iterator dicts = dictonaryList.iterator(); + for (Node keyEntry : keyList) { + String key = keyEntry.getText(); + Node dict = dicts.next(); + String name = dict.selectSingleNode("string").getText(); + // Load equivalents + final List equivalents = dict.selectNodes("array/string"); + final List equivs = new ArrayList<>(equivalents.size()); + for (Node equivalent : equivalents) { + equivs.add(equivalent.getText()); + } + final Emoticon emoticon = new Emoticon(key, name, equivs, emoticonSet); + for (String equivalent : emoticon.getEquivalants()) { + emoticons.put(equivalent, emoticon); + } + } + emoticonMap.put(packName, emoticons); + } + + /** + * Retrieve the URL to an emoticon. + * + * @param emoticon the emoticon. + * @return the URL of the image. + */ + public URL getEmoticonURL(Emoticon emoticon) { + final String imageName = emoticon.getImageName(); + File file = new File(emoticon.getEmoticonDirectory(), imageName); + try { + return file.toURI().toURL(); + } catch (MalformedURLException ignored) { + } + return null; + } + + /** + * Retrieves the associated key emoticon. + * + * @param packName the name of the Archive Pack File. + * @param key the key. + * @return the emoticon. + */ + public Emoticon getEmoticon(String packName, String key) { + final Map emoticons = emoticonMap.get(packName); + if (emoticons == null) { + return null; + } + return emoticons.get(key); + } + + /** + * Returns the Emoticon associated with the given key. Note: + * This gets the emoticon from the active emoticon pack. + * + * @param key the key. + * @return the Emoticon found. If no emoticon is found, null is returned. + */ + public Emoticon getEmoticon(String key) { + return getEmoticon(getActiveEmoticonSetName(), key); + } + + /** + * Returns the Icon that is mapped to a given key. + * + * @param key the key to search for. + * @return the Icon representing the key. + */ + public ImageIcon getEmoticonImage(String key) { + final Emoticon emoticon = getEmoticon(key); + if (emoticon != null) { + ImageIcon icon = imageMap.get(key); + if (icon == null) { + URL url = getEmoticonURL(emoticon); + icon = new ImageIcon(url); + imageMap.put(key, icon); + } + return imageMap.get(key); + } + return null; + } + + /** + * Returns a list of all available emoticon packs. + * + * @return Collection of Emoticon Pack names. + */ + public Collection getEmoticonPacks() { + final List emoticonList = new ArrayList<>(); + File[] dirs = EMOTICON_DIRECTORY.listFiles(); + // If no emoticons are available + if (dirs == null) { + return null; + } + + for (File file : dirs) { + if (file.isDirectory() + && file.getName().toLowerCase().endsWith("adiumemoticonset")) { + try { + String name = URLFileSystem.getName(file.toURI().toURL()); + name = name.replaceAll("adiumemoticonset", ""); + name = name.replaceAll("AdiumEmoticonset", ""); + emoticonList.add(name); + } catch (MalformedURLException ignored) { + } + } + } + return emoticonList; + } + + /** + * Expands any zipped Emoticon Packs. + * + * @param file File to unpack. + * @param dist Dist file. + */ + private void expandNewPack(File file, File dist) { + URL url; + try { + url = file.toURI().toURL(); + } catch (MalformedURLException ignored) { + return; + } + String name = URLFileSystem.getName(url); + File directory = new File(dist, name); + + // Unzip contents into directory + unzipPack(file, directory.getParentFile()); + } + + /** + * Checks the zip file for the Emoticons.plist file. This is Sparks way of + * detecting a valid file. + * + * @param zip the zip file to check. + * @return true if the EmoticonPlist exists in the archive. + */ + private boolean containsEmoticonPList(File zip) { + ZipFile zipFile = null; + boolean result = false; + try { + zipFile = new JarFile(zip); + for (Enumeration e = zipFile.entries(); e.hasMoreElements(); ) { + JarEntry entry = (JarEntry) e.nextElement(); + if (entry.getName().contains("Emoticons.plist")) { + result = true; + break; + } + } + } catch (IOException e) { + Log.error(e); + } + closeFile(zipFile); + return result; + } + + /** + * Unzips a theme from a ZIP file into a directory. + * + * @param zip the ZIP file + * @param dir the directory to extract the plugin to. + * @return the root directory. + */ + private File unzipPack(File zip, File dir) { + File rootDirectory = null; + try { + ZipFile zipFile = new JarFile(zip); + dir.mkdir(); + for (Enumeration e = zipFile.entries(); e.hasMoreElements(); ) { + JarEntry entry = (JarEntry) e.nextElement(); + File entryFile = new File(dir, entry.getName()); + + //Fix Zip Slip Vulnerability + if (!entryFile.toPath().normalize().startsWith(dir.toPath().normalize())) { + throw new RuntimeException("Bad zip entry"); + } + + // Ignore any manifest.mf entries. + if (entry.getName().toLowerCase().endsWith("manifest.mf")) { + continue; + } + + if (entry.isDirectory() && rootDirectory == null) { + rootDirectory = entryFile; + } + + // Extract non‑directory entries from ZIP to filesystem + if (!entry.isDirectory()) { + entryFile.getParentFile().mkdirs(); + FileOutputStream out = new FileOutputStream(entryFile); + InputStream zin = zipFile.getInputStream(entry); + byte[] b = new byte[512]; + int len; + while ((len = zin.read(b)) != -1) { + out.write(b, 0, len); + } + out.flush(); + out.close(); + zin.close(); + } + } + zipFile.close(); + } catch (Exception e) { + Log.error("Error unzipping emoticon pack", e); + } + return rootDirectory; + } + + /** + * Deletes Emoticons in pathToSearch that have a different md5-hash than its correspondant in install\spark\xtra\emoticons + */ + private void deleteOldEmoticons(File pathToSearch) { + final String installPath = Spark.getBinDirectory().getParentFile() + File.separator + "xtra" + File.separator + + "emoticons" + File.separator; + final File[] files = new File(installPath).listFiles(); + final List installerFiles; + if (files == null) { + installerFiles = List.of(); + } else { + installerFiles = asList(files); + } + + final File[] installedEmoticons = pathToSearch.listFiles(File::isDirectory); + if (installedEmoticons == null) { + return; + } + + for (final File file : installedEmoticons) { + final File zipFile = new File(pathToSearch, file.getName() + ".zip"); + if (!zipFile.exists()) { + uninstall(file); + } else { + try { + final File f = new File(installPath + zipFile.getName()); + // Compare old and new files by checksums + if (installerFiles.contains(f)) { + final String oldfile = StringUtils.getMD5Checksum(zipFile.getAbsolutePath()); + final String newfile = StringUtils.getMD5Checksum(f.getAbsolutePath()); + if (!oldfile.equals(newfile)) { + Log.debug("deleting: " + file.getAbsolutePath() + "," + zipFile.getAbsolutePath()); + uninstall(file); + zipFile.delete(); + } + } + } catch (Exception e) { + Log.error("No such file", e); + } + } + } + } + + private void uninstall(File emoticonDir) { + try { + Files.walkFileTree(emoticonDir.toPath(), new SimpleFileVisitor<>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + Log.error("An unexpected exception occurred while trying to uninstall a emoticon from: " + emoticonDir, e); + } + } + +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonPlugin.java similarity index 83% rename from src/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonPlugin.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonPlugin.java index d9b07c16d..cb0efb004 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonPlugin.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonPlugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,6 +15,7 @@ */ package org.jivesoftware.sparkimpl.plugin.emoticons; +import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.Collection; @@ -30,6 +27,7 @@ import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.component.RolloverButton; import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.ChatContainer; import org.jivesoftware.spark.ui.ChatInputEditor; import org.jivesoftware.spark.ui.ChatRoom; import org.jivesoftware.spark.ui.ChatRoomListener; @@ -39,13 +37,18 @@ import org.jivesoftware.sparkimpl.settings.local.SettingsManager; /** + * Emoticon Plugin. * Adds an EmoticonPickList to each ChatRoom. + * Allows users to use a pick list for Emoticons. + * + * @author Derek DeMoro */ public class EmoticonPlugin implements Plugin, ChatRoomListener { private EmoticonManager emoticonManager; private ChatManager chatManager; + @Override public void initialize() { emoticonManager = EmoticonManager.getInstance(); chatManager = SparkManager.getChatManager(); @@ -64,6 +67,7 @@ private void addChatRoomListener() { .addPreference(new ThemePreference()); } + @Override public void chatRoomOpened(final ChatRoom room) { // Check to see if emoticons are enabled. if (!SettingsManager.getLocalPreferences().areEmoticonsEnabled()) { @@ -85,6 +89,7 @@ public void chatRoomOpened(final ChatRoom room) { room.addEditorComponent(emoticonPicker); emoticonPicker.addMouseListener(new MouseAdapter() { + @Override public void mouseClicked(MouseEvent e) { // Show popup final JPopupMenu popup = new JPopupMenu(); @@ -109,7 +114,15 @@ public void mouseClicked(MouseEvent e) { } ); popup.add(emoticonUI); - popup.show(emoticonPicker, e.getX(), e.getY()); + int actualX = e.getX()+10; + int actualY = e.getY(); + final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + final ChatContainer chat = SparkManager.getChatManager().getChatContainer(); + // if height Spark Chat Windows > height 0.9* screenSize we should put emoticon window above + if(chat.getHeight() > screenSize.getHeight()*0.90){ + actualY = e.getY()-100; + } + popup.show(emoticonPicker, actualX, actualY); } }); @@ -117,29 +130,17 @@ public void mouseClicked(MouseEvent e) { } } - public void chatRoomLeft(ChatRoom room) { - } - - public void chatRoomClosed(ChatRoom room) { - } - - public void chatRoomActivated(ChatRoom room) { - } - - public void userHasJoined(ChatRoom room, String userid) { - } - - public void userHasLeft(ChatRoom room, String userid) { - } - + @Override public void shutdown() { } + @Override public boolean canShutDown() { return false; } + @Override public void uninstall() { // Do nothing. } diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonUI.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonUI.java similarity index 98% rename from src/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonUI.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonUI.java index fde0503ca..fc873b9a4 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonUI.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonUI.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/Downloads.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/Downloads.java similarity index 95% rename from src/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/Downloads.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/Downloads.java index 92f81574b..57aa80055 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/Downloads.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/Downloads.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -54,9 +50,8 @@ public static File getDownloadDirectory() { } /** - * Check if the downloaddirectory is accessable and throws exceptions if not + * Check if the download directory is accessible and throws exceptions if not * - * @param downloadDir * @throws FileNotFoundException if the directory not exist * @throws SecurityException if user hasn't permissions to write to the directory * @throws NullPointerException if the directory is not set in preferences diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/ReceiveFileTransfer.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/ReceiveFileTransfer.java new file mode 100644 index 000000000..bc7ae9eec --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/ReceiveFileTransfer.java @@ -0,0 +1,827 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.filetransfer.transfer.ui; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Desktop; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.*; +import java.util.Timer; + +import javax.swing.*; + +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smackx.filetransfer.FileTransfer; +import org.jivesoftware.smackx.filetransfer.FileTransferNegotiator; +import org.jivesoftware.smackx.filetransfer.FileTransferRequest; +import org.jivesoftware.smackx.filetransfer.IncomingFileTransfer; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.FileDragLabel; +import org.jivesoftware.spark.filetransfer.preferences.FileTransferPreference; +import org.jivesoftware.spark.preference.Preference; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.spark.ui.ContactList; +import org.jivesoftware.spark.util.ByteFormat; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.URLFileSystem; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.filetransfer.transfer.Downloads; + +import org.jivesoftware.sparkimpl.settings.Sizes; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.Jid; + +public class ReceiveFileTransfer extends JPanel { + + private static final long serialVersionUID = -2974192409566650923L; + private final FileDragLabel imageLabel = new FileDragLabel(); + private final JLabel titleLabel = new JLabel(); + private final JLabel fileLabel = new JLabel(); + + private final TransferButton acceptButton = new TransferButton(Res.getString("accept"), SparkRes.getImageIcon(SparkRes.Icon.ACCEPT_INVITE_IMAGE)); + private final TransferButton declineButton = new TransferButton(Res.getString("reject"), SparkRes.getImageIcon(SparkRes.Icon.REJECT_INVITE_IMAGE)); + private final TransferButton pathButton = new TransferButton(Res.getString("message.file.transfer.direrror.setdir"), SparkRes.getImageIcon(SparkRes.Icon.SETTINGS_IMAGE_16x16)); + private final JProgressBar progressBar = new JProgressBar(); + private IncomingFileTransfer transfer; + private final TransferButton cancelButton = new TransferButton(); + private final JLabel progressLabel = new JLabel(); + private long bytesRead; + private long startTime; + private long endTime; + private final ChatRoom chatRoom; + private String nickname; + private String fileName; + + public ReceiveFileTransfer(ChatRoom chatRoom) { + this.chatRoom = chatRoom; + setLayout(new GridBagLayout()); + + setBackground(new Color(250, 249, 242)); + add(imageLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + + add(titleLabel, new GridBagConstraints(1, 0, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + titleLabel.setFont(new Font("Dialog", Font.BOLD, 11)); + titleLabel.setForeground(new Color(211, 174, 102)); + add(fileLabel, new GridBagConstraints(1, 1, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0)); + + add(acceptButton, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); + add(pathButton, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); + pathButton.setVisible(false); + add(declineButton, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); + + // Decorate Cancel Button + decorateCancelButton(); + + pathButton.setForeground(new Color(73, 113, 196)); + acceptButton.setForeground(new Color(73, 113, 196)); + declineButton.setForeground(new Color(73, 113, 196)); + pathButton.setFont(new Font("Dialog", Font.BOLD, 11)); + declineButton.setFont(new Font("Dialog", Font.BOLD, 11)); + acceptButton.setFont(new Font("Dialog", Font.BOLD, 11)); + + acceptButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196))); + declineButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196))); + + setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.white)); + + pathButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + pathButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + pathButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + }); + + acceptButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + acceptButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + acceptButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + }); + + declineButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + declineButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + declineButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + }); + } + + public void acceptFileTransfer(final FileTransferRequest request) { + fileName = request.getFileName(); + long fileSize = request.getFileSize(); + Jid requestor = request.getRequestor(); + BareJid bareJID = requestor.asBareJid(); + //SPARK-1869 + FileTransferNegotiator.getInstanceFor(SparkManager.getConnection()); + FileTransferNegotiator.IBB_ONLY = SettingsManager.getLocalPreferences().isFileTransferIbbOnly(); + + ByteFormat format = new ByteFormat(); + String fileSizeString = format.format(fileSize); + + fileLabel.setText(fileName + " (" + fileSizeString + ")"); + + ContactList contactList = SparkManager.getWorkspace().getContactList(); + ContactItem contactItem = contactList.getContactItemByJID(bareJID); + nickname = contactItem.getDisplayName(); + + saveEventToHistory(bareJID, Res.getString("message.file.transfer.history.request.received", fileName, fileSizeString, nickname)); + titleLabel.setText(Res.getString("message.user.is.sending.you.a.file", nickname)); + + File tempFile = new File(Spark.getSparkUserHome(), "/tmp"); + try { + tempFile.mkdirs(); + + File file = new File(tempFile, fileName); + file.delete(); + BufferedWriter out = new BufferedWriter(new FileWriter(file)); + out.write("a"); + out.close(); + + imageLabel.setIcon(GraphicUtils.getIcon(file)); + + // Delete temp file when program exits. + file.delete(); + } catch (IOException e) { + imageLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.DOCUMENT_INFO_32x32)); + Log.error("An exception occurred while accepting a file transfer.", e); + } + + if (SettingsManager.getLocalPreferences().isAutoAcceptFileTransferFromContacts()) { + final Roster roster = SparkManager.getRoster(); + if (roster.isSubscribedToMyPresence(requestor)) { + doAccept(request); + return; + } + } + acceptButton.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + doAccept(request); + } + }); + + declineButton.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + doReject(request); + } + }); + } + + private void doAccept(FileTransferRequest request) { + Jid requestor = request.getRequestor(); + BareJid bareJID = requestor.asBareJid(); + saveEventToHistory(bareJID, Res.getString("message.file.transfer.history.you.accepted", fileName, nickname)); + try { + Downloads.checkDownloadDirectory(); + acceptRequest(request); + } catch (Exception ex) { + // this means there is a problem with the download directory + saveEventToHistory(bareJID, Res.getString("message.file.transfer.history.receive.failed", fileName, nickname)); + try { + request.reject(); + } catch (SmackException.NotConnectedException | InterruptedException e1) { + Log.warning("Unable to reject the request.", ex); + } + + setBackground(new Color(239, 245, 250)); + acceptButton.setVisible(false); + declineButton.setVisible(false); + if (Downloads.getDownloadDirectory() == null) { + fileLabel.setText(""); + } else { + ResourceUtils.resLabel(fileLabel, null, Res.getString("label.transfer.download.directory") + + " " + Downloads.getDownloadDirectory().getAbsolutePath()); + } + + // option to set a new path for the file-download + pathButton.setVisible(true); + pathButton.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + Preference p = SparkManager.getPreferenceManager().getPreference( + new FileTransferPreference().getNamespace()); + // retrieve the file transfer preferences and show the preference menu + // to the user + SparkManager.getPreferenceManager().showPreferences(p); + } + }); + + titleLabel.setText(ex.getMessage()); + titleLabel.setForeground(new Color(65, 139, 179)); + + invalidate(); + validate(); + repaint(); + } + } + + private void doReject(FileTransferRequest request) { + Jid requestor = request.getRequestor(); + BareJid bareJID = requestor.asBareJid(); + saveEventToHistory(bareJID, Res.getString("message.file.transfer.history.you.rejected", fileName, nickname)); + rejectRequest(request); + } + + private void rejectRequest(FileTransferRequest request) { + try { + request.reject(); + } catch (SmackException.NotConnectedException | InterruptedException ex) { + Log.warning("Unable to reject the request.", ex); + } + setBackground(new Color(239, 245, 250)); + acceptButton.setVisible(false); + declineButton.setVisible(false); + fileLabel.setText(""); + titleLabel.setText(Res.getString("message.file.transfer.canceled")); + titleLabel.setForeground(new Color(65, 139, 179)); + + invalidate(); + validate(); + repaint(); + } + + private void acceptRequest(final FileTransferRequest request) { + Jid requester = request.getRequestor(); + BareJid bareJID = requester.asBareJid(); + + ContactList contactList = SparkManager.getWorkspace().getContactList(); + final ContactItem contactItem = contactList + .getContactItemByJID(bareJID); + + setBackground(new Color(239, 245, 250)); + acceptButton.setVisible(false); + declineButton.setVisible(false); + titleLabel.setText(Res.getString("message.negotiate.file.transfer")); + titleLabel.setForeground(new Color(65, 139, 179)); + + add(progressBar, new GridBagConstraints(1, 2, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 150, 0)); + add(progressLabel, new GridBagConstraints(1, 3, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 150, 0)); + add(cancelButton, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0)); + cancelButton.setVisible(true); + transfer = request.accept(); + + final File downloadedFile = toUniqueDownloadedFile(request); + + try { + startTime = System.currentTimeMillis(); + transfer.receiveFile(downloadedFile); + } catch (SmackException | IOException e) { + Log.error("An error occurred while accepting a file transfer request.", e); + } + + progressBar.setMaximum(100); // setting it to percent + progressBar.setStringPainted(true); + + final Timer timer = new Timer(); + TimerTask updateProgressBar = new TimerTask() { + @Override + public void run() { + if (transfer.getAmountWritten() >= request.getFileSize() + || transfer.getStatus() == FileTransfer.Status.error + || transfer.getStatus() == FileTransfer.Status.refused + || transfer.getStatus() == FileTransfer.Status.cancelled + || transfer.getStatus() == FileTransfer.Status.complete) { + this.cancel(); + timer.cancel(); + endTime = System.currentTimeMillis(); + updateOnFinished(request, downloadedFile); + } else { + // 100 % = FileSize + // x % = CurrentSize + long p = (transfer.getAmountWritten() * 100 / transfer.getFileSize()); + progressBar.setValue(Math.round(p)); + } + + } + }; + + final Timer timer2 = new Timer(); + TimerTask updateProgressBarText = new TimerTask() { + long timeNow; + long timeEarlier; + long bytesNow; + long bytesEarlier; + + @Override + public void run() { + if (transfer.getAmountWritten() >= request.getFileSize() + || transfer.getStatus() == FileTransfer.Status.error + || transfer.getStatus() == FileTransfer.Status.refused + || transfer.getStatus() == FileTransfer.Status.cancelled + || transfer.getStatus() == FileTransfer.Status.complete) { + this.cancel(); + timer2.cancel(); + } else { + timeNow = System.currentTimeMillis(); + bytesNow = transfer.getAmountWritten(); + bytesRead = transfer.getAmountWritten(); + if (bytesRead == -1) { + bytesRead = 0; + } + ByteFormat format = new ByteFormat(); + String text = format.format(bytesRead); + + FileTransfer.Status status = transfer.getStatus(); + if (status == FileTransfer.Status.in_progress) { + titleLabel.setText(Res.getString("message.receiving.file", contactItem.getDisplayName())); + String speed = TransferUtils.calculateSpeed(bytesNow - bytesEarlier, timeNow - timeEarlier); + String est = TransferUtils.calculateEstimate(bytesNow, transfer.getFileSize(), startTime, System.currentTimeMillis()); + progressLabel.setText(Res.getString("message.transfer.progressbar.text.received", text, speed, est)); + } else if (status == FileTransfer.Status.negotiating_stream) { + titleLabel.setText(Res.getString("message.negotiate.stream")); + } + bytesEarlier = bytesNow; + timeEarlier = timeNow; + } + } + }; + + timer.scheduleAtFixedRate(updateProgressBar, 10, 10); + timer2.scheduleAtFixedRate(updateProgressBarText, 10, 500); + } + + /** + * Return a file reference that is suitable to store the content from the inbound file transfer into. + * + * This method will use the filename as provided by the request, but will add increments to that name in case a file + * of the same name already exists in the download directory. + * + * @param request The file transfer request + * @return A file object that can be used to store the inbound file data into. + * @see SPARK-2198 Prevent incoming file transfer to overwrite existing file. + */ + protected static File toUniqueDownloadedFile(FileTransferRequest request) + { + File downloadedFile = new File(Downloads.getDownloadDirectory(), request.getFileName()); + int count = 1; + while (downloadedFile.isFile() && downloadedFile.exists()) { + if ( request.getFileName().contains(".")) { + // start finding unused names like 'file (1).txt' and 'file (2).txt' + final String name = request.getFileName().substring(0, request.getFileName().lastIndexOf('.')); + final String ext = request.getFileName().substring(request.getFileName().lastIndexOf('.')); + downloadedFile = new File(Downloads.getDownloadDirectory(), name +" ("+count++ +")" + ext); + } else { + // start finding unused names like 'file-1' and 'file-2' + downloadedFile = new File(Downloads.getDownloadDirectory(), request.getFileName() + "-"+count++); + } + } + return downloadedFile; + } + + private void updateOnFinished(final FileTransferRequest request, + final File downloadedFile) { + Jid requestor = request.getRequestor(); + BareJid bareJID = requestor.asBareJid(); + if (transfer.getAmountWritten() >= request.getFileSize()) { + transferDone(bareJID, downloadedFile); + + imageLabel.setFile(downloadedFile); + imageLabel.setToolTipText(Res.getString("message.click.to.open")); + titleLabel.setToolTipText(Res.getString("message.click.to.open")); + String fin = TransferUtils.convertSecondstoHHMMSS(Math.round(endTime - startTime) / 1000); + progressLabel.setText(Res.getString("label.time", fin)); + + imageLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + launchFile(downloadedFile); + } + } + }); + + imageLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + imageLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + imageLabel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + }); + + titleLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + launchFile(downloadedFile); + } + } + }); + + titleLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + titleLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + titleLabel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + }); + + invalidate(); + validate(); + repaint(); + } + + String transferMessage = ""; + if (transfer.getStatus() == FileTransfer.Status.error) { + if (transfer.getException() != null) { + Log.error("There was an error during file transfer.", transfer.getException()); + } + transferMessage = Res.getString("message.error.during.file.transfer"); + saveEventToHistory(bareJID, Res.getString("message.file.transfer.history.receive.failed", fileName, nickname)); + } else if (transfer.getStatus() == FileTransfer.Status.refused) { + transferMessage = Res.getString("message.transfer.refused"); + } else if (transfer.getStatus() == FileTransfer.Status.cancelled || + transfer.getAmountWritten() < request.getFileSize()) { + transferMessage = Res.getString("message.transfer.cancelled"); + saveEventToHistory(bareJID, Res.getString("message.file.transfer.history.receive.canceled", fileName, nickname)); + } else if (transfer.getAmountWritten() >= request.getFileSize()) { + transferMessage = Res.getString("message.transfer.complete", downloadedFile.getName()); // TODO this overwrites the message that was set by transferDone + saveEventToHistory(bareJID, Res.getString("message.file.transfer.history.receive.success", fileName, nickname)); + } + + setFinishedText(transferMessage); + showAlert(true); + } + + private void setFinishedText(String text) { + acceptButton.setVisible(false); + declineButton.setVisible(false); + fileLabel.setText(""); + titleLabel.setText(text); + titleLabel.setForeground(new Color(65, 139, 179)); + progressBar.setVisible(false); + cancelButton.setVisible(false); + invalidate(); + validate(); + repaint(); + } + + private void transferDone(final BareJid requestor, final File downloadedFile) { + cancelButton.setVisible(false); + + showAlert(true); + + ContactList contactList = SparkManager.getWorkspace().getContactList(); + ContactItem contactItem = contactList.getContactItemByJID(requestor); + + titleLabel.setText(Res.getString("message.received.file", contactItem.getDisplayName())); + fileLabel.setText(downloadedFile.getName()); + + remove(acceptButton); + remove(declineButton); + remove(progressBar); + remove(pathButton); + + final TransferButton openFileButton = new TransferButton(); + final TransferButton openFolderButton = new TransferButton(); + add(openFileButton, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); + add(openFolderButton, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); + + openFileButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + openFileButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + openFileButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + + @Override + public void mousePressed(MouseEvent e) { + launchFile(downloadedFile); + } + }); + + openFolderButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + openFolderButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + openFolderButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + + @Override + public void mousePressed(MouseEvent event) { + launchFile(Downloads.getDownloadDirectory()); + } + }); + + add(fileLabel, new GridBagConstraints(1, 1, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0)); + + ResourceUtils.resButton(openFileButton, Res.getString("open")); + ResourceUtils.resButton(openFolderButton, Res.getString("open.folder")); + + openFileButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196))); + openFileButton.setForeground(new Color(73, 113, 196)); + openFileButton.setFont(new Font("Dialog", Font.BOLD, 11)); + + openFolderButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196))); + openFolderButton.setForeground(new Color(73, 113, 196)); + openFolderButton.setFont(new Font("Dialog", Font.BOLD, 11)); + + imageLabel.setIcon(GraphicUtils.getIcon(downloadedFile)); + imageLabel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + showPopup(e, downloadedFile); + } + + @Override + public void mouseReleased(MouseEvent e) { + showPopup(e, downloadedFile); + } + }); + + if (isImage(downloadedFile.getName())) { + try { + URL imageURL = downloadedFile.toURI().toURL(); + ImageIcon image = new ImageIcon(imageURL); + image = GraphicUtils.scaleImageIcon(image, Sizes.Transfer.THUMBNAIL, Sizes.Transfer.THUMBNAIL); + imageLabel.setIcon(image); + } catch (MalformedURLException e) { + Log.error("Could not locate image.", e); + imageLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.DOCUMENT_INFO_32x32)); + } + } + + invalidate(); + validate(); + repaint(); + } + + /*** + * Adds an event text as a message to transcript and saves it to history + * @param bareJID requestor JID + * @param eventText Contains file transfer event text + */ + private void saveEventToHistory(BareJid bareJID, String eventText) { + MessageBuilder messageBuilder = StanzaBuilder.buildMessage() + .setBody(eventText) + .to(bareJID) + .from(SparkManager.getSessionManager().getJID()); + Message message = messageBuilder.build(); + chatRoom.addToTranscript(message, false); + SparkManager.getWorkspace().getTranscriptPlugin().persistChatRoom(chatRoom); + } + + private static class TransferButton extends JButton { + private static final long serialVersionUID = -9198495278243559064L; + + public TransferButton() { + decorate(); + } + + /** + * Create a new RolloverButton. + * + * @param text the button text. + * @param icon the button icon. + */ + public TransferButton(String text, Icon icon) { + super(text, icon); + decorate(); + } + + /** + * Decorates the button with the approriate UI configurations. + */ + private void decorate() { + setBorderPainted(false); + setOpaque(true); + + setContentAreaFilled(false); + setMargin(new Insets(1, 1, 1, 1)); + } + } + + private boolean isImage(String fileName) { + fileName = fileName.toLowerCase(); + + String[] imageTypes = {"jpeg", "gif", "jpg", "png"}; + for (String imageType : imageTypes) { + if (fileName.endsWith(imageType)) { + return true; + } + } + return false; + } + + private void showAlert(boolean alert) { + if (alert) { + titleLabel.setForeground(new Color(211, 174, 102)); + setBackground(new Color(250, 249, 242)); + } else { + setBackground(new Color(239, 245, 250)); + titleLabel.setForeground(new Color(65, 139, 179)); + } + } + + public void cancelTransfer() { + if (transfer != null) { + transfer.cancel(); + } + } + + /** + * Handle the UI for the Cancel Button + */ + private void decorateCancelButton() { + cancelButton.setVisible(false); + ResourceUtils.resButton(cancelButton, Res.getString("cancel")); + cancelButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196))); + cancelButton.setForeground(new Color(73, 113, 196)); + cancelButton.setFont(new Font("Dialog", Font.BOLD, 11)); + cancelButton.setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_DELETE)); + + cancelButton.addActionListener(e -> { + cancelTransfer(); + acceptButton.setVisible(false); + declineButton.setVisible(false); + cancelButton.setVisible(false); + }); + + cancelButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + cancelButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + cancelButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + }); + } + + private void showPopup(MouseEvent e, final File downloadedFile) { + if (e.isPopupTrigger()) { + final JPopupMenu popup = new JPopupMenu(); + + final ReceiveFileTransfer ui = this; + Action saveAsAction = new AbstractAction() { + private static final long serialVersionUID = -3010501340128285438L; + + @Override + public void actionPerformed(ActionEvent e) { + final JFileChooser chooser = Downloads.getFileChooser(); + File selectedFile = chooser.getSelectedFile(); + if (selectedFile != null) { + selectedFile = new File(selectedFile.getParent(), downloadedFile.getName()); + } else { + selectedFile = downloadedFile; + } + chooser.setSelectedFile(selectedFile); + + int ok = chooser.showSaveDialog(ui); + if (ok == JFileChooser.APPROVE_OPTION) { + File file = chooser.getSelectedFile(); + try { + if (file.exists()) { + int confirm = JOptionPane.showConfirmDialog(ui, Res.getString("message.file.exists.question"), Res.getString("title.file.exists"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + if (confirm == JOptionPane.NO_OPTION) { + return; + } + } + URLFileSystem.copy(downloadedFile.toURI().toURL(), file); + } catch (IOException e1) { + Log.error("An exception occurred while selecting a location to save a received file.", e1); + } + } + } + }; + + saveAsAction.putValue(Action.NAME, Res.getString("menuitem.save.as")); + popup.add(saveAsAction); + popup.show(this, e.getX(), e.getY()); + } + } + + /** + * Return correct URI for filePath. dont mind of local or remote path + * + * @param file to open + * @return URI for the file. + */ + private static URI getFileURI(File file) { + URI uri = null; + String filePath = file.getPath().trim(); + if (filePath.indexOf("http") == 0 || filePath.indexOf("\\") == 0) { + if (filePath.indexOf("\\") == 0) + filePath = "file:" + filePath; + try { + filePath = filePath.replaceAll(" ", "%20"); + URL url = new URL(filePath); + uri = url.toURI(); + } catch (MalformedURLException | URISyntaxException ex) { + ex.printStackTrace(); + } + } else { + uri = new File(filePath).toURI(); + } + return uri; + } + + /** + * Attempts to open the file. If no associated application can be found, or if that application fails to launch, or + * if the provided file is a directory, a file browser that shows the content of the folder in which the file + * resides is shown. + * + * @param file the file to be shown. + */ + private void launchFile(File file) { + if (!Desktop.isDesktopSupported()) { + Log.warning("Cannot launch file (not supported in this environment)."); + return; + } + + final Desktop desktop = Desktop.getDesktop(); + try { + desktop.open(file); + } catch (IOException ex) { + try { + // Potentially trying to open on a network path that has spaces (SPARK-1350). Try again, using a URI. + desktop.browse(getFileURI(file)); + return; + } catch (Exception ex1) { + // The specified file has no associated application or the associated application fails to be launched. + // Show the folder containing the file as a last-ditch effort (SPARK-2199). + if (file.isFile() && file.getParentFile() != null) { + try { + desktop.open(file.getParentFile()); + return; + } catch (IOException ex2) { + // Log the original exception (see below) + } + } + } + // In case of failure, log the original exception, which is likely to be most relevant. + Log.warning("Unable to open file: " + file.getName(), ex); + } + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/SendFileTransfer.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/SendFileTransfer.java new file mode 100644 index 000000000..9a47a91fd --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/SendFileTransfer.java @@ -0,0 +1,405 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.filetransfer.transfer.ui; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Desktop; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +import javax.swing.*; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smackx.filetransfer.FileTransfer; +import org.jivesoftware.smackx.filetransfer.FileTransfer.Status; +import org.jivesoftware.smackx.filetransfer.FileTransferManager; +import org.jivesoftware.smackx.filetransfer.FileTransferNegotiator; +import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.FileDragLabel; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.spark.ui.ContactList; +import org.jivesoftware.spark.util.ByteFormat; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.Sizes; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.EntityFullJid; + +public class SendFileTransfer extends JPanel { + + private static final long serialVersionUID = -4403839897649365671L; + private final FileDragLabel imageLabel = new FileDragLabel(); + private final JLabel titleLabel = new JLabel(); + private final JLabel fileLabel = new JLabel(); + + private final TransferButton cancelButton = new TransferButton(); + private final JProgressBar progressBar = new JProgressBar(); + private File fileToSend; + private OutgoingFileTransfer transfer; + + private final TransferButton retryButton = new TransferButton(); + + private FileTransferManager transferManager; + private EntityFullJid fullJID; + private String nickname; + private final JLabel progressLabel = new JLabel(); + private long _startTime; + private final ChatRoom chatRoom; + + public SendFileTransfer(ChatRoom chatRoom) { + this.chatRoom = chatRoom; + + setLayout(new GridBagLayout()); + + setBackground(new Color(250, 249, 242)); + add(imageLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + + add(titleLabel, new GridBagConstraints(1, 0, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + titleLabel.setFont(new Font("Dialog", Font.BOLD, 11)); + titleLabel.setForeground(new Color(211, 174, 102)); + add(fileLabel, new GridBagConstraints(1, 1, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0)); + + cancelButton.setText(Res.getString("cancel")); + retryButton.setText(Res.getString("retry")); + cancelButton.setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_DELETE)); + retryButton.setIcon(SparkRes.getImageIcon(SparkRes.Icon.REFRESH_IMAGE)); + + add(cancelButton, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); + add(retryButton, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); + retryButton.setVisible(false); + + retryButton.addActionListener(e -> { + try { + File file = new File(transfer.getFilePath()); + transfer = transferManager.createOutgoingFileTransfer(fullJID); + transfer.sendFile(file, "Sending"); + } catch (SmackException e1) { + Log.error("An error occurred while creating an outgoing file transfer.", e1); + } + sendFile(transfer, transferManager, fullJID, nickname); + }); + + cancelButton.setForeground(new Color(73, 113, 196)); + cancelButton.setFont(new Font("Dialog", Font.BOLD, 11)); + cancelButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196))); + + retryButton.setForeground(new Color(73, 113, 196)); + retryButton.setFont(new Font("Dialog", Font.BOLD, 11)); + retryButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196))); + + setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.white)); + } + + public void sendFile(final OutgoingFileTransfer transfer, FileTransferManager transferManager, final EntityFullJid jid, final String nickname) { + this.transferManager = transferManager; + //SPARK-1869 + FileTransferNegotiator.getInstanceFor(SparkManager.getConnection()); + FileTransferNegotiator.IBB_ONLY = SettingsManager.getLocalPreferences().isFileTransferIbbOnly(); + + cancelButton.setVisible(true); + retryButton.setVisible(false); + this.fullJID = jid; + this.nickname = nickname; + final BareJid bareJid = jid.asBareJid(); + + this.transfer = transfer; + String fileName = transfer.getFileName(); + String filePath = transfer.getFilePath(); + long fileSize = transfer.getFileSize(); + ByteFormat format = new ByteFormat(); + String fileSizeString = format.format(fileSize); + + fileToSend = new File(transfer.getFilePath()); + imageLabel.setFile(fileToSend); + + fileLabel.setText(fileName + " (" + fileSizeString + ")"); + + ContactList contactList = SparkManager.getWorkspace().getContactList(); + ContactItem contactItem = contactList.getContactItemByJID(jid); + + saveEventToHistory(bareJid, Res.getString("message.file.transfer.history.request.sent", filePath, fileSizeString, nickname)); + titleLabel.setText(Res.getString("message.transfer.waiting.on.user", contactItem.getDisplayName())); + + if (isImage(fileName)) { + try { + URL imageURL = new File(transfer.getFilePath()).toURI().toURL(); + ImageIcon image = new ImageIcon(imageURL); + image = GraphicUtils.scaleImageIcon(image, Sizes.Transfer.THUMBNAIL, Sizes.Transfer.THUMBNAIL); + imageLabel.setIcon(image); + } catch (MalformedURLException e) { + Log.error("Could not locate image.", e); + imageLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.DOCUMENT_INFO_32x32)); + } + } else { + File file = new File(transfer.getFilePath()); + Icon icon = GraphicUtils.getIcon(file); + imageLabel.setIcon(icon); + } + cancelButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent mouseEvent) { + transfer.cancel(); + } + }); + + cancelButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + cancelButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + cancelButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + }); + + progressBar.setMaximum(100); + progressBar.setVisible(false); + progressBar.setStringPainted(true); + add(progressBar, new GridBagConstraints(1, 2, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 150, 0)); + add(progressLabel, new GridBagConstraints(1, 3, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 150, 0)); + + SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + while (true) { + try { + if (transfer.getBytesSent() > 0 && _startTime == 0) { + _startTime = System.currentTimeMillis(); + } + + long startTime = System.currentTimeMillis(); + long startByte = transfer.getBytesSent(); + Thread.sleep(500); + FileTransfer.Status status = transfer.getStatus(); + if (status == Status.complete) { + saveEventToHistory(bareJid, Res.getString("message.file.transfer.history.send.complete", filePath, nickname)); + break; + } else if (status == Status.error) { + saveEventToHistory(bareJid, Res.getString("message.file.transfer.history.send.error", filePath, nickname)); + break; + } else if (status == Status.cancelled) { + saveEventToHistory(bareJid, Res.getString("message.file.transfer.history.send.canceled", filePath, nickname)); + break; + } else if (status == Status.refused) { + saveEventToHistory(bareJid, Res.getString("message.file.transfer.history.contact.rejected", filePath, nickname)); + break; + } + long endTime = System.currentTimeMillis(); + long endByte = transfer.getBytesSent(); + + long timeDiff = endTime - startTime; + long byteDiff = endByte - startByte; + + updateBar(transfer, nickname, TransferUtils.calculateSpeed(byteDiff, timeDiff)); + } catch (InterruptedException e) { + Log.error("Unable to sleep thread.", e); + } + } + return ""; + } + + @Override + public void finished() { + updateBar(transfer, nickname, "??MB/s"); + } + }; + + worker.start(); + + makeClickable(imageLabel); + makeClickable(titleLabel); + } + + private void makeClickable(final JLabel label) { + label.setToolTipText(Res.getString("message.click.to.open")); + + label.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + openFile(fileToSend); + } + + @Override + public void mouseEntered(MouseEvent e) { + label.setCursor(new Cursor(Cursor.HAND_CURSOR)); + + } + + @Override + public void mouseExited(MouseEvent e) { + label.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + }); + } + + private void openFile(File downloadedFile) { + try { + Desktop.getDesktop().open(downloadedFile); + } catch (IOException e) { + Log.error("An error occurred while trying to open downloaded file: " + downloadedFile, e); + } + } + + private void updateBar(final OutgoingFileTransfer transfer, String nickname, String kBperSecond) { + FileTransfer.Status status = transfer.getStatus(); + if (status == Status.negotiating_stream) { + titleLabel.setText(Res.getString("message.negotiation.file.transfer", nickname)); + } else if (status == Status.error) { + if (transfer.getException() != null) { + Log.error("Error occurred during file transfer.", transfer.getException()); + } + progressBar.setVisible(false); + progressLabel.setVisible(false); + titleLabel.setText(Res.getString("message.unable.to.send.file", nickname)); + cancelButton.setVisible(false); + retryButton.setVisible(true); + showAlert(true); + } else if (status == Status.in_progress) { + titleLabel.setText(Res.getString("message.sending.file.to", nickname)); + showAlert(false); + if (!progressBar.isVisible()) { + progressBar.setVisible(true); + progressLabel.setVisible(true); + } + + try { + SwingUtilities.invokeAndWait(() -> { + // 100 % = Filesize + // x % = Currentsize + long p = (transfer.getBytesSent() * 100 / transfer.getFileSize()); + progressBar.setValue(Math.round(p)); + }); + } catch (Exception e) { + Log.error("An error occurred while trying to update the file transfer progress bar.", e); + } + + ByteFormat format = new ByteFormat(); + String bytesSent = format.format(transfer.getBytesSent()); + String est = TransferUtils.calculateEstimate(transfer.getBytesSent(), transfer.getFileSize(), _startTime, System.currentTimeMillis()); + + progressLabel.setText(Res.getString("message.transfer.progressbar.text.sent", bytesSent, kBperSecond, est)); + } else if (status == Status.complete) { + progressBar.setVisible(false); + + if ( _startTime == 0 ) { // SPARK-2192: Sometimes, the startTime of the transfer hasn't been recorded yet when it already finished. + _startTime = System.currentTimeMillis(); + } + String fin = TransferUtils.convertSecondstoHHMMSS(Math.round(Math.max(0, System.currentTimeMillis() - _startTime)) / 1000); + _startTime = 0; + progressLabel.setText(Res.getString("label.time", fin)); + titleLabel.setText(Res.getString("message.you.have.sent", nickname)); + cancelButton.setVisible(false); + showAlert(true); + } else if (status == Status.cancelled) { + progressBar.setVisible(false); + progressLabel.setVisible(false); + titleLabel.setText(Res.getString("message.file.transfer.canceled")); + cancelButton.setVisible(false); + retryButton.setVisible(true); + showAlert(true); + } else if (status == Status.refused) { + progressBar.setVisible(false); + progressLabel.setVisible(false); + titleLabel.setText(Res.getString("message.file.transfer.rejected", nickname)); + cancelButton.setVisible(false); + retryButton.setVisible(true); + showAlert(true); + } + } + + /*** + * Adds an event text as a message to transcript and saves it to history + * @param bareJid receiver JID + * @param eventText Contains file transfer event text + */ + private void saveEventToHistory(BareJid bareJid, String eventText) { + MessageBuilder messageBuilder = StanzaBuilder.buildMessage() + .setBody(eventText) + .to(bareJid) + .from(SparkManager.getSessionManager().getJID()); + Message message = messageBuilder.build(); + chatRoom.addToTranscript(message, false); + SparkManager.getWorkspace().getTranscriptPlugin().persistChatRoom(chatRoom); + } + + private static class TransferButton extends JButton { + private static final long serialVersionUID = 8807434179541503654L; + + public TransferButton() { + decorate(); + } + + /** + * Decorates the button with the approriate UI configurations. + */ + private void decorate() { + setBorderPainted(false); + setOpaque(true); + + setContentAreaFilled(false); + setMargin(new Insets(1, 1, 1, 1)); + } + } + + private boolean isImage(String fileName) { + fileName = fileName.toLowerCase(); + + String[] imageTypes = {"jpeg", "gif", "jpg", "png"}; + for (String imageType : imageTypes) { + if (fileName.endsWith(imageType)) { + return true; + } + } + return false; + } + + private void showAlert(boolean alert) { + if (alert) { + titleLabel.setForeground(new Color(211, 174, 102)); + setBackground(new Color(250, 249, 242)); + } else { + setBackground(new Color(239, 245, 250)); + titleLabel.setForeground(new Color(65, 139, 179)); + } + } + + public void cancelTransfer() { + if (transfer != null) { + transfer.cancel(); + } + } + +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/TransferUtils.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/TransferUtils.java similarity index 94% rename from src/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/TransferUtils.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/TransferUtils.java index de4b82ec4..5ee13ad64 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/TransferUtils.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/TransferUtils.java @@ -48,8 +48,7 @@ public static String calculateSpeed(long bytediff, long timediff) { */ public static double calculateSpeedLong(long bytediff, long timediff) { timediff = timediff == 0 ? 1 : timediff; - double kB = ((bytediff / timediff) * 1000.0) / 1024.0; - return kB; + return (double) bytediff / (double) timediff * 1000.0 / 1024.0; } /** @@ -67,7 +66,7 @@ public static double calculateSpeedLong(long bytediff, long timediff) { */ public static String calculateEstimate(long currentsize, long totalsize, long timestart, long timenow) { - long timediff = timenow - timestart; + long timediff = Math.max(0, timenow - timestart); long sizeleft = totalsize - currentsize; // currentsize = timediff @@ -90,8 +89,8 @@ public static String calculateEstimate(long currentsize, long totalsize, */ public static String convertSecondstoHHMMSS(int second) { - int hours = Math.round(second / 3600); - int minutes = Math.round((second / 60) % 60); + int hours = Math.round((float) second / 3600); + int minutes = Math.round((float) second / 60 % 60); int seconds = Math.round(second % 60); String hh = hours < 10 ? "0" + hours : "" + hours; String mm = minutes < 10 ? "0" + minutes : "" + minutes; diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/Gateway.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/Gateway.java new file mode 100644 index 000000000..131ea0d4d --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/Gateway.java @@ -0,0 +1,142 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.gateways; + +import org.jivesoftware.smack.*; +import org.jivesoftware.smack.filter.StanzaIdFilter; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IqData; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.parsing.SmackParsingException; +import org.jivesoftware.smack.provider.IqProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jivesoftware.spark.SparkManager; +import org.jxmpp.JxmppContext; +import org.jxmpp.jid.DomainBareJid; + +import java.io.IOException; +import java.text.ParseException; + +/** + */ +public class Gateway extends IQ { + + private String jid; + private String username; + + protected Gateway() + { + super( ELEMENT_NAME, NAMESPACE ); + } + + + public String getJid() { + return jid; + } + + public void setJid(String jid) { + this.jid = jid; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + /** + * Element name of the packet extension. + */ + public static final String ELEMENT_NAME = "query"; + + /** + * Namespace of the packet extension. + */ + public static final String NAMESPACE = "jabber:iq:gateway"; + + @Override + protected IQChildElementXmlStringBuilder getIQChildElementBuilder( IQChildElementXmlStringBuilder buf ) + { + buf.rightAngleBracket(); + buf.append("").append(username).append(""); + return buf; + } + + /** + * An IQProvider for Gateway packet. + * + * @author Derek DeMoro + */ + public static class Provider extends IqProvider { + + public Provider() { + super(); + } + + @Override + public Gateway parse(XmlPullParser parser, int i, IqData iqData, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) + throws IOException, XmlPullParserException { + Gateway version = new Gateway(); + + boolean done = false; + while (!done) { + XmlPullParser.Event eventType = parser.next(); + if (eventType == XmlPullParser.Event.START_ELEMENT) { + if (parser.getName().equals("jid")) { + version.setJid(parser.nextText()); + } + else if (parser.getName().equals("username")) { + version.setUsername(parser.nextText()); + } + } + + else if (eventType == XmlPullParser.Event.END_ELEMENT) { + if (parser.getName().equals(ELEMENT_NAME)) { + done = true; + } + } + } + + return version; + } + } + + /** + * Returns the fully qualified JID of a user. + * + * @param serviceName the service the user belongs to. + * @param username the name of the user. + * @return the JID. + */ + public static String getJID(DomainBareJid serviceName, String username) throws Exception { + Gateway registration = new Gateway(); + registration.setType(IQ.Type.set); + registration.setTo(serviceName); + registration.setUsername(username); + + XMPPConnection connection = SparkManager.getConnection(); + IQ result = connection.sendIqRequestAndWaitForResponse(registration); + Gateway response = (Gateway) result; + return response.getJid(); + } + + +} + + diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayButton.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayButton.java similarity index 80% rename from src/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayButton.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayButton.java index f622595e6..0a77ec566 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayButton.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayButton.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,6 +30,7 @@ import org.jivesoftware.resource.Res; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.spark.PresenceManager; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.component.RolloverButton; @@ -44,12 +41,11 @@ import org.jivesoftware.sparkimpl.plugin.gateways.transports.TransportUtils; /** - * */ public class GatewayButton extends JPanel implements GatewayItem { private static final long serialVersionUID = -2692869826501622612L; private final RolloverButton button = new RolloverButton(); - private Transport transport; + private final Transport transport; private boolean signedIn; public GatewayButton(final Transport transport) { @@ -61,7 +57,7 @@ public GatewayButton(final Transport transport) { final StatusBar statusBar = SparkManager.getWorkspace().getStatusBar(); final JPanel commandPanel = SparkManager.getWorkspace().getCommandPanel(); - if (PresenceManager.isOnline(transport.getServiceName())) { + if (PresenceManager.isOnline(transport.getXMPPServiceDomain())) { button.setIcon(transport.getIcon()); } else { @@ -72,7 +68,8 @@ public GatewayButton(final Transport transport) { commandPanel.add(button); button.addMouseListener(new MouseAdapter() { - public void mousePressed(MouseEvent mouseEvent) { + @Override + public void mousePressed(MouseEvent mouseEvent) { handlePopup(mouseEvent); } }); @@ -82,16 +79,21 @@ public void mousePressed(MouseEvent mouseEvent) { final boolean isRegistered = TransportUtils.isRegistered(SparkManager.getConnection(), transport); if (isRegistered) { // Check if auto login is set. - boolean autoJoin = TransportUtils.autoJoinService(transport.getServiceName()); + boolean autoJoin = TransportUtils.autoJoinService(transport.getXMPPServiceDomain()); if (autoJoin) { Presence oldPresence = statusBar.getPresence(); - Presence presence = new Presence(oldPresence.getType(), oldPresence.getStatus(), oldPresence.getPriority(), oldPresence.getMode()); - presence.setTo(transport.getServiceName()); + Presence presence = StanzaBuilder.buildPresence() + .ofType(oldPresence.getType()) + .setStatus(oldPresence.getStatus()) + .setPriority(oldPresence.getPriority()) + .setMode(oldPresence.getMode()) + .build(); + presence.setTo(transport.getXMPPServiceDomain()); try { SparkManager.getConnection().sendStanza(presence); } - catch ( SmackException.NotConnectedException e ) + catch ( SmackException.NotConnectedException | InterruptedException e ) { Log.error( "Unable to register.", e ); } @@ -113,14 +115,16 @@ private void handlePopup(MouseEvent event) { // Create action to sign off of transport. final JMenuItem signOutMenu = new JMenuItem(Res.getString("menuitem.sign.out")); signOutMenu.addActionListener( actionEvent -> { - final Presence offlinePresence = new Presence(Presence.Type.unavailable); - offlinePresence.setTo(transport.getServiceName()); + final Presence offlinePresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .build(); + offlinePresence.setTo(transport.getXMPPServiceDomain()); try { SparkManager.getConnection().sendStanza(offlinePresence); } - catch ( SmackException.NotConnectedException e ) + catch ( SmackException.NotConnectedException | InterruptedException e ) { Log.warning( "Unable to send sign-off.", e ); } @@ -129,13 +133,15 @@ private void handlePopup(MouseEvent event) { // Create menu to sign in. final JMenuItem signInMenu = new JMenuItem(Res.getString("menuitem.sign.in")); signInMenu.addActionListener( actionEvent -> { - final Presence onlinePresence = new Presence(Presence.Type.available); - onlinePresence.setTo(transport.getServiceName()); + final Presence onlinePresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .build(); + onlinePresence.setTo(transport.getXMPPServiceDomain()); try { SparkManager.getConnection().sendStanza(onlinePresence); } - catch ( SmackException.NotConnectedException e ) + catch ( SmackException.NotConnectedException | InterruptedException e ) { Log.error( "Unable sign-in.", e ); } @@ -144,11 +150,11 @@ private void handlePopup(MouseEvent event) { // Create menu item to toggle signing in at startup. final JCheckBoxMenuItem signInAtLoginMenu = new JCheckBoxMenuItem(); signInAtLoginMenu.setText(Res.getString("menuitem.sign.in.at.login")); - signInAtLoginMenu.addActionListener( actionEvent -> TransportUtils.setAutoJoin(transport.getServiceName(), signInAtLoginMenu.isSelected()) ); + signInAtLoginMenu.addActionListener( actionEvent -> TransportUtils.setAutoJoin(transport.getXMPPServiceDomain(), signInAtLoginMenu.isSelected()) ); final JMenuItem registerMenu = new JMenuItem(Res.getString("menuitem.enter.login.information")); registerMenu.addActionListener( actionEvent -> { - TransportRegistrationDialog registrationDialog = new TransportRegistrationDialog(transport.getServiceName()); + TransportRegistrationDialog registrationDialog = new TransportRegistrationDialog(transport.getXMPPServiceDomain()); registrationDialog.invoke(); } ); @@ -161,9 +167,9 @@ private void handlePopup(MouseEvent event) { int confirm = JOptionPane.showConfirmDialog(SparkManager.getMainWindow(), Res.getString("message.disable.transport", transport.getName()), Res.getString("title.disable.transport"), JOptionPane.YES_NO_OPTION); if (confirm == JOptionPane.YES_OPTION) { try { - TransportUtils.unregister(SparkManager.getConnection(), transport.getServiceName()); + TransportUtils.unregister(SparkManager.getConnection(), transport.getXMPPServiceDomain()); } - catch (SmackException e1) { + catch (SmackException | InterruptedException e1) { Log.error(e1); } } @@ -189,7 +195,7 @@ private void handlePopup(MouseEvent event) { popupMenu.add(signInMenu); } - boolean autoJoin = TransportUtils.autoJoinService(transport.getServiceName()); + boolean autoJoin = TransportUtils.autoJoinService(transport.getXMPPServiceDomain()); signInAtLoginMenu.setSelected(autoJoin); popupMenu.add(signInAtLoginMenu); @@ -198,7 +204,8 @@ private void handlePopup(MouseEvent event) { popupMenu.show((Component)event.getSource(), event.getX(), event.getY()); } - public void signedIn(boolean signedIn) { + @Override + public void signedIn(boolean signedIn) { if (!signedIn) { button.setIcon(transport.getInactiveIcon()); } @@ -209,7 +216,8 @@ public void signedIn(boolean signedIn) { this.signedIn = signedIn; } - public boolean isLoggedIn() { + @Override + public boolean isLoggedIn() { return signedIn; } diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayItem.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayItem.java new file mode 100644 index 000000000..19aea4bf5 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayItem.java @@ -0,0 +1,12 @@ +/** + */ +package org.jivesoftware.sparkimpl.plugin.gateways; + +/** + * @author holger.bergunde + * + */ +public interface GatewayItem { + void signedIn(boolean signedIn); + boolean isLoggedIn(); +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayPlugin.java new file mode 100644 index 000000000..a7f38f40f --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayPlugin.java @@ -0,0 +1,330 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.gateways; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.filter.OrFilter; +import org.jivesoftware.smack.filter.StanzaFilter; +import org.jivesoftware.smack.filter.StanzaTypeFilter; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smack.provider.ProviderManager; +import org.jivesoftware.smackx.disco.packet.DiscoverItems; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.MessageDialog; +import org.jivesoftware.spark.component.VerticalFlowLayout; + +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.*; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.gateways.transports.*; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.Jid; + +import javax.swing.*; + + +import java.awt.Color; +import java.util.HashMap; +import java.util.Map; + +/** + * Handles Gateways/Transports in Spark. + * + * @author Derek DeMoro + */ +public class GatewayPlugin implements Plugin, ContactItemHandler { + + /** + * Defined Static Variable for Gateways. * + */ + public static final String GATEWAY = "gateway"; + private boolean useTab; + + private final Map uiMap = new HashMap<>(); + private final JPanel transferTab = new JPanel(); + + @Override + public void initialize() { + ProviderManager.addIQProvider(Gateway.ELEMENT_NAME, Gateway.NAMESPACE, new Gateway.Provider()); + LocalPreferences localPref = SettingsManager.getLocalPreferences(); + useTab = localPref.getShowTransportTab(); + transferTab.setBackground((Color)UIManager.get("ContactItem.background")); + SwingWorker thread = new SwingWorker() { + @Override + public Object construct() { + try { + // Let's try and avoid any timing issues with the gateway presence. + Thread.sleep(5000); + populateTransports(); + } + catch (Exception e) { + Log.error(e); + return false; + } + + return true; + } + + @Override + public void finished() { + + transferTab.setLayout(new VerticalFlowLayout(0,0,0,true,false)); + Boolean transportExists = (Boolean)get(); + if (!transportExists) { + return; + } + + + + if (TransportUtils.getTransports().size() > 0 && useTab) { + SparkManager.getWorkspace().getWorkspacePane().addTab(Res.getString("title.transports"), SparkRes.getImageIcon(SparkRes.Icon.TRANSPORT_ICON), transferTab); + } + + for (final Transport transport : TransportUtils.getTransports()) { + addTransport(transport); + } + + // Register presences. + registerPresenceListener(); + } + }; + + thread.start(); + } + + @Override + public void shutdown() { + } + + @Override + public boolean canShutDown() { + return false; + } + + @Override + public void uninstall() { + } + + private void populateTransports() { + DiscoverItems discoItems = SparkManager.getSessionManager().getDiscoveredItems(); + for (DiscoverItems.Item item : discoItems.getItems()) { + String entityName = item.getEntityID().toString(); + int dotPos = entityName.indexOf('.'); + if (dotPos == -1) { + continue; + } + String transportPrefix = entityName.substring(0, dotPos); + switch (transportPrefix) { + case "xmpp": + XMPPTransport xmppTransport = new XMPPTransport(item.getEntityID().asDomainBareJid()); + TransportUtils.addTransport(item.getEntityID().asDomainBareJid(), xmppTransport); + break; + case "irc": + IRCTransport ircTransport = new IRCTransport(item.getEntityID().asDomainBareJid()); + TransportUtils.addTransport(item.getEntityID().asDomainBareJid(), ircTransport); + break; + case "sip": + case "simple": + SimpleTransport simpleTransport = new SimpleTransport(item.getEntityID().asDomainBareJid()); + TransportUtils.addTransport(item.getEntityID().asDomainBareJid(), simpleTransport); + break; + case "gadugadu": + GaduGaduTransport gadugaduTransport = new GaduGaduTransport(item.getEntityID().asDomainBareJid()); + TransportUtils.addTransport(item.getEntityID().asDomainBareJid(), gadugaduTransport); + break; + case "qq": + QQTransport qqTransport = new QQTransport(item.getEntityID().asDomainBareJid()); + TransportUtils.addTransport(item.getEntityID().asDomainBareJid(), qqTransport); + break; + case "sametime": + SametimeTransport sametimeTransport = new SametimeTransport(item.getEntityID().asDomainBareJid()); + TransportUtils.addTransport(item.getEntityID().asDomainBareJid(), sametimeTransport); + break; + case "facebook": + FacebookTransport facebookTransport = new FacebookTransport(item.getEntityID().asDomainBareJid()); + TransportUtils.addTransport(item.getEntityID().asDomainBareJid(), facebookTransport); + break; + case "myspace": + case "myspaceim": + MySpaceTransport myspaceTransport = new MySpaceTransport(item.getEntityID().asDomainBareJid()); + TransportUtils.addTransport(item.getEntityID().asDomainBareJid(), myspaceTransport); + break; + } + } + } + + private void addTransport(final Transport transport) { + GatewayItem item; + if (useTab) + { + item = new GatewayTabItem(transport); + transferTab.add((GatewayTabItem)item); + } + else + { + item = new GatewayButton(transport); + } + uiMap.put(transport, item); + // transferTab.add(button); + // transferTab.add(new GatewayTabItem(transport)); + } + + private void registerPresenceListener() { + StanzaFilter orFilter = new OrFilter(new StanzaTypeFilter(Presence.class), new StanzaTypeFilter(Message.class)); + + SparkManager.getConnection().addAsyncStanzaListener( stanza -> { + if (stanza instanceof Presence) { + Presence presence = (Presence)stanza; + Transport transport = TransportUtils.getTransport(stanza.getFrom().asDomainBareJid()); + if (transport != null) { + boolean registered = true; + if (presence.getType() == Presence.Type.unavailable) { + registered = false; + } + + + GatewayItem button = uiMap.get(transport); + + button.signedIn(registered); + + SwingWorker worker = new SwingWorker() { + + @Override + public Object construct() { + transferTab.revalidate(); + transferTab.repaint(); + return 41; + } + }; + worker.start(); + } + } + else if (stanza instanceof Message) { + Message message = (Message)stanza; + DomainBareJid from = message.getFrom().asDomainBareJid(); + boolean hasError = message.getType() == Message.Type.error; + String body = message.getBody(); + + if (from != null && hasError) { + Transport transport = TransportUtils.getTransport(from); + if (transport != null) { + String title = "Alert from " + transport.getName(); + // Show error + MessageDialog.showAlert(body, title, "Information", SparkRes.getImageIcon(SparkRes.Icon.INFORMATION_IMAGE)); + } + } + } + }, orFilter); + + + ChatManager chatManager = SparkManager.getChatManager(); + chatManager.addContactItemHandler(this); + + // Iterate through Contacts and check for + final ContactList contactList = SparkManager.getWorkspace().getContactList(); + for (ContactGroup contactGroup : contactList.getContactGroups()) { + for (ContactItem contactItem : contactGroup.getContactItems()) { + Presence presence = contactItem.getPresence(); + if (presence.isAvailable()) { + DomainBareJid domain = presence.getFrom().asDomainBareJid(); + Transport transport = TransportUtils.getTransport(domain); + if (transport != null) { + handlePresence(contactItem, presence); + contactGroup.fireContactGroupUpdated(); + } + } + } + } + + SparkManager.getSessionManager().addPresenceListener( presence -> { + for (Transport transport : TransportUtils.getTransports()) { + GatewayItem button = uiMap.get(transport); + if (button.isLoggedIn()) { + if (!presence.isAvailable()) { + return; + } + // Create new presence + Presence p = StanzaBuilder.buildPresence() + .ofType(presence.getType()) + .setStatus(presence.getStatus()) + .setPriority(presence.getPriority()) + .setMode(presence.getMode()) + .build(); + + p.setTo(transport.getXMPPServiceDomain()); + try + { + SparkManager.getConnection().sendStanza(p); + } + catch ( SmackException.NotConnectedException | InterruptedException e ) + { + Log.warning( "Unable to forward presence change to transport.", e ); + } + } + } + } ); + } + + + @Override + public boolean handlePresence(ContactItem item, Presence presence) { + if (presence.isAvailable()) { + Jid from = presence.getFrom(); + if (from == null) { + return false; + } + DomainBareJid domain = from.asDomainBareJid(); + Transport transport = TransportUtils.getTransport(domain); + if (transport != null) { + if (presence.getType() == Presence.Type.available) { + item.setSpecialIcon(transport.getIcon()); + } + else { + item.setSpecialIcon(transport.getInactiveIcon()); + } + return false; + } + } + + return false; + } + + @Override + public Icon getIcon(BareJid jid) { + DomainBareJid domain = jid.asDomainBareJid(); + Transport transport = TransportUtils.getTransport(domain); + if (transport != null) { + if (PresenceManager.isOnline(jid)) { + return transport.getIcon(); + } + else { + return transport.getInactiveIcon(); + } + } + return null; + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayPrivateData.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayPrivateData.java new file mode 100644 index 000000000..cc47eae47 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayPrivateData.java @@ -0,0 +1,135 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.gateways; + +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jivesoftware.smackx.iqprivate.packet.PrivateData; +import org.jivesoftware.smackx.iqprivate.provider.PrivateDataProvider; +import org.jxmpp.JxmppContext; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.impl.JidCreate; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * Handle Gateway preferences through private data to persist through seperate locations of the client. + * + * @author Derek DeMoro + */ +public class GatewayPrivateData implements PrivateData { + + private final Map loginSettingsMap = new HashMap<>(); + + public static final String ELEMENT = "gateway-settings"; + public static final String NAMESPACE = "http://www.jivesoftware.org/spark"; + + public void addService(DomainBareJid serviceName, boolean autoLogin) { + loginSettingsMap.put(serviceName, Boolean.toString(autoLogin)); + } + + public boolean autoLogin(DomainBareJid serviceName) { + String str = loginSettingsMap.get(serviceName); + if(str == null){ + return true; + } + + return Boolean.parseBoolean(str); + } + + @Override + public String getElementName() { + return ELEMENT; + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + + @Override + public String toXML() { + StringBuilder buf = new StringBuilder(); + buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append("\">"); + buf.append(""); + for (DomainBareJid serviceName : loginSettingsMap.keySet()) { + buf.append(""); + String autoLogin = loginSettingsMap.get(serviceName); + buf.append("").append(serviceName).append(""); + buf.append("").append(autoLogin).append(""); + buf.append(""); + } + buf.append(""); + + + buf.append(""); + return buf.toString(); + } + + public static class ConferencePrivateDataProvider implements PrivateDataProvider { + + public ConferencePrivateDataProvider() { + } + + @Override + public PrivateData parsePrivateData(XmlPullParser parser, JxmppContext jxmppContext) throws XmlPullParserException, IOException { + GatewayPrivateData data = new GatewayPrivateData(); + + boolean done = false; + + boolean isInstalled = false; + while (!done) { + XmlPullParser.Event eventType = parser.next(); + if (eventType == XmlPullParser.Event.START_ELEMENT && parser.getName().equals("gateways")) { + isInstalled = true; + } + + if (eventType == XmlPullParser.Event.START_ELEMENT && parser.getName().equals("gateway")) { + boolean gatewayDone = false; + DomainBareJid serviceName = null; + String autoLogin = null; + while (!gatewayDone) { + XmlPullParser.Event eType = parser.next(); + if (eType == XmlPullParser.Event.START_ELEMENT && parser.getName().equals("serviceName")) { + String serviceNameString = parser.nextText(); + serviceName = JidCreate.domainBareFrom(serviceNameString); + } + else if (eType == XmlPullParser.Event.START_ELEMENT && parser.getName().equals("autoLogin")) { + autoLogin = parser.nextText(); + } + else if (eType == XmlPullParser.Event.END_ELEMENT && parser.getName().equals("gateway")) { + data.addService(serviceName, Boolean.parseBoolean(autoLogin)); + gatewayDone = true; + } + } + } + + else if (eventType == XmlPullParser.Event.END_ELEMENT && parser.getName().equals("gateways")) { + done = true; + } + else if (!isInstalled) { + done = true; + } + } + return data; + } + } + + +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayTabItem.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayTabItem.java similarity index 76% rename from src/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayTabItem.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayTabItem.java index ea9f2de4d..eeb2c941e 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayTabItem.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayTabItem.java @@ -21,6 +21,7 @@ import org.jivesoftware.resource.SparkRes; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.spark.PresenceManager; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.component.RolloverButton; @@ -35,26 +36,23 @@ public class GatewayTabItem extends CollapsiblePane implements GatewayItem { /** - * */ private static final long serialVersionUID = 5589644402913737488L; /** - * */ private boolean signedIn; - private Transport _transport; - private DefaultListModel model = new DefaultListModel(); - private JLabel _status = new JLabel(); - private JPanel _listPanel = new JPanel(new GridBagLayout()); - private JLabel _statusIcon = new JLabel(); - private RolloverButton _signInOut = new RolloverButton(); - private RolloverButton _registerButton = new RolloverButton(); - private JCheckBox _autoJoin = new JCheckBox(); - private boolean _transportRegistered = false; - - private RolloverButton _autoJoinButton = new RolloverButton(); + private final Transport _transport; + private final JLabel _status = new JLabel(); + private final JPanel _listPanel = new JPanel(new GridBagLayout()); + private final JLabel _statusIcon = new JLabel(); + private final RolloverButton _signInOut = new RolloverButton(); + private final RolloverButton _registerButton = new RolloverButton(); + private final JCheckBox _autoJoin = new JCheckBox(); + private boolean _transportRegistered; + + private final RolloverButton _autoJoinButton = new RolloverButton(); public GatewayTabItem(final Transport transport) { this._transport = transport; @@ -70,8 +68,9 @@ public GatewayTabItem(final Transport transport) { getTitlePane().add(_status); this.setTitle(transport.getName()); - _listPanel.setBackground((Color)UIManager.get("ContactItem.background")); - JList _transportMenu = new JList( model ); + _listPanel.setBackground((Color) UIManager.get("ContactItem.background")); + DefaultListModel model = new DefaultListModel<>(); + JList _transportMenu = new JList<>(model); _transportMenu.setCellRenderer(new JPanelRenderer()); this.setContentPane(_listPanel); @@ -81,7 +80,7 @@ public GatewayTabItem(final Transport transport) { // Check if transport is already registered if (_transportRegistered) { // If yes, check if it is online - if (PresenceManager.isOnline(transport.getServiceName())) { + if (PresenceManager.isOnline(transport.getXMPPServiceDomain())) { getTitlePane().setIcon(transport.getIcon()); _status.setText(Res.getString("online")); @@ -110,19 +109,21 @@ public GatewayTabItem(final Transport transport) { if (isRegistered) { // Check if auto login is set. boolean autoJoin = TransportUtils.autoJoinService(transport - .getServiceName()); + .getXMPPServiceDomain()); if (autoJoin) { Presence oldPresence = statusBar.getPresence(); - Presence presence = new Presence(oldPresence.getType(), - oldPresence.getStatus(), - oldPresence.getPriority(), - oldPresence.getMode()); - presence.setTo(transport.getServiceName()); + Presence presence = StanzaBuilder.buildPresence() + .ofType(oldPresence.getType()) + .setStatus(oldPresence.getStatus()) + .setPriority(oldPresence.getPriority()) + .setMode(oldPresence.getMode()) + .build(); + presence.setTo(transport.getXMPPServiceDomain()); try { SparkManager.getConnection().sendStanza(presence); } - catch ( SmackException.NotConnectedException e ) + catch ( SmackException.NotConnectedException | InterruptedException e ) { Log.error( "Unable to send presence.", e ); } @@ -139,31 +140,31 @@ private void createTransportMenu() { _signInOut.addActionListener( e -> { if (signedIn) { - final Presence offlinePresence = new Presence( - Presence.Type.unavailable); - offlinePresence.setTo(_transport.getServiceName()); + final Presence offlinePresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .build(); + offlinePresence.setTo(_transport.getXMPPServiceDomain()); try { SparkManager.getConnection().sendStanza(offlinePresence); - _statusIcon.setIcon(SparkRes - .getImageIcon(SparkRes.YELLOW_BALL)); + _statusIcon.setIcon(SparkRes.getImageIcon(SparkRes.Icon.YELLOW_BALL)); } - catch ( SmackException.NotConnectedException e1 ) + catch ( SmackException.NotConnectedException | InterruptedException e1 ) { Log.error( "Unable to send presence.", e1 ); } } else { - final Presence onlinePresence = new Presence( - Presence.Type.available); - onlinePresence.setTo(_transport.getServiceName()); + final Presence onlinePresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .build(); + onlinePresence.setTo(_transport.getXMPPServiceDomain()); try { SparkManager.getConnection().sendStanza(onlinePresence); - _statusIcon.setIcon(SparkRes - .getImageIcon(SparkRes.YELLOW_BALL)); + _statusIcon.setIcon(SparkRes.getImageIcon(SparkRes.Icon.YELLOW_BALL)); } - catch ( SmackException.NotConnectedException e1 ) + catch ( SmackException.NotConnectedException | InterruptedException e1 ) { Log.error( "Unable to send presence.", e1 ); } @@ -176,7 +177,7 @@ private void createTransportMenu() { // If transport is registered, we can check if the autojoin is enabled if (_transportRegistered) { _autoJoin.setSelected(TransportUtils.autoJoinService(_transport - .getServiceName())); + .getXMPPServiceDomain())); _registerButton.setText(Res .getString("menuitem.delete.login.information")); _signInOut.setEnabled(true); @@ -187,7 +188,7 @@ private void createTransportMenu() { _autoJoinButton.addActionListener( e -> { _autoJoin.setSelected(!_autoJoin.isSelected()); - TransportUtils.setAutoJoin(_transport.getServiceName(), _autoJoin.isSelected()); + TransportUtils.setAutoJoin(_transport.getXMPPServiceDomain(), _autoJoin.isSelected()); } ); @@ -209,9 +210,9 @@ private void createTransportMenu() { try { TransportUtils.unregister( SparkManager.getConnection(), - _transport.getServiceName()); + _transport.getXMPPServiceDomain()); setNotRegistered(); - } catch (SmackException e1) { + } catch (SmackException | InterruptedException e1) { Log.error(e1); } } @@ -219,7 +220,7 @@ private void createTransportMenu() { // If transport is not registered we should show the // register gui TransportRegistrationDialog registrationDialog = new TransportRegistrationDialog( - _transport.getServiceName()); + _transport.getXMPPServiceDomain()); registrationDialog.invoke(); // Set user as offline while he fills in the login // information @@ -271,27 +272,27 @@ private void setNotRegistered() { _signInOut.setEnabled(false); _signInOut.setText(Res.getString("menuitem.sign.in")); _autoJoinButton.setEnabled(false); - _statusIcon.setIcon(SparkRes.getImageIcon(SparkRes.BLUE_BALL)); + _statusIcon.setIcon(SparkRes.getImageIcon(SparkRes.Icon.BLUE_BALL)); } // Set GUI when user is registered but offline private void setOffline() { _transportRegistered = true; _autoJoin.setSelected(TransportUtils.autoJoinService(_transport - .getServiceName())); + .getXMPPServiceDomain())); _registerButton.setText(Res .getString("menuitem.delete.login.information")); _signInOut.setEnabled(true); _signInOut.setText(Res.getString("menuitem.sign.in")); _autoJoinButton.setEnabled(true); - _statusIcon.setIcon(SparkRes.getImageIcon(SparkRes.RED_BALL)); + _statusIcon.setIcon(SparkRes.getImageIcon(SparkRes.Icon.RED_BALL)); } // Set GUI when user is online with rigistered transport private void setOnline() { - _statusIcon.setIcon(SparkRes.getImageIcon(SparkRes.GREEN_BALL)); + _statusIcon.setIcon(SparkRes.getImageIcon(SparkRes.Icon.GREEN_BALL)); EventQueue.invokeLater( () -> _autoJoin.setSelected(TransportUtils.autoJoinService(_transport - .getServiceName())) ); + .getXMPPServiceDomain())) ); _signInOut.setText(Res.getString("menuitem.sign.out")); _signInOut.setEnabled(true); @@ -301,17 +302,18 @@ private void setOnline() { } // Change gui if transport signed on or off - public void signedIn(final boolean signedIn) { + @Override + public void signedIn(final boolean signedIn) { if (!signedIn) { getTitlePane().setIcon(_transport.getInactiveIcon()); _status.setText(Res.getString("offline")); if (!_transportRegistered) { - _statusIcon.setIcon(SparkRes.getImageIcon(SparkRes.BLUE_BALL)); + _statusIcon.setIcon(SparkRes.getImageIcon(SparkRes.Icon.BLUE_BALL)); _signInOut.setText(Res.getString("menuitem.sign.in")); } else { - _statusIcon.setIcon(SparkRes.getImageIcon(SparkRes.RED_BALL)); + _statusIcon.setIcon(SparkRes.getImageIcon(SparkRes.Icon.RED_BALL)); setOffline(); } @@ -324,7 +326,8 @@ public void signedIn(final boolean signedIn) { this.signedIn = signedIn; } - public boolean isLoggedIn() { + @Override + public boolean isLoggedIn() { return signedIn; } diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/TransportItem.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/TransportItem.java similarity index 92% rename from src/java/org/jivesoftware/sparkimpl/plugin/gateways/TransportItem.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/TransportItem.java index 7b60923a2..c46d7e7e2 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/TransportItem.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/TransportItem.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,18 +28,17 @@ import javax.swing.JPanel; /** - * */ public class TransportItem extends JPanel { private static final long serialVersionUID = 6321253573105576262L; - private JLabel iconLabel; - private JLabel titleLabel; - private JLabel descriptionLabel; - private JLabel activeLabel; + private final JLabel iconLabel; + private final JLabel titleLabel; + private final JLabel descriptionLabel; + private final JLabel activeLabel; private String transportAddress; - private Transport transport; + private final Transport transport; public TransportItem(Transport transport, boolean active, String address) { setLayout(new GridBagLayout()); @@ -67,7 +62,7 @@ public TransportItem(Transport transport, boolean active, String address) { activeLabel.setFont(new Font("Dialog", Font.PLAIN, 10)); if (active) { - activeLabel.setText(Res.getString("active")); + activeLabel.setText(Res.getString("is.active")); activeLabel.setForeground(Color.green); } else { diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/TransportRegistrationDialog.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/TransportRegistrationDialog.java similarity index 80% rename from src/java/org/jivesoftware/sparkimpl/plugin/gateways/TransportRegistrationDialog.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/TransportRegistrationDialog.java index c93a226ff..b71562275 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/TransportRegistrationDialog.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/TransportRegistrationDialog.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +17,7 @@ import org.jivesoftware.resource.Res; import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.component.RolloverButton; @@ -32,7 +28,7 @@ import org.jivesoftware.spark.util.ResourceUtils; import org.jivesoftware.sparkimpl.plugin.gateways.transports.Transport; import org.jivesoftware.sparkimpl.plugin.gateways.transports.TransportUtils; - +import org.jxmpp.jid.DomainBareJid; import javax.swing.JDialog; import javax.swing.JLabel; @@ -60,21 +56,21 @@ */ public class TransportRegistrationDialog extends JPanel implements ActionListener, KeyListener { private static final long serialVersionUID = -5766084489027807577L; - private JTextField usernameField = new JTextField(); - private JPasswordField passwordField = new JPasswordField(); - private JTextField nicknameField = new JTextField(); - private RolloverButton registerButton = new RolloverButton("", null); - private RolloverButton cancelButton = new RolloverButton("", null); + private final JTextField usernameField = new JTextField(); + private final JPasswordField passwordField = new JPasswordField(); + private final JTextField nicknameField = new JTextField(); + private final RolloverButton registerButton = new RolloverButton("", null); + private final RolloverButton cancelButton = new RolloverButton("", null); private JDialog dialog; - private String serviceName; - private Transport transport; + private final DomainBareJid serviceName; + private final Transport transport; /** * Initiation Dialog with the tranport service name. * * @param serviceName the name of the transport service. */ - public TransportRegistrationDialog(String serviceName) { + public TransportRegistrationDialog(DomainBareJid serviceName) { setLayout(new GridBagLayout()); @@ -131,7 +127,7 @@ public void invoke() { dialog = new JDialog(SparkManager.getMainWindow(), transport.getTitle(), false); dialog.add(this); dialog.pack(); - dialog.setSize(400, 200); + dialog.setSize(400, 250); dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); GraphicUtils.centerWindowOnComponent(dialog, SparkManager.getMainWindow()); @@ -163,7 +159,8 @@ public String getNickname() { return nicknameField.getText(); } - public void actionPerformed(ActionEvent e) { + @Override + public void actionPerformed(ActionEvent e) { String username = getScreenName(); String password = getPassword(); String nickname = getNickname(); @@ -182,20 +179,23 @@ public void actionPerformed(ActionEvent e) { } try { - TransportUtils.registerUser(SparkManager.getConnection(), serviceName, username, password, nickname, stanza -> { - IQ result = (IQ) stanza; - if ( result.getType() == IQ.Type.error ) { - JOptionPane.showMessageDialog(TransportRegistrationDialog.this, Res.getString("message.registration.transport.failed"), Res.getString("title.registration.error"), JOptionPane.ERROR_MESSAGE); - } else { - // Send Directed Presence - final StatusBar statusBar = SparkManager.getWorkspace().getStatusBar(); - Presence presence = statusBar.getPresence(); - presence.setTo(transport.getServiceName()); - SparkManager.getConnection().sendStanza(presence); - } - } ); + TransportUtils.registerUser(SparkManager.getConnection(), serviceName, username, password, nickname, + stanza -> { + // Send Directed Presence + final StatusBar statusBar = SparkManager.getWorkspace().getStatusBar(); + Presence presence = statusBar.getPresence(); + presence.setTo(transport.getXMPPServiceDomain()); + try { + SparkManager.getConnection().sendStanza(presence); + } catch (NotConnectedException | InterruptedException e1) { + // TODO: handle this. + } + }, + exception -> + JOptionPane.showMessageDialog(TransportRegistrationDialog.this, Res.getString("message.registration.transport.failed"), Res.getString("title.registration.error"), JOptionPane.ERROR_MESSAGE) + ); } - catch (SmackException e1) { + catch (SmackException | InterruptedException e1) { JOptionPane.showMessageDialog(TransportRegistrationDialog.this, Res.getString("message.registration.transport.failed"), Res.getString("title.registration.error"), JOptionPane.ERROR_MESSAGE); } @@ -204,16 +204,19 @@ public void actionPerformed(ActionEvent e) { - public void keyTyped(KeyEvent keyEvent) { + @Override + public void keyTyped(KeyEvent keyEvent) { } - public void keyPressed(KeyEvent keyEvent) { + @Override + public void keyPressed(KeyEvent keyEvent) { if (keyEvent.getKeyCode() == KeyEvent.VK_ENTER) { actionPerformed(null); } } - public void keyReleased(KeyEvent keyEvent) { + @Override + public void keyReleased(KeyEvent keyEvent) { } } diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/FacebookTransport.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/FacebookTransport.java new file mode 100644 index 000000000..29e6ec7e2 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/FacebookTransport.java @@ -0,0 +1,80 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.gateways.transports; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jxmpp.jid.DomainBareJid; + +import javax.swing.*; + +public class FacebookTransport implements Transport { + + private DomainBareJid serviceName; + + public FacebookTransport(DomainBareJid serviceName){ + this.serviceName = serviceName; + } + + @Override + public String getTitle(){ + return Res.getString("title.facebook.registration"); + } + + @Override + public String getInstructions() { + return Res.getString("message.enter.facebook"); + } + + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.FACEBOOK_TRANSPORT_ACTIVE_IMAGE); + } + + @Override + public Icon getInactiveIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.FACEBOOK_TRANSPORT_INACTIVE_IMAGE); + } + + @Override + public DomainBareJid getXMPPServiceDomain() { + return serviceName; + } + + @Override + public String getName(){ + return "Facebook"; + } + + public void setServiceName(DomainBareJid serviceName) { + this.serviceName = serviceName; + } + + @Override + public Boolean requiresUsername() { + return true; + } + + @Override + public Boolean requiresPassword() { + return true; + } + + @Override + public Boolean requiresNickname() { + return false; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/GaduGaduTransport.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/GaduGaduTransport.java new file mode 100644 index 000000000..6c72ec157 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/GaduGaduTransport.java @@ -0,0 +1,83 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.gateways.transports; + +import org.jivesoftware.resource.SparkRes; +import org.jxmpp.jid.DomainBareJid; +import org.jivesoftware.resource.Res; + +import javax.swing.*; + +/** + */ +public class GaduGaduTransport implements Transport { + + private DomainBareJid serviceName; + + public GaduGaduTransport(DomainBareJid serviceName){ + this.serviceName = serviceName; + } + + @Override + public String getTitle(){ + return Res.getString("title.gadugadu.registration"); + } + + @Override + public String getInstructions() { + return Res.getString("message.enter.gadugadu"); + } + + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.GADUGADU_TRANSPORT_ACTIVE_IMAGE); + } + + @Override + public Icon getInactiveIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.GADUGADU_TRANSPORT_INACTIVE_IMAGE); + } + + @Override + public DomainBareJid getXMPPServiceDomain() { + return serviceName; + } + + @Override + public String getName(){ + return "GaduGadu"; + } + + public void setServiceName(DomainBareJid serviceName) { + this.serviceName = serviceName; + } + + @Override + public Boolean requiresUsername() { + return true; + } + + @Override + public Boolean requiresPassword() { + return true; + } + + @Override + public Boolean requiresNickname() { + return false; + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/IRCTransport.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/IRCTransport.java new file mode 100644 index 000000000..0fc95a2cb --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/IRCTransport.java @@ -0,0 +1,83 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.gateways.transports; + +import org.jivesoftware.resource.SparkRes; +import org.jxmpp.jid.DomainBareJid; +import org.jivesoftware.resource.Res; + +import javax.swing.*; + +/** + */ +public class IRCTransport implements Transport { + + private DomainBareJid serviceName; + + public IRCTransport(DomainBareJid serviceName){ + this.serviceName = serviceName; + } + + @Override + public String getTitle(){ + return Res.getString("title.irc.registration"); + } + + @Override + public String getInstructions() { + return Res.getString("message.enter.irc"); + } + + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.IRC_TRANSPORT_ACTIVE_IMAGE); + } + + @Override + public Icon getInactiveIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.IRC_TRANSPORT_INACTIVE_IMAGE); + } + + @Override + public DomainBareJid getXMPPServiceDomain() { + return serviceName; + } + + @Override + public String getName(){ + return "IRC"; + } + + public void setServiceName(DomainBareJid serviceName) { + this.serviceName = serviceName; + } + + @Override + public Boolean requiresUsername() { + return true; + } + + @Override + public Boolean requiresPassword() { + return false; + } + + @Override + public Boolean requiresNickname() { + return true; + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/MySpaceTransport.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/MySpaceTransport.java new file mode 100644 index 000000000..f1105552c --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/MySpaceTransport.java @@ -0,0 +1,79 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.gateways.transports; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jxmpp.jid.DomainBareJid; + +import javax.swing.*; + +public class MySpaceTransport implements Transport { + private DomainBareJid serviceName; + + public MySpaceTransport(DomainBareJid serviceName){ + this.serviceName = serviceName; + } + + @Override + public String getTitle(){ + return Res.getString("title.myspace.registration"); + } + + @Override + public String getInstructions() { + return Res.getString("message.enter.myspace"); + } + + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.MYSPACE_TRANSPORT_ACTIVE_IMAGE); + } + + @Override + public Icon getInactiveIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.MYSPACE_TRANSPORT_INACTIVE_IMAGE); + } + + @Override + public DomainBareJid getXMPPServiceDomain() { + return serviceName; + } + + @Override + public String getName(){ + return "MySpace"; + } + + public void setServiceName(DomainBareJid serviceName) { + this.serviceName = serviceName; + } + + @Override + public Boolean requiresUsername() { + return true; + } + + @Override + public Boolean requiresPassword() { + return true; + } + + @Override + public Boolean requiresNickname() { + return false; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/QQTransport.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/QQTransport.java new file mode 100644 index 000000000..facd3ec3d --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/QQTransport.java @@ -0,0 +1,83 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.gateways.transports; + + +import org.jivesoftware.resource.SparkRes; +import org.jxmpp.jid.DomainBareJid; +import org.jivesoftware.resource.Res; + +import javax.swing.*; + +/** + */ +public class QQTransport implements Transport { + private DomainBareJid serviceName; + + public QQTransport(DomainBareJid serviceName) { + this.serviceName = serviceName; + + } + + @Override + public String getTitle() { + return Res.getString("title.qq.registration"); + } + + @Override + public String getInstructions() { + return Res.getString("message.enter.qq"); + } + + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.QQ_TRANSPORT_ACTIVE_IMAGE); + } + + @Override + public Icon getInactiveIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.QQ_TRANSPORT_INACTIVE_IMAGE); + } + + @Override + public DomainBareJid getXMPPServiceDomain() { + return serviceName; + } + + @Override + public String getName() { + return "QQ"; + } + + public void setServiceName(DomainBareJid serviceName) { + this.serviceName = serviceName; + } + + @Override + public Boolean requiresUsername() { + return true; + } + + @Override + public Boolean requiresPassword() { + return true; + } + + @Override + public Boolean requiresNickname() { + return false; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/SametimeTransport.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/SametimeTransport.java new file mode 100644 index 000000000..ea251091d --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/SametimeTransport.java @@ -0,0 +1,79 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.gateways.transports; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jxmpp.jid.DomainBareJid; + +import javax.swing.*; + +public class SametimeTransport implements Transport { + private DomainBareJid serviceName; + + public SametimeTransport(DomainBareJid serviceName){ + this.serviceName = serviceName; + } + + @Override + public String getTitle(){ + return Res.getString("title.sametime.registration"); + } + + @Override + public String getInstructions() { + return Res.getString("message.enter.sametime"); + } + + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.SAMETIME_TRANSPORT_ACTIVE_IMAGE); + } + + @Override + public Icon getInactiveIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.SAMETIME_TRANSPORT_INACTIVE_IMAGE); + } + + @Override + public DomainBareJid getXMPPServiceDomain() { + return serviceName; + } + + @Override + public String getName(){ + return "Sametime"; + } + + public void setServiceName(DomainBareJid serviceName) { + this.serviceName = serviceName; + } + + @Override + public Boolean requiresUsername() { + return true; + } + + @Override + public Boolean requiresPassword() { + return true; + } + + @Override + public Boolean requiresNickname() { + return false; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/SimpleTransport.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/SimpleTransport.java new file mode 100644 index 000000000..404da5c76 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/SimpleTransport.java @@ -0,0 +1,83 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.gateways.transports; + +import org.jivesoftware.resource.SparkRes; +import org.jxmpp.jid.DomainBareJid; +import org.jivesoftware.resource.Res; + +import javax.swing.*; + +/** + */ +public class SimpleTransport implements Transport { + + private DomainBareJid serviceName; + + public SimpleTransport(DomainBareJid serviceName){ + this.serviceName = serviceName; + } + + @Override + public String getTitle(){ + return Res.getString("title.simple.registration"); + } + + @Override + public String getInstructions() { + return Res.getString("message.enter.simple"); + } + + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.SIMPLE_TRANSPORT_ACTIVE_IMAGE); + } + + @Override + public Icon getInactiveIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.SIMPLE_TRANSPORT_INACTIVE_IMAGE); + } + + @Override + public DomainBareJid getXMPPServiceDomain() { + return serviceName; + } + + @Override + public String getName(){ + return "SIMPLE"; + } + + public void setServiceName(DomainBareJid serviceName) { + this.serviceName = serviceName; + } + + @Override + public Boolean requiresUsername() { + return true; + } + + @Override + public Boolean requiresPassword() { + return true; + } + + @Override + public Boolean requiresNickname() { + return false; + } + +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/Transport.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/Transport.java similarity index 92% rename from src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/Transport.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/Transport.java index 0ff6b258a..15cb7bb67 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/Transport.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/Transport.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,8 +17,9 @@ import javax.swing.Icon; +import org.jxmpp.jid.DomainBareJid; + /** - * */ public interface Transport { @@ -34,7 +31,7 @@ public interface Transport { Icon getInactiveIcon(); - String getServiceName(); + DomainBareJid getXMPPServiceDomain(); String getName(); diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/TransportUtils.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/TransportUtils.java new file mode 100644 index 000000000..7ac7f49bb --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/TransportUtils.java @@ -0,0 +1,228 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.gateways.transports; + +import org.jivesoftware.smack.*; +import org.jivesoftware.smack.filter.IQReplyFilter; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.util.ExceptionCallback; +import org.jivesoftware.smack.util.SuccessCallback; +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smackx.iqregister.packet.Registration; +import org.jivesoftware.smackx.iqprivate.PrivateDataManager; +import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; +import org.jivesoftware.smackx.disco.packet.DiscoverInfo; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.gateways.GatewayPrivateData; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; + +import javax.xml.namespace.QName; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * Handles some basic handling of + */ +public class TransportUtils { + + private static final Map transports = new HashMap<>(); + private static GatewayPrivateData gatewayPreferences; + + private TransportUtils() { + } + + static { + PrivateDataManager.addPrivateDataProvider(GatewayPrivateData.ELEMENT, GatewayPrivateData.NAMESPACE, new GatewayPrivateData.ConferencePrivateDataProvider()); + + final Runnable loadGateways = () -> { + PrivateDataManager pdm = SparkManager.getSessionManager().getPersonalDataManager(); + gatewayPreferences = null; + //Re: SPARK-1483 comment the loop as it causes Out Of Memory (infinite loop) if preferences not found + //If really necessary to try more times, a Thread Pool may be used: java ScheduledThreadPoolExecutor for example + //while (gatewayPreferences == null){ + try { + gatewayPreferences = (GatewayPrivateData)pdm.getPrivateData(GatewayPrivateData.ELEMENT, GatewayPrivateData.NAMESPACE); + } + catch (XMPPException | SmackException | InterruptedException e) { + Log.error("Unable to load private data for Gateways", e); + } + //} + }; + + TaskEngine.getInstance().submit(loadGateways); + } + + public static boolean autoJoinService(DomainBareJid serviceName) { + if (gatewayPreferences != null) { + return gatewayPreferences.autoLogin(serviceName); + }else{ + return false; + } + } + + public static void setAutoJoin(DomainBareJid serviceName, boolean autoJoin) { + if (gatewayPreferences != null) { + gatewayPreferences.addService(serviceName, autoJoin); + PrivateDataManager pdm = SparkManager.getSessionManager().getPersonalDataManager(); + try { + pdm.setPrivateData(gatewayPreferences); + } + catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + } + } else { + Log.warning("Cannot set privacy data as gatewayPreferences is NULL"); + } + } + + /** + * + * @param transportAddress + * @return + */ + public static Transport getTransport(DomainBareJid transportAddress) { + // Return transport. + return transports.get(transportAddress); + } + + /** + * Returns true if the jid is from a gateway. + * @param jid the jid. + * @return true if the jid is from a gateway. + */ + public static boolean isFromGateway(Jid jid) { + DomainBareJid serviceName = jid.asDomainBareJid(); + return transports.containsKey(serviceName); + } + + /** + * + * @param address + * @param transport + */ + public static void addTransport(DomainBareJid address, Transport transport) { + transports.put(address, transport); + } + + public static Collection getTransports() { + return transports.values(); + } + + /** + * Checks if the user is registered with a gateway. + * + * @param con the XMPPConnection. + * @param transport the transport. + * @return true if the user is registered with the transport. + */ + public static boolean isRegistered(XMPPConnection con, Transport transport) { + if (!con.isConnected()) { + return false; + } + + ServiceDiscoveryManager discoManager = SparkManager.getDiscoManager(); + try { + DiscoverInfo info = discoManager.discoverInfo(transport.getXMPPServiceDomain()); + return info.containsFeature("jabber:iq:registered"); + } + catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + } + return false; + } + + /** + * Registers a user with a gateway. + * + * @param con the XMPPConnection. + * @param gatewayDomain the domain of the gateway (service name) + * @param username the username. + * @param password the password. + * @param nickname the nickname. + * @throws InterruptedException + * @throws XMPPException thrown if there was an issue registering with the gateway. + */ + public static void registerUser(XMPPConnection con, DomainBareJid gatewayDomain, String username, String password, + String nickname, SuccessCallback callback, ExceptionCallback exceptionCallback) + throws SmackException.NotConnectedException, InterruptedException { + Map attributes = new HashMap<>(); + if (username != null) { + attributes.put("username", username); + } + if (password != null) { + attributes.put("password", password); + } + if (nickname != null) { + attributes.put("nick", nickname); + } + Registration registration = new Registration( attributes ); + registration.setType(IQ.Type.set); + registration.setTo(gatewayDomain); + registration.addExtension(new GatewayRegisterExtension()); + + con.sendIqRequestAsync(registration) + .onSuccess(callback) + .onError(exceptionCallback); + } + + /** + * @param con the XMPPConnection. + * @param gatewayDomain the domain of the gateway (service name) + * @throws InterruptedException + * @throws XMPPException thrown if there was an issue unregistering with the gateway. + */ + public static void unregister(XMPPConnection con, DomainBareJid gatewayDomain) throws SmackException.NotConnectedException, InterruptedException + { + Map map = new HashMap<>(); + map.put("remove", ""); + Registration registration = new Registration( map ); + registration.setType(IQ.Type.set); + registration.setTo(gatewayDomain); + + con.sendIqRequestAsync(registration) + .onError(e -> Log.warning( "Unable to unregister from gateway: " + e)); + } + + + static class GatewayRegisterExtension implements ExtensionElement { + public static final String ELEMENT_NAME = "x"; + public static final String NAMESPACE = "jabber:iq:gateway:register"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT_NAME); + + @Override + public String getElementName() { + return ELEMENT_NAME; + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public String toXML(XmlEnvironment xmlEnvironment) { + return "<" + getElementName() + " xmlns=\"" + getNamespace() + "\"/>"; + } + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/XMPPTransport.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/XMPPTransport.java new file mode 100644 index 000000000..318fb789b --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/XMPPTransport.java @@ -0,0 +1,83 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.gateways.transports; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jxmpp.jid.DomainBareJid; + +import javax.swing.*; + +/** + */ +public class XMPPTransport implements Transport { + + private DomainBareJid serviceName; + + public XMPPTransport(DomainBareJid serviceName) { + this.serviceName = serviceName; + } + + @Override + public String getTitle() { + return Res.getString("title.xmpp.registration"); + } + + @Override + public String getInstructions() { + return Res.getString("message.enter.xmpp"); + } + + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.XMPP_TRANSPORT_ACTIVE_IMAGE); + } + + @Override + public Icon getInactiveIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.XMPP_TRANSPORT_INACTIVE_IMAGE); + } + + @Override + public DomainBareJid getXMPPServiceDomain() { + return serviceName; + } + + @Override + public String getName() { + return "XMPP"; + } + + public void setServiceName(DomainBareJid serviceName) { + this.serviceName = serviceName; + } + + @Override + public Boolean requiresUsername() { + return true; + } + + @Override + public Boolean requiresPassword() { + return true; + } + + @Override + public Boolean requiresNickname() { + return false; + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/history/ConversationHistoryPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/history/ConversationHistoryPlugin.java new file mode 100644 index 000000000..9e133daaa --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/history/ConversationHistoryPlugin.java @@ -0,0 +1,341 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.history; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.xml.SmackXmlParser; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.spark.ui.ContactList; +import org.jivesoftware.spark.ui.MessageFilter; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.impl.JidCreate; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Adds a simple shortcut to see the last 10 conversations. + * + * @author Derek DeMoro + */ +public class ConversationHistoryPlugin implements Plugin { + + private final List historyList = new ArrayList<>(); + private File transcriptDir; + private File conFile; + + private final DefaultListModel model = new DefaultListModel<>(); + private JList contacts; + private Window window; + + private final Map jidMap = new HashMap<>(); + + @Override + public void initialize() { + transcriptDir = new File(SparkManager.getUserDirectory(), "transcripts"); + conFile = new File(transcriptDir, "conversations.xml"); + + contacts = new JList<>(model); + contacts.setCellRenderer(new InternalRenderer()); + + window = new Window(SparkManager.getMainWindow()); + + + final JPanel mainPanel = new JPanel(new BorderLayout()); + final JLabel titleLabel = new JLabel(Res.getString("label.recent.conversation")); + titleLabel.setFont(new Font("Dialog", Font.BOLD, 11)); + titleLabel.setHorizontalAlignment(JLabel.CENTER); + mainPanel.add(titleLabel, BorderLayout.NORTH); + mainPanel.add(contacts, BorderLayout.CENTER); + mainPanel.setBorder(BorderFactory.createLineBorder(Color.gray)); + + window.add(mainPanel); + + // Add Listeners + contacts.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (SwingUtilities.isRightMouseButton(e)) { + + contacts.setSelectedIndex(contacts.locationToIndex(e + .getPoint())); + EntityBareJid user = jidMap.get( contacts + .getSelectedValue() ); + ContactItem contact = SparkManager.getContactList() + .getContactItemByJID(user); + SparkManager.getContactList().setSelectedUser(contact.getJid().asBareJid()); + SparkManager.getContactList().showPopup(contacts, e, + contact); + } + + if (e.getClickCount() == 2) { + final JLabel label = contacts.getSelectedValue(); + EntityBareJid user = jidMap.get(label); + if (user != null) { + final String contactUsername = SparkManager + .getUserManager().getUserNicknameFromJID(user); + SparkManager.getChatManager().activateChat(user, + contactUsername); + window.dispose(); + } + } + } + }); + + contacts.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyChar() == KeyEvent.VK_ENTER) { + final JLabel label = contacts.getSelectedValue(); + EntityBareJid user = jidMap.get(label); + if (user != null) { + final String contactUsername = SparkManager.getUserManager().getUserNicknameFromJID(user); + SparkManager.getChatManager().activateChat(user, contactUsername); + window.dispose(); + } + } + else if (e.getKeyChar() == KeyEvent.VK_ESCAPE) { + window.dispose(); + } + } + }); + + contacts.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + + } + + @Override + public void focusLost(FocusEvent e) { + window.dispose(); + } + }); + + // Load Previous History + loadPreviousHistory(); + + // Add Keymapping to ContactList + SparkManager.getMainWindow().getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_E, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "historyPeople"); + SparkManager.getMainWindow().getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_E, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "historyPeople"); + + SparkManager.getMainWindow().getRootPane().getActionMap().put("historyPeople", new AbstractAction("historyPeople") { + private static final long serialVersionUID = 2465628887318732082L; + + @Override + public void actionPerformed(ActionEvent e) { + // Show History Popup + showHistoryPopup(); + } + }); + + // Persist order of conversations. + SparkManager.getChatManager().addMessageFilter(new MessageFilter() { + @Override + public void filterOutgoing(ChatRoom room, MessageBuilder messageBuilder) { + addUserToHistory(room); + } + + @Override + public void filterIncoming(ChatRoom room, MessageBuilder messageBuilder) { + addUserToHistory(room); + } + }); + } + + /** + * Adds the last user to the history tags. + * + * @param room the ChatRoom where the conversation took place. + */ + private void addUserToHistory(ChatRoom room) { + if (room instanceof ChatRoomImpl) { + ChatRoomImpl roomImpl = (ChatRoomImpl) room; + EntityBareJid jid = roomImpl.getParticipantJID(); + historyList.remove(jid); + historyList.add(0, jid); + } + } + + /** + * Displays the Previous Conversation Window. + */ + private void showHistoryPopup() { + // Get Transcript Directory + if (!transcriptDir.exists()) { + return; + } + + jidMap.clear(); + model.clear(); + + + final ContactList contactList = SparkManager.getWorkspace().getContactList(); + + int limit = Math.min(historyList.size(), 10); + + for (final EntityBareJid user : historyList.subList(0, limit)) { + + ContactItem contactItem = contactList.getContactItemByJID(user); + Icon icon; + if (contactItem != null) { + icon = contactItem.getIcon(); + if (icon == null) { + icon = SparkRes.getImageIcon(SparkRes.Icon.CLEAR_BALL_ICON); + } + + JLabel label = new JLabel(); + label.setText(contactItem.getDisplayName()); + label.setIcon(icon); + + model.addElement(label); + jidMap.put(label, user); + } + } + + + window.setSize(200, 200); + GraphicUtils.centerWindowOnComponent(window, SparkManager.getMainWindow()); + + + if (model.size() > 0) { + contacts.setSelectedIndex(0); + } + + window.setVisible(true); + + + } + + /** + * Loads the previous history. + */ + private void loadPreviousHistory() { + if (!conFile.exists()) { + return; + } + + // Otherwise load it. + try { + BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(conFile), StandardCharsets.UTF_8)); + final XmlPullParser parser = SmackXmlParser.newXmlParser(in); + + boolean done = false; + while (!done) { + XmlPullParser.Event eventType = parser.next(); + if (eventType == XmlPullParser.Event.START_ELEMENT && "user".equals(parser.getName())) { + EntityBareJid jid = JidCreate.entityBareFromUnescapedOrThrowUnchecked(parser.nextText()); + historyList.add(jid); + } + else if (eventType == XmlPullParser.Event.END_ELEMENT && "conversations".equals(parser.getName())) { + done = true; + } + } + in.close(); + } + catch (Exception e) { + Log.error(e); + } + } + + @Override + public void shutdown() { + final StringBuilder builder = new StringBuilder(); + builder.append(""); + for (EntityBareJid user : historyList) { + builder.append("").append(user.asUnescapedString()).append(""); + } + builder.append(""); + + // Write out to file system. + + if (!transcriptDir.exists()) { + transcriptDir.mkdirs(); + } + + // Write out new File + try { + File conFile = new File(transcriptDir, "conversations.xml"); + Files.write(conFile.toPath(), builder.toString().getBytes(StandardCharsets.UTF_8)); + } + catch (IOException e) { + Log.error(e); + } + } + + @Override + public boolean canShutDown() { + return true; + } + + @Override + public void uninstall() { + } + + /** + * Internal handling of a Jlabel Renderer. + */ + public static class InternalRenderer extends JLabel implements ListCellRenderer { + private static final long serialVersionUID = 1812281106979897477L; + + /** + * Construct Default Renderer. + */ + public InternalRenderer() { + setOpaque(true); + } + + @Override + public Component getListCellRendererComponent(JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus) { + if (isSelected) { + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + } + else { + setBackground(list.getBackground()); + setForeground(list.getForeground()); + } + + JLabel label = (JLabel) value; + setText(label.getText()); + setIcon(label.getIcon()); + return this; + } + } + + +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/history/FrequentContactsPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/history/FrequentContactsPlugin.java similarity index 82% rename from src/java/org/jivesoftware/sparkimpl/plugin/history/FrequentContactsPlugin.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/history/FrequentContactsPlugin.java index cc2c105e0..df4767a27 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/history/FrequentContactsPlugin.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/history/FrequentContactsPlugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,6 +22,7 @@ import org.jivesoftware.spark.ui.ContactItem; import org.jivesoftware.spark.ui.ContactList; import org.jivesoftware.spark.util.GraphicUtils; +import org.jxmpp.jid.impl.JidCreate; import java.awt.*; import java.awt.event.ActionEvent; @@ -45,36 +42,27 @@ import java.util.List; import java.util.Map; -import javax.swing.AbstractAction; -import javax.swing.BorderFactory; -import javax.swing.DefaultListModel; -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.KeyStroke; -import javax.swing.ListCellRenderer; -import javax.swing.SwingUtilities; +import javax.swing.*; /** - * Adds a simple feature to list your most "Popular" contacts. Popular contacts is basically who - * you talk with the most. + * Adds a simple feature to list your most "Popular" contacts. + * Popular contacts is basically who you talk with the most. */ public class FrequentContactsPlugin implements Plugin { private File transcriptDir; - private final DefaultListModel model = new DefaultListModel(); - private JList contacts; + private final DefaultListModel model = new DefaultListModel<>(); + private JList contacts; private Window window; - private Map jidMap = new HashMap<>(); + private final Map jidMap = new HashMap<>(); - public void initialize() { + @Override + public void initialize() { transcriptDir = new File(SparkManager.getUserDirectory(), "transcripts"); - contacts = new JList(model); + contacts = new JList<>(model); contacts.setCellRenderer(new InternalRenderer()); window = new Window(SparkManager.getMainWindow()); @@ -92,7 +80,8 @@ public void initialize() { // Add Listeners contacts.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { + @Override + public void mouseClicked(MouseEvent e) { if (SwingUtilities.isRightMouseButton(e)) { contacts.setSelectedIndex(contacts.locationToIndex(e @@ -101,17 +90,17 @@ public void mouseClicked(MouseEvent e) { .getSelectedValue() ); ContactItem contact = SparkManager.getContactList() .getContactItemByJID(user); - SparkManager.getContactList().setSelectedUser(contact.getJID()); + SparkManager.getContactList().setSelectedUser(contact.getJid().asBareJid()); SparkManager.getContactList().showPopup(contacts, e, contact); } if (e.getClickCount() == 2) { - final JLabel label = (JLabel) contacts.getSelectedValue(); + final JLabel label = contacts.getSelectedValue(); String user = jidMap.get(label); if (user != null) { final String contactUsername = SparkManager - .getUserManager().getUserNicknameFromJID(user); + .getUserManager().getUserNicknameFromJID(JidCreate.bareFromOrThrowUnchecked(user)); SparkManager.getChatManager().activateChat(user, contactUsername); window.dispose(); @@ -121,12 +110,13 @@ public void mouseClicked(MouseEvent e) { }); contacts.addKeyListener(new KeyAdapter() { - public void keyReleased(KeyEvent e) { + @Override + public void keyReleased(KeyEvent e) { if (e.getKeyChar() == KeyEvent.VK_ENTER) { - final JLabel label = (JLabel) contacts.getSelectedValue(); + final JLabel label = contacts.getSelectedValue(); String user = jidMap.get(label); if (user != null) { - final String contactUsername = SparkManager.getUserManager().getUserNicknameFromJID(user); + final String contactUsername = SparkManager.getUserManager().getUserNicknameFromJID(JidCreate.bareFromOrThrowUnchecked(user)); SparkManager.getChatManager().activateChat(user, contactUsername); window.dispose(); } @@ -138,11 +128,13 @@ else if (e.getKeyChar() == KeyEvent.VK_ESCAPE) { }); contacts.addFocusListener(new FocusListener() { - public void focusGained(FocusEvent e) { + @Override + public void focusGained(FocusEvent e) { } - public void focusLost(FocusEvent e) { + @Override + public void focusLost(FocusEvent e) { window.dispose(); } }); @@ -153,6 +145,7 @@ public void focusLost(FocusEvent e) { SparkManager.getMainWindow().getRootPane().getActionMap().put("favoritePeople", new AbstractAction("favoritePeople") { private static final long serialVersionUID = 6836584242669218932L; + @Override public void actionPerformed(ActionEvent e) { // Show History Popup showPopup(); @@ -184,7 +177,7 @@ private void showPopup() { if (contactItem != null) { icon = contactItem.getIcon(); if (icon == null) { - icon = SparkRes.getImageIcon(SparkRes.CLEAR_BALL_ICON); + icon = SparkRes.getImageIcon(SparkRes.Icon.CLEAR_BALL_ICON); } JLabel label = new JLabel(); @@ -221,7 +214,7 @@ private Collection getFavoriteContacts() { final File[] transcriptFiles = transcriptDir.listFiles( ( dir, name ) -> !name.contains("_current") && !name.equals("conversations.xml") ); final List files = Arrays.asList(transcriptFiles); - Collections.sort(files, sizeComparator); + files.sort(sizeComparator); int size = files.size(); if (size > 10) { @@ -244,21 +237,24 @@ private Collection getFavoriteContacts() { } - public void shutdown() { + @Override + public void shutdown() { } - public boolean canShutDown() { + @Override + public boolean canShutDown() { return true; } - public void uninstall() { + @Override + public void uninstall() { } /** * Internal handling of a JLabel Renderer. */ - public class InternalRenderer extends JLabel implements ListCellRenderer { + public static class InternalRenderer extends JLabel implements ListCellRenderer { private static final long serialVersionUID = -2925096995694392323L; /** @@ -268,7 +264,8 @@ public InternalRenderer() { setOpaque(true); } - public Component getListCellRendererComponent(JList list, + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, @@ -296,19 +293,7 @@ public Component getListCellRendererComponent(JList list, long int1 = item1.length(); long int2 = item2.length(); - if (int1 == int2) { - return 0; - } - - if (int1 > int2) { - return -1; - } - - if (int1 < int2) { - return 1; - } - - return 0; + return Long.compare(int2, int1); }; } diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/IdleTimeDetector.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/IdleTimeDetector.java new file mode 100644 index 000000000..1361fc4f8 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/IdleTimeDetector.java @@ -0,0 +1,13 @@ +package org.jivesoftware.sparkimpl.plugin.idle; + +/** + * Interface for classes fetching the computer idle time on a specific OS. + * @author Laurent Cohen + */ +interface IdleTimeDetector { + /** + * Get the total idle time of the system. + * @return the idle time in milliseconds. + */ + long getIdleTimeMillis(); +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/IdleTimeDetectorFactory.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/IdleTimeDetectorFactory.java new file mode 100644 index 000000000..dc411b072 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/IdleTimeDetectorFactory.java @@ -0,0 +1,21 @@ +package org.jivesoftware.sparkimpl.plugin.idle; + +import static org.apache.commons.lang3.SystemUtils.*; + +/** + * A factory implementation that returns an idle system detector based on the OS detected for the current host. + * + * @author Laurent Cohen + */ +public class IdleTimeDetectorFactory { + public IdleTimeDetector newIdleTimeDetector() { + if (IS_OS_WINDOWS) { + return new WindowsIdleTimeDetector(); + } else if (IS_OS_MAC) { + return new MacIdleTimeDetector(); + } else if (IS_OS_LINUX || IS_OS_FREE_BSD || IS_OS_OPEN_BSD) { + return new X11IdleTimeDetector(); + } + return null; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/MacIdleTimeDetector.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/MacIdleTimeDetector.java new file mode 100644 index 000000000..07f5f5f11 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/MacIdleTimeDetector.java @@ -0,0 +1,57 @@ +package org.jivesoftware.sparkimpl.plugin.idle; + +import com.sun.jna.Library; +import com.sun.jna.Native; + +/** + * Utility method to retrieve the idle time on Mac OS X 10.4+ + * @author kwindszus + * @author Laurent Cohen + */ +class MacIdleTimeDetector implements IdleTimeDetector { + /** + * Wraps the interactions with the native library. + */ + public interface ApplicationServices extends Library { + /** + * Wrapper for the native library. + */ + ApplicationServices INSTANCE = Native.load("ApplicationServices", ApplicationServices.class); + /** + * The type for any mouse or keyboard input event. + */ + int KCG_ANY_INPUT_EVENT_TYPE = ~0; + /** + * User-only state. + */ + int KCG_EVENT_SOURCE_STATE_PRIVATE = -1; + /** + * System-only state. + */ + int KCG_EVENT_SOURCE_STATE_HID_SYSTEM_STATE = 1; + /** + * User and system state. + */ + int KCG_EVENT_SOURCE_STATE_COMBINED_SESSION_STATE = 0; + + /** + * Returns the elapsed time since the last event for a Quartz event source. + * + * @param sourceStateId the source state to access. + * @param eventType the event type to access. To get the elapsed time since the previous input event: keyboard, mouse, or tablet, specify KCG_ANY_INPUT_EVENT_TYPE. + * @return the elapsed seconds since the last input event. + * @see "http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventSourceSecondsSinceLastEventType" + */ + double CGEventSourceSecondsSinceLastEventType(int sourceStateId, int eventType); + } + + /** + * {@inheritDoc} + */ + @Override + public long getIdleTimeMillis() { + final double idleTimeSeconds = ApplicationServices.INSTANCE.CGEventSourceSecondsSinceLastEventType( + ApplicationServices.KCG_EVENT_SOURCE_STATE_COMBINED_SESSION_STATE, ApplicationServices.KCG_ANY_INPUT_EVENT_TYPE); + return (long) (idleTimeSeconds * 1000); + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/UserIdlePlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/UserIdlePlugin.java new file mode 100644 index 000000000..a3f319d80 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/UserIdlePlugin.java @@ -0,0 +1,178 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * This plugin 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 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.jivesoftware.sparkimpl.plugin.idle; + +import org.jivesoftware.Spark; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.util.StringUtils; +import org.jivesoftware.spark.util.log.Log; +//import org.jivesoftware.sparkimpl.plugin.phone.PhonePlugin; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import java.util.Timer; +import java.util.TimerTask; + +/** + * Sets idle or online status based on activity + */ +public class UserIdlePlugin extends TimerTask implements Plugin { + + private final int CHECKTIME = 2; + private boolean hasChanged = false; + private static final LocalPreferences pref = SettingsManager.getLocalPreferences(); + private static Presence latestPresence; + private static String statustext; + private static boolean isLocked; + private IdleTimeDetector idleTimeDetector; + + @Override + public boolean canShutDown() { + return false; + } + + @Override + public void initialize() { + Timer timer = new Timer(); + // Since 10 minutes after boot start checking every 2 minutes + timer.schedule(this, (60 * 1000 * 10), (60 * 1000 * CHECKTIME)); + idleTimeDetector = new IdleTimeDetectorFactory().newIdleTimeDetector(); + + if (Spark.isWindows()) { + LockListener lockListener = new LockListener(); + lockListener.intWinLockListener(); + } + } + + @Override + public void shutdown() { + } + + @Override + public void uninstall() { + } + + private void setIdle() { + latestPresence = SparkManager.getWorkspace().getStatusBar().getPresence(); + if (!latestPresence.isAway()) { + statustext = pref.getIdleMessage(); + } else { + statustext = latestPresence.getStatus(); + } + + if (latestPresence.isAway()) { + Log.debug("UserIdlePlugin: Presence is already set to away"); + } else { + Presence statusPresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .setStatus(StringUtils.modifyWildcards(statustext)) + .setPriority(0) + .setMode(Presence.Mode.away) + .build(); + SparkManager.getSessionManager().changePresence(statusPresence); + Log.debug("UserIdlePlugin: Setting idle presence"); + } + } + + + private void setOnline() { + + /* TODO commented out when PhonePlugin was not ported to Maven. + if (PhonePlugin.onPhonePresence != null) { + SparkManager.getSessionManager().changePresence(PhonePlugin.onPhonePresence); + Log.debug("UserIdlePlugin: Returning from idle/lock - On the Phone"); + + } else if ((latestPresence.getStatus().contains("On the phone")) && (PhonePlugin.offPhonePresence != null) + && ((PhonePlugin.offPhonePresence.getMode().equals(Presence.Mode.dnd)) + || (PhonePlugin.offPhonePresence.getMode().equals(Presence.Mode.xa)))) { + SparkManager.getSessionManager().changePresence(PhonePlugin.offPhonePresence); + Log.debug("UserIdlePlugin: Matched DND/XA - Setting presence from PhonePlugin"); + + } else if (((latestPresence.getStatus().contains("On the phone")) && (PhonePlugin.offPhonePresence != null) + && (PhonePlugin.offPhonePresence.getStatus().contentEquals(statustext)))) { + Presence presence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .setStatus(PhonePlugin.offPhonePresence.getStatus()) + .setPriority(1) + .setMode(Presence.Mode.available) + .build(); + SparkManager.getSessionManager().changePresence(presence); + Log.debug("UserIdlePlugin: Setting presence from PhonePlugin ...."); + + } else if ((latestPresence.getStatus().contains("On the phone")) && (PhonePlugin.offPhonePresence != null)) { + SparkManager.getSessionManager().changePresence(PhonePlugin.offPhonePresence); + Log.debug("UserIdlePlugin: Setting presence from PhonePlugin"); + + } else { + */ + SparkManager.getSessionManager().changePresence(latestPresence); + Log.debug("UserIdlePlugin: Setting presence using latestPresence"); + /*}*/ + + + } + + @Override + public void run() { + if (idleTimeDetector == null) { + return; + } + if (!SparkManager.getConnection().isConnected()) return; + if (!pref.isIdleOn()) { + return; + } + + if (isLocked) { + if (!hasChanged) { + setIdle(); + hasChanged = true; + } + } else { + // Set idle/online status based on duration + long idleDuration = idleTimeDetector.getIdleTimeMillis() / 1000; + if (!hasChanged && idleDuration > pref.getIdleTime() * 60) { + setIdle(); + hasChanged = true; + } else if (hasChanged && idleDuration < 10) { + setOnline(); + hasChanged = false; + } + } + } + + + public static class LockListener { + + public void intWinLockListener() { + new Thread(() -> new WinLockListener() { + @Override + protected void onMachineLocked(int sessionId) { + isLocked = true; + } + + @Override + protected void onMachineUnlocked(int sessionId) { + isLocked = false; + } + }).start(); + } + + } +} + diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/WinLockListener.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/WinLockListener.java new file mode 100644 index 000000000..afd89b111 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/WinLockListener.java @@ -0,0 +1,121 @@ +package org.jivesoftware.sparkimpl.plugin.idle; + +import com.sun.jna.WString; +import com.sun.jna.platform.win32.*; +import org.jivesoftware.spark.util.log.Log; + + +public class WinLockListener implements WinUser.WindowProc { + + public WinLockListener() { + // define new window class + final WString windowClass = new WString("MyWindowClass"); + final WinDef.HMODULE hInst = Kernel32.INSTANCE.GetModuleHandle(""); + + WinUser.WNDCLASSEX wClass = new WinUser.WNDCLASSEX(); + wClass.hInstance = hInst; + wClass.lpfnWndProc = WinLockListener.this; + wClass.lpszClassName = windowClass.toString(); + + // register window class + User32.INSTANCE.RegisterClassEx(wClass); + getLastError(); + + // create new window + final WinDef.HWND hWnd = User32.INSTANCE.CreateWindowEx(User32.WS_EX_TOPMOST, windowClass.toString(), "'hidden helper window to catch Windows events", 0, 0, 0, 0, 0, null, // WM_DEVICECHANGE contradicts parent=WinUser.HWND_MESSAGE + null, hInst, null); + + getLastError(); + Log.debug("window sucessfully created! window hwnd: " + hWnd.getPointer().toString()); + + Wtsapi32.INSTANCE.WTSRegisterSessionNotification(hWnd, Wtsapi32.NOTIFY_FOR_THIS_SESSION); + + WinUser.MSG msg = new WinUser.MSG(); + while (User32.INSTANCE.GetMessage(msg, hWnd, 0, 0) != 0) { + User32.INSTANCE.TranslateMessage(msg); + User32.INSTANCE.DispatchMessage(msg); + } + + /// This code is to clean at the end. You can attach it to your custom application shutdown listener + Wtsapi32.INSTANCE.WTSUnRegisterSessionNotification(hWnd); + User32.INSTANCE.UnregisterClass(windowClass.toString(), hInst); + User32.INSTANCE.DestroyWindow(hWnd); + Log.debug("program exit!"); + } + + /* + * (non-Javadoc) + * + * @see com.sun.jna.platform.win32.User32.WindowProc#callback(com.sun.jna.platform .win32.WinDef.HWND, int, com.sun.jna.platform.win32.WinDef.WPARAM, com.sun.jna.platform.win32.WinDef.LPARAM) + */ + @Override + public WinDef.LRESULT callback(WinDef.HWND hwnd, int uMsg, WinDef.WPARAM wParam, WinDef.LPARAM lParam) { + switch (uMsg) { + case WinUser.WM_DESTROY: { + User32.INSTANCE.PostQuitMessage(0); + return new WinDef.LRESULT(0); + } + case WinUser.WM_SESSION_CHANGE: { + this.onSessionChange(wParam, lParam); + return new WinDef.LRESULT(0); + } + default: + return User32.INSTANCE.DefWindowProc(hwnd, uMsg, wParam, lParam); + } + } + + /** + * Gets the last error. + * + * @return the last error + */ + public int getLastError() { + int rc = Kernel32.INSTANCE.GetLastError(); + + if (rc != 0) + Log.debug("error: " + rc); + + return rc; + } + + /** + * On session change. + * + * @param wParam the w param + * @param lParam the l param + */ + protected void onSessionChange(WinDef.WPARAM wParam, WinDef.LPARAM lParam) { + switch (wParam.intValue()) { + case Wtsapi32.WTS_SESSION_LOCK: { + this.onMachineLocked(lParam.intValue()); + break; + } + case Wtsapi32.WTS_SESSION_UNLOCK: { + this.onMachineUnlocked(lParam.intValue()); + break; + } + } + } + + /** + * On machine locked. + * + * @param sessionId the session id + */ + protected void onMachineLocked(int sessionId) { + } + + /** + * On machine unlocked. + * + * @param sessionId the session id + */ + protected void onMachineUnlocked(int sessionId) { + } + /** + * Utility method to retrieve the idle time on Windows and sample code to test it. + * JNA shall be present in your classpath for this to work (and compile). + * @author ochafik + */ + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/WindowsIdleTimeDetector.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/WindowsIdleTimeDetector.java new file mode 100644 index 000000000..085af6d7b --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/WindowsIdleTimeDetector.java @@ -0,0 +1,67 @@ +package org.jivesoftware.sparkimpl.plugin.idle; + +import com.sun.jna.Native; +import com.sun.jna.Structure; +import com.sun.jna.win32.StdCallLibrary; + +import java.util.Arrays; +import java.util.List; + +/** + * Utility method to retrieve the idle time on Windows and sample code to test it. + * JNA shall be present in your classpath for this to work (and compile). + * @author ochafik + */ +class WindowsIdleTimeDetector implements IdleTimeDetector { + + public interface Kernel32 extends StdCallLibrary { + Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class); + + /** + * Retrieves the number of milliseconds that have elapsed since the system was started. + * @see "http://msdn2.microsoft.com/en-us/library/ms724408.aspx" + * @return number of milliseconds that have elapsed since the system was started. + */ + int GetTickCount(); + } + + /** + * Contains the time of the last input. + * @see "http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputstructures/lastinputinfo.asp" + */ + class LASTINPUTINFO extends Structure { + public int cbSize = 8; + + /** Tick count of when the last input event was received. */ + public int dwTime; + + @SuppressWarnings("rawtypes") + @Override + protected List getFieldOrder() { + return Arrays.asList("cbSize", "dwTime"); + } + } + + public interface User32 extends StdCallLibrary { + User32 INSTANCE = Native.load("user32", User32.class); + /** + * Retrieves the time of the last input event. + * @see "http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputfunctions/getlastinputinfo.asp" + * @return time of the last input event, in milliseconds + */ + boolean GetLastInputInfo(LASTINPUTINFO result); + } + + /** + * Get the amount of milliseconds that have elapsed since the last input event + * (mouse or keyboard) + * @return idle time in milliseconds + */ + @Override + public long getIdleTimeMillis() { + LASTINPUTINFO lastInputInfo = new LASTINPUTINFO(); + User32.INSTANCE.GetLastInputInfo(lastInputInfo); + return Kernel32.INSTANCE.GetTickCount() - lastInputInfo.dwTime; + } +} + diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/X11IdleTimeDetector.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/X11IdleTimeDetector.java new file mode 100644 index 000000000..53fca5b14 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/X11IdleTimeDetector.java @@ -0,0 +1,111 @@ +package org.jivesoftware.sparkimpl.plugin.idle; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.NativeLong; +import com.sun.jna.Structure; +import com.sun.jna.platform.unix.X11; +import com.sun.jna.platform.unix.X11.*; + + +/** + * Utility method to retrieve the idle time on Linux with X11 + * + * @author Martin + * @author MoonRockSeven + * @author Ian Zwanink + * @see "http://ochafik.com/blog/?p=98" + */ +class X11IdleTimeDetector implements IdleTimeDetector { + + /** + * Structure providing info on the XScreensaver. + */ + public static class XScreenSaverInfo extends Structure { + /** + * screen saver window + */ + public Window window; + /** + * ScreenSaver{Off,On,Disabled} + */ + public int state; + /** + * ScreenSaver{Blanked,Internal,External} + */ + public int kind; + /** + * milliseconds + */ + public NativeLong til_or_since; + /** + * milliseconds + */ + public NativeLong idle; + /** + * events + */ + public NativeLong event_mask; + + @Override + protected List getFieldOrder() { + return Arrays.asList("window", "state", "kind", "til_or_since", "idle", "event_mask"); + } + } + + /** + * Definition (incomplete) of the Xext library. + */ + public interface Xss extends Library { + /** + * Instance of the Xss library bindings. + */ + Xss INSTANCE = Native.load("Xss", Xss.class); + + /** + * Allocate a XScreensaver information structure. + * @return a {@link XScreenSaverInfo} instance. + */ + XScreenSaverInfo XScreenSaverAllocInfo(); + + /** + * Query the XScreensaver. + * @param display the display. + * @param drawable a {@link Drawable} structure. + * @param saver_info a previously allocated {@link XScreenSaverInfo} instance. + * @return an int return code. + */ + int XScreenSaverQueryInfo(Display display, Drawable drawable, XScreenSaverInfo saver_info); + } + + @Override + public long getIdleTimeMillis() { + Window window; + XScreenSaverInfo info = null; + Display display = null; + final X11 x11 = X11.INSTANCE; + final Xss xss = Xss.INSTANCE; + + long idleMillis = 0; + try { + display = x11.XOpenDisplay(null); + if (display != null) { + window = x11.XDefaultRootWindow(display); + info = xss.XScreenSaverAllocInfo(); + if (info != null) { + xss.XScreenSaverQueryInfo(display, window, info); + idleMillis = info.idle.longValue(); + } + } + } catch (Throwable e) { + return 0; + } finally { + if (info != null) x11.XFree(info.getPointer()); + if (display != null) x11.XCloseDisplay(display); + } + return idleMillis; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/package-info.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/package-info.java new file mode 100644 index 000000000..0eb7fa1f3 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/idle/package-info.java @@ -0,0 +1,22 @@ +/** + * Copyright (C) 2004-2026 Jive Software. All rights reserved. + * This plugin 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 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +/** + * Support for detection of an idle state on the current host.
      + * Here idle means no keyboard or mouse activity was detected for a specified time. + * @exclude + */ +package org.jivesoftware.sparkimpl.plugin.idle; diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/jabber/JabberBrowser.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/jabber/JabberBrowser.java new file mode 100644 index 000000000..d9290ceb1 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/jabber/JabberBrowser.java @@ -0,0 +1,243 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.jabber; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; +import org.jivesoftware.smackx.disco.packet.DiscoverItems; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.*; + +/** + * Jabber Browser. + * Discovering items on an XMPP server + * + * @author Derek DeMoro + */ +public class JabberBrowser implements Plugin { + private JLabel addressLabel; + private JComboBox addressField; + private XMPPConnection con; + private JPanel browsePanel; + + /** + * Displays Jabber browser in the modal dialog + */ + public void display() { + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new GridBagLayout()); + + // Setup resource + ResourceUtils.resLabel(addressLabel, addressField, Res.getString("label.jabber.address") + ":"); + + RolloverButton backButton = new RolloverButton(); + backButton.setIcon(SparkRes.getImageIcon(SparkRes.Icon.LEFT_ARROW_IMAGE)); + backButton.addActionListener(e -> { + int selectedItem = addressField.getSelectedIndex(); + if (selectedItem > 0) { + String historyItem = addressField.getItemAt(selectedItem - 1); + browse(historyItem); + } + }); + + mainPanel.add(backButton, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + mainPanel.add(addressLabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + mainPanel.add(addressField, new GridBagConstraints(2, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + + JButton browseButton = new JButton(""); + ResourceUtils.resButton(browseButton, Res.getString("button.browse")); + browseButton.addActionListener(e -> { + String serviceName = (String) addressField.getSelectedItem(); + if (!ModelUtil.hasLength(serviceName)) { + return; + } + browse(serviceName); + }); + mainPanel.add(addressField, new GridBagConstraints(2, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + mainPanel.add(browseButton, new GridBagConstraints(3, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + + browsePanel = new JPanel(); + browsePanel.setLayout(new FlowLayout(FlowLayout.LEFT)); + browsePanel.setBackground(Color.white); + + JScrollPane pane = new JScrollPane(browsePanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + browsePanel.setPreferredSize(new Dimension(0, 0)); + mainPanel.add(pane, new GridBagConstraints(0, 1, 4, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); + + JFrame frame = new JFrame(); + frame.setIconImage(SparkRes.getImageIcon(SparkRes.Icon.FIND_IMAGE).getImage()); + + JDialog dialog = new JDialog(frame, Res.getString("title.jabber.browser")); + dialog.getContentPane().setLayout(new BorderLayout()); + dialog.getContentPane().add(mainPanel, BorderLayout.CENTER); + dialog.pack(); + dialog.setSize(600, 400); + dialog.setLocationRelativeTo(SparkManager.getMainWindow()); + dialog.setVisible(true); + } + + private void browse(String serviceNameString) { + Jid serviceName = JidCreate.fromOrThrowUnchecked(serviceNameString); + + browsePanel.removeAll(); + + ServiceDiscoveryManager discoManager = SparkManager.getDiscoManager(); + DiscoverItems result; + try { + result = discoManager.discoverItems(serviceName); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + return; + } + + addAddress(serviceName.toString()); + + for (DiscoverItems.Item item : result.getItems()) { + Entity entity = new Entity(item); + browsePanel.add(entity); + } + + browsePanel.invalidate(); + browsePanel.validate(); + browsePanel.repaint(); + } + + /** + * Add address; discover items; updates the browser panel + */ + private void browseItem(DiscoverItems.Item discoveredItem) { + addAddress(discoveredItem.getEntityID().toString()); + browsePanel.removeAll(); + ServiceDiscoveryManager discoManager = SparkManager.getDiscoManager(); + DiscoverItems result; + try { + result = discoManager.discoverItems(discoveredItem.getEntityID()); + } catch (XMPPException | SmackException | InterruptedException e) { + browsePanel.invalidate(); + browsePanel.validate(); + browsePanel.repaint(); + return; + } + + List resultItems = result.getItems(); + List list = new ArrayList<>(); + for (DiscoverItems.Item item : resultItems) { + Entity entity = new Entity(item); + browsePanel.add(entity); + list.add(entity); + } + + GraphicUtils.makeSameSize(list.toArray(new JComponent[0])); + + browsePanel.invalidate(); + browsePanel.validate(); + browsePanel.repaint(); + } + + public class Entity extends RolloverButton { + private final DiscoverItems.Item item; + + public Entity(final DiscoverItems.Item item) { + this.item = item; + setVerticalTextPosition(JLabel.BOTTOM); + setHorizontalTextPosition(JLabel.CENTER); + setText(item.getName() != null ? item.getName() : item.getEntityID().toString()); + setIcon(SparkRes.getImageIcon(SparkRes.Icon.USER1_MESSAGE_24x24)); + + addActionListener(e -> browseItem(item)); + } + + public DiscoverItems.Item getItem() { + return item; + } + } + + private void addAddress(String address) { + addressField.addItem(address); + addressField.setSelectedItem(address); + } + + @Override + public void initialize() { + this.con = SparkManager.getConnection(); + EventQueue.invokeLater(() -> { + addressLabel = new JLabel(); + addressField = new JComboBox<>(); + addressField.setEditable(true); + addressField.addItem(con.getHost()); + }); + SparkManager.getWorkspace().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("F8"), "showBrowser"); + AbstractAction actionShowXmppBrowser = new AbstractAction("showBrowser") { + @Override + public void actionPerformed(ActionEvent evt) { + display(); + } + }; + SparkManager.getWorkspace().getActionMap().put("showBrowser", actionShowXmppBrowser); + addMainMenuItem(actionShowXmppBrowser); + } + + private void addMainMenuItem(AbstractAction actionShowXmppBrowser) { + JMenu actionsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions")); + if (actionsMenu == null) { + return; + } + JMenuItem menuShowXmppBrowser = new JMenuItem(Res.getString("title.jabber.browser"), SparkRes.getImageIcon(SparkRes.Icon.FIND_IMAGE)); + menuShowXmppBrowser.addActionListener(actionShowXmppBrowser); + actionsMenu.add(menuShowXmppBrowser); + } + + @Override + public void shutdown() { + } + + @Override + public boolean canShutDown() { + return false; + } + + @Override + public void uninstall() { + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/jabber/JabberVersion.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/jabber/JabberVersion.java new file mode 100644 index 000000000..0d52601dc --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/jabber/JabberVersion.java @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.jabber; + +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.filter.StanzaFilter; +import org.jivesoftware.smack.filter.StanzaTypeFilter; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smackx.iqversion.VersionManager; +import org.jivesoftware.smackx.time.packet.Time; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.ContextMenuListener; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.spark.ui.ContactList; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.JiveInfo; +import org.jivesoftware.resource.Res; +import org.jxmpp.jid.Jid; + +import javax.swing.*; + +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.time.ZonedDateTime; +import java.util.Collection; +import java.util.Date; + +/** + * Jabber Version. + * Displays which version of Spark users are running. + * + * @author Derek DeMoro + */ +public class JabberVersion implements Plugin { + + @Override + public void initialize() { + // Populate Smack's Version Manager with Sparks version information. + VersionManager.getInstanceFor( SparkManager.getConnection() ).setVersion( + JiveInfo.getName(), + JiveInfo.getVersion(), + JiveInfo.getOS() + ); + + // Create IQ Filter + StanzaFilter packetFilter = new StanzaTypeFilter(IQ.class); + SparkManager.getConnection().addAsyncStanzaListener( stanza -> { + IQ iq = (IQ)stanza; + + try + { + if (iq instanceof Time && iq.getType() == IQ.Type.get) { + Time time = Time.builder(iq.getStanzaId()) + .ofType(IQ.Type.result) + .set(ZonedDateTime.now()) + .from(iq.getTo()) + .to(iq.getFrom()) + .build(); + + // Send Time + SparkManager.getConnection().sendStanza(time); + } + } + catch ( SmackException.NotConnectedException e ) + { + Log.warning( "Unable to answer request: " + stanza, e); + } + }, packetFilter); + + final ContactList contactList = SparkManager.getWorkspace().getContactList(); + contactList.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control F11"), "viewClient"); + contactList.addContextMenuListener(new ContextMenuListener() { + @Override + public void poppingUp(final Object component, JPopupMenu popup) { + if (!(component instanceof ContactItem)) { + return; + } + + ContactItem contactItem = (ContactItem)component; + if(contactItem.getPresence() == null){ + return; + } + + Action versionRequest = new AbstractAction() { + private static final long serialVersionUID = -5619737417315441711L; + + @Override + public void actionPerformed(ActionEvent e) { + viewClient(); + } + }; + + versionRequest.putValue(Action.NAME, Res.getString("menuitem.view.client.version")); + popup.add(versionRequest); + } + + @Override + public void poppingDown(JPopupMenu popup) { + + } + + @Override + public boolean handleDefaultAction(MouseEvent e) { + return false; + } + }); + + + contactList.getActionMap().put("viewClient", new AbstractAction("viewClient") { + private static final long serialVersionUID = 8282301357403753561L; + + @Override + public void actionPerformed(ActionEvent evt) { + viewClient(); + } + }); + + + } + + private void viewClient() { + final JTextField field = new JTextField(); + final ContactList contactList = SparkManager.getWorkspace().getContactList(); + Collection selectedUsers = contactList.getSelectedUsers(); + if (selectedUsers.size() == 1) { + final ContactItem item = (ContactItem)selectedUsers.toArray()[0]; + final Presence presence = item.getPresence(); + if (presence == null || presence.getFrom() == null) { + JOptionPane.showMessageDialog(field, + item.getAlias() + " " +Res.getString("user.has.signed.off"), + Res.getString("title.notification"), + JOptionPane.INFORMATION_MESSAGE); + return; + } + final Jid jid = presence.getFrom(); + SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + try { + Thread.sleep(10); + } + catch (InterruptedException e1) { + // Nothing to do + } + return jid; + } + + @Override + public void finished() { + VersionViewer.viewVersion(jid); + } + }; + worker.start(); + } + } + + @Override + public void shutdown() { + + } + + @Override + public boolean canShutDown() { + return false; + } + + @Override + public void uninstall() { + // Do nothing. + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/jabber/VersionViewer.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/jabber/VersionViewer.java new file mode 100644 index 000000000..5134d01aa --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/jabber/VersionViewer.java @@ -0,0 +1,138 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.jabber; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smackx.time.packet.Time; +import org.jivesoftware.smackx.iqversion.packet.Version; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.UserManager; +import org.jivesoftware.spark.component.MessageDialog; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.Jid; + +import javax.swing.*; + +import java.awt.*; +import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; + +public class VersionViewer { + + private VersionViewer() { + + } + + public static void viewVersion(Jid jid) { + final JPanel loadingCard = new JPanel(); + final ImageIcon icon = new ImageIcon( VersionViewer.class.getClassLoader().getResource( "images/ajax-loader.gif")); + loadingCard.add(new JLabel("loading... ", icon, JLabel.CENTER)); + loadingCard.setVisible(true); + + final JPanel dataCard = new JPanel(); + dataCard.setVisible( false ); + dataCard.setLayout(new GridBagLayout()); + + JLabel timeLabel = new JLabel(); + JLabel softwareLabel = new JLabel(); + JLabel versionLabel = new JLabel(); + JLabel osLabel = new JLabel(); + + final JTextField timeField = new JTextField(); + final JTextField softwareField = new JTextField(); + final JTextField versionField = new JTextField(); + final JTextField osField = new JTextField(); + + // Add resources + ResourceUtils.resLabel(timeLabel, timeField, Res.getString("label.local.time") + ":"); + ResourceUtils.resLabel(softwareLabel, softwareField, Res.getString("label.software") + ":"); + ResourceUtils.resLabel(versionLabel, versionField, Res.getString("label.version") + ":"); + ResourceUtils.resLabel(osLabel, osField, Res.getString("label.os") + ":"); + + // Add Time Label + dataCard.add(timeLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + dataCard.add(timeField, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + dataCard.add(softwareLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + dataCard.add(softwareField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + + dataCard.add(versionLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + dataCard.add(versionField, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + + dataCard.add(osLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + dataCard.add(osField, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + osField.setEditable(false); + versionField.setEditable(false); + softwareField.setEditable(false); + timeField.setEditable(false); + + final JPanel cards = new JPanel(new CardLayout()); + cards.add(loadingCard); + cards.add(dataCard); + + final XMPPConnection connection = SparkManager.getConnection(); + // Load Version + final Version versionRequest = Version.builder(connection) + .ofType(IQ.Type.get) + .build(); + versionRequest.setTo(jid); + + CardLayout cardLayout = (CardLayout) cards.getLayout(); + connection.sendIqRequestAsync(versionRequest) + .onSuccess(iq -> { + final Version versionResult = (Version) iq; + softwareField.setText(versionResult.getName()); + versionField.setText(versionResult.getVersion()); + osField.setText(versionResult.getOs()); + cardLayout.last(cards); + }) + .onError(e -> { + Log.warning("Version request error: " + e); + softwareField.setText(""); + versionField.setText(""); + osField.setText(""); + cardLayout.last(cards); + }); + + // Time + final Time time = Time.builder(connection) + .ofType(IQ.Type.get) + .build(); + time.setTo(jid); + + connection.sendIqRequestAsync(time) + .onSuccess(iq -> { + DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL); + timeField.setText(f.format(((Time) iq).getZonedDateTime())); + cardLayout.last(cards); + }) + .onError(e -> { + Log.warning("Time request error: " + e); + timeField.setText(""); + cardLayout.last(cards); + }); + + MessageDialog.showComponent(Res.getString("title.version.and.time"), Res.getString("message.client.information", UserManager.unescapeJID(jid)), SparkRes.getImageIcon(SparkRes.Icon.PROFILE_IMAGE_24x24), cards, SparkManager.getMainWindow(), 400, 300, false); + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/language/LanguagePlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/language/LanguagePlugin.java new file mode 100644 index 000000000..fee7f5449 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/language/LanguagePlugin.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2004-2011 Jive Software. 2020 Ignite Realtime Foundation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.language; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.net.JarURLConnection; +import java.net.URI; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Locale; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; + +import static java.util.Locale.ENGLISH; +import static java.util.stream.Collectors.toList; + +/** + * Allows users to explicitly set their language. + * + * @author Derek DeMoro + */ +public class LanguagePlugin implements Plugin { + + @Override + public void initialize() { + // Register with action menu + final JMenu actionsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions")); + + String languageMenuLabel = Res.getString("menuitem.languages"); + // For non-English locales append "Language" for those who accidentally changed language + if (!Locale.getDefault().getLanguage().equals("en")) { + languageMenuLabel += " (Language)"; + } + JMenu languageMenu = new JMenu(languageMenuLabel); + languageMenu.setIcon(SparkRes.getImageIcon(SparkRes.Icon.LANGUAGE_ICON)); + + addLanguage(ENGLISH, languageMenu); + // If we have a translation file for this locale, we can support the language! + List i18nResources = getI18nLangCodesFromResourceFiles(); + for (String localeFile : i18nResources) { + Locale locale = Locale.forLanguageTag(localeFile.replace("_", "-")); + addLanguage(locale, languageMenu); + } + + actionsMenu.add(languageMenu); + } + + private void addLanguage(Locale locale, JMenu languageMenu) { + Action action = new AbstractAction() { + private static final long serialVersionUID = -7093236616888591766L; + + @Override + public void actionPerformed(ActionEvent e) { + final LocalPreferences preferences = SettingsManager.getLocalPreferences(); + preferences.setLanguage(locale.toString()); + + UIManager.put("OptionPane.yesButtonText", Res.getString("yes")); + UIManager.put("OptionPane.noButtonText", Res.getString("no")); + + int ok = JOptionPane.showConfirmDialog(SparkManager.getMainWindow(), Res.getString("message.restart.required"), Res.getString("title.confirmation"), JOptionPane.YES_NO_OPTION); + if (ok == JOptionPane.YES_OPTION) { + SparkManager.getMainWindow().closeConnectionAndInvoke("Language Change"); + } + } + }; + String label = locale.getDisplayName(locale); + action.putValue(Action.NAME, label); + languageMenu.add(action); + } + + @Override + public void shutdown() { + } + + @Override + public boolean canShutDown() { + return false; + } + + + @Override + public void uninstall() { + } + + private List getI18nLangCodesFromResourceFiles() { + String folder = "/i18n/"; + URL resource = getClass().getResource(folder); + if (resource == null) { + Log.error("list resources from /i18n/ no folder"); + return List.of(); + } + try { + if ("jar".equals(resource.getProtocol())) { + // Lists resource files from jar + String folderInJar = folder.substring(1); // drop leading '/' + String i18nFilePrefix = folderInJar + "spark_i18n_"; + JarURLConnection connection = (JarURLConnection) resource.openConnection(); + try (JarFile jarFile = connection.getJarFile()) { + return jarFile.stream() + .filter(entry -> !entry.isDirectory() && entry.getName().startsWith(i18nFilePrefix)) + .map(ZipEntry::getName) + .map(name -> name.substring(i18nFilePrefix.length(), name.length() - ".properties".length())) + .sorted() + .collect(toList()); + } + } else if ("file".equals(resource.getProtocol())) { + // Lists resource files from a file system when running from IDE + final URI uri = resource.toURI(); + final Path dir = Paths.get(uri); + try (var paths = Files.list(dir)) { + return paths + .filter(Files::isRegularFile) + .map(path -> path.getFileName().toString()) + .filter(name -> name.startsWith("spark_i18n_")) + .map(name -> name.substring("spark_i18n_".length(), name.lastIndexOf("."))) + .sorted() + .collect(toList()); + } + } else { + // Unknown protocol. Never happens + return List.of(); + } + } catch (Exception e) { + Log.error("Failed to list resources from /i18n/", e); + return List.of(); + } + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutPlugin.java new file mode 100644 index 000000000..86cecba9e --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutPlugin.java @@ -0,0 +1,81 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.layout; + +import org.jivesoftware.MainWindow; +import org.jivesoftware.MainWindowListener; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.Plugin; + +/** + * Layout Plugin. + * Persists users layouts on subsequent loads. + * + * @author Derek DeMoro + */ +public class LayoutPlugin implements Plugin +{ + + @Override + public void initialize() + { + final MainWindow mainWindow = SparkManager.getMainWindow(); + + SparkManager.getMainWindow().addMainWindowListener( new MainWindowListener() + { + @Override + public void shutdown() + { + LayoutSettingsManager.getLayoutSettings().setMainWindowBounds( mainWindow.getBounds() ); + if ( mainWindow.isDocked() ) + { + LayoutSettingsManager.getLayoutSettings().setSplitPaneDividerLocation( mainWindow.getSplitPane().getDividerLocation() ); + } + else + { + LayoutSettingsManager.getLayoutSettings().setSplitPaneDividerLocation( -1 ); + } + LayoutSettingsManager.saveLayoutSettings(); + } + + @Override + public void mainWindowActivated() + { + } + + @Override + public void mainWindowDeactivated() + { + } + } ); + } + + @Override + public void shutdown() + { + } + + @Override + public boolean canShutDown() + { + return true; + } + + @Override + public void uninstall() + { + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutSettings.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutSettings.java new file mode 100644 index 000000000..b1bf653fe --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutSettings.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.layout; + +import java.awt.*; + + +public class LayoutSettings +{ + private Rectangle mainWindowBounds; + private Rectangle chatFrameBounds; + private Rectangle preferencesBounds; + private Rectangle conferenceRoomBrowserBounds; + private Rectangle pluginViewerBounds; + private Rectangle broadcastHistoryBounds; + private Rectangle broadcastMessageBounds; + private Rectangle vCardEditorBounds; + + private int splitPaneDividerLocation; + + public Rectangle getMainWindowBounds() + { + return mainWindowBounds; + } + + public void setMainWindowBounds( Rectangle mainWindowBounds ) + { + this.mainWindowBounds = mainWindowBounds; + } + + public Rectangle getChatFrameBounds() + { + return chatFrameBounds; + } + + public void setChatFrameBounds( Rectangle chatFrameBounds ) + { + this.chatFrameBounds = chatFrameBounds; + } + + public Rectangle getPreferencesBounds() + { + return preferencesBounds; + } + + public void setPreferencesBounds( Rectangle preferencesBounds ) + { + this.preferencesBounds = preferencesBounds; + } + + public int getSplitPaneDividerLocation() + { + return splitPaneDividerLocation; + } + + public void setSplitPaneDividerLocation( int splitPaneDividerLocation ) + { + this.splitPaneDividerLocation = splitPaneDividerLocation; + } + + public Rectangle getConferenceRoomBrowserBounds() + { + return conferenceRoomBrowserBounds; + } + + public void setConferenceRoomBrowserBounds( Rectangle conferenceRoomBrowserBounds ) + { + this.conferenceRoomBrowserBounds = conferenceRoomBrowserBounds; + } + + public Rectangle getPluginViewerBounds() + { + return pluginViewerBounds; + } + + public void setPluginViewerBounds( Rectangle pluginViewerBounds ) + { + this.pluginViewerBounds = pluginViewerBounds; + } + + public Rectangle getBroadcastHistoryBounds() + { + return broadcastHistoryBounds; + } + + public void setBroadcastHistoryBounds( Rectangle broadcastHistoryBounds ) + { + this.broadcastHistoryBounds = broadcastHistoryBounds; + } + + public Rectangle getBroadcastMessageBounds() + { + return broadcastMessageBounds; + } + + public void setBroadcastMessageBounds( Rectangle broadcastMessageBounds ) + { + this.broadcastMessageBounds = broadcastMessageBounds; + } + + public Rectangle getVCardEditorBounds() + { + return vCardEditorBounds; + } + + public void setVCardEditorBounds( Rectangle vCardEditorBounds ) + { + this.vCardEditorBounds = vCardEditorBounds; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutSettingsManager.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutSettingsManager.java new file mode 100644 index 000000000..3965c5ff7 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutSettingsManager.java @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.layout; + +import org.jivesoftware.Spark; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.log.Log; + +import java.awt.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.Properties; + +/** + * Responsible for the loading and persisting of layout-settings. + */ +public class LayoutSettingsManager +{ + private static LayoutSettings layoutSettings; + + private LayoutSettingsManager() + { + } + + /** + * Returns the LayoutSettings for this agent. + * + * @return the LayoutSettings for this agent. + */ + public static LayoutSettings getLayoutSettings() + { + if ( !exists() && layoutSettings == null ) + { + layoutSettings = new LayoutSettings(); + } + + if ( layoutSettings == null ) + { + // Do Initial Load from FileSystem. + File settingsFile = getSettingsFile(); + layoutSettings = load( settingsFile ); + } + return layoutSettings; + } + + /** + * Persists the settings to the local file system. + */ + public static void saveLayoutSettings() + { + final Properties props = new Properties(); + + final Rectangle mainWindow = layoutSettings.getMainWindowBounds(); + if ( mainWindow != null ) + { + props.setProperty( "mainWindowX", Integer.toString( mainWindow.x ) ); + props.setProperty( "mainWindowY", Integer.toString( mainWindow.y ) ); + props.setProperty( "mainWindowHeight", Integer.toString( mainWindow.height ) ); + props.setProperty( "mainWindowWidth", Integer.toString( mainWindow.width ) ); + } + + final Rectangle chatFrame = layoutSettings.getChatFrameBounds(); + if ( chatFrame != null ) + { + props.setProperty( "chatFrameX", Integer.toString( chatFrame.x ) ); + props.setProperty( "chatFrameY", Integer.toString( chatFrame.y ) ); + props.setProperty( "chatFrameWidth", Integer.toString( chatFrame.width ) ); + props.setProperty( "chatFrameHeight", Integer.toString( chatFrame.height ) ); + } + + final Rectangle preferences = layoutSettings.getPreferencesBounds(); + if ( preferences != null ) + { + props.setProperty( "preferencesFrameX", Integer.toString( preferences.x ) ); + props.setProperty( "preferencesFrameY", Integer.toString( preferences.y ) ); + props.setProperty( "preferencesFrameWidth", Integer.toString( preferences.width ) ); + props.setProperty( "preferencesFrameHeight", Integer.toString( preferences.height ) ); + } + props.setProperty( "splitDividerLocation", Integer.toString( layoutSettings.getSplitPaneDividerLocation() ) ); + + final Rectangle conferenceRoomBrowser = layoutSettings.getConferenceRoomBrowserBounds(); + if ( conferenceRoomBrowser != null ) + { + props.setProperty( "conferenceRoomBrowserX", Integer.toString( conferenceRoomBrowser.x ) ); + props.setProperty( "conferenceRoomBrowserY", Integer.toString( conferenceRoomBrowser.y ) ); + props.setProperty( "conferenceRoomBrowserHeight", Integer.toString( conferenceRoomBrowser.height ) ); + props.setProperty( "conferenceRoomBrowserWidth", Integer.toString( conferenceRoomBrowser.width ) ); + } + + final Rectangle pluginViewer = layoutSettings.getPluginViewerBounds(); + if ( pluginViewer != null ) + { + props.setProperty( "pluginViewerX", Integer.toString( pluginViewer.x ) ); + props.setProperty( "pluginViewerY", Integer.toString( pluginViewer.y ) ); + props.setProperty( "pluginViewerHeight", Integer.toString( pluginViewer.height ) ); + props.setProperty( "pluginViewerWidth", Integer.toString( pluginViewer.width ) ); + } + + final Rectangle broadcastHistory = layoutSettings.getBroadcastHistoryBounds(); + if ( broadcastHistory != null ) + { + props.setProperty( "broadcastHistoryX", Integer.toString( broadcastHistory.x ) ); + props.setProperty( "broadcastHistoryY", Integer.toString( broadcastHistory.y ) ); + props.setProperty( "broadcastHistoryHeight", Integer.toString( broadcastHistory.height ) ); + props.setProperty( "broadcastHistoryWidth", Integer.toString( broadcastHistory.width ) ); + } + + final Rectangle broadcastMessage = layoutSettings.getBroadcastMessageBounds(); + if ( broadcastMessage != null ) + { + props.setProperty( "broadcastMessageX", Integer.toString( broadcastMessage.x ) ); + props.setProperty( "broadcastMessageY", Integer.toString( broadcastMessage.y ) ); + props.setProperty( "broadcastMessageHeight", Integer.toString( broadcastMessage.height ) ); + props.setProperty( "broadcastMessageWidth", Integer.toString( broadcastMessage.width ) ); + } + + final Rectangle vCardEditor = layoutSettings.getVCardEditorBounds(); + if ( vCardEditor != null ) + { + props.setProperty( "vCardEditorX", Integer.toString( vCardEditor.x ) ); + props.setProperty( "vCardEditorY", Integer.toString( vCardEditor.y ) ); + props.setProperty( "vCardEditorHeight", Integer.toString( vCardEditor.height ) ); + props.setProperty( "vCardEditorWidth", Integer.toString( vCardEditor.width ) ); + } + + try + { + props.store( new FileOutputStream( getSettingsFile() ), "Storing Spark Layout Settings" ); + } + catch ( Exception e ) + { + Log.error( "Error saving settings.", e ); + } + } + + /** + * Return true if the settings file exists. + * + * @return true if the settings file exists.('settings.xml') + */ + public static boolean exists() + { + return getSettingsFile().exists(); + } + + /** + * Returns the settings file. + * + * @return the settings file. + */ + public static File getSettingsFile() + { + File file = Spark.getSparkUserHome(); + if ( !file.exists() ) + { + file.mkdirs(); + } + return new File( file, "layout.settings" ); + } + + public static int asInt( Properties props, String propertyName ) + { + return Integer.parseInt( props.getProperty( propertyName, "-1" ) ); + } + + private static LayoutSettings load( File file ) + { + final Properties props = new Properties(); + try + { + props.load( new FileInputStream( file ) ); + + final LayoutSettings settings = new LayoutSettings(); + + final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + // Main Window + final Dimension mainWindowDimension = new Dimension( + asInt( props, "mainWindowWidth" ), + asInt( props, "mainWindowHeight" ) + ); + + if ( mainWindowDimension.width > screenSize.width ) + { + mainWindowDimension.width = screenSize.width - 50; + } + + if ( mainWindowDimension.height > screenSize.height ) + { + mainWindowDimension.height = screenSize.height - 50; + } + + final Point mainWindowLocation = ensureValidWindowPosition( + new Point( + asInt( props, "mainWindowX" ), + asInt( props, "mainWindowY" ) + ), + mainWindowDimension ); + + settings.setMainWindowBounds( new Rectangle( mainWindowLocation, mainWindowDimension ) ); + + // Chat Frame + final Dimension chatFrameDimension = new Dimension( + asInt( props, "chatFrameWidth" ), + asInt( props, "chatFrameHeight" ) + ); + final Point chatFrameLocation = ensureValidWindowPosition( + new Point( + asInt( props, "chatFrameX" ), + asInt( props, "chatFrameY" ) + ), + chatFrameDimension ); + + settings.setChatFrameBounds( new Rectangle( chatFrameLocation, chatFrameDimension ) ); + + // Preferences + final Dimension preferencesDimension = new Dimension( + asInt( props, "preferencesFrameWidth" ), + asInt( props, "preferencesFrameHeight" ) + ); + final Point preferencesLocation = ensureValidWindowPosition( + new Point( + asInt( props, "preferencesFrameX" ), + asInt( props, "preferencesFrameY" ) + ), + preferencesDimension ); + + settings.setPreferencesBounds( new Rectangle( preferencesLocation, preferencesDimension ) ); + + // Conference Room Browser + final Dimension conferenceRoomBrowserDimension = new Dimension( + asInt( props, "conferenceRoomBrowserWidth" ), + asInt( props, "conferenceRoomBrowserHeight" ) + ); + final Point conferenceRoomBrowserLocation = ensureValidWindowPosition( + new Point( + asInt( props, "conferenceRoomBrowserX" ), + asInt( props, "conferenceRoomBrowserY" ) + ), + conferenceRoomBrowserDimension ); + + settings.setConferenceRoomBrowserBounds( new Rectangle( conferenceRoomBrowserLocation, conferenceRoomBrowserDimension ) ); + + // Plugin viewer + final Dimension pluginViewerDimension = new Dimension( + asInt( props, "pluginViewerWidth" ), + asInt( props, "pluginViewerHeight" ) + ); + final Point pluginViewerLocation = ensureValidWindowPosition( + new Point( + asInt( props, "pluginViewerX" ), + asInt( props, "pluginViewerY" ) + ), + pluginViewerDimension ); + + settings.setPluginViewerBounds( new Rectangle( pluginViewerLocation, pluginViewerDimension ) ); + + // Broadcast History + final Dimension broadcastHistoryDimension = new Dimension( + asInt( props, "broadcastHistoryWidth" ), + asInt( props, "broadcastHistoryHeight" ) + ); + final Point broadcastHistoryLocation = ensureValidWindowPosition( + new Point( + asInt( props, "broadcastHistoryX" ), + asInt( props, "broadcastHistoryY" ) + ), + broadcastHistoryDimension ); + + settings.setBroadcastHistoryBounds( new Rectangle( broadcastHistoryLocation, broadcastHistoryDimension ) ); + + // Broadcast Message + final Dimension broadcastMessageDimension = new Dimension( + asInt( props, "broadcastMessageWidth" ), + asInt( props, "broadcastMessageHeight" ) + ); + final Point broadcastMessageLocation = ensureValidWindowPosition( + new Point( + asInt( props, "broadcastMessageX" ), + asInt( props, "broadcastMessageY" ) + ), + broadcastMessageDimension ); + + settings.setBroadcastMessageBounds( new Rectangle( broadcastMessageLocation, broadcastMessageDimension ) ); + + // VCard Editor + final Dimension vCardEditorDimension = new Dimension( + asInt( props, "vCardEditorWidth" ), + asInt( props, "vCardEditorHeight" ) + ); + final Point vCardEditorLocation = ensureValidWindowPosition( + new Point( + asInt( props, "vCardEditorX" ), + asInt( props, "vCardEditorY" ) + ), + vCardEditorDimension ); + + settings.setVCardEditorBounds( new Rectangle( vCardEditorLocation, vCardEditorDimension ) ); + + // Split Divider + settings.setSplitPaneDividerLocation( asInt( props, "splitDividerLocation" ) ); + + return settings; + } + catch ( Exception e ) + { + Log.error( e ); + return new LayoutSettings(); + } + } + + protected static boolean isValidWindowPosition( Point location, Dimension dimension ) + { + Rectangle windowTitleBounds = new Rectangle( location.x, location.y, dimension.width, 20 ); + double windowTitleArea = windowTitleBounds.getWidth() * windowTitleBounds.getHeight(); + + Rectangle[] screenBounds = GraphicUtils.getScreenBounds(); + for ( Rectangle screenBound : screenBounds ) + { + Rectangle screen = screenBound.getBounds(); + Rectangle intersection = screen.intersection( windowTitleBounds ); + double visibleArea = intersection.getWidth() * intersection.getHeight(); + + // if 25% of it is visible in the device, then it is good + if ( ( visibleArea / windowTitleArea ) > 0.25 ) + { + return true; + } + } + + return false; + } + + protected static Point ensureValidWindowPosition( Point location, Dimension dimension ) + { + if ( isValidWindowPosition( location, dimension ) ) + { + return location; + } + + // Center + final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + return new Point( (screenSize.width - dimension.width) / 2, (screenSize.height - dimension.height) / 2 ); + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/manager/Enterprise.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/manager/Enterprise.java new file mode 100644 index 000000000..9ffd14da4 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/manager/Enterprise.java @@ -0,0 +1,167 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.manager; + +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; +import org.jivesoftware.smackx.disco.packet.DiscoverInfo; +import org.jivesoftware.smackx.disco.packet.DiscoverItems; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.util.log.Log; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * EnterpriseSparkManager is responsible for the detecting of features on the server. This allows for fine-grain control of + * feature sets to enable/disable within Spark. + * + * @author Derek DeMoro + */ +public class Enterprise { + + public static final String ACCOUNTS_REG_FEATURE = "accounts-reg"; + public static final String ADD_CONTACTS_FEATURE = "add-contacts"; + public static final String ADD_GROUPS_FEATURE = "add-groups"; + public static final String ADVANCED_CONFIG_FEATURE = "advanced-config"; + public static final String AVATAR_TAB_FEATURE = "avatar-tab"; + public static final String BROADCAST_FEATURE = "broadcast"; + public static final String REMOVALS_FEATURE = "removals"; + public static final String RENAMES_FEATURE = "renames"; + public static final String FILE_TRANSFER_FEATURE = "file-transfer"; + public static final String HELP_FORUMS_FEATURE = "help-forums"; + public static final String HELP_USERGUIDE_FEATURE = "help-userguide"; + public static final String HISTORY_SETTINGS_FEATURE = "history-settings"; + public static final String HISTORY_TRANSCRIPTS_FEATURE = "history-transcripts"; + public static final String HOST_NAME_FEATURE = "host-name"; + public static final String INVISIBLE_LOGIN_FEATURE = "invisible-login"; + public static final String ANONYMOUS_LOGIN_FEATURE = "anonymous-login"; + public static final String LOGOUT_EXIT_FEATURE = "logout-exit"; + public static final String MOVE_COPY_FEATURE = "move-copy"; + public static final String MUC_FEATURE = "muc"; + public static final String PASSWORD_CHANGE_FEATURE = "password-change"; + public static final String PERSON_SEARCH_FEATURE = "person-search"; + public static final String PLUGINS_MENU_FEATURE = "plugins-menu"; + public static final String PREFERENCES_MENU_FEATURE = "preferences-menu"; + public static final String PRESENCE_STATUS_FEATURE = "presence-status"; + public static final String VCARD_FEATURE = "vcard"; + public static final String SAVE_PASSWORD_FEATURE = "save-password"; + public static final String UPDATES_FEATURE = "updates"; + public static final String VIEW_NOTES_FEATURE = "view-notes"; + public static final String VIEW_TASKS_FEATURE = "view-tasks"; + public static final String START_A_CHAT_FEATURE = "start-a-chat"; + public static final String HOSTNAME_AS_RESOURCE_FEATURE = "hostname-as-resource"; + public static final String VERSION_AS_RESOURCE_FEATURE = "version-as-resource"; + public static final String PLUGINS_BLACKLIST_NODE = "spark-plugins-blacklist"; + public static final String IDLE_FEATURE = "idle"; + + public static final String IBB_FEATURE = "ibb-only"; + + private static DiscoverInfo featureInfo; + private static final Map nodeInfo = new HashMap<>(); + + private static boolean sparkManagerInstalled; + + public Enterprise() { + // Retrieve feature list. + populateFeatureSet(); + } + + /** + * Returns true if the Enterprise Spark Manager module is installed on the server we are currently connected to. + * + * @return true if Enterprise Spark Manager exists. + */ + public static boolean isSparkManagerInstalled() { + return sparkManagerInstalled; + } + + /** + * Returns true if the feature is available. + * + * @param feature the name of the feature to detect. + * @return true if the feature is available on the server, otherwise false. + */ + public static boolean containsFeature(String feature) { + if (featureInfo == null) { + return true; + } + + return featureInfo.containsFeature(feature); + } + + /** + * Returns all items (node-attribute values) for a particular node + * + * @param node The node for which to return items. + * @return A collection of node item names, possibly empty, never null. + */ + public static Set getItemsForNode(String node) { + if (nodeInfo == null || nodeInfo.isEmpty()) { + return Collections.emptySet(); + } + + final DiscoverItems discoverItems = nodeInfo.get(node); + if (discoverItems == null) { + return Collections.emptySet(); + } + + return discoverItems.getItems().stream().map(DiscoverItems.Item::getNode).collect(Collectors.toSet()); + } + + private void populateFeatureSet() { + ServiceDiscoveryManager discoManager = SparkManager.getDiscoManager(); + final DiscoverItems items = SparkManager.getSessionManager().getDiscoveredItems(); + for (DiscoverItems.Item item : items.getItems() ) { + String entity = item.getEntityID().toString(); + if (entity.startsWith("manager.")) { + sparkManagerInstalled = true; + // Populate with feature sets. + try { + featureInfo = discoManager.discoverInfo(item.getEntityID()); + } + catch (XMPPException | SmackException | InterruptedException e) { + Log.error("Error while retrieving feature list for SparkManager.", e); + } + + // Check for nodes. + try { + final DiscoverItems discoveredItems = discoManager.discoverItems(item.getEntityID()); + for (DiscoverItems.Item discoveredItem : discoveredItems.getItems()) { + final String node = discoveredItem.getNode(); + if (node != null) { + try { + // We're expecting Openfire to return unique JID/Node combinations. + final DiscoverItems nodeItems = discoManager.discoverItems(discoveredItem.getEntityID(), node); + nodeInfo.put(node, nodeItems); + } + catch (XMPPException | SmackException | InterruptedException e) { + Log.error("Error while retrieving node items for SparkManager, node " + node, e); + } + } + } + } + catch (XMPPException | SmackException | InterruptedException e) { + Log.error("Error while retrieving feature list for SparkManager.", e); + } + } + } + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/manager/Features.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/manager/Features.java new file mode 100644 index 000000000..7b445a62a --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/manager/Features.java @@ -0,0 +1,100 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.manager; + +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.provider.ExtensionElementProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.JxmppContext; + +import javax.xml.namespace.QName; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + + +public class Features implements ExtensionElement { + + private final List availableFeatures = new ArrayList<>(); + + + public List getAvailableFeatures() { + return availableFeatures; + } + + public void addFeature(String feature) { + availableFeatures.add(feature); + } + + /** + * Element name of the packet extension. + */ + public static final String ELEMENT_NAME = "event"; + + /** + * Namespace of the packet extension. + */ + public static final String NAMESPACE = "http://jabber.org/protocol/disco#info"; + + public static final QName QNAME = new QName(NAMESPACE, ELEMENT_NAME); + + + @Override + public String getElementName() { + return ELEMENT_NAME; + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public String toXML(XmlEnvironment xmlEnvironment) { + return ( ""; + } + + public static class Provider extends ExtensionElementProvider + { + public Provider() { + } + + @Override + public Features parse( XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException { + Features features = new Features(); + boolean done = false; + while (!done) { + XmlPullParser.Event eventType = parser.next(); + if (eventType == XmlPullParser.Event.START_ELEMENT && "event".equals(parser.getName())) { + parser.nextText(); + } + if (eventType == XmlPullParser.Event.START_ELEMENT && "feature".equals(parser.getName())) { + String feature = parser.getAttributeValue("", "var"); + features.addFeature(feature); + } + else if (eventType == XmlPullParser.Event.END_ELEMENT) { + if ("event".equals(parser.getName())) { + done = true; + } + } + } + + return features; + } + } +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyException.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyException.java similarity index 95% rename from src/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyException.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyException.java index a26afcec2..8ccfeee43 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyException.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyException.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +18,6 @@ import org.jivesoftware.smack.XMPPException; /** - * * @author Zolotarev Konstantin */ public class PrivacyException extends XMPPException { diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyManager.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyManager.java similarity index 78% rename from src/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyManager.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyManager.java index 9600c8d72..d04c2f31b 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyManager.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,21 +15,15 @@ */ package org.jivesoftware.sparkimpl.plugin.privacy; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smackx.privacy.PrivacyList; -import org.jivesoftware.smackx.privacy.PrivacyListManager; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.privacy.packet.PrivacyItem; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.packet.DiscoverInfo; import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Feature; +import org.jivesoftware.smackx.privacy.PrivacyList; +import org.jivesoftware.smackx.privacy.PrivacyListManager; +import org.jivesoftware.smackx.privacy.packet.PrivacyItem; import org.jivesoftware.spark.PresenceManager; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.util.log.Log; @@ -41,6 +31,9 @@ import org.jivesoftware.sparkimpl.plugin.privacy.list.SparkPrivacyList; import org.jivesoftware.sparkimpl.plugin.privacy.list.SparkPrivacyListListener; +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; + /** * @author Zolotarev Konstantin, Bergunde Holger @@ -58,11 +51,11 @@ public class PrivacyManager { // with regard to roster groups and JIDs. Obviously list names could become rather complex, // such as "visible-to-Group1 Group2 Group3". private static final String INVISIBLE_LIST_NAME = "invisible"; - private List _privacyLists = new ArrayList<>(); + private final List _privacyLists = new ArrayList<>(); private PrivacyListManager privacyManager; - private PrivacyPresenceHandler _presenceHandler = new PrivacyPresenceHandler(); - private Set _listListeners = new HashSet<>(); - private boolean _active = false; + private final PrivacyPresenceHandler _presenceHandler = new PrivacyPresenceHandler(); + private final CopyOnWriteArrayList _listListeners = new CopyOnWriteArrayList<>(); + private final boolean _active; private SparkPrivacyList previousActiveList; /** @@ -103,11 +96,11 @@ public static PrivacyManager getInstance() { private boolean checkIfPrivacyIsSupported(XMPPConnection conn) { - ServiceDiscoveryManager servDisc = ServiceDiscoveryManager.getInstanceFor(conn); + ServiceDiscoveryManager discoManager = SparkManager.getDiscoManager(); DiscoverInfo info = null; try { - info = servDisc.discoverInfo(conn.getServiceName()); - } catch (XMPPException | SmackException e) { + info = discoManager.discoverInfo(conn.getXMPPServiceDomain()); + } catch (XMPPException | SmackException | InterruptedException e) { // We could not query the server } if (info != null) { @@ -132,9 +125,8 @@ private void initializePrivacyLists() if (!isListHidden(sparkList)) _privacyLists.add(sparkList); } - } catch (XMPPException | SmackException e) { - Log.error("Could not load PrivacyLists"); - e.printStackTrace(); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.error("Could not load PrivacyLists", e); } if(hasDefaultList()) @@ -150,9 +142,8 @@ public void removePrivacyList(String listName) { privacyManager.deletePrivacyList(listName); _privacyLists.remove(getPrivacyList(listName)); - } catch (XMPPException | SmackException e) { - Log.warning("Could not remove PrivacyList " + listName); - e.printStackTrace(); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.warning("Could not remove PrivacyList " + listName, e); } } @@ -248,9 +239,8 @@ public SparkPrivacyList createPrivacyList(String listName) { sparklist = new SparkPrivacyList(privacyManager.getPrivacyList(listName)); _privacyLists.add(sparklist); sparklist.addSparkPrivacyListener(_presenceHandler); - } catch (XMPPException | SmackException e) { - Log.warning("Could not create PrivacyList "+listName); - e.printStackTrace(); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.warning("Could not create PrivacyList "+listName, e); } return sparklist; @@ -291,9 +281,8 @@ public void setListAsActive(String listname) } _presenceHandler.setIconsForList(getActiveList()); - } catch (XMPPException | SmackException e) { - Log.warning("Could not activate PrivacyList " + listname); - e.printStackTrace(); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.warning("Could not activate PrivacyList " + listname, e); } } @@ -307,9 +296,8 @@ public void setListAsDefault(String listname) { if (!plist.getListName().equals(listname)) plist.setListIsDefault(false); } - } catch (XMPPException | SmackException e) { - Log.warning("Could not set PrivacyList " + listname+" as default"); - e.printStackTrace(); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.warning("Could not set PrivacyList " + listname+" as default", e); } } @@ -327,9 +315,8 @@ public void declineActiveList() for (SparkPrivacyList plist : _privacyLists) { plist.setListAsActive(false); } - } catch (XMPPException | SmackException e) { - Log.warning("Could not decline active privacy list"); - e.printStackTrace(); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.warning("Could not decline active privacy list", e); } } @@ -344,9 +331,8 @@ public void declineDefaultList() plist.setListIsDefault(false); } } - } catch (XMPPException | SmackException e) { - Log.warning("Could not decline default privacy list"); - e.printStackTrace(); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.warning("Could not decline default privacy list", e); } } @@ -357,40 +343,71 @@ public boolean isPrivacyActive() public void addListListener (SparkPrivacyListListener listener) { - _listListeners.add(listener); + _listListeners.addIfAbsent(listener); } public void deleteListListener (SparkPrivacyListListener listener) { _listListeners.remove(listener); } - - private void fireListActivated(String listname) + + private void fireListActivated( String listName ) { - for (SparkPrivacyListListener listener: _listListeners) + for ( final SparkPrivacyListListener listener : _listListeners ) { - listener.listActivated(listname); + try + { + listener.listActivated( listName ); + } + catch ( Exception e ) + { + Log.error( "A SparkPrivacyListListener (" + listener + ") threw an exception while processing a 'listActivated' event for: " + listName, e ); + } } } - private void fireListDeActivated(String listname) + + private void fireListDeActivated( String listName ) { - for (SparkPrivacyListListener listener: _listListeners) + for ( final SparkPrivacyListListener listener : _listListeners ) { - listener.listDeActivated(listname); + try + { + listener.listDeActivated( listName ); + } + catch ( Exception e ) + { + Log.error( "A SparkPrivacyListListener (" + listener + ") threw an exception while processing a 'listDeActivated' event for: " + listName, e ); + } } } - private void fireListSetAsDefault(String listname) + + private void fireListSetAsDefault( String listName ) { - for (SparkPrivacyListListener listener: _listListeners) + for ( final SparkPrivacyListListener listener : _listListeners ) { - listener.listSetAsDefault(listname); + try + { + listener.listSetAsDefault( listName ); + } + catch ( Exception e ) + { + Log.error( "A SparkPrivacyListListener (" + listener + ") threw an exception while processing a 'listSetAsDefault' event for: " + listName, e ); + } } } - private void fireListRemovedAsDefault(String listname) + + private void fireListRemovedAsDefault( String listName ) { - for (SparkPrivacyListListener listener: _listListeners) + for ( final SparkPrivacyListListener listener : _listListeners ) { - listener.listRemovedAsDefault(listname); + try + { + listener.listRemovedAsDefault( listName ); + } + catch ( Exception e ) + { + Log.error( "A SparkPrivacyListListener (" + listener + ") threw an exception while processing a 'listRemovedAsDefault' event for: " + listName, e ); + } } } @@ -422,8 +439,7 @@ public void goToVisible() } } catch (Exception e) { - // e.printStackTrace(); - Log.error("PrivacyManager#goToVisible: " + e.getMessage()); + Log.error("PrivacyManager#goToVisible: ", e); } } @@ -440,8 +456,7 @@ public void activateGloballyInvisibleList() { SparkManager.getConnection().sendStanza(PresenceManager.getAvailablePresence()); Log.debug("List \"" + INVISIBLE_LIST_NAME + "\" has been activated "); } catch (Exception e) { - // e.printStackTrace(); - Log.error("PrivacyManager#activateGloballyInvisibleList: " + e.getMessage()); + Log.error("PrivacyManager#activateGloballyInvisibleList: ", e); } } @@ -454,13 +469,12 @@ public boolean isGloballyInvisibleListActive() { return false; try { - PrivacyList pl = privacyManager.getActiveList(); - return pl != null && INVISIBLE_LIST_NAME.equalsIgnoreCase(pl.toString()); + String pl = privacyManager.getActiveListName(); + return INVISIBLE_LIST_NAME.equalsIgnoreCase(pl); } catch (Exception e){ // it can return item-not-found if there is no active list. // so it is fine to fall here. - //e.printStackTrace(); - Log.error("PrivacyManager#isGloballyInvisibleListActive: " + e.getMessage()); + Log.error("PrivacyManager#isGloballyInvisibleListActive: ", e); } return false; } @@ -476,7 +490,7 @@ private PrivacyList ensureGloballyInvisibleListExists() { if (list != null) return list; - } catch (XMPPException | SmackException e1) { + } catch (XMPPException | SmackException | InterruptedException e1) { Log.debug("PrivacyManager#ensureGloballyInvisibleListExists: Could not find globally invisible list. We need to create one"); } @@ -484,15 +498,14 @@ private PrivacyList ensureGloballyInvisibleListExists() { PrivacyItem item = new PrivacyItem(false, 1); item.setFilterPresenceOut(true); - List items = Arrays.asList(item); + List items = Collections.singletonList(item); privacyManager.createPrivacyList(INVISIBLE_LIST_NAME, items); list = privacyManager.getPrivacyList(INVISIBLE_LIST_NAME); Log.debug("List \"" + INVISIBLE_LIST_NAME + "\" has been created "); } - catch (XMPPException | SmackException e) + catch (XMPPException | SmackException | InterruptedException e) { - Log.warning("PrivacyManager#ensureGloballyInvisibleListExists: Could not create PrivacyList " + INVISIBLE_LIST_NAME); - //e.printStackTrace(); + Log.warning("PrivacyManager#ensureGloballyInvisibleListExists: Could not create PrivacyList " + INVISIBLE_LIST_NAME, e); } return list; diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyPlugin.java new file mode 100644 index 000000000..f80819493 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyPlugin.java @@ -0,0 +1,142 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.privacy; + +import java.awt.event.MouseEvent; +import java.util.TimerTask; + + +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; + +import org.jivesoftware.smackx.privacy.packet.PrivacyItem; +import org.jivesoftware.smackx.privacy.packet.PrivacyItem.Type; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.ContextMenuListener; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.sparkimpl.plugin.privacy.list.SparkPrivacyList; + +/** + * Privacy lists. + * + * This plugin built using specification: XEP-0016: Privacy Lists + * {@see http://xmpp.org/extensions/xep-0016.html} + * + * @author Zolotarev Konstantin, Bergunde Holger + */ +public class PrivacyPlugin implements Plugin { + + @Override + public void initialize() { + TimerTask pManagerInstance = new TimerTask() { + @Override + public void run() { + PrivacyManager.getInstance(); // Initiating PrivacyLists + + TimerTask thread = new TimerTask() { + @Override + public void run() { + addMenuItemToContactItems(); + } + }; + TaskEngine.getInstance().schedule(thread, 500); + } + }; + TaskEngine.getInstance().schedule(pManagerInstance, 1000); + + + } + + @Override + public void shutdown() { + // @todo remove Privacy List + } + + @Override + public boolean canShutDown() { + return false; + } + + @Override + public void uninstall() { + + } + + // /** + // * Adding block menu item to contact popup menu + // */ + protected void addMenuItemToContactItems() { + if (PrivacyManager.getInstance().isPrivacyActive()) { + SparkManager.getContactList().addContextMenuListener(new ContextMenuListener() { + @Override + public void poppingUp(Object object, JPopupMenu popup) { + + if (object instanceof ContactItem) { + final PrivacyManager pManager = PrivacyManager.getInstance(); + + if (pManager.hasActiveList()) { + final SparkPrivacyList activeList = pManager.getActiveList(); + + final ContactItem item = (ContactItem) object; + JMenuItem blockMenu; + + if (activeList.isBlockedItem(item.getJid().toString())) { + blockMenu = new JMenuItem(Res.getString("menuitem.unblock.contact"), SparkRes.getImageIcon(SparkRes.Icon.UNBLOCK_CONTACT_16x16)); + blockMenu.addActionListener( ae -> { + if (item != null) { + activeList.removeItem( item.getJid().toString()); + activeList.save(); + } + } ); + } else { + blockMenu = new JMenuItem(Res.getString("menuitem.block.contact"), SparkRes.getImageIcon(SparkRes.Icon.BLOCK_CONTACT_16x16)); + blockMenu.addActionListener( ae -> { + if (item != null) { + PrivacyItem pItem = new PrivacyItem(Type.jid, item.getJid().toString(), false, activeList.getNewItemOrder()); + pItem.setFilterMessage(true); + pItem.setFilterPresenceOut(true); + + activeList.addItem(pItem); + activeList.save(); + } + } ); + } + + popup.add(blockMenu); + } + } + } + + @Override + public void poppingDown(JPopupMenu popup) { + // ignore + } + + @Override + public boolean handleDefaultAction(MouseEvent e) { + return false; + } + }); + } + + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/list/PrivacyPresenceHandler.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/list/PrivacyPresenceHandler.java new file mode 100644 index 000000000..924687ad8 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/list/PrivacyPresenceHandler.java @@ -0,0 +1,159 @@ +package org.jivesoftware.sparkimpl.plugin.privacy.list; + + + +import java.util.Collection; + +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smackx.privacy.packet.PrivacyItem; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.ContactGroup; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.sparkimpl.plugin.privacy.PrivacyManager; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; + + +/** + * @author Bergunde Holger + */ + +public class PrivacyPresenceHandler implements SparkPrivacyItemListener { + /** + * Send Unavailable (offline status) to jid . + * + * @param jid the JID to send offline status + * @throws SmackException.NotConnectedException if Spark is not connected + */ + public void sendUnavailableTo(Jid jid) throws SmackException.NotConnectedException + { + Presence pack = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .build(); + pack.setTo(jid); + try { + SparkManager.getConnection().sendStanza(pack); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } + } + + /** + * Send my presence for user + * + * @param jid the JID to send presence + * @throws SmackException.NotConnectedException if Spark is not connected + */ + public void sendRealPresenceTo(Jid jid) throws SmackException.NotConnectedException + { + Presence presence = SparkManager.getWorkspace().getStatusBar().getPresence(); + Presence pack = StanzaBuilder.buildPresence() + .ofType(presence.getType()) + .setStatus(presence.getStatus()) + .setPriority(1) + .setMode(presence.getMode()) + .build(); + pack.setTo(jid); + try { + SparkManager.getConnection().sendStanza(pack); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } + } + + public void setIconsForList(SparkPrivacyList list) throws SmackException.NotConnectedException + { + for (PrivacyItem pItem : list.getPrivacyItems()) { + setIconsForItem(pItem); + } + SparkManager.getContactList().updateUI(); + } + + private void setIconsForItem(PrivacyItem item) throws SmackException.NotConnectedException { + if (item.getType().equals(PrivacyItem.Type.jid)) { + Jid jid = JidCreate.fromOrThrowUnchecked(item.getValue()); + setBlockedIconToContact(jid); + if (item.isFilterPresenceOut()) { + sendUnavailableTo(jid); + } + } + + if (item.getType().equals(PrivacyItem.Type.group)) { + ContactGroup group = SparkManager.getWorkspace().getContactList().getContactGroup(item.getValue()); + for (ContactItem contact : group.getContactItems()) { + setBlockedIconToContact(contact.getJid()); + if (item.isFilterPresenceOut()) { + sendUnavailableTo(contact.getJid()); + } + } + } + } + + private void setBlockedIconToContact(Jid jid) { + Collection items = SparkManager.getWorkspace().getContactList().getContactItemsByJID(jid); + for (ContactItem contactItem : items) { + if (contactItem != null) { + contactItem.setSpecialIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_ICON_SMALL)); + } + } + } + + public void removeIconsForList(SparkPrivacyList list) throws SmackException.NotConnectedException + { + for (PrivacyItem pItem : list.getPrivacyItems()) { + removeIconsForItem(pItem); + } + SparkManager.getContactList().updateUI(); + } + + private void removeIconsForItem(PrivacyItem item) throws SmackException.NotConnectedException { + if (item.getType().equals(PrivacyItem.Type.jid)) { + Jid jid = JidCreate.fromOrThrowUnchecked(item.getValue()); + removeBlockedIconFromContact(jid); + if (item.isFilterPresenceOut()) { + sendRealPresenceTo(jid); + } + } + + if (item.getType().equals(PrivacyItem.Type.group)) { + ContactGroup group = SparkManager.getWorkspace().getContactList().getContactGroup(item.getValue()); + for (ContactItem contact : group.getContactItems()) { + removeBlockedIconFromContact(contact.getJid()); + if (item.isFilterPresenceOut()) { + sendRealPresenceTo(contact.getJid()); + } + } + } + } + + private void removeBlockedIconFromContact(Jid jid) { + Collection items = SparkManager.getWorkspace().getContactList().getContactItemsByJID(jid); + for (ContactItem item : items) { + if (item != null) { + item.setSpecialIcon(null); + } + } + } + + @Override + public void itemAdded(PrivacyItem item, String listName) throws SmackException.NotConnectedException + { + if (PrivacyManager.getInstance().getPrivacyList(listName).isActive()) { + setIconsForItem(item); + SparkManager.getContactList().updateUI(); + } + } + + @Override + public void itemRemoved(PrivacyItem item, String listName) throws SmackException.NotConnectedException + { + if (PrivacyManager.getInstance().getPrivacyList(listName).isActive()) { + removeIconsForItem(item); + SparkManager.getContactList().updateUI(); + } + } +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyItemListener.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyItemListener.java similarity index 99% rename from src/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyItemListener.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyItemListener.java index a66352198..4f47d5d9c 100755 --- a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyItemListener.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyItemListener.java @@ -9,7 +9,6 @@ import org.jivesoftware.smackx.privacy.packet.PrivacyItem; /** - * * @author Zolotarev Konstantin, Bergunde Holger */ public interface SparkPrivacyItemListener { diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyList.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyList.java similarity index 78% rename from src/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyList.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyList.java index 2647cb823..7a5a398f1 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyList.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyList.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,21 +15,17 @@ */ package org.jivesoftware.sparkimpl.plugin.privacy.list; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smackx.privacy.PrivacyList; import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.privacy.PrivacyList; import org.jivesoftware.smackx.privacy.packet.PrivacyItem; import org.jivesoftware.spark.util.log.Log; import org.jivesoftware.sparkimpl.plugin.privacy.PrivacyManager; +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; + /** - * * @author Zolotarev Konstantin, Bergunde Holger */ public class SparkPrivacyList { @@ -41,21 +33,20 @@ public class SparkPrivacyList { /** * List name will be used to identify PrivacyList */ - private String _listName = ""; - private boolean _isActive = false; - private boolean _isDefault = false; - private List _privacyItems = new LinkedList<>(); - private PrivacyList _myPrivacyList; - private final Set _listeners = new HashSet<>(); + private final String _listName; + private boolean _isActive; + private boolean _isDefault; + private final List _privacyItems = new LinkedList<>(); + private final PrivacyList _myPrivacyList; + private final CopyOnWriteArrayList _listeners = new CopyOnWriteArrayList<>(); /** * Action associated with the items, it MUST be filled and will allow or deny * the communication by default */ - public SparkPrivacyList(PrivacyList list) throws SmackException.NotConnectedException - { - _listName = list.toString(); + public SparkPrivacyList(PrivacyList list) { + _listName = list.getName(); _myPrivacyList = list; _isActive = _myPrivacyList.isActiveList(); _isDefault = _myPrivacyList.isDefaultList(); @@ -63,8 +54,7 @@ public SparkPrivacyList(PrivacyList list) throws SmackException.NotConnectedExce } - private void loadItems() throws SmackException.NotConnectedException - { + private void loadItems() { List itemList = _myPrivacyList.getItems(); for (PrivacyItem item: itemList) @@ -84,7 +74,7 @@ private void loadItems() throws SmackException.NotConnectedException */ private long getMaxItemOrder() { if(getLastItem() != null) { - return getLastItem().getOrder(); + return getLastItem().getOrder().longValue(); } return 1; } @@ -95,10 +85,7 @@ private long getMaxItemOrder() { * @return is user blocked */ public boolean isBlockedItem(String jid) { - if ( searchPrivacyItem(jid) != null ) { - return true; - } - return false; + return searchPrivacyItem(jid) != null; } /** @@ -110,8 +97,9 @@ public PrivacyItem getLastItem() { long order = 0; PrivacyItem item = null; for (PrivacyItem privacyItem : _privacyItems) { - if ( order < privacyItem.getOrder() ) { - order = privacyItem.getOrder(); + final long itemsOrder = privacyItem.getOrder().longValue(); + if (order < itemsOrder) { + order = itemsOrder; item = privacyItem; } } @@ -178,21 +166,18 @@ public ArrayList searchPrivacyItems(PrivacyItem.Type type, String v } - public void addItem (PrivacyItem item) throws SmackException.NotConnectedException - { + public void addItem (PrivacyItem item) { _privacyItems.add(item); fireItemAdded(item); } - public void removeItem(PrivacyItem item) throws SmackException.NotConnectedException - { + public void removeItem(PrivacyItem item) { _privacyItems.remove(item); fireItemRemoved(item); } - public void removeItem(String name) throws SmackException.NotConnectedException - { + public void removeItem(String name) { List tempList = new ArrayList<>( _privacyItems ); for (PrivacyItem item: tempList) { @@ -272,14 +257,13 @@ public void save() { PrivacyManager.getInstance().getPrivacyListManager().updatePrivacyList(getListName(), _privacyItems); PrivacyManager.getInstance().getPrivacyListManager().getPrivacyList(_listName).getItems().remove(item); _privacyItems.remove(item); - } catch (XMPPException | SmackException e) { + } catch (XMPPException | SmackException | InterruptedException e) { Log.warning("Could not save PrivacyList "+_listName); e.printStackTrace(); } } /** - * * @return listName */ @Override @@ -289,31 +273,43 @@ public String toString() { /** - * * @param item user was added into blockList */ - private void fireItemAdded(PrivacyItem item) throws SmackException.NotConnectedException - { - for (SparkPrivacyItemListener listener :_listeners) { - listener.itemAdded(item, _listName); + private void fireItemAdded( PrivacyItem item ) { + for ( final SparkPrivacyItemListener listener : _listeners ) + { + try + { + listener.itemAdded( item, _listName ); + } + catch ( Exception e ) + { + Log.error( "A SparkPrivacyItemListener (" + listener + ") threw an exception while processing a 'itemAdded' event for: " + item + " on list: " + _listName, e ); + } } } /** - * * @param item user removed from blackList */ - private void fireItemRemoved(PrivacyItem item) throws SmackException.NotConnectedException - { - for (SparkPrivacyItemListener listener : _listeners) { - listener.itemRemoved(item, _listName); + private void fireItemRemoved( PrivacyItem item ) { + for ( final SparkPrivacyItemListener listener : _listeners ) + { + try + { + listener.itemRemoved( item, _listName ); + } + catch ( Exception e ) + { + Log.error( "A SparkPrivacyItemListener (" + listener + ") threw an exception while processing a 'itemRemoved' event for: " + item + " on list: " + _listName, e ); + } } } public void addSparkPrivacyListener(SparkPrivacyItemListener listener) { - _listeners.add(listener); + _listeners.addIfAbsent(listener); } public void removeSparkPrivacyListener(SparkPrivacyItemListener listener) diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyListListener.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyListListener.java similarity index 99% rename from src/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyListListener.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyListListener.java index 555cfd672..92866ec6a 100755 --- a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyListListener.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/list/SparkPrivacyListListener.java @@ -1,7 +1,6 @@ package org.jivesoftware.sparkimpl.plugin.privacy.list; /** - * * @author Bergunde Holger */ diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyAddDialogUI.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyAddDialogUI.java similarity index 81% rename from src/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyAddDialogUI.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyAddDialogUI.java index 558fde7f5..c2dc098b5 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyAddDialogUI.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyAddDialogUI.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,8 +23,6 @@ import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; import java.util.List; @@ -56,17 +50,19 @@ import org.jivesoftware.spark.ui.ContactItem; import org.jivesoftware.spark.util.log.Log; +import static org.jivesoftware.spark.ui.ContactItem.CONTACT_ITEM_COMPARATOR; + /** * @author Bergunde Holger */ public class PrivacyAddDialogUI extends JPanel { - private JCheckBox _showOffCheckbox = new JCheckBox(); + private final JCheckBox _showOffCheckbox = new JCheckBox(); private static final long serialVersionUID = -7725304880236329893L; - private DefaultListModel model = new DefaultListModel<>(); - private JList rosterList = new JList<>( model ); + private final DefaultListModel model = new DefaultListModel<>(); + private final JList rosterList = new JList<>( model ); private boolean _showGroups = false; - private List _userList = new ArrayList<>(); + private final List _userList = new ArrayList<>(); private JCheckBox _blockPIn; private JCheckBox _blockPOout; private JCheckBox _blockMsg; @@ -94,20 +90,20 @@ private JPanel createCheckBoxes() { panel.setLayout(new GridBagLayout()); panel.setBorder(BorderFactory.createTitledBorder(Res.getString("privacy.border.block"))); _blockPIn = new JCheckBox(Res.getString("privacy.label.pin.desc")); - _blockPIn.setIcon(SparkRes.getImageIcon("PRIVACY_PIN_ALLOW")); - _blockPIn.setSelectedIcon(SparkRes.getImageIcon("PRIVACY_PIN_DENY")); + _blockPIn.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_PIN_ALLOW)); + _blockPIn.setSelectedIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_PIN_DENY)); _blockPIn.setRolloverEnabled(false); _blockPOout = new JCheckBox(Res.getString("privacy.label.pout.desc")); - _blockPOout.setIcon(SparkRes.getImageIcon("PRIVACY_POUT_ALLOW")); - _blockPOout.setSelectedIcon(SparkRes.getImageIcon("PRIVACY_POUT_DENY")); + _blockPOout.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_POUT_ALLOW)); + _blockPOout.setSelectedIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_POUT_DENY)); _blockPOout.setRolloverEnabled(false); _blockMsg = new JCheckBox(Res.getString("privacy.label.msg.desc")); - _blockMsg.setSelectedIcon(SparkRes.getImageIcon("PRIVACY_MSG_DENY")); - _blockMsg.setIcon(SparkRes.getImageIcon("PRIVACY_MSG_ALLOW")); + _blockMsg.setSelectedIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_MSG_DENY)); + _blockMsg.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_MSG_ALLOW)); _blockMsg.setRolloverEnabled(false); _blockIQ = new JCheckBox(Res.getString("privacy.label.iq.desc")); - _blockIQ.setSelectedIcon(SparkRes.getImageIcon("PRIVACY_QUERY_DENY")); - _blockIQ.setIcon(SparkRes.getImageIcon("PRIVACY_QUERY_ALLOW")); + _blockIQ.setSelectedIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_QUERY_DENY)); + _blockIQ.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_QUERY_ALLOW)); _blockIQ.setRolloverEnabled(false); panel.add(_blockPIn, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); panel.add(_blockPOout, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); @@ -119,30 +115,31 @@ private JPanel createCheckBoxes() { private void createList() { _userList.clear(); - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); + final Roster roster = SparkManager.getRoster(); if (_showGroups) { for (RosterGroup group : roster.getGroups()) { _showOffCheckbox.setVisible(false); - ContactItem item = new ContactItem(group.getName(), null, group.getName()); +// ContactItem item = new ContactItem(group.getName(), null, group.getName()); + ContactItem item = new ContactItem(group.getName(), null, null); _userList.add(item); } } else { for (RosterEntry entry : roster.getEntries()) { - Presence presence = PresenceManager.getPresence(entry.getUser()); + Presence presence = PresenceManager.getPresence(entry.getJid()); if (presence.isAvailable()) { - ContactItem item = new ContactItem(entry.getName(), null, entry.getUser()); + ContactItem item = new ContactItem(entry.getName(), null, entry.getJid()); item.setPresence(presence); _userList.add(item); } else if (_showOffCheckbox.isSelected()) { - ContactItem item = new ContactItem(entry.getName(), null, entry.getUser()); + ContactItem item = new ContactItem(entry.getName(), null, entry.getJid()); item.setPresence(presence); _userList.add(item); } } } - Collections.sort(_userList, itemComparator); + _userList.sort(CONTACT_ITEM_COMPARATOR); model.clear(); for (ContactItem item : _userList) { @@ -172,7 +169,7 @@ public Collection showRoster(Component parent, boolean showGroups) TitlePanel titlePanel; // Create the title panel for this dialog - titlePanel = new TitlePanel(Res.getString("privacy.title.add.picker"), Res.getString("privacy.pick.one.or.more"), SparkRes.getImageIcon(SparkRes.BLANK_IMAGE), true); + titlePanel = new TitlePanel(Res.getString("privacy.title.add.picker"), Res.getString("privacy.pick.one.or.more"), SparkRes.getImageIcon(SparkRes.Icon.BLANK_IMAGE), true); // Construct main panel w/ layout. final JPanel mainPanel = new JPanel(); @@ -218,14 +215,13 @@ public Collection showRoster(Component parent, boolean showGroups) - Object[] values = rosterList.getSelectedValues(); - final int no = values != null ? values.length : 0; - for (int i = 0; i < no; i++) { + Object[] values = rosterList.getSelectedValuesList().toArray(); + for (Object value : values) { try { - ContactItem item = (ContactItem) values[i]; + ContactItem item = (ContactItem) value; PrivacyItem.Type type = _showGroups ? PrivacyItem.Type.group : PrivacyItem.Type.jid; - PrivacyItem pitem = new PrivacyItem(type, item.getJID(), false, 999); + PrivacyItem pitem = new PrivacyItem(type, item.getJid().toString(), false, 999); pitem.setFilterIQ(_blockIQ.isSelected()); pitem.setFilterMessage(_blockMsg.isSelected()); pitem.setFilterPresenceIn(_blockPIn.isSelected()); @@ -239,17 +235,5 @@ public Collection showRoster(Component parent, boolean showGroups) return selectedContacts; } - /** - * Sorts ContactItems. - */ - final Comparator itemComparator = ( item1, item2 ) -> { - String nickname1 = item1.getDisplayName(); - String nickname2 = item2.getDisplayName(); - if (nickname1 == null || nickname2 == null) { - return 0; - } - - return nickname1.toLowerCase().compareTo(nickname2.toLowerCase()); - }; } diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyListTree.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyListTree.java similarity index 85% rename from src/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyListTree.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyListTree.java index a40728b07..78bbe6d3e 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyListTree.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyListTree.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -42,10 +38,8 @@ import javax.swing.tree.TreePath; import org.jivesoftware.resource.Res; import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; import org.jivesoftware.smackx.privacy.packet.PrivacyItem; import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.util.log.Log; import org.jivesoftware.sparkimpl.plugin.privacy.PrivacyManager; import org.jivesoftware.sparkimpl.plugin.privacy.list.SparkPrivacyList; import org.jivesoftware.sparkimpl.plugin.privacy.list.SparkPrivacyListListener; @@ -57,11 +51,11 @@ public class PrivacyListTree extends JPanel implements SparkPrivacyListListener private static final long serialVersionUID = 1885262127050966627L; private DefaultTreeModel _model; - private JTree _tree; - private PrivacyManager _pManager; - private PrivacyTreeNode _top = new PrivacyTreeNode(Res.getString("privacy.root.node")); - private JComponent _comp; - private JPanel treeandInfo = new JPanel(new GridBagLayout()); + private final JTree _tree; + private final PrivacyManager _pManager; + private final PrivacyTreeNode _top = new PrivacyTreeNode(Res.getString("privacy.root.node")); + private final JComponent _comp; + private final JPanel treeandInfo = new JPanel(new GridBagLayout()); private RolloverButton _actList; private RolloverButton _defList; @@ -99,10 +93,10 @@ private void createInfoPanel() { JPanel info = new JPanel(new GridBagLayout()); JLabel infolabel = new JLabel(Res.getString("privacy.label.information")); info.setBorder(BorderFactory.createTitledBorder(Res.getString("privacy.border.information"))); - JLabel iq = new JLabel(Res.getString("privacy.label.iq.desc"), SparkRes.getImageIcon("PRIVACY_QUERY_ALLOW"), SwingConstants.LEFT); - JLabel msg = new JLabel(Res.getString("privacy.label.msg.desc"), SparkRes.getImageIcon("PRIVACY_MSG_ALLOW"), SwingConstants.LEFT); - JLabel pin = new JLabel(Res.getString("privacy.label.pin.desc"), SparkRes.getImageIcon("PRIVACY_PIN_ALLOW"), SwingConstants.LEFT); - JLabel pout = new JLabel(Res.getString("privacy.label.pout.desc"), SparkRes.getImageIcon("PRIVACY_POUT_ALLOW"), SwingConstants.LEFT); + JLabel iq = new JLabel(Res.getString("privacy.label.iq.desc"), SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_QUERY_ALLOW), SwingConstants.LEFT); + JLabel msg = new JLabel(Res.getString("privacy.label.msg.desc"), SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_MSG_ALLOW), SwingConstants.LEFT); + JLabel pin = new JLabel(Res.getString("privacy.label.pin.desc"), SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_PIN_ALLOW), SwingConstants.LEFT); + JLabel pout = new JLabel(Res.getString("privacy.label.pout.desc"), SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_POUT_ALLOW), SwingConstants.LEFT); info.add(infolabel, new GridBagConstraints(0, 0, 4, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 10, 10, 0), 0, 0)); info.add(iq, new GridBagConstraints(0, 1, 1, 1, 0.0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 0, 0), 0, 0)); info.add(msg, new GridBagConstraints(1, 1, 1, 1, 0.0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 0, 0), 0, 0)); @@ -123,9 +117,9 @@ private void createCurrentListInfoPanel() { _actList.setHorizontalTextPosition(SwingConstants.LEFT); _defList.setHorizontalTextPosition(SwingConstants.LEFT); if (_pManager.hasActiveList()) { - _actList.setIcon(SparkRes.getImageIcon("PRIVACY_DEACTIVATE_LIST")); + _actList.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_DEACTIVATE_LIST)); _actList.setText(_pManager.getActiveList().getListName()); - _actList.setIcon(SparkRes.getImageIcon("PRIVACY_DEACTIVATE_LIST")); + _actList.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_DEACTIVATE_LIST)); } else { _actList.setText(Res.getString("privacy.button.no.list.selected")); @@ -136,7 +130,7 @@ private void createCurrentListInfoPanel() { if (_pManager.hasDefaultList()) { _defList.setText(_pManager.getDefaultList().getListName()); _defList.setEnabled(true); - _defList.setIcon(SparkRes.getImageIcon("PRIVACY_DEACTIVATE_LIST")); + _defList.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_DEACTIVATE_LIST)); } else { _defList.setText(Res.getString("privacy.button.no.list.selected")); @@ -154,8 +148,8 @@ private void createCurrentListInfoPanel() { defPanel.add(defListLabel); defPanel.add(_defList); - listInfo.add(actPanel, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 00, 00, 0), 0, 0)); - listInfo.add(defPanel, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 00, 00, 0), 0, 0)); + listInfo.add(actPanel, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + listInfo.add(defPanel, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); treeandInfo.add(listInfo, new GridBagConstraints(0, 1, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); // treeandInfo.add(listInfo); } @@ -189,7 +183,7 @@ private void addMenuForLeaf(JPopupMenu menu, final PrivacyTreeNode node) { } else { remUser = new JMenuItem(Res.getString("privacy.menu.remove") + node.getPrivacyItem().getValue()); } - remUser.setIcon(SparkRes.getImageIcon(SparkRes.SMALL_DELETE)); + remUser.setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_DELETE)); menu.add(remUser); remUser.addActionListener( e -> { @@ -200,17 +194,10 @@ private void addMenuForLeaf(JPopupMenu menu, final PrivacyTreeNode node) { PrivacyTreeNode parent1 = (PrivacyTreeNode) path.getPathComponent(1); SparkPrivacyList list = parent1.getPrivacyList(); // Remove contact or group - try - { - list.removeItem( node1.getPrivacyItem().getValue()); - //list.removePrivacyItem(node.getPrivacyItem().getType(), node.getPrivacyItem().getValue()); - list.save(); - _model.removeNodeFromParent( node1 ); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to remove item for privacly list.", e1 ); - } + list.removeItem( node1.getPrivacyItem().getValue()); + //list.removePrivacyItem(node.getPrivacyItem().getType(), node.getPrivacyItem().getValue()); + list.save(); + _model.removeNodeFromParent( node1 ); } } ); @@ -236,26 +223,17 @@ private void addMenuForGroupNodes(JPopupMenu menu, final PrivacyTreeNode node) { final SparkPrivacyList list = listnode.getPrivacyList(); final PrivacyTreeNode parent = (PrivacyTreeNode) _tree.getSelectionPath().getPathComponent(2); JMenuItem addContact = new JMenuItem(showStringforAdd); - addContact.setIcon(SparkRes.getImageIcon(SparkRes.SMALL_ADD_IMAGE)); + addContact.setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_ADD_IMAGE)); addContact.addActionListener( e -> { PrivacyAddDialogUI browser = new PrivacyAddDialogUI(); - Collection col = browser.showRoster(_comp, node.isContactGroup() ? false : true); - try - { - for (PrivacyItem pI : col) { - final PrivacyItem clone = new PrivacyItem( pI.getType(), pI.getValue(), pI.isAllow(), list.getNewItemOrder() ); - list.addItem(clone); - PrivacyTreeNode newChild = new PrivacyTreeNode(clone); - _model.insertNodeInto(newChild, parent, 0); - } - list.save(); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to add item to privacy list.", e1 ); + Collection col = browser.showRoster(_comp, !node.isContactGroup()); + for (PrivacyItem pI : col) { + final PrivacyItem clone = new PrivacyItem( pI.getType(), pI.getValue(), pI.isAllow(), list.getNewItemOrder() ); + list.addItem(clone); + PrivacyTreeNode newChild = new PrivacyTreeNode(clone); + _model.insertNodeInto(newChild, parent, 0); } - - + list.save(); } ); menu.add(addContact); @@ -272,12 +250,12 @@ private void addMenuForGroupNodes(JPopupMenu menu, final PrivacyTreeNode node) { */ private void addMenuForListNodes(JPopupMenu menu, final PrivacyTreeNode node) { JMenuItem addList = new JMenuItem(Res.getString("privacy.menu.add.list")); - addList.setIcon(SparkRes.getImageIcon(SparkRes.SMALL_ADD_IMAGE)); + addList.setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_ADD_IMAGE)); JMenuItem rem = new JMenuItem(Res.getString("privacy.menu.remove.list")); JMenuItem act = new JMenuItem(Res.getString("privacy.menu.activate.list")); - act.setIcon(SparkRes.getImageIcon("PRIVACY_LIGHTNING")); + act.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_LIGHTNING)); JMenuItem def = new JMenuItem(Res.getString("privacy.menu.default.list")); - def.setIcon(SparkRes.getImageIcon("PRIVACY_CHECK")); + def.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_CHECK)); act.addActionListener( e -> node.setListAsActive() ); def.addActionListener( e -> node.setListAsDefault() ); @@ -305,7 +283,7 @@ private void addMenuForListNodes(JPopupMenu menu, final PrivacyTreeNode node) { _model.removeNodeFromParent(node); } } ); - rem.setIcon(SparkRes.getImageIcon(SparkRes.SMALL_DELETE)); + rem.setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_DELETE)); menu.add(addList); if (!node.equals(_top)) { @@ -432,7 +410,7 @@ public void mouseExited(MouseEvent e) { public void listActivated(String listname) { _actList.setText(listname); _actList.setEnabled(true); - _actList.setIcon(SparkRes.getImageIcon("PRIVACY_DEACTIVATE_LIST")); + _actList.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_DEACTIVATE_LIST)); } @Override @@ -448,7 +426,7 @@ public void listDeActivated(String listname) { @Override public void listSetAsDefault(String listname) { _defList.setText(listname); - _defList.setIcon(SparkRes.getImageIcon("PRIVACY_DEACTIVATE_LIST")); + _defList.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_DEACTIVATE_LIST)); _defList.setEnabled(true); } diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyPreferences.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyPreferences.java similarity index 86% rename from src/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyPreferences.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyPreferences.java index 6dd813a73..c3cb05bf2 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyPreferences.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyPreferences.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,9 +15,7 @@ */ package org.jivesoftware.sparkimpl.plugin.privacy.ui; -import javax.swing.Icon; - -import javax.swing.JComponent; +import javax.swing.*; import org.jivesoftware.resource.Res; import org.jivesoftware.resource.SparkRes; @@ -32,8 +26,8 @@ */ public class PrivacyPreferences implements Preference { - String _title = Res.getString("privacy.label.preferences"); - String _toolTip = Res.getString("pricacy.tooltip.preferences"); + private final String _title = Res.getString("privacy.label.preferences"); + private final String _toolTip = Res.getString("privacy.tooltip.preferences"); public PrivacyPreferences() { } @@ -45,8 +39,7 @@ public String getTitle() { @Override public Icon getIcon() { - - return SparkRes.getImageIcon("PRIVACY_ICON"); + return SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_ICON); } @Override diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyTreeCellRenderer.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyTreeCellRenderer.java similarity index 81% rename from src/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyTreeCellRenderer.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyTreeCellRenderer.java index c2d5f1415..0084ff763 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyTreeCellRenderer.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyTreeCellRenderer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,12 +22,7 @@ import java.awt.GridBagLayout; import java.awt.Insets; -import javax.swing.Icon; - -import javax.swing.JLabel; -import javax.swing.JPanel; - -import javax.swing.JTree; +import javax.swing.*; import javax.swing.tree.DefaultTreeCellRenderer; @@ -58,10 +49,10 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean myPanel.setBackground(Color.LIGHT_GRAY); } - Icon iq = node.getPrivacyItem().isFilterIQ() ? SparkRes.getImageIcon("PRIVACY_QUERY_DENY") : SparkRes.getImageIcon("PRIVACY_QUERY_ALLOW"); - Icon in = node.getPrivacyItem().isFilterPresenceIn() ? SparkRes.getImageIcon("PRIVACY_PIN_DENY") : SparkRes.getImageIcon("PRIVACY_PIN_ALLOW"); - Icon out = node.getPrivacyItem().isFilterPresenceOut() ? SparkRes.getImageIcon("PRIVACY_POUT_DENY") : SparkRes.getImageIcon("PRIVACY_POUT_ALLOW"); - Icon msg = node.getPrivacyItem().isFilterMessage() ? SparkRes.getImageIcon("PRIVACY_MSG_DENY") : SparkRes.getImageIcon("PRIVACY_MSG_ALLOW"); + Icon iq = node.getPrivacyItem().isFilterIQ() ? SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_QUERY_DENY) : SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_QUERY_ALLOW); + Icon in = node.getPrivacyItem().isFilterPresenceIn() ? SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_PIN_DENY) : SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_PIN_ALLOW); + Icon out = node.getPrivacyItem().isFilterPresenceOut() ? SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_POUT_DENY) : SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_POUT_ALLOW); + Icon msg = node.getPrivacyItem().isFilterMessage() ? SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_MSG_DENY) : SparkRes.getImageIcon(SparkRes.Icon.PRIVACY_MSG_ALLOW); myPanel.add(new JLabel(node.getPrivacyItem().getValue()), new GridBagConstraints(4, 0, 1, 1, 0, 0, GridBagConstraints.FIRST_LINE_START, GridBagConstraints.HORIZONTAL, new Insets(0, 10, 0, 0), 0, 0)); @@ -73,15 +64,15 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean } else { if (node.isRoot()) { - setIcon(SparkRes.getImageIcon("CLIPBOARD")); + setIcon(SparkRes.getImageIcon(SparkRes.Icon.CLIPBOARD)); } if (node.isGroupNode()) { - setIcon(SparkRes.getImageIcon(SparkRes.SMALL_CURRENT_AGENTS)); + setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_CURRENT_AGENTS)); } else if (node.isContactGroup()) { - setIcon(SparkRes.getImageIcon(SparkRes.AVAILABLE_USER)); + setIcon(SparkRes.getImageIcon(SparkRes.Icon.AVAILABLE_USER)); } @@ -94,7 +85,7 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean // listName += " [" + Res.getString("privacy.label.list.is.default") + "]"; // } setText(listName); - setIcon(SparkRes.getImageIcon(SparkRes.SMALL_ENTRY)); + setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_ENTRY)); } diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyTreeNode.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyTreeNode.java similarity index 97% rename from src/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyTreeNode.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyTreeNode.java index bd7cf9175..c0defa859 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyTreeNode.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/privacy/ui/PrivacyTreeNode.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,7 +35,7 @@ public class PrivacyTreeNode extends DefaultMutableTreeNode { private boolean _isGroupGroup = false; private boolean _isDefault = false; private boolean _isActive = false; - private PrivacyManager _pmanager = PrivacyManager.getInstance(); + private final PrivacyManager _pmanager = PrivacyManager.getInstance(); /** * Creates a Node with a reference to the SparkPrivacyList and changes the diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/PrivateNotes.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/PrivateNotes.java new file mode 100644 index 000000000..19773105d --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/PrivateNotes.java @@ -0,0 +1,120 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.scratchpad; + +import org.jivesoftware.smack.util.XmlStringBuilder; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jivesoftware.smackx.iqprivate.PrivateDataManager; +import org.jivesoftware.smackx.iqprivate.packet.PrivateData; +import org.jivesoftware.smackx.iqprivate.provider.PrivateDataProvider; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.JxmppContext; + +import java.io.IOException; + +/** + * @author Derek DeMoro + */ +public class PrivateNotes implements PrivateData { + public static final String ELEMENT = "scratchpad"; + public static final String NAMESPACE = "scratchpad:notes"; + + private String notes; + + public PrivateNotes() { + } + + public String getNotes() { + return notes; + } + + public void setNotes(String notes) { + this.notes = notes; + } + + @Override + public String getElementName() { + return ELEMENT; + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public XmlStringBuilder toXML() { + XmlStringBuilder buf = new XmlStringBuilder(); + buf.halfOpenElement(ELEMENT).xmlnsAttribute(NAMESPACE).rightAngleBracket(); + buf.optElement("text", getNotes()); + buf.closeElement(ELEMENT); + return buf; + } + + /** + * The IQ Provider for BookmarkStorage. + */ + public static class Provider implements PrivateDataProvider { + private final PrivateNotes notes = new PrivateNotes(); + + public Provider() { + super(); + } + + @Override + public PrivateData parsePrivateData(XmlPullParser parser, JxmppContext jxmppContext) throws XmlPullParserException, IOException { + boolean done = false; + while (!done) { + XmlPullParser.Event eventType = parser.next(); + if (eventType == XmlPullParser.Event.START_ELEMENT && "text".equals(parser.getName())) { + notes.setNotes(parser.nextText()); + } else if (eventType == XmlPullParser.Event.END_ELEMENT) { + if (ELEMENT.equals(parser.getName())) { + done = true; + } + } + } + return notes; + } + } + + static { + PrivateDataManager.addPrivateDataProvider(ELEMENT, NAMESPACE, new PrivateNotes.Provider()); + } + + public static void savePrivateNotes(PrivateNotes notes) { + PrivateDataManager manager = SparkManager.getSessionManager().getPersonalDataManager(); + try { + manager.setPrivateData(notes); + } catch (Exception e) { + Log.error(e); + throw new RuntimeException(e.getMessage()); + } + } + + public static PrivateNotes getPrivateNotes() { + PrivateDataManager manager = SparkManager.getSessionManager().getPersonalDataManager(); + try { + PrivateData privateData = manager.getPrivateData(ELEMENT, NAMESPACE); + return privateData != null ? (PrivateNotes) privateData : new PrivateNotes(); + } catch (Exception e) { + Log.error(e); + throw new RuntimeException(e.getMessage()); + } + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/ScratchPadPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/ScratchPadPlugin.java new file mode 100644 index 000000000..bbb1066a4 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/ScratchPadPlugin.java @@ -0,0 +1,506 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.scratchpad; + +import org.jdesktop.swingx.calendar.DateUtils; +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.component.VerticalFlowLayout; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.ContactList; +import org.jivesoftware.spark.util.*; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.TimerTask; + +/** + * Allows users to have scratch paper within Spark. + */ +public class ScratchPadPlugin implements Plugin { + + public static boolean SHOW_ALL_TASKS = true; + + private static final String dateShortFormat = ((SimpleDateFormat)SimpleDateFormat.getDateInstance(SimpleDateFormat.SHORT)).toPattern(); + private final SimpleDateFormat formatter = new SimpleDateFormat(dateShortFormat); + private static final List taskList = new ArrayList<>(); + private static JPanel panel_events; + private static JPanel mainPanel; + private static JFrame frame; + + private static final Color COLOR_GRADIENT = new Color(198, 211, 247); + + @Override + public void initialize() { + TimerTask startTask = new TimerTask() { + @Override + public void run() { + EventQueue.invokeLater(() -> { + panel_events = new JPanel(); + mainPanel = new JPanel(); + }); + } + }; + + TaskEngine.getInstance().schedule(startTask, 500); + + ContactList contactList = SparkManager.getWorkspace().getContactList(); + contactList.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control F6"), "viewNotes"); + + contactList.getActionMap().put("viewNotes", new AbstractAction("viewNotes") { + private static final long serialVersionUID = -3258500919859584696L; + + @Override + public void actionPerformed(ActionEvent evt) { + // Retrieve notes and display in editor. + retrieveNotes(); + } + }); + + contactList.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control F5"), "viewTasks"); + + contactList.getActionMap().put("viewTasks", new AbstractAction("viewTasks") { + private static final long serialVersionUID = 8589614513097901484L; + + @Override + public void actionPerformed(ActionEvent evt) { + // Retrieve notes and display in editor. + showTaskList(); + } + }); + + JMenuItem taskMenu = new JMenuItem(Res.getString("button.view.tasklist"), SparkRes.getImageIcon(SparkRes.Icon.DESKTOP_IMAGE)); + taskMenu.addActionListener(e -> showTaskList()); + + JMenuItem notesMenu = new JMenuItem(Res.getString("button.view.notes"), SparkRes.getImageIcon(SparkRes.Icon.DOCUMENT_16x16)); + notesMenu.addActionListener(e -> retrieveNotes()); + + // Add To toolbar + final JMenu actionsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions")); + actionsMenu.addSeparator(); + + // See if we should disable the "View task list" option under "Actions" + if (!Default.getBoolean(Default.DISABLE_VIEW_TASK_LIST) && Enterprise.containsFeature(Enterprise.VIEW_TASKS_FEATURE)) actionsMenu.add(taskMenu); + + // See if we should disable the "View notes" option under "Actions" + if (!Default.getBoolean(Default.DISABLE_VIEW_NOTES) && Enterprise.containsFeature(Enterprise.VIEW_NOTES_FEATURE)) actionsMenu.add(notesMenu); + + // Start notifications. + new TaskNotification(); + } + + + private void showTaskList() { + frame = new JFrame(Res.getString("title.tasks")); + frame.setIconImage(SparkManager.getMainWindow().getIconImage()); + panel_events.removeAll(); + mainPanel.removeAll(); + + mainPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); + mainPanel.setBackground(Color.white); + + final JPanel topPanel = new JPanel(new GridBagLayout()); + final JTextField taskField = new JTextField(); + final JTextField dueDateField = new JTextField(); + + final JButton addButton = new JButton(Res.getString("add")); + final JLabel addTaskLabel = new JLabel(Res.getString("label.add.task")); + topPanel.setOpaque(false); + + topPanel.add(addTaskLabel, new GridBagConstraints(0, 0, 1, 1, .9, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); + topPanel.add(taskField, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 0, 2), 0, 0)); + + topPanel.add(dueDateField, new GridBagConstraints(1, 1, 1, 1, 0.1, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 0, 2), 50, 0)); + topPanel.add(addButton, new GridBagConstraints(3, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 0, 2), 0, 0)); + + topPanel.add(new JLabel(Res.getString("label.timeformat", formatter.toPattern())), new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); + mainPanel.add(topPanel); + + // Add Selection + final JPanel middlePanel = new JPanel(new GridBagLayout()); + final JLabel showLabel = new JLabel(Res.getString("label.show")); + final JToggleButton allButton = new JToggleButton(Res.getString("button.tasks.all")); + final JToggleButton activeButton = new JToggleButton(Res.getString("button.tasks.active")); + final ButtonGroup buttonGroup = new ButtonGroup(); + buttonGroup.add(allButton); + buttonGroup.add(activeButton); + middlePanel.setOpaque(false); + + middlePanel.add(showLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); + middlePanel.add(allButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); + middlePanel.add(activeButton, new GridBagConstraints(2, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); + + mainPanel.add(middlePanel); + mainPanel.setBackground(Color.white); + + final JPanel titlePanel = new JPanel(new BorderLayout()) { + private static final long serialVersionUID = -8812868562658925280L; + + @Override + public void paintComponent(Graphics g) { + Color startColor = Color.white; + Color endColor = COLOR_GRADIENT; + + Graphics2D g2 = (Graphics2D)g; + + int w = getWidth(); + int h = getHeight(); + + GradientPaint gradient = new GradientPaint(0, 0, startColor, w, h, endColor, true); + g2.setPaint(gradient); + g2.fillRect(0, 0, w, h); + } + + }; + final JLabel taskLabel = new JLabel(Res.getString("label.due") + " "); + taskLabel.setFont(taskLabel.getFont().deriveFont(Font.BOLD)); + titlePanel.add(taskLabel, BorderLayout.EAST); + mainPanel.add(titlePanel); + + Action showAllAction = new AbstractAction() { + private static final long serialVersionUID = -7031122285194582204L; + + @Override + public void actionPerformed(ActionEvent e) { + for (TaskUI ui : taskList) { + ui.setVisible(true); + } + + SHOW_ALL_TASKS = true; + } + }; + + Action showActiveAction = new AbstractAction() { + private static final long serialVersionUID = -7551153291479117311L; + + @Override + public void actionPerformed(ActionEvent e) { + for (TaskUI ui : taskList) { + if (ui.isSelected()) { + ui.setVisible(false); + } + } + + SHOW_ALL_TASKS = false; + } + }; + + final Action addAction = new AbstractAction() { + private static final long serialVersionUID = -5937301529216080813L; + + @Override + public void actionPerformed(ActionEvent e) { + String taskTitle = taskField.getText(); + if (!ModelUtil.hasLength(taskTitle)) { + return; + } + Task task = new Task(); + task.setTitle(taskTitle); + + // Set creation time. + final Date creationDate = new Date(); + task.setCreatedDate(creationDate.getTime()); + + // Set due date. + String dueDate = dueDateField.getText(); + if (ModelUtil.hasLength(dueDate)) { + + try { + Date date = formatter.parse(dueDate); + task.setDueDate(date.getTime()); + } + catch (ParseException e1) { + // Nothing to do + } + + } + + taskField.setText(""); + + final TaskUI taskUI = new TaskUI(task); + //mainPanel.add(taskUI); + panel_events.add(taskUI); + taskList.add(taskUI); + + panel_events.invalidate(); + panel_events.validate(); + panel_events.repaint(); + mainPanel.invalidate(); + mainPanel.validate(); + mainPanel.repaint(); + frame.invalidate(); + frame.validate(); + frame.repaint(); + } + }; + + mainPanel.add(panel_events); + panel_events.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); + panel_events.setBackground(Color.white); + + allButton.addActionListener(showAllAction); + activeButton.addActionListener(showActiveAction); + + GraphicUtils.makeSameSize(allButton, activeButton); + + addButton.addActionListener(addAction); + + Tasks tasks = Tasks.getTaskList(); + SHOW_ALL_TASKS = tasks.isShowAll(); + updateTaskUI(tasks); + + if (SHOW_ALL_TASKS) { + allButton.setSelected(true); + } + else { + activeButton.setSelected(true); + showActiveAction.actionPerformed(null); + } + + long tomorrow = DateUtils.addDays(new Date().getTime(), 1); + SimpleDateFormat formatter = new SimpleDateFormat(dateShortFormat); + dueDateField.setText(formatter.format(new Date(tomorrow))); + + + final JScrollPane pane = new JScrollPane(mainPanel); + + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(pane, BorderLayout.CENTER); + frame.pack(); + frame.setSize(400, 400); + + final Action saveAction = new AbstractAction() { + private static final long serialVersionUID = -4287799161421970177L; + + @Override + public void actionPerformed(ActionEvent actionEvent) { + // Save it. + Tasks tasks = new Tasks(); + tasks.setShowAll(SHOW_ALL_TASKS); + for (TaskUI ui : taskList) { + Task task = ui.getTask(); + tasks.addTask(task); + } + taskList.clear(); + + Tasks.saveTasks(tasks); + } + }; + + addButton.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyChar() == KeyEvent.VK_ESCAPE) { + saveAction.actionPerformed(null); + frame.dispose(); + } + } + }); + + + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent windowEvent) { + saveAction.actionPerformed(null); + } + }); + + taskField.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyChar() == KeyEvent.VK_ENTER) { + addAction.actionPerformed(null); + } + } + }); + + + GraphicUtils.centerWindowOnComponent(frame, SparkManager.getMainWindow()); + frame.setVisible(true); + } + + /** + * Updates the GUI of Tasks + * + * @param tasks Tasks + */ + public static void updateTaskUI(Tasks tasks) { + panel_events.removeAll(); + taskList.clear(); + + for (Task task : tasks.getTasks()) { + final TaskUI taskUI = new TaskUI(task); + + if ( !SHOW_ALL_TASKS ) { + taskUI.setVisible(!taskUI.isSelected()); + } + + panel_events.add(taskUI); + taskList.add(taskUI); + } + + panel_events.invalidate(); + panel_events.validate(); + panel_events.repaint(); + mainPanel.invalidate(); + mainPanel.validate(); + mainPanel.repaint(); + frame.invalidate(); + frame.validate(); + frame.repaint(); + } + + /** + * Retrieve private notes from server. + */ + private void retrieveNotes() { + // Retrieve private notes from server. + final SwingWorker notesWorker = new SwingWorker() { + @Override + public Object construct() { + return PrivateNotes.getPrivateNotes(); + } + + @Override + public void finished() { + final PrivateNotes privateNotes = (PrivateNotes)get(); + showPrivateNotes(privateNotes); + } + }; + + notesWorker.start(); + } + + private void showPrivateNotes(final PrivateNotes privateNotes) { + String text = privateNotes.getNotes(); + + final JLabel titleLabel = new JLabel(Res.getString("button.view.notes")); + titleLabel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.LIGHT_GRAY)); + titleLabel.setFont(new Font("Dialog", Font.BOLD, 13)); + titleLabel.setHorizontalAlignment(JLabel.CENTER); + + + final JTextPane pane = new JTextPane(); + pane.setFont(new Font("Dialog", Font.PLAIN, 12)); + + pane.setOpaque(false); + + final JScrollPane scrollPane = new JScrollPane(pane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setOpaque(false); + scrollPane.getViewport().setOpaque(false); + + pane.setText(text); + final RolloverButton button = new RolloverButton(Res.getString("save"), null); + final RolloverButton cancelButton = new RolloverButton(Res.getString("cancel"), null); + ResourceUtils.resButton(button, Res.getString("button.save")); + ResourceUtils.resButton(cancelButton, Res.getString("button.cancel")); + + final JFrame frame = new JFrame(Res.getString("title.notes")); + + + final JPanel mainPanel = new JPanel(); + + pane.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyChar() == KeyEvent.VK_ESCAPE) { + frame.dispose(); + + // Save it. + String text = pane.getText(); + privateNotes.setNotes(text); + PrivateNotes.savePrivateNotes(privateNotes); + } + } + }); + + mainPanel.setBackground(Color.white); + mainPanel.setLayout(new GridBagLayout()); + frame.setIconImage(SparkManager.getMainWindow().getIconImage()); + frame.getContentPane().add(mainPanel); + + // mainPanel.add(titleLabel, new GridBagConstraints(0, 0, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + + mainPanel.add(scrollPane, new GridBagConstraints(0, 1, 3, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); + mainPanel.add(button, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + mainPanel.add(cancelButton, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + + frame.pack(); + frame.setSize(400, 400); + + + GraphicUtils.centerWindowOnComponent(frame, SparkManager.getMainWindow()); + frame.setVisible(true); + pane.setCaretPosition(0); + + button.addActionListener( actionEvent -> { + frame.dispose(); + + // Save it. + String text1 = pane.getText(); + privateNotes.setNotes( text1 ); + PrivateNotes.savePrivateNotes(privateNotes); + } ); + + cancelButton.addActionListener( actionEvent -> frame.dispose() ); + } + + @Override + public void shutdown() { + } + + @Override + public boolean canShutDown() { + return true; + } + + @Override + public void uninstall() { + } + + public static List getTaskList() { + return taskList; + } + + /** + * Delete task + */ + public static void deleteTask(Task deletedTask) { + List taskList = getTaskList(); + // save Tasks + Tasks tasks = new Tasks(); + for (TaskUI ui : taskList) { + Task nTask = ui.getTask(); + if (nTask != deletedTask) { + tasks.addTask(nTask); + } + } + // update GUI + updateTaskUI(tasks); + } + +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/Task.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/Task.java similarity index 96% rename from src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/Task.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/Task.java index 34e0e265b..46bd9076f 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/Task.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/Task.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +16,6 @@ package org.jivesoftware.sparkimpl.plugin.scratchpad; /** - * */ public class Task { diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/TaskNotification.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/TaskNotification.java new file mode 100644 index 000000000..a0372da3c --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/TaskNotification.java @@ -0,0 +1,134 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.scratchpad; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.component.VerticalFlowLayout; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; + +import javax.swing.*; +import java.awt.*; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.util.TimerTask; + +import static java.time.ZoneId.*; +import static java.time.format.FormatStyle.SHORT; + +/** + * Notification about a Task that has a due date of today. + */ +public class TaskNotification { + private final DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate(SHORT); + + private static final Color COLOR_TASK_NOTIFICATION_GRADIENT = new Color(198, 211, 247); + + + public TaskNotification() { + TimerTask task = new TimerTask() { + @Override + public void run() { + notifyUser(); + } + }; + + long twoHours = (60 * 1000) * 120; + TaskEngine.getInstance().scheduleAtFixedRate(task, (10 * 1000), twoHours); + } + + private void notifyUser() { + + TimerTask newTask = new TimerTask() { + + @Override + public void run() { + EventQueue.invokeLater(() -> { + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); + mainPanel.setBackground(Color.white); + + long now = System.currentTimeMillis(); + Tasks tasks; + try { + tasks = Tasks.getTaskList(); + } catch (Exception ignored) { + return; + } + + final JPanel titlePanel = new JPanel(new BorderLayout()) { + @Override + public void paintComponent(Graphics g) { + Color startColor = Color.white; + Color endColor = COLOR_TASK_NOTIFICATION_GRADIENT; + + Graphics2D g2 = (Graphics2D) g; + + int w = getWidth(); + int h = getHeight(); + + GradientPaint gradient = new GradientPaint(0, 0, startColor, w, h, endColor, true); + g2.setPaint(gradient); + g2.fillRect(0, 0, w, h); + } + + }; + final JLabel taskLabel = new JLabel("Due "); + taskLabel.setFont(taskLabel.getFont().deriveFont(Font.BOLD)); + titlePanel.add(taskLabel, BorderLayout.EAST); + mainPanel.add(titlePanel); + + boolean hasItems = false; + for (Task task : tasks.getTasks()) { + if (task.isCompleted()) { + continue; + } + + long dueDate = task.getDueDate(); + if (dueDate != -1) { + if (now > dueDate) { + final JPanel item = new JPanel(new BorderLayout()); + item.setOpaque(false); + JLabel label = new JLabel(task.getTitle()); + item.add(label, BorderLayout.CENTER); + + String dueDateStr = formatter.format(Instant.ofEpochMilli(task.getDueDate()).atZone(systemDefault())); + JLabel dueItem = new JLabel(dueDateStr); + item.add(dueItem, BorderLayout.EAST); + mainPanel.add(item); + hasItems = true; + } + } + } + + if (hasItems) { + SparkToaster toaster = new SparkToaster(); + toaster.setDisplayTime(30000); + toaster.setToasterHeight(175); + toaster.setToasterWidth(300); + + toaster.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); + JScrollPane pane = new JScrollPane(mainPanel); + pane.getViewport().setBackground(Color.white); + toaster.showToaster(Res.getString("title.task.notification"), pane); + } + }); + } + }; + TaskEngine.getInstance().schedule(newTask, 500); + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/TaskUI.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/TaskUI.java new file mode 100644 index 000000000..5f8427350 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/TaskUI.java @@ -0,0 +1,128 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.scratchpad; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Font; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.font.TextAttribute; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; + +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.jdesktop.swingx.calendar.DateUtils; +import org.jivesoftware.resource.SparkRes; + +/** + * Task item with a checkbox and date + */ +public class TaskUI extends JPanel { + + private final Task task; + private final JCheckBox box; + + public TaskUI(final Task task) { + setLayout(new BorderLayout()); + setOpaque(false); + + this.task = task; + + box = new JCheckBox(); + box.setOpaque(false); + JLabel dueLabel = new JLabel(); + dueLabel.setOpaque(false); + + JPanel p_east = new JPanel(new BorderLayout()); + p_east.setBackground(Color.white); + + JLabel btn_del = new JLabel(SparkRes.getImageIcon(SparkRes.Icon.TASK_DELETE_IMAGE)); + + p_east.add(btn_del, BorderLayout.EAST); + p_east.add(new JLabel(" "), BorderLayout.CENTER); + p_east.add(dueLabel, BorderLayout.WEST); + + add(box, BorderLayout.WEST); + + //add(dueLabel, BorderLayout.EAST); + add(p_east, BorderLayout.EAST); + + long dueDate = task.getDueDate(); + if (dueDate != -1) { + Date d = new Date(dueDate); + String dateShortFormat = ( (SimpleDateFormat) SimpleDateFormat.getDateInstance( SimpleDateFormat.SHORT ) ).toPattern(); + SimpleDateFormat formatter = new SimpleDateFormat( dateShortFormat ); + String theDate = formatter.format(d); + dueLabel.setText(theDate); + } + + int diff = DateUtils.getDaysDiff(dueDate, new Date().getTime()); + if (diff > 0){ + dueLabel.setForeground(Color.red); + } + + box.setText(task.getTitle()); + + updateTitleFont(); + + box.addActionListener(e -> { + task.setCompleted(isSelected()); + updateTitleFont(); + if (ScratchPadPlugin.SHOW_ALL_TASKS) { + setVisible(true); + } + else if (task.isCompleted()) { + setVisible(false); + } + }); + btn_del.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent arg0) { + ScratchPadPlugin.deleteTask(task); + } + }); + } + + public boolean isSelected() { + return box.isSelected(); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void updateTitleFont() { + if (task.isCompleted()) { + Font font = box.getFont(); + Map attribs = font.getAttributes(); + attribs.put(TextAttribute.STRIKETHROUGH, true); + box.setFont(new Font(attribs)); + box.setSelected(true); + } else { + Font font = box.getFont(); + Map Attribs = font.getAttributes(); + Attribs.put(TextAttribute.STRIKETHROUGH, false); + box.setFont(new Font(Attribs)); + box.setSelected(false); + } + } + + public Task getTask() { + return task; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/Tasks.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/Tasks.java new file mode 100644 index 000000000..d7ac13592 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/scratchpad/Tasks.java @@ -0,0 +1,185 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.scratchpad; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.jivesoftware.smack.util.XmlStringBuilder; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jivesoftware.smackx.iqprivate.PrivateDataManager; +import org.jivesoftware.smackx.iqprivate.packet.PrivateData; +import org.jivesoftware.smackx.iqprivate.provider.PrivateDataProvider; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.JxmppContext; + +/** + * Tasks for a TO-DO list + * @author Derek DeMoro + */ +public class Tasks implements PrivateData { + public static final String ELEMENT = "scratchpad"; + public static final String NAMESPACE = "scratchpad:tasks"; + private List tasks = new ArrayList<>(); + private boolean showAll; + + public List getTasks() { + return tasks; + } + + public void setTasks(List tasks) { + this.tasks = tasks; + } + + public void addTask(Task task) { + tasks.add(task); + } + + public boolean isShowAll() { + return showAll; + } + + public void setShowAll(boolean showAll) { + this.showAll = showAll; + } + + @Override + public String getElementName() { + return ELEMENT; + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public XmlStringBuilder toXML() { + XmlStringBuilder buf = new XmlStringBuilder(); + buf.halfOpenElement(ELEMENT).xmlnsAttribute(NAMESPACE).rightAngleBracket(); + buf.halfOpenElement("tasks"); + buf.attribute("showAll", isShowAll()); + buf.rightAngleBracket(); + for (Task task : getTasks()) { + buf.openElement("task"); + buf.optElement("title", task.getTitle()); + buf.optElement("dueDate", task.getDueDate()); + buf.optElement("creationDate", task.getCreatedDate()); + if (task.isCompleted()) { + buf.optElement("completed", "true"); + } + buf.closeElement("task"); + } + buf.closeElement("tasks"); + buf.closeElement(ELEMENT); + return buf; + } + + /** + * The IQ Provider for Tasks + */ + public static class Provider implements PrivateDataProvider { + private final Tasks tasks = new Tasks(); + + public Provider() { + super(); + } + + @Override + public PrivateData parsePrivateData(XmlPullParser parser, JxmppContext jxmppContext) throws XmlPullParserException, IOException { + boolean done = false; + while (!done) { + XmlPullParser.Event eventType = parser.next(); + if (eventType == XmlPullParser.Event.START_ELEMENT && "tasks".equals(parser.getName())) { + String showAll = parser.getAttributeValue("", "showAll"); + tasks.setShowAll(Boolean.parseBoolean(showAll)); + } + + if (eventType == XmlPullParser.Event.START_ELEMENT && "task".equals(parser.getName())) { + tasks.addTask(getTask(parser)); + } else if (eventType == XmlPullParser.Event.END_ELEMENT && ELEMENT.equals(parser.getName())) { + done = true; + } + } + + return tasks; + } + } + + public static Task getTask(XmlPullParser parser) throws XmlPullParserException, IOException { + final Task task = new Task(); + + boolean done = false; + while (!done) { + XmlPullParser.Event eventType = parser.next(); + if (eventType == XmlPullParser.Event.START_ELEMENT && "title".equals(parser.getName())) { + task.setTitle(parser.nextText()); + } + + if (eventType == XmlPullParser.Event.START_ELEMENT && "dueDate".equals(parser.getName())) { + String dueDate = parser.nextText(); + task.setDueDate(Long.parseLong(dueDate)); + } + + if (eventType == XmlPullParser.Event.START_ELEMENT && "creationDate".equals(parser.getName())) { + String creationDate = parser.nextText(); + task.setCreatedDate(Long.parseLong(creationDate)); + } + + if (eventType == XmlPullParser.Event.START_ELEMENT && "completed".equals(parser.getName())) { + String completed = parser.nextText(); + if (ModelUtil.hasLength(completed)) { + task.setCompleted(Boolean.parseBoolean(completed)); + } + } else if (eventType == XmlPullParser.Event.END_ELEMENT && "task".equals(parser.getName())) { + done = true; + } + } + + return task; + } + + + static { + PrivateDataManager.addPrivateDataProvider(ELEMENT, NAMESPACE, new Tasks.Provider()); + } + + public static void saveTasks(Tasks tasks) { + PrivateDataManager manager = SparkManager.getSessionManager().getPersonalDataManager(); + try { + manager.setPrivateData(tasks); + } catch (Exception e) { + Log.error(e); + throw new RuntimeException(e.getMessage()); + } + } + + public static Tasks getTaskList() { + PrivateDataManager manager = SparkManager.getSessionManager().getPersonalDataManager(); + try { + PrivateData privateData = manager.getPrivateData(ELEMENT, NAMESPACE); + return privateData != null ? (Tasks) privateData : new Tasks(); + } catch (Exception e) { + Log.error(e); + throw new RuntimeException(e.getMessage()); + } + } + +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/sparklers/SparklersPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/sparklers/SparklersPlugin.java similarity index 75% rename from src/java/org/jivesoftware/sparkimpl/plugin/sparklers/SparklersPlugin.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/sparklers/SparklersPlugin.java index df066369e..f234f614a 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/sparklers/SparklersPlugin.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/sparklers/SparklersPlugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,26 +19,34 @@ import org.jivesoftware.spark.ui.Sparkler; import org.jivesoftware.spark.ui.SparklerDecorator; +/** + * Allows users set Active Sparklers within a Chat Conversation. + */ public class SparklersPlugin implements Plugin { - public void initialize() { + @Override + public void initialize() { new Sparkler() { - public void decorateMessage(String message, SparklerDecorator decorator) { + @Override + public void decorateMessage(String message, SparklerDecorator decorator) { decorator.setURL("Spark", "http://www.test.com"); } }; } - public void shutdown() { + @Override + public void shutdown() { } - public boolean canShutDown() { + @Override + public boolean canShutDown() { return false; } - public void uninstall() { + @Override + public void uninstall() { } } diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/systray/ChatMessageHandlerImpl.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/systray/ChatMessageHandlerImpl.java similarity index 100% rename from src/java/org/jivesoftware/sparkimpl/plugin/systray/ChatMessageHandlerImpl.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/systray/ChatMessageHandlerImpl.java diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/systray/SysTrayPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/systray/SysTrayPlugin.java new file mode 100644 index 000000000..0883dddfb --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/systray/SysTrayPlugin.java @@ -0,0 +1,469 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.systray; + +import java.awt.MouseInfo; +import java.awt.SystemTray; +import java.awt.TrayIcon; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; + +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.chat2.Chat; +import org.jivesoftware.smack.ConnectionListener; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smackx.chatstates.ChatState; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.NativeHandler; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.Workspace; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.status.CustomStatusItem; +import org.jivesoftware.spark.ui.status.StatusBar; +import org.jivesoftware.spark.ui.status.StatusItem; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; +import org.jivesoftware.sparkimpl.settings.JiveInfo; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jivesoftware.smackx.chatstates.ChatStateListener; +import org.jivesoftware.smackx.chatstates.ChatStateManager; + + +/** + * Handles tray icon operations inside of Spark. + * Use to display incoming chat requests, incoming messages and general notifications. + */ +public class SysTrayPlugin implements Plugin, NativeHandler, ChatStateListener { + private final JPopupMenu popupMenu = new JPopupMenu(); + + private final LocalPreferences pref = SettingsManager.getLocalPreferences(); + private ImageIcon availableIcon; + private ImageIcon dndIcon; + private ImageIcon awayIcon; + private ImageIcon xawayIcon; + private ImageIcon offlineIcon; + private ImageIcon connectingIcon; + private ImageIcon newMessageIcon; + private ImageIcon typingIcon; + private TrayIcon trayIcon; + private boolean newMessage = false; + private Presence presence; + private final ChatMessageHandlerImpl chatMessageHandler = new ChatMessageHandlerImpl(); + + @Override + public boolean canShutDown() { + return true; + } + + @Override + public void initialize() { + if (!SystemTray.isSupported()) { + Log.error("Tray don't supports on this platform."); + return; + } + JMenuItem openMenu = new JMenuItem(Res.getString("menuitem.open")); + JMenuItem minimizeMenu = new JMenuItem(Res.getString("menuitem.hide")); + JMenuItem exitMenu = new JMenuItem(Res.getString("menuitem.exit")); + JMenuItem logoutMenu = new JMenuItem(Res.getString("menuitem.logout.no.status")); + + SystemTray tray = SystemTray.getSystemTray(); + SparkManager.getNativeManager().addNativeHandler(this); + ChatManager.getInstance().addChatMessageHandler(chatMessageHandler); + //XEP-0085 support (replaces the obsolete XEP-0022) + ChatStateManager.getInstance(SparkManager.getConnection()).addChatStateListener(this); + + if (Spark.isLinux()) { + newMessageIcon = SparkRes.getImageIcon(SparkRes.Icon.MESSAGE_NEW_TRAY_LINUX); + typingIcon = SparkRes.getImageIcon(SparkRes.Icon.TYPING_TRAY_LINUX); + } else { + newMessageIcon = SparkRes.getImageIcon(SparkRes.Icon.MESSAGE_NEW_TRAY); + typingIcon = SparkRes.getImageIcon(SparkRes.Icon.TYPING_TRAY); + } + + availableIcon = Default.getImageIcon(Default.TRAY_IMAGE); + if (Spark.isLinux()) { + if (availableIcon == null) { + availableIcon = SparkRes.getImageIcon(SparkRes.Icon.TRAY_IMAGE_LINUX); + } + awayIcon = SparkRes.getImageIcon(SparkRes.Icon.TRAY_AWAY_LINUX); + xawayIcon = SparkRes.getImageIcon(SparkRes.Icon.TRAY_XAWAY_LINUX); + dndIcon = SparkRes.getImageIcon(SparkRes.Icon.TRAY_DND_LINUX); + offlineIcon = SparkRes.getImageIcon(SparkRes.Icon.TRAY_OFFLINE_LINUX); + connectingIcon = SparkRes.getImageIcon(SparkRes.Icon.TRAY_CONNECTING_LINUX); + } else { + if (availableIcon == null) { + availableIcon = SparkRes.getImageIcon(SparkRes.Icon.TRAY_IMAGE); + } + awayIcon = SparkRes.getImageIcon(SparkRes.Icon.TRAY_AWAY); + xawayIcon = SparkRes.getImageIcon(SparkRes.Icon.TRAY_XAWAY); + dndIcon = SparkRes.getImageIcon(SparkRes.Icon.TRAY_DND); + offlineIcon = SparkRes.getImageIcon(SparkRes.Icon.TRAY_OFFLINE); + connectingIcon = SparkRes.getImageIcon(SparkRes.Icon.TRAY_CONNECTING); + } + + popupMenu.add(openMenu); + + openMenu.addActionListener(new AbstractAction() { + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent event) { + SparkManager.getMainWindow().setVisible(true); + SparkManager.getMainWindow().toFront(); + } + + }); + + popupMenu.add(minimizeMenu); + + minimizeMenu.addActionListener(new AbstractAction() { + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent event) { + SparkManager.getMainWindow().setVisible(false); + } + }); + + // See if we should disable the ability to change presence status + if (!Default.getBoolean(Default.DISABLE_PRESENCE_STATUS_CHANGE) && Enterprise.containsFeature(Enterprise.PRESENCE_STATUS_FEATURE)) { + popupMenu.addSeparator(); + addStatusMessages(); + popupMenu.addSeparator(); + } + + // Logout Menu + if (Spark.isWindows()) { + if (!Default.getBoolean(Default.DISABLE_EXIT) && Enterprise.containsFeature(Enterprise.LOGOUT_EXIT_FEATURE)) { + if (!Default.getBoolean(Default.HIDE_SAVE_PASSWORD_AND_AUTO_LOGIN) && pref.getPswdAutologin()) { + logoutMenu.addActionListener(new AbstractAction() { + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + SparkManager.getMainWindow().logout(false); + } + }); + popupMenu.add(logoutMenu); + } + } + } + + // Exit Menu + exitMenu.addActionListener(new AbstractAction() { + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + SparkManager.getMainWindow().shutdown(); + } + }); + + if (!Default.getBoolean(Default.DISABLE_EXIT) && Enterprise.containsFeature(Enterprise.LOGOUT_EXIT_FEATURE)) + popupMenu.add(exitMenu); + + // If connection closed set offline tray image + SparkManager.getConnection().addConnectionListener(new TrayConnectionListener()); + + SparkManager.getSessionManager().addPresenceListener( + presence -> { + setIconByPresence(presence, availableIcon); + }); + + try { + trayIcon = new TrayIcon(availableIcon.getImage(), JiveInfo.getName(), null); + trayIcon.setImageAutoSize(true); + trayIcon.addMouseListener(new TrayMouseListener()); + + tray.add(trayIcon); + } catch (Exception e) { + Log.error("Unable to render tray icon", e); + } + } + + public void addStatusMessages() { + StatusBar statusBar = SparkManager.getWorkspace().getStatusBar(); + for (StatusItem statusItem : statusBar.getStatusList()) { + final AbstractAction action = new AbstractAction() { + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + SparkManager.getSessionManager().changePresence(statusItem.getPresence()); + statusBar.setStatus(statusItem.getText()); + } + }; + action.putValue(Action.NAME, statusItem.getText()); + action.putValue(Action.SMALL_ICON, statusItem.getIcon()); + + boolean hasChildren = false; + for (CustomStatusItem cItem : statusBar.getCustomStatusList()) { + String type = cItem.getType(); + if (type.equals(statusItem.getText())) { + hasChildren = true; + break; + } + } + + if (!hasChildren) { + JMenuItem status = new JMenuItem(action); + popupMenu.add(status); + } else { + final JMenu status = new JMenu(action); + popupMenu.add(status); + + status.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent mouseEvent) { + action.actionPerformed(null); + popupMenu.setVisible(false); + } + }); + + for (CustomStatusItem customItem : statusBar.getCustomStatusList()) { + String type = customItem.getType(); + if (type.equals(statusItem.getText())) { + AbstractAction customAction = new AbstractAction() { + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + Presence oldPresence = statusItem.getPresence(); + Presence presence = StanzaBuilder.buildPresence() + .ofType(oldPresence.getType()) + .setStatus(customItem.getStatus()) + .setPriority(customItem.getPriority()) + .setMode(oldPresence.getMode()) + .build(); + SparkManager.getSessionManager().changePresence(presence); + + statusBar.setStatus(statusItem.getName() + " - " + customItem.getStatus()); + } + }; + customAction.putValue(Action.NAME, customItem.getStatus()); + customAction.putValue(Action.SMALL_ICON, statusItem.getIcon()); + JMenuItem menuItem = new JMenuItem(customAction); + status.add(menuItem); + } + } + + } + } + } + + @Override + public void shutdown() { + if (SystemTray.isSupported()) { + SystemTray tray = SystemTray.getSystemTray(); + tray.remove(trayIcon); + } + ChatManager.getInstance().removeChatMessageHandler(chatMessageHandler); + } + + @Override + public void uninstall() { + ChatManager.getInstance().removeChatMessageHandler(chatMessageHandler); + } + + // Info on new Messages + @Override + public void flashWindow(Window window) { + if (pref.isSystemTrayNotificationEnabled()) { + trayIcon.setImage(newMessageIcon.getImage()); + if (window instanceof JFrame) { + String counteredTitle = getCounteredTitle(((JFrame) window).getTitle(), chatMessageHandler.getUnreadMessages()); + ((JFrame) window).setTitle(counteredTitle); + } + newMessage = true; + } + } + + private String getCounteredTitle(String title, int counter) { + String stringCounter = String.format("[%s] ", counter); + String MESSAGE_COUNTER_REG_EXP = "\\[\\d+\\] "; + String titleWithoutCount = title.replaceFirst(MESSAGE_COUNTER_REG_EXP, ""); + return counter > 0 ? stringCounter + titleWithoutCount : titleWithoutCount; + } + + @Override + public void flashWindowStopWhenFocused(Window window) { + presence = Workspace.getInstance().getStatusBar().getPresence(); + setIconByPresence(presence, availableIcon); + newMessage = false; + chatMessageHandler.clearUnreadMessages(); + } + + @Override + public boolean handleNotification() { + return true; + } + + @Override + public void stopFlashing(Window window) { + presence = Workspace.getInstance().getStatusBar().getPresence(); + setIconByPresence(presence, availableIcon); + newMessage = false; + chatMessageHandler.clearUnreadMessages(); + } + + @Override + public void stateChanged(Chat chat, ChatState state, Message message) { + presence = Workspace.getInstance().getStatusBar().getPresence(); + if (ChatState.composing.equals(state)) { + changeSysTrayIcon(); + } else { + if (!newMessage) { + setIconByPresence(presence, newMessageIcon); + } + } + } + + private void setIconByPresence(Presence presence, ImageIcon newTrayIcon) { + if (presence.getMode() == Presence.Mode.available) { + trayIcon.setImage(newTrayIcon.getImage()); + } else if (presence.getMode() == Presence.Mode.away) { + trayIcon.setImage(awayIcon.getImage()); + } else if (presence.getMode() == Presence.Mode.xa) { + trayIcon.setImage(xawayIcon.getImage()); + } else if (presence.getMode() == Presence.Mode.dnd) { + trayIcon.setImage(dndIcon.getImage()); + } else { + trayIcon.setImage(newTrayIcon.getImage()); + } + } + + private void changeSysTrayIcon() { + if (pref.isTypingNotificationShown()) { + trayIcon.setImage(typingIcon.getImage()); + } + } + + private class TrayMouseListener implements MouseListener { + + @Override + public void mouseClicked(MouseEvent event) { + // if we are using double click on tray icon + if ((!pref.isUsingSingleTrayClick() + && event.getButton() == MouseEvent.BUTTON1 + && event.getClickCount() % 2 == 0) + || + // if we're using single click on tray icon + (pref.isUsingSingleTrayClick() + && event.getButton() == MouseEvent.BUTTON1 + && event.getClickCount() == 1)) { + + // bring the mainwindow to front + if ((SparkManager.getMainWindow().isVisible()) + && (SparkManager.getMainWindow().getState() == java.awt.Frame.NORMAL)) { + SparkManager.getMainWindow().setVisible(false); + } else { + SparkManager.getMainWindow().setVisible(true); + SparkManager.getMainWindow().setState(java.awt.Frame.NORMAL); + SparkManager.getMainWindow().toFront(); + } + + } else if (event.getButton() == MouseEvent.BUTTON1) { + SparkManager.getMainWindow().toFront(); + // SparkManager.getMainWindow().requestFocus(); + } else if (event.getButton() == MouseEvent.BUTTON3) { + if (popupMenu.isVisible()) { + popupMenu.setVisible(false); + } else { + double x = MouseInfo.getPointerInfo().getLocation().getX(); + double y = MouseInfo.getPointerInfo().getLocation().getY(); + + if (Spark.isMac()) { + popupMenu.setLocation((int) x, (int) y); + } else { + popupMenu.setLocation(event.getX(), event.getY()); + } + + popupMenu.setInvoker(popupMenu); + popupMenu.setVisible(true); + } + } + } + + @Override + public void mouseEntered(MouseEvent event) { + + } + + @Override + public void mouseExited(MouseEvent event) { + + } + + @Override + public void mousePressed(MouseEvent event) { + // on Mac I would want the window to show when I left-click the Icon + if (Spark.isMac() && event.getButton() != MouseEvent.BUTTON3) { + SparkManager.getMainWindow().setVisible(false); + SparkManager.getMainWindow().setVisible(true); + SparkManager.getMainWindow().requestFocusInWindow(); + SparkManager.getMainWindow().bringFrameIntoFocus(); + SparkManager.getMainWindow().toFront(); + SparkManager.getMainWindow().requestFocus(); + } + } + + @Override + public void mouseReleased(MouseEvent event) { + + } + + } + + private class TrayConnectionListener implements ConnectionListener { + @Override + public void connected(XMPPConnection xmppConnection) { + trayIcon.setImage(availableIcon.getImage()); + } + + @Override + public void authenticated(XMPPConnection xmppConnection, boolean b) { + trayIcon.setImage(availableIcon.getImage()); + } + + @Override + public void connectionClosed() { + trayIcon.setImage(offlineIcon.getImage()); + } + + @Override + public void connectionClosedOnError(Exception arg0) { + trayIcon.setImage(offlineIcon.getImage()); + } + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscript.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscript.java new file mode 100644 index 000000000..aa2e67e44 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscript.java @@ -0,0 +1,142 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.transcripts; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * A single chat transcript mapped to one JID. + * + * @author Derek DeMoro + */ +public class ChatTranscript { + + private List messages = new ArrayList<>(); + + /** + * Add a HistoryMessage to users chat transcript. + * + * @param entry the HistoryMessage to add. + */ + public void addHistoryMessage(HistoryMessage entry) { + messages.add(entry); + } + + /** + * Returns all messages. + * + * @return all messages. + */ + public List getMessages() { + return messages; + } + + /** + * Returns a specified number of messages. + * + * @param number the number of messages to return. + * @return the specified number of messages, or all messages if number is greater than the current amount. + */ + public Collection getNumberOfEntries(int number) { + int listSize = messages.size(); + + if (messages.size() <= number) { + return messages; + } + else { + int start = listSize - number; + return messages.subList(start, listSize); + } + } + + /** + * Returns messages that included search keywords. + * + * @param text search keywords.If the search keywords is null, return all message. + * @return the messages that included search keywords. + */ + public List getMessage(String text) { + if (text == null || "".equals(text)) { + return messages; + } else { + List searchResult = new ArrayList<>(); + Set lines = new HashSet<>(); + HistoryMessage previous = null; + int iter = -1; + for(HistoryMessage message : messages) { + iter++; + if (message.getBody().toLowerCase().contains(text.toLowerCase())) { + if (previous != null && !lines.contains(iter - 1)) { + searchResult.add(previous); + lines.add(iter - 1); + } + if (!lines.contains(iter)) { + searchResult.add(message); + lines.add(iter); + } + if (iter + 1 <= messages.size() - 1 + && !lines.contains(iter + 1)) { + searchResult.add(messages.get(iter + 1)); + lines.add(iter + 1); + } + } + previous = message; + } + return searchResult; + } + } + + /** + * Clears the Message History if its not needed anymore + */ + public void release() { + messages.clear(); + } + + /** + * Set the new List for the chat transcript + * @param newList The list with the history messages + */ + public void setList(List newList){ + this.messages = newList; + } + + /** + * Return the size of the message list + * @return The size of the message list + */ + public int size(){ + return this.messages.size(); + } + + /** + * Return the HistoryMessage by the given index + * @param i the index of the history message + * @return the history message, null if out of bounds + */ + public HistoryMessage getMessage(int i){ + HistoryMessage result = null; + if ((i > -1) && i < messages.size()){ + result = messages.get(i); + } + return result; + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscriptPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscriptPlugin.java new file mode 100644 index 000000000..16cafcf09 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscriptPlugin.java @@ -0,0 +1,304 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.transcripts; + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.List; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +import org.jivesoftware.MainWindowListener; +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.ConnectionListener; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; + +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.ContextMenuListener; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomButton; +import org.jivesoftware.spark.ui.ChatRoomClosingListener; +import org.jivesoftware.spark.ui.ChatRoomListener; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.spark.ui.ContactList; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.util.UIComponentRegistry; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.*; + +/** + * The ChatTranscriptPlugin is responsible for transcript handling within Spark. + * It registers the listeners for transcript persistence. + * + * @author Derek DeMoro + */ +public class ChatTranscriptPlugin implements ChatRoomListener { + + private final SimpleDateFormat notificationDateFormatter; + private final SimpleDateFormat messageDateFormatter; + private final HashMap lastMessage = new HashMap<>(); + private JDialog Frame; + private HistoryTranscript transcript = null; + private final LocalPreferences pref = SettingsManager.getLocalPreferences(); + + public ChatTranscriptPlugin() { + SparkManager.getChatManager().addChatRoomListener(this); + String dateFormat = ((SimpleDateFormat) SimpleDateFormat.getDateInstance(SimpleDateFormat.FULL)).toPattern(); + notificationDateFormatter = new SimpleDateFormat(dateFormat); + String timeFormat = "HH:mm:ss"; + messageDateFormatter = new SimpleDateFormat(timeFormat); + + final ContactList contactList = SparkManager.getWorkspace().getContactList(); + + final Action viewHistoryAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + ContactItem item = contactList.getSelectedUsers().iterator().next(); + final BareJid jid = item.getJid(); + transcript = new HistoryTranscript(notificationDateFormatter, messageDateFormatter); + transcript.showHistory(jid); + //showHistory(jid); + } + }; + + viewHistoryAction.putValue(Action.NAME, Res.getString("menuitem.view.contact.history")); + viewHistoryAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.HISTORY_16x16)); + + final Action showStatusMessageAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + ContactItem item = contactList.getSelectedUsers().iterator().next(); + showStatusMessage(item); + } + }; + + showStatusMessageAction.putValue(Action.NAME, Res.getString("menuitem.show.contact.statusmessage")); + + contactList.addContextMenuListener(new ContextMenuListener() { + @Override + public void poppingUp(Object object, JPopupMenu popup) { + if (object instanceof ContactItem) { + if (!Default.getBoolean(Default.HISTORY_DISABLED) && Enterprise.containsFeature(Enterprise.HISTORY_TRANSCRIPTS_FEATURE)) { + popup.add(viewHistoryAction); + } + popup.add(showStatusMessageAction); + } + } + + @Override + public void poppingDown(JPopupMenu popup) { + } + + @Override + public boolean handleDefaultAction(MouseEvent e) { + return false; + } + }); + + SparkManager.getMainWindow().addMainWindowListener(new MainWindowListener() { + @Override + public void shutdown() { + persistConversations(); + } + + @Override + public void mainWindowActivated() { + } + + @Override + public void mainWindowDeactivated() { + } + }); + + SparkManager.getConnection().addConnectionListener(new ConnectionListener() { + @Override + public void connectionClosedOnError(Exception e) { + persistConversations(); + } + }); + } + + public void persistConversations() { + for (ChatRoom room : SparkManager.getChatManager().getChatContainer().getChatRooms()) { + if (room instanceof ChatRoomImpl) { + ChatRoomImpl roomImpl = (ChatRoomImpl) room; + if (roomImpl.isActive()) { + persistChatRoom(roomImpl); + } + } + } + } + + public boolean canShutDown() { + return true; + } + + @Override + public void chatRoomOpened(final ChatRoom room) { + if (!pref.isChatHistoryEnabled()) { + return; + } + final EntityBareJid jid = room.getBareJid(); + File transcriptFile = ChatTranscripts.getTranscriptFile(jid); + if (!transcriptFile.exists()) { + return; + } + if (room instanceof ChatRoomImpl) { + new ChatRoomDecorator(room); + } + } + + @Override + public void chatRoomClosed(final ChatRoom room) { + // Persist only agent to agent chat rooms. + if (room.getChatType() == Message.Type.chat) { + persistChatRoom(room); + } + } + + public void persistChatRoom(final ChatRoom room) { + if (!pref.isChatHistoryEnabled()) { + return; + } + // If this is a MUC then don't persist this chat. + if (room.getChatType() == Message.Type.groupchat) { + return; + } + + EntityJid jid = room.getBareJid(); + //If private chat in MUC then use EntityJid + if (((ChatRoomImpl) room).isPrivateChat()) { + jid = room.getJid(); + } + + final List transcripts = room.getTranscripts(); + int count = 0; + Message lastKnownMessage = lastMessage.get(jid); + if (lastKnownMessage != null) { + count = transcripts.indexOf(lastKnownMessage) + 1; + } + if (count == transcripts.size()) { + return; + } + // Build transcript from messages after the last known message + ChatTranscript transcript = new ChatTranscript(); + for (int j = count; j < transcripts.size(); j++) { + Message message = transcripts.get(j); + HistoryMessage history = new HistoryMessage(); + history.setTo(message.getTo()); + history.setFrom(message.getFrom()); + history.setBody(message.getBody()); + final JivePropertiesExtension extension = message.getExtension(JivePropertiesExtension.class); + Date date = null; + if (extension != null) { + date = (Date) extension.getProperty("date"); + } + history.setDate(date == null ? new Date() : date); + transcript.addHistoryMessage(history); + } + Message newLastKnownMessage = transcripts.get(transcripts.size() - 1); + lastMessage.put(jid, newLastKnownMessage); + ChatTranscripts.appendToTranscript(jid, transcript); + } + + private void showStatusMessage(ContactItem item) { + Frame = new JDialog(); + Frame.setTitle(item.getDisplayName() + " - Status"); + JPanel pane = new JPanel(); + JTextArea textArea = new JTextArea(5, 30); + JButton btn_close = new JButton(Res.getString("button.close")); + + btn_close.addActionListener(e -> Frame.setVisible(false)); + + textArea.setLineWrap(true); + textArea.setWrapStyleWord(true); + + pane.add(new JScrollPane(textArea)); + Frame.setLayout(new BorderLayout()); + Frame.add(pane, BorderLayout.CENTER); + Frame.add(btn_close, BorderLayout.SOUTH); + + textArea.setEditable(false); + textArea.setText(item.getStatus()); + + Frame.setLocationRelativeTo(SparkManager.getMainWindow()); + Frame.setBounds(Frame.getX() - 175, Frame.getY() - 75, 350, 150); + Frame.setSize(350, 150); + Frame.setResizable(false); + Frame.setVisible(true); + } + + private class ChatRoomDecorator implements ActionListener, ChatRoomClosingListener { + private ChatRoom chatRoom; + private ChatRoomButton chatHistoryButton; + + public ChatRoomDecorator(ChatRoom chatRoom) { + this.chatRoom = chatRoom; + chatRoom.addClosingListener(this); + + // Add History Button + if (!pref.isChatHistoryEnabled()) { + return; + } + chatHistoryButton = UIComponentRegistry.getButtonFactory().createChatTranscriptButton(); + + if (!Default.getBoolean(Default.HISTORY_DISABLED) && Enterprise.containsFeature(Enterprise.HISTORY_TRANSCRIPTS_FEATURE)) { + chatRoom.addChatRoomButton(chatHistoryButton); + } + + chatHistoryButton.setToolTipText(Res.getString("tooltip.view.history")); + chatHistoryButton.addActionListener(this); + } + + + @Override + public void closing() { + if (pref.isChatHistoryEnabled()) { + chatHistoryButton.removeActionListener(this); + } + chatRoom.removeClosingListener(this); + chatRoom = null; + chatHistoryButton = null; + } + + @Override + public void actionPerformed(ActionEvent e) { + ChatRoomImpl roomImpl = (ChatRoomImpl) chatRoom; + transcript = new HistoryTranscript(notificationDateFormatter, messageDateFormatter); + transcript.showHistory(roomImpl.getParticipantJID()); + } + } + +} + diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscripts.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscripts.java new file mode 100644 index 000000000..3d95546a5 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscripts.java @@ -0,0 +1,275 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.transcripts; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.smack.xml.SmackXmlParser; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.util.StringUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.RandomAccessFile; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; + + +/** + * A Utility class that manages the Chat Transcripts within Spark. + * + * @author Derek DeMoro + */ +public final class ChatTranscripts { + + /** + * Default Date Formatter * + */ + private static final DateFormat FORMATTER; + + static { + FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S z"); + } + + private ChatTranscripts() { + + } + + /** + * Appends the given ChatTranscript to the transcript file associated with a JID. + * + * @param jid the jid of the user. + * @param transcript the ChatTranscript. + */ + public static void appendToTranscript(Jid jid, ChatTranscript transcript) { + final File transcriptFile = getTranscriptFile(jid); + + if (!Default.getBoolean(Default.HISTORY_DISABLED) && Enterprise.containsFeature(Enterprise.HISTORY_TRANSCRIPTS_FEATURE)) { + // Write Full Transcript, appending the messages. + writeToFile(transcriptFile, transcript.getMessages(), true); + + // Write to current history File + final File currentHistoryFile = getCurrentHistoryFile(jid); + ChatTranscript tempTranscript = getCurrentChatTranscript(jid); + for (HistoryMessage message : transcript.getMessages()) { + tempTranscript.addHistoryMessage(message); + } + int max = SettingsManager.getLocalPreferences().getMaxCurrentHistorySize(); + writeToFile(currentHistoryFile, tempTranscript.getNumberOfEntries(max), false); + } + } + + private static void writeToFile(File transcriptFile, Collection messages, boolean append) { + final StringBuilder builder = new StringBuilder(); + + final String one = " "; + final String two = " "; + final String three = " "; + + // Handle new transcript file. + if (!transcriptFile.exists() || !append) { + builder.append("\n"); + builder.append(one+"\n"); + } + + for (HistoryMessage m : messages) { + builder.append(two+"\n"); + builder.append(three+"").append(m.getTo()).append("\n"); + builder.append(three+"").append(m.getFrom()).append("\n"); + builder.append(three+"").append(StringUtils.escapeForXML(m.getBody())).append("\n"); + + String dateString = FORMATTER.format(m.getDate()); + builder.append(three+"").append(dateString).append("\n"); + builder.append(two+"\n"); + } + + if (!transcriptFile.exists() || !append) { + builder.append(one+"\n"); + builder.append(""); + } + + + if (!transcriptFile.exists() || !append) { + // Write out new File + try { + transcriptFile.getParentFile().mkdirs(); + Files.write(transcriptFile.toPath(), builder.toString().getBytes(StandardCharsets.UTF_8)); + } + catch (IOException e) { + Log.error(e); + } + return; + } + + // Append to File + try { + final RandomAccessFile raf = new RandomAccessFile(transcriptFile, "rw"); + + // We want to append near the end of the document as the last + // child in the transcript. + final String endTag = " \n"; + + String line = raf.readLine(); + if(line.contains("")) + { + // replace the old one with the new one + line = line.replace("",endTag); + raf.write(line.getBytes(StandardCharsets.UTF_8)); + } + + builder.append(endTag); + + raf.seek(transcriptFile.length() - endTag.length()); + + // Append to the end + raf.write(builder.toString().getBytes(StandardCharsets.UTF_8)); + raf.close(); + } + catch (IOException e) { + Log.error(e); + } + } + + /** + * Retrieve the current chat history. + * + * @param jid the jid of the user whos history you wish to retrieve. + * @return the ChatTranscript (default = last 20 messages max). + */ + public static ChatTranscript getCurrentChatTranscript(Jid jid) { + return getTranscript(getCurrentHistoryFile(jid)); + } + + /** + * Retrieve the full chat history. + * + * @param jid the jid of the the user whos history you wish to retrieve. + * @return the ChatTranscript. + */ + public static ChatTranscript getChatTranscript(Jid jid) { + return getTranscript(getTranscriptFile(jid)); + } + + /** + * Reads in the transcript file using the Xml Pull Parser. + * + * @param transcriptFile the transcript file to read. + * @return the ChatTranscript. + */ + public static ChatTranscript getTranscript(File transcriptFile) { + final ChatTranscript transcript = new ChatTranscript(); + if (!transcriptFile.exists()) { + return transcript; + } + + try { + BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(transcriptFile), StandardCharsets.UTF_8)); + final XmlPullParser parser = SmackXmlParser.newXmlParser(in); + boolean done = false; + while (!done) { + XmlPullParser.Event eventType = parser.next(); + if (eventType == XmlPullParser.Event.START_ELEMENT && "message".equals(parser.getName())) { + transcript.addHistoryMessage(getHistoryMessage(parser)); + } + else if (eventType == XmlPullParser.Event.END_ELEMENT && "transcript".equals(parser.getName())) { + done = true; + } + } + in.close(); + } + catch (Exception e) { + e.printStackTrace(); + } + + + return transcript; + } + + /** + * Returns the settings file. + * + * @param jid the + * @return the settings file. + */ + public static File getTranscriptFile(Jid jid) { + return new File(SparkManager.getUserDirectory(), "transcripts/" + jid.asUnescapedString() + ".xml"); + } + + /** + * Returns the current transcript (default = 20 messages) for a particular jid. + * + * @param jid the jid of the user. + * @return the current transcript file. + */ + public static File getCurrentHistoryFile(Jid jid) { + return new File(SparkManager.getUserDirectory(), "transcripts/" + jid.asUnescapedString() + "_current.xml"); + } + + private static HistoryMessage getHistoryMessage(XmlPullParser parser) throws Exception { + HistoryMessage message = new HistoryMessage(); + + // Check for nickname + boolean done = false; + while (!done) { + XmlPullParser.Event eventType = parser.next(); + if (eventType == XmlPullParser.Event.START_ELEMENT && "to".equals(parser.getName())) { + String jidString = parser.nextText(); + Jid jid = JidCreate.from(jidString); + message.setTo(jid); + } + else if (eventType == XmlPullParser.Event.START_ELEMENT && "from".equals(parser.getName())) { + String jidString = parser.nextText(); + Jid jid = JidCreate.from(jidString); + message.setFrom(jid); + } + else if (eventType == XmlPullParser.Event.START_ELEMENT && "body".equals(parser.getName())) { + message.setBody(StringUtils.unescapeFromXML(parser.nextText())); + } + else if (eventType == XmlPullParser.Event.START_ELEMENT && "date".equals(parser.getName())) { + Date d; + try { + d = FORMATTER.parse(parser.nextText()); + } + catch (ParseException e) { + d = new Date(); + } + message.setDate(d); + } + else if (eventType == XmlPullParser.Event.END_ELEMENT && "message".equals(parser.getName())) { + done = true; + } + } + + + return message; + } + + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/transcripts/HistoryMessage.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/transcripts/HistoryMessage.java new file mode 100644 index 000000000..ec0604e33 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/transcripts/HistoryMessage.java @@ -0,0 +1,60 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.transcripts; + +import java.util.Date; + +import org.jxmpp.jid.Jid; + +public class HistoryMessage { + + private Jid to; + private Jid from; + private String body; + private Date date; + + public Jid getTo() { + return to; + } + + public void setTo(Jid to) { + this.to = to; + } + + public Jid getFrom() { + return from; + } + + public void setFrom(Jid from) { + this.from = from; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/transcripts/HistoryTranscript.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/transcripts/HistoryTranscript.java new file mode 100644 index 000000000..849ba3269 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/transcripts/HistoryTranscript.java @@ -0,0 +1,780 @@ +package org.jivesoftware.sparkimpl.plugin.transcripts; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.swing.*; +import javax.swing.text.*; +import javax.swing.text.html.*; + +import org.jdesktop.swingx.calendar.DateUtils; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.BackgroundPanel; +import org.jivesoftware.spark.ui.VCardPanel; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.util.XmppStringUtils; + +/** + * This class represents the history transcript + * + * @author tim.jentz + * + */ +public class HistoryTranscript extends SwingWorker { + + private final Semaphore token = new Semaphore(1); + private int pageIndex = 0; + private int maxPages = 0; + private final String period_oneDay = "message.search.period.day.one"; + private final String period_oneWeek = "message.search.period.week.one"; + private final String period_oneMonth = "message.search.period.month.one"; + private final String period_oneYear = "message.search.period.year.one"; + private final String period_noPeriod = "message.search.period.none"; + private String searchPeriod = ""; + private final List periods = new ArrayList<>(); + private final timerTranscript transcriptTask = new timerTranscript(); + private final JLabel pageCounter = new JLabel("0 / 0"); + private final JButton pageLeft = new JButton("<"); + private final JButton pageRight = new JButton(">"); + private BareJid jid = null; + private final SimpleDateFormat notificationDateFormatter; + private final SimpleDateFormat messageDateFormatter; + private final AtomicBoolean isInitialized = new AtomicBoolean(false); + + private final LocalPreferences pref = SettingsManager.getLocalPreferences(); + private final JComboBox periodChooser = new JComboBox<>(); + private final JPanel filterPanel = new JPanel(); + private final JPanel mainPanel = new BackgroundPanel(); + private final JPanel searchPanel = new BackgroundPanel(); + private final JPanel navigatorPanel = new JPanel(); + private final JPanel overTheTopPanel = new BackgroundPanel(); + private final JPanel controlPanel = new BackgroundPanel(); + private VCardPanel vacardPanel = null; + private final JTextField searchField = new JTextField(25); + private final JEditorPane window = new JEditorPane(); + private final JScrollPane pane = new JScrollPane(window); + private final JFrame frame = new JFrame(Res.getString("title.history.for", jid)); + private final StringBuilder builder = new StringBuilder(); + private List searchFilteredList = new ArrayList<>(); + private List dateFilteredUnfilteredList = new ArrayList<>(); + private final AtomicBoolean isHistoryLoaded = new AtomicBoolean(false); + private final String SEPARATOR = System.getProperty("line.separator"); + private final DefaultHighlighter.DefaultHighlightPainter highlighter = new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW); + private boolean focusFlag = false; + private String searchQuery = Res.getString("message.search.for.history"); + /** + * The currently selected Font Size to use. + */ + private final int fontSize = SettingsManager.getLocalPreferences().getChatRoomFontSize(); + + /** + * Open the Transcript with the given formatter. + * + * @param notificationDateFormatter the formatter for the notifications + * @param messageDateFormatter the formatter for dates + */ + public HistoryTranscript(SimpleDateFormat notificationDateFormatter, SimpleDateFormat messageDateFormatter) { + this.notificationDateFormatter = notificationDateFormatter; + this.messageDateFormatter = messageDateFormatter; + } + + /** + * Show the History for the given Contact. + * + * @param jid the JID of the current transcript + */ + public void showHistory(BareJid jid) { + vacardPanel = new VCardPanel(jid); + frame.setTitle(Res.getString("title.history.for", jid)); + this.jid = jid; + this.start(); + } + + /** + * Check if the period was changed an apply the filter to the message + * history + * + * @param change the choosen value for the period + */ + private synchronized void handlePeriodChange(String change) { + try { + token.acquire(); + if (!Objects.equals(change, searchPeriod) && isInitialized.get()) { + searchPeriod = change; + pref.setSearchPeriod(searchPeriod); + isHistoryLoaded.set(false); + TaskEngine.getInstance().schedule(transcriptTask, 10); + } + token.release(); + } catch (InterruptedException e) { + Log.error(e); + e.printStackTrace(); + } + } + + /** + * Navigate one page left through the history. Do nothing if at index 0. + */ + private synchronized void pageLeft() { + try { + AtomicBoolean changed = new AtomicBoolean(); + changed.set(false); + token.acquire(); + if (pageIndex > 1) { + pageIndex--; + changed.set(true); + } + token.release(); + if (changed.get()) { + display(); + } + } catch (InterruptedException e) { + Log.error(e); + e.printStackTrace(); + } + } + + /** + * Navigate one page right through the history. Do nothing if at maximum + * index. + */ + private synchronized void pageRight() { + try { + AtomicBoolean changed = new AtomicBoolean(); + changed.set(false); + token.acquire(); + if (pageIndex < maxPages) { + pageIndex++; + changed.set(true); + } + token.release(); + if (changed.get()) { + display(); + } + } catch (InterruptedException e) { + Log.error(e); + e.printStackTrace(); + } + } + + /** + * Builds html string with the stored messages + * + * @return String containing the messages as html + */ + public final String buildString(List messages) { + StringBuilder builder = new StringBuilder(); + final String personalNickname = SparkManager.getUserManager().getNickname(); + Date lastPost = null; + Jid broadcastnick = null; + boolean initialized = false; + + for (HistoryMessage message : messages) { + String color = "blue"; + + Jid from = message.getFrom(); + String nickname = SparkManager.getUserManager() + .getUserNicknameFromJID(message.getFrom().asBareJid()); + String body = org.jivesoftware.spark.util.StringUtils + .escapeHTMLTags(message.getBody()); + if (nickname.equals(message.getFrom().toString()) || nickname.equals(message.getFrom().asBareJid().toString())) { + BareJid otherJID = message + .getFrom().asBareJid(); + EntityBareJid myJID = SparkManager.getSessionManager() + .getUserBareAddress(); + + if (otherJID.equals(myJID)) { + nickname = personalNickname; + } else { + nickname = XmppStringUtils.parseLocalpart(nickname); + broadcastnick = message.getFrom(); + } + } + + if (!from.asBareJid().equals( + SparkManager.getSessionManager().getUserBareAddress())) { + color = "red"; + } + + long lastPostTime = lastPost != null ? lastPost.getTime() : 0; + + int diff; + if (DateUtils.getDaysDiff(lastPostTime, message.getDate() + .getTime()) != 0) { + diff = DateUtils.getDaysDiff(lastPostTime, message + .getDate().getTime()); + } else { + diff = DateUtils.getDayOfWeek(lastPostTime) + - DateUtils.getDayOfWeek(message.getDate() + .getTime()); + } + + if (diff != 0) { + if (initialized) { + builder.append("
      "); + } + builder.append( + "") + .append(notificationDateFormatter.format(message + .getDate())) + .append(""); + initialized = true; + } + + String value = "(" + messageDateFormatter.format(message.getDate()) + ") "; + + builder.append(""); + builder.append(""); + builder.append(value); + if (broadcastnick == null) { + builder.append(nickname).append(": "); + } else { + builder.append(broadcastnick).append(": "); + } + builder.append(""); + builder.append(""); + builder.append(body); + builder.append(""); + builder.append("
      "); + + lastPost = message.getDate(); + broadcastnick = null; + } + builder.append(""); + + return builder.toString(); + } + + /** + * If a new page is loaded or the search is changed, displays the current + * page again. + */ + private synchronized void display() { + try { + token.acquire(); + if ((searchFilteredList.size() > 0) && (pageIndex <= searchFilteredList.size())) { + builder.append(""); + builder.append(buildString(searchFilteredList.get(pageIndex - 1).getMessages())); + } else { + // Handle no history + builder.replace(0, builder.length(), ""); + builder.append("") + .append(Res.getString("message.no.history.found")) + .append(""); + } + Font font = new Font(window.getFont().getFontName(), Font.PLAIN, fontSize); + window.setFont(font); + window.setText(builder.toString()); + + // highlighting searched text + try { + String text = searchQuery; + Document doc = window.getDocument(); + String line; + if (text.length() > 0 && focusFlag) { + String str = doc.getText(1, doc.getLength()); + BufferedReader buf = new BufferedReader(new StringReader(str)); + int globalPos = 1; + while ((line = buf.readLine()) != null) { + Matcher matcherTime = Pattern + .compile("\\(\\d\\d:\\d\\d:\\d\\d\\)\\s[a-zA-Z0-9]+:\\s") + .matcher(line); + if (matcherTime.find()) { + for (int i = matcherTime.end(); i + text.length() < line.length() + 1; i++) { + String match = line.substring(i, i + text.length()); + if (text.equalsIgnoreCase(match)) { + window.getHighlighter().addHighlight(globalPos + i, + globalPos + i + text.length(), highlighter); + } + } + } + globalPos = globalPos + line.length() + 1; + } + } + } catch (BadLocationException | IOException ex) { + Log.error(ex); + ex.printStackTrace(); + } + + builder.replace(0, builder.length(), ""); + if (window.getText().length() > 0) { + window.setCaretPosition(0); + } + pageCounter.setText(pageIndex + " / " + maxPages); + token.release(); + } catch (InterruptedException e) { + Log.error(e); + e.printStackTrace(); + } + } + + /** + * This class will run every time a search has startet on the messages, + * saved in the transcript or the time period has been changed + * + * @author tim.jentz + * + */ + private class timerTranscript extends TimerTask { + + /** + * This function check if the date of the new message is in the same + * period as the date of the old message. + * + * At the moment, there are three different time periods: - one week - + * three weeks - one month + * + * @param newDate the date gained from new message + * @param oldDate the date gained from new message + * @return true if both dates in the same period, false if not + */ + private boolean dateInPeriod(Date newDate, Date oldDate) { + boolean result = false; + Calendar cal = Calendar.getInstance(); + cal.setTime(newDate); + long yearNew = Math.round((double) cal.get(Calendar.YEAR)); + long monthNew = Math.round((double) cal.get(Calendar.MONTH)); + long dayNew = Math.round((double) cal.get(Calendar.DAY_OF_MONTH)); + long weekNew = Math.round((double) cal.get(Calendar.WEEK_OF_MONTH)); + + cal.setTime(oldDate); + long yearOld = Math.round((double) cal.get(Calendar.YEAR)); + long monthOld = Math.round((double) cal.get(Calendar.MONTH)); + long dayOld = Math.round((double) cal.get(Calendar.DAY_OF_MONTH)); + long weekOld = Math.round((double) cal.get(Calendar.WEEK_OF_MONTH)); + + switch (searchPeriod) { + case period_oneDay: + if((dayOld == dayNew) && (monthOld == monthNew) && (yearOld == yearNew)){ + result = true; + } + break; + case period_oneWeek: + if((weekOld == weekNew) && (monthOld == monthNew) && (yearOld == yearNew)){ + result = true; + } + break; + case period_oneMonth: + // for one month, we only check if the month and the year is equal + if ((monthOld == monthNew) && (yearOld == yearNew)) { + result = true; + } + break; + case period_oneYear: + // for one year, we only check if the year is the same + if ((yearOld == yearNew)) { + result = true; + } + break; + case period_noPeriod: + // for unfiltered list, we return true all the time + result = true; + break; + } + return result; + } + + /** + * Sort the messages by the choosen period of time + * + * @param transcript the transcript to sort + * @return List of transcript sorted by period. each transcript contains + * the messages of the giving period + */ + private List getDateSortedTranscript(ChatTranscript transcript) { + List tmpList = new ArrayList<>(); + + if (transcript.size() > 0) { + ChatTranscript sortedTranscript = new ChatTranscript(); + HistoryMessage msg; + + // retrieve the first message + Date oldDate; + int iteratorValue; + int startValue; + int endValue; + + boolean sortDateAsc = pref.getChatHistoryAscending(); + + if (sortDateAsc) { + oldDate = transcript.getMessage(0).getDate(); + iteratorValue = 1; + startValue = 0; + endValue = transcript.size(); + } else { + oldDate = transcript.getMessage(transcript.size() - 1).getDate(); + iteratorValue = -1; + startValue = transcript.size() - 1; + endValue = -1; + } + + Calendar cal = Calendar.getInstance(); + cal.setTime(oldDate); + Date newDate; + + ChatTranscript history; + boolean handled = true; + + for (int i = startValue; i != endValue; i += iteratorValue) { + msg = transcript.getMessage(i); + // get the date of the current message + newDate = msg.getDate(); + + if (!dateInPeriod(newDate, oldDate)) { + history = new ChatTranscript(); + history.setList(sortedTranscript.getMessages()); + + // add the messages to the list + if (history.getMessages().size() > 0) { + tmpList.add(history); + } + + // we have handled this entry + oldDate = msg.getDate(); + sortedTranscript = new ChatTranscript(); + } + sortedTranscript.addHistoryMessage(msg); + // the latest entries not yet saved to the list + handled = false; + } + + // if the latest entries where not yet handled, do it now + if (!handled) { + history = new ChatTranscript(); + history.setList(sortedTranscript.getMessages()); + if (history.getMessages().size() > 0) { + tmpList.add(history); + } + } + } + + return tmpList; + } + + @Override + public void run() { + if (!isHistoryLoaded.get()) { + // if we have to load the history + dateFilteredUnfilteredList = getDateSortedTranscript((ChatTranscript) get()); + + try { + token.acquire(); + // confirm that the history is loaded + isHistoryLoaded.set(true); + token.release(); + } catch (InterruptedException e) { + Log.error(e); + e.printStackTrace(); + } + } + + String searchString = searchField.getText(); + // if we searching for a string or not + if (Res.getString("message.search.for.history").equals( + searchField.getText()) + || searchField.getText().equals("")) { + searchString = null; + } + + List tmpList = new ArrayList<>(); + ChatTranscript tmpTranscript; + + for (ChatTranscript chatTranscript : dateFilteredUnfilteredList) { + tmpTranscript = new ChatTranscript(); + tmpTranscript.setList(chatTranscript.getMessage(searchString)); + if (tmpTranscript.size() > 0) { + tmpList.add(tmpTranscript); + } + } + + try { + token.acquire(); + searchFilteredList = tmpList; + pageIndex = (searchFilteredList.size() > 0) ? 1 : 0; + maxPages = searchFilteredList.size(); + token.release(); + } catch (InterruptedException e) { + Log.error(e); + e.printStackTrace(); + } + display(); + } + } + + /** + * Check if the given String represents a valid period + * + * @param p the period, that have to be checked + * @return true if valid, false if invalid + */ + private int getPeriodIndex(String p) { + int result = 0; + for (int i = 0; i < periods.size(); i++) { + if (p.equals(periods.get(i))) { + result = i; + break; + } + } + return result; + } + + /** + * Set the layout settings + */ + @Override + public void finished() { + pageLeft.addActionListener(arg0 -> pageLeft()); + pageRight.addActionListener(arg0 -> pageRight()); + periodChooser.addActionListener(e -> handlePeriodChange(periods.get(periodChooser.getSelectedIndex()))); + + // add search text input + searchPanel.setLayout(new GridBagLayout()); + navigatorPanel.setLayout(new GridBagLayout()); + controlPanel.setLayout(new BorderLayout()); + filterPanel.setLayout(new GridBagLayout()); + mainPanel.setLayout(new BorderLayout()); + + // the list of periods + periods.add(period_oneDay); + periods.add(period_oneWeek); + periods.add(period_oneMonth); + periods.add(period_oneYear); + periods.add(period_noPeriod); + + // get the default preferences for the search period + int index = getPeriodIndex(pref.getSearchPeriod(periods.get(0))); + + for (String period : periods) { + periodChooser.addItem(Res.getString(period)); + + } + + periodChooser.setToolTipText(Res.getString("message.search.page.timeperiod")); + pageCounter.setToolTipText(Res.getString("message.search.page.counter")); + pageRight.setToolTipText(Res.getString("message.search.page.right")); + pageLeft.setToolTipText(Res.getString("message.search.page.left")); + searchField.setText(Res.getString("message.search.for.history")); + searchField.setToolTipText(Res.getString("message.search.for.history")); + searchField.setForeground((Color) UIManager + .get("TextField.lightforeground")); + + searchPanel.add(vacardPanel, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, + GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, + new Insets(1, 5, 1, 1), 0, 0)); + + filterPanel.add(periodChooser, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, + GridBagConstraints.WEST, GridBagConstraints.NONE, + new Insets(1, 5, 1, 1), 0, 0)); + + filterPanel.add(searchField, new GridBagConstraints(2, 0, + GridBagConstraints.REMAINDER, 1, 1.0, 1.0, + GridBagConstraints.EAST, GridBagConstraints.NONE, + new Insets(1, 1, 6, 1), 0, 0)); + + navigatorPanel.add(pageLeft, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, + GridBagConstraints.WEST, GridBagConstraints.NONE, + new Insets(1, 5, 1, 1), 0, 0)); + navigatorPanel.add(pageCounter, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0, + GridBagConstraints.CENTER, GridBagConstraints.NONE, + new Insets(1, 5, 1, 1), 0, 0)); + navigatorPanel.add(pageRight, new GridBagConstraints(2, 0, + GridBagConstraints.REMAINDER, 1, 1.0, 1.0, + GridBagConstraints.EAST, GridBagConstraints.NONE, + new Insets(1, 1, 6, 1), 0, 0)); + + controlPanel.add(filterPanel, BorderLayout.NORTH); + controlPanel.add(navigatorPanel, BorderLayout.SOUTH); + + overTheTopPanel.setLayout(new BorderLayout()); + overTheTopPanel.add(searchPanel, BorderLayout.NORTH); + overTheTopPanel.add(controlPanel, BorderLayout.SOUTH); + + mainPanel.add(overTheTopPanel, BorderLayout.NORTH); + + window.setEditorKit(new HTMLEditorKit() { + @Override + public ViewFactory getViewFactory() { + return new HTMLFactory() { + @Override + public View create(Element e) { + View v = super.create(e); + if (v instanceof InlineView) { + return new InlineView(e) { + @Override + public int getBreakWeight(int axis, float pos, float len) { + if (axis == View.X_AXIS) { + checkPainter(); + int p0 = getStartOffset(); + int p1 = getGlyphPainter().getBoundedPosition(this, p0, pos, len); + if (p1 == p0) { + // can't even fit a single character + return View.BadBreakWeight; + } + try { + //if the view contains line break char return forced break + if (getDocument().getText(p0, p1 - p0).contains(SEPARATOR)) { + return View.ForcedBreakWeight; + } + } catch (BadLocationException ex) { + //should never happen + } + + } + return super.getBreakWeight(axis, pos, len); + } + + @Override + public View breakView(int axis, int p0, float pos, float len) { + if (axis == View.X_AXIS) { + checkPainter(); + int p1 = getGlyphPainter().getBoundedPosition(this, p0, pos, len); + try { + //if the view contains line break char break the view + int index = getDocument().getText(p0, p1 - p0).indexOf(SEPARATOR); + if (index >= 0) { + return createFragment(p0, p0 + index + 1); + } + } catch (BadLocationException ex) { + //should never happen + } + + } + return super.breakView(axis, p0, pos, len); + } + }; + } else if (v instanceof javax.swing.text.html.ParagraphView) { + return new javax.swing.text.html.ParagraphView(e) { + @Override + protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) { + if (r == null) { + r = new SizeRequirements(); + } + float pref = layoutPool.getPreferredSpan(axis); + float min = layoutPool.getMinimumSpan(axis); + r.minimum = (int) min; + r.preferred = Math.max(r.minimum, (int) pref); + r.maximum = Integer.MAX_VALUE; + r.alignment = 0.5f; + return r; + } + + }; + } + return v; + } + }; + } + }); + window.setBackground(Color.white); + pane.getVerticalScrollBar().setBlockIncrement(200); + pane.getVerticalScrollBar().setUnitIncrement(20); + + mainPanel.add(pane, BorderLayout.CENTER); + + frame.setIconImage(SparkRes.getImageIcon(SparkRes.Icon.HISTORY_16x16) + .getImage()); + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(mainPanel, BorderLayout.CENTER); + frame.pack(); + frame.setSize(600, 400); + window.setCaretPosition(0); + window.requestFocus(); + GraphicUtils.centerWindowOnScreen(frame); + frame.setVisible(true); + window.setEditable(false); + + searchField.addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) { + } + + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyChar() == KeyEvent.VK_ENTER) { + searchQuery = searchField.getText(); + TaskEngine.getInstance().schedule(transcriptTask, 10); + searchField.requestFocus(); + focusFlag = true; + } + } + + @Override + public void keyPressed(KeyEvent e) { + + } + }); + searchField.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + if (searchField.getText().equals(Res.getString("message.search.for.history"))) { + searchField.setText(""); + } + searchField.setForeground((Color) UIManager + .get("TextField.foreground")); + } + + @Override + public void focusLost(FocusEvent e) { + searchField.setForeground((Color) UIManager + .get("TextField.lightforeground")); + if (searchField.getText().length() <= 1) { + searchField.setText(Res.getString("message.search.for.history")); + } + } + }); + + // after initializing the period, we can load the history + isInitialized.set(true); + periodChooser.setSelectedIndex(index); + + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + window.setText(""); + } + + @Override + public void windowClosed(WindowEvent e) { + frame.removeWindowListener(this); + frame.dispose(); + transcriptTask.cancel(); + searchPanel.remove(vacardPanel); + } + }); + } + + @Override + public Object construct() { + return ChatTranscripts.getChatTranscript(jid); + } + +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/viewer/PluginRenderer.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/viewer/PluginRenderer.java similarity index 78% rename from src/java/org/jivesoftware/sparkimpl/plugin/viewer/PluginRenderer.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/viewer/PluginRenderer.java index 83d509fb5..7731976ad 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/viewer/PluginRenderer.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/viewer/PluginRenderer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,10 +17,7 @@ import org.jivesoftware.resource.SparkRes; -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.JLabel; -import javax.swing.JTable; +import javax.swing.*; import javax.swing.border.Border; import javax.swing.table.TableCellRenderer; @@ -37,9 +30,9 @@ public class PluginRenderer extends JLabel implements TableCellRenderer { private static final long serialVersionUID = -4013718080014723319L; - Border unselectedBorder; - Border selectedBorder; - boolean isBordered = true; + private Border unselectedBorder; + private Border selectedBorder; + private final boolean isBordered = true; /** * PluginRenderer @@ -48,9 +41,10 @@ public PluginRenderer() { setOpaque(true); } - public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { + @Override + public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { - final Icon icon = SparkRes.getImageIcon(SparkRes.PLUGIN_IMAGE); + final Icon icon = SparkRes.getImageIcon(SparkRes.Icon.PLUGIN_IMAGE); setIcon(icon); if (isSelected) { @@ -60,9 +54,6 @@ public Component getTableCellRendererComponent(JTable table, Object color, boole else { setForeground(Color.black); setBackground(Color.white); - if (row % 2 == 0) { - //setBackground( new Color( 156, 207, 255 ) ); - } } if (isBordered) { diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/plugin/viewer/PluginViewer.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/viewer/PluginViewer.java new file mode 100644 index 000000000..6a0734501 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/viewer/PluginViewer.java @@ -0,0 +1,731 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.viewer; + +import org.apache.commons.lang3.StringUtils; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.Node; +import org.dom4j.io.SAXReader; +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.PluginManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.MessageDialog; +import org.jivesoftware.spark.component.VerticalFlowLayout; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.plugin.PublicPlugin; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.URLFileSystem; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettingsManager; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; +import org.jivesoftware.sparkimpl.settings.JiveInfo; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jivesoftware.sparkimpl.updater.AcceptAllCertsConnectionManager; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * Plugin Viewer Plugin. + * Class to handle the viewing of installed and downloadable Plugins. + * Allows users to download, install, and uninstall 3rd party plugins. + * + * @author Derek DeMoro + */ +public class PluginViewer extends JPanel implements Plugin +{ + private JTabbedPane tabbedPane; + private boolean loaded = false; + private final String retrieveListURL = Default.getString( Default.PLUGIN_REPOSITORY ); + private JProgressBar progressBar; + private JPanel installedPanel; + private JPanel availablePanel; + private JPanel deactivatedPanel; + private final LocalPreferences _prefs; + private List _deactivatedPlugins; + + public PluginViewer() + { + _prefs = SettingsManager.getLocalPreferences(); + _deactivatedPlugins = _prefs.getDeactivatedPlugins(); + + EventQueue.invokeLater( () -> + { + tabbedPane = new JTabbedPane(); + installedPanel = new JPanel(); + availablePanel = new JPanel(); + deactivatedPanel = new JPanel(); + setLayout( new GridBagLayout() ); + + installedPanel.setLayout( new VerticalFlowLayout( + VerticalFlowLayout.TOP, 0, 0, true, false ) ); + installedPanel.setBackground( Color.white ); + + availablePanel.setLayout( new VerticalFlowLayout( + VerticalFlowLayout.TOP, 0, 0, true, false ) ); + availablePanel.setBackground( Color.white ); + + + // Add TabbedPane + add( tabbedPane, new GridBagConstraints( 0, 1, 2, 1, 1.0, 1.0, + GridBagConstraints.WEST, GridBagConstraints.BOTH, + new Insets( 5, 5, 5, 5 ), 0, 0 ) ); + + // Add Tabs + tabbedPane.addTab( Res.getString( "tab.installed.plugins" ), + new JScrollPane( installedPanel ) ); + if ( !Default.getBoolean( Default.INSTALL_PLUGINS_DISABLED ) ) + { + tabbedPane.addTab( Res.getString( "tab.available.plugins" ), + new JScrollPane( availablePanel ) ); + } + + loadInstalledPlugins(); + loadDeactivatedPlugins(); + + tabbedPane.addChangeListener( changeEvent -> + { + if ( tabbedPane.getSelectedComponent().equals( + availablePanel.getParent().getParent() ) ) + { + loadAvailablePlugins(); + loaded = true; + } + } ); + } ); + } + + private void loadInstalledPlugins() + { + PluginManager pluginManager = PluginManager.getInstance(); + List plugins = pluginManager.getPublicPlugins(); + for ( PublicPlugin plugin : plugins ) + { + final SparkPlugUI ui = new SparkPlugUI( plugin ); + ui.useLocalIcon(); + installedPanel.add( ui ); + addSparkPlugUIListener( ui ); + } + } + + /** + * Initializes the Deactivated Plugins Tab + */ + private void loadDeactivatedPlugins() + { + deactivatedPanel.setLayout( new VerticalFlowLayout( + VerticalFlowLayout.TOP, 0, 0, true, false ) ); + if ( !Default.getBoolean( Default.UNINSTALL_PLUGINS_DISABLED) ) + { + tabbedPane.addTab( Res.getString( "tab.deactivated.plugins" ), new JScrollPane( deactivatedPanel ) ); + } + for ( final String s : _deactivatedPlugins ) + { + PublicPlugin plg = new PublicPlugin(); + plg.setName( s ); + final SparkPlugUI ui = new SparkPlugUI( plg ); + ui.useLocalIcon(); + deactivatedPanel.add( ui ); + addDeactivatedListener( ui ); + } + } + + + @Override + public void initialize() + { + // Add Plugins Menu + JMenuBar menuBar = SparkManager.getMainWindow().getJMenuBar(); + + // Get last menu which is help + JMenu sparkMenu = menuBar.getMenu( 0 ); + + JMenuItem viewPluginsMenu = new JMenuItem(); + + Action viewAction = new AbstractAction() + { + private static final long serialVersionUID = 6518407602062984752L; + + @Override + public void actionPerformed( ActionEvent e ) + { + invokeViewer(); + } + }; + + viewAction.putValue( Action.NAME, Res.getString( "menuitem.plugins" ) ); + viewAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.PLUGIN_IMAGE)); + viewPluginsMenu.setAction( viewAction ); + + // See if we should disable the "Plugins" menu item + if ( !Default.getBoolean( Default.DISABLE_PLUGINS_MENU_ITEM ) && Enterprise.containsFeature( Enterprise.PLUGINS_MENU_FEATURE ) ) + { + sparkMenu.insert( viewPluginsMenu, 2 ); + } + } + + private boolean uninstall( final PublicPlugin plugin ) + { + UIManager.put( "OptionPane.yesButtonText", Res.getString( "yes" ) ); + UIManager.put( "OptionPane.noButtonText", Res.getString( "no" ) ); + UIManager.put( "OptionPane.okButtonText", Res.getString( "ok" ) ); + + int ok = JOptionPane.showConfirmDialog( installedPanel, Res.getString( "message.prompt.plugin.uninstall", plugin.getName() ), Res.getString( "title.confirmation" ), JOptionPane.YES_NO_OPTION ); + if ( ok == JOptionPane.YES_OPTION ) + { + + // DOENST DELETE ANYMORE, Plugin will be added to a 'do-not-load-list' + // Delete main jar. + // File pluginDir = plugin.getPluginDir(); + // File pluginJAR = new File(plugin.getPluginDir().getParentFile(), + // pluginDir.getName() + ".jar"); + // File mainpluginJar = new + // File(Spark.getBinDirectory().getParent()+"/plugins/"+pluginJAR.getName()); + // pluginJAR.delete(); + // mainpluginJar.delete(); + + List deact = new ArrayList<>(_prefs.getDeactivatedPlugins()); + deact.add( plugin.getName() ); + _deactivatedPlugins = deact; + _prefs.setDeactivatedPlugins( _deactivatedPlugins ); + + final SparkPlugUI ui = new SparkPlugUI( plugin ); + deactivatedPanel.add( ui ); + addDeactivatedListener( ui ); + + JOptionPane.showMessageDialog( this, Res.getString( "message.restart.spark.changes" ), Res.getString( "title.reminder" ), JOptionPane.INFORMATION_MESSAGE ); + PluginManager.getInstance().removePublicPlugin( plugin ); + return true; + } + + return false; + } + + private void invokeViewer() + { + final JDialog dialog = MessageDialog.createComponent( Res.getString( "title.plugins" ), "", null, new PluginViewer(), SparkManager.getMainWindow(), false ); + + final Rectangle bounds = LayoutSettingsManager.getLayoutSettings().getPluginViewerBounds(); + if ( bounds == null || bounds.width <= 0 || bounds.height <= 0 ) + { + // Use default settings. + dialog.setSize( 600, 600 ); + dialog.setLocationRelativeTo( SparkManager.getMainWindow() ); + } + else + { + dialog.setBounds( bounds ); + } + + dialog.addComponentListener( new ComponentAdapter() + { + @Override + public void componentResized( ComponentEvent e ) + { + LayoutSettingsManager.getLayoutSettings().setPluginViewerBounds( dialog.getBounds() ); + } + + @Override + public void componentMoved( ComponentEvent e ) + { + LayoutSettingsManager.getLayoutSettings().setPluginViewerBounds( dialog.getBounds() ); + } + } ); + + dialog.setVisible(true); + dialog.toFront(); + dialog.requestFocus(); + } + + @Override + public void shutdown() + { + + } + + @Override + public boolean canShutDown() + { + return false; + } + + private void loadAvailablePlugins() + { + availablePanel.removeAll(); + availablePanel.invalidate(); + availablePanel.validate(); + availablePanel.repaint(); + + JLabel label = new JLabel( Res.getString( "message.loading.please.wait" ) ); + availablePanel.add( label ); + + + SwingWorker worker = new SwingWorker() + { + Collection pluginList = null; + + @Override + public Object construct() + { + final HttpGet request = new HttpGet(retrieveListURL); + try (final CloseableHttpClient httpClient = + HttpClients.custom().useSystemProperties() + .setConnectionManager(AcceptAllCertsConnectionManager.getInstance()) + .build() + ) { + return httpClient.execute(request, response -> { + if (response.getCode() != 200) { + return null; + } + final HttpEntity entity = response.getEntity(); + pluginList = getPluginList( entity.getContent() ); + EntityUtils.consume(entity); + return "ok"; + }); + } catch (Exception e) { + Log.error(e); + return e.getMessage(); + } + } + + @Override + public void finished() + { + final PluginManager pluginManager = PluginManager.getInstance(); + if ( pluginList == null ) + { + availablePanel.removeAll(); + availablePanel.invalidate(); + availablePanel.validate(); + availablePanel.repaint(); + + UIManager.put( "OptionPane.okButtonText", Res.getString( "ok" ) ); + JOptionPane.showMessageDialog( availablePanel, Res.getString( "message.plugins.not.available" ), Res.getString( "title.error" ), JOptionPane.ERROR_MESSAGE ); + return; + } + Iterator plugs = pluginList.iterator(); + availablePanel.removeAll(); + + while ( plugs.hasNext() ) + { + PublicPlugin plugin = plugs.next(); + if ( !pluginManager.isInstalled( plugin ) ) + { + SparkPlugUI ui = new SparkPlugUI( plugin ); + availablePanel.add( ui ); + addSparkPlugUIListener( ui ); + } + } + + availablePanel.invalidate(); + availablePanel.validate(); + availablePanel.repaint(); + } + }; + + worker.start(); + } + + private void downloadPlugin( final PublicPlugin plugin ) + { + if (StringUtils.isEmpty(plugin.getDownloadURL())) { + Log.warning( "Unable to download plugin " + plugin.getName() + " due to missing download URL."); + return; + } + final HttpGet request = new HttpGet(plugin.getDownloadURL()); + try (final CloseableHttpClient httpClient = + HttpClients.custom().useSystemProperties() + .setConnectionManager(AcceptAllCertsConnectionManager.getInstance()) + .build() + ) { + httpClient.execute(request, response -> { + if (response.getCode() != 200) { + return null; + } + + final HttpEntity entity = response.getEntity(); + + progressBar = new JProgressBar( 0, (int) entity.getContentLength()); + + final JFrame frame = new JFrame( Res.getString( "message.downloading", plugin.getName() ) ); + + frame.setIconImage(SparkRes.getImageIcon(SparkRes.Icon.SMALL_MESSAGE_IMAGE).getImage()); + + try + { + Thread.sleep( 2000 ); + InputStream stream = entity.getContent(); + + URL url = new URL( plugin.getDownloadURL() ); + String name1 = URLFileSystem.getFileName( url ); + String directoryName = URLFileSystem.getName( url ); + + File pluginDownload = new File( PluginManager.PLUGINS_DIRECTORY, name1 ); + + FileOutputStream out = new FileOutputStream( pluginDownload ); + copy( stream, out ); + out.close(); + + frame.dispose(); + + // Remove SparkPlugUI + // Clear all selections + Component[] comps = availablePanel.getComponents(); + for ( Component comp : comps ) + { + if ( comp instanceof SparkPlugUI ) + { + SparkPlugUI sparkPlug = (SparkPlugUI) comp; + if ( sparkPlug.getPlugin().getDownloadURL().equals( plugin.getDownloadURL() ) ) + { + availablePanel.remove( sparkPlug ); + + _deactivatedPlugins.remove( sparkPlug.getPlugin().getName() ); + _prefs.setDeactivatedPlugins( _deactivatedPlugins ); + + PluginManager.getInstance().addPlugin( sparkPlug.getPlugin() ); + + sparkPlug.showOperationButton(); + installedPanel.add( sparkPlug ); + sparkPlug.getPlugin().setPluginDir( new File( PluginManager.PLUGINS_DIRECTORY, directoryName ) ); + installedPanel.invalidate(); + installedPanel.repaint(); + availablePanel.invalidate(); + availablePanel.invalidate(); + availablePanel.validate(); + availablePanel.repaint(); + } + } + } + } + catch ( Exception ex ) + { + // Nothing to do + Log.error(ex); + } + + frame.getContentPane().setLayout( new GridBagLayout() ); + frame.getContentPane().add( new JLabel( Res.getString( "message.downloading.spark.plug" ) ), new GridBagConstraints( 0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets( 5, 5, 5, 5 ), 0, 0 ) ); + frame.getContentPane().add( progressBar, new GridBagConstraints( 0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets( 5, 5, 5, 5 ), 0, 0 ) ); + frame.pack(); + frame.setSize( 400, 100 ); + GraphicUtils.centerWindowOnComponent( frame, this ); + + + frame.setVisible( true ); + + return null; + }); + } catch (Exception e) { + Log.error( e ); + } + } + + + public Collection getPluginList( InputStream response ) + { + final List pluginList = new ArrayList<>(); + SAXReader saxReader = SAXReader.createDefault(); + Document pluginXML; + + try + { + pluginXML = saxReader.read( response ); + } + catch ( DocumentException e ) + { + Log.error( e ); + return Collections.emptyList(); + } + + String sparkVersion = JiveInfo.getVersion(); + List plugins = pluginXML.selectNodes( "/plugins/plugin" ); + for ( Node plugin1 : plugins ) + { + try + { + Element plugin = (Element) plugin1; + + String name = plugin.selectSingleNode("name").getText(); + String minSparkVersion = plugin.selectSingleNode( "minSparkVersion" ).getText(); + if ( !isGreaterOrEqual( sparkVersion, minSparkVersion ) ) + { + Log.error( "Unable to load plugin " + name + " due to min version incompatibility." ); + continue; + } + + String clazz = plugin.selectSingleNode("class").getText(); + PublicPlugin publicPlugin = new PublicPlugin(); + publicPlugin.setPluginClass( clazz ); + publicPlugin.setName( name ); + + try + { + String version = plugin.selectSingleNode( "version" ).getText(); + publicPlugin.setVersion( version ); + + String author = plugin.selectSingleNode( "author" ).getText(); + publicPlugin.setAuthor( author ); + + + Node emailNode = plugin.selectSingleNode( "email" ); + if ( emailNode != null ) + { + publicPlugin.setEmail( emailNode.getText() ); + } + + Node descriptionNode = plugin.selectSingleNode( "description" ); + if ( descriptionNode != null ) + { + publicPlugin.setDescription( descriptionNode.getText() ); + } + + Node homePageNode = plugin.selectSingleNode( "homePage" ); + if ( homePageNode != null ) + { + publicPlugin.setHomePage( homePageNode.getText() ); + } + + Node downloadNode = plugin.selectSingleNode( "downloadURL" ); + if ( downloadNode != null ) + { + String downloadURL = downloadNode.getText(); + publicPlugin.setDownloadURL( downloadURL ); + } + + Node changeLogNode = plugin.selectSingleNode( "changeLog" ); + if ( changeLogNode != null ) + { + publicPlugin.setChangeLogURL( changeLogNode.getText() ); + } + + Node readMeNode = plugin.selectSingleNode( "readme" ); + if ( readMeNode != null ) + { + publicPlugin.setReadMeURL( readMeNode.getText() ); + } + + Node smallIcon = plugin.selectSingleNode( "smallIcon" ); + if ( smallIcon != null ) + { + publicPlugin.setSmallIconAvailable( true ); + } + + Node largeIcon = plugin.selectSingleNode( "largeIcon" ); + if ( largeIcon != null ) + { + publicPlugin.setLargeIconAvailable( true ); + } + + } + catch ( Exception e ) + { + Log.error( "Error retrieving PluginInformation from xml.", e ); + } + pluginList.add( publicPlugin ); + } + catch ( Exception ex ) + { + Log.error(ex); + } + } + return pluginList; + } + + /** + * Common code for copy routines. By convention, the streams are + * closed in the same method in which they were opened. Thus, + * this method does not close the streams when the copying is done. + * + * @param in Stream to copy from. + * @param out Stream to copy to. + */ + private void copy( final InputStream in, final OutputStream out ) + { + int read = 0; + while ( true ) + { + try + { + try + { + Thread.sleep( 10 ); + } + catch ( InterruptedException e ) + { + Log.error( e ); + } + final byte[] buffer = new byte[ 4096 ]; + + int bytesRead = in.read( buffer ); + if ( bytesRead < 0 ) + { + break; + } + out.write( buffer, 0, bytesRead ); + read += bytesRead; + final int readprogr = read; + EventQueue.invokeLater( () -> progressBar.setValue( readprogr ) ); + } + catch ( IOException e ) + { + Log.error( e ); + } + } + } + + + private void addSparkPlugUIListener( final SparkPlugUI ui ) + { + ui.addMouseListener( new MouseAdapter() + { + @Override + public void mouseClicked( MouseEvent mouseEvent ) + { + // Clear all selections + Component[] comps = installedPanel.getComponents(); + for ( Component comp : comps ) + { + if ( comp instanceof SparkPlugUI ) + { + SparkPlugUI sparkPlug = (SparkPlugUI) comp; + sparkPlug.setSelected( false ); + } + } + + // Clear all selections + comps = availablePanel.getComponents(); + for ( Component comp : comps ) + { + if ( comp instanceof SparkPlugUI ) + { + SparkPlugUI sparkPlug = (SparkPlugUI) comp; + sparkPlug.setSelected( false ); + } + } + + ui.setSelected( true ); + + final PluginManager pluginManager = PluginManager.getInstance(); + ui.getInstallButton().addMouseListener( new MouseAdapter() + { + + @Override + public void mouseClicked( MouseEvent e ) + { + + boolean isInstalled = pluginManager.isInstalled( ui.getPlugin() ); + if ( isInstalled ) + { + boolean uninstalled = uninstall( ui.getPlugin() ); + if ( uninstalled ) + { + installedPanel.remove( ui ); + installedPanel.invalidate(); + installedPanel.repaint(); + installedPanel.revalidate(); + } + } + else + { + downloadPlugin( ui.getPlugin() ); + } + } + } ); + } + } ); + } + + /** + * Adds the MouseClick Listener to the PluginPreview
      + * Adds the MouseClick Listener to the InstallButton + * @param ui + */ + private void addDeactivatedListener( final SparkPlugUI ui ) + { + + ui.addMouseListener( new MouseAdapter() + { + @Override + public void mouseClicked( MouseEvent e ) + { + for ( Component c : deactivatedPanel.getComponents() ) + { + if ( c instanceof SparkPlugUI ) + { + ( (SparkPlugUI) c ).setSelected( false ); + } + } + ui.setSelected( true ); + } + } ); + + ui.getInstallButton().addActionListener(e -> { + deactivatedPanel.remove(ui); + + List deact = new ArrayList<>(_deactivatedPlugins); + deact.remove(ui.getPlugin().getName()); + _deactivatedPlugins = deact; + _prefs.setDeactivatedPlugins(_deactivatedPlugins); + + deactivatedPanel.repaint(); + deactivatedPanel.revalidate(); + JOptionPane.showMessageDialog( this, Res.getString( "message.restart.spark.changes" ), Res.getString( "title.reminder" ), JOptionPane.INFORMATION_MESSAGE ); + }); + } + + @Override + public void uninstall() + { + // Do nothing. + } + + /** + * Returns true if the first version number is greater than the second. + * + * @param firstVersion the first version number. + * @param secondVersion the second version number. + * @return returns true if the first version is greater than the second. + */ + public boolean isGreaterOrEqual( String firstVersion, String secondVersion ) + { + return firstVersion.compareTo( secondVersion ) >= 0; + } + + public boolean isLoaded() + { + return loaded; + } +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/viewer/SparkPlugUI.java b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/viewer/SparkPlugUI.java similarity index 92% rename from src/java/org/jivesoftware/sparkimpl/plugin/viewer/SparkPlugUI.java rename to core/src/main/java/org/jivesoftware/sparkimpl/plugin/viewer/SparkPlugUI.java index a5173980c..fc04a078f 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/viewer/SparkPlugUI.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/plugin/viewer/SparkPlugUI.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,12 +25,7 @@ import java.net.MalformedURLException; import java.net.URL; -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; +import javax.swing.*; import org.jivesoftware.resource.Default; import org.jivesoftware.resource.Res; @@ -49,9 +40,9 @@ public class SparkPlugUI extends JPanel { private static final long serialVersionUID = -4206533328807591854L; - private PublicPlugin _plugin; + private final PublicPlugin _plugin; private final JButton installButton = new JButton(); - private JLabel imageIcon = new JLabel(); + private final JLabel imageIcon = new JLabel(); public SparkPlugUI(PublicPlugin plugin) { _plugin = plugin; @@ -63,7 +54,7 @@ public SparkPlugUI(PublicPlugin plugin) { JLabel versionLabel = new JLabel(); JLabel descriptionLabel = new JLabel(); - imageIcon.setIcon(SparkRes.getImageIcon(SparkRes.PLUGIN_IMAGE)); + imageIcon.setIcon(SparkRes.getImageIcon(SparkRes.Icon.PLUGIN_IMAGE)); add(imageIcon, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); @@ -86,8 +77,8 @@ public SparkPlugUI(PublicPlugin plugin) { if (_plugin.getChangeLog()!=null && _plugin.getReadMeURL() != null) { - RolloverButton changeLogButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.CHANGELOG_IMAGE)); - RolloverButton readMeButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.README_IMAGE)); + RolloverButton changeLogButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.Icon.CHANGELOG_IMAGE)); + RolloverButton readMeButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.Icon.README_IMAGE)); changeLogButton.addActionListener( e -> { @@ -129,10 +120,10 @@ public SparkPlugUI(PublicPlugin plugin) { public void showOperationButton() { final PluginManager pluginManager = PluginManager.getInstance(); if (!pluginManager.isInstalled(_plugin)) { - installButton.setIcon(SparkRes.getImageIcon(SparkRes.SMALL_ADD_IMAGE)); + installButton.setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_ADD_IMAGE)); } else { - installButton.setIcon(SparkRes.getImageIcon(SparkRes.SMALL_DELETE)); + installButton.setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_DELETE)); } installButton.setVisible(true); } @@ -142,7 +133,7 @@ public void setSelected(boolean isSelected) { setBackground(new Color(234, 230, 212)); showOperationButton(); setBorder(BorderFactory.createEtchedBorder()); - if (Default.getBoolean(Default.DEINSTALL_PLUGINS_DISABLED)) { + if (Default.getBoolean(Default.UNINSTALL_PLUGINS_DISABLED)) { installButton.setVisible(false); } } diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/preference/PreferenceDialog.java b/core/src/main/java/org/jivesoftware/sparkimpl/preference/PreferenceDialog.java new file mode 100644 index 000000000..8587c8dfc --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/preference/PreferenceDialog.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.sparkimpl.preference; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettingsManager; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +public class PreferenceDialog implements PropertyChangeListener +{ + private JDialog preferenceDialog; + private JOptionPane pane = null; + private PreferencesPanel prefPanel; + + public void invoke( JFrame parentFrame, PreferencesPanel contentPane ) + { + this.prefPanel = contentPane; + + // Construct main panel w/ layout. + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout( new BorderLayout() ); + + // Construct Dialog + preferenceDialog = new JDialog( parentFrame, + Res.getString( "title.preferences" ), + false ); + + preferenceDialog.setMinimumSize( new Dimension( 600, 600 ) ); + + + JButton btn_apply = new JButton( Res.getString( "apply" ) ); + JButton btn_save = new JButton( Res.getString( "save" ) ); + JButton btn_close = new JButton( Res.getString( "close" ) ); + + btn_close.addActionListener( e -> + { + preferenceDialog.setVisible( false ); + preferenceDialog.dispose(); + } ); + + btn_save.addActionListener( e -> + { + boolean okToClose = prefPanel.closing(); + if ( okToClose ) + { + preferenceDialog.setVisible( false ); + preferenceDialog.dispose(); + } + else + { + pane.setValue( JOptionPane.UNINITIALIZED_VALUE ); + } + } ); + + btn_apply.addActionListener( e -> + { + boolean okToClose = prefPanel.closing(); + if ( !okToClose ) + { + pane.setValue( JOptionPane.UNINITIALIZED_VALUE ); + } + } ); + + Object[] options = { btn_apply, btn_save, btn_close }; + pane = new JOptionPane( contentPane, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[ 0 ] ); + mainPanel.add( pane, BorderLayout.CENTER ); + preferenceDialog.setContentPane( mainPanel ); + + preferenceDialog.pack(); + final Rectangle preferencesBounds = LayoutSettingsManager.getLayoutSettings().getPreferencesBounds(); + if ( preferencesBounds == null || preferencesBounds.width <= 0 || preferencesBounds.height <= 0 ) + { + // Use default settings. + preferenceDialog.setSize( 750, 550 ); + preferenceDialog.setLocationRelativeTo( SparkManager.getMainWindow() ); + } + else + { + preferenceDialog.setBounds( preferencesBounds ); + } + + pane.addPropertyChangeListener( this ); + + preferenceDialog.setVisible( true ); + preferenceDialog.toFront(); + + preferenceDialog.addComponentListener( new ComponentAdapter() + { + @Override + public void componentResized( ComponentEvent e ) + { + LayoutSettingsManager.getLayoutSettings().setPreferencesBounds( preferenceDialog.getBounds() ); + } + + @Override + public void componentMoved( ComponentEvent e ) + { + LayoutSettingsManager.getLayoutSettings().setPreferencesBounds( preferenceDialog.getBounds() ); + } + } ); + } + + @Override + public void propertyChange( PropertyChangeEvent e ) + { + if ( pane.getValue() instanceof Integer ) + { + pane.removePropertyChangeListener( this ); + preferenceDialog.dispose(); + } + } + + public JDialog getDialog() + { + return preferenceDialog; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/preference/PreferenceUI.java b/core/src/main/java/org/jivesoftware/sparkimpl/preference/PreferenceUI.java new file mode 100644 index 000000000..96ef44f3a --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/preference/PreferenceUI.java @@ -0,0 +1,70 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.sparkimpl.preference; + +import org.jivesoftware.spark.preference.Preference; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.log.Log; + +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JLabel; + +import java.awt.event.MouseEvent; + +public class PreferenceUI extends JLabel { + private static final long serialVersionUID = 1094181037849878301L; + private final Preference preference; + + public PreferenceUI(Preference preference) { + this.preference = preference; + String listName = ""; + String toolTip = ""; + Icon icon = null; + try { + listName = preference.getListName(); + toolTip = GraphicUtils.createToolTip(preference.getTooltip()); + icon = preference.getIcon(); + } catch (Exception e) { + Log.error(e); + } + this.setText(listName); + this.setToolTipText(toolTip); + this.setIcon(icon); + } + + + public void mouseEntered(MouseEvent e) { + if (this.isEnabled()) { + this.invalidate(); + this.repaint(); + } + } + + + public void decorate() { + this.setOpaque(true); + + this.setVerticalTextPosition(JButton.CENTER); + this.setHorizontalTextPosition(JButton.LEADING); + } + + public Preference getPreference() { + return preference; + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/preference/PreferencesPanel.java b/core/src/main/java/org/jivesoftware/sparkimpl/preference/PreferencesPanel.java new file mode 100644 index 000000000..29295ca08 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/preference/PreferencesPanel.java @@ -0,0 +1,193 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.sparkimpl.preference; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.util.Objects; + +import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.UIManager; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.component.TitlePanel; +import org.jivesoftware.spark.component.renderer.JLabelIconRenderer; +import org.jivesoftware.spark.preference.Preference; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +public class PreferencesPanel extends JPanel implements ListSelectionListener { + + private static final long serialVersionUID = 1520420979038154046L; + /** + * flowpanel is the right panel, where the plugin specific UI is displayed + */ + private final JPanel flowPanel = new JPanel(new BorderLayout()); + private final DefaultListModel listModel = new DefaultListModel<>(); + private final JList list = new JList<>(listModel); + private Preference currentPreference; + + /** + *

      Constructor - PreferencesPanel

      + * This is an option to select the transmitted preference by code + * If the given preference is null or not contained in the preference-list, + * the first index of the list will be selected. + * + * @param preferences the preference list + * @param displayPref the preference you want to select + */ + public PreferencesPanel (Iterable preferences, Preference displayPref){ + this(preferences); + if ( displayPref != null || listModel.getSize() == 1){ + // iterate through all preference-ui items + for (int i = 0; i < listModel.size(); i++){ + PreferenceUI p = listModel.get( i ); + // check if the namespace is the namespace we search for + if ( Objects.equals( p.getPreference().getNamespace(), displayPref.getNamespace() ) ){ + // if we've got our target, we can select this item and stop the search + list.setSelectedIndex( i ); + break; + } + } + // if we got a valid target, we trigger the selection changed method + if (list.getSelectedIndex() > -1) selectionChanged(); + } + } + + public PreferencesPanel(Iterable preferences) { + this.setLayout(new GridBagLayout()); + + JLabel titleLabel = new JLabel(); + titleLabel.setText(Res.getString("title.preferences")); + titleLabel.setFont(new Font("Dialog", Font.BOLD, 15)); + /* + scrollPane is the left panel displaying the preference icons + */ + JScrollPane scrollPane = new JScrollPane( list ); + scrollPane.setPreferredSize(new Dimension(125, 0)); + scrollPane.setMinimumSize(new Dimension(125,100)); + list.setFixedCellHeight(40); + + add( scrollPane, new GridBagConstraints(0, 0, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.VERTICAL, new Insets(5, 5, 5, 5), 50, 0)); + add(flowPanel, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); + + + list.setCellRenderer(new JLabelIconRenderer()); + list.addListSelectionListener(this); + // Populate with current preferences + for (Preference preference : preferences) { + listModel.addElement(new PreferenceUI(preference)); + } + + list.setSelectedIndex(0); + } + + private synchronized void selectionChanged(){ + PreferenceUI o = list.getSelectedValue(); + Preference pref = o.getPreference(); + pref.load(); + + JComponent comp = pref.getGUI(); + flowPanel.removeAll(); + + // Create the title panel for this dialog + String title = ""; + String toolTip = ""; + Icon icon = null; + try { + title = pref.getTitle(); + toolTip = pref.getTooltip(); + icon = pref.getIcon(); + } catch (Exception e) { + Log.error(e); + } + TitlePanel titlePanel = new TitlePanel(title, toolTip, icon, false); + + + flowPanel.add(comp, BorderLayout.CENTER); + flowPanel.add(titlePanel, BorderLayout.NORTH); + flowPanel.invalidate(); + flowPanel.validate(); + flowPanel.repaint(); + currentPreference = pref; + } + + @Override + public void valueChanged(ListSelectionEvent e) { + + if (!e.getValueIsAdjusting()) { + + if (currentPreference != null) { + try { + if (currentPreference.isDataValid()) { + currentPreference.commit(); + } + else { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(this, currentPreference.getErrorMessage(), + Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + list.removeListSelectionListener(this); + list.setSelectedIndex(e.getLastIndex()); + list.addListSelectionListener(this); + } + } + catch ( Throwable t ) + { + // This is observed with some plugins, that require classes not (no longer) provided by Spark. + Log.error( "An error occurred while trying to commit settings for preference: " + currentPreference.getListName(), t ); + UIManager.put( "OptionPane.okButtonText", Res.getString( "ok" ) ); + JOptionPane.showMessageDialog( this, "Unable to save all settings for " + currentPreference.getListName() + ":\n" + t.getMessage(), + Res.getString( "title.error" ), JOptionPane.ERROR_MESSAGE ); + list.removeListSelectionListener( this ); + list.setSelectedIndex( e.getLastIndex() ); + list.addListSelectionListener( this ); + } + } + selectionChanged(); + } + } + + public boolean closing() { + if (currentPreference != null) { + if (currentPreference.isDataValid()) { + currentPreference.commit(); + SettingsManager.fireListeners(); + return true; + } + else { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(this, currentPreference.getErrorMessage(), + Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + return false; + } + } + return true; + } +} diff --git a/src/java/org/jivesoftware/sparkimpl/preference/chat/ChatPreference.java b/core/src/main/java/org/jivesoftware/sparkimpl/preference/chat/ChatPreference.java similarity index 80% rename from src/java/org/jivesoftware/sparkimpl/preference/chat/ChatPreference.java rename to core/src/main/java/org/jivesoftware/sparkimpl/preference/chat/ChatPreference.java index 987ca00ea..f5049c9b0 100644 --- a/src/java/org/jivesoftware/sparkimpl/preference/chat/ChatPreference.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/preference/chat/ChatPreference.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,10 +15,7 @@ */ package org.jivesoftware.sparkimpl.preference.chat; -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JOptionPane; -import javax.swing.UIManager; +import javax.swing.*; import org.jivesoftware.resource.Res; import org.jivesoftware.resource.SparkRes; @@ -42,7 +35,7 @@ * to be used and showing dates and times of chat posts. */ public class ChatPreference implements Preference { - private ChatPreferencePanel panel = new ChatPreferencePanel(); + private final ChatPreferencePanel panel = new ChatPreferencePanel(); private String errorMessage = "Error"; /** @@ -50,46 +43,57 @@ public class ChatPreference implements Preference { */ public static final String NAMESPACE = "http://www.jivesoftware.org/spark/chatwindow"; - public String getTitle() { + @Override + public String getTitle() { return Res.getString("title.general.chat.settings"); } - public String getListName() { + @Override + public String getListName() { return Res.getString("title.chat"); } - public String getTooltip() { + @Override + public String getTooltip() { return Res.getString("title.general.chat.settings"); } - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.USER1_MESSAGE_24x24); + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.USER1_MESSAGE_24x24); } - public void load() { + @Override + public void load() { SwingWorker thread = new SwingWorker() { LocalPreferences localPreferences; - public Object construct() { + @Override + public Object construct() { localPreferences = SettingsManager.getLocalPreferences(); return localPreferences; } - public void finished() { + @Override + public void finished() { boolean showTime = localPreferences.isTimeDisplayedInChat(); boolean notificationsOn = localPreferences.isChatRoomNotificationsOn(); boolean chatHistoryHidden = !localPreferences.isChatHistoryEnabled(); boolean prevChatHistoryHidden = !localPreferences.isPrevChatHistoryEnabled(); boolean tabsOnTop = localPreferences.isTabTopPosition(); boolean buzzAllowed = localPreferences.isBuzzEnabled(); + boolean closeUnreadMessage = localPreferences.isCloseUnreadMessage(); boolean isChatHistoryAscending = localPreferences.getChatHistoryAscending(); + boolean tabsScroll = localPreferences.isTabsScroll(); panel.setShowTime(showTime); panel.setGroupChatNotificationsOn(notificationsOn); panel.setChatHistoryHidden(chatHistoryHidden); panel.setPrevChatHistoryHidden(prevChatHistoryHidden); panel.setChatTimeoutTime(localPreferences.getChatLengthDefaultTimeout()); panel.setTabsOnTop(tabsOnTop); + panel.setTabsScrollBox(tabsScroll); panel.setBuzzEnabled(buzzAllowed); + panel.setCloseUnreadMessageEnabled(closeUnreadMessage); panel.setSortChatHistoryAscending(isChatHistoryAscending); } }; @@ -98,7 +102,8 @@ public void finished() { } - public void commit() { + @Override + public void commit() { LocalPreferences pref = SettingsManager.getLocalPreferences(); pref.setTimeDisplayedInChat(panel.getShowTime()); if( panel.getShowTime() ) @@ -110,17 +115,17 @@ public void commit() { pref.setPrevChatHistoryEnabled(!panel.isPrevChatHistoryHidden()); pref.setChatLengthDefaultTimeout(panel.getChatTimeoutTime()); pref.setTabsOnTop(panel.isTabsOnTop()); + pref.setTabsScroll(panel.isTabScroll()); pref.setBuzzEnabled(panel.isBuzzEnabled()); + pref.setCloseUnreadMessageEnabled(panel.isCloseUnreadMessageEnabled()); pref.setChatHistoryAscending(panel.isSortChatHistoryAscending()); - SettingsManager.saveSettings(); - // Do not commit if not changed. if (ModelUtil.hasLength(panel.getPassword()) && ModelUtil.hasLength(panel.getConfirmationPassword())) { try { AccountManager.getInstance( SparkManager.getConnection() ).changePassword(panel.getPassword()); } - catch (XMPPException | SmackException passwordEx) { + catch (XMPPException | SmackException | InterruptedException passwordEx) { UIManager.put("OptionPane.okButtonText", Res.getString("ok")); JOptionPane.showMessageDialog(SparkManager.getMainWindow(), Res.getString("message.unable.to.save.password"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); @@ -129,16 +134,19 @@ public void commit() { } } - public Object getData() { + @Override + public Object getData() { return SettingsManager.getLocalPreferences(); } - public String getErrorMessage() { + @Override + public String getErrorMessage() { return errorMessage; } - public boolean isDataValid() { + @Override + public boolean isDataValid() { boolean dataIsValid = true; if (ModelUtil.hasLength(panel.getPassword()) && ModelUtil.hasLength(panel.getConfirmationPassword())) { if (!panel.getPassword().equals(panel.getConfirmationPassword())) { @@ -149,15 +157,18 @@ public boolean isDataValid() { return dataIsValid; } - public JComponent getGUI() { + @Override + public JComponent getGUI() { return panel; } - public String getNamespace() { + @Override + public String getNamespace() { return NAMESPACE; } - public void shutdown() { + @Override + public void shutdown() { commit(); } diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/preference/chat/ChatPreferencePanel.java b/core/src/main/java/org/jivesoftware/sparkimpl/preference/chat/ChatPreferencePanel.java new file mode 100644 index 000000000..bfbde738d --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/preference/chat/ChatPreferencePanel.java @@ -0,0 +1,331 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.preference.chat; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; + +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JRadioButton; +import javax.swing.JTextField; +import javax.swing.UIManager; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.VerticalFlowLayout; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +/** + * The Preference UI used to handle changing of Chat Preferences. + */ +public class ChatPreferencePanel extends JPanel implements ActionListener { + + private static final long serialVersionUID = 8910938026549098719L; + private final JCheckBox showTimeBox = new JCheckBox(); + private final ButtonGroup timeFormat = new ButtonGroup(); + private final JRadioButton format12 = new JRadioButton("12:00 PM", false); + private final JRadioButton format24 = new JRadioButton("24:00", true); + private final JRadioButton format12s = new JRadioButton("12:00:00 PM", false); + private final JRadioButton format24s = new JRadioButton("24:00:00", false); + private final JCheckBox groupChatNotificationBox = new JCheckBox(); + private final JPanel generalPanel = new JPanel(); + private final JPanel chatWindowPanel = new JPanel(); + + // Password changing + private final JPasswordField passwordField = new JPasswordField(); + private final JPasswordField confirmationPasswordField = new JPasswordField(); + private final JLabel passwordLabel = new JLabel(); + private final JLabel confirmationPasswordLabel = new JLabel(); + private final JCheckBox hideChatHistory = new JCheckBox(); + private final JCheckBox sortChatHistoryAscending = new JCheckBox(); + private final JCheckBox hidePrevChatHistory = new JCheckBox(); + private final JCheckBox tabsOnTopBox = new JCheckBox(); + private final JTextField chatTimeoutField = new JTextField(); + private final JCheckBox buzzBox = new JCheckBox(); + private final JCheckBox closeUnreadMessageBox = new JCheckBox(); + private final JCheckBox tabsScrollBox = new JCheckBox(); + + /** + * Constructor invokes UI setup. + */ + public ChatPreferencePanel() { + // Build the UI + createUI(); + } + + private void createUI() { + setLayout(new VerticalFlowLayout()); + timeFormat.add(format24); + timeFormat.add(format24s); + timeFormat.add(format12); + timeFormat.add(format12s); + final LocalPreferences pref = SettingsManager.getLocalPreferences(); + switch (pref.getTimeFormat()) { + case "HH:mm": + format24.setSelected(true); + break; + case "HH:mm:ss": + format24s.setSelected(true); + break; + case "h:mm a": + format12.setSelected(true); + break; + default: + format12s.setSelected(true); + break; + } + + // Setup Mnemonics + ResourceUtils.resButton(showTimeBox, Res.getString("checkbox.show.time.in.chat.window")); + ResourceUtils.resLabel(passwordLabel, passwordField, Res.getString("label.change.password.to") + ":"); + ResourceUtils.resLabel(confirmationPasswordLabel, confirmationPasswordField, Res.getString("label.confirm.password") + ":"); + ResourceUtils.resButton(groupChatNotificationBox, Res.getString("checkbox.show.notifications.in.conference")); + ResourceUtils.resButton(hideChatHistory, Res.getString("checkbox.disable.chat.history")); + ResourceUtils.resButton(hidePrevChatHistory, Res.getString("checkbox.disable.prev.chat.history")); + ResourceUtils.resButton(sortChatHistoryAscending, Res.getString("checkbox.sort.asc.history")); + ResourceUtils.resButton(tabsOnTopBox, Res.getString("checkbox.tabs.on.top")); + ResourceUtils.resButton(tabsScrollBox, Res.getString("checkbox.tabs.scroll")); + ResourceUtils.resButton(buzzBox, Res.getString("checkbox.allow.buzz")); + ResourceUtils.resButton(closeUnreadMessageBox,Res.getString("checkbox.close.unread.message")); + + generalPanel.setBorder(BorderFactory.createTitledBorder(Res.getString("group.general.information"))); + chatWindowPanel.setBorder(BorderFactory.createTitledBorder(Res.getString("group.chat.window.information"))); + + if (!Default.getBoolean(Default.CHANGE_PASSWORD_DISABLED) && Enterprise.containsFeature(Enterprise.PASSWORD_CHANGE_FEATURE)) add(generalPanel); + add(chatWindowPanel); + + generalPanel.setLayout(new GridBagLayout()); + chatWindowPanel.setLayout(new GridBagLayout()); + + // Chat Window Panel settings + chatWindowPanel.add(showTimeBox, new GridBagConstraints(0, 0, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + chatWindowPanel.add(format24, new GridBagConstraints(1, 0, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + chatWindowPanel.add(format24s, new GridBagConstraints(1, 1, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + chatWindowPanel.add(format12, new GridBagConstraints(2, 0, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + chatWindowPanel.add(format12s, new GridBagConstraints(2, 1, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + + chatWindowPanel.add(groupChatNotificationBox, new GridBagConstraints(0, 2, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + + if (!Default.getBoolean(Default.HISTORY_DISABLED) && !Default.getBoolean(Default.HIDE_HISTORY_SETTINGS) + && Enterprise.containsFeature(Enterprise.HISTORY_SETTINGS_FEATURE) && Enterprise.containsFeature(Enterprise.HISTORY_TRANSCRIPTS_FEATURE)) { + chatWindowPanel.add(hideChatHistory, new GridBagConstraints(0, 3, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + chatWindowPanel.add(hidePrevChatHistory, new GridBagConstraints(0, 4, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + } + + chatWindowPanel.add(sortChatHistoryAscending, new GridBagConstraints(0, 5, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + chatWindowPanel.add(tabsOnTopBox, new GridBagConstraints(0, 6, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + chatWindowPanel.add(tabsScrollBox, new GridBagConstraints(0, 7, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + chatWindowPanel.add(buzzBox, new GridBagConstraints(0, 8, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + chatWindowPanel.add(closeUnreadMessageBox, new GridBagConstraints(0, 9, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + + JLabel chatTimeoutLabel = new JLabel(); + ResourceUtils.resLabel(chatTimeoutLabel, chatTimeoutField, Res.getString("label.minutes.before.stale.chat") + ":"); + chatWindowPanel.add(chatTimeoutLabel, new GridBagConstraints(0, 10, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + chatWindowPanel.add(chatTimeoutField, new GridBagConstraints(1, 10, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); + + + generalPanel.add(passwordLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + generalPanel.add(passwordField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 100, 0)); + generalPanel.add(confirmationPasswordLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + generalPanel.add(confirmationPasswordField, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 100, 0)); + + showTimeBox.addActionListener( e -> { + if(showTimeBox.isSelected()) + { + format12.setEnabled(true); + format24.setEnabled(true); + format12s.setEnabled(true); + format24s.setEnabled(true); + } + else + { + format12.setEnabled(false); + format24.setEnabled(false); + format12s.setEnabled(false); + format24s.setEnabled(false); + } + } ); + + hideChatHistory.addActionListener(this); + + } + + /** + * Set to true to have the ChatWindow show the timestamp of each message. + * + * @param showTime true to show timestamp of each message. + */ + public void setShowTime(boolean showTime) { + showTimeBox.setSelected(showTime); + } + + /** + * Returns true if the ChatWindow should show a timestamp of each message. + * + * @return true if the ChatWindow should show a timestamp of each message. + */ + public boolean getShowTime() { + return showTimeBox.isSelected(); + } + + public String getFormatTime() { + if(format24.isSelected()) + { + return "HH:mm"; + } + else if(format24s.isSelected()) + { + return "HH:mm:ss"; + } + else if(format12.isSelected()) + { + return "h:mm a"; + } + else + { + return "h:mm:ss a"; + } + } + + /** + * Returns the new password to use. + * + * @return the new password to use. + */ + public String getPassword() { + return new String(passwordField.getPassword()); + } + + /** + * Returns the confirmation password used to compare to the first password. + * + * @return the confirmation password used to compare to the first password. + */ + public String getConfirmationPassword() { + return new String(confirmationPasswordField.getPassword()); + } + + public void setSortChatHistoryAscending(boolean on) { + sortChatHistoryAscending.setSelected(on); + } + + public boolean isSortChatHistoryAscending() { + return sortChatHistoryAscending.isSelected(); + } + + public void setGroupChatNotificationsOn(boolean on) { + groupChatNotificationBox.setSelected(on); + } + + public boolean isGroupChatNotificationsOn() { + return groupChatNotificationBox.isSelected(); + } + + public void setChatHistoryHidden(boolean hide) { + hideChatHistory.setSelected(hide); + } + + public boolean isChatHistoryHidden() { + return hideChatHistory.isSelected(); + } + + public void setPrevChatHistoryHidden(boolean hide) { + hidePrevChatHistory.setSelected(hide); + } + + public boolean isPrevChatHistoryHidden() { + return hidePrevChatHistory.isSelected(); + } + + public void setChatTimeoutTime(int time) { + chatTimeoutField.setText(Integer.toString(time)); + } + + public void setTabsOnTop(boolean top){ + tabsOnTopBox.setSelected(top); + } + + public boolean isTabsOnTop(){ + return tabsOnTopBox.isSelected(); + } + public void setTabsScrollBox(boolean top){ tabsScrollBox.setSelected(top); } + public boolean isTabScroll(){ + return tabsScrollBox.isSelected(); + } + + public void setBuzzEnabled(boolean allowBuzz){ + buzzBox.setSelected(allowBuzz); + } + + public boolean isBuzzEnabled(){ + return buzzBox.isSelected(); + } + + public void setCloseUnreadMessageEnabled(boolean askBeforeClosing){ + closeUnreadMessageBox.setSelected(askBeforeClosing); + } + + public boolean isCloseUnreadMessageEnabled(){ + return closeUnreadMessageBox.isSelected(); + } + + public int getChatTimeoutTime() { + try { + return Integer.parseInt(chatTimeoutField.getText()); + } + catch (NumberFormatException e) { + return 15; + } + } + + @Override + public void actionPerformed(ActionEvent actionEvent) { + if (hideChatHistory.isSelected()) { + UIManager.put("OptionPane.yesButtonText", Res.getString("yes")); + UIManager.put("OptionPane.noButtonText", Res.getString("no")); + UIManager.put("OptionPane.cancelButtonText", Res.getString("cancel")); + int ok = JOptionPane.showConfirmDialog(this, Res.getString("message.delete.all.history"), Res.getString("title.confirmation"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + if (ok == JOptionPane.YES_OPTION) { + File transcriptDir = new File(SparkManager.getUserDirectory(), "transcripts"); + File[] files = transcriptDir.listFiles(); + + hidePrevChatHistory.setEnabled(false); + hidePrevChatHistory.setSelected(false); + + for (File transcriptFile : files) { + transcriptFile.delete(); + } + } + } else { + hidePrevChatHistory.setEnabled(true); + } + } + +} diff --git a/src/java/org/jivesoftware/sparkimpl/preference/groupchat/GroupChatPreference.java b/core/src/main/java/org/jivesoftware/sparkimpl/preference/groupchat/GroupChatPreference.java similarity index 82% rename from src/java/org/jivesoftware/sparkimpl/preference/groupchat/GroupChatPreference.java rename to core/src/main/java/org/jivesoftware/sparkimpl/preference/groupchat/GroupChatPreference.java index 92e17f644..779d4e537 100644 --- a/src/java/org/jivesoftware/sparkimpl/preference/groupchat/GroupChatPreference.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/preference/groupchat/GroupChatPreference.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,8 +22,7 @@ import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import javax.swing.Icon; -import javax.swing.JComponent; +import javax.swing.*; /** * Essentially adds a new panel to the menu. @@ -36,39 +31,46 @@ */ public class GroupChatPreference implements Preference { - private GroupChatPreferencePanel panel = new GroupChatPreferencePanel(); + private final GroupChatPreferencePanel panel = new GroupChatPreferencePanel(); /** * Define the Namespace used for this preference. */ public static final String NAMESPACE = "Group Chat"; - public String getTitle() { + @Override + public String getTitle() { return Res.getString("title.group.chat"); } - public String getListName() { + @Override + public String getListName() { return Res.getString("title.group.chat"); } - public String getTooltip() { + @Override + public String getTooltip() { return Res.getString("title.group.chat"); } - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.JOIN_GROUPCHAT_IMAGE); + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.JOIN_GROUPCHAT_IMAGE); } - public void load() { + @Override + public void load() { SwingWorker thread = new SwingWorker() { LocalPreferences localPreferences; - public Object construct() { + @Override + public Object construct() { localPreferences = SettingsManager.getLocalPreferences(); return localPreferences; } - public void finished() { + @Override + public void finished() { boolean highlightMyName = localPreferences.isMucHighNameEnabled(); boolean highlightMyText = localPreferences.isMucHighTextEnabled(); boolean highlightPopName = localPreferences.isMucHighToastEnabled(); @@ -93,7 +95,8 @@ public void finished() { } - public void commit() { + @Override + public void commit() { LocalPreferences pref = SettingsManager.getLocalPreferences(); pref.setMucHighNameEnabled(panel.isMucHighNameEnabled()); @@ -104,31 +107,36 @@ public void commit() { pref.setAutoAcceptMucInvite(panel.isAutoAcceptMuc()); pref.setMucRandomColors(panel.isRandomColors()); pref.setUseAdHocRoom(!panel.isInviteToBookmark()); - SettingsManager.saveSettings(); } - public Object getData() { + @Override + public Object getData() { return SettingsManager.getLocalPreferences(); } - public String getErrorMessage() { + @Override + public String getErrorMessage() { return null; } - public boolean isDataValid() { + @Override + public boolean isDataValid() { return true; } - public JComponent getGUI() { + @Override + public JComponent getGUI() { return panel; } - public String getNamespace() { + @Override + public String getNamespace() { return NAMESPACE; } - public void shutdown() { + @Override + public void shutdown() { commit(); } diff --git a/src/java/org/jivesoftware/sparkimpl/preference/groupchat/GroupChatPreferencePanel.java b/core/src/main/java/org/jivesoftware/sparkimpl/preference/groupchat/GroupChatPreferencePanel.java similarity index 90% rename from src/java/org/jivesoftware/sparkimpl/preference/groupchat/GroupChatPreferencePanel.java rename to core/src/main/java/org/jivesoftware/sparkimpl/preference/groupchat/GroupChatPreferencePanel.java index b6fa8f2a1..cb1de24eb 100644 --- a/src/java/org/jivesoftware/sparkimpl/preference/groupchat/GroupChatPreferencePanel.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/preference/groupchat/GroupChatPreferencePanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,16 +34,16 @@ public class GroupChatPreferencePanel extends JPanel { private static final long serialVersionUID = -4216417602756915148L; - private JCheckBox highlightMyName = new JCheckBox(); - private JCheckBox highlightMyText = new JCheckBox(); - private JCheckBox highlightPopName = new JCheckBox(); - private JCheckBox showjoinleavemessage = new JCheckBox(); - private JCheckBox showroleicons = new JCheckBox(); - private JCheckBox _autoAcceptInvites = new JCheckBox(); - private JCheckBox _randomcolors = new JCheckBox(); - private JCheckBox inviteToBookmark = new JCheckBox(); - - private JPanel gCPanel = new JPanel(); + private final JCheckBox highlightMyName = new JCheckBox(); + private final JCheckBox highlightMyText = new JCheckBox(); + private final JCheckBox highlightPopName = new JCheckBox(); + private final JCheckBox showjoinleavemessage = new JCheckBox(); + private final JCheckBox showroleicons = new JCheckBox(); + private final JCheckBox _autoAcceptInvites = new JCheckBox(); + private final JCheckBox _randomcolors = new JCheckBox(); + private final JCheckBox inviteToBookmark = new JCheckBox(); + + private final JPanel gCPanel = new JPanel(); /** * Constructor invokes UI setup. */ diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationAlertUI.java b/core/src/main/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationAlertUI.java new file mode 100644 index 000000000..c7dab3b5e --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationAlertUI.java @@ -0,0 +1,241 @@ +/** + * Copyright (C) 1999-2010 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.preference.notifications; + +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smackx.vcardtemp.packet.VCard; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.Sizes; +import org.jxmpp.jid.BareJid; + +import javax.swing.*; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.RenderingHints; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; + +import static java.awt.GridBagConstraints.*; +import static java.awt.GridBagConstraints.BOTH; + +public class NotificationAlertUI extends JPanel { + private final JLabel avatarLabel = new JLabel(); + private final JLabel titleLabel = new JLabel(); + private final JLabel emailAddressLabel = new JLabel(); + private final JLabel professionLabel = new JLabel(); + + private final VCard vcard; + private final BareJid jid; + + private final boolean available; + + final JLabel topLabel = new JLabel(); + + private static final int AVATAR_HEIGHT = Sizes.Avatar.NOTIFICATION; + private static final int AVATAR_WIDTH = Sizes.Avatar.NOTIFICATION; + + private static final Color COLOR_NOTIFICATION_TITLE = new Color(64, 103, 162); + private static final Color COLOR_INNER_BLOCK_BORDER = new Color(197, 213, 230); + private static final Color COLOR_LINK = new Color(49, 89, 151); + private static final Color COLOR_GRADIENT = new Color(233, 240, 247); + + public NotificationAlertUI(BareJid jid, boolean available, Presence presence) { + setLayout(new GridBagLayout()); + this.available = available; + this.jid = jid; + vcard = SparkManager.getVCardManager().getVCardFromMemory(jid); + final Icon presenceIcon = PresenceManager.getIconFromPresence(presence); + + topLabel.setIcon(presenceIcon); + topLabel.setHorizontalTextPosition(JLabel.RIGHT); + topLabel.setFont(new Font("Dialog", Font.BOLD, 15)); + topLabel.setForeground(Color.DARK_GRAY); + + // Add Caller Block + buildInnerBlock(); + } + + + /** + * Builds the part of the incoming call UI with the Callers information. + */ + private void buildInnerBlock() { + final JPanel panel = new JPanel(new GridBagLayout()); + panel.setBackground(Color.white); + panel.setBorder(BorderFactory.createLineBorder(COLOR_INNER_BLOCK_BORDER, 1)); + + titleLabel.setHorizontalTextPosition(JLabel.RIGHT); + // Add Avatar + panel.add(avatarLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 1.0, NORTHWEST, NONE, new Insets(10, 15, 5, 0), 0, 0)); + // Add Avatar information + panel.add(titleLabel, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, NORTHWEST, HORIZONTAL, new Insets(10, 5, 0, 0), 0, 0)); + panel.add(professionLabel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, NORTHWEST, HORIZONTAL, new Insets(0, 7, 0, 0), 0, 0)); + panel.add(emailAddressLabel, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, NORTHWEST, HORIZONTAL, new Insets(0, 7, 0, 0), 0, 0)); + + // Set default settings + titleLabel.setForeground(COLOR_NOTIFICATION_TITLE); + titleLabel.setFont(new Font("Dialog", Font.BOLD, 16)); + + + if (vcard != null) { + handleVCardInformation(vcard); + } + else { + updateWithGenericInfo(); + } + + // Add to panel + add(panel, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, NORTHWEST, BOTH, new Insets(5, 5, 5, 5), 0, 0)); + } + + + private void updateWithGenericInfo() { + String title = SparkManager.getUserManager().getUserNicknameFromJID(jid); + + titleLabel.setText(title); + + avatarLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.DEFAULT_AVATAR_64x64_IMAGE)); + avatarLabel.invalidate(); + avatarLabel.validate(); + avatarLabel.repaint(); + + + invalidate(); + validate(); + repaint(); + } + + private void handleVCardInformation(VCard vcard) { + if (vcard.getError() != null) { + updateWithGenericInfo(); + return; + } + + // Nickname label should show presence and nickname. + String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid); + + String fullName = vcard.getField("FN"); + if (ModelUtil.hasLength(fullName)) { + titleLabel.setText(fullName); + } + else { + titleLabel.setText(nickname); + } + + String username = titleLabel.getText(); + String statusMessage = username + " is " + (available ? "Online" : "Offline"); + topLabel.setText(statusMessage); + + String jobTitle = vcard.getField("TITLE"); + if (jobTitle != null) { + professionLabel.setText(jobTitle); + } + + String emailAddress = vcard.getEmailHome(); + if (ModelUtil.hasLength(emailAddress)) { + emailAddressLabel.setText(emailAddress); + + final String unselectedText = "" + emailAddress + ""; + final String hoverText = "" + emailAddress + ""; + emailAddressLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + emailAddressLabel.setText(hoverText); + } + + @Override + public void mouseExited(MouseEvent e) { + emailAddressLabel.setText(unselectedText); + } + }); + } + + byte[] avatarBytes = null; + try { + avatarBytes = vcard.getAvatar(); + } + catch (Exception e) { + Log.error("Cannot retrieve avatar bytes.", e); + } + + if (avatarBytes != null) { + try { + ImageIcon avatarIcon = new ImageIcon(avatarBytes); + int w = avatarIcon.getIconWidth(); + int h = avatarIcon.getIconHeight(); + double ratio = (double) w / (double) h; + if (w > 120 || h > 120) { + if (w > h) { + w = 120; + h = (int) (w / ratio); + } else { + h = 120; + w = (int) (h * ratio); + } + } + + BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + Graphics2D g2 = resizedImg.createGraphics(); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + g2.drawImage(avatarIcon.getImage(), 0, 0, w, h, null); + g2.dispose(); + + avatarIcon = new ImageIcon(resizedImg); + avatarLabel.setIcon(GraphicUtils.scale(avatarIcon, AVATAR_HEIGHT, AVATAR_WIDTH)); + } catch (Exception ignored) { + } + } + else { + avatarLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.DEFAULT_AVATAR_64x64_IMAGE)); + } + + avatarLabel.invalidate(); + avatarLabel.validate(); + avatarLabel.repaint(); + + invalidate(); + validate(); + repaint(); + } + + @Override + public void paintComponent(Graphics g) { + BufferedImage cache = new BufferedImage(2, getHeight(), BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = cache.createGraphics(); + + GradientPaint paint = new GradientPaint(0, 0, COLOR_GRADIENT, 0, getHeight(), Color.white, true); + + g2d.setPaint(paint); + g2d.fillRect(0, 0, getWidth(), getHeight()); + g2d.dispose(); + + g.drawImage(cache, 0, 0, getWidth(), getHeight(), null); + } +} + diff --git a/src/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationPlugin.java similarity index 81% rename from src/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationPlugin.java rename to core/src/main/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationPlugin.java index 13bf93302..d81c2c566 100644 --- a/src/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationPlugin.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationPlugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +16,7 @@ package org.jivesoftware.sparkimpl.preference.notifications; +import java.awt.Color; import org.jivesoftware.smack.StanzaListener; import org.jivesoftware.smack.filter.StanzaTypeFilter; import org.jivesoftware.smack.packet.Stanza; @@ -35,7 +32,8 @@ import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.Jid; import javax.swing.AbstractAction; import javax.swing.BorderFactory; @@ -54,18 +52,20 @@ */ public class NotificationPlugin implements Plugin, StanzaListener { - private Set onlineUsers = new HashSet<>(); + private final Set onlineUsers = new HashSet<>(); private LocalPreferences preferences; - public void initialize() { + @Override + public void initialize() { // Add the preferences NotificationsPreference notifications = new NotificationsPreference(); SparkManager.getPreferenceManager().addPreference(notifications); notifications.load(); final TimerTask registerTask = new SwingTimerTask() { - public void doRun() { + @Override + public void doRun() { registerListener(); } }; @@ -80,8 +80,8 @@ private void registerListener() { ContactList contactList = SparkManager.getWorkspace().getContactList(); for (ContactGroup contactGroup : contactList.getContactGroups()) { for (ContactItem item : contactGroup.getContactItems()) { - if (item != null && item.getJID() != null && item.getPresence().isAvailable()) { - String bareJID = XmppStringUtils.parseBareJid(item.getJID()); + if (item != null && item.getJid() != null && item.getPresence().isAvailable()) { + BareJid bareJID = item.getJid().asBareJid(); onlineUsers.add(bareJID); } } @@ -92,9 +92,10 @@ private void registerListener() { } - public void processPacket(Stanza stanza) { + @Override + public void processStanza(Stanza stanza) { final Presence presence = (Presence)stanza; - String jid = presence.getFrom(); + Jid jid = presence.getFrom(); if (jid == null) { return; } @@ -105,35 +106,38 @@ public void processPacket(Stanza stanza) { return; } - jid = XmppStringUtils.parseBareJid(jid); - boolean isOnline = onlineUsers.contains(jid); + BareJid bareJid = jid.asBareJid(); + boolean isOnline = onlineUsers.contains(bareJid); if (presence.isAvailable()) { if (preferences.isOnlineNotificationsOn()) { if (!isOnline) { - notifyUserOnline(jid, presence); + notifyUserOnline(bareJid, presence); } } - onlineUsers.add(jid); + onlineUsers.add(bareJid); } else { if (preferences.isOfflineNotificationsOn() && isOnline) { - notifyUserOffline(jid, presence); + notifyUserOffline(bareJid, presence); } - onlineUsers.remove(jid); + onlineUsers.remove(bareJid); } } - public void shutdown() { + @Override + public void shutdown() { } - public boolean canShutDown() { + @Override + public boolean canShutDown() { return true; } - public void uninstall() { + @Override + public void uninstall() { SparkManager.getConnection().removeAsyncStanzaListener(this); } @@ -143,12 +147,12 @@ public void uninstall() { * @param jid the jid of the user that has come online. * @param presence Presence of the online user. */ - private void notifyUserOnline(final String jid, final Presence presence) { + private void notifyUserOnline(final BareJid jid, final Presence presence) { try { EventQueue.invokeAndWait( () -> { SparkToaster toaster = new SparkToaster(); toaster.setDisplayTime(preferences.getNotificationsDisplayTime()); - toaster.setBorder(BorderFactory.createBevelBorder(0)); + toaster.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); toaster.setCustomAction(new ChatAction(jid)); NotificationAlertUI alertUI = new NotificationAlertUI(jid, true, presence); @@ -176,13 +180,13 @@ private void notifyUserOnline(final String jid, final Presence presence) { * @param jid the jid of the user who has gone offline. * @param presence of the offline user. */ - private void notifyUserOffline(final String jid, final Presence presence) { + private void notifyUserOffline(final BareJid jid, final Presence presence) { try { EventQueue.invokeAndWait( () -> { SparkToaster toaster = new SparkToaster(); toaster.setCustomAction(new ChatAction(jid)); toaster.setDisplayTime(preferences.getNotificationsDisplayTime()); - toaster.setBorder(BorderFactory.createBevelBorder(0)); + toaster.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); NotificationAlertUI alertUI = new NotificationAlertUI(jid, false, presence); @@ -204,16 +208,17 @@ private void notifyUserOffline(final String jid, final Presence presence) { } } - private class ChatAction extends AbstractAction { + private static class ChatAction extends AbstractAction { private static final long serialVersionUID = 4752515615833181939L; - private String jid; + private final BareJid jid; - public ChatAction(String jid) { + public ChatAction(BareJid jid) { this.jid = jid; } - public void actionPerformed(ActionEvent e) { + @Override + public void actionPerformed(ActionEvent e) { String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid); SparkManager.getChatManager().activateChat(jid, nickname); } diff --git a/src/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationsPreference.java b/core/src/main/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationsPreference.java similarity index 92% rename from src/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationsPreference.java rename to core/src/main/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationsPreference.java index 925d0dbee..52748189b 100644 --- a/src/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationsPreference.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationsPreference.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,8 +22,7 @@ import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import javax.swing.Icon; -import javax.swing.JComponent; +import javax.swing.*; /** * Handles the preferences for notification behavior within the Spark IM Client. @@ -36,38 +31,45 @@ */ public class NotificationsPreference implements Preference { - private NotificationsUI panel = new NotificationsUI(); + private final NotificationsUI panel = new NotificationsUI(); /** * Define the Namespace used for this preference. */ public static final String NAMESPACE = "http://www.jivesoftware.org/spark/notifications"; + @Override public String getTitle() { return Res.getString("title.notifications"); } + @Override public String getListName() { return Res.getString("title.notifications"); } + @Override public String getTooltip() { return Res.getString("tooltip.notifications"); } + @Override public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.PROFILE_ICON); + return SparkRes.getImageIcon(SparkRes.Icon.NOTIFICATIONS); } + @Override public void load() { SwingWorker thread = new SwingWorker() { LocalPreferences localPreferences; + @Override public Object construct() { localPreferences = SettingsManager.getLocalPreferences(); return localPreferences; } + @Override public void finished() { boolean toaster = localPreferences.getShowToasterPopup(); boolean asteriskToaster = localPreferences.getDisableAsteriskToasterPopup(); @@ -89,7 +91,7 @@ public void finished() { panel.setOfflineNotification(offlineNotification); panel.setOnlineNotification(onlineNotification); panel.setCheckForBeta(betaChecking); - panel.setNotificationsDisplayTime(DisplayTime/1000); + panel.setNotificationsDisplayTime(DisplayTime); panel.setTypingNotification(typingNotification); panel.setSystemTrayNotification(systemTrayNotification); @@ -114,6 +116,7 @@ public void finished() { } + @Override public void commit() { LocalPreferences pref = SettingsManager.getLocalPreferences(); @@ -126,29 +129,34 @@ public void commit() { pref.setCheckForBeta(panel.isBetaCheckingEnabled()); pref.setTypingNotificationOn(panel.isTypingNotification()); pref.setSystemTrayNotificationEnabled(panel.isSystemTrayNotificationEnabled()); - SettingsManager.saveSettings(); } + @Override public Object getData() { return SettingsManager.getLocalPreferences(); } + @Override public String getErrorMessage() { return ""; } + @Override public boolean isDataValid() { return true; } + @Override public JComponent getGUI() { return panel; } + @Override public String getNamespace() { return NAMESPACE; } + @Override public void shutdown() { commit(); } diff --git a/src/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationsUI.java b/core/src/main/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationsUI.java similarity index 87% rename from src/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationsUI.java rename to core/src/main/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationsUI.java index b1e9e8575..f51b5db8b 100644 --- a/src/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationsUI.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationsUI.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,6 +19,7 @@ import org.jivesoftware.resource.Default; import org.jivesoftware.resource.Res; import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; import javax.swing.*; import java.awt.*; @@ -35,23 +32,21 @@ public class NotificationsUI extends JPanel { private static final long serialVersionUID = -3372199803443605883L; - private JCheckBox toasterBox; - private JCheckBox asteriskToasterBox; - private JCheckBox windowFocusBox; - private JCheckBox offlineNotificationBox; - private JCheckBox onlineNotificationBox; - private JCheckBox betaCheckBox; - private JCheckBox SystemTrayNotificationBox; - private JCheckBox showTypingNotificationBox; + private final JCheckBox toasterBox; + private final JCheckBox asteriskToasterBox; + private final JCheckBox windowFocusBox; + private final JCheckBox offlineNotificationBox; + private final JCheckBox onlineNotificationBox; + private final JCheckBox betaCheckBox; + private final JCheckBox SystemTrayNotificationBox; + private final JCheckBox showTypingNotificationBox; - private JSpinner notificationDelay; + private final JSpinner notificationDelay; public NotificationsUI() { - - Integer[] spinnerDelay = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}; - SpinnerListModel delayModel = new SpinnerListModel(spinnerDelay); + SpinnerNumberModel delayModel = new SpinnerNumberModel(5, 1, 20, 2); notificationDelay = new JSpinner(delayModel); - notificationDelay.setPreferredSize(new Dimension(40,20)); + notificationDelay.setPreferredSize(new Dimension(80, 35)); setLayout(new FlowLayout(FlowLayout.LEFT)); @@ -63,7 +58,7 @@ public NotificationsUI() { pn_spinner.add(new JLabel(Res.getString("label.display.time"))); pn_spinner.add(notificationDelay); pn_spinner.add(new JLabel(Res.getString("label.seconds"))); - pn_spinner.setPreferredSize(new Dimension(190,25)); + pn_spinner.setPreferredSize(new Dimension(190,45)); JPanel pn_OnOffNotifications = new JPanel(); pn_OnOffNotifications.setLayout(new GridBagLayout()); @@ -105,7 +100,7 @@ public NotificationsUI() { betaCheckBox = new JCheckBox(); ResourceUtils.resButton(betaCheckBox, Res.getString("menuitem.check.for.updates")); - if(!Default.getBoolean(Default.DISABLE_UPDATES)){ + if (!Default.getBoolean(Default.DISABLE_UPDATES) && Enterprise.containsFeature(Enterprise.UPDATES_FEATURE)) { pn.add(betaCheckBox, new GridBagConstraints(0, 7, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); } add(pn); @@ -157,14 +152,16 @@ public boolean shouldWindowPopup() { return windowFocusBox.isSelected(); } - public void setNotificationsDisplayTime(int DisplayTime) - { + public void setNotificationsDisplayTime(int DisplayTime) { + if (DisplayTime <= 0 || DisplayTime > 20) { + DisplayTime = 3; // Default to 3 seconds if the value is out of bounds + } notificationDelay.setValue(DisplayTime); } public Integer getNotificationsDisplayTime() { - return Integer.valueOf(notificationDelay.getValue().toString())*1000; + return Integer.parseInt(notificationDelay.getValue().toString()); } public void setOfflineNotification(boolean notify) { diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPlugin.java b/core/src/main/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPlugin.java new file mode 100644 index 000000000..6ba58c2eb --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPlugin.java @@ -0,0 +1,118 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.sparkimpl.preference.sounds; + +import org.jivesoftware.smack.filter.StanzaTypeFilter; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smackx.delay.packet.DelayInformation; +import org.jivesoftware.smackx.muc.MultiUserChatManager; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomListener; +import org.jivesoftware.spark.ui.MessageListener; +import org.jivesoftware.spark.util.TaskEngine; +import org.jxmpp.jid.BareJid; + +import static org.jivesoftware.spark.Event.*; + +/** + * Sounds Plugin. + * Adds sound preferences for Spark. + * + * @author Derek DeMoro + */ +public class SoundPlugin implements Plugin, MessageListener, ChatRoomListener { + private SoundPreference soundPreference; + + @Override + public void initialize() { + soundPreference = new SoundPreference(); + SparkManager.getPreferenceManager().addPreference(soundPreference); + + SparkManager.getChatManager().addChatRoomListener(this); + + SparkManager.getConnection().addAsyncStanzaListener( stanza -> { + Presence presence = (Presence)stanza; + BareJid presenceBareJid = presence.getFrom().asBareJid(); + // Ignore own presence updates + if (presenceBareJid.equals(SparkManager.getSessionManager().getUserBareAddress())) { + return; + } + + if (!presence.isAvailable()) { + if (!PresenceManager.isOnline(presenceBareJid)) { + SparkManager.getSoundManager().playClip(STATUS_OFFLINE); + } + } + }, new StanzaTypeFilter(Presence.class)); + + // Load sound preferences. + final Runnable soundLoader = () -> soundPreference.loadFromFile(); + + TaskEngine.getInstance().submit(soundLoader); + MultiUserChatManager mucManager = SparkManager.getMucManager(); + mucManager.addInvitationListener( ( xmppConnection, muc, inviter, reason, password, message, invitation ) -> { + SparkManager.getSoundManager().playClip(INCOMING_INVITATION); + } ); + } + + @Override + public void messageReceived(ChatRoom room, Message message) { + // Do not play sounds on history updates. + if (message.hasExtension(DelayInformation.class)) { + return; + } + // Ignore own messages + if (message.getFrom() == null || message.getFrom().asBareJid().equals(SparkManager.getSessionManager().getUserBareAddress())) { + return; + } + SparkManager.getSoundManager().playClip(MSG_INCOMING); + } + + @Override + public void messageSent(ChatRoom room, Message message) { + SparkManager.getSoundManager().playClip(MSG_OUTCOMING); + } + + @Override + public void shutdown() { + + } + + @Override + public boolean canShutDown() { + return false; + } + + @Override + public void chatRoomOpened(ChatRoom room) { + room.addMessageListener(this); + } + + @Override + public void chatRoomClosed(ChatRoom room) { + room.removeMessageListener(this); + } + + @Override + public void uninstall() { + // Do nothing. + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPreference.java b/core/src/main/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPreference.java new file mode 100644 index 000000000..87c2598c1 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPreference.java @@ -0,0 +1,411 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.sparkimpl.preference.sounds; + +import static java.awt.GridBagConstraints.HORIZONTAL; +import static java.awt.GridBagConstraints.NONE; +import static java.awt.GridBagConstraints.NORTHWEST; + +import java.awt.EventQueue; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; + +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; + +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.preference.Preference; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.WindowsFileSystemView; +import org.jivesoftware.spark.util.log.Log; + +import com.thoughtworks.xstream.XStream; + +/** + * Preferences to handle Sounds played within Spark. + * + * @author Derek DeMoro + */ +public class SoundPreference implements Preference { + + private XStream xstream; + private SoundPreferences preferences; + private SoundPanel soundPanel; + + public static final String NAMESPACE = "Sounds"; + + public SoundPreference() { + + } + + + @Override + public String getTitle() { + return Res.getString("title.sound.preferences"); + } + + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.SOUND_PREFERENCES_IMAGE); + } + + @Override + public String getTooltip() { + return Res.getString("title.sounds"); + } + + @Override + public String getListName() { + return Res.getString("title.sounds"); + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public JComponent getGUI() { + if (soundPanel == null) { + try { + EventQueue.invokeAndWait( () -> soundPanel = new SoundPanel()); + } catch (Exception e) { + e.printStackTrace(); + } + + } + return soundPanel; + } + + public void loadFromFile() { + if (preferences != null) { + return; + } + + if (!getSoundSettingsFile().exists()) { + preferences = new SoundPreferences(); + } + else { + + // Do Initial Load from FileSystem. + File settingsFile = getSoundSettingsFile(); + try { + FileReader reader = new FileReader(settingsFile); + preferences = (SoundPreferences)getXStream().fromXML(reader); + } + catch (Exception e) { + Log.error("Error loading Sound Preferences.", e); + preferences = new SoundPreferences(); + } + } + } + + @Override + public void load() { + if (soundPanel == null) { + soundPanel = new SoundPanel(); + } + + SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + loadFromFile(); + return preferences; + } + + @Override + public void finished() { + // Set default settings + soundPanel.setIncomingMessageSound(preferences.getIncomingSound()); + soundPanel.playIncomingSound(preferences.isPlayIncomingSound()); + + soundPanel.setOutgoingMessageSound(preferences.getOutgoingSound()); + soundPanel.playOutgoingSound(preferences.isPlayOutgoingSound()); + + soundPanel.setOfflineSound(preferences.getOfflineSound()); + soundPanel.playOfflineSound(preferences.isPlayOfflineSound()); + + soundPanel.setInvitationSound(preferences.getIncomingInvitationSoundFile()); + soundPanel.setPlayInvitationSound(preferences.playIncomingInvitationSound()); + + soundPanel.setChatRequestSound(preferences.getChatRequestSound()); + soundPanel.setPlayChatRequestSound(preferences.isPlayChatRequestSound()); + } + }; + worker.start(); + } + + @Override + public void commit() { + preferences.setIncomingSound(soundPanel.getIncomingSound()); + preferences.setOutgoingSound(soundPanel.getOutgoingSound()); + + preferences.setOfflineSound(soundPanel.getOfflineSound()); + preferences.setPlayOfflineSound(soundPanel.playOfflineSound()); + + preferences.setPlayIncomingSound(soundPanel.playIncomingSound()); + preferences.setPlayOutgoingSound(soundPanel.playOutgoingSound()); + + preferences.setIncomingInvitationSoundFile(soundPanel.getInvitationSound()); + preferences.setPlayIncomingInvitationSound(soundPanel.playInvitationSound()); + + preferences.setChatRequestSound(soundPanel.getChatRequestSound()); + preferences.setPlayChatRequestSound(soundPanel.isPlayChatRequestSound()); + + saveSoundsFile(); + } + + @Override + public boolean isDataValid() { + return true; + } + + @Override + public String getErrorMessage() { + return null; + } + + @Override + public Object getData() { + return null; + } + + + private static class SoundPanel extends JPanel { + private static final long serialVersionUID = 4332294589601051699L; + private final JCheckBox incomingMessageBox = new JCheckBox(); + private final JTextField incomingMessageSound = new JTextField(); + private final JButton incomingBrowseButton = new JButton(".."); + + private final JCheckBox outgoingMessageBox = new JCheckBox(); + private final JTextField outgoingMessageSound = new JTextField(); + private final JButton outgoingBrowseButton = new JButton(".."); + + private final JCheckBox userOfflineCheckbox = new JCheckBox(); + private final JTextField userOfflineField = new JTextField(); + private final JButton offlineBrowseButton = new JButton(".."); + + private final JCheckBox incomingInvitationBox = new JCheckBox(); + private final JTextField incomingInvitationField = new JTextField(); + private final JButton incomingInvitationBrowseButton = new JButton(".."); + + private final JCheckBox chatRequestBox = new JCheckBox(); + private final JTextField chatRequestSound = new JTextField(); + private final JButton chatRequestBrowseButton = new JButton(".."); + + public SoundPanel() { + setLayout(new GridBagLayout()); + + setBorder(BorderFactory.createTitledBorder(Res.getString("title.sound.preferences"))); + // Add ResourceUtils + ResourceUtils.resButton(incomingMessageBox, Res.getString("checkbox.play.sound.on.new.message")); + ResourceUtils.resButton(outgoingMessageBox, Res.getString("checkbox.play.sound.on.outgoing.message")); + ResourceUtils.resButton(userOfflineCheckbox, Res.getString("checkbox.play.sound.when.offline")); + ResourceUtils.resButton(incomingInvitationBox, Res.getString("checkbox.play.sound.on.invitation")); + ResourceUtils.resButton(chatRequestBox, Res.getString("checkbox.play.sound.chat_request")); + + Insets padding = new Insets(5, 5, 5, 5); + // Handle incoming sounds + add(incomingMessageBox, new GridBagConstraints(0, 0, 1, 1, 0, 0, NORTHWEST, NONE, padding, 0, 0)); + add(incomingMessageSound, new GridBagConstraints(0, 1, 1, 1, 1, 0, NORTHWEST, HORIZONTAL, padding, 0, 0)); + add(incomingBrowseButton, new GridBagConstraints(1, 1, 1, 1, 0, 0, NORTHWEST, NONE, padding, 0, 0)); + + // Handle sending sounds + add(outgoingMessageBox, new GridBagConstraints(0, 2, 1, 1, 0, 0, NORTHWEST, NONE, padding, 0, 0)); + add(outgoingMessageSound, new GridBagConstraints(0, 3, 1, 1, 1, 0, NORTHWEST, HORIZONTAL, padding, 0, 0)); + add(outgoingBrowseButton, new GridBagConstraints(1, 3, 1, 1, 0, 0, NORTHWEST, NONE, padding, 0, 0)); + + // Handle User Online Sound + add(userOfflineCheckbox, new GridBagConstraints(0, 4, 1, 1, 0, 0, NORTHWEST, NONE, padding, 0, 0)); + add(userOfflineField, new GridBagConstraints(0, 5, 1, 1, 1, 0, NORTHWEST, HORIZONTAL, padding, 0, 0)); + add(offlineBrowseButton, new GridBagConstraints(1, 5, 1, 1, 0, 0, NORTHWEST, NONE, padding, 0, 0)); + + // Handle Invitation Sound + add(incomingInvitationBox, new GridBagConstraints(0, 6, 1, 1, 0, 0, NORTHWEST, NONE, padding, 0, 0)); + add(incomingInvitationField, new GridBagConstraints(0, 7, 1, 1, 1, 0, NORTHWEST, HORIZONTAL, padding, 0, 0)); + add(incomingInvitationBrowseButton, new GridBagConstraints(1, 7, 1, 1, 0, 0, NORTHWEST, NONE, padding, 0, 0)); + // Handle Chat Request Sound + add(chatRequestBox, new GridBagConstraints(0, 8, 1, 1, 0, 0, NORTHWEST, NONE, padding, 0, 0)); + add(chatRequestSound, new GridBagConstraints(0, 9, 1, 1, 1, 0, NORTHWEST, HORIZONTAL, padding, 0, 0)); + add(chatRequestBrowseButton, new GridBagConstraints(1, 9, 1, 1, 0, 1, NORTHWEST, NONE, padding, 0, 0)); + + incomingBrowseButton.addActionListener( e -> pickFile(Res.getString("title.choose.incoming.sound"), incomingMessageSound) ); + + + outgoingBrowseButton.addActionListener( e -> pickFile(Res.getString("title.choose.outgoing.sound"), outgoingMessageSound) ); + + offlineBrowseButton.addActionListener( e -> pickFile(Res.getString("title.choose.offline.sound"), userOfflineField) ); + + incomingInvitationBrowseButton.addActionListener( e -> pickFile(Res.getString("title.choose.incoming.sound"), incomingInvitationField) ); + + chatRequestBrowseButton.addActionListener( e -> pickFile(Res.getString("title.choose.chat_request.sound"), chatRequestSound) ); + + } + + public void setIncomingMessageSound(String path) { + incomingMessageSound.setText(path); + } + + public void setOutgoingMessageSound(String path) { + outgoingMessageSound.setText(path); + } + + public void setOfflineSound(String path) { + userOfflineField.setText(path); + } + + public void playIncomingSound(boolean play) { + incomingMessageBox.setSelected(play); + } + + public void playOutgoingSound(boolean play) { + outgoingMessageBox.setSelected(play); + } + + public void playOfflineSound(boolean play) { + userOfflineCheckbox.setSelected(play); + } + + + public String getIncomingSound() { + return incomingMessageSound.getText(); + } + + public boolean playIncomingSound() { + return incomingMessageBox.isSelected(); + } + + public boolean playOutgoingSound() { + return outgoingMessageBox.isSelected(); + } + + public String getOutgoingSound() { + return outgoingMessageSound.getText(); + } + + public boolean playOfflineSound() { + return userOfflineCheckbox.isSelected(); + } + + public String getOfflineSound() { + return userOfflineField.getText(); + } + + public void setInvitationSound(String invitationSound) { + incomingInvitationField.setText(invitationSound); + } + + public String getInvitationSound() { + return incomingInvitationField.getText(); + } + + public void setPlayInvitationSound(boolean play) { + incomingInvitationBox.setSelected(play); + } + + public boolean playInvitationSound() { + return incomingInvitationBox.isSelected(); + } + + public String getChatRequestSound() { + return chatRequestSound.getText(); + } + + public void setChatRequestSound(String sound) { + chatRequestSound.setText(sound); + } + + public boolean isPlayChatRequestSound() { + return chatRequestBox.isSelected(); + } + + public void setPlayChatRequestSound(boolean play) { + chatRequestBox.setSelected(play); + } + + private void pickFile(String title, JTextField field) { + JFileChooser fc = new JFileChooser(); + fc.setFileFilter(new FileNameExtensionFilter(Res.getString("file.type.sound"), "wav")); + if (Spark.isWindows()) { + fc.setFileSystemView(new WindowsFileSystemView()); + } + fc.setDialogTitle(title); + if (!field.getText().isEmpty()) { + fc.setSelectedFile(new File(field.getText())); + } + + if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + File file = fc.getSelectedFile(); + try { + field.setText(file.getCanonicalPath()); + } + catch (IOException e) { + Log.error(e); + } + } + } + } + + private File getSoundSettingsFile() { + File file = Spark.getSparkUserHome(); + if (!file.exists()) { + file.mkdirs(); + } + return new File(file, "sound-settings.xml"); + } + + private void saveSoundsFile() { + try { + FileWriter writer = new FileWriter(getSoundSettingsFile()); + getXStream().toXML(preferences, writer); + } + catch (Exception e) { + Log.error("Error saving sound settings.", e); + } + } + + public SoundPreferences getPreferences() { + if (preferences == null) { + load(); + } + return preferences; + } + + @Override + public void shutdown() { + + } + + private XStream getXStream() { + if (xstream == null) { + xstream = new XStream(); + xstream.allowTypes(new Class[]{SoundPreferences.class}); + xstream.alias("sounds", SoundPreferences.class); + xstream.ignoreUnknownElements(); + } + return xstream; + } + +} diff --git a/src/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPreferences.java b/core/src/main/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPreferences.java similarity index 84% rename from src/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPreferences.java rename to core/src/main/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPreferences.java index 59581439e..9ff9c6ef0 100644 --- a/src/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPreferences.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPreferences.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,11 +28,13 @@ public class SoundPreferences { private String incomingSound; private String offlineSound; private String incomingInvitationSound; + private String chatRequestSound; private boolean playOutgoingSound = false; private boolean playIncomingSound = false; private boolean playOfflineSound = false; private boolean playIncomingInvitationSound = false; + private boolean playChatRequestSound = false; public SoundPreferences() { // Set initial sounds @@ -45,6 +43,7 @@ public SoundPreferences() { incomingSound = new File(Spark.getResourceDirectory(), "sounds/incoming.wav").getCanonicalPath(); incomingInvitationSound = new File(Spark.getResourceDirectory(), "sounds/incoming.wav").getCanonicalPath(); offlineSound = new File(Spark.getResourceDirectory(), "sounds/presence_changed.wav").getCanonicalPath(); + chatRequestSound = new File(Spark.getResourceDirectory(), "sounds/chat_request.wav").getCanonicalPath(); } catch (IOException e) { Log.error(e); @@ -116,4 +115,20 @@ public boolean playIncomingInvitationSound() { public void setPlayIncomingInvitationSound(boolean play) { this.playIncomingInvitationSound = play; } + + public String getChatRequestSound() { + return chatRequestSound; + } + + public void setChatRequestSound(String chatRequestSound) { + this.chatRequestSound = chatRequestSound; + } + + public boolean isPlayChatRequestSound() { + return playChatRequestSound; + } + + public void setPlayChatRequestSound(boolean playChatRequestSound) { + this.playChatRequestSound = playChatRequestSound; + } } diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/profile/AvatarPanel.java b/core/src/main/java/org/jivesoftware/sparkimpl/profile/AvatarPanel.java new file mode 100644 index 000000000..0d6d9135b --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/profile/AvatarPanel.java @@ -0,0 +1,226 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.profile; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; + +import net.coobird.thumbnailator.Thumbnails; +import org.jivesoftware.sparkimpl.settings.Sizes; + +import javax.imageio.ImageIO; +import javax.swing.*; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dialog; +import java.awt.FileDialog; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Image; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; + +import static org.apache.commons.lang3.StringUtils.endsWithAny; + +/** + * UI to view/edit avatar. + */ +public class AvatarPanel extends JPanel implements ActionListener { + private final JLabel avatar; + private byte[] bytes; + final JButton browseButton = new JButton(); + final JButton clearButton = new JButton(); + private FileDialog fileChooser; + + private Dialog dlg; + + public AvatarPanel() { + setLayout(new GridBagLayout()); + final JLabel photo = new JLabel(Res.getString("label.avatar")); + + avatar = new JLabel(); + + add(photo, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(avatar, new GridBagConstraints(1, 0, 1, 2, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(browseButton, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(clearButton, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + + browseButton.addActionListener(this); + + // Add ResourceUtils + ResourceUtils.resButton(browseButton, Res.getString("button.browse")); + ResourceUtils.resButton(clearButton, Res.getString("button.clear")); + + clearButton.addActionListener(actionEvent -> { + avatar.setIcon(null); + bytes = null; + avatar.setBorder(null); + }); + + avatar.setText(Res.getString("message.no.avatar.found")); + + GraphicUtils.makeSameSize(browseButton, clearButton); + } + + /** + * Sets if the Avatar can be edited. + */ + public void setEditable(boolean editable) { + browseButton.setVisible(editable); + clearButton.setVisible(editable); + } + + /** + * Sets the displayable icon with the user's avatar. + */ + public void setAvatar(ImageIcon icon) { + avatar.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); + if (icon.getIconHeight() > Sizes.Avatar.HOVER_BIG || icon.getIconWidth() > Sizes.Avatar.HOVER_BIG) { + avatar.setIcon(new ImageIcon(icon.getImage().getScaledInstance(-1, Sizes.Avatar.HOVER_BIG, Image.SCALE_SMOOTH))); + } else { + avatar.setIcon(icon); + } + avatar.setText(""); + } + + /** + * Sets the avatar bytes. + */ + public void setAvatarBytes(byte[] bytes) { + this.bytes = bytes; + } + + /** + * Returns the avatars bytes. + */ + public byte[] getAvatarBytes() { + return bytes; + } + + /** + * Returns the Icon representation of the Avatar. + */ + public Icon getAvatar() { + return avatar.getIcon(); + } + + @Override + public void actionPerformed(ActionEvent e) { + // init file chooser (if not already done) + initFileChooser(); + fileChooser.setVisible(true); + + final File[] files = fileChooser.getFiles(); + if (files.length == 0) { + // no selection + return; + } + File file = files[0]; // Single-file selection is used. Using the first array item is safe. + changeAvatar(file, this); + } + + private void changeAvatar(final File selectedFile, final Component parent) { + SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + BufferedImage avatarSquare = ImageCropDialog.selectSquareFromPhoto(selectedFile, dlg); + if (avatarSquare == null) { + return null; + } + return resizeImage(avatarSquare); + } + + @Override + public void finished() { + BufferedImage avatarImage = (BufferedImage) get(); + if (avatarImage == null) { + return; + } + String message = ""; + int finalImageWidth = avatarImage.getWidth(); + int finalImageHeight = avatarImage.getHeight(); + boolean showWarning = false; + if (finalImageWidth < Sizes.Avatar.PROFILE_MIN && finalImageHeight < Sizes.Avatar.PROFILE_MIN) { + message += "\u2022 " + Res.getString("message.image.small.resolution") + "\n"; + showWarning = true; + } + if (showWarning) { + JOptionPane.showMessageDialog(parent, message, Res.getString("title.warning"), JOptionPane.WARNING_MESSAGE); + } + //convert BufferedImage to bytes + setAvatarBytes(imageToPng(avatarImage)); + setAvatar(new ImageIcon(avatarImage)); + } + }; + worker.start(); + } + + private byte[] imageToPng(BufferedImage avatarImage) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + ImageIO.write(avatarImage, "png", baos); + } catch (IOException ignored) { + } + return baos.toByteArray(); + } + + public void allowEditing(boolean allowEditing) { + Component[] comps = getComponents(); + if (comps != null) { + for (Component comp : comps) { + if (comp instanceof JTextField) { + ((JTextField) comp).setEditable(allowEditing); + } + } + } + } + + public void initFileChooser() { + if (fileChooser == null) { + fileChooser = new FileDialog(dlg, "Choose Avatar", FileDialog.LOAD); + fileChooser.setFilenameFilter((dir, name) -> endsWithAny(name.toLowerCase(), ".jpeg", ".jpg", ".gif", ".png")); + } + } + + public void setParentDialog(Dialog dialog) { + this.dlg = dialog; + } + + /** + * Resize images larger than 96 pixels (see XEP‑0153). + * Returns a modified image as BufferedImage. + */ + private BufferedImage resizeImage(BufferedImage selectedFile) { + BufferedImage resizedImage = null; + try { + resizedImage = Thumbnails.of(selectedFile) + .size(Sizes.Avatar.PROFILE, Sizes.Avatar.PROFILE) + .asBufferedImage(); + } catch (IOException ex) { + Log.error(ex); + } + return resizedImage; + } +} diff --git a/src/java/org/jivesoftware/sparkimpl/profile/BusinessPanel.java b/core/src/main/java/org/jivesoftware/sparkimpl/profile/BusinessPanel.java similarity index 90% rename from src/java/org/jivesoftware/sparkimpl/profile/BusinessPanel.java rename to core/src/main/java/org/jivesoftware/sparkimpl/profile/BusinessPanel.java index dea899fc1..29c21a61a 100644 --- a/src/java/org/jivesoftware/sparkimpl/profile/BusinessPanel.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/profile/BusinessPanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,21 +34,21 @@ public class BusinessPanel extends JPanel { private static final long serialVersionUID = -6319059605447012843L; - private JTextField companyField = new JTextField(); - private JTextField cityField = new JTextField(); - private JTextField stateField = new JTextField(); - private JTextField zipCodeField = new JTextField(); - private JTextField countryField = new JTextField(); - private JTextField streetField = new JTextField(); + private final JTextField companyField = new JTextField(); + private final JTextField cityField = new JTextField(); + private final JTextField stateField = new JTextField(); + private final JTextField zipCodeField = new JTextField(); + private final JTextField countryField = new JTextField(); + private final JTextField streetField = new JTextField(); - private JTextField jobTitleField = new JTextField(); - private JTextField departmentField = new JTextField(); - private JTextField phoneField = new JTextField(); - private JTextField faxField = new JTextField(); - private JTextField pagerField = new JTextField(); - private JTextField mobileField = new JTextField(); - private JTextField webPageField = new JTextField(); + private final JTextField jobTitleField = new JTextField(); + private final JTextField departmentField = new JTextField(); + private final JTextField phoneField = new JTextField(); + private final JTextField faxField = new JTextField(); + private final JTextField pagerField = new JTextField(); + private final JTextField mobileField = new JTextField(); + private final JTextField webPageField = new JTextField(); public BusinessPanel() { this.setLayout(new GridBagLayout()); @@ -121,7 +117,7 @@ public BusinessPanel() { this.add(webPageField, new GridBagConstraints(3, 6, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - final Component order[] = new Component[] { + final Component[] order = new Component[] { companyField, streetField,cityField, stateField, zipCodeField,countryField, jobTitleField,departmentField,phoneField, @@ -241,14 +237,12 @@ public String getWebPage() { public void allowEditing(boolean allowEditing) { Component[] comps = getComponents(); if (comps != null) { - final int no = comps.length; - for (int i = 0; i < no; i++) { - Component comp = comps[i]; + for (Component comp : comps) { if (comp instanceof JTextField) { - ((JTextField)comp).setEditable(allowEditing); + ((JTextField) comp).setEditable(allowEditing); } } } } -} \ No newline at end of file +} diff --git a/src/java/org/jivesoftware/sparkimpl/profile/HomePanel.java b/core/src/main/java/org/jivesoftware/sparkimpl/profile/HomePanel.java similarity index 90% rename from src/java/org/jivesoftware/sparkimpl/profile/HomePanel.java rename to core/src/main/java/org/jivesoftware/sparkimpl/profile/HomePanel.java index ddc5283ed..7f25b5dcc 100644 --- a/src/java/org/jivesoftware/sparkimpl/profile/HomePanel.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/profile/HomePanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,18 +34,18 @@ public class HomePanel extends JPanel { private static final long serialVersionUID = -838061087276345124L; - private JTextField cityField = new JTextField(); - private JTextField stateField = new JTextField(); - private JTextField zipCodeField = new JTextField(); - private JTextField countryField = new JTextField(); - private JTextField streetField = new JTextField(); + private final JTextField cityField = new JTextField(); + private final JTextField stateField = new JTextField(); + private final JTextField zipCodeField = new JTextField(); + private final JTextField countryField = new JTextField(); + private final JTextField streetField = new JTextField(); - private JTextField phoneField = new JTextField(); - private JTextField faxField = new JTextField(); - private JTextField pagerField = new JTextField(); - private JTextField mobileField = new JTextField(); - private JTextField webPageField = new JTextField(); + private final JTextField phoneField = new JTextField(); + private final JTextField faxField = new JTextField(); + private final JTextField pagerField = new JTextField(); + private final JTextField mobileField = new JTextField(); + private final JTextField webPageField = new JTextField(); public HomePanel() { this.setLayout(new GridBagLayout()); @@ -101,7 +97,7 @@ public HomePanel() { this.add(pagerField, new GridBagConstraints(3, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); this.add(mobileField, new GridBagConstraints(3, 3, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - final Component order[] = new Component[] { + final Component[] order = new Component[] { streetField, cityField, stateField, zipCodeField,countryField, phoneField, faxField, pagerField, mobileField, @@ -196,13 +192,11 @@ public String getWebPage() { public void allowEditing(boolean allowEditing) { Component[] comps = getComponents(); if (comps != null) { - final int no = comps.length; - for (int i = 0; i < no; i++) { - Component comp = comps[i]; + for (Component comp : comps) { if (comp instanceof JTextField) { - ((JTextField)comp).setEditable(allowEditing); + ((JTextField) comp).setEditable(allowEditing); } } } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/profile/ImageCropDialog.java b/core/src/main/java/org/jivesoftware/sparkimpl/profile/ImageCropDialog.java new file mode 100644 index 000000000..cae485a5e --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/profile/ImageCropDialog.java @@ -0,0 +1,220 @@ +package org.jivesoftware.sparkimpl.profile; + +import org.jivesoftware.resource.Res; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +public class ImageCropDialog { + public static BufferedImage selectSquareFromPhoto(File file, Dialog parent) { + BufferedImage originalImage; + try { + originalImage = ImageIO.read(file); + } catch (IOException e) { + return null; + } + if (originalImage == null) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(parent, "Please choose a valid image file.", Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + return null; + } + BufferedImage[] croppedImage = {null}; + JDialog cropDialog = new JDialog(parent, Res.getString("title.avatar.crop"), true); + cropDialog.setLayout(new BorderLayout()); + + // Calculate a scaling factor to fit the image in the dialog + int maxDisplayWidth = 800; + int maxDisplayHeight = 600; + double scaleX = (double) maxDisplayWidth / originalImage.getWidth(); + double scaleY = (double) maxDisplayHeight / originalImage.getHeight(); + double scale = Math.min(Math.min(scaleX, scaleY), 1.0); // Don't scale up + int scaledWidth = (int) (originalImage.getWidth() * scale); + int scaledHeight = (int) (originalImage.getHeight() * scale); + // Create a scaled image for display + BufferedImage displayImage = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2 = displayImage.createGraphics(); + g2.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null); + g2.dispose(); + // Calculate initial square size (smaller dimension) in scaled coordinates + int initialSize = Math.min(scaledWidth, scaledHeight); + Rectangle cropRect = new Rectangle( + (scaledWidth - initialSize) / 2, + (scaledHeight - initialSize) / 2, + initialSize, + initialSize + ); + // Panel to display image with crop rectangle + JPanel imagePanel = new JPanel() { + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + g.drawImage(displayImage, 0, 0, this); + // Draw crop rectangle + Graphics2D g2d = (Graphics2D) g; + g2d.setColor(new Color(255, 255, 255, 100)); + g2d.fillRect(0, 0, scaledWidth, cropRect.y); + g2d.fillRect(0, cropRect.y, cropRect.x, scaledHeight - cropRect.y); + g2d.fillRect(cropRect.x + cropRect.width, cropRect.y, + scaledWidth - (cropRect.x + cropRect.width), scaledHeight - cropRect.y); + g2d.fillRect(cropRect.x, cropRect.y + cropRect.height, cropRect.width, + scaledHeight - (cropRect.y + cropRect.height)); + g2d.setColor(Color.BLACK); + g2d.setStroke(new BasicStroke(3)); + g2d.drawRect(cropRect.x, cropRect.y, cropRect.width, cropRect.height); + // Draw resize handles at all four corners (gray) + g2d.setColor(Color.GRAY); + g2d.fillRect(cropRect.x - 5, cropRect.y - 5, 10, 10); // top-left + g2d.fillRect(cropRect.x + cropRect.width - 5, cropRect.y - 5, 10, 10); // top-right + g2d.fillRect(cropRect.x - 5, cropRect.y + cropRect.height - 5, 10, 10); // bottom-left + g2d.fillRect(cropRect.x + cropRect.width - 5, cropRect.y + cropRect.height - 5, 10, 10); // bottom-right + } + }; + + int[] dragStart = {0, 0}; + boolean[] isDragging = {false}; + boolean[] isResizing = {false}; + int[] resizeCorner = {-1}; // -1: none, 0: top-left, 1: top-right, 2: bottom-left, 3: bottom-right + // Dragging and resizing of crop rectangle + MouseAdapter mouseAdapter = new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + dragStart[0] = e.getX(); + dragStart[1] = e.getY(); + // Check if clicking on any of the four resize handles + Rectangle topLeft = new Rectangle(cropRect.x - 5, cropRect.y - 5, 10, 10); + Rectangle topRight = new Rectangle(cropRect.x + cropRect.width - 5, cropRect.y - 5, 10, 10); + Rectangle bottomLeft = new Rectangle(cropRect.x - 5, cropRect.y + cropRect.height - 5, 10, 10); + Rectangle bottomRight = new Rectangle(cropRect.x + cropRect.width - 5, cropRect.y + cropRect.height - 5, 10, 10); + // Check for a resize handle or dragging within the crop rectangle + if (topLeft.contains(e.getPoint())) { + isResizing[0] = true; + resizeCorner[0] = 0; + } else if (topRight.contains(e.getPoint())) { + isResizing[0] = true; + resizeCorner[0] = 1; + } else if (bottomLeft.contains(e.getPoint())) { + isResizing[0] = true; + resizeCorner[0] = 2; + } else if (bottomRight.contains(e.getPoint())) { + isResizing[0] = true; + resizeCorner[0] = 3; + } else if (cropRect.contains(e.getPoint())) { + isDragging[0] = true; + } + } + + @Override + public void mouseReleased(MouseEvent e) { + isDragging[0] = false; + isResizing[0] = false; + resizeCorner[0] = -1; + } + + @Override + public void mouseDragged(MouseEvent e) { + int dx = e.getX() - dragStart[0]; + int dy = e.getY() - dragStart[1]; + if (isResizing[0]) { + // Resize (maintain square) from different corners + if (resizeCorner[0] == 0) { // top-left + int change = -Math.min(dx, dy); + int newSize = Math.max(50, cropRect.width + change); + int newX = cropRect.x + cropRect.width - newSize; + int newY = cropRect.y + cropRect.height - newSize; + if (newX >= 0 && newY >= 0) { + cropRect.x = newX; + cropRect.y = newY; + cropRect.width = newSize; + cropRect.height = newSize; + dragStart[0] = e.getX(); + dragStart[1] = e.getY(); + } + } else if (resizeCorner[0] == 1) { // top-right + int change = Math.max(dx, -dy); + int newSize = Math.max(50, cropRect.width + change); + int newY = cropRect.y + cropRect.height - newSize; + if (cropRect.x + newSize <= scaledWidth && newY >= 0) { + cropRect.y = newY; + cropRect.width = newSize; + cropRect.height = newSize; + dragStart[0] = e.getX(); + dragStart[1] = e.getY(); + } + } else if (resizeCorner[0] == 2) { // bottom-left + int change = Math.max(-dx, dy); + int newSize = Math.max(50, cropRect.width + change); + int newX = cropRect.x + cropRect.width - newSize; + if (newX >= 0 && cropRect.y + newSize <= scaledHeight) { + cropRect.x = newX; + cropRect.width = newSize; + cropRect.height = newSize; + dragStart[0] = e.getX(); + dragStart[1] = e.getY(); + } + } else if (resizeCorner[0] == 3) { // bottom-right + int delta2 = Math.max(dx, dy); + int newSize = Math.max(50, cropRect.width + delta2); + if (cropRect.x + newSize <= scaledWidth && + cropRect.y + newSize <= scaledHeight) { + cropRect.width = newSize; + cropRect.height = newSize; + dragStart[0] = e.getX(); + dragStart[1] = e.getY(); + } + } + } else if (isDragging[0]) { + // Move rectangle + int newX = cropRect.x + dx; + int newY = cropRect.y + dy; + // Ensure within bounds + if (newX >= 0 && newX + cropRect.width <= scaledWidth) { + cropRect.x = newX; + dragStart[0] = e.getX(); + } + if (newY >= 0 && newY + cropRect.height <= scaledHeight) { + cropRect.y = newY; + dragStart[1] = e.getY(); + } + } + imagePanel.repaint(); + } + }; + + imagePanel.addMouseListener(mouseAdapter); + imagePanel.addMouseMotionListener(mouseAdapter); + imagePanel.setPreferredSize(new Dimension(scaledWidth, scaledHeight)); + // Button panel + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + JButton cropButton = new JButton(Res.getString("button.crop")); + JButton cancelButton = new JButton(Res.getString("button.cancel")); + + cropButton.addActionListener(e -> { + // Convert scaled coordinates back to original image coordinates + int originalX = (int) (cropRect.x / scale); + int originalY = (int) (cropRect.y / scale); + int originalWidth = (int) (cropRect.width / scale); + int originalHeight = (int) (cropRect.height / scale); + croppedImage[0] = originalImage.getSubimage(originalX, originalY, originalWidth, originalHeight); + cropDialog.dispose(); + }); + + cancelButton.addActionListener(e -> cropDialog.dispose()); + + buttonPanel.add(cropButton); + buttonPanel.add(cancelButton); + + cropDialog.add(new JScrollPane(imagePanel), BorderLayout.CENTER); + cropDialog.add(buttonPanel, BorderLayout.SOUTH); + cropDialog.pack(); + cropDialog.setLocationRelativeTo(parent); + cropDialog.setVisible(true); + + return croppedImage[0]; + } +} diff --git a/src/java/org/jivesoftware/sparkimpl/profile/PersonalPanel.java b/core/src/main/java/org/jivesoftware/sparkimpl/profile/PersonalPanel.java similarity index 91% rename from src/java/org/jivesoftware/sparkimpl/profile/PersonalPanel.java rename to core/src/main/java/org/jivesoftware/sparkimpl/profile/PersonalPanel.java index ef43a7186..b0ed4c702 100644 --- a/src/java/org/jivesoftware/sparkimpl/profile/PersonalPanel.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/profile/PersonalPanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,13 +31,13 @@ public class PersonalPanel extends JPanel { private static final long serialVersionUID = 8348926698365178921L; - private JTextField firstNameField; - private JTextField middleNameField; - private JTextField lastNameField; - private JTextField nicknameField; - private JTextField emailAddressField; - private JTextField jidField; - private JLabel jidLabel = new JLabel(); + private final JTextField firstNameField; + private final JTextField middleNameField; + private final JTextField lastNameField; + private final JTextField nicknameField; + private final JTextField emailAddressField; + private final JTextField jidField; + private final JLabel jidLabel = new JLabel(); public PersonalPanel() { @@ -151,11 +147,9 @@ public void showJID(boolean show) { public void allowEditing(boolean allowEditing) { Component[] comps = getComponents(); if (comps != null) { - final int no = comps.length; - for (int i = 0; i < no; i++) { - Component comp = comps[i]; + for (Component comp : comps) { if (comp instanceof JTextField) { - ((JTextField)comp).setEditable(allowEditing); + ((JTextField) comp).setEditable(allowEditing); } } } diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/profile/VCardEditor.java b/core/src/main/java/org/jivesoftware/sparkimpl/profile/VCardEditor.java new file mode 100644 index 000000000..2cd95bbfb --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/profile/VCardEditor.java @@ -0,0 +1,500 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.sparkimpl.profile; + +import java.awt.*; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.UIManager; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smackx.vcardtemp.packet.VCard; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.TitlePanel; +import org.jivesoftware.spark.ui.VCardViewer; +import org.jivesoftware.spark.ui.status.StatusBar; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettingsManager; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; +import org.jivesoftware.sparkimpl.settings.Sizes; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.impl.JidCreate; +import org.jivesoftware.resource.Default; + +/** + * Handles the UI for viewing and editing of VCard information. + */ +public class VCardEditor { + + private BusinessPanel businessPanel; + private PersonalPanel personalPanel; + private HomePanel homePanel; + private AvatarPanel avatarPanel; + private JLabel avatarLabel; + //TODO REMOVE + @SuppressWarnings("unused") + private VCard _vcard; + + /** + * Displays the VCard for an individual. + * + * @param vCard the users vcard. + * @param parent the parent component, used for location. + */ + public void editProfile(final VCard vCard, JComponent parent) { + JTabbedPane tabbedPane = new JTabbedPane(); + // Initialize Panels + personalPanel = new PersonalPanel(); + personalPanel.showJID(false); + + tabbedPane.addTab(Res.getString("tab.personal"), personalPanel); + + businessPanel = new BusinessPanel(); + tabbedPane.addTab(Res.getString("tab.business"), businessPanel); + + homePanel = new HomePanel(); + tabbedPane.addTab(Res.getString("tab.home"), homePanel); + + // See if we should remove the Avatar tab in profile dialog + if (!Default.getBoolean(Default.DISABLE_AVATAR_TAB) && Enterprise.containsFeature(Enterprise.AVATAR_TAB_FEATURE)) { + avatarPanel = new AvatarPanel(); + tabbedPane.addTab(Res.getString("tab.avatar"), avatarPanel); + } + + // Build the UI + buildUI(vCard); + + ImageIcon icon = VCardManager.getAvatarIcon(vCard); + if (icon == null) { + icon = SparkRes.getImageIcon(SparkRes.Icon.BLANK_24x24); + } + + // Create the title panel for this dialog + TitlePanel titlePanel = new TitlePanel(Res.getString("title.edit.profile"), + Res.getString("message.save.profile"), icon, true); + + // Construct main panel w/ layout. + JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BorderLayout()); + mainPanel.add(titlePanel, BorderLayout.NORTH); + + // The user should only be able to close this dialog. + Object[] options = { + Res.getString("save"), + Res.getString("cancel") + }; + JOptionPane pane = new JOptionPane(tabbedPane, JOptionPane.PLAIN_MESSAGE, + JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); + + mainPanel.add(pane, BorderLayout.CENTER); + + JOptionPane p = new JOptionPane(); + JDialog dlg = p.createDialog(parent, Res.getString("title.profile.information")); + dlg.setModal(false); + + dlg.pack(); + dlg.setResizable(true); + dlg.setContentPane(mainPanel); + + Rectangle bounds = LayoutSettingsManager.getLayoutSettings().getVCardEditorBounds(); + if (bounds == null || bounds.width <= 0 || bounds.height <= 0) { + // Use default settings. + dlg.setLocationRelativeTo(parent); + dlg.setSize(600, 400); + } else { + dlg.setBounds(bounds); + } + + dlg.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + LayoutSettingsManager.getLayoutSettings().setVCardEditorBounds(dlg.getBounds()); + } + + @Override + public void componentMoved(ComponentEvent e) { + LayoutSettingsManager.getLayoutSettings().setVCardEditorBounds(dlg.getBounds()); + } + }); + + PropertyChangeListener changeListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent e) { + String value = (String) pane.getValue(); + if (Res.getString("cancel").equals(value)) { + pane.removePropertyChangeListener(this); + dlg.dispose(); + } else if (Res.getString("save").equals(value)) { + pane.removePropertyChangeListener(this); + dlg.dispose(); + saveVCard(); + } + } + }; + + pane.addPropertyChangeListener(changeListener); + + // See if we should remove the Avatar tab in the profile dialog + if (!Default.getBoolean(Default.DISABLE_AVATAR_TAB) && Enterprise.containsFeature(Enterprise.AVATAR_TAB_FEATURE)) { + avatarPanel.setParentDialog(dlg); + } + + dlg.setVisible(true); + dlg.toFront(); + dlg.requestFocus(); + + personalPanel.focus(); + } + + /** + * Displays the VCard for an individual. + * + * @param vCard the users vcard. + * @param parent the parent component, used for location. + */ + public void viewFullProfile(final VCard vCard, JComponent parent) { + JTabbedPane tabbedPane = new JTabbedPane(); + + // Initialize Panels + personalPanel = new PersonalPanel(); + personalPanel.allowEditing(false); + personalPanel.showJID(false); + + tabbedPane.addTab(Res.getString("tab.personal"), personalPanel); + + businessPanel = new BusinessPanel(); + businessPanel.allowEditing(false); + tabbedPane.addTab(Res.getString("tab.business"), businessPanel); + + homePanel = new HomePanel(); + homePanel.allowEditing(false); + tabbedPane.addTab(Res.getString("tab.home"), homePanel); + + // See if we should remove the Avatar tab in profile dialog + if (!Default.getBoolean(Default.DISABLE_AVATAR_TAB) && Enterprise.containsFeature(Enterprise.AVATAR_TAB_FEATURE)) { + avatarPanel = new AvatarPanel(); + avatarPanel.allowEditing(false); + tabbedPane.addTab(Res.getString("tab.avatar"), avatarPanel); + } + + // Build the UI + buildUI(vCard); + + ImageIcon icon = VCardManager.getAvatarIcon(vCard); + if (icon == null) { + icon = SparkRes.getImageIcon(SparkRes.Icon.BLANK_24x24); + } + + // Create the title panel for this dialog + TitlePanel titlePanel = new TitlePanel(Res.getString("title.profile.information"), + "", icon, true); + + // Construct main panel w/ layout. + JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BorderLayout()); + mainPanel.add(titlePanel, BorderLayout.NORTH); + + // The user should only be able to close this dialog. + Object[] options = { + Res.getString("close"), + Res.getString("refresh") + }; + JOptionPane pane = new JOptionPane(tabbedPane, JOptionPane.PLAIN_MESSAGE, + JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); + + mainPanel.add(pane, BorderLayout.CENTER); + + JOptionPane p = new JOptionPane(); + JDialog dlg = p.createDialog(parent, Res.getString("title.profile.information")); + dlg.setModal(false); + + dlg.pack(); + dlg.setSize(600, 400); + dlg.setResizable(true); + dlg.setContentPane(mainPanel); + dlg.setLocationRelativeTo(parent); + PropertyChangeListener changeListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent e) { + Object o = pane.getValue(); + if (o instanceof Integer) { + pane.removePropertyChangeListener(this); + dlg.dispose(); + return; + } + + String value = (String) pane.getValue(); + if (Res.getString("close").equals(value)) { + pane.removePropertyChangeListener(this); + dlg.dispose(); + } + + if (Res.getString("refresh").equals(value)) { + VCardManager manager = SparkManager.getVCardManager(); + BareJid bareJid = JidCreate.bareFromOrThrowUnchecked(vCard.getJabberId()); + VCard card = manager.reloadVCard(bareJid); + fillUI(card); + } + + } + }; + + pane.addPropertyChangeListener(changeListener); + + dlg.setVisible(true); + dlg.toFront(); + dlg.requestFocus(); + + personalPanel.focus(); + } + + /** + * Displays a users profile. + * + * @param jid the jid of the user. + * @param vcard the users vcard. + * @param parent the parent component, used for location handling. + */ + public void displayProfile(final BareJid jid, VCard vcard, JComponent parent) { + VCardViewer viewer = new VCardViewer(jid); + JFrame dlg = new JFrame(Res.getString("title.view.profile.for", jid)); + + avatarLabel = new JLabel(); + avatarLabel.setHorizontalAlignment(JButton.RIGHT); + avatarLabel.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); + + // The user should only be able to close this dialog. + Object[] options = { + Res.getString("button.view.profile"), + Res.getString("close") + }; + JOptionPane pane = new JOptionPane(viewer, + JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, + options, options[0]); + + // mainPanel.add(pane, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, + // GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 5, 5), 0, 0)); + + dlg.setIconImage(SparkRes.getImageIcon(SparkRes.Icon.PROFILE_IMAGE_16x16).getImage()); + + dlg.pack(); + dlg.setSize(350, 250); + dlg.setResizable(true); + dlg.setContentPane(pane); + dlg.setLocationRelativeTo(parent); + + PropertyChangeListener changeListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent e) { + if (pane.getValue() instanceof Integer) { + pane.removePropertyChangeListener(this); + dlg.dispose(); + return; + } + String value = (String) pane.getValue(); + if (Res.getString("close").equals(value)) { + pane.removePropertyChangeListener(this); + dlg.dispose(); + } else if (Res.getString("button.view.profile").equals(value)) { + pane.setValue(JOptionPane.UNINITIALIZED_VALUE); + SparkManager.getVCardManager().viewFullProfile(jid, pane); + } + } + }; + + pane.addPropertyChangeListener(changeListener); + + dlg.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent keyEvent) { + if (keyEvent.getKeyChar() == KeyEvent.VK_ESCAPE) { + dlg.dispose(); + } + } + }); + + dlg.setVisible(true); + dlg.toFront(); + dlg.requestFocus(); + } + + /** + * Builds the UI based on a VCard. + */ + private void buildUI(VCard vcard) { + fillUI(vcard); + // Set Avatar + byte[] bytes = vcard.getAvatar(); + if (bytes != null && bytes.length > 0) { + ImageIcon icon = new ImageIcon(bytes); + // See if we should remove the Avatar tab in the profile dialog + if (!Default.getBoolean(Default.DISABLE_AVATAR_TAB) && Enterprise.containsFeature(Enterprise.AVATAR_TAB_FEATURE)) { + avatarPanel.setAvatar(icon); + avatarPanel.setAvatarBytes(bytes); + } + + if (avatarLabel != null) { + icon = GraphicUtils.scaleImageIcon(icon, Sizes.Avatar.VCARD, Sizes.Avatar.VCARD); + avatarLabel.setIcon(icon); + } + } + } + + private void fillUI(VCard vcard) { + personalPanel.setFirstName(vcard.getFirstName()); + personalPanel.setMiddleName(vcard.getMiddleName()); + personalPanel.setLastName(vcard.getLastName()); + personalPanel.setEmailAddress(vcard.getEmailHome()); + personalPanel.setNickname(vcard.getNickName()); + personalPanel.setJID(vcard.getJabberId()); + // Load business info + businessPanel.setCompany(vcard.getOrganization()); + businessPanel.setDepartment(vcard.getOrganizationUnit()); + businessPanel.setStreetAddress(vcard.getAddressFieldWork("STREET")); + businessPanel.setCity(vcard.getAddressFieldWork("LOCALITY")); + businessPanel.setState(vcard.getAddressFieldWork("REGION")); + businessPanel.setZipCode(vcard.getAddressFieldWork("PCODE")); + businessPanel.setCountry(vcard.getAddressFieldWork("CTRY")); + businessPanel.setJobTitle(vcard.getField("TITLE")); + businessPanel.setPhone(vcard.getPhoneWork("VOICE")); + businessPanel.setFax(vcard.getPhoneWork("FAX")); + businessPanel.setPager(vcard.getPhoneWork("PAGER")); + businessPanel.setMobile(vcard.getPhoneWork("CELL")); + businessPanel.setWebPage(vcard.getField("URL")); + // Load Home Info + homePanel.setStreetAddress(vcard.getAddressFieldHome("STREET")); + homePanel.setCity(vcard.getAddressFieldHome("LOCALITY")); + homePanel.setState(vcard.getAddressFieldHome("REGION")); + homePanel.setZipCode(vcard.getAddressFieldHome("PCODE")); + homePanel.setCountry(vcard.getAddressFieldHome("CTRY")); + homePanel.setPhone(vcard.getPhoneHome("VOICE")); + homePanel.setFax(vcard.getPhoneHome("FAX")); + homePanel.setPager(vcard.getPhoneHome("PAGER")); + homePanel.setMobile(vcard.getPhoneHome("CELL")); + } + + /** + * Saves the VCard. + */ + private void saveVCard() { + VCard vcard = new VCard(); + // Save personal info + vcard.setFirstName(personalPanel.getFirstName()); + vcard.setLastName(personalPanel.getLastName()); + vcard.setMiddleName(personalPanel.getMiddleName()); + vcard.setEmailHome(personalPanel.getEmailAddress()); + vcard.setNickName(personalPanel.getNickname()); + // Save business info + vcard.setOrganization(businessPanel.getCompany()); + vcard.setAddressFieldWork("STREET", businessPanel.getStreetAddress()); + vcard.setAddressFieldWork("LOCALITY", businessPanel.getCity()); + vcard.setAddressFieldWork("REGION", businessPanel.getState()); + vcard.setAddressFieldWork("PCODE", businessPanel.getZipCode()); + vcard.setAddressFieldWork("CTRY", businessPanel.getCountry()); + vcard.setField("TITLE", businessPanel.getJobTitle()); + vcard.setOrganizationUnit(businessPanel.getDepartment()); + vcard.setPhoneWork("VOICE", businessPanel.getPhone()); + vcard.setPhoneWork("FAX", businessPanel.getFax()); + vcard.setPhoneWork("PAGER", businessPanel.getPager()); + vcard.setPhoneWork("CELL", businessPanel.getMobile()); + vcard.setField("URL", businessPanel.getWebPage()); + // Save Home Info + vcard.setAddressFieldHome("STREET", homePanel.getStreetAddress()); + vcard.setAddressFieldHome("LOCALITY", homePanel.getCity()); + vcard.setAddressFieldHome("REGION", homePanel.getState()); + vcard.setAddressFieldHome("PCODE", homePanel.getZipCode()); + vcard.setAddressFieldHome("CTRY", homePanel.getCountry()); + vcard.setPhoneHome("VOICE", homePanel.getPhone()); + vcard.setPhoneHome("FAX", homePanel.getFax()); + vcard.setPhoneHome("PAGER", homePanel.getPager()); + vcard.setPhoneHome("CELL", homePanel.getMobile()); + + // Save Avatar + byte[] avatarBytes = null; + if (avatarPanel != null) { + avatarBytes = avatarPanel.getAvatarBytes(); + // If avatar was set, persist it in the vcard. + if (avatarBytes != null) { + vcard.setAvatar(avatarBytes); + } + } + + try { + // Save vcard on server + org.jivesoftware.smackx.vcardtemp.VCardManager smackVCardManager = org.jivesoftware.smackx.vcardtemp.VCardManager.getInstanceFor(SparkManager.getConnection()); + smackVCardManager.saveVCard(vcard); + // Save vcard on a client + VCardManager vcardManager = SparkManager.getVCardManager(); + vcardManager.setPersonalVCard(vcard); + // Notify users on avatar change + if (avatarBytes != null) { + Presence presence = SparkManager.getWorkspace().getStatusBar().getPresence(); + Presence newPresence = StanzaBuilder.buildPresence() + .ofType(presence.getType()) + .setStatus(presence.getStatus()) + .setPriority(presence.getPriority()) + .setMode(presence.getMode()) + .build(); + + // Change my own presence + SparkManager.getSessionManager().changePresence(newPresence); + // Change avatar in the status bar. + StatusBar statusBar = SparkManager.getWorkspace().getStatusBar(); + statusBar.setAvatar(new ImageIcon(vcard.getAvatar())); + } else { + String fullName = vcard.getField("FN"); + StatusBar statusBar = SparkManager.getWorkspace().getStatusBar(); + if (ModelUtil.hasLength(fullName)) { + statusBar.setNickname(fullName); + } + + statusBar.setAvatar(null); + } + + // Notify listeners + SparkManager.getVCardManager().notifyVCardListeners(); + } catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(SparkManager.getMainWindow(), + Res.getString("message.vcard.not.supported"), + Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + } + } + +} diff --git a/src/java/org/jivesoftware/sparkimpl/profile/VCardListener.java b/core/src/main/java/org/jivesoftware/sparkimpl/profile/VCardListener.java similarity index 94% rename from src/java/org/jivesoftware/sparkimpl/profile/VCardListener.java rename to core/src/main/java/org/jivesoftware/sparkimpl/profile/VCardListener.java index 19f4058ef..3b4585ef9 100644 --- a/src/java/org/jivesoftware/sparkimpl/profile/VCardListener.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/profile/VCardListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/profile/VCardManager.java b/core/src/main/java/org/jivesoftware/sparkimpl/profile/VCardManager.java new file mode 100644 index 000000000..aa92f2906 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/profile/VCardManager.java @@ -0,0 +1,849 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.profile; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.StanzaListener; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.filter.AndFilter; +import org.jivesoftware.smack.filter.StanzaFilter; +import org.jivesoftware.smack.filter.StanzaTypeFilter; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaError; +import org.jivesoftware.smack.packet.XmlElement; +import org.jivesoftware.smack.provider.ProviderManager; +import org.jivesoftware.smack.xml.SmackXmlParser; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smackx.vcardtemp.packet.VCard; +import org.jivesoftware.smackx.vcardtemp.provider.VCardProvider; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.spark.util.*; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; +import org.jivesoftware.sparkimpl.profile.ext.JabberAvatarExtension; +import org.jivesoftware.sparkimpl.profile.ext.VCardUpdateExtension; +import org.jivesoftware.sparkimpl.settings.Sizes; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; +import org.jxmpp.util.XmppStringUtils; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.*; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.time.Duration; +import java.time.Instant; +import java.util.*; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.LinkedBlockingQueue; + +/** + * VCardManager handles all VCard loading/caching within Spark. + * + * @author Derek DeMoro + */ +public class VCardManager { + + private VCard personalVCard; + private transient byte[] personalVCardAvatar; // lazy loaded cache of avatar binary data. + private transient String personalVCardHash; // lazy loaded cache of avatar hash. + + private final Map vcards = Collections.synchronizedMap( new HashMap<>()); + + private final Set delayedContacts = Collections.synchronizedSet( new HashSet<>()); + + private boolean vcardLoaded; + + private final File imageFile; + + private final VCardEditor editor; + + private final File vcardStorageDirectory; + + private final LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); + + private final File contactsDir; + + private final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList<>(); + + private final List writingQueue = Collections.synchronizedList( new ArrayList<>()); + + /** + * Initialize VCardManager. + */ + public VCardManager() { + + // Register providers + ProviderManager.addExtensionProvider( JabberAvatarExtension.ELEMENT_NAME, JabberAvatarExtension.NAMESPACE, new JabberAvatarExtension.Provider() ); + ProviderManager.addExtensionProvider( VCardUpdateExtension.ELEMENT_NAME, VCardUpdateExtension.NAMESPACE, new VCardUpdateExtension.Provider() ); + + imageFile = new File(SparkManager.getUserDirectory(), "personal.png"); + + // Initialize vCard. + personalVCard = new VCard(); + personalVCardAvatar = null; + personalVCardHash = null; + + // Set VCard Storage + vcardStorageDirectory = new File(SparkManager.getUserDirectory(), "vcards"); + vcardStorageDirectory.mkdirs(); + + // Set the current user directory. + contactsDir = new File(SparkManager.getUserDirectory(), "contacts"); + contactsDir.mkdirs(); + + initializeUI(); + + // Intercept all presence packets being sent and append vcard information. + StanzaFilter presenceFilter = new StanzaTypeFilter(Presence.class); + SparkManager.getConnection().addAsyncStanzaListener( stanza -> { + Presence newPresence = (Presence)stanza; + VCardUpdateExtension update = new VCardUpdateExtension(); + JabberAvatarExtension jax = new JabberAvatarExtension(); + + XmlElement updateExt = newPresence.getExtensionElement(update.getElementName(), update.getNamespace()); + XmlElement jabberExt = newPresence.getExtensionElement(jax.getElementName(), jax.getNamespace()); + + if (updateExt != null) { + newPresence.removeExtension(updateExt.getElementName(), updateExt.getNamespace()); + } + + if (jabberExt != null) { + newPresence.removeExtension(jabberExt.getElementName(), jabberExt.getNamespace()); + } + + if (personalVCard != null) { + + if ( personalVCardAvatar == null ) + { + personalVCardAvatar = personalVCard.getAvatar(); + } + if (personalVCardAvatar != null && personalVCardAvatar.length > 0) { + if ( personalVCardHash == null ) + { + personalVCardHash = personalVCard.getAvatarHash(); + } + update.setPhotoHash(personalVCardHash); + jax.setPhotoHash(personalVCardHash); + + newPresence.addExtension(update); + newPresence.addExtension(jax); + } + } + }, presenceFilter); + + editor = new VCardEditor(); + + // Start Listener + startQueueListener(); + } + + /** + * Listens for new VCards to lookup in a queue. + */ + private void startQueueListener() { + final Runnable queueListener = () -> { + while (true) { + try { + BareJid jid = queue.take(); + reloadVCard(jid); + } + catch (InterruptedException e) { + e.printStackTrace(); + break; + } + } + }; + + TaskEngine.getInstance().submit(queueListener); + + StanzaFilter filter = new AndFilter(stanza -> { + Jid from = stanza.getFrom(); + return from != null; + }, new StanzaTypeFilter(VCard.class)); + + StanzaListener myListener = stanza -> { + if (stanza instanceof VCard) + { + VCard VCardpacket = (VCard)stanza; + BareJid jid = VCardpacket.getFrom().asBareJid(); + if (VCardpacket.getType().equals(IQ.Type.result) && delayedContacts.contains(jid)) + { + delayedContacts.remove(jid); + addVCard(jid, VCardpacket); + persistVCard(jid, VCardpacket); + } + } + }; + + SparkManager.getConnection().addAsyncStanzaListener(myListener, filter); + } + + /** + * Adds a jid to lookup vCard. + * + * @param jid the jid to lookup. + */ + public void addToQueue(BareJid jid) { + if (!queue.contains(jid)) { + queue.add(jid); + } + + } + + /** + * Adds VCard capabilities to menus and other components in Spark. + */ + private void initializeUI() { + + // See if we should disable the "Edit my profile" option under "File" + if (Default.getBoolean(Default.DISABLE_EDIT_PROFILE) || !Enterprise.containsFeature(Enterprise.VCARD_FEATURE)) return; + + // Add Actions Menu + final JMenu contactsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.contacts")); + final JMenu communicatorMenu = SparkManager.getMainWindow().getJMenuBar().getMenu(0); + + JMenuItem editProfileMenu = new JMenuItem(SparkRes.getImageIcon(SparkRes.Icon.SMALL_BUSINESS_MAN_VIEW)); + ResourceUtils.resButton(editProfileMenu, Res.getString("menuitem.edit.my.profile")); + + int size = contactsMenu.getMenuComponentCount(); + + communicatorMenu.insert(editProfileMenu, 1); + + editProfileMenu.addActionListener( e -> { + SwingWorker vcardLoaderWorker = new SwingWorker() { + @Override + public Object construct() { + try { + final org.jivesoftware.smackx.vcardtemp.VCardManager smackVCardManager = org.jivesoftware.smackx.vcardtemp.VCardManager.getInstanceFor(SparkManager.getConnection()); + personalVCard = smackVCardManager.loadVCard(); + } + catch (XMPPException | SmackException | InterruptedException e) { + Log.error("Error loading vcard information.", e); + } + return true; + } + + @Override + public void finished() { + editor.editProfile(personalVCard, SparkManager.getWorkspace()); + personalVCardAvatar = null; + personalVCardHash = null; + } + }; + vcardLoaderWorker.start(); + } ); + + JMenuItem viewProfileMenu = new JMenuItem("", SparkRes.getImageIcon(SparkRes.Icon.FIND_TEXT_IMAGE)); + ResourceUtils.resButton(viewProfileMenu, Res.getString("menuitem.lookup.profile")); + contactsMenu.insert(viewProfileMenu, size > 0 ? size - 3 : 0); + viewProfileMenu.addActionListener( e -> { + String jidToView = JOptionPane.showInputDialog(SparkManager.getMainWindow(), Res.getString("message.enter.jabber.id") + ":", Res.getString("title.lookup.profile"), JOptionPane.QUESTION_MESSAGE); + if (ModelUtil.hasLength(jidToView) && jidToView.contains( "@" ) && ModelUtil.hasLength( XmppStringUtils.parseDomain(jidToView))) { + BareJid bareJid = JidCreate.bareFromOrThrowUnchecked(jidToView); + viewProfile(bareJid, SparkManager.getWorkspace()); + } + else if (ModelUtil.hasLength(jidToView)) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(SparkManager.getMainWindow(), Res.getString("message.invalid.jabber.id"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); + } + } ); + } + + + /** + * Displays VCardViewer for a particular JID. + * + * @param jid the jid of the user to display. + * @param parent the parent component to use for displaying dialog. + */ + public void viewProfile(final BareJid jid, final JComponent parent) { + final SwingWorker vcardThread = new SwingWorker() { + VCard vcard = new VCard(); + + @Override + public Object construct() { + vcard = getVCard(jid); + return vcard; + } + + @Override + public void finished() { + if (vcard == null) { + // Show vcard not found + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(parent, Res.getString("message.unable.to.load.profile", jid), Res.getString("title.profile.not.found"), JOptionPane.ERROR_MESSAGE); + } + else { + editor.displayProfile(jid, vcard, parent); + } + } + }; + + vcardThread.start(); + + } + + /** + * Displays the full profile for a particular JID. + * + * @param jid the jid of the user to display. + * @param parent the parent component to use for displaying dialog. + */ + public void viewFullProfile(final BareJid jid, final JComponent parent) { + final SwingWorker vcardThread = new SwingWorker() { + VCard vcard = new VCard(); + + @Override + public Object construct() { + vcard = getVCard(jid); + return vcard; + } + + @Override + public void finished() { + if (vcard.getError() != null || vcard == null) { + // Show vcard not found + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(parent, Res.getString("message.unable.to.load.profile", jid), Res.getString("title.profile.not.found"), JOptionPane.ERROR_MESSAGE); + } + else { + editor.viewFullProfile(vcard, parent); + } + } + }; + + vcardThread.start(); + + } + + /** + * Returns the VCard for this Spark user. This information will be cached after loading. + * + * @return this users VCard. + */ + public VCard getVCard() { + if (!vcardLoaded) { + reloadPersonalVCard(); + vcardLoaded = true; + } + return personalVCard; + } + + /** + * Loads the vcard for this Spark user + * @return this users VCard. + */ + public void reloadPersonalVCard() { + try { + personalVCard = org.jivesoftware.smackx.vcardtemp.VCardManager.getInstanceFor(SparkManager.getConnection()).loadVCard(); + personalVCardAvatar = personalVCard.getAvatar(); + personalVCardHash = null; // reload lazy later, when need + + // If VCard is loaded, then save the avatar to the personal folder. + if (personalVCardAvatar != null && personalVCardAvatar.length > 0) { + ImageIcon icon = new ImageIcon(personalVCardAvatar); + icon = VCardManager.scale(icon); + if (icon.getIconWidth() != -1) { + BufferedImage image = GraphicUtils.convert(icon.getImage()); + ImageIO.write(image, "PNG", imageFile); + } + } + } + catch (Exception e) { + StanzaError.Builder errorBuilder = StanzaError.getBuilder(StanzaError.Condition.conflict); + personalVCard.setError(errorBuilder.build()); + personalVCardAvatar = null; + personalVCardHash = null; + Log.error(e); + } + } + + /** + * Returns the Avatar in the form of an ImageIcon. + * + * @param vcard the vCard containing the avatar. + * @return the ImageIcon or null if no avatar was present. + */ + public static ImageIcon getAvatarIcon(VCard vcard) { + // Set avatar + byte[] bytes = vcard.getAvatar(); + if (bytes != null && bytes.length > 0) { + ImageIcon icon = new ImageIcon(bytes); + return GraphicUtils.scaleImageIcon(icon, Sizes.Avatar.SMALL, Sizes.Avatar.SMALL); + } + return null; + } + + /** + * Returns the VCard. Will first look in VCard cache. You will receive a + * dummy vcard, if there is no vCard for specified jid in cache. Same as + * getVCard(jid, true) + * + * @param jid + * the users jid. + * @return the VCard. + */ + public VCard getVCard(BareJid jid) { + return getVCard(jid, true); + } + + /** + * Loads the vCard from memory. If no vCard is found in memory, will add it + * to a loading queue for future loading. Users of this method should only + * use it if the correct vCard is not important the first time around. You + * will get a dummy vCard if there is currently no vCard in memory. + * + * @param jid + * the users jid. + * @return the users VCard or an empty VCard. + */ + public VCard getVCardFromMemory(BareJid jid) { + // Check in memory first. + VCard currentVcard = vcards.get(jid); + if (currentVcard != null) { + return currentVcard; + } + + // if not in memory + VCard vcard = loadFromFileSystem(jid); + if (vcard == null) { + addToQueue(jid); + + // Create temp vcard. + vcard = new VCard(); + vcard.setJabberId(jid.toString()); + } + + return vcard; + } + + /** + * Returns the VCard. You should always use useCachedVCards. VCardManager + * will keep the VCards up to date. If you want to force a network reload + * of the VCard you can set useCachedVCards to false. That means that you + * have to wait for the vcard response. The method will block until the + * result is available or a timeout occurs (like reloadVCard(String jid)). + * If there is no response from server this method a dummy vcard with an + * error. Use getVCard(String jid) to get a dummy VCard if there is + * currently no VCard. If you get a vCard with an error you may wait some + * seconds. Sometimes vCards could not be loaded within smack timeout but we + * are still listening for vCards that are too late. Be patient for some + * seconds and try again, maybe we will get it. + * + * @param jid + * the users jid. + * @param useCachedVCards + * true to check in cache and hdd, otherwise false will do a new + * network vcard operation. + * @return the VCard. + */ + public VCard getVCard(BareJid jid, boolean useCachedVCards) { + if (useCachedVCards) + { + return getVCardFromMemory(jid); + + } else { + return reloadVCard(jid); + } + } + + + /** + * Forces a reload of a VCard. To load a VCard you should use + * getVCard(String jid) instead. This method will perform a network lookup + * which could take some time. If you're having problems with request + * timeout you should also use getVCard(String jid). Use addToQueue(String + * jid) if you want VCardManager to update the VCard by the given jid. The + * method will block until the result is available or a timeout occurs. + * + * @param jidString the JID of the user. + * + * @return the new network vCard or a vCard with an error + */ + public VCard reloadVCard(BareJid jidString) { + EntityBareJid jid = JidCreate.entityBareFromOrThrowUnchecked(jidString); + VCard vcard = new VCard(); + try { + vcard = org.jivesoftware.smackx.vcardtemp.VCardManager.getInstanceFor(SparkManager.getConnection()).loadVCard( jid ); + vcard.setJabberId(jid.toString()); + if (vcard.getNickName() != null && vcard.getNickName().length() > 0) + { + // update nickname. + ContactItem item = SparkManager.getWorkspace().getContactList().getContactItemByJID(jid.toString()); + item.setNickname(vcard.getNickName()); + // TODO: this doesn't work if someone removes his nickname. If we remove it in that case, it will cause problems with people using another way to manage their nicknames. + } + addVCard(jid, vcard); + persistVCard(jid, vcard); + } + catch (XMPPException | SmackException | InterruptedException e) { + ////System.out.println(jid+" Fehler in reloadVCard ----> null"); + StanzaError.Builder errorBuilder = StanzaError.getBuilder(StanzaError.Condition.resource_constraint); + vcard.setError(errorBuilder.build()); + vcard.setJabberId(jid.toString()); + delayedContacts.add(jid); + return vcard; + //We dont want cards with error + // vcard.setError(new StanzaError(XMPPError.Condition.request_timeout)); + //addVCard(jid, vcard); + } + + // Persist XML + + + return vcard; + } + + + /** + * Adds a new vCard to the cache. + * + * @param jid the jid of the user. + * @param vcard the users vcard to cache. + */ + public void addVCard(BareJid jid, VCard vcard) { + if (vcard == null) + return; + vcard.setJabberId(jid.toString()); + VCard currentVcard = vcards.get(jid); + if (currentVcard != null && currentVcard.getError() == null && vcard.getError()!= null) + { + return; + + } + vcards.put(jid, vcard); + } + + /** + * Scales an image to the preferred avatar size. + * + * @param icon the icon to scale. + * @return the scaled version of the image. + */ + public static ImageIcon scale(ImageIcon icon) { + Image avatarImage = icon.getImage(); + if (icon.getIconHeight() > Sizes.Avatar.VCARD_VIEW || icon.getIconWidth() > Sizes.Avatar.VCARD_VIEW) { + avatarImage = avatarImage.getScaledInstance(-1, Sizes.Avatar.VCARD_VIEW, Image.SCALE_SMOOTH); + } + + return new ImageIcon(avatarImage); + } + + /** + * Returns the URL of the avatar image associated with the users JID. + * + * @param jid the jid of the user. + * @return the URL of the image. If not image is found, a default avatar is returned. + */ + public URL getAvatar(BareJid jid) { + // Handle own avatar file. + if (jid != null && SparkManager.getSessionManager().getUserBareAddress().equals(jid)) { + if (imageFile.exists()) { + try { + return imageFile.toURI().toURL(); + } + catch (MalformedURLException e) { + Log.error(e); + } + } + else { + return SparkRes.getURL(SparkRes.DUMMY_CONTACT_IMAGE); + } + } + + // Handle other users JID + ContactItem item = SparkManager.getWorkspace().getContactList().getContactItemByJID(jid); + URL avatarURL = null; + if (item != null) { + try { + avatarURL = item.getAvatarURL(); + } + catch (MalformedURLException e) { + Log.error(e); + } + } + + if (avatarURL == null) { + return SparkRes.getURL(SparkRes.DUMMY_CONTACT_IMAGE); + } + + return avatarURL; + } + + /** + * Searches all vCards for a specified phone number. + * + * @param phoneNumber the phoneNumber. + * @return the vCard which contains the phone number. + */ + public VCard searchPhoneNumber(String phoneNumber) { + for (VCard vcard : vcards.values()) { + String homePhone = getNumbersFromPhone(vcard.getPhoneHome("VOICE")); + String workPhone = getNumbersFromPhone(vcard.getPhoneWork("VOICE")); + String cellPhone = getNumbersFromPhone(vcard.getPhoneWork("CELL")); + + String query = getNumbersFromPhone(phoneNumber); + if ((homePhone != null && homePhone.endsWith(query)) || + (workPhone != null && workPhone.endsWith(query)) || + (cellPhone != null && cellPhone.endsWith(query))) { + return vcard; + } + } + + return null; + } + + /** + * Parses out the numbers only from a phone number. + * + * @param number the full phone number. + * @return the phone number only (5551212) + */ + public static String getNumbersFromPhone(String number) { + if (number == null) { + return null; + } + + number = number.replace("-", ""); + number = number.replace("(", ""); + number = number.replace(")", ""); + number = number.replace(" ", ""); + + return number; + } + + /** + * Sets the personal vcard of the user. + * + * @param vcard the users vCard. + */ + public void setPersonalVCard(VCard vcard) { + this.personalVCard = vcard; + this.personalVCardHash = null; + this.personalVCardAvatar = null; + } + + public URL getAvatarURL(BareJid jid) { + VCard vcard = getVCard(jid); + if (vcard != null) { + String hash = vcard.getAvatarHash(); + if (!ModelUtil.hasLength(hash)) { + return null; + } + + final File avatarFile = new File(contactsDir, hash); + try { + return avatarFile.toURI().toURL(); + } + catch (MalformedURLException e) { + Log.error(e); + } + } + return null; + } + + /** + * Get URL for avatar from vcard. If there is no vcard available we will try + * to get it from the server and return null. + * + * @param jid + * the users jid + * @return the vcard if there is already one, otherwise null and we try to + * load vcard in background + * + */ + public URL getAvatarURLIfAvailable(BareJid jid) { + if (getVCard(jid) != null) { + return getAvatarURL(jid); + } else { + addToQueue(jid); + return null; + } + } + + + /** + * Persist vCard information out for caching. + * + * @param jid the users jid. + * @param vcard the users vcard. + */ + private void persistVCard(BareJid jid, VCard vcard) { + if (jid == null || vcard == null) { + return; + } + + + String fileName = Base64.getEncoder().encodeToString(jid.toString().getBytes()); + // remove tab + fileName = fileName.replaceAll("\t", ""); + // remove new line (Unix) + fileName = fileName.replaceAll("\n", ""); + // remove new line (Windows) + fileName = fileName.replaceAll("\r", ""); + + byte[] bytes = vcard.getAvatar(); + if (bytes != null && bytes.length > 0) { + vcard.setAvatar(bytes); + try { + String hash = vcard.getAvatarHash(); + final File avatarFile = new File(contactsDir, hash); + ImageIcon icon = new ImageIcon(bytes); + icon = VCardManager.scale(icon); + if (icon != null && icon.getIconWidth() != -1) { + BufferedImage image = GraphicUtils.convert(icon.getImage()); + if (image == null) { + Log.warning("Unable to write out avatar for " + jid); + } + else { + + if (writingQueue.contains(jid)) { + writeAvatarSync(image, avatarFile); + } else { + writingQueue.add(jid); + ImageIO.write(image, "PNG", avatarFile); + writingQueue.remove(jid); + } + + + } + } + } + catch (Exception e) { + Log.error("Unable to update avatar in Contact Item.", e); + } + } + + // Set timestamp + vcard.setField("timestamp", Long.toString(System.currentTimeMillis())); + + final String xml = vcard.toXML().toString(); + + File vcardFile = new File(vcardStorageDirectory, fileName); + + // write xml to file + try { + Files.write(vcardFile.toPath(), xml.getBytes(StandardCharsets.UTF_8)); + } + catch (IOException e) { + Log.error(e); + } + } + + private synchronized void writeAvatarSync(BufferedImage image, File avatarFile) throws IOException { + ImageIO.write(image, "PNG", avatarFile); + } + + /** + * Attempts to load + * + * @param jid the jid of the user. + * @return the VCard if found, otherwise null. + */ + private VCard loadFromFileSystem(BareJid jid) { + if (jid == null) { + return null; + } + + // Unescape JID + String fileName = Base64.getEncoder().encodeToString(jid.toString().getBytes()); + final File vcardFile = new File(vcardStorageDirectory, fileName); + if (!vcardFile.exists()) { + return null; + } + + final VCard vcard; + try ( final BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(vcardFile), StandardCharsets.UTF_8)) ) + { + // Otherwise load from file system. + XmlPullParser parser = SmackXmlParser.newXmlParser(in); + + // Skip forward until we're at + while ( !( parser.getEventType() == XmlPullParser.Event.START_ELEMENT && VCard.ELEMENT.equals( parser.getName() ) && VCard.NAMESPACE.equals( parser.getNamespace() ) ) ) + { + parser.next(); + } + + VCardProvider provider = new VCardProvider(); + vcard = provider.parse( parser, null ); + } + catch (Exception e) { + Log.warning("Unable to load vCard for " + jid, e); + vcardFile.delete(); + return null; + } + + addVCard(jid, vcard); + + // Check to see if the file is older 60 minutes. If so, reload. + final String timestamp = vcard.getField( "timestamp" ); + if ( timestamp != null ) + { + final Duration duration = Duration.between( Instant.ofEpochMilli( Long.parseLong( timestamp ) ), Instant.now() ); + if ( duration.toMinutes() >= 60 ) + { + addToQueue( jid ); + } + } + + return vcard; + } + + + /** + * Add VCardListener. Listens to the personalVCard. + * + * @param listener the listener to add. + */ + public void addVCardListener(VCardListener listener) { + listeners.addIfAbsent(listener); + } + + /** + * Remove VCardListener. + * + * @param listener the listener to remove. + */ + public void removeVCardListener(VCardListener listener) { + listeners.remove(listener); + } + + /** + * Notify all VCardListener implementations. + */ + protected void notifyVCardListeners() { + for (VCardListener listener : listeners) { + listener.vcardChanged(personalVCard); + } + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/profile/ext/JabberAvatarExtension.java b/core/src/main/java/org/jivesoftware/sparkimpl/profile/ext/JabberAvatarExtension.java new file mode 100644 index 000000000..1244203b0 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/profile/ext/JabberAvatarExtension.java @@ -0,0 +1,102 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.sparkimpl.profile.ext; + +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.parsing.SmackParsingException; +import org.jivesoftware.smack.provider.ExtensionElementProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.JxmppContext; + +import javax.xml.namespace.QName; +import java.io.IOException; +import java.text.ParseException; + +/** + * XEP-0008: IQ-Based Avatars + * TODO Should be replaced with XEP-0084: User Avatar + */ +public class JabberAvatarExtension implements ExtensionElement { + + public static final String ELEMENT_NAME = "x"; + + public static final String NAMESPACE = "jabber:x:avatar"; + + public static final QName QNAME = new QName(NAMESPACE, ELEMENT_NAME); + + private String photoHash; + + public void setPhotoHash(String hash) { + photoHash = hash; + } + + @Override + public String getElementName() { + return ELEMENT_NAME; + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public String toXML(XmlEnvironment xmlEnvironment) { + return "<" + getElementName() + " xmlns=\"" + getNamespace() + "\">" + + "" + photoHash + "" + + ""; + } + + public static class Provider extends ExtensionElementProvider + { + public Provider() { + } + + @Override + public JabberAvatarExtension parse(XmlPullParser parser, int i, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) + throws XmlPullParserException, IOException { + final JabberAvatarExtension result = new JabberAvatarExtension(); + + while ( true ) + { + parser.next(); + String elementName; + switch ( parser.getEventType() ) + { + case START_ELEMENT: + elementName = parser.getName(); + if ( "photo".equals( elementName ) ) + { + result.setPhotoHash( parser.nextText() ); + } + break; + + case END_ELEMENT: + elementName = parser.getName(); + if ( ELEMENT_NAME.equals( elementName ) ) + { + return result; + } + break; + } + } + } + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/profile/ext/VCardUpdateExtension.java b/core/src/main/java/org/jivesoftware/sparkimpl/profile/ext/VCardUpdateExtension.java new file mode 100644 index 000000000..fdd5f39ce --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/profile/ext/VCardUpdateExtension.java @@ -0,0 +1,98 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.sparkimpl.profile.ext; + +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.provider.ExtensionElementProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.JxmppContext; + +import javax.xml.namespace.QName; +import java.io.IOException; + +public class VCardUpdateExtension implements ExtensionElement { + + public static final String ELEMENT_NAME = "x"; + + public static final String NAMESPACE = "vcard-temp:x:update"; + + public static final QName QNAME = new QName(NAMESPACE, ELEMENT_NAME); + + private String photoHash; + + public void setPhotoHash(String hash) { + photoHash = hash; + } + + public String getPhotoHash() { + return photoHash; + } + + @Override + public String getElementName() { + return ELEMENT_NAME; + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public String toXML(XmlEnvironment xmlEnvironment) { + return "<" + getElementName() + " xmlns=\"" + getNamespace() + "\">" + + "" + + photoHash + + "" + + ""; + } + + public static class Provider extends ExtensionElementProvider + { + public Provider() { + } + + @Override + public VCardUpdateExtension parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) + throws XmlPullParserException, IOException { + final VCardUpdateExtension result = new VCardUpdateExtension(); + + while ( true ) + { + parser.next(); + switch ( parser.getEventType() ) + { + case START_ELEMENT: + if ( "photo".equals( parser.getName() ) ) + { + result.setPhotoHash( parser.nextText() ); + } + break; + + case END_ELEMENT: + if ( parser.getDepth() == initialDepth ) + { + return result; + } + break; + } + } + } + } +} diff --git a/src/java/org/jivesoftware/sparkimpl/search/users/SearchForm.java b/core/src/main/java/org/jivesoftware/sparkimpl/search/users/SearchForm.java similarity index 78% rename from src/java/org/jivesoftware/sparkimpl/search/users/SearchForm.java rename to core/src/main/java/org/jivesoftware/sparkimpl/search/users/SearchForm.java index 9a8346a0d..18d26c685 100644 --- a/src/java/org/jivesoftware/sparkimpl/search/users/SearchForm.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/search/users/SearchForm.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +19,8 @@ import org.jivesoftware.resource.Res; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.xdata.Form; +import org.jivesoftware.smackx.xdata.form.FillableForm; +import org.jivesoftware.smackx.xdata.packet.DataForm; import org.jivesoftware.smackx.search.ReportedData; import org.jivesoftware.smackx.search.UserSearchManager; import org.jivesoftware.spark.SparkManager; @@ -31,6 +28,9 @@ import org.jivesoftware.spark.util.ResourceUtils; import org.jivesoftware.spark.util.SwingWorker; import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; import javax.swing.AbstractAction; import javax.swing.BorderFactory; @@ -52,28 +52,28 @@ public class SearchForm extends JPanel { private UserSearchResults searchResults; private DataFormUI questionForm; private UserSearchManager searchManager; - private String serviceName; - private Form searchForm; + private final DomainBareJid serviceName; + private DataForm searchForm; - public SearchForm(String service) { - this.serviceName = service; + // TODO: Constructor should use DomainBareJid type instead of String. + public SearchForm(String serviceString) { + this.serviceName = JidCreate.domainBareFromOrThrowUnchecked(serviceString); - searchManager = new UserSearchManager(SparkManager.getConnection()); + searchManager = UserSearchManager.getInstanceFor(SparkManager.getConnection()); setLayout(new GridBagLayout()); // Load searchForm try { - searchForm = searchManager.getSearchForm(service); + searchForm = searchManager.getSearchForm(serviceName).getDataForm(); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error("Unable to load search services.", e); UIManager.put("OptionPane.okButtonText", Res.getString("ok")); JOptionPane.showMessageDialog(SparkManager.getMainWindow(), Res.getString("message.search.service.not.available"), Res.getString("title.notification"), JOptionPane.ERROR_MESSAGE); return; } - searchManager = new UserSearchManager(SparkManager.getConnection()); questionForm = new DataFormUI(searchForm); questionForm.setBorder(BorderFactory.createTitledBorder(Res.getString("group.search.form"))); @@ -95,7 +95,8 @@ public SearchForm(String service) { getActionMap().put("enter", new AbstractAction("enter") { private static final long serialVersionUID = -7308854327447291219L; - public void actionPerformed(ActionEvent evt) { + @Override + public void actionPerformed(ActionEvent evt) { performSearch(); } }); @@ -110,7 +111,7 @@ public DataFormUI getQuestionForm() { return questionForm; } - public Form getSearchForm() { + public DataForm getSearchForm() { return searchForm; } @@ -123,20 +124,22 @@ public void performSearch() { SwingWorker worker = new SwingWorker() { ReportedData data; - public Object construct() { + @Override + public Object construct() { try { - Form answerForm = questionForm.getFilledForm(); - data = searchManager.getSearchResults(answerForm, serviceName); + FillableForm filledForm = questionForm.getFilledForm(); + data = searchManager.sendSimpleSearchForm(filledForm.getDataFormToSubmit(), serviceName); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error("Unable to load search service.", e); } return data; } - public void finished() { - if (data != null) { + @Override + public void finished() { + if (data != null && !data.getRows().isEmpty() ) { searchResults.showUsersFound(data); searchResults.invalidate(); searchResults.validate(); diff --git a/src/java/org/jivesoftware/sparkimpl/search/users/UserSearchForm.java b/core/src/main/java/org/jivesoftware/sparkimpl/search/users/UserSearchForm.java similarity index 82% rename from src/java/org/jivesoftware/sparkimpl/search/users/UserSearchForm.java rename to core/src/main/java/org/jivesoftware/sparkimpl/search/users/UserSearchForm.java index 7ae78e5cc..4bffae7fe 100644 --- a/src/java/org/jivesoftware/sparkimpl/search/users/UserSearchForm.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/search/users/UserSearchForm.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,8 +21,8 @@ import org.jivesoftware.resource.SparkRes; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.xdata.Form; import org.jivesoftware.smackx.search.UserSearchManager; +import org.jivesoftware.smackx.xdata.packet.DataForm; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.component.TitlePanel; import org.jivesoftware.spark.ui.DataFormUI; @@ -34,6 +30,9 @@ import org.jivesoftware.spark.util.ResourceUtils; import org.jivesoftware.spark.util.SwingWorker; import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; import javax.swing.JButton; import javax.swing.JComboBox; @@ -63,34 +62,34 @@ */ public class UserSearchForm extends JPanel { private static final long serialVersionUID = -9192188543673595941L; - private JComboBox servicesBox; - private UserSearchManager searchManager; + private JComboBox servicesBox; + private final UserSearchManager searchManager; - private Collection searchServices; + private final Collection searchServices; - private CardLayout cardLayout = new CardLayout(); - private JPanel cardPanel = new JPanel(); + private final CardLayout cardLayout = new CardLayout(); + private final JPanel cardPanel = new JPanel(); private TitlePanel titlePanel; - private Map serviceMap = new HashMap<>(); + private final Map serviceMap = new HashMap<>(); - private static File pluginsettings = new File(Spark.getSparkUserHome() + File.separator + "search.properties"); //new + private static final File pluginsettings = new File(Spark.getSparkUserHome(), "search.properties"); //new /** * Initializes the UserSearchForm with all available search services. * * @param searchServices a Collection of all search services found. */ - public UserSearchForm(Collection searchServices) { + public UserSearchForm(Collection searchServices) { setLayout(new GridBagLayout()); cardPanel.setLayout(cardLayout); this.searchServices = searchServices; - searchManager = new UserSearchManager(SparkManager.getConnection()); + searchManager = UserSearchManager.getInstanceFor(SparkManager.getConnection()); addSearchServices(); @@ -104,10 +103,10 @@ public UserSearchForm(Collection searchServices) { private void addSearchServices() { // Populate with Search Services - servicesBox = new JComboBox(); + servicesBox = new JComboBox<>(); - for (String searchService : searchServices) { - String service = searchService; + for (CharSequence searchService : searchServices) { + String service = searchService.toString(); servicesBox.addItem(service); } @@ -137,21 +136,16 @@ private void addSearchServices() { } } catch (IOException ioe) { - System.err.println(ioe); + Log.error(ioe); } - } - else { - // Log.error("Search-Searvice-Error: Properties-file does not exist= " + pluginsettings.getPath()); - } - + } if (servicesBox.getItemCount() > 0) { servicesBox.setSelectedIndex(0); } - - titlePanel = new TitlePanel("", "", SparkRes.getImageIcon(SparkRes.BLANK_IMAGE), true); + titlePanel = new TitlePanel("", "", SparkRes.getImageIcon(SparkRes.Icon.BLANK_IMAGE), true); add(titlePanel, new GridBagConstraints(0, 0, 3, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); // Add Search Service ComboBox @@ -168,19 +162,22 @@ private void addSearchServices() { if (ModelUtil.hasLength(serviceName)) { SwingWorker findServiceThread = new SwingWorker() { - Form newForm; + DataForm newForm; - public Object construct() { + @Override + public Object construct() { try { - newForm = searchManager.getSearchForm(serviceName); + DomainBareJid serviceJid = JidCreate.domainBareFrom(serviceName); + newForm = searchManager.getSearchForm(serviceJid).getDataForm(); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | XmppStringprepException | InterruptedException e) { // Nothing to do } return newForm; } - public void finished() { + @Override + public void finished() { if (newForm == null) { UIManager.put("OptionPane.okButtonText", Res.getString("ok")); JOptionPane.showMessageDialog(getGUI(), Res.getString("message.search.service.not.available"), Res.getString("title.notification"), JOptionPane.ERROR_MESSAGE); @@ -208,7 +205,7 @@ public void finished() { try { props.store(new FileOutputStream(pluginsettings), null); } catch (IOException e) { - System.err.println(e); + Log.error(e); } } @@ -222,7 +219,8 @@ public void finished() { servicesBox.addActionListener( actionEvent -> { SwingWorker worker = new SwingWorker() { - public Object construct() { + @Override + public Object construct() { try { Thread.sleep(50); } @@ -232,7 +230,8 @@ public Object construct() { return "ok"; } - public void finished() { + @Override + public void finished() { showService(getSearchService()); } }; @@ -249,22 +248,23 @@ public void finished() { * @param service the search service to display. */ public void showService(String service) { - if (serviceMap.containsKey(service)) { - cardLayout.show(cardPanel, service); - } - else { + if (!serviceMap.containsKey(service)) { // Create new Form SearchForm searchForm = new SearchForm(service); cardPanel.add(searchForm, service); serviceMap.put(service, searchForm); - cardLayout.show(cardPanel, service); } + cardLayout.show(cardPanel, service); SearchForm searchForm = serviceMap.get(service); - Form form = searchForm.getSearchForm(); - String description = form.getInstructions(); //XXX maybe add a Spark String instead + DataForm form = searchForm.getSearchForm(); + StringBuilder description = new StringBuilder(); + for (String instruction : form.getInstructions()) { + description.append(instruction).append('\n'); + } + titlePanel.setTitle(Res.getString("title.person.search")); - titlePanel.setDescription(description); + titlePanel.setDescription(description.toString()); } diff --git a/src/java/org/jivesoftware/sparkimpl/search/users/UserSearchResults.java b/core/src/main/java/org/jivesoftware/sparkimpl/search/users/UserSearchResults.java similarity index 79% rename from src/java/org/jivesoftware/sparkimpl/search/users/UserSearchResults.java rename to core/src/main/java/org/jivesoftware/sparkimpl/search/users/UserSearchResults.java index 97c6a1fb7..82934ed66 100644 --- a/src/java/org/jivesoftware/sparkimpl/search/users/UserSearchResults.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/search/users/UserSearchResults.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +16,7 @@ package org.jivesoftware.sparkimpl.search.users; +import org.apache.commons.lang3.StringUtils; import org.jivesoftware.resource.Default; import org.jivesoftware.resource.SparkRes; import org.jivesoftware.resource.Res; @@ -33,7 +30,11 @@ import org.jivesoftware.spark.ui.ChatRoom; import org.jivesoftware.spark.ui.RosterDialog; import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; import org.jivesoftware.sparkimpl.profile.VCardManager; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.util.XmppStringUtils; import javax.swing.AbstractAction; @@ -62,7 +63,7 @@ public class UserSearchResults extends JPanel { private UsersInfoTable resultsTable; /** - * Intiliaze the Search Service Results UI. + * Initialize the Search Service Results UI. */ public UserSearchResults() { setLayout(new BorderLayout()); @@ -81,7 +82,7 @@ public void showUsersFound(ReportedData data) { } if (resultsTable == null) { - resultsTable = new UsersInfoTable(columnList.toArray(new String[columnList.size()])); + resultsTable = new UsersInfoTable(columnList.toArray(new String[0])); final JScrollPane scrollPane = new JScrollPane(resultsTable); scrollPane.getViewport().setBackground(Color.white); @@ -89,18 +90,21 @@ public void showUsersFound(ReportedData data) { add(scrollPane, BorderLayout.CENTER); resultsTable.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { + @Override + public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { int row = resultsTable.getSelectedRow(); openChatRoom(row); } } - public void mouseReleased(MouseEvent e) { + @Override + public void mouseReleased(MouseEvent e) { checkPopup(e); } - public void mousePressed(MouseEvent e) { + @Override + public void mousePressed(MouseEvent e) { checkPopup(e); } }); @@ -142,17 +146,18 @@ private void checkPopup(MouseEvent e) { Action addContactAction = new AbstractAction() { private static final long serialVersionUID = -6377937878941477145L; - public void actionPerformed(ActionEvent e) { + @Override + public void actionPerformed(ActionEvent e) { RosterDialog dialog = new RosterDialog(); String jid = (String)resultsTable.getValueAt(row, 0); TableColumn column = null; try { - column = resultsTable.getColumn("Username"); + column = resultsTable.getColumn("Name"); } catch (Exception ex) { try { - column = resultsTable.getColumn("nick"); + column = resultsTable.getColumn("Username"); } catch (Exception e1) { // Nothing to do @@ -175,7 +180,8 @@ public void actionPerformed(ActionEvent e) { Action chatAction = new AbstractAction() { private static final long serialVersionUID = 5651812282020177800L; - public void actionPerformed(ActionEvent e) { + @Override + public void actionPerformed(ActionEvent e) { openChatRoom(row); } }; @@ -183,27 +189,29 @@ public void actionPerformed(ActionEvent e) { Action profileAction = new AbstractAction() { private static final long serialVersionUID = -2014872840628217586L; - public void actionPerformed(ActionEvent e) { + @Override + public void actionPerformed(ActionEvent e) { VCardManager vcardSupport = SparkManager.getVCardManager(); - String jid = (String)resultsTable.getValueAt(row, 0); + String jidString = (String)resultsTable.getValueAt(row, 0); + BareJid jid = JidCreate.bareFromOrThrowUnchecked(jidString); vcardSupport.viewProfile(jid, resultsTable); } }; - if (!Default.getBoolean(Default.ADD_CONTACT_DISABLED)) { + if (!Default.getBoolean(Default.ADD_CONTACT_DISABLED) && Enterprise.containsFeature(Enterprise.ADD_CONTACTS_FEATURE)) { final JMenuItem addAsContact = new JMenuItem(addContactAction); - addContactAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_ADD_IMAGE)); + addContactAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_ADD_IMAGE)); addContactAction.putValue(Action.NAME, Res.getString("menuitem.add.as.contact")); menu.add(addAsContact); } final JMenuItem chatMenu = new JMenuItem(chatAction); - chatAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_MESSAGE_IMAGE)); + chatAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_MESSAGE_IMAGE)); chatAction.putValue(Action.NAME, Res.getString("menuitem.chat")); menu.add(chatMenu); final JMenuItem viewProfileMenu = new JMenuItem(profileAction); - profileAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_PROFILE_IMAGE)); + profileAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icon.SMALL_PROFILE_IMAGE)); profileAction.putValue(Action.NAME, Res.getString("menuitem.view.profile")); menu.add(viewProfileMenu); @@ -211,7 +219,7 @@ public void actionPerformed(ActionEvent e) { menu.show(resultsTable, e.getX(), e.getY()); } - private final class UsersInfoTable extends Table { + private static final class UsersInfoTable extends Table { private static final long serialVersionUID = -7097826349368800291L; UsersInfoTable(String[] headers) { @@ -231,30 +239,37 @@ private final class UsersInfoTable extends Table { * @return the first value found in the ReportedData.Row */ public String getFirstValue(ReportedData.Row row, String key) { - List values = row.getValues( key ); - return values == null && values.isEmpty() ? null : values.get( 0 ); + List values = row.getValues( key ); + return values == null || values.isEmpty() ? null : values.get( 0 ).toString(); } private void openChatRoom(int row) { - String jid = (String)resultsTable.getValueAt(row, 0); - String nickname = XmppStringUtils.parseLocalpart(jid); + String jidString = (String)resultsTable.getValueAt(row, 0); + EntityBareJid jid = JidCreate.entityBareFromOrThrowUnchecked(jidString); + String nickname = jid.getLocalpart().toString(); TableColumn column; try { column = resultsTable.getColumn("nick"); int col = column.getModelIndex(); - nickname = (String)resultsTable.getValueAt(row, col); - if (!ModelUtil.hasLength(nickname)) { - nickname = XmppStringUtils.parseLocalpart(jid); + String nicknameString = (String)resultsTable.getValueAt(row, col); + if (!ModelUtil.hasLength(nicknameString)) { + nickname = JidCreate.from(nicknameString).getLocalpartOrThrow().toString(); } } catch (Exception e1) { // Ignore e1 } + String nameForTab = (String)resultsTable.getValueAt(row, 2); + if(nameForTab != null){ + if(!StringUtils.isBlank(nameForTab)){ + nickname = nameForTab; + } + } ChatManager chatManager = SparkManager.getChatManager(); ChatRoom chatRoom = chatManager.createChatRoom(jid, nickname, nickname); - + ChatContainer chatRooms = chatManager.getChatContainer(); chatRooms.activateChatRoom(chatRoom); } diff --git a/src/java/org/jivesoftware/sparkimpl/search/users/UserSearchService.java b/core/src/main/java/org/jivesoftware/sparkimpl/search/users/UserSearchService.java similarity index 84% rename from src/java/org/jivesoftware/sparkimpl/search/users/UserSearchService.java rename to core/src/main/java/org/jivesoftware/sparkimpl/search/users/UserSearchService.java index c5979d847..cded4059e 100644 --- a/src/java/org/jivesoftware/sparkimpl/search/users/UserSearchService.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/search/users/UserSearchService.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,22 +28,23 @@ import org.jivesoftware.spark.util.GraphicUtils; import org.jivesoftware.spark.util.SwingWorker; import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.DomainBareJid; import javax.swing.*; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; +import java.util.*; public class UserSearchService implements Searchable { - private Collection searchServices; + private Collection searchServices; public UserSearchService() { loadSearchServices(); } - public void search(final String query) { + @Override + public void search(final String query) { SwingWorker worker = new SwingWorker() { - public Object construct() { + @Override + public Object construct() { // On initialization, find search service. if (searchServices == null) { loadSearchServices(); @@ -55,7 +52,8 @@ public Object construct() { return true; } - public void finished() { + @Override + public void finished() { processQuery(query); } }; @@ -66,7 +64,7 @@ public void finished() { private void processQuery(String query) { UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - if (searchServices == null) { + if (searchServices == null || searchServices.isEmpty()) { JOptionPane.showMessageDialog(SparkManager.getMainWindow(), Res.getString("message.search.service.not.available"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); return; } @@ -105,7 +103,7 @@ private void processQuery(String query) { } JFrame frame = new JFrame(); - frame.setIconImage(SparkRes.getImageIcon(SparkRes.VIEW_IMAGE).getImage()); + frame.setIconImage(SparkRes.getImageIcon(SparkRes.Icon.VIEW_IMAGE).getImage()); final JDialog dialog = new JDialog(frame, Res.getString("title.person.search"), false); dialog.getContentPane().add(searchForm); dialog.pack(); @@ -131,11 +129,10 @@ private void loadSearchServices() { * Returns a collection of search services found on the server. * * @return a Collection of search services found on the server. - * @throws XMPPException thrown if a server error has occurred. */ - private Collection getServices() throws Exception { - final Set searchServices = new HashSet<>(); - ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(SparkManager.getConnection()); + private Collection getServices() { + List searchServices = new ArrayList<>(2); + ServiceDiscoveryManager discoManager = SparkManager.getDiscoManager(); DiscoverItems items = SparkManager.getSessionManager().getDiscoveredItems(); for (DiscoverItems.Item item : items.getItems() ) { try { @@ -152,7 +149,7 @@ private Collection getServices() throws Exception { // Check that the search service belongs to user searches (and not room searches or other searches) for (DiscoverInfo.Identity identity : info.getIdentities() ) { if ("directory".equals(identity.getCategory()) && "user".equals(identity.getType())) { - searchServices.add(item.getEntityID()); + searchServices.add(item.getEntityID().asDomainBareJid()); } } } @@ -170,24 +167,28 @@ private Collection getServices() throws Exception { * * @return the discovered search services. */ - public Collection getSearchServices() { + public Collection getSearchServices() { return searchServices; } - public String getToolTip() { + @Override + public String getToolTip() { return Res.getString("message.search.for.other.people"); } - public String getDefaultText() { + @Override + public String getDefaultText() { return Res.getString("message.search.for.other.people"); } - public String getName() { + @Override + public String getName() { return Res.getString("title.person.search"); } - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.SEARCH_USER_16x16); + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.SEARCH_USER_16x16); } diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/settings/JiveInfo.java b/core/src/main/java/org/jivesoftware/sparkimpl/settings/JiveInfo.java new file mode 100644 index 000000000..ca9aca2fa --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/settings/JiveInfo.java @@ -0,0 +1,51 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.sparkimpl.settings; + + +import org.jivesoftware.resource.SparkRes; + +public class JiveInfo { + + private JiveInfo() { + + } + + public static String getName() { + final String name = SparkRes.getString( "APP_NAME" ); + if ( name != null && !name.trim().isEmpty() ) + { + return name.trim(); + } + + return "Spark"; + } + + public static String getVersion() { + final String version = SparkRes.getString( "VERSION" ); + if ( version!= null && !version.trim().isEmpty() ) + { + return version.trim(); + } + + return "3.0.3"; // avoid null and return at least some current version + } + + public static String getOS() { + return System.getProperty("os.name"); + } +} diff --git a/src/java/org/jivesoftware/sparkimpl/settings/SettingsData.java b/core/src/main/java/org/jivesoftware/sparkimpl/settings/SettingsData.java similarity index 89% rename from src/java/org/jivesoftware/sparkimpl/settings/SettingsData.java rename to core/src/main/java/org/jivesoftware/sparkimpl/settings/SettingsData.java index 386f44ce0..cc48c45af 100644 --- a/src/java/org/jivesoftware/sparkimpl/settings/SettingsData.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/settings/SettingsData.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,7 +22,7 @@ import java.util.Map; public class SettingsData implements PrivateData { - private Map settingsMap; + private final Map settingsMap; public SettingsData(Map map) { @@ -37,15 +33,18 @@ public Map getMap() { return settingsMap; } - public String getElementName() { + @Override + public String getElementName() { return "personal_settings"; } - public String getNamespace() { + @Override + public String getNamespace() { return "jive:user:settings"; } - public String toXML() { + @Override + public String toXML() { StringBuilder buf = new StringBuilder(); buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append("\">"); String key; @@ -62,4 +61,4 @@ public String toXML() { } -} \ No newline at end of file +} diff --git a/src/java/org/jivesoftware/sparkimpl/settings/SettingsDataProvider.java b/core/src/main/java/org/jivesoftware/sparkimpl/settings/SettingsDataProvider.java similarity index 83% rename from src/java/org/jivesoftware/sparkimpl/settings/SettingsDataProvider.java rename to core/src/main/java/org/jivesoftware/sparkimpl/settings/SettingsDataProvider.java index fa6d3338c..a7ab171e2 100644 --- a/src/java/org/jivesoftware/sparkimpl/settings/SettingsDataProvider.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/settings/SettingsDataProvider.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,10 +16,11 @@ package org.jivesoftware.sparkimpl.settings; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; import org.jivesoftware.smackx.iqprivate.packet.PrivateData; import org.jivesoftware.smackx.iqprivate.provider.PrivateDataProvider; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; +import org.jxmpp.JxmppContext; import java.io.IOException; import java.util.HashMap; @@ -34,7 +31,8 @@ public class SettingsDataProvider implements PrivateDataProvider { public SettingsDataProvider() { } - public PrivateData parsePrivateData(XmlPullParser parser) throws XmlPullParserException, IOException + @Override + public PrivateData parsePrivateData(XmlPullParser parser, JxmppContext jxmppContext) throws XmlPullParserException, IOException { Map map = new HashMap<>(); parser.getEventType(); @@ -50,4 +48,4 @@ public PrivateData parsePrivateData(XmlPullParser parser) throws XmlPullParserEx return new SettingsData(map); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/settings/Sizes.java b/core/src/main/java/org/jivesoftware/sparkimpl/settings/Sizes.java new file mode 100644 index 000000000..769969943 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/settings/Sizes.java @@ -0,0 +1,23 @@ +package org.jivesoftware.sparkimpl.settings; + +public class Sizes { + public static class Avatar { + public static final int PROFILE_MIN = 32; + public static final int PROFILE = 96; + public static final int VCARD = 48; + public static final int VCARD_VIEW = 64; + public static final int HOVER_BIG = 128; + public static final int STATUS = 64; + public static final int NOTIFICATION = 64; + public static final int SMALL = 40; + public static final int CONTACT_LIST = 32; + } + + public static class Toaster { + public static final int ICON = 64; + } + + public static class Transfer { + public static final int THUMBNAIL = 64; + } +} diff --git a/src/java/org/jivesoftware/sparkimpl/settings/UserSettings.java b/core/src/main/java/org/jivesoftware/sparkimpl/settings/UserSettings.java similarity index 86% rename from src/java/org/jivesoftware/sparkimpl/settings/UserSettings.java rename to core/src/main/java/org/jivesoftware/sparkimpl/settings/UserSettings.java index b4ebbab36..a2b93e314 100644 --- a/src/java/org/jivesoftware/sparkimpl/settings/UserSettings.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/settings/UserSettings.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,7 +27,6 @@ public class UserSettings { public static final String NAMESPACE = "jive:user:settings"; public static final String ELEMENT_NAME = "personal_settings"; - private PrivateDataManager privateDataManager; private SettingsData settingsData; private static UserSettings singleton; private static final Object LOCK = new Object(); @@ -48,13 +43,13 @@ public static UserSettings getInstance() { } private UserSettings() { - privateDataManager = PrivateDataManager.getInstanceFor(SparkManager.getConnection()); + PrivateDataManager privateDataManager = SparkManager.getSessionManager().getPersonalDataManager(); PrivateDataManager.addPrivateDataProvider("personal_settings", "jive:user:settings", new SettingsDataProvider()); try { settingsData = (SettingsData)privateDataManager.getPrivateData("personal_settings", "jive:user:settings"); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error("Error in User Settings", e); } } @@ -85,18 +80,15 @@ public String getProperty(String name) { return getSettings().get(name); } - public String getEmptyPropertyIfNull(String name) { - return ModelUtil.nullifyIfEmpty(getSettings().get(name)); - } - public void save() { try { + PrivateDataManager privateDataManager = SparkManager.getSessionManager().getPersonalDataManager(); privateDataManager.setPrivateData(settingsData); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error("Error in User Settings.", e); } } -} \ No newline at end of file +} diff --git a/src/java/org/jivesoftware/sparkimpl/settings/local/LocalPreference.java b/core/src/main/java/org/jivesoftware/sparkimpl/settings/local/LocalPreference.java similarity index 81% rename from src/java/org/jivesoftware/sparkimpl/settings/local/LocalPreference.java rename to core/src/main/java/org/jivesoftware/sparkimpl/settings/local/LocalPreference.java index 7bd0b2278..9a18a766d 100644 --- a/src/java/org/jivesoftware/sparkimpl/settings/local/LocalPreference.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/settings/local/LocalPreference.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,8 +20,7 @@ import org.jivesoftware.resource.SparkRes; import org.jivesoftware.spark.preference.Preference; -import javax.swing.Icon; -import javax.swing.JComponent; +import javax.swing.*; /** * Represents the Local Preference inside the Preference Manager. @@ -42,36 +37,42 @@ public LocalPreference() { preferences = SettingsManager.getLocalPreferences(); } - public String getTitle() { + @Override + public String getTitle() { return Res.getString("title.login.settings"); } - public String getListName() { + @Override + public String getListName() { return Res.getString("title.login"); } - public String getTooltip() { + @Override + public String getTooltip() { return Res.getString("title.login.settings"); } - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.LOGIN_KEY_IMAGE); + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icon.LOGIN_KEY_IMAGE); } - public void load() { + @Override + public void load() { preferences = SettingsManager.getLocalPreferences(); } - public void commit() { + @Override + public void commit() { getData(); - - SettingsManager.saveSettings(); } - public Object getData() { + @Override + public Object getData() { preferences = SettingsManager.getLocalPreferences(); preferences.setAutoLogin(panel.getAutoLogin()); preferences.setTimeOut(Integer.parseInt(panel.getTimeout())); + preferences.setReconnectDelay(Integer.parseInt(panel.getReconnectDelay())); preferences.setXmppPort(Integer.parseInt(panel.getPort())); preferences.setSavePassword(panel.isSavePassword()); preferences.setIdleOn(panel.isIdleOn()); @@ -84,11 +85,13 @@ public Object getData() { return preferences; } - public String getErrorMessage() { + @Override + public String getErrorMessage() { return errorMessage; } - public boolean isDataValid() { + @Override + public boolean isDataValid() { preferences.setTimeOut(Integer.parseInt(panel.getTimeout())); preferences.setXmppPort(Integer.parseInt(panel.getPort())); @@ -111,19 +114,21 @@ public boolean isDataValid() { return true; } - public JComponent getGUI() { + @Override + public JComponent getGUI() { panel = new LocalPreferencePanel(); return panel; } - public String getNamespace() { + @Override + public String getNamespace() { return "LOGIN"; } - public void shutdown() { + @Override + public void shutdown() { // Commit to file. - SettingsManager.saveSettings(); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/settings/local/LocalPreferencePanel.java b/core/src/main/java/org/jivesoftware/sparkimpl/settings/local/LocalPreferencePanel.java new file mode 100644 index 000000000..1a022a855 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/settings/local/LocalPreferencePanel.java @@ -0,0 +1,345 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.sparkimpl.settings.local; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; + +import javax.swing.BorderFactory; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.VerticalFlowLayout; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; + +/** + * UI for editing Local Preferences. + */ +public class LocalPreferencePanel extends JPanel { + private static final long serialVersionUID = -1675058807882383560L; + + private final JTextField _portField = new JTextField(); + private final JTextField _timeOutField = new JTextField(); + private final JTextField _reconnectDelayField = new JTextField(); + private final JTextField _idleField = new JTextField(); + private final JTextField _idleStatusText; + + private final JCheckBox _autoLoginBox = new JCheckBox(); + private final JCheckBox _savePasswordBox = new JCheckBox(); + private final JCheckBox _idleBox = new JCheckBox(); + private final JCheckBox _launchOnStartupBox = new JCheckBox(); + private final JCheckBox _startMinimizedBox = new JCheckBox(); + private final JCheckBox _useSingleTrayClick = new JCheckBox(); + + + /** + * Construct Local Preference UI. + */ + public LocalPreferencePanel() { + setLayout(new VerticalFlowLayout()); + + + // Load local localPref + LocalPreferences preferences = SettingsManager.getLocalPreferences(); + _portField.setText(Integer.toString(preferences.getXmppPort())); + _timeOutField.setText(Integer.toString(preferences.getTimeOut())); + _reconnectDelayField.setText(Integer.toString(preferences.getReconnectDelay())); + _autoLoginBox.setSelected(preferences.isAutoLogin()); + _savePasswordBox.setSelected(preferences.isSavePassword()); + _startMinimizedBox.setSelected(preferences.isStartedHidden()); + _useSingleTrayClick.setSelected(preferences.isUsingSingleTrayClick()); + + _idleStatusText = new JTextField(preferences.getIdleMessage()); + if (preferences.isSSOEnabled()) { + _savePasswordBox.setSelected(false); + _autoLoginBox.setEnabled(true); + } else { + _savePasswordBox.addActionListener(e -> { + _autoLoginBox.setEnabled(_savePasswordBox.isSelected()); + if (_savePasswordBox.isSelected()) { + String user = SparkManager.getSessionManager().getUserBareAddress().toString(); + String password = SparkManager.getSessionManager().getPassword(); + try { + preferences.setPasswordForUser(user,password); + } catch (Exception ex) { + Log.error("Error storing encrypted password.", ex); + } + } + if (!_savePasswordBox.isSelected()) { + _autoLoginBox.setSelected(false); + try { + preferences.clearPasswordForAllUsers(); + } catch (Exception e1) { + Log.debug("Unable to clear saved password..." + e1); + } + + } + }); + } + + _autoLoginBox.addActionListener( e -> { + if ((_autoLoginBox.isSelected()) && (!preferences.isSSOEnabled())) { + _savePasswordBox.setSelected(true); + } + } ); + + _idleBox.addActionListener( e -> _idleField.setEnabled(_idleBox.isSelected()) ); + + + _idleBox.setSelected(preferences.isIdleOn()); + _idleField.setText(Integer.toString(preferences.getIdleTime())); + + final JPanel inputPanel = new JPanel(); + inputPanel.setLayout(new GridBagLayout()); + inputPanel.setBorder(BorderFactory.createTitledBorder(Res + .getString("group.login.information"))); + + JLabel _portLabel = new JLabel(); + ResourceUtils.resLabel( _portLabel, _portField,Res.getString("label.xmpp.port") + ":"); + JLabel _timeOutLabel = new JLabel(); + ResourceUtils.resLabel( _timeOutLabel, _timeOutField, + Res.getString("label.response.timeout") + ":"); + + JLabel _reconnectDelayLabel = new JLabel(); + ResourceUtils.resLabel( _reconnectDelayLabel, _reconnectDelayField, + Res.getString("label.reconnect.delay") + ":"); + + JLabel _idleStatusLabel = new JLabel(); + ResourceUtils.resLabel( _idleStatusLabel, _idleStatusText, + Res.getString("label.time.till.idlemessage") + ":"); + + ResourceUtils.resButton(_autoLoginBox, + Res.getString("checkbox.auto.login")); + ResourceUtils.resButton(_savePasswordBox, + Res.getString("checkbox.save.password")); + JLabel _idleLabel = new JLabel(); + ResourceUtils.resLabel( _idleLabel, _idleField, + Res.getString("label.time.till.idle") + ":"); + ResourceUtils.resButton(_idleBox, + Res.getString("checkbox.idle.enabled")); + + ResourceUtils.resButton(_launchOnStartupBox, + Res.getString("checkbox.launch.on.startup")); + ResourceUtils.resButton(_startMinimizedBox, + Res.getString("checkbox.start.in.tray")); + ResourceUtils.resButton(_useSingleTrayClick, + Res.getString("checkbox.click.single.tray")); + + inputPanel.add( _portLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + inputPanel.add(_portField, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,new Insets(5, 5, 5, 5), 0, 0)); + inputPanel.add( _timeOutLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,new Insets(5, 5, 5, 5), 50, 0)); + inputPanel.add(_timeOutField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); + inputPanel.add( _reconnectDelayLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,new Insets(5, 5, 5, 5), 50, 0)); + inputPanel.add(_reconnectDelayField, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); + inputPanel.add( _idleLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,new Insets(5, 5, 5, 5), 50, 0)); + inputPanel.add(_idleField, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,new Insets(5, 5, 5, 5), 50, 0)); + inputPanel.add( _idleStatusLabel,new GridBagConstraints(0, 4, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); + inputPanel.add(_idleStatusText, new GridBagConstraints(1, 4, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); + inputPanel.add(_idleBox, new GridBagConstraints(0, 5, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); + + if(Default.getBoolean(Default.IDLE_LOCK) || !Enterprise.containsFeature(Enterprise.IDLE_FEATURE)) { + _idleField.setEnabled(false); + _idleStatusText.setEnabled(false); + _idleBox.setEnabled(false); + } + + if(!Default.getBoolean(Default.HIDE_SAVE_PASSWORD_AND_AUTO_LOGIN) && SettingsManager.getLocalPreferences().getPswdAutologin()) { + if (!preferences.isSSOEnabled()) { + inputPanel.add(_savePasswordBox, new GridBagConstraints(0, 6, 2, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); + } + inputPanel.add(_autoLoginBox, new GridBagConstraints(0, 7, 2, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); + } + + if (Spark.isWindows()) { + inputPanel.add(_launchOnStartupBox, new GridBagConstraints(0, 8, 2, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50,0)); + _launchOnStartupBox.addActionListener( e -> setStartOnStartup(_launchOnStartupBox.isSelected()) ); + + _launchOnStartupBox.setSelected(preferences.getStartOnStartup()); + } + + inputPanel.add(_startMinimizedBox, new GridBagConstraints(0, 9, 2, 1,0.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); + inputPanel.add(_useSingleTrayClick, new GridBagConstraints(0, 10, 2, 1,0.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); + inputPanel.add(new JLabel(), new GridBagConstraints(0, 11, 2, 1, 1.0,1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,new Insets(5, 5, 5, 5), 50, 0)); + + + add(inputPanel); + } + + /** + * Sets the XMPP port to comminucate on. + * + * @param port + * the XMPP port to communicate on. + */ + public void setPort(String port) { + _portField.setText(port); + } + + /** + * Return the XMPP Port to communicate on. + * + * @return the XMPP Port to communicate on. + */ + public String getPort() { + return _portField.getText(); + } + + /** + * Sets the XMPP Timeout(in seconds). + * + * @param timeOut + * the XMPP Timeout(in seconds). + */ + public void setTimeOut(String timeOut) { + _timeOutField.setText(timeOut); + } + + /** + * Return the XMPP Timeout variable. + * + * @return the XMPP Timeout variable. + */ + public String getTimeout() { + return _timeOutField.getText(); + } + + public void setReconnectDelay(String reconnectDelay) { + _reconnectDelayField.setText(reconnectDelay); + } + + public String getReconnectDelay() { + return _reconnectDelayField.getText(); + } + + /** + * Sets Auto Login on and off. + * + * @param auto + * true if Auto Login is on. + */ + public void setAutoLogin(boolean auto) { + _autoLoginBox.setSelected(auto); + } + + /** + * Return true if Auto Login is on. + * + * @return true if Auto Login is on. + */ + public boolean getAutoLogin() { + return _autoLoginBox.isSelected(); + } + + /** + * Set true if the password should be encoded and saved. + * + * @param save + * true if the password should be encoded and saved. + */ + public void setSavePassword(boolean save) { + _savePasswordBox.setSelected(save); + } + + /** + * Return true if the password should be saved. + * + * @return true if the password should be saved. + */ + public boolean isSavePassword() { + return _savePasswordBox.isSelected(); + } + + /** + * Returns true if IDLE is on. + * + * @return true if IDLE is on. + */ + public boolean isIdleOn() { + return _idleBox.isSelected(); + } + + /** + * Sets the IDLE on or off. + * + * @param on + * true if IDLE should be on. + */ + public void setIdleOn(boolean on) { + _idleBox.setSelected(on); + } + + /** + * Sets the Idle Time in minutes. + * + * @param time + * the Idle time in minutes. + */ + public void setIdleTime(int time) { + String idleTime = Integer.toString(time); + _idleField.setText(idleTime); + } + + /** + * Return the time to IDLE. + * + * @return the time to IDLE. + */ + public String getIdleTime() { + return _idleField.getText(); + } + + public void startInSystemTray(boolean startInTray) { + _startMinimizedBox.setSelected(startInTray); + } + + public boolean startInSystemTray() { + return _startMinimizedBox.isSelected(); + } + + public void useSingleClickInTray(boolean clickInTray) { + _useSingleTrayClick.setSelected(clickInTray); + } + + public boolean useSingleClickInTray() { + return _useSingleTrayClick.isSelected(); + } + + public boolean startOnStartup() { + return _launchOnStartupBox.isSelected(); + } + + public void setStartOnStartup(boolean startup) { + _launchOnStartupBox.setSelected(startup); + } + + public String getIdleMessage(){ + return _idleStatusText.getText(); + } + public void setIdleMessage(String text){ + _idleStatusText.setText(text); + } + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/settings/local/LocalPreferences.java b/core/src/main/java/org/jivesoftware/sparkimpl/settings/local/LocalPreferences.java new file mode 100644 index 000000000..5a6a30c4e --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/settings/local/LocalPreferences.java @@ -0,0 +1,1516 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.sparkimpl.settings.local; + +import org.apache.commons.lang3.StringUtils; +import org.jasypt.properties.EncryptableProperties; +import org.jasypt.properties.PropertyValueEncryptionUtils; +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.ConnectionConfiguration; +import org.jivesoftware.spark.PluginRes; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.util.Encryptor; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.Sizes; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Resourcepart; + +import javax.swing.*; +import java.io.File; +import java.util.Date; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Represents the LocalPreference Model for this system. + */ +public class LocalPreferences { + + private final EncryptableProperties props; + + public LocalPreferences(EncryptableProperties props) { + this.props = props; + } + + public LocalPreferences() { + this.props = new EncryptableProperties(Encryptor.AES256_INSTANCE); + } + + public Properties getProperties() { + return props; + } + + /** + * Returns the XMPP Port to communicate on. + * + * @return the XMPP Port to communicate on. Default is 5222. + */ + public int getXmppPort() { + return Integer.parseInt(props.getProperty("xmppPort", Default.getString(Default.XMPP_PORT))); + } + + /** + * Sets the XMPP Port to communicate on. + * + * @param xmppPort + * the XMPP Port to communicate on. Default is 5222. + */ + public void setXmppPort(int xmppPort) { + props.setProperty("xmppPort", Integer.toString(xmppPort)); + } + + /** + * Sets room's password. + * + * @param password + * sets encrypted password for a room. + */ + public void setGroupChatPassword(String roomName, String password) throws Exception { + Encryptor.setMasterPassword(!hasStoredPasswords()); + // property must start with "password." for hasStoredPasswords() to find it + props.setProperty("password.room."+roomName, PropertyValueEncryptionUtils.encrypt(password, Encryptor.AES256_INSTANCE)); + } + + /** + * Returns decrypted room's password. + * + * @return decrypted room's password. + */ + public String getGroupChatPassword(String roomName) + { + // property must start with "password." for hasStoredPasswords() to find it + final String propName = "password.room."+roomName; + if(!props.containsKey(propName)) { + return null; + } + + Encryptor.setMasterPassword(!hasStoredPasswords()); + return props.getProperty(propName); // automatically decrypted by EncryptableProperties + } + + /** + * Return the smack timeout for requests. Default is 5 seconds. + * + * @return the smack timeout for requests. + */ + public int getTimeOut() { + return Integer.parseInt(props.getProperty("timeout", Default.getString(Default.TIME_OUT))); + } + + /** + * Sets the smack timeout for requests. The default is 5 seconds, but you + * may wish to increase this number for low bandwidth users. + * + * @param timeOut + * the smack timeout. + */ + public void setTimeOut(int timeOut) { + props.setProperty("timeout", Integer.toString(timeOut)); + } + + public int getReconnectDelay() { + return Integer.parseInt(props.getProperty("reconnectDelay", "10")); + } + + public void setReconnectDelay(int reconnectDelay) { + props.setProperty("reconnectDelay", Integer.toString(reconnectDelay)); + } + + + /** + * Returns the encoded password. + * + * @return the encoded password. + */ +// public String getPassword() { +// return props.getProperty("password"); +// } + + /** + * Sets the encoded password. + * + * @param password + * the encoded password. + */ +// public void setPassword(String password) { +// props.setProperty("password", password); +// } + + /** + * Returns room's password. + * + * @return room's password. + */ + public String getPasswordForRoom(String room) + { + // property must start with "password." for hasStoredPasswords() to find it + final String propName = "password.room."+room; + if(!props.containsKey(propName)) { + return null; + } + + Encryptor.setMasterPassword(!hasStoredPasswords()); + return props.getProperty("password.room."+room,""); + } + + /** + * returns the password for an encrypted jid + * @param barejid + * @return + */ + public String getPasswordForUser(String barejid) + { + // property must start with "password." for hasStoredPasswords() to find it + final String propName = "password.user."+barejid; + if(!props.containsKey(propName)) { + return null; + } + + Encryptor.setMasterPassword(!hasStoredPasswords()); + try { + return props.getProperty(propName); + } catch(Exception e){ + return null; + } + } + + /** + * Sets the password for barejid
      + * both will be encrypted + * @param barejid + * @param password + * @throws Exception + */ + public void setPasswordForUser(String barejid, String password) throws Exception + { + Encryptor.setMasterPassword(!hasStoredPasswords()); + // property must start with "password." for hasStoredPasswords() to find it + props.setProperty("password.user."+barejid, PropertyValueEncryptionUtils.encrypt(password, Encryptor.AES256_INSTANCE)); + } + + /** + * Checks if the preferences contain any stored/saved account passwords. + * + * @return true if at least one stored account password was found, otherwise null. + */ + public boolean hasStoredPasswords() { + return !findPropertyNamesForStoredPasswords().isEmpty(); + } + + /** + * Remove all previously saved user-account passwords. + */ + public void clearPasswordForAllUsers() + { + final Set propertyNames = findPropertyNamesForStoredPasswords(); + + // Remove all of the properties that are a stored password. + propertyNames.forEach(props::remove); + } + + /** + * Find the name of all properties that store a password. + * + * @return A collection of property names (possibly empty) + */ + private Set findPropertyNamesForStoredPasswords() { + return props.stringPropertyNames().stream() + // The property name starts with 'password.'. + .filter(name -> name.startsWith("password.")) + .collect(Collectors.toSet()); + } + + /** + * Return true if the IDLE feature is on. The IDLE feature allows to monitor + * computer activity and set presence accordingly. + * + * @return true if IDLE is on. + */ + public boolean isIdleOn() { + return Boolean.parseBoolean(props.getProperty("idleOn", "true")); + } + + /** + * Set the IDLE feature on or off. The IDLE feature allows to monitor + * computer activity and set presence accordingly. + * + * @param idleOn + * true to turn idle on. + */ + public void setIdleOn(boolean idleOn) { + props.setProperty("idleOn", Boolean.toString(idleOn)); + } + + /** + * Is "Use ad hoc room" enabled + * @return true if it is wanted that a new ad hoc room to be created every time Actions/Start conference room is chosen, + * or, from a chat window - invite to group chat room icon is pressed. + * Returns false if it is wanted that the bookmarked room (if any) to be opened every time Actions/Start conference room is chosen, + * or, from a chat window - invite to group chat room icon is pressed. + */ + public boolean isUseAdHocRoom() { + String adhoc = PluginRes.getPreferenceRes("useAdHocRoom"); + return getBoolean("useAdHocRoom", adhoc == null || Boolean.parseBoolean(adhoc)); + } + + /** + * Set useAdHocRoom on or off. When disabled, if there is at least one bookmark room, that + * room will be used in Actions/Start conference room Invitation Dialog (instead of creating an ad-hoc room) + * If there is more than one bookmark room, you can select the bookmarked room that you want to be used + * Also, when invite to join group chat room will be sent from the chat window, the bookmark room will automatically + * be opened. + * @param adHocRoom + * @return + */ + public void setUseAdHocRoom(boolean adHocRoom) { + setBoolean("useAdHocRoom", adHocRoom); + } + /** + * Returns the Idle Message to Display when going automatically away + * @return + */ + public String getIdleMessage(){ + return props.getProperty("idleOnMessage",Res.getString("status.away")); + } + + /** + * Sets the idle Message when going automatically away + * @param message + */ + public void setIdleMessage(String message){ + props.setProperty("idleOnMessage",message); + } + + /** + * Returns the number of minutes to set to unavailable if the computer has + * no activity. + * + * @return the number of minutes before checking for IDLE computer. + */ + public int getIdleTime() { + return Integer.parseInt(props.getProperty("idleTime", Default.getString(Default.IDLE_TIME))); + } + + /** + * Set the number of minutes to set to unavailable if the computer has no + * activity. + * + * @param secondIdleTime + * the number of minutes. + */ + public void setIdleTime(int secondIdleTime) { + props.setProperty("idleTime", Integer.toString(secondIdleTime)); + } + + /** + * Return true if Auto Login is on. + * + * @return true if Auto Login is on. + */ + public boolean isAutoLogin() { + return Boolean.parseBoolean(props.getProperty("autoLoginEnabled", + "false")); + } + + /** + * Turn on or off Auto Login. Auto Login allows a user to login to the + * system without inputting their signing information. + * + * @param autoLogin + * true if Auto Login should be on. + */ + public void setAutoLogin(boolean autoLogin) { + props.setProperty("autoLoginEnabled", Boolean.toString(autoLogin)); + } + + /** + * Return true if Login As Invisible is on. + * + * @return true if Login As Invisible is on. + */ + public boolean isLoginAsInvisible() { + return Boolean.parseBoolean(props.getProperty("loginAsInvisibleEnabled", + "false")); + } + + /** + * Turn on or off Login As Invisible option. + * + * @param loginAsInvisible true if Login As Invisible should be on. + */ + public void setLoginAsInvisible(boolean loginAsInvisible) { + props.setProperty("loginAsInvisibleEnabled", Boolean.toString(loginAsInvisible)); + } + + /** + * Return true if Login Anonymously is on. + * + * @return true if Login Anonymously is on. + */ + public boolean isLoginAnonymously() { + return Boolean.parseBoolean(props.getProperty("loginAnonymously", + "false")); + } + + /** + * Turn on or off Login Anonymously option. + * + * @param loginAnonymously true if Login Anonymously should be on. + */ + public void setLoginAnonymously(boolean loginAnonymously) { + props.setProperty("loginAnonymously", Boolean.toString(loginAnonymously)); + } + + /** + * Return true if the password should be encoded and persisted. + * + * @return true if the password is encoded and persisted. + */ + public boolean isSavePassword() { + return Boolean + .parseBoolean(props.getProperty("passwordSaved", "false")); + } + + /** + * Set to true to encode and save password. You would use this if you wish + * to not always input ones password. + * + * @param savePassword + * true if the password should be saved. + */ + public void setSavePassword(boolean savePassword) { + props.setProperty("passwordSaved", Boolean.toString(savePassword)); + } + + /** + * Returns the last used Username + * + * @return the username of the agent. + */ + public String getLastUsername() { + return props.getProperty("username"); + } + + /** + * Sets the Agents username. + * + * @param username + * the agents username. + */ + public void setLastUsername(String username) { + props.setProperty("username", username); + } + + /** + * Returns the last Server accessed. + * + * @return the last Server accessed. + */ + public String getServer() { + return props.getProperty("server"); + } + + /** + * Sets the last Server accessed. + * + * @param server + * the last Server accessed. + */ + public void setServer(String server) { + props.setProperty("server", server); + } + + /** + * Return true if this is a fresh install. + * + * @return true if a fresh install. + */ + public boolean isNewInstall() { + return Boolean.parseBoolean(props.getProperty("newInstall", "false")); + } + + /** + * Set if this is a fresh install. + * + * @param newInstall + * true if this is a fresh install. + */ + public void setNewInstall(boolean newInstall) { + props.setProperty("newInstall", Boolean.toString(newInstall)); + } + + /** + * Return the desirability of encryption. + * + * @return The security mode. + * @see org.jivesoftware.smack.ConnectionConfiguration.SecurityMode + */ + public ConnectionConfiguration.SecurityMode getSecurityMode() + { + try + { + final String securityMode = props.getProperty( "securityMode", Default.getString(Default.SECURITY_MODE) ); + return ConnectionConfiguration.SecurityMode.valueOf( securityMode ); + } + catch ( Exception e ) + { + Log.warning( "Unable to parse 'securityMode' value. Using default instead.", e ); + return ConnectionConfiguration.SecurityMode.ifpossible; + } + } + + /** + * Sets the desirability of encryption. + * + * @return The security mode. + * @see org.jivesoftware.smack.ConnectionConfiguration.SecurityMode + */ + public void setSecurityMode( ConnectionConfiguration.SecurityMode securityMode ) + { + props.setProperty( "securityMode", securityMode.toString() ); + } + + /** + * Returns true to use 'old style' Direct TLS. + *

      + * This type of encryption typically occurs on port 5223, and causes the socket to be TLS-encrypted immediately. + *

      + * When this option is disabled, but encryption is still to be used, STARTTLS will be used instead. + * + * @return true if we should connect via 'old-style' Direct TLS (otherwise, STARTTLS might be used). + */ + public boolean isDirectTls() { + return getBoolean("sslEnabled", Default.getBoolean(Default.OLD_SSL_ENABLED)); + } + + /** + * Sets if the agent should use 'old style' Direct TLS for connecting. + *

      + * This type of encryption typically occurs on port 5223, and causes the socket to be SSL-encrypted immediately. + *

      + * When this option is disabled, but encryption is still to be used, STARTTLS will be used instead. + * + * @param directTls true if we should be using Direct TLS, false if STARTTLS is to be used for encryption. + */ + public void setDirectTls(boolean directTls) { + props.setProperty("sslEnabled", Boolean.toString(directTls)); + } + + /** + * Returns the Download Directory, doesnt return null + * @return {@link String} + */ + public String getDownloadDir() { + + File downloadedDir = null; + if (Spark.isLinux() || Spark.isMac()) { + downloadedDir = new File(System.getProperty("user.home") + "/Downloads/"); + if (!downloadedDir.exists()) { + downloadedDir.mkdir(); + } + Log.debug("Absolute path for download directory: " + downloadedDir.getAbsolutePath()); + } else if (Spark.isWindows()) { + File docDir = new File(System.getProperty("user.home") + "\\Documents"); + if (docDir.canWrite()) { + downloadedDir = new File(docDir + "\\Downloads"); + if (!downloadedDir.exists()) { + downloadedDir.mkdir(); + } + } else { + // if for some Reason there is no "My Documents" Folder we should select the Desktop + downloadedDir = new File(System.getProperty("user.home") + "\\Desktop\\"); + } + } else { + downloadedDir = new File(System.getProperty("user.home")); + } + return props.getProperty("downloadDirectory", downloadedDir.getAbsolutePath()); + } + + public void setDownloadDir(String downloadDir) { + props.setProperty("downloadDirectory", downloadDir); + } + + public String getFileExplorer() { + return props.getProperty("fileExplorer"); + } + + public void setFileExplorer(String fileExplorer) { + props.setProperty("fileExplorer", fileExplorer); + } + + public boolean isProxyEnabled() { + return getBoolean("proxyEnabled", Default.getBoolean(Default.PROXY_ENABLED)); + } + + public void setProxyEnabled(boolean proxyEnabled) { + setBoolean("proxyEnabled", proxyEnabled); + } + + public String getHost() { + return props.getProperty("host"); + } + + public void setHost(String host) { + props.setProperty("host", host); + } + + public String getPort() { + return props.getProperty("port"); + } + + public void setPort(String port) { + props.setProperty("port", port); + } + + public String getProxyUsername() { + return props.getProperty("proxyUsername"); + } + + public void setProxyUsername(String proxyUsername) { + props.setProperty("proxyUsername", proxyUsername); + } + + public String getProxyPassword() { + // property must start with "password." for hasStoredPasswords() to find it + if(!props.containsKey("password.proxy")) { + return null; + } + + Encryptor.setMasterPassword(!hasStoredPasswords()); + return props.getProperty("password.proxy"); + } + + public void setProxyPassword(String proxyPassword) { + Encryptor.setMasterPassword(!hasStoredPasswords()); + // property must start with "password." for hasStoredPasswords() to find it + props.setProperty("password.proxy", PropertyValueEncryptionUtils.encrypt(proxyPassword, Encryptor.AES256_INSTANCE)); + } + + public String getProtocol() { + return props.getProperty("protocol"); + } + + public void setProtocol(String protocol) { + props.setProperty("protocol", protocol); + } + + public String getDefaultNickname() { + return props.getProperty("defaultNickname"); + } + + public void setDefaultNickname(String defaultNickname) { + props.setProperty("defaultNickname", defaultNickname); + } + + public int getCheckForUpdates() { + return Integer.parseInt(props.getProperty("checkForUpdates", "7")); + } + + public Date getLastCheckForUpdates() { + String date = props.getProperty("lastUpdateCheck"); + if (date == null) { + return null; + } + + // Convert to long + long time = Long.parseLong(date); + return new Date(time); + } + + public void setLastCheckForUpdates(Date lastCheckForUpdates) { + String time = Long.toString(lastCheckForUpdates.getTime()); + props.setProperty("lastUpdateCheck", time); + } + + public String getXmppHost() { + return props.getProperty("xmppHost"); + } + + public void setXmppHost(String xmppHost) { + props.setProperty("xmppHost", xmppHost); + } + + public boolean isHostAndPortConfigured() { + return getBoolean("hostAndPort", Default.getBoolean(Default.HOST_AND_PORT_CONFIGURED)); + } + + public void setHostAndPortConfigured(boolean configured) { + setBoolean("hostAndPort", configured); + } + + public String getResource() { + return props.getProperty("resource", Default.getString(Default.SHORT_NAME)); + } + + public void setResource(String resource) { + props.setProperty("resource", resource); + } + + public boolean isStartedHidden() { + return getBoolean("startHidden", false); + } + + public void setStartedHidden(boolean startedHidden) { + setBoolean("startHidden", startedHidden); + } + + public boolean isUsingSingleTrayClick() { + return getBoolean("useSingleTrayClick", true); + } + + public void setUsingSingleTrayClick(boolean useSingle) { + setBoolean("useSingleTrayClick", useSingle); + } + + public boolean isTimeDisplayedInChat() { + return getBoolean("timeDisplayed", true); + } + + public void setTimeDisplayedInChat(boolean timeDisplayedInChat) { + setBoolean("timeDisplayed", timeDisplayedInChat); + } + + public void setTimeFormat(String format) { + props.setProperty("timeFormat", format); + } + + public String getTimeFormat() { + return props.getProperty("timeFormat", "HH:mm"); + } + + public boolean isSpellCheckerEnabled() { + return getBoolean("spellCheckerEnabled", true); + } + + public void setSpellCheckerEnabled(boolean enabled) { + setBoolean("spellCheckerEnabled", enabled); + } + + public boolean isChatRoomNotificationsOn() { + return getBoolean("chatNotificationOn", true); + } + + public void setChatRoomNotifications(boolean on) { + setBoolean("chatNotificationOn", on); + } + + public boolean isChatHistoryEnabled() { + return getBoolean("showHistory", true); + } + + public void setChatHistoryEnabled(boolean hidePrevChatHistory) { + setBoolean("showHistory", hidePrevChatHistory); + } + + public boolean isPrevChatHistoryEnabled() { + return getBoolean("showPrevHistory", true); + } + + public void setPrevChatHistoryEnabled(boolean hidePrevChatHistory) { + setBoolean("showPrevHistory", hidePrevChatHistory); + } + + public boolean isEmptyGroupsShown() { + return getBoolean("showEmptyGroups", false); + } + + public void setEmptyGroupsShown(boolean shown) { + setBoolean("showEmptyGroups", shown); + } + + public boolean isOfflineUsersShown() { + return getBoolean("showOfflineUsers", true); + } + + public void setOfflineUsersShown(boolean shown) { + setBoolean("showOfflineUsers", shown); + } + + public boolean isTypingNotificationShown() { + String showTypingNotification = PluginRes.getPreferenceRes("showTypingNotification"); + return getBoolean("showTypingNotification", Boolean.parseBoolean(showTypingNotification)); + } + + public void setSystemTrayNotificationEnabled(boolean shown) { + setBoolean("SystemTrayNotificationEnabled", shown); + } + + public boolean isSystemTrayNotificationEnabled() { + String SystemTrayNotificationEnabled = PluginRes.getPreferenceRes("SystemTrayNotificationEnabled"); + return getBoolean("SystemTrayNotificationEnabled", Boolean.parseBoolean(SystemTrayNotificationEnabled)); + } + + public void setTypingNotificationOn(boolean shown) { + setBoolean("showTypingNotification", shown); + } + + public int getFileTransferTimeout() { + return Integer.parseInt(props.getProperty("fileTransferTimeout", "30")); + } + + public void setFileTransferTimeout(int minutes) { + props.setProperty("fileTransferTimeout", Integer.toString(minutes)); + } + + public void setChatLengthDefaultTimeout(int minutes) { + props + .setProperty("defaultChatLengthTimeout", Integer + .toString(minutes)); + } + + public int getChatLengthDefaultTimeout() { + return Integer.parseInt(props.getProperty("defaultChatLengthTimeout", + "15")); + } + + public void setNickname(Resourcepart nickname) { + props.setProperty("nickname", nickname.toString()); + } + + public Resourcepart getNickname() { + String nicknameString = props.getProperty("nickname", SparkManager.getUserManager() + .getNickname()); + return Resourcepart.fromOrThrowUnchecked(nicknameString); + } + + public void setShowToasterPopup(boolean show) { + setBoolean("toasterPopup", show); + } + + public boolean getShowToasterPopup() { + String toasterPopup = PluginRes.getPreferenceRes("toasterPopup"); + return getBoolean("toasterPopup", Boolean.parseBoolean(toasterPopup)); + } + + public void setDisableAsteriskToasterPopup(boolean disable) { + setBoolean("disableAsteriskToasterPopup", disable); + } + + public boolean getDisableAsteriskToasterPopup() { + return getBoolean("disableAsteriskToasterPopup", false); + } + + public void setWindowTakesFocus(boolean focus) { + setBoolean("windowTakesFocus", focus); + } + + public boolean getWindowTakesFocus() { + return getBoolean("windowTakesFocus", false); + } + + public void setStartOnStartup(boolean startup) { + setBoolean("startOnStartup", startup); + } + + public boolean getStartOnStartup() { + return getBoolean("startOnStartup", false); + } + + /** + * Sets the Reconnection display type

      + * 0 = ReconnectPanel

      + * 1 = Reconnect as Group

      + * 2 = Reconnect as Icon

      + * @param reconnect + */ + public void setReconnectPanelType(int reconnect) { + setInt("ReconnectPanelType", reconnect); + } + + /** + * Sets the Reconnection display type

      + * 0 = ReconnectPanel

      + * 1 = Reconnect as Group

      + * 2 = Reconnect as Icon

      + * @return + */ + public int getReconnectPanelType() { + return getInt("ReconnectPanelType", 1); + } + + public void setCompressionEnabled(boolean on) { + setBoolean("compressionOn", on); + } + + public boolean isCompressionEnabled() { + return getBoolean("compressionOn", Default.getBoolean(Default.COMPRESSION_ENABLED)); + } + + public void setTheme(String theme) { + props.setProperty("theme", theme); + } + + public String getTheme() { + return props.getProperty("theme", "Default"); + } + + public void setEmoticonPack(String pack) { + props.setProperty("emoticonPack", pack); + } + + public String getEmoticonPack() { + return props.getProperty("emoticonPack", "Default"); + } + + public void setNotificationsDisplayTime(Integer DisplayTime) { + setInt("DisplayTime", DisplayTime); + } + + public int getNotificationsDisplayTime() { + return getInt("DisplayTime", 3); + } + + public void setOfflineNotifications(boolean notify) { + setBoolean("notifyOnOffline", notify); + } + + public boolean isOfflineNotificationsOn() { + String notifyOnOffline = PluginRes.getPreferenceRes("notifyOnOffline"); + return getBoolean("notifyOnOffline", Boolean.parseBoolean(notifyOnOffline)); + } + + public void setOnlineNotifications(boolean notify) { + setBoolean("notifyOnOnline", notify); + } + + public boolean isOnlineNotificationsOn() { + String notifyOnOnline = PluginRes.getPreferenceRes("notifyOnOnline"); + return getBoolean("notifyOnOnline", Boolean.parseBoolean(notifyOnOnline)); + } + + public void setDockingEnabled(boolean dockingEnabled) { + setBoolean("dockingEnabled", dockingEnabled); + } + + public boolean isDockingEnabled() { + return getBoolean("dockingEnabled", false); + } + + public void setAutoCloseChatRoomsEnabled(boolean autoCloseChatRoomsEnabled) { + setBoolean("autoCloseChatRoomsEnabled", autoCloseChatRoomsEnabled); + } + + public boolean isAutoCloseChatRoomsEnabled() { + return getBoolean("autoCloseChatRoomsEnabled", true); + } + + public void setTabsOnTop(boolean onTop) { + setBoolean("tabsOnTop", onTop); + } + + public boolean isTabTopPosition() { + return getBoolean("tabsOnTop", true); + } + + public void setTabsScroll(boolean tabsScroll) { + setBoolean("tabsScroll", tabsScroll); + } + + public boolean isTabsScroll() { + return getBoolean("tabsScroll", true); + } + + public void setBuzzEnabled(boolean enabled) { + setBoolean("buzzEnabled", enabled); + } + + public boolean isBuzzEnabled() { + return getBoolean("buzzEnabled", true); + } + + public void setCloseUnreadMessageEnabled(boolean askBeforeCLosing) { + setBoolean("closeUnreadMessage", askBeforeCLosing); + } + + public boolean isCloseUnreadMessage() { + return getBoolean("closeUnreadMessage", true); + } + + public void setOfflineGroupVisible(boolean visible) { + setBoolean("offlineGroupVisible", visible); + } + + public boolean isOfflineGroupVisible() { + return getBoolean("offlineGroupVisible", true); + } + + public void setEmoticonsEnabled(boolean enabled) { + setBoolean("emoticonsEnabled", enabled); + } + + public boolean areEmoticonsEnabled() { + return getBoolean("emoticonsEnabled", true); + } + + public void setGrayingOutEnabled(boolean enabled) { + setBoolean("GrayingOut", enabled); + } + + public boolean isGrayingOutEnabled() { + return getBoolean("GrayingOut", true); + } + + public void setLookAndFeel(String laf) + { + setString("LookAndFeel",laf); + } + + public String getLookAndFeel() { + String defaultstring = Default.getString(Spark.isMac() ? Default.DEFAULT_LOOK_AND_FEEL_MAC : Default.DEFAULT_LOOK_AND_FEEL); + if (defaultstring == null || defaultstring.isEmpty()) { + defaultstring = UIManager.getSystemLookAndFeelClassName(); + } + return getString("LookAndFeel", defaultstring); + } + + public void setCheckForBeta(boolean checkForBeta) { + setBoolean("checkForBeta", checkForBeta); + } + + public boolean isBetaCheckingEnabled() { + return getBoolean("checkForBeta", false); + } + + public boolean isMucHighNameEnabled() { + return getBoolean("isMucHighNameOn", false); + } + + public boolean isMucHighTextEnabled() { + return getBoolean("isMucHighTextOn", false); + } + + public boolean isMucRandomColors(){ + return getBoolean("isMucRandomColors", true); + } + + public void setMucRandomColors(boolean value){ + setBoolean("isMucRandomColors", value); + } + + public boolean isMucHighToastEnabled() { + return getBoolean("isMucHighToastOn", false); + } + + public boolean isShowingRoleIcons() { + return getBoolean("isShowingRoleIcons",false); + } + + public boolean isShowJoinLeaveMessagesEnabled() { + return getBoolean("isShowJoinLeaveMessagesOn", false); + } + + public void setShowJoinLeaveMessagesEnabled(boolean enabled) { + setBoolean("isShowJoinLeaveMessagesOn", enabled); + } + + public void setMucHighNameEnabled(boolean setMucNHigh) { + setBoolean("isMucHighNameOn", setMucNHigh); + } + + public void setMucHighTextEnabled(boolean setMucTHigh) { + setBoolean("isMucHighTextOn", setMucTHigh); + } + + public void setMuchHighToastEnabled(boolean setMucPHigh) { + setBoolean("isMucHighToastOn", setMucPHigh); + } + + public void setShowRoleIconInsteadStatusIcon(boolean roleicons){ + setBoolean("isShowingRoleIcons",roleicons); + } + + public void setSSOEnabled(boolean enabled) { + setBoolean("ssoEnabled", enabled); + } + + public boolean isSSOEnabled() { + return getBoolean("ssoEnabled", Default.getBoolean(Default.USE_SSO)); + } + + public boolean isSaslGssapiSmack3Compatible() { + return getBoolean("saslGssapiSmack3compat", Default.getBoolean(Default.USE_SASL_GSS_API_SMACK_3_COMPATIBLE)); + } + + public void setSaslGssapiSmack3Compatible( boolean b) { + setBoolean( "saslGssapiSmack3compat", b ); + } + public void setSSOMethod(String method) { + props.setProperty("ssoMethod", method); + } + + public String getSSOMethod() { + return props.getProperty("ssoMethod"); + } + + public void setSSORealm(String realm) { + props.setProperty("ssoRealm", realm); + } + + public String getSSORealm() { + return props.getProperty("ssoRealm"); + } + + public void setSSOKDC(String kdc) { + props.setProperty("ssoKDC", kdc); + } + + public String getSSOKDC() { + return props.getProperty("ssoKDC"); + } + + public boolean getDebug() { + return getBoolean("debug", false); + } + + public void setDebug(boolean debug) { + setBoolean("debug", debug); + } + + public void setDebuggerEnabled(boolean enabled) { + setBoolean("debuggerEnabled", enabled); + } + + public boolean isDebuggerEnabled() { + return getBoolean("debuggerEnabled", Default.getBoolean(Default.DEBUGGER_ENABLED)); + } + + public void setContactListFontSize(int fontSize) { + setInt("contactListFontSize", fontSize); + } + + public int getContactListFontSize() { + return getInt("contactListFontSize", 11); + } + + public void setContactListIconSize(int iconSize) { + setInt("contactListIconSize", iconSize); + } + + public int getContactListIconSize() { + return getInt("contactListIconSize", Sizes.Avatar.CONTACT_LIST); + } + + public void setChatRoomFontSize(int fontSize) { + setInt("chatRoomFontSize", fontSize); + } + + public int getChatRoomFontSize() { + return getInt("chatRoomFontSize", 12); + } + + public void setLanguage(String language) { + props.setProperty("language", language); + } + + public String getLanguage() { + return props.getProperty("language", ""); + } + + public void setAvatarVisible(boolean visible) { + setBoolean("showAvatar", visible); + } + + public boolean areAvatarsVisible() { + return getBoolean("showAvatar", false); + } + + public void setVCardsVisible(boolean visible) { + setBoolean("showVCards", visible); + } + + public boolean areVCardsVisible() { + return getBoolean("showVCards", true); + } + + public void setAudioSystem(String device) { + props.setProperty("audioSystem", device); + } + + public String getAudioSystem() { + return props.getProperty("audioSystem","wasapi"); + } + + + public void setAudioDevice(String device) { + props.setProperty("audioDevice", device); + } + + public String getAudioDevice() { + return props.getProperty("audioDevice","javasound://"); + } + + public void setPlaybackDevice(String device) { + props.setProperty("playbackDevice", device); + } + + public String getPlaybackDevice() { + return props.getProperty("playbackDevice","javasound://"); + } + + public void setVideoDevice(String device) { + props.setProperty("videoDevice", device); + } + + public String getVideoDevice() { + return props.getProperty("videoDevice",null); + } + + public boolean isMainWindowAlwaysOnTop() { + return getBoolean("MainWindowAlwaysOnTop", false); + } + + public void setMainWindowAlwaysOnTop(boolean onTop) { + setBoolean("MainWindowAlwaysOnTop", onTop); + } + + public boolean isChatWindowAlwaysOnTop() { + return getBoolean("ChatWindowAlwaysOnTop", false); + } + + public void setChatWindowAlwaysOnTop(boolean onTop) { + setBoolean("ChatWindowAlwaysOnTop", onTop); + } + + public String getSelectedCodecs() { + return getString("SelectedCodecs", null); + } + + public String getStunFallbackHost() + { + return getString("stunFallbackHost", ""); + } + + public int getStunFallbackPort() + { + return getInt("stunFallbackPort", 3478); + } + + public void setStunFallbackHost(String host) { + setString("stunFallbackHost", host); + } + + public void setStunFallbackPort(int port) { + setInt("stunFallbackPort", port); + } + + public boolean getShowTransportTab() + { + return getBoolean("useTabForTransport", false); + } + + public void setShowTransportTab(boolean value) + { + setBoolean("useTabForTransport", value); + } + + public boolean isShowConferenceTab() + { + return getBoolean("useTabForConference", true); + } + + public void setShowConferenceTab(boolean value) + { + setBoolean("useTabForConference", value); + } + + public String getAvailableCodecs() { + return getString("AvailableCodecs", null); + } + + public void setSelectedCodecs(String value) { + setString("SelectedCodecs", value); + } + + public void setAvailableCodecs(String value) { + setString("AvailableCodecs", value); + } + + public void setDisableHostnameVerification(boolean accept) { + setBoolean("DisableHostnameVerification", accept); + } + + public boolean isDisableHostnameVerification() { + return getBoolean("DisableHostnameVerification", Default.getBoolean(Default.DISABLE_HOSTNAME_VERIFICATION)); + } + + private boolean getBoolean(String property, boolean defaultValue) { + return Boolean.parseBoolean(props.getProperty(property, Boolean + .toString(defaultValue))); + } + + private void setBoolean(String property, boolean value) { + props.setProperty(property, Boolean.toString(value)); + } + + private int getInt(String property, int defaultValue) { + return Integer.parseInt(props.getProperty(property, Integer + .toString(defaultValue))); + } + + private void setInt(String property, int value) { + props.setProperty(property, Integer.toString(value)); + } + + private String getString(String property, String defaultValue) { + return props.getProperty(property, defaultValue); + } + + private void setString(String property, String value) { + props.setProperty(property, value); + } + + public boolean isAutoAcceptMucInvite() { + return getBoolean("autoAcceptMucInvite", false); + } + + public void setAutoAcceptMucInvite(boolean autoAcceptMuc) { + setBoolean("autoAcceptMucInvite", autoAcceptMuc); + + } + + public EntityBareJid getDefaultBookmarkedConf() { + String jidString = props.getProperty("defaultBookmarkedConf"); + if (jidString == null) { + return null; + } + return JidCreate.entityBareFromOrThrowUnchecked(jidString); + } + + public void setDefaultBookmarkedConf(EntityBareJid bookmarkedConferenceJid) { + setString("defaultBookmarkedConf",bookmarkedConferenceJid.toString()); + } + + /** + * This will save if themessage-history should be display the messages
      + * by {@link Date} ascending (true) or descending (false) + * + * @param dateIsAsc indicates if the date should be displayed ascending or not + */ + public void setChatHistoryAscending(boolean dateIsAsc){ + setBoolean("HISTORY_SORT_DATEASC", dateIsAsc); + } + + /** + * This will return a {@link Boolean} to indicate if the message-history should display
      + * the messages by {@link Date} ascending (true) or descending (false) + * + * @return an {@link Boolean} that indicates if the message-history should
      + * be displayed ascending or descending + */ + public boolean getChatHistoryAscending(){ + return getBoolean("HISTORY_SORT_DATEASC", true); + } + + /** + * Get the default value for the search period in the + * history transcript plugin + * @param defaultValue the default value for the period + * @return the last value that was set + */ + public String getSearchPeriod(String defaultValue){ + return getString("HISTORY_SEARCH_PERIOD", "defaultValue"); + } + + /** + * Get the defaultVaue for the search period in the + * history transcript period + * @param value the last value that was set + */ + public void setSearchPeriod(String value){ + setString("HISTORY_SEARCH_PERIOD", value); + } + + public List getDeactivatedPlugins() + { + String plugs = getString("deactivatedPlugins", ""); + return List.of(StringUtils.split(plugs, ",")); + } + + public void setDeactivatedPlugins(List list) { + + // [hallo, hallo, hallo, hallo, hallo] + // = + // hallo,hallo,hallo,hallo,hallo + if (list.size() > 0) { + String liste = list.toString().substring(1, + list.toString().length() - 1); + liste = liste.replace(", ", ","); + setString("deactivatedPlugins", liste); + } else { + setString("deactivatedPlugins", ""); + } + + } + + public boolean isUseHostnameAsResource() { + return getBoolean("useHostnameAsResource", Default.getBoolean(Default.USE_HOSTNAME_AS_RESOURCE)); + } + + public void setUseHostnameAsResource(boolean useHostnameAsResource) { + setBoolean("useHostnameAsResource", useHostnameAsResource); + } + + public boolean isUseVersionAsResource() { + return getBoolean("useVersionAsResource", Default.getBoolean(Default.USE_VERSION_AS_RESOURCE)); + } + + public void setUseVersionAsResource(boolean useVersionAsResource) { + setBoolean("useVersionAsResource", useVersionAsResource); + } + + // The following methods are used by LoginPanel to support certain Enterprise features + public boolean getAccountsReg() { + return Boolean.parseBoolean(props.getProperty("ccAccountsReg","true")); + } + + public void setAccountsReg(boolean ccAccountsReg) { + props.setProperty("ccAccountsReg", Boolean.toString(ccAccountsReg)); + } + + public boolean getAdvancedConfig() { + return Boolean.parseBoolean(props.getProperty("ccAdvancedConfig","true")); + } + + public void setAdvancedConfig(boolean ccAdvancedConfig) { + props.setProperty("ccAdvancedConfig", Boolean.toString(ccAdvancedConfig)); + } + + public boolean getHostNameChange() { + return Boolean.parseBoolean(props.getProperty("ccHostNameChange","true")); + } + + public void setHostNameChange(boolean ccHostNameChange) { + props.setProperty("ccHostNameChange", Boolean.toString(ccHostNameChange)); + } + + public boolean getInvisibleLogin() { + return Boolean.parseBoolean(props.getProperty("ccInvisibleLogin","true")); + } + + public void setInvisibleLogin(boolean ccInvisibleLogin) { + props.setProperty("ccInvisibleLogin", Boolean.toString(ccInvisibleLogin)); + } + + public boolean getAnonymousLogin() { + return Boolean.parseBoolean(props.getProperty("ccAnonymousLogin","true")); + } + + public void setAnonymousLogin(boolean ccAnonymousLogin) { + props.setProperty("ccAnonymousLogin", Boolean.toString(ccAnonymousLogin)); + } + + public boolean getPswdAutologin() { + return Boolean.parseBoolean(props.getProperty("ccPswdAutologin","true")); + } + + public void setPswdAutologin(boolean ccPswdAutologin) { + props.setProperty("ccPswdAutologin", Boolean.toString(ccPswdAutologin)); + } + + public boolean isAcceptSelfSigned() { + return getBoolean("acceptSelfSigned", Default.getBoolean(Default.ACCEPT_SELF_SIGNED)); + } + + public void setAcceptSelfSigned(boolean acceptSelfSigned) { + props.setProperty("acceptSelfSigned", Boolean.toString(acceptSelfSigned)); + } + + public boolean isAcceptRevoked() { + return getBoolean("acceptRevoked", Default.getBoolean(Default.ACCEPT_REVOKED)); + } + + public void setAcceptRevoked(boolean acceptRevoked) { + props.setProperty("acceptRevoked", Boolean.toString(acceptRevoked)); + } + + public boolean isAcceptExpired() { + + return getBoolean("acceptExpired", Default.getBoolean(Default.ACCEPT_EXPIRED)); + } + + public void setAcceptExpired(boolean acceptExpired) { + props.setProperty("acceptExpired", Boolean.toString(acceptExpired)); + } + + public boolean isAcceptNotValidYet() { + return getBoolean("acceptNotValidYet", Default.getBoolean(Default.ACCEPT_NOT_VALID_YET)); + } + + public void setAcceptNotValidYet(boolean acceptNotValidYet) { + props.setProperty("acceptNotValidYet", Boolean.toString(acceptNotValidYet)); + } + + public boolean isCheckCRL() { + return getBoolean("checkCRL", Default.getBoolean(Default.CHECK_CRL)); + } + + public void setCheckCRL(boolean checkCRL) { + props.setProperty("checkCRL", Boolean.toString(checkCRL)); + } + + public boolean isCheckOCSP() { + return getBoolean("checkOCSP", Default.getBoolean(Default.CHECK_OCSP)); + } + + public void setCheckOCSP(boolean checkOCSP) { + props.setProperty("checkOCSP", Boolean.toString(checkOCSP)); + } + + public boolean isAllowSoftFail() { + return getBoolean("allowSoftFail", Default.getBoolean(Default.ALLOW_SOFT_FAIL)); + } + + public void setAllowSoftFail(boolean allowSoftFail) { + props.setProperty("allowSoftFail", Boolean.toString(allowSoftFail)); + } + + public boolean isAllowClientSideAuthentication() { + return getBoolean("allowClientSideAuthentication", Default.getBoolean(Default.ALLOW_CLIENT_SIDE_AUTH)); + } + + public void setAllowClientSideAuthentication(boolean allowClientSideAuthentication) { + props.setProperty("allowClientSideAuthentication", Boolean.toString(allowClientSideAuthentication)); + } + public void setFileTransferIbbOnly(boolean enable) { + setBoolean("fileTransferIbbOnly", enable); + } + + public boolean isFileTransferIbbOnly() { + return getBoolean("fileTransferIbbOnly", Default.getBoolean(Default.FILE_TRANSFER_IBB_ONLY)); + } + + public void setAutoAcceptFileTransferFromContacts(boolean enable) { + setBoolean("fileTransferAutoAcceptPresence", enable); + } + + public boolean isAutoAcceptFileTransferFromContacts() { + return getBoolean("fileTransferAutoAcceptPresence", Default.getBoolean(Default.FILE_TRANSFER_AUTO_ACCEPT_PRESENCE)); + } + + public void setMaxCurrentHistorySize( int value ) { + setInt( "currentHistoryMaxSize", value ); + } + + public int getMaxCurrentHistorySize() { + return getInt( "currentHistoryMaxSize", 20 ); + } +} diff --git a/src/java/org/jivesoftware/sparkimpl/settings/local/PreferenceListener.java b/core/src/main/java/org/jivesoftware/sparkimpl/settings/local/PreferenceListener.java similarity index 95% rename from src/java/org/jivesoftware/sparkimpl/settings/local/PreferenceListener.java rename to core/src/main/java/org/jivesoftware/sparkimpl/settings/local/PreferenceListener.java index 0631be3dd..889151cfb 100644 --- a/src/java/org/jivesoftware/sparkimpl/settings/local/PreferenceListener.java +++ b/core/src/main/java/org/jivesoftware/sparkimpl/settings/local/PreferenceListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/settings/local/SettingsManager.java b/core/src/main/java/org/jivesoftware/sparkimpl/settings/local/SettingsManager.java new file mode 100644 index 000000000..90a132358 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/settings/local/SettingsManager.java @@ -0,0 +1,184 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.sparkimpl.settings.local; + +import com.sun.jna.platform.win32.Advapi32Util; +import com.sun.jna.platform.win32.WinReg; +import org.jasypt.properties.EncryptableProperties; +import org.jivesoftware.Spark; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.util.Encryptor; +import org.jivesoftware.spark.util.log.Log; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Properties; +import java.util.concurrent.CopyOnWriteArrayList; + + +/** + * Responsible for the loading and persisting of LocalSettings. + */ +public class SettingsManager { + private static LocalPreferences localPreferences; + + private static final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList<>(); + + private SettingsManager() { + } + + static { + // always save settings on shutdown + Runtime.getRuntime().addShutdownHook(new Thread(SettingsManager::saveSettings)); + } + + /** + * Returns the LocalPreferences for this user. + */ + public synchronized static LocalPreferences getLocalPreferences() { + if (localPreferences != null) { + return localPreferences; + } + // Do Initial Load from FileSystem. + localPreferences = load(); + return localPreferences; + } + + /** + * Persists the settings to the local file system. + */ + public static void saveSettings() { + if (localPreferences == null) { + return; + } + Log.debug("Saving settings..."); + final Properties props = localPreferences.getProperties(); + try { + props.store(Files.newOutputStream(getSettingsFile().toPath()), "Spark Settings"); + } catch (Exception e) { + Log.error("Error saving settings.", e); + } + setUpAutostart(localPreferences.getStartOnStartup()); + Log.debug("Settings saved"); + } + + /** + * Returns the settings file. + * + * @return the settings file. + */ + public static File getSettingsFile() { + File file = Spark.getSparkUserHome(); + if (!file.exists()) { + file.mkdirs(); + } + return new File(file, "spark.properties"); + } + + + private static LocalPreferences load() { + final EncryptableProperties props = new EncryptableProperties(Encryptor.AES256_INSTANCE); + File settingsFile = getSettingsFile(); + if (settingsFile.exists()) { + try { + props.load(Files.newInputStream(settingsFile.toPath())); + } catch (IOException e) { + Log.error(e); + return new LocalPreferences(); + } + } + + // Override with global settings file + File globalSettingsFile = new File("spark.properties"); + if (globalSettingsFile.exists()) { + try { + props.load(Files.newInputStream(globalSettingsFile.toPath())); + } catch (IOException e) { + Log.error(e); + } + } + + return new LocalPreferences(props); + } + + public static void addPreferenceListener(PreferenceListener listener) { + listeners.addIfAbsent(listener); + } + + public static void removePreferenceListener(PreferenceListener listener) { + listeners.remove(listener); + } + + public static void fireListeners() { + for (PreferenceListener listener : listeners) { + try { + listener.preferencesChanged(localPreferences); + } catch (Exception e) { + Log.error("A PreferenceListener (" + listener + ") threw an exception while processing a 'referencesChanged' event.", e); + } + } + } + + + private static void setUpAutostart(boolean startOnStartup) { + if (localPreferences.getStartOnStartup()) { + if (Spark.isWindows()) { + addToAutostartWindows(); + } + } else { + if (Spark.isWindows()) { + removeFromAutostartWindows(); + } + } + } + + private static void addToAutostartWindows() { + try { + // Persists autostart via Windows registry, if executable exists + String PROGDIR = Spark.getBinDirectory().getParent(); + File exeFile = new File(PROGDIR + "\\" + SparkRes.getString(SparkRes.EXECUTABLE_NAME)); + if (exeFile.exists()) { + Advapi32Util.registryCreateKey(WinReg.HKEY_CURRENT_USER, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"); + Advapi32Util.registrySetStringValue( + WinReg.HKEY_CURRENT_USER, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", + SparkRes.getString(SparkRes.APP_NAME), + exeFile.getAbsolutePath()); + } + } catch (Exception e) { + Log.error("Error enabling start on reboot", e); + } + } + + private static void removeFromAutostartWindows() { + if (!Advapi32Util.registryValueExists(WinReg.HKEY_CURRENT_USER, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", + SparkRes.getString(SparkRes.APP_NAME))) { + return; + } + try { + Advapi32Util.registryDeleteValue( + WinReg.HKEY_CURRENT_USER, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", + SparkRes.getString(SparkRes.APP_NAME)); + } catch (Exception e) { + Log.error("Can not delete registry entry", e); + } + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/updater/AcceptAllCertsConnectionManager.java b/core/src/main/java/org/jivesoftware/sparkimpl/updater/AcceptAllCertsConnectionManager.java new file mode 100644 index 000000000..b7b2ffc2e --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/updater/AcceptAllCertsConnectionManager.java @@ -0,0 +1,80 @@ +/** + * Copyright (C) 2023 Ignite Realtime Foundation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.updater; + +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager; +import org.apache.hc.client5.http.socket.ConnectionSocketFactory; +import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory; +import org.apache.hc.client5.http.ssl.NoopHostnameVerifier; +import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.core5.http.config.Registry; +import org.apache.hc.core5.http.config.RegistryBuilder; +import org.apache.hc.core5.http.io.SocketConfig; +import org.apache.hc.core5.ssl.SSLContexts; +import org.apache.hc.core5.ssl.TrustStrategy; +import org.jivesoftware.smack.SmackConfiguration; + +import javax.net.ssl.SSLContext; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.util.concurrent.TimeUnit; + +/** + * A HTTP Client connection manager that knowingly by-passes all verification of TLS certificates. + * + * This SHOULD NOT be used for productive systems due to security reasons, unless it is a conscious decision and you are + * perfectly aware of security implications of accepting self-signed certificates. + * + * Usage example: + * + * AcceptAllCertsConnectionManager connectionManager = AcceptAllCertsConnectionManager.getInstance(); + * try( CloseableHttpClient httpClient = HttpClients.custom() + * .setConnectionManager(connectionManager) + * .build(); + * + * CloseableHttpResponse response = (CloseableHttpResponse) httpClient + * .execute(getMethod, new CustomHttpClientResponseHandler())) { + * + * final int statusCode = response.getCode(); + * assertThat(statusCode, equalTo(HttpStatus.SC_OK)); + * }; + * + * @author Guus der Kinderen, guus.der.kinderen@gmail.com + */ +public class AcceptAllCertsConnectionManager extends BasicHttpClientConnectionManager +{ + public static BasicHttpClientConnectionManager getInstance() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException + { + // Taken from https://www.baeldung.com/httpclient-ssl + final TrustStrategy acceptingTrustStrategy = (cert, authType) -> true; + final SSLContext sslContext = SSLContexts.custom() + .loadTrustMaterial(null, acceptingTrustStrategy) + .build(); + final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE); + final Registry socketFactoryRegistry = + RegistryBuilder. create() + .register("https", sslsf) + .register("http", new PlainConnectionSocketFactory()) + .build(); + + final BasicHttpClientConnectionManager result = new BasicHttpClientConnectionManager(socketFactoryRegistry); + result.setSocketConfig(SocketConfig.custom().setSoTimeout(SmackConfiguration.getDefaultReplyTimeout(), TimeUnit.MILLISECONDS).build()); + result.setConnectionConfig(ConnectionConfig.custom().setConnectTimeout(SmackConfiguration.getDefaultReplyTimeout(), TimeUnit.MILLISECONDS).build()); + return result; + } +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/updater/CheckUpdates.java b/core/src/main/java/org/jivesoftware/sparkimpl/updater/CheckUpdates.java new file mode 100644 index 000000000..b217c73ba --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/updater/CheckUpdates.java @@ -0,0 +1,646 @@ +/** + * Copyright (C) 2004-2011 Jive Software, 2023 Ignite Realtime Foundation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.sparkimpl.updater; + +import com.thoughtworks.xstream.XStream; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.StanzaError; +import org.jivesoftware.smack.provider.ProviderManager; +import org.jivesoftware.smackx.disco.packet.DiscoverItems; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.ConfirmDialog; +import org.jivesoftware.spark.component.ConfirmDialog.ConfirmListener; +import org.jivesoftware.spark.component.TitlePanel; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.*; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.JiveInfo; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.impl.JidCreate; + +import javax.swing.*; +import javax.swing.text.html.HTMLEditorKit; +import java.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.*; +import java.util.Calendar; +import java.util.Date; +import java.util.TimerTask; + +public class CheckUpdates { + private final String mainUpdateURL; + private JProgressBar bar; + private TitlePanel titlePanel; + private boolean downloadComplete = false; + private boolean cancel = false; + public static boolean UPDATING = false; + private final boolean sparkPluginInstalled; + private final XStream xstream = new XStream(); + private String sizeText; + + + public CheckUpdates() { + // Set the Jabber IQ Provider for Jabber:iq:spark + ProviderManager.addIQProvider("query", "jabber:iq:spark", new SparkVersion.Provider()); + + // For simplicity, use an alias for the root xml tag + xstream.allowTypes(new Class[] { + SparkVersion.class, + }); + xstream.alias("Version", SparkVersion.class); + + // Specify the main update url for JiveSoftware + this.mainUpdateURL = "http://www.igniterealtime.org/updater/updater"; + + sparkPluginInstalled = isSparkPluginInstalled(); + } + + public SparkVersion newBuildAvailable() { + if (!sparkPluginInstalled && !Spark.disableUpdatesOnCustom()) { + // Handle Jivesoftware.org update + return isNewBuildAvailableFromJivesoftware(); + } + else if (sparkPluginInstalled) { + SparkVersion serverVersion = getLatestVersion(SparkManager.getConnection()); + if (serverVersion != null && isGreater(serverVersion.getVersion(), JiveInfo.getVersion())) { + return serverVersion; + } + } + return null; + } + + + /** + * Returns true if there is a new build available for download. + */ + public SparkVersion isNewBuildAvailableFromJivesoftware() { + final String os; + if (Spark.isWindows()) { + os = "windows"; + } + else if (Spark.isMac()) { + os = "mac"; + } + else { + os = "linux"; + } + + // Properties isBetaCheckingEnabled is now used to indicate if updates are allowed + // // Check to see if the beta should be included. + // LocalPreferences pref = SettingsManager.getLocalPreferences(); + // boolean isBetaCheckingEnabled = pref.isBetaCheckingEnabled(); + // if (isBetaCheckingEnabled) { + // post.addParameter("beta", "true"); + // } + try (final CloseableHttpClient httpClient = + HttpClients.custom().useSystemProperties() + .setConnectionManager(AcceptAllCertsConnectionManager.getInstance()) + .build() + ) { + final ClassicHttpRequest request = ClassicRequestBuilder.post(mainUpdateURL) + .addParameter("os", os) + .setHeader("User-Agent", "Spark HttpFileUpload") + .build(); + + return httpClient.execute(request, httpResponse -> { + final int statusCode = httpResponse.getCode(); + if ((statusCode >= 200) && (statusCode <= 202)) { + String xml = EntityUtils.toString(httpResponse.getEntity()); + + // Server Version + SparkVersion serverVersion = (SparkVersion)xstream.fromXML(xml); + if (isGreater(serverVersion.getVersion(), JiveInfo.getVersion())) { + return serverVersion; + } + } + return null; + }); + } catch (Exception e) { + Log.error(e); + } + return null; + } + + + public void downloadUpdate(final File downloadedFile, final SparkVersion version) { + final java.util.Timer timer = new java.util.Timer(); + + final HttpGet request = new HttpGet(version.getDownloadURL()); + try (final CloseableHttpClient httpClient = + HttpClients.custom().useSystemProperties() + .setConnectionManager(AcceptAllCertsConnectionManager.getInstance()) + .build() + ) { + httpClient.execute(request, response -> { + if (response.getCode() != 200) { + return null; + } + final HttpEntity entity = response.getEntity(); + int contentLength = (int) entity.getContentLength(); + + bar = new JProgressBar(0, contentLength); + + final JFrame frame = new JFrame(Res.getString("title.downloading.im.client")); + + frame.setIconImage(SparkRes.getImageIcon(SparkRes.Icon.SMALL_MESSAGE_IMAGE).getImage()); + + titlePanel = new TitlePanel(Res.getString("title.upgrading.client"), Res.getString("message.version", version.getVersion()), SparkRes.getImageIcon(SparkRes.Icon.SEND_FILE_24x24), true); + + final Thread thread = new Thread( () -> { + try { + InputStream stream = entity.getContent(); + long size = entity.getContentLength(); + ByteFormat formater = new ByteFormat(); + sizeText = formater.format(size); + titlePanel.setDescription(Res.getString("message.version", version.getVersion()) + " \n" + Res.getString("message.file.size", sizeText)); + + + downloadedFile.getParentFile().mkdirs(); + + FileOutputStream out = new FileOutputStream(downloadedFile); + copy(stream, out); + out.close(); + + if (!cancel) { + downloadComplete = true; + promptForInstallation(downloadedFile, Res.getString("title.download.complete"), Res.getString("message.restart.spark")); + } + else { + out.close(); + downloadedFile.delete(); + } + + + UPDATING = false; + frame.dispose(); + } + catch (Exception ex) { + // Nothing to do + } + finally { + timer.cancel(); + // Release current connection to the connection pool once you are done + } + } ); + + + frame.getContentPane().setLayout(new GridBagLayout()); + frame.getContentPane().add(titlePanel, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + frame.getContentPane().add(bar, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + JEditorPane pane = new JEditorPane(); + boolean displayContentPane = version.getChangeLogURL() != null || version.getDisplayMessage() != null; + + try { + pane.setEditable(false); + if (version.getChangeLogURL() != null) { + pane.setEditorKit(new HTMLEditorKit()); + pane.setPage(version.getChangeLogURL()); + } + else if (version.getDisplayMessage() != null) { + pane.setText(version.getDisplayMessage()); + } + + if (displayContentPane) { + frame.getContentPane().add(new JScrollPane(pane), new GridBagConstraints(0, 2, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); + } + } + catch (IOException e) { + Log.error(e); + } + + frame.getContentPane().setBackground(Color.WHITE); + frame.pack(); + if (displayContentPane) { + frame.setSize(600, 400); + } + else { + frame.setSize(400, 100); + } + frame.setLocationRelativeTo(SparkManager.getMainWindow()); + GraphicUtils.centerWindowOnScreen(frame); + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent windowEvent) { + thread.interrupt(); + cancel = true; + + UPDATING = false; + + if (!downloadComplete) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(SparkManager.getMainWindow(), Res.getString("message.updating.cancelled"), Res.getString("title.cancelled"), JOptionPane.ERROR_MESSAGE); + } + + } + }); + frame.setVisible(true); + thread.start(); + + + timer.scheduleAtFixedRate(new TimerTask() { + int seconds = 1; + + @Override + public void run() { + ByteFormat formatter = new ByteFormat(); + long value = bar.getValue(); + long average = value / seconds; + String text = formatter.format(average) + "/Sec"; + + String total = formatter.format(value); + titlePanel.setDescription(Res.getString("message.version", version.getVersion()) + " \n" + Res.getString("message.file.size", sizeText) + "\n" + Res.getString("message.transfer.rate") + ": " + text + "\n" + Res.getString("message.total.downloaded") + ": " + total); + seconds++; + } + }, 1000, 1000); + return null; + }); + } catch (Exception e) { + Log.error(e); + } + } + + /** + * Common code for copy routines. By convention, the streams are + * closed in the same method in which they were opened. Thus, + * this method does not close the streams when the copying is done. + * + * @param in Source stream + * @param out Destination stream + */ + private void copy(final InputStream in, final OutputStream out) { + int read = 0; + + try { + final byte[] buffer = new byte[4096]; + while (!cancel) { + int bytesRead = in.read(buffer); + if (bytesRead < 0) { + break; + } + out.write(buffer, 0, bytesRead); + read += bytesRead; + bar.setValue(read); + } + } + catch (IOException e) { + Log.error(e); + } + } + + /** + * Checks Spark Manager and/or Jive Software for the latest version of Spark. + * + * @param explicit true if the user explicitly asks for the latest version. + */ + public void checkForUpdate(boolean explicit) { + if (UPDATING) { + return; + } + + UPDATING = true; + + if (isLocalBuildAvailable()) { + return; + } + + LocalPreferences localPreferences = SettingsManager.getLocalPreferences(); + + //defaults to 7, 0=disabled + int CheckForUpdates = localPreferences.getCheckForUpdates(); + if (CheckForUpdates == 0) { + return; + } + + Date lastChecked = localPreferences.getLastCheckForUpdates(); + if (lastChecked == null) { + lastChecked = new Date(); + // This is the first invocation of Communicator + localPreferences.setLastCheckForUpdates(lastChecked); + } + + // Check to see if it has been a CheckForUpdates (default 7) days + Calendar calendar = Calendar.getInstance(); + calendar.setTime(lastChecked); + calendar.add(Calendar.DATE, CheckForUpdates); + + final Date lastCheckedPlusAPeriod = calendar.getTime(); + + boolean periodOrLonger = new Date().getTime() >= lastCheckedPlusAPeriod.getTime(); + + + if (periodOrLonger || explicit || sparkPluginInstalled) { + + if (!explicit && !localPreferences.isBetaCheckingEnabled()) + { + return; + } + // Check version on server. + lastChecked = new Date(); + localPreferences.setLastCheckForUpdates(lastChecked); + final SparkVersion serverVersion = newBuildAvailable(); + if (serverVersion == null) { + UPDATING = false; + + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + + if (explicit) { + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(SparkManager.getMainWindow(), Res.getString("message.no.updates"), Res.getString("title.no.updates"), JOptionPane.INFORMATION_MESSAGE); + } + return; + } + + // Otherwise updates are available + String downloadURL = serverVersion.getDownloadURL(); + String filename = downloadURL.substring(downloadURL.lastIndexOf("/") + 1); + + if (filename.indexOf('=') != -1) { + filename = filename.substring(filename.indexOf('=') + 1); + } + + // Set Download Directory + final File downloadDir = new File(Spark.getSparkUserHome(), "updates"); + downloadDir.mkdirs(); + + // Set file to download. + final File fileToDownload = new File(downloadDir, filename); + if (fileToDownload.exists()) { + fileToDownload.delete(); + } + + ConfirmDialog confirm = new ConfirmDialog(); + confirm.showConfirmDialog(SparkManager.getMainWindow(), Res.getString("title.new.version.available"), + Res.getString("message.new.spark.available", filename), Res.getString("yes"), Res.getString("no"), + null); + confirm.setDialogSize(400, 300); + confirm.setConfirmListener(new ConfirmListener() { + @Override + public void yesOption() { + SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + try { + Thread.sleep(50); + } + catch (InterruptedException e) { + Log.error(e); + } + return "ok"; + } + + @Override + public void finished() { + if (Spark.isWindows()) { + downloadUpdate(fileToDownload, serverVersion); + } + else { + // Launch browser to download page. + try { + if (sparkPluginInstalled) { + BrowserLauncher.openURL(serverVersion.getDownloadURL()); + } + else { + BrowserLauncher.openURL("http://www.igniterealtime.org/downloads/index.jsp#spark"); + } + } + + catch (Exception e) { + Log.error(e); + } + UPDATING = false; + } + } + + }; + worker.start(); + } + + @Override + public void noOption() { + UPDATING = false; + } + }); + } + else { + UPDATING = false; + } + + } + + + /** + * Returns true if the first version number is greater than the second. + * + * @param firstVersion the first version number. + * @param secondVersion the second version number. + * @return returns true if the first version is greater than the second. + */ + public static boolean isGreater(String firstVersion, String secondVersion) { + int indexOne = firstVersion.indexOf("_"); + if (indexOne != -1) { + firstVersion = firstVersion.substring(indexOne + 1); + } + + int indexTwo = secondVersion.indexOf("_"); + if (indexTwo != -1) { + secondVersion = secondVersion.substring(indexTwo + 1); + } + + firstVersion = firstVersion.replaceAll(".online", ""); + secondVersion = secondVersion.replace(".online", ""); + + boolean versionOneBetaOrAlpha = firstVersion.toLowerCase().contains("beta") || firstVersion.toLowerCase().contains("alpha"); + boolean versionTwoBetaOrAlpha = secondVersion.toLowerCase().contains("beta") || secondVersion.toLowerCase().contains("alpha"); + + // Handle case where they are both betas / alphas + if ((versionOneBetaOrAlpha && versionTwoBetaOrAlpha) || (!versionOneBetaOrAlpha && !versionTwoBetaOrAlpha)) { + return firstVersion.compareTo(secondVersion) >= 1; + } + + // Handle the case where version 1 is a beta or alpha + if (versionOneBetaOrAlpha) { + String versionOne = getVersion(firstVersion); + return versionOne.compareTo(secondVersion) >= 1; + } + else if (versionTwoBetaOrAlpha) { + String versionTwo = getVersion(secondVersion); + int result = firstVersion.compareTo(versionTwo); + return result >= 0; + } + + + return firstVersion.compareTo(secondVersion) >= 1; + } + + public static String getVersion(String version) { + int lastIndexOf = version.lastIndexOf("."); + if (lastIndexOf != -1) { + return version.substring(0, lastIndexOf); + } + return version; + } + + /** + * Returns the latest version of Spark available via Spark Manager or Jive Software. + * + * @param connection the XMPPConnection to use. + * @return the information for about the latest Spark Client. + * @throws InterruptedException + * @throws XMPPException If unable to retrieve latest version. + */ + public static SparkVersion getLatestVersion(XMPPConnection connection) + { + SparkVersion request = new SparkVersion(); + request.setType(IQ.Type.get); + request.setTo(JidCreate.fromOrThrowUnchecked("updater." + connection.getXMPPServiceDomain())); + try { + IQ result = connection.sendIqRequestAndWaitForResponse(request); + SparkVersion response = (SparkVersion) result; + return response; + } catch (XMPPException.XMPPErrorException e) { + if (e.getStanzaError().getCondition() == StanzaError.Condition.service_unavailable) { + // no new version available + return null; + } + Log.warning("Unable the check fo new build.", e); + return null; + } catch (Exception e) { + Log.error("Unable the check fo new build.", e); + return null; + } + } + + /** + * Does a service discovery on the server to see if a Client Control plugin is enabled. + * + * @return true if Spark Manager is available. + */ + public static boolean isSparkPluginInstalled() { + XMPPConnection con = SparkManager.getConnection(); + if (!con.isConnected()) { + return false; + } + + try { + DiscoverItems items = SparkManager.getSessionManager().getDiscoveredItems(); + for (DiscoverItems.Item item : items.getItems() ) { + if ("Spark Updater".equals(item.getName())) { + return true; + } + } + } + catch (Exception e) { + Log.error(e); + } + return false; + } + + /** + * Prompts the user to install the latest Spark. + * + * @param downloadedFile the location of the latest downloaded client. + * @param title the title + * @param message the message + */ + private void promptForInstallation(final File downloadedFile, String title, String message) { + ConfirmDialog confirm = new ConfirmDialog(); + confirm.showConfirmDialog(SparkManager.getMainWindow(), title, + message, Res.getString("yes"), Res.getString("no"), + null); + confirm.setConfirmListener(new ConfirmListener() { + @Override + public void yesOption() { + try { + if (Spark.isWindows()) { + Runtime.getRuntime().exec(downloadedFile.getAbsolutePath()); + } + else if (Spark.isMac()) { + Runtime.getRuntime().exec("open " + downloadedFile.getCanonicalPath()); + } + } + catch (IOException e) { + Log.error(e); + } + SparkManager.getMainWindow().shutdown(); + } + + @Override + public void noOption() { + + } + }); + } + + /** + * Checks to see if a new version of Spark has already been downloaded by not installed. + * + * @return true if a newer version exists. + */ + private boolean isLocalBuildAvailable() { + // Check the bin directory for previous downloads. If there is a + // newer version of Spark, ask if they wish to install. + if (Spark.isWindows()) { + File binDirectory = Spark.getBinDirectory(); + File[] files = binDirectory.listFiles(); + if (files != null) { + for (File file : files) { + String fileName = file.getName(); + if (fileName.endsWith(".exe")) { + int index = fileName.indexOf("_"); + + // Add version number + String versionNumber = fileName.substring(index + 1); + int indexOfPeriod = versionNumber.indexOf("."); + + versionNumber = versionNumber.substring(0, indexOfPeriod); + versionNumber = versionNumber.replaceAll("_online", ""); + versionNumber = versionNumber.replaceAll("_", "."); + + boolean isGreater = versionNumber.compareTo(JiveInfo.getVersion()) >= 1; + if (isGreater) { + // Prompt + promptForInstallation(file, Res.getString("title.new.client.available"), Res.getString("message.restart.spark.to.install")); + return true; + } else { + file.delete(); + } + + } + } + } + } + + return false; + } + + +} diff --git a/core/src/main/java/org/jivesoftware/sparkimpl/updater/SparkVersion.java b/core/src/main/java/org/jivesoftware/sparkimpl/updater/SparkVersion.java new file mode 100644 index 000000000..c23e99b6c --- /dev/null +++ b/core/src/main/java/org/jivesoftware/sparkimpl/updater/SparkVersion.java @@ -0,0 +1,156 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.sparkimpl.updater; + +import org.jivesoftware.Spark; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IqData; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.provider.IqProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.JxmppContext; + +import java.io.IOException; +import java.time.Instant; + +public class SparkVersion extends IQ { + + private String version; + private Instant updateTime; + private String downloadURL; + private String displayMessage; + private String changeLogURL; + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public Instant getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Instant updateTime) { + this.updateTime = updateTime; + } + + public String getDownloadURL() { + return downloadURL; + } + + public void setDownloadURL(String downloadURL) { + this.downloadURL = downloadURL; + } + + public String getDisplayMessage() { + return displayMessage; + } + + public void setDisplayMessage(String displayMessage) { + this.displayMessage = displayMessage; + } + + public String getChangeLogURL() { + return changeLogURL; + } + + public void setChangeLogURL(String changeLogURL) { + this.changeLogURL = changeLogURL; + } + + + /** + * Element name of the packet extension. + */ + public static final String ELEMENT_NAME = "query"; + + /** + * Namespace of the packet extension. + */ + public static final String NAMESPACE = "jabber:iq:spark"; + + public SparkVersion() { + super( ELEMENT_NAME, NAMESPACE); + } + + @Override + protected IQChildElementXmlStringBuilder getIQChildElementBuilder( IQChildElementXmlStringBuilder buf) + { + buf.rightAngleBracket(); + // Add os specific information + if (Spark.isWindows()) { + buf.append("windows"); + } + else if (Spark.isMac()) { + buf.append("mac"); + } + else { + buf.append("linux"); + } + return buf; + } + + /** + * An IQProvider for SparkVersion packets. + * + * @author Derek DeMoro + */ + public static class Provider extends IqProvider { + + public Provider() { + super(); + } + + @Override + public SparkVersion parse(XmlPullParser parser, int i, IqData iqData, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException{ + SparkVersion version = new SparkVersion(); + + boolean done = false; + while (!done) { + XmlPullParser.Event eventType = parser.next(); + if (eventType == XmlPullParser.Event.START_ELEMENT) { + switch (parser.getName()) { + case "version": + version.setVersion(parser.nextText()); + break; + case "updatedTime": + long time = Long.parseLong(parser.nextText()); + version.setUpdateTime(Instant.ofEpochMilli(time)); + break; + case "downloadURL": + version.setDownloadURL(parser.nextText()); + break; + case "displayMessage": + version.setDisplayMessage(parser.nextText()); + break; + } + } + else if (eventType == XmlPullParser.Event.END_ELEMENT) { + if (parser.getName().equals(ELEMENT_NAME)) { + done = true; + } + } + } + + return version; + } + } +} diff --git a/src/resources/META-INF/mime.types b/core/src/main/resources/META-INF/mime.types similarity index 100% rename from src/resources/META-INF/mime.types rename to core/src/main/resources/META-INF/mime.types diff --git a/core/src/main/resources/default.properties b/core/src/main/resources/default.properties new file mode 100644 index 000000000..c34ccf321 --- /dev/null +++ b/core/src/main/resources/default.properties @@ -0,0 +1,346 @@ +#See https://download.igniterealtime.org/spark/docs/latest/documentation/spark%20guide/Spark.default.properties.guide.html +################# Login Window ################# +# The Login image. Suggested image dimensions 244 x 188 px +MAIN_IMAGE = images/spark.gif +SHORT_NAME = Spark + +USER_DIRECTORY_WINDOWS = Spark +USER_DIRECTORY_LINUX = .Spark +USER_DIRECTORY_MAC = Library/Application Support/Spark + +LOGIN_DIALOG_BACKGROUND_IMAGE = images/login_dialog_background.png +TOP_BOTTOM_BACKGROUND_IMAGE = images/top_bottom_background_image.png + +# Specify a fixed Hostname +# Changing the Hostname will also be prohibited if set +HOST_NAME = +# Set true if you don't want the user to change the server +HOST_NAME_CHANGE_DISABLED = false +# Proxy Settings +# Protocols are HTTP or SOCKS, case-sensitive +PROXY_PROTOCOL = +PROXY_HOST = +PROXY_PORT = + +# Remove account creation Button from the Login window +# Users won't be able to register new Accounts from within Spark +ACCOUNT_DISABLED = +# Remove the Advanced Configuration Button from the login window +# Users won't be able to access the advanced configuration +ADVANCED_DISABLED = + +# Force using hostname or version as a resource (both are "false" by default; only one can be +# "true" at a time; if both are "true", then hostname will be used as a resource) +USE_HOSTNAME_AS_RESOURCE = false +USE_VERSION_AS_RESOURCE = false + +# When enabled, it removes history from the chat window and doesn't save history into transcript files. Also removes history +# settings from the preferences, removes the history button from the chat window and contact's history context menu. +HISTORY_DISABLED = false +# When enabled, it hides history settings from the preferences and removes the Clear button from the context menu in the Chat window +HIDE_HISTORY_SETTINGS = false + +# If Advanced preferences are enabled, you are able to remove tabs, except the "General" tab +#Removes SSO Tab +SSO_DISABLED = false +#Removes PKI Tab +PKI_DISABLED = false +#Removes Proxy Tab +PROXY_DISABLED = false +#Removes Certificates Tab +CERTIFICATES_MANAGER_DISABLED = false +#Removes Mutual Authentication Tab +MUTUAL_AUTH_DISABLED = false + +# These are default settings in LoginSettingsDialog tabs +# General +HOST_AND_PORT_CONFIGURED = false +XMPP_PORT = 5222 +TIME_OUT = 10 +COMPRESSION_ENABLED = false +DEBUGGER_ENABLED = false +#Security tab +DISABLE_HOSTNAME_VERIFICATION = false +ALLOW_CLIENT_SIDE_AUTH = false +SECURITY_MODE = ifpossible +# Direct TLS +OLD_SSL_ENABLED = false +#PROXY +PROXY_ENABLED = false +#SSO +USE_SSO = false +USE_SASL_GSS_API_SMACK_3_COMPATIBLE = false +SSO_METHOD = file +# Certificate ManagerSettingsPanel +ACCEPT_EXPIRED = false +ACCEPT_NOT_VALID_YET = false +ACCEPT_SELF_SIGNED = false +ACCEPT_REVOKED = false +CHECK_CRL = true +CHECK_OCSP = false +ALLOW_SOFT_FAIL = true + + +# Show the Password Reset Button on LoginDialog. +# !!!! This will replace the "register new user" button, please set ACCOUNT_DISABLED = true !!!! +PASSWORD_RESET_ENABLED = false +# URL to your password reset HTML +PASSWORD_RESET_URL = +# Hides Save Password and Auto Login checkboxes on the Login screen and in the Preferences +HIDE_SAVE_PASSWORD_AND_AUTO_LOGIN = false + +# Branding only +# Branded images appear in the Top-Right corner, and must be included in the classpath +# place them in "src/resource/images" and the path will be "images/file.jpg" +# BRANDED_IMAGE = images/my-corporation-logo.png +BRANDED_IMAGE = + +# Shows a powered by logo below the Main Image of Spark +SHOW_POWERED_BY = +# Disables updatability, you should set this, if you have a custom Spark-build +# or are in an environment where install files are distributed via network +DISABLE_UPDATES = + +# If true, Spark cannot shut down +# users won't be able to shut down Spark +DISABLE_EXIT = + +# If true, hides "Login as invisible" checkbox on the login screen +HIDE_LOGIN_AS_INVISIBLE = false + +HIDE_LOGIN_ANONYMOUSLY = false + +# If true, the "Preferences" menu item will be disabled +DISABLE_PREFERENCES_MENU_ITEM = false + +# This allows an administrator to override the DISABLE_PREFERENCES_MENU_ITEM setting +# The "Preferences" menu item will become enabled when the specified file exists +# Specify the maintenance path/file here (i.e. \\\\server\\share\\filename.ext) +# It is best to place this file on a read-only network share +MAINTENANCE_FILE_PATH = + +# If true, don't allow a user to manually change presence status +DISABLE_PRESENCE_STATUS_CHANGE = false + +# If true, disable all "Broadcast" menu items +DISABLE_BROADCAST_MENU_ITEM = false + +#if true, hide Start a chat option in the Actions menu +HIDE_START_A_CHAT = false + +# If true, remove the "Avatar" tab in the Profile dialog +DISABLE_AVATAR_TAB = false + +# If true, disable the "Plugins" menu item +DISABLE_PLUGINS_MENU_ITEM = false + +# If true, disable the option to transfer files and images +DISABLE_FILE_TRANSFER = false + +# If true, disable the option to remove contacts and groups in the contact list +DISABLE_REMOVALS = false + +# If true, disable the option to rename contacts and groups in the contact list +DISABLE_RENAMES = false + +# If true, disable the options to move and copy contacts +DISABLE_MOVE_AND_COPY = false + +# If true, disable the option to edit the profile +DISABLE_EDIT_PROFILE = false + +# If true, disable the "View scratchpad" option under "Actions" +DISABLE_VIEW_NOTES = false + +# If true, disable the "View task list" option under "Actions" +DISABLE_VIEW_TASK_LIST = false + +# If true, do not allow modifying the Idle Settings and set client values for Idle Settings. +IDLE_LOCK = false + +# Idle time, default value = 5min +IDLE_TIME = 5 + +################## File Transfer ################ + +# Specify a size on which Users will get a +# warning of a possibly too big file +# 10 MB = 10485760 +# 1 GB = 1073741824 +# default = -1 (infinity) +# maximum is 9223372036854775806 byte = 8_388_608 TB +FILE_TRANSFER_WARNING_SIZE = -1 + +# Specify the Maximum file size to be permitted to send +# 10 MB = 10485760 +# 1 GB = 1073741824 +# default = -1 (infinity) +# maximum is 9223372036854775806 byte = 8_388_608 TB +FILE_TRANSFER_MAXIMUM_SIZE = -1 + +# Force in-band bytestream only. +FILE_TRANSFER_IBB_ONLY = true + +# Automatically accept file transfer offers from people that have presence subscription +FILE_TRANSFER_AUTO_ACCEPT_PRESENCE = false + +################## Main Window ################## +# [Not yet implemented:] +# Changing this won't have any effect +# Contact List Management +#HOVER_TEXT_COLOR = +#TEXT_COLOR = +#CONTACT_GROUP_START_COLOR = +#CONTACT_GROUP_END_COLOR = +#TAB_START_COLOR = +#TAB_END_COLOR = +# [/NYI] +################ Settings Window ################ + +# Disables adding of contacts +# The User won't be able to add contacts, +# Useful for shared contact list management +ADD_CONTACT_DISABLED = +# Disables adding contact groups +# The User won't be able to add contact groups, +# Useful for shared contact list management +ADD_CONTACT_GROUP_DISABLED = + +# Change Password Disabled +# Users won't be able to change their password +CHANGE_PASSWORD_DISABLED = + +# Sets the Location of the User's guide +#Default is https://download.igniterealtime.org/spark/docs/spark_user_guide.pdf +HELP_USER_GUIDE = https://discourse.igniterealtime.org/t/spark-user-guide-revised/41731 +# Set to true, if you don't want this displayed +HELP_USER_GUIDE_DISABLED = +# Sets the Location of the Help-Forum +HELP_FORUM = https://discourse.igniterealtime.org/c/spark/spark-support +# Set to true, if you don't want this displayed +HELP_FORUM_DISABLED = +# The following Text will be displayed instead of "Spark forum" +# leave blank for default +HELP_FORUM_TEXT = + +############### About Box Window ################ + +# Version and Developer Info +# Note: Application name and Version are always displayed + +# Display Version and Developer Info +# 'true' or 'false' +DISPLAY_DEV_INFO = true +# Leave blank for auto-detect +JAVA_VERSION = + +# Set additional About Box information +APPLICATION_INFO1 = Ignite Realtime +APPLICATION_INFO2 = +APPLICATION_INFO3 = +# Clickable Link - must be a valid and complete URL +APPLICATION_LICENSE_LINK = https://igniterealtime.org/builds/spark/docs/latest/LICENSE.html +APPLICATION_LICENSE_LINK_TXT = Apache License, Version 2.0 +APPLICATION_INFO4 = +# Clickable Link - must be a valid and complete URL +APPLICATION_LINK = https://igniterealtime.org/ +APPLICATION_LINK_TXT = IgniteRealtime.org + +################################################# +################ Plugins ################ +################################################# + +# This is the default location where Plugins can be downloaded from +# for a sample structure see src/documentation/sample_plugin_repository.xml +PLUGIN_REPOSITORY = https://igniterealtime.org/updater/plugins.jsp +# Disable Installing of Plugins +# set true if you want to disable installing of Plugins +INSTALL_PLUGINS_DISABLED = +# Disable deleting of Plugins +# set true if you want to disable uninstalling of Plugins +UNINSTALL_PLUGINS_DISABLED = +# Put plugins here that you don't want enabled +# comma separated, case insensitive +# names of plugins can be found in the plugin.xml +# example: Fastpath,Jingle Client,Phone Client,Window Flashing Plugin +# default is empty +PLUGIN_BLACKLIST = +# Disable Plugins by entry point Class +# Comma separated, case sensitive +# example org.jivesoftware.fastpath.FastpathPlugin +# default is empty +PLUGIN_BLACKLIST_CLASS = + + +######### Color + LookAndFeel ########### + +# by Default Server-Broadcast get their own JFrame containing the Message +# also HTML tags like can be used +# if you want server broadcasts handled like every other message including transcripts +# set this to true +BROADCAST_IN_CHAT_WINDOW = false +# Disable Look&Feel change || "true" = disabled , anything else = enabled +# By Default the user can Change his Look&Feel in the Preferences Menu, +# if you don't want this then set it to true +# Preferences -> Appearance -> Customization Tab +LOOK_AND_FEEL_DISABLED = +# Disable if you don't want Users to be able to Change the text colors in the Preference Menu +# the colors will be loaded from below +# Preferences -> Appearance -> ColorTab +CHANGE_COLORS_DISABLED = +# Changes the Default Look&Feel +DEFAULT_LOOK_AND_FEEL = org.jivesoftware.spark.ui.themes.lafs.SparkLightLaf +DEFAULT_LOOK_AND_FEEL_MAC = org.jivesoftware.spark.ui.themes.lafs.SparkMacLightLaf + +# tabs are placed on bottom by default. if set to true will be placed on top +TABS_PLACEMENT_TOP = + +# the person search field is displayed by default. if set to true the search field will +# not be displayed +HIDE_PERSON_SEARCH_FIELD = + +# Below are Single Color Elements +# They are Stored as RedValue,GreenValue,BlueValue,AlphaValue. +# Ranging in 0-255. +# An Alpha value of 255 means it is completely opaque. +# An Alpha value of 0 means it is transparent. +# All values must be set or it will produce errors. +# They are preconfigured to look nice with the Windows theme or the SubstanceBusinessBlueSteel Look. +ChatInput.SelectedTextColor = 255,255,255,255 +ChatInput.SelectionColor = 10,36,106,255 +ContactItemNickname.foreground = 0,0,0,255 +ContactItemDescription.foreground = 128,128,128,255 +ContactItem.background = 255, 255, 255,255 +ContactItemOffline.color = 128,128,128,255 +Link.foreground = 0,0,255,255 +List.selectionBackground = 217,232,250,255 +List.selectionForeground = 0,0,0,255 +List.selectionBorder = 187,195,215,255 +List.foreground = 0,0,0,255 +List.background = 255,255,255,255 +TextField.lightforeground = 128,128,128,255 +TextField.foreground = 0,0,0,255 +TextField.caretForeground = 0,0,0,255 +TextPane.foreground = 0,0,0,255 +TextPane.background = 255,255,255,255 +TextPane.inactiveForeground = 255,255,255,255 +TextPane.caretForeground = 0,0,0,255 +MenuItem.selectionBackground = 217,232,250,255 +MenuItem.selectionForeground = 0,0,0,255 +Table.foreground = 0,0,0,255 +Table.background = 255,255,255,255 +## ChatWindow Colors: ## +Message.foreground = 0,0,0,255 +Address.foreground = 212,160,0,255 +User.foreground = 0,0,255,255 +OtherUser.foreground = 255,0,0,255 +Notification.foreground = 0,128,0,255 +Error.foreground = 255,0,0,255 +Question.foreground = 255,0,0,255 +History.foreground = 64,64,64,255 +SparkTabbedPane.startColor = 236,236,236,255 +SparkTabbedPane.endColor = 236,236,236,255 +SparkTabbedPane.borderColor = 192,192,192,255 +Chat.activeTabColor = 0,0,0,255 +Chat.inactiveTabColor = 80,80,80,255 +Chat.unreadMessageColor = 255,0,0,255 diff --git a/core/src/main/resources/i18n/spark_i18n.properties b/core/src/main/resources/i18n/spark_i18n.properties new file mode 100644 index 000000000..18360d000 --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n.properties @@ -0,0 +1,1138 @@ +## For translation use https://explore.transifex.com/igniterealtime/spark/ +## In property strings that are parameterized, single quotes can be used to +## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. +accept = Accept +is.active = Active +add = Add +administrator = Administrator +apply = Apply +available = Available +broadcast = Broadcast +cancel = Cancel +delete = Delete +details = Details +close = Close +create = Create +date = Date +description = Description +from = From +invite = Invite +join = Join +no = No +not.registered = Not registered +occupants = Occupants +offline = Offline +online = Online +ok = Ok +open = Open +open.folder = Open folder +participants = Participants +refresh = Refresh +reject = Reject +retry = Retry +room.name = Room Name +save = Save +subject = Subject +unfiled = Not in any group +use.default = Use Default +user.has.signed.in = has signed in. +user.has.signed.off = has signed off. +while.offline = While offline +yes = Yes + +action.clear = Clear +action.copy = Copy +action.cut = Cut +action.paste = Paste +action.print = Print +action.save = Save +action.select.all = Select all + +button.accept = Accept +button.add = A&dd +button.add.a.contact = Add a contact +button.add.bookmark = Add bookmark +button.add.service = Add service +button.add.user = Add user +button.add2 = Add +button.advanced = A&dvanced +button.approve = Approve +button.bookmark.room = Bookmark room +button.browse = &Browse... +button.browse2 = Browse... +button.browse3 = Browse... +button.cancel = Cancel +button.cert.info = Details +button.clear = Clear +button.close = Close +button.copy.to.clipboard = Copy to clipboard +button.start.registration = Start registration +button.create.account = Create account +button.create.room = Create room +button.decline = Decline +button.deny = Deny +button.dial.number = Dial number +button.find = Find +button.join = Join +button.join.room = Join selected room +button.login = &Login +button.new = New +button.profile = Profile +button.quit = Quit +button.re.detect = &Re-detect +button.reconnect = Reconnect +button.reconnect2 = Reconnect +button.refresh = Refresh +button.register = Register +button.reject = Reject +button.remove.bookmark = Remove bookmark +button.roster = Roster +button.save = Save +button.save.for.future.use = Save for future use +button.search = Search +button.send = Send +button.send.email = Email +button.start.chat = Chat +button.tasks.active = Active +button.tasks.all = All +button.unset.file.explorer = Unset File Browser +button.update = Update +button.view.notes = Scratchpad +button.view.profile = View full profile +button.view.tasklist = View task list +button.check.validity = Check validity +button.show.certificate = Show certificate +button.delete.saved.passwords = Forget All Login Passwords +button.crop=Crop + +table.column.certificate.subject = Subject +table.column.certificate.validity = Validity +table.column.certificate.exempted = Exempted + +checkbox.allow.buzz = Allow users to &buzz you +checkbox.auto.discover.port = Automatically discover host and port +checkbox.auto.login = &Auto login +checkbox.login.as.invisible = L&ogin as invisible +checkbox.login.anonymously = Login anony&mously +checkbox.disable.chat.history = &Disable chat history +checkbox.sort.asc.history = Sort messages in contact history by date ascending +checkbox.disable.prev.chat.history = Disable &showing previous conversation in chat +checkbox.enable.emoticons = E&nable emoticons +checkbox.graying.out = Dim idle contacts (requires restart) +checkbox.idle.enabled = &Idle enabled +checkbox.launch.on.startup = &Launch on startup +checkbox.reconnect.info = Specify reconnection display: +checkbox.reconnect.panel.big = Display as Panel +checkbox.reconnect.panel.small = Display in contact group +checkbox.reconnect.panel.icon = Display as icon +checkbox.notify.user.comes.online = Notify when a user &comes online +checkbox.notify.user.goes.offline = &Notify when a user goes offline +checkbox.notify.typing.systemtray = &Show typing notification in the system tray +checkbox.notify.systemtray = Show new &messages in the system tray +checkbox.permanent = Room is permanent +room.config.public=Room is public +room.config.public.hint=Room is public, so people can find it in the list of rooms +checkbox.play.sound.on.invitation = Play sound when &invitation is received +checkbox.play.sound.on.new.message = &Play sound when new message arrives +checkbox.play.sound.on.outgoing.message = Play sound when message is &sent +checkbox.play.sound.when.offline = Play sound when user goes &offline +checkbox.play.sound.chat_request=Play sound when chat request received +checkbox.private.room = Room has a password +checkbox.save.password = Sa&ve password +checkbox.show.avatars.in.contactlist = Show &avatars in contact list +checkbox.show.notifications.in.conference = Show ¬ifications in conference rooms +checkbox.show.time.in.chat.window = Show &time in chat window +checkbox.show.toaster = Show a &toast popup +checkbox.disable.asterisk.toaster = Disable phone toast popup +checkbox.split.chat.window = Dock windows (requires restart) +checkbox.start.in.tray = &Start in system tray +checkbox.click.single.tray = S&ingle click in system tray brings Spark to front (requires restart) +checkbox.tabs.on.top = Chat tabs &appear on top (requires restart) +checkbox.tabs.scroll = Use scroll for chat tabs (requires restart) +checkbox.use.compression = Use compression +checkbox.use.debugger.on.startup = Start debugger on startup +checkbox.use.proxy.server = Use proxy server +checkbox.use.system.look.and.feel = Use system &look And feel (requires restart) +checkbox.window.to.front = Bring &window to front +checkbox.broadcast.hide.offline.user = Hide offline user +checkbox.use.krbconf = Use krb5.conf or krb5.ini +checkbox.use.krb.dns = Use DNS +checkbox.use.specify.below = Specify below +checkbox.use.pki.authentication = Use PKI authentication +checkbox.transport.tab.setting = Show available transports in tab (requires restart) +checkbox.conference.tab.setting = Show conference service in tab (requires restart) +checkbox.use.hostname.as.resource = Use hostname as resource +checkbox.use.version.as.resource = Use Spark version as resource +checkbox.accept.all.certificates = Accept all certificates (self-signed/expired/not trusted) +checkbox.disable.hostname.verification = Disable certificate hostname verification (not recommended) +checkbox.allow.client.side.authentication = Allow for client side authentication +checkbox.accept.all = Accept all +checkbox.accept.expired = Accept expired +checkbox.accept.not.valid.yet = Accept not valid yet +checkbox.accept.self.signed = Accept self-signed +checkbox.accept.revoked = Accept revoked +checkbox.check.crl = Check CRL +checkbox.check.ocsp = Check OCSP +checkbox.allow.soft.fail = Allow soft fail policy +checkbox.on.exception.list = On the exception list +checkbox.filetransfer.ibb.only = In-Band Bytestreams Only +checkbox.filetransfer.autoaccept.presence = Automatically accept file transfers from known contacts +checkbox.close.unread.message = Ask when closing the window if there are unread messages +radio.encryptionmode.required = Required +radio.encryptionmode.ifpossible = If possible +radio.encryptionmode.disabled = Disabled + +delete.log.permanently = Permanently delete log +delete.permanently = Permanently delete? + +gateway.username.password.error = Username and/or password need to be supplied + +group.chat.window.information = Chat window information +group.comma.delimited = Comma delimited +group.conferences.found = Conference services Found +group.connection = Connection +group.empty = There are no online contacts in this group +group.general.information = General information +group.login.information = Login information +group.notification.options = Notification options +group.offline = Offline group +group.search.form = Search form +group.search.results = Search results +group.chat.name.notification = Seen your name... +group.chat.name.match = Your name has been said in group chat: +group.send_config.error = An exception occurred while trying to save the updated form! +group.encryption_mode = Encryption mode + +label.na = n/a +label.home = Home +label.accounts = Sign Up +label.add.conference.service = Add conference service +label.add.jid = Add JID +label.add.task = Add task +label.auto.login = Auto login +label.available.users.in.roster = Available users in roster +label.avatar = Avatar: +label.broadcast.history.search.date = Search date (year-month): +label.cancel = Cancel +label.cell = Cell +label.change.password.to = Change &password to +label.chatroom.fontsize = Chat room &font size: +label.chatroom.maxcurrenthistorysize = Max current history size: +label.city = City +label.close = Close +label.company = Company +label.confirm.password = &Confirm password +label.conflict.error = Unable to login due to account already signed in +label.contact.to.find = Find contact +label.recent.conversation = Recent Conversations +label.frequent.contacts = Frequent Contacts +label.contactlist.avatarsize = Contact list avatar &size: +label.contactlist.fontsize = &Contact List font size: +label.country = Country +label.create.account = Create account +label.department = Department +label.dial = Dial +label.display.time = Display Time: +label.downloads = Downloads +label.due = Due +label.email.address = Email address +label.emoticons = &Emoticons +label.enter.address = Enter address +label.enter.group.name = Enter new group name +label.fax = Fax +label.find = Find +label.first.name = First name +label.group = Group +label.host = Host +label.invited.users = Invited users +label.jabber.address = Jabber address +label.jabber.id = Jabber ID +label.jid = JID +label.job.title = Job title +label.last.name = Last name +label.local.time = Local time +label.message = Message +label.message.style = Message style +label.middle.name = Middle name +label.minutes.before.stale.chat = &Minutes before an inactive room becomes stale +label.mobile = Mobile +label.name = Name +label.network = Network +label.new.nickname = New nickname +label.nickname = Nickname +label.number = Number +label.ok = OK +label.old.ssl = Use Direct TLS method +label.os = Operating system +label.pager = Pager +label.password = &Password +label.passwordreset = Password reset +label.phone = Phone +label.port = Port +label.postal.code = Postal code +label.presence = Presence +label.priority = Priority +label.protocol = Protocol +label.received = Received +label.rename.to = Rename to +label.resource = Resource +label.response.timeout = &Response timeout (sec) +label.reconnect.delay = Reconnection Delay (sec) (restart required) +label.room = Room +label.room.name = Room name +label.room.topic = Room topic +label.search = Search +label.search.service = Search service +label.seconds = Seconds +label.server = Do&main +label.server.address = Server address +label.show = Show: +label.software = Software +label.state.and.province = State/province +label.street.address = Street address +label.time = Time: {0} +label.time.till.idle = &Time till idle (min) +label.time.till.idlemessage = Automatic idl&e message +label.timeformat = Use {0} +label.transfer.download.directory = &Download directory: +label.transfer.timeout = &Transfer timeout (min): +label.unable.to.add.contact = Unable to add contact +label.use.default = Use default +label.user.on.public.network = User is on a public network +label.username = &Username +label.version = Version +label.web.page = Web page +label.work = Work +label.xmpp.port = &XMPP port +label.krb.realm = Realm +label.krb.kdc = KDC +label.which.pki.method = Which PKI method? +label.choose.file = Choose file +label.trust.store.password = Trust store password +label.enter.password = Enter password +label.move.focus.forwards = Move focus forwards +label.move.focus.backwards = Move focus backwards +label.keystore.location = KeyStore location +label.truststore.location = TrustStore location +label.pkcs.library.file = PKCS#11 library file +label.x509.certificate = X.509 certificate +label.apple.keychain = Apple KeyChain +label.add.to.roster = Add user to your roster +label.audio.device = &Audio device +label.video.device = &Video device +label.certificate.version = Version +label.certificate.serial.number = Serial number +label.certificate.signature.value = Signature value +label.certificate.signature.algorithm = Signature algorithm +label.certificate.issuer = Issuer +label.certificate.subject = Subject +label.certificate.not.before = Invalid before +label.certificate.not.after = Invalid after +label.certificate.public.key = Public key +label.certificate.public.key.algorithm = Public key algorithm +label.certificate.issuer.unique.id = Issuer unique ID +label.certificate.subject.unique.id = Subject unique ID +label.certificate.add.certificate.to.truststore = Add certificate to TrustStore +label.certificate.add.certificate.to.identitystore = Add certificate to IdentityStore +label.certificate.status = Status of the certificate. + +menuitem.about = About +menuitem.actions = Actions +menuitem.bookmarks = Bookmarks +menuitem.add = Add +menuitem.add.as.contact = Add as a contact +menuitem.add.contact = Add contact +menuitem.add.contact.group = Add contact group +menuitem.add.groupchat.myname = Highlight my &name when someone says it +menuitem.add.groupchat.mytext = &Highlight my text when I say something +menuitem.add.groupchat.popname = Show &toast popup when someone says my name +menuitem.add.groupchat.showjoinleavemessage = &Show join and leave messages +menuitem.add.groupchat.showrolesinsteadofstatus = Show chat role icons instead of presence icons +menuitem.add.groupchat.auto.accept.invite = &Automatically accept groupchat invites +menuitem.add.groupchat.random.colors = Names have &random colors +menuitem.affiliation = Affiliation +menuitem.always.on.top = Always on top +menuitem.alert.when.online = Alert when user is available +menuitem.ban = Ban +menuitem.ban.user = Ban user +menuitem.block.contact = Block contact +menuitem.block.user = Block user +menuitem.broadcast.to.group = Broadcast message to group +menuitem.browse.service = Browse service +menuitem.change.nickname = Change nickname +menuitem.change.subject = Change subject +menuitem.chat = Chat +menuitem.check.for.updates = Check for &updates +menuitem.connect = File +menuitem.contacts = Contacts +menuitem.copy.to = Copy to +menuitem.delete = Delete +menuitem.delete.login.information = Delete login information +menuitem.destroy.room = Destroy room +menuitem.dial = Dial +menuitem.edit = Edit +menuitem.edit.my.profile = Edit my profile... +menuitem.edit.status.message = Edit custom status messages... +menuitem.enter.login.information = Enter login information +menuitem.exit = Exit +menuitem.grant.moderator = Grant moderator +menuitem.grant.member = Grant Membership +menuitem.grant.admin = Grant Admin +menuitem.grant.owner = Grant Ownership +menuitem.grant.voice = Grant voice +menuitem.help = Help +menuitem.hide = Hide +menuitem.invite.group.to.conference = Invite group to conference +menuitem.invite.users = Invite users +menuitem.join.on.startup = Join on startup +menuitem.join.room = Join selected room +menuitem.kick.user = Kick user +menuitem.languages = Languages +menuitem.logout.no.status = Log out +menuitem.logout.with.status = Log out with reason +menuitem.lookup.profile = Lookup profile... +menuitem.move.to = Move to +menuitem.online.help = Spark forums +menuitem.open = Open +menuitem.open.with = Open with... +menuitem.plugins = Plugins +menuitem.preferences = Preferences +menuitem.remove = Remove +menuitem.remove.alert.when.online = Remove alert +menuitem.remove.bookmark = Remove bookmark +menuitem.remove.from.group = Remove From group +menuitem.remove.from.roster = Remove from roster +menuitem.unblock.contact = Unblock contact +menuitem.remove.service = Remove service +menuitem.rename = Rename +menuitem.revoke.moderator = Revoke moderator +menuitem.revoke.voice = Revoke voice +menuitem.revoke.member = Revoke Membership +menuitem.revoke.admin = Revoke Admin +menuitem.revoke.owner = Revoke Ownership +menuitem.save = Save +menuitem.save.as = Save as... +menuitem.send.a.file = Send a file +menuitem.send.a.message = Send broadcast to selected users... +menuitem.set.status.message = Set status message... +menuitem.show.empty.groups = Show empty groups +menuitem.show.offline.group = Group offline users +menuitem.show.traffic = Show traffic window +menuitem.sign.in = Sign in +menuitem.sign.in.at.login = Sign in at login +menuitem.sign.out = Sign out +menuitem.start.a.chat = Start a chat +menuitem.start.a.conference = Start a conference... +menuitem.status = Status +menuitem.subscribe.to = Subscribe to +menuitem.unban = Unban user on current list +menuitem.unblock.user = Unblock user on current list +menuitem.user.guide = User guide +menuitem.view.client.version = View client version +menuitem.view.contact.history = View contact history +menuitem.view.downloads = View downloads +menuitem.view.last.activity = View last activity +menuitem.view.logs = View logs +menuitem.view.profile = View profile +menuitem.view.room.info = View room info +menuitem.voice = Voice +menuitem.show.offline.users = Show offline users +menuitem.show.contact.statusmessage = Show status message +menuitem.bookmark.room = Bookmark room +menuitem.refresh = Refresh +menuitem.create.room=Create room +menuitem.expand.all.groups = Expand all groups +menuitem.collapse.all.groups = Collapse all groups +menuitem.invite.again = Invite again +menuitem.chatframe.option = Options +menuitem.add.groupchat.invitetobookmark = Automatically invite users to bookmarked room +menuitem.certificate.files.filter = Certificates files (*.cer), (*.crt), (*.der) + +message = Message +message.account.create = Create a new chat account +message.account.created = New account has been created +message.account.error = Specify the server to create the account on +message.add.a.contact = Add a contact +message.add.conference.service = Add a conference service +message.add.contact.to.list = Add a user to your contact list +message.add.favorite.room = Add room to favorites list or join directly +message.add.this.user.to.your.roster = Add this user to your buddy list +message.add.to.roster = Add To roster +message.add.user = Add user to your roster? +message.alert.notify = Alert notification +message.already.exists = Account already exists, please try a different username +message.create.account.not.allowed = Account creation is not allowed on the server +message.approve.subscription = Allow {0} to add you to their roster? +message.authenticating = Authenticating +message.away.idle = Away due to idle +message.bookmark.temporary.room.error = You cannot bookmark temporary rooms +message.broadcast.from = Broadcast from {0} +message.broadcast.no.user.selected = Please select at least one recipient +message.broadcast.no.text = Please enter text to broadcast +message.broadcast.message.sent = The broadcast message has been sent +message.broadcast.to = Enter message to broadcast to {0} +message.hasbeenbroadcast.to = The message has been broadcast to the following users\:\n{0} +message.buzz.alert.notification = Get the user's attention +message.buzz.message = {0} wants your attention +message.buzz.sent = Requested users attention +message.calling = Calling {0} +message.came.online = {0} is online at {1} +message.cannot.add.contact.to.shared.group = You cannot add new contacts to a shared group +message.cert.hostname.verification.failed = Certificate hostname verification failed +message.cert.verification.failed = Unable to verify certificate +message.chat.session.ended = Chat session has ended on {0} +message.click.to.open = Click to open +message.client.information = Client information for {0} +message.close.other.chats = Close all other chats +message.close.stale.chats = Close stale chats +message.close.this.chat = Close this chat +message.close.unread.window = You have unread messages, are you sure you want to close the window? +message.conference.info.error = Unable to retrieve conference information, please try back later +message.conference.rooms.unsupported=Rooms listing unsupported or unavailable +message.conference.service.error = Unable to locate the conference service +message.confirm.destruction.of.room = Destroying the room removes all users from the room, continue? +message.confirmation.password.error = Specify a confirmation password +message.connecting.please.wait = Connecting, please wait... +message.connection.failed = Unable to connect to {0} +message.create.account = Account could not be created +message.create.or.join.room = Create a conference chat room +message.current.status = Let others know your current status or activity +message.default.error = An error has been detected +message.delete.all.history = Delete all previous conversations? +message.delete.confirmation = Are you sure you want to delete {0}? +message.disable.transport = Remove login information from {0}? +message.disconnected.conflict.error = Your connection was closed due to the same user logging in from another location +message.disconnected.error = Your connection was closed due to an error +message.disconnected.group.chat.error = Your connection was closed due to an error, Spark will automatically re-join the channel when reconnection is successful +message.disconnected.shutdown = Your connection was closed because the server was shut down +message.downloading = Downloading {0} +message.downloading.spark.plug = Downloading Spark-Plug +message.end.chat = Would you like to end this chat? +message.end.conversation = Would you like to end this session? +message.enter.broadcast.message = Enter message to broadcast to selected users +message.enter.gadugadu = Enter your GaduGadu username and password below +message.enter.irc = Enter your IRC username, password and nickname below +message.enter.sametime = Enter your Sametime username and password below +message.enter.facebook = Enter your Facebook username and password below +message.enter.myspace = Enter your MySpace username and password below +message.enter.jabber.id = Enter Jabber ID +message.enter.message.to.broadcast = Enter message to broadcast to your entire roster list +message.enter.new.subject = Enter new subject +message.enter.qq = Enter your QQ Number and password below +message.enter.room.password = Enter room password +message.enter.simple = Enter your SIMPLE username and password below +message.enter.valid.jid = Enter a valid Jabber ID +message.enter.xmpp = Enter your XMPP username and password below +message.error.during.file.transfer = There was an error during file transfer +message.error.must.use.reserved.nick = You must use your reserved room nick. +message.error.nickname.in.use = Your desired nickname is in use or reserved by someone else. +message.error.no.permission.create.room = You do not have permission to create a room. +message.error.no.response = No response from server. +message.error.not.member = You are not a member of this room.\nThis room requires you to be a member to join. +message.error.room.not.exist = The room you are trying to enter does not exist. +message.error.room.password.incorrect = The password did not match the room's password. +message.error.unable.join.room = Unable to join the room. +message.file.exists.question = The file already exists, overwrite? +message.file.size = File Size: {0} +message.file.transfer.canceled = You have canceled the file transfer +message.file.transfer.rejected = The file transfer was not accepted by {0} +message.file.transfer.dirnull = Download directory for file transfer is not valid +message.file.transfer.nodir = Download directory for file transfer does not exist +message.file.transfer.cantwritedir = Can't write to the directory for file transfer +message.file.transfer.notification = File transfer notification +message.file.transfer.short.message = is sending you a file called\: +message.file.transfer.chat.window = File transfer request: +message.file.transfer.file.too.big.error = The selected file is too big.\nThe maximum file size is {0} the selected file has {1} +message.file.transfer.file.too.big.warning = The selected file is too big.\nProceed anyway? +message.file.transfer.direrror.setdir = Click here to change the directory +message.file.transfer.history.request.sent = Request for transfer file "{0}" ({1}) was sent to {2}. +message.file.transfer.history.send.complete = File "{0}" was successfully sent to {1}. +message.file.transfer.history.send.error = Sending file "{0}" to {1} failed. +message.file.transfer.history.send.canceled = Sending file "{0}" to {1} canceled. +message.file.transfer.history.contact.rejected = {1} rejected transfer request for file "{0}". +message.file.transfer.history.request.received = Request for transfer file "{0}" ({1}) was received from {2}. +message.file.transfer.history.you.rejected = You have rejected transfer request for file "{0}" from {1}. +message.file.transfer.history.you.accepted = You have accepted transfer request for file "{0}" from {1}. +message.file.transfer.history.receive.success = File "{0}" was successfully received from {1}. +message.file.transfer.history.receive.failed = Receiving file "{0}" from {1} failed. +message.file.transfer.history.receive.canceled = Receiving file "{0}" from {1} canceled. +message.find.conference.services = Find conference services +message.forbidden.error = Received a forbidden error from the server +message.gateway.username.error = Username needs to be supplied +message.gateway.password.error = Password needs to be supplied +message.gateway.nickname.error = Nickname needs to be supplied +message.general.error = You have lost your connection to the server due to {0} +message.generic.reconnect.message = You have lost your connection to the server, to login again, click on the reconnect button below +message.idle.for = Idle for {0} +message.image.small.resolution = Image size is less than 32x32 pixels +message.invalid.jabber.id = Not a valid Jabber ID +message.invalid.jid.error = The JID specified is invalid +message.invalid.status = Specify a valid status message +message.invalid.username.password = Invalid username or password +message.invite.to.groupchat = {0} is inviting you to join a group chat +message.invite.users.to.conference = Invite users to a conference room +message.is.shared.group = {0} is a shared group +message.is.typing.a.message = {0} is typing a message... +message.join.conference.room = Join conference room +message.kicked.error = You are not able to kick {0} out of this room +message.last.message.received = Last message received on {0} +message.loading.please.wait = Loading. Please wait... +message.locked.workstation = User has locked their workstation +message.name.of.group = Name of group +message.name.of.search.service.question = Name of search service? +message.negotiate.file.transfer = Negotiating file transfer, please wait... +message.negotiate.stream = Negotiating connection stream, please wait... +message.negotiation.file.transfer = Negotiating file transfer with {0}, please wait... +message.new.message = New message from {0} +message.new.spark.available = {0} is now available, would you like to install? +message.nickname.error = Nickname should be set +message.nickname.in.use = Nickname in use, please specify another Nickname +message.nickname.not.acceptable = Nickname change is not enabled! +message.no.avatar.found = No avatar was configured by the user +message.no.caller.id = No caller ID available +message.no.description.available = No description available +message.no.history.found = There is no previous conversation history for this user +message.no.results.found = No search results were returned by the server +message.no.room.to.join.error = No room to join +message.no.subject.available = No subject available +message.no.updates = There are no updates +message.normal = Normal message +message.number.to.call = Specify number to dial +message.offline = The user is offline and will receive the message on their next login +message.offline.error = The user will be unable to receive offline messages +message.participants.in.room = Participants in room +message.password.error = Specify a password for this account +message.password.private.room.error = Specify password for the private room +message.passwords.no.match = Passwords do not match +message.please.join.in.conference = Please join me in a conference +message.plugins.not.available = Unable to contact the plugin repository +message.prompt.plugin.uninstall = Are you sure you want to deactivate {0}? +message.received.file = You have received a file from {0} +message.receiving.file = You are receiving a file from {0} +message.reconnect.attempting = Attempting... +message.reconnect.failed = Reconnect failed +message.reconnect.wait = Reconnecting in {0} seconds +message.register.transports = Register with these available transports +message.registering = Registering with {0}, please wait... +message.registration.transport.failed = Unable to register with gateway +message.restart.spark = You will need to shut down the client to \n install the new version, would you like to do that now? +message.restart.spark.changes = Plugin changes will be applied on the next startup of Spark +message.restart.spark.to.install = You need to shut down the client to install latest version, would you like to do that now? +message.restart.required = You will need to restart Spark to have your changes take effect, restart now? +message.room.creation.error = The room could not be created +message.room.destroyed.no.reason = This room has been destroyed. +message.room.destroyed = This room has been destroyed due to the following reason: {0} +message.room.destruction.reason = Reason for destroying the room? +message.room.information.for = Room information for {0} +message.save.profile = To save changes to your profile, click save +message.search.for.contacts = Search for contacts +message.search.input.short = Please provide at least two letters. +message.search.for.other.people = Search for other people on the server +message.search.service.not.available = Contact search service is not available +message.searching.please.wait = Searching, please wait... +message.select.add.room.to.add = Please select a room to add to your service list +message.select.one.or.more = Select one or more users in your roster +message.select.room.to.enter = Specify room to enter +message.select.room.to.join = Select room to join +message.send.a.broadcast = Send a broadcast +message.send.file.to.user = Send files to this user +message.send.picture = Capture and send anything you see on your screen +message.send.to.these.people = Send to these people +message.sending.file.to = Sending file to {0} +message.sent.offline.files = You have just been sent offline file(s). +message.server.unavailable = Can't connect to server: invalid name or server not reachable +message.service.already.exists = Service is already in your service list +message.shared.group = Shared group +message.specify.contact.jid = Please specify the contact JID (ex. ddman@jabber.org) +message.specify.group = Specify contact group to add the new user to +message.specify.information.for.conference = Specify information for conference room +message.specify.name.error = Specify a valid name +message.specify.users.to.join.conference = Specify users to join this conference room +message.specify.valid.time.error = Specify a valid timeout and port +message.subject.change.error = You are not allowed to change the subject of this room +message.subject.has.been.changed.to = {1} changed the subject to "{0}" +message.supply.resource = Supply a valid resource +message.supply.valid.port = Supply a valid port +message.supply.valid.timeout = Supply a valid time out value +message.timeout.error = The timeout must be 5 seconds or greater +message.total.downloaded = Total downloaded +message.transfer.cancelled = The file transfer was canceled +message.transfer.complete = The file transfer was complete ({0}) +message.transfer.progressbar.text.received = {0} received @ {1} {2} +message.transfer.progressbar.text.sent = {0} sent @ {1} {2} +message.transfer.rate = Transfer rate +message.transfer.refused = The file transfer was refused +message.transfer.waiting.on.user = Waiting for {0} to accept file transfer +message.unable.to.load.profile = Unable to locate a profile for {0} +message.unable.to.retrieve.last.activity = Unable to determine last activity for {0} +message.unable.to.save.password = Unable to change password, please contact your server admin +message.unable.to.send.file = You were unable to send the file to {0} +message.unable.to.use.hostname.as.resource = Unable to use hostname as resource +message.unrecoverable.error = Unknown connection error. Please review the logs for more information. +message.update.room.list = Update room list +message.updating.cancelled = Updating has been canceled +message.user.banned = {0} has been banned from this room. Reason: {1} +message.user.banned.no.reason = {0} has been banned from this room. +message.user.given.voice = {0} has been given a voice in this room +message.user.granted.admin = {0} has been granted administrator privileges +message.user.granted.membership = {0} has been given membership privileges +message.user.granted.moderator = {0} has been granted moderator privileges +message.user.granted.owner = {0} has been granted owner privileges +message.user.is.sending.you.a.file = {0} is sending you a file +message.user.joined.room = {0} has joined the room +message.user.kicked.from.room = {0} has been kicked out of the room by {1}. Reason: {2} +message.user.kicked.from.room.no.reason = {0} has been kicked out of the room by {1}. +message.user.left.room = {0} has left the room +message.user.nickname.changed = {0} is now known as {1} +message.user.now.available.to.chat = {0} is online at {1} +message.user.revoked.admin = Administrator privileges have been revoked for {0} +message.user.revoked.membership = Membership has been revoked for {0} +message.user.revoked.moderator = Moderator privileges have been revoked for {0} +message.user.revoked.owner = Owner privileges have been revoked for {0} +message.user.voice.revoked = Voice has been revoked for {0} +message.username.error = Specify a username for the account +message.username.password.error = Username and/or password need to be supplied. +message.vcard.not.supported = Server does not support VCards, unable to save your VCard +message.version = Version: {0} +message.view.information.about.this.user = View information about this user +message.waiting.for.user.to.join = Waiting for {0} to join +message.went.offline = {0} went offline at {1} +message.you.have.been.banned = You have been banned from this room +message.you.have.been.kicked = You have been kicked out of this room +message.you.have.sent = You have sent a file to {0} +message.your.admin.granted = You have been granted administrator privileges +message.your.banned = You have been banned from this room +message.your.kicked = You have been kicked by {0} +message.your.membership.granted = You have been granted membership privileges +message.your.membership.revoked = Your membership has been revoked +message.your.moderator.granted = You have been granted moderator privileges +message.your.moderator.revoked = Your moderator privileges have been revoked +message.your.ownership.granted = Your have been granted owner privileges +message.your.ownership.revoked = Your owner privileges have been revoked +message.your.revoked.granted = Your admin privileges have been revoked +message.your.voice.granted = You have been given a voice in this chat +message.your.voice.revoked = Your voice has been revoked +message.groupchat.require.password = This group chat room requires a password to enter +message.groupchat.registered.member = Successfully registered with {0} +message.search.for.history = Search conversation history +message.search.period.day.one = one day per page +message.search.period.week.one = one week per page +message.search.period.month.one = one month per page +message.search.period.year.one = one year per page +message.search.period.none = show all on one page +message.search.page.timeperiod = choose the timespan of messages, which are displayed per page +message.search.page.counter = the current index of your page and the amount of all pages +message.search.page.right = navigate one page forward +message.search.page.left = navigate one page backward + +status.away = Away +status.custom.messages = Custom messages +status.do.not.disturb = Do not disturb +status.extended.away = Extended away +status.free.to.chat = Free to chat +status.on.phone = On the phone +status.online = Online +status.pending = Pending +status.invisible = Invisible +status.offline = Offline + +tab.available.plugins = Available plugins +tab.avatar = Avatar +tab.business = Business +tab.conferences = Conferences +tab.contacts = Contacts +tab.deactivated.plugins = Deactivated plugins +tab.general = General +tab.security = Security +tab.home = Home +tab.installed.plugins = Installed plugins +tab.personal = Personal +tab.proxy = Proxy +tab.sso = SSO +tab.pki = PKI +tab.certificates = Certificates +tab.mutual.auth = Mutual auth +title.about = About +title.advanced.connection.preferences = Advanced connection preferences +title.account.create.registration = Account registration +title.account.created = Account created +title.add.contact = Add contact +title.add.contact.group = Add contact group +title.add.new.group = Add new group +title.add.search.service = Add search service +title.add.to.roster = Add to roster +title.address = Address +title.advanced.connection.sso = Using Single Sign-On (SSO) +title.advanced.connection.usesso = Use Single Sign-On (SSO) via GSSAPI +title.advanced.connection.sso.account = This will use the Desktop Account for "{0}" to login to the server. +title.advanced.connection.sso.unable = Unable to connect using Single Sign-On. Please check your principal and server settings. +title.advanced.connection.sso.noprincipal = Spark is unable to find the principal to use for Single Sign-On. This will prevent SSO from working. +title.advanced.connection.sso.smack3compat = Smack 3 compatibility mode +title.alert = Alert +title.appearance = Appearance +title.appearance.preferences = Customization +title.available.transports = Available transports +title.bookmarks = Bookmarks +title.broadcast.message = Broadcast message +title.broadcast.history = Broadcast history +title.browse.conference.services = Browse conference services +title.browse.room.service = Browse conference rooms - {0} +title.cancelled = Cancelled +title.change.nickname = Change nickname +title.change.subject = Change subject +title.chat = Chat +title.choose.directory = Choose directory +title.choose.incoming.sound = Choose incoming sound file +title.choose.offline.sound = Choose offline sound file +title.choose.outgoing.sound = Choose outgoing sound file +title.choose.chat_request.sound=Choose chat request sound file +title.client.logs = Client logs +title.conference.invitation = Conference invitation +title.conference.rooms = Conference rooms +title.configure.chat.room = Configure chat room +title.configure.room = Configure room +title.confirmation = Confirmation +title.create.new.account = Create new account +title.create.or.bookmark.room = Join or bookmark room +title.create.room = Create room +title.create.problem = Account creation problem +title.delete.file = Do you really want to delete this file? +title.dial.phone = Dial phone +title.disable.transport = Remove login information +title.download.complete = Download complete +title.downloading.im.client = Download IM client +title.downloads = Downloads +title.edit.custom.message = Edit custom messages +title.edit.profile = Edit profile information +title.enter.reason = Enter reason +title.error = Error +title.error.couldnot.open.file = Could not open the file +title.error.delete.file = Could not delete file +title.error.find.app = Could not find a matching application +title.error.rename.file = Could not rename the file +title.file = File +title.filesize = Size +title.file.exists = File exists +title.file.transfer = File transfer +title.file.transfer.preferences = File transfer preferences +title.find.conference.service = Find conference service +title.find.contacts = Find contacts +title.gadugadu.registration = GaduGadu account credentials +title.general.media = Media settings +title.general.chat.settings = General chat settings +title.group.chat = Group chat +title.group.chat.settings = Group chat settings +title.history.for = Conversation history for {0} +title.irc.registration = IRC account credentials +title.sametime.registration = Sametime account credentials +title.facebook.registration = Facebook account credentials +title.myspace.registration = MySpace account credentials +title.incoming.call = Incoming call +title.input.fileexplorer = Please input the name of your file browser: +title.input.newname = Please input the new name\: +title.input.openwith = Please input the name of the application which you want to use: +title.invite.to.conference = Invite To conference +title.jabber.browser = Browser +title.join.conference.room = Join conference room +title.last.activity = Last activity +title.login = Login +title.login.error = Login error +title.login.settings = Login settings +title.login.no.account = Unable to determine +title.lookup.profile = Lookup profile +title.name = Name +title.new.client.available = New client available +title.new.roster.group = New roster group +title.new.version.available = New version available +title.no.updates = No updates +title.notes = Notes +title.notification = Notification +title.notifications = Notifications +title.occupants = Occupants +title.on.the.phone = On the phone +title.password = Password +title.password.required = Password required +title.passwords.no.match = Confirm passwords +title.person.search = Person search +title.plugins = Plugins +title.preferences = Preferences +title.profile.information = Profile information +title.profile.not.found = Profile not found +title.qq.registration = QQ account credentials +title.register.account = Register new account +title.registration.error = Registration error +title.reminder = Reminder +title.rename.roster.group = Rename roster group +title.room.destroyed = Room destroyed +title.room.information = Room information +title.roster = Roster +title.select.file.to.send = Select file(s) to send +title.set.status.message = Set status message +title.simple.registration = SIMPLE account credentials +title.sound.preferences = Sound preferences +title.sounds = Sounds +title.spark.preferences = Spark preferences +title.start.chat = Start chat +title.status.message = Status message +title.task.notification = Task notification +title.tasks = Tasks +title.transports = Transports +title.tray.information = Tray information +title.upgrading.client = Upgrading client +title.version.and.time = Version and time +title.view.bookmarks = View bookmarks +title.view.profile.for = Viewing profile for {0} +title.view.room.information = View room information +title.waiting.to.call = Waiting to place call +title.warning = Warning +title.xmpp.registration = XMPP account credentials +title.appearance.showVCards = Show &VCards in the contact list +title.subscription.request = Subscription request +title.certificate = Certificate +title.avatar.crop=Crop image + +time.days = d +time.hours = h +time.minutes = min +time.since = since +time.less.than.one.minute = less than 1 minute + +tooltip.place.a.call = Place a call to this individual +tooltip.appearance = Change the appearance of your conversations +tooltip.file.transfer = Preferences for file transfer +tooltip.notifications = Notification preferences for incoming chats +tooltip.place.voice.call = Place a phone call to this user +tooltip.send.email = Send an e-mail +tooltip.start.chat = Start a conversation +tooltip.view.changelog = View change log +tooltip.view.history = View conversation history +tooltip.view.readme = View readme +tooltip.encryptionmode.required = Encryption is required in order to connect. If the server does not offer encryption, or if the encryption negotiation fails, the connection to the server will fail. +tooltip.encryptionmode.ifpossible = Encryption is used whenever it's available. +tooltip.encryptionmode.disabled = Encryption is disabled and only non-encrypted connections will be used. If encryption is required by the server, the connection will fail. + +tree.conference.services = Conference services +tree.users.in.room = Users in room + +lookandfeel.select = Select Look & Feel +lookandfeel.change.now = Change now +lookandfeel.tooltip.restart.no = No restart is needed +lookandfeel.tooltip.restart.yes = To toggle a System Look&Feel press Save and restart Spark. +lookandfeel.color.label = Colors +lookandfeel.color.red = Red +lookandfeel.color.green = Green +lookandfeel.color.blue = Blue +lookandfeel.color.opacity = Opacity +lookandfeel.color.saved = Color saved + + +##Settings for the privacy plugin +privacy.title.preferences = Spark Privacy Preferences +privacy.title.panel = Please use right mouse button +privacy.label.iq.desc = Query +privacy.label.pin.desc = Presence in +privacy.label.pout.desc = Presence out +privacy.label.msg.desc = Messages +privacy.border.information = Privacy Information +privacy.label.information = Use right click menu to add or delete lists or items +privacy.root.node = Privacy Lists +privacy.label.preferences = Privacy Plugin +privacy.tooltip.preferences = Spark privacy settings +privacy.label.list.is.active = Current active list: +privacy.label.list.is.default = Default list: +privacy.border.block = Block +privacy.pick.one.or.more = Pick one or more items to add to the list +privacy.title.add.picker = Add Items to List +privacy.node.contacts = Contacts +privacy.node.groups = Groups +privacy.menu.add.contacts = Add Contacts to list +privacy.menu.add.groups = Add Groups to list +privacy.menu.add.rem.items = Remove {0} items from list +privacy.menu.remove = Remove +privacy.menu.activate.list = Activate +privacy.menu.default.list = Set as default +privacy.menu.add.list = Add list +privacy.menu.remove.list = Remove list +privacy.dialog.add.list = Please enter list name +privacy.dialog.rem.list = Do you really want to remove {0}? +privacy.status.menu.entry = Privacy Lists +privacy.name.for.default.list = Default +privacy.button.no.list.selected = No list selected +privacy.menuitem.deactivate.current.list = Deactivate {0} +privacy.label.not.supported = Privacy lists are not supported by server. + +##Stunfallback in media settings +stun.border.label = STUN fallback server +stun.server.addr = STUN Server: +stun.server.port = STUN Port: + +##Text Field Hints +hint.login.username = Enter Username +hint.login.password = Enter Password +hint.login.domain = Enter Domain + +composing = {0} is typing... +paused = {0} has stopped typing +active = {0} is paying attention +inactive = {0} is doing something else +gone = {0} has left + +#!# +action.viewlog=View Log + +dialog.confirm.to.reveal.visibility.title=Are you sure? +dialog.confirm.to.reveal.visibility.msg=If you are going to proceed your invisibility will be revealed +dialog.confirm.close.all.conferences.if.invisible.msg = If you want to proceed all conference rooms will be closed +dialog.certificate.show = This is the certificate and private key you are trying to add to the TrustStore.

      After adding this certificate Spark will be able to establish secured
      communications with servers that are identified by this certificate.

      If you are sure that you want to add this certificate click the OK button. +dialog.id.certificate.show = This is the certificate you are trying to add to the IdentityStore

      After adding this certificate Spark will be able to present this certificate to remote server during establishing connection in order to authenticate itself and encrypt that connection.

      If you are sure that you want to add this certificate click the OK button. +dialog.certificate.add.from.connection = This is the certificate provided by the server you are trying to connect to.
      This certificate isn't in your TrustStore, which means it is not trusted
      and you cannot connect to this server.

      Do you want to trust it and add this certificate to your TrustStore? +dialog.certificate.unrecognized.server.certificate = The server that you are connecting to identifies itself with a certificate that
      is not recognized by Spark. Please review the details below. +dialog.certificate.ask.allow.self-signed = The server that you are connecting to identifies itself with a certificate that is self-signed.
      The current configuration of Spark disallows the use of self-signed certificates. Would you
      like to change this configuration and try again? +dialog.certificate.subject.label = Subject: + +dialog.certificate.add.unrecognized.server.certificate = Do you want to add this certificate to the set of certificates that is trusted by Spark? +dialog.certificate.chain.add.from.connection = This is the certificate chain provided by the server you are connecting to.
      It is not in your trusted list, so you can't connect.

      Do you want to add this certificates to your trusted list? +dialog.certificate.cannot.have.copy = This certificate is already stored within TrustStore. +dialog.certificate.has.been.added = Certificate has been added to the TrustStore. +dialog.certificate.has.been.added.to.identity.store = Certificate has been added to the IdentityStore. +dialog.certificate.is.distrusted = Certificate is invalid, so it shouldn't be trusted, as it is dangerous. \n If you still want to trust it, click on Trust radio button or add it to exception list. +dialog.certificate.sure.to.delete = Are you sure that you want to delete this certificate? \nIf you do it, you will be unable to establish a secured connection \nto servers identified by this certificate. +dialog.certificate.has.been.deleted = Certificate has been successfully deleted. +dialog.self.signed.certificate.has.been.created = Self signed certificate and private key have been created in directory: \n +dialog.certificate.request.has.been.created = Certificate Sign Request and private key have been created in directory: \n +dialog.cannot.upload.certificate.might.be.ill.formatted = Cannot upload certificate file, certificate might be ill formatted +dialog.cannot.upload.certificate = Cannot upload certificate file +dialog.certificate.title.certificate.not.in.truststore = Provided certificate is not in your TrustStore +dialog.title.master.password.prompt.new = Enter a new master password below for encryption of secrets (user/proxy/room passwords) +dialog.title.master.password.prompt.old = Enter your master password below for encryption of secrets (user/proxy/room passwords) + +cert.valid = Valid +cert.revoked = Revoked +cert.expired = Expired +cert.not.valid.yet = Not valid yet +cert.self.signed = Self signed +cert.sign.request = Certificate Signing Request +cert.self.signed.save.to.file = Save certificate to file +cert.unknown.oid = Unknown OID description. +cert.is.critical = Is critical: +cert.critical = Critical: +cert.not.critical = Not critical: +cert.common.name = Common name +cert.organization.unit = Organization unit +cert.organization = Organization +cert.country = Country +cert.city = City + +cert.extensions = Certificate extensions: +cert.extensions.unsupported = Unsupported extensions +cert.extension.extended.usage.digital.signature = Digital signature +cert.extension.extended.usage.non.repudiation = Non repudiation +cert.extension.extended.usage.key.encipherment = Key encipherment +cert.extension.extended.usage.data.encipherment = Data encipherment +cert.extension.extended.usage.key.agreement = Key agreement +cert.extension.extended.usage.key.cert.sign = Key cert sign +cert.extension.extended.usage.crl.sign = CRL sign +cert.extension.extended.usage.encipher.only = Encipher only +cert.extension.extended.usage.decipher.only = Decipher only +cert.extension.basic.constraints.is.ca = Is certificate authority +cert.extension.basic.constraints.path.length = Validation path length +cert.extension.name.constraints.permitted.subtrees = Permitted subtrees +cert.extension.name.constraints.excluded.subtrees = Excluded subtrees + +# File types +file.type.sound=Sound files + +##OID's mapping +2.5.29.1 = X.509 old Authority Key Identifier +2.5.29.2 = Key attributes +2.5.29.3 = Certificate policies +2.5.29.4 = Key usage restrictions +2.5.29.5 = Policy mapping +2.5.29.6 = Subtree constraints +2.5.29.7 = Subject alternative name +2.5.29.8 = Issuer alternative name +2.5.29.9 = Subject directory attributes +2.5.29.10 = Basic constraints +2.5.29.11 = Certificate Extension +2.5.29.12 = Certificate Extension +2.5.29.13 = Certificate Extension +2.5.29.14 = Subject key identifier +2.5.29.15 = Key usage +2.5.29.16 = Private key usage period +2.5.29.17 = Subject alternative name +2.5.29.18 = Issuer alternative name +2.5.29.19 = Basic constraints +2.5.29.20 = CRL number +2.5.29.21 = Reason code +2.5.29.22 = Expiration date +2.5.29.23 = Hold instruction code +2.5.29.24 = Invalidity date +2.5.29.25 = CRL Distribution Points +2.5.29.26 = Issuing distribution point +2.5.29.27 = CRL indicator +2.5.29.28 = Issuing distribution point +2.5.29.29 = Certificate issuer +2.5.29.30 = Name constraints +2.5.29.31 = CRL distribution points +2.5.29.32 = Certificate policies +2.5.29.33 = Policy mappings +2.5.29.34 = Policy constraints +2.5.29.35 = Authority key identifier +2.5.29.36 = Policy constraints +2.5.29.37 = Extended key usage +2.5.29.38 = Authority attribute identifier +2.5.29.39 = Role specification certificate identifier +2.5.29.40 = CRL stream identifier +2.5.29.41 = basicAttConstraints +2.5.29.42 = Delegated Name Constraints +2.5.29.43 = Time specification +2.5.29.44 = CRL scope +2.5.29.45 = Status referrals +2.5.29.46 = Freshest CRL +2.5.29.47 = Ascending order list in CRL +2.5.29.48 = Attribute descriptor +2.5.29.49 = User notice +2.5.29.50 = SOA identifier +2.5.29.51 = Base CRL update time +2.5.29.52 = Acceptable certificate policies +2.5.29.53 = Delta info +2.5.29.54 = Inhabit any-policy +2.5.29.55 = Targeting information +2.5.29.56 = No revocation information available +2.5.29.57 = Acceptable privilege policies +2.5.29.58 = id-ce-toBeRevoked +2.5.29.59 = id-ce-RevokedGroups +2.5.29.60 = id-ce-expiredCertsOnCRL +2.5.29.61 = Indirect issuer +2.5.29.62 = id-ce-noAssertion +2.5.29.63 = id-ce-aAissuingDistributionPoint +2.5.29.64 = id-ce-issuedOnBehaIFOF +2.5.29.65 = id-ce-singleUse +2.5.29.66 = id-ce-groupAC +2.5.29.67 = id-ce-allowedAttAss +2.5.29.68 = id-ce-attributeMappings +2.5.29.69 = id-ce-holderNameConstraints + +2.16.840.1.113730.1.1 = +1.3.6.1.4.1.311.20.2 = szOID_ENROLL_CERTTYPE_EXTENSION +1.3.6.1.4.1.311.21.1 = MS Certificate Services CA Version +1.2.840.113533.7.65.0 = Entrust version extension +1.3.6.1.5.5.7.1.1 = Certificate authority information access +1.3.6.1.5.5.7.3.1 = Certificate can be used as a Secure Sockets Layer (SSL) server certificate. +1.3.6.1.5.5.7.3.2 = Certificate can be used as a Secure Sockets Layer (SSL) client certificate. +1.3.6.1.5.5.7.3.3 = Certificate can be used for code signing. +1.3.6.1.5.5.7.3.4 = Certificate can be used for protecting email (signing, encryption, key agreement). +1.3.6.1.5.5.7.3.5 = Internet Protocol SECurity (IPSEC) end system certificate. +1.3.6.1.5.5.7.3.6 = Internet Protocol SECurity (IPSEC) tunnel certificate. +1.3.6.1.5.5.7.3.7 = Internet Protocol SECurity (IPSEC) user certificate. +1.3.6.1.5.5.7.3.8 = PKIX key purpose time stamping. Certificate can be used to bind the hash of an object to a time from a trusted time source. + +1.3.6.1.5.5.7.3.9 = Rec. ITU-T X.509 certificates corresponding private key may be used by an authority to sign OCSP-Responses. +1.3.6.1.5.5.7.3.10 = PKIX key purpose Data Validation and Certification Server Protocols. +1.3.6.1.5.5.7.3.11 = sbgpCertAAServerAuth. +1.3.6.1.5.5.7.3.12 = id-kp-scvp-responder key purpose. +1.3.6.1.5.5.7.3.13 = id-kp-eapOverPPP + +1.3.6.1.5.5.7.1.12 = id-pe-logotype +1.3.6.1.4.1.311.10.3.4 = Automatically extracted from Object IDs Associated with Microsoft Cryptography. +2.23.42.7.0 = Hashed Root Key diff --git a/core/src/main/resources/i18n/spark_i18n_cs.properties b/core/src/main/resources/i18n/spark_i18n_cs.properties new file mode 100644 index 000000000..24ac382c0 --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_cs.properties @@ -0,0 +1,591 @@ +ok = Ok +cancel = Storno +add = PÅ™idat +use.default = Použít výchozí +close = Zavřít +create = VytvoÅ™it +invite = Pozvat +date = Datum +from = Od +room.name = Jméno místnosti +join = PÅ™ijmout +description = Popis +subject = PÅ™edmÄ›t +occupants = Obyvatelé +accept = PÅ™ijmout +reject = Odmítnout +open = Otevřít +open.folder = Otevřít složku +retry = Opakovat +is.active = Aktivní +not.registered = Není registrován +save = Uložit +yes = Ano +no = Ne +broadcast = Vysílat +available = Dostupný +user.has.signed.off = odhlásil/a se. +message = Zpráva + + +button.create.account = &VytvoÅ™it úÄet +button.close = Za&vřít +button.advanced = Da&lší +button.browse = &Procházet... +button.browse2 = P&rocházet... +button.browse3 = Pr&ocházet... +button.approve = &Schválit +button.deny = &Zamítnout +button.accept = &Povolit +button.profile = &Profil +button.add.a.contact = &PÅ™idat kontakt +button.reconnect = &Znovu pÅ™ipojit +button.add = &PÅ™idat +button.roster = &PÅ™ehled +button.add.bookmark = PÅ™idat záložku +button.remove.bookmark = Odebrat záložku +button.bookmark.room = &Záložková místnost +button.create.room = &VytvoÅ™it nebo PÅ™ipojit se do místnosti +button.join.room = &PÅ™ipojit se do vybrané místnosti +button.refresh = &Obnovit +button.find = &Najít +button.update = &Aktualizovat +button.cancel = &Storno +button.decline = &Odmítnout +button.join = &PÅ™ipojit +button.save.for.future.use = &Uložit na přístÄ› +button.register = &Registrovat +button.dial.number = &VytoÄit Äíslo +button.clear = &Smazat +button.search = &Najít +button.add.service = &PÅ™idat službu +button.quit = &Odejít +button.new = &Nový +button.add.user = &PÅ™idat uživatele +button.save = &Uložit +button.start.chat = Chat +button.send.email = Email +button.send = Poslat + + + +checkbox.save.password = &Uložit heslo +checkbox.auto.login = &Auto pÅ™ihlášení +checkbox.use.proxy.server = &Použít server Proxy +checkbox.auto.discover.port = &Automaticky najít server a port +checkbox.permanent = Místnost je &stálá +checkbox.private.room = Místnost &je soukromá +checkbox.show.time.in.chat.window = &Ukázat Äas v chat oknÄ› +checkbox.show.notifications.in.conference = &Ukázat notifikace v místnostech konference +checkbox.disable.chat.history = &Vypnout historii chatu +checkbox.show.toaster = Ukázat &Toast popup +checkbox.window.to.front = &PÅ™enést okno dopÅ™edu +checkbox.play.sound.on.new.message = PÅ™ehrát zvuk když pÅ™ijde nová &zpráva +checkbox.play.sound.when.offline = PÅ™ehrát zvuk když uživatel jde &offline +checkbox.play.sound.on.outgoing.message = PÅ™ehrát zvuk když je zpráva &poslána +checkbox.play.sound.on.invitation = PÅ™ehrát zvuk když pÅ™ijde &pozvánka +checkbox.idle.enabled = &NeÄinný Zapnuto +checkbox.launch.on.startup = &Spustit pÅ™i startu +checkbox.start.in.tray = &Spustit v minimalizovaném režimu +checkbox.split.chat.window = Dokovat &Okna (PotÅ™ebuje restart) +checkbox.tabs.on.top = &Chat záložky nahoÅ™e (PotÅ™ebuje restart) +checkbox.tabs.scroll = Pro karty chatu použít posouvání (PotÅ™ebuje restart) +checkbox.allow.buzz = Povolit uživatelům pro&zvánÄ›t tÄ› +checkbox.enable.emoticons = Povolit Sm&ajlíky +checkbox.use.system.look.and.feel = Použít &barvy a prostÅ™edí systému (PotÅ™ebuje restart) +checkbox.notify.user.goes.offline = Oznámit když uživatel odejde offline. +checkbox.notify.user.comes.online = Oznámit když uživatel pÅ™ijde online. +checkbox.close.unread.message = PÅ™i zavírání okna se zeptejte, zda existují nepÅ™eÄtené zprávy + + +label.user.on.public.network = Uživatel je na veÅ™ejné síti +label.change.password.to = &ZmÄ›nit heslo na +label.username = &Uživatelské jméno +label.name = &Jméno +label.room.name = J&méno Místnosti +label.room.topic= &Téma Místnosti +label.password = &Heslo +label.confirm.password = &Potvrdit Heslo +label.server = Do&ména +label.create.account = VytvoÅ™it úÄet +label.close = Z&avřít +label.ok = OK +label.cancel = Storno +label.use.default = Použít výchyozí +label.port = &Port +label.auto.login = &Auto Login +label.old.ssl = P&oužít starou SSL port metodu +label.host = &Host +label.resource = &Zdroj +label.protocol = &Protokol +label.accounts = &ÚÄty +label.received = &PÅ™ijato +label.transfer.timeout = &Timeout PÅ™enosu (min): +label.transfer.download.directory = &Složka pro stahování: +label.find = &Najít +label.rename.to = PÅ™ejmenovat na +label.contact.to.find = Najít Kontakt +label.available.users.in.roster = &Dostupní uživatelé v seznamu +label.time = ÄŒas: {0} +label.add.conference.service = &PÅ™idat službu konference +label.add.jid = &PÅ™idat JID +label.message = &Zpráva +label.room = &Mísnost +label.invited.users = PÅ™izvaní Uživatelé +label.new.nickname = Nová PÅ™ezdívka +label.server.address = Adresa &Serveru +label.nickname = PÅ™&ezdívka +label.presence = &Přítomnost +label.priority = P&riorita +label.enter.address = Vlož Adresu +label.jabber.address = &Jabber Adresa +label.local.time = &Místní ÄŒas +label.software = &Software +label.version = &Verze +label.os = &OperaÄní Systém +label.number = &Číslo +label.dial = &Volat +label.minutes.before.stale.chat = &Minuty pÅ™ed zvÄ›tráním místnosti +label.company = &SpoleÄnost +label.street.address = &Adresa +label.city = &MÄ›sto +label.state.and.province = S&tát +label.postal.code = &PSÄŒ +label.country = K&raj +label.job.title = &Pracovní zaÅ™azení +label.department = &OddÄ›lení +label.phone = &Telefon +label.fax = &Fax +label.mobile = &Mobil +label.web.page = &Webová Prezentace +label.pager = &Pager +label.first.name = &Jméno +label.middle.name = &PÅ™ostÅ™ední jméno +label.last.name = Pří&jmení +label.email.address = &Emailová Adresa +label.jid = &JID +label.search.service = &Služba hledání +label.xmpp.port = &XMPP Port +label.response.timeout = &Timeout odezvy (sec) +label.time.till.idle = ÄŒ&as do neÄinnosti (min) +label.jabber.id = &Jabber ID +label.group = &Skupina +label.enter.group.name = Zadej nové jméno skupiny +label.network = &Síť +label.unable.to.add.contact = Nemůžu pÅ™idat kontakt. +label.conflict.error = Nemohu se pÅ™ihlásit, protože úÄet je již pÅ™ihlášen. +label.message.style = &Styl Zprávy +label.emoticons = S&majlíci + + +message.confirmation.password.error = Zadej potvrzení hesla. +message.account.error = Zadej server na kterém mám vytvoÅ™it úÄet. +message.registering = Registruji s {0}. Prosím vyÄkejte... +message.connection.failed = Nemohu se pÅ™ipojit k {0}. +message.create.account = ÚÄet nemůže být vytvoÅ™en. +message.already.exists = ÚÄet již existuje. Prosím vyberte si jiné uživatelské jméno. +message.account.created = Nový úÄet byl vytvoÅ™en. +message.account.create = VytvoÅ™it nový chat úÄet. +message.connecting.please.wait = PÅ™ipojuji. Prosím vyÄkejte... +message.supply.valid.timeout = Zadej platnou time out hodnotu. +message.supply.valid.port = Zadej platný port. +message.supply.resource = Zadej platný zdroj. +message.current.status = Povol ostatním vidÄ›t tvůj status a aktivitu. +message.disconnected.error = VaÅ¡e pÅ™ipojení bylo ukonÄeno díky chybÄ›. +message.disconnected.group.chat.error = VaÅ¡e pÅ™ipojení bylo ukonÄeno díky chybÄ›. Budete se muset znovu pÅ™ipojit do místosti po nalogování se. +message.disconnected.conflict.error = VaÅ¡e pÅ™ipojení bylo ukonÄeno díky chybÄ›: Stejný uživatel se pÅ™ihlaÅ¡uje odjinud. +message.locked.workstation = Uživatel si uzamkl pracovní stanici. +message.away.idle = PryÄ díky neÄinnosti. +message.default.error = Chyba byla detekována. Prosím reportujte na support@jivesoftware.com. +message.new.message = Nová zpráva od {0}. +message.send.file.to.user = PoÅ¡li soubory tomuto uživateli. +message.send.picture = ZachyÅ¥te a poÅ¡lete cokoliv co vidíte na obrazovce. +message.sent.offline.files = You have just been sent offline file(s). +message.search.for.contacts = Najít kontakty. +message.end.conversation = PÅ™ejete si ukonÄit tuto relaci? +message.end.chat = PÅ™ejete si ukonÄit tento chat? +message.close.this.chat = Zavřít tento chat +message.close.other.chats = Zavřít vÅ¡echny ostatní chaty +message.close.stale.chats = Zavřít zvÄ›tralé chaty +message.close.unread.window = Máte nepÅ™eÄtené zprávy, opravdu chcete zavřít okno? +message.last.message.received = Poslední zpráva pÅ™ijata v {0} +message.shared.group = Sdílená skupina +message.is.shared.group = {0} je sdílená skupina. +message.delete.confirmation = Opravdu smazat {0}? +message.idle.for = NeÄinný {0} +message.enter.broadcast.message = Zadejte zprávu pro rozeslání vybraným uživatelům. +message.name.of.group = Jméno skupiny +message.approve.subscription = Povolit {0} pÅ™idat si vás do svého seznamu? +message.add.user = PÅ™idat uživatele do seznamu? +message.general.error = Spojení se serverem ztraceno: {0}. +message.add.a.contact = PÅ™idat kontakt. +message.generic.reconnect.message = Spojení se serverem ztraceno. Nalogujte se znovu tlaÄítkem níže. +message.select.one.or.more = Vyberte jednoho nebo více uživatelů ze seznamu. +message.add.conference.service = PÅ™idat službu konference. +message.service.already.exists = Služba uz je ve vaÅ¡em seznamu služeb. +message.searching.please.wait = Hledám. Pockejte prosím... +message.conference.service.error = Nemohu najít konferenÄní službu. +message.create.or.join.room = VytvoÅ™it nebo se pÅ™ipojit do konferenÄní místnosti +message.specify.name.error = Zadej platné jméno. +message.password.private.room.error = Zadej heslo pro privátní místnost +message.passwords.no.match = Hesla se neshodují. +message.enter.valid.jid = Zadej platné Jabber ID +message.please.join.in.conference = Prosím pÅ™ipojte se ke mÄ› v konferenci. +message.invite.users.to.conference = Pozvi uživatele do konferenÄní místnosti. +message.specify.users.to.join.conference = Vyber uživatele co se pÅ™ipojí do této konferenÄní místnosti. +message.no.room.to.join.error = Žádná místnost na pÅ™ipojení se +message.participants.in.room = ÚÄastníci v místnosti +message.you.have.been.kicked = Byl jste vyhozen z této místnosti. +message.kicked.error = Nejste schopen vyhodit {0} z této místnosti. +message.you.have.been.banned = Byl jste vypovÄ›zen z této místnosti. +message.nickname.in.use = PÅ™ezdívka se používá. Prosím vyberte si jinou pÅ™ezdívku +message.update.room.list = Obnovení seznamu místností +message.join.conference.room = PÅ™ipojit se do konferenÄní místnosti +message.select.add.room.to.add = Prosím vyberte místnost na pÅ™idaní do vaÅ¡eho seznamu služeb +message.bookmark.temporary.room.error = DoÄasné místnosti nemohou být v záložkách +message.select.room.to.join = Vyber místnost na pÅ™ipojení se +message.conference.info.error = Nejsem schopen stáhnout informace o konferenci. Prosím zkuste to pozdÄ›ji. +message.add.favorite.room = PÅ™idat místnost do oblíbených nebo pÅ™ipojit přímo. +message.select.room.to.enter = Vyberte místnost pro vstup. +message.find.conference.services = Najít konferenÄní služby +message.specify.information.for.conference = Zadej informace pro konferenÄní místnost. +message.no.description.available = Žádný popis +message.no.subject.available = Žádný pÅ™edmÄ›t +message.room.information.for = Informace o místnosti {0} +message.view.information.about.this.user = Prohlížet informace o tomto uživateli. +message.add.this.user.to.your.roster = PÅ™idat uživatele do vaÅ¡eho kámoÅ¡ seznamu. +message.came.online = {0} je online v {1} +message.went.offline = {0} Å¡el offline v {1} +message.offline.error = Uživatel nebude schopen pÅ™ijmout offline zprávu. +message.offline = Uživatel je offline a dostane vaší zprávu pÅ™i příštím pÅ™ihlášení. +message.is.typing.a.message = {0} píše zprávu... +message.enter.new.subject = Zadej nový pÅ™edmÄ›t +message.confirm.destruction.of.room = ZniÄení místnosti odebere vÅ¡echny uživatele z místosti. PokraÄovat? +message.room.destruction.reason = Důvod pro zniÄení místnosti? +message.user.left.room = {0} odeÅ¡el z místnosti. +message.user.joined.room = {0} pÅ™iÅ¡el do místnosti. +message.chat.session.ended = Chat relace ukonÄena v {0} +message.subject.change.error = Nemáte právo na zmÄ›nu pÅ™edmÄ›tu místnosti. +message.forbidden.error = Dostal jsem chybu ze serveru: Zamítnuto +message.room.destroyed = Tato místnost byla zniÄena s tímto důvodem: {0} +message.subject.has.been.changed.to = PÅ™edmÄ›t byl zmÄ›nÄ›n na {0}. +message.user.kicked.from.room = {0} byl vyhozen z místnosti. +message.user.given.voice = {0} bylo mu povoleno hovoÅ™it v této místnosti. +message.user.voice.revoked = {0} bylo mu zakázáno hovoÅ™it. +message.user.banned = {0} byl vypovÄ›zen z místnosti. +message.user.granted.membership = {0} dostal Älenská práva. +message.user.revoked.membership = ÄŒlenská práva byla odebrána {0}. +message.user.granted.moderator = {0} dostal práva moderátora. +message.user.revoked.moderator = Práva moderátora byla odebrána {0}. +message.user.granted.owner = {0} dostal práva vlastníka. +message.user.revoked.owner = Práva vlastníka byla odebrána {0}. +message.user.granted.admin = {0} dostal práva administrátora. +message.user.revoked.admin = Administrátorská práva byla odebrána {0}. +message.user.nickname.changed = {0} je teÄ znám jako {1}. +message.your.kicked = Byl jste vyhozen od {0}. +message.your.voice.granted = Byl vám umožnÄ›no hovoÅ™it. +message.your.voice.revoked = Bylo vám znemožnÄ›no hovoÅ™it. +message.your.banned = Byl jste banned z této místnosti. +message.your.membership.granted = Byla vám dána Älenská práva. +message.your.membership.revoked = Byla vám odebrána Älenská práva. +message.your.moderator.granted = Byla vám dána práva moderátora. +message.your.moderator.revoked = Byla vám odebrána práva moderátora. +message.your.ownership.granted = Byla vám dána práva vlastníka. +message.your.ownership.revoked = Byla vám odebrána práva vlastníka. +message.your.admin.granted = Byla vám dána práva administrátora. +message.your.revoked.granted = Byla vám odebrána práva administrátora. +message.send.a.broadcast = PoÅ¡li vÅ¡em +message.broadcast.from = Hromadná zpráva od {0} +message.enter.message.to.broadcast = Zadejte zprávu na rozeslání do celého vaÅ¡eho seznamu. +message.broadcast.message.sent = Hromadná zpráva byla poslána. +message.broadcast.to = Zadej zprávu na hromadné zaslání {0} +message.hasbeenbroadcast.to = Zpráva byla rozeslána tÄ›mto uživatelům:\n{0} +message.user.now.available.to.chat = {0} je online v {1} +message.user.is.sending.you.a.file = {0} posílá vám soubor. +message.file.transfer.canceled = ZruÅ¡il jste pÅ™enos souboru. +message.negotiate.file.transfer = Domlouvám pÅ™enos souboru. PoÄkejte prosím... +message.negotiate.stream = Domlouvám ustavení spojení. Prosím poÄkejte... +message.receiving.file = Dostáváte soubor od {0} +message.click.to.open = KliknÄ›te pro otevÅ™ení +message.error.during.file.transfer = PÅ™i pÅ™enosu souborů se vyskytla chyba. +message.transfer.refused = PÅ™enos souborů byl odmítnut. +message.transfer.cancelled = PÅ™enos souborů byl zruÅ¡en. +message.received.file = Dostal jste soubor od {0}. +message.file.exists.question = Soubor již existuje. PÅ™epsat? +message.transfer.waiting.on.user = ÄŒekám na {0} pro potvrzení pÅ™enosu souboru. +message.negotiation.file.transfer = Domlouvám pÅ™enos souboru s {0}. Prosím poÄkejte... +message.unable.to.send.file = Nebyl jste schopen poslat soubor {0}. +message.sending.file.to = Posílám soubor {0}. +message.you.have.sent = Poslal jste soubor {0}. +message.file.transfer.rejected = PÅ™enos souborů nebyl odsouhlasen {0}. +message.disable.transport = Odstranit pÅ™ihlaÅ¡ovací informace z {0}? +message.register.transports = Registrovat s tÄ›mito možnýmy transporty. +message.enter.xmpp = Zadejte svoje XMPP uživatelské jméno a heslo níže. +message.enter.irc = Zadejte svoje IRC uživatelské jméno, heslo a pÅ™ezdívku níže. +message.enter.simple = Zadejte svoje SIMPLE uživatelské jméno a heslo níže. +message.enter.gadugadu = Zadejte svoje GaduGadu uživatelské jméno a heslo níže. +message.username.error = Uživatelské jméno musí být zadáno. +message.password.error = Heslo musí být zadáno. +message.nickname.error = PÅ™ezdívka musí být zadána. +message.username.password.error = Uživatelské jméno a/nebo heslo musí být zadáno. +message.registration.transport.failed = Nemohu vás registrovat s bránou. +message.client.information = Klient informace o {0} +message.calling = Volá {0} +message.number.to.call = Zadejte Äíslo pro vytáÄení +message.no.caller.id = Nemohu zobrazit Äíslo volajícího. +message.no.history.found = Není žádná historie komunikace pro tohoto uživatele. +message.prompt.plugin.uninstall = Jste si jist že chcete odinstalovat {0}? +message.restart.spark.changes = Plugin bude odebrán pÅ™i příštím startu Sparka. +message.loading.please.wait = NaÄítám. Prosím poÄkejte... +message.plugins.not.available = Nemohu se pÅ™ipojit ke skladiÅ¡ti pluginů. +message.downloading = Stahuji {0} +message.downloading.spark.plug = Stahuji Spark-Plug +message.unable.to.save.password = Nemohu zmÄ›nit heslo. Kontaktujte správce vaÅ¡eho serveru. +message.delete.all.history = Smazat vÅ¡echny pÅ™edchozí konverzace? +message.no.avatar.found = Tento uživatel nemá nastaven žádného avatara. +message.image.too.large = Tento obrázek je příliÅ¡ velký. Zadejte obrázek o velikosti 16k nebo menší. +message.save.profile = Pro zapsání zmÄ›n do vaÅ¡eho profilu kliknÄ›te na Uložit. +message.unable.to.load.profile = Nemohu najít profil pro {0} +message.enter.jabber.id = Vložte Jabber ID +message.invalid.jabber.id = Není platné Jabber ID +message.vcard.not.supported = Server nepodporuje VCards. Nemohu uložit vaší VCard. +message.search.service.not.available = Nemohu kontaktovat službu hledání. +message.no.results.found = Server nevrátil žádné výsledky hledání. +message.name.of.search.service.question = Jméno služby hledání? +message.search.for.other.people = Najít ostatní lidi na serveru. +message.specify.valid.time.error = Zadejte platny timeout a port. +message.timeout.error = Timeout musí být 5 vteÅ™in nebo delší. +message.version = Verze: {0} +message.file.size = Velikost souboru: {0} +message.restart.spark = Budete potÅ™ebovat vypnout klienta pro instalaci nové verze. \n Provést teÄ? +message.updating.cancelled = Update byl zruÅ¡en. +message.transfer.rate = Rychlost pÅ™enosu +message.total.downloaded = Celkem staženo +message.new.spark.available = {0} je teÄ dostupná. PÅ™ejete si nainstalovat? +message.restart.spark.to.install = Budete potÅ™ebovat vypnout klienta pro instalaci poslední verze. \n Provést teÄ? +message.add.to.roster = PÅ™idat do seznamu +message.enter.room.password = Zadejte heslo do místnosti +message.add.contact.to.list = PÅ™idat uživatele do vaÅ¡eho senzamu kontaktů +message.authenticating = Autentikace +message.invalid.status = Zadejte platnou zprávu stavu. +message.cannot.add.contact.to.shared.group = Nemůžete pÅ™idávat nové kontakty do sdílene skupiny. +message.specify.contact.jid = Prosím zadejte JID kontaktu (napÅ™. ddman@jabber.org) +message.invalid.jid.error = Zadané JID je neplatné. +message.specify.group = Vyberte skupinu kontaktů pro pÅ™idání nového uživatele. +message.room.creation.error = Místnost nemůže být vytvoÅ™ena. +message.unable.to.retrieve.last.activity = Nemohu zjistit poslední aktivitu od {0}. +message.buzz.alert.notification = Vyvolejte uživatelovu pozornost. +message.buzz.sent = Poslat notifikaci výstrahy uživateli. +message.restart.required = Budete muset restartovat Sparka, aby se vaÅ¡e zmÄ›ny provedly. Restartovat teÄ? +message.send.to.these.people = Poslat tÄ›mto lidem +message.normal = Normlální zpráva +message.alert.notify = Notifikace výstrahy + +title.passwords.no.match = PotvrÄte hesla. +title.create.problem = Problém s vytvoÅ™ením úÄtu +title.account.created = ÚÄet vytvoÅ™en +title.create.new.account = VytvoÅ™it nový úÄet +title.account.create.registration = Registrace úÄtu +title.register.account = Registrovat nový úÄet +title.notification = Notifikace +title.advanced.connection.preferences = Podrobné nastavená pÅ™ipojení +title.preferences = Možnosti +title.error = Chyba +title.status.message = Zpráva statusu +title.spark.preferences = Spark Možnosti +title.alert = Výstraha +title.tray.information = Tray Informace +title.select.file.to.send = Vyberte soubor(y) pro poslání +title.choose.directory = Vyberte složku +title.confirmation = Potvrzení +title.last.activity = Poslední aktivita +title.add.new.group = PÅ™idat novou skupinu +title.add.to.roster = PÅ™idat do seznamu +title.find.contacts = Najít kontakty +title.rename.roster.group = PÅ™ejmenovat skupiny seznamu +title.roster = Seznam +title.create.room = VytvoÅ™it +title.conference.rooms = KonferenÄní místnosti +title.invite.to.conference = PÅ™izvat do konference +title.room.information = Informace o místnosti +title.change.nickname = ZmÄ›nit pÅ™ezdívku +title.group.chat = Skupinový chat +title.create.or.bookmark.room = PÅ™ipojit se nebo Bookmarkovat místnost +title.browse.room.service = Procházet konferenÄní místnosti - {0} +title.name = Jméno +title.address = Adresa +title.occupants = ÚÄastníci +title.browse.conference.services = Procházet konferenÄní služby +title.find.conference.service = Najít konferenÄní službu +title.configure.chat.room = Nastavit chat místnost +title.conference.invitation = Pozvání konference +title.join.conference.room = PÅ™ipojit konferenÄní místnost +title.view.room.information = Prohlédnout informace místnosti +title.configure.room = Nastavit Místnost +title.change.subject = ZmÄ›nit PÅ™edmÄ›t +title.enter.reason = Zadat Důvod +title.room.destroyed = Místnost ZniÄena +title.edit.custom.message = Editovat Osobní Zprávy +title.set.status.message = Nastavit Status Zprávu +title.broadcast.message = HromadnÄ› Rozeslaná Zpráva +title.start.chat = ZaÄít Chat +title.view.bookmarks = Prohlédnout Záložky +title.downloads = Downloady +title.file.exists = Soubor Existuje +title.disable.transport = Odstranit PÅ™ihlaÅ¡ovací Informace +title.available.transports = Dostupné Transporty +title.transports = Trasnporty +title.xmpp.registration = XMPP PÅ™ihlaÅ¡ovací Údaje +title.irc.registration = IRC PÅ™ihlaÅ¡ovací Údaje +title.simple.registration = SIMPLE PÅ™ihlaÅ¡ovací Údaje +title.gadugadu.registration = GaduGadu PÅ™ihlaÅ¡ovací Údaje +title.registration.error = Chyba Registrace +title.jabber.browser = ProhlížeÄ +title.version.and.time = Verze a ÄŒas +title.waiting.to.call = ÄŒekání na uskuteÄnÄ›ní hovoru +title.incoming.call = Příchozí Hovor +title.on.the.phone = Volající +title.dial.phone = VytoÄit Telefon +title.history.for = Historie Konverzace Pro {0} +title.reminder = UpomínaÄ +title.plugins = Pluginy +title.general.chat.settings = Obecné Nastavení Chatu +title.chat = Chat +title.notifications = Notifikace +title.sound.preferences = Možnosti zvuku +title.sounds = Zvuky +title.choose.incoming.sound = Vyberte Příchozí Zvukový Soubor +title.choose.outgoing.sound = Vyberte Odchozí Zvukový Soubor +title.choose.offline.sound = Vyberte Offline Zvukový soubor +title.edit.profile = Editovat Informace Profilu +title.profile.information = Informace Profilu +title.profile.not.found = Profil Nenalezen +title.view.profile.for = Prohlížení Profilu Pro {0} +title.lookup.profile = Vyhledání Profilu +title.add.search.service = PÅ™idat Službu Hledání +title.person.search = Hledání Lidí +title.login.settings = Nastavení PÅ™ihlášení +title.login = PÅ™ihlášení +title.downloading.im.client = Stáhnout IM Klienta +title.upgrading.client = Upgraduji Klienta +title.cancelled = ZruÅ¡eno +title.new.version.available = Dostupná Nová Verze +title.new.client.available = Dostupný Nový Klient +title.password = Heslo +title.download.complete = Stahování DokonÄeno +title.new.roster.group = Nová Skupina Seznamu +title.add.contact.group = PÅ™idat Skupinu Kontaktů +title.add.contact = PÅ™idat Kontakt +title.file.transfer.preferences = Možnosti PÅ™enosu Souboru +title.file.transfer = PÅ™enos Souboru + +menuitem.connect = Soubor +menuitem.contacts = Kontakty +menuitem.actions = Akce +menuitem.exit = Konec +menuitem.plugins = Pluginy +menuitem.logout.no.status = Odhlásit se +menuitem.logout.with.status = Odhlásit se s důvodem +menuitem.show.traffic = Ukázat Okno Síťového Provozu +menuitem.check.for.updates = Zkontrolovat Updaty +menuitem.help = NápovÄ›da +menuitem.preferences = Možnosti +menuitem.about = O nás +menuitem.online.help = Spark Forums +menuitem.user.guide = Uživatelská PříruÄka +menuitem.open = Otevřít +menuitem.hide = Schovat +menuitem.status = Status +menuitem.view.downloads = Prohlédnout Downloady +menuitem.save = Uložit +menuitem.add = PÅ™idat +menuitem.add.contact = PÅ™idat Kontakt +menuitem.add.contact.group = PÅ™idat Skupinu Kontaktů +menuitem.remove.from.group = Odebrat Ze Skupiny +menuitem.start.a.chat = ZaÄít Chat +menuitem.rename = PÅ™ejmenovat +menuitem.delete = Smazat +menuitem.edit = Upravit +menuitem.remove.from.roster = Odebrat ze Seznamu +menuitem.view.profile = Prohlédnout Profil +menuitem.subscribe.to = Odebírat +menuitem.send.a.message = Poslat hromadnou zpávu vybraným uživatelům... +menuitem.show.empty.groups = Ukázat Prázdné Skupiny +menuitem.send.a.file = Poslat Soubor +menuitem.view.last.activity = Prohlédnout Poslední Aktivitu +menuitem.unban = Unban +menuitem.ban = Ban +menuitem.browse.service = Procházet Služby +menuitem.remove.service = Odebrat Službu +menuitem.join.room = PÅ™ipojit Místnost +menuitem.remove.bookmark = Odebrat Záložku +menuitem.join.on.startup = PÅ™ipojit PÅ™i Startu +menuitem.view.room.info = Prohlédnout Informace o Místnosti +menuitem.remove = Odebrat +menuitem.change.nickname = ZmÄ›nit PÅ™ezdívku +menuitem.block.user = Blokovat Uživatele +menuitem.unblock.user = Odblokovat Uživatele +menuitem.kick.user = Vyhodit Uživatele +menuitem.voice = Hlas +menuitem.revoke.voice = Odebrat Hlas +menuitem.grant.voice = Dát Hlas +menuitem.ban.user = Ban Uživatele +menuitem.grant.moderator = Dát Moderátora +menuitem.revoke.moderator = Odebrat Moderátora +menuitem.invite.users = Pozvat Uživatele +menuitem.invite.group.to.conference = Pozvat skupinu do konference +menuitem.start.a.conference = ZaÄít konferenci... +menuitem.change.subject = ZmÄ›nit PÅ™edmÄ›t +menuitem.destroy.room = ZniÄit Místnost +menuitem.set.status.message = Nastavit status zprávu... +menuitem.edit.status.message = Editovat osobní status zprávu... +menuitem.broadcast.to.group = HromadnÄ› zaslat zprávu skupinÄ› +menuitem.alert.when.online = Varovat když je uživatel dostupný +menuitem.remove.alert.when.online = Odebrat Varování +menuitem.save.as = Uložit jako... +menuitem.view.client.version = Zobrazit Verzi Klienta +menuitem.view.contact.history = Zobrazit Historii Kontaktu +menuitem.edit.my.profile = &Upravit Můj Profil... +menuitem.lookup.profile = &Vyhledat Profil... +menuitem.add.as.contact = PÅ™idat jako kontakt +menuitem.chat = Chat +menuitem.sign.in = Zapsat se +menuitem.sign.out = Odepsat se +menuitem.sign.in.at.login = Zapsat se pÅ™i pÅ™ihlášení +menuitem.enter.login.information = Zadejte pÅ™ihlaÅ¡ovací informace +menuitem.delete.login.information = Smazat pÅ™ihlaÅ¡ovací informace +menuitem.show.offline.group = Skupina uživatelů offline +menuitem.move.to = PÅ™esunout do +menuitem.copy.to = Kopírovat do +menuitem.languages = Jazyky + +tree.conference.services = KonferenÄní Služby +tree.users.in.room = Uživatelé V Místnosti + +tab.general = Obecné +tab.proxy = Proxy +tab.contacts = Kontakty +tab.installed.plugins = Instalované Pluginy +tab.available.plugins = Dostupné Pluginy +tab.personal = Osobní +tab.business = Obchodní +tab.home = Domácí +tab.avatar = Avatar +tab.conferences = Konference + +group.connection = PÅ™ipojení +group.conferences.found = KonferenÄní Služby Nalezeny +group.comma.delimited = OddÄ›lené Čárkou +group.general.information = Obecné Informace +group.chat.window.information = Informace Chat Okna +group.notification.options = Možnosti Notifikací +group.search.form = Vyhledávací Formulář +group.search.results = Výsledky Vyhledávání +group.login.information = PÅ™ihlaÅ¡ovací Informace + +tooltip.place.a.call = Zavolejte tomuto ÄlovÄ›ku +tooltip.view.history = Zobrazit historii konverzace +tooltip.view.changelog = Zopbrazit Change Log +tooltip.view.readme = Zobrazit ÄŒti mÄ› +tooltip.notifications = Nastavení upozorňování na příchozí chaty. +tooltip.place.voice.call = Telefonovat. diff --git a/core/src/main/resources/i18n/spark_i18n_de.properties b/core/src/main/resources/i18n/spark_i18n_de.properties new file mode 100644 index 000000000..0831368ec --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_de.properties @@ -0,0 +1,851 @@ +accept = Akzeptieren +is.active = Aktiv +add = Hinzufügen +administrator = Administrator +apply = Übernehmen +available = Anwesend +broadcast = Rundnachricht +cancel = Abbrechen +close = Schließen +create = Erstellen +date = Datum +description = Beschreibung +from = Von +invite = Einladen +join = Beitreten +no = Nein +not.registered = Nicht registriert +occupants = Teilnehmer +offline = Offline +online = Online +ok = Ok +open = Öffnen +open.folder = Verzeichnis öffnen +participants = Teilnehmer +refresh = Aktualisieren +reject = Zurückweisen +retry = Wiederholen +room.name = Raumname +save = Speichern +subject = Thema +unfiled = Nicht kategorisiert +use.default = Voreinstellungen laden +user.has.signed.in = hat sich eingeloggt. +user.has.signed.off = hat sich ausgeloggt. +while.offline = Während offline +yes = Ja + +action.clear = Löschen +action.copy = Kopieren +action.cut = Ausschneiden +action.paste = Einfügen +action.print = Drucken +action.save = Speichern +action.select.all = Alles auswählen + +button.accept = &Akzeptieren +button.add = &Hinzufügen +button.add.a.contact = &Kontakt hinzufügen +button.add.bookmark = Lesezeichen hinzufügen +button.add.service = &Hinzufügen +button.add.user = &Hinzufügen +button.add2 = Hinzufügen +button.advanced = &Erweitert +button.approve = &Annehmen +button.bookmark.room = &Raum als Lesezeichen setzen +button.browse = &Anzeigen... +button.browse2 = A&nzeigen... +button.browse3 = An&zeigen... +button.cancel = &Abbrechen +button.clear = &Löschen +button.close = Schließen +button.copy.to.clipboard = In Zwischenablage kopieren +button.create.account = &Konto erstellen +button.create.room = &Raum erstellen oder beitreten +button.decline = &Ablehnen +button.deny = &Verweigern +button.dial.number = &Nummer wählen +button.find = &Finden +button.join = &Beitreten +button.join.room = &Ausgewählten Raum betreten +button.login = &Login +button.new = &Neu +button.profile = &Profil +button.quit = Beenden +button.re.detect = Wiede&rerkennen +button.reconnect = &Verbindung wiederherstellen +button.reconnect2 = Wiederverbinden +button.refresh = &Aktualisieren +button.register = &Registrierung +button.reject = Ablehnen +button.remove.bookmark = Lesezeichen löschen +button.roster = &Kontaktliste +button.save = &Speichern +button.save.for.future.use = Für spätere Verwendung &speichern +button.search = &Suchen +button.send = Senden +button.send.email = E-Mail +button.start.chat = Chat +button.tasks.active = Aktiv +button.tasks.all = Alles +button.unset.file.explorer = entferne gespeicherten Dateibrowser +button.update = &Aktualisieren +button.view.notes = Notizen anzeigen +button.view.profile = Gesamtes Profil anzeigen +button.view.tasklist = Aufgabenliste anzeigen + +checkbox.allow.buzz = "&Buzzer"-Funktion aktivieren.checkbox.save.password = Pass&wort speichern +checkbox.auto.discover.port = &Host und Port automatisch bestimmen +checkbox.auto.login = &Automatische Anmeldung +checkbox.login.as.invisible = Unsichtbar anme&lden +checkbox.disable.chat.history = &Den Chatverlauf nicht speichern +checkbox.sort.asc.history = Nachrichten in Kontaktverlauf aufsteigend nach Datum sortieren +checkbox.disable.prev.chat.history = Die letzte &Unterhaltung nicht anzeigen +checkbox.enable.emoticons = &Emoticons aktivieren +checkbox.graying.out = Nichtstuende Kontakte ausgrauen (benötigt Neustart von Spark) +checkbox.idle.enabled = &Automatisches 'Away' bei Inaktivität aktivieren +checkbox.launch.on.startup = &Spark bei Systemstart ausführen +checkbox.reconnect.info = Art des Wiederverbindens: +checkbox.reconnect.panel.big = Zeige ein Panel +checkbox.reconnect.panel.small = Zeige eine Gruppe +checkbox.reconnect.panel.icon = Zeige ein Icon +checkbox.notify.user.comes.online = &Benachrichtigen, wenn ein User online kommt +checkbox.notify.user.goes.offline = Benachrichtigen, wenn ein &User offline geht +checkbox.notify.typing.systemtray = Zeige &Schreibhinweise im System-Tray +checkbox.notify.systemtray = Zeige &neue Nachrichten im System-Tray +checkbox.permanent = Raum ist &permanent Online +checkbox.play.sound.on.invitation = Klang abspielen bei Eintreffen einer &Konferenzeinladung +checkbox.play.sound.on.new.message = Klang abspielen, wenn eine neue &Nachricht eintrifft +checkbox.play.sound.on.outgoing.message = &Klang abspielen, wenn Nachricht ge&sendet wird +checkbox.play.sound.when.offline = Klang abspielen, wenn ein &Teilnehmer &offline geht +checkbox.private.room = Raum &ist privat +checkbox.save.password = Pass&wort speichern +checkbox.show.avatars.in.contactlist = &Zeige Avatare in der Kontaktliste +checkbox.show.notifications.in.conference = &Anzeigen von Benachrichtigungen in Konferenzräumen +checkbox.show.time.in.chat.window = &Zeit im Chatfenster anzeigen +checkbox.show.toaster = Informationen in einem &Popup anzeigen +checkbox.disable.asterisk.toaster = Popups von Anrufen deaktivieren +checkbox.split.chat.window = &Fenster 'andocken' (benötigt Neustart von Spark) +checkbox.start.in.tray = Spark automatisch in der &Taskleiste starten +checkbox.click.single.tray = &Einfachen Klick im System Tray verwenden, um Spark in den Vordergrund zu bringen (benötigt Neustart von Spark) +checkbox.tabs.on.top = &Chat-Tabs oben anzeigen (benötigt Neustart von Spark) +checkbox.tabs.scroll = Scrollen für Chat-Tabs verwenden (benötigt Neustart von Spark) +checkbox.use.compression = Komprimierung verwenden +checkbox.use.debugger.on.startup = Debugger beim Starten öffnen +checkbox.use.proxy.server = &Proxy-Server benutzen +checkbox.use.system.look.and.feel = System-Look-And-&Feel verwenden (benötigt Neustart von Spark) +checkbox.window.to.front = &Fenster in den Vordergrund bringen +checkbox.broadcast.hide.offline.user = Offline User ausblenden +checkbox.use.krbconf = krb5.conf oder krb5.ini verwenden +checkbox.use.krb.dns = DNS verwenden +checkbox.use.specify.below = Unten angeben +checkbox.use.pki.authentication = PKI-Authentifizierung verwenden +checkbox.transport.tab.setting = Verfügbare Transports in einem Tab an anzeigen (benötigt Neustart von Spark) +checkbox.conference.tab.setting = Konferenzreiter anzeigen (benötigt Neustart von Spark) +checkbox.use.hostname.as.resource = Hostnamen als Ressource verwenden +checkbox.use.version.as.resource = Spark-Version als Ressource verwenden +checkbox.close.unread.message =Beim Schließen des Fensters fragen, ob ungelesene Nachrichten vorhanden sind + +delete.log.permanently = Protokolle permanent löschen +delete.permanently = Permanent löschen? + +gateway.username.password.error = Benutzername und/oder Passwort muss eingetragen sein + +group.chat.window.information = Chatfenster-Informationen +group.comma.delimited = Komma separiert +group.conferences.found = Konferenzen gefunden +group.connection = Verbindung +group.empty = Keine Offline-User in dieser Gruppe +group.general.information = Allgemeine Informationen +group.login.information = Anmeldeinformationen +group.notification.options = Optionen zur Benachrichtigung +group.offline = Offline-Gruppe +group.search.form = Suchformular +group.search.results = Suchergebnisse +group.chat.name.notification = Deinen Nick gesehen... +group.chat.name.match = Dein Name wurde im Gruppenchat erwähnt: + +label.na = n/a +label.cell = &Mobil +label.work = &Geschäftlich +label.home = &Privat +label.accounts = &Konten +label.passwordreset = Passwort zurücksetzen +label.add.conference.service = Dien&st für Konferenzen hinzufügen +label.add.jid = &JID hinzufügen +label.add.task = Aufgabe hinzufügen +label.auto.login = &Automatische Anmeldung +label.available.users.in.roster = &Verfügbare Teilnehmer in der Kontaktliste +label.avatar = Avatar: +label.cancel = Abbrechen +label.change.password.to = &Neues Passwort eingeben +label.chatroom.fontsize = &Chatraum-Schriftgröße: +label.chatroom.maxcurrenthistorysize = Maximale Größe des aktuellen Verlaufs: +label.city = Sta&dt +label.close = &Schließen +label.company = &Firma +label.confirm.password = Neues Passwort &wiederholen +label.conflict.error = Benutzer ist bereits angemeldet. Anmeldung wird verweigert. +label.contact.to.find = Kontakt finden +label.recent.conversation = Kürzliche Konversationen +label.frequent.contacts = Meistgenutzte Kontakte +label.contactlist.avatarsize = Kontaktliste-&Avatargröße: +label.contactlist.fontsize = Kontaktliste-&Schriftgröße: +label.country = &Land +label.create.account = &Konto erstellen +label.department = &Abteilung +label.dial = &Wählen +label.display.time = Anzeigedauer: +label.downloads = Downloads +label.due = Due +label.email.address = &E-Mail-Adresse +label.emoticons = E&moticons +label.enter.address = Adresse eingeben +label.enter.group.name = Namen für neue Gruppe eingeben +label.fax = Fa&x +label.find = &Finden +label.first.name = &Vorname +label.group = &Gruppe +label.host = &Host +label.invited.users = Eingeladene Teilnehmer +label.jabber.address = &Jabber-Adresse +label.jabber.id = &Jabber-ID +label.jid = &JID +label.job.title = &Beruf +label.last.name = &Nachname +label.local.time = &Lokale Zeit +label.message = &Nachricht +label.message.style = &Nachrichtenstil +label.middle.name = &Zweiter Vorname +label.minutes.before.stale.chat = &Ein Chatfenster als 'inaktiv' kennzeichnen nach (min) +label.mobile = &Mobil +label.name = &Name +label.network = Netzwerk +label.new.nickname = Neuer angezeigter Name +label.nickname = &Angezeigter Name +label.number = &Nummer +label.ok = OK +label.old.ssl = ALTE SSL-Port-Methode &verwenden +label.os = &Betriebssystem +label.pager = Pa&ger +label.password = &Passwort +label.phone = &Telefon +label.port = &Port +label.postal.code = &Postleitzahl +label.presence = S&tatus +label.priority = P&riorität +label.protocol = &Protokoll +label.received = Empfangen +label.rename.to = Umbenennen zu +label.resource = &Ressource +label.response.timeout = &Zeitspanne bis zum Abbruch (sek) +label.room = &Raum +label.room.name = &Raumname +label.room.topic = Raum&thema +label.search = Suchen +label.search.service = &Suchdienst +label.seconds = Sekunden +label.server = Do&main +label.server.address = &Serveradresse +label.show = Zeigen: +label.software = &Software +label.state.and.province = Staat/&Region +label.street.address = &Straße +label.time = Zeit: {0} +label.time.till.idle = Zeitspanne für automatisches 'Away' bei &Inaktivität (min) +label.time.till.idlemessage = Stat&usnachricht für automatisches 'Away' +label.timeformat = {0} verwenden +label.transfer.download.directory = &Download-Verzeichnis: +label.transfer.timeout = &Zeitspanne bis zum Abbruch des Transfers (min): +label.unable.to.add.contact = Kann Kontakt nicht hinzufügen. +label.use.default = Standard nutzen +label.user.on.public.network = Teilnehmer befindet sich in einem öffentlichen Netzwerk +label.username = &Benutzername +label.version = &Version +label.web.page = &Internetseite +label.xmpp.port = &XMPP-Port +label.krb.realm = Realm +label.krb.kdc = KDC +label.which.pki.method = Welche PKI-Methode? +label.choose.file = Datei auswählen +label.trust.store.password = Trust-Store-Passwort +label.enter.password = Password eingeben +label.move.focus.forwards = Fokus nach vorne verschieben +label.move.focus.backwards = Fokus nach hinten verschieben +label.keystore.location = Keystore-Pfad +label.truststore.location = Truststore-Pfad +label.pkcs.library.file = PKCS11-Bibliotheksdatei +label.x509.certificate = X.509-Zertifikat +label.apple.keychain = Apple-KeyChain +label.add.to.roster = Benutzer zur Kontaktliste hinzufügen +label.audio.device = &Audiogerät +label.video.device = &Videogerät + +menuitem.about = Über +menuitem.actions = Aktionen +menuitem.bookmarks = Lesezeichen +menuitem.add = Hinzufügen +menuitem.add.as.contact = Als Kontakt hinzufügen +menuitem.add.contact = Kontakt hinzufügen +menuitem.add.contact.group = Kontaktgruppe hinzufügen +menuitem.add.groupchat.myname = Meinen &Namen hervorheben, wenn ihn jemand schreibt +menuitem.add.groupchat.mytext = Meinen &Text hervorheben, wenn ich etwas schreibe +menuitem.add.groupchat.popname = Popup an&zeigen, wenn jemand meinen Namen schreibt +menuitem.add.groupchat.showjoinleavemessage = Anzeigen, wenn jemand den &Raum betritt oder verlässt +menuitem.add.groupchat.showrolesinsteadofstatus = &Chatrechtsymbole anstelle von Statussymbolen anzeigen +menuitem.add.groupchat.auto.accept.invite = &Konferenzeinladungen automatisch akzeptieren +menuitem.add.groupchat.random.colors = Namen mit zufälligen &Farben anzeigen +menuitem.always.on.top = Immer im Vordergrund +menuitem.alert.when.online = Benachrichtigen, wenn Teilnehmer verfügbar +menuitem.ban = Verbannen +menuitem.ban.user = Teilnehmer sperren +menuitem.block.user = Teilnehmer blockieren +menuitem.broadcast.to.group = Rundnachricht an Gruppe +menuitem.browse.service = Dienste anzeigen +menuitem.change.nickname = Angezeigten Namen ändern +menuitem.change.subject = Konferenzthema ändern +menuitem.chat = Chat +menuitem.check.for.updates = Ist eine neuere &Version verfügbar? +menuitem.connect = Datei +menuitem.contacts = Kontakte +menuitem.copy.to = Kopieren nach +menuitem.delete = Löschen +menuitem.delete.login.information = Anmeldeinformationen löschen +menuitem.destroy.room = Raum löschen +menuitem.dial = Wählen +menuitem.edit = Ändern +menuitem.edit.my.profile = &Profil ändern... +menuitem.edit.status.message = Statusnachrichten ändern... +menuitem.enter.login.information = Anmeldeinformationen eingeben +menuitem.exit = Beenden +menuitem.affiliation = Raumassoziierung +menuitem.grant.moderator = Moderatorenstatus geben +menuitem.grant.member = Mitgliedsstatus geben +menuitem.grant.admin = Adminstatus geben +menuitem.grant.owner = Besitzerstatus geben +menuitem.grant.voice = Schreibrecht geben +menuitem.help = &Hilfe +menuitem.hide = Minimieren +menuitem.invite.group.to.conference = Gruppe zu einer Konferenz einladen +menuitem.invite.users = Teilnehmer einladen +menuitem.join.on.startup = Beim Starten beitreten +menuitem.join.room = Raum beitreten +menuitem.kick.user = Teilnehmer rauswerfen +menuitem.languages = Sprachen +menuitem.logout.no.status = Abmelden +menuitem.logout.with.status = Abmelden mit Nachricht +menuitem.lookup.profile = &Profil suchen... +menuitem.move.to = Verschieben nach +menuitem.online.help = Online-Hilfe +menuitem.open = Öffnen +menuitem.open.with = Öffnen mit... +menuitem.plugins = Plugins +menuitem.preferences = Einstellungen +menuitem.remove = Entfernen +menuitem.remove.alert.when.online = Benachrichtigung entfernen +menuitem.remove.bookmark = Lesezeichen entfernen +menuitem.remove.from.group = Aus dieser Gruppe entfernen +menuitem.remove.from.roster = Von Kontaktliste entfernen +menuitem.block.contact = Kontakt auf akueller Liste blockieren +menuitem.unblock.contact = Blockierung eines Kontaktes aufheben +menuitem.remove.service = Dienst entfernen +menuitem.rename = Umbenennen +menuitem.revoke.moderator = Moderatorenstatus widerrufen +menuitem.revoke.voice = Schreibrecht entziehen +menuitem.revoke.member = Mitgliedsstatus widerrufen +menuitem.revoke.admin = Adminstatus widerrufen +menuitem.revoke.owner = Besitzerstatus widerrufen +menuitem.save = Speichern +menuitem.save.as = Speichern als... +menuitem.send.a.file = Datei senden +menuitem.send.a.message = Nachricht senden... +menuitem.set.status.message = Statusnachricht setzen... +menuitem.show.empty.groups = Leere Gruppen anzeigen +menuitem.show.offline.group = Offline-Benutzer gruppieren +menuitem.show.traffic = Verbindungsdaten +menuitem.sign.in = Anmelden +menuitem.sign.in.at.login = Anmeldung während der Benutzerabfrage +menuitem.sign.out = Abmelden +menuitem.start.a.chat = Chat starten +menuitem.start.a.conference = Eine Konferenz starten... +menuitem.status = Status +menuitem.subscribe.to = Kontaktanfrage senden +menuitem.unban = Teilnehmer entsperren +menuitem.unblock.user = Blockierung auf aktueller Liste aufheben +menuitem.user.guide = Benutzerhandbuch +menuitem.view.client.version = Programmversion anzeigen +menuitem.view.contact.history = Kontaktverlauf anzeigen +menuitem.view.downloads = Downloads anzeigen +menuitem.view.last.activity = Letzte Aktivität anzeigen +menuitem.view.logs = Protokolle anzeigen +menuitem.view.profile = Profil anzeigen +menuitem.view.room.info = Rauminformationen anzeigen +menuitem.voice = Schreibrecht +menuitem.show.offline.users = Offline-Benutzer anzeigen +menuitem.show.contact.statusmessage = Statusnachricht anzeigen +menuitem.bookmark.room = Raum als Lesezeichen setzen +menuitem.refresh = Aktualisieren +menuitem.create.room = Raum erstellen oder beitreten +menuitem.expand.all.groups = Alle Gruppen öffnen +menuitem.collapse.all.groups = Alle Gruppen schließen +menuitem.invite.again = Nochmals einladen +menuitem.chatframe.option = Einstellungen +menuitem.add.groupchat.invitetobookmark = Benutzer automatisch zu Raum aus den Lesezeichen einladen + +message.username.error = Wählen Sie einen Benutzernamen für dieses Konto aus. +message.password.error = Wählen Sie ein Passwort für dieses Konto aus. +message.confirmation.password.error = Wiederholen Sie das Passwort. +message.account.error = Server, auf dem das Konto erstellt werden soll. +message.registering = Registrierung mit {0}. Bitte warten... +message.connection.failed = Es konnte keine Verbindung zu {0} hergestellt werden. +message.create.account = Konto konnte nicht erstellt werden. +message.already.exists = Konto ist bereits angelegt. Bitte einen anderen Benutzernamen auswählen. +message.account.created = Das Konto wurde erstellt. +message.account.create = Ein neues Chatkonto erstellen. +message.connecting.please.wait = Verbinde - Bitte warten... +message.supply.valid.timeout = Bitte einen korrekten Wert eingeben. +message.supply.valid.port = Bitte einen korrekten Port eingeben. +message.supply.resource = Bitte die korrekte Ressource eingeben. +message.current.status = Andere Teilnehmer können meinen Status einsehen. +message.disconnected.error = Die Verbindung wurde aufgrund eines Fehlers abgebrochen. +message.disconnected.group.chat.error = Die Verbindung wurde wegen eines Fehlers unterbrochen. Spark wird diesen Chatraum automatisch betreten, wenn die Verbindung wieder hergestellt wurde. +message.disconnected.conflict.error = Die Verbindung wurde abgebrochen, da mit ihren Zugangsdaten ein weiteres Login registriert wurde. +message.locked.workstation = Computer gesperrt +message.away.idle = Abwesend +message.default.error = Ein Fehler wurde erkannt. Bitte schicken Sie eine Fehlerbeschreibung an support@jivesoftware.com. +message.new.message = Neue Nachricht von {0}. +message.send.file.to.user = Dateien an diesen Teilnehmer senden. +message.send.picture = Bildschirminhalt versenden. +message.sent.offline.files = Sie haben offline Dateien gesendet. +message.search.for.contacts = Nach Kontakten suchen. +message.search.input.short = Bitte geben Sie mehr als ein Zeichen ein. +message.end.conversation = Soll diese Sitzung beendet werden? +message.end.chat = Soll dieser Chat beendet werden? +message.close.this.chat = Diesen Chat schließen +message.close.other.chats = Alle anderen Chats schließen +message.close.stale.chats = Inaktive Chats schließen +message.close.unread.window = Sie haben ungelesene Nachrichten, möchten Sie das Fenster wirklich schließen? +message.last.message.received = Letzte Nachricht empfangen um {0} +message.shared.group = Gemeinsame Gruppen +message.is.shared.group = {0} ist eine gemeinsame Gruppe. +message.delete.confirmation = {0} - Wirklich löschen? +message.idle.for = Inaktiv seit {0} +message.enter.broadcast.message = Nachricht eingeben zur Weiterleitung an die ausgewählten Benutzer. +message.name.of.group = Name der Gruppe +message.approve.subscription = Wollen Sie {0} erlauben ihren Kontakt der Kontaktliste hinzuzufügen? +message.add.user = Teilnehmer der Kontaktliste hinzufügen? +message.general.error = Die Verbindung zum Server wurde abgebrochen wegen {0}. +message.add.a.contact = Kontakt hinzufügen +message.generic.reconnect.message = Die Verbindung zum Server ist abgebrochen. Für eine erneute Verbindung bitte auf die Schaltfläche Verbindung wiederherstellen klicken. +message.select.one.or.more = Wählen Sie einen oder mehrere Teilnehmer aus. +message.add.conference.service = Eine Konferenz hinzufügen. +message.service.already.exists = Dieser Dienst ist bereits in der Liste vorhanden. +message.searching.please.wait = Suche läuft. Bitte warten... +message.conference.service.error = Der Konferenzdienst konnte nicht gefunden werden. +message.create.or.join.room = Konferenz erstellen oder einer bestehen beitreten +message.specify.name.error = Bitte einen erlaubten Namen auswählen. +message.password.private.room.error = Bitte ein Passwort für diesen Raum auswählen +message.passwords.no.match = Passwörter stimmen nicht überein. +message.enter.valid.jid = Bitte eine korrekte Jabber-ID eingeben +message.please.join.in.conference = Bitte treten Sie dieser Konferenz bei. +message.invite.users.to.conference = Teilnehmer zu einer Konferenz einladen. +message.specify.users.to.join.conference = Teilnehmer auswählen die diesem Raum beitreten sollen. +message.no.room.to.join.error = Kein Raum zum Beitreten vorhanden +message.participants.in.room = Teilnehmer im Raum +message.you.have.been.kicked = Sie wurden aus dem Raum ausgeladen. +message.kicked.error = Sie haben nicht das Recht {0} aus dem Raum auszuladen. +message.you.have.been.banned = Der Zugriff auf diesem Raum wurde Ihnen entzogen. +message.nickname.in.use = Ausgewählter Name wird bereits verwendet. Bitte einen anderen Namen auswählen. +message.nickname.not.acceptable = Das Ändern des Spitznamens ist nicht erlaubt! +message.update.room.list = Raumliste aktualisieren +message.join.conference.room = Konferenz beitreten +message.select.add.room.to.add = Bitte einen Raum auswählen, um ihn der Dienstliste hinzuzufügen. +message.bookmark.temporary.room.error = Temporäre Räume können nicht in die Lesezeichen aufgenommen werden. +message.select.room.to.join = Wählen Sie einen Raum aus, dem Sie Beitreten möchten. +message.conference.info.error = Konnte keine Informationen zu dieser Konferenz erhalten. Bitte versuchen Sie es später noch einmal. +message.add.favorite.room = Raum zu den Lesezeichen hinzufügen oder direkt betreten. +message.select.room.to.enter = Wählen Sie einen Raum aus. +message.find.conference.services = Konferenzen suchen +message.specify.information.for.conference = Bitte Informationen zu dieser Konferenz eingeben. +message.no.description.available = Keine Beschreibung verfügbar +message.no.subject.available = Kein Konferenzthema verfügbar +message.room.information.for = Rauminformation für {0} +message.view.information.about.this.user = Informationen über diesen Teilnehmer anzeigen. +message.add.this.user.to.your.roster = Diesen Teilnehmer zu meiner Kontaktliste hinzufügen. +message.came.online = {0} ist online seit {1} +message.went.offline = {0} ist offline seit {1} +message.offline.error = Der Teilnehmer kann keine Offline-Nachrichten empfangen. +message.offline = Der Teilnehmer ist offline und wird die Nachricht nach seinem nächsten Login erhalten. +message.is.typing.a.message = {0} schreibt eine Nachricht... +message.enter.new.subject = Neues Konferenzthema eingeben +message.confirm.destruction.of.room = Raum löschen und alle Teilnehmer aus diesem Raum entfernen. Fortfahren? +message.room.destruction.reason = Grund für das Löschen dieses Raumes? +message.user.left.room = {0} hat den Raum verlassen. +message.user.joined.room = {0} hat den Raum betreten. +message.chat.session.ended = Chatsitzung wurde beendet um {0} +message.subject.change.error = Sie haben keine Rechte das Konferenzthema in diesem Raum zu ändern. +message.forbidden.error = Sie haben nicht die Rechte für diese Aktion. +message.room.destroyed = Dieser Raum wurde aus dem folgenden Grund gelöscht: {0} +message.subject.has.been.changed.to = Das Thema der Konferenz wurde von {1} in "{0}" geändert. +message.user.kicked.from.room = {0} wurde von {1} aus dem Raum geworfen. Grund: {2} +message.user.given.voice = {0} hat jetzt Schreibenrechte. +message.user.voice.revoked = Schreibrechte wurde {0} entzogen. +message.user.banned = {0} wurde für diesen Raum gesperrt. Grund: {2} +message.user.granted.membership = {0} ist jetzt Mitglied. +message.user.revoked.membership = Mitgliedschaft für {0} wurde widerufen. +message.user.granted.moderator = {0} ist jetzt Moderator. +message.user.revoked.moderator = Moderatorrechte wurden {0} entzogen. +message.user.granted.owner = {0} ist jetzt Besitzer. +message.user.revoked.owner = Besitzerrechte wurden {0} entzogen. +message.user.granted.admin = {0} ist jetzt Administrator. +message.user.revoked.admin = Administratorrechte wurden {0} entzogen. +message.user.nickname.changed = {0} nennt sich jetzt {1}. +message.your.kicked = Sie wurden von {0} ausgeladen. +message.your.voice.revoked = Das Schreibrecht wurde Ihnen entzogen. +message.your.banned = Sie sind für diesen Raum gesperrt. +message.your.membership.granted = Sie sind jetzt Mitglied. +message.your.membership.revoked = Ihre Mitgliedschaft wurde widerufen. +message.your.moderator.granted = Sie haben jetzt Moderatorenrechte. +message.your.moderator.revoked = Ihre Moderatorrechte wurden widerufen. +message.your.ownership.granted = Sie sind jetzt Besitzer. +message.your.ownership.revoked = Ihre Besitzerrechte wurden widerufen. +message.your.admin.granted = Sie sind jetzt Administrator. +message.your.revoked.granted = Ihre Administratorenrechte wurden widerufen. +message.send.a.broadcast = Rundnachricht senden +message.broadcast.from = Rundnachricht von {0} +message.broadcast.no.user.selected = Bitte mindestens einen Empfänger auswählen +message.broadcast.no.text = Bitte Text für die Rundnachricht eingeben +message.enter.message.to.broadcast = Eine Nachricht an alle Teilnehmer Ihrer Kontaktliste senden. +message.broadcast.message.sent = Die Rundnachricht wurde versendet. +message.broadcast.to = Eine Rundnachricht eingeben für {0} +message.hasbeenbroadcast.to = Die Nachricht wurde gesendet an:\n{0} +message.user.now.available.to.chat = {0} ist online seit {1} +message.user.is.sending.you.a.file = {0} sendet Ihnen eine Datei. +message.file.transfer.canceled = Sie haben den Dateitransfer abgebrochen. +message.file.transfer.dirnull = Das Download-Verzeichnis für den Dateitransfer wurde nicht festgelegt +message.file.transfer.nodir = Das Download-Verzeichnis für den Dateitransfer wurde nicht gefunden +message.file.transfer.cantwritedir = Sie haben keine ausreichenden Schreibrechte auf dem Download-Verzeichnis +message.file.transfer.direrror.setdir = Bitte klicken Sie hier, um den Download-Pfad neu festzulegen +message.negotiate.file.transfer = Dateitransfer wird vorbereitet. Bitte warten... +message.negotiate.stream = Verbindungsdaten werden vorbereitet. Bitte warten... +message.receiving.file = Sie haben eine Datei von {0} erhalten +message.received.file = Sie haben eine Datei von {0} erhalten. +message.click.to.open = Öffnen +message.error.during.file.transfer = Während des Dateitransfers ist ein Fehler aufgetreten. +message.transfer.refused = Der Dateitransfer wurde verweigert. +message.transfer.cancelled = Der Dateitransfer wurde abgebrochen. +message.transfer.complete = Der Dateitransfer war erfolgreich ({0}) +message.transfer.progressbar.text.received = {0} empfangen @ {1} {2} +message.transfer.progressbar.text.sent = {0} gesendet @ {1} {2} +message.file.transfer.file.too.big.error = Die ausgewählte Datei ist zu groß.\nEs dürfen maximal {0} versandt werden, die ausgewählte Datei hat {1} +message.file.transfer.file.too.big.warning = Die ausgewählte Datei ist zu groß.\nDennoch fortfahren? +message.file.exists.question = Die Datei existiert bereits. Überschreiben? +message.transfer.waiting.on.user = {0} muss den Dateitransfer akzeptieren. Bitte warten... +message.negotiation.file.transfer = Dateitransfer mit {0} wird initialisiert. Bitte warten... +message.unable.to.send.file = Die Datei konnte nicht an {0} übertragen werden. +message.sending.file.to = Datei wird an {0} gesendet. +message.you.have.sent = Datei wurde an {0} gesendet. +message.file.transfer.rejected = Der Dateitransfer wurde von {0} abgelehnt. +message.disable.transport = Soll der aktive Transport unterbunden werden? +message.register.transports = Bei den verfügbaren Transportprotokollen registrieren. +message.enter.sametime = Geben Sie Ihre Anmeldung und Passwort für Sametime ein. +message.enter.facebook = Geben Sie Ihre Anmeldung und Passwort für Facebook ein. +message.enter.myspace = Geben Sie Ihre Anmeldung und Passwort für MySpace ein. +message.username.password.error = Benutzername und/oder Passwort muss eingegeben werden. +message.registration.transport.failed = Registrierung mit dem Transportprotokoll schlug fehl. +message.client.information = Programminformationen für {0} +message.calling = Rufe {0} +message.number.to.call = Bitte eine Nummer eingeben +message.no.caller.id = Keine Ruf-ID verfügbar. +message.no.history.found = Es sind keine weiteren Nachrichten verfügbar. +message.prompt.plugin.uninstall = Dieses Plugin {0} wirklich deaktivieren? +message.restart.spark = Das Programm muss neugestartet werden damit die Änderungen aktiviert werden. +message.loading.please.wait = Lade. Bitte warten... +message.plugins.not.available = Konnte keine Verbindung mit der Pluginliste herstellen. +message.downloading = Lade {0} herunter +message.downloading.spark.plug = Lade Plugin +message.unable.to.save.password = Passwort konnte nicht geändert werden. Kontaktieren Sie bitte den Administrator. +message.delete.all.history = Lösche alle älteren Nachrichten? +message.no.avatar.found = Der Teilnehmer hat keinen Avatar eingerichtet. +message.image.too.large = Das Bild ist zu groß! Bitte ein Bild mit 16Kb oder kleiner wählen. +message.save.profile = Auf Speichern klicken um die Änderungen zu sichern. +message.unable.to.load.profile = Profil von {0} konnte nicht gefunden werden +message.enter.jabber.id = Jabber-ID eingeben +message.invalid.jabber.id = Keine korrekte Jabber-ID +message.vcard.not.supported = Der Server unterstützt keine VCards. Ihre VCard konnte nicht gespeichert werden. +message.search.service.not.available = Die Verbindung zum Suchdienst konnte nicht hergestellt werden. +message.no.results.found = Es wurden keine Suchergebnisse gefunden. +message.name.of.search.service.question = Name des Suchdienstes? +message.search.for.other.people = Nach weiteren Personen suchen +message.specify.valid.time.error = Bitte korrekte Werte eingeben. +message.timeout.error = Die Zeitspanne muss mindestens 5 Sekunden betragen. +message.version = Version: {0} +message.file.size = Dateigröße: {0} +message.updating.cancelled = Das Aktualisieren wurde verweigert. +message.transfer.rate = Datendurchsatz +message.total.downloaded = Insgesamt heruntergeladen +message.new.spark.available = {0} ist jetzt verfügbar. Soll die Installation durchgeführt werden? +message.restart.spark.to.install = Das Programm muss beendet werden, um eine Version zu installieren. Programm beenden? +message.add.to.roster = Zur Kontaktliste hinzufügen +message.enter.room.password = Passwort für diesen Raum eingeben +message.add.contact.to.list = Teilnehmer zur Kontaktliste hinzufügen +message.authenticating = Authentifizierung +message.invalid.status = Bitte eine gültige Statusnachricht eingeben. +message.cannot.add.contact.to.shared.group = Es können keine neue Kontakte zu der Gruppe hinzugefügt werden. +message.specify.contact.jid = Bitte die JID des Kontakts eingeben (bsp. jemand@jabber.org) +message.invalid.jid.error = Die eingegebene JID ist ungültig. +message.specify.group = Bitte die Gruppe angeben, der der neue Kontakt hinzugefügt werden soll. +message.room.creation.error = Der Raum kann nicht erstellt werden. +message.unable.to.retrieve.last.activity = Keine letzte Aktivität für {0} vorhanden +message.buzz.alert.notification = Sich beim Benutzer bemerkbar machen. +message.buzz.message = {0} möchte Ihre Aufmerksamkeit +message.buzz.sent = Benutzer wurde um Aufmerksamkeit gebeten. +message.invite.to.groupchat = Sie wurden von {0} zu einem Gruppenchat eingeladen +title.advanced.connection.preferences = Erweiterte Verbindungseinstellungen +title.passwords.no.match = Passwörter stimmen nicht überein. Bitte Eingabe wiederholen. +title.create.problem = Problem beim Anlegen eines Kontos +title.account.created = Konto erstellt +title.create.new.account = Neues Konto erstellen +title.account.create.registration = Konto registrieren +title.register.account = Neues Konto registrieren +title.notification = Benachrichtigungen +title.advanced.connection.sso = Single Sign-On verwenden (SSO) +title.advanced.connection.usesso = Single Sign-On (SSO) über GSSAPI verwenden +title.advanced.connection.sso.account = Das Desktopkonto "{0}" verwenden, um mit dem Server zu verbinden. +title.advanced.connection.sso.unable = Single Sign-On fehlgeschlagen. Bitte die Einstellungen überprüfen. +title.advanced.connection.sso.noprincipal = Spark kann den Klienten für Single Sign-On nicht finden. +title.preferences = Einstellungen +title.error = Fehler +title.client.logs = Client-Protokolle +title.status.message = Statusnachricht +title.spark.preferences = Spark-Einstellungen +title.alert = Benachrichtigung +title.tray.information = Tray Information +title.select.file.to.send = Datei(en) zum Senden auswählen +title.choose.directory = Verzeichnis auswählen +title.confirmation = Bestätigung +title.last.activity = Letzte Aktivität +title.add.new.group = Neue Gruppe hinzufügen +title.add.to.roster = Der Kontaktliste hinzufügen +title.find.contacts = Kontakte finden +title.rename.roster.group = Kontaktgruppe umbenennen +title.roster = Kontaktliste +title.create.room = Erstellen +title.conference.rooms = Konferenzräume +title.invite.to.conference = Zu einer Konferenz einladen +title.room.information = Rauminformationen +title.change.nickname = Angezeigten Name ändern +title.group.chat.settings = Konferenzeinstellungen +title.group.chat = Konferenz +title.create.or.bookmark.room = Raum als Lesezeichen setzen oder dem Raum beitreten +title.browse.room.service = Liste der Konferenzen - {0} +title.name = Name +title.address = Adresse +title.occupants = Teilnehmer +title.browse.conference.services = Dienste zu Konferenzen anzeigen +title.find.conference.service = Konferenzdienst finden +title.configure.chat.room = Konferenzraum konfigurieren +title.conference.invitation = Konferenzeinladung +title.join.conference.room = Konferenzraum beitreten +title.view.room.information = Rauminformationen +title.configure.room = Raum konfigurieren +title.change.subject = Konferenzthema ändern +title.enter.reason = Geben Sie einen Grund ein +title.room.destroyed = Raum löschen +title.edit.custom.message = Eigene Nachrichten ändern +title.set.status.message = Statusnachricht festlegen +title.broadcast.message = Rundnachricht +title.start.chat = Chat starten +title.view.bookmarks = Lesezeichen anzeigen +title.downloads = Downloads +title.file.exists = Datei existiert +title.disable.transport = Transport deaktivieren +title.available.transports = Verfügbare Transportprotokolle +title.transports = Transporte +title.facebook.registration = Facebook-Registrierung +title.myspace.registration = MySpace-Registrierung +title.sametime.registration = Sametime-Registrierung +title.registration.error = Fehler in der Registrierung +title.jabber.browser = Browser +title.version.and.time = Version und Zeit +title.waiting.to.call = Warten auf Anruf +title.incoming.call = Ankommender Anruf +title.on.the.phone = Telefoniert +title.dial.phone = Rufnummer wählen +title.history.for = Nachrichtenverlauf für {0} +title.reminder = Erinnerung +title.plugins = Plugins +title.general.chat.settings = Allgemeine Chateinstellungen +title.chat = Chat +title.notifications = Benachrichtigungen +title.sound.preferences = Klangeinstellungen +title.sounds = Klänge +title.choose.incoming.sound = Klangdatei für ankommende Nachrichten auswählen +title.choose.outgoing.sound = Klangdatei für ausgehende Nachrichten auswählen +title.choose.offline.sound = Klangdatei für Offline auswählen +title.edit.profile = Profilinformationen ändern +title.profile.information = Profilinformationen +title.profile.not.found = Profil nicht gefunden +title.view.profile.for = Profil von {0} +title.lookup.profile = Profil suchen +title.add.search.service = Suchdienst hinzufügen +title.person.search = Suche nach Personen +title.login.settings = Anmeldeeinstellungen +title.login.no.account = Unbestimmbar +title.login = Anmeldung +title.downloading.im.client = IM-Programm herunterladen +title.upgrading.client = Programm upgraden +title.cancelled = Abgebrochen +title.new.version.available = Neue Version verfügbar +title.new.client.available = Neues Programm verfügbar +title.password = Passwort +title.download.complete = Download abgeschlossen +title.new.roster.group = Neue Kontaktgruppe +title.add.contact.group = Neue Kontaktgruppe hinzufügen +title.add.contact = Neuen Kontakt hinzufügen +title.file.transfer.preferences = Dateitransfer-Einstellungen +title.file.transfer = Dateitransfer +title.appearance.preferences = Anpassung +title.appearance.showVCards = &VCards in der Kontaktliste anzeigen +title.input.fileexplorer = Geben Sie den Namen Ihres Dateibrowsers ein: +title.input.openwith = Geben Sie den Namen des Programms ein, welches Sie verwenden möchten: +title.error.find.app = Es konnte keine passende Anwendung gefunden werden. +title.input.newname = Geben Sie den neuen Namen ein: +title.error.rename.file = Datei konnte nicht umbenannt werden! +title.file = Datei +title.filesize = Dateigröße +title.error.delete.file = Datei konnte nicht gelöscht werden! +title.error.couldnot.open.file = Datei konnte nicht geöffnet werden! Eventuell Dateityp unbekannt! +title.bookmarks = Lesezeichen +title.task.notification = Aufgabenbenachrichtigung +status.away = Abwesend +status.custom.messages = Benutzerdefinierte Nachricht +status.do.not.disturb = Nicht stören +status.on.phone = Am Telefon +status.online = Verfügbar +tree.conference.services = Konferenzen +tree.users.in.room = Teilnehmer im Raum +tab.general = Allgemein +tab.proxy = Proxy +tab.contacts = Kontakte +tab.installed.plugins = Installierte Plugins +tab.available.plugins = Verfügbare Plugins +tab.deactivated.plugins = Deaktivierte Plugins +tab.personal = Persönlich +tab.business = Geschäftlich +tab.home = Privat +tab.avatar = Avatar +tab.conferences = Konferenzen +tab.sso = SSO +tab.pki = PKI +tooltip.place.a.call = Diesen Teilnehmer anrufen +tooltip.view.history = Nachrichtenverlauf anzeigen +tooltip.view.changelog = Änderungen anzeigen +tooltip.view.readme = LiesMich anzeigen +tooltip.notifications = Einstellungen der Benachrichtigungen für eingehende Chats. +tooltip.place.voice.call = VOIP-Anruf starten. +message = Nachricht +message.alert.notify = Warnungsbenachrichtigung +message.disconnected.shutdown = Ihre Verbindung wurde unterbrochen, weil der Server heruntergefahren wurde +message.enter.gadugadu = GaduGadu-Benutzername und -Passwort eingeben +message.enter.irc = IRC-Benutzername und -Passwort eingeben +message.enter.qq = QQ-Benutzername und -Passwort eingeben +message.enter.simple = SIMPLE-Benutzername und -Passwort eingeben +message.enter.xmpp = XMPP-Benutzername und -Passwort eingeben +message.file.transfer.notification = Dateitransferbenachrichtigung +message.file.transfer.short.message = sendet Ihnen eine Datei mit Namen\: +message.file.transfer.chat.window = Dateitransfer angefordert: +message.gateway.username.error = Benutzername muss eingegeben werden +message.gateway.password.error = Passwort muss eingegeben werden +message.gateway.nickname.error = Spitzname muss eingegeben werden +message.invalid.username.password = Ungültiges Passwort oder Benutzername +message.no.updates = Es gibt keine Aktualisierungen +message.normal = Normale Nachricht +message.reconnect.attempting = Versuche... +message.reconnect.failed = Wiederverbinden gescheitert +message.reconnect.wait = Wiederverbinden in {0} Sekunden +message.restart.spark.changes = Das Plugin wird beim nächsten Start von Spark entfernt +message.restart.required = Sie müssen Spark neustarten, damit die Änderungen wirksam werden, möchten Sie jetzt neustarten? +message.send.to.these.people = An diese Leute senden +message.server.unavailable = Kann nicht mit Server verbinden: Ungültiger Name oder Server nicht erreichbar +message.unrecoverable.error = Ungültiger Benutzername oder Passwort +message.waiting.for.user.to.join = Warte auf {0} zum Beitritt +message.your.voice.granted = Sie haben Schreibrechte in diesem Chat bekommen +message.groupchat.require.password = Dieser Gruppenchat benötigt ein Passwort +message.groupchat.registered.member = Registrierung mit {0} erfolgreich +message.search.for.history = Gesprächsverlauf durchsuchen +status.extended.away = Nicht verfügbar +status.free.to.chat = Bereit zu Chatten +status.pending = Schwebend +title.about = Über +title.password.required = Passwort benötigt +title.appearance = Erscheinung +title.delete.file = Möchten Sie diese Datei wirklich löschen? +title.gadugadu.registration = GaduGadu-Kontoinformationen +title.general.media = Medieneinstellungen +title.irc.registration = IRC-Kontoinformationen +title.login.error = Anmeldefehler +title.no.updates = Keine Aktualisierungen +title.notes = Notizen +title.qq.registration = QQ-Kontoinformationen +title.simple.registration = SIMPLE-Kontoinformationen +title.tasks = Aufgaben +title.xmpp.registration = XMPP-Kontoinformationen +title.subscription.request = Kontaktanfrage +tooltip.appearance = Aussehen der Unterhaltungen ändern +tooltip.file.transfer = Präferenzen für Dateitransfers +tooltip.send.email = E-Mail senden +tooltip.start.chat = Konversation starten + +lookandfeel.select = Thema auswählen +lookandfeel.change.now = Jetzt ändern +lookandfeel.tooltip.restart.no = Es wird kein Neustart benötigt +lookandfeel.tooltip.restart.yes = Um ein System Look&Feel auszuwählen, bitte Speichern und Spark neustarten. +lookandfeel.color.label = Farben +lookandfeel.color.red = Rot +lookandfeel.color.green = Grün +lookandfeel.color.blue = Blau +lookandfeel.color.opacity = Deckkraft +lookandfeel.color.saved = Farben gespeichert + + +##Settings for the privacy plugin +privacy.title.preferences = Privatsphäreeinstellungen +privacy.title.panel = Benutzen Sie die rechte Maustaste +privacy.label.iq.desc = Abfragen +privacy.label.pin.desc = Anwesenheit empfangen +privacy.label.pout.desc = Anwesenheit senden +privacy.label.msg.desc = Nachrichten +privacy.border.information = Legende +privacy.label.information = Benutzen Sie die rechte Maustaste, um Elemente hinzuzufügen oder zu entfernen +privacy.root.node = Privatsphärelisten +privacy.label.preferences = Privatsphäre +privacy.tooltip.preferences = Spark-Privatsphäreeinstellungen +privacy.label.list.is.active = Aktuell aktive Liste: +privacy.label.list.is.default = Standardliste: +privacy.border.block = Sperren +privacy.pick.one.or.more = Wählen Sie ein oder mehrere Elemente aus der Liste aus +privacy.title.add.picker = Elemente zur Liste hinzufügen +privacy.node.contacts = Kontakte +privacy.node.groups = Gruppen +privacy.menu.add.contacts = Kontakt zur Liste hinzufügen +privacy.menu.add.groups = Gruppe zur Liste hinzufügen +privacy.menu.add.rem.items = {0} Elemente von der Liste entfernen +privacy.menu.remove = Entfernen +privacy.menu.activate.list = Aktivieren +privacy.menu.default.list = Als Standard festlegen +privacy.menu.add.list = Liste hinzufügen +privacy.menu.remove.list = Liste entfernen +privacy.dialog.add.list = Bitte den Namen der Liste eingeben +privacy.dialog.rem.list = Möchten Sie wirklich "{0}" entfernen? +privacy.status.menu.entry = Privatsphäre +privacy.name.for.default.list = Standard +privacy.button.no.list.selected = Keine Liste ausgewählt +privacy.menuitem.deactivate.current.list = {0} deaktivieren +privacy.label.not.supported = Privatsphärelisten werden vom Server leider nicht unterstüzt. + + +##Stunfallback in media settings +stun.border.label = STUN-Ausweichserver +stun.server.addr = STUN-Server: +stun.server.port = STUN-Port: diff --git a/core/src/main/resources/i18n/spark_i18n_es.properties b/core/src/main/resources/i18n/spark_i18n_es.properties new file mode 100644 index 000000000..d7307a7c6 --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_es.properties @@ -0,0 +1,754 @@ +## Traduccion al espanol por Jeffrey Steve Borbon Sanabria (jeffto@aclibre.org) +## Corrección de Juan Gabriel +## Noviembre 2008 +accept = Aceptar + +action.clear = Limpiar +action.copy = Copiar +action.cut = Cortar +action.paste = Pegar +action.print = Imprimir +action.save = Guardar +action.select.all = Seleccionar todo +is.active = Activar +add = Agregar +apply = Aplicar +available = Disponible +broadcast = Difusión + +button.accept = &Aceptar +button.add = &Agregar +button.add.a.contact = &Agregar contacto +button.add.bookmark = Agregar favorito +button.add.service = &Agregar servicio +button.add.user = &Agregar usuario +button.add2 = &Agregar +button.advanced = A&vanzado +button.approve = &Aprobar +button.bookmark.room = Cuarto &favorito +button.browse = &Consultar... +button.browse2 = C&onsultar... +button.browse3 = Co&nsultar... +button.cancel = &Cancelar +button.clear = &Limpiar +button.close = C&errar +button.copy.to.clipboard = Copiar al portapapeles +button.create.account = &Crear cuenta +button.create.room = &Crear o ingresar a cuarto +button.decline = &Declinar +button.deny = &Denegar +button.dial.number = &Discar número +button.find = &Buscar +button.join = &Ingresar +button.join.room = &Ingresar cuarto seleccionado +button.new = &Nuevo +button.profile = &Perfil +button.quit = &Salir +button.reconnect = &Reconectar +button.reconnect2 = Reconectar +button.refresh = &Refrescar +button.register = &Registrar +button.remove.bookmark = Eliminar favorito +button.roster = &Lista +button.save = &Guardar +button.save.for.future.use = &Guardar para uso futuro +button.search = &Buscar +button.send = Enviar +button.send.email = Email +button.start.chat = Chat +button.tasks.active = Activo +button.tasks.all = Todo +button.unset.file.explorer = Deshabilitar el Explorador de archivos +button.update = &Actualizar +button.view.notes = Ver notas +button.view.profile = Ver perfil completo +button.view.tasklist = Ver lista de tareas +cancel = Cancelar + +checkbox.allow.buzz = Permitir la recepción de &zumbidos +checkbox.auto.discover.port = &Descubrir automáticamente servidor y puerto +checkbox.auto.login = Login &automático +checkbox.broadcast.hide.offline.user = Ocultar usuario desconectado +checkbox.disable.chat.history = &Deshabilitar Historial de Chat +checkbox.disable.prev.chat.history = &Deshabilitar Mostrar conversaciones anteriores en el chat +checkbox.enable.emoticons = Habilitar Em&oticones +checkbox.idle.enabled = Activar detección de tiempo &ocioso +checkbox.launch.on.startup = &Iniciar luego de arranque +checkbox.notify.user.comes.online = Notificar cuando un usuario se conecta +checkbox.notify.user.goes.offline = Notificar cuando un usuario se desconecta +checkbox.permanent = El cuarto es &permanente +checkbox.play.sound.on.invitation = Ejecutar sonido cuando reciba una &invitación +checkbox.play.sound.on.new.message = Ejecutar sonido cuando &llegan nuevos mensajes +checkbox.play.sound.on.outgoing.message = Ejecutar sonido cuando un mensaje es &enviado +checkbox.play.sound.when.offline = Ejecutar sonido cuando un usuario se &desconecta +checkbox.private.room = El cuarto &es privado +checkbox.save.password = &Guardar contraseña +checkbox.show.avatars.in.contactlist = Mostrar &avatares en la Lista de Contactos +checkbox.show.notifications.in.conference = &Mostrar notificaciones en Cuartos de conferencia +checkbox.show.time.in.chat.window = &Mostrar hora en ventana de chat +checkbox.show.toaster = Mostrar ventana de &Avisos +checkbox.split.chat.window = Fijar Ventanas (Requiere reiniciar) +checkbox.start.in.tray = &Iniciar en la bandeja del sistema +checkbox.tabs.on.top = Las solapas de &chat aparecen arriba (Requiere reiniciar) +checkbox.tabs.scroll = Use el desplazamiento para las pestañas de chat (requiere reiniciar) +checkbox.use.compression = Usar Co&mpresión +checkbox.use.proxy.server = &Usar servidor Proxy +checkbox.use.system.look.and.feel = Usar apariencia del sistema (Requiere reiniciar) +checkbox.window.to.front = &Traer ventana al frente +checkbox.close.unread.message = Preguntar al cerrar la ventana si hay mensajes sin leer +close = Cerrar +create = Crear +date = Fecha + +delete.log.permanently = Borrar registro permanentemente +delete.permanently = ¿Borrar permanente? +description = Descripción +from = Desde + +gateway.username.password.error = El nombre de usuario y/o contraseña debe ser reemplazado. +group.chat.name.match = Tu nombre ha sido dicho en el grupo de chat: +group.chat.name.notification = Tu nombre apareció... + +group.chat.window.information = Información de la conversación +group.comma.delimited = Delimitado por comas +group.conferences.found = Servicio de conferencia encontrado +group.connection = Conexión +group.empty = No hay contactos en línea en este grupo. +group.general.information = Información general +group.login.information = Información de login +group.notification.options = Opciones de notificación +group.offline = Grupo de usuarios desconectados +group.search.form = Formulario de búsqueda +group.search.results = Resultados de la búsqueda +invite = Invitar +join = Ingresar + +label.accounts = &Cuentas +label.add.conference.service = &Agregar servicio de conferencia +label.add.jid = &Agregar JID +label.add.task = Agregar tarea +label.auto.login = Login &automático +label.available.users.in.roster = &Contactos disponibles en lista +label.cancel = Cancelar +label.change.password.to = &Cambiar contraseña a +label.chatroom.fontsize = Tamaño de letra del Cuarto de Chat: +label.city = &Ciudad +label.close = C&errar +label.company = &Compañía +label.confirm.password = &Confirmar contraseña +label.conflict.error = No se pudo hacer el login ya que la cuenta está siendo utilizada. +label.contact.to.find = Buscar contacto +label.contactlist.avatarsize = Tamaño de avatar de lista de contactos: +label.contactlist.fontsize = Tamaño de fuente de &lista de contactos: +label.country = P&aís +label.create.account = Crear &cuenta +label.department = &Departmento +label.dial = &Discar +label.downloads = Descargas +label.due = Debido +label.email.address = &Dirección de Email +label.emoticons = &Emoticones +label.enter.address = Ingresar dirección +label.enter.group.name = Ingrese un nuevo nombre de grupo +label.fax = &Fax +label.find = &Buscar +label.first.name = &Primer nombre +label.group = &Grupo +label.host = &Servidor +label.invited.users = Usuarios invitados +label.jabber.address = &Dirección Jabber +label.jabber.id = &Jabber ID +label.jid = &JID +label.job.title = &Puesto de trabajo +label.last.name = &Apellido +label.local.time = &Hora local +label.message = &Mensaje +label.message.style = Estilo de &Mensaje +label.middle.name = &Segundo nombre +label.minutes.before.stale.chat = &Minutos para considerar un cuarto inactivo como caducado +label.mobile = &Celular +label.name = &Nombre +label.network = Red +label.new.nickname = Nuevo Apodo +label.nickname = &Apodo +label.number = &Número +label.ok = OK +label.old.ssl = &Usar viejo método de SSL +label.os = &Sistema Operativo +label.pager = &Localizador +label.password = &Contraseña +label.phone = &Teléfono +label.port = &Puerto +label.postal.code = &Código postal +label.presence = &Presencia +label.priority = P&rioridad +label.protocol = &Protocolo +label.received = Recibido +label.rename.to = Renombrar a +label.resource = &Recurso +label.response.timeout = &Tiempo máximo de espera (seg) +label.room = &Cuarto +label.room.name = &Nombre del cuarto +label.room.topic = &Tema del cuarto +label.search.service = &Servicio de búsqueda +label.server = Do&minio +label.server.address = &Dirección del servidor +label.show = Mostrar: +label.software = &Software +label.state.and.province = E&stado/Provincia +label.street.address = &Dirección +label.time = Tiempo: {0} +label.time.till.idle = &Tiempo para considerarse Ocioso (min) +label.timeformat = Usar {0} +label.transfer.download.directory = &Carpeta para descargas: +label.transfer.timeout = Tiempo mínimo de espera para &transferencias: +label.unable.to.add.contact = No se pudo agregar el contacto. +label.use.default = Usar predeterminado +label.user.on.public.network = El usuario está en una red pública +label.username = &Nombre de usuario +label.version = &Versión +label.web.page = &Página web +label.xmpp.port = &Puerto XMPP + +menuitem.about = Acerca de +menuitem.actions = Acciones +menuitem.add = Agregar +menuitem.add.as.contact = Agregar como contacto +menuitem.add.contact = Agregar contacto +menuitem.add.contact.group = Agregar contacto al grupo +menuitem.add.groupchat.myname = Destacar mi nombre cuando alguien lo dice +menuitem.add.groupchat.mytext = Destacar mi texto cuando yo digo algo +menuitem.add.groupchat.popname = Mostrar mensaje emergente cuando alguien dice mi nombre +menuitem.alert.when.online = Alertar cuando el usuario esté disponible +menuitem.ban = Censurar +menuitem.ban.user = Censurar usuario +menuitem.block.user = Bloquear usuario +menuitem.bookmark.room = Agregar sala a Favoritos +menuitem.broadcast.to.group = Difundir mensaje al grupo +menuitem.browse.service = Buscar servicio +menuitem.change.nickname = Cambiar apodo +menuitem.change.subject = Cambiar tema +menuitem.chat = Chat +menuitem.check.for.updates = Verificar actualizaciones +menuitem.connect = Archivo +menuitem.contacts = Contactos +menuitem.copy.to = Copiar a +menuitem.create.room = Crear o unirse a una sala de chat +menuitem.delete = Eliminar +menuitem.delete.login.information = Eliminar información de conexión +menuitem.destroy.room = Destruir cuarto +menuitem.dial = Marcar +menuitem.edit = Editar +menuitem.edit.my.profile = &Editar mi perfil... +menuitem.edit.status.message = Editar mensaje de estado personalizado... +menuitem.enter.login.information = Ingresar información de conexión +menuitem.exit = Salir +menuitem.grant.moderator = Conceder Moderador +menuitem.grant.voice = Conceder Chat de Voz +menuitem.help = Ayuda +menuitem.hide = Ocultar +menuitem.invite.group.to.conference = Invitar grupo a conferencia +menuitem.invite.users = Invitar usuarios +menuitem.join.on.startup = Ingresar al comienzo +menuitem.join.room = Ingresar al cuarto +menuitem.kick.user = Desconectar usuario +menuitem.languages = Idiomas +menuitem.logout.no.status = Cerrar la sesión +menuitem.logout.with.status = Cerrar sesión con un motivo +menuitem.lookup.profile = &Buscar perfil... +menuitem.move.to = Mover a +menuitem.online.help = Foro de Spark +menuitem.open = Abrir +menuitem.open.with = Abrir con... +menuitem.plugins = Plugins +menuitem.preferences = Preferencias +menuitem.refresh = Actualizar +menuitem.remove = Eliminar +menuitem.remove.alert.when.online = Eliminar alerta +menuitem.remove.bookmark = Eliminar favorito +menuitem.remove.from.group = Eliminar del grupo +menuitem.remove.from.roster = Eliminar de la Lista +menuitem.remove.service = Eliminar servicio +menuitem.rename = Renombrar +menuitem.revoke.moderator = Revocar moderador +menuitem.revoke.voice = Revocar Chat de Voz +menuitem.save = Guardar +menuitem.save.as = Guardar como... +menuitem.send.a.file = Enviar un archivo +menuitem.send.a.message = Enviar un mensaje a usuarios seleccionados... +menuitem.set.status.message = Configurar mensaje de estado ... +menuitem.show.contact.statusmessage = Mostrar mensaje de estado +menuitem.show.empty.groups = Mostrar grupos vacíos +menuitem.show.offline.group = Agrupar usuarios desconectados +menuitem.show.offline.users = Mostrar usuarios desconectados +menuitem.show.traffic = Mostrar ventana de tráfico +menuitem.sign.in = Conectarse +menuitem.sign.in.at.login = Conectarse al iniciar sesión +menuitem.sign.out = Desconectarse +menuitem.start.a.chat = Comenzar una conversación +menuitem.start.a.conference = Comenzar una conferencia... +menuitem.status = Estado +menuitem.subscribe.to = Subscribirse a +menuitem.unban = Habilitar +menuitem.unblock.user = Desbloquear usuario +menuitem.user.guide = Guía del usuario +menuitem.view.client.version = Ver versión del cliente +menuitem.view.contact.history = Ver historial del contacto +menuitem.view.downloads = Ver descargas +menuitem.view.last.activity = Ver última actividad +menuitem.view.logs = Ver registros +menuitem.view.profile = Ver perfil +menuitem.view.room.info = Ver información del cuarto +menuitem.voice = Chat de voz + +message = &Mensaje +message.account.create = Crear una nueva cuenta de chat. +message.account.created = La cuenta ha sido creada exitosamente. +message.account.error = Especificar el servidor donde crear la cuenta. +message.add.a.contact = Agregar un contacto. +message.add.conference.service = Agregar un servicio de conferencia. +message.add.contact.to.list = Agregar un usuario a la lista de contactos +message.add.favorite.room = Agregar cuarto como favorito o ingresar directamente. +message.add.this.user.to.your.roster = Agregar este usuario a su lista de contactos. +message.add.to.roster = Agregar a la lista +message.add.user = ¿Desea agregar el usuario a su lista de contactos? +message.alert.notify = Notificación de alerta +message.already.exists = La cuenta ya existe. Intente con otro nombre de usuario. +message.approve.subscription = ¿Permitir a {0} que lo agregue a su lista de contactos? +message.authenticating = Autenticando +message.away.idle = Ausente por inactividad. +message.bookmark.temporary.room.error = No se pueden guardar cuartos temporales como favoritos +message.broadcast.from = Difusión enviada por {0} +message.broadcast.message.sent = El mensaje para difundir ha sido enviado. +message.broadcast.to = Ingrese el mensaje para difundir a {0} +message.hasbeenbroadcast.to = El mensaje a sido enviado a los siguientes usuarios:\n{0} +message.buzz.alert.notification = Obtener la atención del usuario. +message.buzz.sent = Enviar notificaciones de alertas al usuario. +message.calling = Llamando {0} +message.came.online = {0} está disponible en {1} +message.cannot.add.contact.to.shared.group = No puede agregar nuevos contactos a un grupo compartido. +message.chat.session.ended = La sesión de chat ha finalizado a las {0} +message.click.to.open = Haga clic para abrir +message.client.information = Información del cliente para {0} +message.close.other.chats = Cerrar demás conversaciones +message.close.stale.chats = Cerrar conversaciones viejas +message.close.this.chat = Cerrar esta chat +message.close.unread.window = Tiene mensajes sin leer, ¿está seguro de que desea cerrar la ventana? +message.conference.info.error = No se ha podido obtener información de la conferencia. Intente nuevamente en un momento. +message.conference.service.error = No se ha podido encontrar el servicio de conferencia. +message.confirm.destruction.of.room = Al destruir el cuarto los usuarios seran eliminados del cuarto. ¿Continuar? +message.confirmation.password.error = Especificar la contraseña de confirmación. +message.connecting.please.wait = Conectando. Aguarde un momento... +message.connection.failed = No se ha podido establecer una conexión con {0}. +message.create.account = No se ha podido crear la cuenta. +message.create.or.join.room = Crear o ingresar a cuarto de conferencia +message.current.status = Permitir a otros ver mi estado actual o mi actividad. +message.default.error = Un error ha sido detectado. Por favor repórtelo a support@jivesoftware.com. +message.delete.all.history = ¿Eliminar todas las conversaciones previas? +message.delete.confirmation = ¿Está seguro que desea eliminar {0}? +message.disable.transport = ¿Desea eliminar la información de login de {0}? +message.disconnected.conflict.error = Su conexión se ha cerrado ya que el mismo usuario ha sido utilizado desde otra ubicación. +message.disconnected.error = Su conexión se ha cerrado por un error. +message.disconnected.group.chat.error = La conexión se ha cerrado debido a un error. Necesitas reconectarte para ingresar nuevamente al cuarto. +message.disconnected.shutdown = Su conexión ha sido cerrada porque el servidor ha sido apagado. +message.downloading = Descargando {0} +message.downloading.spark.plug = Descargando Spark-Plug +message.end.chat = ¿Desea finalizar esta conversación? +message.end.conversation = ¿Desea finalizar esta sesión? +message.enter.broadcast.message = Ingrese un mensaje para difundir a los usuarios seleccionados. +message.enter.gadugadu = Ingrese su usuario y contraseña de de GaduGadu. +message.enter.irc = Ingrese su usuario, contraseña y apodo de IRC. +message.enter.jabber.id = Ingrese un Jabber ID +message.enter.message.to.broadcast = Ingresar mensaje para difundir a su lista de contactos. +message.enter.new.subject = Ingrese un tema +message.enter.qq = Ingrese su número QQ y contraseña. +message.enter.room.password = Ingresar la contraseña de cuarto +message.enter.simple = Ingrese su usuario y contraseña de SIMPLE. +message.enter.valid.jid = Ingrese un Jabber ID válido +message.enter.xmpp = Ingrese su usuario y contraseña de XMPP. +message.error.during.file.transfer = Hubo un error transfiriendo el archivo. +message.file.exists.question = El archivo ya existe. ¿Sobreescribir? +message.file.size = Tamaño del archivo: {0} +message.file.transfer.canceled = Ha cancelado la transferencia del archivo. +message.file.transfer.chat.window = Solicitud de Transferencia de archivos +message.file.transfer.notification = Notificación de Transferencia de archivos +message.file.transfer.rejected = La transferencia del archivo no ha sido aceptada por {0}. +message.file.transfer.short.message = te está enviando un archivo llamado: +message.find.conference.services = Buscar servicios de conferencia +message.forbidden.error = Se ha recibido un error de prohibición del servidor. +message.gateway.nickname.error = El apodo es requerido. +message.gateway.password.error = La contraseña es requerida. +message.gateway.username.error = El nombre de usuario es requerido. +message.general.error = Ha perdido su conexión al servidor debido a: {0}. +message.generic.reconnect.message = Ha perdido su conexión al servidor. Para ingresar nuevamente, haga clic en Reconectar. +message.idle.for = Inactivo por {0} +message.image.too.large = Esta imagen es muy pesada para ser usada. Utilice una imagen de 16k o menos. +message.invalid.jabber.id = El Jabber ID no es válido +message.invalid.jid.error = El JID especificado es inválido. +message.invalid.status = Especifique un mensaje de estado válido. +message.invalid.username.password = Usuario o contraseña inválidos. +message.invite.users.to.conference = Invitar usuarios al cuarto de conferencia. +message.is.shared.group = {0} es un grupo compartido. +message.is.typing.a.message = {0} está escribiendo un mensaje... +message.join.conference.room = Ingresar al Cuarto de conferencia +message.kicked.error = No ha sido capaz de echar {0} del cuarto. +message.last.message.received = Último mensaje recibido el {0} +message.loading.please.wait = Cargando. Espere un momento... +message.locked.workstation = El usuario a bloqueado su estación de trabajo. +message.name.of.group = Nombre del grupo +message.name.of.search.service.question = ¿Nombre del servicio de búsqueda? +message.negotiate.file.transfer = Negociando transferencia de archivo. Aguarde un momento... +message.negotiate.stream = Negociando conexión. Aguarde un momento... +message.negotiation.file.transfer = Negociando transferencia de archivo con {0}. Aguarde un momento... +message.new.message = Nuevo mensaje de {0}. +message.new.spark.available = {0} está ahora disponible. ¿Desea instalarla? +message.nickname.in.use = Apodo en uso. Especifique otro apodo. +message.no.avatar.found = El usuario no ha configurado su avatar. +message.no.caller.id = Identificación de llamadas no disponible. +message.no.description.available = No hay una descripción disponible +message.no.history.found = No existe un historial de conversaciones previas con este usuario. +message.no.results.found = El servidor no ha retornado resultados para la búsqueda. +message.no.room.to.join.error = No hay un cuarto al cual ingresar +message.no.subject.available = No hay un tema disponible +message.no.updates = No hay actualizaciones. +message.normal = Mensaje normal +message.number.to.call = Especifique el número a discar +message.offline = El usuario no está conectado y recibirá el mensaje cuando se conecte. +message.offline.error = El usuario no será capaz de recibir mensajes diferidos. +message.participants.in.room = Participantes en el cuarto +message.password.error = Especificar una contraseña para la cuenta. +message.password.private.room.error = Especifique una contraseña para el cuarto privado +message.passwords.no.match = Las claves no son iguales. +message.please.join.in.conference = Únete conmigo al cuarto de conferencia. +message.plugins.not.available = Imposible contactar el repositorio de plugins. +message.prompt.plugin.uninstall = ¿Está seguro que desea desintalar {0}? +message.received.file = Ha recibido un archivo de {0}. +message.receiving.file = Está recibiendo un archivo de {0} +message.reconnect.attempting = Intentando... +message.reconnect.failed = Reconexión fallida. +message.reconnect.wait = Reconectando en {0} segundos. +message.register.transports = Registrar con los siguientes transportes. +message.registering = Registrándose en {0}. Aguarde un momento... +message.registration.transport.failed = No se ha podido registrar con el Transporte. +message.restart.required = Debe reiniciar el cliente para que sus cambios tomen efecto. ¿Desea hacerlo ahora? +message.restart.spark = Debe reiniciar el cliente para \n instalar la nueva versión. ¿Desea hacerlo ahora? +message.restart.spark.changes = El plugin será borrado la próxima vez que se inicie Spark. +message.restart.spark.to.install = Debe reiniciar el cliente para instalar la nueva versión. ¿Desea hacerlo ahora? +message.room.creation.error = No se pudo crear el cuarto. +message.room.destroyed = Este cuarto ha sido destruido por el siguiente motivo: {0} +message.room.destruction.reason = ¿Motivo para destruir el cuarto? +message.room.information.for = Información del cuarto para {0} +message.save.profile = Para guardar los cambios a su perfil haga click en Salvar. +message.search.for.contacts = Buscar contactos. +message.search.for.other.people = Buscar otras personas en el servidor. +message.search.service.not.available = No se ha podido contactar al servicio de búsqueda. +message.searching.please.wait = Buscando. Aguarde un momento... +message.select.add.room.to.add = Seleccione cuarto a agregar a la lista. +message.select.one.or.more = Seleccione uno o más usuarios de su lista de contactos. +message.select.room.to.enter = Especifique cuarto a ingresar. +message.select.room.to.join = Seleccione cuarto a ingresar. +message.send.a.broadcast = Difundir mensaje +message.send.file.to.user = Enviar archivos a este usuario. +message.send.picture = Enviar foto de su escritorio. +message.send.to.these.people = Enviar a estas personas +message.sending.file.to = Enviando archivo a {0}. +message.sent.offline.files = Ha recibido un archivo mientras estaba desconectado. +message.server.unavailable = No se puede conectar al servidor: nombre inválido o servidor no disponible. +message.service.already.exists = El servicio ya se encuentra en su lista de servicios. +message.shared.group = Grupo compartido +message.specify.contact.jid = Por favor especifique el JID del contacto (ej: ddman@jabber.org) +message.specify.group = Especificar Grupo de contactos para agregar al nuevo usuario. +message.specify.information.for.conference = Especifique información del cuarto de conferencia. +message.specify.name.error = Especifique un nombre válido. +message.specify.users.to.join.conference = Especifique usuarios a invitar al cuarto. +message.specify.valid.time.error = Especifique un tiempo máximo y un puerto válido. +message.subject.change.error = No está permitido cambiar el tema del cuarto. +message.subject.has.been.changed.to = El tema ha sido cambiado a {0}. +message.supply.resource = Especifique un recurso válido. +message.supply.valid.port = Especifique un puerto válido. +message.supply.valid.timeout = Especifique un tiempo máximo válido. +message.timeout.error = El tiempo máximo debe ser de al menos 5 segundos. +message.total.downloaded = Total descargado +message.transfer.cancelled = La transferencia del archivo ha sido cancelada. +message.transfer.rate = Tasa de Transferencia +message.transfer.refused = La transferencia del archivo ha sido rechazada. +message.transfer.waiting.on.user = Esperando que {0} acepte la transferencia del archivo. +message.unable.to.load.profile = No se ha encontrado un perfil para {0} +message.unable.to.retrieve.last.activity = No se pudo determinar la última actividad de {0} +message.unable.to.save.password = No se ha podido cambiar la contraseña. Contacte el administrador del servidor. +message.unable.to.send.file = No ha sido capaz de transferir el archivo a {0}. +message.unrecoverable.error = Usuario o contraseña no válida. +message.update.room.list = Actualizar lista de cuartos +message.updating.cancelled = La actualización ha sido cancelada. +message.user.banned = {0} ha sido censurado en este cuarto. +message.user.given.voice = {0} puede hablar en el cuarto. +message.user.granted.admin = {0} ha recibido permisos de administrador. +message.user.granted.membership = {0} ha recibido permisos de membresía. +message.user.granted.moderator = {0} ha recibido permisos de moderador. +message.user.granted.owner = {0} ha recibido permisos de dueño. +message.user.is.sending.you.a.file = {0} está enviando un archivo. +message.user.joined.room = {0} ha ingresado al cuarto. +message.user.kicked.from.room = {0} ha sido echado del cuarto. +message.user.left.room = {0} ha abandonado el cuarto. +message.user.nickname.changed = {0} es ahora conocido como {1}. +message.user.now.available.to.chat = {0} está en línea en {1} +message.user.revoked.admin = Los privilegios de administrador han sido removidos para {0}. +message.user.revoked.membership = La membresia ha sido revocada para {0}. +message.user.revoked.moderator = Los privilegios de moderador han sido removidos para {0}. +message.user.revoked.owner = Los privilegios de dueño han sido removidos para {0}. +message.user.voice.revoked = Voz ha sido removida para {0}. +message.username.error = Especificar nombre de usuario para la cuenta. +message.username.password.error = Debe ingresar un nombre de usuario o contraseña. +message.vcard.not.supported = El servidor no soporta VCards. No se ha podido salvar su VCard. +message.version = Versión: {0} +message.view.information.about.this.user = Ver información sobre este usuario. +message.waiting.for.user.to.join = Esperando que {0} se una. +message.went.offline = {0} se desconectó a las {1} +message.you.have.been.banned = Ha sido censurado en este cuarto. +message.you.have.been.kicked = Ha sido echado del cuarto. +message.you.have.sent = Ha enviado un archivo a {0}. +message.your.admin.granted = Se le han otorgado permisos de administrador. +message.your.banned = Ha sido censurado en esta conversación. +message.your.kicked = Has sido echado por {0}. +message.your.membership.granted = Se le han otorgado permisos de membresia. +message.your.membership.revoked = Su membresia ha sido revocada. +message.your.moderator.granted = Se le han otorgado permisos de moderador. +message.your.moderator.revoked = Sus privilegios de moderador han sido revocados. +message.your.ownership.granted = Se le han otorgado permisos de dueño. +message.your.ownership.revoked = Sus privilegios de dueño han sido revocados. +message.your.revoked.granted = Sus privilegios de administrador han sido revocados. +message.your.voice.granted = Se permitió el uso de voz en este chat. +message.your.voice.revoked = Su voz ha sido revocada. +no = No +not.registered = No registrado +occupants = Ocupantes +offline = Desconectado +ok = Ok +online = en línea +open = Abrir +open.folder = Abrir carpeta +participants = Participantes +reject = Rechazar +retry = Reintentar +room.name = Nombre del cuarto +save = Guardar + +status.away = Ausente +status.custom.messages = Mensaje personalizado +status.do.not.disturb = No molestar +status.extended.away = Ausencia extendida +status.free.to.chat = Libre para chatear +status.on.phone = Al telefono +status.online = En línea +status.pending = Pendiente +subject = Tema + +tab.available.plugins = Plugins disponibles +tab.avatar = Avatar +tab.business = Negocio +tab.conferences = Conferencias +tab.contacts = Contactos +tab.general = General +tab.home = Hogar +tab.installed.plugins = Plugins instalados +tab.personal = Personal +tab.proxy = Proxy + +title.about = Acerca de +title.account.create.registration = Registro de cuenta +title.account.created = Cuenta creada exitosamente +title.add.contact = Agregar contactos +title.add.contact.group = Agregar nuevo grupo de contactos +title.add.new.group = Agregar nuevo grupo +title.add.search.service = Agregar Servicio de Búsqueda +title.add.to.roster = Agregar a Lista de contactos +title.address = Dirección +title.advanced.connection.preferences = Preferencias avanzadas de conexión +title.alert = Alerta +title.appearance = Apariencia +title.appearance.preferences = Personalización +title.appearance.showVCards = Motrar VCards en la Lista de Contactos +title.available.transports = Transportes disponibles +title.broadcast.message = Difundir mensaje +title.browse.conference.services = Ver servicios de conferencia +title.browse.room.service = Buscar cuartos de conferencia - {0} +title.cancelled = Cancelado +title.change.nickname = Cambiar apodo +title.change.subject = Cambiar tema +title.chat = Chat +title.choose.directory = Seleccione carpeta +title.choose.incoming.sound = Seleccione archivo de sonido entrante +title.choose.offline.sound = Seleccione archivo de sonido no conectado +title.choose.outgoing.sound = Seleccione archivo de sonido saliente +title.conference.invitation = Invitación a conferencia +title.conference.rooms = Cuartos de conferencia +title.configure.chat.room = Configurar cuarto +title.configure.room = Configurar cuarto +title.confirmation = Confirmación +title.create.new.account = Crear nueva cuenta +title.create.or.bookmark.room = Ingresar o guardar cuarto como favorito +title.create.room = Crear / Ingresar +title.create.problem = Hubo un problema al crear la cuenta +title.delete.file = ¿Realmente quieres eliminar este archivo? +title.dial.phone = Discar teléfono +title.disable.transport = Deshabilitar transporte +title.download.complete = Descarga completa +title.downloading.im.client = Descargar Cliente IM +title.downloads = Descargas +title.edit.custom.message = Editar mensajes personalizados +title.edit.profile = Editar información de perfil +title.enter.reason = Ingresar motivo +title.error = Error +title.error.couldnot.open.file = ¡No se pudo abrir el archivo! Posiblemente un tipo de archivos desconocido. +title.error.delete.file = ¡No se pudo eliminar el archivo! +title.error.find.app = ¡No se pudo encontrar la aplicación! +title.error.rename.file = ¡No se pudo renombrar el archivo! +title.file = Archivo +title.file.exists = Archivo existe +title.file.transfer = Transferencias de archivos +title.file.transfer.preferences = Preferencias de transferencia de archivos +title.filesize = Tamaño +title.find.conference.service = Buscar servicio de conferencia +title.find.contacts = Buscar contactos +title.gadugadu.registration = Credenciales de cuentas GaduGadu +title.general.chat.settings = Configuración General de Chat +title.group.chat = Grupo de chat +title.group.chat.settings = Configuraciones de Chat grupal +title.history.for = Historial de conversación Con {0} +title.incoming.call = Llamada entrante +title.input.fileexplorer = Por favor ingrese el nombre del Explorador de Archivos +title.input.newname = Por favor ingrese el nuevo nombre: +title.input.openwith = Por favor ingrese el nombre de la aplicación que desea usar: +title.invite.to.conference = Invitar a conferencia +title.irc.registration = Registro de cuenta IRC +title.jabber.browser = Buscador +title.join.conference.room = Ingresar a cuarto de conferencia +title.last.activity = Última actividad +title.login = Ingresar +title.login.error = Error de inicio de sesión +title.login.settings = Configuración de Login +title.lookup.profile = Buscar Perfil +title.name = Nombre +title.new.client.available = Nuevo Cliente disponible +title.new.roster.group = Nuevo grupo de contactos +title.new.version.available = Nueva Versión disponible +title.no.updates = No hay actualizaciones +title.notes = Notas +title.notification = Notificación +title.notifications = Notificaciones +title.occupants = Ocupantes +title.on.the.phone = En el teléfono +title.password = Contraseña +title.passwords.no.match = Confirmar contraseñas. +title.person.search = Búsqueda de Personas +title.plugins = Plugins +title.preferences = Preferencias +title.profile.information = Información de Perfil +title.profile.not.found = Perfil No Encontrado +title.qq.registration = Credenciales de cuenta QQ +title.register.account = Registrar Nueva cuenta +title.registration.error = Error de registro +title.reminder = Recordatorio +title.rename.roster.group = Renombrar grupo +title.room.destroyed = Cuarto destruido +title.room.information = Información del cuarto +title.roster = Lista de contactos +title.select.file.to.send = Seleccione los archivo(s) para enviar +title.set.status.message = Configurar mensaje de estado +title.simple.registration = Credenciales de cuenta SIMPLE +title.sound.preferences = Preferencias de sonido +title.sounds = Sonidos +title.spark.preferences = Preferencias de Spark +title.start.chat = Comenzar conversación +title.status.message = Mensaje de estado +title.tasks = Tareas +title.transports = Transportes +title.tray.information = Información de bandeja +title.upgrading.client = Actualizando Cliente +title.version.and.time = Versión y Hora +title.view.bookmarks = Ver favoritos +title.view.profile.for = Viendo Perfil De {0} +title.view.room.information = Ver Información del cuarto +title.waiting.to.call = Esperando para hacer llamado +title.xmpp.registration = Credenciales de cuenta XMPP + +tooltip.appearance = Cambiar la apariencia de sus conversaciones. +tooltip.file.transfer = Preferencias de transferencia de archivos. +tooltip.notifications = Preferencias de notificación para conversaciones entrantes. +tooltip.place.voice.call = Realizar llamada de voz +tooltip.send.email = Enviar un correo electrónico +tooltip.start.chat = Comenzar una conversación +tooltip.view.changelog = Ver registro de cambios +tooltip.view.history = Ver historial de conversaciones +tooltip.view.readme = Ver archivo Leeme + +tree.conference.services = Servicios de conferencia +tree.users.in.room = Usuarios en el cuarto +unfiled = Sin clasificar +use.default = Usar predeterminado +user.has.signed.in = se ha conectado. +user.has.signed.off = se ha desconectado. +while.offline = mientras estaba desconectado +yes = Si + +administrator = Administrator +button.reject = Reject +button.login = &Login +button.re.detect = &Re-detect +checkbox.notify.typing.systemtray = &Show typing notification in the system tray +checkbox.notify.systemtray = Show new &messages in the system tray +checkbox.use.debugger.on.startup = Start debugger on startup +checkbox.use.krbconf = Use krb5.conf or krb5.ini +checkbox.use.krb.dns = Use DNS +checkbox.use.specify.below = Specify below +checkbox.use.pki.authentication = Use PKI authentication +label.na = n/a +label.cell = Cell +label.work = Work +label.home = Home +label.krb.realm = Realm +label.krb.kdc = KDC +label.which.pki.method = Which PKI method? +label.choose.file = Choose file +label.trust.store.password = Trust store password +label.enter.password = Enter password +label.move.focus.forwards = Move focus forwards +label.move.focus.backwards = Move focus backwards +label.keystore.location = Keystore location +label.truststore.location = Truststore location +label.pkcs.library.file = PKCS#11 library file +label.x509.certificate = X.509 certificate +label.apple.keychain = Apple KeyChain +label.add.to.roster = Add user to your roster +label.audio.device = &Audio device +label.video.device = &Video device +menuitem.bookmarks = Bookmarks +menuitem.add.groupchat.showjoinleavemessage = &Show join and leave messages +menuitem.add.groupchat.showrolesinsteadofstatus = Show chatroleicons instead of statusicons +menuitem.always.on.top = Always on top +menuitem.block.contact = Block contact +menuitem.unblock.contact = Unblock contact +menuitem.expand.all.groups = Expand all groups +menuitem.collapse.all.groups = Collapse all groups +menuitem.invite.again = Invite again +menuitem.chatframe.option = Options +message.invite.to.groupchat = {0} is inviting you to join a group chat +message.enter.sametime = Enter your Sametime username and password below +message.enter.facebook = Enter your Facebook username and password below +message.enter.myspace = Enter your MySpace username and password below +message.nickname.not.acceptable = Nickname change is not enabled! +message.groupchat.require.password = This group chat room requires a password to enter +message.search.for.history = Search conversation history +tab.sso = SSO +tab.pki = PKI +title.password.required = Password required +title.task.notification = Task notification +title.client.logs = Client logs +title.bookmarks = Bookmarks +title.advanced.connection.usesso = Use Single Sign-On (SSO) via GSSAPI +title.general.media = Media settings +title.sametime.registration = Sametime account credentials +title.facebook.registration = Facebook account credentials +title.myspace.registration = MySpace account credentials +title.subscription.request = Subscription request +tooltip.place.a.call = Place a call to this individual diff --git a/core/src/main/resources/i18n/spark_i18n_fi.properties b/core/src/main/resources/i18n/spark_i18n_fi.properties new file mode 100644 index 000000000..aabbfed7e --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_fi.properties @@ -0,0 +1,751 @@ +administrator = Pääkäyttäjä +apply = Ota käyttöön +ok = Ok +cancel = Peruuta +add = Lisää +use.default = Palauta oletukset +close = Sulje +create = Luo +invite = Kutsu +date = Päiväys +from = Lähettäjä +room.name = Huoneen nimi +join = Liity +description = Kuvaus +subject = Aihe +occupants = Osallistujat +accept = Hyväksy +answer = Vastaa +online = linjoilla +offline = Poissa linjoilta +reject = Hylkää +open = Avaa +open.folder = Avaa kansio +participants = Osallistujat +retry = Yritä uudelleen +is.active = Aktiivinen +not.registered = Ei rekisteröitynyt +save = Tallenna +unfiled = Luokittelematon +yes = Kyllä +no = Ei +while.offline = Poissaollessa +broadcast = Kuulutus +available = Paikalla +user.has.signed.in = kirjautui sisään. +user.has.signed.off = kirjautui ulos. +gateway.username.password.error = Käyttäjätunnus ja/tai salasana tarvitaan +delete.log.permanently = Poista logi +delete.permanently = Poista pysyvästi? + +action.clear = Tyhjennä +action.copy = Kopioi +action.cut = Leikkaa +action.paste = Liitä +action.print = Tulosta +action.save = Tallenna +action.select.all = Valitse kaikki + +button.create.account = &Lisää tili +button.close = &Sulje +button.advanced = &Asetukset +button.browse = &Selaa... +button.browse2 = S&elaa... +button.browse3 = Se&laa... +button.approve = &Hyväksy +button.deny = &Hylkää +button.accept = &Hyväksy +button.profile = &Profiili +button.add.a.contact = &Lisää yhteystieto +button.reconnect = &Yhdistä uudelleen +button.reconnect2 = Yhdistä uudelleen +button.add = &Lisää +button.add2 = Li&sää +button.roster = &Tuttavalista +button.add.bookmark = Lisää kirjanmerkki +button.remove.bookmark = Poista kirjanmerkki +button.bookmark.room = &Lisää huone kirjanmerkkeihin +button.create.room = &Luo huone +button.join.room = &Liity huoneeseen +button.refresh = &Virkistä +button.find = &Etsi +button.update = &Päivitä +button.cancel = &Peruuta +button.decline = &Kieltäydy +button.join = &Liity +button.save.for.future.use = &Tallenna myähempää käyttää varten +button.register = &Rekisteröidy +button.dial.number = &Valitse numero +button.clear = &Tyhjennä +button.search = &Etsi +button.add.service = &Lisää palvelu +button.quit = Lopeta +button.new = &Uusi +button.add.user = &Lisää käyttäjä +button.save = &Tallenna +button.start.chat = Aloita keskustelu +button.send.email = Sähköposti +button.send = Lähetä +button.copy.to.clipboard = Kopioi leikepöydälle +button.tasks.active = Aktiivisena +button.tasks.all = Kaikki +button.view.notes = Näytä muistiinpanot +button.view.profile = Näytä koko profiili +button.view.tasklist = Näytä tehtävälista +button.reject = Hylkää +button.login = &Kirjaudu +button.unset.file.explorer = Poista tiedostoselainvalinta +button.re.detect = &Havaitse uudelleen + +checkbox.save.password = &Tallenna salasana +checkbox.auto.login = &Kirjaudu automaattisesti +checkbox.use.proxy.server = &Käytä välityspalvelinta +checkbox.auto.discover.port = &Etsi isäntä ja portti automaattisesti +checkbox.permanent = Huone &pysyvästi käytössä +checkbox.private.room = Huone &on yksityinen +checkbox.show.time.in.chat.window = &näytä aika keskusteluikkunassa +checkbox.show.notifications.in.conference = &Näytä huomautukset ryhmäkeskustelussa +checkbox.disable.chat.history = &älä tallenna keskusteluhistoriaa +checkbox.show.toaster = Näytä &Popup tyyppiset tiedotusikkunat +checkbox.window.to.front = &Ikkuna päällimmäiseksi +checkbox.play.sound.on.new.message = Soita viestin &merkkiääni +checkbox.play.sound.when.offline = Soita merkkiääni &offline tiedotuksista +checkbox.play.sound.on.outgoing.message = Merkkiääni viestin &lähetyksestä +checkbox.play.sound.on.invitation = Soita merkkiääni &ryhmäkeskustelukutsusta +checkbox.idle.enabled = &Automaattinen poissaoloilmoitus +checkbox.launch.on.startup = &Käynnistä automaattisesti +checkbox.notify.user.comes.online = Ilmoita kun käyttäjä tulee linjoille +checkbox.notify.user.goes.offline = Ilmoita kun käyttäjä poistuu linjoilta +checkbox.start.in.tray = &Käynnistä Spark piilotettuna +checkbox.split.chat.window = &Erilliset keskusteluikkunat (vaatii uudelleenkäynnistyksen) +checkbox.tabs.on.top = &Keskusteluvälilehdet aukeavat päällimmäisiksi (vaatii uudelleenkäynnistyksen) +checkbox.tabs.scroll = Käytä vierittämistä chat-välilehdissä (vaatii uudelleenkäynnistyksen) +checkbox.allow.buzz = Sal&li muiden käyttäjien painaa summeria. +checkbox.enable.emoticons = Hy&miöt käytössä +checkbox.use.system.look.and.feel = Käytä järjestelmän &teemaa (vaatii uudelleenkäynnistyksen) +checkbox.use.compression = Käytä Pa&kkausta +checkbox.show.avatars.in.contactlist = Näytä &hahmot yhteystiedoissa +checkbox.use.debugger.on.startup = Käynnistä debuggeri käynnistyessä +checkbox.broadcast.hide.offline.user = Piilota poissaolevat +checkbox.use.krbconf = Käytä krb5.conf tai krb5.ini +checkbox.use.krb.dns = Käytä DNS +checkbox.use.specify.below = Määrittele alla +checkbox.use.pki.authentication = Käytä PKI tunnistautumista +checkbox.disable.prev.chat.history = E&stä aiempien keskustelujen näyttäminen +checkbox.notify.typing.systemtray = &Näytä kirjoitushälytys tehtäväpalkissa +checkbox.notify.systemtray = Näytä uudet &viestit tehtäväpalkissa +checkbox.close.unread.message = Kysy, kun suljet ikkunan, jos sinulla on lukemattomia viestejä + +label.user.on.public.network = Käyttäjä julkisessa verkossa +label.change.password.to = &Uusi salasana +label.username = &Käyttäjänimi +label.name = &Nimi +label.room.name = &Huoneen nimi +label.room.topic = Puheen&aihe +label.password = &Salasana +label.confirm.password = &Varmista salasana +label.server = Toi&mialueen +label.create.account = &Tee uusi tili +label.close = &Sulje +label.ok = OK +label.cancel = Peruuta +label.use.default = Palauta oletukset +label.port = &Portti +label.auto.login = &Automaattinen sisäänkirjautuminen +label.old.ssl = &Vanha SSL PORT salaus +label.host = &Isäntä +label.resource = &Resurssi +label.protocol = &Protokolla +label.accounts = &Tilit +label.transfer.timeout = &Siirron aikakatkaisu (min): +label.transfer.download.directory = &Lataushakemisto: +label.find = &Etsi +label.rename.to = Nimeä uudelleen +label.contact.to.find = Etsittävä yhteystieto? +label.available.users.in.roster = &Paikalla olevat käyttäjät tuttavalistassa +label.time = Aika: {0} +label.add.conference.service = &Lisää keskustelupalvelu +label.add.jid = &Lisää JID +label.add.task = Lisää tehtävä +label.due = Erääntyvä +label.chatroom.fontsize = Keskusteluhuoneen &kirjasinkoko: +label.chatroom.maxcurrenthistorysize = Nykyisen historian enimmäiskoko: +label.contactlist.fontsize = Yhteystietojen &kirjasinkoko: +label.contactlist.avatarsize = Yhteystietojen kuvien koko: +label.message = &Viesti +label.room = &Huone +label.invited.users = Kutsutut käyttäjät +label.new.nickname = Uusi lempinimi +label.server.address = &Palvelimen osoite +label.nickname = &Lempinimi +label.presence = &Läsnäolo +label.priority = K&iireellisyys +label.enter.address = Syötä osoite +label.jabber.address = &Jabber osoite +label.local.time = &Paikallinen aika +label.software = &Ohjelmisto +label.version = &Versio +label.os = &Käyttöjärjestelmä +label.show = Näytä: +label.timeformat = Käytä {0} +label.number = &Numero +label.dial = &Soita +label.minutes.before.stale.chat = &Hiljaisuuden kesto, jonka jälkeen huone muuttuu tunkkaiseksi(min) +label.company = &Yhtiö +label.street.address = &Katuosoite +label.city = &Kaupunki +label.state.and.province = L&ääni +label.postal.code = &Postinumero +label.country = &Maa +label.job.title = &Asema +label.department = &Osasto +label.phone = &Puhelin +label.fax = &Faksi +label.mobile = &Matkapuhelin +label.web.page = &Internetsivu +label.pager = &Piipperi +label.first.name = &Etunimi +label.middle.name = &Toinen etunimi +label.last.name = &Sukunimi +label.email.address = &Sähköpostiosoite +label.jid = &JID +label.search.service = &Hakupalvelu +label.xmpp.port = &XMPP Portti +label.response.timeout = &Vastauksen aikakatkaisu (sekuntia) +label.time.till.idle = &Aikaa joutilaana automaattiseen poissaolotilaan (min) +label.jabber.id = &Jabber ID +label.group = &Ryhmä +label.enter.group.name = Anna ryhmälle nimi +label.network = Verkko +label.unable.to.add.contact = Yhteystiedon lisäys ei onnistu +label.conflict.error = Kirjautuminen ei onnistu. Käyttäjä on kirjautunut sisään muualta +label.message.style = &Viestien ulkoasu +label.emoticons = &Hymiöt +label.cell = Kännykkä +label.work = Työ +label.home = Koti +label.downloads = Lataukset +label.received = Saapuneet +label.krb.realm = Piiri +label.krb.kdc = KDC +label.which.pki.method = Mikä PKI metodi? +label.choose.file = Valitse tiedosto +label.trust.store.password = Luota säilön salasanaan +label.enter.password = Anna salasana +label.move.focus.forwards = Siirrä kohdistin eteenpäin +label.move.focus.backwards = Siirrä kohdistin taaksepäin +label.keystore.location = Keystore sijainti +label.truststore.location = Truststore sijainti +label.pkcs.library.file = PKCS#11 kirjasto +label.x509.certificate = X.509 varmenne +label.add.to.roster = Lisää käyttäjä tuttavalistaasi +label.audio.device = &äänilaite +label.video.device = &Kuvalaite + +message = &Viesti +message.normal = Tavallinen viesti +message.alert.notify = Tiedota hälytyksistä +message.username.error = Anna tilille nimi. +message.password.error = Anna tilille salasana. +message.confirmation.password.error = Syötä salasanan vahvistus. +message.account.error = Syötä palvelin, jolle tili luodaan. +message.registering = Rekisteröidytään {0}. Ole hyvä ja odota... +message.connection.failed = Yhistäminen ei onnistu {0} +message.create.account = Tiliä ei voitu luoda. +message.already.exists = Tili on jo olemassa. +message.account.created = Tili luotu. +message.account.create = Luo uusi tili. +message.connecting.please.wait = Yhdistetään, ole hyvä ja odota... +message.supply.valid.timeout = Anna hyväksyttävä aikakatkaisu aika. +message.supply.valid.port = Syötä hyväksyttävä porttinumero. +message.supply.resource = Syötä hyväksyttävä resurssi. +message.current.status = Tiedota tilastasi ja toiminnoistasi muille. +message.disconnected.error = Yhteytesi suljettiin virheen takia. +message.disconnected.group.chat.error = Yhteytesi suljettiin virheen takia. Sinun täytyy liittyä keskusteluhuoneisiin uudelleen yhdistämisen jälkeen. +message.disconnected.conflict.error = Yhteytesi suljettiin, koska nimelläsi on kirjauduttu toisesta paikasta. +message.disconnected.shutdown = Yhteytesi suljettiin, koska palvelin sammutettiin. +message.locked.workstation = Tietokone lukittu +message.away.idle = Poissa tietokoneelta +message.default.error = Virhe havaittiin. Ole hyvä ja ilmoita siitä osoitteeseen support@jivesoftware.com. +message.new.message = Uusi viesti käyttäjältä {0}. +message.send.file.to.user = Lähetä tiedostoja tälle käyttäjälle. +message.send.picture = Kaappaa ja lähetä mitä vain ruudultasi. +message.send.to.these.people = Lähetä näille käyttäjille +message.sent.offline.files = Sinulle on lähetetty tiedostoja poissaolevalta käyttäjältä. +message.search.for.contacts = Etsi yhteystietoja. +message.end.conversation = Haluatko sulkea tämän keskustelun? +message.end.chat = Lopetetaanko ryhmäkeskustelu? +message.close.this.chat = Sulje tämä ryhmäkeskustelu +message.close.other.chats = Sulje muut ryhmäkeskustelut +message.close.stale.chats = Sulje pitkään hiljaisena olleet huoneet +message.close.unread.window = Sinulla on lukemattomia viestejä. Haluatko varmasti sulkea ikkunan? +message.last.message.received = Viimeisin viesti vastaanotettu {0} +message.shared.group = Jaettu ryhmä +message.is.shared.group = {0} on jaettu ryhmä. +message.delete.confirmation = Haluatko varmasti poistaa {0}? +message.idle.for = Joutilaana {0} minuuttia +message.enter.broadcast.message = Syötä valituille käyttäjille kuulutettava viesti. +message.name.of.group = Ryhmän nimi +message.approve.subscription = Sallitko käyttäjän {0} lisätä sinut yhteystietoihinsa? +message.add.user = Lisää käyttäjä yhteystietoihisi +message.general.error = Yhteys palvelimeen menetettiin {0} johdosta. +message.add.a.contact = Lisää yhteystieto +message.generic.reconnect.message = Yhteys palvelimeen menetettiin. Paina Yhdistä nappulaa kirjautuaksesi uudelleen. +message.select.one.or.more = Valitse yksi tai useampi käyttäjä yhteystiedoistasi. +message.add.conference.service = Lisää ryhmäkeskustelupalvelin. +message.service.already.exists = Palvelu on jo listattuna palvelulistassa. +message.searching.please.wait = Etsitään. Ole hyvä ja odota... +message.conference.service.error = Ryhmäkeskustelupalvelinta ei läydy +message.create.or.join.room = Liity ryhmäkeskusteluun tai luo uusi +message.specify.name.error = Anna hyväksyttävä nimi +message.password.private.room.error = Anna yksityiselle huoneelle salasana +message.passwords.no.match = Salasanat eivät täsmää. +message.enter.valid.jid = Syötä hyväksyttävä Jabber ID +message.please.join.in.conference = Ole hyvä ja liity ryhmäkeskusteluun. +message.invite.users.to.conference = Kutsu käyttäjiä ryhmäkeskusteluun. +message.specify.users.to.join.conference = Valitse tähän keskusteluhuoneeseen liittyvät käyttäjät. +message.no.room.to.join.error = Liityttäviä huoneita ei ole +message.participants.in.room = Huoneen keskustelijat +message.you.have.been.kicked = Sinut on potkittu pois huoneesta. +message.kicked.error = Et pysty potkimaan {0} pois tästä huoneesta. +message.you.have.been.banned = Sinulle on langetettu porttikielto tähän huoneeseen. +message.nickname.in.use = Nimimerkki on käytössä, valitse toinen nimimerkki ja yritä uudelleen +message.update.room.list = Virkistä huonelista +message.join.conference.room = Liity keskusteluhuoneeseen +message.select.add.room.to.add = Valitse palvelulistaan lisättävä huone. +message.bookmark.temporary.room.error = Väliaikaiseksi tarkoitettuja huoneita ei voi kirjanmerkitä. +message.select.room.to.join = Valitse huone johon haluat liittyä. +message.conference.info.error = Ryhmäkeskusteluista ei saatu tietoa. Yritä myöhemmin uudelleen. +message.add.favorite.room = Lisää suosikkihuone. +message.select.room.to.enter = Valitse huone johon haluat liittyä. +message.find.conference.services = Etsi ryhmäkeskustelupalvelimia +message.specify.information.for.conference = Anna keskusteluhuoneen tiedot. +message.no.description.available = Ei kuvausta saatavilla +message.no.subject.available = Ei aihetta saatavilla +message.room.information.for = Tiedot huoneelle {0} +message.view.information.about.this.user = Näytä käyttäjän tiedot +message.add.this.user.to.your.roster = Lisää käyttäjä tuttavalistaasi. +message.came.online = {0} on linjoilla {1} +message.went.offline = {0} meni pois linjoita {1} +message.offline.error = Käyttäjälle ei voi lähettää offline viestejä. +message.offline = Käyttäjä on poissa linjoilta ja saa viestin kirjautuessaan seuraavan kerran sisään. +message.is.typing.a.message = {0} kirjoittaa viestiä... +message.enter.new.subject = Kirjoita uusi aihe +message.confirm.destruction.of.room = Huoneen tuhoaminen poistaa kaikki käyttäjät huoneesta. Jatketaanko? +message.room.destruction.reason = Syy huoneen poistamiseen? +message.user.left.room = {0} poistui huoneesta. +message.user.joined.room = {0} tuli huoneeseen. +message.chat.session.ended = Keskustelu päättyi {0} +message.subject.change.error = Sinulla ei ole oikeuksia vaihtaa aihetta. +message.forbidden.error = Palvelin kielsi suorittamasi toiminnon. +message.gateway.username.error = Käyttäjänimi tarvitaan. +message.gateway.password.error = Salasana tarvitaan. +message.gateway.nickname.error = Nimimerkki tarvitaan. +message.room.destroyed = Huone tuhottiin. Tuhoamisen syy: {0} +message.subject.has.been.changed.to = Huoneen aiheeksi vaihdettiin "{0}". +message.user.kicked.from.room = {0} potkittiin ulos huoneesta. +message.user.given.voice = {0} sai luvan puhua tässä huoneessa +message.user.voice.revoked = Käyttäjältä {0} poistettiin lupa puhua. +message.user.banned = Käyttäjälle {0} annettiin porttikielto huoneeseen +message.user.granted.membership = Käyttäjälle {0} myönnettiin jäsenyys +message.user.revoked.membership = Jäsenyysoikeudet poistettiin käyttäjältä {0} +message.user.granted.moderator = {0} on nyt Moderaattori. +message.user.revoked.moderator = {0} ei enää ole Moderaattori. +message.user.granted.owner = {0} on huoneen omistaja. +message.user.revoked.owner = {0} ei enää ole huoneen omistaja. +message.user.granted.admin = {0} on nyt Järjestelmänvalvoja. +message.user.revoked.admin = Järjestelmänvalvojan oikeudet poistettiin käyttäjältä {0}. +message.user.nickname.changed = {0} vaihtoi nimimerkikseen {1}. +message.your.kicked = {0} potkaisi sinut ulos huoneesta. +message.your.voice.granted = Sinulle myönnettiin puheoikeus. +message.your.voice.revoked = Sinulta poistettiin puheoikeus. +message.your.banned = Sinulle annettiin porttikielto tähän huoneeseen. +message.your.membership.granted = Sinulle myönnettiin jäsenyys. +message.your.membership.revoked = Jäsenyytesi poistettiin. +message.your.moderator.granted = Sinulla on nyt Moderaattorin oikeudet. +message.your.moderator.revoked = Moderaattorin oikeutesi poistettiin. +message.your.ownership.granted = Sinulle on myönnetty huoneen omistajuus. +message.your.ownership.revoked = Omistajan oikeutesi tähän huoneeseen poistettiin. +message.your.admin.granted = Sinulle on myönnetty järjestelmänvalvojan oikeudet. +message.your.revoked.granted = Järjestelmänvalvojan oikeutesi poistettiin. +message.send.a.broadcast = Lähetä kuulutus +message.broadcast.from = Kuulutus henkilöltä {0} +message.enter.message.to.broadcast = Kirjoita viesti, joka kuulutetaan kaikille kontakteillesi. +message.broadcast.message.sent = Kuulutus lähetetty +message.broadcast.to = Kirjoita {0}:lle kuulutettava viesti +message.hasbeenbroadcast.to = Viesti kuulutettu:\n{0} +message.user.now.available.to.chat = {0} on nyt linjoilla {1} +message.user.is.sending.you.a.file = {0} lähettää sinulle tiedoston. +message.file.transfer.canceled = Tiedoston siirto peruttu. +message.negotiate.file.transfer = Tiedostonsiirrosta sovitaan. Hetkinen... +message.negotiate.stream = Yhteysvirtaa avataan. Odota hetki... +message.receiving.file = {0} tarjoaa tiedostoa +message.click.to.open = Avaa +message.error.during.file.transfer = Tiedostonsiirrossa tapahtui virhe. +message.transfer.refused = Vastaanottaja kieltäytyi siirrosta. +message.transfer.cancelled = Tiedostonsiirto peruttiin. +message.received.file = Sait tiedoston käyttäjältä {0}. +message.file.exists.question = Tiedosto on jo olemassa. Ylikirjoita? +message.transfer.waiting.on.user = Odotetaan, että {0} hyväksyy tiedoston siirron... +message.negotiation.file.transfer = Sovitaan tiedostonsiirrosta käyttäjän {0} kanssa. Odota hetki... +message.unable.to.send.file = Tiedostonlähetys käyttäjälle {0} ei onnistu. +message.sending.file.to = Lähetetään tiedostoa käyttäjälle {0}. +message.you.have.sent = Olet lähettänyt tiedoston käyttäjälle {0}. +message.file.transfer.rejected = Tiedostonsiirto käyttäjälle {0} hylättiin. +message.disable.transport = Poista kirjautumistiedot {0}? +message.register.transports = Rekisteröidy näihin siirtoprotokolliin +message.enter.simple = Anna SIMPLE käyttäjänimi ja salasana +message.enter.irc = Anna IRC käyttäjänimi ja salasana +message.enter.gadugadu = Anna GaduGadu käyttäjänimi ja salasana. +message.enter.qq = Syätä QQ numerosi ja salasanasi +message.username.password.error = Käyttäjänimi ja salasana tarvitaan. +message.registration.transport.failed = Siirtoprotokollan rekisteröinti epäonnistui. +message.client.information = Asiakasohjelman tiedot käyttäjälle {0} +message.calling = Soitetaan {0} +message.number.to.call = Anna numero, johon soitetaan +message.no.caller.id = Soittajan tunnistetta ei ole saatavilla +message.no.history.found = Keskusteluhistoriaa ei löytynyt tälle käyttäjälle. +message.prompt.plugin.uninstall = Haluatko poistaa lisäosan {0}? +message.loading.please.wait = Ladataan. Odota hetki... +message.plugins.not.available = Lisäosia tarjoavaan palvelimeen ei saada yhteyttä. +message.downloading = Ladataan {0} +message.downloading.spark.plug = Ladataan lisäosaa +message.unable.to.save.password = Salasanaa ei voitu tallentaa. Ota yhteyttä järjestelmänvalvojaan. +message.delete.all.history = Poista kaikki historiatiedot? +message.no.avatar.found = Henkilö ei ole asettanut itselleen hahmoa. +message.image.too.large = Kuva on liian suuri. Kuvan maksimikoko on 16 kilotavua. +message.save.profile = Tallentaaksesi muutokset paina nappia Tallenna. +message.unable.to.load.profile = Profiilin {0} lataaminen ei onnistu. +message.enter.jabber.id = Syötä Jabber ID +message.invalid.jabber.id = Antamasi Jabber ID ei ole kelvollinen +message.invalid.username.password = Virheellinen käyttäjänimi tai salasana +message.vcard.not.supported = Palvelin ei tue käyntikortteja. Käyntikorttiasi ei tallennettu. +message.search.service.not.available = Hakupalveluun ei saada yhteyttä. +message.no.results.found = Hakutuloksia ei läytynyt. +message.name.of.search.service.question = Hakupalvelun nimi? +message.search.for.other.people = Etsi palvelimelta muita käyttäjiä. +message.specify.valid.time.error = Anna hyväksyttävä katkaisuaika ja portti. +message.timeout.error = Aikakatkaisun rajan täytyy olla vähintään viisi sekuntia. +message.version = Versio: {0} +message.file.size = Tiedoston koko: {0} +message.restart.spark = Sinun täytyy sulkea ohjelma asentaaksesi uuden version, \n Käynnistetäänkö nyt? +message.restart.required = Muutosten toteuttamiseksi Spark täytyy käynnistää uudelleen. Käynnistetäänkö nyt? +message.updating.cancelled = Päivitys peruutettiin. +message.transfer.rate = Siirtonopeus +message.total.downloaded = Yhteensä ladattuna +message.new.spark.available = {0} on nyt saatavilla. Asennetaanko se nyt? +message.restart.spark.to.install = Ohjelma täytyy sulkea uuden version asennuksen ajaksi. Käynnistetäänkö ohjelma uudelleen nyt? +message.add.to.roster = Lisää tuttavalistaan +message.enter.room.password = Anna huoneen salasana +message.add.contact.to.list = Lisää käyttäjä yhteystiedoihin +message.authenticating = Tunnistaudutaan +message.invalid.status = Anna hyväksyttävä tilaviesti. +message.cannot.add.contact.to.shared.group = Et voi lisätä uusia henkilöitä jaettuun ryhmään. +message.specify.contact.jid = Anna yhteystiedon Jabber ID (esim. ddman@jabber.org) +message.invalid.jid.error = Antamasi JID on epäkelpo. +message.specify.group = Anna ryhmä johon uusi yhteystieto lisätään. +message.room.creation.error = Huonetta ei voitu luoda. +message.unable.to.retrieve.last.activity = Läsnäolotietoja ei saatu käyttäjälle {0} +message.buzz.alert.notification = Lähetä käyttäjälle summerihälytys. +message.buzz.sent = Käyttäjän summeria painettiin. +message.no.updates = Päivityksiä ei ole +message.reconnect.attempting = Yhdistetään... +message.reconnect.failed = Uudelleenyhdistys ei onnistunut +message.reconnect.wait = Yhdistetään uudelleen {0} sekunnin kuluttua. +message.server.unavailable = Palvelimeen ei saada yhteyttä, virheellinen nimi tai palvelin ei ole käytössä. +message.unrecoverable.error = Virheellinen käyttäjänimi tai salasana. +message.waiting.for.user.to.join = Odotellaan käyttäjän {0} liittymistä. +message.invite.to.groupchat = {0} pyytää sinua liittymään ryhmäkeskusteluun +message.enter.sametime = Anna Sametime tunnus ja salasana alla +message.enter.facebook = Anna Facebook tunnus ja salasana alla +message.enter.myspace = Anna MySpace tunnus ja salasana alla +message.enter.xmpp = Anna XMPP tunnus ja salasana alla +message.file.transfer.notification = Tiedostonlähetysilmoitus +message.file.transfer.short.message = lähettää tiedostoa nimeltä\: +message.file.transfer.chat.window = Tiedostonlähetyspyyntö: +message.nickname.not.acceptable = Lempinimen vaihto ei käytössä! +message.restart.spark.changes = Liitännäinen poistetaan seuraavan Sparkin käynnistyksen yhteydessä +message.groupchat.require.password = Tämä ryhmäkeskusteluhuone vaatii salasanan +message.search.for.history = Etsi keskusteluhistoriasta + +status.away = Poissa +status.custom.messages = Muokatut viestit +status.do.not.disturb = älä häiritse +status.extended.away = Poissa pitkään +status.free.to.chat = Vapaa keskustelemaan +status.on.phone = Puhelimessa +status.online = Linjoilla +status.pending = Tulossa linjoille + +title.about = Tietoja +title.passwords.no.match = Salasanat eivät täsmää, syötä ne uudelleen. +title.create.problem = Tilin luonnissa esiintyi ongelmia +title.account.created = Tili luotiin +title.create.new.account = Tee uusi tili +title.account.create.registration = Tilin rekisteröinti +title.register.account = Uusi tili rekisteröitiin +title.notification = Tiedonanto +title.advanced.connection.preferences = Edistyneet yhteysasetukset +title.preferences = Asetukset +title.error = Virhe +title.status.message = Tila Viesti +title.spark.preferences = Spark Asetukset +title.alert = Varoitus +title.tray.information = Tray Information +title.select.file.to.send = Valitse lähetettävät tiedostot +title.choose.directory = Valitse hakemisto +title.confirmation = Varmistus +title.last.activity = Viimeisin toimenpide +title.add.new.group = Lisää uusi ryhmä +title.add.to.roster = Lisää tuttavalistaan +title.find.contacts = Etsi yhteystietoja +title.rename.roster.group = Uudelleennimeä tuttavaryhmä +title.roster = Tuttavalista +title.create.room = Luo +title.conference.rooms = Keskusteluhuone +title.invite.to.conference = Kutsu keskusteluhuoneeseen +title.room.information = Huoneeen tiedot +title.change.nickname = Vaihda lempinimeä +title.group.chat = Ryhmäkeskustelu +title.create.or.bookmark.room = Liity tai lisää huone kirjanmerkkeihin +title.browse.room.service = Selaa keskusteluhuoneita - {0} +title.name = Nimi +title.address = Osoite +title.occupants = Osallistujat +title.browse.conference.services = Selaa keskustelupalvelinta +title.find.conference.service = Etsi keskustelupalvelu +title.configure.chat.room = Keskusteluhuoneen asetukset +title.conference.invitation = Kutsu keskusteluhuoneeseen +title.join.conference.room = Liity keskusteluhuoneeseen +title.view.room.information = Huoneen tiedot +title.configure.room = Huoneen asetukset +title.change.subject = Vaihda puheenaihetta +title.enter.reason = Anna syy +title.room.destroyed = Huone tuhottu +title.edit.custom.message = Muokkaa viestiä itse +title.set.status.message = Aseta tilaviesti +title.broadcast.message = Kuulutus +title.start.chat = Aloita keskustelu +title.view.bookmarks = Näytä kirjanmerkit +title.downloads = Lataukset +title.file.exists = Tiedosto on olemassa +title.disable.transport = Poista kirjautumistunnukset +title.available.transports = Käytössä olevat siirtoprotokollat +title.transports = Siirtoprotokollat +title.qq.registration = QQ Tilitiedot +title.simple.registration = SIMPLE Tilitiedot +title.irc.registration = IRC Tilitiedot +title.gadugadu.registration = GaduGadu Tilitiedot +title.registration.error = Virhe rekisteröityessä +title.jabber.browser = Selain +title.version.and.time = Versio ja aika +title.waiting.to.call = Odotetaan puhelun yhdistymistä +title.incoming.call = Saapuva puhelu +title.on.the.phone = Puhelimessa +title.dial.phone = Valitse numero +title.history.for = Historiatiedot käyttäjälle {0} +title.reminder = Muistutus +title.plugins = Lisäosat +title.general.chat.settings = Yleiset keskusteluasetukset +title.chat = Keskustelu +title.notifications = Huomautukset +title.sound.preferences = ääniasetukset +title.sounds = äänet +title.choose.incoming.sound = Saapuvan viestin merkkiääni +title.choose.outgoing.sound = Lähtevän viestin merkkiääni +title.choose.offline.sound = Poissaolon merkkiääni +title.edit.profile = Muokkaa profiilia +title.profile.information = Profiilin tiedot +title.profile.not.found = Profiilia ei löydy +title.view.profile.for = Profiili käyttäjälle {0} +title.lookup.profile = Profiilin tarkistus +title.add.search.service = Lisää hakupalvelu +title.person.search = Etsi henkilöä +title.login.settings = Kirjautumisasetukset +title.login = Kirjaudu +title.downloading.im.client = Lataa pikaviestiohjelma +title.upgrading.client = Ohjelman päivitys +title.cancelled = Peruutettu +title.new.version.available = Uusi versio saatavilla +title.new.client.available = Uusi asiakasohjelma saatavilla +title.password = Salasana +title.download.complete = Lataus valmistui +title.new.roster.group = Uusi tuttavalistan ryhmä +title.add.contact.group = Lisää uusi ryhmä +title.add.contact = Lisää uusi yhteystieto +title.file.transfer.preferences = Tiedostojen siirron asetukset +title.file.transfer = Tiedostojen siirrot +title.appearance = Ulkoasu +title.appearance.preferences = Tuunaus +title.login.error = Virhe kirjautuessa +title.no.updates = Ei päivityksiä +title.notes = Muistiinpanot +title.tasks = Tehtävät +title.password.required = Salasana vaaditaan +title.task.notification = Tehtäväilmoitus +title.client.logs = Työasemalogit +title.bookmarks = Kirjanmerkit +title.advanced.connection.usesso = Käytä kertakirjautumista (SSO) GSSAPI:n kautta +title.delete.file = Halutatko todella poistaa tiedoston? +title.error.couldnot.open.file = Tiedoston avaus ei onnistu +title.error.delete.file = Tiedoston poisto ei onnistu +title.error.find.app = Sovellusta ei löytynyt +title.error.rename.file = Tiedoston nimen muutos ei onnistu +title.file = Tiedosto +title.filesize = Koko +title.general.media = Media-asetukset +title.group.chat.settings = Ryhmäkeskusteluasetukset +title.sametime.registration = Sametime tunnuksen tiedot +title.facebook.registration = Facebook tunnuksen tiedot +title.myspace.registration = MySpace tunnuksen tiedot +title.input.fileexplorer = Anna tiedostoselaimesi nimi: +title.input.newname = Anna uusI nimi\: +title.input.openwith = Anna käytettävän sovelluksen nimi: +title.xmpp.registration = XMPP tunnuksen tiedot +title.appearance.showVCards = Näytä &VCardit yhteystiedoissa +title.subscription.request = Lisäyspyyntö + +menuitem.connect = Tiedosto +menuitem.contacts = Tuttavat +menuitem.actions = Toiminnot +menuitem.exit = Sulje +menuitem.plugins = Liitännäiset +menuitem.logout.no.status = Kirjaudu ulos +menuitem.logout.with.status = Kirjaudu ulos ja aseta tila +menuitem.show.traffic = Näytä liikenne +menuitem.check.for.updates = Tarkista päivitykset? +menuitem.help = Ohjeet +menuitem.preferences = Asetukset +menuitem.about = Tietoja +menuitem.online.help = Online-tuki +menuitem.open = Avaa +menuitem.hide = Piilota +menuitem.status = Tila +menuitem.view.downloads = Näytä lataukset +menuitem.save = Tallenna +menuitem.add = Lisää +menuitem.add.contact = Lisää yhteystieto +menuitem.add.contact.group = Lisää yhteysryhmä +menuitem.remove.from.group = Poista ryhmästä +menuitem.start.a.chat = Aloita keskustelu +menuitem.rename = Nimeä uudelleen +menuitem.delete = Poista +menuitem.edit = Muokkaa +menuitem.remove.from.roster = Poista tuttavalistasta +menuitem.view.profile = Näytä profiili +menuitem.subscribe.to = Liity jäseneksi +menuitem.send.a.message = Viestin lähetys... +menuitem.show.empty.groups = Näytä tyhjät ryhmät +menuitem.send.a.file = Tiedostonsiirto +menuitem.view.last.activity = Näytä viimeisimmät aktiivisuustiedot +menuitem.unban = Poista porttikielto +menuitem.ban = Aseta porttikielto +menuitem.browse.service = Selaa palvelua +menuitem.remove.service = Poista palvelu +menuitem.join.room = Liity huoneeseen +menuitem.remove.bookmark = Poista kirjanmerkki +menuitem.join.on.startup = Liity käynnistyksen yhteydessä +menuitem.view.room.info = Näytä huoneen tiedot +menuitem.remove = Poista +menuitem.change.nickname = Vaihda lempinimeä +menuitem.block.user = Estä käyttäjä +menuitem.unblock.user = Pura esto käyttäjältä +menuitem.kick.user = Potkaise käyttäjä ulos +menuitem.voice = Puheoikeus +menuitem.revoke.voice = Mykistä käyttäjä +menuitem.grant.voice = Anna puheoikeus +menuitem.ban.user = Anna porttikielto käyttäjälle +menuitem.grant.moderator = Anna moderointioikeudet +menuitem.revoke.moderator = Poista moderointioikeudet +menuitem.invite.users = Kutsu käyttäjiä +menuitem.invite.group.to.conference = Kutsu ryhmäkeskusteluun +menuitem.start.a.conference = Aloita ryhmäkeskustelu... +menuitem.change.subject = Vaihda puheenaihetta +menuitem.destroy.room = Tuhoa huone +menuitem.set.status.message = Aseta tilaviesti... +menuitem.edit.status.message = Muokkaa tilaviestiä... +menuitem.broadcast.to.group = Kuuluta ryhmälle +menuitem.alert.when.online = Hälytä käyttäjän tullessa linjalle +menuitem.remove.alert.when.online = Poista hälytys +menuitem.save.as = Tallenna nimellä... +menuitem.view.client.version = Asiakasohjelman tiedot +menuitem.view.contact.history = Näytä yhteyshistoria +menuitem.edit.my.profile = &Muokkaa profiiliasi... +menuitem.lookup.profile = &Profiilin tarkastelu... +menuitem.add.as.contact = Lisää yhteystiedoksi +menuitem.chat = Keskustele +menuitem.sign.in = Liity +menuitem.sign.out = Poistu +menuitem.sign.in.at.login = Liity kirjautumisen yhteydessä +menuitem.enter.login.information = Syötä kirjautumistiedot +menuitem.delete.login.information = Poista kirjautumistiedot +menuitem.show.offline.group = Näytä poissaolevat tuttavat +menuitem.move.to = Siirrä kohteeseen +menuitem.copy.to = Kopioi kohteeseen +menuitem.user.guide = Käyttöopas +menuitem.languages = Valitse kieli +menuitem.dial = Soita +menuitem.view.logs = Näytä logit +menuitem.bookmarks = Kirjanmerkit +menuitem.add.groupchat.myname = Korosta &nimeni kun joku kirjottaa sen +menuitem.add.groupchat.mytext = &Korosta tekstini kun kirjoitan jotain +menuitem.add.groupchat.popname = Näytä &tiedotusikkuna-popup kun joku kirjoittaa nimeni +menuitem.add.groupchat.showjoinleavemessage = &Näytä liittymis- ja poistumisviestit +menuitem.add.groupchat.showrolesinsteadofstatus = Näytä keskusteluroolikuvakkeet tilakuvakkeiden sijaan +menuitem.always.on.top = Aina päällimmäisenä +menuitem.open.with = Käytä avaamiseen... +menuitem.block.contact = Estä henkilö +menuitem.unblock.contact = Pura henkilön esto +menuitem.show.offline.users = Näytä poissaolevat +menuitem.show.contact.statusmessage = Näytä tilaviesti +menuitem.bookmark.room = Kirjanmerkki huoneesta +menuitem.refresh = Päivitä +menuitem.create.room = Luo tai liity huoneeseen +menuitem.expand.all.groups = Laajenna kaikki ryhmät +menuitem.collapse.all.groups = Tiivistä kaikki ryhmät +menuitem.invite.again = Kutsu uudelleen +menuitem.chatframe.option = Valinnat + +tree.conference.services = Keskustelupalvelut +tree.users.in.room = Huoneen keskustelijat + +tab.general = Yleinen +tab.proxy = Välityspalvelin +tab.contacts = Yhteystiedot +tab.installed.plugins = Asennetut lisäosat +tab.available.plugins = Saatavilla olevat lisäosat +tab.personal = Henkilökohtaiset +tab.business = Työ +tab.home = Koti +tab.avatar = Hahmo +tab.conferences = Ryhmäkeskustelut + +group.connection = Yhteys +group.conferences.found = Löytyneet ryhmäkeskustelut +group.comma.delimited = Pilkuin erotettu +group.general.information = Yleiset tiedot +group.chat.window.information = Keskusteluikkunan tiedot +group.notification.options = Huomautusten valinnat +group.search.form = Hakulomake +group.search.results = Hakutulokset +group.login.information = Kirjautumistiedot +group.empty = Tässä ryhmässä ei ole linjoilla olevia käyttäjiä. +group.offline = Poissa linjoilta +group.chat.name.notification = Nimesi on nähty... +group.chat.name.match = Nimesi on kirjoitettu ryhmäkeskustelussa: + +tooltip.place.a.call = Soita tälle henkilölle +tooltip.view.history = Näytä historiatiedot +tooltip.view.changelog = Näytä muutoshistoria +tooltip.view.readme = Näytä LueMinut tiedote +tooltip.notifications = Tiedoteasetukset saapuville keskusteluille. +tooltip.place.voice.call = Soita VOIP-puhelu. +tooltip.appearance = Vaihda keskusteluikkunoiden tyyliä. +tooltip.file.transfer = Tiedostonsiirron asetukset +tooltip.send.email = Lähetä sähköposti. +tooltip.start.chat = Aloita keskustelu. + +label.na = n/a +label.apple.keychain = Apple KeyChain +tab.sso = SSO +tab.pki = PKI diff --git a/core/src/main/resources/i18n/spark_i18n_fr.properties b/core/src/main/resources/i18n/spark_i18n_fr.properties new file mode 100644 index 000000000..5913da15f --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_fr.properties @@ -0,0 +1,853 @@ +## French Translation by Ben LeBlond & Jonathan Pitre +## ben@jivesfotware.com - jakeld@gmail.com +## August 2011 +## +## http://people.w3.org/rishida/tools/conversion/ +## à = à +## â = â +## ç = ç +## é = é +## è = è +## ê = ê +## ô = ô +## î = î +## +## Translation updated by Eric Ficheux +## May 2014 + +accept = Accepter +is.active = Actif +add = Ajouter +administrator = Administrateur +apply = Appliquer +available = Disponible +broadcast = Diffuser un message a tout le monde +cancel = Annuler +close = Fermer +create = Créer +date = Date +description = Description +from = De +invite = Inviter +join = Rejoindre +no = Non +not.registered = Non enregistré +occupants = Occupants +offline = Déconnecté +online = Connecté +ok = OK +open = Ouvrir +open.folder = Ouvrir Répertoire +participants = Participants +reject = Refuser +retry = Réessayer +room.name = Nom du Salon +save = Sauver +refresh = Refresh +subject = Sujet +unfiled = Non classé +use.default = Utiliser les valeurs par défaut +user.has.signed.in = s'est connecté. +user.has.signed.off = s'est déconnecté. +while.offline = Pendant que vous êtiez hors ligne +yes = Oui + +action.clear = Vider +action.copy = Copier +action.cut = Couper +action.paste = Coller +action.print = Imprimer +action.save = Sauver +action.select.all = Tout sélectionner + +button.accept = &Accepter +button.add = &Ajouter +button.add.a.contact = &Ajouter un Contact +button.add.bookmark = &Ajouter un Signet +button.add.service = &Ajouter un Service +button.add.user = Ajouter un utilisateur +button.add2 = Ajouter +button.advanced = A&vancé +button.approve = &Approuver +button.bookmark.room = Salle de Discussion &Favorite +button.browse = &Parcourir +button.browse2 = P&arcourir +button.browse3 = Pa&rcourir +button.cancel = &Annuler +button.clear = &Effacer +button.close = &Fermer +button.copy.to.clipboard = Copier vers le presse-papier +button.create.account = &Créer un Compte +button.create.room = &Créer ou Joindre une Salle de Discussion +button.decline = &Refuser +button.deny = &Refuser +button.dial.number = &Composer Numéro +button.find = &Rechercher +button.join = &Entrer +button.join.room = &Joindre la Salle de Discussion Selectionnée +button.login = &Connexion +button.new = &Nouveau +button.profile = &Profil +button.quit = &Quitter +button.re.detect = &Re-détecter +button.reconnect = &Reconnecter +button.reconnect2 = &Reconnecter +button.refresh = &Actualiser +button.register = &S'enregistrer +button.reject = Refuser +button.remove.bookmark = Supprimer le Signet +button.roster = &Liste de Contacts +button.save = Sauver +button.save.for.future.use = &Sauvegarder pour plus tard +button.search = &Rechercher +button.send = Envoyer +button.send.email = Email +button.start.chat = Discuter +button.tasks.active = Actif +button.tasks.all = Tout +button.unset.file.explorer = Déselectionné le navigateur de fichier +button.update = &Mettre à jour +button.view.notes = Voir les notes +button.view.profile = Voir le profil complet +button.view.tasklist = Voir la liste des tâches + +checkbox.allow.buzz = Autoriser les contacts à vous interpeller +checkbox.auto.discover.port = &Détecter automatiquement l'hôte et le port +checkbox.auto.login = &Login Automatique +checkbox.broadcast.hide.offline.user = Cacher les contacts déconnectés +checkbox.disable.chat.history = &Désactiver l'Historique de Conversation +checkbox.disable.prev.chat.history = &Désactiver l'afichage des conversations précédentes dans le chat +checkbox.enable.emoticons = &Activer les smileys +checkbox.idle.enabled = &Mise en Veille Activée +checkbox.launch.on.startup = &Lancer au Démarrage +checkbox.notify.systemtray = Afficher les nouveaux &messages dans la barre d'état du systeme +checkbox.notify.typing.systemtray = &Affcher l'indicateur de frappe dans la barre d'état du systeme +checkbox.notify.user.comes.online = Me notifier quand un contact se &connecte +checkbox.notify.user.goes.offline = Me ¬ifier quand un contact se déconnecte +checkbox.permanent = Le salon est &permanent +checkbox.play.sound.on.invitation = Alerte sonore lors d'une &invitation +checkbox.play.sound.on.new.message = Alerte sonore lors d'un &nouveau message +checkbox.play.sound.on.outgoing.message = Alerte sonore lors de l'envoi d'un message +checkbox.play.sound.when.offline = Alerte sonore lorsqu'un utilisateur se &déconnecte +checkbox.private.room = Salon de Discussion Privé +checkbox.reconnect.panel.big = Afficher en tant que panneau +checkbox.reconnect.panel.icon = Afficher en tant qu'icône +checkbox.reconnect.panel.small = Afficher dans le groupe de contact +checkbox.reconnect.info = Indiquez le type d'affichage à utiliser pour la reconnexion: +checkbox.save.password = &Enregistrer le Mot de Passe +checkbox.show.avatars.in.contactlist = Afficher les &avatars +checkbox.show.notifications.in.conference = &Afficher les Notifications en Conférence +checkbox.show.time.in.chat.window = &Afficher l'heure dans la fenêtre de conversation +checkbox.show.toaster = Afficher une notification &Popup +checkbox.split.chat.window = Réduire les &fenêtres (Nécessite de redémarrer Spark) +checkbox.start.in.tray = &Démarrer dans la zone d'iconification +checkbox.tabs.on.top = Fenêtre de discussion toujours visible (nécessite de redémarrer) +checkbox.tabs.scroll = Utiliser le défilement pour les onglets de chat (nécessite un redémarrage) +checkbox.use.compression = Utiliser la compression +checkbox.use.debugger.on.startup = Lancer le débugger au démarrage +checkbox.use.proxy.server = &Utiliser un Proxy +checkbox.use.system.look.and.feel = Utiliser l'ergonomie du système (nécessite de redémarrer) +checkbox.window.to.front = &Mettre la fenêtre en premier plan +checkbox.use.krbconf = Utilier krb5.conf ou krb5.ini +checkbox.use.krb.dns = Utilier le DNS +checkbox.use.specify.below = Indiquer ci-dessous +checkbox.use.pki.authentication = Utiliser l'authentification par PKI +checkbox.transport.tab.setting = Montrer les types de transports disponibles dans un onglet (redémarrage nécessaire) +checkbox.conference.tab.setting = Montrer les services de conférence disponibles dans un onglet (redémarrage nécessaire) +checkbox.close.unread.message = Demander à la fermeture de la fenêtre s'il y a des messages non lus + +delete.log.permanently = Effacer les logs définitivement +delete.permanently = Effacer définitivement? + +gateway.username.password.error = Identifiant et/ou mot de passe requis + +group.chat.name.match = Votre nom a été prononcé dans une conversation: +group.chat.name.notification = Quelqu'un parle de vous... +group.chat.window.information = Infos de la fenêtre de chat +group.comma.delimited = Délimité par virgule (CSV) +group.conferences.found = Services de conférence +group.connection = Connexion +group.empty = Il n'y a pas de contact connecté dans ce groupe +group.general.information = Infos Générales +group.login.information = Infos Login +group.notification.options = Options de Notification +group.offline = Contacts déconnectés +group.search.form = Formulaire de Recherche +group.search.results = Resultats de Recherche + +label.accounts = &Comptes +label.add.conference.service = &Ajouter un Service de Conférence +label.add.jid = &Ajouter JID +label.add.task = Ajouter une tâche +label.auto.login = &Auto Login +label.audio.device = &Périphérique Audio +label.available.users.in.roster = &Contacts disponibles +label.cancel = Annuler +label.cell = Cell +label.change.password.to = &Changer le mot de passe +label.chatroom.fontsize = Taille de la &police de la fenêtre de discussion: +label.chatroom.maxcurrenthistorysize = Taille maximale de l'historique actuel: +label.choose.file = Choisissez un fichier +label.city = &Ville +label.close = F&ermer +label.company = &Société +label.confirm.password = &Confirmez le mot de passe +label.conflict.error = Impossible de vous connecter: vous êtes déjà connecté +label.contact.to.find = Contact a Rechercher? +label.contactlist.avatarsize = Taille des avatars dans la liste de contacts: +label.contactlist.fontsize = Taille de la police de la liste des contacts: +label.country = P&ays +label.create.account = Créer un compte +label.department = Département +label.dial = &Numéroter +label.downloads = Téléchargements +label.due = Pour le +label.email.address = &Adresse Email +label.emoticons = &Smileys +label.enter.address = Entrez l'Adresse +label.enter.group.name = Entrez un nouveau nom de groupe +label.enter.password = Entrez le mot de passe +label.fax = &Fax +label.find = &Rechercher +label.first.name = &Prénom +label.frequent.contacts = Frequent Contacts +label.group = &Groupe +label.home = Maison +label.host = &Hôte +label.invited.users = Utilisateurs Invités +label.jabber.address = &Adresse Jabber +label.jabber.id = &Jabber ID +label.jid = &JID +label.job.title = &Fonction +label.keystore.location = Keystore location +label.krb.kdc = KDC +label.krb.realm = Realm +label.last.name = &Nom de famille +label.local.time = &Heure Locale +label.message = &Message +label.message.style = Style du message +label.middle.name = &Deuxième prénom +label.minutes.before.stale.chat = &Nombre de minutes avant qu'un salon de discussion inactif soit suspendu +label.mobile = &Mobile +label.move.focus.backwards = Déplacer le focus vers l'arrière +label.move.focus.forwards = Déplacer le focus vers l'avant +label.na = sans objet +label.name = &Nom +label.network = Réseau +label.new.nickname = Nouveau Pseudo +label.nickname = &Pseudo +label.number = &Numéro +label.ok = OK +label.old.ssl = &Utiliser l'ancienne méthode SSL +label.os = &Système d'exploitation +label.pager = &Pager +label.password = &Mot de Passe +label.passwordreset = Réinitialiser le mot de passe +label.phone = &Téléphone +label.pkcs.library.file = PKCS#11 library file +label.port = &Port +label.postal.code = &Code Postal +label.presence = &Présence +label.priority = P&riorité +label.protocol = &Protocole +label.received = Recu +label.recent.conversation = Conversations récentes +label.rename.to = &Renommer +label.resource = &Resource +label.response.timeout = &Temps maximal de réponse (sec) +label.room = &Salon +label.room.name = &Nom du Salon +label.room.topic = &Thème +label.search.service = &Service de Recherche +label.server = Do&maine +label.server.address = &Adresse du Serveur +label.show = Montrer: +label.software = &Logiciel +label.state.and.province = Etat ou Province +label.street.address = &Adresse Postale +label.time = Heure\: (0) +label.time.till.idle = &Temps maximum avant mise en veille (min) +label.time.till.idlemessage = Message d'absence automatique +label.timeformat = Utilise {0} +label.transfer.download.directory = &Répertoire de Téléchargement +label.transfer.timeout = &Temps d'attente maximal pour un transfert de fichier (min)\: +label.trust.store.password = Trust store password +label.truststore.location = Truststore location +label.unable.to.add.contact = Impossible d'ajouter le contact +label.use.default = Utiliser les valeurs par défaut +label.user.on.public.network = L'utilisateur est sur un réseau public +label.username = &Nom d'utilisateur +label.version = &Version +label.video.device = &Périphérique Vidéo +label.web.page = &Site Web +label.which.pki.method = Quel type de PKI? +label.work = Travail +label.x509.certificate = Certificat X.509 +label.xmpp.port = &Port XMPP + +lookandfeel.change.now = Changer maintenant +lookandfeel.color.blue = Bleu +lookandfeel.color.green = Vert +lookandfeel.color.label = Couleurs +lookandfeel.color.opacity = Opacité +lookandfeel.color.red = Rouge +lookandfeel.color.saved = Couleur enregistrée +lookandfeel.select = Choisir l'apparence +lookandfeel.tooltip.restart.no = Redémarrage non nécessaire +lookandfeel.tooltip.restart.yes = Pour choisir une apparence, cliquer sur sauver et redémarrer Spark. + +menuitem.about = A propos +menuitem.actions = Actions +menuitem.add = Ajouter +menuitem.add.as.contact = Ajouter en tant que Contact +menuitem.add.contact = Ajouter Contact +menuitem.add.contact.group = Ajouter Groupe de Contact +menuitem.add.groupchat.auto.accept.invite = &Accepter automatiquement les invitations à une discussion de groupe +menuitem.add.groupchat.myname = Mettre mon &nom en évidence quand quelqu'un me cite +menuitem.add.groupchat.mytext = Mettre en évidence le texte que j'écris +menuitem.add.groupchat.popname = Afficher un &popup quand quelqu'un cite mon nom +menuitem.add.groupchat.random.colors = Couleurs aléatoires pour les noms +menuitem.add.groupchat.showjoinleavemessage = &Afficher les messages d'arrivée et de départ +menuitem.add.groupchat.showrolesinsteadofstatus = Afficher les icônes de rôle à la place des icônes de statut +menuitem.affiliation = Affiliation +menuitem.alert.when.online = Notifier lorsque l'utilisateur est disponible +menuitem.always.on.top = Toujours visible +menuitem.ban = Bannir +menuitem.ban.user = Bannir l'utilisateur +menuitem.block.contact = Bloquer un contact +menuitem.block.user = Bloquer l'utilisateur +menuitem.bookmark.room = Ajouter le salon dans les marques pages +menuitem.bookmarks = Marques-pages +menuitem.broadcast.to.group = Envoyer un message à tout le groupe +menuitem.browse.service = Voir les Services +menuitem.change.nickname = Changer de Nickname +menuitem.change.subject = Changer le Sujet +menuitem.chat = Conversation +menuitem.chatframe.option = Options +menuitem.check.for.updates = Mettre à jour +menuitem.collapse.all.groups = Réduire tous les groupes +menuitem.connect = Fichier +menuitem.contacts = Contacts +menuitem.copy.to = Copier vers +menuitem.create.room = Créer ou rejoindre un salon +menuitem.delete = Effacer +menuitem.delete.login.information = Supprimer les informations d'identification +menuitem.destroy.room = Fermer le Salon +menuitem.dial = Composer +menuitem.edit = Editer +menuitem.edit.my.profile = &Editer mon Profil +menuitem.edit.status.message = Editer les messages personalisés... +menuitem.enter.login.information = Entre les informations d'identification +menuitem.exit = Sortir +menuitem.expand.all.groups = Afficher le contenu de tous les groupes +menuitem.grant.admin = Rendre admin +menuitem.grant.member = Rendre membre +menuitem.grant.owner = Rendre propriètaire +menuitem.grant.moderator = Rendre Modérateur +menuitem.grant.voice = Voice +menuitem.help = Aide +menuitem.hide = Cacher +menuitem.invite.again = Inviter de nouveau +menuitem.invite.group.to.conference = Inviter le groupe à cette conférence +menuitem.invite.users = Inviter Utilisateurs +menuitem.join.on.startup = Rejoindre au Démarrage +menuitem.join.room = Rejoindre le Salon +menuitem.kick.user = Kicker l'Utilisateur +menuitem.languages = Langages +menuitem.logout.no.status = Fermer cette Session +menuitem.logout.with.status = Fermer cette Session avec un message +menuitem.lookup.profile = &Rechercher le Profil +menuitem.move.to = Déplacer vers +menuitem.online.help = Aide en Ligne +menuitem.open = Ouvrir +menuitem.open.with = Ouvrir avec... +menuitem.plugins = Plugins +menuitem.preferences = Préférences +menuitem.refresh = Rafraichir +menuitem.remove = Enlever +menuitem.remove.alert.when.online = Enlever l'Alerte +menuitem.remove.bookmark = Retirer de mes Favoris +menuitem.remove.from.group = Supprimer le Groupe +menuitem.remove.from.roster = Retirer des Contacts +menuitem.remove.service = Enlever le Service +menuitem.rename = Renommer +menuitem.revoke.admin = Révoquer les droits admin +menuitem.revoke.member = Révoquer les droits de membre +menuitem.revoke.moderator = Révoquer les droits de Modérateur +menuitem.revoke.owner = Révoquer les droits propriétaire +menuitem.revoke.voice = Révoquer les droits de Voice +menuitem.save = Enregistrer +menuitem.save.as = Enregistrer sous... +menuitem.send.a.file = Envoyer un Fichier +menuitem.send.a.message = Envoyer un Message... +menuitem.set.status.message = Message d'état +menuitem.show.contact.statusmessage = Afficher un message d'état +menuitem.show.empty.groups = Montrer les Groupes Vides +menuitem.show.offline.group = Regrouper les contacts non connectés +menuitem.show.offline.users = Montrer les contacts non connectés +menuitem.show.traffic = Montrer la Fenêtre de Traffic +menuitem.sign.in = Se connecter +menuitem.sign.in.at.login = Se connecter après l'identification +menuitem.sign.out = Se déconnecter +menuitem.start.a.chat = Commencer une Conversation +menuitem.start.a.conference = Commencer une Conférence +menuitem.status = Etat +menuitem.subscribe.to = Souscrire à +menuitem.unban = Débannir +menuitem.unblock.contact = Débloquer un contact +menuitem.unblock.user = Débloquer l'Utilisateur +menuitem.user.guide = Guide d'utilisation +menuitem.view.client.version = Voir Version du Client +menuitem.view.contact.history = Voir l'Historique de ce Contact +menuitem.view.downloads = Voir les Téléchargements +menuitem.view.last.activity = Voir la dernière activité +menuitem.view.logs = Consulter les logs +menuitem.view.profile = Voir Profil +menuitem.view.room.info = Voir les Infos du Salon +menuitem.voice = Voice + +message = Message +message.account.create = Créer un nouveau compte. +message.account.created = Le nouveau compte a été crée. +message.account.error = Spécifiez le serveur sur lequel créer le compte. +message.add.a.contact = Ajouter un contact. +message.add.conference.service = Ajouter un Service de Conférence +message.add.contact.to.list = Ajouter l'utilisateur a mes Contacts +message.add.favorite.room = Ajouter à mes salon favoris ou rejoindre directement. +message.add.this.user.to.your.roster = Ajouter cet utilisateur a mes Contacts. +message.add.to.roster = Ajouter aux Contacts +message.add.user = Ajouter cet utilisateur a vos Contacts? +message.alert.notify = Notification d'alerte +message.already.exists = Un compte existe déja avec ce nom d'utilisateur. Veuillez réessayer. +message.approve.subscription = Permettre à {0} de vous ajouter à ses Contacts? +message.authenticating = Vérification en cours +message.away.idle = Pas là... (mise en veille) +message.bookmark.temporary.room.error = Impossible d'ajouter un Salon Temporaire à vos favoris. +message.broadcast.from = Message groupé de {0} +message.broadcast.message.sent = Le message groupé a été envoyé. +message.broadcast.no.text = SVP entrez le texte à diffuser +message.broadcast.no.user.selected = SVP sélectionner au moins un destinataire +message.broadcast.to = Entrez le message groupé à {0} +message.hasbeenbroadcast.to = Le message groupé a été envoyé aux utilisateurs suivants\: \n{0} +message.buzz.alert.notification = Solliciter l'attention +message.buzz.message = {0} veut votre attention +message.buzz.sent = La notification d'alerte a bien été envoyée à l'utilisateur +message.calling = Appel de {0} en cours +message.came.online = {0} s''est connecté à {1} +message.cannot.add.contact.to.shared.group = Impossible d'ajouter de nouveaux contacts à un Groupe Partagé. +message.chat.session.ended = Session de chat terminée à {0} +message.click.to.open = Cliquez pour ouvrir +message.client.information = Infos client de {0} +message.close.other.chats = Fermer les autres chats +message.close.stale.chats = Fermer les chats suspendus +message.close.this.chat = Fermer ce chat +message.close.unread.window = Vous avez des messages non lus, êtes-vous sûr de vouloir fermer la fenêtre ? +message.conference.info.error = Impossible d'obtenir des infos sur cette conférence. Veuillez réessayer plus tard. +message.conference.service.error = Service de conférence introuvable. +message.confirm.destruction.of.room = Supprimer le salon en enlève aussi tous ses utilisateurs. Continuer? +message.confirmation.password.error = Confirmez le mot de passe. +message.connecting.please.wait = Connexion en cours. Veuillez patienter... +message.connection.failed = Connexion à {0} a échouée. +message.create.account = Le compte n'a pas pu être crée. +message.create.or.join.room = Créer ou rejoindre un salon +message.current.status = Permettre aux autres de voir votre état ou activité. +message.default.error = Une Erreur a été détectée. Veuillez la transmettre https://discourse.igniterealtime.org, s'il vous plait. +message.delete.all.history = Effacer toutes les anciennes conversations? +message.delete.confirmation = Etes vous sur de vouloir effacer {0}? +message.disable.transport = Voulez-vous désactiver un transport déja actif? +message.disconnected.conflict.error = Votre connexion a été fermée car un autre utilisateur du même nom s'est loggé depuis un autre endroit. +message.disconnected.error = Votre connexion a été fermée à cause d'une erreur. +message.disconnected.group.chat.error = Vous avez été déconnecté suite à une erreur, vous devrez entrer de nouveau dans ce salon de discussion après vous être reconnecté +message.disconnected.shutdown = Vous avez été déconnecté car le serveur vient de s'arrêter +message.downloading = Téléchargement de {0} en cours +message.downloading.spark.plug = Téléchargement du Spark-Plug +message.end.chat = Voulez-vous en finir avec ce chat? +message.end.conversation = Voulez-vous en finir avec cette session? +message.enter.broadcast.message = Entrez le message groupé à envoyer aux utilisateurs selectionnés. +message.enter.facebook = Indiquez votre identifiant et mot de passe Facebook ci-dessous +message.enter.gadugadu = Indiquez votre identifiant et mot de passe GaduGadu ci-dessous +message.enter.irc = Indiquez votre identifiant et mot de passe IRC ci-dessous +message.enter.jabber.id = Entrez votre Jabber ID +message.enter.message.to.broadcast = Entrez le message groupé qui sera envoyé à tous vos Contacts. +message.enter.myspace = Indiquez votre identifiant et mot de passe MySpace ci-dessous +message.enter.new.subject = Entrez un nouveau sujet +message.enter.qq = Indiquez votre identifiant et mot de passe QQ ci-dessous +message.enter.room.password = Entrez le mot de passe du salon +message.enter.sametime = Indiquez votre identifiant et mot de passe Sametime ci-dessous +message.enter.simple = Indiquez votre identifiant et mot de passe SIMPLE ci-dessous +message.enter.valid.jid = Entrez un JID valide +message.enter.xmpp = Indiquez votre identifiant et mot de passe XMPP ci-dessous +message.error.during.file.transfer = Erreur s'est produite durant le transfert de fichier. +message.file.exists.question = Le fichier existe déjà. Ecrire par dessus? +message.file.size = Taille du Fichier\: {0} +message.file.transfer.canceled = Vous avez annulé le transfert du fichier. +message.file.transfer.chat.window = Demande de transfert de fichier: +message.file.transfer.file.too.big.error = Le fichier sélectionné est trop gros.\nLa taille maximale est {0} le fichier sélectionné est de {1} +message.file.transfer.file.too.big.warning = Le fichier sélectionné est trop gros.\nProcéder malgré tout? +message.file.transfer.notification = Notification de transfert de fichier +message.file.transfer.rejected = Le fichier n''a pas été accepté par {0}. +message.file.transfer.short.message = vous envoie un fichier appelé\: +message.find.conference.services = Rechercher les Services de Conférence +message.forbidden.error = Une erreur de type inconnu à été reçue du serveur. +message.gateway.nickname.error = Veuillez indiquer un pseudo +message.gateway.password.error = Veuillez indiquer un mot de passe +message.gateway.username.error = Veuillez indiquer un identifiant +message.general.error = Vous avez perdu votre connexion au serveur à cause de {0}. +message.generic.reconnect.message = Vous avez perdu votre connexion au serveur. Cliquez sur le bouton ci-dessous pour vous reconnecter. +message.groupchat.registered.member = Enregistrement réussi avec {0} +message.groupchat.require.password = Cette salle de conférence nécessite un mot de passe +message.idle.for = Mise en veille de {0} +message.image.too.large = La taille de cette image est trop grosse. Veuillez utiliser une image de 16k ou moins. +message.invalid.jabber.id = Jabber ID invalide +message.invalid.jid.error = Le JID utilisé est invalide. +message.invalid.status = Veuillez entrer un message d'état valide. +message.invalid.username.password = Identifiant ou mot de passe invalide +message.invite.to.groupchat = {0} vous invite à rejoindre une discussion de groupe +message.invite.users.to.conference = Inviter ces utilisateurs dans une salle de conférence. +message.is.shared.group = {0} est un groupe partagé. +message.is.typing.a.message = {0} tappe son message... +message.join.conference.room = Rejoindre la Salle de Conférence +message.kicked.error = Vous n''avez pas le droit de kicker {0}. +message.last.message.received = Dernier message reçu à {0} +message.loading.please.wait = Chargement en cours. Veuillez patienter... +message.locked.workstation = L'utilisateur a verrouillé sa station de travail. +message.name.of.group = Nom du Groupe +message.name.of.search.service.question = Nom du Service de Recherche? +message.negotiate.file.transfer = Négociation du transfert de fichier en cours. Veuillez patienter... +message.negotiate.stream = Négociation du transfert. Veuillez patienter... +message.negotiation.file.transfer = Négociation du transfert de fichier avec {0}. Veuillez patienter... +message.new.message = Nouveau message de {0}. +message.new.spark.available = {0} est disponible. Souhaitez-vous l''installer? +message.nickname.in.use = Ce nickname est déjà utilisé. Veuillez en choisir un autre. +message.nickname.not.acceptable = Vous n'êtes pas autorisé à modifier votre pseudo! +message.no.avatar.found = Aucun avatar n'a été configuré par l'utilisateur. +message.no.caller.id = Aucune info d'appel disponible. +message.no.description.available = Aucune description disponible. +message.no.history.found = Il n'y a pas d'historique de conversation pour cet utilisateur. +message.no.results.found = Aucun résultat n'a été donné par le serveur. +message.no.room.to.join.error = Pas de salons. +message.no.subject.available = Aucun sujet disponible +message.no.updates = Il n'y a pas de mises à jour disponibles +message.normal = Message normal +message.number.to.call = Indiquez le numéro à composer +message.offline = L'utilisateur est déconnecté et ne recevra ce message qu' à sa prochaine connexion. +message.offline.error = L'utilisateur ne recevra hélas aucun message tant qu'il est déconnecté. +message.participants.in.room = Participants du Salon +message.password.error = Veuillez entrer un mot de passe pour ce compte. +message.password.private.room.error = Veuillez entrer un mot de pass pour ce salon privé +message.passwords.no.match = Les mots de passes ne correspondent pas. +message.please.join.in.conference = Rejoins-moi dans cette conférence. Merci. +message.plugins.not.available = Le dépôt de plugins n'a pas pu être contacté. +message.prompt.plugin.uninstall = Souhaitez-vous désinstaller {0}? +message.received.file = Vous avez reçu un fichier de {0}. +message.receiving.file = Vous êtes en train de recevoir un ficher de {0} +message.reconnect.attempting = Essai... +message.reconnect.failed = Echecc de la reconnexion +message.reconnect.wait = Reconnexion dans {0} secondes +message.register.transports = S'enregistrer avec ces transports. +message.registering = Enregistrement avec {0} en cours. Veuillez patienter... +message.registration.transport.failed = Impossible de s'enregistrer avec ce Transport. +message.restart.required = Vous devez redémarrer Spark pour que ces changements soient effectifs. Voulez-vous redémarer maintenant? +message.restart.spark = Vous devrez redémarrer votre client pour installer cette nouvelle version. Voulez vous le faire tout de suite? +message.restart.spark.changes = Ce Plugin sera éliminé lors du prochain redémarrage de Spark. +message.restart.spark.to.install = Vous devez éteindre votre client afin d'installer la derniere version. Souhaitez-vous faire cela tout de suite? +message.room.creation.error = La salle n'a pas pu être créée +message.room.destroyed = Ce salon a été detruit\: {0} +message.room.destruction.reason = Raison pour laquelle vous souhaitez détruire ce salon? +message.room.information.for = Infos du Salon pour {0} +message.save.profile = Pour enregistrer votre profil, cliquez sur Sauver. +message.search.for.contacts = Recherche de Contacts. +message.search.for.history = Rechercher dans l'historique des conversations +message.search.for.other.people = Rechercher les utilisateurs de ce même serveur. +message.search.input.short = SVP fournir au moins deux lettres. +message.search.service.not.available = Service de Recherche hors service. +message.searching.please.wait = Recherche en cours, veuillez patienter... +message.select.add.room.to.add = Veuillez électionner un salon a ajouter à vos favoris. +message.select.one.or.more = Sélectionnez un ou plusieurs utilisateurs parmis vos Contacts. +message.select.room.to.enter = Indiquez le salon que vous souhaitez rejoindre. +message.select.room.to.join = Indiquez le salon que vous souhaitez rejoindre. +message.send.a.broadcast = Envoyez un message groupé +message.send.file.to.user = Envoyer des fichiers a cet utilisateur. +message.send.picture = Envoyez un screenshot. +message.send.to.these.people = Envoyer à ces personnes +message.sending.file.to = Envoyer le fichier à {0}. +message.sent.offline.files = On vous a envoyé un/des fichier(s) offline. +message.server.unavailable = Connexion au serveur impossible: nom de serveur incorrect ou le serveur est hors ligne +message.service.already.exists = Ce service fait déjà partie de vos services. +message.shared.group = Groupe Partagé +message.specify.contact.jid = Veuillez spécifier le JID du contact (ex. ddman@jabber.org) +message.specify.group = Indiquez le groupe auquel ajouter ce nouvel utilisateur. +message.specify.information.for.conference = Veuillez indiquer les infos de la conférence. +message.specify.name.error = Indiquez un nom valide. +message.specify.users.to.join.conference = Indiquez les utilisateurs autorisés a rejoindre la conférence. +message.specify.valid.time.error = Veuillez indiquer un timeout et un port valide. +message.subject.change.error = Vous ne pouvez pas changer le sujet de ce salon. +message.subject.has.been.changed.to = Le sujet a été changé\: {0}. +message.supply.resource = Indiquez une resource valide. +message.supply.valid.port = Indiquez un port valide. +message.supply.valid.timeout = Indiquez une valeur de timeout valide +message.timeout.error = Le temps limite doit être d'au moins 5 secondes ou plus. +message.total.downloaded = Total Téléchargé +message.transfer.cancelled = Ce transfer a été annulé. +message.transfer.complete = Le transfert de fichier a été complété ({0}) +message.transfer.progressbar.text.received = {0} received @ {1} {2} +message.transfer.progressbar.text.sent = {0} sent @ {1} {2} +message.transfer.rate = Taux de Transfert +message.transfer.refused = Ce transfert de fichier a été refusé. +message.transfer.waiting.on.user = En attente de {0} pour qu''il/elle accepte le tranfert. +message.unable.to.load.profile = Aucun profil trouvé pour {0} +message.unable.to.retrieve.last.activity = Impossible de déterminer la dernière activité de {0} +message.unable.to.save.password = Impossible de changer le mot de passe. Veuillez contacter votre administrateur système. +message.unable.to.send.file = Le transfert a {0} a échoué. +message.unrecoverable.error = Identifiant ou mot de passe incorrect +message.update.room.list = Mise à Jour de la liste de salons +message.updating.cancelled = Mise à Jour annulée. +message.user.banned = {0} a été banni de ce salon. +message.user.given.voice = {0} a été donné le droit voice dans ce salon. +message.user.granted.admin = {0} a été donné les droits d'Administrateur. +message.user.granted.membership = {0} a été donné les droits de membre. +message.user.granted.moderator = {0} a été donné les droits de modérateur. +message.user.granted.owner = {0} a été donné les droits de propriétaire. +message.user.is.sending.you.a.file = {0} vous envoie un fichier. +message.user.joined.room = {0} a rejoint le salon. +message.user.kicked.from.room = {0} a été kické du salon. +message.user.left.room = {0} a quitté le salon. +message.user.nickname.changed = {0} est maintenant sous le nom {1}. +message.user.now.available.to.chat = {0} est connecté à {1} +message.user.revoked.admin = Les droits d''Administrateurs ont été révoqués de {0}. +message.user.revoked.membership = Les droits de membre ont été révoqués pour {0}. +message.user.revoked.moderator = Les droits de modérateur ont été revoqués pour {0}. +message.user.revoked.owner = Les droits de propriétaire ont été révoqués pour {0}. +message.user.voice.revoked = Le droit Voice a été révoqué pour {0} +message.username.error = Indiquez un nom d'utilisateur pour le compte. +message.username.password.error = Le nom d'utilisateur et/ou mot de passe doit etre indique. +message.vcard.not.supported = Le Serveur n'est pas en mesure de supporter les VCards. Sauvegarde de votre VCard impossible. +message.version = Version\: {0} +message.view.information.about.this.user = Voir les information à propos de cet utilisateur +message.waiting.for.user.to.join = En attente de {0} +message.went.offline = {0} s''est déconnecté à {1} +message.you.have.been.banned = Vous avez été banni de ce salon +message.you.have.been.kicked = Vous avez été kické de ce salon +message.you.have.sent = Vous avez envoyé un fichier à {0} +message.your.admin.granted = Vous avez reçu les droits d'Administrateur +message.your.banned = Vous avez été banni de ce salon +message.your.kicked = Vous avez été kické par {0} +message.your.membership.granted = Vous avez reçu les droits de membre. +message.your.membership.revoked = Vos droits de membre ont été révoqués +message.your.moderator.granted = Vous avez reçu les droits de modérateur. +message.your.moderator.revoked = Vos droits de modérateur ont été révoqués +message.your.ownership.granted = Vous avez reçu les droits de propriétaire. +message.your.ownership.revoked = Vos droits de propriétaire ont été révoqués. +message.your.revoked.granted = Vos droits d'Administrateur ont été révoqués. +message.your.voice.granted = Vous avez la parole dans cette discussion +message.your.voice.revoked = Vos droits Voice ont été révoqués. + +##Settings for the privacy plugin +privacy.tooltip.preferences = Paramètres de confidentialité +privacy.border.block = Bloquer +privacy.border.information = Informations +privacy.button.no.list.selected = Pas de liste séléctionnée +privacy.dialog.add.list = Veuillez saisir le nom de famille +privacy.dialog.rem.list = Voulez-vous vraiment enlever {0}? +privacy.label.information = Utilisez le menu du clic droit pour ajouter ou supprimer des listes et éléments +privacy.label.iq.desc = Rechercher +privacy.label.list.is.active = Liste active en ce moment: +privacy.label.list.is.default = Liste par défaut: +privacy.label.msg.desc = Messages +privacy.label.not.supported = Les réglages vie privée ne sont pas possibles sur le serveur +privacy.label.pin.desc = Notifications de connexion +privacy.label.pout.desc = Notifications de déconnexion +privacy.label.preferences = Plugin vie privée +privacy.menu.activate.list = Activer +privacy.menu.add.contacts = Ajouter des Contacts à la liste +privacy.menu.add.groups = Ajouter des Groupes à la liste +privacy.menu.add.list = Ajouter une liste +privacy.menu.add.rem.items = Retirer {0} éléments de la liste +privacy.menu.default.list = Choisir par défaut +privacy.menu.remove = Retirer +privacy.menu.remove.list = Supprimer une liste +privacy.menuitem.deactivate.current.list = Désactiver {0} +privacy.name.for.default.list = Par défaut +privacy.node.contacts = Contacts +privacy.node.groups = Groupes +privacy.pick.one.or.more = Choisir un ou plusieurs éléments à ajouter à la liste +privacy.root.node = Listes d'autorisations +privacy.status.menu.entry = Liste de réglages vie privée +privacy.title.add.picker = Ajouter à la liste +privacy.title.panel = Utilisez le bouton droit de la souris SVP +privacy.title.preferences = Réglages vie privée + +status.away = Absent +status.custom.messages = Messages personnalisés +status.do.not.disturb = Ne pas déranger +status.extended.away = Absence prolongée +status.free.to.chat = Disponible +status.on.phone = Au téléphone +status.online = Connecté +status.pending = En attente + +##Stunfallback in media settings +stun.border.label = Serveur de redondance STUN +stun.server.addr = Serveur Stun: +stun.server.port = Port Stun: + +tab.available.plugins = Plugins Disponibles +tab.avatar = Avatar +tab.business = Business +tab.conferences = Conférences +tab.contacts = Contacts +tab.deactivated.plugins = Plugins désactivés +tab.general = Général +tab.home = Home +tab.installed.plugins = Plugins Installés +tab.personal = Personnel +tab.pki = PKI +tab.proxy = Proxy +tab.sso = SSO + +title.about = A propos +title.account.create.registration = Création des Comptes +title.account.created = Compte Crée +title.add.contact = Ajouter Contact +title.add.contact.group = Ajouter Groupe +title.add.new.group = Ajouter Nouveau Groupe +title.add.search.service = Ajouter Service de Recherche +title.add.to.roster = Ajouter aux Contacts +title.address = Adresse +title.advanced.connection.preferences = Préférences de Connexion Avancées +title.advanced.connection.sso = Utiliser le Single Sign-On (SSO) +title.advanced.connection.sso.account = Ceci utilisera le compte du bureau pour "{0}" à connecter au serveur. +title.advanced.connection.sso.noprincipal = Spark est incapable de trouver le principal à utiliser pour le Single Sign-On. Ceci empêche SSO de fonctionner. +title.advanced.connection.sso.unable = Impossible de connecter en utilisant le Single Sign-On. SVP vérifiez votre principal et les paramètres du serveur. +title.advanced.connection.usesso = Se connecter via GSSAPI (SSO) +title.alert = Alerte +title.appearance = Apparence +title.appearance.preferences = Personnalisation +title.appearance.showVCards = Montrer les &VCards dans la liste de contacts +title.available.transports = Transports Disponibles +title.bookmarks = Marques-pages +title.broadcast.message = Message groupé +title.browse.conference.services = Voir les services de conférence +title.browse.room.service = Voir les salles de conférence +title.cancelled = Annulé +title.change.nickname = Changer de nickname +title.change.subject = Changer de sujet +title.chat = Chat +title.choose.directory = Sélectionnez un répertoire +title.choose.incoming.sound = Sélectionnez un fichier d'alerte sonore lors de messages entrants +title.choose.offline.sound = Sélectionnez un fichier d'alerte sonore pour les déconnexions +title.choose.outgoing.sound = Sélectionnez un fichier d'alerte sonore pour les messages sortants +title.client.logs = Logs client +title.conference.invitation = Invitation à une Conférence +title.conference.rooms = Salles de conférence +title.configure.chat.room = Configurer le Salon de Discussion +title.configure.room = Configurer le Salon +title.confirmation = Confirmation +title.create.new.account = Créer un nouveau compte +title.create.or.bookmark.room = Rejoindre ou ajouter le salon aux favoris +title.create.room = Créer +title.create.problem = Erreur de création du compte +title.delete.file = Voulez-vous vraiment supprimer le fichier? +title.dial.phone = Téléphoner +title.disable.transport = Désactiver le Transport +title.download.complete = Téléchargement Terminé +title.downloading.im.client = Téléchargement du client d'IM +title.downloads = Téléchargements +title.edit.custom.message = Editer les messages personnalisés +title.edit.profile = Editer Profil +title.enter.reason = Donnez une raison +title.error = Erreur +title.error.couldnot.open.file = Impossible d'ouvrir le fichier +title.error.delete.file = Impossible d'effacer le fichier +title.error.find.app = Impossible de trouver l'application correspondante +title.error.rename.file = Impossible de renommer le fichier +title.facebook.registration = Identifiants Facebook +title.file = Fichier +title.file.exists = Le fichier existe déjà +title.file.transfer = Transfert de fichier +title.file.transfer.preferences = Préférences Transfert de Fichier +title.filesize = Taille +title.find.conference.service = Rechercher les Services de Conférence +title.find.contacts = Rechercher Contacts +title.gadugadu.registration = Identifiants GaduGadu +title.general.chat.settings = Paramètres de Chat +title.general.media = Réglages Multimedia +title.group.chat = Conférence +title.group.chat.settings = Réglages des groupes de discussion +title.history.for = Historique de conversation de {0} +title.incoming.call = Appel Entrant +title.input.fileexplorer = Saisissez le nom de votre navigateur: +title.input.newname = Saisissez le nouveau nom\: +title.input.openwith = Saisissez le nom de l'application que vous voulez utiliser: +title.invite.to.conference = Inviter à une Conférence +title.irc.registration = Identifiants IRC +title.jabber.browser = Navigateur +title.join.conference.room = Rejoindre une Conférence +title.last.activity = Dernière Activité +title.login = Login +title.login.error = Erreur de connexion +title.login.no.account = Impossible de déterminer +title.login.settings = Paramètres de Login +title.lookup.profile = Voir Profil +title.myspace.registration = Identifiants MySpace +title.name = Nom +title.new.client.available = Nouveau Client disponible +title.new.roster.group = Nouveau Groupe de Contacts +title.new.version.available = Nouvelle Version disponible +title.no.updates = Pas de mise à jour +title.notes = Notes +title.notification = Notification +title.notifications = Notifications +title.occupants = Occupants +title.on.the.phone = Au téléphone +title.password = Mot de Passe +title.password.required = Mot de passe requis +title.passwords.no.match = Confirmez le mot de passe. +title.person.search = Recherche de Personne +title.plugins = Plugins +title.preferences = Préférences +title.profile.information = Infos de Profil +title.profile.not.found = Profil inexistant +title.qq.registration = Identifiants QQ +title.register.account = Créer un nouveau compte +title.registration.error = Erreur de création +title.reminder = Rappel +title.rename.roster.group = Renommer un group de contacts +title.room.destroyed = Salon Supprimé +title.room.information = Infos du Salon +title.roster = Contacts +title.sametime.registration = Identifiants Sametime +title.select.file.to.send = Selectionnez un Fichier à envoyer +title.set.status.message = Editer le message d'état +title.simple.registration = Identifiants SIMPLE +title.sound.preferences = Préférences Sonores +title.sounds = Sons +title.spark.preferences = Préférences Spark +title.start.chat = Ouvrir une conversation +title.status.message = Message d'état +title.subscription.request = Demande d'abonnement +title.task.notification = Notification de tâche +title.tasks = Tâches +title.transports = Transports +title.tray.information = Infos de la Zone d'iconification +title.upgrading.client = Mise à Jour du Client +title.version.and.time = Version et Heure +title.view.bookmarks = Voir les Favoris +title.view.profile.for = Voir le Profil de {0} +title.view.room.information = Voir les Infos du Salon +title.waiting.to.call = Attente +title.xmpp.registration = Identifiants XMPP + +tooltip.appearance = Changer l'apparence des conversations +tooltip.file.transfer = Préférences pour le transfert de fichiers +tooltip.notifications = Préférences de Notification pour les chat entrants +tooltip.place.a.call = Appeler cette Personne +tooltip.place.voice.call = Appeler cet utilisateur +tooltip.send.email = Envoyer un email +tooltip.start.chat = Démarrer une conversation +tooltip.view.changelog = Lire le Change Log +tooltip.view.history = Voir l'historique de conversation +tooltip.view.readme = Lire le ReadMe + +tree.conference.services = Service de Conférence +tree.users.in.room = Utilisateurs du Salon diff --git a/core/src/main/resources/i18n/spark_i18n_it.properties b/core/src/main/resources/i18n/spark_i18n_it.properties new file mode 100644 index 000000000..14fc98cc3 --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_it.properties @@ -0,0 +1,885 @@ +accept = Accetta +is.active = Attiva +add = Aggiungi +administrator = Amministratore +apply= Applica +available = Disponibile +broadcast = Messaggio a Tutti +cancel = Annulla +close = Chiudi +create = Crea +date = Data +description = Descrizione +from = Da +invite = Invita +join = Entra +no = No +not.registered = Non Registrato +occupants = Presenti +offline = Offline +online = Online +ok = Ok +open = Apri +open.folder = Apri Cartella +participants = Partecipanti +refresh = Aggiorna +reject = Rifiuta +retry = Riprova +room.name = Nome Stanza +save = Salva +subject = Argomento +unfiled = Altri +use.default = Usa Predefinito +user.has.signed.in = è entrato. +user.has.signed.off = è uscito. +while.offline = Quando disconnesso +yes = Sì + +action.clear = Pulisci +action.copy = Copia +action.cut = Taglia +action.paste = Incolla +action.print = Stampa +action.save = Salva +action.select.all = Seleziona tutto + +button.accept = &Accetta +button.add = &Aggiungi +button.add.a.contact = &Aggiungi Un Contatto +button.add.bookmark = Aggiungi Preferito +button.add.service = &Aggiungi Servizio +button.add.user = &Aggiungi Utente +button.add2 = A&ggiungi... +button.advanced = A&vanzate +button.approve = &Conferma +button.bookmark.room = &Stanza Preferita +button.browse = &Sfoglia... +button.browse2 = S&foglia... +button.browse3 = Sf&oglia... +button.cancel = &Annulla +button.clear = &Azzera +button.close = C&hiudi +button.copy.to.clipboard = Copia negli appunti +button.create.account = &Crea Account +button.create.room = &Crea o Entra nella Stanza +button.decline = &Rifiuta +button.deny = &Ignora +button.dial.number = &Numero di Telefono +button.find = &Trova +button.join = &Entra +button.join.room = &Entra nella Stanza Selezionata +button.login = &Login +button.new = &Nuovo +button.profile = &Profilo +button.quit = &Esci +button.re.detect = &Rileva +button.reconnect = &Riconnetti +button.reconnect2 = Riconnetti +button.refresh = &Aggiorna +button.register = &Registrati +button.reject = Rifiuta +button.remove.bookmark = Elimina Preferito +button.roster = &Elenco +button.save = &Salva +button.save.for.future.use = &Salva per utilizzi futuri +button.search = &Cerca +button.send = Invia +button.send.email = Email +button.start.chat = Chat +button.tasks.active = Attivi +button.tasks.all = Tutti +button.unset.file.explorer = Disabilita File Browser +button.update = &Aggiorna +button.view.notes = Mostra note +button.view.profile = Visualizza profilo completo +button.view.tasklist = Mostra lista impegni + +checkbox.allow.buzz = Abilita gli utenti ad attira&re la tua attenzione. +checkbox.auto.discover.port = &Rileva Automaticamente host e porta +checkbox.auto.login = &Login Automatico +checkbox.click.single.tray = &Usa singolo click nella tray bar per portare spark in primo piano (richiede riavvio) +checkbox.disable.asterisk.toaster = Disabilita popup a comparsa +checkbox.disable.chat.history = &Disattiva la Cronologia nella Chat +checkbox.disable.prev.chat.history = Non &mostrare più le precedenti conversazioni della chat +checkbox.enable.emoticons = Attiva Em&oticons +checkbox.graying.out = Nascondi i contatti in pausa (richiede riavvio) +checkbox.idle.enabled = &Rileva Inattività +checkbox.launch.on.startup = &Esegui all'avvio +checkbox.login.as.invisible = L&ogin invisibile +checkbox.reconnect.info = Specifica la schermata di riconnessione: +checkbox.reconnect.panel.big = Mostra come pannello +checkbox.reconnect.panel.small = Mostra nel gruppo dei contatti +checkbox.reconnect.panel.icon = Mostra come icona +checkbox.notify.user.comes.online = Notifica quando un utente si connette. +checkbox.notify.user.goes.offline = Notifica quando un utente si disconnette. +checkbox.notify.typing.systemtray = &Mostra notifica di scrittura nella tray di sistema +checkbox.notify.systemtray = Mostra nuovi &messaggi nella try di sistema +checkbox.permanent = La Stanza è &permanente +checkbox.play.sound.on.invitation = Esegui file audio alla &ricezione di un invito +checkbox.play.sound.on.new.message = Esegui file audio quando arriva un nuovo &messaggio +checkbox.play.sound.on.outgoing.message = Esegui file audio quando viene &inviato un messaggio +checkbox.play.sound.when.offline = Esegui file audio quando un utente si &disconnette +checkbox.private.room = La stanza &è privata +checkbox.save.password = &Salva Password +checkbox.show.avatars.in.contactlist = Mostra gli &avatars nella lista contatti +checkbox.show.notifications.in.conference = &Mostra notifiche nelle Stanze +checkbox.show.time.in.chat.window = &Mostra orario nella finestra di chat +checkbox.show.toaster = Mostra &Popup a comparsa +checkbox.sort.asc.history = Ordina messaggi per data crescente nella storia contatti +checkbox.split.chat.window = Dividi le &Finestre di chat (Richiede il riavvio di Spark) +checkbox.start.in.tray = &Avvia Spark nella Tray Bar +checkbox.tabs.on.top = Schede della &Chat appaiono in alto (Richiede il riavvio di Spark) +checkbox.tabs.scroll = Usa lo scorrimento per le schede della chat (Richiede il riavvio di Spark) +checkbox.use.compression = Usa Co&mpressione +checkbox.use.debugger.on.startup = Avvia debugger all'avvio +checkbox.use.proxy.server = &Usa Proxy Server +checkbox.use.system.look.and.feel = Utilizza il Look and &Feel di sistema (Richiede il riavvio di Spark) +checkbox.window.to.front = &Porta la finestra in primo piano +checkbox.broadcast.hide.offline.user = Nascondi utenti non in linea +checkbox.use.krbconf = Usa krb5.conf o krb5.ini +checkbox.use.krb.dns = Usa DNS +checkbox.use.specify.below = Specifica sotto +checkbox.use.pki.authentication = Usa autenticazione PKI +checkbox.transport.tab.setting = Mostra trasporti disponibili nel tab (Richiede il riavvio di Spark) +checkbox.conference.tab.setting = Mostra servizio di conferenza nel tab (Richiede il riavvio di Spark) +checkbox.use.hostname.as.resource = Usa hostname come risorsa +checkbox.use.version.as.resource = Usa versione di Spark come risorsa +checkbox.accept.all.certificates = Accetta tutti i certificati (self-signed/expired/not trusted) +checkbox.disable.hostname.verification = Disabilita la verifica dell'hostname del certificato (non consigliato) +checkbox.close.unread.message = Chiedi quando chiudi la finestra se ci sono messaggi non letti + +delete.log.permanently = Elimina definitivamente log +delete.permanently = Eliminare definitivamente? + +gateway.username.password.error = Devono essere inseriti username e/o password. + +group.chat.window.information = Informazioni sulla finestra di chat +group.comma.delimited = Delimitato da Virgola +group.conferences.found = Trovato un Servizio Conferenza +group.connection = Connessione +group.empty = Nessun contatto online in questo gruppo. +group.general.information = Informazioni Generali +group.login.information = Informazioni di Login +group.notification.options = Opzioni di Notifica +group.offline = Utenti Offline +group.search.form = Cerca in +group.search.results = Risultati della ricerca +group.chat.name.notification = Visto il tuo nome... +group.chat.name.match = Il tuo nome è stato citato in una chat: + +label.na = n/a +label.home = Casa +label.accounts = &Accounts +label.add.conference.service = &Aggiungi un servizio conferenza +label.add.jid = &Aggiungi JID +label.add.task = &Aggiungi impegno +label.auto.login = &Login Automatico +label.available.users.in.roster = &Utenti disponibili in Elenco +label.avatar = Avatar: +label.cancel = Annulla +label.cell = Cellulare +label.change.password.to = &Cambia Password +label.chatroom.fontsize = Dimensione font finestra chat: +label.chatroom.maxcurrenthistorysize = Dimensione massima della cronologia corrente: +label.city = &Località +label.close = C&hiudi +label.company = &Azienda +label.confirm.password = &Conferma Password +label.conflict.error = Impossibile loggarsi, l'account è già loggato. +label.contact.to.find = Cerca contatto +label.recent.conversation = Conversazioni recenti +label.frequent.contacts = Contatti frequenti +label.contactlist.avatarsize = Dimensione avatar nella lista contatti: +label.contactlist.fontsize = Dimensione font lista contatti: +label.country = N&azione +label.create.account = Crea un &Account +label.department = &Dipartimento +label.dial = &Chiama +label.display.time = Mostra orario: +label.downloads = Download +label.due = Entro +label.email.address = &Email +label.emoticons = &Emoticons +label.enter.address = Inserisci indirizzo +label.enter.group.name = Inserisci il nome del nuovo gruppo +label.fax = &Fax +label.find = &Cerca +label.first.name = &Nome +label.group = &Gruppo +label.host = &Host +label.invited.users = Utenti invitati +label.jabber.address = Indirizzo &Jabber +label.jabber.id = &Jabber ID +label.jid = &JID +label.job.title = &Posizione Lavorativa +label.last.name = &Cognome +label.local.time = &Ora Locale +label.message = Messaggio +label.message.style = &Stile Messaggi +label.middle.name = &Secondo Nome +label.minutes.before.stale.chat = &Minuti di inattività massima per la stanza +label.mobile = &Cellulare +label.name = &Nome +label.network = Ret&e +label.new.nickname = Nuovo nickname +label.nickname = &Nickname +label.number = &Numero +label.ok = OK +label.old.ssl = &Usa vecchio metodo su porta SSL +label.os = &Sistema Operativo +label.pager = &Cercapersone +label.password = &Password +label.passwordreset = Reimposta password +label.phone = &Telefono +label.port = &Porta +label.postal.code = &CAP +label.presence = &Presenza +label.priority = P&riorità +label.protocol = &Protocollo +label.received = &Ricevuti +label.rename.to = Rinomina in +label.resource = &Risorsa +label.response.timeout = &Timeout di risposta (sec) +label.room = &Stanza +label.room.name = &Nome stanza +label.room.topic= &Argomento stanza +label.search = Cerca +label.search.service = &Servizio di ricerca +label.seconds = Secondi +label.server = Do&minio +label.server.address = &Indirizzo server +label.show = Mostra: +label.software = &Software +label.state.and.province = &Regione +label.street.address = &Via +label.time = Orario: {0} +label.time.till.idle = &Intervallo di inattività (min) +label.time.till.idlemessage = Messaggio automatico di a&ssenza +label.timeformat = Usa {0} +label.transfer.download.directory = &Directory di download: +label.transfer.timeout = &Timeout di trasferimento(min): +label.unable.to.add.contact = Impossibile aggiungere il contatto. +label.use.default = Usa Predefinito +label.user.on.public.network = L'utente è in una rete pubblica +label.username = &Nome utente +label.version = &Versione +label.web.page = &Home page +label.work = Lavoro +label.xmpp.port = Porta &XMPP +label.krb.realm = Realm +label.krb.kdc = KDC +label.which.pki.method = Quale metodo PKI? +label.choose.file = Scegli il file +label.trust.store.password = Fidati della password memorizzata +label.enter.password = Inserisci password +label.move.focus.forwards = Sposta il focus avanti +label.move.focus.backwards = Sposta il focus indietro +label.keystore.location = Locazione keystore +label.truststore.location = Locazione truststore +label.pkcs.library.file = File di libreria PKCS#11 +label.x509.certificate = Certificato X.509 +label.apple.keychain = Apple keyChain +label.add.to.roster = Aggiungi utente all'elenco +label.audio.device = &Audio device +label.video.device = &Video device + +menuitem.about = Versione +menuitem.actions = Azioni +menuitem.bookmarks = Preferiti +menuitem.add = Aggiungi +menuitem.add.as.contact = Aggiungi come contatto +menuitem.add.contact = Aggiungi contatti +menuitem.add.contact.group = Aggiungi gruppi di contatti +menuitem.add.groupchat.myname = Evidenzia il mio &nome quando qualcuno lo dice +menuitem.add.groupchat.mytext = &Evidenzia il mio testo quando dico qualcosa +menuitem.add.groupchat.popname = Mostra finestra a comparsa quando qualcuno dice il mio nome +menuitem.add.groupchat.showjoinleavemessage = &Mostra messaggi di unione e uscita +menuitem.add.groupchat.showrolesinsteadofstatus = Mostra icone di ruolo invece che di presenza +menuitem.add.groupchat.auto.accept.invite = &Accetta automaticamente gli inviti alle chat di gruppo +menuitem.add.groupchat.random.colors = I nomi hanno colori &differenti +menuitem.affiliation = Affiliazione +menuitem.always.on.top = Sempre in primo piano +menuitem.alert.when.online = Avverti quanto l'utente è disponibile +menuitem.ban = Bandisci +menuitem.ban.user = Bandisci utente +menuitem.block.contact = Blocca contatto +menuitem.block.user = Blocca utente +menuitem.broadcast.to.group = Messaggio di broadcast al gruppo +menuitem.browse.service = Elenca servizi +menuitem.change.nickname = Cambia nickname +menuitem.change.subject = Cambia argomento +menuitem.chat = Chat +menuitem.check.for.updates = Verifica la presenza di aggiornamenti +menuitem.connect = File +menuitem.contacts = Contatti +menuitem.copy.to = Copia in +menuitem.delete = Cancella +menuitem.delete.login.information = Cancella le informazioni di login +menuitem.destroy.room = Distruggi stanza +menuitem.dial = Componi +menuitem.edit = Modifica +menuitem.edit.my.profile = &Modifica il tuo profilo... +menuitem.edit.status.message = Modifica messaggi di stato personalizzati... +menuitem.enter.login.information = Inserisci le informazioni di login +menuitem.exit = Esci +menuitem.grant.moderator = Concedi moderatore +menuitem.grant.member = Concedi Membership +menuitem.grant.admin = Concedi Admin +menuitem.grant.owner = Concedi Ownership +menuitem.grant.voice = Concedi voice +menuitem.help = Help +menuitem.hide = Nascondi +menuitem.invite.group.to.conference = Invita il gruppo in una stanza +menuitem.invite.users = Invita Utenti +menuitem.join.on.startup = Entra all'Avvio +menuitem.join.room = Entra nella Stanza +menuitem.kick.user = Espelli Utente +menuitem.languages = Lingue +menuitem.logout.no.status = Log out +menuitem.logout.with.status = Log out con motivazione +menuitem.lookup.profile = &Ricerca Profilo... +menuitem.move.to = Sposta in +menuitem.online.help = Online Help +menuitem.open = Apri +menuitem.open.with = Apri con... +menuitem.plugins = Plugins +menuitem.preferences = Preferenze +menuitem.remove = Elimina +menuitem.remove.alert.when.online = Elimina Alert +menuitem.remove.bookmark = Elimina Preferiti +menuitem.remove.from.group = Rimuovi dal Gruppo +menuitem.remove.from.roster = Rimuovi dall'Elenco +menuitem.remove.service = Rimuovi Servizio +menuitem.rename = Rinomina +menuitem.revoke.moderator = Rimuovi Moderatore +menuitem.revoke.voice = Rimuovi Voice +menuitem.revoke.member = Revoca Membership +menuitem.revoke.admin = Revoca Admin +menuitem.revoke.owner = Revoca Ownership +menuitem.save = Salva +menuitem.save.as = Salva come... +menuitem.send.a.file = Invia un file +menuitem.send.a.message = Invia un messaggio... +menuitem.set.status.message = Imposta messaggio di stato... +menuitem.show.empty.groups = Mostra i gruppi vuoti +menuitem.show.offline.group = Raggruppa gli utenti offline +menuitem.show.traffic = Mostra finestra di traffico +menuitem.sign.in = Login +menuitem.sign.in.at.login = Entra al login +menuitem.sign.out = Logout +menuitem.start.a.chat = Avvia una chat +menuitem.start.a.conference = Apri una stanza... +menuitem.status = Stato +menuitem.subscribe.to = Iscriviti A +menuitem.unban = Rimuovi Ban +menuitem.unblock.user = Sblocca utente +menuitem.unblock.contact = Sblocca contatto +menuitem.user.guide = Guida utente +menuitem.view.client.version = Visualizza versione client +menuitem.view.contact.history = Visualizza storico dei contatti +menuitem.view.downloads = Visualizza Downloads +menuitem.view.last.activity = Visualizza l'ultima Attività +menuitem.view.logs = Visualizza Logs +menuitem.view.profile = Visualizza Profilo +menuitem.view.room.info = Visualizza Informazioni sulla Stanza +menuitem.voice = Voce +menuitem.show.offline.users = Mostra utenti offline +menuitem.show.contact.statusmessage = Mostra messaggio di stato +menuitem.bookmark.room = Memorizza stanza +menuitem.refresh = Aggiorna +menuitem.create.room = Crea o unisci stanza +menuitem.expand.all.groups = Espandi tutti i gruppi +menuitem.collapse.all.groups = Collassa tutti i gruppi +menuitem.invite.again = Invita di nuovo +menuitem.chatframe.option = Opzioni +menuitem.add.groupchat.invitetobookmark = Invita automaticamente gli utenti nella stanza memorizzata + +message = &Messaggio +message.account.create = Crea un nuovo account di chat. +message.account.created = L'account è stato creato. +message.account.error = Indica il server su cui creare l'account. +message.add.a.contact = Aggiungi un contatto. +message.add.conference.service = Aggiungi un servizio conferenza. +message.add.contact.to.list = Aggiungi l'utente all'elenco dei contatti +message.add.favorite.room = Inserisci la stanza nell'elenco dei preferiti o entraci direttamente. +message.add.this.user.to.your.roster = Aggiungi l'utente all'elenco degli amici. +message.add.to.roster = Aggiungi all'elenco +message.add.user = Aggiungi l'utente nel tuo elenco? +message.alert.notify = Richiesta attenzione +message.already.exists = Account già esistente, indicare un nome diverso. +message.approve.subscription = Consenti a {0} di inserirti nel proprio elenco? +message.authenticating = Autenticazione in corso +message.away.idle = L'utente è assente per inattività. +message.bookmark.temporary.room.error = Impossibile rendere preferita una stanza temporanea +message.broadcast.from = Messaggio broadcast da {0} +message.broadcast.no.user.selected = Prego selezionare almeno un destinatario +message.broadcast.no.text = Prego inserire il testo da diffondere +message.broadcast.message.sent = Il messaggio broadcast è stato inviato. +message.broadcast.to = Digitare il messaggio broadcast da inviare a {0} +message.hasbeenbroadcast.to = Il messaggio broadcast è stato inviato ai seguenti utenti:\n{0} +message.buzz.alert.notification = Ottieni l'attenzione dell'utente. +message.buzz.message = {0} richiede la tua attenzione +message.buzz.sent = Invia una notifica all'utente. +message.calling = Chiamata a {0} in corso +message.came.online = {0} è online dalle {1} +message.cannot.add.contact.to.shared.group = Impossibile aggiungere nuovi contatti ad un gruppo condiviso. +message.cert.hostname.verification.failed = Verifica del certificato dell'hostname fallita +message.cert.verification.failed = Impossibile verificare il certificato +message.chat.session.ended = La sessione di chat è terminata alle {0} +message.click.to.open = Fai click per aprire +message.client.information = Informazioni sul client di {0} +message.close.other.chats = Chiudi tutte le altre chat +message.close.stale.chats = Chiudi le chat inattive +message.close.this.chat = Termina questa chat +message.close.unread.window = Hai messaggi non letti, sei sicuro di voler chiudere la finestra? +message.conference.info.error = Impossibile ottenere delle informazioni sulla stanza. Riprova più tardi. +message.conference.service.error = Impossibile avviare il servizio conferenze. +message.confirm.destruction.of.room = Se elimini la stanza, disconnetterai tutti gli utenti presenti. Vuoi continuare? +message.confirmation.password.error = Conferma Password. +message.connecting.please.wait = Connessione in corso. Attendere prego... +message.connection.failed = Collegamento con {0} non riuscito. +message.create.account = Impossibile creare l'account. +message.create.or.join.room = Crea o Entra in una stanza di chat +message.current.status = Mostra agli altri il tuo stato. +message.default.error = E' stato rilevato un errore grave, per favore segnalare il problema all'amministratore. +message.delete.all.history = Eliminare tutte le conversazioni precedenti? +message.delete.confirmation = Confermi l''eliminazione di {0}? +message.disable.transport = Vuoi disattivare questo trasporto? +message.disconnected.conflict.error = La connessione è stata chiusa a causa del login dello stesso utente da un altro computer. +message.disconnected.error = La connessione è stata chiusa a causa di un errore. +message.disconnected.group.chat.error = La connessione è stata chiusa a causa di un errore. Dovrai rientrare in questa stanza dopo esserti riconnesso. +message.disconnected.shutdown = La tua connessione è stata chiusa perché il server è stato spento. +message.downloading = Download di {0} in corso +message.downloading.spark.plug = Download di Spark-Plug in corso +message.end.chat = Terminare questa chat? +message.end.conversation = Terminare questa sessione? +message.enter.broadcast.message = Inserisci il messaggio broadcast per gli utenti selezionati. +message.enter.gadugadu = Digita nei campi sottostanti il tuo nome utente e password per GaduGadu. +message.enter.irc = Digita nei campi sottostanti l'username, la password, e il nickname per IRC. +message.enter.sametime = Inserisci qua sotto il tuo username e password Sametime +message.enter.facebook = Inserisci qua sotto il tuo username e password Facebook +message.enter.myspace = Inserisci qua sotto il tuo username e password MySpace +message.enter.jabber.id = Digita Jabber ID +message.enter.message.to.broadcast = Inserisci il messaggio broadcast da inviare al tuo elenco. +message.enter.new.subject = Digita un nuovo argomento +message.enter.qq = Inserisci qua sotto il tuo numero e password QQ +message.enter.room.password = Digita la Password della stanza +message.enter.simple = Digita nei campi sottostanti il tuo nome utente e password per SIMPLE. +message.enter.valid.jid = Inserisci un Jabber ID valido +message.enter.xmpp = Digita nei campi sottostanti il tuoi nome utente e password per XMPP. +message.error.during.file.transfer = Si è verificato un errore durante il trasferimento di un file. +message.file.exists.question = Il file esiste già. Vuoi sovrascriverlo? +message.file.size = Dimensione File: {0} +message.file.transfer.canceled = Hai annullato il trasferimento del file. +message.file.transfer.rejected = Il trasferimento del file non è stato accettato da {0}. +message.file.transfer.dirnull = La directory di download per il trasferimento dei file non è valida +message.file.transfer.nodir = La directory di download per il trasferimento dei file non esiste +message.file.transfer.cantwritedir = Impossibile scrivere nella directory per il trasferimento dei file +message.file.transfer.notification = Notifica trasferimento file +message.file.transfer.short.message = sta invindo un file chiamato\: +message.file.transfer.chat.window = Richiesta di trasferimento file: +message.file.transfer.file.too.big.error = Il file selezionato è troppo grande.\nLa massima dimensione è {0} the selected file has {1} +message.file.transfer.file.too.big.warning = Il file selezionato è troppo grande.\nVuoi continuare comunque? +message.file.transfer.direrror.setdir = Clicca qua per cambiare la directory +message.find.conference.services = Trova servizi di conferenza +message.forbidden.error = Operazione non permessa dal server. +message.gateway.nickname.error = Inserisci un nickname per l'account. +message.gateway.password.error = Inserisci una password per l'account. +message.gateway.username.error = Inserisci un nome utente per l'account. +message.general.error = Connessione al server terminata a causa di {0}. +message.generic.reconnect.message = Connessione al server terminata. Per rieffettuare il login, fare click sul pulsante Riconnetti. +message.idle.for = Inattivo per {0} +message.image.too.large = Hai scelto un'immagine troppo grande. Indica un immagine di 16k o di dimensioni minori. +message.invalid.jabber.id = Il Jabber ID indicato non è valido +message.invalid.jid.error = Il JID indicato non è valido. +message.invalid.status = Digita un messaggio di stato valido. +message.invalid.username.password = Username o password non validi. +message.invite.to.groupchat = {0} ti sta invitando ad unirti alla chat +message.invite.users.to.conference = Invita gli utenti ad una conferenza. +message.is.shared.group = {0} è un gruppo condiviso. +message.is.typing.a.message = {0} sta digitando un messaggio... +message.join.conference.room = Entra in una Stanza +message.kicked.error = Non hai il permesso di espellere {0} da questa stanza. +message.last.message.received = Ultimo messaggio ricevuto alle {0} +message.loading.please.wait = Caricamento in corso. Attendere prego... +message.locked.workstation = L'utente ha bloccato il computer. +message.name.of.group = Nome del Gruppo +message.name.of.search.service.question = Indica il nome del servizio di riceca +message.negotiate.file.transfer = Negoziazione del trasferimento file in corso. Attendere prego... +message.negotiate.stream = Negoziazione della connessione in corso. Attendere prego... +message.negotiation.file.transfer = Negoziazione del file transfer con {0} in corso. Attendere prego... +message.new.message = Nuovo messaggio da {0}. +message.new.spark.available = {0} è ora disponibile. Vuoi procedere con l''installazione? +message.nickname.in.use = Nickname già in uso. Indicane un altro. +message.nickname.not.acceptable = Il cambio del nickname non è abilitato! +message.no.avatar.found = L'utente non ha configurato nessun avatar. +message.no.caller.id = Identificativo del chiamante non disponibile. +message.no.description.available = Nessuna descrizione disponibile +message.no.history.found = La cronologia non contiene conversazioni precedenti con questo utente. +message.no.results.found = La ricerca sul server non ha restituito nessun risultato. +message.no.room.to.join.error = Nessuna stanza in cui entrare +message.no.subject.available = Argomento non impostato +message.no.updates = Non sono disponibili aggiornamenti. +message.normal = Messaggio normale +message.number.to.call = Indicare il numero di telefono +message.offline = L'utente è offline e riceverà il tuo messaggio al prossimo login. +message.offline.error = L'utente non è in grado di ricevere messaggi offline. +message.participants.in.room = Partecipanti +message.password.error = Inserisci la password per questo account. +message.password.private.room.error = Indica una password per la stanza privata +message.passwords.no.match = Le Password sono diverse. +message.please.join.in.conference = Hai ricevuto un invito ad entrare in una stanza. +message.plugins.not.available = Impossibile contattare il server dei plugins. +message.prompt.plugin.uninstall = Confermi di voler disinstallare {0}? +message.received.file = Hai appena ricevuto un file da {0}. +message.receiving.file = Stai ricevendo un file da {0} +message.reconnect.attempting = Nuovo tentativo... +message.reconnect.failed = Riconnessione fallita. +message.reconnect.wait = Riconnessione tra {0} secondi. +message.register.transports = Registrati con i trasporti disponibili. +message.registering = Registrazione in corso con {0}. Attendere prego... +message.registration.transport.failed = Impossibile registrarsi con il trasporto. +message.restart.spark = E' necessario terminare il client \n per installare una nuova versione. Procedere ora? +message.restart.spark.changes = Il Plugin sarà disinstallato al prossimo riavvio di Spark. +message.restart.spark.to.install = E' necessario terminare il client per installare una nuova versione. Procedere ora? +message.restart.required = E' necessario riavviare Spark perché i cambiamenti abbiano effetto. Riavviare ora? +message.room.creation.error = La stanza non può essere creata. +message.room.destroyed = La stanza è stata eliminata per il seguente motivo: {0} +message.room.destruction.reason = Indica la ragione per cui distruggere la stanza? +message.room.information.for = Informazioni della stanza per {0} +message.save.profile = Per salvare le modifiche al tuo profilo, fai click su salva. +message.search.for.contacts = Ricerca Contatti. +message.search.for.other.people = Ricerca altre persone collegate al server. +message.search.input.short = Per favore inserire almeno due lettere. +message.search.service.not.available = Impossibile contattare i servizi di ricerca. +message.searching.please.wait = Ricerca in corso. Attendere prego... +message.select.add.room.to.add = Seleziona una stanza da inserire nell'elenco dei servizi. +message.select.one.or.more = Seleziona uno o più utenti dal tuo elenco. +message.select.room.to.enter = Indica la stanza in cui entrare. +message.select.room.to.join = Indica la stanza in cui entrare. +message.send.a.broadcast = Invia un messaggio broadcast +message.send.file.to.user = Invia file a questo utente. +message.send.picture = Invia l'immagine del tuo desktop. +message.send.to.these.people = Invia a queste persone +message.sending.file.to = Trasferimento del file a {0} in corso. +message.sent.offline.files = Hai ricevuto dei files offline. +message.server.unavailable = Il server non è raggiungibile. +message.service.already.exists = Il servizio è già presente nell'elenco. +message.shared.group = Gruppo Condiviso +message.specify.contact.jid = Indica il JID (ex. ddman@jabber.org) del contatto +message.specify.group = Indicare il gruppo di contatti in cui collocare l'utente. +message.specify.information.for.conference = Imposta le proprietà della Stanza. +message.specify.name.error = Indica un nome valido. +message.specify.users.to.join.conference = Indica gli utenti da invitare in questa stanza. +message.specify.valid.time.error = Indica dei valori validi per il timeout e la porta. +message.subject.change.error = non hai il permesso di cambiare l'argomento della stanza. +message.subject.has.been.changed.to = Il nuovo argomento è {0}. +message.supply.resource = Indica una risorsa valida. +message.supply.valid.port = Indica una porta valida. +message.supply.valid.timeout = Indica un timeout valido. +message.timeout.error = Il valore del timeout deve essere di minimo 5 secondi. +message.total.downloaded = Download totale +message.transfer.cancelled = Il trasferimento file è stato annullato. +message.transfer.complete = Il trasferimento del file è completo ({0}) +message.transfer.progressbar.text.received = {0} ricevuto @ {1} {2} +message.transfer.progressbar.text.sent = {0} inviato @ {1} {2} +message.transfer.rate = Velocità del trasferimento +message.transfer.refused = Il trasferimento file è stato rifiutato. +message.transfer.waiting.on.user = Attendi che {0} accetti il trasferimento del file. +message.unable.to.load.profile = Impossibile trovare il profilo di {0} +message.unable.to.retrieve.last.activity = Impossibile determinare l''ultima attività per {0}. +message.unable.to.save.password = Impossibile cambiare la password. Prego contattare l'amministratore. +message.unable.to.send.file = Impossibile inviare il file a {0}. +message.unable.to.use.hostname.as.resource = Impossibile utilizzare l'hostname come risorsa +message.unrecoverable.error = Errore non recuperabile. +message.update.room.list = Aggiorna l'elenco delle stanze +message.updating.cancelled = L'aggiornamento è stato annullato. +message.user.banned = {0} è stato bannato dalla stanza. +message.user.given.voice = {0} ha avuto il VOICE in questa stanza. +message.user.granted.admin = {0} ha ricevuto il privilegio di amministratore. +message.user.granted.membership = {0} ha ricevuto il privilegio di membro. +message.user.granted.moderator = {0} ha ricevuto il privilegio di moderatore. +message.user.granted.owner = {0} ha ricevuto il privilegio di proprietario. +message.user.is.sending.you.a.file = {0} ti sta trasmettendo un file. +message.user.joined.room = {0} è entrato nella stanza. +message.user.kicked.from.room = {0} è stato espulso dalla stanza. +message.user.left.room = {0} si è disconnesso dalla stanza. +message.user.nickname.changed = {0} ha cambiato il suo Nickname in {1}. +message.user.now.available.to.chat = {0} è online dalle {1} +message.user.revoked.admin = Il privilegio di amministratore è stato revocato a {0}. +message.user.revoked.membership = Il privilegio di membro è stato revocato a {0}. +message.user.revoked.moderator = Il privilegio di moderatore è stato revocato a {0}. +message.user.revoked.owner = Il privilegio di proprietario è stato revocato a {0}. +message.user.voice.revoked = Il VOICE di {0} è stato revocato. +message.username.error = Inserisci l'username per l'account. +message.username.password.error = E' necessario digitare nome utente e password. +message.vcard.not.supported = Il server non supporta le VCards. Impossibile salvarle. +message.version = Versione: {0} +message.view.information.about.this.user = Visualizza informazioni su questo utente. +message.waiting.for.user.to.join = In attesa che entri l'utente {0}. +message.went.offline = {0} è offline dalle {1} +message.you.have.been.banned = Sei stato bannato da questa stanza. +message.you.have.been.kicked = Sei stato espulso dalla stanza. +message.you.have.sent = Il trasferimento del file a {0} è appena terminato. +message.your.admin.granted = Ti sono stati concessi i privilegi di administrator. +message.your.banned = Sei stato bannato da questa stanza. +message.your.kicked = Sei stato espulso da {0}. +message.your.membership.granted = Ti sono stati concessi i privilegi di membro. +message.your.membership.revoked = I privilegi di membro ti sono stati revocati. +message.your.moderator.granted = Ti sono stati concessi i privilegi di moderatore. +message.your.moderator.revoked = I privilegi di moderatore ti sono stati revocati. +message.your.ownership.granted = Ti sono stati concessi i privilegi di proprietario. +message.your.ownership.revoked = I privilegi di proprietario ti sono stati revocati. +message.your.revoked.granted = I privilegi di administrator ti sono stati revocati. +message.your.voice.granted = Hai avuto il VOICE in questa chat. +message.your.voice.revoked = Ti è stato tolto il VOICE in questa chat. +message.groupchat.require.password = Questa stanza richiede una password per poter entrare +message.groupchat.registered.member = Registrato correttamento con {0} +message.search.for.history = Cerca nello storico conversazioni +message.search.period.day.one = un giorno per pagina +message.search.period.week.one = una settimana per pagina +message.search.period.month.one = un mese per pagina +message.search.period.year.one = un anno per pagina +message.search.period.none = mostra tutto in una pagina +message.search.page.timeperiod = scegli il periodo dei messaggi da visualizzare +message.search.page.counter = indice corrente della pagina e numero totale di pagine +message.search.page.right = naviga in avanti di una pagina +message.search.page.left = naviga indietro di una pagina + + + +status.away = Torno subito +status.custom.messages = Messaggi personalizzati +status.do.not.disturb = Non disturbare +status.extended.away = Non al computer +status.free.to.chat = Pronto a chattare +status.on.phone = Al telefono +status.online = Disponibile +status.pending = In attesa +status.invisible = Invisibile +status.offline = Offline + +tab.available.plugins = Plugin disponibili +tab.avatar = Avatar +tab.business = Lavoro +tab.conferences = Stanze +tab.contacts = Contatti +tab.deactivated.plugins = Plugin disattivati +tab.general = Generale +tab.home = Casa +tab.installed.plugins = Plugins Installati +tab.personal = Personale +tab.proxy = Proxy +tab.sso = SSO +tab.pki = PKI + +title.about = About +title.advanced.connection.preferences = Preferenze avanzate di connessione +title.account.created = Account creato +title.account.create.registration = Registrazione account +title.bookmarks = Preferiti +title.add.contact = Aggiungi contatto +title.add.contact.group = Aggiungi Gruppo di Contatti +title.add.new.group = Aggiungi Nuovo Gruppo +title.add.search.service = Aggiungi Servizio di Ricerca +title.add.to.roster = Aggiungi all'Elenco +title.address = Indirizzo +title.advanced.connection.sso = Utilizza Single Sign-On (SSO) +title.advanced.connection.usesso = Utilizza Single Sign-On (SSO) via GSSAPI +title.advanced.connection.sso.account = Utilizza desktop account per "{0}" per il collegamento al server. +title.advanced.connection.sso.unable = Impossibile connettersi con il Single Sign-On. Controlla le impostazioni del principal e del server. +title.advanced.connection.sso.noprincipal = Spark non riesce a trovare il principal per l'uso del Single Sign-On. Per questo motivo SSO non funzionerà.. +title.alert = Alert +title.appearance = Aspetto +title.appearance.preferences = Aspetto +title.available.transports = Trasporti Disponibili +title.broadcast.message = Messaggio Broadcast +title.browse.conference.services = Elenca i Servizi Conferenza +title.browse.room.service = Sfoglia Stanze - {0} +title.cancelled = Terminato +title.change.nickname = Cambia Nickname +title.change.subject = Cambia Argomento +title.chat = Chat +title.choose.directory = Scegli Directory +title.choose.incoming.sound = Scegli file audio da riprodurre all'arrivo +title.choose.offline.sound = Scegli file audio da riprodurre in offline +title.choose.outgoing.sound = Scegli file audio da riprodurre all'invio +title.conference.invitation = Invito alla stanza +title.client.logs = Log dei client +title.conference.rooms = Stanze +title.configure.chat.room = Configura la chat +title.configure.room = Configura la stanza +title.confirmation = Conferma +title.create.new.account = Crea nuovo account +title.create.or.bookmark.room = Entra nella stanza o mettila nei preferiti +title.create.room = Crea +title.create.problem = Problema nella creazione account +title.delete.file = Vuoi procedere con la cancellazione del file? +title.dial.phone = Chiama numero +title.disable.transport = Disabilita trasporto +title.download.complete = Download completato +title.downloading.im.client = Download IM client +title.downloads = Download +title.edit.custom.message = Modifica Messaggi Personalizzati +title.edit.profile = Modifica le Informazioni del profilo +title.enter.reason = Inserisci Motivazione +title.error = Errore +title.error.couldnot.open.file = Impossibile aprire il file +title.error.delete.file = Impossibile cancellare file +title.error.find.app = Impossibile trovare l''applicazione corrispondente +title.error.rename.file = Impossibile rinominare file +title.file = File +title.filesize = Dimensione +title.file.exists = Il File esiste +title.file.transfer = Trasferimento file +title.file.transfer.preferences = Preferenze di trasferimento file +title.find.conference.service = Cerca i servizi conferenza +title.find.contacts = Ricerca Contatti +title.gadugadu.registration = Credenziali account GaduGadu +title.general.media = Impostazioni media +title.general.chat.settings = Impostazioni generali per la chat +title.group.chat = Chat di gruppo +title.group.chat.settings = Impostazioni chat di gruppo +title.history.for = Cronologia delle conversazioni per {0} +title.irc.registration = Credenziali account IRC +title.sametime.registration = Credenziali account Sametime +title.facebook.registration = Credenziali account Facebook +title.myspace.registration = Credenziali account MySpace +title.incoming.call = Chiamata in arrivo +title.input.fileexplorer = Inserire il nome del browser: +title.input.newname = Inserire nuovo nome\: +title.input.openwith = Inserire il nome dell''applicazione da utilizzare: +title.invite.to.conference = Invita in una stanza +title.jabber.browser = Browser +title.join.conference.room = Entra nella stanza +title.last.activity = Ultima Attività +title.login = Login +title.login.error = Errore di login +title.login.no.account = Impossibile trovare account +title.login.settings = Parametri di login +title.lookup.profile = Ricerca del profilo +title.name = Nome +title.new.client.available = Nuovo client disponibile +title.new.roster.group = Nuovo gruppo di elenco +title.new.version.available = Nuova versione disponibile +title.no.updates = Nessun aggiornamento +title.notes = Note +title.notification = Notifica +title.notifications = Notifiche +title.occupants = Presenti +title.on.the.phone = Al Telefono +title.password = Password +title.password.required = Richiesta una password +title.passwords.no.match = Conferma passwords. +title.person.search = Ricerca Persona +title.plugins = Plugins +title.preferences = Preferenze +title.profile.information = Informazioni Profilo +title.profile.not.found = Profilo Non Trovato +title.qq.registration = Credenziali account QQ +title.register.account = Registra nuovo account +title.registration.error = Errore di registrazione +title.reminder = Promemoria +title.rename.roster.group = Rinomina l''elenco +title.room.destroyed = Stanza eliminata +title.room.information = Informazioni stanza +title.roster = Elenco +title.select.file.to.send = Seleziona il/i file da inviare +title.set.status.message = Imposta messaggi di stato +title.simple.registration = Credenziali account SIMPLE +title.sound.preferences = Preferenze suoni +title.sounds = Suoni +title.spark.preferences = Preferenze di Spark +title.start.chat = Avvia Chat +title.status.message = Messaggio di status +title.task.notification = Notifica task +title.tasks = Impegni +title.transports = Trasporti +title.tray.information = Informazioni sulla Tray +title.upgrading.client = Aggiornamento client +title.version.and.time = Versione e Ora +title.view.bookmarks = Visualizza Preferiti +title.view.profile.for = Visualizzazione Profilo Per {0} +title.view.room.information = Visualizza informazioni sulla stanza +title.waiting.to.call = In attesa di effettuare la chiamata +title.xmpp.registration = Credenziali Account XMPP +title.appearance.showVCards = Mostra &VCards nella lista dei contatti +title.subscription.request = Richiesta di sottoscrizione + +tooltip.place.a.call = Effettua una chiamata questa persona +tooltip.appearance = Modifica l'aspetto di Spark +tooltip.file.transfer = Impostazioni trasferimento file +tooltip.notifications = Notifica preferenze per le chat in arrivo. +tooltip.place.voice.call = Fai una chiamata vocale. +tooltip.send.email = Invia una email. +tooltip.start.chat = Avvia una conversazione. +tooltip.view.changelog = Visualizza il ChangeLog +tooltip.view.history = Visualizza lo storico delle conversazioni +tooltip.view.readme = Visualizza ReadMe + +tree.conference.services = Servizi conferenza +tree.users.in.room = Utenti nella stanza + +lookandfeel.select = Seleziona aspetto +lookandfeel.change.now = Cambia ora +lookandfeel.tooltip.restart.no = Non è necessario alcun riavvio +lookandfeel.tooltip.restart.yes = Per passare al nuovo stile premere Salva e riavviare Spark +lookandfeel.color.label = Colori +lookandfeel.color.red = Rosso +lookandfeel.color.green = Verde +lookandfeel.color.blue = Blu +lookandfeel.color.opacity = Opacità +lookandfeel.color.saved = Colore salvato + + +##Settings for the privacy plugin +privacy.title.preferences = Impostazioni di privacy di Spark +privacy.title.panel = Utilizza il tasto destro del mouse +privacy.label.iq.desc = Query +privacy.label.pin.desc = Presenza dentro +privacy.label.pout.desc = Presenza fuori +privacy.label.msg.desc = Messaggi +privacy.border.information = Informazioni sulla privacy +privacy.label.information = Utilizza il tasto destro del mouse per aggiungere o cancellare liste od oggetti +privacy.root.node = Liste di privacy +privacy.label.preferences = Plugin di privacy +privacy.tooltip.preferences = Impostazioni di privacy di Spark +privacy.label.list.is.active = Lista attiva: +privacy.label.list.is.default = Lista di default: +privacy.border.block = Blocca +privacy.pick.one.or.more = Scegli uno o più elementi da aggiungere alla lista +privacy.title.add.picker = Aggiungi elementi alla lista +privacy.node.contacts = Contatti +privacy.node.groups = Gruppi +privacy.menu.add.contacts = Aggiungi i contatti alla lista +privacy.menu.add.groups = Aggiungi i gruppi alla lista +privacy.menu.add.rem.items = Rimuovi {0} oggetti dalla lista +privacy.menu.remove = Rimuovi +privacy.menu.activate.list = Attiva +privacy.menu.default.list = Imposta come default +privacy.menu.add.list = Aggiungi lista +privacy.menu.remove.list = Rimuovi lista +privacy.dialog.add.list = Inserisci il nome della lista +privacy.dialog.rem.list = Vuoi davvero rimuovere {0}? +privacy.status.menu.entry = Liste di privacy +privacy.name.for.default.list = Default +privacy.button.no.list.selected = Nessuna lista selezionata +privacy.menuitem.deactivate.current.list = Disattiva {0} +privacy.label.not.supported = Le liste di privacy non sono supportate dal server. + +##Stunfallback in media settings +stun.border.label = STUN fallback server +stun.server.addr = STUN Server: +stun.server.port = STUN Port: + +composing = {0} sta digitando... +paused = {0} ha smesso di digitare +active = {0} sta prestando attenzione +inactive = {0} sta facendo altro +gone = {0} sta facendo altro + +action.viewlog=Vedi log + +dialog.confirm.to.reveal.visibility.title= Sei sicuro? +dialog.confirm.to.reveal.visibility.msg= Se procedi, la tua invisibilità verrà rivelata +dialog.confirm.close.all.conferences.if.invisible.msg= Se procedi, tutte le stanze verranno chiuse diff --git a/core/src/main/resources/i18n/spark_i18n_ja.properties b/core/src/main/resources/i18n/spark_i18n_ja.properties new file mode 100644 index 000000000..344be2b8a --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_ja.properties @@ -0,0 +1,572 @@ +ok = Ok +cancel = キャンセル +add = 追加 +use.default = デフォルト +close = é–‰ã˜ã‚‹ +create = ä½œæˆ +invite = 招待 +date = 削除 +from = From +room.name = ルームå +join = å‚加 +description = 詳細 +subject = 対象 +occupants = å æœ‰è€… +accept = 承諾 +reject = æ‹’çµ¶ +open = é–‹ã +open.folder = フォルダを開ã +retry = リトライ +is.active = アクティブ +not.registered = 登録ã—ã¦ã„ãªã„ +save = ä¿å­˜ +yes = ã¯ã„ +no = ã„ã„㈠+broadcast = ブロードキャスト +available = 使用å¯èƒ½ +user.has.signed.off = æ—¢ã«ã‚µã‚¤ãƒ³ã‚ªãƒ• + + +button.create.account = ã‚¢ã‚«ã‚¦ãƒ³ãƒˆä½œæˆ +button.close = é–‰ã˜ã‚‹ +button.advanced = 上級者用 +button.browse = 見る... +button.browse2 = 見る... +button.browse3 = 見る... +button.approve = èªå¯ +button.deny = å¦èª +button.accept = 承諾 +button.profile = プロファイル +button.add.a.contact = 連絡先を追加 +button.reconnect = å†æŽ¥ç¶š +button.add = 追加 +button.roster = åç°¿ +button.add.bookmark = ブックマーク追加 +button.remove.bookmark = ブックマーク削除 +button.bookmark.room = ルームをブックマーク +button.create.room = ãƒ«ãƒ¼ãƒ ã‚’ä½œæˆ or å‚加 +button.join.room = é¸æŠžã—ãŸãƒ«ãƒ¼ãƒ ã«å‚加 +button.refresh = æ›´æ–° +button.find = 検索 +button.update = æ›´æ–° +button.cancel = キャンセル +button.decline = 辞退 +button.join = å‚加 +button.save.for.future.use = 利用ã®ãŸã‚ã®ä¿å­˜ +button.register = 登録 +button.dial.number = ãƒ€ã‚¤ã‚¢ãƒ«ç•ªå· +button.clear = クリア +button.search = 検索 +button.add.service = サービス追加 +button.quit = 終了 +button.new = æ–°è¦ +button.add.user = ユーザ追加 +button.save = ä¿å­˜ +button.start.chat = ãƒãƒ£ãƒƒãƒˆ +button.send.email = メール +button.send = é€ã‚‹ + + + +checkbox.save.password = パスワードをä¿å­˜ +checkbox.auto.login = オートログイン +checkbox.use.proxy.server = プロキシーサーãƒãƒ¼ã‚’使ㆠ+checkbox.auto.discover.port = 自動的ã«ãƒ›ã‚¹ãƒˆã‚’見ã¤ã‘ã‚‹ +checkbox.permanent = 永続的ãªãƒ«ãƒ¼ãƒ  +checkbox.private.room = プライベートãªãƒ«ãƒ¼ãƒ  +checkbox.show.time.in.chat.window = ãƒãƒ£ãƒƒãƒˆã‚¦ã‚£ãƒ³ãƒ‰ã‚¦å†…ã§ã®æ™‚é–“ã®è¡¨ç¤º +checkbox.show.notifications.in.conference = 会議室ã§é€šçŸ¥ã‚’表示 +checkbox.disable.chat.history = ãƒãƒ£ãƒƒãƒˆå±¥æ­´ã®ç„¡åŠ¹åŒ– +checkbox.show.toaster = トーストãƒãƒƒãƒ—アップを表示 +checkbox.window.to.front = ウィンドウをå‰ã«è¡¨ç¤º +checkbox.play.sound.on.new.message = æ–°ã—ã„メッセージãŒå±Šã„ãŸã‚‰é€šçŸ¥éŸ³ã‚’鳴ら㙠+checkbox.play.sound.when.offline = ユーザãŒã‚ªãƒ•ラインã«ãªã£ãŸã‚‰é€šçŸ¥éŸ³ã‚’鳴ら㙠+checkbox.play.sound.on.outgoing.message = メッセージをé€ã‚ŒãŸã‚‰é€šçŸ¥éŸ³ã‚’鳴ら㙠+checkbox.play.sound.on.invitation = 招待をå—ã‘ãŸã‚‰é€šçŸ¥éŸ³ã‚’鳴ら㙠+checkbox.idle.enabled = アイドルを有効ã«ã™ã‚‹ +checkbox.launch.on.startup = スタートアップã¨åŒæ™‚ã«èµ·å‹•ã™ã‚‹ +checkbox.start.in.tray = システムトレイã§ã‚¹ã‚¿ãƒ¼ãƒˆ +checkbox.split.chat.window = ウィンドウをドックã«å…¥ã‚Œã‚‹ (å†èµ·å‹•ãŒå¿…è¦) +checkbox.tabs.on.top = ãƒãƒ£ãƒƒãƒˆã‚¿ãƒ–をトップã«è¡¨ç¤º (å†èµ·å‹•ãŒå¿…è¦) +checkbox.tabs.scroll = ãƒãƒ£ãƒƒãƒˆ タブã®ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«ã‚’使用ã™ã‚‹ (å†èµ·å‹•ãŒå¿…è¦) +checkbox.allow.buzz = 通知音を許å¯ã™ã‚‹ +checkbox.enable.emoticons = アイコンを有効ã«ã™ã‚‹ +checkbox.use.system.look.and.feel = システムã®ãƒ«ãƒƒã‚¯ï¼†ãƒ•ィールを用ã„ã‚‹ (å†èµ·å‹•ãŒå¿…è¦) +checkbox.close.unread.message = ウィンドウを閉ã˜ã‚‹ã¨ãã«æœªèª­ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒã‚ã‚‹ã‹ã©ã†ã‹ã‚’確èªã™ã‚‹ + + +label.user.on.public.network = ユーザãŒãƒ‘ブリックãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«ã„ã‚‹ +label.change.password.to = パスワードを変更 +label.username = ユーザå +label.name = åå‰ +label.room.name = ルームå +label.room.topic= ルームトピック +label.password = パスワード +label.confirm.password = ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ç¢ºèª +label.server = ドメイン +label.create.account = ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’ä½œæˆ +label.close = é–‰ã˜ã‚‹ +label.ok = OK +label.cancel = キャンセル +label.use.default = デフォルトを用ã„ã‚‹ +label.port = ãƒãƒ¼ãƒˆ +label.auto.login = 自動的ã«ãƒ­ã‚°ã‚¤ãƒ³ +label.old.ssl = å¤ã„SSLãƒãƒ¼ãƒˆãƒ¢ãƒ¼ãƒ‰ã‚’用ã„ã‚‹ +label.host = ホスト +label.resource = リソース +label.protocol = プロトコル +label.accounts = アカウント +label.received = å—ä¿¡ã•れã¾ã—㟠+label.transfer.timeout = 通信タイムアウト(分): +label.transfer.download.directory = ダウンロードディレクトリ: +label.find = 検索 +label.rename.to = æ–°ã—ã„åå‰ +label.contact.to.find = 連絡先を探㙠+label.available.users.in.roster = åç°¿ã®ãƒ¦ãƒ¼ã‚¶ã‚’有効 +label.time = 時間: {0} +label.add.conference.service = 会議サービスを追加 +label.add.jid = JIDを追加 +label.message = メッセージ +label.room = ルーム +label.invited.users = 招待ã—ãŸãƒ¦ãƒ¼ã‚¶ +label.new.nickname = æ–°ã—ã„ニックãƒãƒ¼ãƒ  +label.server.address = サーãƒãƒ¼ã‚¢ãƒ‰ãƒ¬ã‚¹ +label.nickname = ニックãƒãƒ¼ãƒ  +label.presence = 出席 +label.priority = é‡è¦åº¦ +label.enter.address = アドレスを入力 +label.jabber.address = Jabberアドレス +label.local.time = ローカルタイム +label.software = プログラム +label.version = ãƒãƒ¼ã‚¸ãƒ§ãƒ³ +label.os = オペレーティングシステム +label.number = ç•ªå· +label.dial = ダイアル +label.minutes.before.stale.chat = 利用ã•れãªã„ルームãŒä¸æ´»ç™ºã«ãªã‚‹ã¾ã§ã®æ™‚間(分) +label.company = 会社 +label.street.address = 番地 +label.city = å¸‚åŒºç”ºæ‘ +label.state.and.province = 都é“府県 +label.postal.code = éƒµä¾¿ç•ªå· +label.country = 国 +label.job.title = 肩書ã +label.department = 部署 +label.phone = é›»è©±ç•ªå· +label.fax = ファックス +label.mobile = æºå¸¯é›»è©± +label.web.page = ホームページ +label.pager = ãƒã‚±ãƒ™ãƒ« +label.first.name = åå‰ +label.middle.name = ミドルãƒãƒ¼ãƒ  +label.last.name = å§“ +label.email.address = é›»å­ãƒ¡ãƒ¼ãƒ« +label.jid = &JID +label.search.service = サービス検索 +label.xmpp.port = &XMPP ãƒãƒ¼ãƒˆ +label.response.timeout = レスãƒãƒ³ã‚¹ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆ (ç§’) +label.time.till.idle = アイドルã¾ã§ã®æ™‚é–“ (分) +label.jabber.id = &Jabber ID +label.group = グループ +label.enter.group.name = グループåを入力 +label.network = ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ +label.unable.to.add.contact = 連絡先ã®è¿½åŠ ãŒä¸å¯ +label.conflict.error = æ—¢ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã®å ´åˆã¯ãƒ­ã‚°ã‚¤ãƒ³ä¸å¯ +label.message.style = メッセージスタイル +label.emoticons = 感情アイコン + + +message.username.error = ユーザーåを入力ã—ã¦ãã ã•ã„。 +message.password.error = パスワードを入力ã—ã¦ãã ã•ã„。 +message.confirmation.password.error = 確èªç”¨ãƒ‘スワードを入力ã—ã¦ãã ã•ã„。 +message.account.error = アカウントを作æˆã™ã‚‹ã‚µãƒ¼ãƒãƒ¼ã‚’入力ã—ã¦ãã ã•ã„。 +message.registering = {0}を登録中。ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„〠+message.connection.failed = {0}ã«æŽ¥ç¶šã§ãã¾ã›ã‚“。 +message.create.account = アカウントãŒä½œæˆã§ãã¾ã›ã‚“。 +message.already.exists = ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒæ—¢ã«å­˜åœ¨ã—ã¾ã™ã€åˆ¥ã®ãƒ¦ãƒ¼ã‚¶åã§è©¦ã—ã¦ãã ã•ã„。 +message.account.created = æ–°ã—ã„ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯æ—¢ã«ä½œæˆæ¸ˆã¿ã§ã™ã€‚ +message.account.create = æ–°ã—ã„ãƒãƒ£ãƒƒãƒˆã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’作æˆã™ã‚‹ã€‚ +message.connecting.please.wait = 接続中。ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„〠+message.supply.valid.timeout = æ­£ã—ã„タイムアウト時間を設定ã—ã¦ãã ã•ã„。 +message.supply.valid.port = æ­£ã—ã„ãƒãƒ¼ãƒˆç•ªé ­ã‚’設定ã—ã¦ãã ã•ã„。 +message.supply.resource = æ­£ã—ã„リソースを設定ã—ã¦ãã ã•ã„。 +message.current.status = ç¾åœ¨ã®çŠ¶æ…‹ã‚’ã»ã‹ã®ãƒ¦ãƒ¼ã‚¶ã«çŸ¥ã‚‰ã›ã¦ãã ã•ã„。 +message.disconnected.error = ã‚ãªãŸã®æŽ¥ç¶šã¯ã‚¨ãƒ©ãƒ¼ã«ã‚ˆã‚Šã‚¯ãƒ­ãƒ¼ã‚ºã•れã¾ã—ãŸã€‚ +message.disconnected.group.chat.error = ã‚ãªãŸã®æŽ¥ç¶šã¯ã‚¨ãƒ©ãƒ¼ã«ã‚ˆã‚Šã‚¯ãƒ­ãƒ¼ã‚ºã•れã¾ã—ãŸã€‚å†æŽ¥ç¶šå¾Œã«å†åº¦å‚加ã—ã¦ãã ã•ã„。 +message.disconnected.conflict.error = ã‚ãªãŸã®æŽ¥ç¶šã¯åŒã˜ãƒ¦ãƒ¼ã‚¶ãŒåˆ¥ã®å ´æ‰€ã‹ã‚‰ãƒ­ã‚°ã‚¤ãƒ³ã—ãŸã“ã¨ã«ã‚ˆã‚Šã‚¯ãƒ­ãƒ¼ã‚ºã•れã¾ã—ãŸã€‚ +message.locked.workstation = ユーザã®ãƒ¯ãƒ¼ã‚¯ã‚¹ãƒ†ãƒ¼ã‚·ãƒ§ãƒ³ãŒãƒ­ãƒƒã‚¯ã•れã¾ã—ãŸã€‚ +message.away.idle = アイドル状態ã«ã‚ˆã‚Šé›¢å¸­ã—ã¦ãã ã•ã„。 +message.default.error = エラーを検知ã—ã¾ã—ãŸã€‚support@jivesoftware.com.ã¸ãƒ¬ãƒãƒ¼ãƒˆã—ã¦ãã ã•ã„。 +message.new.message = {0}ã‹ã‚‰æ–°ã—ã„メッセージã§ã™ã€‚ +message.send.file.to.user = ã“ã®ãƒ¦ãƒ¼ã‚¶ã«ãƒ•ァイルをé€ä¿¡ã—ã¾ã™ã€‚ +message.send.picture = ç”»é¢ã®å†…容をキャプãƒãƒ£ã—ã¦é€ã‚‹ã€‚ +message.sent.offline.files = オフラインファイルをã¡ã‚‡ã†ã©é€ã‚Šã¾ã—ãŸã€‚ +message.search.for.contacts = 連絡先を検索 +message.end.conversation = ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’終ãˆã¾ã™ã‹ï¼Ÿ +message.end.chat = ã“ã®ãƒãƒ£ãƒƒãƒˆã‚’終ãˆã¾ã™ã‹ï¼Ÿ +message.close.this.chat = ã“ã®ãƒãƒ£ãƒƒãƒˆã‚’é–‰ã˜ã‚‹ã€‚ +message.close.other.chats = ä»–ã®ã™ã¹ã¦ã®ãƒãƒ£ãƒƒãƒˆã‚’é–‰ã˜ã‚‹ã€‚ +message.close.stale.chats = å¤ã„ãƒãƒ£ãƒƒãƒˆã‚’é–‰ã˜ã‚‹ã€‚ +message.close.unread.window = 未読ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒã‚りã¾ã™ã€‚ウィンドウを閉ã˜ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹? +message.last.message.received = 最終å—信メッセージ時刻 {0} +message.shared.group = 共有グループ +message.is.shared.group = {0}ã¯å…±æœ‰ã‚°ãƒ«ãƒ¼ãƒ—ã§ã™ã€‚ +message.delete.confirmation = {0}を削除ã—ã¾ã™ã‹ï¼Ÿ +message.idle.for = {0}ã®ãŸã‚アイドル状態 +message.enter.broadcast.message = é¸æŠžã—ãŸãƒ¦ãƒ¼ã‚¶ã¸ã®ãƒ–ロードキャストメッセージを入力ã—ã¦ãã ã•ã„。 +message.name.of.group = グループã®åå‰ +message.approve.subscription = {0}ã«åç°¿ã®ç™»éŒ²ã‚’許å¯ã—ã¾ã™ã‹ï¼Ÿ +message.add.user = åç°¿ã«ãƒ¦ãƒ¼ã‚¶ã‚’登録ã—ã¾ã™ã‹ï¼Ÿ +message.general.error = {0}ã«ã‚ˆã‚Šã€ã‚µãƒ¼ãƒãƒ¼ã¸ã®æŽ¥ç¶šãŒå‡ºæ¥ãªããªã‚Šã¾ã—ãŸã€‚ +message.add.a.contact = 連絡先を追加 +message.generic.reconnect.message = サーãƒãƒ¼ã¸ã®æŽ¥ç¶šãŒå‡ºæ¥ãªããªã‚Šã¾ã—ãŸã€‚å†åº¦ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹ã«ã¯ã€å†æŽ¥ç¶šãƒœã‚¿ãƒ³ã‚’押ã—ã¦ãã ã•ã„。 +message.select.one.or.more = åç°¿ã‹ã‚‰ï¼‘人ã‹ã‚‰ãれ以上ã®ãƒ¦ãƒ¼ã‚¶ã‚’é¸æŠžã—ã¦ãã ã•ã„。 +message.add.conference.service = 会議サービスを追加 +message.service.already.exists = ã‚µãƒ¼ãƒ“ã‚¹ã¯æ—¢ã«ãƒªã‚¹ãƒˆã«åœ¨ã‚Šã¾ã™ã€‚ +message.searching.please.wait = 検索中。ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„... +message.conference.service.error = 会議室を見るã‘ã‚‹ã“ã¨ãŒå‡ºæ¥ã¾ã›ã‚“ã§ã—ãŸã€‚ +message.create.or.join.room = 会議室を作æˆã¾ãŸã¯å‚加ã—ã¦ãã ã•ã„。 +message.specify.name.error = æ­£ã—ã„åå‰ã‚’入力ã—ã¦ãã ã•ã„。 +message.password.private.room.error = プライベートルームã®ãƒ‘スワードを入力ã—ã¦ãã ã•ã„。 +message.passwords.no.match = パスワードãŒä¸€è‡´ã—ã¾ã›ã‚“。 +message.enter.valid.jid = æ­£ã—ã„ Jabber ID を入力ã—ã¦ãã ã•ã„。 +message.please.join.in.conference = ç§ã‚‚会議ã«å‚加ã•ã›ã¦ãã ã•ã„。 +message.invite.users.to.conference = 会議室ã«ãƒ¦ãƒ¼ã‚¶ã‚’招待ã™ã‚‹ã€‚ +message.specify.users.to.join.conference = ã“ã®ä¼šè­°å®¤ã«å‚加ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ã‚’指定ã—ã¦ãã ã•ã„。 +message.no.room.to.join.error = å‚加ã™ã‚‹ãƒ«ãƒ¼ãƒ ãŒã‚りã¾ã›ã‚“。 +message.participants.in.room = ルームã®é–¢ä¿‚者 +message.you.have.been.kicked = ã‚ãªãŸã¯ã“ã®éƒ¨å±‹ã‹ã‚‰è¿½ã„出ã•れã¾ã—ãŸã€‚ +message.kicked.error = {0}ã‚’ã“ã®éƒ¨å±‹ã‹ã‚‰è¿½ã„出ã™ã“ã¨ãŒã§ãã¾ã›ã‚“。 +message.you.have.been.banned = ã‚ãªãŸã¯ã“ã®éƒ¨å±‹ã‹ã‚‰ç¦æ­¢ã•れã¾ã—ãŸã€‚ +message.nickname.in.use = ニックãƒãƒ¼ãƒ ãŒä½¿ç”¨ã•れã¦ã„ã¾ã™ã€‚ä»–ã®ãƒ‹ãƒƒã‚¯ãƒãƒ¼ãƒ ã‚’指定ã—ã¦ãã ã•ã„。 +message.update.room.list = ルーム一覧を更新ã™ã‚‹ã€‚ +message.join.conference.room = 会議室ã«å‚加ã™ã‚‹ã€‚ +message.select.add.room.to.add = サービスリストã«è¿½åŠ ã™ã‚‹ãƒ«ãƒ¼ãƒ ã‚’é¸æŠžã—ã¦ãã ã•ã„。 +message.bookmark.temporary.room.error = テンãƒãƒ©ãƒªãƒ«ãƒ¼ãƒ ã¯ãƒ–ックマークã™ã‚‹ã“ã¨ãŒå‡ºæ¥ã¾ã›ã‚“。 +message.select.room.to.join = å‚加ã™ã‚‹ãƒ«ãƒ¼ãƒ ã‚’é¸æŠžã—ã¦ãã ã•ã„。 +message.conference.info.error = 会議室情報を検索ã™ã‚‹ã“ã¨ãŒå‡ºæ¥ã¾ã›ã‚“。後ã»ã©è©¦ã—ã¦ã¿ã¦ãã ã•ã„。 +message.add.favorite.room = ãƒ«ãƒ¼ãƒ ã‚’ãŠæ°—ã«å…¥ã‚Šãƒªã‚¹ãƒˆã«è¿½åŠ ã™ã‚‹ã‹ã€ç›´æŽ¥å‚加ã—ã¦ãã ã•ã„。 +message.select.room.to.enter = 入室ã™ã‚‹ãƒ«ãƒ¼ãƒ ã‚’指定ã—ã¦ãã ã•ã„。 +message.find.conference.services = 会議室サービスを探ã™ã€‚ +message.specify.information.for.conference = ä¼šè­°å®¤ã®æƒ…報を入力ã—ã¦ãã ã•ã„。 +message.no.description.available = 利用å¯èƒ½ãªè©³ç´°ãŒã‚りã¾ã›ã‚“。 +message.no.subject.available = 利用å¯èƒ½ãªè©±é¡ŒãŒã‚りã¾ã›ã‚“。 +message.room.information.for = {0}ã®ãŸã‚ã®ãƒ«ãƒ¼ãƒ æƒ…å ± +message.view.information.about.this.user = ã“ã®ãƒ¦ãƒ¼ã‚¶ã®æƒ…報をå‚ç…§ã—ã¦ãã ã•ã„。 +message.add.this.user.to.your.roster = ã“ã®ãƒ¦ãƒ¼ã‚¶ã‚’å‹é”リストã«è¿½åŠ ã—ã¦ãã ã•ã„。 +message.came.online = {0}ã¯{1}ã®ç‚ºã‚ªãƒ•ラインã§ã™ã€‚ +message.went.offline = {0}ã¯{1}ã®ç‚ºã‚ªãƒ•ラインã«ãªã‚Šã¾ã—ãŸã€‚ +message.offline.error = ユーザã¯ã‚ªãƒ•ラインメッセージをå—ã‘å–ã‚‹ã“ã¨ã¯å‡ºæ¥ã¾ã›ã‚“。 +message.offline = ユーザãŒã‚ªãƒ•ラインã§ã™ã€æ¬¡å›žãƒ¦ãƒ¼ã‚¶ãŒãƒ­ã‚°ã‚¤ãƒ³ã—ãŸæ™‚ã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒå—ã‘å–られã¾ã™ã€‚ +message.is.typing.a.message = {0}ã¯ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’入力ã—ã¦ã„ã¾ã™... +message.enter.new.subject = æ–°ãŸãªè©±é¡Œã‚’入力ã—ã¦ãã ã•ã„。 +message.confirm.destruction.of.room = ルームを破棄ã™ã‚‹ã“ã¨ã¯ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ã‚’ã“ã®ãƒ«ãƒ¼ãƒ ã‹ã‚‰å‰Šé™¤ã™ã‚‹ã“ã¨ã«ãªã‚Šã¾ã™ãŒã€ç ´æ£„ã—ã¾ã™ã‹ï¼Ÿ +message.room.destruction.reason = ルームを破棄ã™ã‚‹ç†ç”±ã¯ã‚りã¾ã™ã‹ï¼Ÿ +message.user.left.room = {0}ã¯é€€å‡ºã—ã¾ã—ãŸã€‚ +message.user.joined.room = {0}ã¯ãƒ«ãƒ¼ãƒ ã«å‚加ã—ã¾ã—ãŸã€‚ +message.chat.session.ended = ãƒãƒ£ãƒƒãƒˆã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯{0}ã§çµ‚ã‚りã¾ã—ãŸã€‚ +message.subject.change.error = ã“ã®ãƒ«ãƒ¼ãƒ ã®è©±é¡Œã®å¤‰æ›´ã¯è¨±ã•れã¦ã„ã¾ã›ã‚“。 +message.forbidden.error = サーãƒãƒ¼ãŒã‚¨ãƒ©ãƒ¼ã‚’è¿”ã—ã¾ã—ãŸã€‚ +message.room.destroyed = ルームã¯ä»¥ä¸‹ã®ç†ç”±ã§å‰Šé™¤ã•れã¾ã—ãŸ: {0} +message.subject.has.been.changed.to = 話題ã¯{0}ã«å¤‰æ›´ã•れã¾ã—ãŸã€‚ +message.user.kicked.from.room = {0}ã¯ãƒ«ãƒ¼ãƒ ã‹ã‚‰è¿½ã„出ã•れã¾ã—ãŸã€‚ +message.user.given.voice = {0}ã¯ã“ã®ãƒ«ãƒ¼ãƒ ã§ç™ºè¨€ã‚’与ãˆã¾ã—ãŸã€‚ +message.user.voice.revoked = 発言ã¯{0}ã®ãŸã‚ã«å–り消ã•れã¾ã—ãŸã€‚ +message.user.banned = {0}ã¯ã“ã®ãƒ«ãƒ¼ãƒ ã‹ã‚‰ã€ç¦æ­¢ã•れã¾ã—ãŸã€‚ +message.user.granted.membership = {0}ã¯ãƒ¡ãƒ³ãƒãƒ¼ã‚·ãƒƒãƒ—を与ãˆã‚‰ã‚Œã¦ã„ã¾ã™ã€‚ +message.user.revoked.membership = メンãƒãƒ¼ã‚·ãƒƒãƒ—ã¯{0}ã®ãŸã‚ã«å–り消ã•れã¾ã—ãŸã€‚ +message.user.granted.moderator = {0}ã¯å¸ä¼šè€…権é™ã‚’与ãˆã‚‰ã‚Œã¦ã„ã¾ã™ã€‚ +message.user.revoked.moderator = å¸ä¼šè€…特権ã¯{0}ã®ãŸã‚ã«å–り消ã•れã¾ã—ãŸã€‚ +message.user.granted.owner = {0}ã¯ã‚ªãƒ¼ãƒŠãƒ¼æ¨©é™ã‚’与ãˆã‚‰ã‚Œã¦ã„ã¾ã™ã€‚ +message.user.revoked.owner = オーナー特権ã¯{0}ã®ãŸã‚ã«å–り消ã•れã¾ã—ãŸã€‚ +message.user.granted.admin = {0}ã¯ç®¡ç†è€…権é™ã‚’与ãˆã‚‰ã‚Œã¦ã„ã¾ã™ã€‚ +message.user.revoked.admin = 管ç†è€…特権ã¯{0}ã®ãŸã‚ã«å–り消ã•れã¾ã—ãŸã€‚ +message.user.nickname.changed = {0}ã¯{1}ã¨ã—ã¦è­˜åˆ¥ã•れã¾ã—ãŸã€‚ +message.your.kicked = {0}ã«ã‚ˆã£ã¦è¿½ã„出ã•れã¾ã—ãŸã€‚ +message.your.voice.granted = ã“ã®ãƒãƒ£ãƒƒãƒˆã«å¯¾ã—ã¦ç™ºè¨€ã‚’ã—ã¾ã—ãŸã€‚ +message.your.voice.revoked = ã‚ãªãŸã®ç™ºè¨€ã¯å–り消ã•れã¾ã—ãŸã€‚ +message.your.banned = ã‚ãªãŸã¯ã“ã®ãƒ«ãƒ¼ãƒ ã‹ã‚‰ç¦æ­¢ã•れã¾ã—ãŸã€‚ +message.your.membership.granted = メンãƒãƒ¼ã‚·ãƒƒãƒ—ãŒä¸Žãˆã‚‰ã‚Œã¾ã—ãŸã€‚ +message.your.membership.revoked = メンãƒãƒ¼ã‚·ãƒƒãƒ—ãŒå–り消ã•れã¾ã—ãŸã€‚ +message.your.moderator.granted = å¸ä¼šè€…権é™ãŒä¸Žãˆã‚‰ã‚Œã¾ã—ãŸã€‚ +message.your.moderator.revoked = å¸ä¼šè€…権é™ãŒå–り消ã•れã¾ã—ãŸã€‚ +message.your.ownership.granted = オーナー権é™ãŒä¸Žãˆã‚‰ã‚Œã¾ã—ãŸã€‚ +message.your.ownership.revoked = オーナー権é™ãŒå–り消ã•れã¾ã—ãŸã€‚ +message.your.admin.granted = ç®¡ç†æ¨©é™ãŒä¸Žãˆã‚‰ã‚Œã¾ã—ãŸã€‚ +message.your.revoked.granted = ç®¡ç†æ¨©é™ãŒå–り消ã•れã¾ã—ãŸã€‚ +message.send.a.broadcast = ブロードキャストをé€ä¿¡ã—ã¾ã—ãŸã€‚ +message.broadcast.from = {0}ã‹ã‚‰ãƒ–ロードキャストã•れã¾ã—ãŸã€‚ +message.enter.message.to.broadcast = å簿一覧ã¸ã®ãƒ–ロードキャストメッセージを入力ã—ã¦ãã ã•ã„。 +message.broadcast.message.sent = ブロードキャストメッセージã¯é€ä¿¡ã•れã¾ã—ãŸã€‚ +message.broadcast.to = {0}ã¸ã®ãƒ–ロードキャストメッセージを入力ã—ã¦ãã ã•ã„。 +message.hasbeenbroadcast.to = メッセージã¯ä»¥ä¸‹ã®ãƒ¦ãƒ¼ã‚¶ã«ãƒ–ロードキャストã•れã¾ã—ãŸã€‚\n{0} +message.user.now.available.to.chat = {0}ã¯{1}ã§ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ä¸­ +message.user.is.sending.you.a.file = {0}ã¯ãƒ•ァイルをã‚ãªãŸã«é€ä¿¡ã—ã¦ã„ã¾ã™ã€‚ +message.file.transfer.canceled = ファイル転é€ã‚’キャンセルã—ã¾ã—ãŸã€‚ +message.negotiate.file.transfer = ファイル転é€ã‚’交渉中。ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„... +message.negotiate.stream = コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚¹ãƒˆãƒªãƒ¼ãƒ ã‚’交渉中。ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„... +message.receiving.file = {0}ã‹ã‚‰ãƒ•ァイルをå—信中 +message.click.to.open = クリックã§é–‹ã +message.error.during.file.transfer = ファイル転é€ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒèµ·ã“りã¾ã—ãŸã€‚ +message.transfer.refused = ファイル転é€ã¯æ‹’å¦ã•れã¾ã—ãŸã€‚ +message.transfer.cancelled = ファイル転é€ã¯ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•れã¾ã—ãŸã€‚ +message.received.file = {0}ã‹ã‚‰ãƒ•ァイルをå—ä¿¡ã—ã¾ã—ãŸã€‚ +message.file.exists.question = ãƒ•ã‚¡ã‚¤ãƒ«ã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚上書ãã¾ã™ã‹ï¼Ÿ +message.transfer.waiting.on.user = {0}ãŒãƒ•ァイル転é€ã‚’許å¯ã™ã‚‹ã®ã‚’å¾…ã£ã¦ã„ã¾ã™ã€‚ +message.negotiation.file.transfer = {0}ã¸ã®ãƒ•ァイル転é€ã‚’交渉中。ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„... +message.unable.to.send.file = {0}ã¸ãƒ•ァイルé€ä¿¡ãŒå‡ºæ¥ã¾ã›ã‚“ã§ã—ãŸã€‚ +message.sending.file.to = {0}ã¸ãƒ•ァイルをé€ä¿¡ä¸­ã€‚ +message.you.have.sent = {0}ã«ãƒ•ァイルをé€ä¿¡ã—ã¾ã—ãŸã€‚ +message.file.transfer.rejected = {0}ã¯ãƒ•ァイル転é€ã‚’æ‹’å¦ã—ã¦ã„ã¾ã™ã€‚ +message.disable.transport = {0}ã®ãƒ­ã‚°ã‚¤ãƒ³æƒ…報を削除ã—ã¦ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ +message.register.transports = 利用å¯èƒ½ãªé€šä¿¡ã‚’設定ã—ã¦ãã ã•ã„。 +message.username.password.error = ユーザåã¨ãƒ‘スワードを設定ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚ +message.registration.transport.failed = ゲートウエイã®ç™»éŒ²ãŒå‡ºæ¥ã¾ã›ã‚“。 +message.client.information = {0}ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆæƒ…å ± +message.calling = {0}を呼ã³å‡ºã—中 +message.number.to.call = ダイアルã™ã‚‹ç•ªå·ã‚’入力ã—ã¦ãã ã•ã„。 +message.no.caller.id = 利用å¯èƒ½ãªç™ºä¿¡è€…IDãŒã‚りã¾ã›ã‚“。 +message.no.history.found = ã“ã®ãƒ¦ãƒ¼ã‚¶ã®ä¼šè©±ãƒ­ã‚°ãŒã‚りã¾ã›ã‚“。 +message.prompt.plugin.uninstall = {0}をアンインストールã—ã¾ã™ã€ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ +message.restart.spark.changes = Sparkã‚’å†èµ·å‹•後ã«ãƒ—ãƒ©ã‚°ã‚¤ãƒ³ãŒæœ‰åйã«ãªã‚Šã¾ã™ã€‚ +message.loading.please.wait = ロード中。ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„... +message.plugins.not.available = プラグインリãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã§ãã¾ã›ã‚“。 +message.downloading = {0}をダウンロード中 +message.downloading.spark.plug = Spark-Plugをダウンロード中 +message.unable.to.save.password = パスワードを変更ã§ãã¾ã›ã‚“。サーãƒãƒ¼ã‚’ã‚‚ã†ä¸€åº¦ç¢ºèªã—ã¦ãã ã•ã„。 +message.delete.all.history = ã™ã¹ã¦ã®ä¼šè©±ãƒ­ã‚°ã‚’削除ã—ã¾ã™ã‹ï¼Ÿ +message.no.avatar.found = ã‚¢ãƒã‚¿ãƒ¼ç„¡ã—ã«è¨­å®šã•れã¾ã—ãŸã€‚ +message.image.too.large = ã“ã®ç”»åƒã¯ä½¿ç”¨ã™ã‚‹ã®ã«å¤§ãã™ãŽã¾ã™ã€‚16KBよりå°ã•ã„サイズã§è¨­å®šã—ã¦ãã ã•ã„。 +message.save.profile = ã‚ãªãŸã®ãƒ—ロファイルを変更ä¿å­˜ã™ã‚‹ã«ã¯ã€ã€Œä¿å­˜ã€ã‚’クリックã—ã¦ãã ã•ã„。 +message.unable.to.load.profile = {0}ã®ãƒ—ロファイルを登録ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ +message.enter.jabber.id = Jabber ID を入力ã—ã¦ãã ã•ã„。 +message.invalid.jabber.id = æ­£ã—ã„ Jabber ID ã§ã¯ã‚りã¾ã›ã‚“。 +message.vcard.not.supported = サーãƒã¯ VCards å½¢å¼ã‚’サãƒãƒ¼ãƒˆã—ã¾ã›ã‚“。ã‚ãªãŸã® VCard ã‚’ä¿å­˜ã§ãã¾ã›ã‚“。 +message.search.service.not.available = æ¤œç´¢ã‚µãƒ¼ãƒ“ã‚¹ã«æŽ¥ç¶šã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ +message.no.results.found = サーãƒãƒ¼ãŒæ¤œç´¢çµæžœã‚’何も返ã—ã¾ã›ã‚“ã§ã—ãŸã€‚ +message.name.of.search.service.question = 検索サービスåã§ã™ã‹ï¼Ÿ +message.search.for.other.people = サーãƒä¸Šã§ã»ã‹ã®äººã‚’探ã—ã¦ãã ã•ã„。 +message.specify.valid.time.error = ãƒãƒ¼ãƒˆã¨ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã¯æ­£ã—ã設定ã—ã¦ãã ã•ã„。 +message.timeout.error = タイムアウト時間ã¯5ç§’ã‹ãれ以上ã®å€¤ã§è¨­å®šã—ã¦ãã ã•ã„。 +message.version = ãƒãƒ¼ã‚¸ãƒ§ãƒ³: {0} +message.file.size = ファイルサイズ: {0} +message.restart.spark = 最新版ã®ã‚½ãƒ•トウエアをインストールã™ã‚‹ãŸã‚ã«\nå†èµ·å‹•ãŒå¿…è¦ã«ãªã‚Šã¾ã™ã€‚å†èµ·å‹•ã—ã¾ã™ã‹ï¼Ÿ +message.updating.cancelled = アップデートã¯ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•れã¾ã—ãŸã€‚ +message.transfer.rate = 通信レート +message.total.downloaded = ã™ã¹ã¦ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã•れã¾ã—ãŸã€‚ +message.new.spark.available = {0}ã¯æœ‰åйã§ã™ã€‚インストールã—ã¾ã™ã‹ï¼Ÿ +message.restart.spark.to.install = 最新版ã®ã‚½ãƒ•トウエアをインストールã™ã‚‹ãŸã‚ã«å†èµ·å‹•ãŒå¿…è¦ã§ã™ã€‚å†èµ·å‹•ã—ã¾ã™ã‹ï¼Ÿ +message.add.to.roster = åç°¿ã«è¿½åŠ  +message.enter.room.password = ルームã®ãƒ‘スワードを入力ã—ã¦ãã ã•ã„。 +message.add.contact.to.list = ã‚ãªãŸã®é€£çµ¡å…ˆã«ãƒ¦ãƒ¼ã‚¶ã‚’追加ã—ã¾ã—ãŸã€‚ +message.authenticating = ログイン中 +message.invalid.status = ステータスメッセージã®å…¥åŠ›ãŒä¸æ­£ã§ã™ã€‚ +message.cannot.add.contact.to.shared.group = 共有グループã¸ã®é€£çµ¡å…ˆã®è¿½åŠ ãŒå‡ºæ¥ã¾ã›ã‚“ã§ã—ãŸã€‚ +message.specify.contact.jid = コンタクトã™ã‚‹ JID を指定ã—ã¦ãã ã•ã„。 (例 ddman@jabber.org) +message.invalid.jid.error = JID ãŒä¸æ­£ã§ã™ã€‚ +message.specify.group = æ–°è¦ãƒ¦ãƒ¼ã‚¶ã‚’追加ã™ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—を指定ã—ã¦ãã ã•ã„。 +message.room.creation.error = ルームã®ä½œæˆãŒå‡ºæ¥ã¾ã›ã‚“ã§ã—ãŸã€‚ +message.unable.to.retrieve.last.activity = {0}ã®æœ€å¾Œã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティを決定ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ + + +title.passwords.no.match = ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ç¢ºèª +title.create.problem = アカウント作æˆã«é–¢ã™ã‚‹å•題 +title.account.created = アカウントãŒä½œæˆã•れã¾ã—ãŸã€‚ +title.create.new.account = æ–°è¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆä½œæˆ +title.account.create.registration = アカウント登録 +title.register.account = æ–°ã—ã„アカウントを作æˆã™ã‚‹ +title.notification = 通知 +title.advanced.connection.preferences = 上級者用接続設定 +title.preferences = 設定 +title.error = エラー +title.status.message = ステータスメッセージ +title.spark.preferences = Spark設定 +title.alert = アラート +title.tray.information = トレイ情報 +title.select.file.to.send = é€ä¿¡ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž +title.choose.directory = ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’é¸æŠž +title.confirmation = ç¢ºèª +title.last.activity = 最後ã®è¡Œå‹• +title.add.new.group = æ–°è¦ã‚°ãƒ«ãƒ¼ãƒ—を追加 +title.add.to.roster = åç°¿ã«è¿½åŠ  +title.find.contacts = 連絡先を探㙠+title.rename.roster.group = åç°¿ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’å称変更 +title.roster = åç°¿ +title.create.room = ä½œæˆ +title.conference.rooms = 会議室 +title.invite.to.conference = 会議ã«èª˜ã† +title.room.information = ルーム情報 +title.change.nickname = ニックãƒãƒ¼ãƒ å¤‰æ›´ +title.group.chat = グループãƒãƒ£ãƒƒãƒˆ +title.create.or.bookmark.room = ブックマークルームã«å‚加ã™ã‚‹ã€‚ +title.browse.room.service = 会議室å‚ç…§ - {0} +title.name = åå‰ +title.address = アドレス +title.occupants = ä½äºº +title.browse.conference.services = 会議サービスをå‚ç…§ã™ã‚‹ã€‚ +title.find.conference.service = 会議サービスを検索ã™ã‚‹ã€‚ +title.configure.chat.room = ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’設定ã™ã‚‹ã€‚ +title.conference.invitation = 会議ã«èª˜ã† +title.join.conference.room = 会議室ã«å‚加ã™ã‚‹ã€‚ +title.view.room.information = ルーム情報をå‚ç…§ã™ã‚‹ã€‚ +title.configure.room = ルームを設定ã™ã‚‹ã€‚ +title.change.subject = 話題を変ãˆã‚‹ +title.enter.reason = ç†ç”±ã‚’入力 +title.room.destroyed = ルームã¯ç ´æ£„ã•れã¾ã—ãŸã€‚ +title.edit.custom.message = カスタムメッセージを編集ã™ã‚‹ã€‚ +title.set.status.message = 状態メッセージを設定ã™ã‚‹ã€‚ +title.broadcast.message = メッセージをブロードキャストã™ã‚‹ã€‚ +title.start.chat = ãƒãƒ£ãƒƒãƒˆé–‹å§‹ +title.view.bookmarks = ブックマークをå‚ç…§ +title.downloads = ダウンロード +title.file.exists = ファイルãŒå­˜åœ¨ +title.disable.transport = ログイン情報を破棄 +title.available.transports = 利用å¯èƒ½ãªé€šä¿¡ +title.transports = 通信 +title.registration.error = 登録エラー +title.jabber.browser = ブラウザ +title.version.and.time = ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¨æ™‚é–“ +title.waiting.to.call = ç€ä¿¡å¾…ã¡ +title.incoming.call = ç€ä¿¡ +title.on.the.phone = 電話ã«é–¢ã—㦠+title.dial.phone = ダイアルフォン +title.history.for = {0}ã®ä¼šè©±å±¥æ­´ +title.reminder = リマインダ +title.plugins = プラグイン +title.general.chat.settings = ãƒãƒ£ãƒƒãƒˆè¨­å®š +title.chat = ãƒãƒ£ãƒƒãƒˆ +title.notifications = 通知 +title.sound.preferences = サウンド設定 +title.sounds = サウンド +title.choose.incoming.sound = 入室時ã®ã‚µã‚¦ãƒ³ãƒ‰ã‚’é¸æŠž +title.choose.outgoing.sound = 退出時ã®ã‚µã‚¦ãƒ³ãƒ‰ã‚’é¸æŠž +title.choose.offline.sound = オフライン時ã®ã‚µã‚¦ãƒ³ãƒ‰ã‚’é¸æŠž +title.edit.profile = プロファイル情報を編集ã™ã‚‹ã€‚ +title.profile.information = プロファイル情報 +title.profile.not.found = プロファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 +title.view.profile.for = {0}ã®ãƒ—ロファイルをå‚照中 +title.lookup.profile = ルックアッププロファイル +title.add.search.service = 検索サービス追加 +title.person.search = 人物検索 +title.login.settings = ログイン設定 +title.login = ログイン +title.downloading.im.client = IM クライアントをダウンロード +title.upgrading.client = クライアントをアップグレード中 +title.cancelled = キャンセルã•れã¾ã—ãŸã€‚ +title.new.version.available = æ–°è¦ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒåˆ©ç”¨å¯èƒ½ã§ã™ã€‚ +title.new.client.available = æ–°è¦ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒåˆ©ç”¨å¯èƒ½ã§ã™ã€‚ +title.password = パスワード +title.download.complete = ダウンロード完了 +title.new.roster.group = æ–°è¦å簿グループ +title.add.contact.group = 連絡先グループを追加 +title.add.contact = 連絡先を追加 +title.file.transfer.preferences = ファイル転é€è¨­å®š +title.file.transfer = ãƒ•ã‚¡ã‚¤ãƒ«è»¢é€ + +menuitem.connect = ファイル +menuitem.contacts = 連絡先 +menuitem.actions = アクション +menuitem.exit = 終了 +menuitem.plugins = プラグイン +menuitem.logout.no.status = ログアウト +menuitem.logout.with.status = ã‚ã‘ã‚ã£ã¦ãƒ­ã‚°ã‚¢ã‚¦ãƒˆ +menuitem.show.traffic = トラフィックウィンドウã®è¡¨ç¤º +menuitem.check.for.updates = アップデートã®ãƒã‚§ãƒƒã‚¯ +menuitem.help = ヘルプ +menuitem.preferences = 設定 +menuitem.about = ã“ã®ãƒ—ログラムã«ã¤ã„㦠+menuitem.online.help = オンラインヘルプ +menuitem.open = é–‹ã +menuitem.hide = éš ã™ +menuitem.status = ステータス +menuitem.view.downloads = ダウンロードを見る +menuitem.save = ä¿å­˜ +menuitem.add = 追加 +menuitem.add.contact = 連絡先を追加 +menuitem.add.contact.group = 連絡先グループを追加 +menuitem.remove.from.group = グループã‹ã‚‰å‰Šé™¤ +menuitem.start.a.chat = ãƒãƒ£ãƒƒãƒˆé–‹å§‹ +menuitem.rename = å称変更 +menuitem.delete = 削除 +menuitem.edit = 編集 +menuitem.remove.from.roster = åç°¿ã‹ã‚‰å‰Šé™¤ +menuitem.view.profile = プロファイルå‚ç…§ +menuitem.subscribe.to = ç½²åã™ã‚‹ +menuitem.send.a.message = é¸æŠžã—ãŸãƒ¦ãƒ¼ã‚¶ã«è¦‹å‡ºã—ã‚’é€ä¿¡ã™ã‚‹... +menuitem.show.empty.groups = 空ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’å‚ç…§ +menuitem.send.a.file = ファイルをé€ã‚‹ +menuitem.view.last.activity = 最後ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティをå‚ç…§ +menuitem.unban = è§£ç¦ã™ã‚‹ +menuitem.ban = ç¦æ­¢ã™ã‚‹ +menuitem.browse.service = サービスを見る +menuitem.remove.service = サービスを削除 +menuitem.join.room = ルームã«å‚加 +menuitem.remove.bookmark = ブックマークを削除 +menuitem.join.on.startup = スタートアップ時ã«å‚加 +menuitem.view.room.info = ãƒ«ãƒ¼ãƒ ã®æƒ…報をå‚ç…§ +menuitem.remove = 削除 +menuitem.change.nickname = ニックãƒãƒ¼ãƒ ã‚’変更 +menuitem.block.user = ユーザをブロック +menuitem.unblock.user = ユーザブロックを解除 +menuitem.kick.user = ユーザを追ã„出㙠+menuitem.voice = 発言 +menuitem.revoke.voice = 発言を廃止 +menuitem.grant.voice = 発言を承諾 +menuitem.ban.user = ãƒ¦ãƒ¼ã‚¶ã‚’ç¦æ­¢ã™ã‚‹ã€‚ +menuitem.grant.moderator = å¸ä¼šè€…を承諾 +menuitem.revoke.moderator = å¸ä¼šè€…を廃止 +menuitem.invite.users = ユーザを招待 +menuitem.invite.group.to.conference = ã‚°ãƒ«ãƒ¼ãƒ—ã‚’ä¼šè­°ã«æ‹›å¾…ã™ã‚‹ +menuitem.start.a.conference = 会議開始... +menuitem.change.subject = 話題を変ãˆã‚‹ +menuitem.destroy.room = ルームを廃止 +menuitem.set.status.message = ステータスメッセージをセットã™ã‚‹... +menuitem.edit.status.message = ステータスメッセージを編集ã™ã‚‹... +menuitem.broadcast.to.group = メッセージをグループã«ãƒ–ロードキャストã™ã‚‹ +menuitem.alert.when.online = ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒæœ‰åйã«ãªã£ãŸã‚‰é€šçŸ¥ã™ã‚‹ +menuitem.remove.alert.when.online = 通知を削除 +menuitem.save.as = 別åã§ä¿å­˜... +menuitem.view.client.version = クライアントãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’å‚ç…§ +menuitem.view.contact.history = 連絡履歴をå‚ç…§ +menuitem.edit.my.profile = プロファイルを編集... +menuitem.lookup.profile = プロファイルをå‚ç…§... +menuitem.add.as.contact = 連絡先ã¨ã—ã¦è¿½åŠ  +menuitem.chat = ãƒãƒ£ãƒƒãƒˆ +menuitem.sign.in = サインイン +menuitem.sign.out = サインアウト +menuitem.sign.in.at.login = ログイン時ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³ +menuitem.enter.login.information = ログイン情報を入力 +menuitem.delete.login.information = ログイン情報を削除 +menuitem.show.offline.group = オフラインユーザをグループ +menuitem.move.to = 移動 +menuitem.copy.to = コピー + +tree.conference.services = 会議サービス +tree.users.in.room = ユーザãŒãƒ«ãƒ¼ãƒ ã«ã„ã¾ã™ + +tab.general = 一般 +tab.proxy = プロキシ +tab.contacts = 連絡先 +tab.installed.plugins = インストール済ã¿ãƒ—ラグイン +tab.available.plugins = 利用å¯èƒ½ãªãƒ—ラグイン +tab.personal = 個人 +tab.business = 仕事 +tab.home = å®¶ +tab.avatar = ã‚¢ãƒã‚¿ãƒ¼ +tab.conferences = 会議 + +group.connection = 接続 +group.conferences.found = 会議サービスãŒè¦‹ã¤ã‹ã‚Šã¾ã—㟠+group.comma.delimited = コンマデリミタ +group.general.information = 一般情報 +group.chat.window.information = ãƒãƒ£ãƒƒãƒˆã‚¦ã‚£ãƒ³ãƒ‰ã‚¦æƒ…å ± +group.notification.options = 通知オプション +group.search.form = 検索開始 +group.search.results = æ¤œç´¢çµæžœ +group.login.information = ログイン情報 + +tooltip.place.a.call = ã“ã®äººã«é›»è©±ã—ã¦ãã ã•ã„。 +tooltip.view.history = 会話履歴å‚ç…§ +tooltip.view.changelog = 変更ログå‚ç…§ +tooltip.view.readme = ReadMeå‚ç…§ +tooltip.notifications = ãƒãƒ£ãƒƒãƒˆå‘¼ã³ã‹ã‘時ã®é€šçŸ¥è¨­å®š +tooltip.place.voice.call = 発言ã—ã¦ãã ã•ã„。 diff --git a/core/src/main/resources/i18n/spark_i18n_ko.properties b/core/src/main/resources/i18n/spark_i18n_ko.properties new file mode 100644 index 000000000..1dddef606 --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_ko.properties @@ -0,0 +1,748 @@ +accept = ìˆ˜ë½ +is.active = 활성화 +add = 추가 +answer = 대답 +apply = ì ìš© +available = 사용가능 +broadcast = 브로드케스트 +cancel = 취소 +close = 닫기 +create = ìƒì„± +date = ë‚ ì§œ +description = 설명 +from = 부터 +invite = 초대 +join = 참여 +no = ê±°ì ˆ +not.registered = 등ë¡ë˜ì§€ ì•ŠìŒ +occupants = ì¸ì›ìˆ˜ +offline = 오프ë¼ì¸ +online = 온ë¼ì¸ +ok = í™•ì¸ +open = 열기 +open.folder = í´ë” 열기 +participants = ì°¸ì—¬ìž +reject = ê±°ì ˆ +retry = ìž¬ì‹œë„ +room.name = 대화방 ì´ë¦„ +save = 저장 +subject = 주제 +unfiled = .기타 +use.default = 기본값 +user.has.signed.in = has signed in. +user.has.signed.off = has signed off. +while.offline = 오프ë¼ì¸ ë™ì•ˆ +yes = 예 + +action.clear = 지우기 +action.copy = 복사 +action.cut = ìžë¥´ê¸° +action.paste = 붙여넣기 +action.print = ì¸ì‡„ +action.save = 저장 +action.select.all = ëª¨ë‘ ì„ íƒ + +button.accept = 수ë½(&A) +button.reject = ê±°ì ˆ(&R) +button.add = 추가(&A) +button.add.a.contact = 친구 추가(&A) +button.add.bookmark = ë¶ë§ˆí¬ 추가 +button.add.service = 서비스 추가(&A) +button.add.user = 친구 추가(&A) +button.add2 = 추가(&D) +button.advanced = 기타 설정 +button.approve = ìŠ¹ì¸ +button.bookmark.room = 책갈피 모ìŒ(&B) +button.browse = 찾아보기(&b)... +button.browse2 = 찾아보기... +button.browse3 = 찾아보기... +button.cancel = 취소 +button.clear = 지우기 +button.close = 닫기 +button.copy.to.clipboard = í´ë¦½ë³´ë“œ 복사 +button.create.account = 계정 ìƒì„± +button.create.room = 대화방 ìƒì„±/참여 +button.decline = &Decline +button.deny = ê±°ì ˆ +button.dial.number = 전화번호 +button.find = 검색 +button.join = 참여 +button.join.room = ì„ íƒí•œ 대화방 참여 +button.new = 새로하기 +button.profile = 프로필 +button.quit = 나가기 +button.reconnect = 다시 ì—°ê²° +button.reconnect2 = 다시 ì—°ê²° +button.refresh = 새로하기 +button.register = ë“±ë¡ +button.remove.bookmark = 책갈피 제거 +button.roster = 친구 ì„ íƒ +button.save = 저장 +button.save.for.future.use = 다ìŒì— 사용하기 위해 저장 +button.search = 검색 +button.send = 보내기 +button.send.email = ì´ë©”ì¼ +button.start.chat = 대화 +button.tasks.active = í• ì¼ +button.tasks.all = ëª¨ë‘ +button.unset.file.explorer = íŒŒì¼ ë¸Œë¼ìš°ì € 설정하지 ì•ŠìŒ +button.update = ì—…ë°ì´íЏ +button.view.notes = 메모 보기 +button.view.profile = 프로필 ëª¨ë‘ ë³´ê¸° +button.view.tasklist = 작업 리스트 보기 +button.re.detect = 다시 검색 + +checkbox.allow.buzz = ë‚´ ì±„íŒ…ì°½ì„ ì£¼ëª©ì‹œí‚¬ 목ì ìœ¼ë¡œ í”드는 ê²ƒì„ í—ˆë½(&z) +checkbox.auto.discover.port = ìžë™ìœ¼ë¡œ 호스트와 í¬íŠ¸ë²ˆí˜¸ 알아내기(&A) +checkbox.auto.login = ìžë™ 로그ì¸(&A) +checkbox.disable.chat.history = 채팅 기ë¡í•˜ì§€ 않ìŒ(&D) +checkbox.disable.prev.chat.history = ì´ì „ 채팅 ê¸°ë¡ ë³´ëŠ” 것 허용하지 않ìŒ(&D) +checkbox.enable.emoticons = ì´ëª¨í‹°ì½˜ 사용하기(&o) +checkbox.idle.enabled = ìžë¦¬ë¹„움 기능 +checkbox.launch.on.startup = ìš´ì˜ì²´ì œ 시작시 실행 +checkbox.notify.user.comes.online = 친구가 로그ì¸í• ë•Œ 알려주기 +checkbox.notify.user.goes.offline = 친구가 오프ë¼ì¸í• ë•Œ 알려주기 +checkbox.notify.typing.systemtray = 시스템 트레ì´ì— 타ì´í•‘ 알림 ë³´ì´ê¸° +checkbox.notify.systemtray = 시스템 트레ì´ì— 새메시지 ë³´ì´ê¸° +checkbox.permanent = ì˜êµ¬ì ì¸ 방으로 ìƒì„±(&p) +checkbox.play.sound.on.invitation = 초대ë ë•Œ 소리 ìž¬ìƒ +checkbox.play.sound.on.new.message = 새로운 메시지가 ë„착할때 소리 ìž¬ìƒ +checkbox.play.sound.on.outgoing.message = 메시지 전송ë ë•Œ 소리 ìž¬ìƒ +checkbox.play.sound.when.offline = 친구가 오프ë¼ì¸ì¼ë•Œ 소리 ìž¬ìƒ +checkbox.private.room = 비공개 방으로 ìƒì„±(&I) +checkbox.save.password = 비밀번호 저장 +checkbox.show.avatars.in.contactlist = 친구목ë¡ì— 아바타 ë³´ì´ê¸° +checkbox.show.notifications.in.conference = &회ì˜ì‹¤ì— 알림 ë³´ì´ê¸° +checkbox.show.time.in.chat.window = ëŒ€í™”ì°½ì— ì‹œê°„ì •ë³´ ë³´ì´ê¸° +checkbox.show.toaster = íŒì—…으로 ë³´ì´ê¸° +checkbox.split.chat.window = Dock &Windows (프로그램 재시작시 ì ìš©) +checkbox.start.in.tray = 시스템 트레ì´ì— 시작 +checkbox.tabs.on.top = ëŒ€í™”íƒ­ì´ ìœ„ì— ë³´ìž„ (프로그램 재시작시 ì ìš©) +checkbox.tabs.scroll = 채팅 íƒ­ì— ìŠ¤í¬ë¡¤ 사용 (프로그램 재시작시 ì ìš©) +checkbox.use.compression = ì••ì¶• 사용 +checkbox.use.debugger.on.startup = Start &Debugger on startup +checkbox.use.proxy.server = Proxy 서버 사용 +checkbox.use.system.look.and.feel = 시스템 테마 사용 (프로그램 재시작시 ì ìš©) +checkbox.window.to.front = 윈ë„우를 앞으로 보내기 +checkbox.broadcast.hide.offline.user = 오프ë¼ì¸ 친구 숨기기 +checkbox.use.krbconf = Use krb5.conf or krb5.ini +checkbox.use.krb.dns = DNS 사용 +checkbox.use.specify.below = 아래 ìž…ë ¥ +checkbox.use.pki.authentication = PKI ì¸ì¦ 사용 +checkbox.close.unread.message = ì½ì§€ ì•Šì€ ë©”ì‹œì§€ê°€ 있으면 ì°½ì„ ë‹«ì„ ë•Œ í™•ì¸ + +delete.log.permanently = ì˜êµ¬ížˆ 로그 ì‚­ì œ +delete.permanently = ì˜êµ¬ížˆ 삭제하시겠습니까? + +gateway.username.password.error = ì•„ì´ë””나 비밀번호가 ìž…ë ¥ë˜ì–´ì•¼ 합니다. + +group.chat.window.information = 대화창 ì •ë³´ +group.comma.delimited = 콤마(,)로 êµ¬ë¶„ë¨ +group.conferences.found = íšŒì˜ ì„œë¹„ìŠ¤ë¥¼ ì°¾ìŒ +group.connection = ì—°ê²° +group.empty = ì´ ê·¸ë£¹ì— ì˜¨ë¼ì¸ 친구가 없습니다. +group.general.information = ì¼ë°˜ ì •ë³´ +group.login.information = ë¡œê·¸ì¸ ì •ë³´ +group.notification.options = 알림 옵션 +group.offline = 오프ë¼ì¸ 그룹 +group.search.form = ê²€ìƒ‰í¼ +group.search.results = 검색 ê²°ê³¼ +group.chat.name.notification = ì´ë¦„ ë³´ì´ê¸°... +group.chat.name.match = 당신 ì´ë¦„ì´ ê·¸ë£¹ëŒ€í™”ì—서 ë§í•´ì¡ŒìŠµë‹ˆë‹¤: + +label.na = n/a +label.cell = 휴대전화 +label.work = 근무처 +label.home = ì§‘ +label.accounts = 계정 ìƒì„± +label.add.conference.service = íšŒì˜ ì„œë¹„ìŠ¤ 추가하기 +label.add.jid = JID 추가 +label.add.task = 작업 추가 +label.auto.login = ìžë™ ë¡œê·¸ì¸ +label.available.users.in.roster = 가능한 친구들 +label.cancel = 취소 +label.change.password.to = 새 비밀번호 +label.chatroom.fontsize = 대화창 í°íЏ í¬ê¸°: +label.chatroom.maxcurrenthistorysize = 최대 현재 ê¸°ë¡ í¬ê¸°: +label.city = ë„시 +label.close = 닫기 +label.company = 회사 +label.confirm.password = 비밀번호 í™•ì¸ +label.conflict.error = ê³„ì •ì€ ì´ë¯¸ 서명ë˜ì—ˆê¸° ë•Œë¬¸ì— ë¡œê·¸ì¸ì´ 불가능함 +label.contact.to.find = 친구 검색 +label.contactlist.avatarsize = 리스트 아바타 í¬ê¸°: +label.contactlist.fontsize = 리스트 í°íЏ í¬ê¸°: +label.country = êµ­ê°€/지역 +label.create.account = 계정 ìƒì„±(&A) +label.department = 부서(&D) +label.dial = ì „í™”(&D) +label.downloads = 다운로드 +label.due = ë§Œê¸°ì¼ +label.email.address = ì´ë©”ì¼ ì£¼ì†Œ(&E) +label.emoticons = ì´ëª¨í‹°ì½˜(&E) +label.enter.address = 주소 ìž…ë ¥ +label.enter.group.name = 새 그룹 ì´ë¦„ ìž…ë ¥ +label.fax = 팩스 +label.find = 검색 +label.first.name = ì´ë¦„ +label.group = 그룹 +label.host = 호스트 +label.invited.users = 친구 초대 +label.jabber.address = &Jabber 주소 +label.jabber.id = &Jabber ID +label.jid = &JID +label.job.title = ì§í•¨ +label.last.name = 성 +label.local.time = 지역 시간 +label.message = 메시지 +label.message.style = 메시지 í˜•ì‹ +label.middle.name = ì´ë¦„ +label.minutes.before.stale.chat = ë‹¤ìŒ ì‹œê°„ì´ ì§€ë‚˜ë©´ ìžë¦¬ë¹„움으로 표시(ë¶„) +label.mobile = íœ´ëŒ€í° +label.name = ì´ë¦„(&N) +label.network = 네트워í¬(&K) +label.new.nickname = 새 별명 +label.nickname = 별명(&c) +label.number = 번호(&N) +label.ok = í™•ì¸ +label.old.ssl = 구 SSL í¬íЏ ë°©ì‹ ì‚¬ìš©(&U) +label.os = ìš´ì˜ì²´ì œ(&O) +label.pager = 호출(기) 번호(&P) +label.password = 비밀번호(&P) +label.phone = ì „í™”(&P) +label.port = í¬íЏ(&P) +label.postal.code = 우편번호(&P) +label.presence = ìžˆìŒ +label.priority = 우선순위 +label.protocol = 프로토콜 +label.received = 수신 +label.rename.to = ì´ë¦„ 변경하기 +label.resource = ìžì›(&R) +label.response.timeout = ì‘답 시간(sec) 초과(&R) +label.room = 대화방 +label.room.name = 대화방 ì´ë¦„ +label.room.topic= 토론주제(&T) +label.search.service = 검색 서비스(&S) +label.server = ë„ë©”ì¸ +label.server.address = 서버 주소(&S) +label.show = 보기: +label.software = 소프트웨어 +label.state.and.province = 시/ë„(&t) +label.street.address = ìƒì„¸ì£¼ì†Œ(&S) +label.time = 시간: {0} +label.time.till.idle = ìžë¦¬ë¹„움 시간(ë¶„)(&T): +label.timeformat = 사용 {0} +label.transfer.download.directory = 다운로드 디렉토리(&D): +label.transfer.timeout = 전송 시간 제한(ë¶„)(&T): +label.unable.to.add.contact = 친구를 추가할수 없습니다. +label.use.default = 기본값 사용 +label.user.on.public.network = 사용ìžê°€ 공용 ë„¤íŠ¸ì›Œí¬ ìƒì— ìžˆìŒ +label.username = 사용ìžëª…(&U) +label.version = 버전(&V) +label.web.page = 홈페ì´ì§€(&W) +label.xmpp.port = &XMPP í¬íЏ +label.krb.realm = 관심ì˜ì—­ +label.krb.kdc = KDC +label.which.pki.method = ì–´ë–¤ PKI 방법입니까? +label.choose.file = 파ì¼ì„ 고르십시요 +label.trust.store.password = 암호화ë˜ì–´ 패스워드가 저장ë©ë‹ˆë‹¤. +label.enter.password = 비밀번호를 입력하십시요. +label.move.focus.forwards = í¬ì»¤ìŠ¤ë¥¼ 앞으로 ì´ë™ +label.move.focus.backwards = í¬ì»¤ìŠ¤ë¥¼ 뒤로 ì´ë™ +label.keystore.location = Keystore 위치 +label.truststore.location = TrustStore 위치 +label.pkcs.library.file = PKCS#11 Library File +label.x509.certificate = X.509 Certificate +label.apple.keychain = Apple KeyChain +label.add.to.roster = 친구 추가 +label.audio.device = 오디오 디바ì´ìФ +label.video.device = 비디오 디바ì´ìФ + +menuitem.about = ì •ë³´ +menuitem.actions = ë™ìž‘ +menuitem.bookmarks = ë¶ë§ˆí¬ +menuitem.add = 추가 +menuitem.add.as.contact = 친구 추가 +menuitem.add.contact = 친구 추가 +menuitem.add.contact.group = 그룹 추가 +menuitem.add.groupchat.myname = ìƒëŒ€ë°©ì— ë‚´ ì´ë¦„ 강조하기 +menuitem.add.groupchat.mytext = ë‚´ê¸€ì— ê°•ì¡°í•˜ê¸° +menuitem.add.groupchat.popname= ë‚´ ì´ë¦„ì„ ì´ì•¼ê¸°í• ë•Œ íŒì—…ì°½ ë³´ì´ê¸° +menuitem.add.groupchat.showjoinleavemessage = 입장할때와 나갈때 메시지 ë³´ì´ê¸° +menuitem.always.on.top = í•­ìƒ ìœ„ë¡œí•˜ê¸° +menuitem.alert.when.online = 친구가 ìžë¦¬ì— 있ìŒì¼ë•Œ 알리기 +menuitem.ban = 금지 +menuitem.ban.user = ì‚¬ìš©ìž ê¸ˆì§€ +menuitem.block.user = ì‚¬ìš©ìž ì°¨ë‹¨ +menuitem.broadcast.to.group = ê·¸ë£¹ì— ì „ì²´ì•Œë¦¼ 메시지 +menuitem.browse.service = íƒìƒ‰ 서비스 +menuitem.change.nickname = 별명 변경 +menuitem.change.subject = 주제 변경 +menuitem.chat = 대화 +menuitem.check.for.updates = ì—…ë°ì´íЏ ì²´í¬ +menuitem.connect = íŒŒì¼ +menuitem.contacts = 친구 +menuitem.copy.to = 복사 +menuitem.delete = ì‚­ì œ +menuitem.delete.login.information = ë¡œê·¸ì¸ ì •ë³´ ì‚­ì œ +menuitem.destroy.room = ë°© 없애기 +menuitem.dial = 전화걸기 +menuitem.edit = 편집 +menuitem.edit.my.profile = ë‚´ 프로필 편집(&E)... +menuitem.edit.status.message = ìƒíƒœ 메시지 편집... +menuitem.enter.login.information = ë¡œê·¸ì¸ ì •ë³´ ìž…ë ¥ +menuitem.exit = 종료 +menuitem.grant.moderator = ìš´ì˜ìž ìˆ˜ë½ +menuitem.grant.voice = ìŒì„±ì±„팅 ìˆ˜ë½ +menuitem.help = ë„ì›€ë§ +menuitem.hide = 숨기기 +menuitem.invite.group.to.conference = 회ì˜ì— 그룹 초대 +menuitem.invite.users = 친구 초대하기 +menuitem.join.on.startup = 시작시 참여하기 +# TODO: Sort out with duplicates +menuitem.join.room = 대화방 참여 +menuitem.kick.user = ì‚¬ìš©ìž ë‚´ë³´ë‚´ê¸° +menuitem.languages = 언어 +menuitem.logout.no.status = 로그아웃 +menuitem.logout.with.status = ... ì´ìœ ë¡œ 로그아웃 +menuitem.lookup.profile = 프로필 검색... +menuitem.move.to = ì´ë™ +menuitem.online.help = Spark í¬ëŸ¼ +menuitem.open = 열기 +menuitem.open.with = 열기... +menuitem.plugins = í”ŒëŸ¬ê·¸ì¸ +menuitem.preferences = 환경 설정 +menuitem.remove = 제거 +menuitem.remove.alert.when.online = 알림 제거 +menuitem.remove.bookmark = ë¶ë§ˆí¬ 제거 +menuitem.remove.from.group = 그룹ì—서 제거 +menuitem.remove.from.roster = 친구 리스트ì—서 제거 +menuitem.remove.service = 서비스 제거 +menuitem.rename = ì´ë¦„ 변경 +menuitem.revoke.moderator = ìš´ì˜ìž 취소 +menuitem.revoke.voice = ìŒì„± 취소 +menuitem.save = 저장 +menuitem.save.as = 다른 ì´ë¦„으로 저장하기... +menuitem.send.a.file = íŒŒì¼ ë³´ë‚´ê¸° +menuitem.send.a.message = ì„ íƒëœ 친구들ì—게 브로드케스트 보내기... +menuitem.set.status.message = ìƒíƒœ 메시지 설정... +menuitem.show.empty.groups = 비어있는 그룹 ë³´ì´ê¸° +menuitem.show.offline.group = 오프ë¼ì¸ 친구들 그룹 +menuitem.show.traffic = 트래픽 윈ë„ìš° 보기 +menuitem.sign.in = ë¡œê·¸ì¸ +menuitem.sign.in.at.login = 로그ì¸ì‹œ ë¡œê·¸ì¸ +menuitem.sign.out = 로그 아웃 +menuitem.start.a.chat = 대화 시작 +menuitem.start.a.conference = íšŒì˜ ì‹œìž‘... +menuitem.status = ìƒíƒœ +menuitem.subscribe.to = 기부 +menuitem.unban = ì ‘ê·¼ 허용 +menuitem.unblock.user = ì‚¬ìš©ìž ì°¨ë‹¨ +menuitem.user.guide = ì‚¬ìš©ìž ë„ì›€ë§ +menuitem.view.client.version = í´ë¼ì´ì–¸íЏ 버전 보기 +menuitem.view.contact.history = ëŒ€í™”ê¸°ë¡ ë³´ê¸° +menuitem.view.downloads = 다운로드 í´ë” +menuitem.view.last.activity = 마지막 í™œë™ ë³´ê¸° +menuitem.view.logs = 로그 보기 +menuitem.view.profile = 프로필 보기 +menuitem.view.room.info = 대화방 ì •ë³´ 보기 +menuitem.voice = ìŒì„±ëŒ€í™” +menuitem.show.offline.users = 오프ë¼ì¸ 친구 보기 +menuitem.show.contact.statusmessage = ìƒíƒœ 메시지 보기 +menuitem.join.room = ì„ íƒëœ 대화방 참여하기 +menuitem.bookmark.room = ë¶ë§ˆí¬ë°© +menuitem.refresh = 새로하기 +menuitem.create.room = 대화방 ìƒì„±/참여 +menuitem.expand.all.groups = 모든 그룹 íŽ¼ì³ ë³´ì´ê¸° +menuitem.collapse.all.groups = 모든 그룹 닫기 +menuitem.invite.again = 다시 초대 +menuitem.chatframe.option = 옵션 + +message.invite.to.groupchat = {0} ê°€ ë‹¹ì‹ ì„ ê·¸ë£¹ëŒ€í™”ì— ì´ˆëŒ€í•˜ì˜€ìŠµë‹ˆë‹¤. +message = 메시지 +message.account.create = 새로운 채팅 ê³„ì •ì„ ìƒì„±í•©ë‹ˆë‹¤. +message.account.created = 새로운 ê³„ì •ì´ ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤. +message.account.error = 계정 추가하기 위해 서버를 입력하세요. +message.add.a.contact = 친구 추가 +message.add.conference.service = íšŒì˜ ì„œë¹„ìŠ¤ 추가. +message.add.contact.to.list = 친구 ë¦¬ìŠ¤íŠ¸ì— ì¶”ê°€í•˜ê¸° +message.add.favorite.room = ì¦ê²¨ì°¾ê¸° ë¦¬ìŠ¤íŠ¸ì— ì¶”ê°€í•˜ê±°ë‚˜ ì§ì ‘ 참여 +message.add.this.user.to.your.roster = 친구 목ë¡ì— 추가 +message.add.to.roster = 친구 ë¦¬ìŠ¤íŠ¸ì— ì¶”ê°€ +message.add.user = 친구를 추가하시겠습니까? +message.alert.notify = 알림 메시지 +message.already.exists = ê³„ì •ì´ ì´ë¯¸ 존재합니다. 다른 ID로 입력하세요 +message.approve.subscription = ìƒëŒ€ë°© {0}ì˜ ì£¼ì†Œë¡ì— 추가하는 ê²ƒì„ í—ˆë½í•˜ì‹­ë‹ˆê¹Œ? +message.authenticating = 로그ì¸ì¤‘입니다. +message.away.idle = 장시간 ìžë¦¬ 비움 +message.bookmark.temporary.room.error = ìž„ì‹œë°©ì„ ë¶ë§ˆí¬í• ìˆ˜ 없습니다. +message.broadcast.from = {0}로부터 온 전체알림 +message.broadcast.message.sent = ì „ì²´ 알림 메시지를 ë³´ëƒˆìŒ +message.broadcast.to = {0}ì—게 보낼 전체알림 메시지를 입력하세요 +message.hasbeenbroadcast.to = ì´ ë©”ì‹œì§€ëŠ” ë‹¤ìŒ ì‚¬ìš©ìžì—게 전체알림ë˜ì—ˆìŒ:\n{0} +message.buzz.alert.notification = ìƒëŒ€ì˜ ì±„íŒ…ì°½ì„ í”듭니다. +message.buzz.sent = ìƒëŒ€ë°©ì—게 주목 메시지를 보냈습니다. +message.calling = {0}ì—게 전화중... +message.came.online = {0} ì€(는) {1} 현재 온ë¼ì¸ ìƒíƒœìž…니다 +message.cannot.add.contact.to.shared.group = 공유 ê·¸ë£¹ì— ìƒˆ 친구를 추가할수 없습니다. +message.chat.session.ended = {0}ìƒì˜ 채팅 ì„¸ì…˜ì€ ì¢…ë£Œë˜ì—ˆìŠµë‹ˆë‹¤. +message.click.to.open = ì—´ì–´ 볼려면 í´ë¦­í•˜ì„¸ìš” +message.client.information = {0}ì˜ í´ë¼ì´ì–¸íЏ ì •ë³´ +message.close.other.chats = 모든 대화창 닫기 +message.close.stale.chats = ì˜¤ëž˜ëœ ì±„íŒ… 닫기 +message.close.this.chat = 현재 채팅창 닫기 +message.close.unread.window = ì½ì§€ ì•Šì€ ë©”ì‹œì§€ê°€ 있습니다. ì°½ì„ ë‹«ìœ¼ì‹œê² ìŠµë‹ˆê¹Œ? +message.conference.info.error = íšŒì˜ ì •ë³´ë¥¼ 검색할 수없습니다. 잠시 후 다시 시ë„해주십시오. +message.conference.service.error = íšŒì˜ ì„œë¹„ìŠ¤ê°€ 존재하지 않습니다. +message.confirm.destruction.of.room = 없어진 ë°©ì˜ ëª¨ë“  사용ìžëŠ” ì´ ë°©ìœ¼ë¡œ 부터 ì‚­ì œ ë©ë‹ˆë‹¤. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ? +message.confirmation.password.error = í™•ì¸ ë¹„ë°€ë²ˆí˜¸ ìž…ë ¥ +message.connecting.please.wait = 연결중입니다. 기다리세요... +message.connection.failed = {0} ì— ì—°ê²°í• ìˆ˜ 없습니다.. +message.create.account = ê³„ì •ì„ ìƒì„±í• ìˆ˜ 없습니다. +message.create.or.join.room = íšŒì˜ ëŒ€í™”ë°©ì„ ì¶”ê°€ë‚˜ ì°¸ì„ +message.current.status = ë‚´ ìƒíƒœë‚˜ 활ë™ì„ 다른 사람ì—게 알리기 +message.default.error = ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤.. support@jivesoftware.comì— ì•Œë ¤ì£¼ì„¸ìš”. +message.delete.all.history = 지난 대화를 ëª¨ë‘ ì§€ìš¸ê¹Œìš”? +message.delete.confirmation = {0} 삭제하시겠습니까? +message.disable.transport = {0} 로부터 ë¡œê·¸ì¸ ì •ë³´ë¥¼ 제거하시겠습니까? +message.disconnected.conflict.error = ê°™ì€ ì‚¬ìš©ê°€ 다른 장소ì—서 ë¡œê·¸ì¸ í–ˆê¸° ë•Œë¬¸ì— í˜„ìž¬ ì ‘ì†ì€ ëŠì–´ì¡ŒìŠµë‹ˆë‹¤. +message.disconnected.error = ì—러로 ì¸í•˜ì—¬ ì—°ê²°ì´ ëŠê²¼ìŠµë‹ˆë‹¤. +message.disconnected.group.chat.error = ì—°ê²° 오류로 ì¸í•´ ëŠê²¼ìŠµë‹ˆë‹¤. 다시 연결하십시요. +message.disconnected.shutdown = 서버가 종료ë˜ì–´ ì—°ê²°ì´ ëŠê²¼ìŠµë‹ˆë‹¤. +message.downloading = {0} 다운로드 중 +message.downloading.spark.plug = 플러그 다운로드중 +message.end.chat = ì´ ì±„íŒ…ì„ ì¢…ë£Œí•˜ì‹œê² ìŠµë‹ˆê¹Œ? +message.end.conversation = 지금 ì„¸ì…˜ì„ ì¢…ë£Œí•˜ê¸¸ ì›í•˜ì„¸ìš”? +message.enter.broadcast.message = ì„ íƒëœ 친구들ì—게 브로드케스트 메시지 보내기 +message.enter.gadugadu = GaduGadu 사용ìžëª…ê³¼ 비밀번호를 ì•„ëž˜ì— ìž…ë ¥í•˜ì„¸ìš”. +message.enter.irc = IRC 사용ìžëª…ê³¼ 비밀번호를 ì•„ëž˜ì— ìž…ë ¥í•˜ì„¸ìš”. +message.enter.sametime = SameTime 사용ìžëª…ê³¼ 비밀번호를 ì•„ëž˜ì— ìž…ë ¥í•˜ì„¸ìš”. +message.enter.facebook = FaceBook 사용ìžëª…ê³¼ 비밀번호를 ì•„ëž˜ì— ìž…ë ¥í•˜ì„¸ìš”. +message.enter.myspace = Myspace 사용ìžëª…ê³¼ 비밀번호를 ì•„ëž˜ì— ìž…ë ¥í•˜ì„¸ìš”. +message.enter.jabber.id = Jabber 사용ìžëª…ì„ ì•„ëž˜ì— ìž…ë ¥í•˜ì„¸ìš”. +message.enter.message.to.broadcast = 주소ë¡ì˜ 모ë‘ì—게 전체알림 í•  메시지를 입력하세요.. +message.enter.new.subject = 새로운 주제를 입력하세요 +message.enter.qq = QQ 번호와 비밀번호를 ì•„ëž˜ì— ìž…ë ¥í•˜ì„¸ìš” +message.enter.room.password = ë°© 비밀번호를 입력하세요 +message.enter.simple = Simpleì— ì ‘ì†í•˜ê¸° 위해 ë‹¹ì‹ ì˜ ì‚¬ìš©ìžëª…ê³¼ 비밀번호를 입력하세요. +message.enter.valid.jid = 유효한 Jabber ID ìž…ë ¥ +message.enter.xmpp = XMPPì— ì ‘ì†í•˜ê¸° 위해 ë‹¹ì‹ ì˜ ì‚¬ìš©ìžëª…ê³¼ 비밀번호를 입력하세요. +message.error.during.file.transfer = íŒŒì¼ ì „ì†¡ì¤‘ ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. +message.file.exists.question = 파ì¼ì´ 존재합니다. ë®ì–´ì“°ì‹œê² ìŠµë‹ˆê¹Œ? +message.file.size = íŒŒì¼ í¬ê¸°: {0} +message.file.transfer.canceled = íŒŒì¼ ì „ì†¡ 취소했습니다. +message.file.transfer.rejected = íŒŒì¼ ì „ì†¡ì€ {0}ì—게 받아들여지지 않았습니다.. +message.file.transfer.notification = íŒŒì¼ ì „ì†¡ 알림 +message.file.transfer.short.message = ì´ ë‹¹ì‹ ì—게 파ì¼ì„ 보냅니다: +message.file.transfer.chat.window = íŒŒì¼ ì „ì†¡ 요청: +message.find.conference.services = íšŒì˜ ì„œë¹„ìŠ¤ 검색 +message.forbidden.error = 서버로 부터 ì ‘ê·¼ 금지 ì—러가 수신ë˜ì—ˆìŠµë‹ˆë‹¤. +message.gateway.username.error = ID를 입력해야합니다. +message.gateway.password.error = 비밀번호를 입력해야 합니다. +message.gateway.nickname.error = ë³„ëª…ì„ ìž…ë ¥í•´ì•¼í•©ë‹ˆë‹¤. +message.general.error = {0}ì˜ ì´ìœ ë¡œ ì„œë²„ì™€ì˜ ì—°ê²°ì´ ëŠê²¼ìŠµë‹ˆë‹¤. +message.generic.reconnect.message = ì—°ê²°ì´ ëŠê²¼ìŠµë‹ˆë‹¤. ì•„ëž˜ì— ìž¬ì—°ê²°ì„ í´ë¦­í•˜ì—¬ 다시 로그ì¸í•˜ì‹­ì‹œìš”. +message.idle.for = Idle for {0} +message.image.too.large = ì´ë¯¸ì§€ê°€ 너무 í½ë‹ˆë‹¤. ì´ë¯¸ì§€ í¬ê¸°ê°€ 16k보다 작아야합니다. +message.invalid.jabber.id = 유효한 Jabber IDê°€ 아닙니다. +message.invalid.jid.error = ì§€ì •ëœ JIDê°€ 잘못ë˜ì—ˆìŠµë‹ˆë‹¤. +message.invalid.status = 유효한 ìƒíƒœ 메시지를 지정합니다. +message.invalid.username.password = ID나 비밀번호가 유효하지 않습니다. +message.invite.users.to.conference = 회ì˜ì‹¤ì— 초대합니다. +message.is.shared.group = {0}ì€ ê³µìœ ëœ ê·¸ë£¹ìž…ë‹ˆë‹¤. +message.is.typing.a.message = {0} ì´ ë©”ì‹œì§€ 입력중입니다.... +message.join.conference.room = 회ì˜ì‹¤ì— ì°¸ì„ +message.kicked.error = ë‹¹ì‹ ì€ {0}ì„(를) ì´ ë°©ì—서 추방할 수 없습니다. +message.last.message.received = {0}로부터 마지막 메시지가 받아졌습니다 +message.loading.please.wait = 로딩중입니다. 기다리세요... +message.locked.workstation = 사용ìžëŠ” ê·¸ë“¤ì˜ ì›Œí¬ìŠ¤í…Œì´ì…˜ìœ¼ë¡œ 잠궈졌습니다. +message.name.of.group = 그룹 ì´ë¦„ +message.name.of.search.service.question = 검색 서비스 ì´ë¦„? +message.negotiate.file.transfer = 파ì¼ì „송 준비 중 입니다. 기다려주세요... +message.negotiate.stream = 스트림 ì—°ê²°ì„ ì¤€ë¹„ 중 입니다. 기다려주세요... +message.negotiation.file.transfer = {0}ì—게 파ì¼ì „송 준비 중 입니다. 기다려주세요... +message.new.message = {0}로부터 새로운 메시지. +message.new.spark.available = {0}ì€ í˜„ìž¬ 설치 가능합니다. 설치 하시겠습니까? +message.nickname.in.use = ë³„ëª…ì´ ì‚¬ìš©ì¤‘ìž…ë‹ˆë‹¤. 다른 ë³„ëª…ì„ ìž…ë ¥í•˜ì„¸ìš”. +message.no.avatar.found = 아바타를 수정할수 없습니다. +message.no.caller.id = 유효한 í˜¸ì¶œìž IDê°€ 없습니다. +message.no.description.available = 유효한 ì„¤ëª…ì´ ì—†ìŠµë‹ˆë‹¤ +message.no.history.found = 지난 대화 기ë¡ì´ 없습니다. +message.no.results.found = ê²€ìƒ‰ëœ ê²°ê³¼ê°€ 없습니다. +message.no.room.to.join.error = 들어갈 ë°©ì´ ì—†ìŠµë‹ˆë‹¤. +message.no.subject.available = ì œëª©ì„ ì‚¬ìš©í• ìˆ˜ 없습니다. +message.no.updates = ì—…ë°ì´íŠ¸ê°€ 없습니다. +message.normal = 메시지 +message.number.to.call = 전화를 걸기 위해 번호를 지정하세요 +message.offline = 사용ìžëŠ” 오프ë¼ì¸ ìƒíƒœì—¬ì„œ ì´ ë©”ì‹œì§€ëŠ” 사용ìžê°€ 다ìŒë²ˆ ë¡œê·¸ì¸ í•  때 ë°›ì„ ê²ƒ 입니다. +message.offline.error = 사용ìžëŠ” 오프ë¼ì¸ 메시지를 ë°›ì„ ìˆ˜ ì—†ì„ ê²ƒ 입니다. +message.participants.in.room = ë°©ì— ì°¸ì—¬í•˜ì˜€ìŠµë‹ˆë‹¤ +message.password.error = ì´ ê³„ì •ì„ ìœ„í•œ 암호를 지정하세요. +message.password.private.room.error = 비공개 ë°©ì„ ìœ„í•´ 암호를 지정하세요 +message.passwords.no.match = 비밀번호가 틀립니다. +message.please.join.in.conference = 회ì˜ì— ì°¸ì„해주세요. +message.plugins.not.available = í”ŒëŸ¬ê·¸ì¸ ì €ìž¥ì†Œì— ì ‘ì†í•  수 없습니다. +message.prompt.plugin.uninstall = ì •ë§ {0}ì„(를) 제거하시겠습니까? +message.received.file = {0}로부터 파ì¼ì„ 받았습니다. +message.receiving.file = {0}로부터 파ì¼ì„ 받고 있습니다. +message.reconnect.attempting = 연결중... +message.reconnect.failed = ìž¬ì‹œë„ ì‹¤íŒ¨ +message.reconnect.wait = 재연결중 {0} ì´ˆ. +message.register.transports = 유용한 ì „ì†¡ì— ë“±ë¡í•˜ê¸°. +message.registering = {0} 등ë¡ì¤‘입니다. 기다리세요.. +message.registration.transport.failed = 게ì´íŠ¸ì›¨ì´ì— ë“±ë¡ í•  수 없습니다. +message.restart.spark = 새로운 ë²„ì „ì˜ ì„¤ì¹˜ë¥¼ 위해 í´ë¼ì´ì–¸íŠ¸ë¥¼ \n재시작하여야 합니다. 지금 설치하시겠습니까? +message.restart.spark.changes = 플러그ì¸ì€ 다ìŒë²ˆ Spark 시작시 ì‚­ì œë  ê²ƒìž…ë‹ˆë‹¤. +message.restart.spark.to.install = 최신 ë²„ì „ì„ ì„¤ì¹˜ 하기 위해 í´ë¼ì´ì–¸íŠ¸ë¥¼ 종료하여야 합니다. 지금 종료 하시겠습니까? +message.restart.required = ìž¬ì‹œìž‘ì´ í•„ìš”í•©ë‹ˆë‹¤. 재시작 하시겠습니까? +message.room.creation.error = ì´ë°©ì€ ìƒì„±í• ìˆ˜ê°€ 없습니다. +message.room.destroyed = ì´ ë°©ì€ ë‹¤ìŒì˜ ì´ìœ ë¡œ í쇄ë˜ì—ˆìŠµë‹ˆë‹¤: {0} +message.room.destruction.reason = ë°©ì„ ì—†ì• ëŠ” ì´ìœ ëŠ”? +message.room.information.for = {0} ë°©ì •ë³´ +message.save.profile = ë³€ê²½ëœ í”„ë¡œí•„ì„ ì €ìž¥í•˜ê¸° 위해 ì €ìž¥ë²„íŠ¼ì„ í´ë¦­í•˜ì„¸ìš”. +message.search.for.contacts = 친구 검색 +message.search.for.other.people = 서버ì—서 친구 검색. +message.search.service.not.available = 검색 서비스 ì ‘ì†ì´ ë˜ì§€ 않습니다. +message.searching.please.wait = 검색중입니다. 기다리세요... +message.select.add.room.to.add = ë‹¹ì‹ ì˜ ì„œë¹„ìŠ¤ 목ë¡ì— 추가하기 위해 ë°©ì„ ì„ íƒí•˜ì„¸ìš”. +message.select.one.or.more = 친구를 ì„ íƒí•˜ì„¸ìš”. +message.select.room.to.enter = 들어가기 위한 ë°©ì„ ì§€ì •í•˜ì„¸ìš”. +message.select.room.to.join = 들어가기 위해 ë°©ì„ ì„ íƒí•˜ì„¸ìš”. +message.send.a.broadcast = 브로드케스트 보내기 +message.send.file.to.user = íŒŒì¼ ë³´ë‚´ê¸° +message.send.picture = 컴퓨터 í™”ë©´ì„ ìº¡ì³í•´ì„œ 보내기 +message.send.to.these.people = ì„ íƒí•œ 친구들ì—게 보내기 +message.sending.file.to = {0} ì—게 íŒŒì¼ ë³´ë‚´ëŠ” 중입니다. +message.sent.offline.files = ë‹¹ì‹ ì€ ë°©ê¸ˆ 오프ë¼ì¸ 파ì¼ì„ 전송했습니다. +message.server.unavailable = ì„œë²„ì— ì—°ê²°í•  수없습니다 : ìž˜ëª»ëœ ì´ë¦„ì´ë‚˜ ì„œë²„ì— ì—°ê²°í•  수없습니다. +message.service.already.exists = 서비스 ë¦¬ìŠ¤íŠ¸ì— ì´ë¯¸ 있습니다. +message.shared.group = 공유 그룹 +message.specify.contact.jid = 친구 JDI를 지정하세요(예. ddman@jabber.org) +message.specify.group = 새로운 ì‚¬ìš©ìž ì¶”ê°€ë¥¼ 위해 친구 ê·¸ë£¹ì„ ì§€ì •í•˜ì„¸ìš”. +message.specify.information.for.conference = 컨í¼ëŸ°ìФ ë°©ì˜ ì •ë³´ë¥¼ 지정하세요. +message.specify.name.error = 유효한 ì´ë¦„ì„ ì§€ì •í•˜ì„¸ìš”. +message.specify.users.to.join.conference = ì´ ì»¨í¼ëŸ°ìФ ë°©ì— ì°¸ì—¬í•  사용ìžë¥¼ 지정하세요. +message.specify.valid.time.error = 유효한 타임아웃과 í¬íŠ¸ë¥¼ 지정하세요. +message.subject.change.error = ë‹¹ì‹ ì€ ì´ ë°©ì˜ ì£¼ì œë¥¼ 바꾸ë„ë¡ í—ˆë½ë˜ì§€ 않았습니다. +message.subject.has.been.changed.to = 주제가 {0}(으)로 바꿔졌습니다. +message.supply.resource = 유효한 ìžì›ì„ ì ìœ¼ì„¸ìš”. +message.supply.valid.port = 유효한 í¬íЏ 번호를 ì ìœ¼ì„¸ìš”. +message.supply.valid.timeout = 유효한 타임아웃 ê°’ì„ ì ìœ¼ì„¸ìš”. +message.timeout.error = 제한 ì‹œê°„ì´ 5 ì´ˆ ì´ìƒì´ì–´ì•¼í•©ë‹ˆë‹¤. +message.total.downloaded = ì´ ë‹¤ìš´ë¡œë“œ +message.transfer.cancelled = íŒŒì¼ ì „ì†¡ì´ ì·¨ì†Œë˜ì—ˆìŠµë‹ˆë‹¤. +message.transfer.rate = 전송 ì†ë„ +message.transfer.refused = íŒŒì¼ ì „ì†¡ì´ ê±°ë¶€ë˜ì—ˆìŠµë‹ˆë‹¤. +message.transfer.waiting.on.user = íŒŒì¼ ì „ì†¡ì„ ìœ„í•´ {0} ì˜ ìˆ˜ë½ì„ 기다립니다. +message.unable.to.load.profile = {0]ì„(를) 위한 프로파ì¼ì„ 위치시킬 수 없습니다 +message.unable.to.retrieve.last.activity = {0}ì„(를) 위한 마지막 ë™ìž‘ì„ ê²°ì •í•  수 없습니다. +message.unable.to.save.password = 비밀 번호를 변경할 수 없습니다. 서버 관리ìžì—게 문ì˜í•˜ì‹­ì‹œìš”. +message.unable.to.send.file = {0} ì—게 파ì¼ì„ 보낼수 없습니다. +message.unrecoverable.error = ID나 비밀번호가 틀렸습니다. +message.update.room.list = 대화방 리스트 ì—…ë°ì´íЏ +message.updating.cancelled = ì—…ë°ì´íŠ¸ê°€ 취소ë˜ì—ˆìŠµë‹ˆë‹¤. +message.user.banned = {0}ì€(는) ì´ ë°©ì—서 금지 ë˜ì—ˆìŠµë‹ˆë‹¤. +message.user.given.voice = ì´ ë°©ì—서 {0}ì—게 ë°œì–¸ê¶Œì´ ì£¼ì–´ì¡ŒìŠµë‹ˆë‹¤. +message.user.granted.admin = {0}ì—게 ê´€ë¦¬ìž ê¶Œí•œì´ ë¶€ì—¬ë˜ì—ˆìŠµë‹ˆë‹¤. +message.user.granted.membership = {0}ì—게 멤버쉽 íŠ¹ê¶Œì´ ë¶€ì—¬ë˜ì—ˆìŠµë‹ˆë‹¤. +message.user.granted.moderator = {0}ì—게 ì§„í–‰ìž ê¶Œí•œì´ ì£¼ì–´ì¡ŒìŠµë‹ˆë‹¤.. +message.user.granted.owner = {0}ì—게 ì†Œìœ ìž ê¶Œí•œì´ ë¶€ì—¬ë˜ì—ˆìŠµë‹ˆë‹¤. +message.user.is.sending.you.a.file = {0} ì´(ê°€) 당신ì—게 파ì¼ì„ 보내려고 합니다. +message.user.joined.room = {0} ì´ ë“¤ì–´ì™”ìŠµë‹ˆë‹¤. +message.user.kicked.from.room = {0}ì€(는) ë°©ì—서 추방ë˜ì—ˆìŠµë‹ˆë‹¤. +message.user.left.room = {0}ì€(는) ë°©ì— ë‚¨ê²¨ì¡ŒìŠµë‹ˆë‹¤. +message.user.nickname.changed = {0}ì€(는) {1}로서 현재 알려졌습니다. +message.user.now.available.to.chat = {0}ì€(는) {1}ì— ì˜¨ë¼ì¸ ìƒíƒœìž…니다. +message.user.revoked.admin = {0} ë•Œë¬¸ì— ê´€ë¦¬ìž ê¶Œí•œì´ ì² íšŒë˜ì—ˆìŠµë‹ˆë‹¤. +message.user.revoked.membership = {0} ë•Œë¬¸ì— ë©¤ë²„ì‰½ ê¶Œí•œì´ ì² íšŒë˜ì—ˆìŠµë‹ˆë‹¤. +message.user.revoked.moderator = {0} ë•Œë¬¸ì— ì§„í–‰ìž ê¶Œí•œì´ ì² íšŒë˜ì—ˆìŠµë‹ˆë‹¤. +message.user.revoked.owner = {0} ë•Œë¬¸ì— ì†Œìœ ìž ê¶Œí•œì´ ì² íšŒë˜ì—ˆìŠµë‹ˆë‹¤. +message.user.voice.revoked = {0} ë•Œë¬¸ì— ë°œì–¸ê¶Œì´ ì² íšŒë˜ì—ˆìŠµë‹ˆë‹¤. +message.username.error = ê³„ì •ì˜ ì‚¬ìš©ìžì´ë¦„ì„ ì§€ì •í•˜ì„¸ìš”. +message.username.password.error = ì•„ì´ë”” ë° ë¹„ë°€ë²ˆí˜¸ ìž…ë ¥ë˜ì–´ì•¼ 합니다. +message.vcard.not.supported = ì„œë²„ì— VCard를 ì§€ì›í•˜ì§€ 않습니다. 저장할수 없습니다. +message.version = 버젼: {0} +message.view.information.about.this.user = 친구 ì •ë³´ +message.waiting.for.user.to.join = {0} ê°€ 들어오기 위해 대기중 +message.went.offline = {0} ì€(는) {1} 현재 오프ë¼ì¸ ìƒíƒœë¡œ ë˜ì—ˆìŠµë‹ˆë‹¤. +message.you.have.been.banned = ë‹¹ì‹ ì€ ì´ ë°©ì— ì°¨ë‹¨ë˜ì—ˆìŠµë‹ˆë‹¤. +message.you.have.been.kicked = ì´ ë°© 밖으로 쫓겨났습니다. +message.you.have.sent = {0} ì—게 íŒŒì¼ ì „ì†¡í–ˆìŠµë‹ˆë‹¤. +message.your.admin.granted = ê´€ë¦¬ìž ê¶Œí•œì´ ë¶€ì—¬ë˜ì—ˆìŠµë‹ˆë‹¤. +message.your.banned = ë‹¹ì‹ ì€ ì´ ë°©ì— ì°¨ë‹¨ë˜ì—ˆìŠµë‹ˆë‹¤. +message.your.kicked = ë‹¹ì‹ ì€ {0}ì— ì˜í•´ 추방ë˜ì—ˆìŠµë‹ˆë‹¤.. +message.your.membership.granted = íšŒì› ê¶Œí•œì´ ë¶€ì—¬ë¬ìŠµë‹ˆë‹¤. +message.your.membership.revoked = íšŒì› ìžê²©ì´ 취소ë˜ì—ˆìŠµë‹ˆë‹¤. +message.your.moderator.granted = ìš´ì˜ìž ê¶Œí•œì´ ë¶€ì—¬ë˜ì—ˆìŠµë‹ˆë‹¤. +message.your.moderator.revoked = ìš´ì˜ìž ê¶Œí•œì´ ì·¨ì†Œë˜ì—ˆìŠµë‹ˆë‹¤. +message.your.ownership.granted = ì†Œìœ ìž ê¶Œí•œì´ ì£¼ì–´ì¡ŒìŠµë‹ˆë‹¤. +message.your.ownership.revoked = ì†Œìœ ìž ê¶Œí•œì´ ì² íšŒë˜ì—ˆìŠµë‹ˆë‹¤. +message.your.revoked.granted = ê´€ë¦¬ìž ê¶Œí•œì´ ì·¨ì†Œë˜ì—ˆìŠµë‹ˆë‹¤. +message.your.voice.granted = 현재 채팅ì—서 ë°œì–¸ê¶Œì´ ì£¼ì–´ì¡ŒìŠµë‹ˆë‹¤. +message.your.voice.revoked = ìŒì„±ëŒ€í™”ê°€ 취소ë˜ì—ˆìŠµë‹ˆë‹¤. +message.groupchat.require.password = ì´ ê·¸ë£¹ ëŒ€í™”ë°©ì€ ë¹„ë°€ë²ˆí˜¸ë¥¼ 입력해야합니다. +message.search.for.history = ëŒ€í™”ê¸°ë¡ ê²€ìƒ‰ + +status.away = ìžë¦¬ë¹„움 +status.custom.messages = ì‚¬ìš©ìž ë©”ì‹œì§€ +status.do.not.disturb = 다른용무중 +status.extended.away = ìžë¦¬ë¹„움 +status.free.to.chat = 대화 가능 +status.on.phone = 전화중 +status.online = 온ë¼ì¸ +status.pending = 기다림 + +tab.available.plugins = 사용가능한 í”ŒëŸ¬ê·¸ì¸ +tab.avatar = 사진 +tab.business = ì§ìž¥ +tab.conferences = íšŒì˜ +tab.contacts = 대화 +tab.general = ì¼ë°˜ì‚¬í•­ +tab.home = ì§‘ +tab.installed.plugins = ì„¤ì¹˜ëœ í”ŒëŸ¬ê·¸ì¸ +tab.personal = ê°œì¸ +tab.proxy = Proxy +tab.sso = SSO +tab.pki = PKI + +title.about = Spark ì •ë³´ +title.password.required = 비밀번호 필요함 +title.task.notification = 작업 알림 +title.client.logs = í´ë¼ì´ì–¸íЏ 로그 +title.account.create.registration = 계정 ë“±ë¡ +title.bookmarks = ë¶ë§ˆí¬ +title.account.created = 계정 추가ë˜ì—ˆìŠµë‹ˆë‹¤. +title.add.contact = 친구 추가 +title.add.contact.group = 친구 그룹 추가 +title.add.new.group = 새 그룹 추가 +title.add.search.service = 검색 서비스 추가 +title.add.to.roster = 친구 ë¦¬ìŠ¤íŠ¸ì— ì¶”ê°€ +title.address = 주소 +title.advanced.connection.preferences = 고급 ì—°ê²° 설정 +title.advanced.connection.usesso = GSAPI 를 통해서 Sign-on(SSO) 를 사용합니다.(&U) +title.alert = 알림 +title.appearance = 외모 +title.appearance.preferences = ì‚¬ìš©ìž ì •ì˜ +title.available.transports = 사용 가능한 전송 +title.broadcast.message = 브로드케스트 메시지 +title.browse.conference.services = íšŒì˜ ì„œë¹„ìŠ¤ íƒìƒ‰ +title.browse.room.service = 회ì˜ì‹¤ íƒìƒ‰ - {0} +title.cancelled = ì·¨ì†Œë¨ +title.change.nickname = 별명 변경 +title.change.subject = 주제 변경 +title.chat = 대화 +title.choose.directory = 디렉토리 ì„ íƒ +title.choose.incoming.sound = 들어옴 소리 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” +title.choose.offline.sound = 오프ë¼ì¸ 소리 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” +title.choose.outgoing.sound = ë‚˜ê° ì†Œë¦¬ 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” +title.conference.invitation = íšŒì˜ ì´ˆëŒ€ +title.conference.rooms = 회ì˜ì‹¤ +title.configure.chat.room = 대화방 설정 +title.configure.room = 대화방 설정 +title.confirmation = í™•ì¸ +title.create.new.account = 새 계정 ìƒì„± +title.create.or.bookmark.room = 참여 ë˜ëŠ” ë¶ë§ˆí¬ë°© +title.create.room = ìƒì„± +title.create.problem = 계정 ìƒì„± 문제 +title.delete.file = ì´ íŒŒì¼ì„ 삭제하시겠습니까? +title.dial.phone = 전화걸기 +title.disable.transport = ë¡œê·¸ì¸ ì •ë³´ ì‚­ì œ +title.download.complete = 다운로드 완료 +title.downloading.im.client = IM í´ë¼ì´ì–¸íЏ 다운로드 +title.downloads = 다운로드 +title.edit.custom.message = ì‚¬ìš©ìž ë©”ì‹œì§€ 편집 +title.edit.profile = 프로필 ì •ë³´ 편집 +title.enter.reason = 메시지 ìž…ë ¥ +title.error = ì—러 +title.error.couldnot.open.file = 파ì¼ì„ 열수 없습니다. 알려지지 ì•Šì€ íŒŒì¼ í˜•ì‹ìž…니다. +title.error.delete.file = íŒŒì¼ ì‚­ì œí• ìˆ˜ 없습니다! +title.error.find.app = 어플리케ì´ì…˜ê³¼ 매칭할 파ì¼ì„ ì°¾ì„수 없습니다. +title.error.rename.file = 파ì¼ëª… 변경할수 없습니다.! +title.file = íŒŒì¼ +title.filesize = í¬ê¸° +title.file.exists = 파ì¼ì´ 존재합니다. +title.file.transfer = íŒŒì¼ ì „ì†¡ +title.file.transfer.preferences = íŒŒì¼ ì „ì†¡ 설정 +title.find.conference.service = íšŒì˜ ì„œë¹„ìŠ¤ 검색 +title.find.contacts = 친구 검색 +title.gadugadu.registration = GaduGadu 계정ì¸ì¦ +title.general.media = 미디어 설정 +title.general.chat.settings = ì¼ë°˜ 대화 설정 +title.group.chat = 그룹 대화 +title.group.chat.settings = 그룹 대화 설정 +title.history.for = {0} ì„ ìœ„í•œ 대화내용 +title.irc.registration = IRC 계정 ì¸ì¦ +title.sametime.registration = Sametime 계정ì¸ì¦ +title.facebook.registration = Facebook 계정ì¸ì¦ +title.myspace.registration = MySpace 계정ì¸ì¦ +title.incoming.call = ì „í™” 오는 중 +title.input.fileexplorer = íƒìƒ‰ê¸°ì—서 ì´ë¦„ ìž…ë ¥: +title.input.newname = 새 ì´ë¦„ ìž…ë ¥: +title.input.openwith = ë‹¹ì‹ ì´ ì‚¬ìš©í•˜ê³  ì‹¶ì€ ì–´í”Œë¦¬ì¼€ì´ì…˜ì— ì´ë¦„ì„ ë„£ì–´ì£¼ì‹­ì‹œìš”: +title.invite.to.conference = 회ì˜ì— 초대합니다. +title.jabber.browser = íƒìƒ‰ +title.join.conference.room = 회ì˜ë°©ì— 참여 +title.last.activity = 마지막 ë™ìž‘ +title.login = ë¡œê·¸ì¸ +title.login.error = ë¡œê·¸ì¸ ì‹¤íŒ¨ +title.login.settings = ë¡œê·¸ì¸ ì„¤ì • +title.lookup.profile = 프로필 검색 +title.name = ì´ë¦„ +title.new.client.available = 새로운 í´ë¼ì´ì–¸íЏ 사용가능 +title.new.roster.group = 새 그룹 +title.new.version.available = 새로운 ë²„ì „ì´ ìžˆìŠµë‹ˆë‹¤. +title.no.updates = ì—…ë°ì´íŠ¸ê°€ 없습니다. +title.notes = 노트 +title.notification = 공지 +title.notifications = 알림 +title.occupants = ì¸ì›ìˆ˜ +title.on.the.phone = 전화중 +title.password = 비밀번호 +title.passwords.no.match = 비밀번호 확ì¸. +title.person.search = 친구 검색 +title.plugins = í”ŒëŸ¬ê·¸ì¸ +title.preferences = 설정 +title.profile.information = 프로필 ì •ë³´ +title.profile.not.found = í”„ë¡œí•„ì„ ì°¾ì„수 없습니다. +title.qq.registration = QQ 계정 ì¸ì¦ +title.register.account = 새 계정 ë“±ë¡ +title.registration.error = ë“±ë¡ ì—러 +title.reminder = 알림 +title.rename.roster.group = 그룹 ì´ë¦„ 바꾸기 +title.room.destroyed = ë°©ì´ íì‡„ë¨ +title.room.information = 대화방 ì •ë³´ +title.roster = 친구 리스트 +title.select.file.to.send = 전송할 íŒŒì¼ ì„ íƒ +title.set.status.message = ìƒíƒœ 메시지 설정 +title.simple.registration = SIMPLE 계정 ì¸ì¦ +title.sound.preferences = 소리 설정 +title.sounds = 소리 +title.spark.preferences = Spark 설정 +title.start.chat = 대화 시작 +title.status.message = ìƒíƒœ 메시지 +title.tasks = 작업 +title.transports = 전송 +title.tray.information = íŠ¸ë ˆì´ ì •ë³´ +title.upgrading.client = í´ë¼ì´ì–¸íЏ 업그레ì´ë“œì¤‘ +title.version.and.time = 버젼과 시간 +title.view.bookmarks = ë¶ë§ˆí¬ 보기 +title.view.profile.for = {0} 프로필 +title.view.room.information = ë°©ì •ë³´ 보기 +title.waiting.to.call = ì „í™”ì—°ê²°ì„ ìœ„í•´ 기다려주십시오. +title.xmpp.registration = xmpp 계정ì¸ì¦ +title.appearance.showVCards = 친구 리스트ì—서 프로필 ì •ë³´ ë³´ì´ê¸° +title.subscription.request= 구ë…ì´ í•„ìš”í•©ë‹ˆë‹¤. + +tooltip.place.a.call = ì „í™” 걸기 +tooltip.appearance = ë‹¹ì‹ ì˜ ëŒ€í™”ì˜ ëª¨ì–‘ì„ ë°”ê¿‰ë‹ˆë‹¤. +tooltip.file.transfer = íŒŒì¼ ì „ì†¡ 설정 +tooltip.notifications = 들어오는 채팅 선호 알림 +tooltip.place.voice.call = ìŒì„± ì „í™” 하기. +tooltip.send.email = ì´ë©”ì¼ ë³´ë‚´ê¸°. +tooltip.start.chat = 대화 시작. +tooltip.view.changelog = 변경 로그 보기 +tooltip.view.history = 지난 대화 보기 +tooltip.view.readme = ReadMe 보기 + +tree.conference.services = íšŒì˜ ì„œë¹„ìŠ¤ +tree.users.in.room = ë°©ì— ìžˆëŠ” 친구들 diff --git a/core/src/main/resources/i18n/spark_i18n_ky.properties b/core/src/main/resources/i18n/spark_i18n_ky.properties new file mode 100644 index 000000000..e95c26cbd --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_ky.properties @@ -0,0 +1,720 @@ +accept= Кабыл алуу +action.clear=Тазалоо +action.copy=Көчүрүү +action.cut=КеÑÒ¯Ò¯ +action.paste=Коюу +action.print=БаÑмалоо +action.save=Сактоо +action.select.all=Бардыгын тандоо +is.active= Ðктивдүү +add= Кошуу +answer=Жооп берүү +apply=Ðткаруу +available= Тармакта +broadcast= Көптүк кабарлама +button.accept=&Кабыл алуу +button.add= &Кошуу +button.add.a.contact= Ко&нтакт кошуу +button.add.bookmark= ЭÑбелгини кошуу +button.add.service= Кы&зматты кошуу +button.add.user= Ко&лдонуучу кошуу +button.add2=Ко&шуу +button.advanced= Ко&шумча +button.approve= &УрукÑат берүү +button.bookmark.room=&Бөлмөнү ÑÑбелгилөө +button.browse= &Ðралоо... +button.browse2= Ð&ралоо... +button.browse3= ÐÑ€&алоо... +button.cancel= Ð&йнуу +button.clear= &Тазалоо +button.close=&Жабуу +button.copy.to.clipboard=Буферге көчүрүү +button.create.account= К&атталуу +button.create.room= Бө&лмөнү түзүү же кирүү +button.decline= &Четке кагуу +button.deny= Ч&етке кагуу +button.dial.number= &Ðомерди терүү +button.find= Та&буу +button.join= Ко&шулуу +button.join.room= Тандал&ган бөлмөгө кирүү +button.new= &Жаңы +button.profile= Пр&офиль +button.quit=&Чыгуу +button.reconnect= Ка&йрадан туташуу +button.reconnect2=Кайрадан туташуу +button.refresh= Ж&аңылоо +button.register= Ка&тталуу +button.reject=&Четке кагуу +button.remove.bookmark= ЭÑбелгини алып Ñалуу +button.roster= К&онтакт тизмеÑи +button.save= &Сактоо +button.save.for.future.use= Кийи&нки колдонуштарга үчүн Ñактоо +button.search= &Издөө +button.send=Жөнөтүү +button.send.email= Email +button.start.chat= Чат +button.tasks.active=Ðктивдүү +button.tasks.all=Бардыгы +button.unset.file.explorer= Unset File Browser +button.update= &Жаңылоо +button.view.notes=ЭÑкертмелерди көрÑөтүү +button.view.profile=Толук профилди көрÑөтүү +button.view.tasklist=Тапширмалар тизмеÑин көрÑөтүү +cancel= Ðйнуу +checkbox.allow.buzz= Сизди «ойготуу» аракетине урукÑат берүү. +checkbox.auto.discover.port= &Ðвтоматтык түрдө Ñерверди жана портту табуу +checkbox.auto.login= Ð&втоматтык кирүү +checkbox.broadcast.hide.offline.user= өчүк колдонуучуларды жашыруу +checkbox.disable.chat.history= Чат &тарыхын иштен чыгаруу +checkbox.disable.prev.chat.history= &Мурунку Ñүйлөшүүлөрдү көрÑөтүүÑүн өчүрүү +checkbox.enable.emoticons= Күлкү Ñүрөтбелгилерди жандыруу +checkbox.idle.enabled=«Орунда ÑмеÑ» &жандыруу +checkbox.launch.on.startup= &Жүктөлүүдө баштоо +checkbox.notify.systemtray=Жаңы кабарламаларды ÑиÑтемдик трейде көрÑөтүү +checkbox.notify.typing.systemtray=Жазып жаткандыгын ÑиÑтемдик трейде көрÑөтүү +checkbox.notify.user.comes.online=Колдонуучу тармакка киргенде ÑÑтетүү +checkbox.notify.user.goes.offline=Колдонуучу тармактан чыкканда ÑÑтетүү +checkbox.permanent= Т&урактуу бөлмө +checkbox.play.sound.on.invitation= Чакырууну кабыл а&лууда үндү ойнотуу +checkbox.play.sound.on.new.message= Жаңы &кабарламалар үчүн үндү ойнотуу +checkbox.play.sound.on.outgoing.message=Кабарламаны &жөнөтүүдө үндү ойнотуу +checkbox.play.sound.when.offline= Колдонуучу тармактан &чыкканда үндү ойнотуу +checkbox.private.room= Жеке &бөлмө +checkbox.save.password= &СырÑөздү Ñактоо +checkbox.show.avatars.in.contactlist=&Cүрөтбелгилерди Контакт тизмеÑинде көрÑөтүү +checkbox.show.notifications.in.conference= &КонференциÑларда ÑÑкертүүлөрдү көрÑөтүү +checkbox.show.time.in.chat.window= &Чат терезеÑинде убакытты көрÑөтүү +checkbox.show.toaster= ÐÑ€ бир &кабарламаны билдирүү +checkbox.split.chat.window= Терезелерге &жабыштыруу (программаны кайрадан баштоо керек) +checkbox.start.in.tray= &СиÑтемдик трейде баштоо +checkbox.tabs.on.top= Чатты терезелердин Ò¯Ñтүнөн ачуу (программаны кайрадан баштоо керек) +checkbox.tabs.scroll = Чат өтмөктөрү үчүн Ñыдырууну колдонуңуз (программаны кайрадан баштоо керек) +checkbox.use.compression=Use Co&mpression +checkbox.use.debugger.on.startup=Башталышта &Debugger'ди баштоо +checkbox.use.krb.dns=DNS колдонуу +checkbox.use.krbconf=krb5.conf же krb5.ini колдонуу +checkbox.use.pki.authentication= &PKI аутентификацыÑÑын колдонуу +checkbox.use.proxy.server= Pro&xy Ñерверди колдонуу +checkbox.use.specify.below=Төмөндө көрÑөтүү +checkbox.use.system.look.and.feel= Темаларды колдонуу (System Look And &Feel) (программаны кайрадан баштоо керек) +checkbox.window.to.front=&Терезени алдыга алып келүү +checkbox.close.unread.message = Терезени жаап жатканда окула Ñлек билдирүүлөр бар-жогун Ñураңыз +close=Жабуу +create= Түзүү +date= Дата +delete.log.permanently=Permanently delete log +delete.permanently= Permanently delete? +description= КыÑкача маалымат +from= Кимдем +gateway.username.password.error=Колдонуучу аты жана/же СырÑөз көрÑөтүлүшү керек. +group.chat.name.match=Сиздин атыңыз группа чатында айтылды: +group.chat.name.notification=Ðтыңыз көрүлдү... +group.chat.window.information= Чат жөнүндө маалымат +group.comma.delimited= Comma Delimited +group.conferences.found=ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ñ ÐºÑ‹Ð·Ð¼Ð°Ñ‚Ñ‚Ð°Ñ€Ñ‹ табылды +group.connection= Туташуу +group.empty=Бул группадан Ñч кимиÑи тармакта жок. +group.general.information= Ðегизги маалымат +group.login.information=Логин маалыматы +group.notification.options= ЭÑтетүү ыраÑтоолору +group.offline=Тармакта ÑÐ¼ÐµÑ Ð³Ñ€ÑƒÐ¿Ð¿Ð°ÑÑ‹ +group.search.form=Издөө +group.search.results=Издөө жыйынтыгы +invite= Чакыруу +join=Кошулуу +label.accounts=&Колдонуучулар +label.add.conference.service= Конфе&ренциÑлар Ñерверин кошуу +label.add.jid= JID &кошуу +label.add.task=Тапшырма кошуу +label.auto.login= &Ðвтоматтык кирүү +label.available.users.in.roster= &Бар болгон колдонуучулар +label.cancel= Ðйнуу +label.cell=Cell +label.change.password.to= &СырÑөздү алмаштыруу +label.chatroom.fontsize=Чат &бөлмөнүн фонт өлчөмү: +label.chatroom.maxcurrenthistorysize =Учурдагы тарыхтын макÑималдуу өлчөмү: +label.choose.file=Файлды тандаңыз +label.city= &Шаар +label.close=&Жабуу +label.company= К&Ð¾Ð¼Ð¿Ð°Ð½Ð¸Ñ +label.confirm.password= Сы&Ñ€Ñөздү кайталоо +label.conflict.error= Туташуу мүмкүн ÑмеÑ. Колдонуучу башка жерден туташты. +label.contact.to.find= Контактты табуу +label.contactlist.avatarsize=Контакт тизмеде аватар өлчөмү: +label.contactlist.fontsize=Контакт тизменин &фонт өлчөмү: +label.country= &Өлкө +label.create.account= Колдонуучу атын &түзүү +label.department=&Отдел +label.dial= Т&ерүү +label.downloads=Жүктөөлөр +label.due=Due +label.email.address= &Email адреÑи +label.emoticons= &Күлкү Ñүрөтбелгилери +label.enter.address= ÐдреÑти кириңиз +label.enter.group.name= Группанын жаңы атын кириңиз +label.enter.password=СырÑөздү кириңиз +label.fax= &Ð¤Ð°ÐºÑ +label.find= &Табуу +label.first.name=&Ðты +label.group=&Группа +label.home=Үй +label.host=&Сервер +label.invited.users= Чакырылган колдонуучулар +label.jabber.address= &Jabber адреÑи +label.jabber.id= &Jabber ID +label.jid= &JID +label.job.title=&Кызматы +label.krb.kdc=KDC +label.krb.realm=Realm +label.last.name= &Ð¤Ð°Ð¼Ð¸Ð»Ð¸Ñ +label.local.time= Ж&ергиликтүү убакыт +label.message= &Кабарлама +label.message.style= Кабарлама &Ñтили +label.middle.name= &ÐтаÑынын аты +label.minutes.before.stale.chat=&Ðктивдүү ÑÐ¼ÐµÑ Ð±Ó©Ð»Ð¼Ó©Ð½Ò¯Ð½ ÑÑкирүүÑүнө өткөн убакыты +label.mobile= &Уюлдук телефон +label.move.focus.backwards=ФокуÑту алдыга жылдыруу +label.move.focus.forwards=ФокуÑту артка жылдыруу +label.na=жок +label.name= &Ðты +label.network= &Тармак +label.new.nickname= Жаңы такма Ñ‹Ñымы +label.nickname= Так&ма Ñ‹Ñымы +label.number= &Ðомери +label.ok= OK +label.old.ssl= «OLD SSL port» методун &колдонуу +label.os= &ОС +label.pager= &Пейджер +label.password= &СырÑөз +label.phone= Теле&фон +label.port= Пор&Ñ‚ +label.postal.code= Почта &индекÑи +label.presence= &Ð¡Ñ‚Ð°Ñ‚ÑƒÑ +label.priority= П&риоритет +label.protocol= П&ротокол +label.received=Кы&был алынды +label.rename.to= Ðтын алмаштыруу +label.resource= &РеÑÑƒÑ€Ñ +label.response.timeout= &Жооп таймауту (Ñек) +label.room= &Бөлмө +label.room.name= Бөлмөнүн &аты +label.room.topic= Бөлмөнүн &темаÑÑ‹ +label.search.service=&Издөө ÑервиÑи +label.server= Сер&вер +label.server.address= Сервердин адреÑи +label.show=КөрÑөтүү: +label.software= &Клиенти +label.state.and.province= О&блаÑть +label.street.address= Ð&Ð´Ñ€ÐµÑ +label.time= Убакыт: {0} +label.time.till.idle= «Орунда ÑмеÑ» өткөн убакыт (мин) +label.timeformat=Колдонуу {0} +label.transfer.download.directory=&Папкага Ñактоо: +label.transfer.timeout= Өткөзүү таймауту (минута менен): +label.trust.store.password= Trust Store ÑырÑөзү +label.unable.to.add.contact= Контакт кошулган жок. +label.use.default= Ðлдынала +label.user.on.public.network= Колдонуучу жалпы тармак ичинде +label.username= К&олдонуучу аты +label.version= &ВерÑиÑÑÑ‹ +label.web.page= &Веб баракчаÑÑ‹ +label.which.pki.method=КайÑÑ‹ PKI методу? +label.work=Жумушу +label.xmpp.port= &XMPP порту +menuitem.about= Программа жөнүндө +menuitem.actions= Ðмалдар +menuitem.add= Кошуу +menuitem.add.as.contact= Контактты кошуу +menuitem.add.contact=Контактты кошуу +menuitem.add.contact.group= Группаны кошуу +menuitem.add.groupchat.myname=Менин атым айтылганда атымды жаркыратуу +menuitem.add.groupchat.mytext=Мен Ñүйлөгөндө текÑтти жаркыратуу +menuitem.add.groupchat.popname= Show custom toaster popup when someone says my name +menuitem.add.groupchat.showjoinleavemessage=Кошулуу жана чыгуу кабарламалырды көрÑөтүү +menuitem.alert.when.online= Колдонуучу тармакка киргенде ÑÑтетүү +menuitem.always.on.top=ÐÑ€ дайым Ò¯Ñтүдө +menuitem.ban= Чектөө +menuitem.ban.user= Колдонуучуну чектөө +menuitem.block.user= Колдонуучуну блоктоо +menuitem.bookmark.room= Bookmark Room +menuitem.bookmarks=ЭÑбелгелер +menuitem.broadcast.to.group=Группага көптүк кабарламаны жөнөтүү +menuitem.browse.service=Кызматты аралоо +menuitem.change.nickname= Такма Ñ‹Ñымды алмаштыруу +menuitem.change.subject= Теманы алмаштыруу +menuitem.chat= Чат +menuitem.chatframe.option=Параметрлер +menuitem.check.for.updates= Жаңылоолорду текшерүү +menuitem.collapse.all.groups=Бардык группаларды жыю +menuitem.contacts= Контакт +menuitem.copy.to= Көчүрүү +menuitem.create.room=Бөлмөнү түзүү же кошулуу +menuitem.delete= Өчүрүү +menuitem.delete.login.information=Катталуу маалыматтарын өчүрүү +menuitem.destroy.room= Бөлмөнү бузуу +menuitem.dial=Терүү +menuitem.edit= Ондоо +menuitem.edit.my.profile= &Профилди ондоо... +menuitem.edit.status.message= СтатуÑтарды ондоо... +menuitem.enter.login.information= Катталуу маалыматтарын кирүү +menuitem.exit=Чыгуу +menuitem.expand.all.groups=Бардык группаларды жайноо +menuitem.grant.moderator= Модератор укуктарын берүү +menuitem.grant.voice= Сүйлөө укугун берүү +menuitem.help= Жардам +menuitem.hide=Жашыруу +menuitem.invite.again=Кайрадан чакыруу +menuitem.invite.group.to.conference=Группаны конференциÑга чакыруу +menuitem.invite.users= Колдонуучуларды чакыруу +menuitem.join.on.startup= Жүктөлүүдө кирүү +menuitem.join.room= Бөлмөгө кирүү +menuitem.kick.user= Колдонуучуну айдап Ñалуу +menuitem.languages=Тилдер +menuitem.logout.no.status=Тармактан чыгуу +menuitem.logout.with.status= Себеп менен чыгуу +menuitem.lookup.profile= Про&филди көрүү... +menuitem.move.to= Жылдыруу +menuitem.online.help= Spark форумдары +menuitem.open= Ðчуу +menuitem.open.with=Менен ачуу... +menuitem.plugins= Плагиндер +menuitem.preferences= ЫраÑтоолор +menuitem.refresh=Жаңылоо +menuitem.remove=Ðлып Ñалуу +menuitem.remove.alert.when.online= ЭÑкертүүнү алып Ñалуу +menuitem.remove.bookmark=ЭÑбелгени алып Ñалуу +menuitem.remove.from.group=Группадан алып Ñалуу +menuitem.remove.from.roster=Контакт тизмеден алып Ñалуу +menuitem.remove.service=Кызматты алып Ñалуу +menuitem.rename= Ðтын алмаштыруу +menuitem.revoke.moderator=Модератор укугун алып Ñалуу +menuitem.revoke.voice= Сүйлөө укугун алып Ñалуу +menuitem.save= Сактоо +menuitem.save.as=Жаңыча Ñактоо... +menuitem.send.a.file= Файл жөнөтүү +menuitem.send.a.message=Тандалган колдонуучуларга кабарламаны жөнөтүү... +menuitem.set.status.message=СтатуÑту орнотуу... +menuitem.show.contact.statusmessage=CтатуÑун көрÑөтүү +menuitem.show.empty.groups=Бош группаларды көрÑөтүү +menuitem.show.offline.group=Тармакта ÑÐ¼ÐµÑ ÐºÐ¾Ð»Ð´Ð¾Ð½ÑƒÑƒÑ‡ÑƒÐ»Ð°Ñ€Ð´Ñ‹ жыйноо +menuitem.show.offline.users=Тармакта ÑÐ¼ÐµÑ ÐºÐ¾Ð»Ð´Ð¾Ð½ÑƒÑƒÑ‡ÑƒÐ»Ð°Ñ€Ð´Ñ‹ көрÑөтүү +menuitem.show.traffic= Трафик терезеÑин көрÑөтүү +menuitem.sign.in= Войти +menuitem.sign.in.at.login=Жүктөлүүдө кирүү +menuitem.sign.out=Тармактан чыгуу +menuitem.start.a.chat= Чатты баштоо +menuitem.start.a.conference=КонференциÑны баштоо... +menuitem.status= Ð¡Ñ‚Ð°Ñ‚ÑƒÑ +menuitem.subscribe.to= Жазылуу +menuitem.unban=Чектөөнү алып Ñалуу +menuitem.unblock.user= Колдонуучуну блоктон алып Ñалуу +menuitem.user.guide= Колдонуучу инÑтрукциÑÑÑ‹ +menuitem.view.client.version= Клиент верÑиÑÑын көрÑөтүү +menuitem.view.contact.history= Контакт тарыхын көрÑөтүү +menuitem.view.downloads= Жүктөөлөр папкаÑын ачуу +menuitem.view.last.activity=Ðкыркы активдүүлүк убакытын көрÑөтүү +menuitem.view.logs=Логдорду көрÑөтүү +menuitem.view.profile= Профилди көрÑөтүү +menuitem.view.room.info= Бөлмө жөнүндө маалыматты көрÑөтүү +menuitem.voice= Сүйлөө укугу +message=Кабарлама +message.account.create= Жаңы колдонуучу атын түзүү. +message.account.created=Жаңы колдонуучу түзүлдү. +message.account.error= Колдонуучу түзүлүүчү Ñерверди көрÑөтүңүз. +message.add.a.contact=Контактты кошуу +message.add.conference.service=ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ñ ÐºÑ‹Ð·Ð¼Ð°Ñ‚Ñ‹Ð½ кошуу. +message.add.contact.to.list= Колдонуучуну контакт тизмеÑине кошуу +message.add.favorite.room=Бөлмөнү жактырылгандарга кошуу же дароо кирүү. +message.add.this.user.to.your.roster=Колдонуучуну контакт тизмеÑине кошуу. +message.add.to.roster=Контакт тизмеÑине кошуу +message.add.user=Колдонуучу контакт тизмеге кошулÑунбу? +message.alert.notify=ЭÑкертүү +message.already.exists=Мындай колдонуучу аты алда качан бар. Башка колдонуучу атын колдонуп көрүңүз. +message.approve.subscription= {0} Ñизди алардын контакт тизмеÑине кошууга урукÑат береÑизби? +message.authenticating= ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ +message.away.idle=«Орунда ÑмеÑ» (Колдонулбай калгандыгынан) +message.bookmark.temporary.room.error=Убактылуу бөлмөлөрдү ÑÑбелгилерге кошо албайÑыз +message.broadcast.from= Кабарлама {0} атынан +message.broadcast.message.sent=Көптүк кабарлама жөнөтүлдүү. +message.broadcast.to={0} жөнөтүүлүчү текÑтти кириңиз +message.hasbeenbroadcast.to=Көптүк кабарлама төмөнкү колдонуучуларга жөнөтүлдү: +message.buzz.alert.notification= Get the user's attention. +message.buzz.sent= Колдонуучуну «ойготуу» +message.calling= {0} чалып жатат +message.came.online= {0} колдонуучу {1} бери тармакта +message.cannot.add.contact.to.shared.group=Бөлүштүрүлгөн группага жаңы колдонуучуларды кошалбайÑыз. +message.chat.session.ended= Чат {0} убакытында бүттү +message.click.to.open=Ðчуу +message.client.information={0} үчүн клиент маалыматы +message.close.other.chats=Башка чаттарды жабуу +message.close.stale.chats=ЭÑкирген чаттарды жабуу +message.close.this.chat=Бул чатты жабуу +message.close.unread.window = Сизде окула Ñлек билдирүүлөр бар, чын Ñле терезени жапкыңыз келеби? +message.conference.info.error= ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ„Ð¸Ñ Ð¶Ó©Ð½Ò¯Ð½Ð´Ó© маалымат алуу мүмкүн ÑмеÑ. Кийинчерек кайталап көрүңүз. +message.conference.service.error=ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ñ ÐºÑ‹Ð·Ð¼Ð°Ñ‚Ñ‹ табылган жок. +message.confirm.destruction.of.room=Бузулуучу бөлмөдө бар болгон колдонуучулар бөлмөдөн айдалынып Ñалынат. Улантуу? +message.confirmation.password.error=СырÑөздү кайра кириңиз. +message.connecting.please.wait=Туташуу. Күтө туруңуз... +message.connection.failed={0} менен байланыш жок. +message.create.account=Колдонуучу аты түзүлгөн жок. +message.create.or.join.room=Бөлмөнү түзүү же конференц чат бөлмөÑүнө кошулуу +message.current.status= СтатуÑту башкаларга көрÑөтүү. +message.default.error=Ката табылды. Сураныч, көрÑөтүлгөн адреÑке support@jivesoftware.com билдириңиз. +message.delete.all.history=Бардык Ñүйлөшүү тарыхтары өчүрүлÑүнбү? +message.delete.confirmation={0} өчүрүлÑүнбү? +message.disable.transport={0} колдонуучу маалыматы өчүрүлÑүнбү? +message.disconnected.conflict.error=Башка компьютерден Ñиздин атыңыз менен киргендигинен Ñиздин туташууңуз жабылды. +message.disconnected.error= Туташуу ийгиликÑиз аÑктады. +message.disconnected.group.chat.error= Туташуу ийгиликÑиз аÑктады. Кайра туташуудан кийин бөлмөгө кайра киришиңиз керек. +message.disconnected.shutdown=Сервердин өчүүÑүнө байланыштуу Ñиздин туташууңуз жабылды. +message.downloading={0} жүктөөлүп жатат +message.downloading.spark.plug=Spark-Plug жүктөлүп жатат +message.end.chat= Чатты аÑктоо? +message.end.conversation= Сүйлөшүүнү аÑктоо? +message.enter.broadcast.message= Тандалган колдонуучулар үчүн көптүк кабарламаны киргизиңиз. +message.enter.facebook=Facebook колдонуучу атын жана ÑырÑөзүн кириңиз. +message.enter.gadugadu=GaduGadu колдонуучу атын жана ÑырÑөзүн кириңиз. +message.enter.irc=IRC колдонуучу атын, ÑырÑөзүн жана такма Ñ‹Ñымыңызы кириңиз. +message.enter.jabber.id=Jabber ID'ни кириңиз +message.enter.message.to.broadcast= Контакт тизмеÑинде бардык колдонуучуларга жөнөтүлүүчү көптүк кабарламаны кириңиз. +message.enter.myspace=MySpace колдонуучу атын жана ÑырÑөзүн кириңиз. +message.enter.new.subject= Введите тему +message.enter.qq=QQ номерин жана ÑырÑөзүн кириңиз. +message.enter.room.password= Введите пароль Ð´Ð»Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹ +message.enter.sametime=Sametime колдонуучу атын жана ÑырÑөзүн кириңиз. +message.enter.simple=SIMPLE колдонуучу атын жана ÑырÑөзүн кириңиз. +message.enter.valid.jid=Туура Jabber ID кириңиз +message.enter.xmpp=XMPP колдонуучу атын жана ÑырÑөзүн кириңиз. +message.error.during.file.transfer= Файлды жөнөтүүдө ката чыкты. +message.file.exists.question= Мындай файл бар. Ò®Ñтүнөн жазылÑынбы? +message.file.size=Файлдын өлчөмү: {0} +message.file.transfer.canceled=Ð’Ñ‹ отменили приём файла. +message.file.transfer.chat.window=Файл жөнөтүү талабы: +message.file.transfer.notification=Файлды жөнөтүү ÑÑкертүүÑÒ¯ +message.file.transfer.rejected= {0} файл жиберүүнү таÑтыктаган жок. +message.file.transfer.short.message= Ñизге файлды жиберип жатат: +message.find.conference.services=ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ñ ÐºÑ‹Ð·Ð¼Ð°Ñ‚Ñ‚Ð°Ñ€Ñ‹Ð½ издөө +message.forbidden.error=Сервер жетүү катаÑын билдирди. +message.gateway.nickname.error=Такма Ñ‹Ñымы көрÑөтүлүшү керек. +message.gateway.password.error=СырÑөз көрÑөтүлүшү керек. +message.gateway.username.error=Колдонуучу аты көрÑөтүлүшү керек. +message.general.error={0} Ñебебинен Ñервер менен туташуу жоголуп кетти. +message.generic.reconnect.message=Сервер менен туташуу жоголуп кетти. Кайра туташуу үчүн «Кайрадан туташуу» баÑкычын баÑыңыз. +message.groupchat.require.password=Бул чат группаÑÑ‹ кирүүгө ÑырÑөздү талап кылат. +message.idle.for={0} активдүү ÑÐ¼ÐµÑ +message.image.too.large=Сүрөт өтө чоң. 16k же кичинекей Ñүрөттү көрÑөтүңүз. +message.invalid.jabber.id=Туура ÑÐ¼ÐµÑ Jabber ID +message.invalid.jid.error= JID некорректный. +message.invalid.status= Туура ÑÑ‚Ð°Ñ‚ÑƒÑ ÐºÐ°Ð±Ð°Ñ€Ð»Ð°Ð¼Ð°Ñын кириңиз. +message.invalid.username.password=Колдонуучу аты же ÑырÑөз туура ÑмеÑ. +message.invite.to.groupchat={0} чат группаÑына чакырып жатат. +message.invite.users.to.conference=Колдонуучуларды ÐºÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ñ Ð±Ó©Ð»Ð¼Ó©Ñүнө чакыруу. +message.is.shared.group= {0} бул бөлүштүрүлгөн групп. +message.is.typing.a.message= {0} жазып жатат... +message.join.conference.room=ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ñ Ð±Ó©Ð»Ð¼Ó©Ñүнө кирүү +message.kicked.error= Сиз бөлмөдөн {0} айдап ÑалалбайÑыз. +message.last.message.received={0} акыркы кабарлама алынды +message.loading.please.wait=Жүктөлүү. Күтө туруңуз... +message.locked.workstation= Колдонуучу компьютерди кулупталган. +message.name.of.group=Группанын аты +message.name.of.search.service.question=Издөө кызматынын аты? +message.negotiate.file.transfer= Файлды жиберүү үчүн туташуу орнотулуп жатат. Күтө туруңуз... +message.negotiate.stream= Туташуу орнотулуп жатат. Күтө туруңуз... +message.negotiation.file.transfer={0} файлды жиберүү үчүн туташуу орнотулуп жатат. Күтө туруңуз... +message.new.message={0} колдонуучудан жаңы кабарлама. +message.new.spark.available= {0} бар. Орнотуу? +message.nickname.in.use= Такма Ñ‹Ñымы бош ÑмеÑ. БашкаÑын тандаңыз +message.no.avatar.found= Ðватар табылган жок. +message.no.caller.id= Caller ID табылган жок. +message.no.description.available=КыÑкача маалымат табылган жок +message.no.history.found=Бул колдонуучу үчүн Ñүйлөшүү тарыхчаÑÑ‹ жок. +message.no.results.found=Эч нерÑе табылган жок. +message.no.room.to.join.error=Кирүүгө Ñч кандай бөлмө жок +message.no.subject.available=Эч кандай тема жок +message.no.updates=Эч кандай жаңылоолор жок +message.normal=Жөнөкөй кабарлама +message.number.to.call=Терүү үчүн номерди көрÑөтүңүз +message.offline= Пользователь получит ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ ÐºÐ¾Ð³Ð´Ð° подключитÑÑ. +message.offline.error=Эгерде бул колдонуучу тармакта ÑÐ¼ÐµÑ Ð±Ð¾Ð»Ð³Ð¾Ð½Ð´Ð¾, анда ал кабарламаларды кабыл албайт. +message.participants.in.room=Бөлмөдө катышуучулар +message.password.error=СырÑөздү кириңиз. +message.password.private.room.error=Жеке бөлмө үчүн ÑырÑөздү көрÑөтүңүз +message.passwords.no.match= СырÑөздөр туура келген жок. +message.please.join.in.conference= Сураныч, конференциÑга кошулуңуз. +message.plugins.not.available= Плагин булагына туташылган жок. +message.prompt.plugin.uninstall= {0} алып ÑалынÑынбы? +message.received.file={0} колдонуучудан файлды алдыныз. +message.receiving.file={0} колдонуучудан файлды алып жатаÑыз +message.reconnect.attempting=Ðракеттенүү... +message.reconnect.failed=Кайрадан туташуу ийгиликÑиз аÑктады. +message.reconnect.wait={0} Ñекунд ичинде кайрадан туташуу. +message.register.transports=Бар болгон транÑпортторду каттоо. +message.registering={0} катталып жатат. Күтө туруңуз... +message.registration.transport.failed=Катталуу мүмкүн ÑмеÑ. +message.restart.required=Өзгөртүүлөр ишке кирүүÑÒ¯ үчүн Spark программаÑын кайрадан баштоо керек Кайрадан башталÑынбы? +message.restart.spark.changes= Плагин Spark программаÑÑ‹ кийинки жолу кайрадан башталганда алынып Ñалынат. +message.restart.spark.to.install= Жаңы верÑиÑны орнотуу үчүн Spark программаÑын жабуу керек. Ðзыр жабылÑынбы? +message.room.creation.error=Бөлмө түзүлгөн жок. +message.room.destroyed=Бөлмө көрÑөтүлгөн Ñебеби менен бузулду: {0} +message.room.destruction.reason= Бөлмөнүн бузулуш Ñебеби? +message.room.information.for={0} бөлмө маалыматы +message.save.profile= Профилдин өзгөрүүлөрүн Ñактоо үчүн «Сактоо» баÑкычын баÑыңыз. +message.search.for.contacts=Контакттарды табуу. +message.search.for.other.people=Серверде адамдарды издөө. +message.search.service.not.available=Издөө кызматы менен туташуу жок. +message.searching.please.wait=Изделип жатат. Күтө туруңуз... +message.select.add.room.to.add=Бөлмөнү Ñиздин кызматтар тизмеÑине кошуу үчүн тандаңыз. +message.select.one.or.more=Бирди же бир нече колдонуучуну тандаңыз. +message.select.room.to.enter=Кирүү үчүн бөлмөнү тандаңыз. +message.select.room.to.join=Кошулуу үчүн бөлмөнү тандаңыз. +message.send.a.broadcast=Көптүк кабарламаны жөнөтүү +message.send.file.to.user=Файлды бул колдонуучуга жөнөтүү. +message.send.picture= Экран Ñүрөтүн көчүрүү жана жөнөтүү. +message.send.to.these.people=Бул колдонуучуларга жөнөтүү +message.sending.file.to={0} үчүн файл жиберилип жатат. +message.sent.offline.files= You have just been sent offline file(s). +message.server.unavailable=Сервер менен туташылган жок: Ñервердин аты туура ÑÐ¼ÐµÑ Ð¶Ðµ Ñервер менен туташуу мүмкүн ÑмеÑ. +message.service.already.exists=Кызмат алда качан кошулган. +message.shared.group=Бөлүштүрүлгөн группа +message.specify.contact.jid= Контакттын JID белгиÑин көрÑөтүңүз (миÑалы: ilyas@jabber.org) +message.specify.group=Жаңы колдонуучуну кошуу үчүн группаны көрÑөтүңүз. +message.specify.information.for.conference=ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ñ Ð±Ó©Ð»Ð¼Ó©Ð½Ò¯Ð½ маалыматын көрÑөтүңүз. +message.specify.name.error=Туура атты киргизиңиз. +message.specify.users.to.join.conference=КонференциÑга кошулуучу колдонуучуларды көрÑөтүңүз. +message.specify.valid.time.error= Туура таймаут убакытын жана портту көрÑөтүңүз. +message.subject.change.error=Бул бөлмөдө теманы өзгөртө албайÑыз. +message.subject.has.been.changed.to=Тема өзгөрдү: {0}. +message.supply.resource=Туура реÑурÑту кириңиз. +message.supply.valid.port=Туура портту кириңиз. +message.supply.valid.timeout=Туура таймаут убакытын кириңиз. +message.timeout.error= Таймаут убакыты 5 Ñек. же андан көп болушу керек. +message.total.downloaded=Жалпы жүктөөлөр +message.transfer.cancelled=Приём файла отменён. +message.transfer.rate=Ылдамдыгы +message.transfer.refused=Файлды кабыл алуу четке кагылды. +message.transfer.waiting.on.user={0} колдонуучунун файлды кабыл алууÑу күтүлүп жатат. +message.unable.to.load.profile={0} үчүн профиль табылган жок +message.unable.to.retrieve.last.activity={0} үчүн акыркы активдүүлүк убакыты аныкталган жок. +message.unable.to.save.password= СырÑөздү өзгөртүү мүмкүн ÑмеÑ. Сервердин админиÑтраторуна кайрылыңыз. +message.unable.to.send.file={0} колдонуучуга файл жөнөтө албайÑыз. +message.unrecoverable.error=Колдонуучу аты же ÑырÑөзу туура ÑмеÑ. +message.update.room.list=Бөлмөлөр тизмеÑин жаңылоо +message.updating.cancelled= Обновление отменено. +message.user.banned= {0} колдонуучу бул бөлмөдө чектелген. +message.user.given.voice= {0} колдонуучу бул бөлмөдө Ñүйлөшүү укугуна ÑÑ Ð±Ð¾Ð»Ð´Ñƒ. +message.user.granted.admin= {0} колдонуучу админиÑтратор укуктарына ÑÑ Ð±Ð¾Ð»Ð´Ñƒ. +message.user.granted.membership= {0} колдонуучу кошумча укуктарга ÑÑ Ð±Ð¾Ð»Ð´Ñƒ. +message.user.granted.moderator= {0} колдонуучу модератор укуктарына ÑÑ Ð±Ð¾Ð»Ð´Ñƒ. +message.user.granted.owner= {0} колдонуучу бөлмө түзүү укугуна ÑÑ Ð±Ð¾Ð»Ð´Ñƒ. +message.user.is.sending.you.a.file= {0} колдонуучу Ñизге файл жөнөтүп жатат. +message.user.joined.room= {0} бөлмөгө кошулду. +message.user.kicked.from.room= {0} бөлмөдөн айдалып чыкты. +message.user.left.room= {0} бөлмөдөн чыкты. +message.user.nickname.changed= {0} колдонуучу такма Ñ‹Ñымын {1} деп өзгөрттү. +message.user.now.available.to.chat= {0} колдонуучу {1} бери тармакта +message.user.revoked.admin={0} колдонуучунун админиÑтратор укуктары алынды. +message.user.revoked.membership={0} колдонуучунун кошумча укуктары алынды. +message.user.revoked.moderator={0} колдонуучунун модератор укуктары алынды. +message.user.revoked.owner={0} колдонуучунун бөлмө түзүү укуктары алынды. +message.user.voice.revoked={0} колдонуучунун Ñүйлөө укугу алынды. +message.username.error=Колдонуучу атын киргизиңиз. +message.username.password.error=Колдонуучу аты жана/же ÑырÑөз көрÑөтүлүшү керек. +message.vcard.not.supported= Сервер VCards колдобойт. Сиздин VCard Ñакталган жок. +message.version= ВерÑиÑÑÑ‹: {0} +message.view.information.about.this.user=Колдонуучу жөнүндө маалыматты көрÑөтүү. +message.waiting.for.user.to.join={0} колдонуучу кошулууга күтүлүп жатат. +message.went.offline= {0} колдонуучу {1} бери тармата ÑÐ¼ÐµÑ +message.you.have.been.banned=Сиз бул бөлмөдөн чектелдиңиз. +message.you.have.been.kicked=Сизди бул бөлмөдөн айдап Ñалышты. +message.you.have.sent=Сиз {0} колдонуучуга файл жөнөттүңүз. +message.your.admin.granted= Сизге админиÑтратор укуктары берилди. +message.your.banned= Сиз бул бөлмөдөн чектелдиңиз. +message.your.kicked={0} Ñизди айдап Ñалды. +message.your.membership.granted=Сизге кошумча укуктар берилди. +message.your.membership.revoked= Сизден кошумча укуктар алынды. +message.your.moderator.granted= Сизге модератор укуктары берилди. +message.your.moderator.revoked= Сизден модератор укуктары алынды. +message.your.ownership.granted= Сизге бөлмө түзүү укуктары берилди. +message.your.ownership.revoked= Сизден бөлмө түзүү укуктары алынды. +message.your.revoked.granted= Сизден админиÑтратор укуктары алынды. +message.your.voice.granted= Сизге Ñүйлөө укугу берилди. +message.your.voice.revoked= Сизден Ñүйлөө укугу алынды. +no= Жок +not.registered= Катталбаган +occupants= Катышуучулар +offline=Тармакта ÑÐ¼ÐµÑ +## +ok= OK +online=тармакта +open= Ðчуу +open.folder= Папканы ачуу +participants=Катышуучулар +reject= Четке кагуу +retry= Кайталоо +room.name= Бөлмөнүн аты +save= Сактоо +status.away=Орунда ÑÐ¼ÐµÑ +status.custom.messages=Жөнөкөй текÑÑ‚ +status.do.not.disturb=Тынчымды алба +status.extended.away=Кеңейтилген «Орунда ÑмеÑ» +status.free.to.chat=Сүйлөшүүгө даÑÑ€ +status.on.phone=Телефондо +status.online=Тармакта +status.pending=Күтүлүүдө +subject= Тема +tab.available.plugins=Бар болгон плагиндер +tab.avatar=Ðватар +tab.business= Жумуш +tab.conferences= КонференциÑлар +tab.contacts= Контакттар +tab.general=Ðегизги +tab.home= Үй +tab.installed.plugins=Орнотулган плагиндер +tab.personal=Жеке +tab.pki=PKI +tab.proxy= Proxy +tab.sso=SSO +title.about=Программа жөнүндө +title.account.create.registration= Колдонуучу атын каттоо +title.account.created= Колдонуучу аты түзүлдү +title.add.contact= Добавит контакт +title.add.contact.group=Группаны кошуу +title.add.new.group=Жаңы группаны кошуу +title.add.search.service=Издөө кызматын кошуу +title.add.to.roster=Контакт тизмеÑине кошуу +title.address= ÐÐ´Ñ€ÐµÑ +title.advanced.connection.preferences= Кошумча туташуу ыраÑтоолору +title.advanced.connection.usesso= &Single Sign-On (SSO) via GSSAPI колдонуу +title.alert=Көңүл буруңуз +title.appearance=Көрүнүш +title.appearance.preferences=Көрүнүш ыраÑтоолору +title.appearance.showVCards=Контакт тизмеÑинде VCard көрÑөтүү +title.available.transports=Бар болгон транÑпорттор +title.bookmarks=ЭÑбелгелер +title.broadcast.message=Көптүк кабарлама +title.browse.conference.services=ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ñ ÐºÑ‹Ð·Ð¼Ð°Ñ‚Ñ‚Ð°Ñ€Ð´Ñ‹Ð½ тизмеÑи +title.browse.room.service=КонференциÑлар тизмеÑи - {0} +title.cancelled=Калтырылды +title.change.nickname=Такма Ñ‹Ñымды алмаштыруу +title.change.subject=Теманы алмаштыруу +title.chat=Чат +title.choose.directory=Каталогду тандаңыз +title.choose.incoming.sound=Келүүчү чалуу үчүн үндү тандаңыз +title.choose.offline.sound=«Тармакта ÑмеÑ» үнүн тандаңыз +title.choose.outgoing.sound= Чалуу үнүн тандаңыз +title.client.logs=Клиент логдору +title.conference.invitation=КонференциÑга чакыруу +title.conference.rooms=ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ñ Ð±Ó©Ð»Ò¯Ð¼Ð´Ó©Ñ€Ò¯ +title.configure.chat.room=Бөлмө ыраÑтоолору +title.configure.room=Бөлмөнү ыраÑтоо +title.confirmation=ТаÑтыктоо +title.create.new.account= Жаңы колдонуучу атын түзүү +title.create.or.bookmark.room= Кирүү же бөлмөнү ÑÑбелерге кошуу +title.create.room=Түзүү +title.create.problem= Колдонуучу атын түзүүдө кыйынчылыктар чыкты +title.delete.file=Сиз файлды өчүрүүнү каалайÑызбы? +title.dial.phone=Телефонго чалуу +title.disable.transport= Колдонуучу маалыматтарын өчүрүү +title.download.complete=Жүктөө аÑкталды +title.downloading.im.client=IM клиентти жүктөө +title.downloads=Жүктөөлөр +title.edit.custom.message=Жөнөкөй ÑтатуÑтарды ондоо +title.edit.profile=Профилди ондоо +title.enter.reason=Себепти кириңиз +title.error=Ката +title.error.couldnot.open.file=Файл ачылган жок! Балким файл тиби белгиÑиз! +title.error.delete.file=Файл өчүрүлгөн жок! +title.error.find.app=Туш келген программа табылган жок! +title.error.rename.file=Файлдын аты алмаштырылган жок! +title.facebook.registration= Facebook маалыматтары +title.file=Файл +title.file.exists= Файл алда качан бар +title.file.transfer=Файл жөнөтүү +title.file.transfer.preferences= Файл жөнөтүү ыраÑтоолору +title.filesize=Файл өлчөмү +title.find.conference.service=ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ñ ÐºÑ‹Ð·Ð¼Ð°Ñ‚Ñ‚Ð°Ñ€Ñ‹Ð½ табуу +title.find.contacts=Контакт табуу +title.gadugadu.registration= GaduGadu маалыматтары +title.general.chat.settings=Ðегизги чат ыраÑтоолору +title.general.media=ÐœÐµÐ´Ð¸Ñ Ñ‹Ñ€Ð°Ñтоолору +title.group.chat=Группалык чат +title.group.chat.settings=Группалык чат ыраÑтоолору +title.history.for={0} Ñүйлөшүү тарыхы +title.incoming.call= Жаңы чалуу +title.input.fileexplorer=Файл аралагыч атын киргизиңиз: +title.input.newname=Жаңы атын киргизиңиз: +title.input.openwith=Программа жардамы менен ачуу үчүн программанын атын киргизиңиз: +title.invite.to.conference=КонференциÑга чакыруу +title.irc.registration= IRC маалыматтары +title.jabber.browser=Ðралагыч +title.join.conference.room=КонференциÑга кошулуу +title.last.activity=Ðкыркы активдүүлүгү +title.login=Байланыш +title.login.error=Кирүү катаÑÑ‹ +title.login.settings= Колдонуучу кирүү ыраÑтоолору +title.lookup.profile=Профилдин көрүнүшү +title.myspace.registration= MySpace маалыматтары +title.name=Ðты +title.new.client.available= Жаңы клиент бар +title.new.roster.group=Жаңы группа +title.new.version.available= Жаңы верÑиÑÑÑ‹ бар +title.no.updates=Жаңылоолор жок +title.notes=ЭÑкертмелер +title.notification= ЭÑкертүү +title.notifications=ЭÑкертүүлөр +title.occupants=Катышуучулар +title.on.the.phone=Телефондо +title.password=СырÑөз +title.password.required=СырÑөз талап кылынат +title.passwords.no.match= СырÑөздөрдү кайрадан кириңиз. +title.person.search=Ðдамдарды издөө +title.plugins= Плагиндер +title.preferences=ЫраÑтоолор +title.profile.information=Профиль маалыматы +title.profile.not.found= Профиль табылган жок +title.qq.registration= QQ маалыматтары +title.register.account= Жаңы колдонуучу атын каттоо +title.registration.error= Каттоо катаÑÑ‹ +title.reminder= ЭÑтетүү +title.rename.roster.group= Группанын атын алмаштыруу +title.room.destroyed= Бөлмө бузулду +title.room.information= Бөлмө маалыматы +title.roster=Контакт тизмеÑи +title.sametime.registration= Sametime маалыматтары +title.select.file.to.send=Файлды тандоо +title.set.status.message=СтатуÑту орнотуу +title.simple.registration=SIMPLE маалыматтары +title.sound.preferences=Үндөр ыраÑтоолору +title.sounds=Үндөр +title.spark.preferences=Spark ыраÑтоолору +title.start.chat=Чатты баштоо +title.status.message= Ð¡Ñ‚Ð°Ñ‚ÑƒÑ +title.task.notification=Тапшырма ÑÑтетүүÑÒ¯ +title.tasks=Тапшырмалар +title.transports= ТранÑпорттор +title.tray.information=Трей маалыматы +title.upgrading.client=IM клиентти жаңылоо +title.version.and.time= ВерÑиÑÑÑ‹ жана убакыты +title.view.bookmarks= ЭÑбелгелерди көрÑөтүү +title.view.profile.for={0} профили +title.view.room.information=ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ñ Ð¼Ð°Ð°Ð»Ñ‹Ð¼Ð°Ñ‚Ñ‹ +title.waiting.to.call=Чалуу күтүлүүдө +title.xmpp.registration= XMPP маалыматтары +tooltip.appearance=Сүйлөшүү көрүнүшүн өзгөртүү. +tooltip.file.transfer=Файл жөнөтүү ыраÑтоолору. +tooltip.notifications= Келген чаттар үчүн билдирүү ыраÑтоолору. +tooltip.place.a.call=Колдонуучуга чалуу +tooltip.place.voice.call=Колдонуучуга телефон чалуу. +tooltip.send.email=e-mail жөнөтүү. +tooltip.start.chat=Сүйлөшүүнү баштоо. +tooltip.view.changelog=Өзгөрүүлөр тарыхын көрÑөтүү +tooltip.view.history=Сүйлөшүү тарыхын көрÑөтүү +tooltip.view.readme=ReadMe көрÑөтүү +tree.conference.services=ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ñ ÐºÑ‹Ð·Ð¼Ð°Ñ‚Ñ‚Ð°Ñ€Ñ‹ +tree.users.in.room=Бөлмөдө колдонуучулар +unfiled=Толтурулбаган +use.default= Ðлыднала +user.has.signed.in= кирди. +user.has.signed.off= чыкты. +while.offline=Тармакта ÑÐ¼ÐµÑ ÑƒÐ±Ð°ÐºÑ‹Ñ‚Ñ‹Ð½Ð´Ð° +yes= Ооба diff --git a/core/src/main/resources/i18n/spark_i18n_lt.properties b/core/src/main/resources/i18n/spark_i18n_lt.properties new file mode 100644 index 000000000..f7383424a --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_lt.properties @@ -0,0 +1,960 @@ +accept = Priimti +is.active = Aktyvu +add = PridÄ—ti +administrator = Administratorius +answer = Atsakymas +apply = Taikyti +available = Prieinamas +broadcast = Transliavimas +cancel = AtÅ¡aukti +delete = IÅ¡trinti +details = Detaliau +close = Užverti +create = Sukurti +date = Data +description = Pavadinimas +from = SiuntÄ—jas +invite = Pakviesti +join = Prisiju&ngti +no = Ne +not.registered = Neregistruota +occupants = Lankytojų sk.: +offline = AtsijungÄ™s +ok = Gerai +online = PrisijungÄ— +open = Atverti +open.folder = Atverti aplankÄ… +participants = Dalyviai +reject = Atmesti +retry = Pakartoti +room.name = Kambario vardas +save = Ä®raÅ¡yti +subject = Tema +unfiled = Jokioje grupÄ—je +use.default = Naudoti kaip numatyta +user.has.signed.in = PrisijungÄ— +user.has.signed.off = AtsijungÄ— +while.offline = Kol atsijungÄ™s +yes = Taip + +action.clear = Valyti +action.copy = Kopijuoti +action.cut = IÅ¡kirpti +action.paste = Ä®klijuoti +action.print = Spausdinti +action.save = Ä®raÅ¡yti +action.select.all = ŽymÄ—ti viskÄ… + +button.accept = &Priimti +button.reject = &Atmesti +button.add = P&ridÄ—ti +button.add.a.contact = PridÄ—ti &adresatÄ… +button.add.bookmark = PridÄ—ti žymÄ… +button.add.service = PridÄ—ti &tarnybÄ… +button.add.user = PridÄ—ti a&bonentÄ… +button.add2 = Pri&dÄ—ti +button.advanced = Nustaty&mai +button.approve = Pa&tvirtinti +button.bookmark.room = PasižymÄ—ti kambarį +button.browse = &NarÅ¡yti… +button.browse2 = N&arÅ¡yti… +button.browse3 = Na&rÅ¡yti… +button.cancel = &AtÅ¡aukti +button.cert.info = Detaliau +button.clear = &Valyti +button.close = Užverti +button.copy.to.clipboard = Kopijuoti iÅ¡karpinÄ—n +button.create.account = Paskyros &sukÅ«rimas +button.create.room = Sukurti arba prisijungti &kambarį +button.decline = &Atmesti +button.deny = &Nepriimti +button.dial.number = Numeris &skambinimui +button.find = &IeÅ¡koti +button.join = P&risijungti +button.join.room = Prisijungti prie pasirinktojo &kambario +button.login = P&risijungti +button.new = &Nauja +button.profile = &Profilis +button.quit = &Baigti +button.reconnect = &Prisijungti iÅ¡ naujo +button.reconnect2 = Prisijungti iÅ¡ naujo +button.refresh = &Atnaujinti +button.register = &Registruoti +button.remove.bookmark = PaÅ¡alinti žymÄ… +button.roster = &SÄ…raÅ¡as +button.save = Ä®&raÅ¡yti +button.save.for.future.use = Ä®raÅ¡yti paskesniam &naudojimui +button.search = IeÅ¡koti +button.send = Siųsti +button.send.email = PaÅ¡tas +button.start.chat = Pokalbis +button.tasks.active = Aktualios +button.tasks.all = Visos +button.unset.file.explorer = Nustatyti bylų peržiÅ«rÄ… iÅ¡ naujo +button.update = &Atnaujinti +button.view.notes = PeržiÅ«rÄ—ti užraÅ¡us +button.view.profile = PeržiÅ«rÄ—ti profilį +button.view.tasklist = PeržiÅ«rÄ—ti užduotis +button.re.detect = &Aptikti iÅ¡ naujo +button.check.validity = Patikrint galiojimÄ… +button.show.certificate = Parodyti sertifikatus + + +table.column.certificate.subject = Subjektas +table.column.certificate.validity = Galiojimas +table.column.certificate.exempted = Atleistas + +checkbox.allow.buzz = &Leisti paÅ¡nekovams purtyti jÅ«sų pokalbio langÄ… +checkbox.auto.discover.port = &Automatinis serverio ir jo prievado aptikimas +checkbox.auto.login = A&utomatiÅ¡kai prisijungti +checkbox.login.as.invisible = &Prisijungti nematomam +checkbox.login.anonymously = Prisijungti anoni&miÅ¡kai +checkbox.disable.chat.history = IÅ¡j&ungti pokalbių žurnalÄ… +checkbox.sort.asc.history = Rūšiuo&ti žinutes kontakto istorijoje datos didÄ—jimo tvarka +checkbox.disable.prev.chat.history = &IÅ¡jungti ankstesnių pokalbių rodymÄ… +checkbox.enable.emoticons = &Rodyti jaustukus +checkbox.graying.out = Užpilkinti neaktyvius adresatus (reikalingas perkrovimas) +checkbox.idle.enabled = Ä®jungti neveikos rodymÄ… +checkbox.launch.on.startup = Paleisti startavus +checkbox.reconnect.info = Nurodyti pakartotino prisijungimo rodymÄ…: +checkbox.reconnect.panel.big = Rodyti kaip PanelÄ™ +checkbox.reconnect.panel.small = Rodyti adresatų grupÄ—je +checkbox.reconnect.panel.icon = Rodyti kaip ikonÄ… +checkbox.notify.user.comes.online = Rodyti kito prisijungimÄ… +checkbox.notify.user.goes.offline = Rodyti kito atsijungimÄ… +checkbox.notify.typing.systemtray = Sistemos juostelÄ—je rodyti kada raÅ¡oma +checkbox.notify.systemtray = Naujų žinuÄių rodymas sistemos juostelÄ—je +checkbox.permanent = &Kambarys ilgam +checkbox.play.sound.on.invitation = Pagroti gavus pakvieti&mÄ… +checkbox.play.sound.on.new.message = Pagroti &gavus naujÄ… žinutÄ™ +checkbox.play.sound.on.outgoing.message = Pagroti &iÅ¡siunÄiant žinutÄ™ +checkbox.play.sound.when.offline = Pagroti, kai kitas &atsijungia +checkbox.private.room = Priva&tus Kambarys +checkbox.save.password = Ä®s&iminti slaptažodį +checkbox.show.avatars.in.contactlist = Adresų sÄ…raÅ¡e rodyti ps&eudoportretus +checkbox.show.notifications.in.conference = &Rodyti praneÅ¡imus konferencijų kambariuose +checkbox.show.time.in.chat.window = P&okalbio lange rodyti laikÄ… +checkbox.show.toaster = Rodyti iššokantį praneÅ¡imÄ… +checkbox.disable.asterisk.toaster = IÅ¡jungti skambuÄio iššokantį praneÅ¡imÄ… +checkbox.split.chat.window = Lango įt&virtinimas (reikÄ—s iÅ¡ naujo paleisti programÄ…) +checkbox.start.in.tray = &Startuoti sistemos juostelÄ—je +checkbox.click.single.tray = Vie&nas paspaudimas sistemos juostelÄ—je pakelia Spark langÄ… (reikÄ—s iÅ¡ naujo paleisti programÄ…) +checkbox.tabs.on.top = &Pokalbių korteles rodyti virÅ¡uje (reikÄ—s iÅ¡ naujo paleisti programÄ…) +checkbox.tabs.scroll = Naudokite slinktį pokalbių skirtukams (reikÄ—s iÅ¡ naujo paleisti programÄ…) +checkbox.use.compression = Nau&doti suspaudimÄ… +checkbox.use.debugger.on.startup = S&tartavus įjungti klaidų paieÅ¡kos veiksenÄ… +checkbox.use.proxy.server = Na&udoti tarpinį serverį +checkbox.use.system.look.and.feel = Naudoti operacinÄ—s sistemos iÅ¡vaizdÄ… (reikÄ—s iÅ¡ naujo paleisti programÄ…) +checkbox.window.to.front = &IÅ¡kelti praneÅ¡imo langÄ… į ekrano priekį +checkbox.broadcast.hide.offline.user = SlÄ—pti atsijungusius +checkbox.use.krbconf = Naudoti krb5.conf ir krb5.ini bylas +checkbox.use.krb.dns = Naudoti sriÄių vardų serverį (DNS) +checkbox.use.specify.below = ApibÅ«dinimas žemiau +checkbox.use.pki.authentication = &PKI autentifikavimo naudojimas +checkbox.transport.tab.setting = Rodyti prieinamus ryÅ¡io kanalus kortelÄ—je (reikalingas perkrovimas) +checkbox.conference.tab.setting = Rodyti grupinių pokalbių tarnybÄ… kortelÄ—je (reikalingas perkrovimas) +checkbox.use.hostname.as.resource = Na&udoti kompiuterio vardÄ… kaip resursÄ… +checkbox.use.version.as.resource = Naudot&i Spark versijÄ… kaip resursÄ… +checkbox.accept.all.certificates = Priimti visus sertifikatus (self-signed/negaliojantys/nepatikimi) +checkbox.disable.hostname.verification = IÅ¡jungti sertifikato vardo patikrinimÄ… (nerekomenduojama) +checkbox.accept.all = Priimti visus +checkbox.accept.expired = Priimti su pasibaigusia galiojimo data +checkbox.accept.not.valid.yet = Priimti dar negaliojanÄius +checkbox.accept.self.signed = Priimti "self-signed" +checkbox.accept.revoked = Priimti atÅ¡auktus +checkbox.check.crl = Patikrinti CRL +checkbox.check.ocsp = Patikrinti OCSP +checkbox.allow.soft.fail = Leisti "soft fail" politikÄ… +checkbox.on.exception.list = IÅ¡imÄių sÄ…raÅ¡e +checkbox.filetransfer.ibb.only = Naudoti tik In-Band Bytestreams +checkbox.close.unread.message = PrieÅ¡ uždarydami langÄ… paklauskite, ar yra neskaitytų praneÅ¡imų +radio.encryptionmode.required = Privaloma +radio.encryptionmode.ifpossible = Jeigu įmanoma +radio.encryptionmode.disabled = IÅ¡jungta + +delete.log.permanently = VisiÅ¡kas žurnalo paÅ¡alinimas +delete.permanently = Galutinai paÅ¡alinti? + +gateway.username.password.error = ReikÄ—s pateikti abonento vardÄ… ir/arba slaptažodį + +group.chat.window.information = Pokalbio lango informacija +group.comma.delimited = Atskirta kableliu +group.conferences.found = Atrasta konferencijų tarnyba +group.connection = Jungtis +group.empty = Prisijungusių Å¡ioje grupÄ—je nÄ—ra +group.general.information = Bendra informacija +group.login.information = Prisijungimo informacija +group.notification.options = PraneÅ¡imų nuostatos +group.offline = Atsijungusiųjų grupÄ— +group.search.form = PaieÅ¡kos anketa +group.search.results = PaieÅ¡kos rezultatai +group.chat.name.notification = Apie jus kalba… +group.chat.name.match = JÅ«sų vardÄ… paminÄ—jo grupiniame pokalbyje: +group.encryption_mode = Å ifravimo veiksena + +label.na = nÄ—ra iraÅ¡o +label.cell = Mobilus nr. +label.work = Darbinis nr. +label.home = Namų nr. +label.accounts = Pas&kyros +label.add.conference.service = &Konferencijų tarnybos pridÄ—jimas +label.add.jid = &Pakviesti ir +label.add.task = Pridedama užduotis +label.auto.login = &Automatinis prisijungimas +label.available.users.in.roster = &Galimi partneriai visame sÄ…raÅ¡e +label.avatar = Pseudoportretas: +label.broadcast.history.search.date = PaieÅ¡kos data (metai-mÄ—n): +label.cancel = AtÅ¡aukti +label.change.password.to = Ä®r&aÅ¡ykite naujÄ… slaptažodį +label.chatroom.fontsize = Pokalbių kambario Å¡riftas: +label.chatroom.maxcurrenthistorysize = Maksimalus dabartinÄ—s istorijos dydis: +label.city = &Miestas +label.close = &Užverti +label.company = &Organizacija +label.confirm.password = &Slaptažodis pakartotinai +label.conflict.error = Negalima prisijungti, nes jau prisijungta. +label.contact.to.find = Rasti pokalbio partnerį +label.recent.conversation = Paskutiniai pokalbiai +label.frequent.contacts = Dažni pokalbių partneriai +label.contactlist.avatarsize = Pseudoportreto dydis: +label.contactlist.fontsize = Adresų Å¡rifto dydis: +label.country = Å a&lis +label.create.account = Sukurti paskyrÄ… +label.department = &Skyrius +label.dial = &Skambinti +label.display.time = Rodymo laikas: +label.downloads = Siuntos +label.due = Iki +label.email.address = PaÅ¡to &adresas +label.emoticons = &Jaustukai +label.enter.address = KalbÄ—sim su adresatu: +label.enter.group.name = Naujos grupÄ—s įvedimas +label.fax = &Faksas +label.find = &IeÅ¡koti +label.first.name = &Vardas +label.group = &GrupÄ— +label.host = S&erveris +label.invited.users = Pakviestieji +label.jabber.address = &Jabber adresas +label.jabber.id = &Jabber ID +label.jid = &JID +label.job.title = &Pareigos +label.last.name = Pa&vardÄ— +label.local.time = &Vietinis laikas +label.message = Žinu&tÄ— +label.message.style = ŽinutÄ—s &stilius +label.middle.name = &Antras vardas +label.minutes.before.stale.chat = Po &kiek minuÄių neaktyvus kambarys pasidaro blankus +label.mobile = &Mobilaus tel. nr. +label.name = &Vardas +label.network = Tin&klas +label.new.nickname = Naujas pseudonimas +label.nickname = Pseu&donimas +label.number = &Numeris +label.ok = Gerai +label.old.ssl = &Naudoti Direct TLS metodÄ… +label.os = &OperacinÄ— sistema +label.pager = PraneÅ¡imų &gaviklis +label.password = S&laptažodis +label.phone = &Telefonas +label.port = P&rievadas +label.postal.code = PaÅ¡to &kodas +label.presence = &BÅ«sena +label.priority = Prioritetai +label.protocol = &Protokolas +label.received = &Gautas +label.rename.to = Pervardyti į +label.resource = &Resursas +label.response.timeout = R&eakcijos laikas (sek.) +label.reconnect.delay = Prisijungimo bandymų intervalas (sek.) (reikalingas perkrovimas) +label.room = &Kambarys +label.room.name = &Kambario vardas +label.room.topic = Kambario pokalbio tema +label.search = IeÅ¡koti +label.search.service = &IeÅ¡kos paslauga +label.seconds = sekundÄ—s +label.server = Do&menas +label.server.address = &Serverio adresas +label.show = Rodomos: +label.software = &PrograminÄ— įranga +label.state.and.province = &Valstija/Rajonas +label.street.address = &PaÅ¡to adresas +label.time = Laikas: {0} +label.time.till.idle = Neveikos laikas &iki abonentas dar laikomas aktyviu (min.) +label.time.till.idlemessage = PasitraukÄ™s nuo kompiuterio +label.timeformat = Laiko formatas {0} +label.transfer.download.directory = &Parsiuntimo vieta: +label.transfer.timeout = &Kiek laukti siuntimo patvirtinimo (min.): +label.unable.to.add.contact = Nepavyko pridÄ—ti adresato. +label.use.default = Naudoti numatytÄ… +label.user.on.public.network = Abonentas yra vieÅ¡ajame tinkle +label.username = &Abonento vardas +label.version = &Versija +label.web.page = &Tinklalapis +label.xmpp.port = &XMPP prievadas +label.krb.realm = Realm +label.krb.kdc = KDC +label.which.pki.method = Kuris PKI metodas? +label.choose.file = Pasirinkti bylÄ… +label.trust.store.password = Patikimų sertifikatų saugyklos slaptažodis +label.enter.password = Ä®vesti slaptažodį +label.move.focus.forwards = Fokusas pirmyn +label.move.focus.backwards = Fokusas atgal +label.keystore.location = Raktų saugyklos vieta +label.truststore.location = Patikimų sertifikatų saugyklos vieta +label.pkcs.library.file = PKCS#11 bibliotekos byla +label.x509.certificate = X.509 sertifikatas +label.apple.keychain = Apple KeyChain +label.add.to.roster = PridÄ—ti abonentÄ… į adresatų sÄ…rašą +label.audio.device = &Garso įrenginys +label.video.device = &Vaizdo įrenginys +label.certificate.version = Versija +label.certificate.serial.number = Serijinis numeris +label.certificate.signature.value = ParaÅ¡o reikÅ¡mÄ— +label.certificate.signature.algorithm = ParaÅ¡o algoritmas +label.certificate.issuer = Emitentas +label.certificate.subject = Subjektas +label.certificate.not.before = Negalioja iki +label.certificate.not.after = Negalioja po +label.certificate.public.key = VieÅ¡asis raktas +label.certificate.public.key.algorithm = VieÅ¡ojo rakto algoritmas +label.certificate.issuer.unique.id = Emitento unikalus ID +label.certificate.subject.unique.id = Subjekto unikalus ID +label.certificate.add.certificate.to.truststore = PridÄ—ti sertifikatÄ… į Truststore +label.certificate.status = Sertifikato bÅ«sena + +menuitem.about = Apie +menuitem.actions = Veiksmai +menuitem.bookmarks = ŽymÄ—s +menuitem.add = PridÄ—ti +menuitem.add.as.contact = PridÄ—ti kaip adresatÄ… +menuitem.add.contact = PridÄ—ti adresatÄ… +menuitem.add.contact.group = PridÄ—ti adresatų grupÄ™ +menuitem.add.groupchat.myname = IÅ¡ryÅ¡kinti mano vardÄ…, kai apie jį užsimena kiti +menuitem.add.groupchat.mytext = IÅ¡ryÅ¡kinti mano tekstÄ…, kai kÄ… nors raÅ¡au +menuitem.add.groupchat.popname = Parodyti iššokantį praneÅ¡imÄ…, kai kas nors mane pamini +menuitem.add.groupchat.showjoinleavemessage = Rodyti informacijÄ… apie prisijungimÄ… ir atsijungimÄ… +menuitem.add.groupchat.showrolesinsteadofstatus = Rodyti pokalbio roles vietoje bÅ«senos ikonų +menuitem.add.groupchat.auto.accept.invite = &AutomatiÅ¡kai priimti grupinio pokalbio kvietimus +menuitem.add.groupchat.random.colors = Vardams suteikiamos &atsitiktinÄ—s spalvos +menuitem.always.on.top = Visada virÅ¡uje +menuitem.alert.when.online = Informuoti, kai abonentas taps pasiekiamas +menuitem.ban = Uždrausti +menuitem.ban.user = Uždrausti abonentÄ… +menuitem.block.user = Blokuoti abonentÄ… +menuitem.broadcast.to.group = Transliuoti žiniÄ… grupei +menuitem.browse.service = Tarnybos peržiÅ«ra +menuitem.change.nickname = Keisti pseudonimÄ… +menuitem.change.subject = Keisti temÄ… +menuitem.chat = Pokalbis +menuitem.check.for.updates = IeÅ¡koti programos atnaujinimų +menuitem.connect = Failas +menuitem.contacts = Adresatai +menuitem.copy.to = Kopijuoti į grupÄ™ +menuitem.delete = PaÅ¡alinti +menuitem.delete.login.information = PaÅ¡alinti prisijungimo informacijÄ… +menuitem.destroy.room = PaÅ¡alinti kambarį +menuitem.dial = Skambinti +menuitem.edit = Redaguoti +menuitem.edit.my.profile = &Redaguoti mano profilį… +menuitem.edit.status.message = Redaguoti bÅ«senų vardus… +menuitem.enter.login.information = Prisijungimo informacijos įvedimas +menuitem.exit = IÅ¡jungti +menuitem.affiliation = Teisių priskyrimas +menuitem.grant.moderator = Paskirti prižiÅ«rÄ—toju +menuitem.grant.member = Suteikti narystÄ™ +menuitem.grant.admin = Paskirti administratoriumi +menuitem.grant.owner = Paskirti savininku +menuitem.grant.voice = Suteikti balso teisÄ™ +menuitem.help = Žinynas +menuitem.hide = SlÄ—pti +menuitem.invite.group.to.conference = Pakviesti grupÄ™ į konferencijÄ… +menuitem.invite.users = Pakviesti abonentus +menuitem.join.on.startup = Startavus automatiÅ¡kai prisijungti +menuitem.join.room = Prisijungti kambarį +menuitem.kick.user = IÅ¡praÅ¡yti abonentÄ… +menuitem.languages = Pasirinkti kalbÄ… +menuitem.logout.no.status = Atsijungti +menuitem.logout.with.status = Atsijungti nurodant priežastį +menuitem.lookup.profile = &IeÅ¡koti profilio… +menuitem.move.to = Perkelti į grupÄ™ +menuitem.online.help = „Spark“ naudotojų forumai internete +menuitem.open = Atverti +menuitem.open.with = Atverti naudojant… +menuitem.plugins = Priedai +menuitem.preferences = Nuostatos +menuitem.remove = PaÅ¡alinti +menuitem.remove.alert.when.online = PaÅ¡alinti informacijos apie prisijungimÄ… užsakymÄ… +menuitem.remove.bookmark = PaÅ¡alinti žymÄ… +menuitem.remove.from.group = PaÅ¡alinti iÅ¡ grupÄ—s +menuitem.remove.from.roster = PaÅ¡alinti iÅ¡ sÄ…raÅ¡o +menuitem.block.contact = Blokuoti abonentÄ… +menuitem.unblock.contact = Atblokuoti abonentÄ… +menuitem.remove.service = Tarnybos paÅ¡alinimas +menuitem.rename = Keisti vardÄ… +menuitem.revoke.moderator = AtÅ¡aukti prižiÅ«rÄ—tojÄ… +menuitem.revoke.voice = Atimti balsÄ… +menuitem.revoke.member = AtÅ¡aukti narystÄ™ +menuitem.revoke.admin = AtÅ¡aukti administratorių +menuitem.revoke.owner = AtÅ¡aukti savininko privilegijÄ… +menuitem.save = Ä®raÅ¡yti +menuitem.save.as = Ä®raÅ¡yti vardu… +menuitem.send.a.file = Siųsti bylÄ… +menuitem.send.a.message = Transliuoti pasirinktiems abonentams… +menuitem.set.status.message = Parinkti bÅ«seną… +menuitem.show.empty.groups = Rodyti tuÅ¡Äias grupes +menuitem.show.offline.group = Rodyti atsijungusiųjų grupÄ™ +menuitem.show.traffic = Rodyti tinklo apkrovÄ… +menuitem.sign.in = Ä®siregistruoti +menuitem.sign.in.at.login = Ä®siregistruoti prisijungiant +menuitem.sign.out = IÅ¡siregistruoti +menuitem.start.a.chat = PradÄ—ti pokalbį +menuitem.start.a.conference = PradÄ—ti konferenciją… +menuitem.status = BÅ«sena +menuitem.subscribe.to = Užsiprenumeruoti +menuitem.unban = Atblokuoti +menuitem.unblock.user = Atblokuoti abonentÄ… +menuitem.user.guide = Žinyno turinys +menuitem.view.client.version = Informacija apie naudojamÄ… programinÄ™ įrangÄ… +menuitem.view.contact.history = PeržiÅ«rÄ—ti pokalbių žurnalÄ… +menuitem.view.downloads = PeržiÅ«rÄ—ti siuntas +menuitem.view.last.activity = Paskiausių veiksmų peržiÅ«ra +menuitem.view.logs = Žurnalas +menuitem.view.profile = PeržiÅ«rÄ—ti profilį +menuitem.view.room.info = PeržiÅ«rÄ—ti informacijÄ… apie kambarį +menuitem.voice = Balsas +menuitem.show.offline.users = Rodyti neprisijungusius abonentus +menuitem.show.contact.statusmessage = Parodyti bÅ«senÄ… +menuitem.bookmark.room = PasižymÄ—ti kambarį +menuitem.refresh = Atnaujinti +menuitem.create.room = Sukurti arba aplankyti pokalbių kambarį +menuitem.expand.all.groups = Visų grupių iÅ¡skleidimas +menuitem.collapse.all.groups = Visų grupių sutraukimas +menuitem.invite.again = VÄ—l pakviesti +menuitem.chatframe.option = Parinktys +menuitem.add.groupchat.invitetobookmark = AutomatiÅ¡kai kviesti vartotojus į pažymÄ—tÄ… kambarį +menuitem.certificate.files.filter = Sertifikatų bylos (*.cer), (*.crt), (*.der) + +message.invite.to.groupchat = {0} Jus pakvietÄ— prisijungti į pokalbių grupÄ™. +message = Transliuojamas praneÅ¡imas +message.account.create = Naujos paskyros sukÅ«rimas +message.account.created = Nauja paskyra sukurta +message.account.error = Nurodykite kuriamos paskyros serverį +message.add.a.contact = PridÄ—ti adresatÄ… +message.add.conference.service = Konferencijos pridÄ—jimas +message.add.contact.to.list = AdresinÄ—s papildymas dar vienu abonentu +message.add.favorite.room = PasižymÄ—ti reikalingÄ… kambarį, arba prisijungti prie pokalbių jame +message.add.this.user.to.your.roster = PridÄ—ti šį abonentÄ… į biÄiulių sÄ…rašą +message.add.to.roster = PridÄ—ti į sÄ…rašą +message.add.user = Ar pridÄ—ti abonentÄ… į sÄ…rašą? +message.alert.notify = Ä®spÄ—jimas +message.already.exists = Tokia paskyra jau yra. Pabandykite kitÄ… vardÄ…. +message.approve.subscription = Ar Leisite abonentui {0} Jus įtraukti į jo adresinÄ™? +message.authenticating = Autentifikavimas +message.away.idle = Neaktyvus +message.bookmark.temporary.room.error = Laikini kambariai negali bÅ«ti pasižymimi. +message.broadcast.from = ŽiniÄ… transliavo {0} +message.broadcast.no.user.selected = PraÅ¡om pasirinkti bent vienÄ… adresatÄ… +message.broadcast.no.text = PraÅ¡om įvesti žinutÄ™ transliavimui +message.broadcast.message.sent = Transliuota žinia jau iÅ¡siųsta +message.broadcast.to = Ä®veskite kÄ… transliuosite gavÄ—jams {0} +message.hasbeenbroadcast.to = Transliavote Å¡iems abonentams:\n {0} +message.buzz.alert.notification = Atkreipti dÄ—mesį +message.buzz.message = {0} nori jÅ«sų dÄ—mesio +message.buzz.sent = Nusiųsti abonentui iÅ¡kvietimÄ… +message.calling = Skambinama {0} +message.came.online = {0} prisijungÄ— {1} +message.cannot.add.contact.to.shared.group = Jau bendrintos adresatų grupÄ—s papildyti negalima +message.cert.hostname.verification.failed = Nepavyko patikrinti sertifikato vardo (hostname) +message.cert.verification.failed = Nepavyko patikrinti sertifikato +message.chat.session.ended = Pokalbis baigtas {0} +message.click.to.open = Spragtelt, kad atverti +message.client.information = Kliento informacija {0} +message.close.other.chats = Užverti visus kitus pokalbius +message.close.stale.chats = Užverti nevykstanÄius pokalbius +message.close.this.chat = Užverti šį pokalbį +message.close.unread.window = Turite neskaitytų praneÅ¡imų. Ar tikrai norite uždaryti langÄ…? +message.conference.info.error = Nepavyko gauti informacijos apie konferencijÄ…. PraÅ¡om pabandyti vÄ—liau. +message.conference.service.error = Nepavyksta rasti konferencijos. +message.confirm.destruction.of.room = Å alinant kambarį, bus paÅ¡alinti ir visi jame esantys abonentai. TÄ™sti? +message.confirmation.password.error = Patvirtinkite slaptažodį. +message.connecting.please.wait = Lukterkite, jungiamasi… +message.connection.failed = Nepavyko prisijungti prie: {0}. +message.create.account = Paskyros sukurti nepavyko. +message.create.or.join.room = Sukurti arba prisijungti prie konferencijų kambario. +message.current.status = ÄŒia galima kitus informuoti apie atsijungimo priežastis. +message.default.error = Ä®vyko programos klaida. +message.delete.all.history = Ar paÅ¡alinti visus ankstesnius pokalbius? +message.delete.confirmation = Ar tikrai norite paÅ¡alinti {0}? +message.disable.transport = Ar paÅ¡alinti prisijungimo prie {0} informacijÄ…? +message.disconnected.conflict.error = Atsijungta, nes Å¡is abonentas prisijungÄ— kitoje tinklo vietoje. +message.disconnected.error = Sutrikus normaliam programos darbui teko atsijungti. +message.disconnected.group.chat.error = Atsijungta, nes sutriko normalus programos darbas. Po pakartotino prisijungimo, teks iÅ¡ naujo apsilankyti Å¡iame kambaryje. +message.disconnected.shutdown = Atsijungta, nes kažkodÄ—l pokalbių serveris buvo iÅ¡jungtas. +message.downloading = ParsiunÄiama {0} +message.downloading.spark.plug = ParsiunÄiamas „Spark“ programos priedas. +message.end.chat = Ar jau baigsite pokalbį? +message.end.conversation = Ar jau baigsite Å¡iÄ… diskusijÄ…? +message.enter.broadcast.message = Ä®raÅ¡ykite žiniÄ…, kuriÄ… transliuosite pasirinktiems abonentams. +message.enter.gadugadu = Ä®veskite „GaduGadu“ tinklo abonento vardÄ… ir slaptažodį. +message.enter.irc = Žemiau įveskite „IRC“ tinklo abonento vardÄ… ir slaptažodį. +message.enter.sametime = Žemiau įveskite „Sametime“ tinklo abonento vardÄ… ir slaptažodį. +message.enter.facebook = Žemiau įveskite „Facebook“ tinklo abonento vardÄ… ir slaptažodį. +message.enter.myspace = Žemiau įveskite „MySpace“ tinklo abonento vardÄ… ir slaptažodį. +message.enter.jabber.id = Ä®veskite „Jabber“ tinklo identifikatorių (JID) +message.enter.message.to.broadcast = Ä®veskite žiniÄ…, kuriÄ… transliuosite visam abonentų sÄ…raÅ¡ui. +message.enter.new.subject = Ä®veskite naujÄ… temÄ… +message.enter.qq = Žemiau įveskite „QQ“ tinklo numerį. +message.enter.room.password = Ä®veskite kambario slaptažodį +message.enter.simple = Žemiau įveskite „SIMPLE“ tinklo abonento vardÄ… ir slaptažodį. +message.enter.valid.jid = Ä®veskite teisingÄ… „Jabber“ tinklo identifikatorių (JID) +message.enter.xmpp = Žemiau įveskite „XMPP“ tinklo abonento vardÄ… ir slaptažodį. +message.error.during.file.transfer = DÄ—l siuntimo klaidos bylos iÅ¡siųsti nepavyko. +message.error.must.use.reserved.nick = Turite naudoti pseudonimÄ… rezervuotÄ… Å¡iam kambariui. +message.error.nickname.in.use = Pasirinktas pseudonimas jau yra panaudotas arba rezervuotas kito vartotojo. +message.error.no.permission.create.room = Neturite leidimo sukurti kambarį. +message.error.no.response = NÄ—ra atsakymo iÅ¡ serverio. +message.error.not.member = JÅ«s nesate Å¡io kambario narys. \nTam, kad prisijungti prie Å¡io kambario, reikia bÅ«ti jo nariu. +message.error.room.not.exist = Kambarys į kurį bandote įeiti neegzistuoja. +message.error.room.password.incorrect = Slaptažodis nesutapo su kambario slaptažodžiu. +message.error.unable.join.room = NeiÅ¡eina prisijungti prie kambario. +message.file.exists.question = Byla jau egzistuoja. Ar perraÅ¡yti iÅ¡ naujo? +message.file.size = Bylos dydis: {0} +message.file.transfer.canceled = AtÅ¡auktas bylos siuntimas. +message.file.transfer.rejected = Bylos siuntimo nepatvirtino {0}. +message.file.transfer.notification = Bylos siuntimo praneÅ¡imas +message.file.transfer.short.message = Jums siunÄiamas byla, kurios pavadinimas: +message.file.transfer.chat.window = Bylos persiuntimo praÅ¡ymas: +message.file.transfer.file.too.big.error = Pasirinkta byla per didelÄ—.\nMaksimalus bylos dydis {0}. Pasirinkta byla yra {1} dydžio. +message.file.transfer.file.too.big.warning = Pasirinkta byla yra labai didelÄ—.\nTÄ™sti vis tiek? +message.find.conference.services = Konferencijų suradimas +message.forbidden.error = Serveris atsiuntÄ— praneÅ¡imÄ… apie baisiÄ… klaidÄ…. Tokios netoleruosime! +message.gateway.username.error = Turi bÅ«ti pateiktas abonento vardas +message.gateway.password.error = Turi bÅ«ti pateiktas slaptažodis +message.gateway.nickname.error = Pseudonimas turi bÅ«ti pateiktas +message.general.error = Praradote ryšį su serveriu. Problemos priežastis: {0}. +message.generic.reconnect.message = Praradote ryšį su serveriu. Spragtelkite žemiau esantį mygtukÄ… „Prisijungti iÅ¡ naujo“ +message.idle.for = Neaktyvu jau {0} +message.image.small.resolution = Atvaizdo dydis mažiau nei 32x32 pikselių +message.invalid.jabber.id = Netinkamas Jabber ID. +message.invalid.jid.error = Nurodytas identifikatorius JID yra neteisingas. +message.invalid.status = Nurodykite teisingÄ… bÅ«senÄ…. +message.invalid.username.password = Netinkamas slaptažodis arba abonento vardas. +message.invite.users.to.conference = Pakvieskite į konferencijų kambarį ir kitus (nurodysite kvieÄiamojo JID arba pasirinksite jį sÄ…raÅ¡e). +message.is.shared.group = {0} yra bendrinama grupÄ—. +message.is.typing.a.message = {0} raÅ¡o… +message.join.conference.room = Prisijungti prie konferencijų kambario +message.kicked.error = JÅ«s negalite iÅ¡praÅ¡yti {0} iÅ¡ kambario. +message.last.message.received = Paskiausia žinutÄ— gauta nuo {0} +message.loading.please.wait = Kraunama. PraÅ¡om lukterti… +message.locked.workstation = Abonentas užrakino savo kompiuterį. +message.name.of.group = GrupÄ—s vardas +message.name.of.search.service.question = Koks paieÅ¡kos tarnybos vardas? +message.negotiate.file.transfer = Vyksta derybos dÄ—l bylos persiuntimo. PraÅ¡ome palaukti... +message.negotiate.stream = Vyksta derybos dÄ—l jungÄių srautų. PraÅ¡ome palaukti... +message.negotiation.file.transfer = Deramasi dÄ—l bylos persiuntimo su {0}. PraÅ¡ome palaukti... +message.new.message = Nauja žinutÄ— nuo {0}. +message.new.spark.available = {0} pasiekiamas. Ar pageidausite įdiegti? +message.nickname.in.use = Å is pseudonimas jau naudojamas. Susigalvokite kitÄ…. +message.nickname.not.acceptable = NÄ—ra Ä…jungta galimybÄ— keisti pseudonimus! +message.no.avatar.found = Pseudoportretas dar nenurodytas. +message.no.caller.id = NÄ—ra skambintojo identifikatoriaus. +message.no.description.available = Be apraÅ¡ymo. +message.no.history.found = Å iam abonentui nÄ—ra pokalbių žurnalo. +message.no.results.found = Apie paieÅ¡kos rezultatus serveris informacijos nepateikÄ—. +message.no.room.to.join.error = NÄ—ra kambario, kur bÅ«tų galima prisijungti. +message.no.subject.available = Be temos +message.no.updates = Atnaujinimų nÄ—ra +message.normal = Ä®prastas praneÅ¡imas +message.number.to.call = Nurodykite numerį skambinimui. +message.offline = ŽinutÄ—s gavÄ—jas atsijungÄ™s. ŽinutÄ™ jis gaus, kai prisijungs. +message.offline.error = NÄ—ra galimybÄ—s gauti žinuÄių atsijungus. +message.participants.in.room = Pokalbių kambario lankytojai +message.password.error = Nurodykite Å¡ios paskyros slaptažodį. +message.password.private.room.error = Nurodykite privataus kambario slaptažodį. +message.passwords.no.match = Nesutapo slaptažodžiai. +message.please.join.in.conference = KvieÄiame apsilankyti ir dalyvauti naujai sukurtame pokalbių kambaryje. +message.plugins.not.available = Nepavyksta prisijungti prie priedų saugyklos. +message.prompt.plugin.uninstall = Ar tikrai norite iÅ¡jungti priedÄ… {0}? +message.received.file = Gavote bylas, SiuntÄ—jas {0}. +message.receiving.file = Gaunate bylas. SiuntÄ—jas {0} +message.reconnect.attempting = Bandom jungtis iÅ¡ naujo… +message.reconnect.failed = Pakartotinai prisijungti nepavyko. +message.reconnect.wait = VÄ—l jungsimÄ—s po {0} sek. +message.register.transports = Registruotis ryÅ¡io kanaluose. +message.registering = Registruojamasi į {0}. Lukterkite… +message.registration.transport.failed = Nepavyko prisijungti prie ryÅ¡io kanalo. +message.restart.spark = Naujos versijos įdiegimui reikia iÅ¡jungti programÄ….\n Ar iÅ¡jungti? +message.restart.spark.changes = Priedas galutinai bus paÅ¡alintas kitÄ… kartÄ… startuojant „Spark“ programÄ…. +message.restart.spark.to.install = Naujausios versijos įdiegimui reikÄ—s iÅ¡jungti programÄ…. IÅ¡jungti dabar? +message.restart.required = Kad pakeitimai įsigaliotų, reikia startuoti programÄ… iÅ¡ naujo. Startuoti iÅ¡ naujo dabar? +message.room.creation.error = Kambario sukurti nepavyko. +message.room.destroyed = Kambarys paÅ¡alintas. Priežastis: {0} +message.room.destruction.reason = Kokia kambario paÅ¡alinimo priežastis? +message.room.information.for = Informacija apie kambarį {0} +message.save.profile = PaspaudÄ™ mygtukÄ… „ĮraÅ¡yti“ iÅ¡saugosite atliktus pakeitimus. +message.search.for.contacts = Pokalbio partnerių paieÅ¡ka. +message.search.for.history = IeÅ¡koti pokalbio žurnale +message.search.for.other.people = Kitų žmonių paieÅ¡ka serveryje +message.search.input.short = PraÅ¡ome pateikti bent dvi raides. +message.search.service.not.available = Nepavyksta prisijungti prie paieÅ¡kos tarnybos. +message.searching.please.wait = IeÅ¡koma. Lukterkite… +message.select.add.room.to.add = Pasirinkite kambarį, kurį pageidausite įtraukti į paieÅ¡kos tarnybos sÄ…raÅ¡us. +message.select.one.or.more = Pasirinkite vienÄ… ar kelis abonentus. +message.select.room.to.enter = Nurodykite kambarį, kuriame lankysitÄ—s. +message.select.room.to.join = Pasirinkite kambarį, į kurio pokalbius jungsitÄ—s. +message.send.a.broadcast = Transliuoti žiniÄ… +message.send.file.to.user = Siųsti abonentui bylÄ… +message.send.picture = Siųsti ekrano vaizdÄ… +message.send.to.these.people = Transliuojamo praneÅ¡imo gavÄ—jų parinkimas +message.sending.file.to = Bylos siuntimas adresatams {0}. +message.sent.offline.files = IÅ¡siuntÄ—te bylÄ…(as) atsijungus. +message.server.unavailable = Nepavyksta prisijungti prie serverio. Gal neteisingas serverio vardas arba jis dabar yra nepasiekiamas. +message.service.already.exists = Paslauga jau yra. +message.shared.group = Bendrinta grupÄ— +message.specify.contact.jid = PraÅ¡om nurodyti abonento „JID“ (pvz. vardenis@jabber.org). +message.specify.group = Nurodykite adresų grupÄ™, į kuriÄ… įtrauksim naujÄ… abonentÄ…. +message.specify.information.for.conference = Nurodykite informacijÄ… apie konferencijų kambarį. +message.specify.name.error = Nurodykite teisingÄ… vardÄ…. +message.specify.users.to.join.conference = Nurodykite abonentus, kurie jungsis į konferencijų kambarį. +message.specify.valid.time.error = Teisingai nurodykite laukimo laikÄ… ir prievadÄ…. +message.subject.change.error = Jums neleidžiama keisti Å¡io kambario pokalbių temos. +message.subject.has.been.changed.to = Tema pakeista į {0}. +message.supply.resource = Reikia pateikti teisingÄ… resursÄ…. +message.supply.valid.port = Pateikti teisingÄ… prievadÄ…. +message.supply.valid.timeout = Pateikti teisingÄ… laukimo laiko reikÅ¡mÄ™. +message.timeout.error = Laukimo laikas turÄ—tų bÅ«ti bent 5 sek. arba ilgesnis. +message.total.downloaded = Parsiųstos bylos +message.transfer.cancelled = Bylos siuntimas atÅ¡auktas. +message.transfer.complete = Bylos siuntimas užbaigtas ({0}) +message.transfer.progressbar.text.received = {0} gauta @ {1} {2} +message.transfer.progressbar.text.sent = {0} iÅ¡siųsta @ {1} {2} +message.transfer.rate = Siuntimo sparta +message.transfer.refused = Bylos siuntimas buvo atmestas. +message.transfer.waiting.on.user = Laukiama kol {0} patvirtins bylos siuntimÄ…. +message.unable.to.load.profile = Nepavyko rasti profilio {0} vietos. +message.unable.to.retrieve.last.activity = Nepavyko rasti profilio {0}. +message.unable.to.save.password = Nepavyko pasikeisti slaptažodžio. GalbÅ«t to neleidžia administratorius. +message.unable.to.send.file = Jums nepavyko nusiųsti bylos gavÄ—jui {0}. +message.unable.to.use.hostname.as.resource = Neįmanoma panaudoti kompiuterio vardo kaip resurso +message.unrecoverable.error = Nežinoma susijungimo klaida. Daugiau informacijos klaidų žurnaluose (logs). +message.update.room.list = Kambarių sÄ…raÅ¡o atnaujinimas. +message.updating.cancelled = Atnaujinimas atÅ¡auktas. +message.user.banned = {0} Å¡iame kambaryje buvo uždraustas. +message.user.given.voice = {0} gavo galimybÄ™ Å¡iame kambaryje kalbÄ—ti. +message.user.granted.admin = {0} gavo administravimo privilegijas. +message.user.granted.membership = {0} gavo eilinio nario privilegijas. +message.user.granted.moderator = {0} gavo prižiÅ«rÄ—tojo privilegijas. +message.user.granted.owner = {0} gavo savininko privilegijas. +message.user.is.sending.you.a.file = {0} Jums siunÄia bylÄ…. +message.user.joined.room = {0} apsilankÄ— kambaryje. +message.user.kicked.from.room = {0} buvo iÅ¡mestas iÅ¡ kambario. +message.user.left.room = {0} išėjo iÅ¡ kambario. +message.user.nickname.changed = {0} dabar bus žinomas kaip {1}. +message.user.now.available.to.chat = {0} prisijungÄ— {1} +message.user.revoked.admin = Administratoriaus privilegijos atÅ¡auktos abonentui {0}. +message.user.revoked.membership = NarystÄ—s privilegijos atÅ¡auktos abonentui {0}. +message.user.revoked.moderator = PrižiÅ«rÄ—tojo privilegijos atÅ¡auktos abonentui {0}. +message.user.revoked.owner = Savininko privilegijos atÅ¡auktos abonentui {0}. +message.user.voice.revoked = Atimtas balsas iÅ¡ {0}. +message.username.error = Nurodykite abonento vardÄ… ir slaptažodį. +message.username.password.error = Turi bÅ«ti pateiktas abonento vardas ir/arba slaptažodis. +message.vcard.not.supported = Serveris nepalaiko „VCards“ vizitinių kortelių. Tokios kortelÄ—s įraÅ¡yti nepavyko. +message.version = Versija: {0} +message.view.information.about.this.user = Informacija apie abonentÄ… +message.waiting.for.user.to.join = Laukiama kol {0} prisijungs. +message.went.offline = {0} atsijungÄ— {1} +message.you.have.been.banned = JÅ«s esate nepageidaujamas Å¡iame kambaryje. ÄŒia Jums dalyvauti neleista. +message.you.have.been.kicked = Nepykite, bet iÅ¡ Å¡io kambario esate iÅ¡mestas. +message.you.have.sent = IÅ¡siuntÄ—te bylÄ… adresatui {0}. +message.your.admin.granted = Jums suteiktos administratoriaus privilegijos. +message.your.banned = Å iame kambaryje jums dalyvauti uždrausta. +message.your.kicked = Jus iÅ¡metÄ— {0}. +message.your.membership.granted = Jums suteiktos narystÄ—s privilegijos. +message.your.membership.revoked = JÅ«sų narystÄ— atÅ¡aukta. +message.your.moderator.granted = Jums suteiktos prižiÅ«rÄ—tojo privilegijos. +message.your.moderator.revoked = Netekote prižiÅ«rÄ—tojo privilegijų. +message.your.ownership.granted = Jums suteiktos savininko privilegijos. +message.your.ownership.revoked = Netekote savininko privilegijų. +message.your.revoked.granted = Netekote administratoriaus privilegijų. +message.your.voice.granted = Å iame pokalbyje Jums suteiktas balsas. +message.your.voice.revoked = Netekote balso. +message.groupchat.require.password = Å i pokalbių grupÄ— priims, jei įvesite slaptažodį. +message.groupchat.registered.member = SÄ—kmingai prisiregistravote prie {0} + +status.away = PasitraukÄ™s +status.custom.messages = Susikurtos bÅ«senos +status.do.not.disturb = Netrukdykite +status.extended.away = IÅ¡vykÄ™s +status.free.to.chat = Mielai pasikalbÄ—siu +status.on.phone = Kalbu telefonu +status.online = PrisijungÄ™s +status.pending = Laukiama +status.invisible = Nematomas +status.offline = AtsijungÄ™s + +tab.available.plugins = Galimi priedai +tab.avatar = Pseudoportretas +tab.business = DarbovietÄ— +tab.conferences = Konferencijos +tab.contacts = AdresinÄ— +tab.general = Bendra +tab.security = Saugumas +tab.home = Namai +tab.installed.plugins = Ä®diegti priedai +tab.deactivated.plugins = IÅ¡jungti priedai +tab.personal = Asmuo +tab.proxy = Tarpinis serveris +tab.sso = SSO +tab.pki = PKI +tab.certificates = Sertifikatai + +title.about = Apie +title.password.required = Reikalingas slaptažodis +title.task.notification = PraneÅ¡imas apie užduotį +title.client.logs = Žurnalo įraÅ¡ai +title.advanced.connection.preferences = Prisijungimo nuostatos iÅ¡samiau +title.account.create.registration = Paskyros registravimas +title.bookmarks = Žymos +title.account.created = Paskyra sÄ—kmingai sukurta +title.add.contact = PridÄ—ti adresatÄ… +title.add.contact.group = Adresatų grupÄ—s pridÄ—jimas +title.add.new.group = Naujos grupÄ—s pridÄ—jimas +title.add.search.service = PaieÅ¡kos tarnybos pridÄ—jimas +title.add.to.roster = Ä®traukti į sÄ…rašą +title.address = Adresas +title.advanced.connection.usesso = Naudoti Single Sign-On (SSO) via GSSAPI +title.advanced.connection.sso.account = Prisijungimui prie serverio bus panaudota vartotojo paskyra "{0}" +title.advanced.connection.sso.unable = Nepavyko prisijungti naudojant Single Sign-On. PraÅ¡ome patikrinti prisijungimo duomenis ir serverio nustatymus. +title.advanced.connection.sso.noprincipal = Spark negali rasti tinkamos paskyros prisijungimui su Single Sign-On. Tai neleis naudotis SSO. +title.advanced.connection.sso.smack3compat = Smack 3 suderinamumo režimas +title.alert = PraneÅ¡imas +title.appearance = IÅ¡vaizda +title.appearance.preferences = Adaptavimas +title.available.transports = Galimi ryÅ¡io kanalai +title.broadcast.message = Transliuoti žiniÄ… +title.broadcast.history = Transliacijų istorija +title.browse.conference.services = Konferencijų peržiÅ«ra +title.browse.room.service = Pokalbių kambarių peržiÅ«ra - {0} +title.cancelled = AtÅ¡aukta +title.change.nickname = Pseudonimo pakeitimas +title.change.subject = Temos pakeitimas +title.chat = Pokalbis +title.choose.directory = Katalogo pasirinkimas +title.choose.incoming.sound = ŽinutÄ—s gavimo ar prisijungimo garsinio signalo parinkimas +title.choose.offline.sound = Atsijungimo garsinio signalo parinkimas +title.choose.outgoing.sound = ŽinutÄ—s iÅ¡siuntimo garsinio signalo parinkimas +title.conference.invitation = Pakvietimas į konferencijÄ… +title.conference.rooms = Konferencijų kambariai +title.configure.chat.room = Pokalbių kambario konfigÅ«ravimas +title.configure.room = KonfigÅ«ruoti kambarį +title.confirmation = Patvirtinimas +title.create.new.account = Naujos paskyros sukÅ«rimas +title.create.or.bookmark.room = Prisijungti prie konferencijos arba pasižymÄ—ti kambarį +title.create.room = Sukurti +title.create.problem = Paskyros sukÅ«rimo problema +title.delete.file = Ar tikrai norite paÅ¡alinti Å¡iÄ… bylÄ…? +title.dial.phone = Skambinti VOIP telefonu +title.disable.transport = Prisijungimo kanalo informacijos paÅ¡alinimas +title.download.complete = Parsiuntimas baigtas +title.downloading.im.client = Parsisiųsti trumpųjų žinuÄių „IM“ kliento programÄ… +title.downloads = Parsiųsta +title.edit.custom.message = Susikurtų bÅ«senų redagavimas +title.edit.profile = Profilio informacijos redagavimas +title.enter.reason = Priežasties įvedimas +title.error = Klaida +title.error.couldnot.open.file = Nepavyko atverti bylos! Patikrinkite ar teisingas bylos tipas. +title.error.delete.file = Nepavyko paÅ¡alinti bylos! +title.error.find.app = Nepavyko rasti tinkamos programos! +title.error.rename.file = Nepavyko pakeisti bylos vardo! +title.file = Byla +title.filesize = Dydis +title.file.exists = Byla jau egzistuoja +title.file.transfer = Bylų siuntimas +title.file.transfer.preferences = Bylų siuntimo nuostatos +title.find.conference.service = IeÅ¡koti konferencijų +title.find.contacts = IeÅ¡koti abonentų +title.gadugadu.registration = „GaduGadu“ paskyros kredencialai +title.general.media = Medijos nuostatos +title.general.chat.settings = Bendrosios pokalbių nuostatos +title.group.chat = Grupiniai pokalbiai +title.group.chat.settings = Grupinių pokalbių nuostatos +title.history.for = Pokalbio su {0} žurnalas +title.irc.registration = IRC paskyros kredencialai +title.sametime.registration = Sametime paskyros kredencialai +title.facebook.registration = Facebook paskyros kredencialai +title.myspace.registration = MySpace paskyros kredencialai +title.incoming.call = Skambutis +title.input.fileexplorer = Ä®veskite bylų narÅ¡yklÄ—s vardÄ…: +title.input.newname = PraÅ¡om įvesti naujÄ… vardÄ…: +title.input.openwith = Nurodykite programos, kuriÄ… naudosite vardÄ…: +title.invite.to.conference = Pakviesti į konferencijÄ… +title.jabber.browser = NarÅ¡yklÄ— +title.join.conference.room = Prisijungti prie konferencijų +title.last.activity = Paskiausi veiksmai +title.login = Prisijungimas +title.login.error = Prisijungimo klaida +title.login.settings = Prisij&ungimo nuostatos +title.login.no.account = Nepavyksta nustatyti +title.lookup.profile = IeÅ¡koti profilio +title.name = Vardas +title.new.client.available = Galimas naujas klientas +title.new.roster.group = Nauja viso sÄ…raÅ¡o grupÄ— +title.new.version.available = Galima nauja versija +title.no.updates = Atnaujinimų nÄ—ra +title.notes = UžraÅ¡ai +title.notification = PraneÅ¡imas +title.notifications = PraneÅ¡imai +title.occupants = Lankytojų sk. +title.on.the.phone = Kalba telefonu +title.password = Slaptažodis +title.passwords.no.match = Slaptažodžio patvirtinimas +title.person.search = Asmens paieÅ¡ka +title.plugins = Priedai +title.preferences = Nuostatos +title.profile.information = Profilio informacija +title.profile.not.found = Profilis nerastas +title.qq.registration = QQ paskyros kredencialai +title.register.account = Naujos paskyros registravimas +title.registration.error = Registracijos klaida +title.reminder = Priminimas +title.rename.roster.group = Keisti sÄ…raÅ¡o grupÄ—s vardÄ… +title.room.destroyed = Kambarys paÅ¡alintas +title.room.information = Informacija apie kambarį +title.roster = Visi abonentai +title.select.file.to.send = Bylos(ų) siuntimui parinkimas +title.set.status.message = Siųsti bÅ«senos žiniÄ… +title.simple.registration = SIMPLE paskyros kredencialai +title.sound.preferences = Garsų nuostatos +title.sounds = Garsai +title.spark.preferences = „Spark“ programos nuostatos +title.start.chat = PradÄ—ti pokalbį +title.status.message = Informacija apie bÅ«senÄ… +title.tasks = Užduotys +title.transports = RyÅ¡io kanalai +title.tray.information = Informacija sisteminÄ—je eilutÄ—je +title.upgrading.client = Programos atnaujinimas +title.version.and.time = Versija ir laikas +title.view.bookmarks = Parodyti žymas +title.view.profile.for = Profilis {0} +title.view.room.information = Informacija apie kambarį +title.waiting.to.call = Laukiama skambuÄio +title.warning = PerspÄ—jimas +title.xmpp.registration = XMPP paskyros kredencialai +title.appearance.showVCards = Vizitinių kortelių „VCards“ rodymas adresatų sÄ…raÅ¡e +title.subscription.request = Prenumeratos praÅ¡ymas +title.certificate = Sertifikatas + +tooltip.place.a.call = Skambinimas asmeniui VOIP telefonu +tooltip.appearance = Pokalbių aplinkos iÅ¡vaizdos keitimas +tooltip.file.transfer = Bylų siuntimo nuostatos +tooltip.notifications = PraneÅ¡imų apie žinutes nuostatos +tooltip.place.voice.call = Skambinti asmeniui VOIP telefonu +tooltip.send.email = Siųsti el. laiÅ¡kÄ… +tooltip.start.chat = PradÄ—ti pokalbį +tooltip.view.changelog = PeržiÅ«rÄ—ti pakeitimų žurnalÄ… +tooltip.view.history = PeržiÅ«rÄ—ti pokalbių žurnalÄ… +tooltip.view.readme = Skaityti „ReadMe“ bylÄ… +tooltip.encryptionmode.required = Å ifravimas privalomas norint prisijungti. Jeigu serveris nesiÅ«lo Å¡ifravimo arba jei Å¡ifravimo nepavyksta užmegzti, susijungimas su serveriu nepavyks. +tooltip.encryptionmode.ifpossible = Å ifravimas naudojimas kai tai yra įmanoma. +tooltip.encryptionmode.disabled = Å ifravimas iÅ¡jungtas ir bus naudojamas tik neÅ¡ifruotas ryÅ¡is. Jei Å¡ifravimas reikalaujamas serverio, susijungimas nepavyks. + +tree.conference.services = Konferencijos +tree.users.in.room = Kambaryje apsilankÄ™ + +lookandfeel.select = Pasirinkti programos iÅ¡vaizdÄ… +lookandfeel.change.now = Pakeisti dabar +lookandfeel.tooltip.restart.no = Programos perkrovimas nereikalingas +lookandfeel.tooltip.restart.yes = Kad įjungti programos sisteminÄ™ iÅ¡vaizdÄ…, paspauskite Ä®raÅ¡yti ir perkraukite Spark +lookandfeel.color.label = Spalvos +lookandfeel.color.red = Raudona +lookandfeel.color.green = Žalia +lookandfeel.color.blue = MÄ—lyna +lookandfeel.color.opacity = Nepermatomumas +lookandfeel.color.saved = Spalva iÅ¡saugota + + +##Settings for the privacy plugin +privacy.title.preferences = Sparko privatumo nustatymai +privacy.title.panel = PraÅ¡ome naudoti deÅ¡inį pelÄ—s mygtukÄ… +privacy.label.iq.desc = Užklausa +privacy.label.pin.desc = Gaunama bÅ«sena +privacy.label.pout.desc = SiunÄiama bÅ«sena +privacy.label.msg.desc = ŽinutÄ—s +privacy.border.information = Privatumo informacija +privacy.label.information = Naudokite deÅ¡inio paspaudimo meniu, kad pridÄ—ti ar iÅ¡trinti sÄ…raÅ¡us ar punktus +privacy.root.node = Privatumo sÄ…raÅ¡ai +privacy.label.preferences = Privatumo įskiepis +privacy.tooltip.preferences = Sparko privatumo nustatymai +privacy.label.list.is.active = AKTYVUS +privacy.label.list.is.default = NUMATYTASIS +privacy.border.block = Blokuoti +privacy.pick.one.or.more = Pasirinkite vienÄ… ar daugiau punktų, kad pridÄ—ti į sÄ…rašą +privacy.title.add.picker = PridÄ—ti punktus į sÄ…rašą +privacy.node.contacts = Adresatai +privacy.node.groups = GrupÄ—s +privacy.menu.add.contacts = PridÄ—ti adresatÄ… į sÄ…rašą +privacy.menu.add.groups = PridÄ—ti grupÄ™ į sÄ…rašą +privacy.menu.add.rem.items = IÅ¡trinti {0} punktus iÅ¡ sÄ…raÅ¡o +privacy.menu.remove = IÅ¡trinti +privacy.menu.activate.list = Aktyvuoti +privacy.menu.default.list = Nustatyti kaip numatytÄ…jį +privacy.menu.add.list = PridÄ—ti sÄ…rašą +privacy.menu.remove.list = IÅ¡trinti sÄ…rašą +privacy.dialog.add.list = PraÅ¡me nurodyti sÄ…raÅ¡o vardÄ… +privacy.dialog.rem.list = Ar tikrai norite iÅ¡trinti {0}? +privacy.status.menu.entry = Privatumo sÄ…raÅ¡ai +privacy.name.for.default.list = Numatytasis +privacy.button.no.list.selected = Nepasirinktas sÄ…raÅ¡as +privacy.menuitem.deactivate.current.list = Deaktyvuoti {0} +privacy.label.not.supported = Privatumo sÄ…raÅ¡ai nepalaikomi serverio + +##Stunfallback in media settings +stun.border.label = STUN pagalbinis serveris +stun.server.addr = Stun serveris: +stun.server.port = Stun prievadas: + +##Text Field Hints +hint.login.username = Ä®veskite abonentÄ… +hint.login.password = Ä®veskite slaptažodį +hint.login.domain = Ä®veskite domenÄ… + +composing = {0} raÅ¡o... +paused = {0} nustojo raÅ¡yti +active = {0} kreipia dÄ—mesį +inactive = {0} veikia kažkÄ… kitÄ… +gone = {0} pasitraukÄ— + +action.viewlog = PeržiÅ«rÄ—ti žurnalÄ… + +dialog.confirm.to.reveal.visibility.title = Ar esat tikri? +dialog.confirm.to.reveal.visibility.msg = Jeigu tÄ™site, jÅ«sų nematomumas bus nutrauktas +dialog.confirm.close.all.conferences.if.invisible.msg = Jeigu tÄ™site, visi konferencijų kambariai bus uždaryti +dialog.certificate.show = Tai sertifikatas kurį bandote pridÄ—ti į Truststore.

      Po šio sertifikato įtraukimo Spark galės užmegzti apsaugotą
      ryšį su serveriais kurie identifikuojami su šiuo sertifikatu.

      Jei esate tikri, kad norite prid?ti šį sertifikatą, paspauskite OK mygtuką. +dialog.certificate.add.from.connection = Tai sertifikatas, kurį pateikė serveris prie kurio bandote prisijungti.
      Šis sertifikatas nėra įtrauktas į jūsų TrustStore, kas reiškia, kad juo dar nepasitikite
      ir todÄ—l negalite prisijungti prie serverio.

      Ar norite pasitikėti juo ir įtraukti šį sertifikatą į jūsų TrustStore? +dialog.certificate.presented.by.server = Tai sertifikatas pateiktas serverio prie kurio jungiatės. Ar norite
      pasitikėti juo ir pridėti į patikimų sąrašą?

      Paspauskite Detaliau mygtukÄ… norint pamatyti daugiau informacijos
      apie šį sertifikatą. +dialog.certificate.chain.add.from.connection = Tai sertifikato granginė pateikta serverio prie kurio jungiatės.
      Ji nėra patikimų sąraše, todėl negalite prisijungti.

      Ar norite pridÄ—ti šį sertifikatÄ… ar visÄ… grandinÄ™ į jÅ«sų patikimų sÄ…rašą? +dialog.certificate.cannot.have.copy = Å is sertifikatas jau yra patalpintas Truststore. +dialog.certificate.has.been.added = Sertifikatas pridÄ—tas į Truststore. +dialog.certificate.is.distrusted = Sertifikatas negaliojantis, todÄ—l jo nereikÄ—tų pasitikÄ—ti, nes tai gali bÅ«ti pavojinga. \n Jei vis tiek norite jį priimti, spauskite Trust mygtukÄ… arba pridÄ—kite jį į iÅ¡imÄių sÄ…rašą. +dialog.certificate.sure.to.delete = Ar tikrai norite iÅ¡trinti šį sertifikatÄ…? \nJeigu tai padarysite, negal?Ä—site užmegzti saugaus ryÅ¡io \nsu serveriais identifikuojamais Å¡iuo sertifikatu. +dialog.certificate.has.been.deleted = Sertifikatas sÄ—kmingai iÅ¡trintas. +dialog.self.signed.certificate.has.been.created = Paties pasiraÅ¡ytas sertifikatas ir privatus raktas buvo sukurti direktorijoje: +dialog.certificate.request.has.been.created = Sertifikato pasiraÅ¡ymo užklausa ir privatus raktas buvo sukurti direktorijoje: +dialog.cannot.upload.certificate.might.be.ill.formatted = Neįmanoma įkelti sertifikato, sertifikatas gali bÅ«ti blogai suformuotas +dialog.cannot.upload.certificate = Neįmanoma įkelti sertifikato bylos +dialog.certificate.title.certificate.not.in.truststore = Pateiktas sertifikatas nÄ—ra jÅ«sų TrusStore + +cert.valid = Galiojantis +cert.revoked = AtÅ¡auktas +cert.expired = BaigÄ—si galiojimas +cert.not.valid.yet = Dar negaliojantis +cert.self.signed = "Self signed" +cert.unknown.oid = Nežinomas OID apraÅ¡as. +cert.is.critical = Yra kritiÅ¡ka: +cert.critical = KritiÅ¡ka: +cert.not.critical = Ne kritiÅ¡ka: + +cert.extensions = Sertifikato extensions: +cert.extensions.unsupported = Nepalaikomi extensions +cert.extension.extended.usage.digital.signature = Skaitmeninis paraÅ¡as diff --git a/core/src/main/resources/i18n/spark_i18n_nl.properties b/core/src/main/resources/i18n/spark_i18n_nl.properties new file mode 100644 index 000000000..3cd499dae --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_nl.properties @@ -0,0 +1,1118 @@ +accept = Accepteer +is.active = Actief +add = Toevoegen +administrator = Administrator +apply = Toepassen +available = Beschikbaar +broadcast = Bericht rondsturen +cancel = Annuleren +delete = Verwijderen +details = Details +close = Sluiten +create = Aanmaken +date = Datum +description = Beschrijving +from = Van +invite = Uitnodigen +join = Binnengaan +no = Nee +not.registered = Niet geregistreerd +occupants = Aanwezigen +offline = Afgemeld +online = Aangemeld +ok = OK +open = Openen +open.folder = Open Map +participants = Deelnemers +refresh = Verversen +reject = Afwijzen +retry = Opnieuw +room.name = Naam ruimte +save = Opslaan +subject = Onderwerp +unfiled = Niet gegroepeerd +use.default = Standaardinstellingen +user.has.signed.in = heeft zich aangemeld. +user.has.signed.off = heeft zich afgemeld. +while.offline = Tijdens afwezigheid +yes = Ja + +action.clear = Legen +action.copy = Kopiëren +action.cut = Knippen +action.paste = Plakken +action.print = Afdrukken +action.save = Opslaan +action.select.all = Alles selecteren + +button.accept = &Accepteren +button.add = &Toevoegen +button.add.a.contact = &Contact toevoegen... +button.add.bookmark = Bladwijzer toevoegen +button.add.service = &Dienst toevoegen +button.add.user = &Gebruiker toevoegen +button.add2 = Toe&voegen +button.advanced = Gea&vanceerd +button.approve = &Toestaan +button.bookmark.room = &Bladwijzer van deze ruimte maken +button.browse = &Bladeren... +button.browse2 = Blade&ren... +button.browse3 = Blad&eren... +button.cancel = &Annuleren +button.cert.info = Details +button.clear = &Legen +button.close = S&luiten +button.copy.to.clipboard = Naar Klembord kopiëren +button.create.account = &Account aanmaken +button.create.room = &Maak of ga naar ruimte +button.decline = &Weigeren +button.deny = &Weigeren +button.dial.number = &Nummer bellen +button.find = &Zoeken +button.join = &Meedoen +button.join.room = Ruimte &binnengaan +button.login = In&loggen +button.new = &Nieuw +button.profile = &Profiel +button.quit = &Afsluiten +button.re.detect = &Detecteer +button.reconnect = &Opnieuw +button.reconnect2 = Opnieuw verbinden +button.refresh = &Vernieuwen +button.register = &Registreer +button.reject = Afwijzen +button.remove.bookmark = Bladwijzer verwijderen +button.roster = &Contactlijst +button.save = Op&slaan +button.save.for.future.use = &Opslaan voor later gebruik +button.search = &Zoeken +button.send = &Zend +button.send.email = E-mail +button.start.chat = Conversatie +button.tasks.active = Lopende +button.tasks.all = Alle +button.unset.file.explorer = Deslecteer Bestandsverkenner +button.update = &Bijwerken +button.view.notes = Notitieblok +button.view.profile = Bekijk volledig profiel +button.view.tasklist = Bekijk taaklijst +button.check.validity = Valideer +button.show.certificate = Toon certificaat +button.delete.saved.passwords = Vergeet alle inlog-wachtwoorden + +table.column.certificate.subject = Onderwerp +table.column.certificate.validity = Validiteit +table.column.certificate.exempted = Uitgezonderd + +checkbox.allow.buzz = Sta buz&zen toe +checkbox.auto.discover.port = Ontdek server en poort &automatisch +checkbox.auto.login = &Automatisch aanmelden +checkbox.login.as.invisible = L&ogin als onzichtbaar +checkbox.login.anonymously = Login anonie&m +checkbox.disable.chat.history = &Opslag van conversaties uitschakelen +checkbox.sort.asc.history = Sorteer berichten in contactgeschiedenis op datum, oplopend +checkbox.disable.prev.chat.history = &Schakel het tonen van oude gesprekken in de chat uit. +checkbox.enable.emoticons = Em&oticons aan +checkbox.graying.out = Dim contacten die niet actief zijn (vereist herstart) +checkbox.idle.enabled = &Automatisch afwezigheid detecteren +checkbox.launch.on.startup = Start bij &opstarten +checkbox.reconnect.info = Specificeer tonen van herconnectie: +checkbox.reconnect.panel.big = Toon als Paneel +checkbox.reconnect.panel.small = Toon in contactgroep +checkbox.reconnect.panel.icon = Toon als icoon +checkbox.notify.user.comes.online = Melding als een gebruiker zich aanmeldt +checkbox.notify.user.goes.offline = Melding als een gebruiker zich afmeldt +checkbox.notify.typing.systemtray = Toon typ-notificatie in de &system tray +checkbox.notify.systemtray = Toon nieuwe berichten in de system tray +checkbox.permanent = &Permanente ruimte +checkbox.play.sound.on.invitation = Geluid bij &ontvangen uitnodiging +checkbox.play.sound.on.new.message = Geluid bij &nieuw bericht +checkbox.play.sound.on.outgoing.message = Geluid bij &verzenden bericht +checkbox.play.sound.when.offline = Geluid bij &afmelden gebruiker +checkbox.private.room = P&rivéruimte +checkbox.save.password = Wachtwoord &opslaan +checkbox.show.avatars.in.contactlist = Toon &Avatars in Contactlijst +checkbox.show.notifications.in.conference = Toon &meldingen in ruimtes +checkbox.show.time.in.chat.window = Toon &tijd in venster +checkbox.show.toaster = Toon een &toast popup +checkbox.disable.asterisk.toaster = Schakel telefoon toast-popuit uit +checkbox.split.chat.window = Combineer &Vensters (Vereist herstart van Spark) +checkbox.start.in.tray = Start in &systeemvak +checkbox.click.single.tray = Eenmal&ig klikken in de system tray om Spark naar de voorgrond te brengen (vereist herstart) +checkbox.tabs.on.top = &Conversatie tabs altijd vooraan (Herstart vereist) +checkbox.tabs.scroll = Scroll gebruiken voor chattabbladen (Herstart vereist) +checkbox.use.compression = Gebruik &Compressie +checkbox.use.debugger.on.startup = Open diagnostisch scherm tijdens het opstarten +checkbox.use.proxy.server = Proxy &server gebruiken +checkbox.use.system.look.and.feel = Gebruik de systeeminstellingen (Na herstart van Spark) +checkbox.window.to.front = &Breng venster naar voren +checkbox.broadcast.hide.offline.user = Verstop offline gebruiker +checkbox.use.krbconf = Gebruik krb5.conf of krb5.ini +checkbox.use.krb.dns = Gebruik DNS +checkbox.use.specify.below = Specificeer hieronder +checkbox.use.pki.authentication = Gebruik PKI authenticatie +checkbox.transport.tab.setting = Toon beschikbare transporten in tab (vereist herstart) +checkbox.conference.tab.setting = Toon conferentie services in tab (vereist herstart) +checkbox.use.hostname.as.resource = Gebruik hostnaam als resource +checkbox.use.version.as.resource = Gebruik Spark versie als resource +checkbox.accept.all.certificates = Accepteer alle certificaten (self-signed/verlopen/niet-vertrouwde) +checkbox.disable.hostname.verification = Schakel verificatie van hostnaam in certificaat uit (niet aanbevolen) +checkbox.allow.client.side.authentication = Sta wederzijde authenticatie toe +checkbox.accept.all = Accepteer alle +checkbox.accept.expired = Accepteer verlopen +checkbox.accept.not.valid.yet = Accepter nog niet geldige +checkbox.accept.self.signed = Accepteer self-signed +checkbox.accept.revoked = Accepteer teruggetrokkene +checkbox.check.crl = Check CRL +checkbox.check.ocsp = Check OCSP +checkbox.allow.soft.fail = Sta soft fail beleid toe +checkbox.on.exception.list = Op de uitzonderingslijst +checkbox.filetransfer.ibb.only = Uitsluitend In-Band Bytestreams +checkbox.filetransfer.autoaccept.presence = Accepteer verzoeken van bekende contacten autoatisch +checkbox.close.unread.message = Vraag bij het sluiten van het venster of er ongelezen berichten zijn +radio.encryptionmode.required = Vereist +radio.encryptionmode.ifpossible = Indien mogelijk +radio.encryptionmode.disabled = Uitgeschakeld + +delete.log.permanently = Verwijder log permanent +delete.permanently = Permanent verwijderen? + +gateway.username.password.error = Gebruikersnaam en/of wachtwoord moeten worden opgegeven. + +group.chat.window.information = Conversatievenster informatie +group.comma.delimited = Komma-gescheiden +group.conferences.found = Conferentiediensten +group.connection = Verbinding +group.empty = Er zijn geen aangemelde gebruikers in deze groep. +group.general.information = Algemene informatie +group.login.information = Aanmeldingsinformatie +group.notification.options = Meldingsvoorkeuren +group.offline = Niet aangemeld +group.search.form = Zoekformulier +group.search.results = Zoekresultaten +group.chat.name.notification = Uw naam gezien... +group.chat.name.match = Uw naam is is genoemd in het groepsgesprek: +group.send_config.error = Er is een fout opgetreden tijdens het opslaan! +group.encryption_mode = Encryptiemode + +label.na = n/b +label.home = Thuis +label.accounts = A&ccounts +label.add.conference.service = &Conferentiedienst toevoegen +label.add.jid = &JID toevoegen +label.add.task = Taak toevoegen +label.auto.login = &Automatisch aanmelden +label.available.users.in.roster = &Beschikbare gebruikers in contactlijst +label.avatar = Avatar: +label.broadcast.history.search.date = Zoek datum (jaar-maand): +label.cancel = Annuleer +label.cell = cel +label.change.password.to = &Verander wachtwoord +label.chatroom.fontsize = Chat &Ruimte lettergrootte: +label.chatroom.maxcurrenthistorysize = Max huidige geschiedenis grootte: +label.city = P&laats +label.close = S&luiten +label.company = &Bedrijf +label.confirm.password = &Bevestig wachtwoord +label.conflict.error = Aanmelden niet mogelijk omdat de account reeds is aangemeld. +label.contact.to.find = Zoek contact +label.recent.conversation = Recente Conversaties +label.frequent.contacts = Veelgebruikte Contracten +label.contactlist.avatarsize = Contactlij&st Avatargrootte: +label.contactlist.fontsize = Contact &Lijst lettergrootte: +label.country = &Land +label.create.account = Maak &account aan +label.department = &Afdeling +label.dial = &Bellen +label.display.time = Toon Tijd: +label.downloads = Downloads +label.due = Verloopt +label.email.address = &Email adres +label.emoticons = &Emoticons +label.enter.address = Geef adres op +label.enter.group.name = Geef nieuwe groepnaam op +label.fax = &Fax +label.find = &Zoeken +label.first.name = &Voornaam +label.group = &Groep +label.host = &Host +label.invited.users = Uitgenodigde gebruikers +label.jabber.address = &Jabber adres +label.jabber.id = &Jabber ID +label.jid = &JID +label.job.title = &Functie +label.last.name = &Achternaam +label.local.time = &Lokale tijd +label.message = Bericht +label.message.style = &Bericht opmaak +label.middle.name = Verdere &namen +label.minutes.before.stale.chat = &Minuten voor een inactieve ruimte bevriest +label.mobile = &Mobiel +label.name = &Naam +label.network = Netwer&k +label.new.nickname = Nieuwe alias +label.nickname = A&lias +label.number = &Nummer +label.ok = OK +label.old.ssl = Gebruik OUDE &SSL poort methode +label.os = &Besturingssysteem +label.pager = Pa&ger +label.password = &Wachtwoord +label.passwordreset = Reset wachtwoord +label.phone = &Telefoon +label.port = &Poort +label.postal.code = &Postcode +label.presence = &Aanwezigheid +label.priority = &Prioriteit +label.protocol = P&rotocol +label.received = &Ontvangen +label.rename.to = Hernoemen naar +label.resource = &Medium +label.response.timeout = Maximale antwoord&tijd (sec) +label.reconnect.delay = Vertraging Herconnectie (sec) (vereist herstart) +label.room = &Ruimte +label.room.name = &Naam ruimte +label.room.topic = &Onderwerp +label.search = Zoeken +label.search.service = &Zoek dienst +label.seconds = Seconden +label.server = Do&mein +label.server.address = &Server adres +label.show = Toon: +label.software = &Software +label.state.and.province = Staat/P&rovincie +label.street.address = &Straatnaam +label.time = Tijd: {0} +label.time.till.idle = &Tijd tot automatisch afwezig (min): +label.time.till.idlemessage = Automatisch inacti&ef bericht +label.timeformat = Invoeren als {0} +label.transfer.download.directory = &Download map: +label.transfer.timeout = &Maximale overdrachttijd (min): +label.unable.to.add.contact = Persoon toevoegen mislukt. +label.use.default = Standaardinstellingen +label.user.on.public.network = Gebruiker is op een publiek netwerk +label.username = Gebruikers&naam +label.version = &Versie +label.web.page = &Webpagina +label.work = Werk +label.xmpp.port = &XMPP poort +label.krb.realm = Realm +label.krb.kdc = KDC +label.which.pki.method = Welke PKI methode? +label.choose.file = Selecteer bestand +label.trust.store.password = Wachtwoord certificaatbestand +label.enter.password = Voer wachtwoord in +label.move.focus.forwards = Verplaats focus voorwaards +label.move.focus.backwards = Verplaats focus terug +label.keystore.location = Locatie keystore bestand +label.truststore.location = Locatie certificaatbestand +label.pkcs.library.file = PKCS#11 bibliotheekbestand +label.x509.certificate = X.509 certificaat +label.apple.keychain = Apple KeyChain +label.add.to.roster = Voeg gebruiker toe aan uw contactlijst +label.audio.device = &Audioapparaat +label.video.device = &Videoapparaat +label.certificate.version = Versie +label.certificate.serial.number = Serienummer +label.certificate.signature.value = Handtekening waarde +label.certificate.signature.algorithm = Handtekening algoritme +label.certificate.issuer = Uitgever +label.certificate.subject = Onderwerp +label.certificate.not.before = Niet geldig voor +label.certificate.not.after = Niet geldig na +label.certificate.public.key = Publieke sleutel +label.certificate.public.key.algorithm = Publieke sleutel algoritme +label.certificate.issuer.unique.id = Uitgever unieke ID +label.certificate.subject.unique.id = Onderwerp unieke ID +label.certificate.add.certificate.to.truststore = Voeg certificaat to aan certificaatbestand +label.certificate.add.certificate.to.identitystore = Voeg certificaat toe aan identiteitsbestand +label.certificate.status = Status van het certificaat + +menuitem.about = Over +menuitem.actions = Acties +menuitem.bookmarks = Favorieten +menuitem.add = Toevoegen +menuitem.add.as.contact = Voeg als contact toe +menuitem.add.contact = Contact toevoegen +menuitem.add.contact.group = Contactgroep toevoegen +menuitem.add.groupchat.myname = Markeer mijn &naam als iemand dat noemt +menuitem.add.groupchat.mytext = Markeer mijn tekst als iemand die noemt (&h) +menuitem.add.groupchat.popname = Toon &toast popup als iemand mijn naam zegt +menuitem.add.groupchat.showjoinleavemessage = Toon toetreed- en vertrekberichten (&s) +menuitem.add.groupchat.showrolesinsteadofstatus = Toon chat rol iconen in plaats van aanwezigheid +menuitem.add.groupchat.auto.accept.invite = &Accepteer groep chat uitnodigingen automatisch +menuitem.add.groupchat.random.colors = Namen hebben een willekeu&rige kleur +menuitem.affiliation = Affiliatie +menuitem.always.on.top = Altijd bovenop +menuitem.alert.when.online = Melding wanneer gebruiker beschikbaar is +menuitem.ban = Verbannen +menuitem.ban.user = Verban gebruiker +menuitem.block.contact = Blokkeer contact +menuitem.block.user = Blokkeer gebruiker +menuitem.broadcast.to.group = Bericht aan hele groep versturen +menuitem.browse.service = In dienst bladeren +menuitem.change.nickname = Verander alias +menuitem.change.subject = Onderwerp veranderen +menuitem.chat = Conversatie +menuitem.check.for.updates = Controleer op updates +menuitem.connect = File +menuitem.contacts = Contacten +menuitem.copy.to = Kopiëren naar +menuitem.delete = Verwijderen +menuitem.delete.login.information = Verwijder aanmeldingsinformatie +menuitem.destroy.room = Ruimte opheffen +menuitem.dial = Bellen +menuitem.edit = Bewerken +menuitem.edit.my.profile = Mijn profiel &bewerken +menuitem.edit.status.message = Eigen statusmeldingen bewerken +menuitem.enter.login.information = Geef aanmeldingsinformatie +menuitem.exit = Afsluiten +menuitem.grant.moderator = Maak moderator +menuitem.grant.member = Verleen Lidmaatschap +menuitem.grant.admin = Verleen Administratie-rechten +menuitem.grant.owner = Verleen Eigenaarschap +menuitem.grant.voice = Geef stemrecht +menuitem.help = Help +menuitem.hide = Verbergen +menuitem.invite.group.to.conference = Groep voor conferentie uitnodigen +menuitem.invite.users = Gebruikers uitnodigen +menuitem.join.on.startup = Meedoen bij opstarten +menuitem.join.room = Ruimte binnengaan +menuitem.kick.user = Verwijder gebruiker +menuitem.languages = Talen +menuitem.logout.no.status = Afmelden +menuitem.logout.with.status = Afmelden met reden +menuitem.lookup.profile = Profiel &opzoeken +menuitem.move.to = Verplaatsen naar +menuitem.online.help = Spark Fora +menuitem.open = Openen +menuitem.open.with = Open met... +menuitem.plugins = Plugins +menuitem.preferences = Voorkeuren +menuitem.remove = Verwijder +menuitem.remove.alert.when.online = Verwijder waarschuwing +menuitem.remove.bookmark = Bladwijzer verwijderen +menuitem.remove.from.group = Uit groep verwijderen +menuitem.remove.from.roster = Uit Rooster Verwijderen +menuitem.unblock.contact = Deblokkeer contact +menuitem.remove.service = Dienst verwijderen +menuitem.rename = Hernoemen +menuitem.revoke.moderator = Geen moderator meer +menuitem.revoke.voice = Trek stemrecht in +menuitem.revoke.member = Trek Lidmaatschap in +menuitem.revoke.admin = Trek Administratie-rechten in +menuitem.revoke.owner = Trek Eigenaarschap in +menuitem.save = Opslaan +menuitem.save.as = Opslaan als +menuitem.send.a.file = Bestand versturen +menuitem.send.a.message = Bericht versturen aan geselecteerde gebruikers +menuitem.set.status.message = Statusmelding instellen +menuitem.show.empty.groups = Lege groepen tonen +menuitem.show.offline.group = Afgemeldde gebruikers in aparte groep +menuitem.show.traffic = Debug- en verkeersmonitor +menuitem.sign.in = Aanmelden +menuitem.sign.in.at.login = Automatisch aanmelden +menuitem.sign.out = Afmelden +menuitem.start.a.chat = Conversatie beginnen +menuitem.start.a.conference = Conferentie beginnen +menuitem.status = Status +menuitem.subscribe.to = Abonneer op +menuitem.unban = Weer toestaan +menuitem.unblock.user = Deblokkeer gebruiker +menuitem.user.guide = Gebruikers Handleiding +menuitem.view.client.version = Clientversie +menuitem.view.contact.history = Geschiedenis bekijken +menuitem.view.downloads = Gedownloade bestanden +menuitem.view.last.activity = Laatste activiteit bekijken +menuitem.view.logs = Logboeken bekijken +menuitem.view.profile = Profiel bekijken +menuitem.view.room.info = Informatie ruimte bekijken +menuitem.voice = Stemrecht +menuitem.show.offline.users = Toon offline gebruikers +menuitem.show.contact.statusmessage = Toon statusbericht +menuitem.bookmark.room = Voeg ruimte toe aan favorieten +menuitem.refresh = Ververs +menuitem.create.room = Creëer of treedt ruimte binnen +menuitem.expand.all.groups = Klap alle groepen uit +menuitem.collapse.all.groups = Klap alle groepen in +menuitem.invite.again = Nodig opnieuw uit +menuitem.chatframe.option = Opties +menuitem.add.groupchat.invitetobookmark = Nodig gebruikers automatisch uit in ruimte die in de lijst met favorieten staat +menuitem.certificate.files.filter = Bestand met certificaat (*.cert), (*.crt), (*.der) + +message = &Bericht +message.account.create = Maak een nieuwe account aan. +message.account.created = Nieuwe account is aangemaakt. +message.account.error = Geef de server waar de account op moet worden aangemaakt op. +message.add.a.contact = Contact toevoegen... +message.add.conference.service = Conferentiedienst toevoegen. +message.add.contact.to.list = Voeg een gebruiker toe aan de lijst met contacten. +message.add.favorite.room = Voeg ruimte toe aan de favorietenlijst of ga meteen naar binnen. +message.add.this.user.to.your.roster = Voeg deze gebruiker aan de contactlijst toe. +message.add.to.roster = Aan contactlijst toevoegen +message.add.user = Gebruiker aan contactlijst toevoegen? +message.alert.notify = Waarschuwing +message.already.exists = Account bestaat reeds. Probeer een andere gebruikersnaam. +message.approve.subscription = Sta {0} toe om mij aan hun rooster toe te voegen? +message.authenticating = Bezig met authoriseren... +message.away.idle = Afwezig wegens inactiviteit. +message.bookmark.temporary.room.error = Kan geen bladwijzers maken van tijdelijke ruimtes. +message.broadcast.from = Bericht van {0} +message.broadcast.no.user.selected = Selecteer minstens één ontvanger +message.broadcast.no.text = Voer tekst om uit te zenden in +message.broadcast.message.sent = Het bericht is verzonden. +message.broadcast.to = Geef bericht om te versturen aan {0} +message.hasbeenbroadcast.to = Het bericht is verstuurd naar de volgende gebruikers:\n{0} +message.buzz.alert.notification = Vraagt de gebruiker om aandacht. +message.buzz.message = {0} vraagt uw attentie +message.buzz.sent = Melding naar gebruiker verstuurd. +message.calling = Belt {0} +message.came.online = {0} is online gekomen op {1} +message.cannot.add.contact.to.shared.group = Er kunnnen geen contacten worden toegevoegd aan gedeelde groepen. +message.cert.hostname.verification.failed = Certificaat hostnaamverificatie is gefaald +message.cert.verification.failed = Certificaat kan niet worden gevalideerd +message.chat.session.ended = Conversatie is geëindigd op {0} +message.click.to.open = Klik om te openen +message.client.information = Client informatie van {0} +message.close.other.chats = Sluit alle andere conversaties +message.close.stale.chats = Sluit bevroren conversaties +message.close.this.chat = Sluit deze conversatie +message.close.unread.window = U heeft ongelezen berichten, weet u zeker dat u het venster wilt sluiten? +message.conference.info.error = Informatie over de conferentie kon niet worden verkregen worden. Probeer a.u.b. later nog eens. +message.conference.service.error = Kon de conferentiedienst niet vinden. +message.confirm.destruction.of.room = Bij het opheffen van de ruimte worden alle gebruikers uit de ruimte verwijderd. Doorgaan? +message.confirmation.password.error = Bevestig het opgegeven wachtwoord. +message.connecting.please.wait = Bezig met verbinden. Een moment a.u.b.... +message.connection.failed = Geen verbinding mogelijk met {0}. +message.create.account = Account kon niet worden aangemaakt. +message.create.or.join.room = Maak of doe mee in een conferentie ruimte +message.current.status = Toon anderen de huidige status of activiteit. +message.default.error = Er is een fout veroorzaakt. Meld deze a.u.b. aan support@jivesoftware.com. +message.delete.all.history = Alle voorgaande conversaties verwijderen? +message.delete.confirmation = {0} echt verwijderen? +message.disable.transport = De aanmeldingsgegevens uit {0} verwijderen? +message.disconnected.conflict.error = De verbinding werd verbroken omdat dezelfde gebruiker op een andere locatie is aangemeld. +message.disconnected.error = De verbinding werd verbroken door een fout. +message.disconnected.group.chat.error = De verbinding werd verbroken door een fout. Na heraanmelden zult u deze ruimte opnieuw moeten binnengaan. +message.disconnected.shutdown = De verbinding werd verbroken omdat de server uitgeschakeld werd. +message.downloading = Bezig met downloaden van {0} +message.downloading.spark.plug = Spark-Plug downloaden +message.end.chat = Deze conversatie beëindigen? +message.end.conversation = Deze sessie beëindigen? +message.enter.broadcast.message = Bericht om aan geselecteerde gebruikers te versturen: +message.enter.gadugadu = Voer uw GaduGadu gebruikersnaam en wachtwoord hieronder in. +message.enter.irc = Voer uw IRC gebruikersnaam, wachtwoord en bijnaam hieronder in +message.enter.sametime = Voer uw Sametime gebruikersnaam en wachtwoord hieronder in +message.enter.facebook = Voer uw Facetime gebruikersnaam en wachtwoord hieronder in +message.enter.myspace = Voer uw MySpace gebruikersnaam en wachtwoord hieronder in +message.enter.jabber.id = Geef Jabber ID +message.enter.message.to.broadcast = Geef bericht om naar de hele contactlijst te versturen. +message.enter.new.subject = Geef het nieuwe onderwerp +message.enter.qq = Voer uw QQ gebruikersnaam en wachtwoord hieronder in +message.enter.room.password = Geef wachtwoord voor de ruimte +message.enter.simple = Voer uw SIMPLE gebruikersnaam en wachtwoord hieronder in +message.enter.valid.jid = Geef een geldige Jabber ID op. +message.enter.xmpp = Geef XMPP gebruikersnaam en wachtwoord. +message.error.during.file.transfer = Er was een fout gedurende de overdracht. +message.error.must.use.reserved.nick = In deze ruimte moet een gereserveerde bijnaam gebruikt worden. +message.error.nickname.in.use = Uw gewenste bijnaam is al in gebruik of gereserveerd door iemand anders. +message.error.no.permission.create.room = U heeft geen permissie om een ruimte te ceëeren. +message.error.no.response = Geen antwoord van de server. +message.error.not.member = U bent geen lid van deze ruimte.\nDeze ruimte vereist een lidmaatschap. +message.error.room.not.exist = De ruimte die u probeert binnen te treden bestaat niet. +message.error.room.password.incorrect = Het wachtwoord komt niet overeen met het wachtwoord van de ruimte. +message.error.unable.join.room = Het is niet gelukt om de ruimte te betreden. +message.file.exists.question = Het bestand bestaat reeds. Overschrijven? +message.file.size = Formaat: {0} +message.file.transfer.canceled = Bestandsoverdracht werd geannuleerd. +message.file.transfer.rejected = Het bestand werd geweigerd door {0}. +message.file.transfer.dirnull = De folder om binnenkomende bestanden in op te slaan is niet valide. +message.file.transfer.nodir = De folder om binnenkomende bestanden in op te slaan bestaat niet. +message.file.transfer.cantwritedir = Kan niet schrijin in de folder om binnenkomende bestanden in op te slaan. +message.file.transfer.notification = Notificatie van verzenden van bestand +message.file.transfer.short.message = verstuurt u een bestand genaamd: +message.file.transfer.chat.window = Verzoek om bestand te versturen: +message.file.transfer.file.too.big.error = Het geselecteerde bestand is te groot.\nDe maximale bestandsgrootte is {0}. Het geselecteerde bestand is: {1} +message.file.transfer.file.too.big.warning = Het geselecteerde bestand is te groot.\nToch doorgaan? +message.file.transfer.direrror.setdir = Klik hier om de folder aan te passen +message.file.transfer.history.request.sent = Verzoek om bestand "{0}" ({1}) te sturen is verzonden naar {2}. +message.file.transfer.history.send.complete = Bestand "{0}" is succesvol naar {1} verzonden. +message.file.transfer.history.send.error = Het verzenden van bestand "{0}" naar {1} is mislukt. +message.file.transfer.history.send.canceled = Het verzenden van bestand "{0}" naar {1} is geannuleerd. +message.file.transfer.history.contact.rejected = {1} heeft het verzoek om bestand "{0}" te versturen afgewezen. +message.file.transfer.history.request.received = Verzoek om bestand "{0}" ({1}) te versturen is ontvangen van {2}. +message.file.transfer.history.you.rejected = U heeft het verzoek van {1} om bestand "{0}" te zender afgewezen. +message.file.transfer.history.you.accepted = U heeft het verzoek van {1} om bestand "{0}" te zender geaccepteerd. +message.file.transfer.history.receive.success = Bestand "{0}" is succesvol van {1} ontvangen. +message.file.transfer.history.receive.failed = Het ontvangen van bestand "{0}" van {1} is mislukt. +message.file.transfer.history.receive.canceled = Het ontvangen van bestand "{0}" van {1} is geannuleerd. +message.find.conference.services = Zoek conferentie diensten. +message.forbidden.error = Verboden fout van de server ontvangen. +message.gateway.username.error = Gebruikersnaam dient opgegeven te worden +message.gateway.password.error = Wachtwoord dient opgegeven te worden +message.gateway.nickname.error = Bijnaam dient opgegeven te worden +message.general.error = De verbinding met de server werd verbroken door {0}. +message.generic.reconnect.message = De verbinding met de server is verbroken. Om opnieuw aan te melden, klik op "Opnieuw". +message.idle.for = Geen activiteit in de afgelopen {0} minuten +message.image.small.resolution = Afmeting van afbeelding is kleiner dan 32x32 pixels +message.invalid.jabber.id = Geen geldige Jabber ID +message.invalid.jid.error = De opgegeven JID is ongeldig. +message.invalid.status = Geef een geldige statusmelding op. +message.invalid.username.password = Verkeerde gebruikersnaam of wachtwoord. +message.invite.to.groupchat = {0} nodigt u uit om deel te nemen in een groepsgesprek. +message.invite.users.to.conference = Nodig gebruikers uit in een conferentieruimte. +message.is.shared.group = {0} is een gedeelde groep. +message.is.typing.a.message = {0} typt een bericht... +message.join.conference.room = Conferentie ruimte binnengaan +message.kicked.error = Ik kan {0} niet uit deze ruimte schoppen. +message.last.message.received = Laatste bericht ontvangen op {0} +message.loading.please.wait = Bezig met laden. Moment geduld a.u.b.... +message.locked.workstation = Gebruiker heeft de werkplek op slot gezet. +message.name.of.group = Groepnaam: +message.name.of.search.service.question = Naam van zoekdienst? +message.negotiate.file.transfer = Bestandsoverdracht wordt opgezet. Moment geduld a.u.b.... +message.negotiate.stream = Datastroom wordt opgezet. Moment geduld a.u.b.... +message.negotiation.file.transfer = Overdracht met {0} aan het opzetten. Moment geduld a.u.b.... +message.new.message = Nieuw bericht van {0}. +message.new.spark.available = {0} is nu beschikbaar. Deze nu installeren? +message.nickname.error = Bijnaam moet opgegeven worden +message.nickname.in.use = Alias reeds in gebruik. Geef een andere alias op. +message.nickname.not.acceptable = Het wijzigen van een bijnaam is niet ingeschakeld! +message.no.avatar.found = Gebruiker heeft geen avatar ingesteld. +message.no.caller.id = Geen nummer beschikbaar. +message.no.description.available = Geen beschrijving beschikbaar +message.no.history.found = Er is geen conversatie geschiedenis met deze gebruiker. +message.no.results.found = Er waren geen resultaten. +message.no.room.to.join.error = Geen ruimtes om binnen te gaan. +message.no.subject.available = Geen onderwerp beschikbaar +message.no.updates = Er zijn geen updates. +message.normal = Normaal bericht +message.number.to.call = Nummer om te bellen +message.offline = De gebruiker is niet aangemeld, maar zal het bericht ontvangen bij de eerstvolgende aanmelding. +message.offline.error = De gebruiker zal niet in staat zijn om offline berichten te ontvangen. +message.participants.in.room = Aanwezigen in ruimte +message.password.error = Geef een wachtwoord op. +message.password.private.room.error = Geef wachtwoord voor de privé ruimte. +message.passwords.no.match = Wachtwoorden komen niet overeen. +message.please.join.in.conference = Doe mee aan mijn conferentie. +message.plugins.not.available = Plugin server is onbereikbaar. +message.prompt.plugin.uninstall = Plugin {0} deïnstalleren? +message.received.file = Bestand van {0} ontvangen. +message.receiving.file = Bestand van {0} wordt ontvangen. +message.reconnect.attempting = Herverbinden... +message.reconnect.failed = Herverbinden mislukt. +message.reconnect.wait = Herverbinden over {0} seconden. +message.register.transports = Registreer bij deze beschikbare koppeling. +message.registering = Registreren bij {0}. Een moment a.u.b.... +message.registration.transport.failed = Registratie bij transport is mislukt. +message.restart.spark = De client moet worden afgesloten \n om de nieuwe versie te installeren. Nu direct afsluiten? +message.restart.spark.changes = Plugin zal verwijderd worden bij eerstvolgende start van Spark. +message.restart.spark.to.install = Spark moet opnieuw gestart worden om de laatste versie te installeren. Nu opnieuw starten? +message.restart.required = Spark moet opnieuw gestart worden om deze wijzigingen toe te passen. Nu opnieuw starten? +message.room.creation.error = De ruimte kon niet aangemaakt worden. +message.room.destroyed = Deze ruimte is opgeheven om de volgende reden: +message.room.destruction.reason = Reden voor de opheffing van de ruimte? +message.room.information.for = Informatie ruimte voor {0} +message.save.profile = Om wijzigingen in het profiel op te slaan, klik Opslaan. +message.search.for.contacts = Zoek naar contacten. +message.search.input.short = Voer minstens twee letters in. +message.search.for.other.people = Andere personen zoeken op deze server +message.search.service.not.available = De zoekdienst is onbereikbaar. +message.searching.please.wait = Bezig met zoeken. Moment geduld a.u.b.... +message.select.add.room.to.add = Kies een ruimte om aan de dienstenlijst toe te voegen. +message.select.one.or.more = Selecteer één of meer gebruikers in de contactlijst. +message.select.room.to.enter = Geef ruimte om binnnen te gaan. +message.select.room.to.join = Kies een ruimte om binnen te gaan. +message.send.a.broadcast = Bericht versturen +message.send.file.to.user = Verstuur bestand(en) naar deze gebruiker. +message.send.picture = Verstuur afbeelding van wat er op het scherm staat. +message.send.to.these.people = Verstuur naar deze personen +message.sending.file.to = Bezig met verzenden bestand naar {0}. +message.sent.offline.files = Offline bestand(en) ontvangen. +message.server.unavailable = Kan geen verbinding met de server krijgen: Ongeldige naam of server onbereikbaar. +message.service.already.exists = Dienst staat reeds in de lijst. +message.shared.group = Gedeelde groep +message.specify.contact.jid = Geef het JID van het contact op (bijv. ddman@jabber.org) +message.specify.group = Geef een groep voor de nieuwe gebruiker op. +message.specify.information.for.conference = Geef informatie voor de conferentieruimte. +message.specify.name.error = Geef een geldige naam op. +message.specify.users.to.join.conference = Geef gebruikers op die meedoen aan deze conferentie. +message.specify.valid.time.error = Geef een geldige maximumtijd en poort op. +message.subject.change.error = Onvoldoende rechten om het onderwerp van de ruimte te veranderen. +message.subject.has.been.changed.to = Het onderwerp is veranderd naar {0}. +message.supply.resource = Geef een geldig medium op. +message.supply.valid.port = Geef een geldige poort op. +message.supply.valid.timeout = Geef een geldige antwoordtijd op. +message.timeout.error = De tijd moet minimaal 5 seconden zijn. +message.total.downloaded = Totaal gedownload +message.transfer.cancelled = De overdracht werd geannuleerd. +message.transfer.complete = Het versturen van het bestand is voltooid ({0}) +message.transfer.progressbar.text.received = {0} ontving @ {1} {2} +message.transfer.progressbar.text.sent = {0} verzond @ {1} {2} +message.transfer.rate = Snelheid +message.transfer.refused = Het bestand werd geweigerd. +message.transfer.waiting.on.user = Wacht op {0} om bestand te accepteren. +message.unable.to.load.profile = Kan profiel van {0} niet vinden. +message.unable.to.retrieve.last.activity = Laatste activiteit ophalen voor {0} mislukt. +message.unable.to.save.password = Wachtwoord kon niet worden gewijzigd. Neem contact op met de server beheerder. +message.unable.to.send.file = Bestand naar {0} versturen mislukt. +message.unable.to.use.hostname.as.resource = Niet mogelijk om hostnaam als resource te gebruiken +message.unrecoverable.error = Verkeerde gebruikersnaam of wachtwoord. +message.update.room.list = Lijst van ruimtes bijwerken +message.updating.cancelled = Bijwerken is geannuleerd. +message.user.banned = {0} is uit deze ruimte verbannen. +message.user.given.voice = {0} heeft stemrecht in deze ruimte gekregen. +message.user.granted.admin = {0} heeft beheerdersrechten gekregen. +message.user.granted.membership = {0} heeft lidmaatschapsrechten gekregen. +message.user.granted.moderator = {0} heeft moderator rechten gekregen. +message.user.granted.owner = {0} heeft eigenaarsrechten gekregen. +message.user.is.sending.you.a.file = {0} probeert een bestand op te sturen. +message.user.joined.room = {0} is de ruimte binnengekomen. +message.user.kicked.from.room = {0} is uit de ruimte verwijderd. +message.user.left.room = {0} heeft de ruimte verlaten. +message.user.nickname.changed = {0} staat voortaan bekend als {1}. +message.user.now.available.to.chat = {0} is online op {1} +message.user.revoked.admin = Beheerdersrechten van {0} zijn ingetrokken. +message.user.revoked.membership = Lidmaatschap van {0} is ingetrokken. +message.user.revoked.moderator = Moderator rechten van {0} zijn ingetrokken. +message.user.revoked.owner = Eigenaarsrechten van {0} zijn ingetrokken. +message.user.voice.revoked = Stemrecht van {0} is ingetrokken. +message.username.error = Geef een gebruikersnaam op. +message.username.password.error = Gebruikersnaam en/of wachtwoord moeten gegeven worden. +message.vcard.not.supported = De server heeft geen ondersteuning voor VCards. VCard kon niet worden opgeslagen. +message.version = Versie: {0} +message.view.information.about.this.user = Bekijk informatie over deze gebruiker. +message.waiting.for.user.to.join = Wacht op {0} om mee te doen. +message.went.offline = {0} is offline gegaan op {1} +message.you.have.been.banned = Ik ben verbannen uit deze ruimte. +message.you.have.been.kicked = Ik ben uit deze ruimte geschopt. +message.you.have.sent = Bestand naar {0} verstuurd. +message.your.admin.granted = Beheerdersrechten verkregen. +message.your.banned = Verbannnen uit deze ruimte. +message.your.kicked = Verwijderd door {0}. +message.your.membership.granted = Lidmaatschapsrechten verkregen. +message.your.membership.revoked = Lidmaatschap ingetrokken. +message.your.moderator.granted = Moderatorrechten verkregen. +message.your.moderator.revoked = Moderatorrechten ingetrokken. +message.your.ownership.granted = Eigenaarsrechten verkregen. +message.your.ownership.revoked = Eigenaarsrechten ingetrokken. +message.your.revoked.granted = Beheerdersrechten ingetrokken. +message.your.voice.granted = Stemrecht in deze conversatie gekregen. +message.your.voice.revoked = Stemrecht in deze conversatie ingetrokken. +message.groupchat.require.password = Deze gespreksruimte vereist een wachtwoord +message.groupchat.registered.member = Succesvol geregistreerd bij {0} +message.search.for.history = Doorzoek conversatiegeschiedenis +message.search.period.day.one = een dag per pagina +message.search.period.week.one = een week per pagina +message.search.period.month.one = een maand per pagina +message.search.period.year.one = een jaar per pagina +message.search.period.none = toon alles op een pagina +message.search.page.timeperiod = kies de tijdspanne van de berichten die getoond worden per pagina +message.search.page.counter = de huidige index van uw pagina en het totaal aantal pagina's +message.search.page.right = navigeer één pagina vooruit +message.search.page.left = navigeer één pagina achteruit + +status.away = Afwezig +status.custom.messages = Statusmeldingen +status.do.not.disturb = Niet storen +status.extended.away = Langdurig afwezig +status.free.to.chat = Vrij om te praten +status.on.phone = Aan de telefoon +status.online = Aanwezig +status.pending = In aanvraag +status.invisible = Onzichtbaar +status.offline = Offline + +tab.available.plugins = Beschikbare plugins +tab.avatar = Avatar +tab.business = Zakelijk +tab.conferences = Conferenties +tab.contacts = Contacten +tab.deactivated.plugins = Gedeactiveerde plugins +tab.general = Algemeen +tab.security = Beveiliging +tab.home = PrivÂŽ +tab.installed.plugins = Ge•nstalleerde plugins +tab.personal = Persoonlijk +tab.proxy = Proxy +tab.sso = SSO +tab.pki = PKI +tab.certificates = Certificaten +tab.mutual.auth = Wederzijdige authenticatie +title.about = Versie informatie +title.advanced.connection.preferences = Geavanceerde verbindingsinstellingen +title.account.create.registration = Accountregistratie +title.account.created = Account aangemaakt +title.add.contact = Contact toevoegen +title.add.contact.group = Contactgroep toevoegen +title.add.new.group = Voeg groep toe +title.add.search.service = Toevoegen Zoekdienst. +title.add.to.roster = Voeg aan contactlijst toe +title.address = Adres +title.advanced.connection.sso = Gebruik Single Sign-On (SSO) +title.advanced.connection.usesso = Gebruik Single Sign-On (SSO) via GSSAPI +title.advanced.connection.sso.account = Dit gebruikt het Desktop Account voor "{0}" om in te loggen op de server. +title.advanced.connection.sso.unable = Niet mogelijk om te verbinden met Single Sign-On. Controleer uw principal en serverinstellingen. +title.advanced.connection.sso.noprincipal = Spark is niet in staat om de principal te vinden die gebruikt dient te worden voor Single Sign-On. Hierdoor kan SSO niet werken. +title.advanced.connection.sso.smack3compat = Smack 3 compatibiliteitsmodus +title.alert = Waarschuwing +title.appearance = Uiterlijk +title.appearance.preferences = Vormgeving uiterlijk +title.available.transports = Beschikbare koppelingen +title.bookmarks = Favorieten +title.broadcast.message = Bericht versturen +title.broadcast.history = Geschiedenis omroepberichten +title.browse.conference.services = Conferentie diensten bladeren +title.browse.room.service = Conferentieruimtes bladeren - {0} +title.cancelled = Geannuleerd +title.change.nickname = Wijzig alias +title.change.subject = Verander onderwerp +title.chat = Conversatie +title.choose.directory = Kies directory +title.choose.incoming.sound = Binnenkomend geluid kiezen +title.choose.offline.sound = Offline geluid kiezen +title.choose.outgoing.sound = Uitgaand geluid kiezen +title.client.logs = Client logs +title.conference.invitation = Conferentie uitnodiging +title.conference.rooms = Conferentieruimtes +title.configure.chat.room = Configureer Conversatie ruimte +title.configure.room = Eigenschappen ruimte +title.confirmation = Bevestiging +title.create.new.account = Nieuwe account +title.create.or.bookmark.room = Bladwijzer maken of ruimte binnengaan +title.create.room = Aanmaken +title.create.problem = Probleem bij aanmaken account +title.delete.file = Weet u zeker dat u dit bestand wilt verwijderen? +title.dial.phone = Bellen +title.disable.transport = Aanmeldgegevens verwijderen +title.download.complete = Download Voltooid +title.downloading.im.client = IM client aan het downloaden +title.downloads = Downloads +title.edit.custom.message = Eigen statusmeldingen bewerken +title.edit.profile = Profielinformatie bewerken +title.enter.reason = Geef reden op +title.error = Fout +title.error.couldnot.open.file = Kan bestand niet openen +title.error.delete.file = Kan bestand niet verwijderen +title.error.find.app = Kan geen overeenkomstige applicatie vinden +title.error.rename.file = Kan het bestand niet hernoemen +title.file = Bestand +title.filesize = Grootte +title.file.exists = Bestand bestaat reeds +title.file.transfer = Bestandsoverdracht +title.file.transfer.preferences = Voorkeuren bestandsoverdracht +title.find.conference.service = Conferentie dienst zoeken +title.find.contacts = Zoek contacten +title.gadugadu.registration = Inloggegevens GaduGadu +title.general.media = Media-instellingen +title.general.chat.settings = Algemene conversatie instellingen +title.group.chat = Groepsconversatie +title.group.chat.settings = Groepsgesprek-instellingen +title.history.for = Conversatiegeschiedenis met {0} +title.irc.registration = Inloggegevens IRC +title.sametime.registration = Inloggegevens Sametime +title.facebook.registration = Inloggegevens Facebook +title.myspace.registration = Inloggegevens MySpace +title.incoming.call = Binnenkomend gesprek +title.input.fileexplorer = Voer de naam van uw bestandsverkenner in: +title.input.newname = Voer de nieuwe naam in: +title.input.openwith = Voer de naam van de applicatie die u wilt gebruiken in: +title.invite.to.conference = Uitnodigen voor conferentie +title.jabber.browser = Browser +title.join.conference.room = Conferentie ruimte binnengaan +title.last.activity = Laatste activeit +title.login = Aanmelden +title.login.error = Fout bij aanmelden +title.login.settings = Instellingen aanmelden +title.login.no.account = Niet in staat om te bepalen +title.lookup.profile = Zoek profiel op +title.name = Naam +title.new.client.available = Nieuwe client beschikbaar +title.new.roster.group = Nieuwe contactgroep +title.new.version.available = Nieuwe versie beschikbaar +title.no.updates = Meest recente versie aanwezig +title.notes = Notities +title.notification = Melding +title.notifications = Meldingen +title.occupants = Aanwezigen +title.on.the.phone = Aan de telefoon +title.password = Wachtwoord +title.password.required = Wachtwoord vereist +title.passwords.no.match = Controleer wachtwoorden +title.person.search = Personen zoeken +title.plugins = Plugins +title.preferences = Voorkeuren +title.profile.information = Profielinformatie +title.profile.not.found = Profiel niet gevonden +title.qq.registration = Inloggegevens QQ +title.register.account = Registreer nieuwe account +title.registration.error = Registratie fout +title.reminder = Herinnering +title.rename.roster.group = Hernoem Groep +title.room.destroyed = Ruimte opgeheven +title.room.information = Ruimte informatie +title.roster = Contactlijst +title.select.file.to.send = Selecteer bestanden +title.set.status.message = Statusmelding instellen +title.simple.registration = Inloggegevens SIMPLE +title.sound.preferences = Geluidsvoorkeuren +title.sounds = Geluiden +title.spark.preferences = Spark voorkeuren +title.start.chat = Conversatie beginnen +title.status.message = Statusmelding +title.task.notification = Taak notificatie +title.tasks = Nog te doen +title.transports = Koppelingen +title.tray.information = Systeemvak informatie +title.upgrading.client = Client aan het upgraden +title.version.and.time = Versie en tijd +title.view.bookmarks = Bladwijzers bekijken +title.view.profile.for = Profiel van {0} +title.view.room.information = Ruimte informatie +title.waiting.to.call = Wacht met bellen +title.warning = Waarschuwing +title.xmpp.registration = XMPP Aanmeldingsgegevens +title.appearance.showVCards = Toon &VCards in de contactlijst +title.subscription.request = Abonnementsverzoek +title.certificate = Certificaat + +time.days = d +time.hours = h +time.minutes = min +time.since = sinds +time.less.than.one.minute = minder dan 1 minuut + +tooltip.place.a.call = Bel met dit individue +tooltip.appearance = Verander het uiterlijk en de vormgeving van de conversaties. +tooltip.file.transfer = Instellingen voor het verzenden en ontvangen van bestanden. +tooltip.notifications = Meldingsvoorkeuren voor binnenkomende conversaties. +tooltip.place.voice.call = Bel deze persoon op +tooltip.send.email = Verstuur een e-mail +tooltip.start.chat = Begin een gesprek +tooltip.view.changelog = Bekijk wijzigingslogboek +tooltip.view.history = Bekijk conversatie geschiedenis +tooltip.view.readme = Lees ReadMe +tooltip.encryptionmode.required = Voor deze verbinding is versleuteling vereist. Als de server geen versleuteling aanbiedt, of als de versleutelingsonderhandeling faalt, dan zal er niet met de server verbonden worden. +tooltip.encryptionmode.ifpossible = Versleuteling zal worden gebruikt als het beschikbaar is. +tooltip.encryptionmode.disabled = Versleuteilng is uitgeschakeld. Er worden alleen niet-versleutelde connecties gebruikt. Als de server versleuteling vereist, dan zal de verbinding niet tot stand komen. + +tree.conference.services = Conferentie diensten +tree.users.in.room = Gebruikers in ruimte + +lookandfeel.select = Selecteer Look & Feel +lookandfeel.change.now = Verander nu +lookandfeel.tooltip.restart.no = Geen herstart nodig +lookandfeel.tooltip.restart.yes = Om de Look&Feel te veranderen, druk op Opslaan en start Spark opnieuw op. +lookandfeel.color.label = Kleur +lookandfeel.color.red = Rood +lookandfeel.color.green = Groen +lookandfeel.color.blue = Blauw +lookandfeel.color.opacity = Ondoorzichtigheid +lookandfeel.color.saved = Kleur opgeslagen + + +##Settings for the privacy plugin +privacy.title.preferences = Spark Privacy Instellingen +privacy.title.panel = Gebruik rechter muisknop +privacy.label.iq.desc = Vraag +privacy.label.pin.desc = Binnenkomende statusinformatie +privacy.label.pout.desc = Uitgaande statusinformatie +privacy.label.msg.desc = Berichten +privacy.border.information = Privacy informatie +privacy.label.information = Gebruik het menu onder de rechter muisknop om lijsten of elementen te verwijderen of toe te voegen +privacy.root.node = Privacy Lijsten +privacy.label.preferences = Privacy Plugin +privacy.tooltip.preferences = Spark privacy instellingen +privacy.label.list.is.active = Lijst die nu actief is: +privacy.label.list.is.default = Standaard lijst: +privacy.border.block = Blokkeren +privacy.pick.one.or.more = Kies een of meer elementen om toe te voegen aan de lijst +privacy.title.add.picker = Voeg elementen aan de lijst toe +privacy.node.contacts = Contacten +privacy.node.groups = Groepen +privacy.menu.add.contacts = Voeg Contacten toe aan lijst +privacy.menu.add.groups = Voeg groepen toe aan lijst +privacy.menu.add.rem.items = Verwijder {0} elementen van lijst +privacy.menu.remove = Verwijder +privacy.menu.activate.list = Activeer +privacy.menu.default.list = Als standaard instellen +privacy.menu.add.list = Voeg lijst toe +privacy.menu.remove.list = Verwijder lijst +privacy.dialog.add.list = Voer naam van lijst in +privacy.dialog.rem.list = Wilt u {0} verwijderen? +privacy.status.menu.entry = Privacy Lijsten +privacy.name.for.default.list = Standaard +privacy.button.no.list.selected = Geen lijst geselecteerd +privacy.menuitem.deactivate.current.list = Deactiveer {0} +privacy.label.not.supported = Privacy lijsten worden niet door de server ondersteund + +##Stunfallback in media settings +stun.border.label = STUN secondaire server +stun.server.addr = STUN server: +stun.server.port = STUN poort: + +##Text Field Hints +hint.login.username = Voer gebruikersnaam in +hint.login.password = Voer wachtwoord in +hint.login.domain = Voer domein in + +composing = {0} is aan het typen... +paused = {0} is gestopt met typen. +active = {0} is aan het opletten. +inactive = {0} is wat anders aan het doen. +gone = {0} is weggegaan. + +#!# +action.viewlog=Toon Log + +dialog.confirm.to.reveal.visibility.title=Weet u het zeker? +dialog.confirm.to.reveal.visibility.msg=Als u verder gaat dan zal uw onzichtbaarheid worden opgeheven +dialog.confirm.close.all.conferences.if.invisible.msg = Als u door wilt gaan dan worden alle gespreksruimtes gesloten +dialog.certificate.show = Dit is het certificaat en de privesleutel dat u probeert toe te voegen aan het certificaatbestand. Na deze te hebben toegevoegd zal Spark in staat zijn om beveiligde verbindingen met servers op te zetten als die servers geidentificeerd worden door dit certificaat. Als u zeker bent dat u dit certificaat wilt toevoegen, druk dan op de OK knop. +dialog.id.certificate.show = Dit is het certificaat dat u wilt toevoegen aan het certificaatbestand. Nadat u dit certificaat hebt toegevoegd zal Spark het gebruiken om zichzelf the authenticeren en de verbinding te versleutelen tijdens het opzetten van een verbinding met de server. Als u zeker bent dat u dit certificaat wilt toevoegen, druk dan op OK. +dialog.certificate.add.from.connection = Dit certificaat wordt gebruikt door de server waarmee u probeert te verbinden. Het certificaat bestaat niet in uw certificaatbestand, wat betekend dat het niet vertrouwd wordt en dat er geen verbinding met deze server kan worden opgezet. Wilt u dit certificaat vertrouwen en toevoegen aan het certificaatbestand? +dialog.certificate.unrecognized.server.certificate = De server waarmee verbonden wordt identificeert zichzelf met een certificaat
      dat niet wordt herkend door Spark. De details volgen hieronder. +dialog.certificate.ask.allow.self-signed = De server waarmee u verbindt identificeert zichzelf met een self-signed certificaat. De huidige configuratie van Spark verbiedt het gebruik van zulke certificaten. Wilt u die configuratie aanpassen en opnieuw proberen? +dialog.certificate.subject.label = Onderwerp: + +dialog.certificate.add.unrecognized.server.certificate = Wilt u dit certificaat toevoegen aan de collectie van certificaten die Spark accepteert? +dialog.certificate.chain.add.from.connection = Dit is de certificaatketen die door de server waarmee u verbindt wordt gebruikt. De certificaten staan niet in uw certificaatbestand, wat betekent dat u niet kunt verbinden. Wilt u de certificaten toevoegen? +dialog.certificate.cannot.have.copy = Dit certificaat staat al in uw certificaatbestand. +dialog.certificate.has.been.added = Certificaat toegevoegd aan certificaatbestand. +dialog.certificate.has.been.added.to.identity.store = Certificaat toegevoegd aan identiteitsbestand. +dialog.certificate.is.distrusted = Het certificaat is invalide en zou daarom niet vertrouwd moeten worden.\nAls u het toch wil vertrouwen, klik dan op de knop hieronder om een uitzondering toe te voegen. +dialog.certificate.sure.to.delete = Weet u zeker dat u dit certificaat wilt verwijderen?\nAls u dit certificaat verwijdert, dan kunt u geen versleutelde verbinding meer opzetten met servers die zichzelf met dit certificaat identificeren. +dialog.certificate.has.been.deleted = Certificaat is succesvol verwijderd. +dialog.self.signed.certificate.has.been.created = Self-Signed certificaat en privesleutel zijn gecreëerd in de folder: +dialog.certificate.request.has.been.created = Certificate Sign Request en privesleutel zijn gecreëerd in folder: +dialog.cannot.upload.certificate.might.be.ill.formatted = Kan het certificaat niet uploaden. Certificaat zou verkeerd geformatteerd kunnen zijn. +dialog.cannot.upload.certificate = Kan certificaat niet uploaden +dialog.certificate.title.certificate.not.in.truststore = Het certificaat bestaat niet in uw certificaatbestand + +cert.valid = Valide +cert.revoked = Ingetrokken +cert.expired = Verlopen +cert.not.valid.yet = Nog niet geldig +cert.self.signed = Self-signed +cert.sign.request = Certificate Signing Request +cert.self.signed.save.to.file = Sla certificaat op in bestand +cert.unknown.oid = Onbekende OID omschrijving. +cert.is.critical = Is critical: +cert.critical = Critical: +cert.not.critical = Not critical: +cert.common.name = Common name +cert.organization.unit = Organization unit +cert.organization = Organization +cert.country = Country +cert.city = City + +cert.extensions = Certificate extensions: +cert.extensions.unsupported = Unsupported extensions +cert.extension.extended.usage.digital.signature = Digital signature +cert.extension.extended.usage.non.repudiation = Non repudiation +cert.extension.extended.usage.key.encipherment = Key encipherment +cert.extension.extended.usage.data.encipherment = Data encipherment +cert.extension.extended.usage.key.agreement = Key agreement +cert.extension.extended.usage.key.cert.sign = Key cert sign +cert.extension.extended.usage.crl.sign = CRL sign +cert.extension.extended.usage.encipher.only = Encipher only +cert.extension.extended.usage.decipher.only = Decipher only +cert.extension.basic.constraints.is.ca = Is certificate authority +cert.extension.basic.constraints.path.length = Validation path length +cert.extension.name.constraints.permitted.subtrees = Permitted subtrees +cert.extension.name.constraints.excluded.subtrees = Excluded subtrees + +##OID's mapping +2.5.29.1 = X.509 old Authority Key Identifier +2.5.29.2 = Key attributes +2.5.29.3 = Certificate policies +2.5.29.4 = Key usage restrictions +2.5.29.5 = Policy mapping +2.5.29.6 = Subtree constraints +2.5.29.7 = Subject alternative name +2.5.29.8 = Issuer alternative name +2.5.29.9 = Subject directory attributes +2.5.29.10 = Basic constraints +2.5.29.11 = Certificate Extension +2.5.29.12 = Certificate Extension +2.5.29.13 = Certificate Extension +2.5.29.14 = Subject key identifier +2.5.29.15 = Key usage +2.5.29.16 = Private key usage period +2.5.29.17 = Subject alternative name +2.5.29.18 = Issuer alternative name +2.5.29.19 = Basic constraints +2.5.29.20 = CRL number +2.5.29.21 = Reason code +2.5.29.22 = Expiration date +2.5.29.23 = Hold instruction code +2.5.29.24 = Invalidity date +2.5.29.25 = CRL Distribution Points +2.5.29.26 = Issuing distribution point +2.5.29.27 = CRL indicator +2.5.29.28 = Issuing distribution point +2.5.29.29 = Certificate issuer +2.5.29.30 = Name constraints +2.5.29.31 = CRL distribution points +2.5.29.32 = Certificate policies +2.5.29.33 = Policy mappings +2.5.29.34 = Policy constraints +2.5.29.35 = Authority key identifier +2.5.29.36 = Policy constraints +2.5.29.37 = Extended key usage +2.5.29.38 = Authority attribute identifier +2.5.29.39 = Role specification certificate identifier +2.5.29.40 = CRL stream identifier +2.5.29.41 = basicAttConstraints +2.5.29.42 = Delegated Name Constraints +2.5.29.43 = Time specification +2.5.29.44 = CRL scope +2.5.29.45 = Status referrals +2.5.29.46 = Freshest CRL +2.5.29.47 = Ascending order list in CRL +2.5.29.48 = Attribute descriptor +2.5.29.49 = User notice +2.5.29.50 = SOA identifier +2.5.29.51 = Base CRL update time +2.5.29.52 = Acceptable certificate policies +2.5.29.53 = Delta info +2.5.29.54 = Inhabit any-policy +2.5.29.55 = Targeting information +2.5.29.56 = No revocation information available +2.5.29.57 = Acceptable privilege policies +2.5.29.58 = id-ce-toBeRevoked +2.5.29.59 = id-ce-RevokedGroups +2.5.29.60 = id-ce-expiredCertsOnCRL +2.5.29.61 = Indirect issuer +2.5.29.62 = id-ce-noAssertion +2.5.29.63 = id-ce-aAissuingDistributionPoint +2.5.29.64 = id-ce-issuedOnBehaIFOF +2.5.29.65 = id-ce-singleUse +2.5.29.66 = id-ce-groupAC +2.5.29.67 = id-ce-allowedAttAss +2.5.29.68 = id-ce-attributeMappings +2.5.29.69 = id-ce-holderNameConstraints + +2.16.840.1.113730.1.1 = +1.3.6.1.4.1.311.20.2 = szOID_ENROLL_CERTTYPE_EXTENSION +1.3.6.1.4.1.311.21.1 = MS Certificate Services CA Version +1.2.840.113533.7.65.0 = Entrust version extension +1.3.6.1.5.5.7.1.1 = Certificate authority information access +1.3.6.1.5.5.7.3.1 = Certificaat kan gebruikt worden als Secure Sockets Layer (SSL) server certificaat. +1.3.6.1.5.5.7.3.2 = Certificaat kan gebruikt worden als Secure Sockets Layer (SSL) client certificaat. +1.3.6.1.5.5.7.3.3 = Certificaat kan gebruikt worden voor code-signing. +1.3.6.1.5.5.7.3.4 = Certificaat kan gebruikt worden om e-mail te beveiligen (ondertekenen, encryptie, sleutelovereenkomst). +1.3.6.1.5.5.7.3.5 = Internet Protocol SECurity (IPSEC) end system certificate. +1.3.6.1.5.5.7.3.6 = Internet Protocol SECurity (IPSEC) tunnel certificate. +1.3.6.1.5.5.7.3.7 = Internet Protocol SECurity (IPSEC) user certificate. +1.3.6.1.5.5.7.3.8 = PKIX key purpose time stamping. Certificate can be used to bind the hash of an object to a time from a trusted time source. + +1.3.6.1.5.5.7.3.9 = Rec. ITU-T X.509 certificates corresponding private key may be used by an authority to sign OCSP-Responses. +1.3.6.1.5.5.7.3.10 = PKIX key purpose Data Validation and Certification Server Protocols. +1.3.6.1.5.5.7.3.11 = sbgpCertAAServerAuth. +1.3.6.1.5.5.7.3.12 = id-kp-scvp-responder key purpose. +1.3.6.1.5.5.7.3.13 = id-kp-eapOverPPP + +1.3.6.1.5.5.7.1.12 = id-pe-logotype +1.3.6.1.4.1.311.10.3.4 = Automatically extracted from Object IDs Associated with Microsoft Cryptography. +2.23.42.7.0 = Hashed Root Key diff --git a/core/src/main/resources/i18n/spark_i18n_pl.properties b/core/src/main/resources/i18n/spark_i18n_pl.properties new file mode 100644 index 000000000..9cf45ee69 --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_pl.properties @@ -0,0 +1,1065 @@ +## Tlumaczenie wersji pl stworzyl i na biezaco korektuje TEAM MOPR Bytom (informatycy@mopr.bytom.pl) - korekty mile widziane ;) +accept = Akceptuj +is.active = Aktywny +add = Dodaj +administrator = Administrator +answer = Odpowiedz +apply = Zatwierdź +available = DostÄ™pny +broadcast = Wiadomość grupowa +cancel = Anuluj +close = Zamknij +details = Szczegóły +create = Utwórz +date = Data +description = Opis +from = Od +invite = ZaproÅ› +join = Dołącz +no = Nie +not.registered = Nie zarejestrowany +occupants = Użytkownicy +offline = NiedostÄ™pny +online = DostÄ™pny +ok = Ok +open = Otwórz +open.folder = Otwórz katalog +participants = Uczestnicy +refresh = OdÅ›wież +reject = Odrzuć +retry = Powtórz +room.name = Nazwa pokoju +save = Zapisz +subject = Temat +unfiled = NiewypeÅ‚nione +use.default = Użyj domyÅ›lnych +user.has.signed.in = zalogowaÅ‚ siÄ™. +user.has.signed.off = wylogowaÅ‚ siÄ™. +while.offline = W trybie niedostÄ™pnym +yes = Tak + +action.clear = Wyczyść +action.copy = Kopiuj +action.cut = Wytnij +action.paste = Wklej +action.print = Drukuj +action.save = Zapisz +action.select.all = Zaznacz wszystko + +button.accept = Akceptuj +button.add = Dodaj +button.add.a.contact = Dodaj kontakt +button.add.bookmark = Dodaj zakÅ‚adkÄ™ +button.add.service = Dodaj usÅ‚ugÄ™ +button.add.user = Dodaj użytkownika +button.add2 = Dodaj +button.advanced = Ustawienia +button.approve = Zatwierdź +button.bookmark.room = Dodaj pokój +button.browse = PrzeglÄ…daj +button.browse2 = PrzeglÄ…daj +button.browse3 = PrzeglÄ…daj +button.cancel = Anuluj +button.clear = Wyczyść +button.close = Zamknij +button.copy.to.clipboard = Kopiuj do schowka +button.create.account = Utwórz konto +button.create.room = Utwórz lub dołącz do pokoju +button.decline = Odrzuć +button.deny = Zablokuj +button.dial.number = Wybierz numer +button.find = Znajdź +button.join = Dołącz +button.join.room = Dołącz do wybranego pokoju +button.login = Zaloguj +button.new = Nowy +button.profile = Profil +button.quit = Wyjdź +button.re.detect = Wykryj ponownie +button.reconnect = Połącz ponownie +button.reconnect2 = Połącz ponownie +button.refresh = OdÅ›wież +button.register = Zarejestruj +button.reject = Odrzuć +button.remove.bookmark = UsuÅ„ zakÅ‚adkÄ™ +button.roster = Lista współdzielona +button.save = Zapisz +button.save.for.future.use = ZapamiÄ™taj +button.search = Szukaj +button.send = WyÅ›lij +button.send.email = E-mail +button.start.chat = Rozmowa +button.tasks.active = Aktywne +button.tasks.all = Wszystkie +button.unset.file.explorer = Nieustawiona przeglÄ…darka plików +button.update = Aktualizuj +button.view.notes = Zobacz notatki +button.view.profile = Zobacz peÅ‚ny profil +button.view.tasklist = Zobacz listÄ™ zadaÅ„ +button.check.validity = Sprawdź ważność +button.show.certificate = Pokaż certyfikat + +table.column.certificate.subject = Temat +table.column.certificate.validity = Ważność +table.column.certificate.exempted = Zwolniony + +checkbox.allow.buzz = Zezwól użytkownikom na przesyÅ‚anie alertów +checkbox.auto.discover.port = Automatycznie wykryj hosta i port +checkbox.auto.login = Automatyczne logowanie +checkbox.login.as.invisible = Zaloguj jako niewidoczny +checkbox.login.anonymously = Zaloguj anonimowo +checkbox.disable.chat.history = Wyłącz historiÄ™ rozmów +checkbox.sort.asc.history = Sortuj historiÄ™ kontaktu wedÅ‚ug daty rosnÄ…co +checkbox.disable.prev.chat.history = Wyłącz historiÄ™ rozmowy w okienku +checkbox.enable.emoticons = Włącz emotikony +checkbox.graying.out = Przyciemnij bezczynne kontakty (wymaga restartu) +checkbox.idle.enabled = Włącz opcjÄ™ Zaraz wracam +checkbox.launch.on.startup = Uruchom przy starcie systemu +checkbox.reconnect.info = OkreÅ›lenie wyÅ›wietlania ponownego połączenia +checkbox.reconnect.panel.big = WyÅ›wietl jako panel +checkbox.reconnect.panel.small = WyÅ›wietl w grupie kontaktów +checkbox.reconnect.panel.icon = WyÅ›wietl jako ikona +checkbox.notify.user.comes.online = Powiadom o zmianach statusu użytkowników na aktywny +checkbox.notify.user.goes.offline = Powiadom o zmianach statusu użytkowników na nieaktywny +checkbox.notify.typing.systemtray = Pokazuj na pasku systemowym kiedy użytkownik pisze +checkbox.notify.systemtray = Pokazuj nowe wiadomoÅ›ci na pasku systemowym +checkbox.permanent = Pokój zawsze aktywny +checkbox.play.sound.on.invitation = Odtwórz dźwiÄ™k kiedy nadejdzie zaproszenie +checkbox.play.sound.on.new.message = Odtwórz dźwiÄ™k kiedy nadejdzie nowa wiadomość +checkbox.play.sound.on.outgoing.message = Odtwórz dźwiÄ™k podczas wysyÅ‚ania wiadomoÅ›ci +checkbox.play.sound.when.offline = Odtwórz dźwiÄ™k kiedy użytkownik siÄ™ wyloguje +checkbox.private.room = Pokój jest prywatny +checkbox.save.password = Zapisz hasÅ‚o +checkbox.show.avatars.in.contactlist = Pokazuj awatary na liÅ›cie kontaktów +checkbox.show.notifications.in.conference = Pokazuj powiadomienia w pokojach +checkbox.show.time.in.chat.window = Pokazuj czas w oknie rozmowy +checkbox.show.toaster = Pokazuj wyskakujÄ…ce okienko +checkbox.disable.asterisk.toaster = Wyłącz wyskakujÄ…ce okienko rozmów telefonicznych +checkbox.split.chat.window = Podziel okna rozmów (wymagany restart) +checkbox.start.in.tray = WyÅ›wietlaj zakÅ‚adki rozmów na górze (wymagany restart) +checkbox.click.single.tray = Pojedyncze klikniÄ™cie ikony w trayu wywoÅ‚uje główne okno Sparka (wymagany restart) +checkbox.tabs.on.top = ZakÅ‚adki rozmowy na wierzchu (wymagany restart) +checkbox.tabs.scroll = Użyj przewijania kart czatu (wymaga ponownego uruchomienia) +checkbox.use.compression = Używaj kompresji +checkbox.use.debugger.on.startup = Uruchom Å›ledzenie błędów przy starcie +checkbox.use.proxy.server = Użyj serwera proxy +checkbox.use.system.look.and.feel = Używaj systemowego wyglÄ…du (wymagany restart) +checkbox.window.to.front = Zawsze na wierzchu +checkbox.broadcast.hide.offline.user = Ukrywaj nieaktywnych użytkowników +checkbox.use.krbconf = Użyj krb5.conf lub krb5.ini +checkbox.use.krb.dns = Użyj DNS +checkbox.use.specify.below = OkreÅ›l poniższe opcje +checkbox.use.pki.authentication = Użyj autoryzacji PKI +checkbox.transport.tab.setting = Pokazuj dostÄ™pne bramy w tabeli (wymaga restartu) +checkbox.conference.tab.setting = Pokaż usÅ‚ugÄ™ konferencji na karcie (wymaga restartu) +checkbox.use.hostname.as.resource = Użyj nazwy hosta jako zasobu +checkbox.use.version.as.resource = Użyj wersji Sparka jako zasobu +checkbox.accept.all.certificates = Akceptuj wszystkie certyfikaty (podpisane/wygasÅ‚e/niezaufane) +checkbox.disable.hostname.verification = Wyłącz weryfikacjÄ™ certyfikatu nazwy hosta (niezalecane) +checkbox.accept.all = Akceptuj wszystkie +checkbox.accept.expired = Akceptuj wygasÅ‚e +checkbox.accept.not.valid.yet = Akceptuj jeszcze nieważne +checkbox.accept.self.signed = Akceptuj samopodpisane +checkbox.accept.revoked = Akceptuj cofniÄ™te +checkbox.check.crl = Sprawdzaj CRL +checkbox.check.ocsp = Sprawdzaj OCSP +checkbox.allow.soft.fail = Zezwalaj na lekkÄ… politykÄ™ błędów +checkbox.on.exception.list = Włącz listÄ™ wyjÄ…tków +checkbox.close.unread.message = Pytaj przy zamykaniu okna, jeÅ›li sÄ… nieprzeczytane wiadomoÅ›ci +radio.encryptionmode.required = Wymagany +radio.encryptionmode.ifpossible = JeÅ›li możliwy +radio.encryptionmode.disabled = Wyłączony + +delete.log.permanently = UsuÅ„ dziennik zdarzeÅ„ +delete.permanently = Usunąć trwale? + +gateway.username.password.error = Użytkownik i/lub hasÅ‚o muszÄ… zostać wpisane + +group.chat.window.information = Informacje okna rozmów +group.comma.delimited = Rozdzielone przecinkiem +group.conferences.found = Znalezione usÅ‚ugi konferencji +group.connection = Połączenie +group.empty = W tej grupie nie ma aktywnych kontaktów +group.general.information = Zmiana hasÅ‚a +group.login.information = Informacje o logowaniu +group.notification.options = Opcje powiadomieÅ„ +group.offline = Grupa użytkowników niedostÄ™pnych +group.search.form = Wyszukaj +group.search.results = Wyniki wyszukiwania +group.chat.name.notification = WidzÄ™ TwojÄ… nazwÄ™ +group.chat.name.match = Twoje imiÄ™ zostaÅ‚o użyte w rozmowie: +group.send_config.error = WystÄ…piÅ‚ wyjÄ…tek podczas próby zapisania zaktualizowanego formularza +group.encryption_mode = Tryb szyfrowania + +label.na = brak +label.cell = Tel. komórkowy +label.home = Dom +label.accounts = Konta +label.passwordreset = Resetuj hasÅ‚o +label.add.conference.service = Dodaj usÅ‚ugÄ™ konferencji +label.add.jid = Dodaj JID +label.add.task = Dodaj zadanie +label.auto.login = Autologowanie +label.available.users.in.roster = DostÄ™pni użytkownicy na liÅ›cie +label.avatar = Awatar: +label.cancel = Anuluj +label.change.password.to = ZmieÅ„ hasÅ‚o na +label.chatroom.fontsize = Rozmiar czcionki w pokoju rozmów +label.chatroom.maxcurrenthistorysize = Maksymalny rozmiar bieżącej historii: +label.city = Miasto +label.close = Zamknij +label.company = Firma +label.confirm.password = Potwierdź hasÅ‚o +label.conflict.error = Nie można zalogować, ktoÅ› jest już zalogowany na to konto +label.contact.to.find = Znajdź kontakt +label.recent.conversation = Ostatnie rozmowy +label.frequent.contacts = CzÄ™ste kontakty +label.contactlist.avatarsize = Rozmiar awatarów na liÅ›cie kontaktów: +label.contactlist.fontsize = Rozmiar czcionki listy kontaktów: +label.country = Kraj +label.create.account = Utwórz konto +label.department = WydziaÅ‚ +label.dial = Wybieranie +label.display.time = WyÅ›wietlanie czasu: +label.downloads = ÅšciÄ…gniÄ™te pliki +label.due = Powód +label.email.address = Adres e-mail +label.emoticons = Emotikony +label.enter.address = Wpisz adres +label.enter.group.name = Wpisz nazwÄ™ nowej grupy +label.fax = Fax +label.find = Znajdź +label.first.name = ImiÄ™ +label.group = Grupa +label.host = Host +label.invited.users = Zaproszeni użytkownicy +label.jabber.address = Adres Jabbera +label.jabber.id = ID Jabbera +label.jid = JID +label.job.title = Stanowisko +label.last.name = Nazwisko +label.local.time = Czas lokalny +label.message = Wiadomość +label.message.style = Styl wiadomoÅ›ci +label.middle.name = Drugie imiÄ™ +label.minutes.before.stale.chat = Ilość minut po których nieaktywne okno zostanie przedawnione +label.mobile = Telefon komórkowy +label.name = ImiÄ™ +label.network = Sieć +label.new.nickname = Nowy pseudonim +label.nickname = Pseudonim +label.number = Numer +label.ok = OK +label.old.ssl = Używaj starej metody SLL +label.os = Wersja systemu +label.pager = Pager +label.password = HasÅ‚o +label.phone = Telefon +label.port = Port +label.postal.code = Kod pocztowy +label.presence = Obecność +label.priority = Priorytet +label.protocol = Protokół +label.received = Otrzymane +label.rename.to = ZmieÅ„ nazwÄ™ +label.resource = Zasoby +label.response.timeout = Czas oczekiwania na odpowiedź (sek.) +label.reconnect.delay = Opóźnienie powtórnego połączenia (sek) (wymaga restartu) +label.room = Pokój +label.room.name = Nazwa pokoju +label.room.topic = Temat pokoju +label.search = Szukaj +label.search.service = Szukaj usÅ‚ug +label.seconds = Sekund +label.server = Domena +label.server.address = Adres serwera +label.show = Pokaż: +label.software = Komunikator +label.state.and.province = Województwo +label.street.address = Ulica +label.time = Czas: {0} +label.time.till.idle = Czas przejÅ›cia w stan bezczynnoÅ›ci (min) +label.time.till.idlemessage = Wiadomość po automatycznym przejÅ›ciu w stan bezczynnoÅ›ci +label.timeformat = Użyj {0} +label.transfer.download.directory = Katalog pobranych plików: +label.transfer.timeout = Czas wygaÅ›niÄ™cia transferu (min): +label.unable.to.add.contact = Nie można dodać kontaktu +label.use.default = Użyj domyÅ›lnych +label.user.on.public.network = Użytkownik jest w sieci publicznej +label.username = Nazwa użytkownika +label.version = Wersja +label.web.page = Strona WWW +label.work = Praca +label.xmpp.port = Port XMPP +label.krb.realm = Realm +label.krb.kdc = KDC +label.which.pki.method = Jaka metoda PKI? +label.choose.file = Wybierz plik +label.trust.store.password = Przechowuj bezpiecznie hasÅ‚o +label.enter.password = Wpisz hasÅ‚o +label.move.focus.forwards = Przejdź dalej +label.move.focus.backwards = Przejdź wstecz +label.keystore.location = Lokalizacja pliku kluczy +label.truststore.location = Lokalizacja pliku haseÅ‚ +label.pkcs.library.file = Plik bibliotek PKCS#11 +label.x509.certificate = Certyfikat X.509 +label.apple.keychain = Zastosuj KeyChain +label.add.to.roster = Dodaj użytkownika do Twojej listy +label.audio.device = UrzÄ…dzenie audio +label.video.device = UrzÄ…dzenie video +label.certificate.version = Wersja +label.certificate.serial.number = Numer seryjny +label.certificate.signature.value = Podpis +label.certificate.signature.algorithm = Algorytm podpisu +label.certificate.issuer = ZgÅ‚aszajÄ…cy +label.certificate.subject = Temat +label.certificate.not.before = Nieważny przed +label.certificate.not.after = Nieważny po +label.certificate.public.key = Klucz publiczny +label.certificate.public.key.algorithm = Algorytm klucza publicznego +label.certificate.issuer.unique.id = Unikalne ID zgÅ‚aszajÄ…cego +label.certificate.subject.unique.id = Unikalne ID tematu +label.certificate.add.certificate.to.truststore = Dodaj certyfikat do zaufanych +label.certificate.status = Status certyfikatu. + +menuitem.about = O programie +menuitem.actions = CzynnoÅ›ci +menuitem.bookmarks = ZakÅ‚adki +menuitem.add = Dodaj +menuitem.add.as.contact = Dodaj jako kontakt +menuitem.add.contact = Dodaj kontakt +menuitem.add.contact.group = Dodaj grupÄ™ kontaktów +menuitem.add.groupchat.myname = PodÅ›wietlaj mojÄ… nazwÄ™ użytkownika, kiedy ktoÅ› jÄ… napisze +menuitem.add.groupchat.mytext = PodÅ›wietlaj moje wypowiedzi +menuitem.add.groupchat.popname = Pokazuj wyskakujÄ…ce okienko kiedy ktoÅ› napisze mojÄ… nazwÄ™ użytkownika +menuitem.add.groupchat.showjoinleavemessage = WyÅ›wietlaj wiadomoÅ›ci o dołączeniu i opuszczeniu użytkowników +menuitem.add.groupchat.showrolesinsteadofstatus = Pokazuj ikony ról zamiast ikon statusu +menuitem.add.groupchat.auto.accept.invite = Automatycznie akceptuj zaproszenia do rozmów grupowych +menuitem.add.groupchat.random.colors = Nazwiska majÄ… losowe kolory +menuitem.always.on.top = Zawsze na wierzchu +menuitem.alert.when.online = Powiadom o dostÄ™pnoÅ›ci użytkownika +menuitem.ban = Zablokuj +menuitem.ban.user = Zablokuj użytkownika +menuitem.block.user = Zablokuj użytkownika +menuitem.broadcast.to.group = WyÅ›lij wiadomość grupowÄ… +menuitem.browse.service = PrzeglÄ…daj usÅ‚ugi +menuitem.change.nickname = ZmieÅ„ pseudonim +menuitem.change.subject = ZmieÅ„ temat +menuitem.chat = Rozmowa +menuitem.check.for.updates = Sprawdź aktualizacje +menuitem.connect = Plik +menuitem.contacts = Kontakty +menuitem.copy.to = Kopiuj do +menuitem.delete = UsuÅ„ +menuitem.delete.login.information = UsuÅ„ informacje o logowaniu +menuitem.destroy.room = UsuÅ„ pokój +menuitem.dial = ZadzwoÅ„ +menuitem.edit = Edytuj +menuitem.edit.my.profile = Edytuj mój profil +menuitem.edit.status.message = Edytuj opis statusu +menuitem.enter.login.information = Wprowadź informacje logowania +menuitem.exit = Wyjdź +menuitem.affiliation = Przynależność +menuitem.grant.moderator = Zezwól na moderowanie +menuitem.grant.member = Przydziel uprawnienia czÅ‚onkowskie +menuitem.grant.admin = Przydziel uprawnienia administratora +menuitem.grant.owner = Przydziel uprawnienia wÅ‚asnoÅ›ci +menuitem.grant.voice = Zezwól na połączenie gÅ‚osowe +menuitem.help = Pomoc +menuitem.hide = Ukryj +menuitem.invite.group.to.conference = ZaproÅ› grupÄ™ użytkowników do konferencji +menuitem.invite.users = ZaproÅ› użytkowników +menuitem.join.on.startup = Dołącz przy starcie +menuitem.join.room = Dołącz do wybranego pokoju +menuitem.kick.user = Wyrzuć użytkownika +menuitem.languages = JÄ™zyki +menuitem.logout.no.status = Wyloguj +menuitem.logout.with.status = Wyloguj z opisem +menuitem.lookup.profile = Przeszukaj profil +menuitem.move.to = PrzenieÅ› do +menuitem.online.help = Forum Sparka (online) +menuitem.open = Otwórz +menuitem.open.with = Otwórz za pomocÄ… +menuitem.plugins = Wtyczki +menuitem.preferences = Ustawienia Sparka +menuitem.remove = UsuÅ„ +menuitem.remove.alert.when.online = UsuÅ„ alert +menuitem.remove.bookmark = UsuÅ„ zakÅ‚adkÄ™ +menuitem.remove.from.group = UsuÅ„ z grupy +menuitem.remove.from.roster = UsuÅ„ z listy kontaktów +menuitem.block.contact = Zablokuj kontakt +menuitem.unblock.contact = Odblokuj kontakt +menuitem.remove.service = UsuÅ„ usÅ‚ugÄ™ +menuitem.rename = ZmieÅ„ nazwÄ™ +menuitem.revoke.moderator = Odbierz uprawnienia moderatora +menuitem.revoke.voice = Odbierz uprawnienia do połączenia gÅ‚osowego +menuitem.revoke.member = Odbierz uprawnienia czÅ‚onkowskie +menuitem.revoke.admin = Odbierz uprawnienia administratora +menuitem.revoke.owner = Odbierz uprawnienia wÅ‚asnoÅ›ci +menuitem.save = Zapisz +menuitem.save.as = Zapisz jako +menuitem.send.a.file = WyÅ›lij plik +menuitem.send.a.message = WyÅ›lij wiadomość grupowÄ… do wybranych użytkowników +menuitem.set.status.message = Ustaw opis statusu +menuitem.show.empty.groups = Pokaż puste grupy +menuitem.show.offline.group = Pokaż grupÄ™ użytkowników nieaktywnych +menuitem.show.traffic = Pokaż okno statystyk ruchu +menuitem.sign.in = Zapisz siÄ™ +menuitem.sign.in.at.login = Zapisz siÄ™ przy logowaniu +menuitem.sign.out = Wypisz siÄ™ +menuitem.start.a.chat = Rozpocznij rozmowÄ™ +menuitem.start.a.conference = Rozpocznij konferencjÄ™ +menuitem.status = Status +menuitem.subscribe.to = Zapisz siÄ™ do +menuitem.unban = Odblokuj +menuitem.unblock.user = Odblokuj użytkownika +menuitem.user.guide = Przewodnik użytkownika +menuitem.view.client.version = Pokaż wersjÄ™ klienta +menuitem.view.contact.history = Pokaż historiÄ™ kontaktu +menuitem.view.downloads = Pokaż pobrane pliki +menuitem.view.last.activity = Pokaż ostatniÄ… aktywność +menuitem.view.logs = Pokaż logi +menuitem.view.profile = Pokaż profil +menuitem.view.room.info = Pokaż informacje o pokoju +menuitem.voice = Rozmowa gÅ‚osowa +menuitem.show.offline.users = Pokaż nieaktywnych użytkowników +menuitem.show.contact.statusmessage = Pokaż status +menuitem.bookmark.room = Dodaj pokój do ulubionych +menuitem.refresh = OdÅ›wież +menuitem.create.room = Stwórz lub dołącz do pokoju +menuitem.expand.all.groups = RozwiÅ„ wszystkie grupy +menuitem.collapse.all.groups = ZwiÅ„ wszystkie grupy +menuitem.invite.again = ZaproÅ› ponownie +menuitem.chatframe.option = Opcje +menuitem.add.groupchat.invitetobookmark = Automatycznie zaproÅ› użytkowników do zaznaczonego pokoju +menuitem.certificate.files.filter = Pliki certyfikatów (*.cer), (*.crt), (*.der) + +message = Wiadomość +message.account.create = Utwórz nowe konto +message.account.created = Nowe konto zostaÅ‚o utworzone +message.account.error = Wskaż serwer na którym chcesz utworzyć konto +message.add.a.contact = Dodaj kontakt +message.add.conference.service = Dodaj usÅ‚ugÄ™ konferencji +message.add.contact.to.list = Dodaj użytkownika do listy kontaktów +message.add.favorite.room = Dodaj pokój do ulubionych lub połącz bezpoÅ›rednio +message.add.this.user.to.your.roster = Dodaj użytkownika do listy znajomych +message.add.to.roster = Dodaj do grupy kontaktów +message.add.user = Dodać do grupy kontaktów? +message.alert.notify = Powiadomienie alarmowe +message.already.exists = Konto już istnieje, użyj innej nazwy użytkownika +message.approve.subscription = Czy zezwolić {0} na dodanie Ciebie do jej/jego grupy kontaktów? +message.authenticating = Uwierzytelnianie +message.away.idle = Zaraz wracam +message.bookmark.temporary.room.error = Nie możesz dodawać tymczasowych pokoi do ulubionych +message.broadcast.from = Wiadomość grupowa od {0} +message.broadcast.no.user.selected = ProszÄ™ wybierz przynajmniej jednego odbiorcÄ™ +message.broadcast.no.text = ProszÄ™ wprowadź tekst dla wiadomoÅ›ci grupowej enter text to broadcast +message.broadcast.message.sent = Wiadomość grupowa zostaÅ‚a wysÅ‚ana +message.broadcast.to = Wpisz wiadomość i wyÅ›lij do {0} +message.hasbeenbroadcast.to = Wiadomość zostaÅ‚a wysÅ‚ana do nastÄ™pujÄ…cych użytkowników\:\n{0} +message.buzz.alert.notification = Zwróć uwagÄ™ użytkownika +message.buzz.message = {0} chce zwrócić TwojÄ… uwagÄ™ +message.buzz.sent = WyÅ›lij alert do użytkownika +message.calling = Dzwoni do {0} +message.came.online = {0} pojawiÅ‚ siÄ™ o {1} +message.cannot.add.contact.to.shared.group = Nie możesz dodać nowych kontaktów do współdzielonej grupy +message.cert.hostname.verification.failed = Weryfikacja certyfikatu nazwy hosta nie powiodÅ‚a siÄ™ +message.cert.verification.failed = Weryfikacja certyfikatu niemożliwa +message.chat.session.ended = Rozmowa zostaÅ‚a zakoÅ„czona o {0} +message.click.to.open = Kliknij aby otworzyć +message.client.information = Informacja o kliencie użytkownika {0} +message.close.other.chats = Zamknij wszystkie pozostaÅ‚e okna rozmowy +message.close.stale.chats = Zamknij nieaktywne okna rozmowy +message.close.this.chat = Zamknij to okno rozmowy +message.close.unread.window = Masz nieprzeczytane wiadomoÅ›ci, czy na pewno chcesz zamknąć okno? +message.conference.info.error = Nie można uzyskać informacji o konferencji, spróbuj ponownie później +message.conference.service.error = Nie można zlokalizować usÅ‚ugi konferencji +message.confirm.destruction.of.room = UsuniÄ™cie pokoju rozłączy wszystkich uczestników, kontynuować? +message.confirmation.password.error = Powtórz hasÅ‚o +message.connecting.please.wait = ÅÄ…czenie, proszÄ™ czekać +message.connection.failed = Nie można nawiÄ…zać połączenia z {0} +message.create.account = Nie można utworzyć konta +message.create.or.join.room = Utwórz lub dołącz do konferencji +message.current.status = Pokaż innym swój aktualny status +message.default.error = WystÄ…piÅ‚ nieoczekiwany błąd. Skontaktuj siÄ™ z support@jivesoftware.com +message.delete.all.history = Wykasować wszystkie poprzednie rozmowy? +message.delete.confirmation = Czy jesteÅ› pewien, że chcesz usunąć {0}? +message.disable.transport = Usunąć informacje o logowaniu z {0}? +message.disconnected.conflict.error = Taki użytkownik jest już zalogowany, połączenie przerwane +message.disconnected.error = WystÄ…piÅ‚ błąd, połączenie przerwane +message.disconnected.group.chat.error = Połączenie zostaÅ‚o zamkniÄ™te z powodu błędu, dołącz ponownie do pokoju +message.disconnected.shutdown = Połączenie przerwane z powodu niedostÄ™pnoÅ›ci serwera +message.downloading = Pobieranie {0} +message.downloading.spark.plug = Pobieranie wtyczki +message.end.chat = Czy chcesz zakoÅ„czyć tÄ… rozmowÄ™? +message.end.conversation = Czy chcesz zakoÅ„czyć tÄ… sesjÄ™? +message.enter.broadcast.message = Wpisz wiadomość do wysÅ‚ania dla okreÅ›lonych użytkowników +message.enter.gadugadu = Podaj numer i hasÅ‚o usÅ‚ugi Gadu-Gadu +message.enter.irc = Podaj login i hasÅ‚o usÅ‚ugi IRC +message.enter.sametime = Podaj login i hasÅ‚o usÅ‚ugi Sametime +message.enter.facebook = Podaj login i hasÅ‚o usÅ‚ugi Facebook +message.enter.myspace = Podaj login i hasÅ‚o usÅ‚ugi MySpace +message.enter.jabber.id = Podaj Jabber ID +message.enter.message.to.broadcast = Wpisz wiadomość do wysÅ‚ania do wszystkich +message.enter.new.subject = Wpisz nowy temat +message.enter.qq = Podaj login i hasÅ‚o usÅ‚ugi QQ +message.enter.room.password = Podaj hasÅ‚o dostÄ™pu do pokoju +message.enter.simple = Podaj login i hasÅ‚o usÅ‚ugi SIMPLE +message.enter.valid.jid = Wpisz poprawny Jabber ID +message.enter.xmpp = Podaj login i hasÅ‚o usÅ‚ugi XMPP +message.error.during.file.transfer = WystÄ…piÅ‚ błąd podczas wysyÅ‚ania pliku +message.error.must.use.reserved.nick = Musisz użyć zarezerwowanego nicku dla tego pokoju. +message.error.nickname.in.use = Ten nick jest już zajÄ™ty przez innego użytkownika. +message.error.no.permission.create.room = Nie masz uprawnieÅ„ do tworzenia pokoju. +message.error.no.response = Serwer nie odpowiada. +message.error.not.member = Nie jesteÅ› czÅ‚onkiem tego pokoju. Pokój wymaga czÅ‚onkostwa. +message.error.room.not.exist = Pokój, do którego próbujesz dołączyć nie istnieje. +message.error.room.password.incorrect = NieprawidÅ‚owe hasÅ‚o do pokoju. +message.error.unable.join.room = Dołączenie do pokoju jest niemożliwe. +message.file.exists.question = Plik już istnieje, zastÄ…pić? +message.file.size = Rozmiar pliku: {0} +message.file.transfer.canceled = AnulowaÅ‚eÅ› wysyÅ‚anie pliku +message.file.transfer.rejected = WysyÅ‚anie pliku nie zostaÅ‚o zaakceptowane przez {0} +message.file.transfer.dirnull = Katalog dla pobieranego pliku jest niewÅ‚aÅ›ciwy +message.file.transfer.nodir = Katalog dla pobieranego pliku nie istnieje +message.file.transfer.cantwritedir = Nie można zapisać pobieranego pliku w katalogu +message.file.transfer.notification = Powiadomienie o wysyÅ‚aniu pliku +message.file.transfer.short.message = chce wysÅ‚ać plik: +message.file.transfer.chat.window = Czy chcesz odebrać plik: +message.file.transfer.file.too.big.error = Wybrany plik jest za duży. Maksymalny rozmiar pliku to {0} wybrany plik ma {1} +message.file.transfer.file.too.big.warning = Wybrany plik jest za duży. Kontynuować? +message.file.transfer.direrror.setdir = Kliknij aby zmienić katalog +message.find.conference.services = Znajdź usÅ‚ugi konferencyjne +message.forbidden.error = Otrzymano niedozwolony błąd z serwera +message.gateway.username.error = Pole 'użytkownik' nie może być puste +message.gateway.password.error = Musi zostać podane hasÅ‚o +message.gateway.nickname.error = Pole 'pseudonim' nie może być puste +message.general.error = Utracono połączenie z serwerem z powodu {0} +message.generic.reconnect.message = Utracono połączenie z serwerem, aby zalogować siÄ™ ponownie kliknij 'Połącz ponownie' +message.idle.for = Nieaktywny przez {0} +message.image.small.resolution = Rozmiar obrazu jest mniejszy niż 32x32 piksele +message.invalid.jabber.id = NieprawidÅ‚owy Jabber ID +message.invalid.jid.error = NieprawidÅ‚owy JID +message.invalid.status = NieprawidÅ‚owy opis statusu +message.invalid.username.password = Niepoprawna nazwa użytkownika lub hasÅ‚o +message.invite.to.groupchat = {0} zaprasza CiÄ™ do grupowego czatu +message.invite.users.to.conference = ZaproÅ› użytkowników do pokoju konferencyjnego +message.is.shared.group = {0} jest grupÄ… współdzielonÄ… +message.is.typing.a.message = {0} pisze wiadomość +message.join.conference.room = Dołącz do pokoju konferencyjnego +message.kicked.error = Nie masz uprawnieÅ„ aby usunąć {0} z tego pokoju +message.last.message.received = Ostatnia wiadomość otrzymana o {0} +message.loading.please.wait = Åadowanie. ProszÄ™ czekać +message.locked.workstation = Użytkownik zablokowaÅ‚ komputer +message.name.of.group = Nazwa grupy +message.name.of.search.service.question = Nazwa szukanej usÅ‚ugi? +message.negotiate.file.transfer = Negocjowanie przesyÅ‚u pliku, proszÄ™ czekać +message.negotiate.stream = Negocjowanie strumienia połączenia, proszÄ™ czekać +message.negotiation.file.transfer = Negocjowanie transferu pliku z {0}, proszÄ™ czekać +message.new.message = Nowa wiadomość od {0} +message.new.spark.available = {0} jest dostÄ™pny. Czy chcesz zainstalować? +message.nickname.in.use = Pseudonim jest już zajÄ™ty, podaj inny +message.nickname.not.acceptable = Opcja zmiany pseudonimu niedostÄ™pna! +message.no.avatar.found = Użytkownik nie skonfigurowaÅ‚ swojego awatara +message.no.caller.id = Brak ID dzwoniÄ…cego +message.no.description.available = Brak opisu +message.no.history.found = Historia rozmów z tym użytkownikiem nie istnieje +message.no.results.found = Nie znaleziono szukanej frazy +message.no.room.to.join.error = Brak pokoju do dołączenia +message.no.subject.available = Brak tematu +message.no.updates = Nie ma nowych aktualizacji +message.normal = ZwykÅ‚a wiadomość +message.number.to.call = Wybierz numer do rozmowy gÅ‚osowej +message.offline = Użytkownik jest niedostÄ™pny, otrzyma tÄ… wiadomość przy nastÄ™pnym logowaniu +message.offline.error = Użytkownik nie bÄ™dzie mógÅ‚ otrzymywać wiadomoÅ›ci offline +message.participants.in.room = Uczestnicy w pokoju +message.password.error = Podaj poprawne hasÅ‚o +message.password.private.room.error = Podaj poprawne hasÅ‚o do pokoju +message.passwords.no.match = HasÅ‚a nie sÄ… identyczne +message.please.join.in.conference = Dołącz do mnie w konferencji +message.plugins.not.available = Nie można skontaktować siÄ™ z repozytorium wtyczek +message.prompt.plugin.uninstall = Czy jesteÅ› pewien, że chcesz wyłączyć {0}? +message.received.file = OtrzymaÅ‚eÅ› plik od {0} +message.receiving.file = Odbierasz plik od {0} +message.reconnect.attempting = PróbujÄ™ ponownie połączyć +message.reconnect.failed = Nie udaÅ‚o siÄ™ połączyć ponownie +message.reconnect.wait = Ponowna próba połączenia za {0} sekund +message.register.transports = Połącz do jednej z dostÄ™pnych bram +message.registering = ÅÄ…czÄ™ z {0}, proszÄ™ czekać +message.registration.transport.failed = Połączenie do podanej bramy niemożliwe +message.restart.spark = Musisz wyłączyć Sparka aby zainstalować nowÄ… wersjÄ™, czy chcesz kontynuować? +message.restart.spark.changes = Wtyczka zostanie usuniÄ™ta przy ponownym uruchomieniu komunikatora +message.restart.spark.to.install = Musisz wyłączyć komunikator, aby zainstalować jego ostatniÄ… wersjÄ™, chcesz to zrobić teraz? +message.restart.required = Wymagany restart komunikatora aby wprowadzić zmiany, zrestartować teraz? +message.room.creation.error = Nie można utworzyć pokoju +message.room.destroyed = Ten pokój zostaÅ‚ usuniÄ™ty z nastÄ™pujÄ…cego powodu: {0} +message.room.destruction.reason = Powód usuniÄ™cia pokoju? +message.room.information.for = Informacje o pokoju {0} +message.save.profile = Aby zapisać zmiany w profilu, naciÅ›nij Zapisz +message.search.for.contacts = Szukaj kontaktów +message.search.input.short = Podaj przynajmniej dwie litery. +message.search.for.other.people = Szukaj innych osób na serwerze +message.search.service.not.available = Nie można skontaktować siÄ™ z usÅ‚ugÄ… wyszukiwania +message.searching.please.wait = Trwa wyszukiwanie, proszÄ™ czekać +message.select.add.room.to.add = Wybierz pokój do dodania do listy usÅ‚ug +message.select.one.or.more = Wybierz jednego lub wiÄ™cej użytkowników z listy kontaktów +message.select.room.to.enter = OkreÅ›l pokój, do którego dołączyć +message.select.room.to.join = Wybierz pokój do dołączenia +message.send.a.broadcast = WyÅ›lij wiadomość grupowÄ… +message.send.file.to.user = WyÅ›lij pliki do tego użytkownika +message.send.picture = Uchwyć i wyÅ›lij zrzut ekranu +message.send.to.these.people = WyÅ›lij do tych osób +message.sending.file.to = WysyÅ‚anie pliku do {0} +message.sent.offline.files = OtrzymaÅ‚eÅ› plik(i) w trybie offline. +message.server.unavailable = Nie można połączyć z serwerem: nieprawidÅ‚owa nazwa lub serwer niedostÄ™pny +message.service.already.exists = UsÅ‚uga znajduje siÄ™ już na liÅ›cie +message.shared.group = Grupa współdzielona +message.specify.contact.jid = ProszÄ™ podać JID kontaktu (np. ddman@jabber.org) +message.specify.group = OkreÅ› grupÄ™, do której dodać nowego użytkownika +message.specify.information.for.conference = OkreÅ›l informacje o pokoju konferencyjnym +message.specify.name.error = Podaj poprawnÄ… nazwÄ™ +message.specify.users.to.join.conference = OkreÅ›l użytkowników dołączanych do tego pokoju konferencyjnego +message.specify.valid.time.error = Podaj poprawny czas nieaktywnoÅ›ci i port +message.subject.change.error = Nie masz uprawnieÅ„ do zmiany tematu tego pokoju +message.subject.has.been.changed.to = {1} zmieniÅ‚ temat na {0} +message.supply.resource = Podaj poprawne źródÅ‚o +message.supply.valid.port = Podaj poprawny port +message.supply.valid.timeout = Podaj poprawnÄ… wartość czasu oczekiwania +message.timeout.error = Czas oczekiwania musi wynosić minimum 5 sekund +message.total.downloaded = Ilość wszystkich pobraÅ„ plików +message.transfer.cancelled = PrzesyÅ‚anie pliku zostaÅ‚o anulowane +message.transfer.complete = Transfer pliku zostaÅ‚ ukoÅ„czony ({0}) +message.transfer.progressbar.text.received = {0} otrzymano @ {1} {2} +message.transfer.progressbar.text.sent = {0} wysÅ‚ano @ {1} {2} +message.transfer.rate = PrÄ™dkość przesyÅ‚ania +message.transfer.refused = PrzesyÅ‚anie pliku odrzucone +message.transfer.waiting.on.user = Oczekiwanie na akceptacjÄ™ {0} przesyÅ‚ania pliku +message.unable.to.load.profile = Nie można zlokalizować profilu dla {0} +message.unable.to.retrieve.last.activity = Nie można ustalić ostatniej aktywność dla {0} +message.unable.to.save.password = Nie można zmienić hasÅ‚a, skontaktuj siÄ™ z administratorem systemu +message.unable.to.send.file = Nie udaÅ‚o siÄ™ wysÅ‚ać pliku do {0} +message.unable.to.use.hostname.as.resource = Niemożliwe użycie nazwy hosta jako zasobu +message.unrecoverable.error = Niepoprawna nazwa użytkownika lub hasÅ‚o +message.update.room.list = Uaktualnij listÄ™ pokoi +message.updating.cancelled = Aktualizacja zostaÅ‚a anulowana +message.user.banned = {0} zostaÅ‚ zablokowany w tym pokoju. Powód: {1} +message.user.given.voice = {0} otrzymaÅ‚ możliwość rozmowy gÅ‚osowej w tym pokoju +message.user.granted.admin = {0} otrzymaÅ‚ uprawnienia administracyjne +message.user.granted.membership = {0} otrzymaÅ‚ uprawnienia czÅ‚onkowskie +message.user.granted.moderator = {0} otrzymaÅ‚ uprawnienia moderatora +message.user.granted.owner = {0} otrzymaÅ‚ uprawnienia wÅ‚aÅ›ciciela +message.user.is.sending.you.a.file = {0} wysyÅ‚a do Ciebie plik +message.user.joined.room = {0} dołączyÅ‚ do pokoju +message.user.kicked.from.room = {0} zostaÅ‚ usuniÄ™ty z pokoju przez {1}. Powód: {2} +message.user.left.room = {0} opuÅ›ciÅ‚ pokój +message.user.nickname.changed = {0} jest znany jako {1} +message.user.now.available.to.chat = {0} jest dostÄ™pny od {1} +message.user.revoked.admin = Uprawnienia administratora zostaÅ‚y odebrane użytkownikowi {0} +message.user.revoked.membership = CzÅ‚onkowstwo zostaÅ‚o odebrane użytkownikowi {0} +message.user.revoked.moderator = Uprawnienia moderatora zostaÅ‚y odebrane użytkownikowi {0} +message.user.revoked.owner = Uprawnienia wÅ‚aÅ›ciciela zostaÅ‚y odebrane użytkownikowi {0} +message.user.voice.revoked = Możliwość rozmowy gÅ‚osowej zostaÅ‚a odebrana użytkownikowi {0} +message.username.error = Podaj nazwÄ™ użytkownika dla konta +message.username.password.error = Nazwa użytkownika i/lub hasÅ‚o nie mogÄ… być puste +message.vcard.not.supported = Serwer nie obsÅ‚uguje wizytówek, nie można zapisać wizytówki +message.version = Wersja: {0} +message.view.information.about.this.user = Zobacz informacje o tym użytkowniku +message.waiting.for.user.to.join = Oczekiwanie na połączenie użytkownika {0} +message.went.offline = {0} przeszedÅ‚ w tryb niedostÄ™pny o {0} +message.you.have.been.banned = ZostaÅ‚eÅ› zablokowany w tym pokoju +message.you.have.been.kicked = ZostaÅ‚eÅ› wyrzucony z tego pokoju +message.you.have.sent = WysÅ‚aÅ‚eÅ› plik do {0} +message.your.admin.granted = OtrzymaÅ‚eÅ› uprawnienia administracyjne +message.your.banned = ZostaÅ‚eÅ› zablokowany w tym pokoju +message.your.kicked = ZostaÅ‚eÅ› wyrzucony przez {0} +message.your.membership.granted = OtrzymaÅ‚eÅ› uprawnienia czÅ‚onkowskie +message.your.membership.revoked = Twoje czÅ‚onkowstwo zostaÅ‚o anulowane +message.your.moderator.granted = OtrzymaÅ‚eÅ› uprawnienia moderatora +message.your.moderator.revoked = Twoje uprawnienia moderatora zostaÅ‚y anulowane +message.your.ownership.granted = OtrzymaÅ‚eÅ› uprawnienia wÅ‚aÅ›ciciela +message.your.ownership.revoked = Twoje uprawnienia wÅ‚aÅ›ciciela zostaÅ‚y anulowane +message.your.revoked.granted = Twoje uprawnienia administracyjne zostaÅ‚y anulowane +message.your.voice.granted = OtrzymaÅ‚eÅ› możliwość rozmowy gÅ‚osowej w tej rozmowie +message.your.voice.revoked = Anulowano twoje uprawnienia do rozmowy gÅ‚osowej +message.groupchat.require.password = Aby wejść do tego pokoju wymagane jest hasÅ‚o +message.groupchat.registered.member = PomyÅ›lnie zarejestrowany w {0} +message.search.for.history = Przeszukaj historiÄ™ rozmowy +message.search.period.day.one = jeden dzieÅ„ na stronÄ™ +message.search.period.week.one = tydzieÅ„ na stronÄ™ +message.search.period.month.one = miesiÄ…c na stronie +message.search.period.year.one = rok na stronie +message.search.period.none = pokaż wszystko na stronie +message.search.page.timeperiod = wybierz przedziaÅ‚ czasu, jaki ma być wyÅ›wietlony na stronie +message.search.page.counter = aktualny numer strony i ogólna ilość stron +message.search.page.right = strona do przodu +message.search.page.left = strona do tyÅ‚u + +status.away = Zaraz wracam +status.custom.messages = Opisy +status.do.not.disturb = Nie przeszkadzać +status.extended.away = BÄ™dÄ™ później +status.free.to.chat = MogÄ™ rozmawiać +status.on.phone = TelefonujÄ™ +status.online = DostÄ™pny +status.pending = OczekujÄ…cy +status.invisible = Niewidoczny +status.offline = NiedostÄ™pny + +tab.available.plugins = DostÄ™pne wtyczki +tab.avatar = Awatar +tab.business = Praca +tab.conferences = Konferencje +tab.contacts = Kontakty +tab.general = Ogólne +tab.home = Dom +tab.installed.plugins = Zainstalowane wtyczki +tab.deactivated.plugins = Wyłączone wtyczki +tab.personal = Osobiste +tab.proxy = Proxy +tab.sso = SSO +tab.pki = PKI +tab.certificates = Certyfikaty + +title.about = O programie +title.account.create.registration = Rejestracja konta +title.account.created = Konto utworzone +title.add.contact = Dodaj kontakt +title.add.contact.group = Dodaj kontakt grupowy +title.add.new.group = Dodaj nowÄ… grupÄ™ +title.add.search.service = Dodaj usÅ‚ugÄ™ wyszukiwania +title.add.to.roster = Dodaj do listy +title.address = Adres +title.advanced.connection.preferences = Zaawansowane opcje połączenia +title.advanced.connection.sso = Używam metody Using Single Sign-On (SSO) +title.advanced.connection.sso.account = To użyje konta logowania do pulpitu dla "{0}" aby zalogować do serwera. +title.advanced.connection.sso.noprincipal = Spark nie może znaleźć ogólnych ustawieÅ„ dla Single Sign-On. Pozwoli to zapobiec używania SSO. +title.advanced.connection.sso.smack3compat = Tryb kompatybilnoÅ›ci Smack 3 +title.advanced.connection.sso.unable = Nie można połączyć używajÄ…c Single Sign-On. Sprawdź ustawienia. +title.advanced.connection.usesso = Użyj metody Single Sign-On (SSO) via GSSAPI +title.alert = Alert +title.appearance = WyglÄ…d +title.appearance.preferences = Dostosuj +title.appearance.showVCards = Pokazuj wizytówki na liÅ›cie kontaktów +title.available.transports = DostÄ™pne bramy +title.bookmarks = Ulubione +title.broadcast.message = Wiadomość grupowa +title.browse.conference.services = PrzeglÄ…daj usÅ‚ugi konferencyjne +title.browse.room.service = PrzeglÄ…daj pokoje konferencyjne - {0} +title.cancelled = Anulowano +title.change.nickname = ZmieÅ„ pseudonim +title.change.subject = ZmieÅ„ temat +title.chat = Rozmowa +title.choose.directory = Wybierz katalog +title.choose.incoming.sound = Wybierz plik dźwiÄ™kowy wiadomoÅ›ci przychodzÄ…cej +title.choose.offline.sound = Wybierz plik dźwiÄ™kowy przejÅ›cia w tryb offline +title.choose.outgoing.sound = Wybierz plik dźwiÄ™kowy wiadomoÅ›ci wychodzÄ…cej +title.client.logs = Logi +title.conference.invitation = Zaproszenie do konferencji +title.conference.rooms = Pokoje konferencyjne +title.configure.chat.room = Konfiguruj pokój rozmów +title.configure.room = Konfiguruj pokój +title.confirmation = Potwierdzenie +title.create.new.account = Utwórz nowe konto +title.create.or.bookmark.room = Dołącz lub załóż pokój +title.create.room = Utwórz +title.create.problem = Problem z utworzeniem nowego konta +title.delete.file = Czy na pewno chcesz usunąć ten plik? +title.dial.phone = ZadzwoÅ„ +title.disable.transport = UsuÅ„ informacjÄ™ logowania +title.download.complete = Pobieranie ukoÅ„czone +title.downloading.im.client = Pobierz klienta IM +title.downloads = Pobrane pliki +title.edit.custom.message = Edytuj wiadomoÅ›ci +title.edit.profile = Edytuj informacje o profilu +title.enter.reason = Podaj powód +title.error = Błąd +title.error.couldnot.open.file = Nie można otworzyć pliku +title.error.delete.file = Nie można usunąć pliku +title.error.find.app = Nie można znaleźć odpowiedniej aplikacji +title.error.rename.file = Nie można zmienić nazwy pliku +title.facebook.registration = Ustawienia konta Facebook +title.file = Plik +title.file.exists = Plik istnieje +title.file.transfer = Transfer pliku +title.file.transfer.preferences = Ustawienia transferu plików +title.filesize = Rozmiar +title.find.conference.service = Znajdź usÅ‚ugÄ™ konferencyjnÄ… +title.find.contacts = Znajdź kontakty +title.gadugadu.registration = Ustawienia konta Gadu-Gadu +title.general.chat.settings = Ustawienia rozmowy +title.general.media = Ustawienia audio +title.group.chat = Rozmowa grupowa +title.group.chat.settings = Ustawienia rozmowy grupowej +title.history.for = Historia rozmów dla {0} +title.incoming.call = Połączenie przychodzÄ…ce +title.input.fileexplorer = Wstaw nazwÄ™ przeglÄ…darki plików: +title.input.newname = Wpisz nowÄ… nazwÄ™: +title.input.openwith = Wpisz nazwÄ™ aplikacji, której zamierzasz używać: +title.invite.to.conference = ZaproÅ› do konferencji +title.irc.registration = Ustawienia konta IRC +title.jabber.browser = PrzeglÄ…darka +title.join.conference.room = Dołącz do pokoju konferencyjnego +title.last.activity = Ostatnia aktywność +title.login = Login +title.login.error = Błąd logowania +title.login.no.account = Nie można okreÅ›lić +title.login.settings = Ustawienia logowania +title.lookup.profile = PrzeglÄ…daj profil +title.myspace.registration = Ustawienia konta MySpace +title.name = Nazwa +title.new.client.available = DostÄ™pna nowa wersja klienta +title.new.roster.group = Nowa współdzielona grupa kontaktów +title.new.version.available = DostÄ™pna nowa wersja +title.no.updates = Brak nowych aktualizacji +title.notes = Notatki +title.notification = Powiadomienie +title.notifications = Powiadomienia +title.occupants = Uczestnicy +title.on.the.phone = W trakcie rozmowy +title.password = HasÅ‚o +title.password.required = Wymagane hasÅ‚o +title.passwords.no.match = Potwierdź hasÅ‚o +title.person.search = Szukaj osoby +title.plugins = Wtyczki +title.preferences = Ustawienia +title.profile.information = Informacja o profilu +title.profile.not.found = Nie znaleziono profilu +title.qq.registration = Ustawienia konta QQ +title.register.account = Zarejestruj nowe konto +title.registration.error = Błąd rejestracji +title.reminder = Przypomnienie +title.rename.roster.group = ZmieÅ„ nazwÄ™ współdzielonej grupy kontaktów +title.room.destroyed = Pokój zostaÅ‚ zamkniÄ™ty +title.room.information = Informacja o pokoju +title.roster = Współdzielona grupa kontaktów +title.sametime.registration = Ustawienia konta Sametime +title.select.file.to.send = Wybierz plik(i) do wysÅ‚ania +title.set.status.message = Ustaw status +title.simple.registration = Ustawienia konta SIMPLE +title.sound.preferences = Ustawienia dźwiÄ™ków +title.sounds = DźwiÄ™ki +title.spark.preferences = Ustawienia Spark +title.start.chat = Rozpocznij rozmowÄ™ +title.status.message = Status +title.task.notification = Powiadomienie dla zadania +title.tasks = Zadania +title.transports = Bramy +title.tray.information = Informacja na pasku systemowym +title.upgrading.client = Aktualizacja klienta +title.version.and.time = Wersja i czas +title.view.bookmarks = Pokaż ulubione +title.view.profile.for = Informacje o profilu użytkownika {0} +title.view.room.information = Pokaż informacjÄ™ o pokoju +title.waiting.to.call = Oczekiwanie na rozmowÄ™ gÅ‚osowÄ… +title.warning = Ostrzeżenie +title.xmpp.registration = Ustawienia konta XMPP +title.subscription.request = ProÅ›ba o dodanie +title.certificate = Certyfikat + +tooltip.place.a.call = ZadzwoÅ„ do tej osoby +tooltip.appearance = ZmieÅ„ wyglÄ…d okna rozmów +tooltip.file.transfer = Ustawienia transferu plików +tooltip.notifications = Ustawienia powiadomieÅ„ dla nadchodzÄ…cych rozmów +tooltip.place.voice.call = ZadzwoÅ„ do tego użytkownika +tooltip.send.email = WyÅ›lij e-mail +tooltip.start.chat = Rozpocznij rozmowÄ™ +tooltip.view.changelog = PodglÄ…d dziennika zdarzeÅ„ +tooltip.view.history = PodglÄ…d historii rozmów +tooltip.view.readme = Zobacz plik readme +tooltip.encryptionmode.required = Szyfrowanie wymagane w celu połączenia. JeÅ›li serwer nie zapewnia szyfrowania lub negocjacje szyfrowania zakoÅ„czÄ… siÄ™ niepowodzeniem, wówczas połączenie z serwerem nie dojdzie do skutku. +tooltip.encryptionmode.ifpossible = Szyfrowanie jest używane wtedy gdy jest to możliwe. +tooltip.encryptionmode.disabled = Szyfrowanie jest wyłączone i w użyciu bÄ™dÄ… tylko połączenia nieszyfrowane. JeÅ›li szyfrowanie jest wymagane przez serwer, połączenie nie powiedzie siÄ™. + +tree.conference.services = UsÅ‚ugi konferencyjne +tree.users.in.room = Użytkownicy w pokoju + +lookandfeel.select = Wybierz systemowy wyglÄ…d +lookandfeel.change.now = ZmieÅ„ teraz +lookandfeel.tooltip.restart.no = Nie jest wymagany restart +lookandfeel.tooltip.restart.yes = Aby włączyć systemowy wyglÄ…d naciÅ›nij Zapisz i zresetuj Sparka. +lookandfeel.color.label = Kolory +lookandfeel.color.red = Czerwony +lookandfeel.color.green = Zielony +lookandfeel.color.blue = Niebieski +lookandfeel.color.opacity = Przezroczystość +lookandfeel.color.saved = Kolor zapisany + +##Ustawienia wtyczki prywatnosci +privacy.title.preferences = WÅ‚aÅ›ciwoÅ›ci prywatnoÅ›ci Sparka +privacy.title.panel = ProszÄ™ użyj prawego przycisku myszy +privacy.label.iq.desc = Zapytanie +privacy.label.pin.desc = Obecność +privacy.label.pout.desc = Nieobecność +privacy.label.msg.desc = WiadomoÅ›ci +privacy.border.information = Informacje o prywatnoÅ›ci +privacy.label.information = Użyj menu prawego przycisku myszy aby dodać lub usunąć listy lub elementy +privacy.root.node = Listy prywatnoÅ›ci +privacy.label.preferences = Wtyczka prywatnoÅ›ci +privacy.tooltip.preferences = Ustawienia prywatnoÅ›ci Sparka +privacy.label.list.is.active = AKTYWNA +privacy.label.list.is.default = DOMYÅšLNA +privacy.border.block = Zablokuj +privacy.pick.one.or.more = Wybierz jeden lub wiÄ™cej elementów aby dodać do listy +privacy.title.add.picker = Dodaj elementy do listy +privacy.node.contacts = Kontakty +privacy.node.groups = Grupy +privacy.menu.add.contacts = Dodaj kontakty do listy +privacy.menu.add.groups = Dodaj grupy do listy +privacy.menu.add.rem.items = UsuÅ„ {0} elementy z listy +privacy.menu.remove = UsuÅ„ +privacy.menu.activate.list = Aktywuj +privacy.menu.default.list = Ustaw jako domyÅ›lne +privacy.menu.add.list = Dodaj listÄ™ +privacy.menu.remove.list = UsuÅ„ listÄ™ +privacy.dialog.add.list = Wpisz nazwÄ™ listy +privacy.dialog.rem.list = Czy na pewno chcesz usunąć {0}? +privacy.status.menu.entry = Listy prywatnoÅ›ci +privacy.name.for.default.list = DomyÅ›lna +privacy.button.no.list.selected = Nie wybrano listy +privacy.menuitem.deactivate.current.list = Deaktywuj obecnÄ… listÄ™ {0} +privacy.label.not.supported = Prywatne listy nie sÄ… obsÅ‚ugiwane przez serwer. + +##Ustawienia stunfallback w mediach +stun.border.label = Awaryjny serwer STUN +stun.server.addr = Serwer STUN: +stun.server.port = Port STUN: + +composing = {0} pisze... +paused = {0} przestaÅ‚ pisać +active = {0} zwraca uwagÄ™ +inactive = {0} robi coÅ› innego +gone = {0} robi coÅ› innego + +#!# +action.viewlog=Zobacz plik logu + +dialog.confirm.to.reveal.visibility.title=JesteÅ› pewny? +dialog.confirm.to.reveal.visibility.msg=JeÅ›li bÄ™dziesz kontynuowaÅ‚, Twoja niewidoczność zostanie wyłączona +dialog.confirm.close.all.conferences.if.invisible.msg=JeÅ›li bÄ™dziesz kontynuowaÅ‚ wszystkie pokoje konferencyjne zostanÄ… zamkniÄ™te +dialog.certificate.show = To jest certyfikat, który próbujesz dodać do zaufanych.

      Po jego dodaniu Spark będzie mógł nawiązywać bezpieczną komunikację
      z serwerami, które są identyfikowane przez ten certyfikat.

      JeÅ›li jesteÅ› pewny, że chcesz dodać ten certyfikat kliknij OK. +dialog.certificate.cannot.have.copy = Ten certyfikat jest już w magazynie zaufanych. +dialog.certificate.has.been.added = Certyfikat zostaÅ‚ dodany do magazynu zaufanych. +dialog.certificate.is.distrusted = Certyfikat jest nieprawidÅ‚owy i nie powinien być zaufanym ponieważ jest to ryzykowne. \n JeÅ›li pomimo tego chcesz dodać go do zaufanych, kliknij przycisk lub dodaj go do listy wyjÄ…tków. +dialog.certificate.sure.to.delete = Czy jesteÅ› pewny, że chcesz usunąć ten certyfikat? \n JeÅ›li to zrobisz nie bÄ™dziesz w stanie nawiÄ…zać bezpiecznego połączenia \n z serwerami identyfikowanymi przez ten certyfikat. +dialog.certificate.has.been.deleted = Certyfikat zostaÅ‚ pomyÅ›lnie usuniÄ™ty. + +cert.valid = Ważny +cert.revoked = Unieważniony +cert.expired = WygasÅ‚y +cert.not.valid.yet = Jeszcze nieważny +cert.self.signed = Samopodpisany +cert.unknown.oid = Nieznany opis OID. +cert.is.critical = Jest krytyczny: +cert.critical = Krytyczny: +cert.not.critical = Niekrytyczny: + +cert.extensions = Rozszerzenia certyfikatów: +cert.extensions.unsupported = NieobsÅ‚ugiwane rozszerzenia +cert.extension.extended.usage.digital.signature = Podpis cyfrowy +cert.extension.extended.usage.non.repudiation = Nieodrzucony +cert.extension.extended.usage.key.encipherment = Szyfrowanie klucza +cert.extension.extended.usage.data.encipherment = Szyfrowanie danych +cert.extension.extended.usage.key.agreement = Zgodność klucza +cert.extension.extended.usage.key.cert.sign = Podpis kluczem szyfrujÄ…cym +cert.extension.extended.usage.crl.sign = Podpis CRL +cert.extension.extended.usage.encipher.only = Tylko szyfrowane +cert.extension.extended.usage.decipher.only = Tylko odszyfrowane +cert.extension.basic.constraints.is.ca = Czy jest urzÄ…d certyfikacji +cert.extension.basic.constraints.path.length = DÅ‚ugość Å›cieżki walidacji +cert.extension.name.constraints.permitted.subtrees = Włączone podkategorie +cert.extension.name.constraints.excluded.subtrees = Wyłączone podkategorie + +##OID's mapping +2.5.29.1 = X.509 old Authority Key Identifier. +2.5.29.2 = Key attributes. +2.5.29.3 = Certificate policies. +2.5.29.4 = Key usage restrictions. +2.5.29.5 = Policy mapping. +2.5.29.6 = Subtree constraints. +2.5.29.7 = Subject alternative name. +2.5.29.8 = Issuer alternative name. +2.5.29.9 = Subject directory attributes. +2.5.29.10 = Basic constraints. +2.5.29.11 = Certificate Extension +2.5.29.12 = Certificate Extension +2.5.29.13 = Certificate Extension +2.5.29.14 = Subject key identifier. +2.5.29.15 = Key usage. +2.5.29.16 = Private key usage period. +2.5.29.17 = Subject alternative name. +2.5.29.18 = +2.5.29.19 = Basic constraints. +2.5.29.20 = CRL number. +2.5.29.21 = Reason code. +2.5.29.22 = Expiration date. +2.5.29.23 = Hold instruction code. +2.5.29.24 = Invalidity date. +2.5.29.25 = CRL Distribution Points. +2.5.29.26 = Issuing distribution point. +2.5.29.27 = CRL indicator. +2.5.29.28 = Issuing distribution point. +2.5.29.29 = Certificate issuer. +2.5.29.30 = Name constraints. +2.5.29.31 = CRL distribution points. +2.5.29.32 = Certificate policies. +2.5.29.33 = Policy mappings. +2.5.29.34 = Policy constraints. +2.5.29.35 = Authority key identifier. +2.5.29.36 = Policy constraints. +2.5.29.37 = Extended key usage. +2.5.29.38 = Authority attribute identifier. +2.5.29.39 = Role specification certificate identifier. +2.5.29.40 = CRL stream identifier. +2.5.29.41 = basicAttConstraints. +2.5.29.42 = Delegated Name Constraints. +2.5.29.43 = Time specification. +2.5.29.44 = CRL scope. +2.5.29.45 = Status referrals. +2.5.29.46 = Freshest CRL. +2.5.29.47 = Ascending order list in CRL. +2.5.29.48 = Attribute descriptor. +2.5.29.49 = User notice. +2.5.29.50 = SOA identifier. +2.5.29.51 = Base CRL update time. +2.5.29.52 = Acceptable certificate policies. +2.5.29.53 = Delta info. +2.5.29.54 = Inhabit any-policy. +2.5.29.55 = Targeting information. +2.5.29.56 = No revocation information available. +2.5.29.57 = Acceptable privilege policies. +2.5.29.58 = id-ce-toBeRevoked. +2.5.29.59 = id-ce-RevokedGroups. +2.5.29.60 = id-ce-expiredCertsOnCRL. +2.5.29.61 = Indirect issuer. +2.5.29.62 = id-ce-noAssertion +2.5.29.63 = id-ce-aAissuingDistributionPoint +2.5.29.64 = id-ce-issuedOnBehaIFOF +2.5.29.65 = id-ce-singleUse +2.5.29.66 = id-ce-groupAC +2.5.29.67 = id-ce-allowedAttAss +2.5.29.68 = id-ce-attributeMappings +2.5.29.69 = id-ce-holderNameConstraints + +2.16.840.1.113730.1.1 = +1.3.6.1.4.1.311.20.2 = szOID_ENROLL_CERTTYPE_EXTENSION +1.3.6.1.4.1.311.21.1 = MS Certificate Services CA Version +1.2.840.113533.7.65.0 = Entrust version extension +1.3.6.1.5.5.7.1.1 = Certificate authority information access +1.3.6.1.5.5.7.3.1 = Certificate can be used as a Secure Sockets Layer (SSL) server certificate. +1.3.6.1.5.5.7.3.2 = Certificate can be used as a Secure Sockets Layer (SSL) client certificate. +1.3.6.1.5.5.7.3.3 = Certificate can be used for code signing. +1.3.6.1.5.5.7.3.4 = Certificate can be used for protecting email (signing, encryption, key agreement). +1.3.6.1.5.5.7.3.5 = Internet Protocol SECurity (IPSEC) end system certificate. +1.3.6.1.5.5.7.3.6 = Internet Protocol SECurity (IPSEC) tunnel certificate. +1.3.6.1.5.5.7.3.7 = Internet Protocol SECurity (IPSEC) user certificate. +1.3.6.1.5.5.7.3.8 = PKIX key purpose time stamping. Certificate can be used to bind the hash of an object to a time from a trusted time source. + +1.3.6.1.5.5.7.3.9 = Rec. ITU-T X.509 certificates corresponding private key may be used by an authority to sign OCSP-Responses. +1.3.6.1.5.5.7.3.10 = PKIX key purpose Data Validation and Certification Server Protocols. +1.3.6.1.5.5.7.3.11 = sbgpCertAAServerAuth. +1.3.6.1.5.5.7.3.12 = id-kp-scvp-responder key purpose. +1.3.6.1.5.5.7.3.13 = id-kp-eapOverPPP + +1.3.6.1.5.5.7.1.12 = id-pe-logotype +1.3.6.1.4.1.311.10.3.4 = Automatically extracted from Object IDs Associated with Microsoft Cryptography. +2.23.42.7.0 = Hashed Root Key diff --git a/core/src/main/resources/i18n/spark_i18n_pt_BR.properties b/core/src/main/resources/i18n/spark_i18n_pt_BR.properties new file mode 100644 index 000000000..fbaa1fd36 --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_pt_BR.properties @@ -0,0 +1,793 @@ +ok = OK +cancel = Cancelar +use.default = Usar padrão +close = Fechar +create = Criar +invite = Convidar +date = data +add = Adicionar +from = De +room.name = Nome da sala +join = Participar +description = Descrição +subject = Assunto +occupants = Ocupantes +accept = Aceitar +reject = Rejeitar +open = Abrir +open.folder = Abrir pasta +retry = Repetir +is.active = Ativo +not.registered = Não registrado +save = Salvar +yes = Sim +no = Não +message = Mensagem + +button.create.account = &Criar conta +button.close = &Fechar +button.advanced = A&vançado +button.browse = &Procurar... +button.browse2 = &Procurar... +button.browse3 = &Procurar... +button.approve = &Aprovar +button.deny = &Rejeitar +button.accept = &Aceitar +button.profile = &Perfil +button.add.a.contact = &Adicionar contato +button.reconnect = &Reconectar +button.add = &Adicionar +button.roster = &Contatos +button.add.bookmark = Adicionar marcador +button.remove.bookmark = Remover marcador +button.bookmark.room = &Marcar sala +button.create.room = &Criar ou entrar em sala +button.join.room = &Entrar na sala Selecionada +button.refresh = &Atualizar +button.find = &Encontrar +button.update = &Atualizar +button.cancel = &Cancelar +button.decline = &Não aceitar +button.join = &Participar +button.save.for.future.use = &Salvar +button.register = &Registrar +button.dial.number = &Chamar número +button.clear = &Limpar +button.search = &Procurar +button.add.service = &Adicionar serviço +button.new = &Novo +button.view.tasklist = Ver tarefas +button.view.notes = Ver notas + +checkbox.save.password = &Salvar senha +checkbox.enable.emoticons = Habilitar em&oticons +checkbox.auto.login = &Login automático +checkbox.login.as.invisible = L&ogin como invisível +checkbox.login.anonymously = Login anôni&mo +checkbox.use.proxy.server = &Usar proxy +checkbox.auto.discover.port = &Resolver endereço e porta automaticamente +checkbox.permanent = Sala &permanente +checkbox.private.room = Sala pri&vada +checkbox.show.time.in.chat.window = &Mostrar hora na janela de Chat +checkbox.show.notifications.in.conference = &Mostrar notificações nas salas de conferência +checkbox.disable.chat.history = &Desabilitar histórico de Chat +checkbox.show.toaster = Mostrar popup de notificação +checkbox.disable.asterisk.toaster = Desabilitar popup de notificação para telefone +checkbox.window.to.front = &Trazer janela para o topo +checkbox.play.sound.on.new.message = Tocar som quando &receber mensagem +checkbox.play.sound.when.offline = Tocar som quando usuário ficar &offline +checkbox.play.sound.on.outgoing.message = Tocar som quando &enviar mensagem +checkbox.play.sound.on.invitation = Tocar som quando receber convite +checkbox.allow.buzz = Permitir que usuários chamem sua atenção +checkbox.idle.enabled = &Ausente habilitado +checkbox.graying.out = Ofuscar contatos ausentes (Necessita reiniciar) +checkbox.launch.on.startup = &Executar ao iniciar +checkbox.reconnect.info = Especificar exibição de reconexão: +checkbox.reconnect.panel.big = Exibir painel +checkbox.reconnect.panel.small = Exibir como grupo de contato +checkbox.reconnect.panel.icon = Exibir ícone +checkbox.start.in.tray = &Iniciar na bandeja +checkbox.click.single.tray = Clique &simples no ícone da bandeja traz a janela do Spark para frente (Necessita reiniciar) +checkbox.split.chat.window = Encaixar &janelas (Necessário reiniciar) +checkbox.notify.user.goes.offline = Notificar quando usuário ficar offline +checkbox.notify.user.comes.online = Notificar quando usuário ficar online +checkbox.use.system.look.and.feel = Usar gráficos do sistema (Necessário reiniciar) +checkbox.close.unread.message = Perguntar ao fechar a janela se há mensagens não lidas + +label.change.password.to = &Trocar senha para +label.chatroom.fontsize = Tamanho da fonte no Chat: +label.chatroom.maxcurrenthistorysize = Tamanho máximo do histórico atual: +label.username = &Usuário +label.name = &Nome +label.room.name = &Nome da sala +label.room.topic = &Tópico da sala +label.password = &Senha +label.confirm.password = &Confirme a senha +label.server = Do&mínio +label.create.account = Criar &conta +label.close = Fe&char +label.ok = OK +label.cancel = Cancelar +label.use.default = Usar padrão +label.port = &Porta +label.response.timeout = &Tempo de resposta esgotado +label.reconnect.delay = Tempo de atraso para reconectar (seg) (Necessita reiniciar) +label.auto.login = &Login automático +label.contactlist.fontsize = Tamanho da fonte da &lista de contatos: +label.old.ssl = &Usar método antigo de porta SSL +label.host = &Endereço +label.resource = &Recursos +label.protocol = &Protocolo +label.accounts = &Contas +label.transfer.timeout = &Tempo máximo de transferência (min): +label.transfer.download.directory = &Pasta de download: +label.find = &Encontrar +label.rename.to = Renomear para +label.contact.to.find = Contato a ser encontrado: +label.available.users.in.roster = &Usuários online na lista de contatos +label.time = Tempo: {0} +label.add.conference.service = &Adicionar serviço de conferência +label.add.jid = &Adicionar JID +label.message = &Mensagem +label.room = &Sala +label.invited.users = Usuários convidados +label.new.nickname = Novo apelido +label.server.address = &Endereço do servidor +label.nickname = &Apelido +label.presence = &Presença +label.priority = P&rioridade +label.enter.address = Endereço +label.jabber.address = &Endereço Jabber +label.local.time = &Hora local +label.software = &Software +label.version = &Versão +label.os = &Sistema operacional +label.number = &Número +label.dial = &Chamar +label.display.time = Exibir por +label.minutes.before.stale.chat = &Minutos necessários para que a sala fique obsoleta +label.company = &Empresa +label.street.address = &Endereço +label.city = &Cidade +label.state.and.province = E&stado +label.postal.code = &CEP +label.country = &País +label.job.title = &Profissão +label.department = &Departamento +label.phone = &Telefone +label.fax = &Fax +label.mobile = &Celular +label.web.page = &Página Web +label.pager = &Pager +label.first.name = &Primeiro nome +label.middle.name = &Nome do meio +label.last.name = &Último nome +label.email.address = &Endereço de E-mail +label.jid = &JID +label.search.service = &Serviços de procura +label.seconds = segundos +label.xmpp.port = &Porta XMPP +label.time.till.idle = &Tempo antes de ausentar (min) +label.time.till.idlemessage = M&ensagem automática de ausência +label.group = &Grupo +label.enter.group.name = Digite o nome do grupo + +message.username.error = Especificar um nome de usuário para esta conta. +message.password.error = Especificar uma senha para esta conta. +message.confirmation.password.error = Especificar senha de confirmação. +message.account.error = Especificar o servidor em que a conta será criada. +message.registering = Registrando como {0}. Aguarde... +message.connection.failed = Impossível Conectar com {0}. +message.create.account = A conta não pode ser criada. +message.already.exists = A conta já existe. Tente um nome de usuário diferente. +message.account.created = Nova conta criada. +message.account.create = Criar uma nova conta de Chat. +message.connecting.please.wait = Conectando. Aguarde... +message.supply.valid.timeout = Informe um tempo de resposta válido. +message.supply.valid.port = Informe uma porta válida. +message.supply.resource = Informe um recurso válido. +message.current.status = Permitir que outros usuários vejam meu estado atual. +message.disconnected.error = Ocorreu um erro e sua conexão foi fechada. +message.disconnected.conflict.error = Você foi desconectado pois o seu usuário logou em outro local. +message.locked.workstation = Usuário bloqueou sua estação de trabalho. +message.away.idle = Ausente por inatividade. +message.default.error = Um erro foi encontrado. Informe ao support@jivesoftware.com. +message.new.message = Nova mensagem de {0}. +message.send.file.to.user = Enviar arquivos para este usuário. +message.send.picture = Enviar a imagem de seu desktop. +message.sent.offline.files = Você acabou de receber arquivo(s) enviado(s) offline. +message.search.for.contacts = Buscar Contatos. +message.end.conversation = Você deseja terminar esta sessão? +message.end.chat = Você deseja terminar este Chat? +message.close.this.chat = Fechar este Chat +message.close.other.chats = Fechar os outros Chats +message.close.stale.chats = Fechar Chats obsoletos +message.close.unread.window = Você tem mensagens não lidas. Tem certeza de que deseja fechar a janela? +message.last.message.received = última mensagem recebida em {0} +message.shared.group = Grupo compartilhado +message.is.shared.group = {0} é um grupo compartilhado. +message.delete.confirmation = Você tem certeza que deseja remover {0}? +message.idle.for = Ausente por {0} +message.enter.broadcast.message = Entre com a mensagem a ser enviada aos usuários selecionados. +message.name.of.group = Nome do grupo +message.approve.subscription = Permitir que {0} adicione você na lista dele? +message.add.user = Adicionar usuário a sua lista? +message.general.error = Você perdeu sua conexão com o servidor devido a {0}. +message.add.a.contact = Adicionar contato. +message.generic.reconnect.message = Você perdeu sua conexão com o servidor. Para conectar novamente clique em Reconectar +message.select.one.or.more = Selecione um ou mais usuários de sua lista. +message.add.conference.service = Adicionar um serviço de conferência. +message.service.already.exists = Serviço já se encontra em sua lista. +message.searching.please.wait = Procurando. Aguarde... +message.conference.service.error = Impossível localizar o serviço de conferência. +message.create.or.join.room = Criar ou participar de uma sala de conferência +message.specify.name.error = Especifique um nome válido. +message.password.private.room.error = Especifique a senha para a sala privada. +message.passwords.no.match = Senhas não coincidem. +message.enter.valid.jid = Informe um JID válido +message.please.join.in.conference = Por favor me adicione a conferência. +message.invite.users.to.conference = Convidar usuários para a sala de conferência. +message.specify.users.to.join.conference = Especificar usuários desta sala de conferência. +message.no.room.to.join.error = Nenhuma sala para participar +message.participants.in.room = Participantes na sala +message.you.have.been.kicked = Você foi expulso desta sala. +message.kicked.error = Você não pode expulsar {0} desta sala. +message.you.have.been.banned = Você foi banido desta sala. +message.nickname.in.use = Apelido em uso. Selecione outro. +message.update.room.list = Atualizar a lista da sala +message.join.conference.room = Participar da sala de conferência +message.select.add.room.to.add = Selecione uma sala para adicionar a sua lista de serviços +message.bookmark.temporary.room.error = Você não pode marcar salas temporárias +message.select.room.to.join = Selecione a sala para entrar. +message.conference.info.error = Impossível receber informações de conferência. Tenter mais tarde. +message.add.favorite.room = Adicionar aos favoritos ou participar da Sala. +message.select.room.to.enter = Especifique a sala para entrar. +message.find.conference.services = Encontrar serviços de conferência +message.specify.information.for.conference = Especifique as informações para a sala de conferência +message.no.description.available = Não há descrição disponível +message.no.subject.available = Não há título disponível +message.room.information.for = Informação sobre a sala para {0} +message.view.information.about.this.user = Ver informações deste usuário. +message.add.this.user.to.your.roster = Adicionar a lista de amigos. +message.came.online = {0} ficou online as {1} +message.went.offline = {0} ficou offline as {1} +message.offline.error = O usuário não poderá receber mensagens offline. +message.offline = O usuário receberá as mensagens na próxima conexão. +message.is.typing.a.message = {0} está digitando... +message.enter.new.subject = Entre o novo assunto +message.confirm.destruction.of.room = Remover a sala, remove todos os usuários que nela estão. Continuar? +message.room.destruction.reason = Motivo para remover a sala? +message.user.left.room = {0} saiu da sala. +message.user.joined.room = {0} entrou na sala. +message.chat.session.ended = Chat encerrou as {0} +message.subject.change.error = Você não pode mudar o assunto desta sala. +message.forbidden.error = Erro de permissão recebido. +message.room.destroyed = A sala foi removida pela seguinte razão: {0} +message.subject.has.been.changed.to = O assunto mudou para {0}. +message.user.kicked.from.room = {0} foi expulso da sala. +message.user.given.voice = Foi dado a palavra a {0} nesta sala. +message.user.voice.revoked = Palavra revogada para {0}. +message.user.banned = {0} foi banido desta sala. +message.user.granted.membership = Privilégios de membro concedidos para {0}. +message.user.revoked.membership = Privilégios de membro revogados para {0}. +message.user.granted.moderator = Privilégios de moderador concedidos para {0}. +message.user.revoked.moderator = Privilégios de moderador revogados para {0}. +message.user.granted.owner = Privilégios de criador concedidos para {0}. +message.user.revoked.owner = Privilégios de criador revogados para {0}. +message.user.granted.admin = Privilégios de administrador concedidos para {0}. +message.user.revoked.admin = Privilégios de administrador revogados para {0}. +message.user.nickname.changed = {0} agora é {1}. +message.your.kicked = Você foi expulso de {0}. +message.your.voice.granted = Você recebeu a palavra neste Chat. +message.your.voice.revoked = Sua palavra foi revogada. +message.your.banned = Você foi expulso desta sala. +message.your.membership.granted = Você possui privilégios de membro. +message.your.membership.revoked = Sua associação foi revogada. +message.your.moderator.granted = Você possui privilégios de moderador. +message.your.moderator.revoked = Seus privilégios de moderador foram revogados. +message.your.ownership.granted = Você possui privilégios de criador. +message.your.ownership.revoked = Seus privilégios de criador foram revogados. +message.your.admin.granted = Você possui privilégios de administrador. +message.your.revoked.granted = Seus privilégios de administrador foram revogados. +message.send.a.broadcast = Enviar mensagem em massa +message.broadcast.from = Mensagem em massa de {0} +message.enter.message.to.broadcast = Entre com a mensagem a ser enviada para toda sua lista de contatos. +message.broadcast.message.sent = A mensagem foi enviada em massa. +message.broadcast.to = Entre com a mensagem as ser enviada para {0} +message.hasbeenbroadcast.to = A mensagem foi enviada aos seguintes usuários:\n{0} +message.user.now.available.to.chat = {0} está online as {1} +message.user.is.sending.you.a.file = {0} está lhe enviando um arquivo. +message.file.transfer.canceled = Você cancelou a transferência do arquivo. +message.negotiate.file.transfer = Negociando transferência de arquivo. Aguarde... +message.negotiate.stream = Negociando transmissão. Aguarde... +message.receiving.file = Você está recebendo um arquivo de {0} +message.click.to.open = Clique para abrir +message.error.during.file.transfer = Ocorreu um erro durante a transferência. +message.transfer.refused = A transferência foi recusada. +message.transfer.cancelled = A transferência foi cancelada. +message.received.file = Você recebeu um arquivo de {0}. +message.file.exists.question = O arquivo já existe. Deseja substituir? +message.transfer.waiting.on.user = Aguardando {0} aceitar a transferência. +message.negotiation.file.transfer = Negociando a transferência com {0}. Aguarde... +message.unable.to.send.file = Você não pode enviar o arquivo para {0}. +message.sending.file.to = Enviando arquivo para {0}. +message.you.have.sent = Você enviou um arquivo para {0}. +message.file.transfer.rejected = A transferência de arquivo não é aceita por {0}. +message.disable.transport = Você deseja desabilitar os transportes? +message.register.transports = Registrar com os transportes instalados. +message.username.password.error = Usuário e Senha não necessitam ser informados. +message.registration.transport.failed = Não foi possível registrar com transporte. +message.client.information = Informação do cliente para {0} +message.calling = Chamando {0} +message.number.to.call = Especifique o numero a ser chamado +message.no.caller.id = Sem identificação +message.no.history.found = Não há histórico de conversas com este usuário. +message.prompt.plugin.uninstall = Você tem certeza que deseja desinstalar {0}? +message.loading.please.wait = Carregando. Aguarde... +message.plugins.not.available = Não foi possível contatar o repositório de plugins. +message.downloading = Realizando o download {0} +message.downloading.spark.plug = Realizando o download do Spark-Plug +message.unable.to.save.password = Não foi possível alterar a senha. Contate o seu administrador. +message.delete.all.history = Excluir todas as conversas anteriores? +message.no.avatar.found = Usuário não possui avatar. +message.image.too.large = Esta imagem é muito grande para ser usada. Especifique uma imagem de 16k ou menos. +message.save.profile = Para salvar seu perfil, clique em Salvar. +message.unable.to.load.profile = Impossível localizar perfil de {0} +message.enter.jabber.id = Entre com o ID Jabber +message.invalid.jabber.id = ID Jabber inválido +message.vcard.not.supported = Servidor não suporta VCards. Impossível salvar. +message.search.service.not.available = Não foi possível contatar o serviço de busca. +message.no.results.found = Não foi retornado nenhum resultado da busca. +message.name.of.search.service.question = Nome do serviço de busca? +message.search.for.other.people = Buscar outras pessoas no servidor +message.specify.valid.time.error = Especifique o tempo máximo e a porta. +message.timeout.error = O tempo máximo deve ser de 5 segundos ou mais. +message.version = Versão: {0} +message.file.size = Tamanho do Arquivo: {0} +message.restart.spark = Você precisa reiniciar o cliente para instalar a nova versão. Deseja fazer isto agora? +message.updating.cancelled = A atualização foi cancelada. +message.transfer.rate = Taxa de transferência +message.total.downloaded = Total recebido +message.new.spark.available = {0} está disponível. Você deseja instalar? +message.restart.spark.to.install = Você precisa reiniciar o cliente para instalar a mais nova versão. Deseja fazer isto agora? +message.add.to.roster = Adicionar a lista +message.add.contact.to.list = Adicionar usuário na lista de contatos +message.send.to.these.people = Enviar para as seguintes pessoas +message.normal = Mensagem normal +message.alert.notify = Notificar como alerta + +title.passwords.no.match = Confirme a senha. +title.appearance = Aparência +title.appearance.preferences = Personalização +title.create.problem = Problema na criação de conta +title.account.created = Conta criada +title.create.new.account = Criar nova conta +title.account.create.registration = Registro de conta +title.register.account = Registrar nova conta +title.notification = Notificação +title.advanced.connection.preferences = Preferências avançadas de conexão +title.error = Erro +title.status.message = Messagem de status +title.spark.preferences = Preferências +title.alert = Alerta +title.tray.information = Informação na bandeja +title.select.file.to.send = Selecione os arquivos para enviar +title.choose.directory = Selecione a pasta +title.confirmation = Confirmação +title.last.activity = Última atividade +title.add.new.group = Adicionar novo grupo +title.add.to.roster = Adicionar a lista +title.find.contacts = Buscar contatos +title.rename.roster.group = Renomear grupo de contato +title.roster = Lista de contato +title.create.room = Criar +title.conference.rooms = Salas de conferência +title.invite.to.conference = Convidar para a conferência +title.room.information = Informações da sala +title.change.nickname = Trocar apelido +title.group.chat = Chat em grupo +title.create.or.bookmark.room = Entrar em sala marcada +title.browse.room.service = Listar salas de conferência - {0} +title.name = Nome +title.address = Endereço +title.occupants = Ocupantes +title.browse.conference.services = Listar serviços de conferência +title.find.conference.service = Encontrar serviços de conferência +title.configure.chat.room = Configurar janela de Chat +title.conference.invitation = Convite de conferência +title.join.conference.room = Entrar em sala de conferência +title.view.room.information = Ver informações da sala +title.configure.room = Configurar sala +title.change.subject = Trocar assunto +title.enter.reason = Entre com o motivo +title.room.destroyed = Sala removida +title.edit.custom.message = Editar mensagens customizadas +title.set.status.message = Selecionar status +title.broadcast.message = Enviar mensagem em massa +title.broadcast.history = Histórico de mensagens em massa +title.start.chat = Iniciar Chat +title.view.bookmarks = Ver marcadores +title.downloads = Downloads +title.file.exists = Arquivo encontrado +title.disable.transport = Disabilitar transporte +title.available.transports = Transportes disponíveis +title.transports = Transportes +title.registration.error = Erro ao registrar +title.jabber.browser = Listar +title.version.and.time = Versão e Hora +title.waiting.to.call = Aguardando para fazer ligação +title.incoming.call = Ligação recebida +title.on.the.phone = No telefone +title.dial.phone = Chamar telefone +title.history.for = Histórico de Chat com {0} +title.reminder = Alerta +title.plugins = Plugins +title.preferences = Preferências +title.general.chat.settings = Preferências gerais de Chat +title.chat = Chat +title.notifications = Notificações +title.sound.preferences = Preferências de som +title.sounds = Sons +title.choose.incoming.sound = Escolha o som de recebimento +title.choose.outgoing.sound = Escolha o som de envio +title.choose.offline.sound = Escolha o som de desconectado +title.edit.profile = Editar informações do perfil +title.profile.information = Informações do perfil +title.profile.not.found = Perfil não encontrado +title.view.profile.for = Vendo o perfil de {0} +title.lookup.profile = Verificar perfil +title.add.search.service = Adicionar serviço de pesquisa +title.person.search = Busca de pessoas +title.login.settings = Preferências de login +title.login = Login +title.downloading.im.client = Fazer download do cliente de IM +title.upgrading.client = Atualizando cliente +title.cancelled = Cancelado +title.new.version.available = Nova versão disponível +title.new.client.available = Novo cliente disponível +title.file.transfer.preferences = Preferências de transferência +title.file.transfer = Transferência de arquivo +title.add.contact = Adicionar contato +title.new.roster.group = Novo grupo + +menuitem.about = Sobre +menuitem.connect = Arquivo +menuitem.contacts = Contatos +menuitem.actions = Ações +menuitem.exit = Sair +menuitem.plugins = Plugins +menuitem.logout.no.status = Logout +menuitem.logout.with.status = Logout com motivo +menuitem.show.traffic = Ver janela de tráfego +menuitem.check.for.updates = Verificar atualizações +menuitem.help = Ajuda +menuitem.preferences = Preferências +menuitem.online.help = Ajuda online +menuitem.open = Abrir +menuitem.hide = Esconder +menuitem.status = Status +menuitem.view.downloads = Ver downloads +menuitem.view.logs = Ver logs +menuitem.save = Salvar +menuitem.add = Adicionar +menuitem.add.contact = Adicionar contato +menuitem.add.contact.group = Adicionar grupo de contatos +menuitem.remove.from.group = Remover grupo de contatos +menuitem.start.a.chat = Iniciar um Chat +menuitem.rename = Renomear +menuitem.delete = Remover +menuitem.edit = Editar +menuitem.remove.from.roster = Remover da lista +menuitem.view.profile = Ver perfil +menuitem.subscribe.to = Inscrever em +menuitem.send.a.message = Enviar mensagem... +menuitem.show.empty.groups = Mostrar grupos vazios +menuitem.send.a.file = Enviar arquivo +menuitem.view.last.activity = Ver última atividade +menuitem.unban = Remover banido +menuitem.ban = Banir +menuitem.browse.service = Listar serviços +menuitem.remove.service = Remover serviço +menuitem.join.room = Entrar na sala +menuitem.remove.bookmark = Remover marcador +menuitem.join.on.startup = Entrar ao iniciar +menuitem.view.room.info = Ver informações da sala +menuitem.remove = Remover +menuitem.change.nickname = Trocar apelido +menuitem.block.user = Bloquear usuário +menuitem.unblock.user = Desbloquear usuário +menuitem.kick.user = Expulsar usuário +menuitem.voice = Palavra +menuitem.revoke.voice = Revogar palavra +menuitem.grant.voice = Conceder palavra +menuitem.ban.user = Banir usuário +menuitem.grant.moderator = Permitir moderador +menuitem.revoke.moderator = Revogar moderador +menuitem.invite.users = Convidar usuários +menuitem.invite.group.to.conference = Convidar grupo para conferência +menuitem.start.a.conference = Iniciar uma conferência... +menuitem.change.subject = Mudar assunto +menuitem.destroy.room = Remover sala +menuitem.set.status.message = Mudar mensagem de status... +menuitem.edit.status.message = Editar mensagens customizadas... +menuitem.broadcast.to.group = Enviar mensagem para grupo +menuitem.alert.when.online = Alertar quando o usuário estiver online +menuitem.remove.alert.when.online = Remover alerta +menuitem.save.as = Salvar como... +menuitem.view.client.version = Ver versão do cliente +menuitem.view.contact.history = Ver histórico do contato +menuitem.edit.my.profile = &Editar meu perfil +menuitem.lookup.profile = &Verificar perfil... +menuitem.add.as.contact = Adicionar como contato +menuitem.chat = Chat +menuitem.show.offline.group = Agrupar usuários offline +menuitem.move.to = Mover para +menuitem.copy.to = Copiar para + +tree.conference.services = Serviços de conferência +tree.users.in.room = Usuários na sala + +lookandfeel.select = Selecionar tema +lookandfeel.change.now = Mudar agora +lookandfeel.tooltip.restart.no = Não é necessário reiniciar +lookandfeel.tooltip.restart.yes = Para ativar um tema do sistema pressione Salvar e reinicie o Spark. +lookandfeel.color.label = Cores +lookandfeel.color.red = Vermelho (R) +lookandfeel.color.green = Verde (G) +lookandfeel.color.blue = Azul (B) +lookandfeel.color.opacity = Opacidade +lookandfeel.color.saved = Cor salva + +status.away = Ausente +status.custom.messages = Mensagem personalizada +status.do.not.disturb = Não incomode +status.extended.away = Ausência extendida +status.free.to.chat = Disponível para conversar +status.on.phone = Ao telefone +status.online = Online +status.pending = Pendente + +tab.general = Geral +tab.proxy = Proxy +tab.contacts = Contatos +tab.installed.plugins = Plugins instalados +tab.available.plugins = Plugins disponíveis +tab.personal = Pessoal +tab.business = Corporativo +tab.home = Residência +tab.avatar = Avatar +tab.conferences = Conferências + +group.connection = Conexão +group.conferences.found = Serviço de conferência encontrado +group.comma.delimited = Delimitado por vírgula +group.general.information = Informações gerais +group.chat.window.information = Informações da janela de Chat +group.notification.options = Opções de notificação +group.search.form = Formulário de busca +group.search.results = Resultados da busca +group.login.information = Informação de login + +tooltip.place.a.call = Chamar este usuário +tooltip.view.history = Ver histórico de conversas +tooltip.view.changelog = Ver log de mudanças +tooltip.view.readme = Ver 'Leia-me' +tooltip.notifications = Preferências de notificação de novos Chats. +available = Disponível +broadcast = Envio de mensagem em massa +offline = Offline +online = Online +participants = Participantes +unfiled = Indefinido +user.has.signed.in = Usuário entrou +user.has.signed.off = Usuário saiu +while.offline = Enquanto offline +action.clear = Limpar +action.copy = Copiar +action.cut = Recortar +action.paste = Colar +action.print = Imprimir +action.save = Salvar +action.select.all = Selecionar tudo +button.add.user = Adicionar usuário +button.add2 = Adicionar +button.copy.to.clipboard = Copiar +button.quit = Sair +button.save = Salvar +button.send = Enviar +button.send.email = Enviar E-mail +button.start.chat = Iniciar Chat +button.tasks.active = Ativas +button.tasks.all = Todas +button.view.profile = Ver perfil +checkbox.show.avatars.in.contactlist = Mostrar avatar na lista de contatos +checkbox.tabs.on.top = Mostrar Chat no topo (Necessita reiniciar) +checkbox.tabs.scroll = Use a rolagem para as guias de bate-papo (Necessita reiniciar) +checkbox.use.compression = Usar compressão +checkbox.filetransfer.ibb.only = Somente In-Band Bytestreams (IBB) +delete.log.permanently = Apagar permanentemente +delete.permanently = Apagar permanentemente? +gateway.username.password.error = Informe usuário e senha. +group.empty = Nenhum usuário online. +group.offline = Grupo offline +label.add.task = Adicionar tarefa +label.conflict.error = Conflito +label.emoticons = &Emoticons +label.message.style = Estilo de &mensagem +label.network = &Rede +label.received = &Recebido +label.show = Mostrar: +label.timeformat = Usar {0} +label.unable.to.add.contact = Impossível adicionar contato. +label.user.on.public.network = Usuário está em uma rede pública +menuitem.delete.login.information = Remover informação de login +menuitem.dial = Discar +menuitem.enter.login.information = Entrar com informação de login +menuitem.languages = Traduções +menuitem.sign.in.at.login = Conectar ao iniciar +menuitem.sign.out = Sair +menuitem.user.guide = Guia do usuário +message.authenticating = Autenticando +message.buzz.alert.notification = Chamar atenção +message.buzz.sent = Enviar alerta ao usuário. +message.cannot.add.contact.to.shared.group = Você não pode adicionar contatos a um grupo compartilhado. +message.enter.xmpp = Entre com seu usuário e senha XMPP. +message.invalid.status = Especifique um status válido. +message.invalid.username.password = Usuário e senha inválidos. +message.no.updates = Não há atualizações. +message.reconnect.attempting = Tentando... +message.reconnect.failed = Reconexão falhou. +message.reconnect.wait = Reconectando em {0} segundos. +message.restart.spark.changes = O plugin será removido na próxima inicialização. +title.about = Sobre +title.download.complete = Download completo +title.notes = Notas +title.password = Senha +tooltip.place.voice.call = Chamar este usuário +tooltip.send.email = Enviar E-mail +tooltip.start.chat = Iniciar conversa + + + + +########################################## +# # +# # +# Missing Translation: # +# # +# # +########################################## + +administrator = Administrador +answer = Resposta +apply = Aplicar +button.reject = Rejeitar +button.login = &Login +button.reconnect2 = Reconectar +button.unset.file.explorer = Explorador de arquivos não definido +button.re.detect = &Redetectar +checkbox.sort.asc.history = Ordenar mensagens no histórico de contatos por data ascendente +checkbox.disable.prev.chat.history = Desabilitar exibição da conversa anterior no Chat +checkbox.notify.typing.systemtray = Mostrar indicação de &digitação na bandeja do sistema +checkbox.notify.systemtray = Mostrar indicação de novas &mensagens na bandeja do sistema +checkbox.use.debugger.on.startup = Iniciar debugger na inicialização +checkbox.broadcast.hide.offline.user = Ocultar usuários offline +checkbox.use.krbconf = Utilizar krb5.conf ou krb5.ini +checkbox.use.krb.dns = Utilizar DNS +checkbox.use.specify.below = Especificar abaixo +checkbox.use.pki.authentication = Utilizar autenticação PKI +checkbox.transport.tab.setting = Mostrar transportes disponíveis na aba (Necessita reiniciar) +checkbox.conference.tab.setting = Mostrar serviço de conferência na aba (Necessita reiniciar) +group.chat.name.notification = Seu nome... +group.chat.name.match = Seu nome foi dito no Chat em grupo: +label.na = n/a +label.cell = Celular +label.work = Trabalho +label.home = Casa +label.contactlist.avatarsize = &Tamanho do avatar na lista de contatos: +label.downloads = Downloads +label.due = Due +label.jabber.id = ID Jabber +label.krb.realm = Realm +label.krb.kdc = KDC +label.which.pki.method = Qual método PKI? +label.choose.file = Selecionar arquivo +label.trust.store.password = Senha da Truststore +label.enter.password = Entre com a senha +label.move.focus.forwards = Mover foco adiante +label.move.focus.backwards = Mover foco para trás +label.keystore.location = Local da Keystore +label.truststore.location = Local da Truststore +label.pkcs.library.file = Arquivo de biblioteca PKCS#11 +label.x509.certificate = Certificado X.509 +label.apple.keychain = Apple KeyChain +label.add.to.roster = Adicionar usuário na sua lista +label.audio.device = Dispositivo de &áudio +label.video.device = Dispositivo de &vídeo +menuitem.bookmarks = Marcadores +menuitem.add.groupchat.myname = Destacar meu &nome quando alguém mencioná-lo +menuitem.add.groupchat.mytext = Destacar meu te&xto quando eu disser algo +menuitem.add.groupchat.popname = Mostrar popup de no&tificação quando alguém disser meu nome +menuitem.add.groupchat.showjoinleavemessage = Mostrar mensagem quando alguém se &juntar ou sair do Chat +menuitem.add.groupchat.showrolesinsteadofstatus = Mostrar ícones do papel do usuário no grupo ao invés do status +menuitem.add.groupchat.auto.accept.invite = &Aceitar automaticamente convites de chat em grupo +menuitem.add.groupchat.random.colors = Nomes recebem co&res aleatórias +menuitem.always.on.top = Sempre no topo +menuitem.open.with = Abrir com... +menuitem.block.contact = Bloquear contato +menuitem.unblock.contact = Desbloquear contato +menuitem.sign.in = Entrar +menuitem.show.offline.users = Mostrar usuários offline +menuitem.show.contact.statusmessage = Mostrar mensagem de status +menuitem.bookmark.room = Marcar sala +menuitem.refresh = Atualizar +menuitem.create.room = Criar ou juntar-se a sala +menuitem.expand.all.groups = Expandir todos os grupos +menuitem.collapse.all.groups = Recolher todos os grupos +menuitem.invite.again = Convidar novamente +menuitem.chatframe.option = Opções +menuitem.add.groupchat.invitetobookmark = Convidar usuários automaticamente para a sala marcada +message.invite.to.groupchat = {0} está convidando você para juntar-se a um Chat em grupo +message.disconnected.group.chat.error = Sua conexão foi fechada devido a um erro. Você terá que juntar-se novamente a esta sala depois de reconectar +message.disconnected.shutdown = Sua conexão foi fechada porque o servidor foi desligado +message.enter.gadugadu = Entre com o seu usuário e senha do GaduGadu abaixo +message.enter.irc = Entre com o seu nome de usuário IRC, senha e apelido abaixo +message.enter.sametime = Entre com o seu usuário e senha do Sametime abaixo +message.enter.facebook = Entre com o seu usuário e senha do Facebook abaixo +message.enter.myspace = Entre com o seu usuário e senha do MySpace abaixo +message.enter.qq = Entre com o seu QQ Number e senha abaixo +message.enter.room.password = Entre com a senha da sala +message.enter.simple = Entre com o seu usuário e senha SIMPLE abaixo +message.file.transfer.notification = Notificação de transferência de arquivo +message.file.transfer.short.message = está te enviando um arquivo chamado\: +message.file.transfer.chat.window = Requisição de transferência de arquivo: +message.gateway.username.error = O nome de usuário deve ser informado +message.gateway.password.error = A senha deve ser informada +message.gateway.nickname.error = O apelido deve ser imformado +message.invalid.jid.error = O JID especificado é inválido +message.nickname.not.acceptable = ALteração do apelido não é permitida! +message.restart.required = Você precisa reiniciar o Spark para as modificações terem efeito. Reiniciar agora? +message.room.creation.error = A sala não pode ser criada +message.server.unavailable = Não foi possível conectar ao servidor: nome inválido ou servidor fora de alcance +message.specify.contact.jid = Por facor especifique o contato JID (ex. ddman@jabber.org) +message.specify.group = Especifique o grupo de contato para adicionar o usuário +message.unable.to.retrieve.last.activity = ´Não foi possível determinar a última atividade de {0} +message.unrecoverable.error = Usuário ou senha inválidos +message.waiting.for.user.to.join = Esperando por {0} para entrar +message.groupchat.require.password = Esta sala de chat em grupo requer uma senha para entrar +message.search.for.history = Procurar histórico de conversa +tab.sso = SSO +tab.pki = PKI +title.password.required = Senha requerida +title.task.notification = Notoficação de tarefa +title.client.logs = Logs do cliente +title.bookmarks = Marcadores +title.add.contact.group = Adicionar grupo de contato +title.advanced.connection.usesso = Utilizar Single Sign-On (SSO) via GSSAPI +title.delete.file = Você realmente quer excluir este arquivo? +title.error.couldnot.open.file = Não foi possível abrir o arquivo +title.error.delete.file = Não foi possível excluir o arquivo +title.error.find.app = Não foi possível encontrar um aplicativo correspondente +title.error.rename.file = Não foi possível renomear o arquivo +title.file = Arquivo +title.filesize = Tamanho +title.gadugadu.registration = Credenciais da conta GaduGadu +title.general.media = Configurações de mídia +title.group.chat.settings = Configurações de Chat em grupo +title.irc.registration = Credenciais da conta IRC +title.sametime.registration = Credenciais da conta do Sametime +title.facebook.registration = Credenciais da conta do Facebook +title.myspace.registration = Credenciais da conta do MySpace +title.input.fileexplorer = Por favor insira o nome do seu explorador de arquivos: +title.input.newname = Por favor insira o novo nome\: +title.input.openwith = Por favor insira o nome do aplicativo que você quer usar: +title.login.error = Erro de login +title.no.updates = Não há atualizações +title.qq.registration = Credenciais da conta QQ +title.simple.registration = Credenciais da conta SIMPLE +title.tasks = Tarefas +title.xmpp.registration = XMPP account credentials +title.appearance.showVCards = Mostrar &VCards na lista de contatos +title.subscription.request = Requisição de subscrição +tooltip.appearance = Mudar a aparência das suas conversas +tooltip.file.transfer = Preferências para transferência de arquivos diff --git a/core/src/main/resources/i18n/spark_i18n_ru_RU.properties b/core/src/main/resources/i18n/spark_i18n_ru_RU.properties new file mode 100644 index 000000000..d288322b2 --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_ru_RU.properties @@ -0,0 +1,1119 @@ +accept = ПринÑть +is.active = Active +add = Добавить +administrator = ÐдминиÑтратор +apply = Применить +available = Ð’ Ñети +broadcast = РаÑÑылка +cancel = Отмена +delete = Удалить +details = Детали +close = Закрыть +create = Создать +date = Дата +description = ОпиÑание +from = От +invite = ПриглаÑить +join = Войти +no = Ðет +not.registered = Ðе зарегиÑтрирован +occupants = УчаÑтников +offline = Ðе в Ñети +online = Ð’ Ñети +ok = Ок +open = Открыть +open.folder = Открыть папку +participants = УчаÑтники +refresh = Обновить +reject = Отклонить +retry = Повторить +room.name = Ð˜Ð¼Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹ +save = Сохранить +subject = Тема +unfiled = Ðи в одной группе +use.default = По умолчанию +user.has.signed.in = подключилÑÑ. +user.has.signed.off = отключилÑÑ. +while.offline = Пока не в Ñети +yes = Да + +action.clear = ОчиÑтить +action.copy = Скопировать +action.cut = Вырезать +action.paste = Ð’Ñтавить +action.print = Печать +action.save = Сохранить +action.select.all = Выбрать вÑÑ‘ + +button.accept = ПринÑть +button.add = Добавить +button.add.a.contact = Добавить контакт +button.add.bookmark = Добавить закладку +button.add.service = Добавить ÑÐµÑ€Ð²Ð¸Ñ +button.add.user = Добавить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ +button.add2 = Добавить +button.advanced = ÐаÑтройки +button.approve = Разрешить +button.bookmark.room = Комнату в закладки +button.browse = Выбрать... +button.browse2 = Выбрать... +button.browse3 = Выбрать.. +button.cancel = Отмена +button.cert.info = Подробнее +button.clear = ОчиÑтить +button.close = Закрыть +button.copy.to.clipboard = Скопировать в буфер обмена +button.create.account = Создать учетную запиÑÑŒ +button.create.room = Создать или войти в комнату +button.decline = Отклонить +button.deny = Отказать +button.dial.number = Ðабрать номер +button.find = Ðайти +button.join = Войти +button.join.room = Войти в выбранную комнату +button.login = Войти +button.new = Ðовый +button.profile = Профиль +button.quit = Выход из Spark +button.re.detect = Обновить +button.reconnect = ПереподключитьÑÑ +button.reconnect2 = ПереподключитьÑÑ +button.refresh = Обновить +button.register = ЗарегиÑтрировать +button.reject = Отклонить +button.remove.bookmark = Убрать закладку +button.roster = Контакт лиÑÑ‚ +button.save = Сохранить +button.save.for.future.use = Сохранить Ð´Ð»Ñ Ð¿Ð¾Ñледующего иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ +button.search = ПоиÑк +button.send = ПоÑлать +button.send.email = Email +button.start.chat = Чат +button.tasks.active = Ðктивные +button.tasks.all = Ð’Ñе +button.unset.file.explorer = СнÑть браузер файлов +button.update = Обновить +button.view.notes = Показать Заметки +button.view.profile = Показать подробнее +button.view.tasklist = Показать СпиÑок задач +button.check.validity = Проверка дейÑтвительноÑти +button.show.certificate = Показать Ñертификат +button.delete.saved.passwords = Удалить вÑе пароли Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð° в ÑиÑтему + +table.column.certificate.subject = Сертификат +table.column.certificate.validity = ДейÑтвительноÑть +table.column.certificate.exempted = ИÑключение + +checkbox.allow.buzz = Разрешить пользователÑм «будить» ваÑ. +checkbox.auto.discover.port = ÐвтоматичеÑки найти Ñервер и порт +checkbox.auto.login = ÐвтоматичеÑкий вход +checkbox.login.as.invisible = ПодключатьÑÑ "невидимкой" +checkbox.login.anonymously = ПодключатьÑÑ Ð°Ð½Ð¾Ð½Ð¸Ð¼Ð½Ð¾ +checkbox.disable.chat.history = Отключить иÑторию чата +checkbox.sort.asc.history = Сортировать ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð² иÑтории контакта по возраÑтанию даты +checkbox.disable.prev.chat.history = Отключить показ предыдущих беÑед в чате +checkbox.enable.emoticons = Разрешить Ñмайлики +checkbox.graying.out = ТуÑклые ÑтатуÑÑ‹ контактов (требуетÑÑ Ð¿ÐµÑ€ÐµÐ·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°) +checkbox.idle.enabled = Разрешить «Отошел» +checkbox.launch.on.startup = ЗапуÑкать при загрузке +checkbox.reconnect.info = Показывать при переподключении +checkbox.reconnect.panel.big = Показывать панель +checkbox.reconnect.panel.small = Показывать в ÑпиÑке групп +checkbox.reconnect.panel.icon = Показывать иконку +checkbox.notify.user.comes.online = Оповещать когда пользователь входит в Ñеть +checkbox.notify.user.goes.offline = Оповещать когда пользователь выходит из Ñети +checkbox.notify.typing.systemtray = Оповещать когда пользователь набирает текÑÑ‚ (ÑиÑтемный трей) +checkbox.notify.systemtray = Оповещать о новых ÑообщениÑÑ… (ÑиÑтемный трей) +checkbox.permanent = ПоÑтоÑÐ½Ð½Ð°Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ð° +checkbox.play.sound.on.invitation = Проиграть звук при получении Ð¿Ñ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ +checkbox.play.sound.on.new.message = Проиграть звук при получении нового ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ +checkbox.play.sound.on.outgoing.message = Проиграть звук при отправке ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ +checkbox.play.sound.when.offline = Проиграть звук при отключении Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ +checkbox.private.room = Ð›Ð¸Ñ‡Ð½Ð°Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ð° +checkbox.save.password = Сохранить пароль +checkbox.show.avatars.in.contactlist = Показывать &Avatars в ÑпиÑке контактов +checkbox.show.notifications.in.conference = Показывать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð² конференции +checkbox.show.time.in.chat.window = Показывать Ð²Ñ€ÐµÐ¼Ñ Ð² окне чата +checkbox.show.toaster = УведомлÑть о каждом Ñообщении +checkbox.disable.asterisk.toaster = Отключить вÑплывающее окно на телефоне +checkbox.split.chat.window = ПрикреплÑть к окнам (требуетÑÑ Ð¿ÐµÑ€ÐµÐ·Ð°Ð¿ÑƒÑк) +checkbox.start.in.tray = ЗапуÑкать Ñвёрнутым в трей +checkbox.click.single.tray = ИÑпользовать одиночный клик в трее, чтобы активировать Spark (требуетÑÑ Ð¿ÐµÑ€ÐµÐ·Ð°Ð¿ÑƒÑк) +checkbox.tabs.on.top = Вкладки чата вверху (требуетÑÑ Ð¿ÐµÑ€ÐµÐ·Ð°Ð¿ÑƒÑк) +checkbox.tabs.scroll = ИÑпользовать прокрутку Ð´Ð»Ñ Ð²ÐºÐ»Ð°Ð´Ð¾Ðº чата (требуетÑÑ Ð¿ÐµÑ€ÐµÐ·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°) +checkbox.use.compression = ИÑпользовать Ñжатие +checkbox.use.debugger.on.startup = Ðачать отладку при запуÑке +checkbox.use.proxy.server = ИÑпользовать Proxy Ñервер +checkbox.use.system.look.and.feel = ИÑпользовать темы (System Look And &Feel) (требуетÑÑ Ð¿ÐµÑ€ÐµÐ·Ð°Ð¿ÑƒÑк) +checkbox.window.to.front = Показать поверх окон +checkbox.broadcast.hide.offline.user = СпрÑтать ÑобеÑедников "не в Ñети" +checkbox.use.krbconf = ИÑпользовать krb5.conf или krb5.ini +checkbox.use.krb.dns = ИÑпользовать DNS +checkbox.use.specify.below = Указать ниже +checkbox.use.pki.authentication = ИÑпользовать проверку подлинноÑти PKI +checkbox.transport.tab.setting = Показать доÑтупные транÑпорты во вкладке (требуетÑÑ Ð¿ÐµÑ€ÐµÐ·Ð°Ð¿ÑƒÑк) +checkbox.conference.tab.setting = Показать ÑÐµÑ€Ð²Ð¸Ñ ÐºÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ð¸ во вкладке (требуетÑÑ Ð¿ÐµÑ€ÐµÐ·Ð°Ð¿ÑƒÑк) +checkbox.use.hostname.as.resource = ИÑпользовать Ð¸Ð¼Ñ Ñ…Ð¾Ñта в качеÑтве реÑурÑа +checkbox.use.version.as.resource = ИÑпользовать верÑию Spark в качеÑтве реÑурÑа +checkbox.accept.all.certificates = Принимать вÑе Ñертификаты(ÑамозаверÑющие/проÑроченные/не доверенные) +checkbox.disable.hostname.verification = Отключить проверку имени хоÑта(не рекомендуетÑÑ) +checkbox.allow.client.side.authentication = Разрешить аутентификацию на Ñтороне клиента +checkbox.accept.all = ПринÑть вÑе +checkbox.accept.expired = ПринÑть иÑтёкшие +checkbox.accept.not.valid.yet = ПринÑть ещё не дейÑтвительные +checkbox.accept.self.signed = ПринÑть ÑамозаверÑющие +checkbox.accept.revoked = ПринÑть отменённые +checkbox.check.crl = Проверить CRL +checkbox.check.ocsp = Проверить OCSP +checkbox.allow.soft.fail = Разрешить политику soft fail +checkbox.on.exception.list = Ð’ ÑпиÑке иÑключений +checkbox.filetransfer.ibb.only = Только In-Band Bytestreams +checkbox.filetransfer.autoaccept.presence = ÐвтоматичеÑки принимать передачу файлов от извеÑтных контактов +checkbox.close.unread.message = Спрашивать при закрытии окна еÑли еÑть непрочитанные ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ +radio.encryptionmode.required = ТребуетÑÑ +radio.encryptionmode.ifpossible = ЕÑли возможно +radio.encryptionmode.disabled = Выключить + +delete.log.permanently = Удалить журнал навÑегда +delete.permanently = Удалить навÑегда? + +gateway.username.password.error = Ðеобходимо указать Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ / или пароль + +group.chat.window.information = Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ чате +group.comma.delimited = Разделенные запÑтой +group.conferences.found = Ðайдены ÑервиÑÑ‹ конференций +group.connection = Подключение +group.empty = Ð’ Ñтой группе нет контактов, которые в Ñети +group.general.information = ОÑÐ½Ð¾Ð²Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ +group.login.information = Данные учетной запиÑи +group.notification.options = ÐаÑтройки уведомлений +group.offline = Оффлайн группа +group.search.form = ПоиÑк +group.search.results = Результаты поиÑка +group.chat.name.notification = Видел твоё имÑ... +group.chat.name.match = Ваше Ð¸Ð¼Ñ Ð±Ñ‹Ð»Ð¾ Ñказано в групповом чате: +group.send_config.error = ИÑключение при попытке Ñохранить обновленную форму! +group.encryption_mode = Режим ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ + +label.na = n/a +label.home = Домашний +label.accounts = Ðккаунты +label.add.conference.service = Добавить Ñервер конференций +label.add.jid = Добавить JID +label.add.task = Добавить задачу +label.auto.login = ÐвтоматичеÑкий вход +label.available.users.in.roster = ДоÑтупные пользователи в роÑтере +label.avatar = Ðватар: +label.broadcast.history.search.date = Дата поиÑка (год-меÑÑц): +label.cancel = Отмена +label.cell = Мобильный +label.change.password.to = Сменить пароль на +label.chatroom.fontsize = Размер шрифта в чате: +label.chatroom.maxcurrenthistorysize = МакÑимальный размер текущей иÑтории: +label.city = Город +label.close = Закрыть +label.company = ÐšÐ¾Ð¼Ð¿Ð°Ð½Ð¸Ñ +label.confirm.password = Повтор Ð¿Ð°Ñ€Ð¾Ð»Ñ +label.conflict.error = Ðевозможно подключитьÑÑ. Уже подключен Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð³Ð¾ меÑта. +label.contact.to.find = Ðайти контакт +label.recent.conversation = Ðедавние разговоры +label.frequent.contacts = ЧаÑтые контакты +label.contactlist.avatarsize = Размер аватара в ÑпиÑке контактов: +label.contactlist.fontsize = Размер шрифта в ÑпиÑке контактов: +label.country = Страна +label.create.account = Создать учетную запиÑÑŒ +label.department = Отдел +label.dial = Ðабрать +label.display.time = Ð’ течении: +label.downloads = Загрузки +label.due = Срок +label.email.address = Email Ð°Ð´Ñ€ÐµÑ +label.emoticons = Смайлики +label.enter.address = Введите Ð¸Ð¼Ñ +label.enter.group.name = Введите новое Ð¸Ð¼Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹ +label.fax = Ð¤Ð°ÐºÑ +label.find = Ðайти +label.first.name = Ð˜Ð¼Ñ +label.group = Группа +label.host = Сервер +label.invited.users = ПриглаÑить пользователей +label.jabber.address = &Jabber Ð°Ð´Ñ€ÐµÑ +label.jabber.id = &Jabber ID +label.jid = &JID +label.job.title = ДолжноÑть +label.last.name = Ð¤Ð°Ð¼Ð¸Ð»Ð¸Ñ +label.local.time = МеÑтное Ð²Ñ€ÐµÐ¼Ñ +label.message = Сообщение +label.message.style = Стиль ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ +label.middle.name = ОтчеÑтво +label.minutes.before.stale.chat = Минут неактивноÑти до уÑÑ‚Ð°Ñ€ÐµÐ²Ð°Ð½Ð¸Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹ +label.mobile = Мобильный +label.name = Ð˜Ð¼Ñ +label.network = Сеть +label.new.nickname = Ðовый ник +label.nickname = Ð˜Ð¼Ñ +label.number = Ðомер +label.ok = ОК +label.old.ssl = ИÑпользовать метод Direct TLS +label.os = ОС +label.pager = Пейджер +label.password = Пароль +label.passwordreset = ВоÑÑтановление Ð¿Ð°Ñ€Ð¾Ð»Ñ +label.phone = Телефон +label.port = Порт +label.postal.code = Почтовый Ð¸Ð½Ð´ÐµÐºÑ +label.presence = Ð¡Ñ‚Ð°Ñ‚ÑƒÑ +label.priority = Приоритет +label.protocol = Протокол +label.received = ПоÑлано +label.rename.to = Переименовать +label.resource = РеÑÑƒÑ€Ñ +label.response.timeout = Таймаут (Ñек) +label.reconnect.delay = Задержка повторного Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ (Ñек) (требуетÑÑ Ð¿ÐµÑ€ÐµÐ·Ð°Ð¿ÑƒÑк) +label.room = Комната +label.room.name = Ðазвание комнаты +label.room.topic = Заголовок комнаты +label.search = ИÑкать +label.search.service = Ð¡ÐµÑ€Ð²Ð¸Ñ Ð¿Ð¾Ð¸Ñка +label.seconds = Секунд(-Ñ‹) +label.server = До&мен +label.server.address = ÐÐ´Ñ€ÐµÑ Ñервера +label.show = Показать: +label.software = Клиент +label.state.and.province = ОблаÑть +label.street.address = ÐÐ´Ñ€ÐµÑ +label.time = ВремÑ: {0} +label.time.till.idle = «Отошел» через (мин) +label.time.till.idlemessage = ÐвтоматичеÑкое Ñообщение при отÑутÑтвии активноÑти +label.timeformat = ИÑпользуйте {0} +label.transfer.download.directory = СохранÑть в папку: +label.transfer.timeout = Таймаут передачи(минут): +label.unable.to.add.contact = Ðевозможно добавить контакт. +label.use.default = По умолчанию +label.user.on.public.network = Пользователь из Ñети +label.username = Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ +label.version = ВерÑÐ¸Ñ +label.web.page = Интернет +label.work = Рабочий +label.xmpp.port = &XMPP порт +label.krb.realm = Realm +label.krb.kdc = KDC +label.which.pki.method = Какой метод PKI? +label.choose.file = Выберите файл +label.trust.store.password = Пароль доверенного хранилища +label.enter.password = Введите пароль +label.move.focus.forwards = Сдвинуть Ñ„Ð¾ÐºÑƒÑ Ð²Ð¿ÐµÑ€ÐµÐ´ +label.move.focus.backwards = Сдвинуть Ñ„Ð¾ÐºÑƒÑ Ð½Ð°Ð·Ð°Ð´ +label.keystore.location = РаÑположение хранилища ключей +label.truststore.location = РаÑположение TrustStore +label.pkcs.library.file = Файл библиотеки PKCS#11 +label.x509.certificate = Сертификат X.509 +label.apple.keychain = Apple KeyChain +label.add.to.roster = Добавить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² ÑпиÑок контактов +label.audio.device = Ðудио уÑтройÑтво +label.video.device = Видео уÑтройÑтво +label.certificate.version = ВерÑÐ¸Ñ +label.certificate.serial.number = Серийный номер +label.certificate.signature.value = Значение подпиÑи +label.certificate.signature.algorithm = Ðлгоритм подпиÑи +label.certificate.issuer = Издатель +label.certificate.subject = ПредÑтавитель +label.certificate.not.before = ÐедейÑтвительно раньше +label.certificate.not.after = ÐедейÑтвительно позже +label.certificate.public.key = Публичный ключ +label.certificate.public.key.algorithm = Ðлгоритм публичного ключа +label.certificate.issuer.unique.id = Уникальный идентификатор Ð¸Ð·Ð´Ð°Ñ‚ÐµÐ»Ñ +label.certificate.subject.unique.id = Уникальный идентификатор предÑÑ‚Ð°Ð²Ð¸Ñ‚ÐµÐ»Ñ +label.certificate.add.certificate.to.truststore = Добавить Ñертификат в TrustStore +label.certificate.add.certificate.to.identitystore = Добавить Ñертификат в IdentityStore +label.certificate.status = Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñертификата + +menuitem.about = О программе +menuitem.actions = ДейÑÑ‚Ð²Ð¸Ñ +menuitem.bookmarks = Закладки +menuitem.add = Добавить +menuitem.add.as.contact = Добавить контакт +menuitem.add.contact = Добавить контакт... +menuitem.add.contact.group = Добавить группу... +menuitem.add.groupchat.myname = ПодÑветить моё Ð¸Ð¼Ñ ÐºÐ¾Ð³Ð´Ð° его произноÑÑÑ‚ +menuitem.add.groupchat.mytext = ПодÑветить мои ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ +menuitem.add.groupchat.popname = Показать вÑплывающее уведомление когда произноÑÑÑ‚ мое Ð¸Ð¼Ñ +menuitem.add.groupchat.showjoinleavemessage = Оповещать при входе/выходе пользователей +menuitem.add.groupchat.showrolesinsteadofstatus = Показывать значки ролей чата вмеÑто значков приÑутÑÑ‚Ð²Ð¸Ñ +menuitem.add.groupchat.auto.accept.invite = ÐвтоматичеÑки принимать Ð¿Ñ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ðº конференции +menuitem.add.groupchat.random.colors = Случайные цвета Ð´Ð»Ñ Ð¸Ð¼Ñ‘Ð½ +menuitem.affiliation = ПринадлежноÑть +menuitem.always.on.top = Ð’Ñегда поверх +menuitem.alert.when.online = Сообщить когда пользователь будет в Ñети +menuitem.ban = Запретить +menuitem.ban.user = Запретить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ +menuitem.block.contact = Заблокировать контакт +menuitem.block.user = Заблокировать Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ +menuitem.broadcast.to.group = РаÑÑылка группе +menuitem.browse.service = СпиÑок ÑервиÑов +menuitem.change.nickname = Сменить ник +menuitem.change.subject = Сменить тему +menuitem.chat = Чат +menuitem.check.for.updates = Проверить Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ +menuitem.connect = Файл +menuitem.contacts = Контакты +menuitem.copy.to = Скопировать в +menuitem.delete = Удалить +menuitem.delete.login.information = Удалить учетные данные +menuitem.destroy.room = Уничтожить комнату +menuitem.dial = Ðабрать +menuitem.edit = Редактировать +menuitem.edit.my.profile = Редактировать мой профиль... +menuitem.edit.status.message = Редактировать ÑтатуÑÑ‹... +menuitem.enter.login.information = ВвеÑти учетные данные +menuitem.exit = Выход +menuitem.grant.moderator = Дать права модератора +menuitem.grant.member = Дать права учаÑтника +menuitem.grant.admin = Дать права админиÑтратора +menuitem.grant.owner = Дать права владельца +menuitem.grant.voice = Дать право голоÑа +menuitem.help = Помощь +menuitem.hide = Скрыть +menuitem.invite.group.to.conference = ПриглаÑить группу в конференцию +menuitem.invite.users = ПриглаÑить пользователей +menuitem.join.on.startup = Входить при загрузке +menuitem.join.room = Войти в комнату +menuitem.kick.user = Выгнать Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ +menuitem.languages = Язык +menuitem.logout.no.status = Выйти +menuitem.logout.with.status = Выйти указав причину +menuitem.lookup.profile = ПоÑмотреть профиль... +menuitem.move.to = ПеремеÑтить в +menuitem.online.help = Spark форумы +menuitem.open = Открыть +menuitem.open.with = Открыть в ... +menuitem.plugins = Плагины +menuitem.preferences = ÐаÑтройки +menuitem.remove = Удалить +menuitem.remove.alert.when.online = Убрать уведомление +menuitem.remove.bookmark = Удалить закладку +menuitem.remove.from.group = Удалить из группы +menuitem.remove.from.roster = Удалить из контакт-лиÑта +menuitem.unblock.contact = Разблокировать контакт +menuitem.remove.service = Удалить ÑÐµÑ€Ð²Ð¸Ñ +menuitem.rename = Переименовать +menuitem.revoke.moderator = ОтнÑть права модератора +menuitem.revoke.voice = ОтнÑть право голоÑа +menuitem.revoke.member = ОтнÑть право учаÑтника +menuitem.revoke.admin = ОтнÑть право админиÑтратора +menuitem.revoke.owner = ОтнÑть права владельца +menuitem.save = Сохранить +menuitem.save.as = Сохранить как... +menuitem.send.a.file = ПоÑлать файл +menuitem.send.a.message = РаÑÑылка выбранным пользователÑм... +menuitem.set.status.message = УÑтановить ÑтатуÑ... +menuitem.show.empty.groups = Показывать пуÑтые группы +menuitem.show.offline.group = Группировать пользователей не в Ñети +menuitem.show.traffic = Показать окно трафика +menuitem.sign.in = Войти +menuitem.sign.in.at.login = Входить при загрузке +menuitem.sign.out = Выйти +menuitem.start.a.chat = Ðачать чат... +menuitem.start.a.conference = Ðачать конференцию... +menuitem.status = Ð¡Ñ‚Ð°Ñ‚ÑƒÑ +menuitem.subscribe.to = ПодпиÑатьÑÑ +menuitem.unban = Убрать запрет +menuitem.unblock.user = Разблокировать Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ +menuitem.user.guide = ИнÑÑ‚Ñ€ÑƒÐºÑ†Ð¸Ñ +menuitem.view.client.version = Показать верÑию клиента +menuitem.view.contact.history = Показать иÑторию +menuitem.view.downloads = Открыть папку закачек +menuitem.view.last.activity = Показать Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ñледней активноÑти +menuitem.view.logs = Показать логи +menuitem.view.profile = Показать профиль +menuitem.view.room.info = Показать информацию о комнате +menuitem.voice = Право голоÑа +menuitem.show.offline.users = Показывать пользователей не в Ñети +menuitem.show.contact.statusmessage = Показать ÑÑ‚Ð°Ñ‚ÑƒÑ Ñообщение +menuitem.bookmark.room = Добавить комнату в закладки +menuitem.refresh = Обновить +menuitem.create.room = Создать или войти в комнату +menuitem.expand.all.groups = Развернуть вÑе Группы +menuitem.collapse.all.groups = Свернуть вÑе Группы +menuitem.invite.again = ПриглаÑить Ñнова +menuitem.chatframe.option = Опции +menuitem.add.groupchat.invitetobookmark = ÐвтоматичеÑки приглашать пользователей в комнату в закладках +menuitem.certificate.files.filter = Файлы Ñертификатов(*.cer), (*.crt), (*.der) + +message = Сообщение +message.account.create = Создать учетную запиÑÑŒ +message.account.created = Ð£Ñ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ Ñоздана +message.account.error = Укажите Ñервер Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÑƒÑ‡ÐµÑ‚Ð½Ð¾Ð¹ запиÑи +message.add.a.contact = Добавить контакт +message.add.conference.service = Добавить ÑÐµÑ€Ð²Ð¸Ñ ÐºÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ð¹ +message.add.contact.to.list = Добавить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² контакт лиÑÑ‚ +message.add.favorite.room = Добавить комнату в избранное или войти Ñразу.. +message.add.this.user.to.your.roster = Добавить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² контакт лиÑÑ‚ +message.add.to.roster = Добавить в контакт лиÑÑ‚ +message.add.user = Добавить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² контакт лиÑÑ‚? +message.alert.notify = Информационное Ñообщение +message.already.exists = Ð£Ñ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ уже ÑущеÑтвует. Попробуйте другое Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ. +message.create.account.not.allowed = Создание учетной запиÑи на Ñервере запрещено +message.approve.subscription = Разрешить {0} добавить Ð²Ð°Ñ Ð² его ÑпиÑок контактов? +message.authenticating = ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ +message.away.idle = «Отошел» из-за проÑтоÑ. +message.bookmark.temporary.room.error = Ð’Ñ‹ не можете добавлÑть в закладки временные комнаты +message.broadcast.from = РаÑÑылка от {0} +message.broadcast.no.user.selected = ПожалуйÑта, выберите Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одного Ð¿Ð¾Ð»ÑƒÑ‡Ð°Ñ‚ÐµÐ»Ñ +message.broadcast.no.text = ПожалуйÑта, введите текÑÑ‚ Ð´Ð»Ñ Ñ€Ð°ÑÑылки +message.broadcast.message.sent = РаÑÑылка отправлена +message.broadcast.to = Введите текÑÑ‚ раÑÑылки Ð´Ð»Ñ {0} +message.hasbeenbroadcast.to = РаÑÑылка отправлена Ñледующим пользователÑм:\n{0} +message.buzz.alert.notification = Привлечь внимание пользователÑ. +message.buzz.message = {0} требует вашего Ð²Ð½Ð¸Ð¼Ð°Ð½Ð¸Ñ +message.buzz.sent = «Разбудить» пользователÑ. +message.calling = Вызываю {0} +message.came.online = {0} в Ñети Ñ {1} +message.cannot.add.contact.to.shared.group = Ð’Ñ‹ не можете добавлÑть контакты в Общие группы. +message.cert.hostname.verification.failed = Ошибка проверки имени хоÑта Ñертификата +message.cert.verification.failed = Ðевозможно проверить Ñертификат +message.chat.session.ended = Чат закончилÑÑ Ð² {0} +message.click.to.open = Открыть +message.client.information = Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ клиенте Ð´Ð»Ñ {0} +message.close.other.chats = Закрыть вÑе другие чаты +message.close.stale.chats = Закрыть уÑтаревшие чаты +message.close.this.chat = Закрыть чат +message.close.unread.window = У Ð²Ð°Ñ ÐµÑть непрочитанные ÑообщениÑ, вы точно хотите закрыть окно? +message.conference.info.error = Ðевозможно получить информацию о конференции. Попробуйте позже. +message.conference.service.error = Ð¡ÐµÑ€Ð²Ð¸Ñ Ð½Ðµ найден. +message.confirm.destruction.of.room = Уничтожение комнаты выгонит вÑех пользователей из Ñтой комнаты. Продолжить? +message.confirmation.password.error = Введите Повтор паролÑ. +message.connecting.please.wait = Подключение. Ждите... +message.connection.failed = Ðет ÑвÑзи Ñ {0}. +message.create.account = Ð£Ñ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ не Ñоздана. +message.create.or.join.room = Создать или войти в комнату +message.current.status = Показывать другим Ваш ÑтатуÑ. +message.default.error = Обнаружена ошибка. +message.delete.all.history = Удалить вÑÑŽ иÑторию? +message.delete.confirmation = ДейÑтвительно удалить {0}? +message.disable.transport = Удалить учетные данные Ð´Ð»Ñ {0}? +message.disconnected.conflict.error = Ð’Ñ‹ отключены из-за входа Вашей учетной запиÑи Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð³Ð¾ компьютера. +message.disconnected.error = Подключение завершилоÑÑŒ ошибкой. +message.disconnected.group.chat.error = Подключение завершилоÑÑŒ ошибкой. Вам надо будет зайти заново в Ñту комнату поÑле переподключениÑ. +message.disconnected.shutdown = Ваше Ñоединение было закрыто, так как Ñервер был оÑтановлен +message.downloading = Загружено {0} +message.downloading.spark.plug = ЗагружаетÑÑ Spark-Plug +message.end.chat = Закрыть Ñтот чат? +message.end.conversation = Закрыть Ñту беÑеду? +message.enter.broadcast.message = Введите Ñообщение Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ñ… пользователей. +message.enter.gadugadu = Введите Ваше Ð¸Ð¼Ñ Ð² GaduGadu и пароль. +message.enter.irc = Введите Ваше Ð¸Ð¼Ñ Ð² IRC и пароль. +message.enter.sametime = Введите Ваше Ð¸Ð¼Ñ Ð² Sametime и пароль. +message.enter.facebook = Введите Ваше Ð¸Ð¼Ñ Ð² Facebook и пароль. +message.enter.myspace = Введите Ваше Ð¸Ð¼Ñ Ð² MySpace и пароль. +message.enter.jabber.id = Введите Jabber ID. +message.enter.message.to.broadcast = Введите текÑÑ‚ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñ€Ð°ÑÑылки Ð´Ð»Ñ Ð²Ñех в Вашем контакт лиÑте. +message.enter.new.subject = Введите тему +message.enter.qq = Введите Ваше номер в QQ и пароль. +message.enter.room.password = Введите пароль Ð´Ð»Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹ +message.enter.simple = Введите Ваше Ð¸Ð¼Ñ Ð² SIMPLE и пароль. +message.enter.valid.jid = Введите корректный Jabber ID +message.enter.xmpp = Введите Ваше Ð¸Ð¼Ñ Ð² XMPP и пароль. +message.error.during.file.transfer = Ошибка во Ð²Ñ€ÐµÐ¼Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ð¸ файла. +message.error.must.use.reserved.nick = Ð’Ñ‹ должны иÑпользовать зарезервированной комнатой ник. +message.error.nickname.in.use = Ваш желаемый ник уже иÑпользуетÑÑ Ð¸Ð»Ð¸ зарезервирован кем-то другим. +message.error.no.permission.create.room = У Ð²Ð°Ñ Ð½ÐµÑ‚ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð½Ð° Ñоздание комнаты. +message.error.no.response = Ðет ответа от Ñервера. +message.error.not.member = Ð’Ñ‹ не ÑвлÑетеÑÑŒ учаÑтником Ñтой комнаты.\nЭта комната требует, чтобы вы были учаÑтником, чтобы приÑоединитьÑÑ. +message.error.room.not.exist = Комната, в которую вы пытаетеÑÑŒ войти, не ÑущеÑтвует. +message.error.room.password.incorrect = Пароль не Ñовпадал Ñ Ð¿Ð°Ñ€Ð¾Ð»ÐµÐ¼ комнаты. +message.error.unable.join.room = Ðевозможно приÑоединитьÑÑ Ðº комнате. +message.file.exists.question = Файл уже ÑущеÑтвует. ПерезапиÑать? +message.file.size = Размер файла: {0} +message.file.transfer.canceled = Ð’Ñ‹ отменили приём файла. +message.file.transfer.rejected = {0} не подтвердил передачу файла. +message.file.transfer.dirnull = Каталог загрузки Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ð¸ файлов недейÑтвителен +message.file.transfer.nodir = Каталог загрузки Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ð¸ файлов не ÑущеÑтвует +message.file.transfer.cantwritedir = Ðевозможно запиÑать в каталог Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ð¸ файла +message.file.transfer.notification = Уведомление передачи файлов +message.file.transfer.short.message = отправлÑет вам файл Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼\: +message.file.transfer.chat.window = Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ð¸ файлов: +message.file.transfer.file.too.big.error = Выбранный файл Ñлишком велик.\nМакÑимальный размер файла {0}, выбранный файл - {1} +message.file.transfer.file.too.big.warning = Выбранный файл Ñлишком велик.\nÐ’Ñе равно продолжить? +message.file.transfer.direrror.setdir = Ðажмите здеÑÑŒ, чтобы изменить каталог +message.file.transfer.history.request.sent = Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° передачу файла "{0}" ({1}) отправлен пользователю {2}. +message.file.transfer.history.send.complete = Файл "{0}" был уÑпешно передан пользователю {1}. +message.file.transfer.history.send.error = Ðе удалоÑÑŒ отправить файл "{0}" пользователю {1}. +message.file.transfer.history.send.canceled = Отправка файла "{0}" пользователю {1} отменена. +message.file.transfer.history.contact.rejected = {1} отклонил Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° передачу файла "{0}". +message.file.transfer.history.request.received = Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° передачу файла "{0}" ({1}) получен от {2}. +message.file.transfer.history.you.rejected = Ð’Ñ‹ отклонили Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° передачу файла "{0}" от {1}. +message.file.transfer.history.you.accepted = Ð’Ñ‹ принÑли Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° передачу файла "{0}" от {1}. +message.file.transfer.history.receive.success = Файл "{0}" уÑпешно принÑÑ‚ от {1}. +message.file.transfer.history.receive.failed = Ðе удалоÑÑŒ принÑть файл "{0}" от {1}. +message.file.transfer.history.receive.canceled = Прием файла "{0}" от {1} отменен. +message.find.conference.services = ПоиÑк ÑервиÑов конференций +message.forbidden.error = Сервер Ñообщил об ошибке доÑтупа. +message.gateway.username.error = Ðеобходимо указать Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ +message.gateway.password.error = Ðеобходимо указать пароль +message.gateway.nickname.error = Ðеобходимо указать пÑевдоним +message.general.error = Подключение потерÑно из-за {0} +message.generic.reconnect.message = Ð’Ñ‹ отключены от Ñервера. Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð½Ð°Ð¶Ð¼Ð¸Ñ‚Ðµ кнопку «ПереподключитьÑÑ». +message.idle.for = Ðеактивен {0} +message.image.small.resolution = Размер Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¼ÐµÐ½ÐµÐµ 32x32 пикÑелей +message.invalid.jabber.id = Ðекорректный Jabber ID +message.invalid.jid.error = JID некорректный. +message.invalid.status = Введите корректное название ÑтатуÑа. +message.invalid.username.password = Ðеправильное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ пароль +message.invite.to.groupchat = {0} приглашает Ð²Ð°Ñ Ð¿Ñ€Ð¸ÑоединитьÑÑ Ðº групповому чату +message.invite.users.to.conference = ПриглаÑить пользователей в комнату +message.is.shared.group = {0} is a shared group +message.is.typing.a.message = {0} пишет... +message.join.conference.room = Войти в комнату +message.kicked.error = Ð’Ñ‹ не можете кикнуть {0} из комнаты. +message.last.message.received = ПоÑледнее Ñообщение было в {0} +message.loading.please.wait = Загрузка. Ждите... +message.locked.workstation = Пользователь заблокировал компьютер. +message.name.of.group = Ð˜Ð¼Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹ +message.name.of.search.service.question = Ð˜Ð¼Ñ ÑервиÑа поиÑка? +message.negotiate.file.transfer = УÑтановка ÑвÑзи Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ð¸ файла. Ждите... +message.negotiate.stream = УÑтановка канала ÑвÑзи. Ждите... +message.negotiation.file.transfer = УÑтанавливаетÑÑ ÑвÑзь Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ð¸ файла {0}. Ждите... +message.new.message = Ðовое Ñообщение от {0}. +message.new.spark.available = {0} доÑтупен. УÑтановить? +message.nickname.error = Ðик должен быть уÑтановлен +message.nickname.in.use = Ðик уже занÑÑ‚. Выберете другой +message.nickname.not.acceptable = Смена ника запрещена! +message.no.avatar.found = Ðватар не уÑтановлен. +message.no.caller.id = Caller ID не доÑтупен. +message.no.description.available = Ðет опиÑÐ°Ð½Ð¸Ñ +message.no.history.found = Ðет иÑтории Ñообщений Ð´Ð»Ñ Ñтого пользователÑ. +message.no.results.found = ПоиÑк ничего не нашел. +message.no.room.to.join.error = Ðет комнаты Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð° +message.no.subject.available = Ðет темы +message.no.updates = Ðет доÑтупных обновлений. +message.normal = ПроÑтое Ñообщение +message.number.to.call = Укажите номер Ð´Ð»Ñ Ð½Ð°Ð±Ð¾Ñ€Ð° +message.offline = Пользователь получит ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ ÐºÐ¾Ð³Ð´Ð° подключитÑÑ. +message.offline.error = Этот пользователь не может получать ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ ÐµÑли он не в Ñети. +message.participants.in.room = УчаÑтников в комнате +message.password.error = Введите пароль. +message.password.private.room.error = Укажите пароль к личной комнате +message.passwords.no.match = Пароли не Ñовпадают +message.please.join.in.conference = ПожалуйÑта, приÑоединитеÑÑŒ к конференции. +message.plugins.not.available = Ðевозможно подключитьÑÑ Ðº репозиторию плагина. +message.prompt.plugin.uninstall = ДейÑтвительно отменить уÑтановку {0}? +message.received.file = Ð’Ñ‹ получили файл от {0}. +message.receiving.file = Ð’Ñ‹ получаете файл от {0} +message.reconnect.attempting = Попытка переподключениÑ... +message.reconnect.failed = Ðе удалоÑÑŒ переподключитьÑÑ +message.reconnect.wait = Переподключение через {0} Ñек. +message.register.transports = РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð´Ð¾Ñтупных транÑпортов. +message.registering = РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ {0}. Ждите... +message.registration.transport.failed = РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð½Ðµ возможна. +message.restart.spark = Ðеобходимо закрыть Spark Ð´Ð»Ñ ÑƒÑтановки новой верÑии.\n Закрыть ÑейчаÑ? +message.restart.spark.changes = Плагин будет удалён поÑле перезапуÑка Spark. +message.restart.spark.to.install = Ðеобходимо закрыть Spark Ð´Ð»Ñ ÑƒÑтановки поÑледней верÑии. Закрыть ÑейчаÑ? +message.restart.required = Вам нужно будет перезапуÑтить Spark, чтобы Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð²Ñтупили в Ñилу. Перезагрузите ÑейчаÑ? +message.room.creation.error = Комната не может быть Ñоздана. +message.room.destroyed = Эта комната была уничтожена по причине: {0} +message.room.destruction.reason = Причина ÑƒÐ½Ð¸Ñ‡Ñ‚Ð¾Ð¶ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹? +message.room.information.for = Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð´Ð»Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹ {0} +message.save.profile = Чтобы Ñохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ, нажмите Сохранить. +message.search.for.contacts = Ðайти контакты. +message.search.input.short = Укажите Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ две буквы. +message.search.for.other.people = ПоиÑк людей на Ñервере +message.search.service.not.available = Ðет ÑвÑзи Ñ ÑервиÑом поиÑка контактов +message.searching.please.wait = ПоиÑк. Ждите... +message.select.add.room.to.add = Выберете комнату Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð² Ваш ÑпиÑок ÑервиÑов +message.select.one.or.more = Выберете одного или неÑкольких пользователей. +message.select.room.to.enter = Выберете комнату Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð°. +message.select.room.to.join = Выберете комнату Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð°. +message.send.a.broadcast = ПоÑлать раÑÑылку +message.send.file.to.user = ПоÑлать файл Ñтому пользователю. +message.send.picture = Скопировать и поÑлать изображение Ñ Ñкрана. +message.send.to.these.people = Отправить Ñледующим пользователÑм +message.sending.file.to = ПередаётÑÑ Ñ„Ð°Ð¹Ð» Ð´Ð»Ñ {0}. +message.sent.offline.files = Вам только что отправили автономный файл (Ñ‹). +message.server.unavailable = Ðе удаетÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒÑÑ Ðº Ñерверу: неверное Ð¸Ð¼Ñ Ð¸Ð»Ð¸ Ñервер не доÑтупен +message.service.already.exists = Ð¡ÐµÑ€Ð²Ð¸Ñ ÑƒÐ¶Ðµ добавлен. +message.shared.group = Shared Group +message.specify.contact.jid = Введите JID контакта (например ddman@jabber.org) +message.specify.group = Укажите группу Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð°. +message.specify.information.for.conference = Укажите информацию Ð´Ð»Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹. +message.specify.name.error = Введите корректное название. +message.specify.users.to.join.conference = Укажите пользователей подключаемых к конференции. +message.specify.valid.time.error = Укажите корректный таймаут и порт. +message.subject.change.error = Ð’Ñ‹ не можете изменÑть тему в Ñтой комнате. +message.subject.has.been.changed.to = Тема изменена на {0}. +message.supply.resource = Введите корректный реÑурÑ. +message.supply.valid.port = Введите корректный порт. +message.supply.valid.timeout = Введите корректное Ð²Ñ€ÐµÐ¼Ñ Ñ‚Ð°Ð¹Ð¼Ð°ÑƒÑ‚Ð°. +message.timeout.error = Таймаут должен быть не менее 5 Ñек. +message.total.downloaded = Ð’Ñего Ñкачено +message.transfer.cancelled = Приём файла отменён. +message.transfer.complete = Передача файла завершена ({0}) +message.transfer.progressbar.text.received = {0} получил @ {1} {2} +message.transfer.progressbar.text.sent = {0} поÑлал @ {1} {2} +message.transfer.rate = СкороÑть +message.transfer.refused = Приём файла отклонён. +message.transfer.waiting.on.user = Ожидание {0} Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸Ñ‘Ð¼Ð° файла. +message.unable.to.load.profile = Ðе найден профиль Ð´Ð»Ñ {0} +message.unable.to.retrieve.last.activity = Ðе определить Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ñледней активноÑти Ð´Ð»Ñ {0}. +message.unable.to.save.password = Ðевозможно изменить пароль. ОбратитеÑÑŒ к админиÑтратору Ñервера. +message.unable.to.send.file = Ð’Ñ‹ не можете поÑлать файл {0}. +message.unable.to.use.hostname.as.resource = Ðевозможно иÑпользовать Ð¸Ð¼Ñ Ñ…Ð¾Ñта в качеÑтве реÑурÑа +message.unrecoverable.error = Ðеправильное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ пароль +message.update.room.list = Обновить ÑпиÑок комнат +message.updating.cancelled = Обновление отменено. +message.user.banned = {0} был запрещен в Ñтой комнате. +message.user.given.voice = {0} получил право голоÑа в комнате. +message.user.granted.admin = {0} получил права админиÑтратора комнаты. +message.user.granted.membership = {0} получил дополнительные права. +message.user.granted.moderator = {0} получил права модератора. +message.user.granted.owner = {0} получил права ÑÐ¾Ð·Ð´Ð°Ñ‚ÐµÐ»Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹. +message.user.is.sending.you.a.file = {0} поÑылает Вам файл. +message.user.joined.room = {0} вошел в комнату. +message.user.kicked.from.room = {0} был выгнан из комнаты. +message.user.left.room = {0} вышел из комнаты. +message.user.nickname.changed = {0} Ñменил ник на {1}. +message.user.now.available.to.chat = {0} в Ñети Ñ {1} +message.user.revoked.admin = Отменены права админиÑтратора комнаты Ð´Ð»Ñ {0}. +message.user.revoked.membership = Отменены дополнительные права Ð´Ð»Ñ {0}. +message.user.revoked.moderator = Отменены права модератора Ð´Ð»Ñ {0}. +message.user.revoked.owner = Отменены права ÑÐ¾Ð·Ð´Ð°Ñ‚ÐµÐ»Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹ Ð´Ð»Ñ {0}. +message.user.voice.revoked = Отменено право голоÑа Ð´Ð»Ñ {0}. +message.username.error = Введите Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ. +message.username.password.error = Ð˜Ð¼Ñ Ð¸/или пароль не введены. +message.vcard.not.supported = Сервер не поддерживает VCards. Ðевозможно Ñохранить Ваш VCard. +message.version = ВерÑиÑ: {0} +message.view.information.about.this.user = Показать информацию о пользователе. +message.waiting.for.user.to.join = Ð’ ожидании {0} подключении +message.went.offline = {0} отключен Ñ {1} +message.you.have.been.banned = Ð’Ð°Ñ Ð·Ð°Ð¿Ñ€ÐµÑ‚Ð¸Ð»Ð¸ в Ñтой комнате. +message.you.have.been.kicked = Ð’Ð°Ñ ÐºÐ¸ÐºÐ½ÑƒÐ»Ð¸ из комнаты. +message.you.have.sent = Ð’Ñ‹ поÑлали файл Ð´Ð»Ñ {0}. +message.your.admin.granted = Вам дали права админиÑтратора комнаты. +message.your.banned = Вам запретили входить в Ñту комнату. +message.your.kicked = Ð’Ð°Ñ Ð²Ñ‹Ð³Ð½Ð°Ð» {0}. +message.your.membership.granted = Вам дали дополнительные права. +message.your.membership.revoked = Ваше членÑтво было отозвано +message.your.moderator.granted = Вам дали права модератора. +message.your.moderator.revoked = У Ð²Ð°Ñ Ð¾Ñ‚Ð½Ñли права модератора. +message.your.ownership.granted = Вам дали права ÑÐ¾Ð·Ð´Ð°Ñ‚ÐµÐ»Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹. +message.your.ownership.revoked = У Ð’Ð°Ñ Ð¾Ñ‚Ð½Ñли права ÑÐ¾Ð·Ð´Ð°Ñ‚ÐµÐ»Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹. +message.your.revoked.granted = У Ð’Ð°Ñ Ð¾Ñ‚Ð½Ñли права админиÑтратора комнаты. +message.your.voice.granted = Вам дали право голоÑа. +message.your.voice.revoked = У Ð’Ð°Ñ Ð¾Ñ‚Ð½Ñли право голоÑа. +message.groupchat.require.password = Эта конференц-комната требует пароль Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð° +message.groupchat.registered.member = УÑпешно зарегиÑтрирован Ñ {0} +message.search.for.history = ИÑкать в иÑтории разговоров +message.search.period.day.one = один день на Ñтраницу +message.search.period.week.one = одна Ð½ÐµÐ´ÐµÐ»Ñ Ð½Ð° Ñтраницу +message.search.period.month.one = один меÑÑц на Ñтраницу +message.search.period.year.one = один год на Ñтраницу +message.search.period.none = показать вÑе на одной Ñтранице +message.search.page.timeperiod = укажите период времени, за который будут показаны ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ +message.search.page.counter = текущий Ð¸Ð½Ð´ÐµÐºÑ Ð½Ð° Ñтранице и количеÑтво вÑех Ñтраниц +message.search.page.right = Перейти на Ñтраницу вперед +message.search.page.left = Перейти на Ñтраницу назад + +status.away = Отошел +status.custom.messages = Произвольное Ñообщение +status.do.not.disturb = Ðе беÑпокоить +status.extended.away = ÐедоÑтупен +status.free.to.chat = Готов поболтать +status.on.phone = Говорю по телефону +status.online = Ð’ Ñети +status.pending = Ð’ ожидании +status.invisible = Ðевидимый +status.offline = Ðе в Ñети + +tab.available.plugins = ДоÑтупные плагины +tab.avatar = Иконка +tab.business = Работа +tab.conferences = Конференции +tab.contacts = Контакты +tab.deactivated.plugins = Отключенные плагины +tab.general = ОÑновное +tab.security = БезопаÑноÑть +tab.home = Дом +tab.installed.plugins = УÑтановленные плагины +tab.personal = Личное +tab.proxy = ПрокÑи +tab.sso = SSO +tab.pki = PKI +tab.certificates = Сертификаты +tab.mutual.auth = Ð’Ð·Ð°Ð¸Ð¼Ð½Ð°Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ +title.about = О программе +title.advanced.connection.preferences = Дополнительные наÑтройки ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ +title.account.create.registration = РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ ÑƒÑ‡ÐµÑ‚Ð½Ð¾Ð¹ запиÑи +title.account.created = Ð£Ñ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ Ñоздана +title.add.contact = Добавит контакт +title.add.contact.group = Добавить группу +title.add.new.group = Добавить группу +title.add.search.service = Добавить ÑÐµÑ€Ð²Ð¸Ñ Ð¿Ð¾Ð¸Ñка +title.add.to.roster = Добавить в контакт лиÑÑ‚ +title.address = ÐÐ´Ñ€ÐµÑ +title.advanced.connection.sso = ИÑпользование единого входа (SSO) +title.advanced.connection.usesso = ИÑпользование единого входа (SSO) Ñ GSSAPI +title.advanced.connection.sso.account = Это будет иÑпользовать наÑтольную учетную запиÑÑŒ Ð´Ð»Ñ "{0}" Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð° на Ñервер. +title.advanced.connection.sso.unable = Ðевозможно подключитьÑÑ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ÑиÑтемы единого входа. ПожалуйÑта, проверьте наÑтройки вашего аккаунта и Ñервера. +title.advanced.connection.sso.noprincipal = Spark не может найти принципала, который можно иÑпользовать Ð´Ð»Ñ ÐµÐ´Ð¸Ð½Ð¾Ð³Ð¾ входа. Это предотвратит работу SSO. +title.advanced.connection.sso.smack3compat = Режим ÑовмеÑтимоÑти Smack 3 +title.alert = Внимание +title.appearance = Внешний вид +title.appearance.preferences = ÐаÑтройка внешнего вида +title.available.transports = ДоÑтупные транÑпорты +title.bookmarks = Закладки +title.broadcast.message = РаÑÑылка +title.broadcast.history = ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ñ€Ð°ÑÑылок +title.browse.conference.services = СпиÑок ÑервиÑов конференций +title.browse.room.service = СпиÑок конференций - {0} +title.cancelled = Отменено +title.change.nickname = Сменить ник +title.change.subject = Сменить тему +title.chat = ОÑновные +title.choose.directory = Выберите каталог +title.choose.incoming.sound = Выберете звук входÑщего звонка +title.choose.offline.sound = Выберете звук «Отключен» +title.choose.outgoing.sound = Выберете звук иÑходÑщего звонка +title.client.logs = КлиентÑкий журнал +title.conference.invitation = Приглашение в конференцию +title.conference.rooms = Комнаты конференций +title.configure.chat.room = ÐаÑтройки комнаты +title.configure.room = ÐаÑтроить комнату +title.confirmation = Подтверждение +title.create.new.account = Создать новую учетную запиÑÑŒ +title.create.or.bookmark.room = Войти или добавить в закладки +title.create.room = Создать +title.create.problem = Проблемы Ñ Ñозданием учетной запиÑи +title.delete.file = Ð’Ñ‹ дейÑтвительно хотите удалить Ñтот файл? +title.dial.phone = Позвонить +title.disable.transport = Удалить учетные данные +title.download.complete = Загрузка завершена +title.downloading.im.client = Скачать IM клиент +title.downloads = Закачки +title.edit.custom.message = Редактировать ÑтатуÑÑ‹ +title.edit.profile = Редактировать профиль +title.enter.reason = Введите причину +title.error = Ошибка +title.error.couldnot.open.file = Ðе удалоÑÑŒ открыть файл +title.error.delete.file = Ðе удалоÑÑŒ удалить файл +title.error.find.app = Ðе удалоÑÑŒ найти ÑоответÑтвующее приложение +title.error.rename.file = Ðе удалоÑÑŒ переименовать файл +title.file = Файл +title.filesize = Размер +title.file.exists = Файл ÑущеÑтвует +title.file.transfer = Передача файлов +title.file.transfer.preferences = ÐаÑтройки передачи файлов +title.find.conference.service = ПоиÑк ÑервиÑов конференций +title.find.contacts = Ðайти контакт +title.gadugadu.registration = Учетные данные GaduGadu +title.general.media = ÐаÑтройки медиа +title.general.chat.settings = ÐаÑтройки Группового Чата +title.group.chat = Групповой чат +title.group.chat.settings = ÐаÑтройки Группового Чата +title.history.for = ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ð´Ð»Ñ {0} +title.irc.registration = IRC данные +title.sametime.registration = Учетные данные Sametime +title.facebook.registration = Учетные данные Facebook +title.myspace.registration = Учетные данные MySpace +title.incoming.call = ВходÑщий звонок +title.input.fileexplorer = ПожалуйÑта, введите Ð¸Ð¼Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ Ð¾Ð±Ð¾Ð·Ñ€ÐµÐ²Ð°Ñ‚ÐµÐ»Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð²: +title.input.newname = ПожалуйÑта, введите новое имÑ: +title.input.openwith = ПожалуйÑта, введите Ð¸Ð¼Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ, которое вы хотите иÑпользовать: +title.invite.to.conference = ПриглаÑить в конференцию +title.jabber.browser = СпиÑок +title.join.conference.room = Войти в конференцию +title.last.activity = ПоÑледнÑÑ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾Ñть +title.login = Подключение +title.login.error = Ошибка входа +title.login.settings = ÐаÑтройки учетной запиÑи +title.login.no.account = Ðевозможно определить +title.lookup.profile = ПроÑмотр Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ +title.name = Ð˜Ð¼Ñ +title.new.client.available = ДоÑтупен новый клиент +title.new.roster.group = ÐÐ¾Ð²Ð°Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð° +title.new.version.available = ДоÑтупна Ð½Ð¾Ð²Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ +title.no.updates = Обновлений не найдено +title.notes = Заметки +title.notification = Уведомление +title.notifications = Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ +title.occupants = УчаÑтники +title.on.the.phone = Ðа телефоне +title.password = Пароль +title.password.required = ТребуетÑÑ Ð¿Ð°Ñ€Ð¾Ð»ÑŒ +title.passwords.no.match = Введите пароли заново. +title.person.search = ПоиÑк людей +title.plugins = Плагины +title.preferences = ÐаÑтройки +title.profile.information = Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ профиле +title.profile.not.found = Профиль не найден +title.qq.registration = Учетные данные QQ +title.register.account = ЗарегиÑтрировать новую учетную запиÑÑŒ +title.registration.error = Ошибка региÑтрации +title.reminder = Ðапоминание +title.rename.roster.group = Переименовать группу +title.room.destroyed = Комната уничтожена +title.room.information = Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ комнате +title.roster = Контакт лиÑÑ‚ +title.select.file.to.send = Выберите файл(Ñ‹) +title.set.status.message = УÑтановить ÑÑ‚Ð°Ñ‚ÑƒÑ +title.simple.registration = Учетные данные SIMPLE +title.sound.preferences = ÐаÑтройки звука +title.sounds = Звуки +title.spark.preferences = ÐаÑтройки Spark +title.start.chat = Ðачать чат +title.status.message = Ð¡Ñ‚Ð°Ñ‚ÑƒÑ +title.task.notification = Уведомление о задаче +title.tasks = СпиÑок задач +title.transports = ТранÑпорты +title.tray.information = Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð² трее +title.upgrading.client = Обновить IM клиент +title.version.and.time = ВерÑÐ¸Ñ Ð¸ Ð²Ñ€ÐµÐ¼Ñ +title.view.bookmarks = Показать закладки +title.view.profile.for = Профиль {0} +title.view.room.information = Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ конференции +title.waiting.to.call = Ожидание звонка +title.warning = Предупреждение +title.xmpp.registration = XMPP данные +title.appearance.showVCards = Показывать VCards в ÑпиÑке контактов +title.subscription.request = Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸ +title.certificate = Сертификат + +time.days = д +time.hours = ч +time.minutes = мин +time.since = Ñ +time.less.than.one.minute = меньше 1 минуты + +tooltip.place.a.call = Позвонить +tooltip.appearance = Измените внешний вид ваших разговоров +tooltip.file.transfer = ÐаÑтройки передачи файлов +tooltip.notifications = ÐаÑтройки уведомлений Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñщих чатов. +tooltip.place.voice.call = Звонок. +tooltip.send.email = ПоÑлать e-mail +tooltip.start.chat = Ðачать разговор +tooltip.view.changelog = Показать иÑторию изменений +tooltip.view.history = Показать иÑторию +tooltip.view.readme = Показать ReadMe +tooltip.encryptionmode.required = Ð”Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ÑÑ ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ðµ. ЕÑли Ñервер не предлагает шифрование или еÑли ÑоглаÑование ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð½Ðµ удаетÑÑ, Ñоединение Ñ Ñервером будет неудачным +tooltip.encryptionmode.ifpossible = Шифрование иÑпользуетÑÑ Ð²ÑÑкий раз, когда оно доÑтупно. +tooltip.encryptionmode.disabled = Шифрование отключено, будут иÑпользоватьÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ незашифрованные ÑоединениÑ. ЕÑли Ñервером требуетÑÑ ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ðµ, Ñоединение не будет уÑтановлено. + +tree.conference.services = СервиÑÑ‹ конференций +tree.users.in.room = Пользователей в комнате + +lookandfeel.select = Выберите Look & Feel +lookandfeel.change.now = Изменить ÑÐµÐ¹Ñ‡Ð°Ñ +lookandfeel.tooltip.restart.no = ПерезапуÑк не требуетÑÑ +lookandfeel.tooltip.restart.yes = Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¡Ð¸Ñтемного Look&Feel нажмите Сохранить и перезапуÑтите Spark. +lookandfeel.color.label = Цвета +lookandfeel.color.red = КраÑный +lookandfeel.color.green = Зелёный +lookandfeel.color.blue = Синий +lookandfeel.color.opacity = ПрозрачноÑть +lookandfeel.color.saved = Цвет Ñохранён + + +##Settings for the privacy plugin +privacy.title.preferences = ÐаÑтройки приватноÑти Spark +privacy.title.panel = ИÑпользуйте правую кнопку мыши +privacy.label.iq.desc = ЗапроÑÑ‹ +privacy.label.pin.desc = Видеть его ÑÑ‚Ð°Ñ‚ÑƒÑ +privacy.label.pout.desc = Видеть ваш ÑÑ‚Ð°Ñ‚ÑƒÑ +privacy.label.msg.desc = ОтправлÑть ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ +privacy.border.information = Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ +privacy.label.information = ИÑпользуйте правую кнопку мыши Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ/ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñей +privacy.root.node = Приватные ÑпиÑки +privacy.label.preferences = ПриватноÑть +privacy.tooltip.preferences = ÐаÑтройки приватноÑти Spark +privacy.label.list.is.active = Ðктивный: +privacy.label.list.is.default = По умолчанию: +privacy.border.block = Заблокировать +privacy.pick.one.or.more = Выбирите одну или неÑколько запиÑей Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð² ÑпиÑок +privacy.title.add.picker = Добавить запиÑи в ÑпиÑок +privacy.node.contacts = Контакты +privacy.node.groups = Группы +privacy.menu.add.contacts = Добавить контакты в ÑпиÑок +privacy.menu.add.groups = Добавить группу в ÑпиÑок +privacy.menu.add.rem.items = Удалить {0} запиÑей из ÑпиÑка +privacy.menu.remove = Удалить +privacy.menu.activate.list = Ðктивировать +privacy.menu.default.list = УÑтановить "по умолчанию" +privacy.menu.add.list = Добавить ÑпиÑок +privacy.menu.remove.list = Удалить ÑпиÑок +privacy.dialog.add.list = Введите название ÑпиÑка +privacy.dialog.rem.list = Ð’Ñ‹ дейÑтвительно хотите удалить {0}? +privacy.status.menu.entry = Приватные ÑпиÑки +privacy.name.for.default.list = По умолчанию +privacy.button.no.list.selected = Ðет выбранного ÑпиÑка +privacy.menuitem.deactivate.current.list = Отключить {0} +privacy.label.not.supported = СпиÑки конфиденциальноÑти не поддерживаютÑÑ Ñервером. + +##Stunfallback in media settings +stun.border.label = ЗапаÑной STUN Ñервер +stun.server.addr = STUN Ñервер: +stun.server.port = STUN порт: + +##Text Field Hints +hint.login.username = Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ +hint.login.password = Пароль +hint.login.domain = ÐÐ´Ñ€ÐµÑ Ñервера + +composing = {0} пишет... +paused = {0} прекратил пиÑать +active = {0} обращает внимание +inactive = {0} делает что-то ещё +gone = {0} делает что-то ещё + +#!# +action.viewlog=Показать лог + +dialog.confirm.to.reveal.visibility.title=Ð’Ñ‹ уверены? +dialog.confirm.to.reveal.visibility.msg=ЕÑли вы ÑобираетеÑÑŒ продолжить невидимоÑть будет обнаружена +dialog.confirm.close.all.conferences.if.invisible.msg = ЕÑли вы хотите продолжить вÑе конференц-комнаты будет закрыты +dialog.certificate.show = Это Ñертификат и закрытый ключ, которые вы пытаетеÑÑŒ добавить в TrustStore.

      ПоÑле Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñтого Ñертификата Spark Ñможет уÑтановить защищенную
      ÑвÑзь Ñ Ñерверами, которые определены Ñтим Ñертификатом.

      ЕÑли вы уверены, что хотите добавить Ñтот Ñертификат, нажмите кнопку ОК. +dialog.id.certificate.show = Это Ñертификат, который вы пытаетеÑÑŒ добавить в IdentityStore.

      ПоÑле Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñтого Ñертификата Spark Ñможет предоÑтавить Ñтот Ñертификат удаленному Ñерверу во Ð²Ñ€ÐµÐ¼Ñ ÑƒÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ ÑоединениÑ, чтобы аутентифицировать ÑÐµÐ±Ñ Ð¸ зашифровать Ñто Ñоединение.

      ЕÑли вы уверены, что хотите добавить Ñтот Ñертификат, нажмите кнопку ОК. +dialog.certificate.add.from.connection = Это Ñертификат, предоÑтавленный Ñервером, к которому вы пытаетеÑÑŒ подключитьÑÑ.
      Этого Ñертификата нет в вашем TrustStore, что означает, что ему не доверÑÑŽÑ‚.
      и вы не можете подключитьÑÑ Ðº Ñтому Ñерверу.

      Ð’Ñ‹ хотите доверÑть ему и добавить Ñтот Ñертификат в Ñвой TrustStore? +dialog.certificate.unrecognized.server.certificate = Сервер, к которому вы подключаетеÑÑŒ, идентифицирует ÑÐµÐ±Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Ñертификата, который
      не раÑпознаетÑÑ Spark. ПожалуйÑта, ознакомьтеÑÑŒ Ñ Ð´ÐµÑ‚Ð°Ð»Ñми ниже. +dialog.certificate.ask.allow.self-signed = Сервер, к которому вы подключаетеÑÑŒ, идентифицирует ÑÐµÐ±Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ÑамозаверÑющего Ñертификата.
      Ð¢ÐµÐºÑƒÑ‰Ð°Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Spark запрещает иÑпользование ÑамозаверÑющих Ñертификатов. Ðе могли бы вы
      изменить Ñту конфигурацию и попробовать еще раз? +dialog.certificate.subject.label = Тема: + +dialog.certificate.add.unrecognized.server.certificate = Ð’Ñ‹ хотите добавить Ñтот Ñертификат в набор Ñертификатов, которому доверÑет Spark? +dialog.certificate.chain.add.from.connection = Это цепочка Ñертификатов, предоÑтавлÑÐµÐ¼Ð°Ñ Ñервером, к которому вы подключаетеÑÑŒ.
      Его нет в вашем ÑпиÑке доверенных, поÑтому вы не можете подключитьÑÑ.

      Ð’Ñ‹ хотите добавить Ñти Ñертификаты в ÑпиÑок доверенных? +dialog.certificate.cannot.have.copy = Этот Ñертификат уже хранитÑÑ Ð² TrustStore. +dialog.certificate.has.been.added = Сертификат добавлен в TrustStore. +dialog.certificate.has.been.added.to.identity.store = Сертификат добавлен в IdentityStore. +dialog.certificate.is.distrusted = Сертификат недейÑтвителен, поÑтому доверÑть ему не Ñтоит, Ñто опаÑно. \n ЕÑли вы вÑе еще хотите доверÑть ему, уÑтановите переключатель «ДоверÑть» или добавьте его в ÑпиÑок иÑключений. +dialog.certificate.sure.to.delete = Ð’Ñ‹ уверены, что хотите удалить Ñтот Ñертификат? \nЕÑли вы Ñто Ñделаете, вы не Ñможете уÑтановить защищенное Ñоединение. \n Ñ Ñерверами, идентифицированным Ñтим Ñертификатом. +dialog.certificate.has.been.deleted = Сертификат уÑпешно удален. +dialog.self.signed.certificate.has.been.created = СамоподпиÑанный Ñертификат и закрытый ключ были Ñозданы в каталоге: \n +dialog.certificate.request.has.been.created = Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° подпиÑÑŒ Ñертификата и закрытый ключ были Ñозданы в каталоге: \n +dialog.cannot.upload.certificate.might.be.ill.formatted = Ðе удаетÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¸Ñ‚ÑŒ файл Ñертификата, Ñертификат может быть неправильно отформатирован +dialog.cannot.upload.certificate = Ðе удаетÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¸Ñ‚ÑŒ файл Ñертификата +dialog.certificate.title.certificate.not.in.truststore = ПредоÑтавленный Ñертификат отÑутÑтвует в вашем TrustStore + +cert.valid = ДейÑтвительный +cert.revoked = Ðннулирован +cert.expired = ИÑтекший +cert.not.valid.yet = Еще не дейÑтвует +cert.self.signed = СамоподпиÑанный +cert.sign.request = Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° подпиÑÑŒ Ñертификата +cert.self.signed.save.to.file = Сохранить Ñертификат в файл +cert.unknown.oid = ÐеизвеÑтное опиÑание OID. +cert.is.critical = ЯвлÑетÑÑ ÐºÑ€Ð¸Ñ‚Ð¸Ñ‡ÐµÑким: +cert.critical = Критично: +cert.not.critical = Ðе критично: +cert.common.name = РаÑпроÑтраненное Ð¸Ð¼Ñ +cert.organization.unit = ÐžÑ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ ÐµÐ´Ð¸Ð½Ð¸Ñ†Ð° +cert.organization = ÐžÑ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ +cert.country = Страна +cert.city = Город + +cert.extensions = РаÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ñертификата: +cert.extensions.unsupported = Ðеподдерживаемые раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ +cert.extension.extended.usage.digital.signature = Ð¦Ð¸Ñ„Ñ€Ð¾Ð²Ð°Ñ Ð¿Ð¾Ð´Ð¿Ð¸ÑÑŒ +cert.extension.extended.usage.non.repudiation = БезотказноÑть +cert.extension.extended.usage.key.encipherment = Шифрование ключа +cert.extension.extended.usage.data.encipherment = Шифрование данных +cert.extension.extended.usage.key.agreement = Ключевое Ñоглашение +cert.extension.extended.usage.key.cert.sign = ПодпиÑÑŒ Ñертификата ключа +cert.extension.extended.usage.crl.sign = ПодпиÑÑŒ CRL +cert.extension.extended.usage.encipher.only = Только шифрование +cert.extension.extended.usage.decipher.only = Только раÑшифровать +cert.extension.basic.constraints.is.ca = Центр Ñертификации +cert.extension.basic.constraints.path.length = Длина пути проверки +cert.extension.name.constraints.permitted.subtrees = Разрешенные Ð¿Ð¾Ð´Ð´ÐµÑ€ÐµÐ²ÑŒÑ +cert.extension.name.constraints.excluded.subtrees = ИÑключенные Ð¿Ð¾Ð´Ð´ÐµÑ€ÐµÐ²ÑŒÑ + +##OID's mapping +2.5.29.1 = Идентификатор Ñтарого авторитетного ключа X.509 +2.5.29.2 = Ключевые атрибуты +2.5.29.3 = Политики Ñертификатов +2.5.29.4 = ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð½Ð° иÑпользование ключей +2.5.29.5 = Отображение политик +2.5.29.6 = ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€ÐµÐ²Ð° +2.5.29.7 = Ðльтернативное Ð¸Ð¼Ñ Ñубъекта +2.5.29.8 = Ðльтернативное Ð¸Ð¼Ñ Ñмитента +2.5.29.9 = Ðтрибуты предметного каталога +2.5.29.10 = ОÑновные Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ +2.5.29.11 = РаÑширение Ñертификата +2.5.29.12 = РаÑширение Ñертификата +2.5.29.13 = РаÑширение Ñертификата +2.5.29.14 = Идентификатор ключа Ñубъекта +2.5.29.15 = ИÑпользование ключа +2.5.29.16 = Период иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¾Ð³Ð¾ ключа +2.5.29.17 = Ðльтернативное Ð¸Ð¼Ñ Ñубъекта +2.5.29.18 = Ðльтернативное Ð¸Ð¼Ñ Ñмитента +2.5.29.19 = ОÑновные Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ +2.5.29.20 = Ðомер CRL +2.5.29.21 = Код причины +2.5.29.22 = Дата Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ñрока +2.5.29.23 = Удерживать код инÑтрукции +2.5.29.24 = Дата Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ +2.5.29.25 = Точки раÑпроÑÑ‚Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ CRL +2.5.29.26 = Пункт выдачи и раÑÐ¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ +2.5.29.27 = Индикатор CRL +2.5.29.28 = Пункт выдачи и раÑÐ¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ +2.5.29.29 = Эмитент Ñертификата +2.5.29.30 = ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð¸Ð¼ÐµÐ½Ð¸ +2.5.29.31 = Точки раÑпроÑÑ‚Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ CRL +2.5.29.32 = Политики Ñертификатов +2.5.29.33 = СопоÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ð¸Ñ‚Ð¸Ðº +2.5.29.34 = ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ð¸Ñ‚Ð¸ÐºÐ¸ +2.5.29.35 = Идентификатор ключа полномочий +2.5.29.36 = ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ð¸Ñ‚Ð¸ÐºÐ¸ +2.5.29.37 = РаÑширенное иÑпользование ключа +2.5.29.38 = Идентификатор авторитетного атрибута +2.5.29.39 = Идентификатор Ñертификата Ñпецификации роли +2.5.29.40 = Идентификатор потока CRL +2.5.29.41 = basicAttConstraints +2.5.29.42 = ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð´ÐµÐ»ÐµÐ³Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð¾Ð³Ð¾ имени +2.5.29.43 = Ð¡Ð¿ÐµÑ†Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸ +2.5.29.44 = ОблаÑть CRL +2.5.29.45 = Рефералы ÑтатуÑа +2.5.29.46 = Свежайший CRL +2.5.29.47 = ПоÑледние ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð² CRL +2.5.29.48 = ДеÑкриптор атрибута +2.5.29.49 = Уведомление Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ +2.5.29.50 = идентификатор SOA +2.5.29.51 = Базовое Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ CRL +2.5.29.52 = Приемлемые политики Ñертификатов +2.5.29.53 = Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ дельте +2.5.29.54 = ÐаÑелите любую политику +2.5.29.55 = Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ таргетинге +2.5.29.56 = Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð± отзыве отÑутÑтвует +2.5.29.57 = Приемлемые политики привилегий +2.5.29.58 = id-ce-toBeRevoked +2.5.29.59 = id-ce-RevokedGroups +2.5.29.60 = id-ce-expiredCertsOnCRL +2.5.29.61 = КоÑвенный Ñмитент +2.5.29.62 = id-ce-noAssertion +2.5.29.63 = id-ce-aAissuingDistributionPoint +2.5.29.64 = id-ce-issuedOnBehaIFOF +2.5.29.65 = id-ce-singleUse +2.5.29.66 = id-ce-groupAC +2.5.29.67 = id-ce-allowedAttAss +2.5.29.68 = id-ce-attributeMappings +2.5.29.69 = id-ce-holderNameConstraints + +2.16.840.1.113730.1.1 = +1.3.6.1.4.1.311.20.2 = szOID_ENROLL_CERTTYPE_EXTENSION +1.3.6.1.4.1.311.21.1 = MS Certificate Services CA Version +1.2.840.113533.7.65.0 = Доверить раÑширение верÑии +1.3.6.1.5.5.7.1.1 = ДоÑтуп к информации центра Ñертификации +1.3.6.1.5.5.7.3.1 = Сертификат можно иÑпользовать в качеÑтве Ñертификата Ñервера Secure Sockets Layer (SSL). +1.3.6.1.5.5.7.3.2 = Сертификат можно иÑпользовать в качеÑтве Ñертификата Ñервера Secure Sockets Layer (SSL). +1.3.6.1.5.5.7.3.3 = Сертификат можно иÑпользовать Ð´Ð»Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñи кода. +1.3.6.1.5.5.7.3.4 = Сертификат можно иÑпользовать Ð´Ð»Ñ Ð·Ð°Ñ‰Ð¸Ñ‚Ñ‹ Ñлектронной почты (подпиÑание, шифрование, ÑоглаÑование ключей). +1.3.6.1.5.5.7.3.5 = Сертификат конечной ÑиÑтемы Internet Protocol SECurity (IPSEC). +1.3.6.1.5.5.7.3.6 = Сертификат Ñ‚ÑƒÐ½Ð½ÐµÐ»Ñ Internet Protocol SECurity (IPSEC). +1.3.6.1.5.5.7.3.7 = Сертификат Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Internet Protocol SECurity (IPSEC). +1.3.6.1.5.5.7.3.8 = Отметка времени Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ ÐºÐ»ÑŽÑ‡Ð° PKIX. Сертификат можно иÑпользовать Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð²Ñзки Ñ…Ñша объекта к времени из надежного иÑточника времени. + +1.3.6.1.5.5.7.3.9 = Сертификаты ITU-T X.509, ÑоответÑтвующие Ñекретному ключу, могут иÑпользоватьÑÑ ÑƒÐ¿Ð¾Ð»Ð½Ð¾Ð¼Ð¾Ñ‡ÐµÐ½Ð½Ñ‹Ð¼ органом Ð´Ð»Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñи ответов OCSP. +1.3.6.1.5.5.7.3.10 = Ключ PKIX предназначен Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ данных и протоколов Ñервера Ñертификации. +1.3.6.1.5.5.7.3.11 = sbgpCertAAServerAuth. +1.3.6.1.5.5.7.3.12 = id-kp-scvp-responder key purpose. +1.3.6.1.5.5.7.3.13 = id-kp-eapOverPPP + +1.3.6.1.5.5.7.1.12 = id-pe-logotype +1.3.6.1.4.1.311.10.3.4 = ÐвтоматичеÑки извлекаетÑÑ Ð¸Ð· идентификаторов объектов, ÑвÑзанных Ñ ÐºÑ€Ð¸Ð¿Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸ÐµÐ¹ Microsoft. +2.23.42.7.0 = Ð¥Ñшированный корневой ключ diff --git a/core/src/main/resources/i18n/spark_i18n_sv.properties b/core/src/main/resources/i18n/spark_i18n_sv.properties new file mode 100644 index 000000000..3eed32834 --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_sv.properties @@ -0,0 +1,596 @@ +ok = Ok +cancel = Avbryt +add = Lägg till +use.default = Använd standard +close = Stäng +create = Skapa +invite = Bjud in +date = Datum +from = FrÃ¥n +room.name = Rum namn +join = GÃ¥ med +description = Beskrivning +subject = Rubrik +occupants = InvÃ¥nare +accept = Godkän +reject = AvslÃ¥ +open = Öppna +open.folder = Öppna mapp +retry = Försök igen +is.active = Aktiv +not.registered = Ej registrerad +save = Spara +yes = Ja +no = Nej +broadcast = Broadcast +available = Online +user.has.signed.in = har loggat in. +user.has.signed.off = har loggat ut. +message = Meddelande + + +button.create.account = &Skapa konto +button.close = S&täng +button.advanced = Av&ancerad +button.browse = &Bläddra... +button.browse2 = B&läddra... +button.browse3 = Bl&äddra... +button.approve = &Godkänn +button.deny = &Neka +button.accept = &Acceptera +button.profile = &Profil +button.add.a.contact = &Lägg till kontakt +button.reconnect = &Ã…teranslut +button.add = &Lägg till +button.roster = &Deltagarlista +button.add.bookmark = Lägg till bokmärke +button.remove.bookmark = Ta bort bokmärke +button.bookmark.room = &Bokmärk rummet +button.create.room = &Skapa eller anslut till ett rum +button.join.room = &Anslut valt rum +button.refresh = &Uppdatera +button.find = &Hitta +button.update = &Uppdatera +button.cancel = &Avbryt +button.decline = &Neka +button.join = &GÃ¥ med +button.save.for.future.use = &För framtida behov +button.register = &Registrera +button.dial.number = &SlÃ¥ nummer +button.clear = &Rensa +button.search = &Sök +button.add.service = &Lägg till tjänst +button.quit = &Avsluta +button.new = &Ny +button.add.user = &Lägg till användare +button.save = &Spara +button.start.chat = Chatt +button.send.email = Epost +button.send = Skicka + + + +checkbox.save.password = &Spara lösenord +checkbox.auto.login = &Automatisk login +checkbox.use.proxy.server = &Använd Proxy Server +checkbox.auto.discover.port = &Upptäck server och port automatiskt +checkbox.permanent = Rummet är &permanent +checkbox.private.room = Rummet &är privat +checkbox.show.time.in.chat.window = &Visa tid i chatt fönstret +checkbox.perform.spell.check = &Utför stavningskontroll i bakgrunden +checkbox.show.notifications.in.conference = &Visa meddelanden i konferensrummet +checkbox.disable.chat.history = &Stäng av chatt historik +checkbox.show.toaster = Visa &Popup +checkbox.window.to.front = &Flytta fönstret längst fram +checkbox.play.sound.on.new.message = Spela upp ljud vid nytt &meddelande +checkbox.play.sound.when.offline = Spela upp ljud vid när användare &loggar ut +checkbox.play.sound.on.outgoing.message = Spela upp ljud vid när meddelande &skickas +checkbox.play.sound.on.invitation = Spela upp ljud när &du fÃ¥r en inbjudan +checkbox.idle.enabled = &Viloläge aktivt +checkbox.launch.on.startup = &Autostart +checkbox.start.in.tray = &Starta i meddelandefältet +checkbox.split.chat.window = Docka &Fönstret (kräver omstart) +checkbox.tabs.on.top = &Chat tabs appear on top (kräver omstart) +checkbox.tabs.scroll = Använd scroll för chattflikar (kräver omstart) +checkbox.allow.buzz = TillÃ¥t användare ringa dig. +checkbox.enable.emoticons = TillÃ¥tt Kä&nsloikoner +checkbox.use.system.look.and.feel = Använd systemet utseende (kräver omstart) +checkbox.notify.user.goes.offline = Meddela när en användare loggar ut. +checkbox.notify.user.comes.online = Meddela när en användare loggar in. +checkbox.close.unread.message = FrÃ¥ga när du stänger fönstret om det finns olästa meddelanden + +label.user.on.public.network = Användaren är pÃ¥ ett publikt nätverk +label.change.password.to = &Byt lösenord till +label.username = &Användarnamn +label.name = &Namn +label.room.name = &Rummets Namn +label.room.topic= Rummets &rubrik +label.password = &Lösenord +label.confirm.password = &Bekräfta lösenord +label.server = Do&män +label.create.konton = Skapa &konto +label.close = S&täng +label.ok = OK +label.cancel = Avbryt +label.use.default = Använd standard +label.port = &Port +label.auto.login = &Autologin +label.old.ssl = &Använd gamla SSL port metoden +label.host = &Värd +label.resource = &Resurs +label.protocol = &Protokoll +label.kontons = &Konton +label.receieved = &Mottaget +label.transfer.timeout = &Överförings timeout(min): +label.transfer.download.directory = &Mapp för nedladdning: +label.find = &Hitta +label.rename.to = Byt namn till +label.contact.to.find = Hitta kontakt +label.available.users.in.roster = &Användare pÃ¥ deltagarlistan +label.time = Tid: {0} +label.add.conference.service = &Lägg till konferenstjänst +label.add.jid = &Lägg till JID +label.message = &Meddelande +label.room = &Rum +label.invited.users = Bjud in användare +label.new.nickname = Nytt smeknamn +label.server.address = &Server adress +label.nickname = Sm&eknamn +label.presence = &Närvaro +label.priority = P&rioritet +label.enter.address = Ange adress +label.jabber.address = &Jabber adress +label.local.time = &Lokal tid +label.software = &Programvara +label.version = &Version +label.os = &Operativ system +label.number = &Nummer +label.dial = &Ring +label.minutes.before.stale.chat = &Minuter innan ett rum blir inaktivt +label.company = &Företag +label.street.address = &Gatuadress +label.city = &Stad +label.state.and.province = Län +label.postal.code = &Postnummer +label.country = L&and +label.job.title = &Titel +label.department = &Avdelning +label.phone = &Telefon +label.fax = &Fax +label.mobile = &Mobil +label.web.page = &Hemsida +label.pager = &Personsökare +label.first.name = &Förnamn +label.middle.name = &Mellannamn +label.last.name = &Efternamn +label.email.address = &Epost adress +label.jid = &JID +label.search.service = &Sök tjänst +label.xmpp.port = &XMPP Port +label.response.timeout = &Timeout för svarstid (sekunder) +label.time.till.idle = &Tid innan inaktiv (min) +label.jabber.id = &Jabber ID +label.group = &Grupp +label.enter.group.name = Ange nytt grupp namn +label.network = Nätver&k +label.unable.to.add.contact = Kan ej lägga till kontakt. +label.conflict.error = Kan ej logga in dÃ¥ kontot redan är inloggat. +label.message.style = &Meddelande stil +label.emoticons = &Känsloikoner +label.accounts = Konton +# TODO: Sort out with duplicates +message.username.error = Ange ett användarnamn för kontot. +message.password.error = Ange ett lösenord för kontot. +message.confirmation.password.error = Bekräfta lösenordet. +message.konton.error = Ange servern som kontot ska skapas pÃ¥. +message.registering = Registrerar med {0}. Var god vänta... +message.connection.failed = Kan ej ansluta till {0}. +message.create.konton = Kontot kan inte skapas. +message.already.exists = Kontot finns redan. Försök med ett annat användarnamn. +message.konton.created = Nytt konto har skapats. +message.konton.create = Skapa ett nytt konto. +message.connecting.please.wait = Ansluter. Vänta... +message.supply.valid.timeout = Ange ett giltigt timeout värde. +message.supply.valid.port = Ange en giltig port. +message.supply.resource = Ange en giltig resurs. +message.current.status = LÃ¥t andra veta din nuvarande status. +message.disconnected.error = Din anslutning avbröts pga. ett fel. +message.disconnected.group.chat.error = Din anslutning avbröts pga. ett fel. Du mÃ¥ste Ã¥teransluta till grupprummet. +message.disconnected.conflict.error = Din anslutning avbröts pga. eftersom du loggade in pÃ¥ en annan dator. +message.locked.workstation = Användare har lÃ¥st sin dator +message.away.idle = FrÃ¥nvarande pga. inaktivtet. +message.default.error = Ett allmänt fel har uppstÃ¥t. Skicka felrapport till support@jivesoftware.com. +message.new.message = Nytt meddelande frÃ¥n {0}. +message.send.file.to.user = Skicka filer till denna användare. +message.send.picture = FÃ¥nga och skicka allt som syns pÃ¥ skärmen. +message.sent.offline.files = Du har skickat offline fil(er). +message.search.for.contacts = Sök efter kontakter. +message.end.conversation = Vill du avsluta denna session? +message.end.chat = Vill du avsluta denna chatt? +message.close.this.chat = Stänga denna chatt +message.close.other.chats = Stänga alla andra chattfönster +message.close.stale.chats = Stäng inaktiva chattfönster +message.close.unread.window = Du har olästa meddelanden, är du säker pÃ¥ att du vill stänga fönstret? +message.last.message.received = Senaste meddelande togs emot {0} +message.shared.group = Delade grupper +message.is.shared.group = {0} är en delad grupp. +message.delete.confirmation = Vill du verkligen radera {0}? +message.idle.for = Inaktiv i {0} +message.enter.broadcast.message = Ange meddelande att skicka till valda användare. +message.name.of.group = Namn pÃ¥ grupp +message.approve.subscription = TillÃ¥tt {0} att lägga till dig pÃ¥ sin användarlista? +message.add.user = Lägga till användaren pÃ¥ din lista? +message.general.error = Du har tappat kontakten med servern beroende pÃ¥ {0}. +message.add.a.contact = Lägg till en kontakt. +message.generic.reconnect.message = Du har tappat kontakten med servern. För att logga in igen, klicka pÃ¥ knappen nedan. +message.select.one.or.more = Välj en eller flera frÃ¥n din användarlista +message.add.conference.service = Lägg till en konferenstjänst. +message.service.already.exists = Tjänsten finns redan pÃ¥ din servicelista. +message.searching.please.wait = Söker. Vänligen vänta... +message.conference.service.error = Kan inte hitta konferenstjänsten. +message.create.or.join.room = Create or join a conference chat room +message.specify.name.error = Specify a valid name. +message.password.private.room.error = Specify password for the private room +message.passwords.no.match = Passwords do not match. +message.enter.valid.jid = Enter a valid Jabber ID +message.please.join.in.conference = Please join me in a conference. +message.invite.users.to.conference = Invite users to a conference room. +message.specify.users.to.join.conference = Specify users to join this conference room. +message.no.room.to.join.error = No room to join +message.participants.in.room = Participants In Room +message.you.have.been.kicked = You have been kicked out of this room. +message.kicked.error = You are not able to kick {0} out of this room. +message.you.have.been.banned = You have been banned from this room. +message.nickname.in.use = Nickname in use. Please specify another Nickname +message.update.room.list = Update Room List +message.join.conference.room = Join Conference Room +message.select.add.room.to.add = Please select a room to add to your service list. +message.bookmark.temporary.room.error = You cannot bookmark temporary rooms +message.select.room.to.join = Select room to join. +message.conference.info.error = Unable to retrieve conference information. Please try back later. +message.add.favorite.room = Add room to favorites list or join directly. +message.select.room.to.enter = Specify room to enter. +message.find.conference.services = Find conference services +message.specify.information.for.conference = Specify information for conference room. +message.no.description.available = No description available +message.no.subject.available = No subject available +message.room.information.for = Room information for {0} +message.view.information.about.this.user = View information about this user. +message.add.this.user.to.your.roster = Add this user to your buddy list. +message.came.online = {0} is online at {1} +message.went.offline = {0} went offline at {1} +message.offline.error = The user will be unable to receive offline messages. +message.offline = The user is offline and will receive the message on their next login. +message.is.typing.a.message = {0} is typing a message... +message.enter.new.subject = Enter new subject +message.confirm.destruction.of.room = Destroying the room removes all users from the room. Continue? +message.room.destruction.reason = Reason for destroying the room? +message.user.left.room = {0} has left the room. +message.user.joined.room = {0} has joined the room. +message.chat.session.ended = Chat session has ended on {0} +message.subject.change.error = You are not allowed to change the subject of this room. +message.forbidden.error = Received a forbidden error from the server. +message.room.destroyed = This room has been destroyed due to the following reason: {0} +message.subject.has.been.changed.to = The subject has been changed to {0}. +message.user.kicked.from.room = {0} has been kicked out of the room. +message.user.given.voice = {0} has been given a voice in this room. +message.user.voice.revoked = Voice has been revoked for {0}. +message.user.banned = {0} has been banned from this room. +message.user.granted.membership = {0} has been given membership priviliges. +message.user.revoked.membership = Membership has been revoked for {0}. +message.user.granted.moderator = {0} has been granted moderator privileges. +message.user.revoked.moderator = Moderator priviliges have been revoked for {0}. +message.user.granted.owner = {0} has been granted owner privileges. +message.user.revoked.owner = Owner priviliges have been revoked for {0}. +message.user.granted.admin = {0} has been granted administrator priviliges. +message.user.revoked.admin = Administrator privileges have been revoked for {0}. +message.user.nickname.changed = {0} is now known as {1}. +message.your.kicked = You have been kicked by {0}. +message.your.voice.granted = You have been given a voice in this chat. +message.your.voice.revoked = Your voice has been revoked. +message.your.banned = You have been banned from this room. +message.your.membership.granted = You have been granted membership privileges. +message.your.membership.revoked = Your membership has been revoked. +message.your.moderator.granted = You have been granted moderator privileges. +message.your.moderator.revoked = Your moderator privileges have been revoked. +message.your.ownership.granted = Your have been granted owner privileges. +message.your.ownership.revoked = Your owner privilieges have been revoked. +message.your.admin.granted = You have been granted administrator privileges. +message.your.revoked.granted = Your admin privileges have been revoked. +message.send.a.broadcast = Send a broadcast +message.broadcast.from = Broadcast from {0} +message.enter.message.to.broadcast = Enter message to broadcast to your entire roster list. +message.broadcast.message.sent = The broadcast message has been sent. +message.broadcast.to = Enter message to broadcast to {0} +message.hasbeenbroadcast.to = The message has been broadcasted to the following users:\n{0} +message.user.now.available.to.chat = {0} is online at {1} +message.user.is.sending.you.a.file = {0} is sending you a file. +message.file.transfer.canceled = You have cancelled the file transfer. +message.negotiate.file.transfer = Negotiating file transfer. Please wait... +message.negotiate.stream = Negotiating connection stream. Please wait... +message.receiving.file = You are receiving a file from {0} +message.click.to.open = Click to open +message.error.during.file.transfer = There was an error during file transfer. +message.transfer.refused = The file transfer was refused. +message.transfer.cancelled = The file transfer was cancelled. +message.received.file = You have received a file from {0}. +message.file.exists.question = The file already exists. Overwrite? +message.transfer.waiting.on.user = Waiting for {0} to accept file transfer. +message.negotiation.file.transfer = Negotiating file transfer with {0}. Please wait... +message.unable.to.send.file = You were unable to send the file to {0}. +message.sending.file.to = Sending file to {0}. +message.you.have.sent = You have sent a file to {0}. +message.file.transfer.rejected = The file transfer was not accepted by {0}. +message.disable.transport = Remove login information from {0}? +message.register.transports = Register with these available transports. +message.enter.xmpp = Ange ditt XMPP användardnamn och lösenord nedan. +message.enter.irc = Ange ditt IRC användardnamn,smeknamn och lösenord nedan. +message.enter.simple = Ange ditt SIMPLE användardnamn och lösenord nedan. +message.enter.gadugadu = Enter your GaduGadu username and password below. +message.username.error = Du mÃ¥ste ange användarnamn. +message.password.error = Du mÃ¥ste ange lösenord. +message.nickname.error = Du mÃ¥ste ange smeknamn. +message.username.password.error = Användarnamn och/eller lösenord mÃ¥ste anges. +message.registration.transport.failed = Kan inte registrera med gateway. +message.client.information = Klient information för {0} +message.calling = Ringer {0} +message.number.to.call = Ange nummer att ringa +message.no.caller.id = Inget called ID tillgängligt. +message.no.history.found = Det finns ingen historik för denna användare. +message.prompt.plugin.uninstall = Vill du verkligen avinstallera {0}? +message.restart.spark.changes = Plugin kommer att tas bort vid omstart av klienten. +message.loading.please.wait = Laddar. Vänliga vänta... +message.plugins.not.available = Inga plugins tillgängliga. +message.downloading = Laddar ner {0} +message.downloading.spark.plug = Laddar ner plugins +message.unable.to.save.password = Kan inte byta lösenord. Kontakta den systemansvarige. +message.delete.all.history = Radera all historik? +message.no.avatar.found = Ingen minatyrbild finns för denna användare. +message.image.too.large = För stor bild. Välj en bild som är 16k elle mindre. +message.save.profile = För att spara din profil, klicka pÃ¥ Spara. +message.unable.to.load.profile = Kan inte hitta profil för {0} +message.enter.jabber.id = Ange Jabber ID +message.invalid.jabber.id = Ingen giltigt Jabber ID +message.vcard.not.supported = Servern stödjer inte VCard. Kan inte spara ditt VCard. +message.search.service.not.available = Kan inte kontakta sök tjänsten. +message.no.results.found = Inget sökresultat returnerades frÃ¥n servern. +message.name.of.search.service.question = Namn pÃ¥ söktjänst? +message.search.for.other.people = Sök efter andra användare pÃ¥ servern. +message.specify.valid.time.error = Ange ett giltigt timeout värde och port. +message.timeout.error = Timeout värdet mÃ¥ste vara 5 sekunder eller större. +message.version = Version: {0} +message.file.size = Fil storlek: {0} +message.restart.spark = Du mÃ¥ste avsluta klienten för att \n installera den nya versionen. Vill du göra det nu? +message.updating.cancelled = Uppdateringen avbröts. +message.transfer.rate = Överförings hastighet +message.total.downloaded = Totalt nedladdat +message.new.spark.available = {0} är tillgänlig. Vill du installera? +message.restart.spark.to.install = Du mÃ¥ste avsluta klienten för att \n installera den nya versionen. Vill du göra det nu? +message.add.to.roster = Lägg till pÃ¥ användarlista +message.enter.room.password = Ange lösenord för grupprum +message.add.contact.to.list = Lägg till användaren pÃ¥ kontaktlista +message.authenticating = Autentiserar +message.invalid.status = Ange ett giltigt status meddelande. +message.cannot.add.contact.to.shared.group = Du kan inte lägga till kontakter pÃ¥ en delad grupp. +message.specify.contact.jid = Ange ett giltigt JID (ex. user@jabber.org) +message.invalid.jid.error = Felaktigt JID konto angivet. +message.specify.group = Ange kontaktgruppen som användaren ska tillhöra. +message.room.creation.error = Grupprummet kan inte skapas. +message.unable.to.retrieve.last.activity = Kan inte avgöra senaste aktivitet för {0}. +message.buzz.alert.notification = PÃ¥kalla användarens uppmärksamhet. +message.buzz.sent = Skicka larm till användaren. +message.restart.required = Du mÃ¥ste starta om klienten för att ändringarna ska börja gälla. Starta om nu? +message.send.to.these.people = Skicka till dessa människor +message.normal = Normalt meddelande +message.alert.notify = Larm meddelande +message.account.create = Här kan ni skapa ett nytt konto om server tillÃ¥ter det. + +title.account.create.registration = Skapa nytt konto +title.passwords.no.match = Bekräfta lösenorden. +title.create.problem = Problem med att skapa kontot +title.konton.created = Kontor skapat +title.create.new.konton = Skapa nytt konto +title.konton.create.registration = Registrera konto +title.register.konton = Registrera nytt konto +title.notification = Notifieringar +title.advanced.connection.preferences = Avancerade anslutningar +title.preferences = Förinställningar +title.error = Fel +title.status.message = Status meddelande +title.spark.preferences = Klient inställningar +title.alert = Varning +title.tray.information = Tray Information +title.select.file.to.send = Väl fil(er) att sända +title.choose.directory = Välj katalog +title.confirmation = Bekräfta +title.last.activity = Senaste aktivitet +title.add.new.group = Lägg till ny grupp +title.add.to.roster = Lätt till pÃ¥ användarlista +title.find.contacts = Sök kontakter +title.rename.roster.group = Bytt namn användarlist gruppen +title.roster = Användarlista +title.create.room = Skapa +title.conference.rooms = Konferens rum +title.invite.to.conference = Bjud in till konferens +title.room.information = Rumsinformation +title.change.nickname = Bytt smeknamn +title.group.chat = Grupp chatt +title.create.or.bookmark.room = Anslut eller bokmärk rum +title.browse.room.service = Bläddra efter konferensrum - {0} +title.name = Namn +title.address = Adress +title.occupants = Deltagare +title.browse.conference.services = Bläddra konferens tjänster +title.find.conference.service = Sök konferens tjänster +title.configure.chat.room = Konfigurera grupprum för chatt +title.conference.invitation = Bjud in till konferens +title.join.conference.room = Anslut till konferensrum +title.view.room.information = Visa grupprums information +title.configure.room = Konfigurera grupprum +title.change.subject = Ändra rubrik +title.enter.reason = Ange anledning +title.room.destroyed = Grupprum borttaget +title.edit.custom.message = Agen eget meddelande +title.set.status.message = Ange Status meddelande +title.broadcast.message = Skicka meddelande +title.start.chat = Starta chatt +title.view.bookmarks = Visa bokmärken +title.downloads = Nedladdningar +title.file.exists = Fil finns redan +title.disable.transport = Ta bort login information +title.available.transports = Tillgängliga transportgateways +title.transports = Transportgateways +title.xmpp.registration = XMPP konton uppgifter +title.irc.registration = IRC konton uppgifter +title.simple.registration = SIMPLE konton uppgifter +title.gadugadu.registration = GaduGadu konton uppgifter +title.registration.error = Registreringsfel +title.jabber.browser = Bläddrare +title.version.and.time = Version och tid +title.waiting.to.call = Väntar pÃ¥ att ringa +title.incoming.call = Inkommande samtal +title.on.the.phone = Är i telefon +title.dial.phone = Ring nummer +title.history.for = Konversationshistorik för {0} +title.reminder = PÃ¥minnelse +title.plugins = Plugins +title.general.chat.settings = Allmänna chatt inställningar +title.chat = Chatt +title.notifications = Meddelanden +title.sound.preferences = Ljudinställningar +title.sounds = Ljud +title.choose.incoming.sound = Välj fil för inkommande ljud +title.choose.outgoing.sound = Välj fil för utgÃ¥ende ljud +title.choose.offline.sound = Välj fil för offline ljud +title.edit.profile = Editera profil information +title.profile.information = Profil information +title.profile.not.found = Profil hittades ej +title.view.profile.for = Visar profil för {0} +title.lookup.profile = SlÃ¥ upp profil +title.add.search.service = Lägg till söktjänst +title.person.search = Sök efter person +title.login.settings = Login inställningar +title.login = Login +title.downloading.im.client = Ladda ner chatt Client +title.upgrading.client = Uppgradera klient +title.cancelled = Avbruten +title.new.version.available = Ny version tillgänlig +title.new.client.available = Ny klient tillgänlig +title.password = Lösenord +title.download.complete = Nedladdning komplett +title.new.roster.group = Ny användarlista +title.add.contact.group = Lägg till kontaktgrupp +title.add.contact = Lägg till kontakt +title.file.transfer.preferences = Filöverings inställningar +title.file.transfer = Fil överföring + +menuitem.connect = Fil +menuitem.contacts = Kontakter +menuitem.actions = Kommandon +menuitem.exit = Avsluta +menuitem.plugins = Plugin +menuitem.logout.no.status = Logga ut +menuitem.logout.with.status = Logga ut och ange status +menuitem.show.traffic = Visa trafikfönster +menuitem.check.for.updates = Sök efter uppdateringar +menuitem.help = Hjälp +menuitem.preferences = Inställningar +menuitem.about = Om +menuitem.online.help = Internet forum +menuitem.user.guide = Användar guide +menuitem.open = Öppna +menuitem.hide = Dölj +menuitem.status = Status +menuitem.view.downloads = Visa nedladdningar +menuitem.save = Spara +menuitem.add = Lägg till +menuitem.add.contact = Lägg till kontakt +menuitem.add.contact.group = Lägg till grupp +menuitem.remove.from.group = Ta bort frÃ¥n grupp +menuitem.start.a.chat = Starta en chatt +menuitem.rename = Byt namn +menuitem.delete = Radera +menuitem.edit = Editera +menuitem.remove.from.roster = Ta bort frÃ¥n deltagarlista +menuitem.view.profile = Visa profil +menuitem.subscribe.to = Prenumera pÃ¥ +menuitem.send.a.message = Skicka meddelande till valda användare... +menuitem.show.empty.groups = Visa tomma grupper +menuitem.send.a.file = Skicka en fil +menuitem.view.last.activity = Visa senaste aktivitet +menuitem.unban = Avblockera +menuitem.ban = Blockera +menuitem.browse.service = Bläddra bland tjänster +menuitem.remove.service = Ta bort tjänst +menuitem.join.room = Anslut till grupprum +menuitem.remove.bookmark = Ta bort bokmärke +menuitem.join.on.startup = Anslut vid uppstart +menuitem.view.room.info = Visa rums information +menuitem.remove = Ta bort +menuitem.change.nickname = Ange smeknamn +menuitem.block.user = Blockera användare +menuitem.unblock.user = Avblockera användare +menuitem.kick.user = Sparka användare +menuitem.voice = Röst +menuitem.revoke.voice = Ta bort röst +menuitem.grant.voice = TillÃ¥t röst +menuitem.ban.user = Blockera användare +menuitem.grant.moderator = Ge Moderator rättighet +menuitem.revoke.moderator = Ta bort Moderator +menuitem.invite.users = Bjud in användare +menuitem.invite.group.to.conference = Bjud in grupp till konferens +menuitem.start.a.conference = Starta en konferens... +menuitem.change.subject = Byt rubrik +menuitem.destroy.room = Ta bort grupprum +menuitem.set.status.message = Ange status meddelande... +menuitem.edit.status.message = Ange eget status meddelande... +menuitem.broadcast.to.group = Skicka meddelande till grupp +menuitem.alert.when.online = Larma när en användare är online +menuitem.remove.alert.when.online = Ta bort larm +menuitem.save.as = Spara som... +menuitem.view.client.version = Visa klient version +menuitem.view.contact.history = Visa kontakt historik +menuitem.edit.my.profile = &Editera min profil... +menuitem.lookup.profile = &Visa profil... +menuitem.add.as.contact = Lägg till som kontakt +menuitem.chat = Chatta +menuitem.sign.in = Logga in +menuitem.sign.out = Logga ut +menuitem.sign.in.at.login = Logga in vid uppstart +menuitem.enter.login.information = Ange login information +menuitem.delete.login.information = Radera login information +menuitem.show.offline.group = Gruppera offline användare +menuitem.move.to = Flytta till +menuitem.copy.to = Kopiera till +menuitem.languages = SprÃ¥k + +tree.conference.services = Konferenstjänster +tree.users.in.room = Användare i grupprum + +tab.general = Generell +tab.proxy = Proxy +tab.contacts = Kontakter +tab.installed.plugins = Installerade plugins +tab.available.plugins = Tillgängliga plugins +tab.personal = Personligt +tab.business = Företag +tab.home = Hem +tab.avatar = Minibild +tab.conferences = Konferenser + +group.connection = Anslutning +group.conferences.found = Konferenstjänst hittad +group.comma.delimited = Komma separerad +group.general.information = Generell information +group.chat.window.information = Chatt fönster information +group.notification.options = PÃ¥minnelse inställningar +group.search.form = Sök formulär +group.search.results = Sök resultat +group.login.information = Login information + +tooltip.place.a.call = Ring upp denna individ +tooltip.view.history = Visa konversations historik +tooltip.view.changelog = Visa ändrings logg +tooltip.view.readme = Visa Readme +tooltip.notifications = PÃ¥minnelse inställningar för inkommande meddelanden. +tooltip.place.voice.call = Ring upp med röst. diff --git a/core/src/main/resources/i18n/spark_i18n_tr.properties b/core/src/main/resources/i18n/spark_i18n_tr.properties new file mode 100644 index 000000000..2a85e423e --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_tr.properties @@ -0,0 +1,693 @@ +accept = Kabul +is.active = Aktif +add = Ekle +answer = Cevap +apply = Uygula +available = Kullanılabilir +broadcast = Yayın +cancel = İptal +close = Kapat +create = OluÅŸtur +date = Tarih +description = Açıklama +from = gelen +invite = Davet +join = Katıl +no = Hayır +not.registered = Kayıtlı deÄŸil +occupants = YerleÅŸikler +offline = çevrimdışı +ok = Tamam +online = çevrimiçi +open = Açık +open.folder = Dizin aç +participants = Katılımcılar +reject = Reddet +retry = Tekrar dene +room.name = Oda adı +save = Kaydet +subject = Konu +unfiled = Dosyalanmamış +use.default = Öntanımlıyı kullan +user.has.signed.in = giriÅŸ yaptı. +user.has.signed.off = çıkış yaptı. +while.offline = çevrimdışı süresince +yes = Evet + +action.clear = Temizle +action.copy = Kopyala +action.cut = Kes +action.paste = Yapıştır +action.print = Yazdır +action.save = Kaydet +action.select.all = Tümünü seç + +button.accept = &Kabul et +button.add = &Ekle +button.add.a.contact = &Bir baÄŸlantı ekle +button.add.bookmark = Yer imi ekle +button.add.service = &Servis ekle +button.add.user = &Kullanıcı ekle +button.add2 = Ekl&e +button.advanced = &GeliÅŸmiÅŸ +button.approve = &Onayla +button.bookmark.room = &Odayı imle +button.browse = &Tara... +button.browse2 = Ta&ra... +button.browse3 = T&ara... +button.cancel = &İptal +button.clear = &Temizle +button.close = Ka&pat +button.copy.to.clipboard = Panoya kopyala +button.create.account = &Hesap oluÅŸtur +button.create.room = &Oda oluÅŸtur veya katıl +button.decline = &Reddet +button.deny = &Yok say +button.dial.number = &Numarayı ara +button.find = &Bul +button.join = &Katıl +button.join.room = &Seçilen odaya katıl +button.new = &Yeni +button.profile = &Profil +button.quit = &Çık +button.reconnect = &Tekrar baÄŸlan +button.reconnect2 = Tekrar baÄŸlan +button.refresh = &Tazele +button.register = &Kaydet +button.remove.bookmark = Yer imini sil +button.roster = &Liste +button.save = &Kaydet +button.save.for.future.use = &Sonra kullanmak için kaydet +button.search = &Ara +button.send = Gönder +button.send.email = E-posta +button.start.chat = Sohbet +button.tasks.active = Aktif +button.tasks.all = Tümü +button.unset.file.explorer = Dosya tarayıcısı kurulmamış +button.update = &Güncelle +button.view.notes = Notları göster +button.view.profile = Tam profili göster +button.view.tasklist = Görev listesini göster + +checkbox.allow.buzz = Kullanıcılar size uyarı titreÅŸimi gönderebilsin. +checkbox.auto.discover.port = &Sunucu ve portu otomatik bul. +checkbox.auto.login = &Otomatik giriÅŸ +checkbox.disable.chat.history = &Sohbet geçmiÅŸini kapat +checkbox.disable.prev.chat.history = &Sohbette önceki kayıtların görüntülenmesini kapat +checkbox.enable.emoticons = &Duygu ifadelerini aç +checkbox.idle.enabled = &Idle Enabled +checkbox.launch.on.startup = &Açılışta çalıştır +checkbox.notify.user.comes.online = Kullanıcı oturum açtığında uyar +checkbox.notify.user.goes.offline = Kullanıcı oturum kapattığında uyar +checkbox.permanent =Oda &kalıcıdır +checkbox.play.sound.on.invitation = &Davet alındığında ses çal +checkbox.play.sound.on.new.message = &Yeni mesaj alındığında ses çal +checkbox.play.sound.on.outgoing.message = &Mesaj gönderildiÄŸinde ses çal +checkbox.play.sound.when.offline = Kullanıcı oturum &kapattığında ses çal +checkbox.private.room = Oda ö&zeldir +checkbox.save.password = Parolayı &kaydet +checkbox.show.avatars.in.contactlist = BaÄŸlantı listesinde &avatarları göster +checkbox.show.notifications.in.conference = &Konferans odasında uyarıları göster +checkbox.show.time.in.chat.window = &Sohbet penceresinde zamanı göster +checkbox.show.toaster = Show a &Toast Popup +checkbox.split.chat.window = &Taşınabilir pencereler (yeniden baÅŸlatılmalı) +checkbox.start.in.tray = &Sistem çekmecesinde baÅŸlat +checkbox.tabs.on.top = Sohbet sekmelerini &öne getir (yeniden baÅŸlatılmalı) +checkbox.tabs.scroll = Sohbet sekmeleri için kaydırmayı kullanın (yeniden baÅŸlatılmalı) +checkbox.use.compression = Sı&kıştırma kullan +checkbox.use.proxy.server = &Vekil sunucu kullan +checkbox.use.system.look.and.feel = Sistem arayüz görünümünü kullan (yeniden baÅŸlatılmalı) +checkbox.window.to.front = &Pencereyi öne getir +checkbox.broadcast.hide.offline.user = Çevrimdışı kullanıcıları gizle +checkbox.close.unread.message = Pencereyi kapatırken okunmamış mesaj olup olmadığını sor + +delete.log.permanently = Günlükleri kalıcı olarak sil +delete.permanently = Kalıcı olarak silinsin mi? + +gateway.username.password.error = Kullanıcı adı ve/veya parola gerekli. + +group.chat.window.information = Sohbet penceresi bilgisi +group.comma.delimited = Virgülle ayrılmış +group.conferences.found = Konferans servisleri bulundu +group.connection = BaÄŸlantı +group.empty = Bu grupta hiç çevrimiçi baÄŸlantı yok. +group.general.information = Genel bilgi +group.login.information = GiriÅŸ bilgisi +group.notification.options = Uyarı ayarları +group.offline = Çevrimdışı +group.search.form = Arama formu +group.search.results = Arama sonuçları +group.chat.name.notification = Görünen isminiz... +group.chat.name.match = Adınız grup sohbetinde geçti: + +label.accounts = &Hesaplar +label.add.conference.service = &Konferans servisi ekle +label.add.jid = &JID Ekle +label.add.task = Görev ekle +label.auto.login = &Otomatik giriÅŸ +label.available.users.in.roster = &Listemdeki kullanıcılar +label.cancel = İptal +label.change.password.to = &Yeni Parolayı girin +label.chatroom.fontsize = Sohbet odası &yazıtipi boyutu: +label.chatroom.maxcurrenthistorysize = Maksimum geçerli geçmiÅŸ boyutu: +label.city = &Åžehir +label.close = &Kapat +label.company = &KuruluÅŸ +label.confirm.password = Parolayı &onayla +label.conflict.error = GiriÅŸ yapılamadı, zaten giriÅŸ yapılmış. +label.contact.to.find = KiÅŸi bul +label.contactlist.avatarsize = KiÅŸi listesi &avatar boyutu: +label.contactlist.fontsize = Kİşi listesi &yazıtipi boyutu: +label.country = &Ülke +label.create.account = &Hesap oluÅŸtur +label.department = &Bölüm +label.dial = &Dial +label.downloads = İndirmeler +label.due = Due +label.email.address = &E-posta adresi +label.emoticons = &Duygu ifadeleri +label.enter.address = Adres girin +label.enter.group.name = Yeni grup adı girin +label.fax = &Faks +label.find = &Bul +label.first.name = &İlk isim +label.group = &Grup +label.host = &Sunucu +label.invited.users = Davetli kullanıcılar +label.jabber.address = &Jabber adresi +label.jabber.id = &Jabber ID +label.jid = &JID +label.job.title = &İş baÅŸlığı +label.last.name = &Soyad +label.local.time = &Yerel saat +label.message = &Mesaj +label.message.style = &Mesaj türü +label.middle.name = &İkinci isim +label.minutes.before.stale.chat = &Aktif olmayan oda hareketsiz sayılmadan önce beklenecek dakika +label.mobile = &Mobil +label.name = &İsim +label.network = A&ÄŸ +label.new.nickname = Yeni takma ad +label.nickname = Takma &ad +label.number = &Numara +label.ok = Tamam +label.old.ssl = &Eski SSL portu yöntemini kullan +label.os = &İşletim sistemi +label.pager = &Sayfalayıcı +label.password = &Parola +label.phone = &Telefon +label.port = &Port +label.postal.code = &Posta kodu +label.presence = &Görünüş +label.priority = &Öncelik +label.protocol = &Protokol +label.received = &Received +label.rename.to = Adını şöyle deÄŸiÅŸtir +label.resource = &Kaynak +label.response.timeout = &Cevap zaman aşımı (san) +label.room = &Oda +label.room.name = O&da adı +label.room.topic= Oda &konusu +label.search.service = &Arama servisi +label.server = Alan +label.server.address = &Sunucu adresi +label.show = Göster: +label.software = &Yazılım +label.state.and.province = Eyalet/&Bölge +label.street.address = &Sokak +label.time = Zaman: {0} +label.time.till.idle = &BoÅŸa çıkma süresi (dak) +label.timeformat = Kullan {0} +label.transfer.download.directory = &Åžu dizine indir: +label.transfer.timeout = &Aktarım zaman aşımı (dak): +label.unable.to.add.contact = KiÅŸi eklenemedi. +label.use.default = Öntanımlıyı kullan +label.user.on.public.network = Kullanıcı genel aÄŸda +label.username = &Kullanıcı adı +label.version = &Sürüm +label.web.page = &Web sayfası +label.xmpp.port = &XMPP Port + +menuitem.about = Hakkında +menuitem.actions = Eylemler +menuitem.add = Ekle +menuitem.add.as.contact = Bir baÄŸlantı ekle +menuitem.add.contact = BaÄŸlantı ekle +menuitem.add.contact.group = BaÄŸlantı grubu ekle +menuitem.add.groupchat.myname = Sohbette adım geçtiÄŸinde vurgula +menuitem.add.groupchat.mytext = Bir ÅŸeyler yazdığımda yazdıklarımı vurgula +menuitem.add.groupchat.popname= Bir sohbette adım geçtiÄŸinde uyarı penceresi göster +menuitem.alert.when.online = Kullanıcı uygun olduÄŸunda uyar +menuitem.ban = Yasak +menuitem.ban.user = Kullanıcıyı yasakla +menuitem.block.user = Kullanıcıyı engelle +menuitem.broadcast.to.group = Gruba yayın mesajı +menuitem.browse.service = Servisi tara +menuitem.change.nickname = Takma ad deÄŸiÅŸtir +menuitem.change.subject = Konu deÄŸiÅŸtir +menuitem.chat = Sohbet +menuitem.check.for.updates = Güncellemelere bak +menuitem.connect = Dosya +menuitem.contacts = BaÄŸlantılar +menuitem.copy.to = Kopyala +menuitem.delete = Sil +menuitem.delete.login.information = GiriÅŸ bilgisini sil +menuitem.destroy.room = Odayı yok et +menuitem.dial = Sesli ara +menuitem.edit = Düzenle +menuitem.edit.my.profile = &Profilimi düzenle... +menuitem.edit.status.message = Özel durum mesajını düzenle... +menuitem.enter.login.information = BaÄŸlantı bilgisini gir +menuitem.exit = Çık +menuitem.grant.moderator = BaÅŸkanlık hakları +menuitem.grant.voice = Yazma hakkı ver +menuitem.help = Yardım +menuitem.hide = Gizle +menuitem.invite.group.to.conference = Konferansa grup davet et +menuitem.invite.users = Kullanıcıları davet et +menuitem.join.on.startup = Açılışta katıl +# TODO: Sort out with duplicates +menuitem.join.room = Odaya katıl +menuitem.kick.user = Kullanıcıyı dışarı at +menuitem.languages = Diller +menuitem.logout.no.status = Oturumu kapat +menuitem.logout.with.status = Durum mesajı ile oturumu kapat +menuitem.lookup.profile = &Profile bak... +menuitem.move.to = Taşı +menuitem.online.help = Spark forumları +menuitem.open = Aç +menuitem.open.with = Birlikte aç... +menuitem.plugins = Eklentiler +menuitem.preferences = Seçenekler +menuitem.remove = Sil +menuitem.remove.alert.when.online = Alarmı sil +menuitem.remove.bookmark = Yer imini sil +menuitem.remove.from.group = Gruptan sil +menuitem.remove.from.roster = Listemden sil +menuitem.remove.service = Servisi sil +menuitem.rename = Yeniden adlandır +menuitem.revoke.moderator = BaÅŸkanlığı geri al +menuitem.revoke.voice = Yazma hakkını al +menuitem.save = Kaydet +menuitem.save.as = Farklı kaydet... +menuitem.send.a.file = Bir dosya gönder +menuitem.send.a.message = Seçili kullanıcılara mesaj yayınla... +menuitem.set.status.message = Durum mesajını deÄŸiÅŸtir... +menuitem.show.empty.groups = BoÅŸ grupları göster +menuitem.show.offline.group = Çevrimdışı grupları göster +menuitem.show.traffic = Akış penceresini göster +menuitem.sign.in = Oturum aç +menuitem.sign.in.at.login = GiriÅŸ yap +menuitem.sign.out = Oturumu kapat +menuitem.start.a.chat = Bir sohbete baÅŸla +menuitem.start.a.conference = Bir konferansa baÅŸla... +menuitem.status = Durum +menuitem.subscribe.to = Kayıt ol +menuitem.unban = Yasağı kaldır +menuitem.unblock.user = Engellemeyi kaldır +menuitem.user.guide = Kullanıcı rehberi +menuitem.view.client.version = İstemci sürümünü göster +menuitem.view.contact.history = BaÄŸlantı geçmiÅŸini göster +menuitem.view.downloads = İndirmeleri göster +menuitem.view.last.activity = Son hareketleri göster +menuitem.view.logs = Günlükleri göster +menuitem.view.profile = Profili göster +menuitem.view.room.info = Oda bilgisini göster +menuitem.voice = Ses +menuitem.show.offline.users = Çevrimdışı kullanıcıları göster +menuitem.show.contact.statusmessage = Durum mesajlarını göster +menuitem.join.room = Seçili odaya katıl +menuitem.bookmark.room = Odayı yer imlerine ekle +menuitem.refresh = Yenile +menuitem.create.room = Bir oda oluÅŸtur veya katıl + +message = Mesaj +message.account.create = Yeni bir sohbet hesabı oluÅŸtur.. +message.account.created = Yeni sohbet hesabı oluÅŸturuldu. +message.account.error = Hesap oluÅŸturmak için bir sunucu belirtin. +message.add.a.contact = Bir baÄŸlantı ekle. +message.add.conference.service = Bir konferans servisi ekle. +message.add.contact.to.list = BaÄŸlantı listenize bir kullanıcı ekleyin +message.add.favorite.room = Odayı favori listenize ekleyin veya hemen katılın. +message.add.this.user.to.your.roster = Bu kullanıcıyı arkadaÅŸ listenize ekleyin. +message.add.to.roster = Listeme ekle. +message.add.user = Kullanıcı listenize eklensin mi? +message.alert.notify = Alarm uyarısı +message.already.exists = Hesap zaten mevcut. Lütfen farklı bir kullanıcı adı seçin. +message.approve.subscription = {0}, sizi listesine ekleyecek, izin veriyor musunuz? +message.authenticating = Kimlik doÄŸrulanıyor +message.away.idle = Uzakta, ilgisiz +message.bookmark.temporary.room.error = Geçici odaları yer imlerine ekleyemezsiniz. +message.broadcast.from = {0} tarafından yayın mesajı +message.broadcast.message.sent = Yayın mesajı gönderildi. +message.broadcast.to = {0} tarafına gönderilecek mesajı girin. +message.hasbeenbroadcast.to = Mesaj ÅŸu kullanıcılara yayınlandı::\n{0} +message.buzz.alert.notification = Kullanıcıların alarm uyarılarını al. +message.buzz.sent = Kullanıcıya bir alarm uyarısı gönder. +message.calling = {0} aranıyor +message.came.online = {0}, {1} tarafında çevrimiçi +message.cannot.add.contact.to.shared.group = Paylaşılan gruba yeni baÄŸlantılar eklenemedi. +message.chat.session.ended = {0} üzerindeki sohbet sonlandı +message.click.to.open = Tıkla ve aç +message.client.information = {0} için baÄŸlantı bilgisi +message.close.other.chats = DiÄŸer tüm sohbetleri kapat +message.close.stale.chats = Hareketsiz sohbetleri kapat +message.close.this.chat = Bu sohbeti kapat +message.close.unread.window = Okunmamış mesajlarınız var, pencereyi kapatmak istediÄŸinizden emin misiniz? +message.conference.info.error = Konferans bilgisi alınamadı. Lütfen sonra tekrar deneyin. +message.conference.service.error = Konferans servisi konumlandırılamadı. +message.confirm.destruction.of.room = Oda yok ediliyor, odadaki tüm kullanıcılar silinir, devam edilsin mi? +message.confirmation.password.error = Onaylama parolası tanımlayın. +message.connecting.please.wait = BaÄŸlanıyor, lütfen bekleyin... +message.connection.failed = {0} tarafına baÄŸlanılamadı. +message.create.account = Hesap oluÅŸturulamadı. +message.create.or.join.room = Bir konferans sohbet odası oluÅŸtur veya katıl. +message.current.status = DiÄŸerlerinin sizin durumunuzu ve hareketlerinizi bilmesine izin verin. +message.default.error = Bir hata tespit edildi. Bunu lütfen support@jivesoftware.com adresine rapor edin. +message.delete.all.history = Sohbet geçmiÅŸinin tamamı silinsin mi? +message.delete.confirmation = {0}, bunu silmek istediÄŸinizden emin misiniz? +message.disable.transport = {0} tarafından alınan baÄŸlantı bilgisi silinsin mi? +message.disconnected.conflict.error = BaÅŸka bir konumdan aynı kullanıcı giriÅŸ yaptığı için baÄŸlantınız kapandı. +message.disconnected.error = BaÄŸlantınız bir hata nedeniyle kapandı. +message.disconnected.group.chat.error = BaÄŸlantınız bir hata nedeniyle kapandı. Tekrar kullanıcı giriÅŸi yaptıktan sonra odaya tekrar girmeniz gerekecek. +message.disconnected.shutdown = BaÄŸlantınız kapandı çünkü sunucu kapatıldı. +message.downloading = {0} indiriliyor +message.downloading.spark.plug = Spark-Plug indiriliyor +message.end.chat = Bu sohbeti sonlandırmak istiyor musunuz? +message.end.conversation = Bu oturumu sonlandırmak istiyor musunuz? +message.enter.broadcast.message = Seçilen kullanıcılara yayınlanacak mesajı girin. +message.enter.gadugadu = GaduGadu kullanıcı adınızı ve parolanızı aÅŸağıya girin. +message.enter.irc = IRC kullanıcı adınızı, parolanızı ve takma adınızı aÅŸağıya girin. +message.enter.jabber.id = Jabber ID girin +message.enter.message.to.broadcast = Tüm görev listenize yayınlanacak mesajı girin. +message.enter.new.subject = Yeni konuyu girin +message.enter.qq = QQ Numaranızı ve parolanızı aÅŸağıya girin. +message.enter.room.password = Oda parolasını girin +message.enter.simple = SIMPLE Sunucusu için kullanıcı adınızı ve parolanızı aÅŸağıya girin. +message.enter.valid.jid = Geçerli bir Jabber ID girin. +message.enter.xmpp = XMPP Sunucusu için kullanıcı adınızı ve parolanızı aÅŸağıya girin. +message.error.during.file.transfer = Dosya aktarımı sırasında bir hata oluÅŸtu. +message.file.exists.question = Dosya zaten mevcut, üzerine yazılsın mı? +message.file.size = Dosya boyutu: {0} +message.file.transfer.canceled = Dosyanın aktarımını iptal ettiniz. +message.file.transfer.rejected = Dosyanın aktarımı {0} tarafından kabul edilmedi. +message.file.transfer.notification = Dosya aktarım uyarısı +message.file.transfer.short.message = is sending you a file called: +message.file.transfer.chat.window = Dosya aktarım isteÄŸi: +message.find.conference.services = Konferans servislerini bul +message.forbidden.error = Sunucudan yasaklanma hatası alındı. +message.gateway.username.error = Geçerli bir kullanıcı adı gerekli. +message.gateway.password.error = Geçerli bir parola gerekli. +message.gateway.nickname.error = Geçerli bir takma ad gerekli. +message.general.error = {0} nedeniyle sunucu ile baÄŸlantıyı kaybettiniz. +message.generic.reconnect.message = Sunucu ile baÄŸlatınızı kaybettiniz. Tekrar giriÅŸ yapmak için Tekrar BaÄŸlan düğmesine tıklayın. +message.idle.for = {0} boÅŸta +message.image.too.large = Bu dosya kullanmak için çok büyük, 16kb veya daha küçük boyutlu bir dosya seçin. +message.invalid.jabber.id = Jabber ID geçersiz. +message.invalid.jid.error = JID geçersiz. +message.invalid.status = Geçerli bir durum mesajı belirtin. +message.invalid.username.password = Geçersiz kullanıcı adı veya parola. +message.invite.users.to.conference = Kullanıcıları konferans odasına davet et. +message.is.shared.group = {0} paylaşılan bir grup. +message.is.typing.a.message = {0} bir mesaj yazıyor... +message.join.conference.room = Konferans odasına katıl. +message.kicked.error = {0} sizin tarafınızdan odadan atılamaz. +message.last.message.received = {0} tarafından son mesaj gönderildi. +message.loading.please.wait = Yükleniyor, lütfen bekleyin... +message.locked.workstation = Kullanıcı bilgisayarını kilitlemiÅŸ. +message.name.of.group = Grup adı +message.name.of.search.service.question = Arama servisinin adı nedir? +message.negotiate.file.transfer = Dosya aktarımı çözümleniyor. Lütfen bekleyin... +message.negotiate.stream = Akış baÄŸlantısı çözümleniyor. Lütfen bekleyin... +message.negotiation.file.transfer = {0} ile dosya aktarımı çözümleniyor. Lütfen bekleyin... +message.new.message = {0} tarafından yeni mesaj. +message.new.spark.available = {0} kullanılabilir. Kurmak ister misiniz? +message.nickname.in.use = Takma ad kullanılıyor, baÅŸka bir takma ad seçin. +message.no.avatar.found = Kullanıcı avatar kullanmıyor. +message.no.caller.id = Arama ID kullanılamıyor. +message.no.description.available = Açıklama yok. +message.no.history.found = Bu kullanıcı için sohbet geçmiÅŸi yok. +message.no.results.found = Sunucuda hiç arama sonucu bulunamadı. +message.no.room.to.join.error = Katılacak oda yok +message.no.subject.available = No subject available +message.no.updates = Hiç güncelleme yok. +message.normal = Normal Mesaj +message.number.to.call = Arama numarası +message.offline = Kullanıcı çevrimdışı ve mesajı sonraki oturumu açtığında alacak. +message.offline.error = Kullanıcı çevrimdışı mesajları alamayacak. +message.participants.in.room = Odadaki katılımcılar +message.password.error = Bu hesabın parolasını girin. +message.password.private.room.error = Özel odanın parolasını girin. +message.passwords.no.match = Parola uyuÅŸmuyor. +message.please.join.in.conference = Lütfen beni konferansa ekle. +message.plugins.not.available = Eklenti deposuna baÄŸlanılamadı. +message.prompt.plugin.uninstall = Bunu kaldırmak istediÄŸinizden emin misiniz?: {0} +message.received.file = {0} tarafından gönderilen dosya alındı.. +message.receiving.file = {0} tarafından gönderilen dosya alınıyor. +message.reconnect.attempting = Çalışıyor... +message.reconnect.failed = Tekrar baÄŸlanılamadı. +message.reconnect.wait = {0} saniye içinde baÄŸlanıyor. +message.register.transports = Register with these available transports. +message.registering = {0} ile kayıt yapılıyor. Lütfen bekleyin... +message.registration.transport.failed = Kayıt yapılamadı. +message.restart.spark = Yeni sürümü kurmak için \n Spark'ı kapatmanız gerekecek.Bunu ÅŸimdi yapmak ister misiniz? +message.restart.spark.changes = Eklenti Spark’ın sonraki çalıştırılmasında silinmiÅŸ olacak. +message.restart.spark.to.install = Son sürümü kurmak için Spark’ı kapatmalısınız. Bunu ÅŸimdi yapmak ister misiniz? +message.restart.required = DeÄŸiÅŸikliklerin etkin olması için Spark’ı yeniden baÅŸlatmalısınız, yeniden baÅŸlatılsın mı? +message.room.creation.error = Oda oluÅŸturulamadı. +message.room.destroyed = Bu oda ÅŸu nedenden dolayı silindi: {0} +message.room.destruction.reason = Odayı silmenizin nedeni nedir? +message.room.information.for = {0} izin oda bilgisi +message.save.profile = DeÄŸiÅŸiklikleri profilinize kaydetmek için Kaydet’e tıklayın. +message.search.for.contacts = BaÄŸlantıları ara. +message.search.for.other.people = Sunucu üzerinde diÄŸer kiÅŸileri ara. +message.search.service.not.available = Arama servisine baÄŸlanılamadı. +message.searching.please.wait = Aranıyor. Lütfen bekleyin... +message.select.add.room.to.add = Servis listenize eklemek için bir oda seçin. +message.select.one.or.more = Görev listenizden bir veya birkaç kullanıcı seçin. +message.select.room.to.enter = Girmek için bir oda tanımlayın. +message.select.room.to.join = Katılmak için bir oda seçin. +message.send.a.broadcast = Bir yayın gönder +message.send.file.to.user = Dosyaları bu kullanıcıya gönder. +message.send.picture = Ekran görüntüsünü yakala ve gönder. +message.send.to.these.people = Bu kiÅŸilere gönder +message.sending.file.to = {0} kullanıcısına dosya aktarılıyor. +message.sent.offline.files = Çevrimdışı dosyaları gönderdiniz. +message.server.unavailable = Sunucuya baÄŸlanılamadı: geçersiz isim veya sunucu eriÅŸilemez durumda. +message.service.already.exists = Servis zaten servis listenizde. +message.shared.group = Paylaşılmış grup. +message.specify.contact.jid = Lütfen baÄŸlantı JID'i belirleyin. (örn: ddman@jabber.org) +message.specify.group = Yeni kullanıcılar eklemek için baÄŸlantı grubu belirleyin. +message.specify.information.for.conference = Konferans odası için bilgi girin. +message.specify.name.error = Geçerli bir isim girin. +message.specify.users.to.join.conference = Bu konferans odasına belirli kullanıcılar katılır. +message.specify.valid.time.error = Geçerli bir zaman aşımı süresi ve port girin. +message.subject.change.error = Bu odanın konusunu deÄŸiÅŸtirmek için yetkiniz yok. +message.subject.has.been.changed.to = Konu {0} olarak deÄŸiÅŸtirildi. +message.supply.resource = Geçerli bir kaynak girin. +message.supply.valid.port = Geçerli bir port girin. +message.supply.valid.timeout = Geçerli bir zaman aşımı süresi girin. +message.timeout.error = Zaman aşımı 5 saniye veya daha fazla olmalıdır. +message.total.downloaded = Toplan indirilen +message.transfer.cancelled = Dosyanın aktarımı iptal edildi. +message.transfer.rate = Aktarım hızı +message.transfer.refused = Dosyanın aktarımı reddedildi. +message.transfer.waiting.on.user = {0}, dosya aktarımını kabul etmesi için bekleniyor. +message.unable.to.load.profile = {0} için profil yüklenemedi. +message.unable.to.retrieve.last.activity = {0} için son etkinlik belirlenemedi. +message.unable.to.save.password = Parola deÄŸiÅŸtirilemedi. Lütfen sunucu yöneticisine baÅŸvurun. +message.unable.to.send.file = {0} kullanıcısına dosyayı gönderemediniz. +message.unrecoverable.error = Geçersiz kullanıcı adı veya parola. +message.update.room.list = Oda listesini güncelle +message.updating.cancelled = Güngelleme iptal edildi. +message.user.banned = {0} bu odadan yasaklandı. +message.user.given.voice = {0} kullanıcısının yazma hakkı var. +message.user.granted.admin = {0} kullanıcısına yöneticilik hakları verildi. +message.user.granted.membership = {0} kullanıcısına üyelik hakları verildi. +message.user.granted.moderator = {0} kullanıcısına baÅŸkanlık hakları verildi. +message.user.granted.owner = {0} kullanıcısına sahiplik hakları verildi. +message.user.is.sending.you.a.file = {0} size bir dosya gönderiyor. +message.user.joined.room = {0} odaya katıldı. +message.user.kicked.from.room = {0} Odanın dışına atıldı. +message.user.left.room = {0} odadan ayrıldı. +message.user.nickname.changed = {0}, ÅŸimdi {1} olarak biliniyor. +message.user.now.available.to.chat = {0}, {1} tarafında çevrimiçi oldu +message.user.revoked.admin = {0} için yönetici yetkileriniz iptal edildi. +message.user.revoked.membership = {0} için üyeliÄŸiniz iptal edildi. +message.user.revoked.moderator = {0} için baÅŸkanlık yetkileriniz iptal edildi. +message.user.revoked.owner = {0} için sahiplik yetkileriniz iptal edildi. +message.user.voice.revoked = {0} kullanıcısının yazma hakkı yok. +message.username.error = Hesap için bir kullanıcı adı belirleyin. +message.username.password.error = Kullanıcı adı ve/veya parola gerekli. +message.vcard.not.supported = Sunucu VCard'ları desteklemiyor. VCard'ınız kaydedilemedi. +message.version = Sürüm: {0} +message.view.information.about.this.user = Bu kullanıcı için bilgi göster. +message.waiting.for.user.to.join = Katılması için beklenen: {0} +message.went.offline = {0}, {1} tarafında çevrimdışı oldu +message.you.have.been.banned = Bu odadan yasaklandınız. +message.you.have.been.kicked = Bu odanın dışına atıldınız. +message.you.have.sent = {0} kullanıcısına bir dosya gönderdiniz. +message.your.admin.granted = Yönetici yetkileriniz verildi. +message.your.banned = Bu oda için yasaklanmışsınız. +message.your.kicked = {0} tarafından atıldınız. +message.your.membership.granted = Üye yetkileriniz verildi. +message.your.membership.revoked = ÜyeliÄŸiniz iptal edildi. +message.your.moderator.granted = BaÅŸkanlık yetkileriniz verildi. +message.your.moderator.revoked = BaÅŸkanlık yetkileriniz iptal edildi. +message.your.ownership.granted = Sahiplik yetkileriniz verildi. +message.your.ownership.revoked = Sahiplik yetkileriniz iptal edildi. +message.your.revoked.granted = Yönetici yetkileriniz iptal edildi. +message.your.voice.granted = Bu sohbet için yazma hakkı verildi. +message.your.voice.revoked = Yazma hakkınız iptal edildi. + +status.away = Hemen dönecek +status.custom.messages = Özel durum +status.do.not.disturb = Rahatsız etme +status.extended.away = Uzakta +status.free.to.chat = Sohbete açık +status.on.phone = Sesli görüşmede +status.online = Çevrimiçi +status.pending = Beklemede + +tab.available.plugins = Kullanılabilir eklentiler +tab.avatar = Avatar +tab.business = İş +tab.conferences = Konferanslar +tab.contacts = BaÄŸlantılar +tab.general = Genel +tab.home = Ev +tab.installed.plugins = Yüklü eklentiler +tab.personal = KiÅŸisel +tab.proxy = Vekil sunucu + +title.about = Hakkında +title.account.create.registration = Hesap kaydı +title.account.created = Hesap oluÅŸturuldu +title.add.contact = BaÄŸlantı ekle +title.add.contact.group = Yeni baÄŸlantı grubu ekle +title.add.new.group = Yeni grup ekle +title.add.search.service = Arama servisi ekle +title.add.to.roster = Listeme ekle +title.address = Adres +title.advanced.connection.preferences = GeliÅŸmiÅŸ baÄŸlantı seçenekleri +title.alert = Alarm +title.appearance = Görünüş +title.appearance.preferences = ÖzelleÅŸtirmeler +title.available.transports = Kullanılabilir taşımalar +title.broadcast.message = Duyuru mesajı +title.browse.conference.services = Konferans servislerini tara +title.browse.room.service = konferans odalarını tara - {0} +title.cancelled = İptal edildi +title.change.nickname = Takma adı deÄŸiÅŸtir +title.change.subject = Konuyu deÄŸiÅŸtir +title.chat = Sohbet +title.choose.directory = Dizini seç +title.choose.incoming.sound = Gelen ses dosyasını seç +title.choose.offline.sound = Çevrimdışı ses dosyasını seç +title.choose.outgoing.sound = Giden ses dosyasını seç +title.conference.invitation = Konferans daveti +title.conference.rooms = Konferans odaları +title.configure.chat.room = Sohbet odasını ayarla +title.configure.room = Odayı ayarla +title.confirmation = Onaylama +title.create.new.account = Yeni hesap oluÅŸtur +title.create.or.bookmark.room = Odaya katıl veya yer imlerine ekle +title.create.room = OluÅŸtur +title.create.problem = Hesap oluÅŸturma sorunu +title.delete.file = Bu dosyayı gerçeten silmek istiyor musunuz? +title.dial.phone = Telefonu ara +title.disable.transport = Oturum açma bilgisini sil +title.download.complete = İndirme tamamlandı +title.downloading.im.client = IM İstemcisini indir +title.downloads = İndirmeler +title.edit.custom.message = Özel mesajları düzenle +title.edit.profile = Profil bilgisini düzenle +title.enter.reason = Nedeni girin +title.error = Hata +title.error.couldnot.open.file = Dosya açılamadı, bilinmeyen bir tipte olabilir. +title.error.delete.file = Dosya silinemedi. +title.error.find.app = EÅŸleÅŸen bir uygulama bulunamadı. +title.error.rename.file = Dosya adı deÄŸiÅŸtirilemedi. +title.file = Dosya +title.filesize = Boyut +title.file.exists = Dosya mevcut +title.file.transfer = Dosya transferi +title.file.transfer.preferences = Dosya transferi ayarları +title.find.conference.service = Konferans servisi bul +title.find.contacts = BaÄŸlantıları bul +title.gadugadu.registration = GaduGadu Hesap kimliÄŸi +title.general.chat.settings = Genel sohbet ayarları +title.group.chat = Grup sohbeti +title.group.chat.settings = Grup sohbeti ayarları +title.history.for = {0} için sohbet geçmiÅŸi +title.irc.registration = IRC Hesap kimliÄŸi +title.incoming.call = Gelen arama +title.input.fileexplorer = Lütfen dosya tarayıcınızın adını girin: +title.input.newname = Lütfen yeni adı girin: +title.input.openwith = Lütfen kullanmak istediÄŸiniz uygulamanın adını girin: +title.invite.to.conference = Konferansa davet et +title.jabber.browser = Tarayıcı +title.join.conference.room = Konferans odasına katıl +title.last.activity = Son etkinlik +title.login = Oturum aç +title.login.error = Oturum açma hatası +title.login.settings = Oturum açma ayarları +title.lookup.profile = Profile bak +title.name = İsim +title.new.client.available = Yeni istemci kullanılabilir +title.new.roster.group = Yeni liste grubu +title.new.version.available = Yeni sürüm kullanılabilir +title.no.updates = Güncelleme yok +title.notes = Notlar +title.notification = Uyarı +title.notifications = Uyarılar +title.occupants = Occupants +title.on.the.phone = Sesli görüşmede +title.password = Parola +title.passwords.no.match = Parolayı onayla. +title.person.search = KiÅŸi ara +title.plugins = Eklentiler +title.preferences = Özellikler +title.profile.information = Profil bilgisi +title.profile.not.found = Profil bulunamadı +title.qq.registration = QQ Hesabı kimlikleri +title.register.account = Yeni hesap kaydet +title.registration.error = Kayıt hatası +title.reminder = Hatırlatıcı +title.rename.roster.group = Grubun adını deÄŸiÅŸtir +title.room.destroyed = Oda silindi +title.room.information =Oda bilgisi +title.roster = Liste +title.select.file.to.send = Gönderilecek dosyaları seç +title.set.status.message = Durum mesajını ayarla +title.simple.registration = Basit hesap kimlikleri +title.sound.preferences = Ses ayarları +title.sounds = Sesler +title.spark.preferences = Spark ayarları +title.start.chat = Sohbet baÅŸlat +title.status.message = Durum mesajı +title.tasks = Görevler +title.transports = Taşımalar +title.tray.information = Sistem tepsisi bilgisi +title.upgrading.client = İstemci güncellemesi +title.version.and.time = Sürüm ve zaman +title.view.bookmarks = Yer imlerini görüntüle +title.view.profile.for = {0} Profili görüntüleniyor +title.view.room.information = Oda bilgisini görüntüle +title.waiting.to.call = ÇaÄŸrı için bekleniyor +title.xmpp.registration = XMPP Hesap kimliÄŸi +title.appearance.showVCards = BaÄŸlantı listesinde VCard'ları görüntüle + +tooltip.appearance = Sohbetinizin görünümünü deÄŸiÅŸtirin. +tooltip.file.transfer = Dosya transferi ayarları. +tooltip.notifications = Gelen istekler için uyarı ayarları. +tooltip.place.voice.call = Bu kullanıcıya bir telefon çaÄŸrısı yap. +tooltip.send.email = E-posta gönder. +tooltip.start.chat = Sohbeti baÅŸlat. +tooltip.view.changelog = DeÄŸiÅŸiklik kayıtlarını görüntüle +tooltip.view.history = Sohbet geçmiÅŸini görüntüle +tooltip.view.readme = Readme dosyasını oku + +tree.conference.services = Konferans servisleri +tree.users.in.room = Odadaki kullanıcılar diff --git a/core/src/main/resources/i18n/spark_i18n_uk_UA.properties b/core/src/main/resources/i18n/spark_i18n_uk_UA.properties new file mode 100644 index 000000000..ac9f664df --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_uk_UA.properties @@ -0,0 +1,1119 @@ +1.2.840.113533.7.65.0 = Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ð²ÐµÑ€ÑÑ–Ñ— Entrust +1.3.6.1.4.1.311.10.3.4 = Ðвтоматично отримано з OID'ів аÑоційованих з криптографією Microsoft +1.3.6.1.4.1.311.20.2 = Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð¸Ð¿Ñƒ Ñертифіката szOID_ENROLL_CERTTYPE_EXTENSION +1.3.6.1.4.1.311.21.1 = ВерÑÑ–Ñ Ð¾Ñ€Ð³Ð°Ð½Ð° Ñертифікації ÑервіÑів Ñертифікатів MS +1.3.6.1.5.5.7.1.1 = ДоÑтуп до інформації органа Ñертифікації +1.3.6.1.5.5.7.1.12 = id-pe-logotype +1.3.6.1.5.5.7.3.1 = Сертифікат може викориÑтовуватиÑÑ Ñк Ñерверний Ñертифікат Secure Socket Layer (SSL). +1.3.6.1.5.5.7.3.10 = Ключ Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ PKIX протоколи Data Validation and Certification Server (DVCS). +1.3.6.1.5.5.7.3.11 = Ключ Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ sbgpCertAAServerAuth. +1.3.6.1.5.5.7.3.12 = Ключ Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ id-kp-scvp-responder. +1.3.6.1.5.5.7.3.13 = Розширене Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ ÐºÐ»ÑŽÑ‡Ð°: id-kp-eapOverPPP +1.3.6.1.5.5.7.3.2 = Сертифікат може викориÑтовуватиÑÑ Ñк клієнтÑький Ñертифікат Secure Socket Layer (SSL). +1.3.6.1.5.5.7.3.3 = Сертифікат може викориÑтовуватиÑÑ Ð´Ð»Ñ Ð¿Ñ–Ð´Ð¿Ð¸ÑÐ°Ð½Ð½Ñ ÐºÐ¾Ð´Ñƒ. +1.3.6.1.5.5.7.3.4 = Сертифікат може викориÑтовуватиÑÑ Ð´Ð»Ñ Ð·Ð°Ñ…Ð¸Ñту е-пошти (підпиÑаннÑ, шифруваннÑ, Ð¿Ñ€Ð¸Ð¹Ð¼Ð°Ð½Ð½Ñ ÐºÐ»ÑŽÑ‡Ð°). +1.3.6.1.5.5.7.3.5 = Сертифікат кінцевої ÑиÑтеми Internet Protocol SECurity (IPSEC). +1.3.6.1.5.5.7.3.6 = Тунельний Ñертифікат Internet Protocol SECurity (IPSEC). +1.3.6.1.5.5.7.3.7 = Сертифікат кориÑтувача Internet Protocol SECurity (IPSEC). +1.3.6.1.5.5.7.3.8 = Ключ Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ PKIX timeStamping. Сертифікат може викориÑтовуватиÑÑ Ð´Ð»Ñ Ð·Ð²'Ñзку хешу об'єкта з чаÑом з довіреного джерела чаÑу. +1.3.6.1.5.5.7.3.9 = Вказує, що відповідний приватний ключ Ñертифіката ITU-T X.509 може викориÑтовуватиÑÑ Ñк авторитетне джерело підпиÑÐ°Ð½Ð½Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´ÐµÐ¹ OCSP. + +2.16.840.1.113730.1.1 = Тип Ñертифіката Netscape (Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ñертифіката X.509 v3 викориÑтовуєтьÑÑ Ð´Ð»Ñ Ñ–Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ— того, що предметом Ñертифіката Ñ” клієнт Secure Sockets Layer (SSL), Ñервер SSL, чи орган Ñертифікації (CA)) +2.23.42.7.0 = Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ñертифіката SET хешованих кореневих ключів (hashedRootKey) +2.5.29.1 = Старий ідентифкатор ключа авторизації X.509 +2.5.29.10 = Базові Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ +2.5.29.11 = Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ñертифіката (заÑтаріле) +2.5.29.12 = Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ñертифіката (заÑтаріле) +2.5.29.13 = Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ñертифіката (заÑтаріле) +2.5.29.14 = Предметний ідентифікатор ключа +2.5.29.15 = Ключове викориÑÑ‚Ð°Ð½Ð½Ñ +2.5.29.16 = Період викориÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¾Ð³Ð¾ ключа +2.5.29.17 = Ðльтернативна назва предмета +2.5.29.18 = Ðльтернативна назва Ð²Ð¸Ð´Ð°Ð²Ñ†Ñ +2.5.29.19 = Базові Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ +2.5.29.2 = Ключові атрибути (заÑтаріле) +2.5.29.20 = Ðомер CRL +2.5.29.21 = Код причини +2.5.29.22 = Термін придатноÑті +2.5.29.23 = МіÑтить код інÑтрукції +2.5.29.24 = Дата нечинноÑті +2.5.29.25 = Точки розподілу CRL +2.5.29.26 = Точки розподілу випуÑків +2.5.29.27 = Індикатор CRL +2.5.29.28 = Точки розподілу випуÑків +2.5.29.29 = Видавець Ñертифіката +2.5.29.3 = Політики Ñертифіката +2.5.29.30 = ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð½Ð°Ð·Ð²Ð¸ (імені) +2.5.29.31 = Точки розподілу CRL +2.5.29.32 = Політики Ñертифіката +2.5.29.33 = Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ð»Ñ–Ñ‚Ð¸ÐºÐ¸ +2.5.29.34 = ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ð»Ñ–Ñ‚Ð¸ÐºÐ¸ +2.5.29.35 = Ідентифікатор ключа авторизації +2.5.29.36 = ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ð»Ñ–Ñ‚Ð¸ÐºÐ¸ +2.5.29.37 = Розширене викориÑÑ‚Ð°Ð½Ð½Ñ ÐºÐ»ÑŽÑ‡Ð° +2.5.29.38 = Ідентифікатор атрибута авторизації +2.5.29.39 = Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ñ–Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ‚Ð¾Ñ€Ð° Ñертифіката Ñпецифікації ролі +2.5.29.4 = ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ ÐºÐ»ÑŽÑ‡Ð° +2.5.29.40 = Ідентифікатор потоку CRL +2.5.29.41 = basicAttConstraints +2.5.29.42 = ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð´ÐµÐ»ÐµÐ³Ð¾Ð²Ð°Ð½Ð¾Ð³Ð¾ імені +2.5.29.43 = Ð¡Ð¿ÐµÑ†Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ Ñ‡Ð°Ñу +2.5.29.44 = ОблаÑть CRL +2.5.29.45 = Реферали Ñтану +2.5.29.46 = Свіжий CRL +2.5.29.47 = СпиÑок в CRL у порÑдку зроÑÑ‚Ð°Ð½Ð½Ñ +2.5.29.48 = ДеÑкриптор атрибута +2.5.29.49 = ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача +2.5.29.5 = Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ð»Ñ–Ñ‚Ð¸ÐºÐ¸ +2.5.29.50 = ідентифікатор SOA +2.5.29.51 = Ð§Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð±Ð°Ð·Ð¾Ð²Ð¾Ð³Ð¾ CRL +2.5.29.52 = ПрийнÑтні політики Ñертифіката +2.5.29.53 = Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ дельту +2.5.29.54 = Заборона any-policy +2.5.29.55 = Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ ÑпрÑÐ¼ÑƒÐ²Ð°Ð½Ð½Ñ +2.5.29.56 = Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ Ð²Ñ–Ð´ÐºÐ»Ð¸ÐºÐ°Ð½Ð½Ñ Ð½ÐµÐ´Ð¾Ñтупна +2.5.29.57 = ПрийнÑтні політики привілеїв +2.5.29.58 = id-ce-toBeRevoked +2.5.29.59 = id-ce-RevokedGroups +2.5.29.6 = ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ð´ÐµÑ€ÐµÐ²Ð° +2.5.29.60 = id-ce-expiredCertsOnCRL +2.5.29.61 = ÐепрÑмий видавець +2.5.29.62 = id-ce-noAssertion +2.5.29.63 = id-ce-aAissuingDistributionPoint +2.5.29.64 = id-ce-issuedOnBehaIFOF +2.5.29.65 = id-ce-singleUse +2.5.29.66 = id-ce-groupAC +2.5.29.67 = id-ce-allowedAttAss +2.5.29.68 = id-ce-attributeMappings +2.5.29.69 = id-ce-holderNameConstraints +2.5.29.7 = Ðльтернативна назва предмету +2.5.29.8 = Ðльтернативна назва Ð²Ð¸Ð´Ð°Ð²Ñ†Ñ +2.5.29.9 = Ðтрибути каталогу предмета + +accept = ПрийнÑти + +action.clear = ОчиÑтити +action.copy = Копіювати +action.cut = Вирізати +action.paste = Ð’Ñтавити +action.print = Друкувати +action.save = Зберегти +action.select.all = Вибрати вÑе +#!# +action.viewlog = ПереглÑнути журнал + +active = {0} звертає увагу + +add = Додати + +administrator = ÐдмініÑтратор + +answer = Відповідь + +apply = ЗаÑтоÑувати + +available = ДоÑтупний + +broadcast = ТранÑлювати + +button.accept = ПрийнÑти +button.add = Додати +button.add.a.contact = Додати контакт +button.add.bookmark = Додати закладку +button.add.service = Додати Ñлужбу +button.add.user = Додати кориÑтувача +button.add2 = Додати +button.advanced = Д&одатково +button.approve = Підтвердити +button.bookmark.room = ЗаклаÑти кімнату +button.browse = &Вибрати... +button.browse2 = Вибрати... +button.browse3 = Вибрати... +button.cancel = СкаÑувати +button.check.validity = Перевірка чинноÑті +button.clear = ОчиÑтити +button.close = Закрити +button.copy.to.clipboard = Скопіювати до буфера обміну +button.create.account = Створити обліковий Ð·Ð°Ð¿Ð¸Ñ +button.create.room = Створити або приєднатиÑÑŒ до кімнати +button.decline = Відхилити +button.deny = Заборонити +button.dial.number = Ðабрати номер +button.find = Знайти +button.join = ПриєднатиÑÑŒ +button.join.room = ПриєднатиÑÑŒ до обраної кімнати +button.login = &Увійти +button.new = Ðовий +button.profile = Профіль +button.quit = Вихід +button.re.detect = &Визначити заново +button.reconnect = З'єднатиÑÑŒ заново +button.reconnect2 = З'єднатиÑÑŒ заново +button.refresh = Оновити +button.register = ЗареєÑтрувати +button.reject = Відхилити +button.remove.bookmark = Вилучити закладку +button.roster = СпиÑок +button.save = Зберегти +button.save.for.future.use = Зберегти Ð´Ð»Ñ Ð¼Ð°Ð¹Ð±ÑƒÑ‚Ð½ÑŒÐ¾Ð³Ð¾ вжитку +button.search = Пошук +button.send = ÐадіÑлати +button.send.email = E-адреÑа +button.show.certificate = Показати Ñертифікат +button.start.chat = БеÑіда +button.tasks.active = Ðктивна +button.tasks.all = Ð’ÑÑ– +button.unset.file.explorer = Розв'Ñзати файловий оглÑдач +button.update = Оновити +button.view.notes = ПереглÑнути нотатки +button.view.profile = ПереглÑнути увеÑÑŒ профіль +button.view.tasklist = ПереглÑнути ÑпиÑок завдань + +cancel = СкаÑувати + +cert.city = МіÑто +cert.common.name = Загальна назва +cert.country = Країна +cert.critical = Критично: +cert.expired = ЗакінчивÑÑ +cert.extension.basic.constraints.is.ca = Є органом Ñертифікації +cert.extension.basic.constraints.path.length = Довжина шлÑху валідації +cert.extension.extended.usage.crl.sign = ÐŸÑ–Ð´Ð¿Ð¸Ñ CRL +cert.extension.extended.usage.data.encipherment = Ð¨Ð¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… +cert.extension.extended.usage.decipher.only = Лише Ð´ÐµÑˆÐ¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ +cert.extension.extended.usage.digital.signature = Цифровий Ð¿Ñ–Ð´Ð¿Ð¸Ñ +cert.extension.extended.usage.encipher.only = Лише ÑˆÐ¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ +cert.extension.extended.usage.key.agreement = Угода ключа +cert.extension.extended.usage.key.cert.sign = ÐŸÑ–Ð´Ð¿Ð¸Ñ ÐºÐ»ÑŽÑ‡Ð° Ñертифікату +cert.extension.extended.usage.key.encipherment = Ð¨Ð¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ»ÑŽÑ‡Ð° +cert.extension.extended.usage.non.repudiation = Ðе Ð·Ñ€ÐµÑ‡ÐµÐ½Ð½Ñ +cert.extension.name.constraints.excluded.subtrees = Виключені піддерева +cert.extension.name.constraints.permitted.subtrees = Дозволені піддерева +cert.extensions = Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ñертифіката: +cert.extensions.unsupported = Ðепідтримувані Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ +cert.is.critical = Критично: +cert.not.critical = Ðекритично: +cert.not.valid.yet = Ще не чинний +cert.organization = ÐžÑ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ +cert.organization.unit = Організаційна Ð¾Ð´Ð¸Ð½Ð¸Ñ†Ñ +cert.revoked = Відкликаний +cert.self.signed = СамопідпиÑний +cert.sign.request = Запит Ñертифіката +cert.unknown.oid = Ðевідомий Ð¾Ð¿Ð¸Ñ OID. +cert.valid = Чинний + +checkbox.accept.all = ПрийнÑти вÑÑ– +checkbox.accept.all.certificates = ПрийнÑти вÑÑ– Ñертифікати (ÑамопідпиÑні / протерміновані / недовірені) +checkbox.accept.expired = ПрийнÑти протермінований +checkbox.accept.not.valid.yet = ПрийнÑти ще не чинний +checkbox.accept.revoked = ПрийнÑти відкликаний +checkbox.accept.self.signed = ПрийнÑти ÑамопідпиÑний +checkbox.allow.buzz = Дозвилити кориÑтувачам &дзинькати тобі +checkbox.allow.client.side.authentication = Дозволити автентифікацію на клієнтÑькій Ñтороні +checkbox.allow.soft.fail = Дозволити м'Ñку політику помилок +checkbox.auto.discover.port = Ðвтоматично виÑвлÑти вузол Ñ– порт +checkbox.auto.login = &Ðвтовхід +checkbox.broadcast.hide.offline.user = Сховати відключених +checkbox.check.crl = Перевірка CRL +checkbox.check.ocsp = Перевірка OCSP +checkbox.click.single.tray = &Одинарне ÐºÐ»Ð°Ñ†Ð°Ð½Ð½Ñ Ð² Ñитемному лотку відкриває Spark (потрібен перезапуÑк) +checkbox.conference.tab.setting = Показати Ñлужбу конференцій у закладці (потрібен перезапуÑк) +checkbox.disable.asterisk.toaster = Вимкнути телефонні Ñпливаючі вікна +checkbox.disable.chat.history = &Вимкнути Ñ–Ñторію беÑіди +checkbox.disable.hostname.verification = Вимкнути перевірку Ñертифіката вузла (не рекомендовано) +checkbox.disable.prev.chat.history = Вимкнути &показ попередніх розмов +checkbox.enable.emoticons = Д&озволити емоції +checkbox.filetransfer.ibb.only = Лише байтові потоки у Ñмузі +checkbox.graying.out = Затінити неактивні контакти (потрібен перезапуÑк) +checkbox.idle.enabled = &ÐеактивніÑть дозволена +checkbox.launch.on.startup = &ЗапуÑкати при ввімкненні +checkbox.login.anonymously = Увійти анонімно +checkbox.login.as.invisible = З&айти непомітно +checkbox.notify.systemtray = Показати нові &Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñƒ ÑиÑтемному лотку +checkbox.notify.typing.systemtray = Повідомити про набір Ñимволів у ÑиÑтемному лотку +checkbox.notify.user.comes.online = Повідомити, коли &кориÑтувач вийде на зв'Ñзок +checkbox.notify.user.goes.offline = &Повідомити, коли кориÑтувач розірве зв'Ñзок +checkbox.on.exception.list = У ÑпÑику винÑтків +checkbox.permanent = ПоÑтійна кімната +checkbox.play.sound.on.invitation = Звук при отримані Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ +checkbox.play.sound.on.new.message = Звук при новому повідомленні +checkbox.play.sound.on.outgoing.message = Звук при надÑиланні Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ +checkbox.play.sound.when.offline = Звук, коли кориÑтувач відключивÑÑ +checkbox.private.room = Приватна кімната +checkbox.reconnect.panel.big = Відобразити Ñк панель +checkbox.reconnect.panel.icon = Відобразити Ñк значок +checkbox.reconnect.panel.small = Показати в контактній групі +checkbox.reconnect.info = Вказати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸ відновленні зв'Ñзку: +checkbox.save.password = Зберегти пароль +checkbox.show.avatars.in.contactlist = Показати &значки у ÑпиÑку контактів +checkbox.show.notifications.in.conference = Показати &Ð¾Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð² конференціÑÑ… +checkbox.show.time.in.chat.window = Показати Ñ‡Ð°Ñ Ñƒ вікні +checkbox.show.toaster = Показати Ñпливаючі вікна +checkbox.sort.asc.history = ВпорÑдкувати Ñ–Ñторію повідомлень за зроÑтаннÑм дати +checkbox.split.chat.window = Стикувати вікна (потрібен перезапуÑк) +checkbox.start.in.tray = &Стартувати в ÑиÑтемному лотку +checkbox.tabs.on.top = Вікна беÑід нагорі (потрібен перезапуÑк) +checkbox.tabs.scroll = ВикориÑтовуйте прокрутку Ð´Ð»Ñ Ð²ÐºÐ»Ð°Ð´Ð¾Ðº чату (потрібно перезапуÑтити) +checkbox.transport.tab.setting = Показати можливі транÑпорти в закладці (потрібен перезапуÑк) +checkbox.use.compression = ВикориÑтовувати ÑтиÑÐºÐ°Ð½Ð½Ñ +checkbox.use.debugger.on.startup = ЗапуÑкати відладник при ввімкненні +checkbox.use.hostname.as.resource = ВикориÑтовувати назву вузла Ñк джерело +checkbox.use.krb.dns = ВикориÑтовувати DNS +checkbox.use.krbconf = ВикориÑтовувати krb5.conf або krb5.ini +checkbox.use.pki.authentication = ВикориÑтовувати PKI-автентифікацію +checkbox.use.proxy.server = ВикориÑтовувати прокÑÑ–-Ñервер +checkbox.use.specify.below = Вкажи внизу +checkbox.use.system.look.and.feel = ВикориÑтовувати ÑиÑтемний виглÑд (потрібен перезапуÑк) +checkbox.use.version.as.resource = ВикориÑтовувати верÑÑ–ÑŽ Spark Ñк джерело +checkbox.window.to.front = Вікно на передній план +checkbox.close.unread.message = Запитувати при закритті вікна, чи Ñ” непрочитані Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +close = Закрити + +composing = {0} пише... + +create = Створити + +date = Дата + +delete = Вилучити + +delete.log.permanently = ÐазовÑім вилучити журнал +delete.permanently = Вилучити назовÑім? + +description = ÐžÐ¿Ð¸Ñ + +details = Подробиці + +dialog.cannot.upload.certificate = Ðе можу завантажити файл Ñертифіката +dialog.cannot.upload.certificate.might.be.ill.formatted = Ðе вдаєтьÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ файл Ñертифіката: Ñертифікат може бути погано Ñформований +dialog.certificate.cannot.have.copy = Цей Ñертифікат уже збережений у довіреному Ñховищі. +dialog.certificate.has.been.added = Сертифікат доданий до довіреного Ñховища. +dialog.certificate.has.been.deleted = Сертифікат уÑпішно вилучений. +dialog.certificate.is.distrusted = Сертифікат недійÑний, тому його не Ñлід довірÑти, оÑкільки це небезпечно.\r\nЯкщо ти вÑе ще довірÑєш йому, клацни по перемикачу "ДовірÑти" або додай його до ÑпиÑку винÑтків. +dialog.certificate.request.has.been.created = Запит на Ñертифікат та приватний ключ Ñтворено в каталозі: +dialog.certificate.show = Це Ñертифікат та приватний ключ, Ñкий ти намагаєшÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ до довіреного Ñховища.

      ПіÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк додати цей Ñертифікат, Spark зможе вÑтановлювати захищену
      комунікацію з Ñерверами, Ñкі ним ідентифікуютьÑÑ.

      Якщо Ñправді хочеш додати цей Ñертифікат, натиÑни кнопку ОК. +dialog.certificate.sure.to.delete = Ти Ñправді хочеш видалити цей Ñертифікат?\r\nЯкщо ти це зробиш, то надалі не зможеш вÑтановлювати\r\nбезпечне з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· Ñерверами, ідентифікованими ним. +dialog.confirm.close.all.conferences.if.invisible.msg = Якщо ти продовжиш, вÑÑ– кімнати будуть закриті +dialog.confirm.to.reveal.visibility.msg = Якщо ти продовжиш, Ñ‚Ð²Ð¾Ñ Ð½ÐµÐ²Ð¸Ð´Ð¸Ð¼Ñ–Ñть буде розкрита +dialog.confirm.to.reveal.visibility.title = Ти впевнений? +dialog.id.certificate.show = Це Ñертифікат, Ñкий ти хочеш додати до влаÑного Ñховища.

      ПіÑÐ»Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ñертифікату Spark зможе надати його віддаленому Ñерверу під Ñ‡Ð°Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ— та ÑˆÐ¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ з'єднаннÑ.

      Якщо ти Ñправді хочеш додати цей Ñертифікат, натиÑни кнопку ОК. +dialog.self.signed.certificate.has.been.created = СамопідпиÑний Ñертифікат Ñ– приватний ключ Ñтворені в теці: + +from = З + +gateway.username.password.error = Потрібно ввеÑти ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача Ñ–/чи пароль + +gone = {0} зайнÑтий чимоÑÑŒ іншим + +group.chat.name.match = Твоє ім'Ñ Ð·Ð³Ð°Ð´Ð°Ð½Ðµ в групі: +group.chat.name.notification = Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð²Ð¾Ð³Ð¾ імені... +group.chat.window.information = Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ–Ñ Ð²Ñ–ÐºÐ½Ð° беÑіди +group.comma.delimited = Розділені комами +group.conferences.found = Знайдено Ñлужбу конференцій +group.connection = З'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ +group.empty = У цій групі нема кориÑтувачів на зв'Ñзку +group.encryption_mode = Режим ÑˆÐ¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ +group.general.information = Загальна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ +group.login.information = Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ вхід +group.notification.options = ВаріÑнти оповіщень +group.offline = Оффлайнова група +group.search.form = Пошукова форма +group.search.results = Результати пошуку +group.send_config.error = ÐŸÑ–Ð´Ñ‡Ð°Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð¾Ñ— форми трапивÑÑ Ð²Ð¸Ð½Ñток! + +inactive = {0} зайнÑтий чимоÑÑŒ іншим + +invite = ЗапроÑити + +join = ПриєднатиÑÑŒ + +label.accounts = Облікові запиÑи +label.add.conference.service = Додати Ñлужбу конференцій +label.add.jid = Додати JID +label.add.task = Додати Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ +label.add.to.roster = Додати кориÑтувача в ÑпиÑок +label.apple.keychain = Ланцюжок ключів Apple +label.audio.device = &Звуковий приÑтрій +label.auto.login = Ðвтовхід +label.available.users.in.roster = СпиÑок доÑтупних кориÑтувачів +label.avatar = Значок: +label.broadcast.history.search.date = Знайти дату (рік-міÑÑць): +label.cancel = СкаÑувати +label.cell = Комірка +label.certificate.add.certificate.to.identitystore = Додати Ñертифікат до оÑобиÑтого Ñховища +label.certificate.add.certificate.to.truststore = Додати Ñертифікат до довіреного Ñховища +label.certificate.issuer = Видавець +label.certificate.issuer.unique.id = Унікальний ідентифікатор Ð²Ð¸Ð´Ð°Ð²Ñ†Ñ +label.certificate.not.after = Ðечинний піÑÐ»Ñ +label.certificate.not.before = Ðечинний перед +label.certificate.public.key = Відкритий ключ +label.certificate.public.key.algorithm = Ðлгоритм відкритого ключа +label.certificate.serial.number = Серійний номер +label.certificate.signature.algorithm = Ðлгоритм підпиÑу +label.certificate.signature.value = Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñу +label.certificate.status = Стан Ñертифікату. +label.certificate.subject = Суб'єкт +label.certificate.subject.unique.id = Унікальний ідентифікатор Ñуб'єкта +label.certificate.version = ВерÑÑ–Ñ +label.change.password.to = Змінити пароль на +label.chatroom.fontsize = Розмір шрифта в кімнаті +label.chatroom.maxcurrenthistorysize = МакÑимальний розмір поточної Ñ–Ñторії: +label.choose.file = Вибрати файл +label.city = МіÑто +label.close = Закрити +label.company = ÐšÐ¾Ð¼Ð¿Ð°Ð½Ñ–Ñ +label.confirm.password = &Підтвердити пароль +label.conflict.error = Ðеможливо увійти через те, що такий обліковий Ð·Ð°Ð¿Ð¸Ñ ÑƒÐ¶Ðµ зареєÑтрований +label.contact.to.find = Знайти контакт +label.contactlist.avatarsize = Розмір значків контактів: +label.contactlist.fontsize = Розмір шрифта ÑпиÑку контактів: +label.country = Країна +label.create.account = Створити обліковий Ð·Ð°Ð¿Ð¸Ñ +label.department = Підрозділ +label.dial = Телефонувати +label.display.time = Відобразити чаÑ: +label.downloads = Завантажити +label.due = Згідно +label.email.address = E-адреÑа +label.emoticons = &Емоції +label.enter.address = Введи адреÑу +label.enter.group.name = Введи назву нової групи +label.enter.password = Введи пароль +label.fax = Ð¤Ð°ÐºÑ +label.find = Знайти +label.first.name = Ім'Ñ +label.frequent.contacts = ЧаÑті контакти +label.group = Група +label.home = Домівка +label.host = Вузол +label.invited.users = Запрошені кориÑтувачі +label.jabber.address = Jabber-адреÑа +label.jabber.id = Jabber-ідентифікатор +label.jid = JID +label.job.title = ПоÑада +label.keystore.location = МіÑце Ñховища ключів +label.krb.kdc = KDC +label.krb.realm = Царина +label.last.name = Прізвище +label.local.time = МіÑцевий Ñ‡Ð°Ñ +label.message = ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ +label.message.style = Стиль Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ +label.middle.name = По батькові +label.minutes.before.stale.chat = &Хвилин перед тим, Ñк неактивна кімната Ñтане заÑтарілою +label.mobile = Мобільний +label.move.focus.backwards = ЗміÑтити Ñ„Ð¾ÐºÑƒÑ Ð½Ð°Ð·Ð°Ð´ +label.move.focus.forwards = ЗміÑтити Ñ„Ð¾ÐºÑƒÑ ÑƒÐ¿ÐµÑ€ÐµÐ´ +label.na = н/д +label.name = Ім'Ñ +label.network = Мережа +label.new.nickname = Ðове прізвиÑько +label.nickname = ПрізвиÑько +label.number = Ðомер +label.ok = Гаразд +label.old.ssl = ВикориÑтовути прÑмий TLS-метод +label.os = Операційна ÑиÑтема +label.pager = Пейджер +label.password = &Пароль +label.passwordreset = Скинути пароль +label.phone = Телефон +label.pkcs.library.file = Файл бібліотеки PKCS#11 +label.port = Порт +label.postal.code = Поштовий Ñ–Ð½Ð´ÐµÐºÑ +label.presence = ПриÑутніÑть +label.priority = Пріоритет +label.protocol = Протокол +label.received = Отримано +label.recent.conversation = ОÑтанні беÑіди +label.reconnect.delay = Затримка перепід'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ (Ñ) (піÑÐ»Ñ Ð¿ÐµÑ€ÐµÐ·Ð°Ð¿ÑƒÑку) +label.rename.to = Перейменувати на +label.resource = Джерело +label.response.timeout = &Таймаут відповіді (Ñ) +label.room = Кімната +label.room.name = Ðазва кімнати +label.room.topic = Тема кімнати +label.search = Пошук +label.search.service = Пошукова Ñлужба +label.seconds = Секунди +label.server = До&мен +label.server.address = ÐдреÑа Ñервера +label.show = Показати: +label.software = Програма +label.state.and.province = Штат/облаÑть +label.street.address = Ð’ÑƒÐ»Ð¸Ñ†Ñ +label.time = ЧаÑ: {0} +label.time.till.idle = &Ð§Ð°Ñ Ð´Ð¾ Ñтану неактивноÑті (хв.) +label.time.till.idlemessage = ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ñ— неактивноÑті +label.timeformat = ВикориÑÑ‚Ð°Ð½Ð½Ñ {0} +label.transfer.download.directory = &Тека завантажень: +label.transfer.timeout = &Таймаут передачі (хв.): +label.trust.store.password = Пароль довіреного Ñховища +label.truststore.location = МіÑце довіреного Ñховища +label.unable.to.add.contact = Ðеможливо додати контакт +label.use.default = ВикориÑтовувати Ñтандарт +label.user.on.public.network = КориÑтувач Ñ” в публічній мережі +label.username = &Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача +label.version = ВерÑÑ–Ñ +label.video.device = &ВідеоприÑтрій +label.web.page = Веб-Ñторінка +label.which.pki.method = Який PKI метод? +label.work = Робота +label.x509.certificate = Сертифікат X.509 +label.xmpp.port = Порт &XMPP + +lookandfeel.change.now = Змінити зараз +lookandfeel.color.blue = Синій +lookandfeel.color.green = Зелений +lookandfeel.color.label = Барви +lookandfeel.color.opacity = ÐепрозоріÑть +lookandfeel.color.red = Червоний +lookandfeel.color.saved = Барви збережено +lookandfeel.select = Вибір зовнішнього виглÑду +lookandfeel.tooltip.restart.no = ПерезапуÑк не потрібний +lookandfeel.tooltip.restart.yes = Щоб задіÑти зміну зовнішнього виглÑду натиÑни Зберегти Ñ– перезапуÑти Spark. + +menuitem.about = Про програму +menuitem.actions = Дії +menuitem.add = Додати +menuitem.add.as.contact = Додати Ñк контакт +menuitem.add.contact = Додати контакт +menuitem.add.contact.group = Додати групу +menuitem.add.groupchat.auto.accept.invite = &Ðвтоматично приймати Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð² групи +menuitem.add.groupchat.invitetobookmark = Ðвтоматично запрошувати кориÑтувачів до закладеної кімнати +menuitem.add.groupchat.myname = ПідÑвітити моє ім'Ñ, Ñкщо хтоÑÑŒ називає його +menuitem.add.groupchat.mytext = ПідÑвітити мій текÑÑ‚, Ñкщо Ñ Ð¿Ð¸ÑˆÑƒ щоÑÑŒ +menuitem.add.groupchat.popname = Показати Ñпливаюче вікно, Ñкщо хтоÑÑŒ називає моє ім'Ñ +menuitem.add.groupchat.random.colors = Випадкові барви Ð´Ð»Ñ Ñ–Ð¼ÐµÐ½ +menuitem.add.groupchat.showjoinleavemessage = &Показати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ / від'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ +menuitem.add.groupchat.showrolesinsteadofstatus = Показати рольові значки заміÑть значків приÑутноÑті +menuitem.affiliation = ÐŸÑ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ +menuitem.alert.when.online = Сповіщати, коли кориÑтувач Ñтане доÑтупний +menuitem.always.on.top = Завше вгорі +menuitem.ban = Забанити +menuitem.ban.user = Забанити кориÑтувача +menuitem.block.contact = Блокувати контакт +menuitem.block.user = Блокувати кориÑтувача +menuitem.bookmark.room = ЗаклаÑти кімнату +menuitem.bookmarks = Закладки +menuitem.broadcast.to.group = ТранÑлювати в групу +menuitem.browse.service = ОглÑд Ñлужб +menuitem.certificate.files.filter = Файли Ñертифікатів (*.cer), (*.crt), (*.der) +menuitem.change.nickname = Змінити прізвиÑько +menuitem.change.subject = Змінити тему +menuitem.chat = БеÑіда +menuitem.chatframe.option = МожливоÑті +menuitem.check.for.updates = Перевірити &Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ +menuitem.collapse.all.groups = Згорнути вÑÑ– групи +menuitem.connect = Файл +menuitem.contacts = Контакти +menuitem.copy.to = Скопіювати до +menuitem.create.room = Створити або приєднатиÑÑŒ до кімнати +menuitem.delete = Вилучити +menuitem.delete.login.information = Вилучити облікову інформацію +menuitem.destroy.room = Знищити кімнату +menuitem.dial = Телефонувати +menuitem.edit = Редагувати +menuitem.edit.my.profile = Редагувати профіль... +menuitem.edit.status.message = Редагувати ÑтатуÑ... +menuitem.enter.login.information = ВвеÑти облікову інформацію +menuitem.exit = Завершити +menuitem.expand.all.groups = Розгорнути вÑÑ– групи +menuitem.grant.admin = Ðадати права адмініÑтратора +menuitem.grant.member = Ðадати права учаÑника +menuitem.grant.moderator = Ðадати права модератора +menuitem.grant.owner = Ðадати права влаÑника +menuitem.grant.voice = Ðадати право голоÑу +menuitem.help = Поміч +menuitem.hide = Сховати +menuitem.invite.again = ЗапроÑити знов +menuitem.invite.group.to.conference = ЗапроÑити групу до конференції +menuitem.invite.users = ЗапроÑити кориÑтувачів +menuitem.join.on.startup = ПриєднатиÑÑŒ при запуÑку +menuitem.join.room = ПриєднатиÑÑŒ до вибраної кімнати +menuitem.kick.user = Викинути кориÑтувача +menuitem.languages = Мови +menuitem.logout.no.status = Вийти +menuitem.logout.with.status = Вийти через +menuitem.lookup.profile = Шукати профіль... +menuitem.move.to = ПереміÑтити до +menuitem.online.help = Форуми Spark +menuitem.open = Відкрити +menuitem.open.with = Відкрити з... +menuitem.plugins = Додатки +menuitem.preferences = ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ +menuitem.refresh = Оновити +menuitem.remove = Вилучити +menuitem.remove.alert.when.online = Вилучити Ð¾Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ +menuitem.remove.bookmark = Вилучити закладку +menuitem.remove.from.group = Вилучити з групи +menuitem.remove.from.roster = Вилучити зі ÑпиÑку +menuitem.remove.service = Вилучити Ñлужбу +menuitem.rename = Перейменувати +menuitem.revoke.admin = Відкликати адмініÑтратора +menuitem.revoke.member = Відкликати учаÑника +menuitem.revoke.moderator = Відкликати модератора +menuitem.revoke.owner = Відкликати влаÑніÑть +menuitem.revoke.voice = Відкликати право голоÑу +menuitem.save = Зберегти +menuitem.save.as = Зберегти Ñк... +menuitem.send.a.file = ÐадіÑлати файл +menuitem.send.a.message = ТранÑлювати обраним кориÑтувачам... +menuitem.set.status.message = Ð’Ñтановити ÑтатуÑ... +menuitem.show.contact.statusmessage = Показати ÑÑ‚Ð°Ñ‚ÑƒÑ +menuitem.show.empty.groups = Показати порожні групи +menuitem.show.offline.group = Згрупувати відімкнених кориÑтувачів +menuitem.show.offline.users = Показати відімкнених кориÑтувачів +menuitem.show.traffic = Показати вікно трафіку +menuitem.sign.in = ЗареєÑтруватиÑÑŒ +menuitem.sign.in.at.login = ЗареєÑтруватиÑÑŒ при +menuitem.sign.out = ВідключитиÑÑŒ +menuitem.start.a.chat = Почати беÑіду +menuitem.start.a.conference = Почати конференцію... +menuitem.status = Ð¡Ñ‚Ð°Ñ‚ÑƒÑ +menuitem.subscribe.to = ПідпиÑатиÑÑŒ на +menuitem.unban = Розбанити кориÑтувача у ÑпиÑку +menuitem.unblock.contact = Розблокувати контакт +menuitem.unblock.user = Розблокувати кориÑтувача в ÑпиÑку +menuitem.user.guide = ПоÑібник кориÑтувача +menuitem.view.client.version = ВерÑÑ–Ñ ÐºÐ»Ñ–Ñ”Ð½Ñ‚Ð° +menuitem.view.contact.history = ПереглÑнити Ñ–Ñторію контактів +menuitem.view.downloads = ПереглÑнути Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ +menuitem.view.last.activity = ПереглÑнути оÑтанню активніÑть +menuitem.view.logs = ПереглÑнути журнали +menuitem.view.profile = ПереглÑнути профіль +menuitem.view.room.info = Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ кімнату +menuitem.voice = Ð“Ð¾Ð»Ð¾Ñ + +message = ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +message.account.create = Створити новий обліковий Ð·Ð°Ð¿Ð¸Ñ +message.account.created = Ðовий обліковий Ð·Ð°Ð¿Ð¸Ñ Ñтворено +message.account.error = Вкажи Ñервер, де Ñлід Ñтворити обліковий Ð·Ð°Ð¿Ð¸Ñ +message.add.a.contact = Додати контакт +message.add.conference.service = Додати Ñлужбу конференцій +message.add.contact.to.list = Додати кориÑтувача до ÑпиÑку контактів +message.add.favorite.room = Додати кімнату до улюблених або одразу приєднатиÑÑŒ +message.add.this.user.to.your.roster = Додати кориÑтувача до друзів +message.add.to.roster = Додати у ÑпиÑок +message.add.user = Додати кориÑтувача у твій ÑпиÑок? +message.alert.notify = ÐžÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ +message.already.exists = Обліковий Ð·Ð°Ð¿Ð¸Ñ ÑƒÐ¶Ðµ Ñ–Ñнує, Ñпробуй інакше ім'Ñ +message.approve.subscription = Дозволити {0} додати тебе до Ñвого ÑпиÑку? +message.authenticating = ÐÐ²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ +message.away.idle = ВідÑутній через проÑтій +message.bookmark.temporary.room.error = Ðеможливо заклаÑти тимчаÑові кімнати +message.broadcast.from = ТранÑлÑÑ†Ñ–Ñ Ð²Ñ–Ð´ {0} +message.broadcast.message.sent = ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ð°Ð´Ñ–Ñлано +message.broadcast.no.text = Ðапиши текÑÑ‚ Ð´Ð»Ñ Ñ‚Ñ€Ð°Ð½ÑÐ»ÑŽÐ²Ð°Ð½Ð½Ñ +message.broadcast.no.user.selected = Вибери хоча б одного отримувача +message.broadcast.to = Введи Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ‚Ñ€Ð°Ð½ÑлÑції до {0} +message.hasbeenbroadcast.to = ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‚Ñ€Ð°Ð½Ñльовано до таких кориÑтувачів:\n{0} +message.buzz.alert.notification = Звернути увагу кориÑтувача +message.buzz.message = {0} прагне твоєї уваги +message.buzz.sent = ПопроÑив уваги +message.calling = Викликає {0} +message.came.online = {0} на зв'Ñзку з {1} +message.cannot.add.contact.to.shared.group = Ти не можеш додати новий контакт у групу +message.cert.hostname.verification.failed = Ðевдача перевірки Ñертифіката вузла +message.cert.verification.failed = Ðеможливо перевірити Ñертифікат +message.chat.session.ended = БеÑіда закінчена {0} +message.click.to.open = ÐатиÑни, щоб відкрити +message.client.information = Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ клієнта {0} +message.close.other.chats = Закрити вÑÑ– інші беÑіди +message.close.stale.chats = Закрити вÑÑ– заÑтарілі беÑіди +message.close.this.chat = Закрити цю беÑіду +message.close.unread.window = У Ð²Ð°Ñ Ñ” непрочитані повідомленнÑ. Ви впевнені, що бажаєте закрити вікно? +message.conference.info.error = Ðеможливо отримати інформацію про конференцію, Ñпробуй пізніше +message.conference.service.error = Ðеможливо знайти Ñлужбу конференцій +message.confirm.destruction.of.room = Ð’Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ ÐºÑ–Ð¼Ð½Ð°Ñ‚Ð¸ призведе до Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ Ð²ÑÑ–Ñ… кориÑтувачів, продовжити? +message.confirmation.password.error = Вказати пароль Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ +message.connecting.please.wait = З'єднуюÑÑ, чекай... +message.connection.failed = Ðеможливо з'єднатиÑÑŒ з {0} +message.create.account = Обліковий Ð·Ð°Ð¿Ð¸Ñ Ð½Ðµ може бути Ñтворено +message.create.or.join.room = Створити або долучитиÑÑŒ до конференції +message.current.status = Дозволити іншим знати мій ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ‡Ð¸ активніÑть +message.default.error = ВиÑвлено помилку +message.delete.all.history = Вилучити вÑÑ– попередні розмови? +message.delete.confirmation = Впевнено вилучаєш {0}? +message.disable.transport = Вилучити облікову інформацію з {0}? +message.disconnected.conflict.error = З'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ñ€Ð¾Ð·Ñ–Ñ€Ð²Ð°Ð½Ðµ через вхід цього ж кориÑтувача з іншого міÑÑ†Ñ +message.disconnected.error = З'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ñ€Ð¾Ð·Ñ–Ñ€Ð²Ð°Ð½Ð¾ через помилку +message.disconnected.group.chat.error = З'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ñ€Ð¾Ð·Ñ–Ñ€Ð²Ð°Ð½Ð¾ через помилку, Spark автоматично приєднаєтьÑÑ Ð´Ð¾ каналу піÑÐ»Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ +message.disconnected.shutdown = З'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ñ€Ð¾Ð·Ñ–Ñ€Ð²Ð°Ð½Ðµ через те, що Ñервер вимкнений +message.downloading = ЗавантажуєтьÑÑ {0} +message.downloading.spark.plug = ЗавантажуєтьÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¾Ðº Spark +message.end.chat = Закінчити цю розмову? +message.end.conversation = Закінчити цю ÑеÑÑ–ÑŽ? +message.enter.broadcast.message = Введи Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ‚Ñ€Ð°Ð½ÑÐ»ÑŽÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¸Ð¼ кориÑтувачам +message.enter.facebook = Введи ім'Ñ Ñ– пароль Facebook внизу +message.enter.gadugadu = Введи ім'Ñ Ñ– пароль GaduGadu внизу +message.enter.irc = Введи ім'Ñ Ñ– пароль IRC внизу +message.enter.jabber.id = Введи Jabber-ідентифікатор +message.enter.message.to.broadcast = Введи Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ‚Ñ€Ð°Ð½ÑÐ»ÑŽÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾ вÑьому ÑпиÑку +message.enter.myspace = Введи ім'Ñ Ñ– пароль MySpace внизу +message.enter.new.subject = Введи нову тему +message.enter.qq = Введи номер Ñ– пароль QQ внизу +message.enter.room.password = Введи пароль кімнати +message.enter.sametime = Введи ім'Ñ Ñ– пароль Sametime внизу +message.enter.simple = Введи ім'Ñ Ñ– пароль SIMPLE внизу +message.enter.valid.jid = Введи дійÑний Jabber-ідентифікатор +message.enter.xmpp = Введи ім'Ñ Ñ– пароль XMPP внизу +message.error.during.file.transfer = Помилка Ð¿Ñ–Ð´Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ñ– файлу +message.error.must.use.reserved.nick = Ти муÑиш викориÑтовувати зарезервований пÑевдонім кімнати. +message.error.nickname.in.use = Бажаний пÑевдонім уже викориÑтовуєтьÑÑ Ð°Ð±Ð¾ зарезервований кимоÑÑŒ іншим. +message.error.no.permission.create.room = Ти не маєш прав Ñтворювати кімнату. +message.error.no.response = Сервер не відповідає. +message.error.not.member = Ти не Ñ” членом цієї кімнати.\r\nÐ¦Ñ ÐºÑ–Ð¼Ð½Ð°Ñ‚Ð° вимагає членÑтва Ð´Ð»Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ. +message.error.room.not.exist = Кімнати, в Ñку ти намагаєшÑÑ Ð·Ð°Ð¹Ñ‚Ð¸, не Ñ–Ñнує. +message.error.room.password.incorrect = Пароль не Ñпівпадає з паролем кімнвти. +message.error.unable.join.room = Ðеможливо приєднатиÑÑŒ до кімнати. +message.file.exists.question = Файл вже Ñ–Ñнує, перезапиÑати? +message.file.size = Розмір файлу: {0} +message.file.transfer.canceled = Ти ÑкаÑував передачу файла +message.file.transfer.chat.window = Запит передачі файлу: +message.file.transfer.direrror.setdir = ÐатиÑни тут, щоб змінити теку +message.file.transfer.dirnull = Ðеправильна тека Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ñ– файлу +message.file.transfer.file.too.big.error = Вибраний файл надто великий.\nМакÑимально можливий розмір {0}; вибраний файл має {1} +message.file.transfer.file.too.big.warning = Вибраний файл надто великий.\nПродовжити вÑе одно? +message.file.transfer.nodir = Тека Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ñ– файлу не Ñ–Ñнує +message.file.transfer.notification = Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ передачу даних +message.file.transfer.rejected = Передача файлу не прийнÑта {0} +message.file.transfer.short.message = надÑилає тобі файл: +message.find.conference.services = Знайти Ñлужби конференцій +message.forbidden.error = Отримано заборону від Ñервера +message.gateway.nickname.error = Потрібно ввеÑти пÑевдонім +message.gateway.password.error = Потрібно ввеÑти пароль +message.gateway.username.error = Потрібно ввеÑти ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача +message.general.error = Зв'Ñзок із Ñервером розірвано через {0} +message.generic.reconnect.message = Зв'Ñзок із Ñервером розірвано, щоб під'єднатиÑÑŒ знову, натиÑни кнопку Ð¿ÐµÑ€ÐµÐ¿Ñ–Ð´Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð²Ð½Ð¸Ð·Ñƒ +message.groupchat.registered.member = УÑпішно зареєÑтровано {0} +message.groupchat.require.password = Ð”Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ в цю кімнату необхідно ввеÑти пароль +message.idle.for = Ðеактивний {0} +message.image.small.resolution = Розмір Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¼ÐµÐ½ÑˆÐ¸Ð¹, ніж 32x32 крапок +message.invalid.jabber.id = Хибний Jabber-ідентифікатор +message.invalid.jid.error = Вказаний JID неправильний +message.invalid.status = Вкажи правильний ÑÑ‚Ð°Ñ‚ÑƒÑ +message.invalid.username.password = Хибне ім'Ñ Ñ‡Ð¸ пароль +message.invite.to.groupchat = {0} запрошує тебе до групи +message.invite.users.to.conference = ЗапроÑити кориÑтувачів до конференції +message.is.shared.group = {0} запроÑив до групи +message.is.typing.a.message = {0} пише повідомленнÑ... +message.join.conference.room = ПриєднатиÑÑ Ð´Ð¾ групи +message.kicked.error = Ти не можеш викидати {0} з цієї кімнати +message.last.message.received = ОÑтаннє Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð¾ {0} +message.loading.please.wait = ЗавантажуєтьÑÑ... +message.locked.workstation = КориÑтувач заблокував Ñвою робочу Ñтанцію +message.name.of.group = Ðазва групи +message.name.of.search.service.question = Ðазва пошукового ÑервіÑу? +message.negotiate.file.transfer = Підготовка передачі файлів, зачекай... +message.negotiate.stream = Підготовка потоку з'єднаннÑ, зачекай... +message.negotiation.file.transfer = Підготовка до передачі файлів з {0}, зачекай... +message.new.message = Ðове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ {0} +message.new.spark.available = {0} доÑтупний, вÑтановити? +message.nickname.in.use = ПÑевдонім уже викориÑтано, будь лаÑка, вкажи інший +message.nickname.not.acceptable = МожливіÑть зміни пÑевдоніма вимкнена! +message.no.avatar.found = КориÑтувач не налаштував значок +message.no.caller.id = ÐедоÑтупний ідентифікатор абонента +message.no.description.available = Ðема опиÑу +message.no.history.found = Ðема попередніх розмов з цим кориÑтувачем +message.no.results.found = Пошук на Ñервері був безрезультатним +message.no.room.to.join.error = Ðема кімнат Ð´Ð»Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ +message.no.subject.available = Ðема теми +message.no.updates = Ðема оновлень +message.normal = Звичайне Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ +message.number.to.call = Вкажи номер, щоб зателефонувати +message.offline = КориÑтувач не в мережі, він отримає повідомленнÑ, коли з'ÑвитьÑÑ +message.offline.error = Цей кориÑтувач не може отримувати офлайнові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ +message.participants.in.room = УчаÑників у кімнаті +message.password.error = Вкажи пароль Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ облікового запиÑу +message.password.private.room.error = Вкажи пароль до приватної кімнати +message.passwords.no.match = Пароль не Ñпівпадає +message.please.join.in.conference = Прийміть мене до групи +message.plugins.not.available = Ðеможливо з'єднатиÑÑŒ з репозиторієм додатків +message.prompt.plugin.uninstall = Впевнений, що хочеш деактивувати {0}? +message.received.file = Ти отримав файл від {0} +message.receiving.file = Ти отримуєш файл від {0} +message.reconnect.attempting = Спроба... +message.reconnect.failed = Повторне з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð½ÐµÐ²Ð´Ð°Ð»Ðµ +message.reconnect.wait = Повторне з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· {0} Ñекунд +message.register.transports = ЗареєÑтруватиÑÑŒ через доÑтупний транÑпорт +message.registering = РеєÑтруєтьÑÑ {0}, зачекай... +message.registration.transport.failed = Ðеможливо зареєÑтруватиÑÑ Ñ‡ÐµÑ€ÐµÐ· шлюз +message.restart.required = Потрібно перезапуÑтити Spark, щоб актуалізувати зміни. Зробити це зараз? +message.restart.spark = Потрібно перезапуÑтити програму, щоби \n вÑтановити нову верÑÑ–ÑŽ. Зробити це зараз? +message.restart.spark.changes = Додаток буде вилучено піÑÐ»Ñ Ð½Ð°Ñтупного запуÑку Spark'а +message.restart.spark.to.install = Потрібно перезапуÑтити програму, щоби вÑтановити нову верÑÑ–ÑŽ. Зробити це зараз? +message.room.creation.error = Кімната не може бути Ñтворена +message.room.destroyed = Кімнату знищено через: {0} +message.room.destruction.reason = Причина Ð·Ð½Ð¸Ñ‰ÐµÐ½Ð½Ñ ÐºÑ–Ð¼Ð½Ð°Ñ‚Ð¸? +message.room.information.for = Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ кімнату {0} +message.save.profile = ÐатиÑни "зберегти" Ð´Ð»Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ +message.search.for.contacts = Пошук контактів +message.search.for.history = Пошук минулих розмов +message.search.for.other.people = Пошук людей на Ñервері +message.search.input.short = Будь лаÑка, задай щонайменше дві літери. +message.search.page.counter = Поточний номер Ñторінки Ñ– кількіÑть уÑÑ–Ñ… Ñторінок +message.search.page.left = на одну Ñторінку назад +message.search.page.right = на одну Ñторінку вперед +message.search.page.timeperiod = Вибери проміжок чаÑу Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ +message.search.period.day.one = один день на Ñторінку +message.search.period.week.one = one week per page +message.search.period.month.one = один тиждень на Ñторінку +message.search.period.none = вÑÑ– на одній Ñторінці +message.search.period.year.one = один рік на Ñторінку +message.search.service.not.available = Ðеможливо з'єднатиÑÑŒ з пошукового Ñлужбою +message.searching.please.wait = Шукаю... +message.select.add.room.to.add = Вибери кімнату, щоб додати до Ñвого ÑпиÑку Ñлужб +message.select.one.or.more = Вибери одного чи більше кориÑтувачів зі ÑпиÑку +message.select.room.to.enter = Вкажи кімнату Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ +message.select.room.to.join = Вибери кімнату, щоб приєднатиÑÑŒ +message.send.a.broadcast = ТранÑлювати +message.send.file.to.user = ÐадіÑлати файли цьому кориÑтувачу +message.send.picture = Захопити Ñ– надіÑлати знімок екрану +message.send.to.these.people = ÐадіÑлати цим людÑм +message.sending.file.to = ÐадÑÐ¸Ð»Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ до {0} +message.sent.offline.files = Ти щойно надіÑлав файл(и). +message.server.unavailable = Ðеможливо з'єднатиÑÑŒ із Ñервером: Ñервер недоÑтупний або хибне ім'Ñ +message.service.already.exists = Служба вже Ñ” в ÑпиÑку +message.shared.group = Спільна група +message.specify.contact.jid = Вкажи JID (наприклад, ddman@jabber.org) +message.specify.group = Вкажи групу, щоб додати кориÑтувача +message.specify.information.for.conference = Вкажи інформацію Ð´Ð»Ñ ÐºÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ñ–Ñ— +message.specify.name.error = Вкажи правильне ім'Ñ +message.specify.users.to.join.conference = Вкажи кориÑтувачів, щоб приєднати до конференції +message.specify.valid.time.error = Вкажи правильний таймаут Ñ– порт +message.subject.change.error = Тобі не дозволено змінювати тему цієї кімнати +message.subject.has.been.changed.to = {1} змінив тему на "{0}" +message.supply.resource = Вкажи правильне джерело +message.supply.valid.port = Вкажи правильний порт +message.supply.valid.timeout = Вкажи правильне Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‚Ð°Ð¹Ð¼Ð°ÑƒÑ‚Ñƒ +message.timeout.error = Таймаут має бути не менший від 5 Ñекунд +message.total.downloaded = Завантажено вÑього +message.transfer.cancelled = Файлова передача ÑкаÑована +message.transfer.complete = Передачу було завершено ({0}) +message.transfer.progressbar.text.received = {0} отримано @ {1} {2} +message.transfer.progressbar.text.sent = {0} надіÑлано @ {1} {2} +message.transfer.rate = ШвидкіÑть передачі +message.transfer.refused = У передачі файлів відмовлено +message.transfer.waiting.on.user = ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° {0} Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð¹Ð½ÑÑ‚Ñ‚Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ñ– файлів +message.unable.to.load.profile = Ðеможливо знайти профіль Ð´Ð»Ñ {0} +message.unable.to.retrieve.last.activity = Ðеможливо визначити оÑтанню активніÑть Ð´Ð»Ñ {0} +message.unable.to.save.password = Ðеможливо змінити пароль, зверниÑÑŒ до адмініÑтратора Ñервера +message.unable.to.send.file = Ðеможливо надіÑлати файл до {0} +message.unable.to.use.hostname.as.resource = Ðеможливо викориÑтати ім'Ñ Ð²ÑƒÐ·Ð»Ð° Ñк джерело +message.unrecoverable.error = Ðевідома помилка з'єднаннÑ. ПереглÑнь протоколи Ð´Ð»Ñ Ð´Ð¾ÐºÐ»Ð°Ð´Ð½Ñ–ÑˆÐ¾Ñ— інформації. +message.update.room.list = ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÑпиÑку кімнат +message.updating.cancelled = ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÑкаÑоване +message.user.banned = {0} забанений. Причина: {1} +message.user.given.voice = {0} отримав право голоÑу в цій кімнаті +message.user.granted.admin = {0} отримав адмініÑтративні привілеї +message.user.granted.membership = {0} Ñтав учаÑником +message.user.granted.moderator = {0} отримав права модератора +message.user.granted.owner = {0} отримав права влаÑника +message.user.is.sending.you.a.file = {0} надÑилає тобі файл +message.user.joined.room = {0} ввійшов до кімнати +message.user.kicked.from.room = УчаÑника {0} викинув з кімнати {1}. Причина: {2} +message.user.left.room = {0} залишив кімнату +message.user.nickname.changed = {0} відомий Ñк {1} +message.user.now.available.to.chat = {0} на зв'Ñзку з {1} +message.user.revoked.admin = Права адміна відкликані у {0} +message.user.revoked.membership = УчаÑть {0} була відкликана +message.user.revoked.moderator = Права модератора відкликані у {0} +message.user.revoked.owner = Права влаÑника відкликані у {0} +message.user.voice.revoked = Право голоÑу були відкликані у {0} +message.username.error = Вкажи ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача Ð´Ð»Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу +message.username.password.error = Потрібно вказати ім'Ñ Ñ–/чи пароль +message.vcard.not.supported = Сервер не підтримує VCard, неможливо зберегти твою VCard +message.version = ВерÑÑ–Ñ: {0} +message.view.information.about.this.user = ПереглÑд інформації про цього кориÑтувача +message.waiting.for.user.to.join = ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ {0} +message.went.offline = {0} розірвав зв'Ñзок з {1} +message.you.have.been.banned = Тебе забанили +message.you.have.been.kicked = Тебе викинули з цієї кімнати +message.you.have.sent = Ти надіÑлав файл до {0} +message.your.admin.granted = Тобі надано адмініÑтративні привілеї +message.your.banned = Тебе забанили +message.your.kicked = Тебе викинув {0} +message.your.membership.granted = Тобі надано права учаÑника +message.your.membership.revoked = Права учаÑника відкликано +message.your.moderator.granted = Тобі надано права модератора +message.your.moderator.revoked = Права модератора відкликано +message.your.ownership.granted = Тобі надано права влаÑника +message.your.ownership.revoked = Права влаÑника відкликано +message.your.revoked.granted = Права адміна відкликано +message.your.voice.granted = Тобі надано право голоÑу в розмові +message.your.voice.revoked = Право голоÑу у Тебе відкликано + +no = ÐÑ– + +not.registered = Ðе зареєÑтровано + +occupants = Мешканець + +offline = Ðе в мережі + +ok = Гаразд + +online = Ð’ мережі + +open = Відкрити + +open.folder = Відкрити теку + +participants = УчаÑник + +paused = {0} переÑтав пиÑати + +privacy.tooltip.preferences = ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¾Ñті Spark + +privacy.border.block = Блок +privacy.border.information = Інфо приватноÑті +privacy.button.no.list.selected = СпиÑок не вибраний +privacy.dialog.add.list = Введи назву ÑпиÑку +privacy.dialog.rem.list = Справді хочеш вилучити {0}? +privacy.label.information = ВикориÑтовуй контекÑтне меню Ð´Ð»Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ, Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ ÑпиÑків та елементів +privacy.label.iq.desc = Запит +privacy.label.list.is.active = Ðктивний ÑпиÑок: +privacy.label.list.is.default = Стандарний ÑпиÑок: +privacy.label.msg.desc = ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ +privacy.label.not.supported = Сервер не підтримує приватні ÑпиÑки. +privacy.label.pin.desc = ПриÑутніÑть в +privacy.label.pout.desc = ПриÑутніÑть за межами +privacy.label.preferences = Додаток Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¾Ñті +privacy.menu.activate.list = Ðктивувати +privacy.menu.add.contacts = Додати контакти до ÑпиÑку +privacy.menu.add.groups = Додати групи до ÑпиÑку +privacy.menu.add.list = Додати ÑпиÑок +privacy.menu.add.rem.items = Вилучити {0} зі ÑпиÑку +privacy.menu.default.list = Ð’Ñтановити Ñк Ñтандартний +privacy.menu.remove = Вилучити +privacy.menu.remove.list = Вилучити ÑпиÑок +privacy.menuitem.deactivate.current.list = Деактивувати {0} +privacy.name.for.default.list = Стандарт +privacy.node.contacts = Контакти +privacy.node.groups = Групи +privacy.pick.one.or.more = Додати кілька об'єктів до ÑпиÑку +privacy.root.node = СпиÑки приватноÑті +privacy.status.menu.entry = Приватні ÑпиÑки +privacy.title.add.picker = Додати до ÑпиÑку +privacy.title.panel = ВикориÑтовуй праву кнопку маніпулÑтора +##ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¾Ñті +privacy.title.preferences = ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¾Ñті Spark + +radio.encryptionmode.disabled = Вимкнене +radio.encryptionmode.ifpossible = Якщо доÑтупне +radio.encryptionmode.required = Обов'Ñзкове + +refresh = Оновити + +reject = Відхилити + +retry = Повторити + +room.name = Ðазва кімнати + +save = Зберегти + +status.away = Відійшов +status.custom.messages = КлієнтÑькі Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ +status.do.not.disturb = Дайте Ñпокій +status.extended.away = Давно відійшов +status.free.to.chat = Вільний Ð´Ð»Ñ ÑÐ¿Ñ–Ð»ÐºÑƒÐ²Ð°Ð½Ð½Ñ +status.invisible = Прихований +status.offline = Офлайн +status.on.phone = Ðа телефоні +status.online = Ðа зв'Ñзку +status.pending = Ð’ очікуванні + +##Stunfallback in media settings +stun.border.label = ВідÑтупний Ñервер STUN +stun.server.addr = Сервер STUN: +stun.server.port = Порт STUN: + +subject = Тема + +tab.available.plugins = ДоÑтупні додатки +tab.avatar = Значок +tab.business = Ð‘Ñ–Ð·Ð½ÐµÑ +tab.certificates = Сертифікати +tab.conferences = Конференції +tab.contacts = Контакти +tab.deactivated.plugins = Деактивовані додатки +tab.general = Загальне +tab.home = Домівка +tab.installed.plugins = Ð’Ñтановлені додатки +tab.mutual.auth = Можлива Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ +tab.personal = ОÑобиÑте +tab.pki = PKI +tab.proxy = ПрокÑÑ– +tab.security = Безпека +tab.sso = SSO + +table.column.certificate.exempted = Вилучений +table.column.certificate.subject = Предмет +table.column.certificate.validity = ЧинніÑть + +title.about = Про програму +title.account.create.registration = РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу +title.account.created = Обліковий Ð·Ð°Ð¿Ð¸Ñ Ñтворений +title.add.contact = Додати контакт +title.add.contact.group = Додати групу контактів +title.add.new.group = Додати нову групу +title.add.search.service = Додати пошукову Ñлужбу +title.add.to.roster = Додати до ÑпиÑку +title.address = ÐдреÑа +title.advanced.connection.preferences = Додаткові Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð²'Ñзку +title.advanced.connection.sso = ВикориÑÑ‚Ð°Ð½Ð½Ñ Ñ”Ð´Ð¸Ð½Ð¾Ñ— підпиÑки (SSO) +title.advanced.connection.sso.account = ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ облікового запиÑу "{0}" Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ на Ñервер. +title.advanced.connection.sso.noprincipal = Spark не може знайти облікові дані Ð´Ð»Ñ Ð¾Ð´Ð¸Ð½Ð°Ñ€Ð½Ð¾Ñ— підпиÑки (Single Sign-On). Це унеможливлює роботу SSO. +title.advanced.connection.sso.smack3compat = Режим ÑуміÑноÑті Smack 3 +title.advanced.connection.sso.unable = Ðеможливо з'єднатиÑÑŒ, викориÑтовуючи єдиний вхід (Single Sign-On). Перевірте Ñвої облікові дані та Ñерверні налаштуваннÑ. +title.advanced.connection.usesso = ВикориÑÑ‚Ð°Ð½Ð½Ñ Ñ”Ð´Ð¸Ð½Ð¾Ð³Ð¾ входу (Single Sign-On, SSO) через GSSAPI +title.alert = ЗаÑторога +title.appearance = ВиглÑд +title.appearance.preferences = ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ +title.appearance.showVCards = Показати &VCards у ÑпиÑку контактів +title.available.transports = ДоÑтупні транÑпорти +title.bookmarks = Закладки +title.broadcast.history = ІÑÑ‚Ð¾Ñ€Ñ–Ñ Ñ‚Ñ€Ð°Ð½ÑлÑцій +title.broadcast.message = ТранÑÐ»ÑŽÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ +title.browse.conference.services = Вибір Ñлужби конференцій +title.browse.room.service = Вибір конференцій - {0} +title.cancelled = СкаÑовано +title.certificate = Сертифікат +title.change.nickname = Змінити пÑевдонім +title.change.subject = Змінити тему +title.chat = Чат +title.choose.directory = Вибір теки +title.choose.incoming.sound = Вибрати вхідний звук +title.choose.offline.sound = Вибрати звук офлайну +title.choose.outgoing.sound = Вибрати вихідний звук +title.client.logs = Журнали клієнта +title.conference.invitation = Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ конференції +title.conference.rooms = Кімнати конференцій +title.configure.chat.room = ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ +title.configure.room = ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÑ–Ð¼Ð½Ð°Ñ‚Ð¸ +title.confirmation = ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ +title.create.new.account = Створити новий обліковий Ð·Ð°Ð¿Ð¸Ñ +title.create.or.bookmark.room = Створити або заклаÑти кімнату +title.create.room = Створити/приєднатиÑÑŒ +title.create.problem = Ðевдача ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу +title.delete.file = Справді хочеш вилучити цей файл? +title.dial.phone = Телефонувати +title.disable.transport = Вилучити облікові дані +title.download.complete = Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ðµ +title.downloading.im.client = Завантажити клієнта миттєвих повідомлень +title.downloads = Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ +title.edit.custom.message = Ð ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ +title.edit.profile = Ð ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð¾Ð¼Ð¾Ñті профілю +title.enter.reason = Введи причину +title.error = Помилка +title.error.couldnot.open.file = Ðеможливо відрити файл +title.error.delete.file = Ðеможливо вилучити файл +title.error.find.app = Ðеможливо знайти відповідний додаток +title.error.rename.file = Ðеможливо перейменувати файл +title.facebook.registration = Дані облікового запиÑу Facebook +title.file = Файл +title.file.exists = Файл Ñ–Ñнує +title.file.transfer = Передача файлу +title.file.transfer.preferences = ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ñ– файлу +title.filesize = Розмір +title.find.conference.service = Знайти Ñлужбу конференцій +title.find.contacts = Знайти контакти +title.gadugadu.registration = Дані облікового запиÑу GaduGadu +title.general.chat.settings = Загальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ +title.general.media = ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñередовища +title.group.chat = Груповий чат +title.group.chat.settings = ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¾Ð²Ð¾Ð³Ð¾ чату +title.history.for = Минулі розмови з {0} +title.incoming.call = Вхідний дзвінок +title.input.fileexplorer = Введи назву твого файлового оглÑдача: +title.input.newname = Введи нове ім'Ñ: +title.input.openwith = Введи назву додатка Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑтаннÑ: +title.invite.to.conference = ЗапроÑити до конференції +title.irc.registration = Дані обліковго запиÑу IRC +title.jabber.browser = ОглÑдач +title.join.conference.room = ПриєднатиÑÑŒ до конференції +title.last.activity = ОÑÑ‚Ð°Ð½Ð½Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ñ–Ñть +title.login = Вхід +title.login.error = Помилка входу +title.login.no.account = Ðеможливо визначити +title.login.settings = ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ…Ð¾Ð´Ñƒ +title.lookup.profile = Пошук профілю +title.myspace.registration = Дані облікового запиÑу MySpace +title.name = Ім'Ñ +title.new.client.available = ДоÑтупний новий клієнт +title.new.roster.group = Ðова група ÑпиÑку +title.new.version.available = ДоÑтупна нова верÑÑ–Ñ +title.no.updates = Ðема оновлень +title.notes = Ðотатки +title.notification = Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ +title.notifications = Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ +title.occupants = Мешканці +title.on.the.phone = Ðа телефоні +title.password = Пароль +title.password.required = Потрібен пароль +title.passwords.no.match = Підтвердити паролі +title.person.search = Пошук оÑіб +title.plugins = Додатки +title.preferences = ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ +title.profile.information = ВідомоÑті профілю +title.profile.not.found = Профіль не знайдено +title.qq.registration = Дані облікового запиÑу QQ +title.register.account = РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ облікового запиÑу +title.registration.error = Помилка реєÑтрації +title.reminder = ÐÐ°Ð³Ð°Ð´ÑƒÐ²Ð°Ð½Ð½Ñ +title.rename.roster.group = Перейменувати групу ÑпиÑка +title.room.destroyed = Кімнату знищено +title.room.information = Інфо про кімнату +title.roster = СпиÑок +title.sametime.registration = Дані облікового запиÑу Sametime +title.select.file.to.send = Вибери файл(и), щоб надіÑлати +title.set.status.message = Ð’Ñтановити ÑÑ‚Ð°Ñ‚ÑƒÑ +title.simple.registration = Дані облікового запиÑу SIMPLE +title.sound.preferences = ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð²ÑƒÐºÑƒ +title.sounds = Звуки +title.spark.preferences = ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ +title.start.chat = Розпочати чат +title.status.message = Ð¡Ñ‚Ð°Ñ‚ÑƒÑ +title.subscription.request = Запит підпиÑки +title.task.notification = Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ +title.tasks = Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ +title.transports = ТранÑпорти +title.tray.information = Інфо про лоток +title.upgrading.client = ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ»Ñ–Ñ”Ð½Ñ‚Ð° +title.version.and.time = ВерÑÑ–Ñ Ñ– Ñ‡Ð°Ñ +title.view.bookmarks = ПереглÑнути закладки +title.view.profile.for = ПереглÑнути профайл {0} +title.view.room.information = ПреглÑнути інфо кімнати +title.waiting.to.call = ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð·Ð²Ñ–Ð½ÐºÐ° +title.warning = ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ +title.xmpp.registration = Дані облікового запиÑу XMPP + +tooltip.appearance = Змінити виглÑд розмови +tooltip.encryptionmode.disabled = Ð¨Ð¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ðµ, викориÑтовуватимутьÑÑ Ð»Ð¸ÑˆÐµ нешифровані з'єднаннÑ. Якщо Ñервер вимагає шифруваннÑ, то з'єднатиÑÑ Ð½Ðµ вдаÑтьÑÑ. +tooltip.encryptionmode.ifpossible = Якщо ÑˆÐ¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупне, то воно буде викориÑтане. +tooltip.encryptionmode.required = Ð”Ð»Ñ Ð·'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð½ÐµÐ¾Ð±Ñ…Ñ–Ð´Ð½Ðµ шифруваннÑ. Якщо Ñервер не підтримує шифруваннÑ, чи ÑƒÐ·Ð³Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ ÑˆÐ¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ невдалим, з'єднатиÑÑ Ð· Ñервером не вдаÑтьÑÑ. +tooltip.file.transfer = ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ñ– файлів +tooltip.notifications = ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñповіщень про вхідні Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ +tooltip.place.a.call = Виклик цієї оÑоби +tooltip.place.voice.call = Телефонувати до цього кориÑтувача +tooltip.send.email = ÐадіÑлати на е-адреÑу +tooltip.start.chat = Розпочати розмову +tooltip.view.changelog = ПереглÑнути журнал змін +tooltip.view.history = ПереглÑнути минулу беÑіду +tooltip.view.readme = ПереглÑнути readme + +tree.conference.services = Служби конференцій +tree.users.in.room = КориÑтувачі в кімнаті + +unfiled = Ðезаповнено + +use.default = ВикориÑтати Ñтандарт + +user.has.signed.in = зайшов. +user.has.signed.off = вийшов. + +while.offline = Поки не в мережі + +yes = Так diff --git a/core/src/main/resources/i18n/spark_i18n_zh_CN.properties b/core/src/main/resources/i18n/spark_i18n_zh_CN.properties new file mode 100644 index 000000000..e74cbce8a --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_zh_CN.properties @@ -0,0 +1,1125 @@ +## For translation use https://explore.transifex.com/igniterealtime/spark/ +## In property strings that are parameterized, single quotes can be used to +## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. +accept = æŽ¥å— +is.active = 活动 +add = 添加 +administrator = 管ç†å‘˜ +apply = 应用 +available = 空闲 +broadcast = 广播 +cancel = å–æ¶ˆ +delete = 删除 +details = 详情 +close = 关闭 +create = 创建 +date = 日期 +description = æè¿° +from = 从 +invite = 邀请 +join = 加入 +no = å¦ +not.registered = 未注册 +occupants = 使用者 +offline = 离线 +online = 在线 +ok = 确定 +open = 打开 +open.folder = 打开文件夹 +participants = å‚与者 +refresh = 刷新 +reject = æ‹’ç» +retry = é‡è¯• +room.name = 群èŠåç§° +save = ä¿å­˜ +subject = 主题 +unfiled = 我的è”系人 +use.default = 使用默认 +user.has.signed.in = 已登录。 +user.has.signed.off = 已离开 +while.offline = 正离线 +yes = 是 + +action.clear = 清除 +action.copy = å¤åˆ¶ +action.cut = 剪切 +action.paste = 粘贴 +action.print = æ‰“å° +action.save = ä¿å­˜ +action.select.all = 全选 + +button.accept = æŽ¥å— +button.add = 添加(&D) +button.add.a.contact = 添加è”系人 +button.add.bookmark = 添加书签 +button.add.service = 添加æœåŠ¡ +button.add.user = 添加用户 +button.add2 = 添加 +button.advanced = 高级(&V) +button.approve = 批准(&A) +button.bookmark.room = 群èŠä¹¦ç­¾(&B) +button.browse = æµè§ˆ(&B)… +button.browse2 = æµè§ˆâ€¦ +button.browse3 = æµè§ˆâ€¦ +button.cancel = å–æ¶ˆ +button.cert.info = 详情 +button.clear = 清除 +button.close = 关闭 +button.copy.to.clipboard = å¤åˆ¶åˆ°å‰ªè´´æ¿ +button.create.account = åˆ›å»ºè´¦å· +button.create.room = åˆ›å»ºæˆ–åŠ å…¥ç¾¤èŠ +button.decline = æ‹’ç» +button.deny = æ‹’ç» +button.dial.number = æ‹¨å· +button.find = 查找 +button.join = 加入 +button.join.room = åŠ å…¥æ‰€é€‰ç¾¤èŠ +button.login = 登录 +button.new = 添加 +button.profile = 个人资料 +button.quit = 退出 +button.re.detect = 釿–°æ£€æµ‹(&R) +button.reconnect = 釿–°è¿žæŽ¥ +button.reconnect2 = 釿–°è¿žæŽ¥ +button.refresh = 刷新 +button.register = 注册 +button.reject = æ‹’ç» +button.remove.bookmark = 移除书签 +button.roster = è”系人列表 +button.save = ä¿å­˜ +button.save.for.future.use = ä¿å­˜ä»¥å¤‡å°†æ¥ä½¿ç”¨ +button.search = æœç´¢ +button.send = å‘é€ +button.send.email = 电å­é‚®ä»¶ +button.start.chat = èŠå¤© +button.tasks.active = 活动 +button.tasks.all = 所有 +button.unset.file.explorer = å–æ¶ˆè®¾ç½®æ–‡ä»¶æµè§ˆå™¨ +button.update = æ›´æ–° +button.view.notes = 查看笔记 +button.view.profile = 查看完整é…置文件 +button.view.tasklist = 查看任务列表 +button.check.validity = 检查有效性 +button.show.certificate = 显示è¯ä¹¦ +button.delete.saved.passwords = å¿˜è®°æ‰€æœ‰ç™»å½•å¯†ç  + +table.column.certificate.subject = 主题 +table.column.certificate.validity = 有效性 +table.column.certificate.exempted = è±å… + +checkbox.allow.buzz = å…è®¸ç”¨æˆ·å‘æ‚¨å‘é€ä¿¡å·(&B) +checkbox.auto.discover.port = 自动å‘çŽ°ä¸»æœºå’Œç«¯å£ +checkbox.auto.login = 自动登录(&A) +checkbox.login.as.invisible = éšèº«ç™»å½•(&L) +checkbox.login.anonymously = 匿å登录(&M) +checkbox.disable.chat.history = ç¦ç”¨èŠå¤©è®°å½•(&D) +checkbox.sort.asc.history = 按日期å‡åºå¯¹è”系人èŠå¤©è®°å½•ä¸­çš„æ¶ˆæ¯æŽ’åº +checkbox.disable.prev.chat.history = ç¦ç”¨åœ¨èŠå¤©ä¸­æ˜¾ç¤ºä»¥å‰çš„对è¯(&S) +checkbox.enable.emoticons = å¯ç”¨è¡¨æƒ…符å·(&E) +checkbox.graying.out = 空闲è”ç³»äººå˜æ·¡ï¼ˆéœ€è¦é‡å¯ï¼‰ +checkbox.idle.enabled = 空闲已å¯ç”¨(&I) +checkbox.launch.on.startup = éšç³»ç»Ÿå¯åЍ(&L) +checkbox.reconnect.info = æŒ‡å®šé‡æ–°è¿žæŽ¥çš„æ˜¾ç¤ºæ–¹å¼ï¼š +checkbox.reconnect.panel.big = æŒ‰ç…§é¢æ¿æ–¹å¼æ˜¾ç¤º +checkbox.reconnect.panel.small = 按照è”ç³»äººåˆ†ç»„æ–¹å¼æ˜¾ç¤º +checkbox.reconnect.panel.icon = æŒ‰ç…§å›¾æ ‡æ–¹å¼æ˜¾ç¤º +checkbox.notify.user.comes.online = 用户上线时通知(&C) +checkbox.notify.user.goes.offline = 用户离线时通知(&N) +checkbox.notify.typing.systemtray = 在系统托盘中显示输入通知(&S) +checkbox.notify.systemtray = 在系统托盘显示新消æ¯(&M) +checkbox.permanent = ç¾¤èŠæ˜¯æŒä¹…çš„ +checkbox.play.sound.on.invitation = 当收到邀请时播放声音(&I) +checkbox.play.sound.on.new.message = å½“æ”¶åˆ°æ–°æ¶ˆæ¯æ—¶æ’­æ”¾å£°éŸ³(&A) +checkbox.play.sound.on.outgoing.message = 当å‘逿¶ˆæ¯æ—¶æ’­æ”¾å£°éŸ³(&S) +checkbox.play.sound.when.offline = 当用户离线时播放声音(&O) +checkbox.private.room = ç¾¤èŠæ˜¯ç§äººçš„ +checkbox.save.password = ä¿å­˜å¯†ç (&V) +checkbox.show.avatars.in.contactlist = 在è”系人列表中显示头åƒ(&A) +checkbox.show.notifications.in.conference = 在群èŠä¸­æ˜¾ç¤ºé€šçŸ¥(&N) +checkbox.show.time.in.chat.window = 在èŠå¤©çª—壿˜¾ç¤ºæ—¶é—´(&S) +checkbox.show.toaster = 显示 Toast 弹窗(&T) +checkbox.disable.asterisk.toaster = ç¦ç”¨æ‰‹æœº Toast 弹窗 +checkbox.split.chat.window = åœé çª—å£ï¼ˆéœ€è¦é‡å¯ï¼‰ +checkbox.start.in.tray = å¯åŠ¨åŽæ˜¾ç¤ºåˆ°ç³»ç»Ÿæ‰˜ç›˜ä¸­(&S) +checkbox.click.single.tray = å•击系统托盘将 Spark 置于最å‰é¢(需è¦é‡å¯)(&S) +checkbox.tabs.on.top = èŠå¤©æ ‡ç­¾é¡µæ˜¾ç¤ºåœ¨é¡¶éƒ¨(需è¦é‡å¯)(&A) +checkbox.tabs.scroll = 为èŠå¤©æ ‡ç­¾é¡µä½¿ç”¨æ»šåŠ¨ï¼ˆéœ€è¦é‡å¯ï¼‰ +checkbox.use.compression = 使用压缩 +checkbox.use.debugger.on.startup = å¯åŠ¨æ—¶è¿›å…¥è°ƒè¯•æ¨¡å¼ +checkbox.use.proxy.server = ä½¿ç”¨ä»£ç†æœåС噍 +checkbox.use.system.look.and.feel = 使用系统外观(需è¦é‡å¯)(&L) +checkbox.window.to.front = 窗å£ç½®äºŽæœ€å‰é¢(&W) +checkbox.broadcast.hide.offline.user = éšè—离线用户 +checkbox.use.krbconf = 使用 krb5.conf 或 krb5.ini +checkbox.use.krb.dns = 使用 DNS +checkbox.use.specify.below = 说明如下 +checkbox.use.pki.authentication = 使用 PKI èº«ä»½éªŒè¯ +checkbox.transport.tab.setting = 在标签页中显示å¯ç”¨çš„传输(需è¦é‡å¯ï¼‰ +checkbox.conference.tab.setting = åœ¨æ ‡ç­¾é¡µä¸­æ˜¾ç¤ºç¾¤èŠæœåŠ¡ï¼ˆéœ€è¦é‡å¯ï¼‰ +checkbox.use.hostname.as.resource = 使用主机åä½œä¸ºèµ„æº +checkbox.use.version.as.resource = 使用 Spark ç‰ˆæœ¬ä½œä¸ºèµ„æº +checkbox.accept.all.certificates = æŽ¥å—æ‰€æœ‰è¯ä¹¦ï¼ˆè‡ªç­¾å/过期/ä¸å—信任) +checkbox.disable.hostname.verification = ç¦ç”¨è¯ä¹¦ä¸»æœºå验è¯ï¼ˆä¸æŽ¨è) +checkbox.allow.client.side.authentication = å…è®¸å®¢æˆ·ç«¯èº«ä»½éªŒè¯ +checkbox.accept.all = 接å—全部 +checkbox.accept.expired = 接å—过期的 +checkbox.accept.not.valid.yet = 接å—尚未生效 +checkbox.accept.self.signed = 接å—自签å +checkbox.accept.revoked = 接å—已撤销 +checkbox.check.crl = 检查 CRL +checkbox.check.ocsp = 检查 OCSP +checkbox.allow.soft.fail = å…许软故障策略 +checkbox.on.exception.list = 在异常列表 +checkbox.filetransfer.ibb.only = ä»…é™å¸¦å†…å­—èŠ‚æµ +checkbox.filetransfer.autoaccept.presence = è‡ªåŠ¨æŽ¥å—æ¥è‡ªå·²çŸ¥è”系人的文件传输 +checkbox.close.unread.message = å…³é—­çª—å£æ—¶è¯¢é—®æ˜¯å¦æœ‰æœªè¯»æ¶ˆæ¯ +radio.encryptionmode.required = 必需 +radio.encryptionmode.ifpossible = 如果å¯ä»¥ +radio.encryptionmode.disabled = å·²ç¦ç”¨ + +delete.log.permanently = 永久删除日志 +delete.permanently = 永久删除? + +gateway.username.password.error = éœ€è¦æä¾›ç”¨æˆ·åå’Œ/æˆ–å¯†ç  + +group.chat.window.information = èŠå¤©çª—å£ä¿¡æ¯ +group.comma.delimited = 以逗å·éš”å¼€ +group.conferences.found = ç¾¤èŠæœåŠ¡å·²æ‰¾åˆ° +group.connection = 连接 +group.empty = æ­¤ç¾¤èŠæ²¡æœ‰åœ¨çº¿è”系人 +group.general.information = å¸¸è§„ä¿¡æ¯ +group.login.information = ç™»å½•ä¿¡æ¯ +group.notification.options = 通知选项 +group.offline = 离线的分组 +group.search.form = æœç´¢è¡¨å• +group.search.results = æœç´¢ç»“æžœ +group.chat.name.notification = 看到您的å称了… +group.chat.name.match = 群èŠä¸­å·²å‡ºçŽ°æ‚¨çš„å称: +group.send_config.error = å°è¯•ä¿å­˜æ›´æ–°åŽçš„è¡¨å•æ—¶å‘ç”Ÿå¼‚å¸¸ï¼ +group.encryption_mode = åŠ å¯†æ¨¡å¼ + +label.na = ä¸å¯ç”¨ +label.home = 主页 +label.accounts = è´¦å·(&C) +label.add.conference.service = æ·»åŠ ç¾¤èŠæœåŠ¡ +label.add.jid = 添加 JID +label.add.task = 添加任务 +label.auto.login = 自动登录 +label.available.users.in.roster = è”系人列表中的在线用户 +label.avatar = 头åƒï¼š +label.broadcast.history.search.date = æœç´¢æ—¥æœŸï¼ˆå¹´â€“月): +label.cancel = å–æ¶ˆ +label.cell = Cell +label.change.password.to = å°†å¯†ç æ›´æ”¹ä¸º(&P) +label.chatroom.fontsize = 群èŠå­—体大å°(&F): +label.chatroom.maxcurrenthistorysize = 最大当å‰åކå²è®°å½•大å°ï¼š +label.city = 城市 +label.close = 关闭 +label.company = å…¬å¸ +label.confirm.password = 确认密ç (&C) +label.conflict.error = è´¦å·å·²ç™»å½•,无法é‡å¤ç™»å½•。 +label.contact.to.find = 查找è”系人 +label.recent.conversation = æœ€è¿‘çš„å¯¹è¯ +label.frequent.contacts = 常用è”系人 +label.contactlist.avatarsize = è”系人列表头åƒå¤§å°(&S): +label.contactlist.fontsize = è”系人列表字体大å°(&C): +label.country = 国家/地区 +label.create.account = åˆ›å»ºè´¦å· +label.department = 部门 +label.dial = 拨å·ç›˜ +label.display.time = 显示时间: +label.downloads = 下载 +label.due = Due +label.email.address = 电å­é‚®ä»¶åœ°å€ +label.emoticons = 表情符å·(&E) +label.enter.address = è¾“å…¥åœ°å€ +label.enter.group.name = 输入新的组å +label.fax = 传真 +label.find = 查找 +label.first.name = åå­— +label.group = 组 +label.host = 主机 +label.invited.users = å—邀用户 +label.jabber.address = Jabber åœ°å€ +label.jabber.id = Jabber ID +label.jid = JID +label.job.title = èŒç§° +label.last.name = å§“ +label.local.time = 本地时间 +label.message = æ¶ˆæ¯ +label.message.style = æ¶ˆæ¯æ ·å¼ +label.middle.name = 中间å +label.minutes.before.stale.chat = 䏿´»åŠ¨ç¾¤èŠç©ºé—²åˆ†é’Ÿæ•°(&M) +label.mobile = 手机 +label.name = åç§° +label.network = 网络 +label.new.nickname = 新昵称 +label.nickname = 昵称 +label.number = æ•°å­— +label.ok = 确认 +label.old.ssl = 使用 Direct TLS 方法 +label.os = æ“作系统 +label.pager = 传呼机 +label.password = 密ç (&P) +label.passwordreset = é‡ç½®å¯†ç  +label.phone = ç”µè¯ +label.port = ç«¯å£ +label.postal.code = é‚®æ”¿ç¼–ç  +label.presence = åœ¨çº¿çŠ¶æ€ +label.priority = 优先级 +label.protocol = åè®® +label.received = 已收到 +label.rename.to = é‡å‘½å +label.resource = èµ„æº +label.response.timeout = å“应超时(ç§’)(&R) +label.reconnect.delay = 釿–°è¿žæŽ¥å»¶è¿Ÿ(ç§’)(需è¦é‡å¯) +label.room = ç¾¤èŠ +label.room.name = 群èŠåç§° +label.room.topic = 群èŠè¯é¢˜ +label.search = æœç´¢ +label.search.service = æœç´¢æœåŠ¡ +label.seconds = ç§’ +label.server = 域å(&M) +label.server.address = æœåŠ¡å™¨åœ°å€ +label.show = 显示: +label.software = 软件 +label.state.and.province = å·ž/çœ +label.street.address = è¡—é“åœ°å€ +label.time = 时间: {0} +label.time.till.idle = 空闲时间(分钟)(&T) +label.time.till.idlemessage = 空闲自动消æ¯(&E) +label.timeformat = 使用 {0} +label.transfer.download.directory = 下载文件夹(&D): +label.transfer.timeout = 传输超时(分钟)(&T): +label.unable.to.add.contact = 无法添加è”系人 +label.use.default = 使用默认 +label.user.on.public.network = 用户在公共网络上 +label.username = 用户å(&U) +label.version = 版本 +label.web.page = 网页 +label.work = 工作 +label.xmpp.port = XMPP 端å£(&X) +label.krb.realm = 安全域 +label.krb.kdc = KDC +label.which.pki.method = å“ªç§ PKI 方法? +label.choose.file = 选择文件 +label.trust.store.password = å¯ä¿¡å¯†ç å­˜å‚¨ +label.enter.password = è¾“å…¥å¯†ç  +label.move.focus.forwards = å‘å‰ç§»åŠ¨ç„¦ç‚¹ +label.move.focus.backwards = å‘åŽç§»åŠ¨ç„¦ç‚¹ +label.keystore.location = KeyStore ä½ç½® +label.truststore.location = TrustStore ä½ç½® +label.pkcs.library.file = PKCS#11 库文件 +label.x509.certificate = X.509 è¯ä¹¦ +label.apple.keychain = Apple KeyChain +label.add.to.roster = 将用户添加到您的è”系人列表 +label.audio.device = 音频设备(&A) +label.video.device = 视频设备(&V) +label.certificate.version = 版本 +label.certificate.serial.number = åºåˆ—å· +label.certificate.signature.value = ç­¾å值 +label.certificate.signature.algorithm = ç­¾å算法 +label.certificate.issuer = é¢å‘者 +label.certificate.subject = 主题 +label.certificate.not.before = 之剿— æ•ˆ +label.certificate.not.after = ä¹‹åŽæ— æ•ˆ +label.certificate.public.key = 公钥 +label.certificate.public.key.algorithm = 公钥算法 +label.certificate.issuer.unique.id = é¢å‘者唯一 ID +label.certificate.subject.unique.id = 主题唯一 ID +label.certificate.add.certificate.to.truststore = å°†è¯ä¹¦æ·»åŠ åˆ° TrustStore +label.certificate.add.certificate.to.identitystore = å°†è¯ä¹¦æ·»åŠ åˆ° IdentityStore +label.certificate.status = è¯ä¹¦çжæ€ã€‚ + +menuitem.about = 关于 +menuitem.actions = æ“作 +menuitem.bookmarks = 书签 +menuitem.add = 添加 +menuitem.add.as.contact = 作为è”系人添加 +menuitem.add.contact = 添加è”系人 +menuitem.add.contact.group = 添加è”系人分组 +menuitem.add.groupchat.myname = çªå‡ºæ˜¾ç¤ºæˆ‘的昵称(&N) +menuitem.add.groupchat.mytext = çªå‡ºæ˜¾ç¤ºæˆ‘的文本(&H) +menuitem.add.groupchat.popname = æåˆ°æˆ‘的昵称时显示弹窗(&T) +menuitem.add.groupchat.showjoinleavemessage = 显示加入和离开信æ¯(&S) +menuitem.add.groupchat.showrolesinsteadofstatus = 显示èŠå¤©è§’è‰²å›¾æ ‡è€Œä¸æ˜¯åœ¨çº¿çжæ€å›¾æ ‡ +menuitem.add.groupchat.auto.accept.invite = 自动接å—群èŠé‚€è¯·(&A) +menuitem.add.groupchat.random.colors = æ˜µç§°æ˜¾ç¤ºéšæœºé¢œè‰²(&R) +menuitem.affiliation = 从属关系 +menuitem.always.on.top = 始终在最å‰é¢ +menuitem.alert.when.online = 用户上线时显示通知 +menuitem.ban = å°ç¦ +menuitem.ban.user = å°ç¦ç”¨æˆ· +menuitem.block.contact = å±è”½è”系人 +menuitem.block.user = å±è”½ç”¨æˆ· +menuitem.broadcast.to.group = å‘ç»„å¹¿æ’­æ¶ˆæ¯ +menuitem.browse.service = æµè§ˆæœåŠ¡ +menuitem.change.nickname = 更改昵称 +menuitem.change.subject = 更改è¯é¢˜ +menuitem.chat = èŠå¤© +menuitem.check.for.updates = 检查更新(&U) +menuitem.connect = 文件 +menuitem.contacts = è”系人 +menuitem.copy.to = å¤åˆ¶åˆ° +menuitem.delete = 删除 +menuitem.delete.login.information = åˆ é™¤ç™»å½•ä¿¡æ¯ +menuitem.destroy.room = è§£æ•£ç¾¤èŠ +menuitem.dial = æ‹¨å· +menuitem.edit = 编辑 +menuitem.edit.my.profile = 编辑我的个人资料… +menuitem.edit.status.message = 编辑自定义状æ€ä¿¡æ¯â€¦ +menuitem.enter.login.information = è¾“å…¥ç™»å½•ä¿¡æ¯ +menuitem.exit = 退出 +menuitem.grant.moderator = 授予主æŒäºº +menuitem.grant.member = 授予æˆå‘˜ +menuitem.grant.admin = 授予管ç†å‘˜ +menuitem.grant.owner = 授予所有者 +menuitem.grant.voice = 授予å‘è¨€æƒ +menuitem.help = 帮助 +menuitem.hide = éšè— +menuitem.invite.group.to.conference = é‚€è¯·ç»„åŠ å…¥ç¾¤èŠ +menuitem.invite.users = 邀请用户 +menuitem.join.on.startup = 系统å¯åŠ¨æ—¶åŠ å…¥ +menuitem.join.room = åŠ å…¥æ‰€é€‰ç¾¤èŠ +menuitem.kick.user = 踢出用户 +menuitem.languages = 语言 +menuitem.logout.no.status = 登出 +menuitem.logout.with.status = 登出的原因 +menuitem.lookup.profile = 查看个人资料… +menuitem.move.to = 移动到 +menuitem.online.help = 在线帮助 +menuitem.open = 打开 +menuitem.open.with = 打开方å¼â€¦ +menuitem.plugins = æ’ä»¶ +menuitem.preferences = 首选项 +menuitem.remove = 移除 +menuitem.remove.alert.when.online = 移除通知 +menuitem.remove.bookmark = 移除书签 +menuitem.remove.from.group = 从组中移除 +menuitem.remove.from.roster = 从è”系人列表移除 +menuitem.unblock.contact = 解除å±è”½è”系人 +menuitem.remove.service = 移除æœåŠ¡ +menuitem.rename = é‡å‘½å +menuitem.revoke.moderator = 撤销主æŒäºº +menuitem.revoke.voice = 撤销å‘è¨€æƒ +menuitem.revoke.member = 撤销æˆå‘˜ +menuitem.revoke.admin = 撤销管ç†å‘˜ +menuitem.revoke.owner = 撤销所有者 +menuitem.save = ä¿å­˜ +menuitem.save.as = å¦å­˜ä¸ºâ€¦ +menuitem.send.a.file = å‘逿–‡ä»¶ +menuitem.send.a.message = 呿‰€é€‰ç”¨æˆ·å‘é€å¹¿æ’­â€¦ +menuitem.set.status.message = 设置状æ€ä¿¡æ¯â€¦ +menuitem.show.empty.groups = 显示空组 +menuitem.show.offline.group = 对离线用户分组 +menuitem.show.traffic = 显示æµé‡çª—å£ +menuitem.sign.in = 登录 +menuitem.sign.in.at.login = 登录 +menuitem.sign.out = 登出 +menuitem.start.a.chat = 开始èŠå¤© +menuitem.start.a.conference = 开始群èŠâ€¦ +menuitem.status = çŠ¶æ€ +menuitem.subscribe.to = 订阅 +menuitem.unban = è§£ç¦å½“å‰åˆ—表中的用户 +menuitem.unblock.user = 解除å±è”½å½“å‰åˆ—表中的用户 +menuitem.user.guide = 用户手册 +menuitem.view.client.version = 查看客户端版本 +menuitem.view.contact.history = 查看èŠå¤©è®°å½• +menuitem.view.downloads = 查看下载 +menuitem.view.last.activity = æŸ¥çœ‹æœ€åŽæ´»åЍ +menuitem.view.logs = 查看日志 +menuitem.view.profile = 查看个人资料 +menuitem.view.room.info = 查看群èŠä¿¡æ¯ +menuitem.voice = 声音 +menuitem.show.offline.users = 显示离线用户 +menuitem.show.contact.statusmessage = 显示状æ€ä¿¡æ¯ +menuitem.bookmark.room = 群èŠä¹¦ç­¾ +menuitem.refresh = 刷新 +menuitem.create.room = åˆ›å»ºæˆ–åŠ å…¥ç¾¤èŠ +menuitem.expand.all.groups = 展开所有组 +menuitem.collapse.all.groups = æŠ˜å æ‰€æœ‰ç»„ +menuitem.invite.again = 冿¬¡é‚€è¯· +menuitem.chatframe.option = 选项 +menuitem.add.groupchat.invitetobookmark = è‡ªåŠ¨é‚€è¯·ç”¨æˆ·åŠ å…¥ä¹¦ç­¾ä¸­çš„ç¾¤èŠ +menuitem.certificate.files.filter = è¯ä¹¦æ–‡ä»¶ (*.cer), (*.crt), (*.der) + +message = æ¶ˆæ¯ +message.account.create = åˆ›å»ºæ–°è´¦å· +message.account.created = å·²åˆ›å»ºæ–°è´¦å· +message.account.error = 请指定创建账å·çš„æœåŠ¡å™¨ +message.add.a.contact = 添加è”系人 +message.add.conference.service = æ·»åŠ ç¾¤èŠæœåŠ¡ +message.add.contact.to.list = 添加用户到您的è”系人列表 +message.add.favorite.room = å°†ç¾¤èŠæ·»åŠ åˆ°æ”¶è—列表或直接加入 +message.add.this.user.to.your.roster = 将此用户添加到好å‹åˆ—表 +message.add.to.roster = 添加到è”系人列表 +message.add.user = 是å¦å°†ç”¨æˆ·æ·»åŠ åˆ°æ‚¨çš„è”系人列表? +message.alert.notify = 通知 +message.already.exists = è´¦å·å·²å­˜åœ¨ï¼Œè¯·å°è¯•其他用户å +message.create.account.not.allowed = ä¸å…许在æœåŠ¡å™¨ä¸Šåˆ›å»ºè´¦å· +message.approve.subscription = 是å¦å…许 {0} 将您添加到他们的è”系人列表? +message.authenticating = æ­£åœ¨éªŒè¯ +message.away.idle = 因闲置而离开 +message.bookmark.temporary.room.error = æ— æ³•å°†ä¸´æ—¶ç¾¤èŠæ·»åŠ ä¸ºä¹¦ç­¾ +message.broadcast.from = 广播æ¥è‡ª {0} +message.broadcast.no.user.selected = è¯·è‡³å°‘é€‰æ‹©ä¸€åæŽ¥æ”¶è€… +message.broadcast.no.text = 请输入广播的文字 +message.broadcast.message.sent = å‘é€äº†å¹¿æ’­æ¶ˆæ¯ +message.broadcast.to = 输入è¦å¹¿æ’­åˆ° {0} çš„æ¶ˆæ¯ +message.hasbeenbroadcast.to = 已广播消æ¯ç»™ä»¥ä¸‹ç”¨æˆ·ï¼š\n{0} +message.buzz.alert.notification = å¼•èµ·ç”¨æˆ·æ³¨æ„ +message.buzz.message = {0} 想è¦å¼•èµ·æ‚¨çš„æ³¨æ„ +message.buzz.sent = è¯·æ±‚ç”¨æˆ·æ³¨æ„ +message.calling = æ­£åœ¨å‘¼å« {0} +message.came.online = {0} 上线于 {1} +message.cannot.add.contact.to.shared.group = 无法将新è”系人添加到共有的组 +message.cert.hostname.verification.failed = è¯ä¹¦ä¸»æœºå验è¯å¤±è´¥ +message.cert.verification.failed = 无法验è¯è¯ä¹¦ +message.chat.session.ended = èŠå¤©ä¼šè¯å·²äºŽ {0} ç»“æŸ +message.click.to.open = å•击打开 +message.client.information = {0} çš„å®¢æˆ·ç«¯ä¿¡æ¯ +message.close.other.chats = 关闭所有其他èŠå¤© +message.close.stale.chats = 关闭䏿´»åŠ¨çš„èŠå¤© +message.close.this.chat = 关闭此èŠå¤© +message.close.unread.window = 您有未读消æ¯ï¼Œæ˜¯å¦ç¡®å®šè¦å…³é—­çª—å£ï¼Ÿ +message.conference.info.error = 无法检索群èŠä¿¡æ¯ï¼Œè¯·ç¨åŽå†è¯• +message.conference.service.error = 找ä¸åˆ°ç¾¤èŠæœåŠ¡ +message.confirm.destruction.of.room = 解散群èŠä¼šå°†æ‰€æœ‰ç”¨æˆ·ä»Žç¾¤èŠä¸­ç§»é™¤ï¼Œæ˜¯å¦ç»§ç»­ï¼Ÿ +message.confirmation.password.error = æŒ‡å®šç¡®è®¤å¯†ç  +message.connecting.please.wait = 正在连接,请ç¨å€™â€¦ +message.connection.failed = 无法连接到 {0} +message.create.account = æ— æ³•åˆ›å»ºè´¦å· +message.create.or.join.room = åˆ›å»ºæˆ–åŠ å…¥ç¾¤èŠ +message.current.status = è®©åˆ«äººçŸ¥é“æ‚¨çš„当å‰çŠ¶æ€æˆ–活动 +message.default.error = 检测到错误 +message.delete.all.history = 是å¦åˆ é™¤ä»¥å‰çš„æ‰€æœ‰å¯¹è¯ï¼Ÿ +message.delete.confirmation = 是å¦ç¡®å®šè¦åˆ é™¤ {0}? +message.disable.transport = 是å¦ä»Ž {0} 中移除登录信æ¯ï¼Ÿ +message.disconnected.conflict.error = 由于从其他ä½ç½®ç™»å½•,您的连接已关闭 +message.disconnected.error = 由于错误,您的连接已关闭 +message.disconnected.group.chat.error = æ‚¨çš„è¿žæŽ¥å› é”™è¯¯è€Œå…³é—­ï¼Œé‡æ–°è¿žæŽ¥æˆåŠŸåŽï¼ŒSpark å°†è‡ªåŠ¨é‡æ–°åŠ å…¥ç¾¤èŠ +message.disconnected.shutdown = 您的连接已关闭,因为æœåС噍已关闭 +message.downloading = 正在下载 {0} +message.downloading.spark.plug = 正在下载 Spark æ’ä»¶ +message.end.chat = 是å¦è¦ç»“æŸæ­¤èŠå¤©ï¼Ÿ +message.end.conversation = 是å¦è¦ç»“æŸæ­¤ä¼šè¯ï¼Ÿ +message.enter.broadcast.message = 输入è¦å¹¿æ’­ç»™æ‰€é€‰ç”¨æˆ·çš„æ¶ˆæ¯ +message.enter.gadugadu = 在下方输入您的 GaduGadu 用户åå’Œå¯†ç  +message.enter.irc = 在下方输入您的 IRC 用户åã€å¯†ç å’Œæ˜µç§° +message.enter.sametime = 在下方输入您的 Sametime 用户åå’Œå¯†ç  +message.enter.facebook = 在下方输入您的 Facebook 用户åå’Œå¯†ç  +message.enter.myspace = 在下方输入您的 MySpace 用户åå’Œå¯†ç  +message.enter.jabber.id = 输入 Jabber ID +message.enter.message.to.broadcast = 输入è¦å¹¿æ’­åˆ°æ‚¨çš„æ•´ä¸ªè”ç³»äººåˆ—è¡¨çš„æ¶ˆæ¯ +message.enter.new.subject = 输入新的主题 +message.enter.qq = 在下方输入您的 QQ å·ç å’Œå¯†ç  +message.enter.room.password = 输入群èŠå¯†ç  +message.enter.simple = 在下方输入您的 SIMPLE 用户åå’Œå¯†ç  +message.enter.valid.jid = 请输入有效的 Jabber ID +message.enter.xmpp = 在下方输入您的 XMPP 用户åå’Œå¯†ç  +message.error.during.file.transfer = 文件传输过程中出错 +message.error.must.use.reserved.nick = æ‚¨å¿…é¡»ä½¿ç”¨æ‚¨é¢„ç•™çš„ç¾¤èŠæ˜µç§°ã€‚ +message.error.nickname.in.use = 您想è¦çš„æ˜µç§°æ­£åœ¨ä½¿ç”¨æˆ–已被其他人ä¿ç•™ã€‚ +message.error.no.permission.create.room = 您没有创建群èŠçš„æƒé™ +message.error.no.response = æœåŠ¡å™¨æ²¡æœ‰å“应。 +message.error.not.member = æ‚¨ä¸æ˜¯æ­¤ç¾¤èŠçš„æˆå‘˜ï¼Œæ­¤ç¾¤èŠè¦æ±‚ä»…æˆå‘˜å¯åŠ å…¥ã€‚ +message.error.room.not.exist = 您å°è¯•进入的群èŠä¸å­˜åœ¨ã€‚ +message.error.room.password.incorrect = 密ç ä¸Žç¾¤èŠå¯†ç ä¸åŒ¹é…。 +message.error.unable.join.room = 无法加入群èŠã€‚ +message.file.exists.question = 文件已存在,是å¦è¦†ç›–? +message.file.size = 文件大å°ï¼š{0} +message.file.transfer.canceled = æ‚¨å–æ¶ˆäº†æ–‡ä»¶ä¼ è¾“ +message.file.transfer.rejected = {0} æœªæŽ¥å—æ–‡ä»¶ä¼ è¾“ +message.file.transfer.dirnull = 用于文件传输的下载文件夹无效 +message.file.transfer.nodir = 用于文件传输的下载文件夹ä¸å­˜åœ¨ +message.file.transfer.cantwritedir = 无法写入文件夹进行文件传输 +message.file.transfer.notification = 文件传输通知 +message.file.transfer.short.message = æ­£åœ¨å‘æ‚¨å‘逿–‡ä»¶ï¼š +message.file.transfer.chat.window = 文件传输请求: +message.file.transfer.file.too.big.error = 所选文件太大。\n最大文件大å°ä¸º {0} 所选文件为 {1} +message.file.transfer.file.too.big.warning = 所选文件太大。\n是å¦ç»§ç»­ï¼Ÿ +message.file.transfer.direrror.setdir = å•击此处更改文件夹 +message.file.transfer.history.request.sent = 传输文件“{0}â€({1}) 的请求已å‘é€ç»™ {2}。 +message.file.transfer.history.send.complete = 文件“{0}â€å·²æˆåŠŸå‘é€ç»™ {1}。 +message.file.transfer.history.send.error = å‘逿–‡ä»¶"{0}"ç»™{1}失败。 +message.file.transfer.history.send.canceled = 已喿¶ˆå°†æ–‡ä»¶â€œ{0}â€å‘é€ç»™ {1}。 +message.file.transfer.history.contact.rejected = {1} æ‹’ç»äº†æ–‡ä»¶â€œ{0}â€çš„传输请求。 +message.file.transfer.history.request.received = 已从 {2} 收到对传输文件“{0}â€({1}) 的请求。 +message.file.transfer.history.you.rejected = 您拒ç»äº†æ¥è‡ª {1} 的文件“{0}â€çš„传输请求。 +message.file.transfer.history.you.accepted = 您接å—了æ¥è‡ª {1} 的文件“{0}â€çš„传输请求。 +message.file.transfer.history.receive.success = å·²æˆåŠŸä»Ž {1} 接收到文件“{0}â€ã€‚ +message.file.transfer.history.receive.failed = 从 {1} 接收文件“{0}â€å¤±è´¥ã€‚ +message.file.transfer.history.receive.canceled = 已喿¶ˆä»Ž {1} 接收文件“{0}â€ã€‚ +message.find.conference.services = æŸ¥æ‰¾ç¾¤èŠæœåŠ¡ +message.forbidden.error = 从æœåŠ¡å™¨æŽ¥æ”¶åˆ°ç¦æ­¢çš„错误 +message.gateway.username.error = éœ€è¦æä¾›ç”¨æˆ·å +message.gateway.password.error = éœ€è¦æä¾›å¯†ç  +message.gateway.nickname.error = éœ€è¦æä¾›æ˜µç§° +message.general.error = 由于 {0},您断开了与æœåŠ¡å™¨çš„è¿žæŽ¥ +message.generic.reconnect.message = 您断开了与æœåŠ¡å™¨çš„è¿žæŽ¥ï¼Œè¦å†æ¬¡ç™»å½•,请å•å‡»ä¸‹æ–¹é‡æ–°è¿žæŽ¥æŒ‰é’® +message.idle.for = 空闲 {0} +message.image.small.resolution = 图片大å°å°äºŽ 32x32 åƒç´  +message.invalid.jabber.id = 䏿˜¯æœ‰æ•ˆçš„ Jabber ID +message.invalid.jid.error = 指定的 JID 无效 +message.invalid.status = 指定有效的状æ€ä¿¡æ¯ +message.invalid.username.password = æ— æ•ˆçš„ç”¨æˆ·åæˆ–å¯†ç  +message.invite.to.groupchat = {0} æ­£åœ¨é‚€è¯·æ‚¨åŠ å…¥ç¾¤èŠ +message.invite.users.to.conference = é‚€è¯·ç”¨æˆ·åŠ å…¥ç¾¤èŠ +message.is.shared.group = {0} 是共有的组 +message.is.typing.a.message = {0} 正在输入消æ¯â€¦ +message.join.conference.room = åŠ å…¥ç¾¤èŠ +message.kicked.error = 您无法将 {0} è¸¢å‡ºæ­¤ç¾¤èŠ +message.last.message.received = 在 {0} 收到最åŽä¸€æ¡æ¶ˆæ¯ +message.loading.please.wait = 正在加载。请ç¨å€™â€¦ +message.locked.workstation = 用户已é”定其工作站 +message.name.of.group = 分组的åç§° +message.name.of.search.service.question = æœç´¢æœåŠ¡çš„å称? +message.negotiate.file.transfer = 正在å商文件传输,请ç¨å€™â€¦ +message.negotiate.stream = 正在å商连接æµï¼Œè¯·ç¨å€™â€¦ +message.negotiation.file.transfer = 正在与 {0} å商文件传输,请ç¨å€™â€¦ +message.new.message = æ¥è‡ª {0} çš„æ–°æ¶ˆæ¯ +message.new.spark.available = {0} 现在å¯ç”¨ï¼Œæ˜¯å¦è¦å®‰è£…? +message.nickname.error = 请设置昵称 +message.nickname.in.use = 昵称正在使用中,请指定å¦ä¸€ä¸ªæ˜µç§° +message.nickname.not.acceptable = 昵称更改未å¯ç”¨ï¼ +message.no.avatar.found = 用户未é…ç½®ä»»ä½•å¤´åƒ +message.no.caller.id = 没有å¯ç”¨çš„呼å«è€… ID +message.no.description.available = 没有å¯ç”¨çš„æè¿° +message.no.history.found = 没有此用户以å‰çš„对è¯åކå²è®°å½• +message.no.results.found = æœåŠ¡å™¨æœªè¿”å›žä»»ä½•æœç´¢ç»“æžœ +message.no.room.to.join.error = 没有群èŠå¯åŠ å…¥ +message.no.subject.available = 没有å¯ç”¨çš„è¯é¢˜ +message.no.updates = 没有更新å¯ç”¨ +message.normal = æ™®é€šæ¶ˆæ¯ +message.number.to.call = æŒ‡å®šè¦æ‹¨æ‰“çš„å·ç  +message.offline = 用户处于离线状æ€ï¼Œä¸‹æ¬¡ç™»å½•æ—¶å°†æ”¶åˆ°æ¶ˆæ¯ +message.offline.error = ç”¨æˆ·å°†æ— æ³•æŽ¥æ”¶ç¦»çº¿æ¶ˆæ¯ +message.participants.in.room = 群èŠå‚与者 +message.password.error = 指定此账å·çš„å¯†ç  +message.password.private.room.error = 指定ç§äººç¾¤èŠçš„å¯†ç  +message.passwords.no.match = 密ç ä¸åŒ¹é… +message.please.join.in.conference = è¯·æŠŠæˆ‘åŠ å…¥ç¾¤èŠ +message.plugins.not.available = 无法è”ç³»æ’件存储库 +message.prompt.plugin.uninstall = 是å¦ç¡®å®šè¦åœç”¨ {0}? +message.received.file = 您收到了æ¥è‡ª {0} 的文件 +message.receiving.file = 您正在从 {0} 接收文件 +message.reconnect.attempting = 正在å°è¯•… +message.reconnect.failed = 釿–°è¿žæŽ¥å¤±è´¥ +message.reconnect.wait = {0} ç§’åŽé‡æ–°è¿žæŽ¥ +message.register.transports = 注册这些å¯ç”¨çš„传输 +message.registering = 正在注册 {0},请ç¨å€™â€¦ +message.registration.transport.failed = 无法å‘网关注册 +message.restart.spark = 您将需è¦å…³é—­å®¢æˆ·ç«¯ä»¥å®‰è£…新版本,是å¦çŽ°åœ¨å®‰è£…ï¼Ÿ +message.restart.spark.changes = 将在下次å¯åЍ Spark 时移除æ’ä»¶ +message.restart.spark.to.install = 您需è¦å…³é—­å®¢æˆ·ç«¯ä»¥å®‰è£…最新版本,是å¦çŽ°åœ¨å®‰è£…ï¼Ÿ +message.restart.required = 您需è¦é‡å¯ Spark æ‰èƒ½ä½¿æ›´æ”¹ç”Ÿæ•ˆï¼ŒçŽ°åœ¨é‡å¯ï¼Ÿ +message.room.creation.error = æ— æ³•åˆ›å»ºç¾¤èŠ +message.room.destroyed.no.reason = 此群èŠå·²è¢«è§£æ•£ã€‚ +message.room.destroyed = 此群èŠå·²è¢«è§£æ•£ï¼ŒåŽŸå› å¦‚ä¸‹ï¼š{0} +message.room.destruction.reason = 解散此群èŠçš„原因是什么? +message.room.information.for = {0} 的群èŠä¿¡æ¯ +message.save.profile = è¦ä¿å­˜å¯¹ä¸ªäººèµ„料的更改,请å•击ä¿å­˜ +message.search.for.contacts = æœç´¢è”系人 +message.search.input.short = 请至少填写两个字符 +message.search.for.other.people = 在æœåŠ¡å™¨ä¸Šæœç´¢å…¶ä»–用户 +message.search.service.not.available = è”系人æœç´¢æœåŠ¡ä¸å¯ç”¨ +message.searching.please.wait = 正在æœç´¢ï¼Œè¯·ç¨å€™â€¦ +message.select.add.room.to.add = è¯·é€‰æ‹©ä¸€ä¸ªç¾¤èŠæ·»åŠ åˆ°æ‚¨çš„æœåŠ¡åˆ—è¡¨ +message.select.one.or.more = 在è”系人列表中选择一个或多个用户 +message.select.room.to.enter = 指定è¦è¿›å…¥çš„ç¾¤èŠ +message.select.room.to.join = 选择è¦åŠ å…¥çš„ç¾¤èŠ +message.send.a.broadcast = å‘é€å¹¿æ’­æ¶ˆæ¯ +message.send.file.to.user = 将文件å‘é€ç»™æ­¤ç”¨æˆ· +message.send.picture = æ•获并å‘逿‚¨åœ¨å±å¹•上看到的任何内容 +message.send.to.these.people = å‘é€ç»™è¿™äº›ç”¨æˆ· +message.sending.file.to = 正在将文件å‘é€ç»™ {0} +message.sent.offline.files = 您刚收到离线文件。 +message.server.unavailable = 无法连接到æœåŠ¡å™¨ï¼šå称无效或无法访问æœåС噍 +message.service.already.exists = æœåŠ¡å·²åœ¨æ‚¨çš„æœåŠ¡åˆ—è¡¨ä¸­ +message.shared.group = 共有的å°ç»„ +message.specify.contact.jid = 请指定è”系人 JID(例如 ddman@jabber.org) +message.specify.group = 指定è¦å°†æ–°ç”¨æˆ·æ·»åŠ åˆ°çš„è”系人分组 +message.specify.information.for.conference = 指定群èŠä¿¡æ¯ +message.specify.name.error = 指定一个有效的åç§° +message.specify.users.to.join.conference = 指定è¦åŠ å…¥æ­¤ç¾¤èŠçš„用户 +message.specify.valid.time.error = æŒ‡å®šæœ‰æ•ˆçš„è¶…æ—¶å’Œç«¯å£ +message.subject.change.error = ä¸å…许您更改此群èŠçš„è¯é¢˜ +message.subject.has.been.changed.to = {1} 已将è¯é¢˜æ›´æ”¹ä¸ºâ€œ{0}†+message.supply.resource = æä¾›æœ‰æ•ˆçš„èµ„æº +message.supply.valid.port = æä¾›æœ‰æ•ˆç«¯å£ +message.supply.valid.timeout = æä¾›æœ‰æ•ˆçš„超时值 +message.timeout.error = 超时时间必须大于等于 5 ç§’ +message.total.downloaded = 下载总数 +message.transfer.cancelled = æ–‡ä»¶ä¼ è¾“å·²å–æ¶ˆ +message.transfer.complete = æ–‡ä»¶ä¼ è¾“å·²å®Œæˆ ({0}) +message.transfer.progressbar.text.received = {0} 已接收 @ {1} {2} +message.transfer.progressbar.text.sent = {0} å·²å‘é€ @ {1} {2} +message.transfer.rate = 传输速率 +message.transfer.refused = æ–‡ä»¶ä¼ è¾“è¢«æ‹’ç» +message.transfer.waiting.on.user = 正在等待 {0} æŽ¥å—æ–‡ä»¶ä¼ è¾“ +message.unable.to.load.profile = 无法找到 {0} 的个人资料 +message.unable.to.retrieve.last.activity = 无法确定 {0} çš„æœ€åŽæ´»åЍ +message.unable.to.save.password = 无法更改密ç ï¼Œè¯·ä¸Žæ‚¨çš„æœåŠ¡å™¨ç®¡ç†å‘˜è”ç³» +message.unable.to.send.file = 您无法将文件å‘é€ç»™ {0} +message.unable.to.use.hostname.as.resource = 无法将主机åç”¨ä½œèµ„æº +message.unrecoverable.error = 未知连接错误。有关详细信æ¯ï¼Œè¯·æŸ¥çœ‹æ—¥å¿—。 +message.update.room.list = 更新群èŠåˆ—表 +message.updating.cancelled = 已喿¶ˆæ›´æ–° +message.user.banned = ç¦æ­¢ {0} 进入此群èŠã€‚原因:{1} +message.user.banned.no.reason = ç¦æ­¢ {0} 进入此群èŠã€‚ +message.user.given.voice = {0} 在此群èŠä¸­æœ‰äº†å‘è¨€æƒ +message.user.granted.admin = {0} 已被授予管ç†å‘˜æƒé™ +message.user.granted.membership = {0} 已被授予æˆå‘˜æƒé™ +message.user.granted.moderator = {0} 已被授予主æŒäººæƒé™ +message.user.granted.owner = {0} 已被授予所有者æƒé™ +message.user.is.sending.you.a.file = {0} æ­£åœ¨å‘æ‚¨å‘逿–‡ä»¶ +message.user.joined.room = {0} å·²åŠ å…¥ç¾¤èŠ +message.user.kicked.from.room = {0} 已被 {1} 踢出群èŠã€‚原因:{2} +message.user.kicked.from.room.no.reason = {0} 已被 {1} 踢出群èŠã€‚ +message.user.left.room = {0} å·²ç¦»å¼€ç¾¤èŠ +message.user.nickname.changed = {0} 现在昵称为 {1} +message.user.now.available.to.chat = {0} 上线于 {1} +message.user.revoked.admin = {0} 的管ç†å‘˜æƒé™å·²è¢«æ’¤é”€ +message.user.revoked.membership = {0} çš„æˆå‘˜èµ„格已被撤销 +message.user.revoked.moderator = {0} 的主æŒäººæƒé™å·²è¢«æ’¤é”€ +message.user.revoked.owner = {0} 的所有者æƒé™å·²è¢«æ’¤é”€ +message.user.voice.revoked = {0} çš„å‘言æƒå·²è¢«æ’¤é”€ +message.username.error = 指定账å·çš„用户å +message.username.password.error = éœ€è¦æä¾›ç”¨æˆ·åå’Œ/或密ç ã€‚ +message.vcard.not.supported = æœåС噍䏿”¯æŒç”µå­å片,无法ä¿å­˜æ‚¨çš„电å­å片 +message.version = 版本:{0} +message.view.information.about.this.user = æŸ¥çœ‹æœ‰å…³æ­¤ç”¨æˆ·çš„ä¿¡æ¯ +message.waiting.for.user.to.join = 正在等待 {0} 加入 +message.went.offline = {0} 离线于 {1} +message.you.have.been.banned = ç¦æ­¢æ‚¨è¿›å…¥æ­¤ç¾¤èŠ +message.you.have.been.kicked = æ‚¨å·²è¢«è¸¢å‡ºæ­¤ç¾¤èŠ +message.you.have.sent = 您已将文件å‘é€ç»™ {0} +message.your.admin.granted = 您已被授予管ç†å‘˜æƒé™ +message.your.banned = ç¦æ­¢æ‚¨è¿›å…¥æ­¤ç¾¤èŠ +message.your.kicked = 您已被 {0} 踢出 +message.your.membership.granted = 您已被授予æˆå‘˜æƒé™ +message.your.membership.revoked = 您的æˆå‘˜èµ„格已被撤销 +message.your.moderator.granted = 您已被授予主æŒäººæƒé™ +message.your.moderator.revoked = 您的主æŒäººæƒé™å·²è¢«æ’¤é”€ +message.your.ownership.granted = 您已被授予所有者æƒé™ +message.your.ownership.revoked = 您的所有者æƒé™å·²è¢«æ’¤é”€ +message.your.revoked.granted = 您的管ç†å‘˜æƒé™å·²è¢«æ’¤é”€ +message.your.voice.granted = 您已在此èŠå¤©ä¸­èŽ·å¾—å‘è¨€æƒ +message.your.voice.revoked = 您的å‘言æƒå·²è¢«æ’¤é”€ +message.groupchat.require.password = 此群èŠéœ€è¦å¯†ç æ‰èƒ½è¿›å…¥ +message.groupchat.registered.member = æˆåŠŸåœ¨ {0} 注册 +message.search.for.history = æœç´¢å¯¹è¯åކå²è®°å½• +message.search.period.day.one = æ¯é¡µä¸€å¤© +message.search.period.week.one = æ¯é¡µä¸€å‘¨ +message.search.period.month.one = æ¯é¡µä¸€ä¸ªæœˆ +message.search.period.year.one = æ¯é¡µä¸€å¹´ +message.search.period.none = 在一页上显示所有内容 +message.search.page.timeperiod = 选择æ¯é¡µæ˜¾ç¤ºçš„æ¶ˆæ¯çš„æ—¶é—´è·¨åº¦ +message.search.page.counter = 页é¢çš„当å‰ç´¢å¼•和所有页é¢çš„æ•°é‡ +message.search.page.right = å‘å‰å¯¼èˆªä¸€é¡µ +message.search.page.left = å‘åŽå¯¼èˆªä¸€é¡µ + +status.away = 离开 +status.custom.messages = è‡ªå®šä¹‰ä¿¡æ¯ +status.do.not.disturb = 请勿打扰 +status.extended.away = 延长离开 +status.free.to.chat = 有空èŠå¤© +status.on.phone = åœ¨æ‰“ç”µè¯ +status.online = 在线 +status.pending = å¾…å¤„ç† +status.invisible = éšèº« +status.offline = 离线 + +tab.available.plugins = å¯ç”¨çš„æ’ä»¶ +tab.avatar = å¤´åƒ +tab.business = 商业 +tab.conferences = ç¾¤èŠ +tab.contacts = è”系人 +tab.deactivated.plugins = å·²åœç”¨çš„æ’ä»¶ +tab.general = 常规 +tab.security = 安全 +tab.home = 主页 +tab.installed.plugins = 已安装的æ’ä»¶ +tab.personal = 个人 +tab.proxy = ä»£ç† +tab.sso = å•点登录 +tab.pki = 公钥基础设施 +tab.certificates = è¯ä¹¦ +tab.mutual.auth = ç›¸äº’éªŒè¯ +title.about = 关于 +title.advanced.connection.preferences = 高级连接首选项 +title.account.create.registration = è´¦å·æ³¨å†Œ +title.account.created = è´¦å·å·²åˆ›å»º +title.add.contact = 添加è”系人 +title.add.contact.group = 添加è”系人组 +title.add.new.group = 添加新组 +title.add.search.service = 添加æœç´¢æœåŠ¡ +title.add.to.roster = 添加到è”系人列表 +title.address = åœ°å€ +title.advanced.connection.sso = 使用å•点登录 (SSO) +title.advanced.connection.usesso = 通过 GSSAPI 使用å•点登录 (SSO) +title.advanced.connection.sso.account = 这将使用“{0}â€çš„æ¡Œé¢è´¦å·ç™»å½•到æœåŠ¡å™¨ã€‚ +title.advanced.connection.sso.unable = 无法使用å•点登录进行连接,请检查您的主机和æœåŠ¡å™¨è®¾ç½®ã€‚ +title.advanced.connection.sso.noprincipal = Spark 找ä¸åˆ°ç”¨äºŽå•点登录的主机,这将阻止å•点登录工作。 +title.advanced.connection.sso.smack3compat = Smack 3 å…¼å®¹æ¨¡å¼ +title.alert = 通知 +title.appearance = 外观 +title.appearance.preferences = 自定义 +title.available.transports = å¯ç”¨çš„传输 +title.bookmarks = 书签 +title.broadcast.message = å¹¿æ’­æ¶ˆæ¯ +title.broadcast.history = 广播历å²è®°å½• +title.browse.conference.services = æµè§ˆç¾¤èŠæœåŠ¡ +title.browse.room.service = æµè§ˆç¾¤èŠ - {0} +title.cancelled = 已喿¶ˆ +title.change.nickname = 更改昵称 +title.change.subject = 更改è¯é¢˜ +title.chat = èŠå¤© +title.choose.directory = 选择文件夹 +title.choose.incoming.sound = 选择传入的声音文件 +title.choose.offline.sound = 选择离线声音文件 +title.choose.outgoing.sound = 选择传出的声音文件 +title.client.logs = 客户端日志 +title.conference.invitation = 群èŠé‚€è¯· +title.conference.rooms = ç¾¤èŠ +title.configure.chat.room = é…ç½®ç¾¤èŠ +title.configure.room = è®¾ç½®ç¾¤èŠ +title.confirmation = 确认 +title.create.new.account = åˆ›å»ºæ–°è´¦å· +title.create.or.bookmark.room = åŠ å…¥ç¾¤èŠæˆ–为其添加书签 +title.create.room = 创建 +title.create.problem = è´¦å·åˆ›å»ºé—®é¢˜ +title.delete.file = 是å¦ç¡®å®šè¦åˆ é™¤æ­¤æ–‡ä»¶ï¼Ÿ +title.dial.phone = æ‹¨æ‰“ç”µè¯ +title.disable.transport = ç§»é™¤ç™»å½•ä¿¡æ¯ +title.download.complete = ä¸‹è½½å®Œæˆ +title.downloading.im.client = 下载 IM 客户端 +title.downloads = 下载 +title.edit.custom.message = ç¼–è¾‘è‡ªå®šä¹‰ä¿¡æ¯ +title.edit.profile = ç¼–è¾‘ä¸ªäººèµ„æ–™ä¿¡æ¯ +title.enter.reason = 输入ç†ç”± +title.error = 错误 +title.error.couldnot.open.file = 无法打开文件 +title.error.delete.file = 无法删除文件 +title.error.find.app = 找ä¸åˆ°åŒ¹é…çš„åº”ç”¨ç¨‹åº +title.error.rename.file = 无法é‡å‘½å文件 +title.file = 文件 +title.filesize = æ–‡ä»¶å¤§å° +title.file.exists = 文件存在 +title.file.transfer = 文件传输 +title.file.transfer.preferences = 文件传输首选项 +title.find.conference.service = æŸ¥æ‰¾ç¾¤èŠæœåŠ¡ +title.find.contacts = 查找è”系人 +title.gadugadu.registration = GaduGadu è´¦å·å‡­æ® +title.general.media = 媒体设置 +title.general.chat.settings = 常规èŠå¤©è®¾ç½® +title.group.chat = ç¾¤èŠ +title.group.chat.settings = 群èŠè®¾ç½® +title.history.for = {0} 的对è¯åކå²è®°å½• +title.irc.registration = IRC è´¦å·å‡­æ® +title.sametime.registration = Sametime è´¦å·å‡­æ® +title.facebook.registration = Facebook è´¦å·å‡­æ® +title.myspace.registration = MySpace è´¦å·å‡­æ® +title.incoming.call = æ¥ç”µ +title.input.fileexplorer = 请输入文件æµè§ˆå™¨çš„å称: +title.input.newname = 请输入新å称: +title.input.openwith = 请输入您è¦ä½¿ç”¨çš„应用程åºçš„å称: +title.invite.to.conference = é‚€è¯·åŠ å…¥ç¾¤èŠ +title.jabber.browser = æµè§ˆå™¨ +title.join.conference.room = åŠ å…¥ç¾¤èŠ +title.last.activity = æœ€åŽæ´»åЍ +title.login = 登录 +title.login.error = 登录错误 +title.login.settings = 登录设置 +title.login.no.account = 无法确定 +title.lookup.profile = 查看个人资料 +title.name = åç§° +title.new.client.available = 新客户端å¯ç”¨ +title.new.roster.group = æ–°è”系人列表组 +title.new.version.available = 新版本å¯ç”¨ +title.no.updates = 没有更新 +title.notes = 笔记 +title.notification = 通知 +title.notifications = 通知 +title.occupants = 使用者 +title.on.the.phone = åœ¨æ‰“ç”µè¯ +title.password = å¯†ç  +title.password.required = 需è¦å¯†ç  +title.passwords.no.match = ç¡®è®¤å¯†ç  +title.person.search = 查找è”系人 +title.plugins = æ’ä»¶ +title.preferences = 首选项 +title.profile.information = ä¸ªäººèµ„æ–™ä¿¡æ¯ +title.profile.not.found = 个人资料未找到 +title.qq.registration = QQ è´¦å·å‡­æ® +title.register.account = æ³¨å†Œæ–°è´¦å· +title.registration.error = 注册错误 +title.reminder = æé†’ +title.rename.roster.group = é‡å‘½åè”系人列表组 +title.room.destroyed = 群èŠå·²è§£æ•£ +title.room.information = 群èŠä¿¡æ¯ +title.roster = è”系人列表 +title.select.file.to.send = 选择è¦å‘é€çš„æ–‡ä»¶ +title.set.status.message = 设置状æ€ä¿¡æ¯ +title.simple.registration = SIMPLE è´¦å·å‡­æ® +title.sound.preferences = 声音首选项 +title.sounds = 声音 +title.spark.preferences = Spark 首选项 +title.start.chat = 开始èŠå¤© +title.status.message = 状æ€ä¿¡æ¯ +title.task.notification = 任务通知 +title.tasks = 任务 +title.transports = 传输 +title.tray.information = æ‰˜ç›˜ä¿¡æ¯ +title.upgrading.client = 正在å‡çº§å®¢æˆ·ç«¯ +title.version.and.time = 版本和时间 +title.view.bookmarks = 查看书签 +title.view.profile.for = 正在查看 {0} 的个人资料 +title.view.room.information = 查看群èŠä¿¡æ¯ +title.waiting.to.call = æ­£åœ¨ç­‰å¾…æ‹¨å· +title.warning = 警告 +title.xmpp.registration = XMPP è´¦å·å‡­æ® +title.appearance.showVCards = 在è”系人列表中显示电å­å片(&V) +title.subscription.request = 订阅请求 +title.certificate = è¯ä¹¦ + +time.days = 天 +time.hours = å°æ—¶ +time.minutes = 分钟 +time.since = 自从 +time.less.than.one.minute = 少于 1 分钟 + +tooltip.place.a.call = ç»™æ­¤äººæ‹¨æ‰“ç”µè¯ +tooltip.appearance = 更改对è¯çš„外观 +tooltip.file.transfer = 文件传输的首选项 +tooltip.notifications = ä¼ å…¥èŠå¤©çš„通知首选项 +tooltip.place.voice.call = ç»™æ­¤ç”¨æˆ·æ‹¨æ‰“ç”µè¯ +tooltip.send.email = å‘é€é‚®ä»¶ +tooltip.start.chat = å¼€å§‹å¯¹è¯ +tooltip.view.changelog = 查看更改日志 +tooltip.view.history = 查看对è¯åކå²è®°å½• +tooltip.view.readme = 查看自述文件 +tooltip.encryptionmode.required = 需è¦åР坆æ‰èƒ½è¿›è¡Œè¿žæŽ¥ã€‚如果æœåŠ¡å™¨ä¸æä¾›åŠ å¯†ï¼Œæˆ–è€…åŠ å¯†å商失败,则与æœåŠ¡å™¨çš„è¿žæŽ¥å°†å¤±è´¥ã€‚ +tooltip.encryptionmode.ifpossible = åªè¦åР坆å¯ç”¨ï¼Œå°±ä¼šä½¿ç”¨å®ƒã€‚ +tooltip.encryptionmode.disabled = 加密被ç¦ç”¨ï¼Œåªä¼šä½¿ç”¨æœªåŠ å¯†çš„è¿žæŽ¥ã€‚å¦‚æžœæœåŠ¡å™¨éœ€è¦åŠ å¯†ï¼Œåˆ™è¿žæŽ¥å°†å¤±è´¥ã€‚ + +tree.conference.services = ç¾¤èŠæœåŠ¡ +tree.users.in.room = 群èŠå†…的用户 + +lookandfeel.select = 选择外观 +lookandfeel.change.now = ç«‹å³æ›´æ”¹ +lookandfeel.tooltip.restart.no = 无需é‡å¯ +lookandfeel.tooltip.restart.yes = è¦åˆ‡æ¢ç³»ç»Ÿå¤–观,请按ä¿å­˜å¹¶é‡å¯ Spark。 +lookandfeel.color.label = 颜色 +lookandfeel.color.red = 红 +lookandfeel.color.green = 绿 +lookandfeel.color.blue = è“ +lookandfeel.color.opacity = ä¸é€æ˜Žåº¦ +lookandfeel.color.saved = 颜色已ä¿å­˜ + + +##Settings for the privacy plugin +privacy.title.preferences = Spark éšç§é¦–选项 +privacy.title.panel = 请使用鼠标å³é”® +privacy.label.iq.desc = 查询 +privacy.label.pin.desc = 在线状æ€ä¼ å…¥ +privacy.label.pout.desc = 在线状æ€ä¼ å‡º +privacy.label.msg.desc = æ¶ˆæ¯ +privacy.border.information = éšç§ä¿¡æ¯ +privacy.label.information = 使用å³é”®å•击èœå•添加或删除列表或项目 +privacy.root.node = éšç§åˆ—表 +privacy.label.preferences = éšç§æ’ä»¶ +privacy.tooltip.preferences = Spark éšç§è®¾ç½® +privacy.label.list.is.active = 当剿´»åŠ¨åˆ—è¡¨ï¼š +privacy.label.list.is.default = 默认列表: +privacy.border.block = å±è”½ +privacy.pick.one.or.more = 选择一个或多个项目添加到列表 +privacy.title.add.picker = 将项目添加到列表 +privacy.node.contacts = è”系人 +privacy.node.groups = 组 +privacy.menu.add.contacts = å°†è”系人添加到列表 +privacy.menu.add.groups = 将组添加到列表 +privacy.menu.add.rem.items = 从列表中移除 {0} 个项目 +privacy.menu.remove = 移除 +privacy.menu.activate.list = 激活 +privacy.menu.default.list = 设置为默认 +privacy.menu.add.list = 添加列表 +privacy.menu.remove.list = 移除列表 +privacy.dialog.add.list = 请输入列表åç§° +privacy.dialog.rem.list = 是å¦ç¡®å®šè¦ç§»é™¤ {0}? +privacy.status.menu.entry = éšç§åˆ—表 +privacy.name.for.default.list = 默认 +privacy.button.no.list.selected = 未选择列表 +privacy.menuitem.deactivate.current.list = åœç”¨ {0} +privacy.label.not.supported = æœåС噍䏿”¯æŒéšç§åˆ—表。 + +##Stunfallback in media settings +stun.border.label = STUN 回退æœåС噍 +stun.server.addr = STUN æœåŠ¡å™¨ï¼š +stun.server.port = STUN 端å£ï¼š + +##Text Field Hints +hint.login.username = 输入用户å +hint.login.password = è¾“å…¥å¯†ç  +hint.login.domain = 输入域 + +composing = {0} 正在输入… +paused = {0} å·²ç»åœæ­¢è¾“å…¥ +active = {0} æ­£åœ¨è¯·æ±‚æ³¨æ„ +inactive = {0} 正在åšå…¶ä»–事情 +gone = {0} 已离开 + +#!# +action.viewlog=查看日志 + +dialog.confirm.to.reveal.visibility.title=是å¦ç¡®å®šï¼Ÿ +dialog.confirm.to.reveal.visibility.msg=如果您è¦ç»§ç»­ï¼Œæ‚¨çš„éšèº«çжæ€å°±ä¼šæš´éœ² +dialog.confirm.close.all.conferences.if.invisible.msg = 如果您è¦ç»§ç»­ï¼Œå°†å…³é—­æ‰€æœ‰ç¾¤èŠ +dialog.certificate.show = 这是您试图添加到 TrustStore çš„è¯ä¹¦å’Œç§é’¥ã€‚

      添加此è¯ä¹¦åŽï¼ŒSpark 将能够与此è¯ä¹¦æ ‡è¯†çš„æœåŠ¡å™¨å»ºç«‹å®‰å…¨
      通信。

      å¦‚æžœæ‚¨ç¡®å®šè¦æ·»åŠ æ­¤è¯ä¹¦ï¼Œè¯·å•击确定按钮。 +dialog.id.certificate.show = 这是您试图添加到 IdentityStore çš„è¯ä¹¦

      添加此è¯ä¹¦åŽï¼ŒSpark 将能够在建立连接期间å‘远程æœåС噍æä¾›æ­¤è¯ä¹¦ï¼Œä»¥ä¾¿å¯¹å…¶è‡ªèº«è¿›è¡Œèº«ä»½éªŒè¯å¹¶åŠ å¯†è¯¥è¿žæŽ¥ã€‚

      å¦‚æžœæ‚¨ç¡®å®šè¦æ·»åŠ æ­¤è¯ä¹¦ï¼Œè¯·å•击确定按钮。 +dialog.certificate.add.from.connection = 这是您å°è¯•连接到的æœåС噍æä¾›çš„è¯ä¹¦ã€‚
      æ­¤è¯ä¹¦ä¸åœ¨æ‚¨çš„ TrustStore 中,这æ„味ç€å®ƒä¸å—ä¿¡ä»»
      并且您无法连接到此æœåŠ¡å™¨ã€‚

      是å¦è¦ä¿¡ä»»å®ƒå¹¶å°†æ­¤è¯ä¹¦æ·»åŠ åˆ°æ‚¨çš„ TrustStore? +dialog.certificate.unrecognized.server.certificate = 您è¦è¿žæŽ¥åˆ°çš„æœåŠ¡å™¨ä½¿ç”¨è¯ä¹¦æ¥æ ‡è¯†è‡ªå·±ï¼Œè¯¥è¯ä¹¦
      未被 Spark 识别。请查看以下详细信æ¯ã€‚ +dialog.certificate.ask.allow.self-signed = 您è¦è¿žæŽ¥åˆ°çš„æœåŠ¡å™¨ä½¿ç”¨è‡ªç­¾åè¯ä¹¦è¿›è¡Œè‡ªæˆ‘标识。
      Spark的当å‰é…ç½®ä¸å…许使用自签åè¯ä¹¦ã€‚是å¦
      è¦æ›´æ”¹æ­¤é…置并é‡è¯•? +dialog.certificate.subject.label = 主题: + +dialog.certificate.add.unrecognized.server.certificate = 是å¦è¦å°†æ­¤è¯ä¹¦æ·»åŠ åˆ° Spark 信任的è¯ä¹¦é›†ä¸­ï¼Ÿ +dialog.certificate.chain.add.from.connection = 这是由您所连接的æœåС噍æä¾›çš„è¯ä¹¦é“¾ã€‚
      它ä¸åœ¨æ‚¨çš„信任列表中,因此您无法连接。

      是å¦è¦å°†æ­¤è¯ä¹¦æ·»åŠ åˆ°æ‚¨çš„å—信任列表中? +dialog.certificate.cannot.have.copy = æ­¤è¯ä¹¦å·²å­˜å‚¨åœ¨ TrustStore 中。 +dialog.certificate.has.been.added = è¯ä¹¦å·²æ·»åŠ åˆ° TrustStore。 +dialog.certificate.has.been.added.to.identity.store = è¯ä¹¦å·²æ·»åŠ åˆ° IdentityStore。 +dialog.certificate.is.distrusted = è¯ä¹¦æ— æ•ˆï¼Œå› æ­¤ä¸åº”该信任它,因为它很å±é™©ã€‚\n如果ä»è¦ä¿¡ä»»å®ƒï¼Œè¯·å•击信任å•选按钮或将其添加到异常列表中。 +dialog.certificate.sure.to.delete = 是å¦ç¡®å®žè¦åˆ é™¤æ­¤è¯ä¹¦ï¼Ÿ\n如果这样åšï¼Œæ‚¨å°†æ— æ³•建立与此è¯ä¹¦æ ‡è¯†çš„æœåŠ¡å™¨çš„å®‰å…¨è¿žæŽ¥ã€‚ +dialog.certificate.has.been.deleted = è¯ä¹¦å·²æˆåŠŸåˆ é™¤ã€‚ +dialog.self.signed.certificate.has.been.created = 已在以下文件夹中创建自签åè¯ä¹¦å’Œç§é’¥ï¼š\n +dialog.certificate.request.has.been.created = 已在文件夹中创建è¯ä¹¦ç­¾å请求和ç§é’¥ï¼š\n +dialog.cannot.upload.certificate.might.be.ill.formatted = 无法上传è¯ä¹¦æ–‡ä»¶ï¼Œè¯ä¹¦å¯èƒ½æ ¼å¼ä¸æ­£ç¡® +dialog.cannot.upload.certificate = 无法上传è¯ä¹¦æ–‡ä»¶ +dialog.certificate.title.certificate.not.in.truststore = æä¾›çš„è¯ä¹¦ä¸åœ¨æ‚¨çš„ TrustStore 中 + +cert.valid = 有效 +cert.revoked = å·²åŠé”€ +cert.expired = 已过期 +cert.not.valid.yet = 尚未生效 +cert.self.signed = 自签å +cert.sign.request = è¯ä¹¦ç­¾å请求 +cert.self.signed.save.to.file = å°†è¯ä¹¦ä¿å­˜åˆ°æ–‡ä»¶ +cert.unknown.oid = 未知 OID æè¿°ã€‚ +cert.is.critical = 至关é‡è¦ï¼š +cert.critical = é‡è¦ï¼š +cert.not.critical = ä¸é‡è¦ï¼š +cert.common.name = 通用åç§° +cert.organization.unit = 组织å•ä½ +cert.organization = 组织 +cert.country = 国家/地区 +cert.city = 城市 + +cert.extensions = è¯ä¹¦æ‰©å±•: +cert.extensions.unsupported = 䏿”¯æŒçš„æ‰©å±• +cert.extension.extended.usage.digital.signature = æ•°å­—ç­¾å +cert.extension.extended.usage.non.repudiation = ä¸å¯å¦è®¤æ€§ +cert.extension.extended.usage.key.encipherment = 密钥加密 +cert.extension.extended.usage.data.encipherment = æ•°æ®åР坆 +cert.extension.extended.usage.key.agreement = 密钥å商 +cert.extension.extended.usage.key.cert.sign = 密钥è¯ä¹¦ç­¾å +cert.extension.extended.usage.crl.sign = CRL ç­¾å +cert.extension.extended.usage.encipher.only = 仅加密 +cert.extension.extended.usage.decipher.only = 仅解密 +cert.extension.basic.constraints.is.ca = 是è¯ä¹¦é¢å‘机构 +cert.extension.basic.constraints.path.length = 验è¯è·¯å¾„长度 +cert.extension.name.constraints.permitted.subtrees = å…è®¸çš„å­æ ‘ +cert.extension.name.constraints.excluded.subtrees = æŽ’é™¤çš„å­æ ‘ + +##OID's mapping +2.5.29.1 = X.509 旧的授æƒå¯†é’¥æ ‡è¯†ç¬¦ +2.5.29.2 = 密钥属性 +2.5.29.3 = è¯ä¹¦ç­–ç•¥ +2.5.29.4 = 密钥使用é™åˆ¶ +2.5.29.5 = 策略映射 +2.5.29.6 = å­æ ‘çº¦æŸ +2.5.29.7 = 主题替代åç§° +2.5.29.8 = é¢å‘者替代åç§° +2.5.29.9 = 主题目录属性 +2.5.29.10 = åŸºæœ¬çº¦æŸ +2.5.29.11 = è¯ä¹¦æ‰©å±• +2.5.29.12 = è¯ä¹¦æ‰©å±• +2.5.29.13 = è¯ä¹¦æ‰©å±• +2.5.29.14 = 主题密钥标识符 +2.5.29.15 = 密钥使用 +2.5.29.16 = ç§é’¥ä½¿ç”¨æœŸé™ +2.5.29.17 = 主题替代åç§° +2.5.29.18 = é¢å‘者替代åç§° +2.5.29.19 = åŸºæœ¬çº¦æŸ +2.5.29.20 = CRL ç¼–å· +2.5.29.21 = åŽŸå› ä»£ç  +2.5.29.22 = 到期日期 +2.5.29.23 = ä¿æŒæŒ‡ä»¤ç  +2.5.29.24 = 无效日期 +2.5.29.25 = CRL 分å‘点 +2.5.29.26 = é¢å‘分å‘点 +2.5.29.27 = CRL 指示符 +2.5.29.28 = é¢å‘分å‘点 +2.5.29.29 = è¯ä¹¦é¢å‘者 +2.5.29.30 = åç§°çº¦æŸ +2.5.29.31 = CRL 分å‘点 +2.5.29.32 = è¯ä¹¦ç­–ç•¥ +2.5.29.33 = 策略映射 +2.5.29.34 = ç­–ç•¥çº¦æŸ +2.5.29.35 = 授æƒå¯†é’¥æ ‡è¯†ç¬¦ +2.5.29.36 = ç­–ç•¥çº¦æŸ +2.5.29.37 = 扩展密钥使用 +2.5.29.38 = 机构属性标识符 +2.5.29.39 = 角色规范è¯ä¹¦æ ‡è¯†ç¬¦ +2.5.29.40 = CRL æµæ ‡è¯†ç¬¦ +2.5.29.41 = basicAttConstraints +2.5.29.42 = 委托åç§°çº¦æŸ +2.5.29.43 = æ—¶é—´è§„æ ¼ +2.5.29.44 = CRL 范围 +2.5.29.45 = 状æ€è½¬ä»‹ +2.5.29.46 = 最新 CRL +2.5.29.47 = CRL 中的å‡åºåˆ—表 +2.5.29.48 = 属性æè¿°ç¬¦ +2.5.29.49 = 用户须知 +2.5.29.50 = SOA 标识符 +2.5.29.51 = 基本 CRL æ›´æ–°æ—¶é—´ +2.5.29.52 = 坿ޥå—çš„è¯ä¹¦ç­–ç•¥ +2.5.29.53 = Delta ä¿¡æ¯ +2.5.29.54 = Inhabit any-policy +2.5.29.55 = ç›®æ ‡ä¿¡æ¯ +2.5.29.56 = 没有å¯ç”¨çš„åŠé”€ä¿¡æ¯ +2.5.29.57 = 坿ޥå—的特æƒç­–ç•¥ +2.5.29.58 = id-ce-toBeRevoked +2.5.29.59 = id-ce-RevokedGroups +2.5.29.60 = id-ce-expiredCertsOnCRL +2.5.29.61 = 间接é¢å‘者 +2.5.29.62 = id-ce-noAssertion +2.5.29.63 = id-ce-aAissuingDistributionPoint +2.5.29.64 = id-ce-issuedOnBehaIFOF +2.5.29.65 = id-ce-singleUse +2.5.29.66 = id-ce-groupAC +2.5.29.67 = id-ce-allowedAttAss +2.5.29.68 = id-ce-attributeMappings +2.5.29.69 = id-ce-holderNameConstraints + +2.16.840.1.113730.1.1 = +1.3.6.1.4.1.311.20.2 = szOID_ENROLL_CERTTYPE_EXTENSION +1.3.6.1.4.1.311.21.1 = MS è¯ä¹¦æœåŠ¡ CA 版本 +1.2.840.113533.7.65.0 = 委托版本扩展 +1.3.6.1.5.5.7.1.1 = è¯ä¹¦é¢å‘机构信æ¯è®¿é—® +1.3.6.1.5.5.7.3.1 = è¯ä¹¦å¯ä»¥ç”¨ä½œå®‰å…¨å¥—接字层(SSL)æœåС噍è¯ä¹¦ã€‚ +1.3.6.1.5.5.7.3.2 = è¯ä¹¦å¯ä»¥ç”¨ä½œå®‰å…¨å¥—接字层(SSL)客户端è¯ä¹¦ã€‚ +1.3.6.1.5.5.7.3.3 = è¯ä¹¦å¯ä»¥ç”¨äºŽä»£ç ç­¾å。 +1.3.6.1.5.5.7.3.4 = è¯ä¹¦å¯ç”¨äºŽä¿æŠ¤ç”µå­é‚®ä»¶ï¼ˆç­¾åã€åР坆ã€å¯†é’¥å议)。 +1.3.6.1.5.5.7.3.5 = 互è”网å议安全性(IPSEC)终端系统è¯ä¹¦ã€‚ +1.3.6.1.5.5.7.3.6 = 互è”网å议安全(IPSEC)隧é“è¯ä¹¦ã€‚ +1.3.6.1.5.5.7.3.7 = 互è”网å议安全性(IPSEC)用户è¯ä¹¦ã€‚ +1.3.6.1.5.5.7.3.8 = PKIX 关键用途时间戳。è¯ä¹¦å¯ç”¨äºŽå°†å¯¹è±¡çš„哈希绑定到æ¥è‡ªå¯ä¿¡æ—¶é—´æºçš„æ—¶é—´ã€‚ + +1.3.6.1.5.5.7.3.9 = Rec. ITU-T X.509 è¯ä¹¦å¯¹åº”çš„ç§é’¥å¯ä»¥ç”±æœºæž„用æ¥ç­¾ç½² OCSP å“应。 +1.3.6.1.5.5.7.3.10 = PKIX 密钥目的数æ®éªŒè¯å’Œè®¤è¯æœåС噍å议。 +1.3.6.1.5.5.7.3.11 = sbgpCertAAServerAuth. +1.3.6.1.5.5.7.3.12 = id-kp-scvp-responder 密钥用途。 +1.3.6.1.5.5.7.3.13 = id-kp-eapOverPPP + +1.3.6.1.5.5.7.1.12 = id-pe-logotype +1.3.6.1.4.1.311.10.3.4 = 从与 Microsoft Cryptography 相关的对象 ID 中自动æå–。 +2.23.42.7.0 = 散列的根密钥 diff --git a/core/src/main/resources/i18n/spark_i18n_zh_TW.properties b/core/src/main/resources/i18n/spark_i18n_zh_TW.properties new file mode 100644 index 000000000..6ef165498 --- /dev/null +++ b/core/src/main/resources/i18n/spark_i18n_zh_TW.properties @@ -0,0 +1,878 @@ +ok = 確定 +cancel = å–æ¶ˆ +add = 新增 +use.default = 使用é è¨­ +close = 關閉 +create = 創建 +invite = 邀請 +date = 日期 +from = 從 +room.name = 會議室å稱 +join = 加入 +description = æè¿° +subject = 主題 +occupants = 會議室房客 +accept = æŽ¥å— +reject = 拒絕 +open = 打開 +open.folder = 打開資料夾 +retry = é‡è©¦ +is.active = æ´»èº +not.registered = 未註冊 +save = 儲存 +yes = 是 +no = å¦ +broadcast = 廣播 +available = 空閒 +user.has.signed.in = 已簽到 +user.has.signed.off = 已簽離 +unfiled = 未分類 +refresh = 刷新 +participants = åƒèˆ‡è€… +online = 在線 +offline = 離線 +administrator = 管ç†è€… +answer = 回覆 +apply = 應用 +while.offline = ç•¶å‰é›¢ç·š + +action.clear = 清除 +action.copy = 複製 +action.cut = 剪下 +action.paste = 貼上 +action.print = å°å‡º +action.save = 儲存 +action.select.all = å…¨é¸ + +button.create.account = (&C) 創建帳戶 +button.close = (&L) 關閉 +button.copy.to.clipboard = 複製到剪貼簿 +button.advanced = (&V) 進階 +button.browse = (&B) ç€è¦½â€¦ +button.browse2 = (&R) ç€è¦½â€¦ +button.browse3 = (&O) ç€è¦½â€¦ +button.approve = (&A) 批准 +button.deny = (&D) å¦èª +button.accept = (&A) æŽ¥å— +button.reject = é§å›ž +button.profile = (&P) 簡介 +button.add.a.contact = (&A) 新增è¯çµ¡äºº +button.reconnect = (&R) 釿–°é€£æŽ¥ +button.reconnect2 = 釿–°é€£æŽ¥ +button.add = (&A) 新增 +button.add2 = 新增 +button.roster = (&R) è¯çµ¡äººåå–® +button.add.bookmark = 新增書簽 +button.remove.bookmark = 移除書簽 +button.bookmark.room = (&B) 書簽房間 +button.create.room = (&C) 創建或加入房間 +button.join.room = (&J) åŠ å…¥é¸æ“‡çš„æˆ¿é–“ +button.login = 登入 +button.refresh = (&R) 刷新 +button.find = (&F) æœå°‹ +button.update = (&U) æ›´æ–° +button.cancel = (&C) å–æ¶ˆ +button.decline = (&D) 拒絕 +button.join = (&J) 加入 +button.save.for.future.use = (&S) 儲存以備以後使用 +button.register = (&R) 註冊 +button.dial.number = (&D) 撥號 +button.clear = (&C) 清除 +button.search = (&S) æœå°‹ +button.add.service = (&A) 新增æœå‹™ +button.quit = (&Q) 離開 +button.new = (&N) 新增 +button.add.user = (&A) 新增帳戶 +button.save = (&S) 儲存 +button.start.chat = èŠå¤© +button.send.email = é›»å­éƒµä»¶ +button.send = ç™¼é€ +button.tasks.active = æ´»èº +button.tasks.all = 全部 +button.unset.file.explorer = 未設置文件ç€è¦½å™¨ +button.view.notes = 查看筆記 +button.view.profile = 查看完整個人資料 +button.view.tasklist = 查看任務列表 +button.re.detect = 釿–°æª¢æ¸¬ + +checkbox.save.password = (&S) ä¿å­˜å¯†ç¢¼ +checkbox.auto.login = (&A) 啟動 Spark 後自動登入 +checkbox.login.as.invisible = 離線狀態登入 +checkbox.use.proxy.server = (&U) 使用代ç†ä¼ºæœå™¨ +checkbox.auto.discover.port = (&A) 自動檢測主機和連接埠 +checkbox.permanent = (&P) 會議室是固定的 +checkbox.private.room = (&I) 會議室是ç§äººçš„ +checkbox.show.time.in.chat.window = èŠå¤©è¦–窗顯示時間 +checkbox.show.notifications.in.conference = (&S) 在會議室顯示通知 +checkbox.disable.chat.history = (&D) ä¸å•Ÿå‹•èŠå¤©è¨˜éŒ„功能 +checkbox.show.toaster = (&T) é¡¯ç¤ºä¸€å€‹å½ˆå‡ºçª—å£ +checkbox.window.to.front = (&B) 窗å£ç½®æ–¼æœ€å‰é¢ +checkbox.play.sound.on.new.message = (&A) ç•¶æ”¶åˆ°æ–°æ¶ˆæ¯æ™‚播放è²éŸ³ +checkbox.play.sound.when.offline = (&O) ç•¶è¯çµ¡äººé›¢ç·šæ™‚播放è²éŸ³ +checkbox.play.sound.on.outgoing.message = (&S) ç•¶ç™¼é€æ¶ˆæ¯æ™‚播放è²éŸ³ +checkbox.play.sound.on.invitation = (&I) 當收到邀請時播放è²éŸ³ +checkbox.idle.enabled = (&I) 啟動閒置狀態 +checkbox.launch.on.startup = (&L) 開機時啟動 Spark +checkbox.start.in.tray = (&S) 啟動後顯示至時間工具列內 +checkbox.split.chat.window = (&W) èŠå¤©è¦–çª—å€šé æ¡Œé¢(éœ€é‡æ–°å•Ÿå‹• Spark) +checkbox.tabs.on.top = (&C) èŠå¤©è¦–窗置頂(éœ€é‡æ–°å•Ÿå‹• Spark) +checkbox.tabs.scroll = 為èŠå¤©é¸é …å¡ä½¿ç”¨æ»¾å‹• (éœ€é‡æ–°å•Ÿå‹• Spark) +checkbox.use.compression = 使用壓縮 +checkbox.use.debugger.on.startup = 在開機時啟動åµéŒ¯ç¨‹åº +checkbox.allow.buzz = (&Z) å…許è¯çµ¡äººä¸»å‹•çµ¦æ‚¨ç™¼è¨Šæ¯ +checkbox.enable.emoticons = (&O) 啟動表情符號功能 +checkbox.use.system.look.and.feel = (&F) 使用系統外觀(éœ€é‡æ–°å•Ÿå‹• Spark) +checkbox.use.hostname.as.resource = 使用主機åä½œç‚ºä¾†æº +checkbox.use.version.as.resource = 使用 Spark ç‰ˆæœ¬ä½œç‚ºä¾†æº +checkbox.use.pki.authentication = 使用PKIèªè­‰ +checkbox.broadcast.hide.offline.user = éš±è—離線è¯çµ¡äºº +checkbox.show.avatars.in.contactlist = 在è¯çµ¡äººåˆ—è¡¨é¡¯ç¤ºé ­åƒ +checkbox.click.single.tray = 滑鼠點擊一下å³å¯é€²å…¥Spark的系統å‰å°(éœ€é‡æ–°å•Ÿå‹• Spark) +checkbox.sort.asc.history = å°è©±è¨˜éŒ„便—¥æœŸç”±é è€Œè¿‘æŽ’åº +checkbox.disable.prev.chat.history = ä¸é¡¯ç¤ºä¹‹å‰çš„èŠå¤©è¨˜éŒ„ +checkbox.graying.out = 淡化閒置è¯çµ¡äºº(éœ€é‡æ–°å•Ÿå‹• Spark) +checkbox.reconnect.info = æŒ‡å®šé‡æ–°é€£æŽ¥çš„顯示方å¼ï¼š +checkbox.reconnect.panel.big = æŒ‰ç…§é¢æ¿æ–¹å¼é¡¯ç¤º +checkbox.reconnect.panel.small = 按照è¯ç¹«äººåˆ†çµ„æ–¹å¼é¡¯ç¤º +checkbox.reconnect.panel.icon = 按照圖標方å¼é¡¯ç¤º +checkbox.notify.user.comes.online = ç•¶è¯çµ¡äººä¸Šç·šæ™‚通知 +checkbox.notify.user.goes.offline = ç•¶è¯çµ¡äººé›¢ç·šæ™‚通知 +checkbox.notify.typing.systemtray = åœ¨ç³»çµ±ä»»å‹™æ¬„ä¸Šé¡¯ç¤ºæ­£åœ¨æ‰“å­—è¨Šæ¯ +checkbox.notify.systemtray = 在時間工具列上跳出新訊æ¯é€šçŸ¥ +checkbox.use.krbconf = 使用krb5.conf或krb5.ini +checkbox.use.krb.dns = 使用DNS +checkbox.use.specify.below = 指定方å¼å¦‚下 +checkbox.transport.tab.setting = 在標籤中顯示å¯ç”¨çš„傳輸æœå‹™(éœ€é‡æ–°å•Ÿå‹• Spark) +checkbox.conference.tab.setting = 在標籤中顯示會議æœå‹™(éœ€é‡æ–°å•Ÿå‹• Spark) +checkbox.close.unread.message = é—œé–‰çª—å£æ™‚è©¢å•æ˜¯å¦æœ‰æœªè®€æ¶ˆæ¯ + +delete.log.permanently = 永久刪除日誌 +delete.permanently = 永久刪除嗎? + +gateway.username.password.error = éœ€è¦æä¾›ç”¨æˆ¶å稱和密碼 + +group.connection = 連線 +group.conferences.found = 找到會議æœå‹™ +group.comma.delimited = 以逗號分隔 +group.general.information = 一般資訊 +group.chat.window.information = èŠå¤©è¦–窗資訊 +group.notification.options = 通知é¸é … +group.search.form = æœå°‹æ¸…å–® +group.search.results = æœå°‹çµæžœ +group.login.information = 登入資訊 +group.empty = 此群組無在線è¯çµ¡äºº +group.offline = 離線è¯çµ¡äººç¾¤çµ„ +group.chat.name.notification = 看見你的åå­—... +group.chat.name.match = 有人在群組èŠå¤©å®¤ä¸­æåˆ°ä½ çš„åå­—: + +label.user.on.public.network = è¯çµ¡äººä½æ–¼å…¬å…±ç¶²è·¯ä¸Š +label.change.password.to = (&C) 變更密碼 +label.username = (&U) 用戶å稱 +label.name = (&N) åå­— +label.room.name = (&R) 會議室å稱 +label.room.topic = (&T) 會議室主題 +label.password = (&P) 密碼 +label.confirm.password = (&C) 確èªå¯†ç¢¼ +label.server = (&M) 域å +label.create.account = (&A) 建立新帳戶 +label.close = (&L) 關閉 +label.ok = ç¢ºèª +label.cancel = å–æ¶ˆ +label.use.default = 使用é è¨­ +label.port = (&P) 連接埠 +label.auto.login = (&A) 啟動 Spark 後自動登入 +label.old.ssl = (&U) 使用舊的連接埠 +label.host = (&H) 主機 +label.resource = (&R) è³‡æº +label.protocol = (&P) å”è­° +label.accounts = (&A) 帳戶 +label.received = (&R) æŽ¥å— +label.transfer.timeout = (&T) 傳輸超時(分é˜) : +label.transfer.download.directory = (&D) 下載檔案存放目錄 +label.find = (&F) 尋找 +label.rename.to = 釿–°å‘½å +label.contact.to.find = 尋找è¯çµ¡äºº +label.available.users.in.roster = (&A) 在線è¯çµ¡äººåˆ—表 +label.time = 時間: {0} +label.add.conference.service = (&A) 新增會議æœå‹™ +label.add.jid = (&A) 新增JID +label.message = (&M) è¨Šæ¯ +label.room = (&R) 會議室 +label.invited.users = 被邀請的è¯çµ¡äºº +label.new.nickname = 新的暱稱 +label.server.address = (&S) 伺æœå™¨ä½å€ +label.nickname = (&C) 暱稱 +label.presence = (&P) 存在 +label.priority = (&R) 優先 +label.enter.address = 進入ä½å€ +label.jabber.address = &Jabberä½å€ +label.local.time = (&L) 本地時間 +label.software = (&S) 軟體 +label.version = (&V) 版本 +label.os = (&O) æ“作系統 +label.number = (&N) 號碼 +label.dial = (&D) 撥號 +label.minutes.before.stale.chat = (&M) æœƒè­°å®¤å¤šä¹…å¾Œé€²å…¥æš«åœæ¨¡å¼ +label.company = (&C) å…¬å¸ +label.street.address = (&S) è¡—é“åœ°å€ +label.city = (&C) 城市 +label.state.and.province = (&T) å·ž/çœ +label.postal.code = (&P) 郵éžå€è™Ÿ +label.country = (&O) 国家 +label.job.title = (&J) è·ç¨± +label.department = (&D) 部門 +label.phone = (&P) 電話 +label.fax = (&F) 傳真 +label.mobile = (&M) 手機號碼 +label.web.page = (&W) ç¶²é  +label.pager = (&P) 呼å«å™¨ +label.first.name = (&F) åå­— +label.middle.name = (&M) 中間å +label.last.name = (&L) å§“ +label.email.address = (&E) é›»å­éƒµä»¶ +label.jid = &JID +label.search.service = (&S) æœå°‹æœå‹™ +label.xmpp.port = (&X) XMPP 連接埠 +label.response.timeout = (&R) 回應逾時(ç§’) +label.time.till.idle = (&T) é–’ç½®æ™‚é‡æ–°é€£æŽ¥æ™‚é–“(分é˜) +label.jabber.id = &Jabber 編號 +label.group = (&G) 群組 +label.enter.group.name = 輸入新的群組å稱 +label.network = (&K) 網路 +label.unable.to.add.contact = 無法新增è¯çµ¡äººã€‚ +label.conflict.error = 帳戶已經登入,無法é‡è¦†ç™»å…¥ +label.message.style = (&M) è¨Šæ¯æ¨£å¼ +label.emoticons = (&E) 表情 +label.which.pki.method = 其中PKI方法? +label.keystore.location = 鑰匙儲存ä½ç½® +label.choose.file = 鏿“‡æª”案 +label.truststore.location = 信任庫ä½ç½® +label.trust.store.password = 信任庫密碼 +label.pkcs.library.file = PKCS#11庫文件 +label.apple.keychain = Apple鑰匙圈 +label.na = n/a +label.cell = 元件 +label.work = 工作 +label.home = é¦–é  +label.passwordreset = é‡è¨­å¯†ç¢¼ +label.add.task = 新增任務 +label.avatar = é ­åƒåœ–片: +label.chatroom.fontsize = èŠå¤©å®¤å­—體大å°: +label.chatroom.maxcurrenthistorysize = æœ€å¤§ç•¶å‰æ­·å²è¨˜éŒ„大å°: +label.recent.conversation = 最近的å°è©± +label.frequent.contacts = 常用è¯çµ¡äºº +label.contactlist.avatarsize = è¯çµ¡äººåˆ—表頭åƒåœ–片大å°: +label.contactlist.fontsize = è¯çµ¡äººåˆ—表字體大å°: +label.display.time = 顯示時間: +label.downloads = 下載 +label.due = 應有 +label.search = æœå°‹ +label.seconds = ç§’ +label.show = 顯示: +label.time.till.idlemessage = é–’ç½®æ™‚è‡ªå‹•é¡¯ç¤ºè¨Šæ¯ +label.timeformat = 時間: {0} +label.krb.realm = å€åŸŸ +label.krb.kdc = KDC +label.enter.password = 輸入密碼 +label.move.focus.forwards = ç„¦é»žç§»å‹•è‡³å‰æ–¹ +label.move.focus.backwards = 焦點移動至後方 +label.x509.certificate = X.509 證書 +label.add.to.roster = 新增è¯çµ¡äººåˆ°å單中 +label.audio.device = 音頻設備 +label.video.device = 視頻設備 + +menuitem.connect = 文件 +menuitem.contacts = è¯çµ¡äºº +menuitem.actions = 活動 +menuitem.exit = 離開 +menuitem.plugins = æ’ä»¶ +menuitem.logout.no.status = 登出 +menuitem.logout.with.status = 記錄登出的ç†ç”± +menuitem.show.traffic = 顯示通信é‡è¦–窗 +menuitem.check.for.updates = 檢查更新 +menuitem.help = 說明 +menuitem.preferences = 設定 +menuitem.about = 關於 +menuitem.online.help = 線上說明 +menuitem.open = 打開 +menuitem.hide = éš±è— +menuitem.status = 狀態 +menuitem.view.downloads = 查看下載目錄 +menuitem.save = 儲存 +menuitem.add = 新增 +menuitem.add.contact = 新增è¯çµ¡äºº +menuitem.add.contact.group = 新增è¯çµ¡äººç¾¤çµ„ +menuitem.remove.from.group = 從群組中移除 +menuitem.start.a.chat = é–‹å§‹èŠå¤© +menuitem.rename = 釿–°å‘½å +menuitem.delete = 刪除 +menuitem.edit = 編輯 +menuitem.remove.from.roster = 從å單中移除 +menuitem.view.profile = 查看簡介 +menuitem.subscribe.to = åŒæ„ +menuitem.send.a.message = 將廣播訊æ¯é€çµ¦æŒ‡å®šçš„è¯çµ¡äºº ... +menuitem.show.empty.groups = 顯示空的群組 +menuitem.send.a.file = 傳逿ª”案 +menuitem.view.last.activity = 查看最後一個活動 +menuitem.unban = å–æ¶ˆç¦æ­¢ +menuitem.ban = ç¦æ­¢ +menuitem.browse.service = ç€è¦½æœå‹™ +menuitem.remove.service = 移除æœå‹™ +menuitem.join.room = åŠ å…¥é¸æ“‡çš„æœƒè­°å®¤ +menuitem.remove.bookmark = 移除書籤 +menuitem.join.on.startup = 系統啟動時連接 +menuitem.view.room.info = 查看會議室資訊 +menuitem.remove = 移除 +menuitem.change.nickname = 修改暱稱 +menuitem.block.user = å°éŽ–æ­¤ç”¨æˆ¶ +menuitem.unblock.user = 解除å°éŽ–æ­¤ç”¨æˆ¶ +menuitem.kick.user = 踢除此用戶 +menuitem.voice = 發言 +menuitem.revoke.voice = å–æ¶ˆç™¼è¨€æ¬Š +menuitem.grant.voice = 授予發言權 +menuitem.ban.user = ç¦æ­¢æ­¤ç”¨æˆ¶ +menuitem.grant.moderator = 授予主æŒäºº +menuitem.revoke.moderator = 撤銷主æŒäºº +menuitem.invite.users = 邀請使用者 +menuitem.invite.group.to.conference = 邀請群組到會議中 +menuitem.start.a.conference = 開啟會議室 ... +menuitem.change.subject = 變更主題 +menuitem.destroy.room = 撤銷會議室 +menuitem.set.status.message = è¨­ç½®ç‹€æ…‹æ¶ˆæ¯ ... +menuitem.edit.status.message = ç·¨è¼¯è‡ªå®šç¾©ç‹€æ…‹æ¶ˆæ¯ ... +menuitem.broadcast.to.group = å°ç¾¤çµ„廣播 +menuitem.alert.when.online = 用戶在線時顯示通知 +menuitem.remove.alert.when.online = 撤銷通知 +menuitem.save.as = å¦å­˜ç‚º ... +menuitem.view.client.version = 查看客戶端版本 +menuitem.view.contact.history = æŸ¥çœ‹äº¤è«‡çš„æ­·å² +menuitem.edit.my.profile = 編輯我的個人簡介 ... +menuitem.lookup.profile = 查閱個人簡介 ... +menuitem.add.as.contact = 新增為è¯çµ¡äºº +menuitem.chat = èŠå¤© +menuitem.sign.in = 簽到 +menuitem.sign.out = 簽離 +menuitem.sign.in.at.login = 登入時簽到 +menuitem.enter.login.information = 輸入登入資訊 +menuitem.delete.login.information = 刪除登入資訊 +menuitem.show.offline.group = 顯示群組離線è¯çµ¡äºº +menuitem.move.to = 移動到 +menuitem.copy.to = 複製到 +menuitem.bookmarks = 書籤 +menuitem.add.groupchat.myname = 有人æåˆ°æˆ‘çš„å字時,標記出我的åå­— +menuitem.add.groupchat.mytext = 我在發言時,標記出我的èŠå¤©è¨Šæ¯ +menuitem.add.groupchat.popname = 有人æåˆ°æˆ‘çš„å字時,彈出æç¤ºè¦–窗 +menuitem.add.groupchat.showjoinleavemessage = é¡¯ç¤ºåŠ å…¥èˆ‡é›¢é–‹è¨Šæ¯ +menuitem.add.groupchat.showrolesinsteadofstatus = 顯示èŠå¤©è§’色圖標å–代狀態圖標 +menuitem.add.groupchat.auto.accept.invite = 自動接å—群組èŠå¤©é‚€è«‹ +menuitem.add.groupchat.random.colors = 暱稱的é¡è‰²éš¨æ©ŸæŒ‡ç¤º +menuitem.always.on.top = Spark 颿¿ç¸½æ˜¯åœ¨æœ€å‰é¢ +menuitem.dial = 撥號 +menuitem.affiliation = è¯çµ¡ +menuitem.grant.member = 授予會員資格 +menuitem.grant.admin = 授予管ç†è€…資格 +menuitem.grant.owner = æŽˆäºˆæ“æœ‰è€…資格 +menuitem.languages = èªžè¨€é¸æ“‡ +menuitem.open.with = 開啟... +menuitem.block.contact = å°éŽ–æ­¤è¯çµ¡äºº +menuitem.unblock.contact = 解除å°éŽ–æ­¤è¯çµ¡äºº +menuitem.revoke.member = å–æ¶ˆæœƒå“¡è³‡æ ¼ +menuitem.revoke.admin = å–æ¶ˆç®¡ç†è€…資格 +menuitem.revoke.owner = å–æ¶ˆæ“有者資格 +menuitem.user.guide = æ“作說明 +menuitem.view.logs = 查看日誌 +menuitem.show.offline.users = 顯示離線è¯çµ¡äºº +menuitem.show.contact.statusmessage = 顯示è¯çµ¡äººç‹€æ…‹æ¶ˆæ¯ +menuitem.bookmark.room = 書籤室 +menuitem.refresh = 刷新 +menuitem.create.room = 新創或加入會議室 +menuitem.expand.all.groups = 展開所有群組 +menuitem.collapse.all.groups = ç¸®å°æ‰€æœ‰ç¾¤çµ„ +menuitem.invite.again = 冿¬¡é‚€è«‹ +menuitem.chatframe.option = é¸é … +menuitem.add.groupchat.invitetobookmark = 自動邀請è¯çµ¡äººåˆ°æ›¸ç±¤å®¤ + +message.invite.to.groupchat = 邀請您加入群組èŠå¤© ... +message = è¨Šæ¯ +message.account.create = 新創一個èŠå¤©å¸³æˆ¶ +message.account.created = 新帳戶已創建 +message.account.error = 在指定的伺æœå™¨ä¸Šå‰µå»ºå¸³æˆ¶ +message.add.a.contact = 新增è¯çµ¡äºº +message.add.conference.service = 新增會議æœå‹™ +message.add.contact.to.list = 將用戶新增到您的è¯çµ¡äººåˆ—表 +message.add.favorite.room = 新增此會議室到最愛清單,或直接加入此會議室 +message.add.this.user.to.your.roster = 將此è¯çµ¡äººæ–°å¢žåˆ°ä½ çš„好å‹åˆ—表 +message.add.to.roster = 新增到å單列表中 +message.add.user = å°‡è¯çµ¡äººåŠ å…¥æ‚¨çš„å單列表中嗎? +message.alert.notify = 緊急通知 +message.already.exists = 帳戶已存在,請嘗試使用ä¸åŒçš„用戶å +message.approve.subscription = å…許在他們的å單列表中新增您嗎? +message.authenticating = èªè­‰ +message.away.idle = 由於閒置éŽä¹…,因此顯示離開 +message.bookmark.temporary.room.error = ä¸å¯å°‡è‡¨æ™‚的會議室設為書籤室 +message.broadcast.from = 從 ... 廣播 +message.broadcast.no.user.selected = è‡³å°‘é¸æ“‡ä¸€å€‹æŽ¥æ”¶è€… +message.broadcast.no.text = 輸入文字廣播 +message.broadcast.message.sent = 該廣播訊æ¯å·²ç™¼é€ +message.broadcast.to = 輸入的訊æ¯å»£æ’­åˆ° ... +message.hasbeenbroadcast.to = 該訊æ¯å·²è¢«å»£æ’­çµ¦ä»¥ä¸‹ç”¨æˆ¶ : +message.buzz.alert.notification = ç²å–用戶的關注 +message.buzz.message = 希望得到你的關注 +message.buzz.sent = 請用戶關注 +message.calling = å‘¼å« +message.came.online = {0} 在線 {1} +message.cannot.add.contact.to.shared.group = ä¸èƒ½åœ¨å…±äº«ç¾¤çµ„中新增新的è¯çµ¡äºº +message.chat.session.ended = èŠå¤©å°è©±å·²ç¶“çµæŸ +message.click.to.open = 點擊後開啟 +message.client.information = å®¢æˆ¶ä¿¡æ¯ +message.close.other.chats = 關閉所有其他的èŠå¤© +message.close.stale.chats = 關閉之å‰çš„èŠå¤©è¨˜éŒ„ +message.close.this.chat = 關閉這個èŠå¤©è¦–窗 +message.close.unread.window = 您有未讀消æ¯ï¼Œç¢ºå®šè¦é—œé–‰çª—å£å—Žï¼Ÿ +message.conference.info.error = 無法檢索會議信æ¯,è«‹ç¨å¾Œå†è©¦ +message.conference.service.error = 無法找到會議æœå‹™ +message.confirm.destruction.of.room = 刪除此會議室將使裡é¢çš„è¯ç¹«äººé›¢é–‹,是å¦ç¹¼çºŒ? +message.confirmation.password.error = 指定確èªéŽçš„密碼 +message.connecting.please.wait = 連接中,è«‹ç¨å€™ ... +message.connection.failed = 無法連接到 ... +message.create.account = 無法創建帳戶 +message.create.or.join.room = 創建或加入會議èŠå¤©å®¤ +message.current.status = 讓別人知é“你的當å‰ç‹€æ…‹æˆ–活動 +message.default.error = 已檢測到錯誤,請回報 support@jivesoftware.com +message.delete.all.history = åˆªé™¤ä»¥å‰æ‰€æœ‰çš„å°è©±? +message.delete.confirmation = 你確定è¦åˆªé™¤? +message.disable.transport = 從 ... 移除登入信æ¯å—Ž? +message.disconnected.conflict.error = 您已從他處登入,因此此處連接被關閉 +message.disconnected.error = 由於您的連接錯誤,因此被關閉 +message.disconnected.group.chat.error = 由於發生錯誤,所以您的連接被關閉.釿–°é€£æŽ¥æˆåŠŸæ™‚, Spark æœƒè‡ªå‹•é‡æ–°é€£æŽ¥åˆ°æ­¤é€£æŽ¥åŸ  +message.disconnected.shutdown = 因伺æœå™¨è¢«é—œé–‰,所以您的連接被關閉 +message.downloading = 下載中 +message.downloading.spark.plug = 下載 Spark æ’ä»¶ +message.end.chat = ä½ æƒ³çµæŸé€™å ´èŠå¤©å—Ž? +message.end.conversation = ä½ æƒ³çµæŸé€™å ´æœƒè­°å—Ž? +message.enter.broadcast.message = 輸入訊æ¯å»£æ’­åˆ°é¸å®šçš„用戶 +message.enter.gadugadu = 以下輸入您的 GaduGadu 用戶å稱和密碼 +message.enter.irc = 以下輸入您的 IRC 用戶å稱, 密碼和暱稱 +message.enter.sametime = 以下輸入您的 Sametime 用戶å稱和密碼 +message.enter.facebook = 以下輸入您的 Facebook 用戶å稱和密碼 +message.enter.myspace = 以下輸入您的 MySpace 用戶å稱和密碼 +message.enter.jabber.id = 輸入 Jabber ID +message.enter.message.to.broadcast = 輸入訊æ¯å»£æ’­åˆ°æ•´å€‹å單列表 +message.enter.new.subject = 輸入新的主題 +message.enter.qq = 以下輸入您的 QQ 號碼和密碼 +message.enter.room.password = 輸入會議室密碼 +message.enter.simple = 以下輸入您的 SIMPLE 用戶å稱和密碼 +message.enter.valid.jid = 輸入一個有效的 Jabber ID +message.enter.xmpp = 以下輸入您的 XMPP 用戶å稱和密碼 +message.error.during.file.transfer = 文件傳é€éŽç¨‹ä¸­æœ‰éŒ¯èª¤ç™¼ç”Ÿ +message.file.exists.question = 此檔案已經存在,確定å–代它嗎? +message.file.size = æ–‡ä»¶å¤§å° : +message.file.transfer.canceled = æ‚¨å·²å–æ¶ˆæ–‡ä»¶å‚³è¼¸ +message.file.transfer.rejected = 此文件ä¸èƒ½è¢«å‚³è¼¸ +message.file.transfer.dirnull = 文件下載目錄無效 +message.file.transfer.nodir = 文件下載的目錄ä¸å­˜åœ¨ +message.file.transfer.cantwritedir = ä¸èƒ½å¯«å…¥è©²ç›®éŒ„的文件傳輸 +message.file.transfer.notification = 文件傳輸通知 +message.file.transfer.short.message = 呿‚¨ç™¼é€ä¸€å€‹å為 : +message.file.transfer.chat.window = 文件傳輸請求: +message.file.transfer.file.too.big.error = 鏿“‡çš„æ–‡ä»¶æª”案太大,鏿“‡çš„æ–‡ä»¶å¤§å°æœ€å¤§é™åˆ¶ç‚º : +message.file.transfer.file.too.big.warning = é¸å®šçš„æ–‡ä»¶éŽå¤§.ä»ç„¶ç¹¼çºŒå—Ž? +message.file.transfer.direrror.setdir = 點擊此處更改目錄 +message.find.conference.services = æœå°‹æœƒè­°æœå‹™ +message.forbidden.error = 從伺æœå™¨ä¸ŠæŽ¥æ”¶åˆ°ä¸€å€‹éŒ¯èª¤è¨Šæ¯ +message.gateway.username.error = éœ€è¦æä¾›ç”¨æˆ¶å稱 +message.gateway.password.error = éœ€è¦æä¾›å¯†ç¢¼ +message.gateway.nickname.error = éœ€è¦æä¾›æš±ç¨± +message.general.error = 由於 {0} , 您已從伺æœå™¨ä¸­æ–·ç·š +message.generic.reconnect.message = 您已從伺æœå™¨æ–·ç·š, 請點擊下é¢çš„釿–°é€£æŽ¥æŒ‰éˆ•釿–°ç™»å…¥ +message.idle.for = é–’ç½® {0} +message.image.too.large = 此圖片是太大而ä¸èƒ½ä½¿ç”¨, 請指定圖åƒç‚º 16K æˆ–æ›´å° +message.invalid.jabber.id = 䏿˜¯æœ‰æ•ˆçš„ Jabber ID +message.invalid.jid.error = 指定的 JID 無效 +message.invalid.status = æŒ‡å®šä¸€å€‹æœ‰æ•ˆçš„ç‹€æ…‹è¨Šæ¯ +message.invalid.username.password = 無效的用戶å稱或密碼 +message.invite.users.to.conference = 邀請è¯çµ¡äººåˆ°æœƒè­°å®¤ +message.is.shared.group = {0} 是一個共享群組 +message.is.typing.a.message = {0} 正在輸入訊æ¯... +message.join.conference.room = 加入會議室 +message.kicked.error = ä½ æ˜¯ä¸æ˜¯èƒ½å¤ è¸¢é™¤ {0} 離開這個會議室 +message.last.message.received = æ”¶åˆ°çš„æœ€å¾Œä¸€æ¢æ¶ˆæ¯ {0} +message.loading.please.wait = 載入中. è«‹ç¨å€™... +message.locked.workstation = 用戶已鎖定其工作站 +message.name.of.group = 群組å稱 +message.name.of.search.service.question = æœå°‹æœå‹™å稱? +message.negotiate.file.transfer = å°è«‡æ–‡ä»¶å‚³è¼¸ä¸­, è«‹ç¨å€™... +message.negotiate.stream = å°è«‡æµç¨‹é€£æŽ¥ä¸­, è«‹ç¨å€™... +message.negotiation.file.transfer = å°è«‡æ–‡ä»¶å‚³è¼¸ {0}, è«‹ç¨å€™... +message.new.message = 新訊æ¯ä¾†è‡ª {0} +message.new.spark.available = {0} ç¾åœ¨æ˜¯å¯ç”¨çš„, 你想安è£å—Ž? +message.nickname.in.use = 暱稱已被使用, 請指定其他暱稱 +message.nickname.not.acceptable = 暱稱變更未啟用! +message.no.avatar.found = 用戶沒有設定頭åƒåœ–示 +message.no.caller.id = 無來電顯示å¯ç”¨ +message.no.description.available = 沒有å¯ç”¨çš„æè¿° +message.no.history.found = 無與該è¯çµ¡äººä»¥å‰çš„å°è©±æ­·å²ç´€éŒ„ +message.no.results.found = 由伺æœå™¨å›žè¦†ç„¡æœå°‹çµæžœ +message.no.room.to.join.error = 沒有會議室å¯åŠ å…¥ +message.no.subject.available = 無主題å¯ç”¨ +message.no.updates = 沒有更新 +message.normal = ä¸€èˆ¬è¨Šæ¯ +message.number.to.call = æŒ‡å®šè¦æ’¥æ‰“的號碼 +message.offline = è¯çµ¡äººè™•於離線狀態,ä¸‹æ¬¡ç™»å…¥æ™‚å°‡æ”¶åˆ°é›¢ç·šè¨Šæ¯ +message.offline.error = è¯çµ¡äººå°‡ç„¡æ³•æŽ¥æ”¶é›¢ç·šæ¶ˆæ¯ +message.participants.in.room = 會議室內的åƒèˆ‡è€… +message.password.error = 指定此帳戶的密碼 +message.password.private.room.error = 指定密碼的ç§äººæœƒè­°å®¤ +message.passwords.no.match = 密碼ä¸ç›¸ç¬¦ +message.please.join.in.conference = 請加入我的會議 +message.plugins.not.available = 無法è¯ç¹«çš„æ’ä»¶åº« +message.prompt.plugin.uninstall = 你確定è¦åœç”¨ {0} å—Ž? +message.received.file = 您從 {0} 收到一個文件 +message.receiving.file = 您從 {0} 收到文件 +message.reconnect.attempting = 嘗試中... +message.reconnect.failed = 釿–°é€£æŽ¥å¤±æ•— +message.reconnect.wait = 在 {0} ç§’é‡æ–°é€£æŽ¥ +message.register.transports = 這些å¯ç”¨å‚³è¼¸è¨»å†Š +message.registering = 註冊中 {0}, è«‹ç¨å€™... +message.registration.transport.failed = 無法與門戶註冊 +message.restart.spark = 您將需è¦é—œé–‰å®¢æˆ¶ç«¯å®‰è£æ–°ç‰ˆæœ¬, 你想ç¾åœ¨åšå—Ž? +message.restart.spark.changes = 下次啟動 Spark 時,æ’件將被移除 +message.restart.spark.to.install = 您需è¦é—œé–‰å®¢æˆ¶ç«¯å®‰è£æœ€æ–°ç‰ˆæœ¬, 你想ç¾åœ¨åšå—Ž? +message.restart.required = 您將需è¦é‡æ–°å•Ÿå‹• Spark 使更改生效, ç¾åœ¨é‡æ–°å•Ÿå‹•å—Ž? +message.room.creation.error = 無法創建會議室 +message.room.destroyed = 這個會議室已被撤銷,由於以下原因: {0} +message.room.destruction.reason = 撤銷此會議室的原因? +message.room.information.for = 會議室資訊 {0} +message.save.profile = è¦å„²å­˜æ‚¨æ›´æ”¹çš„個人資料, 點é¸å„²å­˜ +message.search.for.contacts = æœå°‹è¯çµ¡äºº +message.search.for.other.people = 在此伺æœå™¨ä¸Šæœå°‹å…¶ä»–è¯çµ¡äºº +message.search.service.not.available = è¯ç¹«ä¸åˆ°æœå°‹æœå‹™ +message.searching.please.wait = æœå°‹ä¸­, è«‹ç¨å€™... +message.select.add.room.to.add = è«‹é¸æ“‡ä¸€å€‹æœƒè­°æ˜¯æ–°å¢žåˆ°æ‚¨çš„æœå‹™åˆ—è¡¨ +message.select.one.or.more = 在你的å單䏭鏿“‡ä¸€å€‹æˆ–多個用戶 +message.select.room.to.enter = 指定進入會議室 +message.select.room.to.join = 鏿“‡åŠ å…¥æœƒè­°å®¤ +message.send.a.broadcast = 發é€å»£æ’­ +message.send.file.to.user = ç™¼é€æ–‡ä»¶çµ¦æ­¤ç”¨æˆ¶ +message.send.picture = 在螢幕上截å–圖示 +message.send.to.these.people = 發é€çµ¦é€™äº›äºº +message.sending.file.to = ç™¼é€æ–‡ä»¶ {0} +message.sent.offline.files = 你被發é€é›¢ç·šæ–‡ä»¶ +message.server.unavailable = 無法連接到伺æœå™¨: 無效的å稱或伺æœå™¨ç„¡æ³•åˆ°é” +message.service.already.exists = æœå‹™å·²ç¶“在你的æœå‹™åˆ—表中 +message.shared.group = 共享群組 +message.specify.contact.jid = 請註明è¯çµ¡äººçš„ JID (例如. ddman@jabber.org) +message.specify.group = 將新用戶新增至指定的è¯çµ¡äººç¾¤çµ„ +message.specify.information.for.conference = æŒ‡å®šæœƒè­°å®¤è¨Šæ¯ +message.specify.name.error = 指定一個有效的å稱 +message.specify.users.to.join.conference = 指定用戶加入這個會議室 +message.specify.valid.time.error = 指定一個有效的超時和連接埠 +message.subject.change.error = 您無權更改此房間的主題 +message.subject.has.been.changed.to = {1} 改變會議主題為 "{0}" +message.supply.resource = æä¾›ä¸€å€‹æœ‰æ•ˆçš„è³‡æº +message.supply.valid.port = æä¾›ä¸€å€‹æœ‰æ•ˆçš„連接埠 +message.supply.valid.timeout = æä¾›ä¸€å€‹æœ‰æ•ˆçš„超時值 +message.timeout.error = 超時值必須是 5 秒或更大 +message.total.downloaded = 總下載 +message.transfer.cancelled = æ–‡ä»¶å‚³è¼¸è¢«å–æ¶ˆ +message.transfer.complete = æ–‡ä»¶å‚³è¼¸å®Œæˆ ({0}) +message.transfer.progressbar.text.received = {0} æŽ¥å— @ {1} {2} +message.transfer.progressbar.text.sent = {0} ç™¼é€ @ {1} {2} +message.transfer.rate = 傳輸速率 +message.transfer.refused = 文件傳輸被拒絕 +message.transfer.waiting.on.user = 等待 {0} æŽ¥å—æ–‡ä»¶å‚³è¼¸ +message.unable.to.load.profile = 無法從 {0} 找到個人簡介 +message.unable.to.retrieve.last.activity = 無法確定最後一個活動 {0} +message.unable.to.save.password = 無法更改密碼, è«‹è¯ç¹«æ‚¨çš„伺æœå™¨ç®¡ç†å“¡ +message.unable.to.send.file = 你無法將文件發é€åˆ° {0} +message.unable.to.use.hostname.as.resource = 無法使用主機åä½œç‚ºè³‡æº +message.unrecoverable.error = 無效的用戶å稱或密碼 +message.update.room.list = 更新會議室列表 +message.updating.cancelled = æ›´æ–°å·²è¢«å–æ¶ˆ +message.user.banned = {0} å·²è¢«ç¦æ­¢é€²å…¥é€™å€‹æœƒè­°å®¤.原因: {1} +message.user.given.voice = {0} 在這個會議室中被授予發言權 +message.user.granted.admin = {0} 已被授予管ç†å“¡æ¬Šé™ +message.user.granted.membership = {0} å·²è¢«æŽˆäºˆæœƒå“¡æ¬Šé™ +message.user.granted.moderator = {0} 已被授予主æŒäººæ¬Šé™ +message.user.granted.owner = {0} å·²è¢«æŽˆäºˆæ“æœ‰è€…æ¬Šé™ +message.user.is.sending.you.a.file = {0} æ­£åœ¨ç™¼é€æ‚¨çš„æ–‡ä»¶ +message.user.joined.room = {0} 已加入會議室 +message.user.kicked.from.room = {0} 已經由 {1} 踢出了房間 .原因: {2} +message.user.left.room = {0} 已經離開會議室 +message.user.nickname.changed = {0} ç¾åœ¨è¢«ç¨±ç‚º {1} +message.user.now.available.to.chat = {0} 在線上 {1} +message.user.revoked.admin = 管ç†å“¡æ¬Šé™å·²è¢«æ’¤éŠ· {0} +message.user.revoked.membership = 會員資格已被撤銷 {0} +message.user.revoked.moderator = 主æŒäººæ¬Šé™å·²è¢«æ’¤éŠ· {0} +message.user.revoked.owner = 所有者權é™å·²è¢«æ’¤éŠ· {0} +message.user.voice.revoked = 發言權已經被撤銷 {0} +message.username.error = 指定一個用戶å稱作為帳戶 +message.username.password.error = éœ€è¦æä¾›ç”¨æˆ¶å稱和密碼 +message.vcard.not.supported = 伺æœå™¨ä¸æ”¯æŒé›»å­å片,無法ä¿å­˜æ‚¨çš„é›»å­å片 +message.version = 版本: {0} +message.view.information.about.this.user = 查看關於這個è¯çµ¡äººçš„資料 +message.waiting.for.user.to.join = 等待 {0} 加入 +message.went.offline = {0} 離線 {1} +message.you.have.been.banned = æ‚¨å·²è¢«ç¦æ­¢é€²å…¥é€™å€‹æœƒè­°å®¤ +message.you.have.been.kicked = 你被踢出這個房間 +message.you.have.sent = 您發é€äº†æ–‡ä»¶ +message.your.admin.granted = 您已被授予管ç†å“¡æ¬Šé™ +message.your.banned = æ‚¨å·²è¢«ç¦æ­¢é€²å…¥é€™å€‹æœƒè­°å®¤ +message.your.kicked = 您已由{0}被踢出 +message.your.membership.granted = æ‚¨å·²è¢«æŽˆäºˆæœƒå“¡æ¬Šé™ +message.your.membership.revoked = 您的會員資格已被撤銷 +message.your.moderator.granted = 您已被授予主æŒäººæ¬Šé™ +message.your.moderator.revoked = 您的主æŒäººæ¬Šé™å·²è¢«æ’¤éŠ· +message.your.ownership.granted = æ‚¨å·²è¢«æŽˆäºˆæ“æœ‰è€…æ¬Šé™ +message.your.ownership.revoked = æ‚¨çš„æ“æœ‰æ¬Šé™å·²è¢«æ’¤éŠ· +message.your.revoked.granted = ä½ çš„ç®¡ç†æ¬Šé™å·²è¢«æ’¤éŠ· +message.your.voice.granted = 在這個會議中你已被授予發言權 +message.your.voice.revoked = 你的發言權已被撤銷 +message.groupchat.require.password = 這個群組會議室需è¦è¼¸å…¥å¯†ç¢¼æ‰èƒ½é€²å…¥ +message.groupchat.registered.member = 註冊æˆåŠŸ +message.search.for.history = 查詢èŠå¤©çš„æ­·å²è¨˜éŒ„ +message.search.period.day.one = æ¯é é¡¯ç¤ºä¸€å¤©çš„æ¶ˆæ¯ +message.search.period.week.one = æ¯é é¡¯ç¤ºä¸€å‘¨çš„æ¶ˆæ¯ +message.search.period.month.one = æ¯é é¡¯ç¤ºä¸€å€‹æœˆçš„è¨Šæ¯ +message.search.period.year.one = æ¯é é¡¯ç¤ºä¸€å¹´çš„è¨Šæ¯ +message.search.period.none = 所有訊æ¯é¡¯ç¤ºåœ¨ä¸€å€‹é é¢ä¸Š +message.search.page.timeperiod = 鏿“‡ä½¿ç”¨ä»€éº¼æ™‚間跨度顯示訊æ¯,其中æ¯é é¡¯ç¤º +message.search.page.counter = ä½ çš„é é¢åœ¨ç•¶å‰ç´¢å¼•的所有網é çš„æ•¸é‡ +message.search.page.right = ä¸‹ä¸€é  +message.search.page.left = ä¸Šä¸€é  + +status.away = 離開 +status.custom.messages = è‡ªå®šç¾©æ¶ˆæ¯ +status.do.not.disturb = 請勿打擾 +status.extended.away = 長時間離開 +status.free.to.chat = 有空èŠå¤© +status.on.phone = 電話中 +status.online = 在線上 +status.pending = 連接中 +status.invisible = éš±è—æ¨¡å¼ +status.offline = 離線 + +tab.general = 一般 +tab.proxy = 代ç†ä¼ºæœå™¨ +tab.contacts = è¯çµ¡äºº +tab.installed.plugins = 已安è£çš„æ’ä»¶ +tab.available.plugins = å¯ç”¨çš„æ’ä»¶ +tab.personal = 個人 +tab.business = 商務 +tab.home = 家庭 +tab.avatar = 顯示頭åƒåœ–片 +tab.conferences = 會議 +tab.deactivated.plugins = å·²åœç”¨çš„æ’ä»¶ +tab.sso = SSO +tab.pki = PKI + +title.passwords.no.match = 確èªå¯†ç¢¼ã€‚ +title.create.problem = 建立帳戶å•題 +title.account.created = 建立帳戶 +title.create.new.account = 建立新帳戶 +title.account.create.registration = 帳戶註冊 +title.register.account = 註冊新帳戶 +title.notification = 通知 +title.advanced.connection.preferences = 進階設定 +title.preferences = 設定 +title.error = 錯誤 +title.status.message = é¡¯ç¤ºç‹€æ…‹è¨Šæ¯ +title.spark.preferences = Spark å好設定 +title.alert = 警報 +title.tray.information = æ‰˜ç›¤ä¿¡æ¯ +title.select.file.to.send = 鏿“‡è¦ç™¼é€çš„æ–‡ä»¶ +title.choose.directory = 鏿“‡ç›®éŒ„ +title.confirmation = ç¢ºèª +title.last.activity = 查看最後一個活動 +title.add.new.group = 新增群組 +title.add.to.roster = 新增到åå–® +title.find.contacts = 尋找è¯çµ¡äºº +title.rename.roster.group = åå–®ç¾¤çµ„é‡æ–°å‘½å +title.roster = åå–® +title.create.room = 新建或加入 +title.conference.rooms = 會議室 +title.invite.to.conference = 邀請åƒèˆ‡æœƒè­° +title.room.information = 會議室資訊 +title.change.nickname = 更改暱稱 +title.group.chat = 群組èŠå¤© +title.create.or.bookmark.room = 加入或新增書籤室 +title.browse.room.service = ç€è¦½æœƒè­°å®¤ +title.name = å稱 +title.address = åœ°å€ +title.advanced.connection.sso = 使用單點登入 +title.advanced.connection.usesso = 通éŽGSSAPI使用單點登錄 +title.advanced.connection.sso.noprincipal = Spark無法找到使用單點登錄的主體。這將防止SSO無法正常工作。 +title.occupants = 會議室中一般åƒèˆ‡è€… +title.browse.conference.services = ç€è¦½æœƒè­°å®¤æœå‹™ +title.find.conference.service = 尋找會議æœå‹™ +title.configure.chat.room = 設定會議室 +title.conference.invitation = 會議室邀請 +title.join.conference.room = 加入會議室 +title.view.room.information = 查看會議室資訊 +title.configure.room = 設定會議室資訊 +title.change.subject = 變更主題 +title.enter.reason = 輸入ç†ç”± +title.room.destroyed = 撤銷會議室 +title.edit.custom.message = ç·¨è¼¯è‡ªå®šç¾©ç‹€æ…‹æ¶ˆæ¯ +title.set.status.message = è¨­å®šç‹€æ…‹æ¶ˆæ¯ +title.broadcast.message = å»£æ’­è¨Šæ¯ +title.start.chat = é–‹å§‹èŠå¤© +title.view.bookmarks = 查看書籤 +title.downloads = 下載 +title.file.exists = 檔案存在 +title.disable.transport = 刪除登入資訊 +title.available.transports = å¯ç”¨çš„å‚³è¼¸æ–¹å¼ +title.transports = å‚³è¼¸æ–¹å¼ +title.registration.error = 註冊錯誤 +title.jabber.browser = ç€è¦½å™¨ +title.version.and.time = 版本和時間 +title.waiting.to.call = ç­‰å¾…å‘¼å« +title.incoming.call = å‘¼å« +title.on.the.phone = 電話中 +title.dial.phone = 撥打電話 +title.history.for = èŠå¤©æ­·å²è¨˜éŒ„ +title.reminder = æé†’ +title.plugins = æ’ä»¶ +title.general.chat.settings = 一般èŠå¤©è¨­å®š +title.chat = èŠå¤© +title.notifications = 通知 +title.sound.preferences = è²éŸ³è¨­å®š +title.sounds = è²éŸ³ +title.choose.incoming.sound = 鏿“‡å‚³å…¥çš„語音檔案 +title.choose.outgoing.sound = 鏿“‡è¼¸å‡ºçš„è²éŸ³æª”案 +title.choose.offline.sound = 鏿“‡é›¢ç·šè²éŸ³æª”案 +title.edit.profile = 編輯個人簡介 +title.profile.information = 簡介資訊 +title.profile.not.found = 找ä¸åˆ°å€‹äººç°¡ä»‹ +title.view.profile.for = 查看個人簡介 +title.lookup.profile = 查閱個人簡介 +title.add.search.service = 新增æœå°‹æœå‹™ +title.person.search = 尋找è¯çµ¡äºº +title.login.settings = 登入設定 +title.login = 登入 +title.downloading.im.client = 下載 IM 客戶端 +title.upgrading.client = 更新客戶端 +title.cancelled = è¢«å–æ¶ˆ +title.new.version.available = å¯ç”¨çš„æ–°ç‰ˆæœ¬ +title.new.client.available = å¯ç”¨çš„的新客戶端 +title.password = 密碼 +title.download.complete = ä¸‹è¼‰å®Œæˆ +title.new.roster.group = æ–°å單群組 +title.add.contact.group = 新增è¯çµ¡äººç¾¤çµ„ +title.add.contact = 新增è¯çµ¡äºº +title.file.transfer.preferences = 檔案傳輸設定 +title.file.transfer = 檔案傳輸 +title.about = 關於 +title.password.required = 需è¦è¼¸å…¥å¯†ç¢¼ +title.task.notification = 任務通知 +title.client.logs = 客戶端日誌 +title.bookmarks = 書籤 +title.advanced.connection.sso.account = 將使用桌é¢å¸³æˆ¶ç™»å…¥åˆ°æœå‹™å™¨ +title.advanced.connection.sso.unable = 無法使用單點登錄連接,請檢查你的主機和伺æœå™¨è¨­å®š +title.appearance = 外觀 +title.appearance.preferences = 自定義 +title.delete.file = 真的è¦åˆªé™¤é€™å€‹æ–‡ä»¶å—Ž? +title.error.couldnot.open.file = 無法打開文件 +title.error.delete.file = 無法刪除文件 +title.error.find.app = 無法找到åˆé©çš„æ‡‰ç”¨ +title.error.rename.file = æ–‡ä»¶ç„¡æ³•é‡æ–°å‘½å +title.file = 檔案 +title.filesize = å¤§å° +title.gadugadu.registration = GaduGadu 帳號設置 +title.general.media = 媒體設置 +title.group.chat.settings = 群èŠè¨­å®š +title.irc.registration = IRC 帳號設置 +title.sametime.registration = Sametime 帳號設置 +title.facebook.registration = Facebook 帳號設置 +title.myspace.registration = MySpace 帳號設置 +title.input.fileexplorer = 請輸入您的文件ç€è¦½å™¨çš„å稱: +title.input.newname = 請輸入新的å稱: +title.input.openwith = 請輸入您想è¦ä½¿ç”¨çš„æ‡‰ç”¨ç¨‹åºçš„å稱: +title.login.no.account = 無法確定 +title.login.error = 登入錯誤 +title.no.updates = ç„¡æ›´æ–° +title.notes = 注æ„事項 +title.qq.registration = QQ 帳號設置 +title.xmpp.registration = XMPP 帳號設置 +title.simple.registration = SIMPLE 帳戶憑證 +title.tasks = 任務 +title.appearance.showVCards = 在è¯çµ¡äººåˆ—表中查看電å­å片 +title.subscription.request = è©¢å•訂閱需求 + +tooltip.place.a.call = è«‹å‘¼å«æ­¤è¯çµ¡äºº +tooltip.view.history = 查看å°è©±æ­·å²è¨˜éŒ„ +tooltip.view.changelog = 查看變更日誌 +tooltip.view.readme = 查看關於我 +tooltip.notifications = èŠå¤©å‘¼å«å好通知 +tooltip.place.voice.call = 撥打電話給此è¯çµ¡äºº +tooltip.appearance = 改變èŠå¤©è¦–窗的外觀 +tooltip.file.transfer = 文件傳輸å好 +tooltip.send.email = 發é€é›»å­éƒµä»¶ +tooltip.start.chat = é–‹å§‹å°è©± + +tree.conference.services = 會議æœå‹™ +tree.users.in.room = 在會議室的使用者 + +lookandfeel.select = 鏿“‡å¤–è§€æ¨£å¼ +lookandfeel.change.now = ç«‹å³è®Šæ›´ +lookandfeel.tooltip.restart.no = ä¸éœ€è¦é‡æ–°å•Ÿå‹• +lookandfeel.tooltip.restart.yes = æ›´æ›å¤–觀樣å¼éœ€æŒ‰å„²å­˜ä¸”釿–°å•Ÿå‹• Spark +lookandfeel.color.label = é¡è‰² +lookandfeel.color.red = 紅色 +lookandfeel.color.green = 綠色 +lookandfeel.color.blue = è—色 +lookandfeel.color.opacity = 逿˜Žåº¦ +lookandfeel.color.saved = 儲存色彩設定 + + +##Settings for the privacy plugin +privacy.title.preferences = Spark éš±ç§å好 +privacy.title.panel = 使用滑鼠å³éµ +privacy.label.iq.desc = è©¢å• +privacy.label.pin.desc = 加入 +privacy.label.pout.desc = 移除 +privacy.label.msg.desc = è¨Šæ¯ +privacy.border.information = éš±ç§è³‡è¨Š +privacy.label.information = 使用å³éµé»žæ“Šé¸å–®ä»¥æ–°å¢žæˆ–刪除項目 +privacy.root.node = éš±ç§åˆ—表 +privacy.label.preferences = éš±ç§æ’ä»¶ +privacy.tooltip.preferences = Spark éš±ç§è¨­å®š +privacy.label.list.is.active = ç•¶å‰å·¥ä½œåˆ—表: +privacy.label.list.is.default = é è¨­åˆ—表: +privacy.border.block = å€å¡Š +privacy.pick.one.or.more = 鏿“‡ä¸€å€‹æˆ–多個項目新增到列表 +privacy.title.add.picker = 新增項目到列表 +privacy.node.contacts = è¯çµ¡æ–¹å¼ +privacy.node.groups = 群組 +privacy.menu.add.contacts = 新增è¯çµ¡äººåˆ°åˆ—表 +privacy.menu.add.groups = 新增群組到列表 +privacy.menu.add.rem.items = 從列表中刪除項目 +privacy.menu.remove = 移除 +privacy.menu.activate.list = 啟動 +privacy.menu.default.list = 設定為é è¨­ +privacy.menu.add.list = 新增列表 +privacy.menu.remove.list = 移除列表 +privacy.dialog.add.list = 請輸入列表å稱 +privacy.dialog.rem.list = 確定è¦åˆªé™¤å—Ž? +privacy.status.menu.entry = éš±ç§åˆ—表 +privacy.name.for.default.list = é è¨­ +privacy.button.no.list.selected = æœªé¸æ“‡åˆ—表 +privacy.menuitem.deactivate.current.list = 關閉 +privacy.label.not.supported = éš±ç§åˆ—è¡¨ä¸æ˜¯ç”±ä¼ºæœå™¨æ”¯æŒ + +##Stunfallback in media settings +stun.border.label = STUN 備用伺æœå™¨ +stun.server.addr = Stun 伺æœå™¨: +stun.server.port = Stun 連接埠: + +composing = 正在打字中... +paused = å·²åœæ­¢æ‰“å­— +active = {0} 正在觀看 +inactive = 正在åšå…¶ä»–事情 +gone = 正在åšå…¶ä»–事情 + +action.viewlog = 查看歷å²è¨Šæ¯ + +dialog.confirm.to.reveal.visibility.title = 你確定嗎? +dialog.confirm.to.reveal.visibility.msg = 繼續執行,éš±å½¢ç™»å…¥ç‹€æ…‹å°‡è¢«å–æ¶ˆ +dialog.confirm.close.all.conferences.if.invisible.msg = 繼續執行,所有會議室將被關閉 diff --git a/core/src/main/resources/images/Away-24x24.png b/core/src/main/resources/images/Away-24x24.png new file mode 100644 index 000000000..7266935c1 Binary files /dev/null and b/core/src/main/resources/images/Away-24x24.png differ diff --git a/src/resources/images/Away.png b/core/src/main/resources/images/Away.png similarity index 100% rename from src/resources/images/Away.png rename to core/src/main/resources/images/Away.png diff --git a/core/src/main/resources/images/DoNotDisturb-24x24.png b/core/src/main/resources/images/DoNotDisturb-24x24.png new file mode 100644 index 000000000..91f7e684b Binary files /dev/null and b/core/src/main/resources/images/DoNotDisturb-24x24.png differ diff --git a/src/resources/images/DoNotDisturb.png b/core/src/main/resources/images/DoNotDisturb.png similarity index 100% rename from src/resources/images/DoNotDisturb.png rename to core/src/main/resources/images/DoNotDisturb.png diff --git a/src/resources/images/Offline.png b/core/src/main/resources/images/Offline.png similarity index 81% rename from src/resources/images/Offline.png rename to core/src/main/resources/images/Offline.png index 50c07bb72..b16467371 100644 Binary files a/src/resources/images/Offline.png and b/core/src/main/resources/images/Offline.png differ diff --git a/src/resources/images/QueryManager.gif b/core/src/main/resources/images/QueryManager.gif similarity index 100% rename from src/resources/images/QueryManager.gif rename to core/src/main/resources/images/QueryManager.gif diff --git a/src/resources/images/Text.gif b/core/src/main/resources/images/Text.gif similarity index 100% rename from src/resources/images/Text.gif rename to core/src/main/resources/images/Text.gif diff --git a/core/src/main/resources/images/User1_32x32.png b/core/src/main/resources/images/User1_32x32.png new file mode 100644 index 000000000..9fc1ffa6b Binary files /dev/null and b/core/src/main/resources/images/User1_32x32.png differ diff --git a/core/src/main/resources/images/XAway-24x24.png b/core/src/main/resources/images/XAway-24x24.png new file mode 100644 index 000000000..31d24d5a6 Binary files /dev/null and b/core/src/main/resources/images/XAway-24x24.png differ diff --git a/core/src/main/resources/images/XAway.png b/core/src/main/resources/images/XAway.png new file mode 100644 index 000000000..868c106c2 Binary files /dev/null and b/core/src/main/resources/images/XAway.png differ diff --git a/src/resources/images/about.png b/core/src/main/resources/images/about.png similarity index 100% rename from src/resources/images/about.png rename to core/src/main/resources/images/about.png diff --git a/src/resources/images/accept.png b/core/src/main/resources/images/accept.png similarity index 100% rename from src/resources/images/accept.png rename to core/src/main/resources/images/accept.png diff --git a/src/resources/images/add.png b/core/src/main/resources/images/add.png similarity index 100% rename from src/resources/images/add.png rename to core/src/main/resources/images/add.png diff --git a/core/src/main/resources/images/add_24x24.png b/core/src/main/resources/images/add_24x24.png new file mode 100644 index 000000000..51fad3aa0 Binary files /dev/null and b/core/src/main/resources/images/add_24x24.png differ diff --git a/src/resources/images/add_contact.png b/core/src/main/resources/images/add_contact.png similarity index 100% rename from src/resources/images/add_contact.png rename to core/src/main/resources/images/add_contact.png diff --git a/src/plugins/jingle/src/resources/images/address_book.png b/core/src/main/resources/images/address_book.png similarity index 100% rename from src/plugins/jingle/src/resources/images/address_book.png rename to core/src/main/resources/images/address_book.png diff --git a/src/resources/images/ajax-loader.gif b/core/src/main/resources/images/ajax-loader.gif similarity index 100% rename from src/resources/images/ajax-loader.gif rename to core/src/main/resources/images/ajax-loader.gif diff --git a/src/resources/images/alarmclock.png b/core/src/main/resources/images/alarmclock.png similarity index 100% rename from src/resources/images/alarmclock.png rename to core/src/main/resources/images/alarmclock.png diff --git a/core/src/main/resources/images/alert.png b/core/src/main/resources/images/alert.png new file mode 100644 index 000000000..bcf2e2926 Binary files /dev/null and b/core/src/main/resources/images/alert.png differ diff --git a/src/resources/images/arrow_left_green.png b/core/src/main/resources/images/arrow_left_green.png similarity index 100% rename from src/resources/images/arrow_left_green.png rename to core/src/main/resources/images/arrow_left_green.png diff --git a/src/resources/images/arrow_right_green.png b/core/src/main/resources/images/arrow_right_green.png similarity index 100% rename from src/resources/images/arrow_right_green.png rename to core/src/main/resources/images/arrow_right_green.png diff --git a/src/resources/images/availableUser.png b/core/src/main/resources/images/availableUser.png similarity index 100% rename from src/resources/images/availableUser.png rename to core/src/main/resources/images/availableUser.png diff --git a/src/resources/images/awayUser.png b/core/src/main/resources/images/awayUser.png similarity index 100% rename from src/resources/images/awayUser.png rename to core/src/main/resources/images/awayUser.png diff --git a/src/resources/images/bell.png b/core/src/main/resources/images/bell.png similarity index 100% rename from src/resources/images/bell.png rename to core/src/main/resources/images/bell.png diff --git a/src/resources/images/blank.gif b/core/src/main/resources/images/blank.gif similarity index 100% rename from src/resources/images/blank.gif rename to core/src/main/resources/images/blank.gif diff --git a/core/src/main/resources/images/blank_24x24.png b/core/src/main/resources/images/blank_24x24.png new file mode 100644 index 000000000..e8e7b12a5 Binary files /dev/null and b/core/src/main/resources/images/blank_24x24.png differ diff --git a/src/resources/images/blue-ball.png b/core/src/main/resources/images/blue-ball.png similarity index 100% rename from src/resources/images/blue-ball.png rename to core/src/main/resources/images/blue-ball.png diff --git a/core/src/main/resources/images/blue-steel-background.png b/core/src/main/resources/images/blue-steel-background.png new file mode 100644 index 000000000..8a68afa87 Binary files /dev/null and b/core/src/main/resources/images/blue-steel-background.png differ diff --git a/src/resources/images/blueArrowDown.png b/core/src/main/resources/images/blueArrowDown.png similarity index 100% rename from src/resources/images/blueArrowDown.png rename to core/src/main/resources/images/blueArrowDown.png diff --git a/core/src/main/resources/images/blueArrowRight.png b/core/src/main/resources/images/blueArrowRight.png new file mode 100644 index 000000000..f9584b954 Binary files /dev/null and b/core/src/main/resources/images/blueArrowRight.png differ diff --git a/src/resources/images/bookmark.png b/core/src/main/resources/images/bookmark.png similarity index 100% rename from src/resources/images/bookmark.png rename to core/src/main/resources/images/bookmark.png diff --git a/src/resources/images/bookmark_add.png b/core/src/main/resources/images/bookmark_add.png similarity index 100% rename from src/resources/images/bookmark_add.png rename to core/src/main/resources/images/bookmark_add.png diff --git a/src/resources/images/bookmark_delete.png b/core/src/main/resources/images/bookmark_delete.png similarity index 100% rename from src/resources/images/bookmark_delete.png rename to core/src/main/resources/images/bookmark_delete.png diff --git a/src/resources/images/brickwall.png b/core/src/main/resources/images/brickwall.png similarity index 100% rename from src/resources/images/brickwall.png rename to core/src/main/resources/images/brickwall.png diff --git a/core/src/main/resources/images/bullet_ball_glass_clear.png b/core/src/main/resources/images/bullet_ball_glass_clear.png new file mode 100644 index 000000000..86175f7e8 Binary files /dev/null and b/core/src/main/resources/images/bullet_ball_glass_clear.png differ diff --git a/src/resources/images/businessman_view.png b/core/src/main/resources/images/businessman_view.png similarity index 100% rename from src/resources/images/businessman_view.png rename to core/src/main/resources/images/businessman_view.png diff --git a/src/resources/images/busy.gif b/core/src/main/resources/images/busy.gif similarity index 100% rename from src/resources/images/busy.gif rename to core/src/main/resources/images/busy.gif diff --git a/core/src/main/resources/images/call.png b/core/src/main/resources/images/call.png new file mode 100644 index 000000000..295c0bdc8 Binary files /dev/null and b/core/src/main/resources/images/call.png differ diff --git a/src/resources/images/cancel.gif b/core/src/main/resources/images/cancel.gif similarity index 100% rename from src/resources/images/cancel.gif rename to core/src/main/resources/images/cancel.gif diff --git a/src/resources/images/chatManager.png b/core/src/main/resources/images/chatManager.png similarity index 100% rename from src/resources/images/chatManager.png rename to core/src/main/resources/images/chatManager.png diff --git a/src/resources/images/check.png b/core/src/main/resources/images/check.png similarity index 100% rename from src/resources/images/check.png rename to core/src/main/resources/images/check.png diff --git a/core/src/main/resources/images/clipboard.png b/core/src/main/resources/images/clipboard.png new file mode 100644 index 000000000..bb120b80d Binary files /dev/null and b/core/src/main/resources/images/clipboard.png differ diff --git a/core/src/main/resources/images/close.png b/core/src/main/resources/images/close.png new file mode 100644 index 000000000..3c0557ac8 Binary files /dev/null and b/core/src/main/resources/images/close.png differ diff --git a/core/src/main/resources/images/close_dark.png b/core/src/main/resources/images/close_dark.png new file mode 100644 index 000000000..9bd280724 Binary files /dev/null and b/core/src/main/resources/images/close_dark.png differ diff --git a/core/src/main/resources/images/close_white.png b/core/src/main/resources/images/close_white.png new file mode 100644 index 000000000..c044f4d0a Binary files /dev/null and b/core/src/main/resources/images/close_white.png differ diff --git a/core/src/main/resources/images/colors.png b/core/src/main/resources/images/colors.png new file mode 100644 index 000000000..2aad3bae1 Binary files /dev/null and b/core/src/main/resources/images/colors.png differ diff --git a/src/resources/images/conference_16x16.png b/core/src/main/resources/images/conference_16x16.png similarity index 100% rename from src/resources/images/conference_16x16.png rename to core/src/main/resources/images/conference_16x16.png diff --git a/src/resources/images/conference_24x24.png b/core/src/main/resources/images/conference_24x24.png similarity index 100% rename from src/resources/images/conference_24x24.png rename to core/src/main/resources/images/conference_24x24.png diff --git a/core/src/main/resources/images/conference_32x32.png b/core/src/main/resources/images/conference_32x32.png new file mode 100644 index 000000000..3b393e38a Binary files /dev/null and b/core/src/main/resources/images/conference_32x32.png differ diff --git a/src/resources/images/copy.png b/core/src/main/resources/images/copy.png similarity index 100% rename from src/resources/images/copy.png rename to core/src/main/resources/images/copy.png diff --git a/src/resources/images/data_delete.png b/core/src/main/resources/images/data_delete.png similarity index 100% rename from src/resources/images/data_delete.png rename to core/src/main/resources/images/data_delete.png diff --git a/src/resources/images/data_find.png b/core/src/main/resources/images/data_find.png similarity index 100% rename from src/resources/images/data_find.png rename to core/src/main/resources/images/data_find.png diff --git a/src/resources/images/data_refresh.png b/core/src/main/resources/images/data_refresh.png similarity index 100% rename from src/resources/images/data_refresh.png rename to core/src/main/resources/images/data_refresh.png diff --git a/src/resources/images/default_avatar_16x16.png b/core/src/main/resources/images/default_avatar_16x16.png similarity index 100% rename from src/resources/images/default_avatar_16x16.png rename to core/src/main/resources/images/default_avatar_16x16.png diff --git a/core/src/main/resources/images/default_avatar_32x32.png b/core/src/main/resources/images/default_avatar_32x32.png new file mode 100644 index 000000000..beaf9f5aa Binary files /dev/null and b/core/src/main/resources/images/default_avatar_32x32.png differ diff --git a/core/src/main/resources/images/default_avatar_64x64.png b/core/src/main/resources/images/default_avatar_64x64.png new file mode 100644 index 000000000..28693fd38 Binary files /dev/null and b/core/src/main/resources/images/default_avatar_64x64.png differ diff --git a/src/resources/images/delete.png b/core/src/main/resources/images/delete.png similarity index 100% rename from src/resources/images/delete.png rename to core/src/main/resources/images/delete.png diff --git a/src/resources/images/deleteitem.gif b/core/src/main/resources/images/deleteitem.gif similarity index 100% rename from src/resources/images/deleteitem.gif rename to core/src/main/resources/images/deleteitem.gif diff --git a/src/resources/images/desktop.png b/core/src/main/resources/images/desktop.png similarity index 100% rename from src/resources/images/desktop.png rename to core/src/main/resources/images/desktop.png diff --git a/src/plugins/jingle/src/resources/images/divider.png b/core/src/main/resources/images/divider.png similarity index 100% rename from src/plugins/jingle/src/resources/images/divider.png rename to core/src/main/resources/images/divider.png diff --git a/src/resources/images/doc-changelog-16x16.gif b/core/src/main/resources/images/doc-changelog-16x16.gif similarity index 100% rename from src/resources/images/doc-changelog-16x16.gif rename to core/src/main/resources/images/doc-changelog-16x16.gif diff --git a/src/resources/images/doc-readme-16x16.gif b/core/src/main/resources/images/doc-readme-16x16.gif similarity index 100% rename from src/resources/images/doc-readme-16x16.gif rename to core/src/main/resources/images/doc-readme-16x16.gif diff --git a/src/resources/images/document.png b/core/src/main/resources/images/document.png similarity index 100% rename from src/resources/images/document.png rename to core/src/main/resources/images/document.png diff --git a/src/resources/images/document_add.png b/core/src/main/resources/images/document_add.png similarity index 100% rename from src/resources/images/document_add.png rename to core/src/main/resources/images/document_add.png diff --git a/core/src/main/resources/images/document_attachment-32x32.png b/core/src/main/resources/images/document_attachment-32x32.png new file mode 100644 index 000000000..2d896f873 Binary files /dev/null and b/core/src/main/resources/images/document_attachment-32x32.png differ diff --git a/core/src/main/resources/images/document_exchange.png b/core/src/main/resources/images/document_exchange.png new file mode 100644 index 000000000..d8b84eb55 Binary files /dev/null and b/core/src/main/resources/images/document_exchange.png differ diff --git a/src/resources/images/document_find.png b/core/src/main/resources/images/document_find.png similarity index 100% rename from src/resources/images/document_find.png rename to core/src/main/resources/images/document_find.png diff --git a/core/src/main/resources/images/document_info.png b/core/src/main/resources/images/document_info.png new file mode 100644 index 000000000..01ee10839 Binary files /dev/null and b/core/src/main/resources/images/document_info.png differ diff --git a/core/src/main/resources/images/document_into.png b/core/src/main/resources/images/document_into.png new file mode 100644 index 000000000..3cc620c38 Binary files /dev/null and b/core/src/main/resources/images/document_into.png differ diff --git a/src/resources/images/document_view.png b/core/src/main/resources/images/document_view.png similarity index 100% rename from src/resources/images/document_view.png rename to core/src/main/resources/images/document_view.png diff --git a/src/resources/images/documents.png b/core/src/main/resources/images/documents.png similarity index 100% rename from src/resources/images/documents.png rename to core/src/main/resources/images/documents.png diff --git a/src/resources/images/door.gif b/core/src/main/resources/images/door.gif similarity index 100% rename from src/resources/images/door.gif rename to core/src/main/resources/images/door.gif diff --git a/src/resources/images/down_arrow.gif b/core/src/main/resources/images/down_arrow.gif similarity index 100% rename from src/resources/images/down_arrow.gif rename to core/src/main/resources/images/down_arrow.gif diff --git a/src/resources/images/download.png b/core/src/main/resources/images/download.png similarity index 100% rename from src/resources/images/download.png rename to core/src/main/resources/images/download.png diff --git a/core/src/main/resources/images/dummyContact.png b/core/src/main/resources/images/dummyContact.png new file mode 100644 index 000000000..bb32d0fee Binary files /dev/null and b/core/src/main/resources/images/dummyContact.png differ diff --git a/src/resources/images/earth_connection-16x16.png b/core/src/main/resources/images/earth_connection-16x16.png similarity index 100% rename from src/resources/images/earth_connection-16x16.png rename to core/src/main/resources/images/earth_connection-16x16.png diff --git a/src/resources/images/earth_lock-16x16.png b/core/src/main/resources/images/earth_lock-16x16.png similarity index 100% rename from src/resources/images/earth_lock-16x16.png rename to core/src/main/resources/images/earth_lock-16x16.png diff --git a/src/resources/images/earth_view.png b/core/src/main/resources/images/earth_view.png similarity index 100% rename from src/resources/images/earth_view.png rename to core/src/main/resources/images/earth_view.png diff --git a/core/src/main/resources/images/emoticons/Emoticons.plist b/core/src/main/resources/images/emoticons/Emoticons.plist new file mode 100644 index 000000000..8ee6a18f9 --- /dev/null +++ b/core/src/main/resources/images/emoticons/Emoticons.plist @@ -0,0 +1,251 @@ + + + + +SparkSetVersion +1 +Emoticons + +angry.png + + Equivalents + + >:o + >:-o + >:O + >:-O + + + Name + Angry + +blush.png + + Equivalents + + :-[ + + Name + Blush + +confused.png + + Equivalents + + ?:| + + Name + Confused + +cool.png + + Equivalents + + B-) + 😎 + + Name + Cool + +cry.png + + Equivalents + + :'( + + + Name + Cry + +devil.png + + Equivalents + + ]:) + + Name + Devil + +grin.png + + Equivalents + + :-D + :D + 😄 + 😃 + 😂 + 😁 + 😀 + + + Name + Grin + +happy.png + + Equivalents + + :-) + + Name + Happy + +laugh.png + + Equivalents + + :^0 + 😅 + 😆 + + Name + Laugh + +love.png + + Equivalents + + :x + 😍 + 😘 + + Name + Love + +mischief.png + + Equivalents + + ;\ + + Name + Mischief + +sad.png + + Equivalents + + :-( + :( + + + + Name + Sad + +happy.png + + Equivalents + + :-) + :) + 😊 + 🙂 + + + + Name + Smile + +plain.png + + Equivalents + + :| + + + Name + Plain + +shocked.png + + Equivalents + + :0 + + + Name + Shocked + +silly.png + + Equivalents + + :-p + :-P + :P + :p + 😋 + 😜 + 😝 + + + Name + Tongue + +wink.png + + Equivalents + + ;-) + ;) + 😉 + + + Name + Wink + +alert.png + + Equivalents + + (!) + + Name + Alert + + + +info.png + + Equivalents + + (i) + + Name + Info + + +minus.png + + Equivalents + + (-) + + Name + Minus + + +plus.png + + Equivalents + + (+) + + Name + Plus + + +heart.png + + Equivalents + + (heart) + + Name + Heart + + + + diff --git a/core/src/main/resources/images/emoticons/alert.png b/core/src/main/resources/images/emoticons/alert.png new file mode 100644 index 000000000..722ddd609 Binary files /dev/null and b/core/src/main/resources/images/emoticons/alert.png differ diff --git a/core/src/main/resources/images/emoticons/angry.png b/core/src/main/resources/images/emoticons/angry.png new file mode 100644 index 000000000..ba2be0eda Binary files /dev/null and b/core/src/main/resources/images/emoticons/angry.png differ diff --git a/core/src/main/resources/images/emoticons/blush.png b/core/src/main/resources/images/emoticons/blush.png new file mode 100644 index 000000000..504e368ec Binary files /dev/null and b/core/src/main/resources/images/emoticons/blush.png differ diff --git a/core/src/main/resources/images/emoticons/confused.png b/core/src/main/resources/images/emoticons/confused.png new file mode 100644 index 000000000..995e273a6 Binary files /dev/null and b/core/src/main/resources/images/emoticons/confused.png differ diff --git a/core/src/main/resources/images/emoticons/cool.png b/core/src/main/resources/images/emoticons/cool.png new file mode 100644 index 000000000..25681c85e Binary files /dev/null and b/core/src/main/resources/images/emoticons/cool.png differ diff --git a/core/src/main/resources/images/emoticons/cry.png b/core/src/main/resources/images/emoticons/cry.png new file mode 100644 index 000000000..0beaaa7cb Binary files /dev/null and b/core/src/main/resources/images/emoticons/cry.png differ diff --git a/core/src/main/resources/images/emoticons/devil.png b/core/src/main/resources/images/emoticons/devil.png new file mode 100644 index 000000000..ca566bedb Binary files /dev/null and b/core/src/main/resources/images/emoticons/devil.png differ diff --git a/core/src/main/resources/images/emoticons/eyeRoll.png b/core/src/main/resources/images/emoticons/eyeRoll.png new file mode 100644 index 000000000..57338d8b5 Binary files /dev/null and b/core/src/main/resources/images/emoticons/eyeRoll.png differ diff --git a/core/src/main/resources/images/emoticons/grin.png b/core/src/main/resources/images/emoticons/grin.png new file mode 100644 index 000000000..602116dce Binary files /dev/null and b/core/src/main/resources/images/emoticons/grin.png differ diff --git a/core/src/main/resources/images/emoticons/happy.png b/core/src/main/resources/images/emoticons/happy.png new file mode 100644 index 000000000..de07c0a58 Binary files /dev/null and b/core/src/main/resources/images/emoticons/happy.png differ diff --git a/core/src/main/resources/images/emoticons/heart.png b/core/src/main/resources/images/emoticons/heart.png new file mode 100644 index 000000000..5dbccc74b Binary files /dev/null and b/core/src/main/resources/images/emoticons/heart.png differ diff --git a/core/src/main/resources/images/emoticons/info.png b/core/src/main/resources/images/emoticons/info.png new file mode 100644 index 000000000..55c80687b Binary files /dev/null and b/core/src/main/resources/images/emoticons/info.png differ diff --git a/core/src/main/resources/images/emoticons/laugh.png b/core/src/main/resources/images/emoticons/laugh.png new file mode 100644 index 000000000..0f673d11b Binary files /dev/null and b/core/src/main/resources/images/emoticons/laugh.png differ diff --git a/core/src/main/resources/images/emoticons/love.png b/core/src/main/resources/images/emoticons/love.png new file mode 100644 index 000000000..e9f8e1db6 Binary files /dev/null and b/core/src/main/resources/images/emoticons/love.png differ diff --git a/core/src/main/resources/images/emoticons/minus.png b/core/src/main/resources/images/emoticons/minus.png new file mode 100644 index 000000000..7f709712c Binary files /dev/null and b/core/src/main/resources/images/emoticons/minus.png differ diff --git a/core/src/main/resources/images/emoticons/mischief.png b/core/src/main/resources/images/emoticons/mischief.png new file mode 100644 index 000000000..884269034 Binary files /dev/null and b/core/src/main/resources/images/emoticons/mischief.png differ diff --git a/core/src/main/resources/images/emoticons/party.png b/core/src/main/resources/images/emoticons/party.png new file mode 100644 index 000000000..035adbec9 Binary files /dev/null and b/core/src/main/resources/images/emoticons/party.png differ diff --git a/core/src/main/resources/images/emoticons/plain.png b/core/src/main/resources/images/emoticons/plain.png new file mode 100644 index 000000000..6f4a78ae0 Binary files /dev/null and b/core/src/main/resources/images/emoticons/plain.png differ diff --git a/core/src/main/resources/images/emoticons/plus.png b/core/src/main/resources/images/emoticons/plus.png new file mode 100644 index 000000000..38febdd39 Binary files /dev/null and b/core/src/main/resources/images/emoticons/plus.png differ diff --git a/core/src/main/resources/images/emoticons/sad.png b/core/src/main/resources/images/emoticons/sad.png new file mode 100644 index 000000000..5b7bc9207 Binary files /dev/null and b/core/src/main/resources/images/emoticons/sad.png differ diff --git a/core/src/main/resources/images/emoticons/shocked.png b/core/src/main/resources/images/emoticons/shocked.png new file mode 100644 index 000000000..54dce70f8 Binary files /dev/null and b/core/src/main/resources/images/emoticons/shocked.png differ diff --git a/core/src/main/resources/images/emoticons/silly.png b/core/src/main/resources/images/emoticons/silly.png new file mode 100644 index 000000000..ed02eca56 Binary files /dev/null and b/core/src/main/resources/images/emoticons/silly.png differ diff --git a/core/src/main/resources/images/emoticons/sleepy.png b/core/src/main/resources/images/emoticons/sleepy.png new file mode 100644 index 000000000..48eb9c22d Binary files /dev/null and b/core/src/main/resources/images/emoticons/sleepy.png differ diff --git a/core/src/main/resources/images/emoticons/wink.png b/core/src/main/resources/images/emoticons/wink.png new file mode 100644 index 000000000..eda88f7cd Binary files /dev/null and b/core/src/main/resources/images/emoticons/wink.png differ diff --git a/core/src/main/resources/images/end_button_24x24.png b/core/src/main/resources/images/end_button_24x24.png new file mode 100644 index 000000000..ea4280069 Binary files /dev/null and b/core/src/main/resources/images/end_button_24x24.png differ diff --git a/src/resources/images/eraser.gif b/core/src/main/resources/images/eraser.gif similarity index 100% rename from src/resources/images/eraser.gif rename to core/src/main/resources/images/eraser.gif diff --git a/src/resources/images/eraser.png b/core/src/main/resources/images/eraser.png similarity index 100% rename from src/resources/images/eraser.png rename to core/src/main/resources/images/eraser.png diff --git a/src/resources/images/facebook-gray.gif b/core/src/main/resources/images/facebook-gray.gif similarity index 100% rename from src/resources/images/facebook-gray.gif rename to core/src/main/resources/images/facebook-gray.gif diff --git a/src/resources/images/facebook.gif b/core/src/main/resources/images/facebook.gif similarity index 100% rename from src/resources/images/facebook.gif rename to core/src/main/resources/images/facebook.gif diff --git a/src/resources/images/fastpath16.png b/core/src/main/resources/images/fastpath16.png similarity index 100% rename from src/resources/images/fastpath16.png rename to core/src/main/resources/images/fastpath16.png diff --git a/src/resources/images/fastpath16_offline.png b/core/src/main/resources/images/fastpath16_offline.png similarity index 85% rename from src/resources/images/fastpath16_offline.png rename to core/src/main/resources/images/fastpath16_offline.png index 34b21a559..f739249c4 100644 Binary files a/src/resources/images/fastpath16_offline.png and b/core/src/main/resources/images/fastpath16_offline.png differ diff --git a/src/resources/images/fastpath24.png b/core/src/main/resources/images/fastpath24.png similarity index 100% rename from src/resources/images/fastpath24.png rename to core/src/main/resources/images/fastpath24.png diff --git a/src/resources/images/fastpath24_offline.png b/core/src/main/resources/images/fastpath24_offline.png similarity index 100% rename from src/resources/images/fastpath24_offline.png rename to core/src/main/resources/images/fastpath24_offline.png diff --git a/core/src/main/resources/images/find.png b/core/src/main/resources/images/find.png new file mode 100644 index 000000000..1ce8ac904 Binary files /dev/null and b/core/src/main/resources/images/find.png differ diff --git a/src/resources/images/find_text.png b/core/src/main/resources/images/find_text.png similarity index 100% rename from src/resources/images/find_text.png rename to core/src/main/resources/images/find_text.png diff --git a/src/resources/images/first_aid_box.png b/core/src/main/resources/images/first_aid_box.png similarity index 100% rename from src/resources/images/first_aid_box.png rename to core/src/main/resources/images/first_aid_box.png diff --git a/src/resources/images/flag.png b/core/src/main/resources/images/flag.png similarity index 87% rename from src/resources/images/flag.png rename to core/src/main/resources/images/flag.png index 97c0c2ec6..2c7730612 100644 Binary files a/src/resources/images/flag.png and b/core/src/main/resources/images/flag.png differ diff --git a/src/resources/images/flag_blue.png b/core/src/main/resources/images/flag_blue.png similarity index 100% rename from src/resources/images/flag_blue.png rename to core/src/main/resources/images/flag_blue.png diff --git a/src/resources/images/flag_green.png b/core/src/main/resources/images/flag_green.png similarity index 100% rename from src/resources/images/flag_green.png rename to core/src/main/resources/images/flag_green.png diff --git a/src/resources/images/flag_red.png b/core/src/main/resources/images/flag_red.png similarity index 100% rename from src/resources/images/flag_red.png rename to core/src/main/resources/images/flag_red.png diff --git a/src/resources/images/flag_yellow.png b/core/src/main/resources/images/flag_yellow.png similarity index 100% rename from src/resources/images/flag_yellow.png rename to core/src/main/resources/images/flag_yellow.png diff --git a/src/resources/images/folder.png b/core/src/main/resources/images/folder.png similarity index 100% rename from src/resources/images/folder.png rename to core/src/main/resources/images/folder.png diff --git a/src/resources/images/folder_add.png b/core/src/main/resources/images/folder_add.png similarity index 100% rename from src/resources/images/folder_add.png rename to core/src/main/resources/images/folder_add.png diff --git a/src/resources/images/folder_closed.png b/core/src/main/resources/images/folder_closed.png similarity index 100% rename from src/resources/images/folder_closed.png rename to core/src/main/resources/images/folder_closed.png diff --git a/src/resources/images/folder_cubes.png b/core/src/main/resources/images/folder_cubes.png similarity index 100% rename from src/resources/images/folder_cubes.png rename to core/src/main/resources/images/folder_cubes.png diff --git a/src/resources/images/folder_delete.png b/core/src/main/resources/images/folder_delete.png similarity index 100% rename from src/resources/images/folder_delete.png rename to core/src/main/resources/images/folder_delete.png diff --git a/src/resources/images/folder_document.png b/core/src/main/resources/images/folder_document.png similarity index 100% rename from src/resources/images/folder_document.png rename to core/src/main/resources/images/folder_document.png diff --git a/src/resources/images/folder_edit.png b/core/src/main/resources/images/folder_edit.png similarity index 100% rename from src/resources/images/folder_edit.png rename to core/src/main/resources/images/folder_edit.png diff --git a/src/resources/images/folder_forbidden.png b/core/src/main/resources/images/folder_forbidden.png similarity index 100% rename from src/resources/images/folder_forbidden.png rename to core/src/main/resources/images/folder_forbidden.png diff --git a/src/resources/images/folder_gear.png b/core/src/main/resources/images/folder_gear.png similarity index 100% rename from src/resources/images/folder_gear.png rename to core/src/main/resources/images/folder_gear.png diff --git a/src/resources/images/folder_information.png b/core/src/main/resources/images/folder_information.png similarity index 100% rename from src/resources/images/folder_information.png rename to core/src/main/resources/images/folder_information.png diff --git a/src/resources/images/folder_into.png b/core/src/main/resources/images/folder_into.png similarity index 100% rename from src/resources/images/folder_into.png rename to core/src/main/resources/images/folder_into.png diff --git a/src/resources/images/folder_lock.png b/core/src/main/resources/images/folder_lock.png similarity index 100% rename from src/resources/images/folder_lock.png rename to core/src/main/resources/images/folder_lock.png diff --git a/src/resources/images/folder_movie.png b/core/src/main/resources/images/folder_movie.png similarity index 100% rename from src/resources/images/folder_movie.png rename to core/src/main/resources/images/folder_movie.png diff --git a/src/resources/images/folder_music.png b/core/src/main/resources/images/folder_music.png similarity index 100% rename from src/resources/images/folder_music.png rename to core/src/main/resources/images/folder_music.png diff --git a/src/resources/images/folder_network.png b/core/src/main/resources/images/folder_network.png similarity index 100% rename from src/resources/images/folder_network.png rename to core/src/main/resources/images/folder_network.png diff --git a/src/resources/images/folder_new.png b/core/src/main/resources/images/folder_new.png similarity index 100% rename from src/resources/images/folder_new.png rename to core/src/main/resources/images/folder_new.png diff --git a/src/resources/images/folder_ok.png b/core/src/main/resources/images/folder_ok.png similarity index 100% rename from src/resources/images/folder_ok.png rename to core/src/main/resources/images/folder_ok.png diff --git a/src/resources/images/folder_out.png b/core/src/main/resources/images/folder_out.png similarity index 100% rename from src/resources/images/folder_out.png rename to core/src/main/resources/images/folder_out.png diff --git a/src/resources/images/folder_preferences.png b/core/src/main/resources/images/folder_preferences.png similarity index 100% rename from src/resources/images/folder_preferences.png rename to core/src/main/resources/images/folder_preferences.png diff --git a/src/resources/images/folder_refresh.png b/core/src/main/resources/images/folder_refresh.png similarity index 100% rename from src/resources/images/folder_refresh.png rename to core/src/main/resources/images/folder_refresh.png diff --git a/src/resources/images/folder_time.png b/core/src/main/resources/images/folder_time.png similarity index 100% rename from src/resources/images/folder_time.png rename to core/src/main/resources/images/folder_time.png diff --git a/src/resources/images/folder_up.png b/core/src/main/resources/images/folder_up.png similarity index 100% rename from src/resources/images/folder_up.png rename to core/src/main/resources/images/folder_up.png diff --git a/src/resources/images/folder_view.png b/core/src/main/resources/images/folder_view.png similarity index 100% rename from src/resources/images/folder_view.png rename to core/src/main/resources/images/folder_view.png diff --git a/src/resources/images/folder_warning.png b/core/src/main/resources/images/folder_warning.png similarity index 100% rename from src/resources/images/folder_warning.png rename to core/src/main/resources/images/folder_warning.png diff --git a/src/resources/images/folder_window.png b/core/src/main/resources/images/folder_window.png similarity index 100% rename from src/resources/images/folder_window.png rename to core/src/main/resources/images/folder_window.png diff --git a/core/src/main/resources/images/folders.png b/core/src/main/resources/images/folders.png new file mode 100644 index 000000000..e8035ef67 Binary files /dev/null and b/core/src/main/resources/images/folders.png differ diff --git a/src/resources/images/font.png b/core/src/main/resources/images/font.png similarity index 100% rename from src/resources/images/font.png rename to core/src/main/resources/images/font.png diff --git a/src/resources/images/forward.gif b/core/src/main/resources/images/forward.gif similarity index 100% rename from src/resources/images/forward.gif rename to core/src/main/resources/images/forward.gif diff --git a/src/resources/images/funnel_down.png b/core/src/main/resources/images/funnel_down.png similarity index 100% rename from src/resources/images/funnel_down.png rename to core/src/main/resources/images/funnel_down.png diff --git a/src/resources/images/gadugadu-gray.gif b/core/src/main/resources/images/gadugadu-gray.gif similarity index 100% rename from src/resources/images/gadugadu-gray.gif rename to core/src/main/resources/images/gadugadu-gray.gif diff --git a/src/resources/images/gadugadu.gif b/core/src/main/resources/images/gadugadu.gif similarity index 100% rename from src/resources/images/gadugadu.gif rename to core/src/main/resources/images/gadugadu.gif diff --git a/core/src/main/resources/images/gray-background.png b/core/src/main/resources/images/gray-background.png new file mode 100644 index 000000000..df729fb63 Binary files /dev/null and b/core/src/main/resources/images/gray-background.png differ diff --git a/src/resources/images/green-ball.gif b/core/src/main/resources/images/green-ball.gif similarity index 100% rename from src/resources/images/green-ball.gif rename to core/src/main/resources/images/green-ball.gif diff --git a/src/resources/images/green-ball.png b/core/src/main/resources/images/green-ball.png similarity index 100% rename from src/resources/images/green-ball.png rename to core/src/main/resources/images/green-ball.png diff --git a/src/resources/images/header-stretch.gif b/core/src/main/resources/images/header-stretch.gif similarity index 100% rename from src/resources/images/header-stretch.gif rename to core/src/main/resources/images/header-stretch.gif diff --git a/src/resources/images/headset.png b/core/src/main/resources/images/headset.png similarity index 100% rename from src/resources/images/headset.png rename to core/src/main/resources/images/headset.png diff --git a/src/resources/images/help2.png b/core/src/main/resources/images/help2.png similarity index 100% rename from src/resources/images/help2.png rename to core/src/main/resources/images/help2.png diff --git a/src/resources/images/help_16x16.png b/core/src/main/resources/images/help_16x16.png similarity index 100% rename from src/resources/images/help_16x16.png rename to core/src/main/resources/images/help_16x16.png diff --git a/core/src/main/resources/images/help_24x24.png b/core/src/main/resources/images/help_24x24.png new file mode 100644 index 000000000..d8d82110a Binary files /dev/null and b/core/src/main/resources/images/help_24x24.png differ diff --git a/core/src/main/resources/images/history-24x24.png b/core/src/main/resources/images/history-24x24.png new file mode 100644 index 000000000..815b45b46 Binary files /dev/null and b/core/src/main/resources/images/history-24x24.png differ diff --git a/src/resources/images/history.png b/core/src/main/resources/images/history.png similarity index 100% rename from src/resources/images/history.png rename to core/src/main/resources/images/history.png diff --git a/src/resources/images/icon_calendarpicker.gif b/core/src/main/resources/images/icon_calendarpicker.gif similarity index 100% rename from src/resources/images/icon_calendarpicker.gif rename to core/src/main/resources/images/icon_calendarpicker.gif diff --git a/src/plugins/jingle/src/resources/images/icon_computer_16x16.png b/core/src/main/resources/images/icon_computer_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_computer_16x16.png rename to core/src/main/resources/images/icon_computer_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_phone-call_16x16.png b/core/src/main/resources/images/icon_phone-call_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_phone-call_16x16.png rename to core/src/main/resources/images/icon_phone-call_16x16.png diff --git a/core/src/main/resources/images/icons/Away-24x24.png b/core/src/main/resources/images/icons/Away-24x24.png new file mode 100644 index 000000000..48c3e454b Binary files /dev/null and b/core/src/main/resources/images/icons/Away-24x24.png differ diff --git a/core/src/main/resources/images/icons/Away.png b/core/src/main/resources/images/icons/Away.png new file mode 100644 index 000000000..588c1d154 Binary files /dev/null and b/core/src/main/resources/images/icons/Away.png differ diff --git a/core/src/main/resources/images/icons/DoNotDisturb-24x24.png b/core/src/main/resources/images/icons/DoNotDisturb-24x24.png new file mode 100644 index 000000000..ee11c3764 Binary files /dev/null and b/core/src/main/resources/images/icons/DoNotDisturb-24x24.png differ diff --git a/core/src/main/resources/images/icons/DoNotDisturb.png b/core/src/main/resources/images/icons/DoNotDisturb.png new file mode 100644 index 000000000..13d2aa4b1 Binary files /dev/null and b/core/src/main/resources/images/icons/DoNotDisturb.png differ diff --git a/core/src/main/resources/images/icons/XAway-24x24.png b/core/src/main/resources/images/icons/XAway-24x24.png new file mode 100644 index 000000000..cc4875b36 Binary files /dev/null and b/core/src/main/resources/images/icons/XAway-24x24.png differ diff --git a/core/src/main/resources/images/icons/XAway.png b/core/src/main/resources/images/icons/XAway.png new file mode 100644 index 000000000..60e0c48c4 Binary files /dev/null and b/core/src/main/resources/images/icons/XAway.png differ diff --git a/core/src/main/resources/images/icons/about.png b/core/src/main/resources/images/icons/about.png new file mode 100644 index 000000000..43ce018bb Binary files /dev/null and b/core/src/main/resources/images/icons/about.png differ diff --git a/core/src/main/resources/images/icons/accept.png b/core/src/main/resources/images/icons/accept.png new file mode 100644 index 000000000..e402dbf47 Binary files /dev/null and b/core/src/main/resources/images/icons/accept.png differ diff --git a/core/src/main/resources/images/icons/add.png b/core/src/main/resources/images/icons/add.png new file mode 100644 index 000000000..e45628838 Binary files /dev/null and b/core/src/main/resources/images/icons/add.png differ diff --git a/core/src/main/resources/images/icons/add_image.png b/core/src/main/resources/images/icons/add_image.png new file mode 100644 index 000000000..548d85762 Binary files /dev/null and b/core/src/main/resources/images/icons/add_image.png differ diff --git a/core/src/main/resources/images/icons/add_user.png b/core/src/main/resources/images/icons/add_user.png new file mode 100644 index 000000000..a6d7ac32f Binary files /dev/null and b/core/src/main/resources/images/icons/add_user.png differ diff --git a/core/src/main/resources/images/icons/add_user_24.png b/core/src/main/resources/images/icons/add_user_24.png new file mode 100644 index 000000000..7602d2b9e Binary files /dev/null and b/core/src/main/resources/images/icons/add_user_24.png differ diff --git a/core/src/main/resources/images/icons/add_users.png b/core/src/main/resources/images/icons/add_users.png new file mode 100644 index 000000000..cf107f60c Binary files /dev/null and b/core/src/main/resources/images/icons/add_users.png differ diff --git a/core/src/main/resources/images/icons/address_book.png b/core/src/main/resources/images/icons/address_book.png new file mode 100644 index 000000000..1a1d9cef1 Binary files /dev/null and b/core/src/main/resources/images/icons/address_book.png differ diff --git a/core/src/main/resources/images/icons/alarmclock.png b/core/src/main/resources/images/icons/alarmclock.png new file mode 100644 index 000000000..773c24e80 Binary files /dev/null and b/core/src/main/resources/images/icons/alarmclock.png differ diff --git a/core/src/main/resources/images/icons/alert.png b/core/src/main/resources/images/icons/alert.png new file mode 100644 index 000000000..0e286001c Binary files /dev/null and b/core/src/main/resources/images/icons/alert.png differ diff --git a/core/src/main/resources/images/icons/appearance.png b/core/src/main/resources/images/icons/appearance.png new file mode 100644 index 000000000..ea0e8eb31 Binary files /dev/null and b/core/src/main/resources/images/icons/appearance.png differ diff --git a/core/src/main/resources/images/icons/back.png b/core/src/main/resources/images/icons/back.png new file mode 100644 index 000000000..5ac404797 Binary files /dev/null and b/core/src/main/resources/images/icons/back.png differ diff --git a/core/src/main/resources/images/icons/ban.png b/core/src/main/resources/images/icons/ban.png new file mode 100644 index 000000000..20a4d3601 Binary files /dev/null and b/core/src/main/resources/images/icons/ban.png differ diff --git a/core/src/main/resources/images/icons/block.png b/core/src/main/resources/images/icons/block.png new file mode 100644 index 000000000..464f896e7 Binary files /dev/null and b/core/src/main/resources/images/icons/block.png differ diff --git a/core/src/main/resources/images/icons/bookmark.png b/core/src/main/resources/images/icons/bookmark.png new file mode 100644 index 000000000..664b92667 Binary files /dev/null and b/core/src/main/resources/images/icons/bookmark.png differ diff --git a/core/src/main/resources/images/icons/broadcast.png b/core/src/main/resources/images/icons/broadcast.png new file mode 100644 index 000000000..1a798c9d8 Binary files /dev/null and b/core/src/main/resources/images/icons/broadcast.png differ diff --git a/core/src/main/resources/images/icons/busy.gif b/core/src/main/resources/images/icons/busy.gif new file mode 100644 index 000000000..74a12ceea Binary files /dev/null and b/core/src/main/resources/images/icons/busy.gif differ diff --git a/core/src/main/resources/images/icons/buzz.png b/core/src/main/resources/images/icons/buzz.png new file mode 100644 index 000000000..87e085225 Binary files /dev/null and b/core/src/main/resources/images/icons/buzz.png differ diff --git a/core/src/main/resources/images/icons/chat_settings.png b/core/src/main/resources/images/icons/chat_settings.png new file mode 100644 index 000000000..a8cd5d8a8 Binary files /dev/null and b/core/src/main/resources/images/icons/chat_settings.png differ diff --git a/core/src/main/resources/images/icons/check_update.png b/core/src/main/resources/images/icons/check_update.png new file mode 100644 index 000000000..ebc0bbd12 Binary files /dev/null and b/core/src/main/resources/images/icons/check_update.png differ diff --git a/core/src/main/resources/images/icons/clear.png b/core/src/main/resources/images/icons/clear.png new file mode 100644 index 000000000..18ef8876d Binary files /dev/null and b/core/src/main/resources/images/icons/clear.png differ diff --git a/core/src/main/resources/images/icons/clipboard.png b/core/src/main/resources/images/icons/clipboard.png new file mode 100644 index 000000000..35a29ffee Binary files /dev/null and b/core/src/main/resources/images/icons/clipboard.png differ diff --git a/core/src/main/resources/images/icons/close.png b/core/src/main/resources/images/icons/close.png new file mode 100644 index 000000000..87bf0e83e Binary files /dev/null and b/core/src/main/resources/images/icons/close.png differ diff --git a/core/src/main/resources/images/icons/close_red.png b/core/src/main/resources/images/icons/close_red.png new file mode 100644 index 000000000..0bc35d78e Binary files /dev/null and b/core/src/main/resources/images/icons/close_red.png differ diff --git a/core/src/main/resources/images/icons/collapse_down.png b/core/src/main/resources/images/icons/collapse_down.png new file mode 100644 index 000000000..100a7ca6f Binary files /dev/null and b/core/src/main/resources/images/icons/collapse_down.png differ diff --git a/core/src/main/resources/images/icons/collapse_up.png b/core/src/main/resources/images/icons/collapse_up.png new file mode 100644 index 000000000..dba0e6992 Binary files /dev/null and b/core/src/main/resources/images/icons/collapse_up.png differ diff --git a/core/src/main/resources/images/icons/colors.png b/core/src/main/resources/images/icons/colors.png new file mode 100644 index 000000000..b50478f3b Binary files /dev/null and b/core/src/main/resources/images/icons/colors.png differ diff --git a/core/src/main/resources/images/icons/conference.png b/core/src/main/resources/images/icons/conference.png new file mode 100644 index 000000000..dfadd5a0c Binary files /dev/null and b/core/src/main/resources/images/icons/conference.png differ diff --git a/core/src/main/resources/images/icons/conference_24x24.png b/core/src/main/resources/images/icons/conference_24x24.png new file mode 100644 index 000000000..d5f2cbf3a Binary files /dev/null and b/core/src/main/resources/images/icons/conference_24x24.png differ diff --git a/core/src/main/resources/images/icons/conference_32x32.png b/core/src/main/resources/images/icons/conference_32x32.png new file mode 100644 index 000000000..0ebc93ed4 Binary files /dev/null and b/core/src/main/resources/images/icons/conference_32x32.png differ diff --git a/core/src/main/resources/images/icons/conference_48x48.png b/core/src/main/resources/images/icons/conference_48x48.png new file mode 100644 index 000000000..aadb554ef Binary files /dev/null and b/core/src/main/resources/images/icons/conference_48x48.png differ diff --git a/core/src/main/resources/images/icons/conferences.png b/core/src/main/resources/images/icons/conferences.png new file mode 100644 index 000000000..d6aafecc7 Binary files /dev/null and b/core/src/main/resources/images/icons/conferences.png differ diff --git a/core/src/main/resources/images/icons/contacts.png b/core/src/main/resources/images/icons/contacts.png new file mode 100644 index 000000000..63e78a986 Binary files /dev/null and b/core/src/main/resources/images/icons/contacts.png differ diff --git a/core/src/main/resources/images/icons/copy.png b/core/src/main/resources/images/icons/copy.png new file mode 100644 index 000000000..603957a2c Binary files /dev/null and b/core/src/main/resources/images/icons/copy.png differ diff --git a/core/src/main/resources/images/icons/create.png b/core/src/main/resources/images/icons/create.png new file mode 100644 index 000000000..628fc683b Binary files /dev/null and b/core/src/main/resources/images/icons/create.png differ diff --git a/core/src/main/resources/images/icons/downloads.png b/core/src/main/resources/images/icons/downloads.png new file mode 100644 index 000000000..25ea188e9 Binary files /dev/null and b/core/src/main/resources/images/icons/downloads.png differ diff --git a/core/src/main/resources/images/icons/edit.png b/core/src/main/resources/images/icons/edit.png new file mode 100644 index 000000000..a290e3767 Binary files /dev/null and b/core/src/main/resources/images/icons/edit.png differ diff --git a/core/src/main/resources/images/icons/edit_profile.png b/core/src/main/resources/images/icons/edit_profile.png new file mode 100644 index 000000000..f0e033294 Binary files /dev/null and b/core/src/main/resources/images/icons/edit_profile.png differ diff --git a/core/src/main/resources/images/icons/folder.png b/core/src/main/resources/images/icons/folder.png new file mode 100644 index 000000000..c00cae879 Binary files /dev/null and b/core/src/main/resources/images/icons/folder.png differ diff --git a/core/src/main/resources/images/icons/forward.png b/core/src/main/resources/images/icons/forward.png new file mode 100644 index 000000000..4b50fae5a Binary files /dev/null and b/core/src/main/resources/images/icons/forward.png differ diff --git a/core/src/main/resources/images/icons/headset.png b/core/src/main/resources/images/icons/headset.png new file mode 100644 index 000000000..5aa4300e6 Binary files /dev/null and b/core/src/main/resources/images/icons/headset.png differ diff --git a/core/src/main/resources/images/icons/help.png b/core/src/main/resources/images/icons/help.png new file mode 100644 index 000000000..c5ee6bbef Binary files /dev/null and b/core/src/main/resources/images/icons/help.png differ diff --git a/core/src/main/resources/images/icons/history.png b/core/src/main/resources/images/icons/history.png new file mode 100644 index 000000000..da1d71636 Binary files /dev/null and b/core/src/main/resources/images/icons/history.png differ diff --git a/core/src/main/resources/images/icons/history24.png b/core/src/main/resources/images/icons/history24.png new file mode 100644 index 000000000..9297e5590 Binary files /dev/null and b/core/src/main/resources/images/icons/history24.png differ diff --git a/core/src/main/resources/images/icons/im_available.png b/core/src/main/resources/images/icons/im_available.png new file mode 100644 index 000000000..d84751bb4 Binary files /dev/null and b/core/src/main/resources/images/icons/im_available.png differ diff --git a/core/src/main/resources/images/icons/im_available_stale.png b/core/src/main/resources/images/icons/im_available_stale.png new file mode 100644 index 000000000..e11c655e1 Binary files /dev/null and b/core/src/main/resources/images/icons/im_available_stale.png differ diff --git a/core/src/main/resources/images/icons/im_away.png b/core/src/main/resources/images/icons/im_away.png new file mode 100644 index 000000000..49f5cccbe Binary files /dev/null and b/core/src/main/resources/images/icons/im_away.png differ diff --git a/core/src/main/resources/images/icons/im_away_stale.png b/core/src/main/resources/images/icons/im_away_stale.png new file mode 100644 index 000000000..a84106a24 Binary files /dev/null and b/core/src/main/resources/images/icons/im_away_stale.png differ diff --git a/core/src/main/resources/images/icons/im_dnd.png b/core/src/main/resources/images/icons/im_dnd.png new file mode 100644 index 000000000..2af48a9cf Binary files /dev/null and b/core/src/main/resources/images/icons/im_dnd.png differ diff --git a/core/src/main/resources/images/icons/im_dnd_stale.png b/core/src/main/resources/images/icons/im_dnd_stale.png new file mode 100644 index 000000000..c95e10975 Binary files /dev/null and b/core/src/main/resources/images/icons/im_dnd_stale.png differ diff --git a/core/src/main/resources/images/icons/im_free_chat.png b/core/src/main/resources/images/icons/im_free_chat.png new file mode 100644 index 000000000..b5a5eb866 Binary files /dev/null and b/core/src/main/resources/images/icons/im_free_chat.png differ diff --git a/core/src/main/resources/images/icons/im_free_chat_stale.png b/core/src/main/resources/images/icons/im_free_chat_stale.png new file mode 100644 index 000000000..b38fe4630 Binary files /dev/null and b/core/src/main/resources/images/icons/im_free_chat_stale.png differ diff --git a/core/src/main/resources/images/icons/im_unavailable.png b/core/src/main/resources/images/icons/im_unavailable.png new file mode 100644 index 000000000..064da65e7 Binary files /dev/null and b/core/src/main/resources/images/icons/im_unavailable.png differ diff --git a/core/src/main/resources/images/icons/im_unavailable_stale.png b/core/src/main/resources/images/icons/im_unavailable_stale.png new file mode 100644 index 000000000..1bab17811 Binary files /dev/null and b/core/src/main/resources/images/icons/im_unavailable_stale.png differ diff --git a/core/src/main/resources/images/icons/im_xa.png b/core/src/main/resources/images/icons/im_xa.png new file mode 100644 index 000000000..cda3f37f0 Binary files /dev/null and b/core/src/main/resources/images/icons/im_xa.png differ diff --git a/core/src/main/resources/images/icons/im_xa_stale.png b/core/src/main/resources/images/icons/im_xa_stale.png new file mode 100644 index 000000000..ccd0dd9f8 Binary files /dev/null and b/core/src/main/resources/images/icons/im_xa_stale.png differ diff --git a/core/src/main/resources/images/icons/incoming_message.png b/core/src/main/resources/images/icons/incoming_message.png new file mode 100644 index 000000000..7b4227a56 Binary files /dev/null and b/core/src/main/resources/images/icons/incoming_message.png differ diff --git a/core/src/main/resources/images/icons/invite24.png b/core/src/main/resources/images/icons/invite24.png new file mode 100644 index 000000000..31be567bc Binary files /dev/null and b/core/src/main/resources/images/icons/invite24.png differ diff --git a/core/src/main/resources/images/icons/invitemore.png b/core/src/main/resources/images/icons/invitemore.png new file mode 100644 index 000000000..163d2958d Binary files /dev/null and b/core/src/main/resources/images/icons/invitemore.png differ diff --git a/core/src/main/resources/images/icons/join.png b/core/src/main/resources/images/icons/join.png new file mode 100644 index 000000000..e91101e13 Binary files /dev/null and b/core/src/main/resources/images/icons/join.png differ diff --git a/core/src/main/resources/images/icons/language.png b/core/src/main/resources/images/icons/language.png new file mode 100644 index 000000000..94d032afa Binary files /dev/null and b/core/src/main/resources/images/icons/language.png differ diff --git a/core/src/main/resources/images/icons/lightning.png b/core/src/main/resources/images/icons/lightning.png new file mode 100644 index 000000000..d6fcc5f72 Binary files /dev/null and b/core/src/main/resources/images/icons/lightning.png differ diff --git a/core/src/main/resources/images/icons/link.png b/core/src/main/resources/images/icons/link.png new file mode 100644 index 000000000..09d22eba7 Binary files /dev/null and b/core/src/main/resources/images/icons/link.png differ diff --git a/core/src/main/resources/images/icons/link_delete.png b/core/src/main/resources/images/icons/link_delete.png new file mode 100644 index 000000000..73b088065 Binary files /dev/null and b/core/src/main/resources/images/icons/link_delete.png differ diff --git a/core/src/main/resources/images/icons/lock.png b/core/src/main/resources/images/icons/lock.png new file mode 100644 index 000000000..ef2673ead Binary files /dev/null and b/core/src/main/resources/images/icons/lock.png differ diff --git a/core/src/main/resources/images/icons/login.png b/core/src/main/resources/images/icons/login.png new file mode 100644 index 000000000..e01f11869 Binary files /dev/null and b/core/src/main/resources/images/icons/login.png differ diff --git a/core/src/main/resources/images/icons/lookup.png b/core/src/main/resources/images/icons/lookup.png new file mode 100644 index 000000000..8836f0d8d Binary files /dev/null and b/core/src/main/resources/images/icons/lookup.png differ diff --git a/core/src/main/resources/images/icons/moderator.png b/core/src/main/resources/images/icons/moderator.png new file mode 100644 index 000000000..bedfe525b Binary files /dev/null and b/core/src/main/resources/images/icons/moderator.png differ diff --git a/core/src/main/resources/images/icons/note.png b/core/src/main/resources/images/icons/note.png new file mode 100644 index 000000000..6a2b995e2 Binary files /dev/null and b/core/src/main/resources/images/icons/note.png differ diff --git a/core/src/main/resources/images/icons/notebook.png b/core/src/main/resources/images/icons/notebook.png new file mode 100644 index 000000000..b42f7540c Binary files /dev/null and b/core/src/main/resources/images/icons/notebook.png differ diff --git a/core/src/main/resources/images/icons/notifications.png b/core/src/main/resources/images/icons/notifications.png new file mode 100644 index 000000000..a901fdb77 Binary files /dev/null and b/core/src/main/resources/images/icons/notifications.png differ diff --git a/core/src/main/resources/images/icons/on-phone.png b/core/src/main/resources/images/icons/on-phone.png new file mode 100644 index 000000000..368c12e40 Binary files /dev/null and b/core/src/main/resources/images/icons/on-phone.png differ diff --git a/core/src/main/resources/images/icons/phone.png b/core/src/main/resources/images/icons/phone.png new file mode 100644 index 000000000..8b40f1566 Binary files /dev/null and b/core/src/main/resources/images/icons/phone.png differ diff --git a/core/src/main/resources/images/icons/phone_24x24.png b/core/src/main/resources/images/icons/phone_24x24.png new file mode 100644 index 000000000..b1bad4f49 Binary files /dev/null and b/core/src/main/resources/images/icons/phone_24x24.png differ diff --git a/core/src/main/resources/images/icons/photo.png b/core/src/main/resources/images/icons/photo.png new file mode 100644 index 000000000..fc4771cab Binary files /dev/null and b/core/src/main/resources/images/icons/photo.png differ diff --git a/core/src/main/resources/images/icons/photo24.png b/core/src/main/resources/images/icons/photo24.png new file mode 100644 index 000000000..921b9fe12 Binary files /dev/null and b/core/src/main/resources/images/icons/photo24.png differ diff --git a/core/src/main/resources/images/icons/pin_top.png b/core/src/main/resources/images/icons/pin_top.png new file mode 100644 index 000000000..e8ad1f184 Binary files /dev/null and b/core/src/main/resources/images/icons/pin_top.png differ diff --git a/core/src/main/resources/images/icons/plugins.png b/core/src/main/resources/images/icons/plugins.png new file mode 100644 index 000000000..caa7d24ca Binary files /dev/null and b/core/src/main/resources/images/icons/plugins.png differ diff --git a/core/src/main/resources/images/icons/preferences.png b/core/src/main/resources/images/icons/preferences.png new file mode 100644 index 000000000..c6fb894ff Binary files /dev/null and b/core/src/main/resources/images/icons/preferences.png differ diff --git a/core/src/main/resources/images/icons/print.png b/core/src/main/resources/images/icons/print.png new file mode 100644 index 000000000..ffd83b090 Binary files /dev/null and b/core/src/main/resources/images/icons/print.png differ diff --git a/core/src/main/resources/images/icons/privacy.png b/core/src/main/resources/images/icons/privacy.png new file mode 100644 index 000000000..2b9a2453c Binary files /dev/null and b/core/src/main/resources/images/icons/privacy.png differ diff --git a/core/src/main/resources/images/icons/privacy_check.png b/core/src/main/resources/images/icons/privacy_check.png new file mode 100644 index 000000000..af7226f0c Binary files /dev/null and b/core/src/main/resources/images/icons/privacy_check.png differ diff --git a/core/src/main/resources/images/icons/privacy_lightning.png b/core/src/main/resources/images/icons/privacy_lightning.png new file mode 100644 index 000000000..76492e8f5 Binary files /dev/null and b/core/src/main/resources/images/icons/privacy_lightning.png differ diff --git a/core/src/main/resources/images/icons/privacy_list_deactivate.png b/core/src/main/resources/images/icons/privacy_list_deactivate.png new file mode 100644 index 000000000..34edf0b29 Binary files /dev/null and b/core/src/main/resources/images/icons/privacy_list_deactivate.png differ diff --git a/core/src/main/resources/images/icons/privacy_message_allow.png b/core/src/main/resources/images/icons/privacy_message_allow.png new file mode 100644 index 000000000..999e209ec Binary files /dev/null and b/core/src/main/resources/images/icons/privacy_message_allow.png differ diff --git a/core/src/main/resources/images/icons/privacy_message_deny.png b/core/src/main/resources/images/icons/privacy_message_deny.png new file mode 100644 index 000000000..5349b3e30 Binary files /dev/null and b/core/src/main/resources/images/icons/privacy_message_deny.png differ diff --git a/core/src/main/resources/images/icons/privacy_presence_in_allow.png b/core/src/main/resources/images/icons/privacy_presence_in_allow.png new file mode 100644 index 000000000..7273f7d60 Binary files /dev/null and b/core/src/main/resources/images/icons/privacy_presence_in_allow.png differ diff --git a/core/src/main/resources/images/icons/privacy_presence_in_deny.png b/core/src/main/resources/images/icons/privacy_presence_in_deny.png new file mode 100644 index 000000000..676b08708 Binary files /dev/null and b/core/src/main/resources/images/icons/privacy_presence_in_deny.png differ diff --git a/core/src/main/resources/images/icons/privacy_presence_out_allow.png b/core/src/main/resources/images/icons/privacy_presence_out_allow.png new file mode 100644 index 000000000..8c552c9f3 Binary files /dev/null and b/core/src/main/resources/images/icons/privacy_presence_out_allow.png differ diff --git a/core/src/main/resources/images/icons/privacy_presence_out_deny.png b/core/src/main/resources/images/icons/privacy_presence_out_deny.png new file mode 100644 index 000000000..623608570 Binary files /dev/null and b/core/src/main/resources/images/icons/privacy_presence_out_deny.png differ diff --git a/core/src/main/resources/images/icons/privacy_query_allow.png b/core/src/main/resources/images/icons/privacy_query_allow.png new file mode 100644 index 000000000..55c80687b Binary files /dev/null and b/core/src/main/resources/images/icons/privacy_query_allow.png differ diff --git a/core/src/main/resources/images/icons/privacy_query_deny.png b/core/src/main/resources/images/icons/privacy_query_deny.png new file mode 100644 index 000000000..55804266e Binary files /dev/null and b/core/src/main/resources/images/icons/privacy_query_deny.png differ diff --git a/core/src/main/resources/images/icons/profile.png b/core/src/main/resources/images/icons/profile.png new file mode 100644 index 000000000..22391c290 Binary files /dev/null and b/core/src/main/resources/images/icons/profile.png differ diff --git a/core/src/main/resources/images/icons/profile24.png b/core/src/main/resources/images/icons/profile24.png new file mode 100644 index 000000000..7121ba7e8 Binary files /dev/null and b/core/src/main/resources/images/icons/profile24.png differ diff --git a/core/src/main/resources/images/icons/refresh.png b/core/src/main/resources/images/icons/refresh.png new file mode 100644 index 000000000..8faaa3b8b Binary files /dev/null and b/core/src/main/resources/images/icons/refresh.png differ diff --git a/core/src/main/resources/images/icons/reject.png b/core/src/main/resources/images/icons/reject.png new file mode 100644 index 000000000..8c346dd8f Binary files /dev/null and b/core/src/main/resources/images/icons/reject.png differ diff --git a/core/src/main/resources/images/icons/remove.png b/core/src/main/resources/images/icons/remove.png new file mode 100644 index 000000000..2d6b53c49 Binary files /dev/null and b/core/src/main/resources/images/icons/remove.png differ diff --git a/core/src/main/resources/images/icons/save.png b/core/src/main/resources/images/icons/save.png new file mode 100644 index 000000000..6f9fb83a9 Binary files /dev/null and b/core/src/main/resources/images/icons/save.png differ diff --git a/core/src/main/resources/images/icons/screenshot24.png b/core/src/main/resources/images/icons/screenshot24.png new file mode 100644 index 000000000..a152de3be Binary files /dev/null and b/core/src/main/resources/images/icons/screenshot24.png differ diff --git a/core/src/main/resources/images/icons/search.png b/core/src/main/resources/images/icons/search.png new file mode 100644 index 000000000..84aa5a0b5 Binary files /dev/null and b/core/src/main/resources/images/icons/search.png differ diff --git a/core/src/main/resources/images/icons/send_file.png b/core/src/main/resources/images/icons/send_file.png new file mode 100644 index 000000000..5e9072756 Binary files /dev/null and b/core/src/main/resources/images/icons/send_file.png differ diff --git a/core/src/main/resources/images/icons/send_file24.png b/core/src/main/resources/images/icons/send_file24.png new file mode 100644 index 000000000..57bdd8d0c Binary files /dev/null and b/core/src/main/resources/images/icons/send_file24.png differ diff --git a/core/src/main/resources/images/icons/settings.png b/core/src/main/resources/images/icons/settings.png new file mode 100644 index 000000000..7bc61c0bf Binary files /dev/null and b/core/src/main/resources/images/icons/settings.png differ diff --git a/core/src/main/resources/images/icons/small_entry.png b/core/src/main/resources/images/icons/small_entry.png new file mode 100644 index 000000000..3179d60c8 Binary files /dev/null and b/core/src/main/resources/images/icons/small_entry.png differ diff --git a/core/src/main/resources/images/icons/sound.png b/core/src/main/resources/images/icons/sound.png new file mode 100644 index 000000000..83cd9137a Binary files /dev/null and b/core/src/main/resources/images/icons/sound.png differ diff --git a/core/src/main/resources/images/icons/spark_tray_connecting-16x16.png b/core/src/main/resources/images/icons/spark_tray_connecting-16x16.png new file mode 100644 index 000000000..f7fc45b96 Binary files /dev/null and b/core/src/main/resources/images/icons/spark_tray_connecting-16x16.png differ diff --git a/core/src/main/resources/images/icons/spark_tray_connecting-24x24.png b/core/src/main/resources/images/icons/spark_tray_connecting-24x24.png new file mode 100644 index 000000000..9b7b15b3a Binary files /dev/null and b/core/src/main/resources/images/icons/spark_tray_connecting-24x24.png differ diff --git a/core/src/main/resources/images/icons/spark_tray_message-16x16.png b/core/src/main/resources/images/icons/spark_tray_message-16x16.png new file mode 100644 index 000000000..d24918ee1 Binary files /dev/null and b/core/src/main/resources/images/icons/spark_tray_message-16x16.png differ diff --git a/core/src/main/resources/images/icons/spark_tray_message-24x24.png b/core/src/main/resources/images/icons/spark_tray_message-24x24.png new file mode 100644 index 000000000..9e943ba4a Binary files /dev/null and b/core/src/main/resources/images/icons/spark_tray_message-24x24.png differ diff --git a/core/src/main/resources/images/icons/star.png b/core/src/main/resources/images/icons/star.png new file mode 100644 index 000000000..79c5b4346 Binary files /dev/null and b/core/src/main/resources/images/icons/star.png differ diff --git a/core/src/main/resources/images/icons/star_admin.png b/core/src/main/resources/images/icons/star_admin.png new file mode 100644 index 000000000..93fb05c27 Binary files /dev/null and b/core/src/main/resources/images/icons/star_admin.png differ diff --git a/core/src/main/resources/images/icons/star_blue.png b/core/src/main/resources/images/icons/star_blue.png new file mode 100644 index 000000000..d03d9fb36 Binary files /dev/null and b/core/src/main/resources/images/icons/star_blue.png differ diff --git a/core/src/main/resources/images/icons/star_green.png b/core/src/main/resources/images/icons/star_green.png new file mode 100644 index 000000000..13ed4e438 Binary files /dev/null and b/core/src/main/resources/images/icons/star_green.png differ diff --git a/core/src/main/resources/images/icons/star_moderator.png b/core/src/main/resources/images/icons/star_moderator.png new file mode 100644 index 000000000..7e95617b9 Binary files /dev/null and b/core/src/main/resources/images/icons/star_moderator.png differ diff --git a/core/src/main/resources/images/icons/star_owner.png b/core/src/main/resources/images/icons/star_owner.png new file mode 100644 index 000000000..7a0f7427d Binary files /dev/null and b/core/src/main/resources/images/icons/star_owner.png differ diff --git a/core/src/main/resources/images/icons/star_red.png b/core/src/main/resources/images/icons/star_red.png new file mode 100644 index 000000000..d4cfd048d Binary files /dev/null and b/core/src/main/resources/images/icons/star_red.png differ diff --git a/core/src/main/resources/images/icons/star_yellow.png b/core/src/main/resources/images/icons/star_yellow.png new file mode 100644 index 000000000..673a65865 Binary files /dev/null and b/core/src/main/resources/images/icons/star_yellow.png differ diff --git a/core/src/main/resources/images/icons/start_chat.png b/core/src/main/resources/images/icons/start_chat.png new file mode 100644 index 000000000..81cfd2db0 Binary files /dev/null and b/core/src/main/resources/images/icons/start_chat.png differ diff --git a/core/src/main/resources/images/icons/start_conference.png b/core/src/main/resources/images/icons/start_conference.png new file mode 100644 index 000000000..cf107f60c Binary files /dev/null and b/core/src/main/resources/images/icons/start_conference.png differ diff --git a/core/src/main/resources/images/icons/subscribe.png b/core/src/main/resources/images/icons/subscribe.png new file mode 100644 index 000000000..31177806e Binary files /dev/null and b/core/src/main/resources/images/icons/subscribe.png differ diff --git a/core/src/main/resources/images/icons/subsribe24.png b/core/src/main/resources/images/icons/subsribe24.png new file mode 100644 index 000000000..e6f6c04ae Binary files /dev/null and b/core/src/main/resources/images/icons/subsribe24.png differ diff --git a/core/src/main/resources/images/icons/tasklist.png b/core/src/main/resources/images/icons/tasklist.png new file mode 100644 index 000000000..aea10f0f6 Binary files /dev/null and b/core/src/main/resources/images/icons/tasklist.png differ diff --git a/core/src/main/resources/images/icons/unblock.png b/core/src/main/resources/images/icons/unblock.png new file mode 100644 index 000000000..1bb154ea0 Binary files /dev/null and b/core/src/main/resources/images/icons/unblock.png differ diff --git a/core/src/main/resources/images/icons/unlock.png b/core/src/main/resources/images/icons/unlock.png new file mode 100644 index 000000000..6f40919eb Binary files /dev/null and b/core/src/main/resources/images/icons/unlock.png differ diff --git a/core/src/main/resources/images/icons/unpin_top.png b/core/src/main/resources/images/icons/unpin_top.png new file mode 100644 index 000000000..3ab26ca25 Binary files /dev/null and b/core/src/main/resources/images/icons/unpin_top.png differ diff --git a/core/src/main/resources/images/icons/upload.png b/core/src/main/resources/images/icons/upload.png new file mode 100644 index 000000000..20400c175 Binary files /dev/null and b/core/src/main/resources/images/icons/upload.png differ diff --git a/core/src/main/resources/images/icons/user.png b/core/src/main/resources/images/icons/user.png new file mode 100644 index 000000000..b59ee1100 Binary files /dev/null and b/core/src/main/resources/images/icons/user.png differ diff --git a/core/src/main/resources/images/icons/user24.png b/core/src/main/resources/images/icons/user24.png new file mode 100644 index 000000000..ba724021b Binary files /dev/null and b/core/src/main/resources/images/icons/user24.png differ diff --git a/core/src/main/resources/images/icons/user32.png b/core/src/main/resources/images/icons/user32.png new file mode 100644 index 000000000..41344f19b Binary files /dev/null and b/core/src/main/resources/images/icons/user32.png differ diff --git a/core/src/main/resources/images/icons/user64.png b/core/src/main/resources/images/icons/user64.png new file mode 100644 index 000000000..686f061b4 Binary files /dev/null and b/core/src/main/resources/images/icons/user64.png differ diff --git a/core/src/main/resources/images/icons/users.png b/core/src/main/resources/images/icons/users.png new file mode 100644 index 000000000..811af998b Binary files /dev/null and b/core/src/main/resources/images/icons/users.png differ diff --git a/core/src/main/resources/images/id_card.png b/core/src/main/resources/images/id_card.png new file mode 100644 index 000000000..916e1b38e Binary files /dev/null and b/core/src/main/resources/images/id_card.png differ diff --git a/src/resources/images/im_available.png b/core/src/main/resources/images/im_available.png similarity index 100% rename from src/resources/images/im_available.png rename to core/src/main/resources/images/im_available.png diff --git a/core/src/main/resources/images/im_available_stale.png b/core/src/main/resources/images/im_available_stale.png new file mode 100644 index 000000000..ce345cc0a Binary files /dev/null and b/core/src/main/resources/images/im_available_stale.png differ diff --git a/core/src/main/resources/images/im_away.png b/core/src/main/resources/images/im_away.png new file mode 100644 index 000000000..ca19eb060 Binary files /dev/null and b/core/src/main/resources/images/im_away.png differ diff --git a/core/src/main/resources/images/im_away_stale.png b/core/src/main/resources/images/im_away_stale.png new file mode 100644 index 000000000..fc4c50345 Binary files /dev/null and b/core/src/main/resources/images/im_away_stale.png differ diff --git a/core/src/main/resources/images/im_dnd.png b/core/src/main/resources/images/im_dnd.png new file mode 100644 index 000000000..f63590852 Binary files /dev/null and b/core/src/main/resources/images/im_dnd.png differ diff --git a/core/src/main/resources/images/im_dnd_stale.png b/core/src/main/resources/images/im_dnd_stale.png new file mode 100644 index 000000000..2ea7abd3a Binary files /dev/null and b/core/src/main/resources/images/im_dnd_stale.png differ diff --git a/core/src/main/resources/images/im_free_chat.png b/core/src/main/resources/images/im_free_chat.png new file mode 100644 index 000000000..4cf352942 Binary files /dev/null and b/core/src/main/resources/images/im_free_chat.png differ diff --git a/core/src/main/resources/images/im_free_chat_stale.png b/core/src/main/resources/images/im_free_chat_stale.png new file mode 100644 index 000000000..9760fb5bb Binary files /dev/null and b/core/src/main/resources/images/im_free_chat_stale.png differ diff --git a/core/src/main/resources/images/im_invisible.png b/core/src/main/resources/images/im_invisible.png new file mode 100644 index 000000000..87c6957a8 Binary files /dev/null and b/core/src/main/resources/images/im_invisible.png differ diff --git a/core/src/main/resources/images/im_unavailable.png b/core/src/main/resources/images/im_unavailable.png new file mode 100644 index 000000000..86175f7e8 Binary files /dev/null and b/core/src/main/resources/images/im_unavailable.png differ diff --git a/core/src/main/resources/images/im_unavailable_stale.png b/core/src/main/resources/images/im_unavailable_stale.png new file mode 100644 index 000000000..87c6957a8 Binary files /dev/null and b/core/src/main/resources/images/im_unavailable_stale.png differ diff --git a/src/resources/images/yellow-ball.png b/core/src/main/resources/images/im_xa.png similarity index 100% rename from src/resources/images/yellow-ball.png rename to core/src/main/resources/images/im_xa.png diff --git a/core/src/main/resources/images/im_xa_stale.png b/core/src/main/resources/images/im_xa_stale.png new file mode 100644 index 000000000..bca64a9e0 Binary files /dev/null and b/core/src/main/resources/images/im_xa_stale.png differ diff --git a/src/resources/images/information.png b/core/src/main/resources/images/information.png similarity index 100% rename from src/resources/images/information.png rename to core/src/main/resources/images/information.png diff --git a/src/resources/images/initials.gif b/core/src/main/resources/images/initials.gif similarity index 100% rename from src/resources/images/initials.gif rename to core/src/main/resources/images/initials.gif diff --git a/src/resources/images/invitemore.png b/core/src/main/resources/images/invitemore.png similarity index 100% rename from src/resources/images/invitemore.png rename to core/src/main/resources/images/invitemore.png diff --git a/core/src/main/resources/images/irc-gray.png b/core/src/main/resources/images/irc-gray.png new file mode 100644 index 000000000..171d052fc Binary files /dev/null and b/core/src/main/resources/images/irc-gray.png differ diff --git a/core/src/main/resources/images/irc.png b/core/src/main/resources/images/irc.png new file mode 100644 index 000000000..a5bd4631a Binary files /dev/null and b/core/src/main/resources/images/irc.png differ diff --git a/src/resources/images/join_groupchat.png b/core/src/main/resources/images/join_groupchat.png similarity index 100% rename from src/resources/images/join_groupchat.png rename to core/src/main/resources/images/join_groupchat.png diff --git a/src/resources/images/language_plugin.png b/core/src/main/resources/images/language_plugin.png similarity index 100% rename from src/resources/images/language_plugin.png rename to core/src/main/resources/images/language_plugin.png diff --git a/src/resources/images/leftArrow.gif b/core/src/main/resources/images/leftArrow.gif similarity index 100% rename from src/resources/images/leftArrow.gif rename to core/src/main/resources/images/leftArrow.gif diff --git a/src/resources/images/lightbulb_on.png b/core/src/main/resources/images/lightbulb_on.png similarity index 100% rename from src/resources/images/lightbulb_on.png rename to core/src/main/resources/images/lightbulb_on.png diff --git a/core/src/main/resources/images/lightning16.png b/core/src/main/resources/images/lightning16.png new file mode 100644 index 000000000..3b867698c Binary files /dev/null and b/core/src/main/resources/images/lightning16.png differ diff --git a/src/resources/images/link-16x16.png b/core/src/main/resources/images/link-16x16.png similarity index 100% rename from src/resources/images/link-16x16.png rename to core/src/main/resources/images/link-16x16.png diff --git a/src/resources/images/link_delete.png b/core/src/main/resources/images/link_delete.png similarity index 100% rename from src/resources/images/link_delete.png rename to core/src/main/resources/images/link_delete.png diff --git a/src/resources/images/lock-16x16.png b/core/src/main/resources/images/lock-16x16.png similarity index 100% rename from src/resources/images/lock-16x16.png rename to core/src/main/resources/images/lock-16x16.png diff --git a/src/resources/images/lock_and_keys.gif b/core/src/main/resources/images/lock_and_keys.gif similarity index 100% rename from src/resources/images/lock_and_keys.gif rename to core/src/main/resources/images/lock_and_keys.gif diff --git a/src/resources/images/lock_unlock-16x16.png b/core/src/main/resources/images/lock_unlock-16x16.png similarity index 100% rename from src/resources/images/lock_unlock-16x16.png rename to core/src/main/resources/images/lock_unlock-16x16.png diff --git a/src/resources/images/login-key.png b/core/src/main/resources/images/login-key.png similarity index 100% rename from src/resources/images/login-key.png rename to core/src/main/resources/images/login-key.png diff --git a/core/src/main/resources/images/login_dialog_background.png b/core/src/main/resources/images/login_dialog_background.png new file mode 100644 index 000000000..864cdcbfa Binary files /dev/null and b/core/src/main/resources/images/login_dialog_background.png differ diff --git a/src/resources/images/magician.png b/core/src/main/resources/images/magician.png similarity index 100% rename from src/resources/images/magician.png rename to core/src/main/resources/images/magician.png diff --git a/src/resources/images/mail.png b/core/src/main/resources/images/mail.png similarity index 97% rename from src/resources/images/mail.png rename to core/src/main/resources/images/mail.png index c22b2a9bb..d89f17b78 100644 Binary files a/src/resources/images/mail.png and b/core/src/main/resources/images/mail.png differ diff --git a/src/resources/images/mail_16x16.png b/core/src/main/resources/images/mail_16x16.png similarity index 100% rename from src/resources/images/mail_16x16.png rename to core/src/main/resources/images/mail_16x16.png diff --git a/core/src/main/resources/images/mail_32x32.png b/core/src/main/resources/images/mail_32x32.png new file mode 100644 index 000000000..3c5e2e17c Binary files /dev/null and b/core/src/main/resources/images/mail_32x32.png differ diff --git a/src/resources/images/mail_forward_16x16.png b/core/src/main/resources/images/mail_forward_16x16.png similarity index 100% rename from src/resources/images/mail_forward_16x16.png rename to core/src/main/resources/images/mail_forward_16x16.png diff --git a/src/resources/images/mail_into_16x16.png b/core/src/main/resources/images/mail_into_16x16.png similarity index 100% rename from src/resources/images/mail_into_16x16.png rename to core/src/main/resources/images/mail_into_16x16.png diff --git a/src/resources/images/megaphone.gif b/core/src/main/resources/images/megaphone.gif similarity index 100% rename from src/resources/images/megaphone.gif rename to core/src/main/resources/images/megaphone.gif diff --git a/src/resources/images/megaphone.png b/core/src/main/resources/images/megaphone.png similarity index 100% rename from src/resources/images/megaphone.png rename to core/src/main/resources/images/megaphone.png diff --git a/core/src/main/resources/images/message-32x32.png b/core/src/main/resources/images/message-32x32.png new file mode 100644 index 000000000..66752924f Binary files /dev/null and b/core/src/main/resources/images/message-32x32.png differ diff --git a/src/resources/images/message.icns b/core/src/main/resources/images/message.icns similarity index 100% rename from src/resources/images/message.icns rename to core/src/main/resources/images/message.icns diff --git a/src/resources/images/message.ico b/core/src/main/resources/images/message.ico similarity index 100% rename from src/resources/images/message.ico rename to core/src/main/resources/images/message.ico diff --git a/src/plugins/jingle/src/resources/images/message.png b/core/src/main/resources/images/message.png similarity index 100% rename from src/plugins/jingle/src/resources/images/message.png rename to core/src/main/resources/images/message.png diff --git a/core/src/main/resources/images/message_away.png b/core/src/main/resources/images/message_away.png new file mode 100644 index 000000000..2be59bbc5 Binary files /dev/null and b/core/src/main/resources/images/message_away.png differ diff --git a/core/src/main/resources/images/message_dnd.png b/core/src/main/resources/images/message_dnd.png new file mode 100644 index 000000000..1346b2867 Binary files /dev/null and b/core/src/main/resources/images/message_dnd.png differ diff --git a/src/resources/images/message_edit.png b/core/src/main/resources/images/message_edit.png similarity index 100% rename from src/resources/images/message_edit.png rename to core/src/main/resources/images/message_edit.png diff --git a/core/src/main/resources/images/messages_48x48.png b/core/src/main/resources/images/messages_48x48.png new file mode 100644 index 000000000..f22e86025 Binary files /dev/null and b/core/src/main/resources/images/messages_48x48.png differ diff --git a/src/resources/images/metallic_down.png b/core/src/main/resources/images/metallic_down.png similarity index 75% rename from src/resources/images/metallic_down.png rename to core/src/main/resources/images/metallic_down.png index d05fe4067..db7108cb6 100644 Binary files a/src/resources/images/metallic_down.png and b/core/src/main/resources/images/metallic_down.png differ diff --git a/src/resources/images/metallic_up.png b/core/src/main/resources/images/metallic_up.png similarity index 76% rename from src/resources/images/metallic_up.png rename to core/src/main/resources/images/metallic_up.png index 70e83b838..68f989215 100644 Binary files a/src/resources/images/metallic_up.png and b/core/src/main/resources/images/metallic_up.png differ diff --git a/core/src/main/resources/images/minus-sign.png b/core/src/main/resources/images/minus-sign.png new file mode 100644 index 000000000..e77fa393a Binary files /dev/null and b/core/src/main/resources/images/minus-sign.png differ diff --git a/core/src/main/resources/images/mobilephone.png b/core/src/main/resources/images/mobilephone.png new file mode 100644 index 000000000..571e246c3 Binary files /dev/null and b/core/src/main/resources/images/mobilephone.png differ diff --git a/src/resources/images/moderator.gif b/core/src/main/resources/images/moderator.gif similarity index 100% rename from src/resources/images/moderator.gif rename to core/src/main/resources/images/moderator.gif diff --git a/src/resources/images/myspaceim-gray.gif b/core/src/main/resources/images/myspaceim-gray.gif similarity index 100% rename from src/resources/images/myspaceim-gray.gif rename to core/src/main/resources/images/myspaceim-gray.gif diff --git a/src/resources/images/myspaceim.gif b/core/src/main/resources/images/myspaceim.gif similarity index 100% rename from src/resources/images/myspaceim.gif rename to core/src/main/resources/images/myspaceim.gif diff --git a/src/resources/images/note_edit.png b/core/src/main/resources/images/note_edit.png similarity index 100% rename from src/resources/images/note_edit.png rename to core/src/main/resources/images/note_edit.png diff --git a/src/resources/images/notebook.png b/core/src/main/resources/images/notebook.png similarity index 100% rename from src/resources/images/notebook.png rename to core/src/main/resources/images/notebook.png diff --git a/core/src/main/resources/images/off-phone.png b/core/src/main/resources/images/off-phone.png new file mode 100644 index 000000000..f883d4f9a Binary files /dev/null and b/core/src/main/resources/images/off-phone.png differ diff --git a/src/resources/images/ok.gif b/core/src/main/resources/images/ok.gif similarity index 100% rename from src/resources/images/ok.gif rename to core/src/main/resources/images/ok.gif diff --git a/core/src/main/resources/images/on-phone.png b/core/src/main/resources/images/on-phone.png new file mode 100644 index 000000000..b9a2e4f14 Binary files /dev/null and b/core/src/main/resources/images/on-phone.png differ diff --git a/src/resources/images/openfile.gif b/core/src/main/resources/images/openfile.gif similarity index 100% rename from src/resources/images/openfile.gif rename to core/src/main/resources/images/openfile.gif diff --git a/src/resources/images/option.png b/core/src/main/resources/images/option.png similarity index 100% rename from src/resources/images/option.png rename to core/src/main/resources/images/option.png diff --git a/core/src/main/resources/images/palette_24x24.png b/core/src/main/resources/images/palette_24x24.png new file mode 100644 index 000000000..cb982e2a8 Binary files /dev/null and b/core/src/main/resources/images/palette_24x24.png differ diff --git a/src/resources/images/pawn_glass_green.png b/core/src/main/resources/images/pawn_glass_green.png similarity index 100% rename from src/resources/images/pawn_glass_green.png rename to core/src/main/resources/images/pawn_glass_green.png diff --git a/src/resources/images/pawn_glass_red.png b/core/src/main/resources/images/pawn_glass_red.png similarity index 100% rename from src/resources/images/pawn_glass_red.png rename to core/src/main/resources/images/pawn_glass_red.png diff --git a/src/resources/images/pawn_glass_white.png b/core/src/main/resources/images/pawn_glass_white.png similarity index 100% rename from src/resources/images/pawn_glass_white.png rename to core/src/main/resources/images/pawn_glass_white.png diff --git a/src/resources/images/pawn_glass_yellow.png b/core/src/main/resources/images/pawn_glass_yellow.png similarity index 100% rename from src/resources/images/pawn_glass_yellow.png rename to core/src/main/resources/images/pawn_glass_yellow.png diff --git a/src/resources/images/pdf.gif b/core/src/main/resources/images/pdf.gif similarity index 100% rename from src/resources/images/pdf.gif rename to core/src/main/resources/images/pdf.gif diff --git a/src/resources/images/people-icon.png b/core/src/main/resources/images/people-icon.png similarity index 100% rename from src/resources/images/people-icon.png rename to core/src/main/resources/images/people-icon.png diff --git a/core/src/main/resources/images/phone_call.png b/core/src/main/resources/images/phone_call.png new file mode 100644 index 000000000..0d3769506 Binary files /dev/null and b/core/src/main/resources/images/phone_call.png differ diff --git a/core/src/main/resources/images/photo_scenery.png b/core/src/main/resources/images/photo_scenery.png new file mode 100644 index 000000000..ffdcf2d5b Binary files /dev/null and b/core/src/main/resources/images/photo_scenery.png differ diff --git a/src/resources/images/pin_blue.png b/core/src/main/resources/images/pin_blue.png similarity index 100% rename from src/resources/images/pin_blue.png rename to core/src/main/resources/images/pin_blue.png diff --git a/core/src/main/resources/images/plug-sign.png b/core/src/main/resources/images/plug-sign.png new file mode 100644 index 000000000..d2ef6faa5 Binary files /dev/null and b/core/src/main/resources/images/plug-sign.png differ diff --git a/src/resources/images/plugin-16x16.gif b/core/src/main/resources/images/plugin-16x16.gif similarity index 100% rename from src/resources/images/plugin-16x16.gif rename to core/src/main/resources/images/plugin-16x16.gif diff --git a/core/src/main/resources/images/plus-sign.png b/core/src/main/resources/images/plus-sign.png new file mode 100644 index 000000000..d2ef6faa5 Binary files /dev/null and b/core/src/main/resources/images/plus-sign.png differ diff --git a/src/resources/images/pointer.gif b/core/src/main/resources/images/pointer.gif similarity index 100% rename from src/resources/images/pointer.gif rename to core/src/main/resources/images/pointer.gif diff --git a/core/src/main/resources/images/powered_by.png b/core/src/main/resources/images/powered_by.png new file mode 100644 index 000000000..007b495d9 Binary files /dev/null and b/core/src/main/resources/images/powered_by.png differ diff --git a/src/resources/images/preferences.png b/core/src/main/resources/images/preferences.png similarity index 100% rename from src/resources/images/preferences.png rename to core/src/main/resources/images/preferences.png diff --git a/src/resources/images/printer.png b/core/src/main/resources/images/printer.png similarity index 100% rename from src/resources/images/printer.png rename to core/src/main/resources/images/printer.png diff --git a/src/resources/images/privacy_block_16x16.png b/core/src/main/resources/images/privacy_block_16x16.png similarity index 100% rename from src/resources/images/privacy_block_16x16.png rename to core/src/main/resources/images/privacy_block_16x16.png diff --git a/src/resources/images/privacy_check.png b/core/src/main/resources/images/privacy_check.png similarity index 100% rename from src/resources/images/privacy_check.png rename to core/src/main/resources/images/privacy_check.png diff --git a/core/src/main/resources/images/privacy_icon.png b/core/src/main/resources/images/privacy_icon.png new file mode 100644 index 000000000..ccf75d002 Binary files /dev/null and b/core/src/main/resources/images/privacy_icon.png differ diff --git a/src/resources/images/privacy_icon_small.png b/core/src/main/resources/images/privacy_icon_small.png similarity index 100% rename from src/resources/images/privacy_icon_small.png rename to core/src/main/resources/images/privacy_icon_small.png diff --git a/src/resources/images/privacy_lightning.png b/core/src/main/resources/images/privacy_lightning.png similarity index 100% rename from src/resources/images/privacy_lightning.png rename to core/src/main/resources/images/privacy_lightning.png diff --git a/src/resources/images/privacy_list_deactivate.png b/core/src/main/resources/images/privacy_list_deactivate.png similarity index 100% rename from src/resources/images/privacy_list_deactivate.png rename to core/src/main/resources/images/privacy_list_deactivate.png diff --git a/core/src/main/resources/images/privacy_message_allow.png b/core/src/main/resources/images/privacy_message_allow.png new file mode 100644 index 000000000..c8ffa1a78 Binary files /dev/null and b/core/src/main/resources/images/privacy_message_allow.png differ diff --git a/core/src/main/resources/images/privacy_message_deny.png b/core/src/main/resources/images/privacy_message_deny.png new file mode 100644 index 000000000..d7c689c6e Binary files /dev/null and b/core/src/main/resources/images/privacy_message_deny.png differ diff --git a/core/src/main/resources/images/privacy_presence_in_allow.png b/core/src/main/resources/images/privacy_presence_in_allow.png new file mode 100644 index 000000000..f1289609f Binary files /dev/null and b/core/src/main/resources/images/privacy_presence_in_allow.png differ diff --git a/core/src/main/resources/images/privacy_presence_in_deny.png b/core/src/main/resources/images/privacy_presence_in_deny.png new file mode 100644 index 000000000..464882e5b Binary files /dev/null and b/core/src/main/resources/images/privacy_presence_in_deny.png differ diff --git a/core/src/main/resources/images/privacy_presence_out_allow.png b/core/src/main/resources/images/privacy_presence_out_allow.png new file mode 100644 index 000000000..1a23e6252 Binary files /dev/null and b/core/src/main/resources/images/privacy_presence_out_allow.png differ diff --git a/core/src/main/resources/images/privacy_presence_out_deny.png b/core/src/main/resources/images/privacy_presence_out_deny.png new file mode 100644 index 000000000..d43cd76d5 Binary files /dev/null and b/core/src/main/resources/images/privacy_presence_out_deny.png differ diff --git a/core/src/main/resources/images/privacy_query_allow.png b/core/src/main/resources/images/privacy_query_allow.png new file mode 100644 index 000000000..6037404e4 Binary files /dev/null and b/core/src/main/resources/images/privacy_query_allow.png differ diff --git a/core/src/main/resources/images/privacy_query_deny.png b/core/src/main/resources/images/privacy_query_deny.png new file mode 100644 index 000000000..c2c8fba2c Binary files /dev/null and b/core/src/main/resources/images/privacy_query_deny.png differ diff --git a/src/resources/images/privacy_unblock_16x16.png b/core/src/main/resources/images/privacy_unblock_16x16.png similarity index 100% rename from src/resources/images/privacy_unblock_16x16.png rename to core/src/main/resources/images/privacy_unblock_16x16.png diff --git a/core/src/main/resources/images/profile.png b/core/src/main/resources/images/profile.png new file mode 100644 index 000000000..586e1219c Binary files /dev/null and b/core/src/main/resources/images/profile.png differ diff --git a/src/resources/images/profile_16x16.png b/core/src/main/resources/images/profile_16x16.png similarity index 100% rename from src/resources/images/profile_16x16.png rename to core/src/main/resources/images/profile_16x16.png diff --git a/core/src/main/resources/images/profile_24x24.png b/core/src/main/resources/images/profile_24x24.png new file mode 100644 index 000000000..cdc70b7be Binary files /dev/null and b/core/src/main/resources/images/profile_24x24.png differ diff --git a/core/src/main/resources/images/profile_32x32.png b/core/src/main/resources/images/profile_32x32.png new file mode 100644 index 000000000..cae40d99c Binary files /dev/null and b/core/src/main/resources/images/profile_32x32.png differ diff --git a/src/resources/images/qq-gray.gif b/core/src/main/resources/images/qq-gray.gif similarity index 100% rename from src/resources/images/qq-gray.gif rename to core/src/main/resources/images/qq-gray.gif diff --git a/src/resources/images/qq.gif b/core/src/main/resources/images/qq.gif similarity index 100% rename from src/resources/images/qq.gif rename to core/src/main/resources/images/qq.gif diff --git a/src/resources/images/questionsAnswers.png b/core/src/main/resources/images/questionsAnswers.png similarity index 100% rename from src/resources/images/questionsAnswers.png rename to core/src/main/resources/images/questionsAnswers.png diff --git a/src/resources/images/red-ball.png b/core/src/main/resources/images/red-ball.png similarity index 100% rename from src/resources/images/red-ball.png rename to core/src/main/resources/images/red-ball.png diff --git a/src/resources/images/refresh.png b/core/src/main/resources/images/refresh.png similarity index 100% rename from src/resources/images/refresh.png rename to core/src/main/resources/images/refresh.png diff --git a/src/resources/images/reject.png b/core/src/main/resources/images/reject.png similarity index 100% rename from src/resources/images/reject.png rename to core/src/main/resources/images/reject.png diff --git a/core/src/main/resources/images/ripple.gif b/core/src/main/resources/images/ripple.gif new file mode 100644 index 000000000..14217c58b Binary files /dev/null and b/core/src/main/resources/images/ripple.gif differ diff --git a/src/resources/images/sametime-gray.gif b/core/src/main/resources/images/sametime-gray.gif similarity index 100% rename from src/resources/images/sametime-gray.gif rename to core/src/main/resources/images/sametime-gray.gif diff --git a/src/resources/images/sametime.gif b/core/src/main/resources/images/sametime.gif similarity index 100% rename from src/resources/images/sametime.gif rename to core/src/main/resources/images/sametime.gif diff --git a/src/resources/images/save_as.png b/core/src/main/resources/images/save_as.png similarity index 100% rename from src/resources/images/save_as.png rename to core/src/main/resources/images/save_as.png diff --git a/src/resources/images/scroll_refresh.png b/core/src/main/resources/images/scroll_refresh.png similarity index 100% rename from src/resources/images/scroll_refresh.png rename to core/src/main/resources/images/scroll_refresh.png diff --git a/core/src/main/resources/images/search_32x32.png b/core/src/main/resources/images/search_32x32.png new file mode 100644 index 000000000..73b66f09b Binary files /dev/null and b/core/src/main/resources/images/search_32x32.png differ diff --git a/src/resources/images/search_user_16x16.png b/core/src/main/resources/images/search_user_16x16.png similarity index 100% rename from src/resources/images/search_user_16x16.png rename to core/src/main/resources/images/search_user_16x16.png diff --git a/core/src/main/resources/images/secondary_background_image.png b/core/src/main/resources/images/secondary_background_image.png new file mode 100644 index 000000000..8447bb878 Binary files /dev/null and b/core/src/main/resources/images/secondary_background_image.png differ diff --git a/src/plugins/google/src/resources/images/send_file_24x24.png b/core/src/main/resources/images/send_file_24x24.png similarity index 100% rename from src/plugins/google/src/resources/images/send_file_24x24.png rename to core/src/main/resources/images/send_file_24x24.png diff --git a/src/resources/images/sendmail.png b/core/src/main/resources/images/sendmail.png similarity index 100% rename from src/resources/images/sendmail.png rename to core/src/main/resources/images/sendmail.png diff --git a/src/resources/images/server.png b/core/src/main/resources/images/server.png similarity index 100% rename from src/resources/images/server.png rename to core/src/main/resources/images/server.png diff --git a/src/resources/images/settings16x16.png b/core/src/main/resources/images/settings16x16.png similarity index 100% rename from src/resources/images/settings16x16.png rename to core/src/main/resources/images/settings16x16.png diff --git a/core/src/main/resources/images/settings24x24.png b/core/src/main/resources/images/settings24x24.png new file mode 100644 index 000000000..bb187860d Binary files /dev/null and b/core/src/main/resources/images/settings24x24.png differ diff --git a/src/resources/images/sign.gif b/core/src/main/resources/images/sign.gif similarity index 100% rename from src/resources/images/sign.gif rename to core/src/main/resources/images/sign.gif diff --git a/core/src/main/resources/images/simple-gray.png b/core/src/main/resources/images/simple-gray.png new file mode 100644 index 000000000..ea09da8f2 Binary files /dev/null and b/core/src/main/resources/images/simple-gray.png differ diff --git a/core/src/main/resources/images/simple.png b/core/src/main/resources/images/simple.png new file mode 100644 index 000000000..0fc8d3456 Binary files /dev/null and b/core/src/main/resources/images/simple.png differ diff --git a/src/resources/images/smallCheck.png b/core/src/main/resources/images/smallCheck.png similarity index 100% rename from src/resources/images/smallCheck.png rename to core/src/main/resources/images/smallCheck.png diff --git a/src/resources/images/smallDelete.png b/core/src/main/resources/images/smallDelete.png similarity index 100% rename from src/resources/images/smallDelete.png rename to core/src/main/resources/images/smallDelete.png diff --git a/src/resources/images/smallStop.png b/core/src/main/resources/images/smallStop.png similarity index 100% rename from src/resources/images/smallStop.png rename to core/src/main/resources/images/smallStop.png diff --git a/src/resources/images/smallUserDelete.png b/core/src/main/resources/images/smallUserDelete.png similarity index 100% rename from src/resources/images/smallUserDelete.png rename to core/src/main/resources/images/smallUserDelete.png diff --git a/src/resources/images/smallUserEnter.png b/core/src/main/resources/images/smallUserEnter.png similarity index 100% rename from src/resources/images/smallUserEnter.png rename to core/src/main/resources/images/smallUserEnter.png diff --git a/src/resources/images/small_add.png b/core/src/main/resources/images/small_add.png similarity index 100% rename from src/resources/images/small_add.png rename to core/src/main/resources/images/small_add.png diff --git a/src/resources/images/small_agent.png b/core/src/main/resources/images/small_agent.png similarity index 100% rename from src/resources/images/small_agent.png rename to core/src/main/resources/images/small_agent.png diff --git a/src/resources/images/small_delete.png b/core/src/main/resources/images/small_delete.png similarity index 100% rename from src/resources/images/small_delete.png rename to core/src/main/resources/images/small_delete.png diff --git a/src/resources/images/small_entry.gif b/core/src/main/resources/images/small_entry.gif similarity index 100% rename from src/resources/images/small_entry.gif rename to core/src/main/resources/images/small_entry.gif diff --git a/src/resources/images/small_profile.png b/core/src/main/resources/images/small_profile.png similarity index 100% rename from src/resources/images/small_profile.png rename to core/src/main/resources/images/small_profile.png diff --git a/src/resources/images/spark-16x16.png b/core/src/main/resources/images/spark-16x16.png similarity index 100% rename from src/resources/images/spark-16x16.png rename to core/src/main/resources/images/spark-16x16.png diff --git a/core/src/main/resources/images/spark-24x24.png b/core/src/main/resources/images/spark-24x24.png new file mode 100644 index 000000000..a11c45d81 Binary files /dev/null and b/core/src/main/resources/images/spark-24x24.png differ diff --git a/core/src/main/resources/images/spark-32x32.png b/core/src/main/resources/images/spark-32x32.png new file mode 100644 index 000000000..630c5ca56 Binary files /dev/null and b/core/src/main/resources/images/spark-32x32.png differ diff --git a/core/src/main/resources/images/spark-60x60.png b/core/src/main/resources/images/spark-60x60.png new file mode 100644 index 000000000..651f98a2b Binary files /dev/null and b/core/src/main/resources/images/spark-60x60.png differ diff --git a/core/src/main/resources/images/spark-64x64.png b/core/src/main/resources/images/spark-64x64.png new file mode 100644 index 000000000..3fbb4d44e Binary files /dev/null and b/core/src/main/resources/images/spark-64x64.png differ diff --git a/src/resources/images/spark.gif b/core/src/main/resources/images/spark.gif similarity index 100% rename from src/resources/images/spark.gif rename to core/src/main/resources/images/spark.gif diff --git a/src/resources/images/spark.ico b/core/src/main/resources/images/spark.ico similarity index 100% rename from src/resources/images/spark.ico rename to core/src/main/resources/images/spark.ico diff --git a/core/src/main/resources/images/spark.png b/core/src/main/resources/images/spark.png new file mode 100644 index 000000000..33c52577e Binary files /dev/null and b/core/src/main/resources/images/spark.png differ diff --git a/src/resources/images/spark_100.jpg b/core/src/main/resources/images/spark_100.jpg similarity index 100% rename from src/resources/images/spark_100.jpg rename to core/src/main/resources/images/spark_100.jpg diff --git a/core/src/main/resources/images/spark_tray_connecting-16x16.png b/core/src/main/resources/images/spark_tray_connecting-16x16.png new file mode 100644 index 000000000..3ce1d95f2 Binary files /dev/null and b/core/src/main/resources/images/spark_tray_connecting-16x16.png differ diff --git a/core/src/main/resources/images/spark_tray_connecting-24x24.png b/core/src/main/resources/images/spark_tray_connecting-24x24.png new file mode 100644 index 000000000..46936fc78 Binary files /dev/null and b/core/src/main/resources/images/spark_tray_connecting-24x24.png differ diff --git a/src/resources/images/spark_tray_message-16x16.png b/core/src/main/resources/images/spark_tray_message-16x16.png similarity index 100% rename from src/resources/images/spark_tray_message-16x16.png rename to core/src/main/resources/images/spark_tray_message-16x16.png diff --git a/core/src/main/resources/images/spark_tray_message-24x24.png b/core/src/main/resources/images/spark_tray_message-24x24.png new file mode 100644 index 000000000..a7d2c284e Binary files /dev/null and b/core/src/main/resources/images/spark_tray_message-24x24.png differ diff --git a/core/src/main/resources/images/spark_tray_offline-16x16.png b/core/src/main/resources/images/spark_tray_offline-16x16.png new file mode 100644 index 000000000..3ce1d95f2 Binary files /dev/null and b/core/src/main/resources/images/spark_tray_offline-16x16.png differ diff --git a/core/src/main/resources/images/spark_tray_offline-24x24.png b/core/src/main/resources/images/spark_tray_offline-24x24.png new file mode 100644 index 000000000..7f4d8a804 Binary files /dev/null and b/core/src/main/resources/images/spark_tray_offline-24x24.png differ diff --git a/core/src/main/resources/images/spark_tray_typing-24x24.png b/core/src/main/resources/images/spark_tray_typing-24x24.png new file mode 100644 index 000000000..545483a6d Binary files /dev/null and b/core/src/main/resources/images/spark_tray_typing-24x24.png differ diff --git a/core/src/main/resources/images/star_admin.png b/core/src/main/resources/images/star_admin.png new file mode 100644 index 000000000..c1a1539ba Binary files /dev/null and b/core/src/main/resources/images/star_admin.png differ diff --git a/src/resources/images/star_blue.png b/core/src/main/resources/images/star_blue.png similarity index 100% rename from src/resources/images/star_blue.png rename to core/src/main/resources/images/star_blue.png diff --git a/src/resources/images/star_green.png b/core/src/main/resources/images/star_green.png similarity index 100% rename from src/resources/images/star_green.png rename to core/src/main/resources/images/star_green.png diff --git a/src/resources/images/star_grey.png b/core/src/main/resources/images/star_grey.png similarity index 100% rename from src/resources/images/star_grey.png rename to core/src/main/resources/images/star_grey.png diff --git a/core/src/main/resources/images/star_moderator.png b/core/src/main/resources/images/star_moderator.png new file mode 100644 index 000000000..827061696 Binary files /dev/null and b/core/src/main/resources/images/star_moderator.png differ diff --git a/core/src/main/resources/images/star_owner.png b/core/src/main/resources/images/star_owner.png new file mode 100644 index 000000000..439c690ef Binary files /dev/null and b/core/src/main/resources/images/star_owner.png differ diff --git a/src/resources/images/star_red.png b/core/src/main/resources/images/star_red.png similarity index 100% rename from src/resources/images/star_red.png rename to core/src/main/resources/images/star_red.png diff --git a/src/resources/images/star_yellow.png b/core/src/main/resources/images/star_yellow.png similarity index 100% rename from src/resources/images/star_yellow.png rename to core/src/main/resources/images/star_yellow.png diff --git a/core/src/main/resources/images/sticky.png b/core/src/main/resources/images/sticky.png new file mode 100644 index 000000000..f507f1204 Binary files /dev/null and b/core/src/main/resources/images/sticky.png differ diff --git a/src/resources/images/stopwatch_pause.png b/core/src/main/resources/images/stopwatch_pause.png similarity index 100% rename from src/resources/images/stopwatch_pause.png rename to core/src/main/resources/images/stopwatch_pause.png diff --git a/src/resources/images/telephone_24x24.png b/core/src/main/resources/images/telephone_24x24.png similarity index 100% rename from src/resources/images/telephone_24x24.png rename to core/src/main/resources/images/telephone_24x24.png diff --git a/src/resources/images/tellAFriend.gif b/core/src/main/resources/images/tellAFriend.gif similarity index 100% rename from src/resources/images/tellAFriend.gif rename to core/src/main/resources/images/tellAFriend.gif diff --git a/src/resources/images/textFile.gif b/core/src/main/resources/images/textFile.gif similarity index 100% rename from src/resources/images/textFile.gif rename to core/src/main/resources/images/textFile.gif diff --git a/src/resources/images/text_bold.png b/core/src/main/resources/images/text_bold.png similarity index 100% rename from src/resources/images/text_bold.png rename to core/src/main/resources/images/text_bold.png diff --git a/src/resources/images/text_italics.png b/core/src/main/resources/images/text_italics.png similarity index 100% rename from src/resources/images/text_italics.png rename to core/src/main/resources/images/text_italics.png diff --git a/src/resources/images/text_loudspeaker.png b/core/src/main/resources/images/text_loudspeaker.png similarity index 100% rename from src/resources/images/text_loudspeaker.png rename to core/src/main/resources/images/text_loudspeaker.png diff --git a/src/resources/images/text_normal.png b/core/src/main/resources/images/text_normal.png similarity index 100% rename from src/resources/images/text_normal.png rename to core/src/main/resources/images/text_normal.png diff --git a/src/plugins/spelling/src/resources/text_ok.png b/core/src/main/resources/images/text_ok.png similarity index 100% rename from src/plugins/spelling/src/resources/text_ok.png rename to core/src/main/resources/images/text_ok.png diff --git a/src/resources/images/text_underlined.png b/core/src/main/resources/images/text_underlined.png similarity index 100% rename from src/resources/images/text_underlined.png rename to core/src/main/resources/images/text_underlined.png diff --git a/core/src/main/resources/images/toolbar.png b/core/src/main/resources/images/toolbar.png new file mode 100644 index 000000000..a65c9024a Binary files /dev/null and b/core/src/main/resources/images/toolbar.png differ diff --git a/core/src/main/resources/images/top_bottom_background_image.png b/core/src/main/resources/images/top_bottom_background_image.png new file mode 100644 index 000000000..e77829b32 Binary files /dev/null and b/core/src/main/resources/images/top_bottom_background_image.png differ diff --git a/src/resources/images/traffic-light.png b/core/src/main/resources/images/traffic-light.png similarity index 100% rename from src/resources/images/traffic-light.png rename to core/src/main/resources/images/traffic-light.png diff --git a/core/src/main/resources/images/transfer-24x24.png b/core/src/main/resources/images/transfer-24x24.png new file mode 100644 index 000000000..10a0082dd Binary files /dev/null and b/core/src/main/resources/images/transfer-24x24.png differ diff --git a/core/src/main/resources/images/transport.png b/core/src/main/resources/images/transport.png new file mode 100644 index 000000000..b6e364e60 Binary files /dev/null and b/core/src/main/resources/images/transport.png differ diff --git a/src/resources/images/txt.gif b/core/src/main/resources/images/txt.gif similarity index 100% rename from src/resources/images/txt.gif rename to core/src/main/resources/images/txt.gif diff --git a/src/resources/images/user.png b/core/src/main/resources/images/user.png similarity index 100% rename from src/resources/images/user.png rename to core/src/main/resources/images/user.png diff --git a/core/src/main/resources/images/user1.png b/core/src/main/resources/images/user1.png new file mode 100644 index 000000000..c152e5a90 Binary files /dev/null and b/core/src/main/resources/images/user1.png differ diff --git a/src/resources/images/user1_add.png b/core/src/main/resources/images/user1_add.png similarity index 100% rename from src/resources/images/user1_add.png rename to core/src/main/resources/images/user1_add.png diff --git a/src/resources/images/user1_back.png b/core/src/main/resources/images/user1_back.png similarity index 100% rename from src/resources/images/user1_back.png rename to core/src/main/resources/images/user1_back.png diff --git a/src/resources/images/user1_earth.png b/core/src/main/resources/images/user1_earth.png similarity index 100% rename from src/resources/images/user1_earth.png rename to core/src/main/resources/images/user1_earth.png diff --git a/src/resources/images/user1_information.png b/core/src/main/resources/images/user1_information.png similarity index 100% rename from src/resources/images/user1_information.png rename to core/src/main/resources/images/user1_information.png diff --git a/src/resources/images/user1_message-16x16.png b/core/src/main/resources/images/user1_message-16x16.png similarity index 100% rename from src/resources/images/user1_message-16x16.png rename to core/src/main/resources/images/user1_message-16x16.png diff --git a/core/src/main/resources/images/user1_message-24x24.png b/core/src/main/resources/images/user1_message-24x24.png new file mode 100644 index 000000000..1b91d0824 Binary files /dev/null and b/core/src/main/resources/images/user1_message-24x24.png differ diff --git a/src/resources/images/user1_mobilephone.png b/core/src/main/resources/images/user1_mobilephone.png similarity index 100% rename from src/resources/images/user1_mobilephone.png rename to core/src/main/resources/images/user1_mobilephone.png diff --git a/src/resources/images/user1_new.png b/core/src/main/resources/images/user1_new.png similarity index 100% rename from src/resources/images/user1_new.png rename to core/src/main/resources/images/user1_new.png diff --git a/src/resources/images/user1_time.png b/core/src/main/resources/images/user1_time.png similarity index 100% rename from src/resources/images/user1_time.png rename to core/src/main/resources/images/user1_time.png diff --git a/core/src/main/resources/images/user2.png b/core/src/main/resources/images/user2.png new file mode 100644 index 000000000..17c79c8f9 Binary files /dev/null and b/core/src/main/resources/images/user2.png differ diff --git a/core/src/main/resources/images/user4.png b/core/src/main/resources/images/user4.png new file mode 100644 index 000000000..0e27a3f56 Binary files /dev/null and b/core/src/main/resources/images/user4.png differ diff --git a/core/src/main/resources/images/user_headset24.png b/core/src/main/resources/images/user_headset24.png new file mode 100644 index 000000000..c152e5a90 Binary files /dev/null and b/core/src/main/resources/images/user_headset24.png differ diff --git a/src/resources/images/users2.png b/core/src/main/resources/images/users2.png similarity index 100% rename from src/resources/images/users2.png rename to core/src/main/resources/images/users2.png diff --git a/src/resources/images/users_family.png b/core/src/main/resources/images/users_family.png similarity index 100% rename from src/resources/images/users_family.png rename to core/src/main/resources/images/users_family.png diff --git a/src/resources/images/users_into.png b/core/src/main/resources/images/users_into.png similarity index 100% rename from src/resources/images/users_into.png rename to core/src/main/resources/images/users_into.png diff --git a/src/resources/images/validate.gif b/core/src/main/resources/images/validate.gif similarity index 100% rename from src/resources/images/validate.gif rename to core/src/main/resources/images/validate.gif diff --git a/src/resources/images/view.png b/core/src/main/resources/images/view.png similarity index 100% rename from src/resources/images/view.png rename to core/src/main/resources/images/view.png diff --git a/src/resources/images/window_to_front_active.png b/core/src/main/resources/images/window_to_front_active.png similarity index 100% rename from src/resources/images/window_to_front_active.png rename to core/src/main/resources/images/window_to_front_active.png diff --git a/src/resources/images/window_to_front_deactive.png b/core/src/main/resources/images/window_to_front_deactive.png similarity index 76% rename from src/resources/images/window_to_front_deactive.png rename to core/src/main/resources/images/window_to_front_deactive.png index 88b8e3afc..62cefabeb 100644 Binary files a/src/resources/images/window_to_front_deactive.png and b/core/src/main/resources/images/window_to_front_deactive.png differ diff --git a/core/src/main/resources/images/xmpp-gray.png b/core/src/main/resources/images/xmpp-gray.png new file mode 100644 index 000000000..716a7ecb2 Binary files /dev/null and b/core/src/main/resources/images/xmpp-gray.png differ diff --git a/src/resources/images/xmpp.png b/core/src/main/resources/images/xmpp.png similarity index 100% rename from src/resources/images/xmpp.png rename to core/src/main/resources/images/xmpp.png diff --git a/core/src/main/resources/images/yellow-ball.png b/core/src/main/resources/images/yellow-ball.png new file mode 100644 index 000000000..ad09b5c50 Binary files /dev/null and b/core/src/main/resources/images/yellow-ball.png differ diff --git a/core/src/main/resources/spark.properties b/core/src/main/resources/spark.properties new file mode 100644 index 000000000..1c5a4ddb4 --- /dev/null +++ b/core/src/main/resources/spark.properties @@ -0,0 +1,357 @@ +APP_NAME = Spark +VERSION = ${project.version} + +SPARK_IMAGE = images/spark.png +WELCOME = Welcome +ID_CARD_48x48 = images/id_card.png + +# LOGIN DIALOG +LOGIN_DIALOG_LOGIN = &Login +LOGIN_DIALOG_QUIT = &Quit +LOGIN_DIALOG_USERNAME = &Username: +LOGIN_DIALOG_PASSWORD = &Password: +LOGIN_DIALOG_WORKSPACE = &Workgroup: +LOGIN_DIALOG_LOGIN_TITLE = Spark +LOGIN_DIALOG_AUTHENTICATING = Authenticating... + + +# PrivacyPlugin +PRIVACY_QUERY_DENY = images/icons/privacy_query_deny.png +PRIVACY_QUERY_ALLOW = images/icons/privacy_query_allow.png +PRIVACY_POUT_DENY = images/icons/privacy_presence_out_deny.png +PRIVACY_POUT_ALLOW = images/icons/privacy_presence_out_allow.png +PRIVACY_PIN_DENY = images/icons/privacy_presence_in_deny.png +PRIVACY_PIN_ALLOW = images/icons/privacy_presence_in_allow.png +PRIVACY_MSG_DENY = images/icons/privacy_message_deny.png +PRIVACY_MSG_ALLOW = images/icons/privacy_message_allow.png +CLIPBOARD = images/icons/clipboard.png +PRIVACY_ICON = images/icons/privacy.png +PRIVACY_ICON_SMALL = images/icons/privacy.png +PRIVACY_LIGHTNING = images/icons/privacy_lightning.png +PRIVACY_CHECK = images/icons/privacy_check.png +PRIVACY_DEACTIVATE_LIST = images/icons/privacy_list_deactivate.png + + + +#MainWindow +MAIN_IMAGE = images/spark-64x64.png +TRAY_IMAGE = images/spark-16x16.png +TRAY_AWAY = images/icons/Away.png +TRAY_XAWAY = images/icons/XAway.png +TRAY_DND = images/icons/DoNotDisturb.png +TRAY_OFFLINE = images/spark_tray_offline-16x16.png +TRAY_CONNECTING = images/icons/spark_tray_connecting-16x16.png +TRAY_IMAGE_LINUX = images/spark-24x24.png +TRAY_AWAY_LINUX = images/icons/Away-24x24.png +TRAY_XAWAY_LINUX = images/icons/XAway-24x24.png +TRAY_DND_LINUX = images/icons/DoNotDisturb-24x24.png +TRAY_OFFLINE_LINUX = images/spark_tray_offline-24x24.png +TRAY_CONNECTING_LINUX = images/icons/spark_tray_connecting-24x24.png +SPARK_IMAGE_32x32 = images/spark-32x32.png +MAIN_IMAGE_ICO = images/icon_16.ico +MAIN_ICNS_FILE = images/message.icns +SMALL_CHECK = images/icons/accept.png +SMALL_DELETE = images/icons/remove.png +AVAILABLE_USER = images/icons/user.png +AWAY_USER = images/awayUser.png +FIND_IMAGE = images/find.png +SMALL_ADD_IMAGE = images/icons/add.png +DOCUMENT_EXCHANGE_IMAGE = images/document_exchange.png +SMALL_DOCUMENT_ADD = images/document_add.png +SMALL_CIRCLE_DELETE = images/icons/close.png +SMALL_DOCUMENT_VIEW = images/document_view.png +SMALL_USER1_MESSAGE = images/icons/chat_settings.png +USER1_MESSAGE_24x24 = images/icons/chat_settings.png +SMALL_USER1_TIME = images/user1_time.png +SMALL_USER1_NEW = images/icons/create.png +SMALL_USER1_STOPWATCH = images/stopwatch_pause.png +SMALL_USER1_MOBILEPHONE = images/user1_mobilephone.png +SMALL_USER1_INFORMATION = images/icons/subscribe.png +SMALL_ENTRY = images/icons/small_entry.png +SMALL_AGENT_IMAGE = images/small_agent.png +CHATTING_AGENT_IMAGE = images/user1.png +CHATTING_CUSTOMER_IMAGE = images/user2.png +INFORMATION_IMAGE = images/icons/about.png +BLANK_IMAGE = images/blank.gif +USER_HEADSET_24x24 = images/user_headset24.png +FOLDER_CLOSED = images/icons/folder.png +FOLDER = images/icons/folder.png +SMALL_PIN_BLUE = images/pin_blue.png +SMALL_DATA_FIND_IMAGE = images/icons/search.png +SMALL_BUSINESS_MAN_VIEW = images/icons/edit_profile.png +SMALL_ALL_AGENTS_IMAGE = images/user1_earth.png +SMALL_WORKGROUP_QUEUE_IMAGE = images/icons/start_conference.png +SMALL_ALL_CHATS_IMAGE = images/icons/contacts.png +SMALL_CURRENT_AGENTS = images/icons/users.png +HELP2_24x24 = images/icons/help.png +SMALL_ALARM_CLOCK = images/icons/alarmclock.png +SMALL_SCROLL_REFRESH = images/scroll_refresh.png +SMALL_QUESTION = images/icons/help.png +USER1_32x32 = images/User1_32x32.png +DATA_DELETE_16x16 = images/data_delete.png +DATA_REFRESH_16x16 = images/data_refresh.png +USER1_BACK_16x16 = images/user1_back.png +FONT_16x16 = images/font.png +DOCUMENT_FIND_16x16 = images/document_find.png +DOCUMENT_INFO_32x32 = images/document_info.png +DOCUMENT_16x16 = images/icons/note.png +SMALL_CLOSE_BUTTON = images/icons/close.png +COPY_16x16 = images/icons/copy.png +BLANK_24x24 = images/blank_24x24.png +PUSH_URL_16x16 = images/earth_connection-16x16.png +LINK_16x16 = images/icons/link.png +LINK_DELETE_16x16 = images/icons/link_delete.png +EARTH_LOCK_16x16 = images/earth_lock-16x16.png +LOCK_16x16 = images/icons/lock.png +BLOCK_CONTACT_16x16 = images/icons/block.png +UNBLOCK_CONTACT_16x16 = images/icons/unblock.png +LOCK_UNLOCK_16x16 = images/icons/unlock.png +ONLINE_ICO = images/icon1.ico +OFFLINE_ICO = images/icon2.ico +INFORMATION_ICO = images/icon3.ico +SAVE_AS_16x16 = images/icons/save.png +NOTE_EDIT_16x16 = images/note_edit.png +ADDRESS_BOOK_16x16 = images/icons/address_book.png +MEGAPHONE_16x16 = images/icons/broadcast.png +EARTH_VIEW_16x16 = images/earth_view.png +HISTORY_16x16 = images/icons/history.png +DOWNLOAD_16x16 = images/icons/downloads.png +CHECK_UPDATE = images/icons/check_update.png +RED_FLAG_16x16 = images/icons/ban.png +GREEN_FLAG_16x16 = images/flag_green.png +YELLOW_FLAG_16x16 = images/flag_yellow.png +FUNNEL_DOWN_16x16 = images/funnel_down.png +MAIL_16x16 = images/mail_16x16.png +MAIL_FORWARD_16x16 = images/mail_forward_16x16.png +MAIL_INTO_16x16 = images/mail_into_16x16.png +RED_BALL = images/red-ball.png +GREEN_BALL = images/icons/im_available.png +BLUE_BALL = images/blue-ball.png +YELLOW_BALL = images/yellow-ball.png +PAWN_GLASS_GREEN = images/pawn_glass_green.png +PAWN_GLASS_RED = images/pawn_glass_red.png +PAWN_GLASS_WHITE = images/pawn_glass_white.png +PAWN_GLASS_YELLOW = images/pawn_glass_yellow.png +PLUS_SIGN = images/plus-sign.png +MINUS_SIGN = images/minus-sign.png +MAGICIAN_IMAGE = images/magician.png +FIND_TEXT_IMAGE = images/icons/lookup.png +LOGIN_KEY_IMAGE = images/icons/login.png +BRICKWALL_IMAGE = images/icons/block.png +MODERATOR_IMAGE = images/icons/moderator.png +DESKTOP_IMAGE = images/icons/tasklist.png +SPELL_CHECK_IMAGE = images/spellcheck_16x16.png +BUSY_IMAGE = images/icons/busy.gif +CLOSE_IMAGE = images/icons/close.png +VIEW_IMAGE = images/icons/search.png +MOBILE_PHONE_IMAGE = images/mobilephone.png +ON_PHONE_IMAGE = images/icons/on-phone.png +REFRESH_IMAGE = images/icons/refresh.png +CLOSE_WHITE_X_IMAGE = images/icons/close.png +CLOSE_RED_X_IMAGE = images/icons/close_red.png +PALETTE_24x24_IMAGE = images/icons/appearance.png +NOTIFICATIONS = images/icons/notifications.png +COLOR_ICON = images/icons/colors.png +DEFAULT_AVATAR_16x16_IMAGE = images/icons/user24.png +DEFAULT_AVATAR_32x32_IMAGE = images/icons/user32.png +DEFAULT_AVATAR_64x64_IMAGE = images/icons/user64.png + +# Global Values +ERROR_INVALID_WORKGROUP = The workgroup is not valid. Please use a valid workgroup. +ERROR_DIALOG_TITLE = Login Error +INVALID_USERNAME_PASSWORD = Invalid username or password. +SERVER_UNAVAILABLE = Can't connect to server: invalid name or server not reachable. +UNRECOVERABLE_ERROR = Unknown connection error. Please review the logs for more information. + +#Chat Window Images +ALERT = images/icons/alert.png +FRAME_ALWAYS_ON_TOP_ACTIVE = images/icons/pin_top.png +FRAME_ALWAYS_ON_TOP_DEACTIVE = images/icons/unpin_top.png + + +#Chat window text +SEND = &Send +ADD_TO_KB = You can assign any response as either a question or an answer add them directly to the knowledge base for future reference. + +#Kbase Window +GO = &Go +ADD_TO_CHAT = &Add document +ADD_LINK_TO_CHAT = Add &link +VIEW = &View +SEARCH = &Search: + +#Chat Queue +ACCEPT_CHAT = &Accept +REJECT_CHAT = &Refuse +TIME_LEFT = Time left: + +#MainWindow +MAIN_TITLE = Spark +TOOLBOX = Toolbox +CHAT_QUEUE = Chat Queue +CURRENT_CHATS = My Chats +CURRENT_AGENTS = Online Agents +ALL_CHATS = All Chats +WORKGROUP_QUEUE = Queues +CHAT_WORKSPACE = Chat Workspace + +#GroupChat +CREATE_FAQ_ENTRY = Create a new FAQ entry? +CREATE_FAQ_TITLE = Create New FAQ +FAQ_TAB_TITLE = Analyzer +KNOWLEDGE_BASE_TAB_TITLE = Search +PROFILE_TAB_TITLE = Profile +CO_BROWSER_TAB_TITLE = Co-Browser +FORUM_TAB_TITLE = Forums + +#Images +CANCEL_IMAGE = images/cancel.gif +CONFERENCE_IMAGE_24x24 = images/icons/invite24.png +CONFERENCE_IMAGE_16x16 = images/icons/conference.png +PROFILE_IMAGE_24x24 = images/icons/profile24.png +SEARCH_USER_16x16 = images/icons/search.png +SEND_FILE_24x24 = images/icons/send_file24.png +ADD_IMAGE_24x24 = images/icons/add_user_24.png +TELEPHONE_24x24 = images/icons/phone.png +IM_DND = images/icons/im_dnd.png +IM_AWAY = images/icons/im_away.png +IM_XA = images/icons/im_xa.png +INVISIBLE = images/icons/im_unavailable_stale.png +MESSAGE_AWAY = images/icons/Away.png +MESSAGE_DND = images/icons/DoNotDisturb.png +MESSAGE_NEW_TRAY = images/icons/spark_tray_message-16x16.png +MESSAGE_NEW_TRAY_LINUX = images/icons/spark_tray_message-24x24.png +TYPING_TRAY = images/icons/edit.png +TYPING_TRAY_LINUX = images/icons/edit.png +OFFLINE_IMAGE = images/Offline.png +ERASER_IMAGE = images/icons/clear.png +TOOLBAR_BACKGROUND = images/toolbar.png +TRAFFIC_LIGHT_IMAGE = images/traffic-light.png +SERVER_ICON = images/icons/conferences.png +BOOKMARK_ICON = images/icons/bookmark.png +ADD_BOOKMARK_ICON = images/icons/bookmark.png +DELETE_BOOKMARK_ICON = images/icons/remove.png +CLEAR_BALL_ICON = images/icons/im_unavailable.png +CALL_ICON = images/call.png +PROFILE_ICON = images/profile.png +SEND_FILE_ICON = images/icons/send_file.png +ADD_CONTACT_IMAGE = images/icons/add_user.png +JOIN_GROUPCHAT_IMAGE = images/icons/join.png +PEOPLE_IMAGE = images/icons/add_user.png +DOWN_ARROW_IMAGE = images/down_arrow.gif +PRINTER_IMAGE_16x16 = images/icons/print.png +SEND_MAIL_IMAGE_16x16 = images/sendmail.png +SEARCH_IMAGE_32x32 = images/icons/search.png +MAIL_IMAGE_32x32 = images/mail_32x32.png +PREFERENCES_IMAGE = images/icons/preferences.png +NOTEBOOK_IMAGE = images/icons/notebook.png +TEXT_BOLD = images/text_bold.png +TEXT_ITALIC = images/text_italics.png +TEXT_UNDERLINE = images/text_underlined.png +TEXT_NORMAL = images/text_normal.png +SMALL_USER_ENTER = images/icons/join.png +SMALL_USER_DELETE = images/icons/remove.png +QUESTIONS_ANSWERS = images/questionsAnswers.png +SMALL_MESSAGE_IMAGE = images/icons/start_chat.png +SMALL_MESSAGE_EDIT_IMAGE = images/icons/edit.png +SMALL_ABOUT_IMAGE = images/icons/about.png +DOOR_IMAGE = images/icons/join.png +STAR_BLUE_IMAGE = images/icons/star_blue.png +STAR_RED_IMAGE = images/icons/star_red.png +STAR_GREY_IMAGE = images/icons/star.png +STAR_YELLOW_IMAGE = images/icons/star_yellow.png +STAR_GREEN_IMAGE = images/icons/star_green.png +STAR_OWNER = images/icons/star_owner.png +STAR_ADMIN = images/icons/star_admin.png +STAR_MODERATOR = images/icons/star_moderator.png +LEFT_ARROW_IMAGE = images/arrow_left_green.png +RIGHT_ARROW_IMAGE = images/arrow_right_green.png +BACKGROUND_IMAGE = images/background.png +FREE_TO_CHAT_IMAGE = images/icons/im_free_chat.png +SOUND_PREFERENCES_IMAGE = images/icons/sound.png +SPARK_LOGOUT_IMAGE = images/spark_100.jpg +PHOTO_IMAGE = images/icons/screenshot24.png +PLUGIN_IMAGE = images/icons/plugins.png +SMALL_PROFILE_IMAGE = images/icons/profile.png +CHANGELOG_IMAGE = images/doc-changelog-16x16.gif +README_IMAGE = images/doc-readme-16x16.gif +DOWN_OPTION_IMAGE = images/icons/collapse_down.png +STICKY_NOTE_IMAGE = images/sticky.png +HISTORY_24x24 = images/icons/history24.png +PANE_UP_ARROW_IMAGE = images/icons/collapse_up.png +PANE_DOWN_ARROW_IMAGE = images/icons/collapse_down.png +PROFILE_IMAGE_16x16 = images/icons/profile.png +LIGHTBULB_ON_16x16_IMAGE = images/lightbulb_on.png +DUMMY_CONTACT_IMAGE = images/dummyContact.png +CALENDAR_IMAGE = images/icon_calendarpicker.gif +TASK_DELETE_IMAGE = images/delete.png + +#Fastpath Icons +FASTPATH_IMAGE_16x16 = images/fastpath16.png +FASTPATH_IMAGE_24x24 = images/fastpath24.png +FASTPATH_IMAGE_32x32 = images/fastpath32.png +CIRCLE_CHECK_IMAGE = images/check.png +TRANSFER_IMAGE_24x24 = images/icons/add_user_24.png +FASTPATH_OFFLINE_IMAGE_16x16 = images/fastpath16_offline.png +FASTPATH_OFFLINE_IMAGE_24x24 = images/fastpath24_offline.png +USER1_ADD_16x16 = images/icons/add_user.png +END_BUTTON_24x24 = images/end_button_24x24.png +POWERED_BY_IMAGE = images/powered_by.png + +# Transport images +XMPP_TRANSPORT_ACTIVE_IMAGE = images/xmpp.png +XMPP_TRANSPORT_INACTIVE_IMAGE = images/xmpp-gray.png +IRC_TRANSPORT_ACTIVE_IMAGE = images/irc.png +IRC_TRANSPORT_INACTIVE_IMAGE = images/irc-gray.png +GADUGADU_TRANSPORT_ACTIVE_IMAGE = images/gadugadu.gif +GADUGADU_TRANSPORT_INACTIVE_IMAGE = images/gadugadu-gray.gif +SIMPLE_TRANSPORT_ACTIVE_IMAGE = images/simple.png +SIMPLE_TRANSPORT_INACTIVE_IMAGE = images/simple-gray.png +QQ_TRANSPORT_ACTIVE_IMAGE = images/qq.gif +QQ_TRANSPORT_INACTIVE_IMAGE = images/qq-gray.gif +FACEBOOK_TRANSPORT_ACTIVE_IMAGE= images/facebook.gif +FACEBOOK_TRANSPORT_INACTIVE_IMAGE= images/facebook-gray.gif +MYSPACE_TRANSPORT_ACTIVE_IMAGE= images/myspaceim.gif +MYSPACE_TRANSPORT_INACTIVE_IMAGE= images/myspaceim-gray.gif +SAMETIME_TRANSPORT_ACTIVE_IMAGE= images/sametime.gif +SAMETIME_TRANSPORT_INACTIVE_IMAGE= images/sametime-gray.gif +TRANSPORT_ICON = images/transport.png +SMALL_STOP = images/smallStop.png + +#Stale Images +IM_AVAILABLE_STALE_IMAGE = images/icons/im_available_stale.png +IM_AWAY_STALE_IMAGE = images/icons/im_away_stale.png +IM_XA_STALE_IMAGE = images/icons/im_xa_stale.png +IM_DND_STALE_IMAGE = images/icons/im_dnd_stale.png +IM_FREE_CHAT_STALE_IMAGE = images/icons/im_free_chat_stale.png +IM_UNAVAILABLE_STALE_IMAGE = images/icons/im_unavailable_stale.png + +#Misc +DIVIDER_IMAGE = images/divider.png +LIGHTING_BOLT_IMAGE = images/icons/lightning.png +HEADSET_IMAGE = images/icons/headset.png +BUZZ_IMAGE = images/icons/buzz.png +SETTINGS_IMAGE_16x16 = images/icons/settings.png +SETTINGS_IMAGE_24x24 = images/icons/settings.png + +#Phone +DIAL_PHONE_IMAGE_24x24 = images/phone_call.png +DIAL_PHONE_IMAGE_16x16 = images/icon_phone-call_16x16.png +COMPUTER_IMAGE_16x16 = images/icon_computer_16x16.png + +# Conferences +CONFERENCE_IMAGE_48x48 = images/icons/conference_48x48.png +ACCEPT_INVITE_IMAGE = images/icons/accept.png +REJECT_INVITE_IMAGE = images/icons/reject.png +INVITE_MORE_IMAGE = images/icons/invitemore.png +FILTER_LABEL = Search + +# Language +LANGUAGE_ICON = images/icons/language.png +EXECUTABLE_NAME = Spark.exe + + +#new icons +UPLOAD_ICON = images/icons/upload.png +PADE_ICON = images/icons/pade.png +NEW_MESSAGE = images/icons/incoming_message.png diff --git a/core/src/test/java/org/jivesoftware/XmppProvidersTest.java b/core/src/test/java/org/jivesoftware/XmppProvidersTest.java new file mode 100644 index 000000000..abcb867e0 --- /dev/null +++ b/core/src/test/java/org/jivesoftware/XmppProvidersTest.java @@ -0,0 +1,22 @@ +package org.jivesoftware; + +import org.junit.Test; + +import java.util.List; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; + +public class XmppProvidersTest { + + @Test + public void testParseProvidersJson() { + List providers = XmppProviders.parseProvidersJson("[\n" + + " \"07f.de\",\n" + + " \"404.city\",\n" + + " \"5222.de\"" + + "]"); + assertEquals(asList("07f.de", "404.city", "5222.de"), providers); + } + +} diff --git a/src/test/org/jivesoftware/spark/plugin/PluginDependencyTest.java b/core/src/test/java/org/jivesoftware/spark/plugin/PluginDependencyTest.java similarity index 96% rename from src/test/org/jivesoftware/spark/plugin/PluginDependencyTest.java rename to core/src/test/java/org/jivesoftware/spark/plugin/PluginDependencyTest.java index 2bf61fd76..ff4cfe007 100644 --- a/src/test/org/jivesoftware/spark/plugin/PluginDependencyTest.java +++ b/core/src/test/java/org/jivesoftware/spark/plugin/PluginDependencyTest.java @@ -1,6 +1,5 @@ package org.jivesoftware.spark.plugin; -import org.jivesoftware.spark.plugin.PluginDependency; import org.junit.Test; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertFalse; diff --git a/core/src/test/java/org/jivesoftware/spark/ui/ContactItemTest.java b/core/src/test/java/org/jivesoftware/spark/ui/ContactItemTest.java new file mode 100644 index 000000000..f86f42ba1 --- /dev/null +++ b/core/src/test/java/org/jivesoftware/spark/ui/ContactItemTest.java @@ -0,0 +1,48 @@ +package org.jivesoftware.spark.ui; + +import org.junit.Ignore; +import org.junit.Test; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; + +import static org.junit.Assert.*; + +@Ignore +public class ContactItemTest { + + @Test + public void getDisplayName() throws XmppStringprepException { + ContactItem o1; + ContactItem o2; + int comp; + o1 = new ContactItem(null, null, null); + o2 = new ContactItem(null, null, null); + assertEquals("", o1.getDisplayName()); + assertEquals("", o2.toString()); + assertEquals("", o2.getAlias()); + assertEquals("", o2.getNickname()); + comp = ContactItem.CONTACT_ITEM_COMPARATOR.compare(o1, o2); + assertEquals(0, comp); + + o1 = new ContactItem(null, null, JidCreate.from("juliet@capulet.lit").asBareJid()); + o2 = new ContactItem(null, null, JidCreate.from("romeo@montague.lit").asBareJid()); + assertEquals("juliet@capulet.lit", o1.getDisplayName()); + assertEquals("romeo@montague.lit", o2.toString()); + comp = ContactItem.CONTACT_ITEM_COMPARATOR.compare(o1, o2); + assertTrue(comp < 0); + + o1 = new ContactItem(null, "a", JidCreate.from("juliet@capulet.lit").asBareJid()); + o2 = new ContactItem(null, "b", JidCreate.from("romeo@montague.lit").asBareJid()); + assertEquals("a", o1.getDisplayName()); + assertEquals("b", o2.toString()); + comp = ContactItem.CONTACT_ITEM_COMPARATOR.compare(o1, o2); + assertTrue(comp < 0); + + o1 = new ContactItem("Ã", "a", JidCreate.from("juliet@capulet.lit").asBareJid()); + o2 = new ContactItem("A", "b", JidCreate.from("romeo@montague.lit").asBareJid()); + assertEquals("Ã", o1.getDisplayName()); + assertEquals("A", o2.toString()); + comp = ContactItem.CONTACT_ITEM_COMPARATOR.compare(o1, o2); + assertTrue(comp > 0); + } +} diff --git a/core/src/test/java/org/jivesoftware/spark/uri/UriManagerTest.java b/core/src/test/java/org/jivesoftware/spark/uri/UriManagerTest.java new file mode 100644 index 000000000..7b59811ff --- /dev/null +++ b/core/src/test/java/org/jivesoftware/spark/uri/UriManagerTest.java @@ -0,0 +1,70 @@ +package org.jivesoftware.spark.uri; + +import org.junit.Test; + +import java.net.URI; +import java.net.URISyntaxException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Unit test for the retrievePassword method of UriManager. + * This method extracts the password from a given URI if present. + * xmpp:open_chat@conference.igniterealtime.org?join;password=somesecret + */ +public class UriManagerTest { + + @Test + public void testRetrieveParam() throws URISyntaxException { + UriManager uriManager = new UriManager(); + // URI with a password present as a semicolon-delimited param + URI testUri = uriManager.parseXmppUri("xmpp:conference@example.com?join;password=secret123%20%40%23%24%25%5E%26"); + String password = uriManager.retrieveParam(testUri, "password"); + assertEquals("secret123 @#$%^&", password); + + // URI with a password and additional parameters + testUri = uriManager.parseXmppUri("xmpp:conference@example.com?join;password=secret123&name=john"); + password = uriManager.retrieveParam(testUri, "password"); + assertEquals("secret123", password); + + // URI with an empty password parameter + testUri = uriManager.parseXmppUri("xmpp:conference@example.com?join;password="); + password = uriManager.retrieveParam(testUri, "password"); + assertNull(password); + + // URI without a password parameter + testUri = uriManager.parseXmppUri("xmpp:conference@example.com?join;"); + password = uriManager.retrieveParam(testUri, "password"); + assertNull(password); + + // URI with no query string + testUri = uriManager.parseXmppUri("xmpp:conference@example.com"); + password = uriManager.retrieveParam(testUri, "password"); + assertNull(password); + } + + @Test + public void testRetrieveJID() throws URISyntaxException { + UriManager uriManager = new UriManager(); + // Case with a user and host + URI testUri = uriManager.parseXmppUri("xmpp:user@domain.com"); + assertEquals("user@domain.com", uriManager.retrieveJID(testUri).toString()); + + // Case with a user, host, and a resource + testUri = uriManager.parseXmppUri("xmpp:user@domain.com/resource"); + assertEquals("user@domain.com/resource", uriManager.retrieveJID(testUri).toString()); + + // Case with only a host + testUri = uriManager.parseXmppUri("xmpp:domain.com"); + assertNull(uriManager.retrieveJID(testUri)); + + // Case with a host and a resource + testUri = uriManager.parseXmppUri("xmpp:domain.com/resource"); + assertNull(uriManager.retrieveJID(testUri)); + + // Case with a malformed URI + testUri = uriManager.parseXmppUri("xmpp://@"); + assertNull(uriManager.retrieveJID(testUri)); + } +} diff --git a/core/src/test/java/org/jivesoftware/spark/util/EncryptorTest.java b/core/src/test/java/org/jivesoftware/spark/util/EncryptorTest.java new file mode 100644 index 000000000..73f1c461e --- /dev/null +++ b/core/src/test/java/org/jivesoftware/spark/util/EncryptorTest.java @@ -0,0 +1,46 @@ +package org.jivesoftware.spark.util; + +import org.jasypt.properties.EncryptableProperties; +import org.jasypt.properties.PropertyValueEncryptionUtils; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class EncryptorTest { + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(new File("target")); + + + @Test + public void encryptAndDecryptProperties() throws IOException + { + final String testString = "How are you today? This is test string!"; + final String masterPasswd = "MyEncryptionPasswordForTestOnly"; + Encryptor.setMasterPassword(masterPasswd); + final String encryptedMessage = PropertyValueEncryptionUtils.encrypt(testString, Encryptor.AES256_INSTANCE); + // System.out.println("Encrypted: " + encryptedMessage); + final EncryptableProperties encProps = new EncryptableProperties(Encryptor.AES256_INSTANCE); + encProps.setProperty("encrypted_property1", encryptedMessage); + encProps.setProperty("unencrypted_property2", testString); + // Save the properties to file + final Path propertiesFilePath = tempFolder.newFile("spark.properties").toPath(); + encProps.store(Files.newOutputStream(propertiesFilePath), "Spark Settings (test)"); + // System.out.println("Properties saved: "); + // System.out.println(Files.readString(propertiesFilePath.toAbsolutePath())); + + // Try to reload properties and decrypt + final EncryptableProperties encPropsAfterReload = new EncryptableProperties(Encryptor.AES256_INSTANCE); + encPropsAfterReload.load(Files.newInputStream(propertiesFilePath)); + + Assert.assertEquals(testString, encPropsAfterReload.getProperty("encrypted_property1")); + Assert.assertEquals(testString, encPropsAfterReload.getProperty("unencrypted_property2")); + } + +} diff --git a/core/src/test/java/org/jivesoftware/spark/util/JavaVersionTest.java b/core/src/test/java/org/jivesoftware/spark/util/JavaVersionTest.java new file mode 100644 index 000000000..5bf41672c --- /dev/null +++ b/core/src/test/java/org/jivesoftware/spark/util/JavaVersionTest.java @@ -0,0 +1,57 @@ +package org.jivesoftware.spark.util; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class JavaVersionTest +{ + @Test + public void testJava7() { + // Setup fixture. + final String value = "1.7.0"; + + // Execute system under test. + final int result = StringUtils.getJavaMajorVersion( value ); + + // Verify results. + assertEquals( 7, result ); + } + + + @Test + public void testJava9() { + // Setup fixture. + final String value = "9.0.0.15"; + + // Execute system under test. + final int result = StringUtils.getJavaMajorVersion( value ); + + // Verify results. + assertEquals( 9, result ); + } + + @Test + public void testJava11() { + // Setup fixture. + final String value = "11.0.1"; + + // Execute system under test. + final int result = StringUtils.getJavaMajorVersion( value ); + + // Verify results. + assertEquals( 11, result ); + } + + @Test + public void testJava26ea() { + // Setup fixture. + final String value = "26-ea"; + + // Execute system under test. + final int result = StringUtils.getJavaMajorVersion( value ); + + // Verify results. + assertEquals( 26, result ); + } +} diff --git a/distribution/pom.xml b/distribution/pom.xml new file mode 100644 index 000000000..2ec9b96ff --- /dev/null +++ b/distribution/pom.xml @@ -0,0 +1,72 @@ + + 4.0.0 + + + org.igniterealtime.spark + parent + 3.1.0-SNAPSHOT + + + distribution + + Spark Distribution + + + distribution + + + org.apache.maven.plugins + maven-assembly-plugin + 3.0.0 + + + src/assembly/basic-distribution.xml + + + + + make-assembly + package + + single + + + + + + + + + + install4j + + + + org.sonatype.install4j + install4j-maven-plugin + 1.1.1 + + + + compile-installers + package + + compile + + + ${project.basedir}/src/installer/spark.install4j + + ${project.version} + ${project.build.directory} + + + + + + + + + + + diff --git a/distribution/src/assembly/basic-distribution.xml b/distribution/src/assembly/basic-distribution.xml new file mode 100644 index 000000000..2c84a7dce --- /dev/null +++ b/distribution/src/assembly/basic-distribution.xml @@ -0,0 +1,51 @@ + + base + + dir + + false + + + + + true + + org.igniterealtime.spark:spark-core + + + false + installation-directory + true + + + + + + true + + + org.igniterealtime.spark.plugins:* + + + + org.igniterealtime.spark.plugins:assembly-descriptor + + + false + spark-plugin + plugins + false + ${artifact.artifactId}.${artifact.extension} + + + + + \ No newline at end of file diff --git a/distribution/src/installer/images/message.icns b/distribution/src/installer/images/message.icns new file mode 100644 index 000000000..bd8ed16c0 Binary files /dev/null and b/distribution/src/installer/images/message.icns differ diff --git a/distribution/src/installer/images/spark-16x16.png b/distribution/src/installer/images/spark-16x16.png new file mode 100644 index 000000000..3d9315ad2 Binary files /dev/null and b/distribution/src/installer/images/spark-16x16.png differ diff --git a/src/resources/images/spark-24x24.png b/distribution/src/installer/images/spark-24x24.png similarity index 100% rename from src/resources/images/spark-24x24.png rename to distribution/src/installer/images/spark-24x24.png diff --git a/src/resources/images/spark-32x32.png b/distribution/src/installer/images/spark-32x32.png similarity index 100% rename from src/resources/images/spark-32x32.png rename to distribution/src/installer/images/spark-32x32.png diff --git a/src/resources/images/spark-60x60.png b/distribution/src/installer/images/spark-60x60.png similarity index 100% rename from src/resources/images/spark-60x60.png rename to distribution/src/installer/images/spark-60x60.png diff --git a/src/resources/images/spark-64x64.png b/distribution/src/installer/images/spark-64x64.png similarity index 100% rename from src/resources/images/spark-64x64.png rename to distribution/src/installer/images/spark-64x64.png diff --git a/distribution/src/installer/images/spark.ico b/distribution/src/installer/images/spark.ico new file mode 100644 index 000000000..4db933c88 Binary files /dev/null and b/distribution/src/installer/images/spark.ico differ diff --git a/distribution/src/installer/spark.install4j b/distribution/src/installer/spark.install4j new file mode 100644 index 000000000..a12f2565a --- /dev/null +++ b/distribution/src/installer/spark.install4j @@ -0,0 +1,954 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [Desktop Entry] +MimeType=x-scheme-handler/xmpp +X-MessagingMenu-UsesChatSection=true +GenericName=XMPP Messenger +GenericName[af]=XMPP boodskapper +GenericName[ar]=مرسال إنترنت +GenericName[as]=ইনà§à¦Ÿà¦¾à§°à¦¨à§‡à¦Ÿ মেসেঞà§à¦œà¦¾à§° +GenericName[ast]=Mensaxeru d'XMPP +GenericName[be]=XMPP беÑедник +GenericName[bg]=XMPP бързи ÑÑŠÐ¾Ð±Ñ‰ÐµÐ½Ð¸Ñ +GenericName[bn]=ইনà§à¦Ÿà¦¾à¦°à¦¨à§‡à¦Ÿ বারà§à¦¤à¦¾à¦¬à¦¾à¦¹à¦• +GenericName[bn_IN]=ইনà§à¦Ÿà¦¾à¦°à¦¨à§‡à¦Ÿ মেসেঞà§à¦œà¦¾à¦° +GenericName[br]=Postelerezh Kenrouedad +GenericName[brx]=इनà¥à¤Ÿà¤¾à¤°à¤¨à¥‡à¤Ÿ मेसेनजार +GenericName[ca]=Missatger d'XMPP +GenericName[ca@valencia]=Missatger d'XMPP +GenericName[cs]=XMPP Messenger +GenericName[da]=XMPP Beskeder +GenericName[de]=Sofortnachrichtendienst +GenericName[dz]=ཨིན་ཊར་ནེཊི་འཕྲིན་སà¾à¾±à½ºà½£à¼‹à½”༠+GenericName[el]=Αποστολέας μηνυμάτων διαδικτÏου +GenericName[eo]=XMPP MesaÄilo +GenericName[es]=Cliente de mensajería de XMPP +GenericName[es_AR]=Mensajero de XMPP +GenericName[et]=XMPP sõnumivahetus +GenericName[eu]=XMPP-Mezularia +GenericName[fa]=پیغام‌رسان اینترنتی +GenericName[fi]=Pikaviestin +GenericName[fr]=Messagerie XMPP +GenericName[ga]=Teachtaire Idirlín +GenericName[gl]=Mensaxería na XMPP +GenericName[gu]=XMPP Messenger +GenericName[he]=×œ×ž×¡×¨×™× ×‘×ינטרנט +GenericName[hi]=इंटरनेट मेसेंजर +GenericName[hr]=XMPP pismonoÅ¡a +GenericName[hu]=Azonnali üzenetküldés +GenericName[id]=Pengirim Pesan XMPP +GenericName[it]=XMPP Messenger +GenericName[ja]=インターãƒãƒƒãƒˆãƒ»ãƒ¡ãƒƒã‚»ãƒ³ã‚¸ãƒ£ãƒ¼ +GenericName[km]=កម្មវិធី​ផ្ញើសារ​អ៊ីនធឺណិហ+GenericName[kn]=ಇಂಟರà³à²¨à³†à²Ÿà³ ಮೆಸà³à²¸à³†à²‚ಜರೠ+GenericName[ko]=ì¸í„°ë„· 메신저 +GenericName[ku]=Peyamnêra XMPP +GenericName[lt]=Pokalbiai XMPP +GenericName[lv]=XMPP ziņnesis +GenericName[mai]=इंटरनेट मेसेंजर +GenericName[mhr]=XMPP ПиÑе калаÑымаш алмаш +GenericName[mk]=XMPP пораки +GenericName[ml]=ഇനàµà´±à´°àµâ€à´¨àµ†à´±àµà´±àµ മെസഞàµà´šà´°àµâ€ +GenericName[mn]=XMPP МеÑÑенжер +GenericName[mr]=इंटरनेट मेसेंजर +GenericName[ms_MY]=Pemesej XMPP +GenericName[my_MM]=အင်á€á€¬á€”က် မစ်ဆင်းဂျာ - +GenericName[nb]=Lynmeldingsklient +GenericName[nl]=XMPP Messenger +GenericName[nn]=XMPP Lynmeldingsklient +GenericName[oc]=XMPP Messatjariá +GenericName[or]=ଇଣà­à¬Ÿà¬°à¬¨à­‡à¬Ÿ ସଂଦେଶବାହାକ +GenericName[pa]=ਇੰਟਰਨੈਟ ਮੈਸੰਜ਼ਰ +GenericName[pl]=XMPP Komunikator +GenericName[ps]=د انترنت زری +GenericName[pt]=XMPP Mensageiro +GenericName[pt_BR]=XMPP Mensageiro +GenericName[ro]=XMPP Mesagerie +GenericName[ru]=XMPP беÑедник +GenericName[si]=අන්තර්ජà·à¶½ පණිවිඩකරු +GenericName[sk]=XMPP komunikátor +GenericName[sl]=Spletni sel +GenericName[sq]=Lajmsjellës +GenericName[sr]=XMPP пиÑмоноша +GenericName[sr@latin]=XMPP pismonoÅ¡a +GenericName[sv]=XMPP Meddelandeklient +GenericName[ta]=இணையதள தூதà¯à®µà®°à¯ +GenericName[te]=ఇంటరà±à°¨à±†à°Ÿà± మెసెంజరౠ+GenericName[th]=โปรà¹à¸à¸£à¸¡à¸‚้อความด่วน +GenericName[tr]=XMPP MesajlaÅŸma Aracı +GenericName[uk]=XMPP беÑєдник +GenericName[ur]=ا نٹرنیٹ میسینجر +GenericName[vi]=Tin Nhắn +GenericName[zh_CN]=XMPP èŠå¤©å®¢æˆ·ç«¯ +GenericName[zh_TW]=ç¶²è·¯å³æ™‚通 +Comment=A fully-featured XMPP chat client +Comment[ar]=عميل Ù…ÙŠÙØ§Ù‚ الحضور والمراسلة القابل للتوسعة (XMPP) متكامل المزايا +Comment[cs]=PlnÄ› funkÄní XMPP chat client +Comment[de]=Ein vollwertiger XMPP-Chatclient +Comment[es]=Un cliente de chat XMPP con todas las características +Comment[fr]=Un client de chat XMPP complet +Comment[hu]=Egy funkciógazdag XMPP üzenetküldÅ‘ +Comment[it]=Un client di messaggistica XMPP completo +Comment[ja]=機能満載㮠XMPP ãƒãƒ£ãƒƒãƒˆã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ +Comment[kk]=Толық мүмкіндіктері бар XMPP чат клиенті +Comment[nl]=Een volledig uitgeruste XMPP-chatclient +Comment[pl]=WpeÅ‚ni funkcjonalny klient rozmów XMPP +Comment[pt]=Um cliente de bate-papo XMPP com uma gama completa de recursos +Comment[pt_BR]=Um cliente de bate-papo XMPP completo +Comment[ro]=Un client de chat XMPP cu funcÈ›ionalități complete +Comment[ru]=Полноценный клиент XMPP-чата +Comment[sv]=En fullfjädrad XMPP-chattklient +Comment[uk]=Повноцінний клієнт XMPP-чату +Comment[zh_CN]=功能é½å…¨çš„ XMPP èŠå¤©å®¢æˆ·ç«¯ +Comment[zh_TW]=功能齊全的 XMPP èŠå¤©å®¢æˆ¶ç«¯ +Keywords=chat;messaging;im;xmpp;voip; +Keywords[ar]=دردشة;مراسلة;رسائل;إكس إم بي بي;اكس ام بي بي;إكس ام بي بي;إكس ام بي بي;Ù…ÙŠÙØ§Ù‚ الحضور والمراسلة القابل للتوسعة;بروتوكول الحضور والمراسلة القابل للتوسعة;جابر; +Keywords[cs]=konverzace;zprávy;besednik; +Keywords[hu]=csevegés;üzenetküldés;azonnali üzenetküldÅ‘; +Keywords[kk]=чат;хабарлаÑу;лезде хабарламалар; +Keywords[pl]=czat;rozmowy;wiadomoÅ›ci;besednik;komunikator; +Keywords[pt]=bate-papo;mensagens;mensageiro-instantâneo; +Keywords[pt_BR]=conversa;mensagens; +Keywords[ro]=mesagerie; +Keywords[ru]=чат;общение;разговоры;беÑедник;меÑенджер;звонки;звонилка;коммуникатор; +Keywords[zh_CN]=èŠå¤©;消æ¯;峿—¶é€šè®¯;通è¯; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + images/spark-16x16.png + + + + + images/spark-32x32.png + + + + + + + + + + + + + + 255 + 255 + 255 + 255 + + + 49 + 52 + 53 + 255 + + + + + + + images/spark-60x60.png + + + + + + + + + + + + + + + + + + + if (!context.isUpdateInstallation()) { + ApplicationRegistry.ApplicationInfo[] infos = + ApplicationRegistry.getApplicationInfoById(context.getApplicationId()); + if (infos.length > 0) { + return infos[0].getInstallationDirectory().getPath(); + } +} +return null; + + + previousDir + + + + + + + + + + context.getBooleanVariable("sys.streamlinedInstallation") + + + + + + ${form:welcomeMessage} + + !context.isConsole() + + + + + + String message = context.getMessage("ConsoleWelcomeLabel", context.getApplicationName()); +return console.askOkCancel(message, true); + + + + + + + + + + + streamlinedInstallationStrategy + + + + + ${i18n:ClickNext} + + + + + + !context.getBooleanVariable("sys.streamlinedInstallation") + + + + ${i18n:SelectDirLabel(${compiler:sys.fullName})} + + + + + + + + suggestAppDir + validateApplicationId + existingDirWarning + checkWritable + manualEntryAllowed + checkFreeSpace + showRequiredDiskSpace + showFreeDiskSpace + allowSpacesOnUnix + validationScript + standardValidation + + + + + + + + + ${i18n:SelectComponentsLabel2} + + !context.isConsole() + + + + + + + selectionChangedScript + + + + + + + ${compiler:sys.fullName} + + !context.getBooleanVariable("sys.streamlinedInstallation") + + + + + + ${i18n:SelectAssociationsLabel} + + + + + + + + showSelectionButtons + selectionButtonPosition + + + + + + + + + ${form:confirmationMessage} + + !context.isConsole() + + + + ${i18n:CreateDesktopIcon} + + createDesktopLinkAction + + + + + ${i18n:CreateQuickLaunchIcon} + + createQuicklaunchIconAction + + component.setVisible(Util.isWindows()); + + + + + + + + + + + ${installer:previousDir} + + + + context.getVariable("previousDir") != null + + + + + ${compiler:sys.fullName} ${compiler:sys.version} + + + + + + + Spark + + + ${compiler:sys.fullName} + + context.getBooleanVariable("createDesktopLinkAction") + + + + Network;InstantMessaging;Chat; + ${installer:sys.programGroupName} + ${installer:sys.symlinkDir} + + !context.getBooleanVariable("sys.programGroupDisabled") + + + + 4 + xmpp + + + + + + + ${i18n:WizardPreparing} + + + + + + + + + 4 + + context.getBooleanVariable("executeLauncherAction") && (!context.isUnattended()) + + + + + + + ${form:finishedMessage} + + + + + ${i18n:RunEntryExec("${compiler:sys.fullName}")} + + executeLauncherAction + + + + + + + + + + + + images/spark-16x16.png + + + + + images/spark-32x32.png + + + + ${i18n:UninstallerMenuEntry(${compiler:sys.fullName})} + + + + + + + + + + + + 255 + 255 + 255 + 255 + + + 49 + 52 + 53 + 255 + + + + + + + images/spark-60x60.png + + + + + + + + + + + + + + + + + + + + + + + ${form:welcomeMessage} + + !context.isConsole() + + + + + + String message = context.getMessage("ConfirmUninstall", context.getApplicationName()); +return console.askYesNo(message, true); + + + + + + + + + + + + + + + ${i18n:UninstallerPreparing} + + + + + + + + + + ${form:successMessage} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/documentation/README.html b/documentation/README.html deleted file mode 100644 index 8cfd67e44..000000000 --- a/documentation/README.html +++ /dev/null @@ -1,229 +0,0 @@ - - - - -Spark Changelog - - - - -
      - - - - -
      -

      Version 2.6.3
      Released July 1st, 2011

      - -Thank you for choosing Spark!
      -Spark is a full-features instant messaging (IM) and groupchat client that uses the XMPP protocol.
      -Further information can be found on the Spark website.
      - -

      Changelog

      -View the changelog for a list of changes since the last release. - -

      Support

      -Free support is provided by the Spark community in the online forums. - -

      License Agreements

      -The Spark source code is governed by the Apache-License 2, which can be found in the LICENSE.html file in this distribution.
      -Spark also contains Open Source software from third-parties.
      -Licensing terms for those components is specifically noted in the relevant source files.

      - - -Spark contains icons which are free for non-commercial use, -are licensed from INCORS GmbH or owned by Jive Software.
      -All icons and images in Spark owned by INCORS GmbH or Jive Software are provided under the following license agreement:
      - -
        
      -License Agreement
      - 
      -This is a legal agreement between You, the User of the Spark application
      -("The Software"), and Jive Software ("Jive Software"). By downloading the Software,
      -you agree to be bound by the terms of this agreement.
      - 
      -All ownership and copyright of the images and icons included in the Software
      -distribution remain the property of Jive Software and INCORS GmbH. Jive Software
      -grants to you a nonexclusive, non-sublicensable right to use the icons royalty-free
      -as part of Spark.
      - 
      -You may not lease, license or sub-license the icons, or a subset of the icons,
      -or any modified icons to any third party. You may not incorporate them into your
      -own software or design products.
      - 
      -All icon files are provided "As is" without warranties of merchantability and
      -fitness for a particular purpose. You agree to hold Jive Software harmless for
      -any result that may occur during the course of using the licensed icons.
      - 
      -This License Agreement shall be governed and construed in accordance with the
      -laws of Oregon. If any provision of this License Agreement is held to be
      -unenforceable, this License Agreement will remain in effect with the provision
      -omitted.      
      - \ No newline at end of file diff --git a/documentation/builder.jar b/documentation/builder.jar deleted file mode 100644 index 9f293e22d..000000000 Binary files a/documentation/builder.jar and /dev/null differ diff --git a/documentation/changelog.html b/documentation/changelog.html deleted file mode 100644 index 866286952..000000000 --- a/documentation/changelog.html +++ /dev/null @@ -1,3268 +0,0 @@ - - - - -Spark Changelog - - - - -
      - - - - -
      - -

      2.7.7 -- April 24, 2016

      -

      Bug -

      -
        -
      • [SPARK-1597] - UNC links in file://\\\ format should work in the chat window -
      • -
      • [SPARK-1660] - Should not fallback to direct connection when proxy is enabled -
      • -
      • [SPARK-1695] - Windows installer is including linux lib folder -
      • -
      • [SPARK-1717] - Failing dependencies when installing RPM version -
      • -
      • [SPARK-1721] - Fix a typo in Network Address Manager in SIP plugin -
      • -
      • [SPARK-1724] - OTR plugin not working after bouncy castle lib update -
      • -
      • [SPARK-1726] - Spark is setting negative priority when switching to Idle -
      • -
      - -

      New Feature -

      -
        -
      • [SPARK-1720] - Add option to disable Incoming Call notification popup -
      • -
      - -

      Task -

      -
        -
      • [SPARK-1687] - Update bundled JRE with the latest version -
      • -
      - -

      Improvement -

      -
        -
      • [SPARK-1716] - Fix alignment of fields on Business card in Profile -
      • -
      • [SPARK-1718] - Remove old java from RPM installation -
      • -
      • [SPARK-1723] - Update of German translation -
      • -
      • [SPARK-1727] - Fix and update Lithuanian translation -
      • -
      - - -

      2.7.6 -- March 15, 2016

      -

      Bug -

      -
        -
      • [SPARK-1192] - Preferences window doesn't open on Mac OS X -
      • -
      • [SPARK-1197] - File transfers don't work on Mac OS X -
      • -
      • [SPARK-1455] - Spark is getting stuck with "On Phone" status after unlocking Windows -
      • -
      • [SPARK-1530] - Broadcast message is not shown with bolded red font in the tab -
      • -
      • [SPARK-1620] - Sound files are not copied into user's profile on Mac OS X -
      • -
      • [SPARK-1667] - Bookmarks menu shows last when using Substance skins -
      • -
      • [SPARK-1671] - Add i18n translation for "(Offline)" prefix before offline message -
      • -
      • [SPARK-1674] - Add Mac OS X installer with bundled JRE -
      • -
      • [SPARK-1677] - Shows app name as Startup instead of Spark on Mac OS X -
      • -
      • [SPARK-1689] - RPM build fails after Libjitsi update -
      • -
      • [SPARK-1692] - Native Jitsi libraries not loading on Mac OSX -
      • -
      • [SPARK-1696] - Fastpath not working on Mac OS X -
      • -
      • [SPARK-1697] - Roar plugins doesn't work on Mac OS X -
      • -
      • [SPARK-1701] - Plugins are not being copied to user's home folder on Mac OS X -
      • -
      • [SPARK-1703] - Spark is constantly trying to access e4j_pxxxx.tmp file -
      • -
      • [SPARK-1704] - Emoticons not loading on mac osx -
      • -
      • [SPARK-1714] - Disconnecting when saving or retrieving Notes -
      • -
      - -

      New Feature -

      -
        -
      • [SPARK-1675] - Add Lithuanian translation for Fastpath plugin -
      • -
      - -

      Task -

      -
        -
      • [SPARK-1643] - Update bundled JRE with the latest version -
      • -
      • [SPARK-1679] - Fix the wrong year on the About window on Mac OS X -
      • -
      • [SPARK-1693] - Increase checkstyle's maxerror value -
      • -
      • [SPARK-1712] - Change JDK to 1.8 in Bamboo build plans (Ant) -
      • -
      - -

      Improvement -

      -
        -
      • [SPARK-1680] - Update top menu item name "Spark" to more commonly used name "File" -
      • -
      • [SPARK-1681] - Update Spark's User Guide -
      • -
      • [SPARK-1684] - Toaster Pop up for Incoming Call is too short. -
      • -
      • [SPARK-1685] - Idle state shouldn't override custom status message -
      • -
      • [SPARK-1691] - Change JNA to version to 3.4.2 -
      • -
      - - -

      2.7.5 -- January 14, 2016

      -

      Bug -

      -
        -
      • [SPARK-1664] - RPM build fails after Smack library update -
      • -
      • [SPARK-1669] - Fix Lithuanian translation of Tic Tac Toe game -
      • -
      • [SPARK-1672] - Spark is not showing "(Offline)" prefix for offline messages on Openfire 4.0.0 -
      • -
      • [SPARK-1673] - Only first offline message is shown -
      • -
      - -

      Improvement -

      -
        -
      • [SPARK-1091] - Create an installer for Mac OS X -
      • -
      • [SPARK-1661] - Change "on phone" to "on the phone" -
      • -
      • [SPARK-1663] - Update jarbundler and ant build file -
      • -
      • [SPARK-1666] - Update Simplified Chinese translation -
      • -
      - -

      New Feature -

      -
        -
      • [SPARK-1668] - Lithuanian translation for the Battleships game -
      • -
      - -

      2.7.4 -- December 18, 2015

      -

      Bug -

      -
        -
      • [SPARK-847] - "Contact List font size" not applied to Offline users group -
      • -
      • [SPARK-1066] - Proxy is not working -
      • -
      • [SPARK-1576] - Spark is not showing room participants when presence icons should be showing -
      • -
      • [SPARK-1592] - Should not show 'Send a file' menu when file transfer is disabled -
      • -
      • [SPARK-1645] - Notifications settings disappear when updates are disabled via default.properties -
      • -
      • [SPARK-1648] - Toast popups are not shown for group chat messages -
      • -
      • [SPARK-1650] - A 'default' directory should not be required when selecting files to transfer -
      • -
      • [SPARK-1658] - NullPointerExceptions when joining an anonymous MUC -
      • -
      - -

      Improvement -

      -
        -
      • [SPARK-1651] - Add i18n translation for Transfer Guard plugin's name in the Preferences -
      • -
      • [SPARK-1652] - Add scrollbar in Emoticon picker -
      • -
      • [SPARK-1655] - Updated Russian translation -
      • -
      • [SPARK-1656] - Update Chinese (Traditional) translation -
      • -
      • [SPARK-1659] - Another Russian translation update -
      • -
      - -

      New Feature -

      -
        -
      • [SPARK-1644] - Add an option to hide auto login checkbox along with the save password box -
      • -
      • [SPARK-1653] - Add Chinese (Traditional) translation for Transfer Guard plugin -
      • -
      - -

      2.7.3 -- October 23, 2015

      -

      Bug -

      -
        -
      • [SPARK-1144] - Ant buildscript should not check for explicit Ant version numbers -
      • -
      • [SPARK-1329] - Various confirmation dialogs should use i18n strings for Yes, No and Cancel buttons -
      • -
      • [SPARK-1631] - Messages are not shown as sent or received when no history is shown -
      • -
      • [SPARK-1634] - Fix Class not found exception in LaF -
      • -
      - -

      Improvement -

      -
        -
      • [SPARK-985] - Online/Offline toast popups improvement -
      • -
      • [SPARK-1472] - Add "Avatar:" to translation file -
      • -
      • [SPARK-1473] - Alert notification popup should show the sender's name -
      • -
      • [SPARK-1517] - Append contact name on every line of conversation history -
      • -
      • [SPARK-1571] - Add phone number to vCard popup -
      • -
      • [SPARK-1627] - Change default reconnection option to Display in contact group -
      • -
      • [SPARK-1633] - Add support for IzPack 5 in the build process -
      • -
      • [SPARK-1641] - Fixed typos in the group chat dialogs -
      • -
      • [SPARK-1642] - Update the Bring window to front code -
      • -
      - -

      New Feature -

      -
        -
      • [SPARK-1436] - Add option to disable chat history via default.properties -
      • -
      • [SPARK-1638] - Add option to hide chat history settings via default.properties -
      • -
      • [SPARK-1640] - Add option to hide save password checkboxes -
      • -
      - -

      Task -

      -
        -
      • [SPARK-1626] - Update bundled JRE with the latest version -
      • -
      - -

      2.7.2 -- August 31, 2015

      -

      Bug -

      -
        -
      • [SPARK-1458] - Spark prepends the default status text to a custom one -
      • -
      - -

      Improvement -

      -
        -
      • [SPARK-1621] - Add a caption "0 = infinite" to the duration option of Roar popups -
      • -
      - -

      New Feature -

      -
        -
      • [SPARK-1614] - Add an option to show seconds in a message time stamp -
      • -
      • [SPARK-1619] - Add an option to use Spark version as a resource -
      • -
      • [SPARK-1622] - Add options to default.properties to use hostname or version as resource -
      • -
      - -

      Task -

      -
        -
      • [SPARK-1615] - Update bundled JRE with the latest version -
      • -
      - -

      2.7.1 -- June 12th, 2015

      -

      Bug -

      -
        -
      • [SPARK-864] - Printing conversation margin cuts off characters from lines that wrap -
      • -
      • [SPARK-1512] - ***<user> is online at message does not always show in chat room -
      • -
      • [SPARK-1513] - After receiving XML data as a message Spark stops displaying history -
      • -
      • [SPARK-1604] - Buzz and stale settings overlap in the Preferences window -
      • -
      - -

      Improvement -

      -
        -
      • [SPARK-1588] - Update French translation -
      • -
      • [SPARK-1607] - Show JID as contact name if instead an empty string would have been shown -
      • -
      • [SPARK-1609] - Default resource should be "Spark" without a version number -
      • -
      • [SPARK-1611] - Update Lithuanian translation -
      • -
      • [SPARK-1617] - Fix loading of Spellchecker's IgnoreUppercase setting -
      • -
      - -

      New Feature -

      -
        -
      • [SPARK-979] - Add an option to disable graying out and italic for idle contacts -
      • -
      • [SPARK-1503] - Option to use hostname as a resource -
      • -
      - -

      Task -

      -
        -
      • [SPARK-1584] - Update bundled JRE with the latest version -
      • -
      - -

      2.7.0 -- April 24th, 2015

      - -

      Sub-task -

      -
        -
      • [SPARK-802] - After a Reconnection error it does not attempt anymore -
      • -
      • [SPARK-1002] - Use some form of "reconnection logic" -
      • -
      • [SPARK-1204] - Counter for online contacts in group sometimes is wrong -
      • -
      • [SPARK-1313] - Enhance ability to overwrite spark properties values through plugin -
      • -
      • [SPARK-1326] - Make tabs position optional: TOP or BOTTOM; make search input appearance optional -
      • -
      • [SPARK-1465] - Checkboxes appear bigger then normal since the jtattoo update -
      • -
      • [SPARK-1478] - Getting vcards from server could freeze Spark at startup -
      • -
      • [SPARK-1482] - Scratchpad plugin could freeze spark at startup -
      • -
      • [SPARK-1483] - Privacy plugin could freeze spark at startup -
      • -
      • [SPARK-1528] - Should show user's Name instead of Username when receiving a broadcast -
      • -
      • [SPARK-1541] - Receiving lots of conference rooms could freeze spark for some time -
      • -
      - -

      Bug -

      -
        -
      • [SPARK-845] - displaying of chat log with "<script" within the message causes trouble -
      • -
      • [SPARK-987] - Spark has the wrong icons -
      • -
      • [SPARK-1042] - Spark looses the content of custom (not shared) group with the shared contacts -
      • -
      • [SPARK-1058] - Spark should let to change the language of GUI to any available -
      • -
      • [SPARK-1074] - Sending part doesnt get a notification about the transfer cancellation -
      • -
      • [SPARK-1097] - Delete the obsolete Available translation string from the i18n file -
      • -
      • [SPARK-1163] - Spark displays wrong error when nickname change is forbidden -
      • -
      • [SPARK-1177] - Memory leak ChatRoom -
      • -
      • [SPARK-1186] - Ctrl + W not working as expected in chat window -
      • -
      • [SPARK-1212] - Shouldn't be able to search for yourself and add yourself to a roster -
      • -
      • [SPARK-1223] - Masterticket: Clean up the error log -
      • -
      • [SPARK-1224] - Masterticket: Rework Reconnection Logic -
      • -
      • [SPARK-1324] - SparkToaster showing avatars in real size -
      • -
      • [SPARK-1355] - No history in Groups chat -
      • -
      • [SPARK-1362] - No confirmation on the sender's part that the file transfer completed -
      • -
      • [SPARK-1382] - File Transfer from WinXP to Win7x64 does not work in nightlies -
      • -
      • [SPARK-1387] - Reversi is not starting -
      • -
      • [SPARK-1397] - Fix the displaying of system tray icons -
      • -
      • [SPARK-1408] - Remove "#" character next to Accounts button on the login screen -
      • -
      • [SPARK-1411] - Sometimes file transfer indication is not updated on the receiving side -
      • -
      • [SPARK-1414] - Chat window is not flashing when receiving new message on Windows 7 64 bit -
      • -
      • [SPARK-1417] - Temporary conference are getting bookmarked -
      • -
      • [SPARK-1419] - Chat room configuration shows wrong roles for which presence is broadcast -
      • -
      • [SPARK-1420] - The messages in the set status message window is not getting deleted -
      • -
      • [SPARK-1421] - Application version and application name are hardcoded -
      • -
      • [SPARK-1422] - persist vcard may throw file not found exception when jid is empty -
      • -
      • [SPARK-1423] - typo error in LayoutSettings.java -
      • -
      • [SPARK-1427] - Default Appearance/Colors cannot be overwritten through plugin;Group-Chat colors are hard-coded -
      • -
      • [SPARK-1431] - Update Smack to the next version. -
      • -
      • [SPARK-1437] - Bug in PrivacyManager that can break smack communication -
      • -
      • [SPARK-1438] - Avatars are not scaled in user login/logout notification dialog -
      • -
      • [SPARK-1439] - Plugins are loaded in random order - plugins with no dependency has to be loaded first -
      • -
      • [SPARK-1440] - Bug in ConferenceUtils.java that can break smack communication -
      • -
      • [SPARK-1441] - ContactItem in shared group - right click popup menu performs copy when move is selected -
      • -
      • [SPARK-1442] - JabberVersion.java uses hardcoded value "Spark IM Client" for version name -
      • -
      • [SPARK-1447] - Chat logs are getting corrupted (after the upgrade to 2.6.3) -
      • -
      • [SPARK-1449] - UNC Path does not link to folder -
      • -
      • [SPARK-1451] - Vcard popup is not always showing up on mouse hover -
      • -
      • [SPARK-1452] - If conferences tab is hidden, then Fastpath tab is hidden also -
      • -
      • [SPARK-1462] - Spark doesn't list rooms when subject has a null value -
      • -
      • [SPARK-1464] - When user accepts group chat invitation, status is always online -
      • -
      • [SPARK-1470] - Typing notification diesn't change its status -
      • -
      • [SPARK-1475] - Connection crashen when sending control characters -
      • -
      • [SPARK-1480] - Reduce VCARD loading of Spark -
      • -
      • [SPARK-1485] - Subscription dialog is hidden when received -
      • -
      • [SPARK-1488] - On unclean disconnect, chat windows, that were already open, cannot be closed -
      • -
      • [SPARK-1490] - Broadcast menu duplicates users in the Online group -
      • -
      • [SPARK-1514] - Ghost icon gets lost when user comes (back) online -
      • -
      • [SPARK-1524] - Spark is not reconnecting automatically after connection loss -
      • -
      • [SPARK-1531] - URL links not working without http:// part -
      • -
      • [SPARK-1534] - Roar should show a popup for broadcast messages and play a sound -
      • -
      • [SPARK-1535] - Custom status message is not set if selected from saved custom statuses -
      • -
      • [SPARK-1546] - Spark visually shows that a message is not sent -
      • -
      • [SPARK-1550] - Integrate next SMACK lib release into Spark (any version post-3.3.0) -
      • -
      • [SPARK-1553] - Privacy feature lookup and invisibility -
      • -
      • [SPARK-1558] - Multiple memory leaks -
      • -
      • [SPARK-1565] - Roar plugin shouldn't show many popups when joining a chat room with old history -
      • -
      - -

      Improvement -

      -
        -
      • [SPARK-33] - Add more content to the About Box -
      • -
      • [SPARK-822] - fix Spark icon -
      • -
      • [SPARK-891] - Typing notifications would be easier to see if also displayed near typing area -
      • -
      • [SPARK-1060] - Spark should remember Preferences window (and others) position on the screen -
      • -
      • [SPARK-1179] - Add time stamps and improve layout of conversation history -
      • -
      • [SPARK-1188] - Emphasize broadcast message in the chat window -
      • -
      • [SPARK-1215] - Log out doesn't log out, it shuts down spark -
      • -
      • [SPARK-1333] - Update Lithuanian translation -
      • -
      • [SPARK-1381] - Group Chat - Actions/Start a conference menu: propose bookmarked room (if any) instead of adhoc (random) room name -
      • -
      • [SPARK-1407] - Fix the direction of 5000 history messages limit and make a GUI option -
      • -
      • [SPARK-1418] - Update simplified Chinese translation -
      • -
      • [SPARK-1429] - Update French translation -
      • -
      • [SPARK-1459] - Update to the latest JTattoo version (Nov 2011) -
      • -
      • [SPARK-1466] - Update the Finnish translation -
      • -
      • [SPARK-1476] - Update the smack to 3.2.2 -
      • -
      • [SPARK-1479] - SettingsManager hadr-codes executable name: Spark.exe -
      • -
      • [SPARK-1487] - Size of chat input field is to small, it dont fit to the rest of the chatwindow -
      • -
      • [SPARK-1491] - Update Polish translation -
      • -
      • [SPARK-1515] - Migrate to latest JTattoo Release -
      • -
      • [SPARK-1526] - Minimized roster window should appear when clicking on a systray icon -
      • -
      • [SPARK-1539] - Update Substance LaF to the latest version -
      • -
      • [SPARK-1540] - Update POPO emoticons set -
      • -
      • [SPARK-1542] - Icon of refresh button in the ConferenceRoomBrowser should change when loading -
      • -
      • [SPARK-1544] - Spark should relog on newly applied LaF -
      • -
      • [SPARK-1545] - Drop Java 5 and 6 support -
      • -
      • [SPARK-1552] - Update Smack to 3.3.1 version -
      • -
      • [SPARK-1566] - Roar popup will change to "broadcast - (sender's name)" when receiving a broadcast message -
      • -
      • [SPARK-1595] - Add an option for Roar popups to stay indefinitely -
      • -
      - -

      New Feature -

      -
        -
      • [SPARK-1105] - Spark should indicate different permissions in MUC with additional icons or colors -
      • -
      • [SPARK-1356] - Limit filetransfer speed -
      • -
      • [SPARK-1378] - Create TicTacToe for Spark -
      • -
      • [SPARK-1405] - Improved last activity recognition -
      • -
      • [SPARK-1435] - Make an option to disable Log out in Spark menu via default.properties -
      • -
      • [SPARK-1486] - For customizing purposes, provide ability to register own error and warning handler in logging mechanism of spark -
      • -
      • [SPARK-1493] - Add translation file for the Transfer Guard plugin -
      • -
      • [SPARK-1521] - Add invisible presence state -
      • -
      • [SPARK-1529] - Display the entire group chat history -
      • -
      - -

      Task -

      -
        -
      • [SPARK-1098] - Investigate two functions in ContactItem.java which can cause issues -
      • -
      • [SPARK-1232] - Release Blocker: Nightly build is not compiling the plugins -
      • -
      • [SPARK-1306] - Attach newest source code, JTattoo Tab Rendering in Spark -
      • -
      • [SPARK-1400] - Update to latest version Exe4J -
      • -
      • [SPARK-1412] - Drop Java 5 support -
      • -
      • [SPARK-1413] - Update build.xml to check for Java 7 -
      • -
      • [SPARK-1416] - Update JRE to 7 version -
      • -
      • [SPARK-1500] - Add Portuguese Brazilian Spelling -
      • -
      • [SPARK-1525] - Update smack -
      • -
      • [SPARK-1538] - Update to latest Trident lib -
      • -
      • [SPARK-1555] - Update build.xml to support Ant 1.9 -
      • -
      • [SPARK-1602] - Update bundled JRE to 1.7.0_76 -
      • -
      - -

      2.6.3 -- July 1st, 2011

      - - -Highlights: -
        -
      • Bug Fixes only
      • -
      - -

      Bug fix

      -
        -
      • [SPARK-615] - Fixed issue with XMPP URI conference chats.
      • -
      • [SPARK-740] - XMPP URI not working in IE
      • -
      • [SPARK-1379] - Support for XEP-0147
      • -
      • [SPARK-1383] - Login screen shows disabled fields.
      • -
      • [SPARK-1392] - Check if Spark is really checking for updates even if that option is turned off
      • -
      • [SPARK-1394] - Search in history is not working
      • -
      • [SPARK-1395] - NPE when exiting a chat window with ESC
      • -
      • [SPARK-1396] - Send Broadcast Window doesn't show when not using JTattoo
      • -
      • [SPARK-1398] - scrollToBottom causes UiThreadingViolationException when using Substance Skins
      • -
      - - -

      2.6.2 Hot Fix -- June 23rd, 2011

      - - -Highlights: -
        -
      • Support XMPP servers without ability to manage privacy lists
      • -
      - -

      Bug fix -

      -
        -
      • [SMACK-338] - IBB filetransfer doesn't work as expected
      • -
      - -

      2.6.1 all resolved issues in Spark and Smack -- June 22nd, 2011

      - -Highlights: -
        -
      • File transfer bug resolved
      • -
      • Standard Mac Look and Feel on that very plattform
      • -
      • OTR (off the record) encryption for chat
      • -
      • I18n updates
      • -
      • New notification mechanism (Roar)
      • -
      • Clean up and enhancements for look and feel
      • -
      - - - -

      Bug fixes (35 bugs + 3 SMACK related) -

      -
        - -
      • [SMACK-338] - IBB filetransfer doesn't work as expected -
      • - -
      • [SMACK-273] - Bug in RoomListenerMultiplexor.java -
      • - -
      • [SMACK-329] - XHTMLText uses improper format for br tag -
      • -
      • [SPARK-791] - Vcard cache not expiring -
      • -
      • [SPARK-1067] - System Look and Feel option should be using system theme highlighting colors -
      • -
      • [SPARK-1080] - IzPack uninstaller doesnt remove Spark entries from Programs and Features list -
      • -
      • [SPARK-1095] - Nested groups are not sorted by name -
      • -
      • [SPARK-1164] - Chat window doesnt scroll to bottom when opened -
      • -
      • [SPARK-1177] - Memory leak ChatRoom -
      • -
      • [SPARK-1198] - Spark has no button for Send Files or Capture in message window on MAC OS X -
      • -
      • [SPARK-1200] - Context menu doesn't show up in chat input area on Windows 7 -
      • -
      • [SPARK-1207] - Linux version of Spark quits when doing logout -
      • -
      • [SPARK-1253] - Transport icons disappear after saving preferences -
      • -
      • [SPARK-1274] - Reverse alphabetical sorting of participants in the group chat -
      • -
      • [SPARK-1275] - contact add loses connection when no username provided -
      • -
      • [SPARK-1280] - Crtl-Backspace doe not work in Chat Windows -
      • -
      • [SPARK-1281] - Spark doesn't goes online after auto away when using Remote Desktop connection -
      • -
      • [SPARK-1283] - File transfer between 2.5.8 and 2.6.0_12222 is broken -
      • -
      • [SPARK-1294] - Spark 2.6 RC2 No Phone Call Button -
      • -
      • [SPARK-1324] - SparkToaster showing avatars in real size -
      • -
      • [SPARK-1325] - Spark File Transfer. Let spark find the right IP -
      • -
      • [SPARK-1331] - Spark->Preferences->Appearance: Null Pointer exception when no emoticon set is available -
      • -
      • [SPARK-1336] - NPE In getContactGroupByJID -
      • -
      • [SPARK-1338] - Spark 12384 is not starting with old profile -
      • -
      • [SPARK-1340] - Spark login profile picker doesn't show profiles with same names but different servers -
      • -
      • [SPARK-1350] - File transfer and windows network path -
      • -
      • [SPARK-1351] - Remove plugins does not remove plugins -
      • -
      • [SPARK-1357] - When in fullscreen mode and switching to smaller screen, spark doesnt rezise to fit smaller screen -
      • -
      • [SPARK-1364] - Investigate the Spark automatic update from the site issue -
      • -
      • [SPARK-1366] - Review padlock icon usage -
      • -
      • [SPARK-1373] - Bring Reversi back, please! -
      • -
      • [SPARK-1375] - Context Menue in roster dows not allow a broadcast to the selected user -
      • -
      • [SPARK-1376] - Fix the "Check for new version" Function -
      • -
      • [SPARK-1383] - Login screen shows disabled fields. -
      • -
      • [SPARK-1385] - Format Bug in Transcript -
      • -
      • [SPARK-1387] - Reversi is not starting -
      • -
      • [SPARK-1388] - Typo in spark i18n - avtivate -
      • -
      • [SPARK-1389] - History is diplayed twice -
      • -
      - -

      New Features, Improvements, Tasks (55 issues) -

      -
        -
      • [SPARK-548] - Add support for animated gifs as avatars -
      • -
      • [SPARK-884] - OTR support for chat -
      • -
      • [SPARK-1277] - Installer should include Java 1.6.0 (build 10) or higher -
      • -
      • [SPARK-1278] - Allow Nimbus Skinning -
      • -
      • [SPARK-1303] - Preferences: Automatically join Groupchat (muc) on invite -
      • -
      • [SPARK-1323] - Allow larger VCard Images -
      • -
      • [SPARK-1342] - MotD opens in Fullscreen since Spark 2.6.0 update -
      • -
      • [SPARK-1344] - Add some more plugins to 2.6.1 -
      • -
      • [SPARK-1345] - Reduce the delivered skins to the usable ones -
      • -
      • [SPARK-1352] - Prevent messages from the server to be stored in Client history -
      • -
      • [SPARK-1354] - Force 32 bit execution on Mac Plattfom -
      • -
      • [SPARK-1359] - Plugin Blacklist -
      • -
      • [SPARK-1367] - Speelchecker default Language -
      • -
      • [SPARK-1369] - When debugger enabled should be able to send raw packets somehow -
      • -
      • [SPARK-1379] - Support for XEP-0147 -
      • - -
      • [SPARK-948] - Bring window to front shouldnt steal focus -
      • -
      • [SPARK-984] - Should be an option to disable username color randomizer in MUC -
      • -
      • [SPARK-1218] - Make Room Configuration dialog translatable -
      • -
      • [SPARK-1220] - Create FlashWindow.dll 64-bit version -
      • -
      • [SPARK-1235] - Add context menu to Ctrl-F, Ctrl-E, Ctrl-T dialogs -
      • -
      • [SPARK-1254] - Select Spellchecker Language in Chatwindow -
      • -
      • [SPARK-1316] - Privacy Plugin needs refactoring -
      • -
      • [SPARK-1332] - Make possible to translate hardcoded strings -
      • -
      • [SPARK-1333] - Update Lithuanian translation -
      • -
      • [SPARK-1334] - Add the login server as STUN server to spark.properties -
      • -
      • [SPARK-1335] - Spark should save received broadcast messages in the chat history -
      • -
      • [SPARK-1341] - Profile picker button should have a button design (with a border) -
      • -
      • [SPARK-1343] - Broadcast window covers whole screen if message is longer than {1*10^x , x?R>5} characters -
      • -
      • [SPARK-1346] - PluginLoader should get a <minJava>1.x.x_xx</minJava> tag -
      • -
      • [SPARK-1347] - apple plugin needs configurable behaviour -
      • -
      • [SPARK-1348] - Make possible to set Join on startup from other interface -
      • -
      • [SPARK-1349] - Option to disable translator plugin -
      • -
      • [SPARK-1361] - If History has more than 5000 Messages it takes forever to load -
      • -
      • [SPARK-1372] - Clicking the [X] in the contact subscription request should be the same as "Decline" -
      • - -
      • [SPARK-1230] - Masterticket: Translations -
      • -
      • [SPARK-1298] - Clean Up Spark UI -
      • -
      • [SPARK-1322] - Rename Debian package -
      • -
      • [SPARK-1360] - Check FMJ lib for revision -
      • -
      • [SPARK-1368] - Check Spark 2.6.1 on W7 without admin rights -
      • -
      • [SPARK-1380] - Exchange of the Spark Spash Screen -
      • -
      • [SPARK-1384] - Change XMPP Ressource String -
      • -
      • [SPARK-1386] - Privacy Plugin shouldn't load if not supported -
      • -
      • [SPARK-1390] - Remove games from the release -
      • - -
      • [SPARK-804] - MSN Offline users in roster -
      • -
      • [SPARK-854] - reconect hangs within "Reconnecting ..." -
      • -
      • [SPARK-1167] - New chat window steals focus when Spark receives new message -
      • -
      • [SPARK-1265] - Fix tabs stacking direction and tabs size with multirow tabbar -
      • -
      • [SPARK-1290] - Redesign "Invisible" Button -
      • -
      • [SPARK-1304] - Allow to hide the conference tab in the Spark screen -
      • -
      • [SPARK-1337] - Create Button to login with other Profiles in LoginDialog -
      • -
      • [SPARK-1353] - JTattoo Render Error -
      • -
      • [SPARK-1358] - Add features to default.properties FILE_TRANSFER_WARNING_SIZE and FILE_TRANSFER_MAXIMUM_SIZE -
      • -
      • [SPARK-1370] - W7 64 Bit: Plugin's are missing -
      • -
      • [SPARK-1371] - Add tooltip to button in chat window -
      • -
      • [SPARK-1374] - Spark freezes on close -
      • - -
      - - - - -

      2.6.0 all resolved issues in Spark and Smack -- May 6th, 2011

      - -Highlights: -
        -
      • Large parts of the code were licenced as Apache 2.0
      • -
      • Commercial packages were removed in favour of open source solutions
      • -
      • Updated Smack library to 3.2
      • -
      • Fixes for roster management and reconnection mechanisms
      • -
      • Reworked look and feel
      • -
      • New skinning library
      • -
      • I18n updates
      • -
      • Clean error log after startup
      • -
      • Support for privacy mode
      • -
      • Spark does not call hard coded fallback servers for STUN services anymore
      • -
      • Major feature updates for conference rooms
      • -
      • More preferences
      • -
      • Ability to set default data in ini files for corporate customizing
      • - - -
      -

      New Features & Improvements (more than 190 issues)

      -
        - - - -
      • [SMACK-137] - File - Transfer Settings
      • - -
      • [SMACK-156] - Add - the ability to register for roster events before logging in
      • - -
      • [SMACK-175] - fix - UNSUBsCRIPTION_PENDING in RosterPacket
      • - -
      • [SMACK-235] - Improve - performance of Roster class
      • - -
      • [SMACK-240] - Update - Jingle implementation to newest version
      • - -
      • [SMACK-241] - Update - Base64 implementation to match Openfire's
      • - -
      • [SMACK-244] - Update - JSTUN to 0.7.2
      • - -
      • [SMACK-245] - Update - Jingle implementation to newest version
      • - -
      • [SMACK-246] - Improve - Jingle logging using commons-logging
      • - -
      • [SMACK-247] - Keep - Jingle compliant with on-going protocol development.
      • - -
      • [SMACK-254] - Offer - an alternative to loading the Roster on login
      • - -
      • [SMACK-261] - Minor - Jingle cleanup to better support Jingle in Spark
      • - -
      • [SMACK-277] - Update - XMLUnit to the latest version
      • - -
      • [SMACK-282] - Support - SASL-related error conditions.
      • - -
      • [SMACK-285] - Add - support for Nicks
      • - -
      • [SMACK-289] - There - is no way of retrieving items from a pubsub node when the user has multiple - subscriptions.
      • - -
      • [SMACK-294] - Handle - empty roster groups and no goups in the same way
      • - -
      • [SMACK-295] - Fire - reconnectionSuccessful event when session is established
      • - -
      • [SMACK-297] - add - configuration for local Socks5 proxy
      • - -
      • [SMACK-298] - Respond - to all incoming Socks5 bytestream requests
      • - -
      • [SMACK-299] - Improve - accepting of Socks5 bytestream requests
      • - -
      • [SMACK-300] - improve - local Socks5 proxy implemetation
      • - -
      • [SMACK-301] - support - for bytestream packets to query Socks5 proxy for network address
      • - -
      • [SMACK-302] - Improve - establishing of Socks5 bytestreams
      • - -
      • [SMACK-303] - integrate - of the extracted Socks5 bytestream API in file transfer API
      • - -
      • [SMACK-304] - Extend - the IQ API to create empty IQ results and IQ error response packets
      • - -
      • [SMACK-307] - Improve - Message Parser Robustness and Message Body I18N
      • - -
      • [SMACK-309] - Fully - implement XEP-0047 In-Band Bytestreams
      • - -
      • [SMACK-310] - Add - Support for Localized Message Subjects
      • - -
      • [SMACK-317] - PrivacyItem - class changes
      • - -
      • [SMACK-142] - Add - support for Kerberos/NTLM
      • - -
      • [SMACK-210] - Support - MD5 SASL
      • - -
      • [SMACK-226] - Need - to add in http/socks proxy support to XMLConnection.
      • - -
      • [SMACK-242] - Add - support for JEP-50: ad-hoc commands
      • - -
      • [SMACK-251] - Add - support for XEP-0163: Personal Eventing Protocol
      • - -
      • [SMACK-255] - Add - ability to set mime type for avatar
      • - -
      • [SMACK-256] - Add - support for new sophisticated TLS mechanisms including SmartCard and Apple's - KeychainStore
      • - -
      • [SMACK-272] - Add - support for pubsub (XEP-0060)
      • - -
      • [SMACK-296] - Add - support for XEP-0224: Attention
      • - -
      • [SMACK-319] - Add - common interfaces for SOCKS5 Bytestreams and In-Band Bytestreams
      • - -
      • [SMACK-279] - SMACK-187 - Create a abstract connection class to allow other implementations connecting - to a XMPP server.
      • - -
      • [SMACK-280] - SMACK-187 - The authentification should use the Connection#sendPacket method and work - transparent with packets and packet listeners.
      • - -
      • [SMACK-281] - SMACK-187 - Move IQ and stream error parsing from PacketReader which depends on the - connection type to PacketParserUtils.
      • - -
      • [SMACK-259] - Update - XPP library to latest version
      • - -
      • [SMACK-283] - Investigate - why Jingle is connecting to stun.xten.net
      • - -
      • [SPARK-1321] - Update Smack to final release - 3.2
      • -
      • [SPARK-1319] - Review Tray Icon of Spark on - Windows
      • -
      • [SPARK-1318] - STUN fallback in error log
      • -
      • [SPARK-1317] - Privacy Plugin causes error log - entry at startup
      • -
      • [SPARK-1312] - Load plugins before Login page - and workspace are initialized
      • -
      • [SPARK-1308] - JTattoo menubar decoration
      • -
      • [SPARK-1307] - Update build.xml to support Ant - 1.8
      • -
      • [SPARK-1300] - Remove Buttons from Spark
      • -
      • [SPARK-1293] - Include JGoodies as LaF
      • -
      • [SPARK-1103] - Add an option to register with - conference room
      • -
      • [SPARK-1091] - Create an installer for Mac OS X
      • -
      • [SPARK-1060] - Spark should remember - Preferences window (and others) position on the screen
      • -
      • [SPARK-1050] - Create a horizontal scrollbar in - the emoticons picker for large emoticons packages
      • -
      • [SPARK-1037] - Timing issue prevents contact - list from updating correctly
      • -
      • [SPARK-1035] - Add ability to have an invisible - presence
      • -
      • [SPARK-764] - Auto-reconnect does not send - available presence or ask for roster
      • -
      • [SPARK-744] - Spark fails to login after - restore from Hibernation
      • -
      • [SPARK-726] - Spark needs to use the users - presence prior to reconnect.
      • -
      • [SPARK-533] - Buzz feature improvements
      • -
      • [SPARK-915] - Tab - completion of conference room nicknames
      • - -
      • [SPARK-1105] - Spark - should indicate different permissions in MUC with additional icons or colors
      • - - -
      • [SPARK-1187] - Auto - tab completion in Spark
      • - - -
      • [SPARK-1261] - Default - properties should be stored visible in the Spark bin directory
      • - - -
      • [SPARK-1264] - Show - Transports in tab
      • - - -
      • [SPARK-1090] - Spark - should show time stamps in the full history
      • - - -
      • [SPARK-1175] - label.message - shows & in most translations
      • - - -
      • [SPARK-1222] - [Patch - ready to commit] Update Lithuanian translation
      • - - -
      • [SPARK-1259] - Add - to i18n new strings in Codecs menu
      • - - -
      • [SPARK-1124] - Chat - window is not flashing when receiving new message
      • - - -
      • [SPARK-1009] - Make gateway icons more - transparent to fit with new theme
      • - - -
      • [SPARK-1010] - On toast popup from a MUC show - the nickname of whoever said the comment
      • - - -
      • [SPARK-1012] - Update Jingle implementation to - latest in Smack
      • - - -
      • [SPARK-1024] - Add finish translation
      • - - -
      • [SPARK-1025] - Make rename global and not - limited to just the contact list
      • - - -
      • [SPARK-1032] - Improve the downloading class
      • - - -
      • [SPARK-1036] - Refactor JinglePlugin to - correctly utilize the latest Smack/Jingle library
      • - - -
      • [SPARK-1040] - Need to release a new SmackLib - that includes part of the changes needed to make Jingle work in Spark
      • - - -
      • [SPARK-1043] - Should automatically set Away - status when Desktop is locked
      • - - -
      • [SPARK-1044] - Replace spellchecker with new - multi-language spellchecker
      • - - -
      • [SPARK-1047] - Improve support of transparent - avatars
      • - - -
      • [SPARK-1054] - Swedish translation
      • - - -
      • [SPARK-1065] - Change Library from JMF to FMJ
      • - - -
      • [SPARK-1070] - Spark should have a faster - reaction on mouse movements when changing status
      • - - -
      • [SPARK-1077] - Add localization support for - hardcoded strings in the GUI
      • - - -
      • [SPARK-1086] - Change the title of the - broadcast message sent from the server
      • - - -
      • [SPARK-1090] - Spark should show time stamps in - the full history
      • - - -
      • [SPARK-1093] - Add Expand/Collapse all Groups - to shared groups
      • - - -
      • [SPARK-1102] - Updated Russion translation for - spark & spellchecker plugin
      • - - -
      • [SPARK-1107] - Updated Chinese translation
      • - - -
      • [SPARK-1115] - Update build.properties with - external resources information
      • - - -
      • [SPARK-1119] - Spark should parse /me in toast - popup
      • - - -
      • [SPARK-1120] - Spark should show who has - changed room's topic
      • - - -
      • [SPARK-1121] - Should be a way to copy URL - without selecting the whole URL text
      • - - -
      • [SPARK-1123] - Linux system tray improvements
      • - - -
      • [SPARK-1125] - Make deb package compatible with - Ubuntu 9.10
      • - - -
      • [SPARK-1127] - Correction of lithuanian - translation
      • - - -
      • [SPARK-1128] - Add a divider between recent - conversation and current conversation in a chat window
      • - - -
      • [SPARK-1136] - Add i18n file to FastPath plugin
      • - - -
      • [SPARK-1137] - Improve latencies in softphone - DTMF tone soundings
      • - - -
      • [SPARK-1139] - Improved linux startup.sh
      • - - -
      • [SPARK-1142] - Replace synthetica with - substance
      • - - -
      • [SPARK-1145] - Add Korean language
      • - - -
      • [SPARK-1156] - Remove double happy emoticon in - default set
      • - - -
      • [SPARK-1157] - Cleaned up resource bundle for - Spark
      • - - -
      • [SPARK-1159] - improve error logging
      • - - -
      • [SPARK-1174] - Korean translation update
      • - - -
      • [SPARK-1178] - Update turkish translation
      • - - -
      • [SPARK-1184] - Make Spark search for a profile - in old profile location
      • - - -
      • [SPARK-1190] - "Alert when user is - available" should open a new chat window
      • - - -
      • [SPARK-1208] - Change the default file transfer - save path
      • - - -
      • [SPARK-1220] - Create FlashWindow.dll 64-bit - version
      • - - -
      • [SPARK-1247] - Fix naming of the new setting - about showing muc roles icons
      • - - -
      • [SPARK-1259] - Add to i18n new strings in - Codecs menu
      • - - -
      • [SPARK-229] - Combine username and server into - a single field
      • - - -
      • [SPARK-251] - Conference button in one-to-one - Chat Does Not Show Feedback to the User
      • - - -
      • [SPARK-254] - Chat History needs to be - seperated into two files.
      • - - -
      • [SPARK-372] - change "Force Old SSL" - to "Force TLS" within the advanced options
      • - - -
      • [SPARK-373] - move SysTray code into a plugin
      • - - -
      • [SPARK-375] - allow to select the language - during installation or later
      • - - -
      • [SPARK-38] - Add support for configuring the - list of owners, admins, ban list and members list
      • - - -
      • [SPARK-389] - MUC, direct chat: chat history - uses room name and not user name
      • - - -
      • [SPARK-412] - improve "Refresh" in - "Browse Conference Rooms" window
      • - - -
      • [SPARK-413] - improve display of buttons in - "Browse Conference Rooms"
      • - - -
      • [SPARK-431] - add "Save / Apply" and - a "Cancel" button to Preferences Dialog
      • - - -
      • [SPARK-496] - Add preference to change look - and feel
      • - - -
      • [SPARK-671] - hide "show chat - history" button if chat history is disabled
      • - - -
      • [SPARK-677] - Hide Offline Users option in the - roster
      • - - -
      • [SPARK-678] - Alphabetize offline users in the - roster
      • - - -
      • [SPARK-700] - Add an option to turn off - Spark's update-checking feature
      • - - -
      • [SPARK-849] - "[ ] Enable Emotions" - should disable more
      • - - -
      • [SPARK-87] - Add ability to view users VCard - in Group Chat.
      • - - -
      • [SPARK-912] - Localization improvements w/ - bonus other improvements
      • - - -
      • [SPARK-930] - Offline contacts in broadcast - window
      • - - -
      • [SPARK-933] - Should show avatars in roster - instead of transport icons
      • - - -
      • [SPARK-934] - SysTray icon behaviour on click, - double click
      • - - -
      • [SPARK-940] - Startup registry entry and - Preferences setting issue
      • - - -
      • [SPARK-954] - Need an option to disable - showing previous conversation in chat window
      • - - -
      • [SPARK-959] - Broadcast dialog input field - should do text wrapping
      • - - -
      • [SPARK-963] - Should be an option to switch to - 24h time format in chat window
      • - - -
      • [SPARK-970] - Improve highliting of tabs
      • - - -
      • [SPARK-975] - Add an option to delete entries - in Tasks permanently
      • - - -
      • [SPARK-980] - Add an option to disable vcard - popups
      • - - -
      • [SPARK-993] - Improve the GUI
      • - - -
      • [SPARK-1011] - When someone says my name in an - MUC, show a custom toast popup if enabled
      • - - -
      • [SPARK-1018] - Add options to expand and - collapse all groups together
      • - - -
      • [SPARK-1049] - Turkish Language Pack
      • - - -
      • [SPARK-1052] - Create a new ant target to make - an IzPack and RPM Installer
      • - - -
      • [SPARK-1057] - Add an option to suppress - join/leave messages in the group chat
      • - - -
      • [SPARK-1072] - Add an option to make chat - window always stay on top
      • - - -
      • [SPARK-1076] - Add lithuanian translation
      • - - -
      • [SPARK-1078] - Add Lithuanian Spelling option
      • - - -
      • [SPARK-1105] - Spark should indicate different - permissions in MUC with additional icons or colors
      • - - -
      • [SPARK-1108] - Spark Kirghiz translation
      • - - -
      • [SPARK-1110] - Jingle and Flashing plugin - Chinese (CHN) translation
      • - - -
      • [SPARK-1135] - Add Korean translation
      • - - -
      • [SPARK-1141] - Allow to disable the add contact - feature
      • - - -
      • [SPARK-1143] - Add Plugin Dependencies
      • - - -
      • [SPARK-1146] - Fastpath Brasilian translation
      • - - -
      • [SPARK-1147] - Phonebook for SIPClient
      • - - -
      • [SPARK-1148] - Support Speex and iLBC Codec
      • - - -
      • [SPARK-1149] - Allow to disable and reorder sip - codecs
      • - - -
      • [SPARK-1187] - Auto tab completion in Spark
      • - - -
      • [SPARK-1201] - Create a plugin to add Send - button to chat input area
      • - - -
      • [SPARK-1246] - Publish smack.packet.PrivacyItem - class setOrder() for RC2
      • - - -
      • [SPARK-1250] - Scroll Bar does not scroll for a - window
      • - - -
      • [SPARK-1261] - Default properties should be - stored visible in the Spark bin directory
      • - - -
      • [SPARK-409] - option to disable the password - change fields
      • - - -
      • [SPARK-448] - show offline users in their - group and not in offline group
      • - - -
      • [SPARK-467] - Persist search information when - doing user searches on multiple search services.
      • - - -
      • [SPARK-640] - File Transfer detection with - disabling if necessary
      • - - -
      • [SPARK-724] - Reorder tabs in chat window
      • - - -
      • [SPARK-730] - Skin: Need to key account login - from users Enterprise License.
      • - - -
      • [SPARK-736] - Set Spark away when workstation - is locked.
      • - - -
      • [SPARK-739] - Need to add a turkish - translation to Spark.
      • - - -
      • [SPARK-799] - Server is editable on failed - login
      • - - -
      • [SPARK-801] - Add a SpellChecker in other - languages
      • - - -
      • [SPARK-877] - Add a Re-Detect Audio Devices to - SparkPhone
      • - - -
      • [SPARK-896] - Spark chat logs should be - searchable
      • - - -
      • [SPARK-915] - Tab completion of conference - room nicknames
      • - - -
      • [SPARK-928] - Hide Offline group option
      • - - -
      • [SPARK-943] - Add an option to read and copy - contact's status message
      • - - -
      • [SPARK-947] - Add QQ transport support?
      • - - -
      • [SPARK-961] - Option to leave nickname blank - by default in add contact window
      • - - -
      • [SPARK-971] - System Tray notification about - incoming messages
      • - - -
      • [SPARK-972] - Typing Notification in System - Tray
      • - - -
      • [SPARK-991] - Group Chat Highlighting
      • - -
      - - - -

      Bug Fixes (more than 250 issues)

      -
        - -
      • [SMACK-330] - Added missing node attribute in the item element for pubsub.
      • - -
      • [SMACK-325] - Reconnection Manager can be running twice
      • - -
      • [SMACK-334] - Error in form for FileTransferNegotiator
      • -
      • [SMACK-163] - Fix NPE in RoomInfo when subject has not value
      • - -
      • [SMACK-207] - Parsing of - messages may disconnect Smack/Spark
      • - -
      • [SMACK-225] - Improper - handeling of DNS SRV records
      • - -
      • [SMACK-232] - Better - handling of Roster error
      • - -
      • [SMACK-236] - Rename - stanza error "unexpected-condition" to - "unexpected-request"
      • - -
      • [SMACK-243] - Packet - with wrong date format makes Smack to disconnect
      • - -
      • [SMACK-258] - Fix - disconnection issue when parsing SASL success that contains a payload
      • - -
      • [SMACK-260] - error - presence packets when server is down
      • - -
      • [SMACK-264] - fix - for NPE in SASLMechanism.java
      • - -
      • [SMACK-269] - Smack - 3.1.0 creates a new chat for every incoming message
      • - -
      • [SMACK-271] - Deadlock - in XMPPConnection while login and parsing stream features
      • - -
      • [SMACK-275] - Patch: - Fix for broken SASL DIGEST-MD5 implementation
      • - -
      • [SMACK-288] - The - parsing of the result for a LeafNode.getItems() call is incorrect. It creates - a DefaultPacketExtension instead of an Item for every other item in the - result.
      • - -
      • [SMACK-290] - Deadlock - while getting Roster before it's initialized
      • - -
      • [SMACK-291] - RosterGroup - modifications should depend on roster push
      • - -
      • [SMACK-293] - Support - optional roster subscription attribute
      • - -
      • [SMACK-305] - RosterEntry#getGroups - causing a roster reload
      • - -
      • [SMACK-308] - Multiple - errors in pubsub GetItemsRequest
      • - -
      • [SMACK-312] - Only - fire RosterListener#entriesUpdated for RosterEntries that changed
      • - -
      • [SMACK-313] - Pubsub - library doesn't allow the packet id to be specified.
      • - -
      • [SMACK-316] - Smack - FromMatchesFilter behaves wrong with chats with similar names
      • - -
      • [SMACK-321] - Usage - of SimpleDateFormat is not threadsafe
      • - -
      • [SMACK-327] - getFeatures() - method on DiscoverInfo is improperly set to be package protected instead of - public
      • - -
      • [SMACK-328] - Number - format exception while parsing dates.
      • - -
      • [SMACK-332] - Smack - 3.2.0b2 shows wrong version in Smack Dubugger Window
      • - -
      • [SPARK-1320] - Errors in - privacy plugin i18n string
      • - -
      • [SPARK-1315] - Spark - cannot find spark.jar to load different languages
      • - -
      • [SPARK-1310] - Local - users are loading slowly
      • - -
      • [SPARK-1309] - Colorsettings - are possibly outdated if profile not cleaned regularly and colors.tab is - deactivated
      • - -
      • [SPARK-1305] - No - rooms are shown in room browser
      • - -
      • [SPARK-1295] - Left - menu panel in Preferences gets squeezed
      • - -
      • [SPARK-1294] - Spark - 2.6 RC2 No Phone Call Button
      • - -
      • [SPARK-743] - Changes - in the user.home directory
      • - - - -
      • [SPARK-1130] - Spark - behaves wrong with chats with similar names
      • - - -
      • [SPARK-1270] - Name Completion on Shared Rosters without Vcards causes NPE
      • -
      • [SPARK-1268] - Cursor changes to hand after sending a message
      • -
      • [SPARK-1267] - Set a default size for Preferences window for new profiles
      • -
      • [SPARK-1183] - Spellchecker is not working normally
      • -
      • [SPARK-1161] - Set a default minimum size of a tab
      • -
      • [SPARK-1068] - Spark is not reacting to outside keyboard events when setting the auto Away status
      • - -
      • [SPARK-1209] - Agent - names are missing in Fastpath Online Agents tab
      • - - -
      • [SPARK-1260] - Search - Dialog error
      • - - -
      • [SPARK-1262] - BUG: - spark_2_6_0_12103 : spark download folder not working
      • - - -
      • [SPARK-618] - Fixed multiple message issue with Broadcast.
      • - - -
      • [SPARK-1004] - if a username is too long then - it gets cut off
      • - - -
      • [SPARK-1016] - Spark should preserve custom - status between automatic changes of presence
      • - - -
      • [SPARK-1019] - Spark IRC support passing wrong - variable for nickname
      • - - -
      • [SPARK-102] - Changing temp conf room name to - permanent name leads to odd behavior
      • - - -
      • [SPARK-1020] - is part of SPARK-1228 - Spark shows wrong popup upon receiving group chat invitation
      • - - -
      • [SPARK-1022] - Linux Tray Icon not appearing
      • - - -
      • [SPARK-1023] - Add remove button to call - history
      • - - -
      • [SPARK-1027] - Prevent duplicate conferences
      • - - -
      • [SPARK-1028] - Spark is still showing null - avatars/display pictures
      • - - -
      • [SPARK-1029] - Clicking the information button - will send the chat text field
      • - - -
      • [SPARK-1034] - Spark 2.6.0b2 Does not display - the entire preference window.
      • - - -
      • [SPARK-1038] - Spark does not currently build - on OS X
      • - - -
      • [SPARK-1039] - Fastpath does not compile - against latest Smack
      • - - -
      • [SPARK-1041] - Update Spanish translation
      • - - -
      • [SPARK-1046] - Log out with reason not work on - other langauges
      • - - -
      • [SPARK-1048] - Correct accuracy of screenshot
      • - - -
      • [SPARK-1055] - is part of SPARK-1224 - Make an option to supress the reconnection popup
      • - - -
      • [SPARK-1056] - Save Spark window positions on - non-primary screen
      • - - -
      • [SPARK-1059] - Show a toast popup when - "Alert when available" is selected
      • - - -
      • [SPARK-1061] - Show new messages in systemtray - option is not working
      • - - -
      • [SPARK-1063] - Spark is not reacting to - keyboard events when setting the auto Away status
      • - - -
      • [SPARK-1064] - Scratchpad (Tasks) Dialog has - graphical errors
      • - - -
      • [SPARK-1069] - Spark continuos flashing - continues to flash after the chat window gets focus
      • - - -
      • [SPARK-1081] - Spark is now showing - APPLICATION_NAME in the tooltip
      • - - -
      • [SPARK-1082] - Spark is showing 2 systray icons - on 64-bit Windows 7
      • - - -
      • [SPARK-1083] - Fix gateway icons toolbar - initialization
      • - - -
      • [SPARK-1085] - Add Fastpath plugin to a Spark - build
      • - - -
      • [SPARK-1089] - Spark should show 24h time - stamps in a previous conversation history
      • - - -
      • [SPARK-1092] - Spark is not showing Canned - responses stored on the server and cant create new ones
      • - - -
      • [SPARK-1096] - Custom status messages should be - sorted by name
      • - - -
      • [SPARK-1097] - Delete the obsolete Available - translation string from the i18n file
      • - - -
      • [SPARK-1099] - Spark is showing received - message twice in MUC private chat
      • - - -
      • [SPARK-1101] - Fix typos in Russian translation - file
      • - - -
      • [SPARK-1109] - incorrect charset in method - MediaPreferencePanel.scanDevices on Windows 2000(CHN)
      • - - -
      • [SPARK-1111] - Recent conversation is still - showing after history cleaning with not english GUI language
      • - - -
      • [SPARK-1112] - Minor visual issues with history - cleaning
      • - - -
      • [SPARK-1116] - Private chat history in MUC is - not saving
      • - - -
      • [SPARK-1117] - Can't change priority field of a - custom status
      • - - -
      • [SPARK-1118] - Not possible to resize text - input area in the chat window
      • - - -
      • [SPARK-1122] - Spark is not sending typing - notifications
      • - - -
      • [SPARK-1124] - is part of SPARK-1228 - Chat window is not flashing when receiving new message
      • - - -
      • [SPARK-1126] - Chat window doesnt appear upon - receiving new message
      • - - -
      • [SPARK-1129] - Idle Enabled shouldn't override - a custom Away status
      • - - -
      • [SPARK-1130] - Spark behaves wrong with chats - with similar names
      • - - -
      • [SPARK-1131] - Log out stopped working in the - latest SVN
      • - - -
      • [SPARK-1132] - Couldn't Get all contact items - from ContactList
      • - - -
      • [SPARK-1133] - Contact list issue
      • - - -
      • [SPARK-1138] - Softphone panel not redisplaying - after close
      • - - -
      • [SPARK-1140] - Change to Apache 2.0 license
      • - - -
      • [SPARK-1144] - Ant buildscript should not check - for explicit Ant version numbers
      • - - -
      • [SPARK-1151] - Taskbar Flashing and - Spellchecker tabs not available in Preferences
      • - - -
      • [SPARK-1152] - Startup.sh doesn't work on - Ubuntu 10.04
      • - - -
      • [SPARK-1153] - Wrong contacts count on - reconnect
      • - - -
      • [SPARK-1154] - Linux version doesn't have Log - out option
      • - - -
      • [SPARK-1155] - Empty messages in Group Chat
      • - - -
      • [SPARK-1158] - Group title doesn't updates - after moving ContactItem from one group to another
      • - - -
      • [SPARK-1163] - Spark displays wrong error when - nickname change is forbidden
      • - - -
      • [SPARK-1164] - Chat window is not positioning - at the last history message when opening window
      • - - -
      • [SPARK-1166] - Spark is not showing a progress - of file transfer
      • - - -
      • [SPARK-1168] - Offline users are shown on login - when option is set to not to show them
      • - - -
      • [SPARK-1169] - is part of SPARK-1229 - Spark shows offline roster after reconnecting
      • - - -
      • [SPARK-1171] - Chat window is not drawn - correctly when opened on a primary monitor
      • - - -
      • [SPARK-1172] - Flashing and Spellchecker - options are absent in Preferences
      • - - -
      • [SPARK-1173] - Reconnection with new and - different IP fails after network loss
      • - - -
      • [SPARK-1180] - Fix the placement of the - Bookmarks menu
      • - - -
      • [SPARK-1182] - File path for a URL bookmark is - not working
      • - - -
      • [SPARK-1186] - Ctrl + W not working as expected - in chat window
      • - - -
      • [SPARK-1189] - Spark systray menu is overlapped - by vertical taskbar
      • - - -
      • [SPARK-1194] - Move/copy contact item to new - group don't check item into new group offline contacts
      • - - -
      • [SPARK-1196] - is part of SPARK-1223 - Spellchecker Bug: Java AWT-EventQueue-1 - null pointer exception
      • - - -
      • [SPARK-1206] - is part of SPARK-1228 - New chat window is not opened while receiving offline messages on login
      • - - -
      • [SPARK-1211] - Spark doesn't show room in the - rooms list
      • - - -
      • [SPARK-1212] - Shouldn't be able to search for - yourself and add yourself to a roster
      • - - -
      • [SPARK-1213] - Spark duplicates rooms in the - conference browser when hitting Refresh button fast
      • - - -
      • [SPARK-1216] - Upgrade Smack in Trunk to Smack - 3.2 beta 2
      • - - -
      • [SPARK-1217] - Locales prevent Plugins from - loading
      • - - -
      • [SPARK-1219] - is part of SPARK-1230 - Polish translation
      • - - -
      • [SPARK-1221] - is part of SPARK-1223 - Bookmark Plugin causes error in error log
      • - - -
      • [SPARK-1225] - is part of SPARK-1223 - Warning Log4J: No appenders could be found for logger
      • - - -
      • [SPARK-1226] - is part of SPARK-1223 - SIP Codec causes error on load
      • - - -
      • [SPARK-1227] - is part of SPARK-1223 - [Patch] Remove sound driver report from error log
      • - - -
      • [SPARK-1229] - Masterticket: Roster Management
      • - - -
      • [SPARK-1231] - Wrong time on loading history - messages in conferences
      • - - -
      • [SPARK-1233] - [Patch ready to commit] Mouse - Click on Avatar in VCard Preview opens another VCard Preview
      • - - -
      • [SPARK-1237] - Remove stun.xten.net as fixed - URL for STUN fall back from Jingle. This should be set in spark.properties
      • - - -
      • [SPARK-1240] - Spark is not saving "Show - empty groups" setting between restarts
      • - - -
      • [SPARK-1241] - is part of SPARK-1223 - UiThreadingViolationException when loading Flashing Plugin
      • - - -
      • [SPARK-1242] - Group disappears after a rename.
      • - -
      • [SPARK-1248] - is part of SPARK-1223 - ArrayIndexOutOfBoundsException in - javax.swing.plaf.basic.BasicListUI.updateLayoutState
      • - - -
      • [SPARK-1249] - is part of SPARK-902 - item-not-found(404) in PrivacyManager
      • - - -
      • [SPARK-1251] - is part of SPARK-902 - PrivacyPlugin causes NullPointerE. when clicking on "block - contact"
      • - - -
      • [SPARK-1252] - is part of SPARK-902 - PrivcyPlugin No rightclick menu on ContactGroups
      • - - -
      • [SPARK-1255] - Translator plugin is not working
      • - - -
      • [SPARK-1256] - Remove & from Check for - updates menu entry
      • - - -
      • [SPARK-158] - Unable to open files after file - transfer.
      • - - -
      • [SPARK-210] - Kicked out user gets incomplete - message, and upon re-entry, doesn't see other room participants
      • - - -
      • [SPARK-237] - Add debug mode to allow for full - debugging capabilities on startup.
      • - - -
      • [SPARK-24] - Memory does not decrease after - closing chat window.
      • - - -
      • [SPARK-261] - Paste in ChatWindow does not - work as expected.
      • - - -
      • [SPARK-278] - URL parser issues
      • - - -
      • [SPARK-284] - Same Alt-? hotkeys set for - different options on the same menu
      • - - -
      • [SPARK-286] - unicode display bug / window - title
      • - - -
      • [SPARK-311] - File Transfer Not Possible - Unless User Is in Contact List
      • - - -
      • [SPARK-340] - is part of SPARK-1229 - Duplicate text entries appear when reconnecting Spark
      • - - -
      • [SPARK-349] - MUC / Create Room: fix strange - behaviour
      • - - -
      • [SPARK-381] - Users with European characters - in their JID can not login
      • - - -
      • [SPARK-404] - Chat history should be saved on - a timer and on shutdown.
      • - - -
      • [SPARK-421] - Add new file transfer within - HTML Viewer.
      • - - -
      • [SPARK-423] - Need a default Spark Theme for - the Chat Window themes.
      • - - -
      • [SPARK-455] - Auto away status does not work - in LInux version of Spark
      • - - -
      • [SPARK-458] - Add support for 64 bit machines
      • - - -
      • [SPARK-475] - Spark 2.0.8 custom skin w/ - wildfire spark version set, always thinks there's a newer version
      • - - -
      • [SPARK-547] - Decrease screenshot memory usage
      • - - -
      • [SPARK-570] - display all received chat - messages
      • - - -
      • [SPARK-572] - Custom status messages under - "On Phone" status now show as phone icon.
      • - - -
      • [SPARK-575] - Spark does not un-escape - usernames properly
      • - - -
      • [SPARK-581] - Fix cut and paste issue in Chat - Window.
      • - - -
      • [SPARK-586] - remove top-left JMC window
      • - - -
      • [SPARK-608] - Updated Spark to use latest - workgroup api.
      • - - -
      • [SPARK-619] - On Linux a user does not come - back from the "Away due to idle" to "Available"
      • - - -
      • [SPARK-624] - ChatRoomNotFoundException - receiving a broadcast
      • - - -
      • [SPARK-625] - Fixes for Jingle on Linux
      • - - -
      • [SPARK-627] - Fixes for SIP on Debian
      • - - -
      • [SPARK-631] - Fix layout for long names in - roster
      • - - -
      • [SPARK-632] - Small "Join Conference - Room" windows in Linux and Vista
      • - - -
      • [SPARK-637] - BUZZ highlight chat tab
      • - - -
      • [SPARK-64] - some animated avatars don't work
      • - - -
      • [SPARK-657] - Improvements for Private Chats - from a Conference Room
      • - - -
      • [SPARK-667] - Spark should only transform - first /me
      • - - -
      • [SPARK-690] - JMF cannot find formats on VISTA
      • - - -
      • [SPARK-692] - multiple bugs with 64-bit OS on - LInux
      • - - -
      • [SPARK-696] - Roster gets out of order over - time
      • - - -
      • [SPARK-697] - Unable to load plugin - TranslatorPlugin
      • - - -
      • [SPARK-699] - Spark is sending multiple, - duplicate, inconsistent Disco Info responses
      • - - -
      • [SPARK-706] - Usernames need to be escaped - when looking up profiles.
      • - - -
      • [SPARK-708] - Need to remove any network calls - when opening a chat room.
      • - - -
      • [SPARK-71] - Custom status messages should be - available in system tray
      • - - -
      • [SPARK-710] - Right-click on URL link inside - transcript window causes browser to be invoked.
      • - - -
      • [SPARK-712] - Groupchat List can become - corrupted.
      • - - -
      • [SPARK-713] - URLs with commas break before - first comma
      • - - -
      • [SPARK-715] - Login screen uses password from - memory if it exists and not the login field.
      • - - -
      • [SPARK-720] - Communication end is not - interpreted
      • - - -
      • [SPARK-721] - Rejecting a SIP call in Spark - does not reject the hard phone call
      • - - -
      • [SPARK-734] - Error: Couldn't find per display - information - JDK 1.6 on Linux
      • - - -
      • [SPARK-741] - Incorrect list of people in the - group chat
      • - - -
      • [SPARK-749] - Ctrl+F does not sort user names
      • - - -
      • [SPARK-750] - chat history not saved
      • - - -
      • [SPARK-756] - Users Leave and Rejoin Groupchat - Causes Them to Not Appear in User List
      • - - -
      • [SPARK-762] - Can Receive Multiple Invitations - To The Same Room
      • - - -
      • [SPARK-765] - Messages without type attribute - are displayed twice (broadcasts)
      • - -
      • [SPARK-769] - is part of SPARK-1229 - Autoreconnect does not always complete the "session - establishment" and does not request users' presence
      • - - -
      • [SPARK-772] - registration / JID escaping
      • - - -
      • [SPARK-776] - Remove systray icon after close
      • - - -
      • [SPARK-777] - is part of SPARK-1229 - Hidden Empty Groups do not become visible
      • - - -
      • [SPARK-780] - is part of SPARK-1224 - Cannot load contacts on reconnection
      • - - -
      • [SPARK-788] - Some avatars are not correctly - displayed
      • - - -
      • [SPARK-789] - Some text not internationalized
      • - - -
      • [SPARK-806] - Chat text box does not have a - scroll when the text to send is large
      • - - -
      • [SPARK-814] - is part of SPARK-1155 - Empty Conversations in Group Chat
      • - - -
      • [SPARK-815] - Local time is not completed in - the Client Version
      • - - -
      • [SPARK-816] - The google talk emoticon: \m/ is - not translated to gif
      • - - -
      • [SPARK-824] - Group Chat Messages from blocked - users are displayed in the Toast Popup
      • - - -
      • [SPARK-835] - Update translations inside Spark
      • - - -
      • [SPARK-841] - Spark does not notify a user - when they are removed from the room.
      • - - -
      • [SPARK-848] - Jabber:IQ:Time not showing up on - request.
      • - - -
      • [SPARK-861] - Spark skinning windows installer - requires MSVCR71.dll
      • - - -
      • [SPARK-872] - Skinned spark does not handle - xmpp: addresses
      • - - -
      • [SPARK-878] - Linux idle plugin not properly - handling coming back from idle
      • - - -
      • [SPARK-879] - Double contacts appear in - roster.
      • - - -
      • [SPARK-883] - Control+T window shows no data
      • - - -
      • [SPARK-886] - Reconnection logic not working - properly
      • - - -
      • [SPARK-889] - New tab/window focus does not - cause focus to be in typing area of window
      • - - -
      • [SPARK-892] - is part of SPARK-1224 - Spark should automatically reconnect you to chatrooms after a reconnection
      • - - -
      • [SPARK-897] - PARK-874 still seems to be - occuring
      • - - -
      • [SPARK-898] - org/jivesoftware/spark/ui/RetryPanel.java - uses non-standard Smack
      • - - -
      • [SPARK-901] - Fix JVM crash when using Jingle - on the Mac OS X
      • - - -
      • [SPARK-903] - Removing a bookmark doesn't - remove it from the bookmarks menu in os x, maybe others
      • - - -
      • [SPARK-906] - Spark's build should unpack - .pack'd files at build time, not at first startup
      • - - -
      • [SPARK-908] - Messages sent by pressing the - View Profile Icon
      • - - -
      • [SPARK-909] - Spark Crashes after ending a - Muted Call
      • - - -
      • [SPARK-910] - Some avatars are not displayed
      • - - -
      • [SPARK-913] - Settings not always being saved - after changes made
      • - - -
      • [SPARK-914] - Spark does not handle messages - with subjects very well
      • - - -
      • [SPARK-917] - Spark Phone is not Unregistering - on Spark Logout
      • - - -
      • [SPARK-921] - Sometimes Spark can't change to - Available automatically
      • - - -
      • [SPARK-922] - is part of SPARK-1228 - Broadcast window resizing should be fixed
      • - - -
      • [SPARK-923] - Fix room topic change tooltip
      • - - -
      • [SPARK-924] - Fix incoming message - notification tooltip showing wrong presence status
      • - - -
      • [SPARK-925] - Should receive offline - broadcasts after logging in
      • - - -
      • [SPARK-926] - Custom status editing no longer - working in trunk
      • - - -
      • [SPARK-937] - Wrong notification popup upon - receiving a file
      • - - -
      • [SPARK-941] - Pressing Cancel in "Log out - with reason" window shouldnt log out
      • - - -
      • [SPARK-944] - After language change should be - "Exit now?", not "Restart now?"
      • - - -
      • [SPARK-950] - Spark is not showing /" - chars in chat window
      • - - -
      • [SPARK-952] - Links will not open from chat - windows under Linux
      • - - -
      • [SPARK-960] - Spark does not remember group - state.
      • - - -
      • [SPARK-962] - Spark gets confused when - multiple conference services are available
      • - - -
      • [SPARK-969] - When someone performs a file - transfer or non-message related event, the last message before it is shown in - growl notifications
      • - - -
      • [SPARK-978] - Buzz delay should not reset - after closing chat window
      • - - -
      • [SPARK-988] - DoS (disconnect of other - clients)
      • - - -
      • [SPARK-990] - View Downloads doesn't pop-up - Downloads window
      • - - -
      • [SPARK-994] - Bookmarks menu is not refreshing - immediately
      • - - -
      • [SPARK-997] - An error occurs when enetering - no Gateway username
      • - -
      - - - - -

      2.5.8 -- November 14th, 2007

      -

      New Features

      -
        -
      • [SPARK-820] - Empty roster items now show jid instead of blank.
      • -
      • [SPARK-856] - Updated avatar size in contact list, also selectable from three choices.
      • -
      • [SPARK-867] - GaduGadu, IRC, and SIMPLE transports now supported.
      • -
      • [SPARK-868] - Entire status message now displayed with word/line wrapping on tooltip.
      • -
      • SIP Phone plugin is now open source.
      • -
      - -

      Bug Fixes

      -
        -
      • [SPARK-618] - Fixed multiple message issue with Broadcast.
      • -
      • [SPARK-857] - Fixed language selection menu is not displaying.
      • -
      • [SPARK-860] - Show offline users in broadcast window.
      • -
      • [SPARK-855] - Allowed mainWindowHeight to have low values.
      • -
      • [SPARK-869] - Gateway icons are now lightning up properly.
      • -
      • [SPARK-870] - Window positions/sizes are being saved upon window close now.
      • -
      • [SPARK-874] - Spark is now able to handle the new conference search capability of Openfire 3.4.1
      • -
      - -

      2.5.7 -- September 20th, 2007

      -

      New Features

      -
        -
      • [SPARK-792] - Add Language Selection to Spark Installation
      • -
      • [SPARK-846] - Allow option to show avatars in Contact List.
      • -
      - -

      Bug Fixes

      -
        -
      • [SPARK-782] - Fixed system tray with limited users and on linux.
      • -
      • [SPARK-818] - Improvements to reconnection code.
      • -
      • [SPARK-825] - Fixed sip stack sending superfluous REGISTER Packet
      • -
      • [SPARK-827] - Fixed limited users issue.l
      • -
      • [SPARK-829] - Fixed XMPP URI in registry.
      • -
      • [SPARK-830] - Fixed start on startup issue with installer.
      • -
      • [SPARK-831] - Fixed XMPP URI not starting conversations when spark is not running.
      • -
      • [SPARK-832] - Fixed offline messages not showing up in certain situations.
      • -
      • [SPARK-833] - Fixed bad MSI installer.
      • -
      • [SPARK-834] - Upgraded to the latest SMACK.
      • -
      • [SPARK-836] - JNIWrapper is now being included with the linux distro.
      • -
      • [SPARK-838] - Fixed gateway issue on initial roster loading.pear.
      • -
      • [SPARK-839] - Fixed loading of spark in system tray.
      • -
      • [SPARK-840] - Added chinese translation to Spark
      • -
      - -

      2.5.6 -- August 23rd, 2007

      -

      Bug Fixes

      -
        -
      • [SPARK-767] - Fixed roster not populating offline users in their respective groups.
      • -
      • [SPARK-807] - Fixed sending of empty broadcast messages.
      • -
      • [SPARK-810] - Added in system tray for linux (requires Java 1.6)
      • -
      • [SPARK-811] - Fixed spark not loading JMF Native libraries
      • -
      • [SPARK-813] - Added GTalk and XMPP gateways.
      • -
      • [SPARK-819] - Fixed issue with file picker hanging spark.
      • -
      • [SPARK-821] - Fixed timestamps in conference rooms.
      • -
      • [SPARK-823] - Explicit loading of plugins no longer fails due to wrong classloader.
      • -
      - -

      2.5.5 -- August 5th, 2007

      -

      Bug Fixes

      -
        -
      • [SPARK-719] - Fixed communication time in Phone.
      • -
      • [SPARK-755] - Fixed Spark crash after login with latest jvm build 1.6.0_01-b06
      • -
      • [SPARK-773] - Fixed file transfer issue after reconnection.
      • -
      • [SPARK-774] - Fixed search service issue after reconnection.
      • -
      • [SPARK-781] - Fixed one to one conversation in group chat room using a single user.
      • -
      • [SPARK-782] - Fixed system tray not appearing on certain users computers.
      • -
      • [SPARK-784] - Update spanish translation file.
      • -
      • [SPARK-786] - Updated the italian translation.
      • -
      • [SPARK-790] - Fixed toaster not timing with Fastpath notifications.
      • -
      • [SPARK-793] - Fixed bookmarks causing NPE on room discovery.
      • -
      • [SPARK-797] - Spark should not show presence updates in chat window if the user is still online.
      • -
      • [SPARK-798] - Fixed chat window not opening when Timer is cancelled.
      • -
      • [SPARK-800] - Increased File Transfer timeout time.
      • -
      - -

      2.5.4 Beta 1 -- June 11th, 2007

      -

      Bug Fixes

      -
        -
      • [SPARK-759] - Fixed File transfer issue on Mac OSX.
      • -
      • [SPARK-763] - Moving all native code to plugin for better linux support.
      • -
      • [SPARK-766] - One to one conversation in group chat room always sending to same user.
      • -
      • [SPARK-770] - Need to fix minor i18n German translation issues.
      • -
      • [SPARK-771] - Multiple offline contacts showing up in roster after reconnection.
      • -
      - - - -

      2.5.3 Beta 2 -- May 28th, 2007

      - -

      Bug Fixes

      -
        -
      • [SPARK-748] - Ctrl-f does not pick up different users with same contact name.
      • -
      • [SPARK-753] - FRAME_IMAGE not found
      • -
      • [SPARK-757] - Upgrade smack to fix SRV DNS issue in SASL.
      • -
      • [SPARK-758] - Spark needs to send messages to full jid on opening of chat room.
      • -
      - - -

      2.5.3 Beta 1 -- May 11th, 2007

      - -

      New Features

      -
        -
      • [SPARK-111] - Users can now select contact items from multiple groups, which allows for better broadcast handling.
      • -
      • [SPARK-662] - Add new emoticons to default emoticon pack.
      • -
      • [SPARK-725] - Added Single Sign-ON (SSO) support.
      • -
      • [SPARK-727] - Added new Spark Users Guide
      • -
      • [SPARK-729] - Skin: Added option for SSO boolean. If selected Spark just tries to connect to the given server as an SSO situation.
      • -
      • [SPARK-735] - Added integrated sso - smack code into Spark.
      • -
      - -

      Bug Fixes

      -
        -
      • [SPARK-718] - Fixed small asterisk-IM issue.
      • -
      • [SPARK-732] - Fixed conference room participant list issue when renaming nickname.
      • -
      • [SPARK-742] - Jingle now uses preffered codec.
      • -
      • [SPARK-746] - Fixed issue with Update checker not updating users from beta to release.
      • -
      • [SPARK-748] - Fixed CTRL+F issue handling multiple matching nicknames.
      • -
      - -

      2.5.2 -- May 3rd, 2007

      - -

      New Features

      -
        -
      • [SPARK-2] - Spark now display offline status information.
      • -
      • [SPARK-399] - Added new color randomizer for user names in group chat rooms.
      • -
      • [SPARK-401] - Added better error handling during conference room creation.
      • -
      • [SPARK-609] - Added a new Conference invitation ui.
      • -
      • [SPARK-661] - Updated the Italian translation.
      • -
      • [SPARK-664] - Added beta release support to the upgrade notification system.
      • -
      • [SPARK-665] - Change update checks to weekly.
      • -
      • [SPARK-674] - Added RTP Media Listening for jingle, improving connectivity check.
      • -
      • [SPARK-679] - Improved notifications when user comes online/offline.
      • -
      • [SPARK-691] - Improved UI for contact list groups.
      • -
      • [SPARK-701] - Added Japanese translation.
      • -
      - -

      Bug Fixes

      -
        -
      • [SPARK-598] - MSI now supports automatic upgrades.
      • -
      • [SPARK-626] - Added in missing jars to classpath on linux.
      • -
      • [SPARK-659] - Socks5 proxy not uses the username and password.
      • -
      • [SPARK-666] - Fixed file transfer timeout issue.
      • -
      • [SPARK-669] - Fixed issue with invalid title showing up in contact info.
      • -
      • [SPARK-682] - Dialing an invalid number is now handled properly by Spark
      • -
      • [SPARK-693] - Changed the buzz icon tool tip.
      • -
      • [SPARK-704] - Users are now able to create new conference rooms when using limited permissions for Group Chat.
      • -
      • [SPARK-714] - SparkPhone handles registration failures properly.
      • -
      - - -

      2.5.2 Beta 1 -- April 20th, 2007

      - -

      New Features

      -
        -
      • [SPARK-399] - Added color randomizer for user names in group chat rooms.
      • -
      • [SPARK-609] - Added new Conference Invitation UI.
      • -
      • [SPARK-674] - Added RTP Media Listening for jingle, improving connectivity check.
      • -
      • [SPARK-691] - Improved UI for contact list groups.
      • -
      • [SPARK-701] - Added Japanese translation.
      • -
      - -

      Bug Fixes

      -
        -
      • [SPARK-2] - Spark now displays offline status messages.
      • -
      • [SPARK-401] - Added better error handling during MUC creation.
      • -
      • [SPARK-598] - Fixed issue with upgrades and MSI builds.
      • -
      • [SPARK-626] - Fixed issue with missing jars from the classpath in Linux.
      • -
      • [SPARK-659] - Socks5 proxy now uses specified username and password.
      • -
      • [SPARK-661] - Updated Italian translation.
      • -
      • [SPARK-664] - Add beta releases to the upgrade notification system
      • -
      • [SPARK-665] - Changed update check to check only once a week and not on every log in.
      • -
      • [SPARK-666] - Fixed file transfer on Mac.
      • -
      • [SPARK-669] - Fixed issue with VCard info showing up for the wrong contact.
      • -
      • [SPARK-679] - Improved notification when user comes online.
      • -
      • [SPARK-682] - Dialing an invalid number is now handled properly by Spark.
      • -
      • [SPARK-693] - Fixed buzz icon tooltip.
      • -
      • [SPARK-714] - Fixed issue with SparkPhone opening 2 Phone Panel after several registration fails and many disconnections
      • -
      - -

      2.5.1 -- April 14th, 2007

      - -

      No Changes.

      - - -

      2.5.1 Beta 1 -- April 9th, 2007

      - -

      New Features

      -
        -
      • [SPARK-2] - Show offline status information
      • -
      - - -

      Bug Fixes

      -
        -
      • [SPARK-623] - Fixed error when trying to establish a voice communication.
      • -
      • [SPARK-633] - Fixed screenshot issue on Linux.
      • -
      • [SPARK-644] - Fixed timing issue with Jingle calls and UI.
      • -
      • [SPARK-645] - Fix tab switching issue on Mac.
      • -
      • [SPARK-647] - Fixed growl issue on Mac.
      • -
      • [SPARK-649] - Fixed screenshot tool on Mac.
      • -
      • [SPARK-650] - Improved descriptive text for Jingle calls.s
      • -
      • [SPARK-652] - Fixed issue with missing icon when viewing plugin information.
      • -
      • [SPARK-654] - Fixed issue registering soft phone on Mac.
      • -
      • [SPARK-655] - Fixed buzz icon and placement
      • -
      • [SPARK-656] - Installer is now adding desktop shortcuts.
      • -
      • [SPARK-658] - Added in missing emoticons.
      • -
      • [SPARK-660] - Emoticon packs can now be unzipped without admin rights.
      • -
      • [SPARK-668] - Fixed issue where first message would be dropped.
      • -
      • [SPARK-673] - Fixed logic with update checker and beta/alpha releases.
      • -
      • [SPARK-681] - Spark now closes a Jingle Session if it establish and don't receive media for more than X(20) seconds
      • -
      • [SPARK-689] - Fixed jingle binding issue on Vista.
      • -
      - -

      2.5.0 -- March 30th, 2007

      - -

      New Features

      -
        -
      • [SPARK-2] - Now show status of offline users.
      • -
      • [SPARK-382] - Added ctrl+e to display last 10 conversations.
      • -
      • [SPARK-410] - Now all plugins to be operating-system specific
      • -
      • [SPARK-559] - Refactored ContactList, ContactGroup and ContactItem to allow all event operations to run through the ContactList itself.
      • -
      • [SPARK-561] - Added new tray notification for incoming fastpath chat requests.
      • -
      • [SPARK-567] - Added Pack200 support to lower the overall deployment size of Spark.
      • -
      • [SPARK-568] - Added typing notification for Fastpath Conference chats.
      • -
      • [SPARK-571] - Added client to client VOIP support.
      • -
      • [SPARK-255] - Added drag and drop contacts into conference rooms to invite.
      • -
      • [SPARK-452] - Added IRC-Style Shortcuts
      • -
      • [SPARK-200] - Allow drag and drop out of the chat window before and after file transfer
      • -
      • [SPARK-517] - Simplified the viewing of users vCard information.
      • -
      • [SPARK-519] - Bookmarks are now located in the Spark main window menu bar.
      • -
      • [SPARK-515] - Spark now has an Enhanced Look and Feel.
      • -
      • [SPARK-518] - Added new auto-grow send field box.
      • -
      • [SPARK-523] - Added support for chat and email options in contact tooltips.
      • -
      • [SPARK-524] - Spark now shows full address of conference room.
      • -
      • [SPARK-528] - Message history is now grouped by Day, Month, Year.
      • -
      • [SPARK-531] - Added the new "Buzz" feature, which allows users to give others a little nudge.
      • -
      • [SPARK-485] - Added preference to specify tabs on top or bottom of Chat Room.
      • -
      • [SPARK-562] - Added Workgroup to Workgroup transfer.
      • -
      • [SPARK-563] - Added in Queue To Queue transfer.
      • -
      • [SPARK-610] - Added OSX dock notification with new incoming messages.
      • -
      - -

      Bug Fixes

      -
        -
      • [SPARK-453] - Linux distribution no longer depends on the windows dir.
      • -
      • [SPARK-471] - Fixed presence issue inside chat rooms.
      • -
      • [SPARK-510] - Conference Invitation page needs UI improvements.
      • -
      • [SPARK-551] - Handle gateway jids and adding of gateway users more gracefully.
      • -
      • [SPARK-552] - Added new error handling UI for Soft Phone.
      • -
      • [SPARK-553] - Presence now changes back to normal presence when hanging up phone call.
      • -
      • [SPARK-554] - Opening of a chat room now hides contact tooltip.
      • -
      • [SPARK-555] - Usernames with escapeable characters are now handled correctly in history.
      • -
      • [SPARK-556] - VCardManager now caches invalid vCards to prevent network abuse.
      • -
      • [SPARK-557] - Soft Phone only loads vCards if the user is registered.
      • -
      • [SPARK-558] - IRC-Style Shortcuts are now displayed in history.
      • -
      • [SPARK-565] - Users are now notified that they need to reconnect to a conference room when disconnected.
      • -
      • [SPARK-314] - Fixed Apple-W to close a chat tab/window.
      • -
      • [SPARK-376] - Fixed problem with usernames with characters like \ / : * ? " < > | in their name.
      • -
      • [SPARK-455] - Fixed auto away issue on linux.
      • -
      • [SPARK-456] - Fix issue with links in send area.
      • -
      • [SPARK-463] - Fixed issue with spaces in gateway contact names.
      • -
      • [SPARK-472] - Fixed double messages with broadcasts.
      • -
      • [SPARK-478] - Fixed issue with losing conference invitations after Spark reconnects.
      • -
      • [SPARK-481] - Fixed reconnect issue with idle.
      • -
      • [SPARK-486] - Timestamps are no correct when running on Vista.
      • -
      • [SPARK-487] - Users can now send screen shots when running Spark on Vista
      • -
      • [SPARK-488] - Fixed file transfer on Vista
      • -
      • [SPARK-500] - Fixed gateway presence change when user is disconnected causes Spark crash.
      • -
      • [SPARK-501] - Fixed Ctrl+F issue on OSX.
      • -
      • [SPARK-502] - Turned off DTD validation in EmoticonManager.
      • -
      • [SPARK-503] - Fixed grin emoticon not showing issue.
      • -
      • [SPARK-509] - Fixed multiple presences being sent issue on VCard change.
      • -
      • [SPARK-511] - No longer put users in invalid conference room.
      • -
      • [SPARK-532] - Spark now alert users when there is no program associated with a file a user is trying to open after File Transfer.
      • -
      • [SPARK-534] - Linux build is no longer corrupted.
      • -
      • [SPARK-535] - Spark no longer validates DTD for Emoticons.plist.
      • -
      • [SPARK-536] - MSI files now contain the Spark.exe file.
      • -
      • [SPARK-537] - Added a universal binary of the JavaApplicationStub for Spark.
      • -
      • [SPARK-538] - Fastpath auto-logs in after disconnect.
      • -
      • [SPARK-540] - Improved error message on login failure.
      • -
      • [SPARK-542] - HTTPS Proxy is now working.
      • -
      • [SPARK-543] - Notifications can now be disabled.
      • -
      • [SPARK-544] - Roster window shows nickname option if specified in Profile.
      • -
      • [SPARK-545] - Clearing avatar takes immeditate effect.
      • -
      • [SPARK-546] - Chat History now shows approriate nicknmes when possible.
      • -
      • [SPARK-549] - [Mac] Starting new conversations no longer fails to bring the message window to the front
      • -
      • [SPARK-550] - Fixed notification issue with tray popups and bring to front.
      • -
      • [SPARK-497] - Fixed "Away due to idle" on/off preference issue.
      • -
      • [SPARK-499] - Fixed error occuring when choosing invalid emoticon packs.
      • -
      • [SPARK-505] - Fixed loading of cached vcard when editing personal profile.
      • -
      • [SPARK-508] - Conference rooms jids are now escaped.
      • -
      • [SPARK-513] - Fixed inconsistent behavior in tab notifications.
      • -
      • [SPARK-514] - Fixed loading of file chooser in avatar panel.
      • -
      • [SPARK-516] - Spark now uses default look and feel when running on Windows Vista.
      • -
      • [SPARK-520] - Fixed hanging of Spark when adding new contacts.
      • -
      • [SPARK-521] - Group chat rooms now ignore presences with type error.
      • -
      • [SPARK-522] - Tabs within Spark are now easier to determine active/inactive.
      • -
      • [SPARK-525] - Spark no longer persists password if user requests password to not be saved.
      • -
      • [SPARK-526] - Fixed "Join on startup" in Conference room tab.
      • -
      • [SPARK-527] - Auto-joined rooms now display spell-checker and emoticon picklist.
      • -
      • [SPARK-529] - Conference invitation dialog now shows names in alphabetical order along with their presence.
      • -
      • [SPARK-235] - Spark now supports Adium emoticon packs.
      • -
      • [SPARK-390] - Fixed presence issue caused by installed gateways.
      • -
      • [SPARK-405] - Conference bookmarks are now persisted on the server.
      • -
      • [SPARK-420] - Fixed window repainting on tab transitions.
      • -
      • [SPARK-424] - Fixed contact list error occuring on reconnect.
      • -
      • [SPARK-427] - Spark now allows for actions to occur on tooltips.
      • -
      • [SPARK-473] - Fixed presence issue in group chat rooms.
      • -
      • [SPARK-483] - Update logic in show/away actions on tray icon.
      • -
      • [SPARK-484] - Auto Login into conference rooms causes chat room buttons to not appear.
      • -
      • [SPARK-491] - Bookmarks are now persisted to the server.
      • -
      • [SPARK-492] - Spark now defaults presence priority to 1 rather than 0.
      • -
      • [SPARK-493] - Chat history broken
      • -
      • [SPARK-494] - Transcripts were being corrupted when persisting Unicode.
      • -
      • [SPARK-506] - Fixed send field resize issue when chat frame was resized.
      • -
      • [SPARK-507] - Fixed asterisks plugin. Asterisks is now fully functional.
      • -
      • [SPARK-530] - Improved performance of loading and persisting of transcripts.
      • - - -
      • [SPARK-569] - Jingle doesn't detect when other client supports Jingle
      • -
      • [SPARK-574] - Workgroup now accepts AgentSession status change.
      • -
      • [SPARK-576] - Typing in chat window disabled after re-connect
      • -
      • [SPARK-577] - Fixed softphone issue when preferecnes could not be loaded.
      • -
      • [SPARK-578] - Available Contacts does not display properly in OSX.
      • -
      • [SPARK-579] - Jingle UI will now show regardless of volume control settings.
      • -
      • [SPARK-580] - MSI build now uses pack200 builds.
      • -
      • [SPARK-582] - Growl notifications in OSX are now working properly.
      • -
      • [SPARK-583] - Fixed Typing notification in ContactList
      • -
      • [SPARK-584] - Ctrl-x and cut now work correctly in send area.
      • -
      • [SPARK-585] - Fixed VCard viewer close button issue.
      • -
      • [SPARK-587] - Update file pickers within Spark
      • -
      • [SPARK-588] - Window controls will not go away
      • -
      • [SPARK-589] - Fixed issue with fastpath tabs turning red without having any new messages.
      • -
      • [SPARK-590] - Fixed layout setting of chat window.
      • -
      • [SPARK-591] - Disconnected spark no longer attempts online activities.
      • -
      • [SPARK-592] - Fixed stale chats.
      • -
      • [SPARK-593] - Updated ringing sound file.
      • -
      • [SPARK-594] - Added notification in Jingle rooms when negotiating call.
      • -
      • [SPARK-595] - Fixed SIP Regsitration on computers with VMWare.
      • -
      • [SPARK-596] - Removed contact info options in tooltip.
      • -
      • [SPARK-597] - Added new icon to represent Jingle calls.
      • -
      • [SPARK-599] - Gateways are no longer loaded on the event thread.
      • -
      • [SPARK-600] - Broadcast button in wrong place
      • -
      • [SPARK-601] - Ending SIP calls does not work properly
      • -
      • [SPARK-602] - Last activity on unsupported clients is handled more gracefully.
      • -
      • [SPARK-603] - SIP: Caller ID missing from incoming call notification
      • -
      • [SPARK-604] - SIP: wrong icon in missed calls list
      • -
      • [SPARK-605] - SIP: two bugs in call history
      • -
      • [SPARK-606] - SIP: escape button doesn't work on dedicated call tab
      • -
      • [SPARK-607] - SIP: voicemail button should always show number of messages
      • -
      • [SPARK-611] - Fixed layout of command buttons on OSX.
      • -
      • [SPARK-612] - Spark now displays notifications from Gateways.
      • -
      • [SPARK-613] - Gateway icons now display disconnection from gateways.
      • -
      • [SPARK-614] - Fixed issue with reconnection.
      • -
      • [SPARK-616] - Fixed issue with redial in Soft Phone.
      • -
      • [SPARK-617] - Send correct presence upon reconnection.,
      • -
      • [SPARK-618] - Fixed multiple message issue with Broadcast.
      • -
      • [SPARK-620] - Mute does not work
      • -
      • [SPARK-621] - Clicking on a user's avatar, then view full profile brings up "edit profile information"
      • -
      • [SPARK-622] - Error at reconnection - no users are connected
      • -
      • [SPARK-628] - No room found answering a SIP call
      • -
      • [SPARK-629] - Fixed incoming Jingle call ui when user has no vcard.
      • -
      • [SPARK-630] - Updated Spark message icon.
      • -
      • [SPARK-641] - Fix User Home Directory in Linux to ".Spark"
      • -
      • [SPARK-646] - SIP Previous Conversations List is in reverse order
      • -
      - - -

      2.0.8 -- January 23rd, 2007

      - -

      New Features

      -
        -
      • [SPARK-462] - Added notification preferences for user presence.
      • -
      -

      Bug Fixes

      -
        -
      • [SPARK-449] - Fix chat transcript parsing error with UTF-8
      • -
      • [SPARK-450] - Fixed tab refreshing problem.
      • -
      • [SPARK-460] - Remove old icons from group chat room.
      • -
      • [SPARK-461] - Improved Toaster popup UI
      • -
      • [SPARK-465] - Conference Participant list becomes corrupted on presence changes.
      • -
      • [SPARK-468] - Logging out with Chat windows open does not save chat transcript.
      • -
      • [SPARK-469] - Spark needs to do update checks against the new Ignite site.
      • -
      • [SPARK-470] - VCard loading for email chat info should not be in own thread.
      • -
      • [SPARK-475] - Spark 2.0.8 custom skin w/ wildfire spark version set, always thinks there's a newer version
      • -
      • [SPARK-476] - Asterisks plugin is fully functional.
      • -
      • [SPARK-477] - Users are being removed from the participant list on presence change.
      • -
      • [SPARK-479] - VCard caching not updating avatar.
      • -
      • [SPARK-480] - Stale chats logic removes incoming message notification.
      • -
      - -

      2.0.7 -- December 4th, 2006

      - -

      New Features

      -
        -
      • [SPARK-444] - Added one-click hide from system tray.
      • -
      • [SPARK-445] - Added simple log viewer.
      • -
      • [SPARK-447] - Added Typing notification to individual tabs and Frame.
      • -
      • [SPARK-398] - Nicknames should be sortable in group chat rooms.
      • -
      -

      Bug Fixes

      -
        -
      • [SPARK-428] - Fixed issue with removing start on startup in preferences.
      • -
      • [SPARK-435] - Setting presence to DND works correctly.
      • -
      • [SPARK-436] - Verify new JID escaping with transports works correctly.
      • -
      • [SPARK-437] - Auto reconnect to notify each connection manager to reset themselves.
      • -
      • [SPARK-438] - Rooms need to be active when Reconnection was successfull
      • -
      • [SPARK-439] - Yahoo! Logo shows up in vcard popup for offline users
      • -
      • [SPARK-440] - No longer sending presence to Gateway if not signed in.
      • -
      • [SPARK-441] - Chat room send field no longer becomes disabled.
      • -
      • [SPARK-442] - Logging out causes temporary blank spark to appear.
      • -
      • [SPARK-443] - The Translator plug-in does not work
      • -
      • [SPARK-446] - No longer show toast popups when a message has an error.
      • -
      - - -

      2.0.6 -- November 20, 2006

      - -

      Bug Fixes

      -
        -
      • [SPARK-414] - Added Grabber icon to the bottom right of each frame.
      • -
      • [SPARK-415] - Removed background from JButtons for better UI on OSX.
      • -
      • [SPARK-416] - Replaced old icon for menu tray.
      • -
      • [SPARK-418] - Improved upon Members Only Group Chats.
      • -
      • [SPARK-419] - Fixed MSI build.
      • -
      • [SPARK-425] - Creating account with in-band registration caused NPE in spark.
      • -
      • [SPARK-426] - Improve compatibility with GTalk.
      • -
      • [SPARK-428] - Fixed issue with removing start on startup in preferences.
      • -
      • [SPARK-429] - Improved Gateway tooltips.
      • -
      • [SPARK-430] - MSN roster invites work.
      • -
      • [SPARK-432] - Adding new users will not offer gateway if the user is not from an external system.
      • -
      • [SPARK-433] - Fixed lost message issue with GTalk users.
      • -
      • [SPARK-353] - Improved upon conference invitations.
      • -
      - -

      2.0.5 -- October 30, 2006

      - -

      New Features

      -
        -
      • [SPARK-358] - Added a beta version of the MSI installer.
      • -
      • [SPARK-402] - Added ability to add new contacts through transports.
      • -
      -

      Bug Fixes

      -
        -
      • [SPARK-393] - Fixed blank tab on MAC OSX when presence changed.
      • -
      • [SPARK-400] - Spark now checks for available real estate on monitor.
      • -
      • [SPARK-403] - Fixed private chats in group chat rooms.
      • -
      - - -

      2.0.4 -- October 18, 2006

      - -

      Bug Fixes

      -
        -
      • [SPARK-394] - Fixed user search.
      • -
      • [SPARK-395] - Fixed issue with broadcasts.
      • -
      • [SPARK-396] - Auto discovery is now working with SRV lookup.
      • -
      • [SPARK-397] - Fixed some minor issues with group chat rooms.
      • -
      - -

      2.0.3 -- October 11, 2006

      - -

      New Features

      -
        -
      • [SPARK-364] - Added French translation to Spark.
      • -
      • [SPARK-385] - Added Italian translation to Spark.
      • -
      • [SPARK-386] - Added Dutch translation to Spark.
      • -
      -

      Bug Fixes

      -
        -
      • [SPARK-379] - Fixed exception that occured when services could be loaded from the server.
      • -
      • [SPARK-383] - Gateway information is now based on disco and not the subdomain name.
      • -
      • [SPARK-387] - Fixed disconnect on illegal error packet.
      • -
      • [SPARK-388] - Fixed flaky gateway detection in contact list
      • -
      • [SPARK-392] - Fixed removal of sames user in multiple rooms.
      • -
      - - -

      2.0.2 -- September 28, 2006

      - -

      New Features

      -
        -
      • [SPARK-363] - Added screen selection capability to the screenshot feature.
      • -
      • [SPARK-356] - Added German translation to Spark.
      • -
      • [SPARK-359] - Updated icons and text in Spark to reflect functionallity better.
      • -
      • [SPARK-370] - Added sound preference for incoming chat invitations.
      • -
      • [SPARK-374] - Improved message notifications using sounds and toasters.
      • -
      - -

      Bug Fixes

      -
        -
      • [SPARK-357] - Spark Manager now handles the online spark distribution correctly.
      • -
      • [SPARK-360] - Added missing i18n properties.
      • -
      • [SPARK-361] - Fixed case where users were showing up as offline when they are online.
      • -
      • [SPARK-362] - Allow passwords with leading and trailing spaces.
      • -
      • [SPARK-365] - File transfers through a proxy no longer fails.
      • -
      • [SPARK-366] - Show login failure when Spark is in the system tray and login fails.
      • -
      • [SPARK-367] - Spark can now run with limited operating system permissions.
      • -
      • [SPARK-368] - Fixed error with wildcard searchs.
      • -
      • [SPARK-369] - Fixed connection issue with Facetime and Akonix.
      • -
      • [SPARK-371] - Added back ctrl+n (now ctrl+f) for user searching within contact list and chat window.
      • -
      - - -

      2.0.1 -- September 11, 2006

      - -

      New Features

      -
        -
      • [SPARK-350] - Added icons and registration for ICQ gateways.
      • -
      - -

      Bug Fixes

      -
        -
      • [SPARK-341] - Changed online installer to require JRE 1.5.
      • -
      • [SPARK-342] - Spark will not start if the language settings do not match i18n.
      • -
      • [SPARK-343] - Spark handles upgrades with the online tag.
      • -
      • [SPARK-344] - Fixed invalid paths with sound preference.
      • -
      • [SPARK-345] - XMPP URI mapping now registers correctly with the registry.
      • -
      • [SPARK-346] - Search no longer crashes in Spark
      • -
      • [SPARK-347] - Fixed multiple presence packets being sent on idle.
      • -
      • [SPARK-348] - Gateway plugin now checks the server on separate thread.
      • -
      • [SPARK-351] - Changed Spark to use default look and feel on OSX.
      • -
      • [SPARK-352] - Display correct message on uninstalls of plugins in the plugin viewer.
      • -
      - -

      2.0.0 -- September 7, 2006

      - -

      New Features

      -
        -
      • Initial release as an Open Source project!
      • -
      • [SPARK-5] - Added resource bundle support so that Spark can support translations.
      • -
      • [SPARK-28] - Added ability to send a file transfer to an offline contact (file is sent when they become available).
      • -
      • [SPARK-45] - Added support for storing group chat bookmarks (JEP-0048).
      • -
      • [SPARK-78] - Improved tab management.
      • -
      • [SPARK-162] - Improved UI of chat history when opening window.
      • -
      • [SPARK-169] - Spark now stacks chat tabs instead of scrolling them.
      • -
      • [SPARK-177] - Added XMPP URI Mapping to Spark
      • -
      • [SPARK-181] - Improved the Mac installer.
      • -
      • [SPARK-290] - Added ability to resend files when transfer fails.
      • -
      • [SPARK-291] - Add file transfer timeout setting to preferences.
      • -
      • [SPARK-292] - starting conversations with "user" (not really a JID) is possible, Spark could attach "@server.com" to make it - "user@server" -
      • -
      • [SPARK-298] - Presence updates now show timestamp.
      • -
      • [SPARK-299] - Incremental scroll units should be moved to 150 instead of 50.
      • -
      • [SPARK-302] - Added nested groups support.
      • -
      • [SPARK-314] - Apple-W now closes a chat tab/window on Mac.
      • -
      • [SPARK-315] - Improved Growl support on Mac.
      • -
      • [SPARK-324] - It's now possible to logout with a reason.
      • -
      • [SPARK-330] - The preferences dialog is no longer modal.
      • -
      • [SPARK-332] - Added activity monitoring for users typing, going offline and online to contact list.
      • -
      • [SPARK-333] - Added support for gateways.
      • -
      • [SPARK-335] - Added new notification preferences.
      • -
      - -

      Bug Fixes

      -
        -
      • [SPARK-14] - Spark no longer unchecks the auto-login feature on disconnects.
      • -
      • [SPARK-88] - The update process now checks to see if the update is already downloaded (in case the user never restarted Spark). -
      • -
      • [SPARK-101] - The chat window now has proper Mac OS X menus.
      • -
      • [SPARK-208] - Allow VM params to be set for graphics rendering options.
      • -
      • [SPARK-218] - Non-English characters were noe displayed correctly in vCards.
      • -
      • [SPARK-221] - Sparkplugs were not "sticking" after restart on the Mac.
      • -
      • [SPARK-238] - Setting download directory in Spark is now persisted on logout.
      • -
      • [SPARK-240] - Some commands should not be offered for workgroups in roster.
      • -
      • [SPARK-245] - 0 byte files were crashing Spark.
      • -
      • [SPARK-253] - GroupChatRoomInfo needs to support DBCS.
      • -
      • [SPARK-279] - Special characters in the away message could crash Spark.
      • -
      • [SPARK-280] - Spark was not showing avatars created in Google.
      • -
      • [SPARK-281] - Conference button hidden in chat room toolbar.
      • -
      • [SPARK-282] - Broadcast message functionallity is now dictated by the broadcast plugin in spark.
      • -
      • [SPARK-283] - In some cases, Spark was not starting due to an exception in Tray handling.
      • -
      • [SPARK-285] - The link-2-text filter was not matching all URL's correctly.
      • -
      • [SPARK-288] - Spark was ignoring error messages in certain cases.
      • -
      • [SPARK-293] - Cancel of Spark Manager download does was actually closing the input stream.
      • -
      • [SPARK-294] - Improved logic around avatar handling.
      • -
      • [SPARK-297] - Mac/Linux - conference invites were never received.
      • -
      • [SPARK-300] - Unsubscribe packet was triggering unsubscribe response.
      • -
      • [SPARK-301] - Offline messages were not saved in transcript history.
      • -
      • [SPARK-303] - Fixed memory leak in ChatRoom.
      • -
      • [SPARK-304] - Added chat history to the chat room window.
      • -
      • [SPARK-305] - Added a preference option to specify a download folder.
      • -
      • [SPARK-306] - The text ": - )" now shows a smiley.
      • -
      • [SPARK-317] - Fixed error when loading user history.
      • -
      • [SPARK-318] - Added a way to specify cleanly that a Sparkplug will fail when Spark API changes.
      • -
      • [SPARK-321] - Pending Presence subscription from other users were not showing up in Spark.
      • -
      • [SPARK-322] - Fixed error retrieving vCards from dJabberd
      • -
      • [SPARK-323] - The auto-away feature now changes presence priority to 0.
      • -
      • [SPARK-326] - Double clicking on a user search result was not starting a chat conversation.
      • -
      • [SPARK-328] - Fixed bug where Spark wouldn't start due to bad proxy config.
      • -
      • [SPARK-331] - Message of type HEADLINE can now popup as a toaster.
      • -
      - - - - -
      -
      - - - diff --git a/documentation/spark guide/Spark.default.properties.guide.html b/documentation/spark guide/Spark.default.properties.guide.html deleted file mode 100644 index 1de8bb301..000000000 --- a/documentation/spark guide/Spark.default.properties.guide.html +++ /dev/null @@ -1,1635 +0,0 @@ - - - - - - - - - - - - -Spark default - - - - - - - - - -
      - -

      Spark -default.properties set up guide

      - -

      @author Wolf.Posdorfer

      - -

       

      - -

      To fully -configure your default.properties -file you can follow this small guide.

      - -

      The -default.properties are located at:

      - -

      a)   In your source folder under -spark/trunk/src/java/org/jivesoftware/resource/default.properties

      - -

      b)   By editing the spark.jar in your -installation folder. Go to C:/Programs/Spark/lib/spark.jar and open it with any -Archive-program (like 7z). Then navigate to -spark.jar/org/jivesoftware/resource/default.properties

      - -

      Now you -will simply have to open it with any TextEditor, modify it and save it. If -you're using method b, your archive-program will ask you to repack, please do so. You can then copy this file into any other installation of Spark. You should note that spark.jar will be overwritten with a subsequent Spark upgrade and all custom settings will be lost. So one should edit spark.jar and redistribute it to all the clients after every new Spark version release.

      - -

      -

      Items -crossed with red markers are Items that become invisible or disabled when -setting a specific option.

      - -

       

      - -

       

      - -

      # Specify a -fixed Hostname

      - -

      # Changing the -Hostname will also be prohibited if set

      - -

      HOST_NAME = -test.lol.com

      - -

      - -

      # Proxy Settings

      - -

      # Protocols are -HTTP or SOCKS , case sensitive!!!

      - -

      PROXY_PROTOCOL = SOCKS

      - -

      PROXY_HOST = myProxy.com

      - -

      PROXY_PORT = 8080

      - -

      - -

       

      - -

      # Remove account -creation Button from Loginwindow

      - -

      # Users wont be able to register new Accounts from within Spark

      - -

      ACCOUNT_DISABLED = -true

      - -

      # Remove -Advanced Configuration Button from Loginwindow

      - -

      # Users wont be able to access the advanced configuration

      - -

      ADVANCED_DISABLED = true

      - -

      - -
      -
      - -

       

      - -

      # Branding only

      - -

      # Branded images -appear in the Top-Right corner, and must be included in the classpath

      - -

      # place them in src/resource/images and path will be -"images/file.jpg"

      - -

      # BRANDED_IMAGE -= images/my-corporation-logo.png

      - -

      BRANDED_IMAGE = images/colors.png

      - -

       

      - -

       

      - -

      # Disables -updateability, you should set this, if you have a custom Spark-build

      - -

      # or are in an environment where installfiles are distributed -via network

      - -

      DISABLE_UPDATES = true

      - -

      - -

       

      - -

      # If true, Spark -cannot shut down

      - -

      # users wont be able to shut down Spark

      - -

      DISABLE_EXIT = true

      - -

           

      - -

       

      - -

      #################################################

      - -

      ################## -File Transfer ################

      - -

      #################################################

      - -

       

      - -

      # Specify a size(in bytes) on which Users will get a

      - -

      # warning of a possibly too big file

      - -

      FILE_TRANSFER_WARNING_SIZE -= 1024    FILE_TRANSFER_MAXIMUM_SIZE -= 10048

      - -

      - -

       

      - -

      # Disables -adding of contacts

      - -

      # The User wont be able to add contacts,

      - -

      # usefull for shared roster management

      - -

      ADD_CONTACT_DISABLED = true

      - -

      - -

       

      - -

      # Disables -adding contact groups

      - -

      # The User wont be able to add contact groups,

      - -

      # usefull for shared roster management

      - -

      ADD_CONTACT_GROUP_DISABLED -= true

      - -

      - -

      # Sets the -Location of the Userguide

      - -

      #Default is -http://www.igniterealtime.org/builds/spark/docs/spark_user_guide.pdf

      - -

      HELP_USER_GUIDE = http://www.igniterealtime.org/builds/spark/docs/spark_user_guide.pdf

      - -

      # Set to true, -if you dont want this displayed

      - -

      HELP_USER_GUIDE_DISABLED -=

      - -

      # Sets the -Location of the Help-Forum

      - -

      #Default is -http://www.igniterealtime.org/forum/forum.jspa?forumID=49

      - -

      HELP_FORUM = http://www.igniterealtime.org/forum/forum.jspa?forumID=49

      - -

      # Set to true, -if you dont want this displayed

      - -

      HELP_FORUM_DISABLED -=

      - -

      # Following Text -will be displayed instead of "Spark forum"

      - -

      # leave blank for default

      - -

      HELP_FORUM_TEXT = My Own Forum

      - -

      - -

       

      - -

       

      - -

       

      - -

       

      - -

       

      - -

       

      - -

       

      - -

      # Disable -Installing of Plugins

      - -

      # set true if you want to disable installing of Plugins

      - -

      INSTALL_PLUGINS_DISABLED -= true

      - -

      # Disable -deleting of Plugins

      - -

      # set true if you want to disable deinstalling of Plugins

      - -

      DEINSTALL_PLUGINS_DISABLED = true

      - -

      - -

      # Put plugins -here that you dont want enabled

      - -

      # comma separated, case insensitive

      - -

      # names of plugins can be found in the plugin.xml

      - -

      # example: Fastpath,Jingle Client,Phone Client,Window Flashing -Plugin

      - -

      # default is empty

      - -

      PLUGIN_BLACKLIST = -Fastpath

      - -

      # Disable -Plugins by entrypoint Class

      - -

      # Comma -separated, case sensitive

      - -

      # example org.jivesoftware.fastpath.FastpathPlugin

      - -

      PLUGIN_BLACKLIST_CLASS -= org.jivesoftware.spark.translator.TranslatorPlugin

      - -

      This will disable -all Plugins with <name>Fastpath</name> and all plugins with -<class>org.jivesoftware.spark.translator.TranslatorPlugin</class>

      - -

      The appropriate -Names or Classes can be found in the plugin.xml within the plugin.jar

      - -

       

      - -

      # by Default Server-Broadcast get their own JFrame containing -the Message

      - -

      # also HTML tags like <b> <i> <u> can be -used

      - -

      # if you want server broadcasts handled like every other -message including transcripts

      - -

      # set this to true

      - -

      BROADCAST_IN_CHATWINDOW -= true            BROADCAST_IN_CHATWINDOW -= false

      - -

      - -

       

      - -

       

      - -

       

      - -

       

      - -

       

      - -

       

      - -

      # Disable -Look&Feel change || "true" = disabled ,  anything else = enabled

      - -

      # By Default the -user can Change his Look&Feel in the Preferences Menu,

      - -

      #if you dont want this then set it to true

      - -

      # Preferences --> Appearence -> Customization Tab

      - -

      LOOK_AND_FEEL_DISABLED -= true

      - -

      # Disable if you -dont want Users to be able to Change the Textcolors in the Preference Menu

      - -

      # the colors will be loaded from below

      - -

      # Preferences -> Appearence -> -ColorTab

      - -

      CHANGE_COLORS_DISABLED = true

      - -

       

      - -

      - -

       

      - -

       

      - -

      # Changes the -Default Look&Feel, if empty it will load the SystemSkin

      - -

      # Default Spark -skin is SubstanceBusinessBlueSteelLookAndFeel

      - -

      DEFAULT_LOOK_AND_FEEL -= com.jtattoo.plaf.luna.LunaLookAndFeel

      - -

      # Default Spark -skin for Mac is empty. This will load the OSX Look&Feel

      - -

      DEFAULT_LOOK_AND_FEEL_MAC -=

      - -

       

      - -

      # in JTatto Menubars can have Texts, default is empty

      - -

      This only works if a JTattoo Look&Feel is -selected!!!

      - -

      MENUBAR_TEXT = HelloWorld

      - -

      - -

       

      - -

       

      - -

      Look and Feels -are:

      - -

      On Windows:

      - -

      javax.swing.plaf.metal.MetalLookAndFeel

      - -

      com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel

      - -

      com.sun.java.swing.plaf.motif.MotifLookAndFeel

      - -

      com.sun.java.swing.plaf.windows.WindowsLookAndFeel

      - -

      com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel

      - -

       

      - -

      On any System:

      - -

      com.jtattoo.plaf.acryl.AcrylLookAndFeel

      - -

      com.jtattoo.plaf.aero.AeroLookAndFeel

      - -

      com.jtattoo.plaf.aluminium.AluminiumLookAndFeel

      - -

      com.jtattoo.plaf.bernstein.BernsteinLookAndFeel

      - -

      com.jtattoo.plaf.fast.FastLookAndFeel

      - -

      com.jtattoo.plaf.graphite.GraphiteLookAndFeel

      - -

      com.jtattoo.plaf.hifi.HiFiLookAndFeel

      - -

      com.jtattoo.plaf.luna.LunaLookAndFeel

      - -

      com.jtattoo.plaf.mcwin.McWinLookAndFeel

      - -

      com.jtattoo.plaf.mint.MintLookAndFeel

      - -

      com.jtattoo.plaf.noire.NoireLookAndFeel

      - -

      com.jtattoo.plaf.smart.SmartLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceAutumnLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceBusinessBlackSteelLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceBusinessBlueSteelLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceBusinessLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceChallengerDeepLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceCremeCoffeeLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceCremeLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceDustCoffeeLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceDustLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceEmeraldDuskLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceMagmaLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceMistAquaLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceMistSilverLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceModerateLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceNebulaBrickWallLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceNebulaLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceOfficeBlue2007LookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceOfficeSilver2007LookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceRavenGraphiteGlassLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceRavenGraphiteLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceRavenLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceSaharaLookAndFeel

      - -

      org.jvnet.substance.skin.SubstanceTwilightLookAndFeel

      - -

      org.jvnet.substance.api.skin.SubstanceGeminiLookAndFeel

      - -

      org.jvnet.substance.api.skin.SubstanceGraphiteAquaLookAndFeel

      - -

      org.jvnet.substance.api.skin.SubstanceMagellanLookAndFeel

      - -
      - - - - diff --git a/documentation/spark guide/images/image033.png b/documentation/spark guide/images/image033.png deleted file mode 100644 index cd6aae8b1..000000000 Binary files a/documentation/spark guide/images/image033.png and /dev/null differ diff --git a/emoticons/pom.xml b/emoticons/pom.xml new file mode 100644 index 000000000..d97460cea --- /dev/null +++ b/emoticons/pom.xml @@ -0,0 +1,59 @@ + + + + + 4.0.0 + + + org.igniterealtime.spark + parent + 3.1.0-SNAPSHOT + + + emoticons + Spark Emoticons + Sets of emoticons used by Spark. + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + src/assembly/Default.adiumemoticonset.xml + src/assembly/GTalk.AdiumEmoticonset.xml + src/assembly/POPO.adiumemoticonset.xml + src/assembly/sparkEmoticonSet.xml + + + + + make-assembly + package + + single + + + + + + ../distribution/target/distribution-base/xtra/emoticons + + diff --git a/emoticons/src/assembly/Default.adiumemoticonset.xml b/emoticons/src/assembly/Default.adiumemoticonset.xml new file mode 100644 index 000000000..1d79ec1ad --- /dev/null +++ b/emoticons/src/assembly/Default.adiumemoticonset.xml @@ -0,0 +1,32 @@ + + + + Default.adiumemoticonset + + zip + + false + + + + ${project.basedir}/src/main/Default.adiumemoticonset + Default.adiumemoticonset + + + diff --git a/emoticons/src/assembly/GTalk.AdiumEmoticonset.xml b/emoticons/src/assembly/GTalk.AdiumEmoticonset.xml new file mode 100644 index 000000000..c27b1c546 --- /dev/null +++ b/emoticons/src/assembly/GTalk.AdiumEmoticonset.xml @@ -0,0 +1,32 @@ + + + + GTalk.AdiumEmoticonset + + zip + + false + + + + ${project.basedir}/src/main/GTalk.AdiumEmoticonset + GTalk.AdiumEmoticonset + + + diff --git a/emoticons/src/assembly/POPO.adiumemoticonset.xml b/emoticons/src/assembly/POPO.adiumemoticonset.xml new file mode 100644 index 000000000..b091caa17 --- /dev/null +++ b/emoticons/src/assembly/POPO.adiumemoticonset.xml @@ -0,0 +1,32 @@ + + + + POPO.adiumemoticonset + + zip + + false + + + + ${project.basedir}/src/main/POPO.adiumemoticonset + POPO.adiumemoticonset + + + diff --git a/emoticons/src/assembly/sparkEmoticonSet.xml b/emoticons/src/assembly/sparkEmoticonSet.xml new file mode 100644 index 000000000..eec499dce --- /dev/null +++ b/emoticons/src/assembly/sparkEmoticonSet.xml @@ -0,0 +1,32 @@ + + + + sparkEmoticonSet + + zip + + false + + + + ${project.basedir}/src/main/sparkEmoticonSet + sparkEmoticonSet + + + diff --git a/emoticons/src/main/Default.adiumemoticonset/Emoticons.plist b/emoticons/src/main/Default.adiumemoticonset/Emoticons.plist new file mode 100644 index 000000000..bb0b88657 --- /dev/null +++ b/emoticons/src/main/Default.adiumemoticonset/Emoticons.plist @@ -0,0 +1,237 @@ + + + + + SparkSetVersion + 1 + Emoticons + + angry.png + + Equivalents + + >:o + >:-o + >:O + >:-O + + Name + Angry + + blush.png + + Equivalents + + :-[ + + Name + Blush + + confused.png + + Equivalents + + ?:| + + Name + Confused + + cool.png + + Equivalents + + B-) + 😎 + + Name + Cool + + cry.png + + Equivalents + + :'( + + Name + Cry + + devil.png + + Equivalents + + ]:) + + Name + Devil + + grin.png + + Equivalents + + :-D + :D + 😄 + 😃 + 😂 + 😁 + 😀 + + Name + Grin + + happy.png + + Equivalents + + :-) + + Name + Happy + + laugh.png + + Equivalents + + :^0 + 😅 + 😆 + + Name + Laugh + + love.png + + Equivalents + + :x + 😍 + 😘 + + Name + Love + + mischief.png + + Equivalents + + ;\ + + Name + Mischief + + sad.png + + Equivalents + + :-( + :( + + + Name + Sad + + happy.png + + Equivalents + + :-) + :) + 😊 + 🙂 + + + Name + Smile + + plain.png + + Equivalents + + :| + + Name + Plain + + shocked.png + + Equivalents + + :0 + + Name + Shocked + + silly.png + + Equivalents + + :-p + :-P + :P + :p + 😋 + 😜 + 😝 + + Name + Tongue + + wink.png + + Equivalents + + ;-) + ;) + 😉 + + Name + Wink + + alert.png + + Equivalents + + (!) + + Name + Alert + + info.png + + Equivalents + + (i) + + Name + Info + + minus.png + + Equivalents + + (-) + + Name + Minus + + plus.png + + Equivalents + + (+) + + Name + Plus + + heart.png + + Equivalents + + (heart) + + Name + Heart + + + + diff --git a/emoticons/src/main/Default.adiumemoticonset/alert.png b/emoticons/src/main/Default.adiumemoticonset/alert.png new file mode 100644 index 000000000..722ddd609 Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/alert.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/angry.png b/emoticons/src/main/Default.adiumemoticonset/angry.png new file mode 100644 index 000000000..ba2be0eda Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/angry.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/blush.png b/emoticons/src/main/Default.adiumemoticonset/blush.png new file mode 100644 index 000000000..504e368ec Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/blush.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/confused.png b/emoticons/src/main/Default.adiumemoticonset/confused.png new file mode 100644 index 000000000..995e273a6 Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/confused.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/cool.png b/emoticons/src/main/Default.adiumemoticonset/cool.png new file mode 100644 index 000000000..25681c85e Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/cool.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/cry.png b/emoticons/src/main/Default.adiumemoticonset/cry.png new file mode 100644 index 000000000..0beaaa7cb Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/cry.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/devil.png b/emoticons/src/main/Default.adiumemoticonset/devil.png new file mode 100644 index 000000000..ca566bedb Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/devil.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/eyeRoll.png b/emoticons/src/main/Default.adiumemoticonset/eyeRoll.png new file mode 100644 index 000000000..57338d8b5 Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/eyeRoll.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/grin.png b/emoticons/src/main/Default.adiumemoticonset/grin.png new file mode 100644 index 000000000..602116dce Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/grin.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/happy.png b/emoticons/src/main/Default.adiumemoticonset/happy.png new file mode 100644 index 000000000..de07c0a58 Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/happy.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/heart.png b/emoticons/src/main/Default.adiumemoticonset/heart.png new file mode 100644 index 000000000..5dbccc74b Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/heart.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/info.png b/emoticons/src/main/Default.adiumemoticonset/info.png new file mode 100644 index 000000000..55c80687b Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/info.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/laugh.png b/emoticons/src/main/Default.adiumemoticonset/laugh.png new file mode 100644 index 000000000..0f673d11b Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/laugh.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/love.png b/emoticons/src/main/Default.adiumemoticonset/love.png new file mode 100644 index 000000000..e9f8e1db6 Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/love.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/minus.png b/emoticons/src/main/Default.adiumemoticonset/minus.png new file mode 100644 index 000000000..7f709712c Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/minus.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/mischief.png b/emoticons/src/main/Default.adiumemoticonset/mischief.png new file mode 100644 index 000000000..884269034 Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/mischief.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/party.png b/emoticons/src/main/Default.adiumemoticonset/party.png new file mode 100644 index 000000000..035adbec9 Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/party.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/plain.png b/emoticons/src/main/Default.adiumemoticonset/plain.png new file mode 100644 index 000000000..6f4a78ae0 Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/plain.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/plus.png b/emoticons/src/main/Default.adiumemoticonset/plus.png new file mode 100644 index 000000000..38febdd39 Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/plus.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/sad.png b/emoticons/src/main/Default.adiumemoticonset/sad.png new file mode 100644 index 000000000..5b7bc9207 Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/sad.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/shocked.png b/emoticons/src/main/Default.adiumemoticonset/shocked.png new file mode 100644 index 000000000..54dce70f8 Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/shocked.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/silly.png b/emoticons/src/main/Default.adiumemoticonset/silly.png new file mode 100644 index 000000000..ed02eca56 Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/silly.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/sleepy.png b/emoticons/src/main/Default.adiumemoticonset/sleepy.png new file mode 100644 index 000000000..48eb9c22d Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/sleepy.png differ diff --git a/emoticons/src/main/Default.adiumemoticonset/wink.png b/emoticons/src/main/Default.adiumemoticonset/wink.png new file mode 100644 index 000000000..eda88f7cd Binary files /dev/null and b/emoticons/src/main/Default.adiumemoticonset/wink.png differ diff --git a/emoticons/src/main/GTalk.AdiumEmoticonset/Emoticons.plist b/emoticons/src/main/GTalk.AdiumEmoticonset/Emoticons.plist new file mode 100644 index 000000000..46d00e4bc --- /dev/null +++ b/emoticons/src/main/GTalk.AdiumEmoticonset/Emoticons.plist @@ -0,0 +1,172 @@ + + + + + AdiumSetVersion + 1 + Emoticons + + angry.gif + + Equivalents + + X-( + X( + + Name + Angry Face + + shocked.gif + + Equivalents + + :-O + :-o + :O + :o + + Name + Shock + + cool.gif + + Equivalents + + B-) + B) + 😎 + + Name + Cool + + Cry.gif + + Equivalents + + :'( + + Name + Cry + + smile.gif + + Equivalents + + =) + :) + + 😊 + 🙂 + + Name + Smile + + rockout.gif + + Equivalents + + \m/ + + Name + Rockout + + Grin.gif + + Equivalents + + :D + =D + :'D + ='D + 😄 + 😃 + 😂 + 😁 + 😀 + 😅 + 😆 + + Name + Grin + + frown.gif + + Equivalents + + :( + =( + + + Name + Frown + + wink.gif + + Equivalents + + ;) + ;-) + 😉 + + Name + Wink + + tongue.gif + + Equivalents + + :P + :p + :-P + :-p + =P + =p + 😋 + 😜 + 😝 + + Name + Tongue + + straightface.gif + + Equivalents + + :-| + :| + + Name + Straight + + slant.gif + + Equivalents + + :-/ + :/ + + Name + Slant + + Monkey.gif + + Equivalents + + :(|) + (monkey) + + Name + Monkey + + Heart.gif + + Equivalents + + <3 + + Name + Heart + + + + diff --git a/emoticons/src/main/GTalk.AdiumEmoticonset/angry.gif b/emoticons/src/main/GTalk.AdiumEmoticonset/angry.gif new file mode 100644 index 000000000..8f5f8b379 Binary files /dev/null and b/emoticons/src/main/GTalk.AdiumEmoticonset/angry.gif differ diff --git a/emoticons/src/main/GTalk.AdiumEmoticonset/cool.gif b/emoticons/src/main/GTalk.AdiumEmoticonset/cool.gif new file mode 100644 index 000000000..4cc5c90a5 Binary files /dev/null and b/emoticons/src/main/GTalk.AdiumEmoticonset/cool.gif differ diff --git a/emoticons/src/main/GTalk.AdiumEmoticonset/cry.gif b/emoticons/src/main/GTalk.AdiumEmoticonset/cry.gif new file mode 100644 index 000000000..3da2d7b3b Binary files /dev/null and b/emoticons/src/main/GTalk.AdiumEmoticonset/cry.gif differ diff --git a/emoticons/src/main/GTalk.AdiumEmoticonset/frown.gif b/emoticons/src/main/GTalk.AdiumEmoticonset/frown.gif new file mode 100644 index 000000000..be497edd7 Binary files /dev/null and b/emoticons/src/main/GTalk.AdiumEmoticonset/frown.gif differ diff --git a/emoticons/src/main/GTalk.AdiumEmoticonset/grin.gif b/emoticons/src/main/GTalk.AdiumEmoticonset/grin.gif new file mode 100644 index 000000000..7d3d0b941 Binary files /dev/null and b/emoticons/src/main/GTalk.AdiumEmoticonset/grin.gif differ diff --git a/emoticons/src/main/GTalk.AdiumEmoticonset/heart.gif b/emoticons/src/main/GTalk.AdiumEmoticonset/heart.gif new file mode 100644 index 000000000..7b6ad4843 Binary files /dev/null and b/emoticons/src/main/GTalk.AdiumEmoticonset/heart.gif differ diff --git a/emoticons/src/main/GTalk.AdiumEmoticonset/monkey.gif b/emoticons/src/main/GTalk.AdiumEmoticonset/monkey.gif new file mode 100644 index 000000000..05228ce17 Binary files /dev/null and b/emoticons/src/main/GTalk.AdiumEmoticonset/monkey.gif differ diff --git a/emoticons/src/main/GTalk.AdiumEmoticonset/rockout.gif b/emoticons/src/main/GTalk.AdiumEmoticonset/rockout.gif new file mode 100644 index 000000000..d534028ea Binary files /dev/null and b/emoticons/src/main/GTalk.AdiumEmoticonset/rockout.gif differ diff --git a/emoticons/src/main/GTalk.AdiumEmoticonset/shocked.gif b/emoticons/src/main/GTalk.AdiumEmoticonset/shocked.gif new file mode 100644 index 000000000..7296d6c9a Binary files /dev/null and b/emoticons/src/main/GTalk.AdiumEmoticonset/shocked.gif differ diff --git a/emoticons/src/main/GTalk.AdiumEmoticonset/slant.gif b/emoticons/src/main/GTalk.AdiumEmoticonset/slant.gif new file mode 100644 index 000000000..cd7c5e2a6 Binary files /dev/null and b/emoticons/src/main/GTalk.AdiumEmoticonset/slant.gif differ diff --git a/emoticons/src/main/GTalk.AdiumEmoticonset/smile.gif b/emoticons/src/main/GTalk.AdiumEmoticonset/smile.gif new file mode 100644 index 000000000..b7f4ac646 Binary files /dev/null and b/emoticons/src/main/GTalk.AdiumEmoticonset/smile.gif differ diff --git a/emoticons/src/main/GTalk.AdiumEmoticonset/straightface.gif b/emoticons/src/main/GTalk.AdiumEmoticonset/straightface.gif new file mode 100644 index 000000000..07e25ac8b Binary files /dev/null and b/emoticons/src/main/GTalk.AdiumEmoticonset/straightface.gif differ diff --git a/emoticons/src/main/GTalk.AdiumEmoticonset/tongue.gif b/emoticons/src/main/GTalk.AdiumEmoticonset/tongue.gif new file mode 100644 index 000000000..810a58433 Binary files /dev/null and b/emoticons/src/main/GTalk.AdiumEmoticonset/tongue.gif differ diff --git a/emoticons/src/main/GTalk.AdiumEmoticonset/wink.gif b/emoticons/src/main/GTalk.AdiumEmoticonset/wink.gif new file mode 100644 index 000000000..8a5f56fe9 Binary files /dev/null and b/emoticons/src/main/GTalk.AdiumEmoticonset/wink.gif differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/.DS_Store b/emoticons/src/main/POPO.adiumemoticonset/.DS_Store similarity index 100% rename from src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/.DS_Store rename to emoticons/src/main/POPO.adiumemoticonset/.DS_Store diff --git a/emoticons/src/main/POPO.adiumemoticonset/Emoticons.plist b/emoticons/src/main/POPO.adiumemoticonset/Emoticons.plist new file mode 100644 index 000000000..80b38c60d --- /dev/null +++ b/emoticons/src/main/POPO.adiumemoticonset/Emoticons.plist @@ -0,0 +1,339 @@ + + + + + + AdiumSetVersion + 1 + Emoticons + + choler.png + + Equivalents + + >:o + :-@ + X( + + Name + Angry + + boss.png + + Equivalents + + 8-) + (H) + 😎 + B-) + + Name + Cool + + too_sad.png + + Equivalents + + :'( + :'-( + :(( + :-(( + + Name + Crying + + confuse.png + + Equivalents + + :-\ + :-S + + Name + Confused + + embarrassed.png + + Equivalents + + :-[ + :[ + :-$ + :"> + + Name + Embarassed + + beat_brick.png + + Equivalents + + :-! + + Name + Faux Pas + + sad.png + + Equivalents + + :-( + :( + + + Name + Frown + + big_smile.png + + Equivalents + + :-D + :D + 😄 + 😃 + 😂 + 😁 + 😀 + 😅 + 😆 + + Name + Grin + + adore.png + + Equivalents + + O:-) + O:) + o:-) + o:) + (A) + + Name + Innocent + + sweet_kiss.png + + Equivalents + + :-* + (K) + 😙 + 😘 + 😗 + 😚 + + Name + Kiss + + canny.png + + Equivalents + + :-x + :-X + :-# + + Name + Lips are Sealed + + smile.png + + Equivalents + + :-) + :) + 😊 + 🙂 + + + Name + Smile + + waaaht.png + + Equivalents + + =-o + =-O + + Name + Surprised + + amazed.png + + Equivalents + + :-| + + Name + Straight Face + + thbbbpt.png + + Equivalents + + :-P + :-p + :p + :P + 😋 + 😜 + 😝 + + Name + Sticking Out Tongue + + look_down.png + + Equivalents + + ;-) + ;) + 😉 + + Name + Wink + + tire.png + + Equivalents + + (:| + + Name + Yawn + + matrix.png + + Equivalents + + :neo: + :matrix: + + Name + Neo + + spidy.png + + Equivalents + + :spider-man: + :spidy: + + Name + Spider-Man + + hell_boy.png + + Equivalents + + :hellboy: + :evil: + :devil: + + Name + Hellboy + + doubt.png + + Equivalents + + :doubt: + + Name + Doubt + + sure.png + + Equivalents + + :sure: + + Name + Sure + + stilldreaming.png + + Equivalents + + :dreaming: + + Name + Dreaming + + hungry.png + + Equivalents + + :hungry: + + Name + Hungry + + oops.png + + Equivalents + + :oops: + :ops: + + Name + Oops + + ah.png + + Equivalents + + :ah: + :argh: + :scream: + + Name + Ah + + surrender.png + + Equivalents + + :surrender: + :giveup: + + Name + Surrender + + byebye.png + + Equivalents + + :bye: + :byebye: + + Name + Bye + + misdoubt.png + + Equivalents + + :misdoubt: + :suspect: + + Name + Misdoubt + + afterboom.png + + Equivalents + + :afterboom: + :boom: + + Name + Boom + + + + diff --git a/emoticons/src/main/POPO.adiumemoticonset/adore.png b/emoticons/src/main/POPO.adiumemoticonset/adore.png new file mode 100644 index 000000000..31756b1d8 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/adore.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/afterboom.png b/emoticons/src/main/POPO.adiumemoticonset/afterboom.png new file mode 100644 index 000000000..9f6f12bb2 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/afterboom.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/ah.png b/emoticons/src/main/POPO.adiumemoticonset/ah.png new file mode 100644 index 000000000..b3fcd497a Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/ah.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/amazed.png b/emoticons/src/main/POPO.adiumemoticonset/amazed.png new file mode 100644 index 000000000..a99d3e894 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/amazed.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/beat_brick.png b/emoticons/src/main/POPO.adiumemoticonset/beat_brick.png new file mode 100644 index 000000000..1c9169eee Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/beat_brick.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/big_smile.png b/emoticons/src/main/POPO.adiumemoticonset/big_smile.png new file mode 100644 index 000000000..8e4774d2d Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/big_smile.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/boss.png b/emoticons/src/main/POPO.adiumemoticonset/boss.png new file mode 100644 index 000000000..1ad0c9c4f Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/boss.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/byebye.png b/emoticons/src/main/POPO.adiumemoticonset/byebye.png new file mode 100644 index 000000000..68d0d4279 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/byebye.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/canny.png b/emoticons/src/main/POPO.adiumemoticonset/canny.png new file mode 100644 index 000000000..d7ac401dc Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/canny.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/choler.png b/emoticons/src/main/POPO.adiumemoticonset/choler.png new file mode 100644 index 000000000..e8a100017 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/choler.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/confuse.png b/emoticons/src/main/POPO.adiumemoticonset/confuse.png new file mode 100644 index 000000000..aad969eef Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/confuse.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/doubt.png b/emoticons/src/main/POPO.adiumemoticonset/doubt.png new file mode 100644 index 000000000..4707ae041 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/doubt.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/embarrassed.png b/emoticons/src/main/POPO.adiumemoticonset/embarrassed.png new file mode 100644 index 000000000..43878be62 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/embarrassed.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/hell_boy.png b/emoticons/src/main/POPO.adiumemoticonset/hell_boy.png new file mode 100644 index 000000000..fc5020794 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/hell_boy.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/hungry.png b/emoticons/src/main/POPO.adiumemoticonset/hungry.png new file mode 100644 index 000000000..41787f1f9 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/hungry.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/look_down.png b/emoticons/src/main/POPO.adiumemoticonset/look_down.png new file mode 100644 index 000000000..18b0f3eb1 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/look_down.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/matrix.png b/emoticons/src/main/POPO.adiumemoticonset/matrix.png new file mode 100644 index 000000000..39bb5fd1c Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/matrix.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/misdoubt.png b/emoticons/src/main/POPO.adiumemoticonset/misdoubt.png new file mode 100644 index 000000000..001a1ddfa Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/misdoubt.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/oops.png b/emoticons/src/main/POPO.adiumemoticonset/oops.png new file mode 100644 index 000000000..655edfb60 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/oops.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/sad.png b/emoticons/src/main/POPO.adiumemoticonset/sad.png new file mode 100644 index 000000000..eddfa8f03 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/sad.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/smile.png b/emoticons/src/main/POPO.adiumemoticonset/smile.png new file mode 100644 index 000000000..e0ba8c43a Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/smile.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/spidy.png b/emoticons/src/main/POPO.adiumemoticonset/spidy.png new file mode 100644 index 000000000..bea3063cb Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/spidy.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/stilldreaming.png b/emoticons/src/main/POPO.adiumemoticonset/stilldreaming.png new file mode 100644 index 000000000..7afe30cfc Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/stilldreaming.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/sure.png b/emoticons/src/main/POPO.adiumemoticonset/sure.png new file mode 100644 index 000000000..aa27614a4 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/sure.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/surrender.png b/emoticons/src/main/POPO.adiumemoticonset/surrender.png new file mode 100644 index 000000000..b70105e74 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/surrender.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/sweet_kiss.png b/emoticons/src/main/POPO.adiumemoticonset/sweet_kiss.png new file mode 100644 index 000000000..ae81cef46 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/sweet_kiss.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/thbbbpt.png b/emoticons/src/main/POPO.adiumemoticonset/thbbbpt.png new file mode 100644 index 000000000..afaf9558a Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/thbbbpt.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/tire.png b/emoticons/src/main/POPO.adiumemoticonset/tire.png new file mode 100644 index 000000000..9930253fd Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/tire.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/too_sad.png b/emoticons/src/main/POPO.adiumemoticonset/too_sad.png new file mode 100644 index 000000000..0feb0cec5 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/too_sad.png differ diff --git a/emoticons/src/main/POPO.adiumemoticonset/waaaht.png b/emoticons/src/main/POPO.adiumemoticonset/waaaht.png new file mode 100644 index 000000000..d611bc066 Binary files /dev/null and b/emoticons/src/main/POPO.adiumemoticonset/waaaht.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/Emoticons.plist b/emoticons/src/main/sparkEmoticonSet/Emoticons.plist new file mode 100644 index 000000000..9e3a69997 --- /dev/null +++ b/emoticons/src/main/sparkEmoticonSet/Emoticons.plist @@ -0,0 +1,242 @@ + + + + + SparkSetVersion + 1 + Emoticons + + angry.png + + Equivalents + + >:o + >:-o + >:O + >:-O + + Name + Angry + + blush.png + + Equivalents + + :-[ + + Name + Blush + + confused.png + + Equivalents + + ?:| + + Name + Confused + + cool.png + + Equivalents + + B-) + 😎 + + Name + Cool + + cry.png + + Equivalents + + :'( + + Name + Cry + + devil.png + + Equivalents + + ]:) + + Name + Devil + + grin.png + + Equivalents + + :-D + :D + 😄 + 😃 + 😂 + 😁 + 😀 + + Name + Grin + + happy.png + + Equivalents + + :-) + + Name + Happy + + laugh.png + + Equivalents + + :^0 + 😅 + 😆 + + Name + Laugh + + love.png + + Equivalents + + :x + 😍 + 😘 + + Name + Love + + mischief.png + + Equivalents + + ;\ + + Name + Mischief + + sad.png + + Equivalents + + :-( + :( + + + Name + Sad + + happy.png + + Equivalents + + :-) + :) + 😊 + 🙂 + + + Name + Smile + + plain.png + + Equivalents + + :| + + Name + Plain + + shocked.png + + Equivalents + + :0 + + Name + Shocked + + silly.png + + Equivalents + + :-p + :-P + :P + :p + 😋 + 😜 + 😝 + + Name + Tongue + + wink.png + + Equivalents + + ;-) + ;) + 😉 + + Name + Wink + + alert.png + + Equivalents + + (!) + + Name + Alert + + + + info.png + + Equivalents + + (i) + + Name + Info + + + minus.png + + Equivalents + + (-) + + Name + Minus + + + plus.png + + Equivalents + + (+) + + Name + Plus + + + heart.png + + Equivalents + + (heart) + + Name + Heart + + + + diff --git a/emoticons/src/main/sparkEmoticonSet/alert.png b/emoticons/src/main/sparkEmoticonSet/alert.png new file mode 100644 index 000000000..722ddd609 Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/alert.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/angry.png b/emoticons/src/main/sparkEmoticonSet/angry.png new file mode 100644 index 000000000..ba2be0eda Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/angry.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/blush.png b/emoticons/src/main/sparkEmoticonSet/blush.png new file mode 100644 index 000000000..504e368ec Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/blush.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/confused.png b/emoticons/src/main/sparkEmoticonSet/confused.png new file mode 100644 index 000000000..995e273a6 Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/confused.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/cool.png b/emoticons/src/main/sparkEmoticonSet/cool.png new file mode 100644 index 000000000..25681c85e Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/cool.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/cry.png b/emoticons/src/main/sparkEmoticonSet/cry.png new file mode 100644 index 000000000..0beaaa7cb Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/cry.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/devil.png b/emoticons/src/main/sparkEmoticonSet/devil.png new file mode 100644 index 000000000..ca566bedb Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/devil.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/eyeRoll.png b/emoticons/src/main/sparkEmoticonSet/eyeRoll.png new file mode 100644 index 000000000..57338d8b5 Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/eyeRoll.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/grin.png b/emoticons/src/main/sparkEmoticonSet/grin.png new file mode 100644 index 000000000..602116dce Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/grin.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/happy.png b/emoticons/src/main/sparkEmoticonSet/happy.png new file mode 100644 index 000000000..de07c0a58 Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/happy.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/heart.png b/emoticons/src/main/sparkEmoticonSet/heart.png new file mode 100644 index 000000000..5dbccc74b Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/heart.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/info.png b/emoticons/src/main/sparkEmoticonSet/info.png new file mode 100644 index 000000000..55c80687b Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/info.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/laugh.png b/emoticons/src/main/sparkEmoticonSet/laugh.png new file mode 100644 index 000000000..0f673d11b Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/laugh.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/love.png b/emoticons/src/main/sparkEmoticonSet/love.png new file mode 100644 index 000000000..e9f8e1db6 Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/love.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/minus.png b/emoticons/src/main/sparkEmoticonSet/minus.png new file mode 100644 index 000000000..7f709712c Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/minus.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/mischief.png b/emoticons/src/main/sparkEmoticonSet/mischief.png new file mode 100644 index 000000000..884269034 Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/mischief.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/party.png b/emoticons/src/main/sparkEmoticonSet/party.png new file mode 100644 index 000000000..035adbec9 Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/party.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/plain.png b/emoticons/src/main/sparkEmoticonSet/plain.png new file mode 100644 index 000000000..6f4a78ae0 Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/plain.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/plus.png b/emoticons/src/main/sparkEmoticonSet/plus.png new file mode 100644 index 000000000..38febdd39 Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/plus.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/sad.png b/emoticons/src/main/sparkEmoticonSet/sad.png new file mode 100644 index 000000000..5b7bc9207 Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/sad.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/shocked.png b/emoticons/src/main/sparkEmoticonSet/shocked.png new file mode 100644 index 000000000..54dce70f8 Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/shocked.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/silly.png b/emoticons/src/main/sparkEmoticonSet/silly.png new file mode 100644 index 000000000..ed02eca56 Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/silly.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/sleepy.png b/emoticons/src/main/sparkEmoticonSet/sleepy.png new file mode 100644 index 000000000..48eb9c22d Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/sleepy.png differ diff --git a/emoticons/src/main/sparkEmoticonSet/wink.png b/emoticons/src/main/sparkEmoticonSet/wink.png new file mode 100644 index 000000000..eda88f7cd Binary files /dev/null and b/emoticons/src/main/sparkEmoticonSet/wink.png differ diff --git a/plugins/apple/pom.xml b/plugins/apple/pom.xml new file mode 100644 index 000000000..de895263b --- /dev/null +++ b/plugins/apple/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + apple + 4.0 + + Apple Plugin + Provides Mac OS X features for Spark. + + + + Wolf Posdorfer + 9posdorf@informatik.uni-hamburg.de + + Author + + + + + + + com.apple + AppleJavaExtensions + 1.4 + + + + diff --git a/plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/AppleBounce.java b/plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/AppleBounce.java new file mode 100644 index 000000000..9eed9620f --- /dev/null +++ b/plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/AppleBounce.java @@ -0,0 +1,117 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jivesoftware.spark.plugin.apple; + +import org.jivesoftware.spark.SparkManager; + +import com.apple.eawt.Application; +import org.jivesoftware.spark.util.log.Log; + +/** + * Utilities for dealing with the apple dock icon + * + * @author Wolf.Posdorfer + */ +public final class AppleBounce { + + private boolean _flash; + final Application _app; + private final AppleProperties _props; + + @SuppressWarnings("deprecation") + public AppleBounce(AppleProperties props) { + _app = new Application(); + _props = props; + + final Thread iconThread = new Thread(() -> { + while (true) { + if (!_flash) { + setDockBadge(_app, getMessageCount()); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + Log.error(e); + } + } else { + setDockBadge(_app, getMessageCount()); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + Log.error(e); + } + setDockBadge(_app, getMessageCount()); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + Log.error(e); + } + } + } + }); + iconThread.start(); + } + + /** + * Sets Flashing to false + */ + public void resetDock() { + if (_flash) { + _flash = false; + } + } + + /** + * Returns a String of the current unread message count + * + * @return String like "10" + */ + public static String getMessageCount() { + int no = SparkManager.getChatManager().getChatContainer().getTotalNumberOfUnreadMessages(); + + if (no > 999) + no = 999; + + if (no == 0) { + return ""; + } else { + return "" + no; + } + + } + + /** + * Sets the Dock badge off the {@link Application} to the specified String + * + * @param app + * @param s + */ + public void setDockBadge(Application app, String s) { + if (_props.getDockBadges()) + app.setDockIconBadge(s); + } + + /** + * Bounce the application's dock icon to get the user's attention. + * + * @param critical + * Bounce the icon repeatedly if this is true. Bounce it only + * once if this is false. + */ + public void bounceDockIcon(boolean critical) { + _app.requestUserAttention(critical); + } + +} diff --git a/src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/AppleDock.java b/plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/AppleDock.java similarity index 95% rename from src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/AppleDock.java rename to plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/AppleDock.java index 9dc69c1b2..bf63e0d02 100644 --- a/src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/AppleDock.java +++ b/plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/AppleDock.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -53,7 +49,7 @@ public AppleDock() { frame.add(menu); // set dock menu - Application app = new Application(); + Application app = Application.getApplication(); app.setDockMenu(menu); } diff --git a/src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/ApplePlugin.java b/plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/ApplePlugin.java similarity index 86% rename from src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/ApplePlugin.java rename to plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/ApplePlugin.java index b61459b36..de23092e1 100644 --- a/src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/ApplePlugin.java +++ b/plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/ApplePlugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +20,6 @@ import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.io.File; -import java.io.IOException; import java.util.Timer; import java.util.TimerTask; @@ -32,14 +27,14 @@ import org.jivesoftware.Spark; import org.jivesoftware.resource.Res; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.spark.NativeHandler; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.Workspace; import org.jivesoftware.spark.plugin.Plugin; import org.jivesoftware.spark.ui.ChatFrame; import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomListenerAdapter; -import org.jivesoftware.spark.ui.PresenceListener; +import org.jivesoftware.spark.ui.ChatRoomListener; import org.jivesoftware.spark.ui.status.StatusItem; import org.jivesoftware.spark.util.BrowserLauncher; import org.jivesoftware.spark.util.log.Log; @@ -172,7 +167,7 @@ public void componentHidden(ComponentEvent componentEvent) { } }); - SparkManager.getChatManager().addChatRoomListener(new ChatRoomListenerAdapter() { + SparkManager.getChatManager().addChatRoomListener(new ChatRoomListener() { public void chatRoomOpened(ChatRoom room) { if (!addedFrameListener) { chatFrame = SparkManager.getChatManager().getChatContainer().getChatFrame(); @@ -206,13 +201,11 @@ public void chatRoomClosed(ChatRoom room) { } }); - SparkManager.getSessionManager().addPresenceListener(new PresenceListener() { - public void presenceChanged(Presence presence) { - if (presence.isAvailable() && !presence.isAway()) { - lastActive = System.currentTimeMillis(); - } - } - }); + SparkManager.getSessionManager().addPresenceListener(presence -> { + if (presence.isAvailable() && !presence.isAway()) { + lastActive = System.currentTimeMillis(); + } + }); final Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { @@ -252,13 +245,16 @@ private void sparkIsIdle() { unavailable = true; StatusItem away = workspace.getStatusBar().getStatusItem("Away"); Presence p = away.getPresence(); - p.setStatus(Res.getString("message.away.idle")); - previousPriority = presence.getPriority(); - p.setPriority(0); + Presence newPresence = StanzaBuilder.buildPresence() + .ofType(p.getType()) + .setStatus(Res.getString("message.away.idle")) + .setPriority(0) + .setMode(p.getMode()) + .build(); - SparkManager.getSessionManager().changePresence(p); + SparkManager.getSessionManager().changePresence(newPresence); } } } catch (Exception e) { @@ -280,11 +276,15 @@ private void setAvailableIfActive() { if (workspace != null) { Presence presence = workspace.getStatusBar().getStatusItem(Res.getString("available")) .getPresence(); - if (previousPriority != -1) { - presence.setPriority(previousPriority); - } - SparkManager.getSessionManager().changePresence(presence); + Presence newPresence = StanzaBuilder.buildPresence() + .ofType(presence.getType()) + .setStatus(presence.getStatus()) + .setPriority(previousPriority != -1 ? previousPriority : presence.getPriority()) + .setMode(presence.getMode()) + .build(); + + SparkManager.getSessionManager().changePresence(newPresence); unavailable = false; lastActive = System.currentTimeMillis(); } @@ -299,13 +299,11 @@ public boolean launchEmailClient(String to, String subject) { } public boolean launchBrowser(String url) { - try { - BrowserLauncher.openURL(url); - } catch (IOException e) { - Log.error(e); - } catch (Exception e) { - Log.error(e); - } - return true; + try { + BrowserLauncher.openURL(url); + } catch (Exception e) { + Log.error(e); + } + return true; } } diff --git a/src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/ApplePreference.java b/plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/ApplePreference.java similarity index 95% rename from src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/ApplePreference.java rename to plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/ApplePreference.java index f07236c29..7b4cc93fb 100644 --- a/src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/ApplePreference.java +++ b/plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/ApplePreference.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,8 +32,8 @@ */ public class ApplePreference implements Preference { - private AppleProperties _props; - private ApplePreferencePanel _prefpanel; + private final AppleProperties _props; + private final ApplePreferencePanel _prefpanel; public ApplePreference(AppleProperties props) { _props = props; diff --git a/src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/ApplePreferencePanel.java b/plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/ApplePreferencePanel.java similarity index 87% rename from src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/ApplePreferencePanel.java rename to plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/ApplePreferencePanel.java index abdb80b43..df88795f1 100644 --- a/src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/ApplePreferencePanel.java +++ b/plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/ApplePreferencePanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,8 +18,6 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import javax.swing.ImageIcon; import javax.swing.JCheckBox; @@ -35,29 +29,28 @@ public class ApplePreferencePanel extends JPanel { /** - * */ private static final long serialVersionUID = 5817620627545918431L; - private JCheckBox _dockbadges; - private JCheckBox _dockbouncing; - private JCheckBox _repeatedbouncing; + private final JCheckBox _dockbadges; + private final JCheckBox _dockbouncing; + private final JCheckBox _repeatedbouncing; public ApplePreferencePanel() { setLayout(new VerticalFlowLayout()); - + JPanel mainpanel = new JPanel(new GridBagLayout()); add(mainpanel); _dockbadges = new JCheckBox("Show Dock Badges"); _dockbouncing = new JCheckBox("Bouncing Dockicon"); _repeatedbouncing = new JCheckBox("Dockicon bounces repeatedly"); - + ClassLoader cl = getClass().getClassLoader(); ImageIcon badge = new ImageIcon(cl.getResource("images/badge.png")); ImageIcon bounce = new ImageIcon(cl.getResource("images/bounce.png")); - + mainpanel.add(_dockbadges, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 1, 1)); mainpanel.add(_dockbouncing, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 1, 1)); mainpanel.add(_repeatedbouncing, new GridBagConstraints(0, 2, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 1, 1)); @@ -66,13 +59,7 @@ public ApplePreferencePanel() { mainpanel.add(new JLabel(bounce), new GridBagConstraints(1, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 1, 1)); - _dockbouncing.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent arg0) { - _repeatedbouncing.setEnabled(_dockbouncing.isSelected()); - } - }); + _dockbouncing.addActionListener(arg0 -> _repeatedbouncing.setEnabled(_dockbouncing.isSelected())); } diff --git a/src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/AppleProperties.java b/plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/AppleProperties.java similarity index 97% rename from src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/AppleProperties.java rename to plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/AppleProperties.java index 04412d565..587080aa0 100644 --- a/src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/AppleProperties.java +++ b/plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/AppleProperties.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,7 +30,7 @@ * */ public class AppleProperties { - private Properties props; + private final Properties props; private File configFile; public static final String DOCKBOUNCE = "DOCKBOUNCE"; diff --git a/src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/AppleTest.java b/plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/AppleTest.java similarity index 93% rename from src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/AppleTest.java rename to plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/AppleTest.java index deb0752de..676e30c0c 100644 --- a/src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/AppleTest.java +++ b/plugins/apple/src/main/java/com/jivesoftware/spark/plugin/apple/AppleTest.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,11 +26,11 @@ public class AppleTest implements ActionListener { - public static void main(String[] args) throws InterruptedException { - new AppleTest(); + public static void main(String[] args) { + new AppleTest(); } - public AppleTest() throws InterruptedException { + public AppleTest() { for (LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) { System.out.println(laf.getClassName() + " " + laf.getName()); diff --git a/plugins/apple/src/main/plugin-metadata/plugin.xml b/plugins/apple/src/main/plugin-metadata/plugin.xml new file mode 100644 index 000000000..1279cdce9 --- /dev/null +++ b/plugins/apple/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,13 @@ + + ${project.name} + ${project.version} + ${project.description} + Wolf Posdorfer + https://IgniteRealtime.org + support@IgniteRealtime.org + com.jivesoftware.spark.plugin.apple.ApplePlugin + 3.1.0 + Mac + 11 + + diff --git a/plugins/apple/src/main/resources/images/X.png b/plugins/apple/src/main/resources/images/X.png new file mode 100644 index 000000000..1afbf9cfe Binary files /dev/null and b/plugins/apple/src/main/resources/images/X.png differ diff --git a/plugins/apple/src/main/resources/images/badge.png b/plugins/apple/src/main/resources/images/badge.png new file mode 100644 index 000000000..52bae4780 Binary files /dev/null and b/plugins/apple/src/main/resources/images/badge.png differ diff --git a/plugins/apple/src/main/resources/images/bounce.png b/plugins/apple/src/main/resources/images/bounce.png new file mode 100644 index 000000000..81f2b93ec Binary files /dev/null and b/plugins/apple/src/main/resources/images/bounce.png differ diff --git a/plugins/assembly-descriptor/pom.xml b/plugins/assembly-descriptor/pom.xml new file mode 100644 index 000000000..df518cdef --- /dev/null +++ b/plugins/assembly-descriptor/pom.xml @@ -0,0 +1,20 @@ + + 4.0.0 + + + org.igniterealtime.spark + parent + 3.1.0-SNAPSHOT + ../../ + + + org.igniterealtime.spark.plugins + assembly-descriptor + + Spark Plugin Assembly Descriptor + + This module contains a Maven Assembly Descriptor that's used to create a Spark plugin package. The usage of this + module is defined in https://maven.apache.org/plugins/maven-assembly-plugin/examples/sharing-descriptors.html + + diff --git a/plugins/assembly-descriptor/src/main/resources/assemblies/spark-plugin.xml b/plugins/assembly-descriptor/src/main/resources/assemblies/spark-plugin.xml new file mode 100644 index 000000000..7ec34720a --- /dev/null +++ b/plugins/assembly-descriptor/src/main/resources/assemblies/spark-plugin.xml @@ -0,0 +1,29 @@ + + spark-plugin + + jar + + false + + + true + lib/ + + + + + + + ${project.build.outputDirectory}/plugin.xml + + + + + + ${project.basedir}/src/main/native/ + native + + + \ No newline at end of file diff --git a/plugins/battleships/pom.xml b/plugins/battleships/pom.xml new file mode 100644 index 000000000..383878103 --- /dev/null +++ b/plugins/battleships/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + battleships + 0.4 + + Battleships + An implementation of the classic Battleships guessing game. + + + + Wolf Posdorfer + 9posdorf@informatik.uni-hamburg.de + + Author + + + + diff --git a/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/BattleshipPlugin.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/BattleshipPlugin.java new file mode 100644 index 000000000..f4170823c --- /dev/null +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/BattleshipPlugin.java @@ -0,0 +1,107 @@ +package org.jivesoftware.spark.plugin.battleship; + +import java.awt.Color; +import java.awt.Font; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.StanzaListener; +import org.jivesoftware.smack.filter.StanzaTypeFilter; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.provider.ProviderManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.ChatRoom; + +import org.jivesoftware.spark.plugin.battleship.listener.ChatRoomOpeningListener; +import org.jivesoftware.spark.plugin.battleship.packets.GameOfferPacket; +import org.jivesoftware.spark.plugin.battleship.packets.MoveAnswerPacket; +import org.jivesoftware.spark.plugin.battleship.packets.MovePacket; +import org.jivesoftware.spark.util.log.Log; + +public class BattleshipPlugin implements Plugin { + + @Override + public void initialize() { + ProviderManager.addIQProvider(GameOfferPacket.ELEMENT_NAME, GameOfferPacket.NAMESPACE, new GameOfferPacket.Provider()); + ProviderManager.addExtensionProvider(MovePacket.ELEMENT_NAME, MovePacket.NAMESPACE, new MovePacket.Provider()); + ProviderManager.addExtensionProvider(MoveAnswerPacket.ELEMENT_NAME, MoveAnswerPacket.NAMESPACE, new MoveAnswerPacket.Provider()); + + StanzaListener _gameOfferListener = stanza -> { + GameOfferPacket invitation = (GameOfferPacket) stanza; + if (invitation.getType() == IQ.Type.get) { + showInvitationInChat(invitation); + } + }; + + SparkManager.getConnection().addAsyncStanzaListener(_gameOfferListener, + new StanzaTypeFilter(GameOfferPacket.class)); + ChatRoomOpeningListener _chatRoomListener = new ChatRoomOpeningListener(); + SparkManager.getChatManager().addChatRoomListener(_chatRoomListener); + } + + private void showInvitationInChat(final GameOfferPacket invitation) { + invitation.setType(IQ.Type.result); + invitation.setTo(invitation.getFrom()); + + final ChatRoom room = SparkManager.getChatManager().getChatRoom(invitation.getFrom().asEntityBareJidIfPossible()); + String name = invitation.getFrom().getLocalpartOrNull().toString(); + final JPanel panel = new JPanel(); + JLabel text = new JLabel("Game request from" + name); + JLabel game = new JLabel("Battleships"); + game.setFont(new Font("Dialog", Font.BOLD, 24)); + game.setForeground(Color.RED); + JButton accept = new JButton(Res.getString("button.accept").replace("&", "")); + JButton decline = new JButton(Res.getString("button.decline").replace("&", "")); + panel.add(text); + panel.add(game); + panel.add(accept); + panel.add(decline); + room.getTranscriptWindow().addComponent(panel); + + accept.addActionListener(e -> { + try { + SparkManager.getConnection().sendStanza(invitation); + } catch (SmackException.NotConnectedException | InterruptedException e1) { + Log.warning("Unable to send invitation accept to " + invitation.getTo(), e1); + } + invitation.setStartingPlayer(!invitation.isStartingPlayer()); + ChatRoomOpeningListener.createWindow(invitation, invitation.getFrom().toString()); + panel.remove(3); + panel.remove(2); + panel.repaint(); + panel.revalidate(); + }); + + decline.addActionListener(e -> { + invitation.setType(IQ.Type.error); + try { + SparkManager.getConnection().sendStanza(invitation); + } catch (SmackException.NotConnectedException | InterruptedException e1) { + Log.warning("Unable to send invitation decline to " + invitation.getTo(), e1); + } + panel.remove(3); + panel.remove(2); + panel.repaint(); + panel.revalidate(); + }); + } + + @Override + public void shutdown() { + } + + @Override + public boolean canShutDown() { + return false; + } + + @Override + public void uninstall() { + } + +} diff --git a/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/BsRes.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/BsRes.java new file mode 100644 index 000000000..4d145f3d1 --- /dev/null +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/BsRes.java @@ -0,0 +1,32 @@ +package org.jivesoftware.spark.plugin.battleship; + +import java.text.MessageFormat; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +import org.jivesoftware.spark.util.log.Log; + + +public class BsRes { + private static final PropertyResourceBundle prb; + + static ClassLoader cl = BsRes.class.getClassLoader(); + + static { + prb = (PropertyResourceBundle) ResourceBundle.getBundle("i18n/battleships_i18n"); + } + + public static String getString(String propertyName) { + try { + return prb.getString(propertyName); + } catch (Exception e) { + Log.error(e); + return propertyName; + } + } + + public static String getString(String propertyName, Object... obj) { + String str = prb.getString(propertyName); + return MessageFormat.format(str, obj); + } +} diff --git a/src/plugins/battleships/src/java/battleship/gui/Display.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/gui/Display.java similarity index 81% rename from src/plugins/battleships/src/java/battleship/gui/Display.java rename to plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/gui/Display.java index bda9a8bdb..366ac781c 100644 --- a/src/plugins/battleships/src/java/battleship/gui/Display.java +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/gui/Display.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,27 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package battleship.gui; +package org.jivesoftware.spark.plugin.battleship.gui; import java.awt.GridLayout; import java.awt.Image; import javax.swing.JLabel; import javax.swing.JPanel; -import battleship.types.Ship; +import org.jivesoftware.spark.plugin.battleship.types.Ship; +/** + * Display panel with ship labels + */ public class Display extends JPanel { private static final long serialVersionUID = 2343499579008942774L; - private JLabel[] _labels; - private JLabel _textlabel; + private final JLabel[] _labels; + private final JLabel _textLabel; public Display() { setLayout(new GridLayout(6, 1)); - - _textlabel = new JLabel(""); + _textLabel = new JLabel(""); _labels = new JLabel[5]; - _labels[0] = new JLabel(Ship.TWO.getScaledInstance(100, 50, Image.SCALE_SMOOTH)); _labels[1] = new JLabel(Ship.THREE.getScaledInstance(100, 50, Image.SCALE_SMOOTH)); @@ -45,29 +42,23 @@ public Display() { _labels[3] = new JLabel(Ship.FOUR.getScaledInstance(100, 50, Image.SCALE_SMOOTH)); _labels[4] = new JLabel(Ship.FIVE.getScaledInstance(100, 50, Image.SCALE_SMOOTH)); - add(_textlabel); - + add(_textLabel); for (JLabel l : _labels) { add(l); } - } /** * Returns the X's ships Label - * - * @return */ public JLabel getLabel(int x) { return _labels[x]; } - - public void setMessage(String text) - { - _textlabel.setText(text); + + public void setMessage(String text) { + _textLabel.setText(text); this.repaint(); this.revalidate(); } - } diff --git a/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/gui/GUI.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/gui/GUI.java new file mode 100644 index 000000000..741a478f8 --- /dev/null +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/gui/GUI.java @@ -0,0 +1,116 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.battleship.gui; + +import java.awt.BorderLayout; + +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.filter.StanzaExtensionFilter; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; + +import org.jivesoftware.spark.plugin.battleship.listener.ShipPlacementListener; +import org.jivesoftware.spark.plugin.battleship.logic.GameBoard; + +import java.util.Observable; +import java.util.Observer; + +import org.jivesoftware.spark.plugin.battleship.packets.MoveAnswerPacket; +import org.jivesoftware.spark.plugin.battleship.packets.MovePacket; +import org.jxmpp.jid.Jid; + +public class GUI extends JPanel implements Observer { + + private static final long serialVersionUID = -7538765009749015196L; + + private final Display _display; + private final GameboardGUI _myField; + private final GameboardGUI _theirField; + private final JFrame _owner; + private final XMPPConnection _connection; + private final int _gameID; + private final GameBoard _gameboard; + + private final ShipPlacementListener _spListener; + + public GUI(boolean imStarting, JFrame owner, XMPPConnection connection, int gameID) { + setLayout(new BorderLayout()); + _owner = owner; + _connection = connection; + _gameID = gameID; + _gameboard = new GameBoard(imStarting); + + _display = new Display(); + _myField = new GameboardGUI(); + _theirField = new GameboardGUI(); + + JPanel West = new JPanel(new BorderLayout(0, 5)); + JPanel wNorth = new JPanel(new BorderLayout()); + wNorth.add(new JLabel("Their Board"), BorderLayout.NORTH); + wNorth.add(_theirField, BorderLayout.SOUTH); + + JPanel wSouth = new JPanel(new BorderLayout()); + wSouth.add(new JLabel("My Board"), BorderLayout.NORTH); + wSouth.add(_myField); + + JPanel East = new JPanel(); + West.add(wSouth, BorderLayout.SOUTH); + West.add(wNorth, BorderLayout.NORTH); + East.add(_display); + + add(East, BorderLayout.EAST); + add(West, BorderLayout.WEST); + + _connection.addAsyncStanzaListener(stanza -> { + MovePacket move = stanza.getExtension(MovePacket.class); + if (move.getGameID() == _gameID) { + boolean opponentMadeHit = _gameboard.placeBomb(move.getPositionX(), move.getPositionY()); + if (opponentMadeHit) { + Message m = createAnswer(move, stanza.getFrom()); + _connection.sendStanza(m); + } + } + }, new StanzaExtensionFilter(MovePacket.ELEMENT_NAME, MovePacket.NAMESPACE)); + + // Start placing of the Ships + _spListener = new ShipPlacementListener(_display, _gameboard, _myField); + _spListener.addObserver(this); + + _myField.initiateShipPlacement(_spListener); + } + + private Message createAnswer(MovePacket incoming, Jid from) { + Message answer = StanzaBuilder.buildMessage().build(); + answer.setTo(from); + + MoveAnswerPacket map = new MoveAnswerPacket(); + map.setGameID(incoming.getGameID()); + map.setPositionX(incoming.getPositionX()); + map.setPositionY(incoming.getPositionY()); + return answer; + } + + @Override + public void update(Observable observable, Object arg) { + //TODO Initial ship placement is done + // Start with normal moves + observable.deleteObserver(this); + } +} diff --git a/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/gui/GameboardGUI.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/gui/GameboardGUI.java new file mode 100644 index 000000000..716d43d83 --- /dev/null +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/gui/GameboardGUI.java @@ -0,0 +1,86 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.battleship.gui; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Image; +import java.awt.geom.AffineTransform; + +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.jivesoftware.spark.plugin.battleship.listener.ShipPlacementListener; +import org.jivesoftware.spark.plugin.battleship.types.Types; + +public class GameboardGUI extends JPanel { + private static final long serialVersionUID = -6429298293488133059L; + + private final Image _bg; + private final JLabel[][] _labels; + + public GameboardGUI() { + ClassLoader cl = getClass().getClassLoader(); + _bg = new ImageIcon(cl.getResource("water.png")).getImage(); + + setLayout(new GridLayout(10, 10)); + _labels = new JLabel[10][10]; + + for (int x = 0; x < 10; x++) { + for (int y = 0; y < 10; y++) { + _labels[x][y] = new JLabel("empty"); + _labels[x][y].setBorder(BorderFactory.createLineBorder(Color.lightGray)); + add(_labels[x][y]); + } + } + this.setPreferredSize(new Dimension(400, 400)); + } + + public void setField(int x, int y, Types t) { + System.out.println("setting field" + x + "," + y); + _labels[x][y].setIcon(t.getImage()); + repaint(); + revalidate(); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + final Image backgroundImage = _bg; + double scaleX = getWidth() / (double) backgroundImage.getWidth(null); + double scaleY = getHeight() / (double) backgroundImage.getHeight(null); + AffineTransform xform = AffineTransform.getScaleInstance(scaleX, scaleY); + ((Graphics2D) g).drawImage(backgroundImage, xform, this); + } + + public void initiateShipPlacement(ShipPlacementListener spl) { + for (int x = 0; x < 10; x++) { + for (int y = 0; y < 10; y++) { + _labels[x][y].addMouseListener(spl); + } + } + } + + public JLabel[][] getLabels() { + return _labels; + } + +} diff --git a/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/listener/ChatRoomOpeningListener.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/listener/ChatRoomOpeningListener.java new file mode 100644 index 000000000..272bc5571 --- /dev/null +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/listener/ChatRoomOpeningListener.java @@ -0,0 +1,90 @@ +package org.jivesoftware.spark.plugin.battleship.listener; + +import java.awt.Color; + +import javax.swing.JFrame; + + +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.filter.StanzaIdFilter; +import org.jivesoftware.smack.packet.ErrorIQ; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomButton; +import org.jivesoftware.spark.ui.ChatRoomListenerAdapter; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; + +import org.jivesoftware.spark.plugin.battleship.BsRes; +import org.jivesoftware.spark.plugin.battleship.gui.GUI; +import org.jivesoftware.spark.plugin.battleship.packets.GameOfferPacket; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.Jid; +import org.jxmpp.util.XmppStringUtils; + +public class ChatRoomOpeningListener extends ChatRoomListenerAdapter { + + @Override + public void chatRoomOpened(final ChatRoom room) { + // Check for 1on1 Chat + if (!(room instanceof ChatRoomImpl)) { + return; + } + + final ChatRoomButton sendGameButton = new ChatRoomButton("BS"); + room.getToolBar().addChatRoomButton(sendGameButton); + + sendGameButton.addActionListener(e -> { + final Jid opponentJID = ((ChatRoomImpl) room).getJidOnline(); + if (opponentJID == null) { + return; + } + final GameOfferPacket offer = new GameOfferPacket(); + offer.setTo(opponentJID); + offer.setType(IQ.Type.get); + + room.getTranscriptWindow().insertCustomText( + BsRes.getString("request"), false, false, + Color.BLUE); + try { + SparkManager.getConnection().sendStanza(offer); + } catch (SmackException.NotConnectedException | InterruptedException e1) { + Log.warning("Unable to send offer to " + opponentJID, e1); + } + + SparkManager.getConnection().addAsyncStanzaListener(stanza -> { + if (stanza.getError() != null) { + room.getTranscriptWindow().insertCustomText( + BsRes.getString("request.error") + stanza.getError().getDescriptiveText(), + false, false, Color.RED); + return; + } + GameOfferPacket answer = (GameOfferPacket) stanza; + answer.setStartingPlayer(offer.isStartingPlayer()); + answer.setGameID(offer.getGameID()); + String name = opponentJID.getLocalpartOrNull().toString(); + if (answer.getType() == IQ.Type.result) { + // ACCEPT + room.getTranscriptWindow() + .insertCustomText(BsRes.getString("accepted", name), false, + false, Color.BLUE); + createWindow(answer, opponentJID.toString()); + } else { + // DECLINE + room.getTranscriptWindow() + .insertCustomText(BsRes.getString("declined", name), false, + false, Color.RED); + } + }, new StanzaIdFilter(offer.getStanzaId())); + }); + + } + + public static void createWindow(GameOfferPacket answer, String opponentJID) { + JFrame frame = new JFrame(BsRes.getString("versus", XmppStringUtils.parseLocalpart(opponentJID))); + frame.add(new GUI(answer.isStartingPlayer(), frame, SparkManager.getConnection(), answer.getGameID())); + frame.pack(); + frame.setLocationRelativeTo(SparkManager.getChatManager().getChatContainer()); + frame.setVisible(true); + } +} diff --git a/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/listener/ShipPlacementListener.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/listener/ShipPlacementListener.java new file mode 100644 index 000000000..8519bf8c9 --- /dev/null +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/listener/ShipPlacementListener.java @@ -0,0 +1,43 @@ +package org.jivesoftware.spark.plugin.battleship.listener; + +import org.jivesoftware.spark.plugin.battleship.gui.Display; +import org.jivesoftware.spark.plugin.battleship.gui.GameboardGUI; +import org.jivesoftware.spark.plugin.battleship.logic.GameBoard; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.Observer; + +public class ShipPlacementListener implements MouseListener { + public ShipPlacementListener(Display display, GameBoard gameBoard, GameboardGUI myField) { + + } + + @Override + public void mouseClicked(MouseEvent mouseEvent) { + + } + + @Override + public void mousePressed(MouseEvent mouseEvent) { + + } + + @Override + public void mouseReleased(MouseEvent mouseEvent) { + + } + + @Override + public void mouseEntered(MouseEvent mouseEvent) { + + } + + @Override + public void mouseExited(MouseEvent mouseEvent) { + + } + + public void addObserver(Observer observer) { + } +} diff --git a/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/logic/CoordinatePair.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/logic/CoordinatePair.java new file mode 100644 index 000000000..479d3213c --- /dev/null +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/logic/CoordinatePair.java @@ -0,0 +1,18 @@ +package org.jivesoftware.spark.plugin.battleship.logic; + +public class CoordinatePair { + private final int x, y; + + public CoordinatePair(int x, int y) { + this.x = x; + this.y = y; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } +} diff --git a/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/logic/GameBoard.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/logic/GameBoard.java new file mode 100644 index 000000000..f19cde9c0 --- /dev/null +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/logic/GameBoard.java @@ -0,0 +1,138 @@ +package org.jivesoftware.spark.plugin.battleship.logic; + +import java.util.ArrayList; +import java.util.List; + +import org.jivesoftware.spark.plugin.battleship.types.Direction; +import org.jivesoftware.spark.plugin.battleship.types.Ship; + +public class GameBoard { + + private final Ship[][] _fields; + private final ShipModel[] _myShips; + + private boolean myTurn; + + public GameBoard(boolean myTurn) { + this.myTurn = myTurn; + + _fields = new Ship[12][12]; + // Construct a 12x12 Gameboard with a surrounding void + // actual game is in [1][1] to [10][10] + _myShips = new ShipModel[5]; + _myShips[0] = new ShipModel(2); + _myShips[1] = new ShipModel(3); + _myShips[2] = new ShipModel(3); + _myShips[3] = new ShipModel(4); + _myShips[4] = new ShipModel(5); + + for (int x = 0; x < _fields.length; x++) { + for (int y = 0; y < _fields.length; y++) { + _fields[x][y] = Ship.EMPTY; + } + } + } + + /** + * Places a Bomb of the Opponent on your field + * + * @return True if the Opponent hit a Ship, else false + */ + public boolean placeBomb(int x, int y) { + // Add one to subtract the void fields + x = x + 1; + y = y + 1; + + if (_fields[x][y] != Ship.EMPTY) { + ShipModel smo = _myShips[_fields[x][y].inArrayPosition()]; + smo.setBomb(); + return true; + } else { + myTurn = !myTurn; // Now it's my turn + return false; + } + } + + /** + * Places a Ship on the Board + */ + public List placeShip(int x, int y, Ship s, Direction dir) { + boolean placementOK = true; + x = x + 1; + y = y + 1; + List liste = new ArrayList<>(); + System.out.println("placing ship"); + // Left to Right + if (dir == Direction.HORIZONTAL) { + for (int i = x; i < x + s.getFields(); i++) { + if (!checkSurrounding(i, y)) + System.out.println("checking " + i + "," + y); + placementOK = false; + } + + if (placementOK) { + for (int i = x, j = 0; i < x + s.getFields(); i++, j++) { + _fields[i][y] = s; + System.out.println("adding coord at horiz" + j); + liste.add(new CoordinatePair(i, y)); + } + } + } else { + // top to bottom + for (int i = y; i < y + s.getFields(); i++) { + if (!checkSurrounding(x, i)) { + System.out.println("checking " + i + "," + y); + } + placementOK = false; + } + + if (placementOK) { + for (int i = y, j = 0; i < y + s.getFields(); i++, j++) { + _fields[x][i] = s; + liste.add(new CoordinatePair(x, i)); + System.out.println("adding coord at vert" + j); + } + } + } + System.out.println("placement ok? " + placementOK); + return placementOK ? liste : null; + } + + /** + * Checks the surrounding fields for collision + */ + private boolean checkSurrounding(int x, int y) { + if (x < 1 || x > 10) { + System.out.println("1"); + return false; + } + if (y < 1 || y > 10) { + System.out.println("2"); + return false; + } + + if (_fields[x - 1][y - 1] != Ship.EMPTY + || _fields[x][y - 1] != Ship.EMPTY + || _fields[x + 1][y - 1] != Ship.EMPTY) { + System.out.println("3"); + return false; + } else if (_fields[x - 1][y] != Ship.EMPTY + || _fields[x][y] != Ship.EMPTY + || _fields[x + 1][y] != Ship.EMPTY) { + System.out.println("4"); + return false; + } else if (_fields[x - 1][y + 1] != Ship.EMPTY + || _fields[x][y + 1] != Ship.EMPTY + || _fields[x + 1][y + 1] != Ship.EMPTY) { + System.out.println("5"); + return false; + } else + return true; + } + + public int getField(int x, int y) { + Ship s = _fields[x][y]; + return s.getFields(); + } + +} diff --git a/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/logic/ShipModel.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/logic/ShipModel.java new file mode 100644 index 000000000..2898a98a6 --- /dev/null +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/logic/ShipModel.java @@ -0,0 +1,30 @@ +package org.jivesoftware.spark.plugin.battleship.logic; + +public class ShipModel { + private final int[] _ship; + + public ShipModel(int size) { + _ship = new int[size]; + } + + public void setBomb() { + for (int i = 0; i < _ship.length; i++) { + if (_ship[i] == 0) { + _ship[i] = 1; + break; + } + } + } + + public boolean isDestroyed() { + boolean dest = true; + for (int i = 0; i < _ship.length && dest; i++) { + dest = _ship[i] != 0; + } + return dest; + } + + public int getSize() { + return _ship.length; + } +} diff --git a/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/packets/GameOfferPacket.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/packets/GameOfferPacket.java new file mode 100644 index 000000000..f3f47d7c1 --- /dev/null +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/packets/GameOfferPacket.java @@ -0,0 +1,122 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.battleship.packets; + +import java.io.IOException; +import java.text.ParseException; +import java.util.Random; + +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IqData; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.parsing.SmackParsingException; +import org.jivesoftware.smack.provider.IqProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.JxmppContext; + +/** + * The Game Offer Packet + * + * @author wolf.posdorfer + */ +public class GameOfferPacket extends IQ { + public static final String ELEMENT_NAME = "battleship"; + public static final String NAMESPACE = "battleship"; + + private int gameID; + private boolean imTheStartingPlayer; + + public GameOfferPacket() { + super(ELEMENT_NAME, NAMESPACE); + imTheStartingPlayer = new Random().nextBoolean(); + gameID = Math.abs(new Random().nextInt()); + } + + /** + * Returns the game ID. + */ + public int getGameID() { + return gameID; + } + + /** + * Sets the game ID. + */ + public void setGameID(int gameID) { + this.gameID = gameID; + } + + /** + * Returns true if the user making the game invitation is the starting player. + */ + public boolean isStartingPlayer() { + return imTheStartingPlayer; + } + + /** + * Sets whether the user making the game invitation is the starting player. + * + * @param startingPlayer true if the user making the game invite is the starting player. + */ + public void setStartingPlayer(boolean startingPlayer) { + this.imTheStartingPlayer = startingPlayer; + } + + @Override + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder buf) { + buf.rightAngleBracket(); + buf.append("<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">"); + if (getType() == IQ.Type.get) { + buf.element("gameID", String.valueOf(gameID)); + buf.element("startingPlayer", String.valueOf(imTheStartingPlayer)); + buf.append(getExtensions()); + } + buf.append(""); + return buf; + } + + public static class Provider extends IqProvider { + public Provider() { + super(); + } + + @Override + public GameOfferPacket parse(XmlPullParser parser, int initialDepth, IqData iqData, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException, SmackParsingException, ParseException { + final GameOfferPacket gameOffer = new GameOfferPacket(); + + boolean done = false; + while (!done) { + XmlPullParser.Event eventType = parser.next(); + if (eventType == XmlPullParser.Event.START_ELEMENT) { + if (parser.getName().equals("gameID")) { + final int gameID = Integer.parseInt(parser.nextText()); + gameOffer.setGameID(gameID); + } else if (parser.getName().equals("startingPlayer")) { + boolean startingPlayer = Boolean.parseBoolean(parser.nextText()); + gameOffer.setStartingPlayer(startingPlayer); + } + } else if (eventType == XmlPullParser.Event.END_ELEMENT) { + if (parser.getName().equals(ELEMENT_NAME)) { + done = true; + } + } + } + + return gameOffer; + } + } +} diff --git a/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/packets/MoveAnswerPacket.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/packets/MoveAnswerPacket.java new file mode 100644 index 000000000..6c5bfff16 --- /dev/null +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/packets/MoveAnswerPacket.java @@ -0,0 +1,158 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.battleship.packets; + +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.provider.ExtensionElementProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.JxmppContext; + +import javax.xml.namespace.QName; +import java.io.IOException; + +/** + * The MoveAnswer Packet Extension + * + * @author wolf.posdorfer + */ +public class MoveAnswerPacket implements ExtensionElement { + + public static final String ELEMENT_NAME = "bs-move"; + public static final String NAMESPACE = "battleship"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT_NAME); + + private int posX; + private int posY; + private int gameID; + private int hit; + private int shipType; + + public int getGameID() { + return gameID; + } + + public void setGameID(int gameID) { + this.gameID = gameID; + } + + @Override + public String getElementName() { + return ELEMENT_NAME; + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + public int getPositionX() { + return posX; + } + + public void setPositionX(int posx) { + this.posX = posx; + } + + public int getPositionY() { + return posY; + } + + public void setPositionY(int posy) { + this.posY = posy; + } + + public int getHit() { + return hit; + } + + public void setHit(int hit) { + this.hit = hit; + } + + public void setShipType(int x) { + this.shipType = x; + } + + public int getShipType() { + return shipType; + } + + @Override + public CharSequence toXML(XmlEnvironment xmlEnvironment) { + String buf = "<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">" + + "" + gameID + "" + + "" + posX + "" + + "" + posY + "" + + "" + hit + "" + + "" + shipType + "" + + ""; + return buf; + } + + public static class Provider extends ExtensionElementProvider + { + @Override + public MoveAnswerPacket parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException + { + final MoveAnswerPacket gameMove = new MoveAnswerPacket(); + boolean done = false; + while ( !done ) + { + final XmlPullParser.Event eventType = parser.next(); + + if ( eventType == XmlPullParser.Event.START_ELEMENT ) + { + if ( "gameID".equals( parser.getName() ) ) + { + final int gameID = Integer.parseInt( parser.nextText() ); + gameMove.setGameID( gameID ); + } + if ( "positionX".equals( parser.getName() ) ) + { + final int position = Integer.parseInt( parser.nextText() ); + gameMove.setPositionX( position ); + } + if ( "positionY".equals( parser.getName() ) ) + { + final int position = Integer.parseInt( parser.nextText() ); + gameMove.setPositionY( position ); + } + if ( "hit".equals( parser.getName() ) ) + { + final int hit = Integer.parseInt( parser.nextText() ); + gameMove.setHit( hit ); + } + if ( "shiptype".equals( parser.getName() ) ) + { + final int shipType = Integer.parseInt( parser.nextText() ); + gameMove.setShipType( shipType ); + } + } + else if ( eventType == XmlPullParser.Event.END_ELEMENT ) + { + if ( ELEMENT_NAME.equals( parser.getName() ) ) + { + done = true; + } + } + } + + return gameMove; + } + } +} diff --git a/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/packets/MovePacket.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/packets/MovePacket.java new file mode 100644 index 000000000..f6c29e6e8 --- /dev/null +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/packets/MovePacket.java @@ -0,0 +1,128 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.battleship.packets; + +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.provider.ExtensionElementProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.JxmppContext; + +import javax.xml.namespace.QName; +import java.io.IOException; + +/** + * The Move Packet extension + * + * @author wolf.posdorfer + */ +public class MovePacket implements ExtensionElement { + + public static final String ELEMENT_NAME = "bs-move"; + public static final String NAMESPACE = "battleship"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT_NAME); + + private int posX; + private int posY; + private int gameID; + + public int getGameID() { + return gameID; + } + + public void setGameID(int gameID) { + this.gameID = gameID; + } + + @Override + public String getElementName() { + return ELEMENT_NAME; + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + public int getPositionX() { + return posX; + } + + public void setPositionX(int posX) { + this.posX = posX; + } + + public int getPositionY() { + return posY; + } + + public void setPositionY(int posY) { + this.posY = posY; + } + + @Override + public CharSequence toXML(XmlEnvironment xmlEnvironment) { + String buf = "<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">" + + "" + gameID + "" + + "" + posX + "" + + "" + posY + "" + + ""; + return buf; + } + + public static class Provider extends ExtensionElementProvider + { + @Override + public MovePacket parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException + { + final MovePacket gameMove = new MovePacket(); + boolean done = false; + while ( !done ) + { + final XmlPullParser.Event eventType = parser.next(); + + if ( eventType == XmlPullParser.Event.START_ELEMENT ) + { + if ( "gameID".equals( parser.getName() ) ) + { + final int gameID = Integer.parseInt( parser.nextText() ); + gameMove.setGameID( gameID ); + } + if ( "positionX".equals( parser.getName() ) ) + { + final int position = Integer.parseInt( parser.nextText() ); + gameMove.setPositionX( position ); + } + if ( "positionY".equals( parser.getName() ) ) + { + final int position = Integer.parseInt( parser.nextText() ); + gameMove.setPositionY( position ); + } + } + else if ( eventType == XmlPullParser.Event.END_ELEMENT ) + { + if ( ELEMENT_NAME.equals( parser.getName() ) ) + { + done = true; + } + } + } + + return gameMove; + } + } +} diff --git a/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/types/Direction.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/types/Direction.java new file mode 100644 index 000000000..c883a7ad7 --- /dev/null +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/types/Direction.java @@ -0,0 +1,5 @@ +package org.jivesoftware.spark.plugin.battleship.types; + +public enum Direction { + HORIZONTAL, VERTICAL +} diff --git a/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/types/Ship.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/types/Ship.java new file mode 100644 index 000000000..ce7c3a12e --- /dev/null +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/types/Ship.java @@ -0,0 +1,121 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.battleship.types; + +import java.awt.Image; + +import javax.swing.ImageIcon; + +public enum Ship { + EMPTY("empty.png"), + TWO("2.png"), + THREE("3.png"), + THREE2("3.png"), + FOUR("4.png"), + FIVE("5.png"); + + private final String image; + + Ship(String s) { + image = s; + } + + public ImageIcon getImage() { + ClassLoader cl = getClass().getClassLoader(); + return new ImageIcon(cl.getResource(image)); + } + + public static Ship valueOf(int x) { + switch (x) { + case 2: + return TWO; + case 3: + return THREE; + case 4: + return THREE2; + case 5: + return FOUR; + case 6: + return FIVE; + default: + return EMPTY; + } + } + + /** + * Returns the Position inside the Array + */ + public int inArrayPosition() { + switch (this) { + case TWO: + return 0; + case THREE: + return 1; + case THREE2: + return 2; + case FOUR: + return 3; + case FIVE: + return 4; + default: + return 0; + } + } + + /** + * Returns the Occupying Fields + */ + public int getFields() { + switch (this) { + case TWO: + return 2; + case THREE: + return 3; + case THREE2: + return 3; + case FOUR: + return 4; + case FIVE: + return 5; + } + return 0; + } + + public ImageIcon getScaledInstance(int w, int h, int hints) { + Image img = getImage().getImage(); + return new ImageIcon(img.getScaledInstance(w, h, hints)); + } + + /** + * Returns the next Bigger Ship
      + * 2 -> 3.1 -> 3.2 -> 4 -> 5 -> 2..... + */ + public Ship increment() { + switch (this) { + case TWO: + return THREE; + case THREE: + return THREE2; + case THREE2: + return FOUR; + case FOUR: + return FIVE; + case FIVE: + return TWO; + } + return TWO; + } +} diff --git a/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/types/Types.java b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/types/Types.java new file mode 100644 index 000000000..049105870 --- /dev/null +++ b/plugins/battleships/src/main/java/org/jivesoftware/spark/plugin/battleship/types/Types.java @@ -0,0 +1,49 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.battleship.types; + +import javax.swing.ImageIcon; + +public enum Types { + EMPTY("empty.png"), + MISS("miss.png"), + SHIP("ship.png"), + SHIPHIT("shiphit.png"); + + public Types getValue(int x) { + switch (x) { + case 1: + return MISS; + case 2: + return SHIP; + case 3: + return SHIPHIT; + default: + return EMPTY; + } + } + + private final String _iconName; + + Types(String iconName) { + _iconName = iconName; + } + + public ImageIcon getImage() { + ClassLoader cl = getClass().getClassLoader(); + return new ImageIcon(cl.getResource(_iconName)); + } +} diff --git a/plugins/battleships/src/main/plugin-metadata/plugin.xml b/plugins/battleships/src/main/plugin-metadata/plugin.xml new file mode 100644 index 000000000..57f69960a --- /dev/null +++ b/plugins/battleships/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,12 @@ + + ${project.name} + ${project.version} + ${project.description} + org.jivesoftware.spark.plugin.battleship.BattleshipPlugin + Wolf Posdorfer + https://IgniteRealtime.org + support@IgniteRealtime.org + 3.1.0 + Windows,Linux,Mac + 11 + diff --git a/src/plugins/battleships/src/resources/2.png b/plugins/battleships/src/main/resources/2.png similarity index 81% rename from src/plugins/battleships/src/resources/2.png rename to plugins/battleships/src/main/resources/2.png index ffa84e8b8..26f515b36 100644 Binary files a/src/plugins/battleships/src/resources/2.png and b/plugins/battleships/src/main/resources/2.png differ diff --git a/src/plugins/battleships/src/resources/3.png b/plugins/battleships/src/main/resources/3.png similarity index 81% rename from src/plugins/battleships/src/resources/3.png rename to plugins/battleships/src/main/resources/3.png index b13a3628d..0c81ddc2e 100644 Binary files a/src/plugins/battleships/src/resources/3.png and b/plugins/battleships/src/main/resources/3.png differ diff --git a/plugins/battleships/src/main/resources/4.png b/plugins/battleships/src/main/resources/4.png new file mode 100644 index 000000000..fbb08afde Binary files /dev/null and b/plugins/battleships/src/main/resources/4.png differ diff --git a/src/plugins/battleships/src/resources/5.png b/plugins/battleships/src/main/resources/5.png similarity index 75% rename from src/plugins/battleships/src/resources/5.png rename to plugins/battleships/src/main/resources/5.png index 33e106151..9b9831d8b 100644 Binary files a/src/plugins/battleships/src/resources/5.png and b/plugins/battleships/src/main/resources/5.png differ diff --git a/plugins/battleships/src/main/resources/_hit.png b/plugins/battleships/src/main/resources/_hit.png new file mode 100644 index 000000000..3c7981aa6 Binary files /dev/null and b/plugins/battleships/src/main/resources/_hit.png differ diff --git a/plugins/battleships/src/main/resources/_nohit.png b/plugins/battleships/src/main/resources/_nohit.png new file mode 100644 index 000000000..4c268a6f2 Binary files /dev/null and b/plugins/battleships/src/main/resources/_nohit.png differ diff --git a/plugins/battleships/src/main/resources/empty.png b/plugins/battleships/src/main/resources/empty.png new file mode 100644 index 000000000..11854b0d1 Binary files /dev/null and b/plugins/battleships/src/main/resources/empty.png differ diff --git a/plugins/battleships/src/main/resources/i18n/battleships_i18n.properties b/plugins/battleships/src/main/resources/i18n/battleships_i18n.properties new file mode 100644 index 000000000..2003e972a --- /dev/null +++ b/plugins/battleships/src/main/resources/i18n/battleships_i18n.properties @@ -0,0 +1,6 @@ +title = Battleships +versus = Battleships versus {0} +request = You requested a game of Battleships +has.request = {0} has requested a game of Battleships +accepted = {0} has accepted the invitation +declined = {0} has declined the invitation diff --git a/plugins/battleships/src/main/resources/i18n/battleships_i18n_lt.properties b/plugins/battleships/src/main/resources/i18n/battleships_i18n_lt.properties new file mode 100644 index 000000000..a5116395c --- /dev/null +++ b/plugins/battleships/src/main/resources/i18n/battleships_i18n_lt.properties @@ -0,0 +1,6 @@ +title = Jūros mūšis +versus = Jūros mūšis prieš {0} +request = Jūs užklausėt Jūros mūšis žaidimo +has.request = {0} užklausė Jūros mūšis žaidimo +accepted = {0} priėmė pakvietimą +declined = {0} atmetė pakvietimą diff --git a/plugins/battleships/src/main/resources/i18n/battleships_i18n_ru.properties b/plugins/battleships/src/main/resources/i18n/battleships_i18n_ru.properties new file mode 100644 index 000000000..5b73877cb --- /dev/null +++ b/plugins/battleships/src/main/resources/i18n/battleships_i18n_ru.properties @@ -0,0 +1,6 @@ +title = ??????? ??? +versus = ??????? ??? ? {0} +request = ?? ????????? ???? ? ??????? ??? +has.request = {0} ???????? ???? ? ??????? ??? +accepted = {0} ?????? ??????????? +declined = {0} ???????? ??????????? diff --git a/plugins/battleships/src/main/resources/miss.png b/plugins/battleships/src/main/resources/miss.png new file mode 100644 index 000000000..8d9995335 Binary files /dev/null and b/plugins/battleships/src/main/resources/miss.png differ diff --git a/plugins/battleships/src/main/resources/ship.png b/plugins/battleships/src/main/resources/ship.png new file mode 100644 index 000000000..efd36d29c Binary files /dev/null and b/plugins/battleships/src/main/resources/ship.png differ diff --git a/plugins/battleships/src/main/resources/shiphit.png b/plugins/battleships/src/main/resources/shiphit.png new file mode 100644 index 000000000..06d7e7292 Binary files /dev/null and b/plugins/battleships/src/main/resources/shiphit.png differ diff --git a/plugins/battleships/src/main/resources/water.png b/plugins/battleships/src/main/resources/water.png new file mode 100644 index 000000000..e156fc1b5 Binary files /dev/null and b/plugins/battleships/src/main/resources/water.png differ diff --git a/plugins/fastpath/pom.xml b/plugins/fastpath/pom.xml new file mode 100644 index 000000000..798fcc6cf --- /dev/null +++ b/plugins/fastpath/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + fastpath + 3.6.0 + + Fastpath + Provides FastPath Agent functionality. + + + + Jive Software + spark@jivesoftware.com + + Author + + + + diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/FastpathContainer.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/FastpathContainer.java similarity index 92% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/FastpathContainer.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/FastpathContainer.java index 9cdd4c5ea..9a8f827af 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/FastpathContainer.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/FastpathContainer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,11 +18,9 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; -import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; -import java.lang.reflect.InvocationTargetException; import javax.swing.BorderFactory; import javax.swing.JPanel; @@ -38,8 +32,8 @@ */ public class FastpathContainer extends JPanel { private static final long serialVersionUID = 1651363083075622414L; - private JPanel topPanel; - private SparkTabbedPane mainPanel; + private final JPanel topPanel; + private final SparkTabbedPane mainPanel; public FastpathContainer() { diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/FastpathPlugin.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/FastpathPlugin.java similarity index 79% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/FastpathPlugin.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/FastpathPlugin.java index 44fe01a76..5fafc9fd4 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/FastpathPlugin.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/FastpathPlugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,26 +15,6 @@ */ package org.jivesoftware.fastpath; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.EventQueue; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.lang.reflect.InvocationTargetException; -import java.util.*; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; - import org.jivesoftware.fastpath.resources.FastpathRes; import org.jivesoftware.fastpath.workspace.Workpane; import org.jivesoftware.fastpath.workspace.panes.BackgroundPane; @@ -47,7 +23,7 @@ import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smackx.disco.packet.DiscoverItems; import org.jivesoftware.smackx.workgroup.agent.Agent; import org.jivesoftware.smackx.workgroup.agent.AgentSession; @@ -60,8 +36,19 @@ import org.jivesoftware.spark.util.SwingWorker; import org.jivesoftware.spark.util.TaskEngine; import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.EntityFullJid; +import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.util.XmppStringUtils; +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.util.Collection; +import java.util.Collections; +import java.util.TimerTask; + public class FastpathPlugin implements Plugin, ConnectionListener { private static Workgroup wgroup; private static AgentSession agentSession; @@ -70,7 +57,7 @@ public class FastpathPlugin implements Plugin, ConnectionListener { private static BackgroundPane mainPanel; private static FastpathContainer container; private JLabel workgroupLabel; - private JComboBox comboBox; + private JComboBox comboBox; private JButton joinButton; private RolloverButton logoutButton; private static boolean wasConnected; @@ -79,21 +66,18 @@ public class FastpathPlugin implements Plugin, ConnectionListener { public void initialize() { - EventQueue.invokeLater(new Runnable() { - - @Override - public void run() { - container = new FastpathContainer(); - workgroupLabel = new JLabel(FpRes.getString("workgroup")); - comboBox = new JComboBox(); - joinButton = new JButton(FpRes.getString("join"), null); - logoutButton = new RolloverButton(FpRes.getString("logout"), null); - // Initialize tab handler for Fastpath chats. - fastpathTabHandler = new FastpathTabHandler(); - mainPanel = new BackgroundPane(); - } - - }); + new WorkgroupInitializer().initialize(); + + EventQueue.invokeLater(() -> { + container = new FastpathContainer(); + workgroupLabel = new JLabel(FpRes.getString("workgroup")); + comboBox = new JComboBox<>(); + joinButton = new JButton(FpRes.getString("join"), null); + logoutButton = new RolloverButton(FpRes.getString("logout"), null); + // Initialize tab handler for Fastpath chats. + fastpathTabHandler = new FastpathTabHandler(); + mainPanel = new BackgroundPane(); + }); @@ -104,11 +88,11 @@ public void run() { try { DiscoverItems items = SparkManager.getSessionManager().getDiscoveredItems(); for (DiscoverItems.Item item : items.getItems() ) { - String entityID = item.getEntityID() != null ? item.getEntityID() : ""; + String entityID = item.getEntityID() != null ? item.getEntityID().toString() : ""; if (entityID.startsWith("workgroup")) { // Log into workgroup - final String workgroupService = "workgroup." + SparkManager.getSessionManager().getServerAddress(); - final String jid = SparkManager.getSessionManager().getJID(); + final DomainBareJid workgroupService = JidCreate.domainBareFromOrThrowUnchecked("workgroup." + SparkManager.getSessionManager().getServerAddress()); + final EntityFullJid jid = SparkManager.getSessionManager().getJID(); SwingWorker worker = new SwingWorker() { @@ -116,7 +100,7 @@ public Object construct() { try { return Agent.getWorkgroups(workgroupService, jid, SparkManager.getConnection()); } - catch (XMPPException | SmackException e1) { + catch (XMPPException | SmackException | InterruptedException e1) { return Collections.emptyList(); } } @@ -157,9 +141,7 @@ private void showSelection(Collection col) { logoutButton.setVisible(false); // Add workgroups to combobox - Iterator workgroups = col.iterator(); - while (workgroups.hasNext()) { - String workgroup = (String)workgroups.next(); + for (String workgroup : col) { String componentAddress = XmppStringUtils.parseDomain(workgroup); setComponentAddress(componentAddress); comboBox.addItem(XmppStringUtils.parseLocalpart(workgroup)); @@ -201,11 +183,7 @@ public void actionPerformed(ActionEvent actionEvent) { joinButton.addActionListener(joinAction); // Load services immeditaly. - Thread loadServicesThread = new Thread(new Runnable() { - public void run() { - SparkManager.getChatManager().getDefaultConferenceService(); - } - }); + Thread loadServicesThread = new Thread(() -> SparkManager.getChatManager().getDefaultConferenceService()); loadServicesThread.start(); } @@ -261,21 +239,6 @@ public void connected( XMPPConnection xmppConnection ) @Override public void authenticated( XMPPConnection xmppConnection, boolean b ) { - - } - - public void connectionClosed() { - lostConnection(); - } - - public void connectionClosedOnError(Exception e) { - lostConnection(); - } - - public void reconnectingIn(int seconds) { - } - - public void reconnectionSuccessful() { // Rejoin the workgroup after 15 seconds. final TimerTask rejoinTask = new SwingTimerTask() { public void doRun() { @@ -288,17 +251,20 @@ public void doRun() { TaskEngine.getInstance().schedule(rejoinTask, 15000); } - public void reconnectionFailed(Exception e) { + public void connectionClosed() { + lostConnection(); + } + + public void connectionClosedOnError(Exception e) { + lostConnection(); } private void lostConnection() { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - if (agentSession != null) { - resetWorkgroups(); - wasConnected = true; - agentSession = null; - } + SwingUtilities.invokeLater(() -> { + if (agentSession != null) { + resetWorkgroups(); + wasConnected = true; + agentSession = null; } }); @@ -325,13 +291,13 @@ public void finished() { logoutButton.setVisible(true); joinButton.setVisible(false); comboBox.setVisible(false); - String workgroup = comboBox.getSelectedItem() + "@" + getComponentAddress(); + EntityBareJid workgroup = JidCreate.entityBareFromOrThrowUnchecked(comboBox.getSelectedItem() + "@" + getComponentAddress()); if (agentSession != null && agentSession.isOnline()) { try { agentSession.setOnline(false); agentSession.setOnline(true); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error(e); leaveWorkgroup(); joinButton.setEnabled(true); @@ -343,7 +309,7 @@ public void finished() { try { agentSession.setOnline(true); } - catch (XMPPException | SmackException e1) { + catch (XMPPException | SmackException | InterruptedException e1) { Log.error(e1); leaveWorkgroup(); joinButton.setEnabled(true); @@ -353,7 +319,12 @@ public void finished() { // Send actual presence to workgroup. final Presence actualPresence = SparkManager.getWorkspace().getStatusBar().getPresence(); - Presence toWorkgroupPresence = new Presence(actualPresence.getType(), actualPresence.getStatus(), actualPresence.getPriority(), actualPresence.getMode()); + Presence toWorkgroupPresence = StanzaBuilder.buildPresence() + .ofType(actualPresence.getType()) + .setStatus(actualPresence.getStatus()) + .setPriority(actualPresence.getPriority()) + .setMode(actualPresence.getMode()) + .build(); toWorkgroupPresence.setTo(workgroup); try { @@ -386,21 +357,19 @@ private void leaveWorkgroup() { comboBox.removeAllItems(); // Log into workgroup - String workgroupService = "workgroup." + SparkManager.getSessionManager().getServerAddress(); - String jid = SparkManager.getSessionManager().getJID(); + DomainBareJid workgroupService = JidCreate.domainBareFromOrThrowUnchecked("workgroup." + SparkManager.getSessionManager().getServerAddress()); + EntityFullJid jid = SparkManager.getSessionManager().getJID(); try { Collection col = Agent.getWorkgroups(workgroupService, jid, SparkManager.getConnection()); // Add workgroups to combobox - Iterator workgroups = col.iterator(); - while (workgroups.hasNext()) { - String workgroup = workgroups.next(); + for (String workgroup : col) { String componentAddress = XmppStringUtils.parseDomain(workgroup); setComponentAddress(componentAddress); comboBox.addItem(XmppStringUtils.parseLocalpart(workgroup)); } } - catch (XMPPException | SmackException ee) { + catch (XMPPException | SmackException | InterruptedException ee) { // If the user does not belong to a workgroup, then don't initialize the rest of the plugin. return; } @@ -408,7 +377,7 @@ private void leaveWorkgroup() { try { agentSession.setOnline(false); } - catch (XMPPException | SmackException e1) { + catch (XMPPException | SmackException | InterruptedException e1) { Log.error(e1); } litWorkspace.unload(); diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/FastpathTabHandler.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/FastpathTabHandler.java similarity index 96% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/FastpathTabHandler.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/FastpathTabHandler.java index 406310c79..e17a9eb20 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/FastpathTabHandler.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/FastpathTabHandler.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -59,7 +55,7 @@ private void handleFastpathRoom(SparkTab tab, ChatRoom room, boolean isSelectedT // Check if is typing. if (isTyping) { - tab.setIcon(SparkRes.getImageIcon(SparkRes.SMALL_MESSAGE_EDIT_IMAGE)); + tab.setIcon(SparkRes.getImageIcon(SparkRes.Icon.SMALL_MESSAGE_EDIT_IMAGE)); } else { tab.setIcon(FastpathRes.getImageIcon(FastpathRes.FASTPATH_IMAGE_16x16)); diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/FpRes.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/FpRes.java similarity index 81% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/FpRes.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/FpRes.java index 382c41139..c266db3d3 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/FpRes.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/FpRes.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,6 +15,7 @@ */ package org.jivesoftware.fastpath; +import org.jivesoftware.resource.UTF8Control; import org.jivesoftware.spark.util.log.Log; import java.text.MessageFormat; @@ -26,22 +23,19 @@ import java.util.ResourceBundle; /** - * */ public class FpRes { - private static PropertyResourceBundle prb; + private static final PropertyResourceBundle prb; private FpRes() { } - static ClassLoader cl = FpRes.class.getClassLoader(); - static { - prb = (PropertyResourceBundle)ResourceBundle.getBundle("i18n/fastpath_i18n"); + prb = (PropertyResourceBundle)ResourceBundle.getBundle("i18n/fastpath_i18n", new UTF8Control()); } - public static final String getString(String propertyName) { + public static String getString(String propertyName) { try { return prb.getString(propertyName); } @@ -52,7 +46,7 @@ public static final String getString(String propertyName) { } - public static final String getString(String propertyName, Object... obj) { + public static String getString(String propertyName, Object... obj) { String str = prb.getString(propertyName); if (str == null) { return null; diff --git a/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/WorkgroupInitializer.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/WorkgroupInitializer.java new file mode 100644 index 000000000..2cff2e6ef --- /dev/null +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/WorkgroupInitializer.java @@ -0,0 +1,27 @@ +package org.jivesoftware.fastpath; + +/** + * Fastpath / Workgroup related code is available in smack-legacy.jar. Sadly, only part of the IQ providers and packet + * extensions is loaded by default by Smack (see SMACK-729 in the issue tracker). + *

      + * To work around this issue, this class initializes the remaining classes. This class should no longer be needed when + * the original problem in Smack is fixed. + * + * @author Guus der Kinderen, guus.der.kinderen@gmail.com + * @see Issue SMACK-729 + */ + +import org.jivesoftware.smack.initializer.UrlInitializer; + +public class WorkgroupInitializer extends UrlInitializer +{ + public WorkgroupInitializer() + { + } + + @Override + protected String getProvidersUri() { + return "classpath:org.jivesoftware.smack.legacy/legacy.providers"; + } +} + diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/internal/FormText.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/internal/FormText.java similarity index 94% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/internal/FormText.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/internal/FormText.java index 4a014e400..bb6330f74 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/internal/FormText.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/internal/FormText.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,6 +19,8 @@ import java.util.Date; import org.jivesoftware.smackx.workgroup.settings.ChatSetting; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.impl.JidCreate; public class FormText { @@ -32,7 +30,7 @@ public class FormText { public static String getChatRoomWelcomeMessage(String agent, String workgroup) { String value = getTextSetting("acceptedChat_text", workgroup); value = FormUtils.replace(value, "${agent}", agent); - value = FormUtils.replace(value, "'", "\\\'"); + value = FormUtils.replace(value, "'", "\\'"); value = FormUtils.replace(value, "\n", "
      "); return value.trim(); @@ -117,7 +115,7 @@ public static String getQueueFooter(String workgroup) { public static String getNoAgentText(String workgroup) { String value = getTextSetting("no_agent_text", workgroup); - value = FormUtils.replace(value, "'", "\\\'"); + value = FormUtils.replace(value, "'", "\\'"); value = FormUtils.replace(value, "\n", "
      "); return value.trim(); @@ -131,7 +129,8 @@ public static String getTransferToAgentText(String workgroup) { return getTextSetting("transferChat_text", workgroup); } - public static String getTextSetting(String key, String workgroup) { + public static String getTextSetting(String key, String workgroupString) { + EntityBareJid workgroup = JidCreate.entityBareFromUnescapedOrThrowUnchecked(workgroupString); WorkgroupManager settingsManager = WorkgroupManager.getInstance(); ChatSetting chatSettings = settingsManager.getChatSetting(key, workgroup); diff --git a/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/internal/FormUtils.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/internal/FormUtils.java new file mode 100644 index 000000000..58fe87b21 --- /dev/null +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/internal/FormUtils.java @@ -0,0 +1,158 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.fastpath.internal; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.packet.Message; +import org.jxmpp.jid.parts.Resourcepart; + +import java.util.Date; + +/** + * The WebUtils class is a utility class for some of the most + * mundane procedures in the WebChat client and in servlet programming. This + * will be moved over to a more suitable class down the line. Probably be handled + * in the com.jivesoftware.web.utils package to be used throughout Jive. + */ +final public class FormUtils { + private FormUtils() { + } + + /** + * Check to see if string has been assigned a value. This is generally used + * in web applications/applet when a user request a parameter from the parameter stack. + * + * @param str - the string to check. + * @return true if String has been assigned a value, false otherwise. + */ + public static boolean isNotNull(String str) { + return str != null && str.trim().length() > 0; + } + + /** + * Checks to see if the String is boolean value and will return the appropriate + * value + * + * @param str - the String to check + * @return true if the string is not null and the value is equal to true, false + * otherwise. + */ + public static boolean isTrue(String str) { + return Boolean.parseBoolean(str); + } + + + /** + * Checks to see if the data is applicable to be added to metadata. + * + * @param data the data to check for validity. + * @return true if the data is valid. + */ + public static boolean isValidData(String data) { + char[] chars = data.toCharArray(); + for (char c : chars) { + if (Character.isLetterOrDigit(c)) { + return true; + } + } + return false; + } + + + + /** + * Replaces all instances of oldString with newString in string. + * + * @param string the String to search to perform replacements on + * @param oldString the String that should be replaced by newString + * @param newString the String that will replace all instances of oldString + * @return a String will all instances of oldString replaced by newString + */ + public static String replace(String string, String oldString, String newString) { + if (string == null) { + return null; + } + // If the newString is null or zero length, just return the string since there's nothing + // to replace. + if (newString == null) { + return string; + } + int i = 0; + // Make sure that oldString appears at least once before doing any processing. + if ((i = string.indexOf(oldString, i)) >= 0) { + // Use char []'s, as they are more efficient to deal with. + char[] string2 = string.toCharArray(); + char[] newString2 = newString.toCharArray(); + int oLength = oldString.length(); + StringBuilder buf = new StringBuilder(string2.length); + buf.append(string2, 0, i).append(newString2); + i += oLength; + int j = i; + // Replace all remaining instances of oldString with newString. + while ((i = string.indexOf(oldString, i)) > 0) { + buf.append(string2, j, i - j).append(newString2); + i += oLength; + j = i; + } + buf.append(string2, j, string2.length - j); + return buf.toString(); + } + return string; + } + + /** + * Validate the given text - to pass it must contain letters, digits, '@', '-', '_', '.', ',' + * or a space character. + * + * @param text the text to check + * @return true if the given text is valid, false otherwise. + */ + public boolean validateChars(String text) { + for (int i = 0; i < text.length(); i++) { + char ch = text.charAt(i); + if (!Character.isLetterOrDigit(ch) && ch != '@' && ch != '-' && ch != '_' + && ch != '.' && ch != ',' && ch != ' ') { + return false; + } + } + return true; + } + + + public static String getPushedURL(String body) { + String urlToPush; + int index = body.indexOf("]"); + urlToPush = body.substring(index + 1); + int index2 = urlToPush.indexOf("http://"); + int httpsIndex = urlToPush.indexOf("https"); + if (index2 == -1 && httpsIndex == -1) { + urlToPush = "http://" + urlToPush; + } + + return urlToPush; + } + + /** + * Returns the nickname of the user who sent the message. + * + * @param message the message sent. + * @return the nickname of the user who sent the message. + */ + public static Resourcepart getNickname(Message message) { + return message.getFrom().getResourceOrThrow(); + } + +} diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/internal/LiveTitlePane.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/internal/LiveTitlePane.java similarity index 96% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/internal/LiveTitlePane.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/internal/LiveTitlePane.java index 9ed6a0ef8..7cdf07ae2 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/internal/LiveTitlePane.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/internal/LiveTitlePane.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/internal/WorkgroupDataForm.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/internal/WorkgroupDataForm.java similarity index 76% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/internal/WorkgroupDataForm.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/internal/WorkgroupDataForm.java index 5d8dc8d1a..2f82d6648 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/internal/WorkgroupDataForm.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/internal/WorkgroupDataForm.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,8 +17,11 @@ import org.jivesoftware.spark.component.CheckBoxList; import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.smackx.xdata.Form; import org.jivesoftware.smackx.xdata.FormField; +import org.jivesoftware.smackx.xdata.FormFieldWithOptions; +import org.jivesoftware.smackx.xdata.ListSingleFormField; +import org.jivesoftware.smackx.xdata.form.FillableForm; +import org.jivesoftware.smackx.xdata.form.Form; import java.awt.Component; import java.awt.GridBagConstraints; @@ -53,11 +52,11 @@ */ public class WorkgroupDataForm extends JPanel { private static final long serialVersionUID = -2368907321868842234L; - private final Map valueMap = new HashMap(); + private final Map valueMap = new HashMap<>(); private int row = 5; - private Form searchForm; - private Map presetVariables = new HashMap(); - private List requiredList = new ArrayList(); + private final Form searchForm; + private final Map presetVariables; + private final List requiredList = new ArrayList<>(); private EnterListener listener; @@ -66,7 +65,7 @@ public class WorkgroupDataForm extends JPanel { * * @param form the DataForm to build a UI with. */ - public WorkgroupDataForm(Form form, Map presetVariables) { + public WorkgroupDataForm(Form form, Map presetVariables) { this.presetVariables = presetVariables; this.setLayout(new GridBagLayout()); this.searchForm = form; @@ -79,8 +78,8 @@ public WorkgroupDataForm(Form form, Map presetVariables) { private void buildUI(Form form) { // Add default answers to the form to submit - for ( final FormField field : form.getFields() ) { - String variable = field.getVariable(); + for ( final FormField field : form.getDataForm().getFields() ) { + String variable = field.getFieldName(); if(field.isRequired()){ requiredList.add(variable); } @@ -92,13 +91,10 @@ private void buildUI(Form form) { String label = field.getLabel(); FormField.Type type = field.getType(); - List valueList = new ArrayList(); - for ( String value : field.getValues() ) { - valueList.add( value ); - } + List valueList = new ArrayList<>(field.getValues()); if (type.equals(FormField.Type.bool)) { - String o = (String)valueList.get(0); + String o = valueList.get(0).toString(); boolean isSelected = o.equals("1"); JCheckBox box = new JCheckBox(label); box.setSelected(isSelected); @@ -107,15 +103,18 @@ private void buildUI(Form form) { else if (type.equals(FormField.Type.text_single) || type.equals(FormField.Type.jid_single)) { String v = ""; if (valueList.size() > 0) { - v = (String)valueList.get(0); + v = valueList.get(0).toString(); } addField(label, new JTextField(v), variable); } else if (type.equals(FormField.Type.text_multi) || type.equals(FormField.Type.jid_multi)) { - StringBuffer buf = new StringBuffer(); - for ( final FormField.Option option : field.getOptions() ) { - buf.append(option); + StringBuilder buf = new StringBuilder(); + if (field instanceof FormFieldWithOptions) { + FormFieldWithOptions formFieldWithOptions = (FormFieldWithOptions) field; + for ( final FormField.Option option : formFieldWithOptions.getOptions() ) { + buf.append(option); + } } addField(label, new JTextArea(buf.toString()), variable); } @@ -123,9 +122,9 @@ else if (type.equals(FormField.Type.text_private)) { addField(label, new JPasswordField(), variable); } else if (type.equals(FormField.Type.list_single)) { - JComboBox box = new JComboBox(); - for ( final FormField.Option option : field.getOptions() ) { - String value = option.getValue(); + ListSingleFormField listSingleFormField = field.ifPossibleAsOrThrow(ListSingleFormField.class); + JComboBox box = new JComboBox<>(); + for ( final FormField.Option option : listSingleFormField.getOptions() ) { box.addItem(option); } if (valueList.size() > 0) { @@ -137,8 +136,8 @@ else if (type.equals(FormField.Type.list_single)) { } else if (type.equals(FormField.Type.list_multi)) { CheckBoxList checkBoxList = new CheckBoxList(); - for ( final String value : field.getValues() ) { - checkBoxList.addCheckBox(new JCheckBox(value), value); + for ( final CharSequence value : field.getValues() ) { + checkBoxList.addCheckBox(new JCheckBox(value.toString()), value.toString()); } addField(label, checkBoxList, variable); } @@ -150,19 +149,19 @@ else if (type.equals(FormField.Type.list_multi)) { * * @return the answered DataForm. */ - public Form getFilledForm() { + public FillableForm getFilledForm() { // Now submit all information Iterator valueIter = valueMap.keySet().iterator(); - Form answerForm = searchForm.createAnswerForm(); + FillableForm answerForm = searchForm.getFillableForm(); while (valueIter.hasNext()) { - String answer = (String)valueIter.next(); + String answer = valueIter.next(); Object o = valueMap.get(answer); if (o instanceof JCheckBox) { boolean isSelected = ((JCheckBox)o).isSelected(); answerForm.setAnswer(answer, isSelected); } else if (o instanceof JTextArea) { - List list = new ArrayList(); + List list = new ArrayList<>(); String value = ((JTextArea)o).getText(); StringTokenizer tokenizer = new StringTokenizer(value, ", ", false); while (tokenizer.hasMoreTokens()) { @@ -179,44 +178,29 @@ else if (o instanceof JTextField) { } } else if (o instanceof JComboBox) { - Object v = ((JComboBox)o).getSelectedItem(); - String value = ""; - if (v instanceof FormField.Option) { - value = ((FormField.Option)v).getValue(); - } - else { - value = (String)v; - } - List list = new ArrayList(); + Object v = ((JComboBox) o).getSelectedItem(); + String value = (v instanceof FormField.Option) ? ((FormField.Option) v).getValue().toString() : (String) v; + + List list = new ArrayList<>(); list.add(value); if (list.size() > 0) { answerForm.setAnswer(answer, list); } } else if (o instanceof CheckBoxList) { - List list = (List)((CheckBoxList)o).getSelectedValues(); + List list = ((CheckBoxList) o).getSelectedValues(); if (list.size() > 0) { answerForm.setAnswer(answer, list); } } } - final Iterator keys = presetVariables.keySet().iterator(); - while(keys.hasNext()){ - String variable = (String)keys.next(); - String value = (String)presetVariables.get(variable); + for (Object o : presetVariables.keySet()) { + String variable = (String) o; + String value = presetVariables.get(variable); answerForm.setAnswer(variable, value); } - final Iterator iter = requiredList.iterator(); - while(iter.hasNext()){ - String variable = (String)iter.next(); - FormField field = answerForm.getField(variable); - if(field != null){ - field.setRequired(true); - } - } - return answerForm; } @@ -253,13 +237,12 @@ public void keyPressed(KeyEvent e) { } public Component getComponent(String label) { - Component comp = (Component)valueMap.get(label); - return comp; + return valueMap.get(label); } private String getValue(String label) { - Component comp = (Component)valueMap.get(label); + Component comp = valueMap.get(label); if (comp instanceof JCheckBox) { return "" + ((JCheckBox)comp).isSelected(); } diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/internal/WorkgroupManager.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/internal/WorkgroupManager.java similarity index 78% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/internal/WorkgroupManager.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/internal/WorkgroupManager.java index 132d73f80..571452bce 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/internal/WorkgroupManager.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/internal/WorkgroupManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,13 +21,10 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -48,12 +41,14 @@ import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.muc.MultiUserChat; -import org.jivesoftware.smackx.xdata.Form; +import org.jivesoftware.smackx.workgroup.packet.QueueOverview; +import org.jivesoftware.smackx.workgroup.packet.WorkgroupInformation; import org.jivesoftware.smackx.xdata.FormField; +import org.jivesoftware.smackx.xdata.form.FillableForm; +import org.jivesoftware.smackx.xdata.form.FilledForm; +import org.jivesoftware.smackx.xdata.form.Form; import org.jivesoftware.smackx.vcardtemp.packet.VCard; import org.jivesoftware.smackx.workgroup.settings.ChatSetting; import org.jivesoftware.smackx.workgroup.settings.ChatSettings; @@ -71,7 +66,10 @@ import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.spark.util.SwingWorker; import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.EntityJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.parts.Localpart; /** @@ -82,8 +80,8 @@ public class WorkgroupManager { * Stores the ChatSettings of each workgroup, and will be updated * when packet date of workgroup changes. */ - private Map chatSettings = new HashMap(); - private Set invites = new HashSet(); + private final Map chatSettings = new HashMap<>(); + private final Set invites = new HashSet<>(); private static WorkgroupManager singleton; @@ -149,10 +147,10 @@ public void contactItemClicked(ContactItem item) { * @param workgroupName the name of the workgroup * @return the ChatSetting found with the specified key. */ - public ChatSetting getChatSetting(String key, String workgroupName) { + public ChatSetting getChatSetting(String key, EntityBareJid workgroupName) { ChatSettings settings = null; if (chatSettings.containsKey(workgroupName)) { - settings = (ChatSettings)chatSettings.get(workgroupName); + settings = chatSettings.get(workgroupName); } else { XMPPConnection connection = SparkManager.getConnection(); @@ -161,7 +159,7 @@ public ChatSetting getChatSetting(String key, String workgroupName) { settings = workgroup.getChatSettings(); chatSettings.put(workgroupName, settings); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error("Error retrieving chat setting using key=" + key + " and workgroup=" + workgroupName, e); } } @@ -175,18 +173,10 @@ public ChatSetting getChatSetting(String key, String workgroupName) { private void showWorkgroup(final ContactItem contactItem) throws Exception { VCard vcard = SparkManager.getVCardManager().getVCard(); - final Map variables = new HashMap(); - String firstName = vcard.getFirstName(); - String lastName = vcard.getLastName(); - - if (ModelUtil.hasLength(firstName) && ModelUtil.hasLength(lastName)) { - variables.put("username", firstName + " " + lastName); - } - else if (ModelUtil.hasLength(firstName)) { - variables.put("username", firstName); - } - else if (ModelUtil.hasLength(lastName)) { - variables.put("username", lastName); + final Map variables = new HashMap<>(); + String fullName = vcard.getField("FN"); + if (ModelUtil.hasLength(fullName)) { + variables.put("username", fullName); } String email = vcard.getEmailHome(); @@ -201,14 +191,14 @@ else if (ModelUtil.hasLength(lastName)) { } - String workgroupJID = contactItem.getJID(); - String nameOfWorkgroup = XmppStringUtils.parseLocalpart(workgroupJID); + EntityBareJid workgroupJID = contactItem.getJid().asEntityBareJidOrThrow(); + Localpart nameOfWorkgroup = workgroupJID.getLocalpart(); final JDialog workgroupDialog = new JDialog(SparkManager.getMainWindow(), "Contact " + nameOfWorkgroup + " Workgroup"); Workgroup workgroup = new Workgroup(workgroupJID, SparkManager.getConnection()); final Form workgroupForm = workgroup.getWorkgroupForm(); - String welcomeText = FormText.getWelcomeText(workgroupJID); - String startButton = FormText.getStartButton(workgroupJID); + String welcomeText = FormText.getWelcomeText(workgroupJID.toString()); + String startButton = FormText.getStartButton(workgroupJID.toString()); final WorkgroupDataForm formUI = new WorkgroupDataForm(workgroupForm, variables); formUI.setBackground(Color.white); @@ -227,22 +217,20 @@ public Dimension getPreferredSize() { formUI.add(titlePane, new GridBagConstraints(0, 0, 3, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); final JButton submitButton = new JButton("Start Chat!"); - submitButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (validateForm(workgroupDialog, workgroupForm, formUI.getFilledForm())) { - enterQueue(contactItem.getJID(), formUI.getFilledForm()); - workgroupDialog.dispose(); - } + submitButton.addActionListener(e -> { + FillableForm form = formUI.getFilledForm(); + if (validateForm(workgroupDialog, workgroupForm, form)) { + enterQueue(contactItem.getJid().asEntityBareJidOrThrow(), form); + workgroupDialog.dispose(); } }); - formUI.setEnterListener(new WorkgroupDataForm.EnterListener() { - public void enterPressed() { - if (validateForm(workgroupDialog, workgroupForm, formUI.getFilledForm())) { - enterQueue(contactItem.getJID(), formUI.getFilledForm()); - workgroupDialog.dispose(); - } + formUI.setEnterListener(() -> { + FillableForm form = formUI.getFilledForm(); + if (validateForm(workgroupDialog, workgroupForm, form)) { + enterQueue(contactItem.getJid().asEntityBareJidOrThrow(), form); + workgroupDialog.dispose(); } }); @@ -258,10 +246,10 @@ public void enterPressed() { workgroupDialog.setVisible(true); } - private static boolean validateForm(JDialog parent, Form workgroupForm, Form form) { - for ( final FormField field : form.getFields()) { + private static boolean validateForm(JDialog parent, Form workgroupForm, FilledForm form) { + for ( final FormField field : form.getDataForm().getFields()) { if (field.isRequired() && field.getValues().isEmpty()) { - String variable = field.getVariable(); + String variable = field.getFieldName(); String elementName = workgroupForm.getField(variable).getLabel(); UIManager.put("OptionPane.okButtonText", Res.getString("ok")); JOptionPane.showMessageDialog(parent, variable + " is required to complete the form.", "Incomplete Form", JOptionPane.ERROR_MESSAGE); @@ -274,11 +262,10 @@ private static boolean validateForm(JDialog parent, Form workgroupForm, Form for public void handleContactItem(final ContactItem contactItem) { Presence presence = contactItem.getPresence(); - - ExtensionElement workgroup = presence.getExtension("workgroup", "http://jivesoftware.com/protocol/workgroup"); - ExtensionElement notifyQueue = presence.getExtension("notify-queue", "http://jabber.org/protocol/workgroup"); - - if (workgroup == null && notifyQueue == null) { + // TODO It probably can be WorkgroupInformation.class but it has namespace http://jabber.org/protocol/workgroup + boolean hasWorkgroup = presence.hasExtension("workgroup", "http://jivesoftware.com/protocol/workgroup"); + boolean hasNotifyQueue = presence.hasExtension(QueueOverview.class); + if (!hasWorkgroup && !hasNotifyQueue) { return; } @@ -291,8 +278,8 @@ public void handleContactItem(final ContactItem contactItem) { } } - private void enterQueue(String workgroupJID, Form form) { - String workgroupName = XmppStringUtils.parseLocalpart(workgroupJID).toUpperCase(); + private void enterQueue(EntityBareJid workgroupJID, FillableForm form) { + Localpart workgroupName = workgroupJID.getLocalpart(); final JDialog workgroupDialog = new JDialog(SparkManager.getMainWindow(), workgroupName + " Workgroup"); @@ -301,7 +288,7 @@ private void enterQueue(String workgroupJID, Form form) { try { workgroup.joinQueue(form); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error(e); } @@ -330,16 +317,15 @@ public Dimension getPreferredSize() { final JButton leaveQueueButton = new JButton("Leave Queue"); mainPanel.add(queueWaitTime, new GridBagConstraints(0, 3, 4, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - leaveQueueButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (workgroup.isInQueue()) { - try { - invites.add(workgroup.getWorkgroupJID()); - workgroup.departQueue(); - } - catch (XMPPException | SmackException e1) { - Log.error(e1); - } + + leaveQueueButton.addActionListener(e -> { + if (workgroup.isInQueue()) { + try { + invites.add(workgroup.getWorkgroupJID()); + workgroup.departQueue(); + } + catch (XMPPException | SmackException | InterruptedException e1) { + Log.error(e1); } } }); @@ -359,7 +345,7 @@ public void windowClosing(WindowEvent e) { try { workgroup.departQueue(); } - catch (XMPPException | SmackException e1) { + catch (XMPPException | SmackException | InterruptedException e1) { Log.error(e1); } } @@ -371,7 +357,7 @@ public Object construct() { while (true) { if (workgroup.isInQueue()) { queuePostionLabel.setText("Current Position in Queue: " + workgroup.getQueuePosition()); - queueWaitTime.setText("It is estimated your wait time to now be " + FormUtils.getTimeFromLong(workgroup.getQueueRemainingTime())); + queueWaitTime.setText("It is estimated your wait time to now be " + ModelUtil.getTimeFromLong(workgroup.getQueueRemainingTime())); } else { return true; @@ -406,11 +392,11 @@ public void finished() { private class InviteListener implements RoomInvitationListener { // Add own invitation listener @Override - public boolean handleInvitation(final XMPPConnection conn, final MultiUserChat room, final String inviter, final String reason, final String password, final Message message) { + public boolean handleInvitation(final XMPPConnection conn, final MultiUserChat room, final EntityBareJid inviter, final String reason, final String password, final Message message) { invites.add(inviter); - if (message.getExtension("workgroup", "http://jabber.org/protocol/workgroup") != null) { - String workgroupName = XmppStringUtils.parseLocalpart(inviter); + if (message.hasExtension(WorkgroupInformation.class)) { + Localpart workgroupName = inviter.getLocalpart(); GroupChatRoom groupChatRoom = ConferenceUtils.enterRoomOnSameThread(workgroupName, room.getRoom(), password); int tabLocation = SparkManager.getChatManager().getChatContainer().indexOfComponent(groupChatRoom); diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/resources/FastpathRes.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/resources/FastpathRes.java similarity index 94% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/resources/FastpathRes.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/resources/FastpathRes.java index 761feb05d..9a9184376 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/resources/FastpathRes.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/resources/FastpathRes.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +16,7 @@ package org.jivesoftware.fastpath.resources; import org.jivesoftware.fastpath.FastpathPlugin; +import org.jivesoftware.spark.util.log.Log; import javax.swing.ImageIcon; import javax.swing.JEditorPane; @@ -34,7 +31,7 @@ import java.util.ResourceBundle; public class FastpathRes { - private static PropertyResourceBundle prb; + private static final PropertyResourceBundle prb; public static final String NOTE_EDIT_16x16 = "NOTE_EDIT_16x16"; public static final String MAGICIAN_IMAGE = "MAGICIAN_IMAGE"; @@ -251,45 +248,48 @@ public class FastpathRes { public static final String CLOSE_DARK_X_IMAGE = "CLOSE_DARK_X_IMAGE"; public static final String CLOSE_WHITE_X_IMAGE = "CLOSE_WHITE_X_IMAGE"; public static final String CHAT_INVITE_IMAGE_24x24 = "CHAT_INVITE_IMAGE_24x24"; - public static final String CHAT_TRANSFER_IMAGE_24x24 = "CHAT_TRANSFER_IMAGE_24x24"; - public static final String CHAT_COBROWSE_IMAGE_24x24 = "CHAT_COBROWSE_IMAGE_24x24"; - public static final String CHAT_ENDED_IMAGE_24x24 = "CHAT_ENDED_IMAGE_24x24"; + public static final String CHAT_TRANSFER_IMAGE_24x24 = "CHAT_TRANSFER_IMAGE_24x24"; + public static final String CHAT_COBROWSE_IMAGE_24x24 = "CHAT_COBROWSE_IMAGE_24x24"; + public static final String CHAT_ENDED_IMAGE_24x24 = "CHAT_ENDED_IMAGE_24x24"; - - static ClassLoader cl = FastpathPlugin.class.getClassLoader(); + private static final ClassLoader cl = FastpathPlugin.class.getClassLoader(); static { prb = (PropertyResourceBundle)ResourceBundle.getBundle("fastpath"); } - public static final String getString(String propertyName) { + public static String getString(String propertyName) { return prb.getString(propertyName); } - public static final ImageIcon getImageIcon(String imageName) { + public static ImageIcon getImageIcon(String imageName) { try { final String iconURI = getString(imageName); final URL imageURL = cl.getResource(iconURI); - return new ImageIcon(imageURL); + if (imageURL != null) { + return new ImageIcon(imageURL); + } else { + Log.warning(imageName + " not found."); + } } - catch (Exception ex) { - System.out.println(imageName + " not found."); + catch (Exception e) { + Log.warning("Unable to load image " + imageName, e); } return null; } - public static final URL getURL(String propertyName) { + public static URL getURL(String propertyName) { return cl.getResource(getString(propertyName)); } - public static void main(String args[]) { + public static void main(String[] args) { JFrame frame = new JFrame(); frame.getContentPane().setLayout(new BorderLayout()); JEditorPane pane = new JEditorPane(); frame.getContentPane().add(new JScrollPane(pane)); - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); Enumeration enumeration = prb.getKeys(); while (enumeration.hasMoreElements()) { String token = enumeration.nextElement(); @@ -330,4 +330,4 @@ private static void checkImageDir() { } } } -} \ No newline at end of file +} diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/FastpathListener.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/FastpathListener.java similarity index 94% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/FastpathListener.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/FastpathListener.java index 03d99e237..1aeb1be9e 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/FastpathListener.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/FastpathListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,7 +21,6 @@ import javax.swing.JTabbedPane; /** - * */ public interface FastpathListener { diff --git a/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/Workpane.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/Workpane.java new file mode 100644 index 000000000..e5d759c93 --- /dev/null +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/Workpane.java @@ -0,0 +1,732 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.fastpath.workspace; + +import org.jivesoftware.MainWindow; +import org.jivesoftware.Spark; +import org.jivesoftware.fastpath.FastpathPlugin; +import org.jivesoftware.fastpath.FpRes; +import org.jivesoftware.fastpath.resources.FastpathRes; +import org.jivesoftware.fastpath.workspace.assistants.*; +import org.jivesoftware.fastpath.workspace.invite.InvitationManager; +import org.jivesoftware.fastpath.workspace.invite.WorkgroupInvitationDialog; +import org.jivesoftware.fastpath.workspace.macros.MacrosEditor; +import org.jivesoftware.fastpath.workspace.panes.*; +import org.jivesoftware.fastpath.workspace.search.ChatSearch; +import org.jivesoftware.fastpath.workspace.util.RequestUtils; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jivesoftware.smackx.workgroup.MetaData; +import org.jivesoftware.smackx.workgroup.agent.*; +import org.jivesoftware.smackx.workgroup.user.Workgroup; +import org.jivesoftware.smackx.xdata.form.Form; +import org.jivesoftware.spark.DataManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.search.SearchManager; +import org.jivesoftware.spark.ui.*; +import org.jivesoftware.spark.ui.conferences.ConferenceUtils; +import org.jivesoftware.spark.ui.conferences.GroupChatParticipantList; +import org.jivesoftware.spark.ui.conferences.RoomInvitationListener; +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Localpart; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import java.awt.*; +import java.awt.event.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.*; +import java.util.List; + +import static org.jivesoftware.spark.Event.CHAT_REQUEST; + +public class Workpane { + // Tracks all the offers coming into the client. + private final Map offerMap = new HashMap<>(); + private final Map>> inviteMap = new HashMap<>(); + private final Map invitations = new HashMap<>(); + + private final Map fastpathRooms = new HashMap<>(); + + private final OnlineAgents onlineAgentsPane; + private AgentConversations agentCons; + private final ChatOfferListener offerListener; + private final RoomInvitationListener roomInviteListener; + private final ChatSearch chatSearch; + + private final QueueActivity queueActivity; + + private final RolloverButton historyButton; + private final RolloverButton workgroupGroupButton; + private final RolloverButton macrosButton; + + public static final String INITIAL_RESPONSE_PROPERTY = "initialResponse"; + + private final JPanel toolbar; + private final List listeners = new ArrayList<>(); + private final PresenceChangeListener presenceListener = new PresenceChangeListener(); + + /** + * Type of states a fastpath room can be in. + */ + public enum RoomState { + /** + * The room contains an incoming request. + */ + incomingRequest, + /** + * The room contains an invitation from another agent. + */ + invitationRequest, + /** + * The room is in an active state. + */ + activeRoom + } + + public Workpane() { + onlineAgentsPane = new OnlineAgents(); + agentCons = new AgentConversations(); + offerListener = new ChatOfferListener(); + roomInviteListener = new InviteListener(); + chatSearch = new ChatSearch(); + + addOnlineAgents(); + handleRoomOpenings(); + + FastpathPlugin.getUI().getMainPanel().addTab(FpRes.getString("tab.current.chats"), null, agentCons); + SearchManager.getInstance().addSearchService(chatSearch); + + // Add Queue Activity Menu + queueActivity = new QueueActivity(); + setupQueueViewer(); + + // Add presence listener. This is used to send presence changes to the workgroup itself. + SparkManager.getSessionManager().addPresenceListener(presenceListener); + + toolbar = new JPanel(new FlowLayout(FlowLayout.LEFT)); + toolbar.setOpaque(false); + historyButton = new RolloverButton(); + ResourceUtils.resButton(historyButton, FpRes.getString("button.history")); + toolbar.add(historyButton); + historyButton.setIcon(FastpathRes.getImageIcon(FastpathRes.HISTORY_16x16)); + + historyButton.addActionListener(e -> { + final ChatHistory chatHistory = new ChatHistory(); + chatHistory.showDialog(); + }); + + workgroupGroupButton = new RolloverButton(); + ResourceUtils.resButton(workgroupGroupButton, FpRes.getString("button.conference")); + workgroupGroupButton.setIcon(FastpathRes.getImageIcon(FastpathRes.CONFERENCE_IMAGE_16x16)); + toolbar.add(workgroupGroupButton); + + workgroupGroupButton.addActionListener(e -> { + final Workgroup workgroup = FastpathPlugin.getWorkgroup(); + String serviceName = "conference." + SparkManager.getSessionManager().getServerAddress(); + final EntityBareJid roomName = JidCreate.entityBareFromOrThrowUnchecked("workgroup-" + workgroup.getWorkgroupJID().getLocalpartOrThrow() + "@" + serviceName); + ConferenceUtils.joinConferenceOnSeparateThread("Workgroup Chat", roomName, null, null); + }); + + macrosButton = new RolloverButton(FastpathRes.getImageIcon(FastpathRes.NOTEBOOK_IMAGE)); + ResourceUtils.resButton(macrosButton, FpRes.getString("button.macros")); + + macrosButton.addActionListener(e -> { + MacrosEditor editor = new MacrosEditor(); + editor.showEditor(macrosButton); + }); + toolbar.add(macrosButton); + + FastpathPlugin.getMainPanel().add(toolbar, new GridBagConstraints(0, 2, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 2, 2, 2), 0, 0)); + } + + + public void unload() { + FastpathPlugin.getUI().getMainPanel().removeComponent(onlineAgentsPane); + // Remove offer listener + FastpathPlugin.getAgentSession().removeOfferListener(offerListener); + // Add own invitation listener + SparkManager.getChatManager().removeInvitationListener(roomInviteListener); + // Remove Chat Search + SearchManager.getInstance().removeSearchService(chatSearch); + // Remove Queue Listener + queueActivity.removeListener(); + FastpathPlugin.getUI().getMainPanel().removeComponent(queueActivity); + FastpathPlugin.getUI().getMainPanel().removeComponent(agentCons); + agentCons = null; + FastpathPlugin.getMainPanel().remove(toolbar); + SparkManager.getSessionManager().removePresenceListener(presenceListener); + } + + private void addOnlineAgents() { + FastpathPlugin.getUI().getMainPanel().addTab(FpRes.getString("tab.online.agents"), null, onlineAgentsPane); + } + + public void listenForOffers() { + FastpathPlugin.getAgentSession().addOfferListener(offerListener); + // Add own invitation listener + SparkManager.getChatManager().addInvitationListener(roomInviteListener); + } + + public Map> getMetadata(String sessionID) { + Map> map = null; + Offer offer = offerMap.get(sessionID); + if (offer != null) { + map = offer.getMetaData(); + } + else { + Map> metadata = inviteMap.get(sessionID); + if (metadata != null) { + map = metadata; + } + } + return map; + } + + private void handleRoomOpenings() { + SparkManager.getChatManager().addChatRoomListener(new ChatRoomListener() { + @Override + public void chatRoomOpened(ChatRoom room) { + if (!(room instanceof GroupChatRoom)) { + return; + } + GroupChatRoom groupChatRoom = (GroupChatRoom) room; + EntityBareJid roomName = room.getBareJid(); + Localpart sessionID = roomName.getLocalpart(); + Offer offer = offerMap.get(sessionID.toString()); + if (offer != null) { + Map> metadata = offer.getMetaData(); + decorateRoom(groupChatRoom, metadata); + } + } + + @Override + public void chatRoomClosed(ChatRoom room) { + EntityBareJid roomName = room.getBareJid(); + Localpart sessionID = roomName.getLocalpart(); + offerMap.remove(sessionID.toString()); + } + }); + } + + public void checkForDecoration(GroupChatRoom chatRoom, String sessionID) { + Map> metadata = inviteMap.get(sessionID); + if (metadata != null) { + decorateRoom(chatRoom, metadata); + } + } + + public void decorateRoom(GroupChatRoom room, Map> metadata) { + EntityBareJid roomName = room.getBareJid(); + Localpart sessionID =roomName.getLocalpart(); + RequestUtils utils = new RequestUtils(metadata); + addRoomInfo(sessionID, utils, room); + addButtons(sessionID.toString(), utils, room); + // Specify to use Typing notifications. + room.setChatStatEnabled(true); + + Properties props = FastpathPlugin.getLitWorkspace().getWorkgroupProperties(); + String initialResponse = props.getProperty(INITIAL_RESPONSE_PROPERTY); + if (ModelUtil.hasLength(initialResponse)) { + room.sendMessage(initialResponse); + } + } + + private void addButtons(final String sessionID, final RequestUtils utils, final ChatRoom room) { + final ChatRoomButton inviteButton = new ChatRoomButton(FastpathRes.getImageIcon(FastpathRes.CHAT_INVITE_IMAGE_24x24)); + final ChatRoomButton transferButton = new ChatRoomButton(FastpathRes.getImageIcon(FastpathRes.CHAT_TRANSFER_IMAGE_24x24)); + final RolloverButton cannedResponses = new RolloverButton(FastpathRes.getImageIcon(FastpathRes.DOWN_ARROW_IMAGE)); + final ChatRoomButton endButton = new ChatRoomButton(FastpathRes.getImageIcon(FastpathRes.CHAT_ENDED_IMAGE_24x24)); + final ChatRoomButton cobrowseButton = new ChatRoomButton(FastpathRes.getImageIcon(FastpathRes.CHAT_COBROWSE_IMAGE_24x24)); + + // Set tooltips + inviteButton.setToolTipText("Invite another user to join in this conversation."); + transferButton.setToolTipText("Transfer this conversation to another agent."); + endButton.setToolTipText("End this conversation."); + cobrowseButton.setToolTipText("Start a co-browsing session with this user."); + + // Update Canned Response button. + ResourceUtils.resButton(cannedResponses, FpRes.getString("button.canned.responses")); + + room.getToolBar().addChatRoomButton(inviteButton); + room.getToolBar().addChatRoomButton(transferButton); + room.getToolBar().addChatRoomButton(cobrowseButton); + room.getToolBar().addChatRoomButton(endButton); + + inviteButton.addActionListener(e -> inviteOrTransfer(room, utils.getWorkgroup(), sessionID, false)); + + cobrowseButton.addActionListener(e -> { + CoBrowser browser = new CoBrowser(sessionID, room); + browser.showDialog(); + }); + + transferButton.addActionListener(actionEvent -> inviteOrTransfer(room, utils.getWorkgroup(), sessionID, true)); + + room.getEditorBar().add(cannedResponses); + cannedResponses.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + final ChatMacroMenu chatMacroMenu = new ChatMacroMenu(room); + chatMacroMenu.show(cannedResponses, e.getX(), e.getY()); + } + }); + + endButton.addActionListener(actionEvent -> { + final GroupChatRoom groupChatRoom = (GroupChatRoom)room; + groupChatRoom.leaveChatRoom(); + }); + + // Set Room is Active + addFastpathChatRoom(room, RoomState.activeRoom); + } + + /** + * Invite or transfer this conversation to another agent, queue or workgroup. + * + * @param room the ChatRoom. + * @param sessionID the current sessionid of this conversation. + * @param transfer true if you wish to transfer this room. + */ + private void inviteOrTransfer(ChatRoom room, String workgroup, String sessionID, boolean transfer) { + WorkgroupInvitationDialog dialog = new WorkgroupInvitationDialog(); + + boolean ok = dialog.hasSelectedAgent(room, transfer); + if (ok) { + String jidString = dialog.getSelectedJID(); + Jid jid = JidCreate.fromUnescapedOrThrowUnchecked(jidString); + + String message = dialog.getMessage(); + // Determine who to send to. + if (jid.hasResource()) { + InvitationManager.transferOrInviteToQueue(room, workgroup, sessionID, jid, message, transfer); + } + else if (jid.getDomain().toString().startsWith("workgroup")) { + InvitationManager.transferOrInviteToWorkgroup(room, workgroup, sessionID, jid, message, transfer); + } + else { + InvitationManager.transferOrInviteUser(room, workgroup, sessionID, jid, message, transfer); + } + } + } + + private void addRoomInfo(final CharSequence sessionID, final RequestUtils utils, final GroupChatRoom room) { + final JTabbedPane tabbedPane = new JTabbedPane(); + + GroupChatParticipantList participantList = room.getConferenceRoomInfo(); + room.getSplitPane().setRightComponent(tabbedPane); + + Form form; + try { + form = FastpathPlugin.getWorkgroup().getWorkgroupForm(); + } + catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + return; + } + + final BackgroundPane transcriptAlert = new BackgroundPane() { + @Override + public Dimension getPreferredSize() { + final Dimension size = super.getPreferredSize(); + size.width = 0; + return size; + } + }; + transcriptAlert.setLayout(new GridBagLayout()); + + JLabel userImage = new JLabel(FastpathRes.getImageIcon(FastpathRes.FASTPATH_IMAGE_24x24)); + userImage.setHorizontalAlignment(JLabel.LEFT); + userImage.setText(utils.getUsername()); + transcriptAlert.add(userImage, new GridBagConstraints(0, 0, 4, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + userImage.setFont(new Font("Dialog", Font.BOLD, 12)); + + + final RoomInformation roomInformation = new RoomInformation(); + roomInformation.showFormInformation(form, utils); + final UserHistory userHistory = new UserHistory(utils.getUserID()); + + final JScrollPane userScroll = new JScrollPane(roomInformation); + final JScrollPane historyScroll = new JScrollPane(userHistory); + historyScroll.getVerticalScrollBar().setBlockIncrement(50); + historyScroll.getVerticalScrollBar().setUnitIncrement(20); + + tabbedPane.addTab(FpRes.getString("tab.user.info"), userScroll); + tabbedPane.addTab(FpRes.getString("tab.participants"), participantList); + tabbedPane.addTab(FpRes.getString("tab.user.history"), historyScroll); + + final Notes notes = new Notes(sessionID, room); + + tabbedPane.addTab(FpRes.getString("tab.notes"), notes); + + + tabbedPane.addChangeListener(new ChangeListener() { + boolean loaded; + + @Override + public void stateChanged(ChangeEvent e) { + if (!loaded) { + if (tabbedPane.getSelectedComponent() == historyScroll) { + userHistory.loadHistory(); + loaded = true; + } + } + } + }); + + room.getTranscriptWindow().clear(); + + final ChatFrame frame = SparkManager.getChatManager().getChatContainer().getChatFrame(); + if (frame != null) { + int height = frame.getHeight(); + int width = frame.getWidth(); + if (height < 400) { + height = 400; + } + + if (width < 600) { + width = 600; + } + + frame.setSize(width, height); + frame.validate(); + frame.repaint(); + } + + fireFastPathChatOpened(room, sessionID.toString(), utils, tabbedPane); + DataManager.getInstance().setMetadataForRoom(room, utils.getMetadata()); + } + + public void blink() { + final MainWindow mainWindow = SparkManager.getMainWindow(); + + if (!mainWindow.isFocused()) { + // Set to a new tab. + if (Spark.isWindows()) { + mainWindow.addWindowListener(new WindowAdapter() { + @Override + public void windowActivated(WindowEvent e) { + SparkManager.getNativeManager().stopFlashing(mainWindow); + } + }); + + // Flash the window or restore it from a minimized state if unfocused and visible + if (!mainWindow.isFocused() && mainWindow.isVisible()) { + SparkManager.getNativeManager().flashWindow(mainWindow); + } + else if (!mainWindow.isVisible()) { + mainWindow.setState(Frame.ICONIFIED); + mainWindow.setVisible(true); + SparkManager.getNativeManager().flashWindow(mainWindow); + } + } + } + } + + private class ChatOfferListener implements OfferListener { + ChatQueue chatQueue; + private SparkToaster toasterManager; + + @Override + public void offerReceived(final Offer offer) { + SwingUtilities.invokeLater(() -> handleOffer(offer)); + } + + private void handleOffer(final Offer offer) { + if (offer.getContent() instanceof InvitationRequest || offer.getContent() instanceof TransferRequest) { + handleOfferInvite(offer); + return; + } + + chatQueue = new ChatQueue(); + chatQueue.offerRecieved(offer); + + toasterManager = new SparkToaster(); + toasterManager.setHidable(false); + toasterManager.setToasterHeight((int)chatQueue.getPreferredSize().getHeight() + 40); + + int width = (int)chatQueue.getPreferredSize().getWidth() + 40; + if (width < 300) { + width = 300; + } + toasterManager.setToasterWidth(width); + toasterManager.setDisplayTime(500000000); + + final JScrollPane pane = new JScrollPane(chatQueue, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + pane.setBorder(BorderFactory.createEmptyBorder()); + toasterManager.showToaster("Incoming Fastpath Request", pane); + toasterManager.hideTitle(); + + chatQueue.getAcceptButton().addActionListener(e -> { + toasterManager.close(); + chatQueue.setVisible(false); + + offerMap.put(offer.getSessionID(), offer); + try + { + offer.accept(); + } + catch ( SmackException.NotConnectedException | InterruptedException e1 ) + { + Log.warning( "Unable to accept offer from " + offer.getUserJID(), e1 ); + } + }); + + chatQueue.getDeclineButton().addActionListener(e -> { + toasterManager.close(); + chatQueue.setVisible(false); + try + { + offer.reject(); + } + catch ( SmackException.NotConnectedException | InterruptedException e1 ) + { + Log.warning( "Unable to reject offer from " + offer.getUserJID(), e1 ); + } + SparkManager.getWorkspace().remove(chatQueue); + offerMap.remove(offer.getSessionID()); + }); + + SparkManager.getSoundManager().playClip(CHAT_REQUEST); + } + + @Override + public void offerRevoked(final RevokedOffer revokedOffer) { + SwingUtilities.invokeLater(() -> { + SparkManager.getNativeManager().stopFlashing(SparkManager.getMainWindow()); + if (toasterManager != null) { + toasterManager.close(); + } + // If the ChatQueue is visible, dispose of it. + if (chatQueue != null) { + chatQueue.setVisible(false); + return; + } + UserInvitationPane pane = invitations.get(revokedOffer.getSessionID()); + if (pane != null) { + pane.dispose(); + invitations.remove(revokedOffer.getSessionID()); + } + }); + } + } + + private class InviteListener implements RoomInvitationListener { + // Add own invitation listener + @Override + public boolean handleInvitation(final XMPPConnection conn, final MultiUserChat chat, final EntityBareJid inviter, final String reason, final String password, final Message message) { + if (offerMap.containsKey(reason)) { + RequestUtils utils = new RequestUtils(getMetadata(reason)); + String roomName = utils.getUsername() != null ? utils.getUsername() : chat.getRoom().getLocalpart().asUnescapedString(); + + // Create the Group Chat Room + GroupChatRoom groupChatRoom = ConferenceUtils.enterRoomOnSameThread(roomName, chat.getRoom(), password); + groupChatRoom.getSplitPane().setDividerSize(5); + groupChatRoom.getVerticalSlipPane().setDividerLocation(0.6); + groupChatRoom.getSplitPane().setDividerLocation(0.6); + + groupChatRoom.getConferenceRoomInfo().setNicknameChangeAllowed(false); + + groupChatRoom.getToolBar().setVisible(true); + fastpathRooms.put(groupChatRoom, RoomState.activeRoom); + + final ChatContainer chatContainer = SparkManager.getChatManager().getChatContainer(); + chatContainer.setChatRoomTitle(groupChatRoom, roomName); + try { + if (chatContainer.getActiveChatRoom() == groupChatRoom) { + chatContainer.getChatFrame().setTitle(roomName); + } + } + catch (ChatRoomNotFoundException e) { + Log.debug(e.getMessage()); + } + + SparkManager.getChatManager().notifySparkTabHandlers(groupChatRoom); + + // Change the subject line. + groupChatRoom.setRoomLabel("Fastpath Conversation with " + roomName + ""); + return true; + } + else if (message != null) { + MetaData metaDataExt = message.getExtension(MetaData.class); + if (metaDataExt != null) { + Map> metadata = metaDataExt.getMetaData(); + List values = new ArrayList<>(); + values.add(chat.getRoom().getLocalpart().toString()); + metadata.put("sessionID", values); + + RequestUtils utils = new RequestUtils(metadata); + inviteMap.put(utils.getSessionID(), metadata); + InvitationPane pane = new InvitationPane(utils, chat.getRoom(), inviter, reason, password, message); + return true; + } + } + + return false; + } + } + + /** + * Handles incoming invitations or transfers. + * + * @param offer the Offer + */ + public void handleOfferInvite(final Offer offer) { + Map> metadata = offer.getMetaData(); + String sessionID = offer.getSessionID(); + List values = new ArrayList<>(); + values.add(sessionID); + metadata.put("sessionID", values); + + RequestUtils utils = new RequestUtils(metadata); + inviteMap.put(sessionID, metadata); + + UserInvitationPane invitationPane = null; + + if (offer.getContent() instanceof InvitationRequest) { + InvitationRequest request = (InvitationRequest)offer.getContent(); + EntityBareJid room = JidCreate.entityBareFromOrThrowUnchecked(request.getRoom()); + EntityBareJid inviter = JidCreate.entityBareFromOrThrowUnchecked(request.getInviter()); + invitationPane = new UserInvitationPane(offer, utils, room, inviter, request.getReason()); + } + else if (offer.getContent() instanceof TransferRequest) { + TransferRequest request = (TransferRequest)offer.getContent(); + EntityBareJid room = JidCreate.entityBareFromOrThrowUnchecked(request.getRoom()); + EntityBareJid inviter = JidCreate.entityBareFromOrThrowUnchecked(request.getInviter()); + invitationPane = new UserInvitationPane(offer, utils, room, inviter, request.getReason()); + } + + invitationPane.setAcceptListener(new UserInvitationPane.AcceptListener() { + @Override + public void yesOption() { + // Remove + invitations.remove(offer.getSessionID()); + } + + @Override + public void noOption() { + invitations.remove(offer.getSessionID()); + } + }); + + invitations.put(offer.getSessionID(), invitationPane); + } + + + public Properties getWorkgroupProperties() { + Localpart workgroupName = FastpathPlugin.getWorkgroup().getWorkgroupJID().getLocalpartOrThrow(); + File workgroupDir = new File(Spark.getSparkUserHome(), "workgroups/" + workgroupName); + workgroupDir.mkdirs(); + + File propertiesFile = new File(workgroupDir, "workgroup.properties"); + Properties props = new Properties(); + try { + props.load(new FileInputStream(propertiesFile)); + } + catch (IOException e) { + // File does not exist. + } + return props; + } + + public void saveProperties(Properties props) { + Localpart workgroupName = FastpathPlugin.getWorkgroup().getWorkgroupJID().getLocalpartOrThrow(); + File propertiesFile = new File(new File(Spark.getSparkUserHome(), "workgroups/" + workgroupName), "workgroup.properties"); + try { + props.store(new FileOutputStream(propertiesFile), "Workgroup Properties"); + } + catch (IOException e) { + Log.error("Unable to save group properties.", e); + } + } + + private void setupQueueViewer() { + FastpathPlugin.getUI().getMainPanel().addTab(FpRes.getString("tab.queue.activity"), null, queueActivity); + } + + public void addFastPathListener(FastpathListener listener) { + listeners.add(listener); + } + + public void removeFastPathListener(FastpathListener listener) { + listeners.remove(listener); + } + + + private void fireFastPathChatOpened( ChatRoom room, String sessionID, RequestUtils utils, JTabbedPane tabbedPane ) + { + for ( final FastpathListener listener : listeners ) + { + try + { + listener.fastpathRoomOpened( room, sessionID, utils, tabbedPane ); + } + catch ( Exception e ) + { + Log.error( "A FastpathListener (" + listener + ") threw an exception while processing a 'fastpathRoomOpened' event for: " + room + " in session: " + sessionID, e ); + } + } + } + + private static class PresenceChangeListener implements PresenceListener { + @Override + public void presenceChanged(Presence presence) { + String status = presence.getStatus(); + if (status == null) { + status = ""; + } + + try { + if (FastpathPlugin.getAgentSession().isOnline()) { + FastpathPlugin.getAgentSession().setStatus(presence.getMode(), status); + } + } + catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + } + } + } + + public void addFastpathChatRoom(ChatRoom chatRoom, RoomState state) { + fastpathRooms.put(chatRoom, state); + } + + public void removeFastpathChatRoom(ChatRoom chatRoom) { + fastpathRooms.remove(chatRoom); + } + + public RoomState getRoomState(ChatRoom chatRoom) { + return fastpathRooms.get(chatRoom); + } +} diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/ChatMacroMenu.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/ChatMacroMenu.java similarity index 80% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/ChatMacroMenu.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/ChatMacroMenu.java index f715bca0d..6d0af8bba 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/ChatMacroMenu.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/ChatMacroMenu.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,9 +16,6 @@ package org.jivesoftware.fastpath.workspace.assistants; import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Iterator; import java.util.List; import javax.swing.JMenu; @@ -64,7 +57,7 @@ public ChatMacroMenu(ChatRoom room) { try { globalMacros = FastpathPlugin.getAgentSession().getMacros(true); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { // Not Global Macros Set Log.error("No global macros have been set."); } @@ -89,7 +82,7 @@ public ChatMacroMenu(ChatRoom room) { try { personalGroup = FastpathPlugin.getAgentSession().getMacros(false); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error("No personal macros set."); } @@ -122,46 +115,34 @@ public ChatMacroMenu(ChatRoom room) { popup.addSeparator(); popup.add(editMacros); - editMacros.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - MacrosEditor editor = new MacrosEditor(); - editor.showEditor(editMacros); - } + editMacros.addActionListener(e -> { + MacrosEditor editor = new MacrosEditor(); + editor.showEditor(editMacros); }); } private void addSubMenus(JMenu menu, List macroGroups) { - Iterator subFolders = macroGroups.iterator(); - while (subFolders.hasNext()) { - MacroGroup folder = subFolders.next(); + for (MacroGroup folder : macroGroups) { JMenu subMenu = new JMenu(folder.getTitle()); menu.add(subMenu); addMenuItems(subMenu, folder.getMacros()); - - addSubMenus(subMenu, folder.getMacroGroups()); - } } private void addMenuItems(JMenu menu, List macros) { - Iterator items = macros.iterator(); - while (items.hasNext()) { - final Macro newItem = items.next(); + for (Macro newItem : macros) { final JMenuItem item = new JMenuItem(newItem.getTitle()); menu.add(item); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - String text = newItem.getResponse() + " "; - try { - chatRoom.getChatInputEditor().insertText(text); - } - catch (BadLocationException e1) { - Log.error("Error inserting macro", e1); - } + item.addActionListener(e -> { + String text = newItem.getResponse() + " "; + try { + chatRoom.getChatInputEditor().insertText(text); + } catch (BadLocationException e1) { + Log.error("Error inserting macro", e1); } }); } diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/CoBrowser.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/CoBrowser.java similarity index 94% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/CoBrowser.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/CoBrowser.java index a28be011f..645acc11c 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/CoBrowser.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/CoBrowser.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,6 +26,7 @@ import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.swing.Icon; @@ -48,9 +45,10 @@ import org.jivesoftware.fastpath.workspace.util.RequestUtils; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; import org.jivesoftware.smackx.xevent.MessageEventManager; -import org.jivesoftware.smackx.workgroup.util.ModelUtil; import org.jivesoftware.spark.ChatManager; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.component.RolloverButton; @@ -60,6 +58,7 @@ import org.jivesoftware.spark.ui.ChatRoom; import org.jivesoftware.spark.ui.rooms.GroupChatRoom; import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.spark.util.log.Log; @@ -71,7 +70,7 @@ public class CoBrowser extends JPanel implements ActionListener, BrowserListener { private static final long serialVersionUID = 1115198448380589259L; private boolean isShowing; - private ChatRoom chatRoom; + private final ChatRoom chatRoom; private final JTextField pushField = new JTextField(); private JCheckBox followMeButton; private RolloverButton goButton; @@ -82,7 +81,7 @@ public class CoBrowser extends JPanel implements ActionListener, BrowserListener private BrowserViewer browser; private JTextField urlField; - private String sessionID; + private final String sessionID; // Define Constants private final static String PUBLIC_TOOLTIP = FpRes.getString("tooltip.allow.cobrowsing"); @@ -212,7 +211,7 @@ private void startFollowMeSession(String url) { // If the disable box is not selected, update customer with // page push. /* - final Message mes = new Message(); + MessageBuilder mes = StanzaBuilder.buildMessage(); mes.setProperty("PUSH_URL", link); mes.setBody("Start a Co-Browsing session with [b]" + link + "[/b]"); @@ -231,7 +230,7 @@ private void pushPage(String link) { // If the disable box is not selected, update customer with // page push. - final Message mes = new Message(); + MessageBuilder mes = StanzaBuilder.buildMessage(); final Map properties = new HashMap<>(); properties.put( "PUSH_URL", link ); mes.addExtension( new JivePropertiesExtension( properties ) ); @@ -263,7 +262,7 @@ public void loadWithoutNotification(String url) { private void navigateUser(String href) { if (followMeButton.isSelected() && hasLoaded) { - final Message mes = new Message(); + MessageBuilder mes = StanzaBuilder.buildMessage(); final Map properties = new HashMap<>(); properties.put( "PUSH_URL", href ); mes.addExtension( new JivePropertiesExtension( properties ) ); @@ -371,7 +370,7 @@ public void documentLoaded(String documentURL) { } private String getStartLocation() { - Map metadata = FastpathPlugin.getLitWorkspace().getMetadata(sessionID); + Map> metadata = FastpathPlugin.getLitWorkspace().getMetadata(sessionID); RequestUtils utils = new RequestUtils(metadata); String location = utils.getRequestLocation(); if (location == null) { @@ -380,17 +379,19 @@ private String getStartLocation() { return location; } - private void send(Message message) { + private void send(MessageBuilder messageBuilder) { GroupChatRoom groupChatRoom = (GroupChatRoom)chatRoom; try { - message.setTo(groupChatRoom.getRoomname()); - message.setType(Message.Type.groupchat); + messageBuilder.ofType(Message.Type.groupchat); + + Message message = messageBuilder.build(); + message.setTo(groupChatRoom.getBareJid()); MessageEventManager.addNotificationsRequests(message, true, true, true, true); - groupChatRoom.getMultiUserChat().sendMessage(message); + groupChatRoom.getMultiUserChat().sendMessage(messageBuilder); } - catch (SmackException ex) { + catch (SmackException | InterruptedException ex) { Log.error("Unable to send message in conference chat.", ex); } diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/Notes.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/Notes.java similarity index 91% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/Notes.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/Notes.java index f902a1477..5880ea956 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/Notes.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/Notes.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -49,7 +45,6 @@ import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.component.RolloverButton; import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomClosingListener; import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.spark.util.ResourceUtils; import org.jivesoftware.spark.util.SwingWorker; @@ -59,25 +54,25 @@ public class Notes extends JPanel { private static final long serialVersionUID = -7789684145607565950L; private JFrame notesFrame; - private JScrollPane scrollPane; - private JTextPane textPane; + private final JScrollPane scrollPane; + private final JTextPane textPane; - private JToolBar toolBar; - private RolloverButton saveButton; + private final JToolBar toolBar; + private final RolloverButton saveButton; - private String sessionID; + private final String sessionID; private boolean hasClickedInPane; - private JLabel statusLabel; + private final JLabel statusLabel; - private ChatRoom chatRoom; + private final ChatRoom chatRoom; private boolean updated; - public Notes(String sessionID, ChatRoom room) { + public Notes(CharSequence sessionID, ChatRoom room) { setLayout(new BorderLayout()); this.chatRoom = room; - this.sessionID = sessionID; + this.sessionID = sessionID.toString(); textPane = new JTextPane(); textPane.setText(FpRes.getString("message.click.to.add.notes")); @@ -143,11 +138,9 @@ public void removeUpdate(DocumentEvent e) { statusLabel = new JLabel(); this.add(statusLabel, BorderLayout.SOUTH); - chatRoom.addClosingListener(new ChatRoomClosingListener() { - public void closing() { - if (updated) { - saveNotes(); - } + chatRoom.addClosingListener(() -> { + if (updated) { + saveNotes(); } }); } @@ -202,7 +195,7 @@ public void finished() { }; worker.start(); } - catch (XMPPException | SmackException e1) { + catch (XMPPException | SmackException | InterruptedException e1) { showError(FpRes.getString("message.unable.to.update.notes")); Log.error("Could not commit note.", e1); } @@ -222,7 +215,7 @@ public void showError(String error) { * @param newString the String that will replace all instances of oldString * @return a String will all instances of oldString replaced by newString */ - public static final String replace(String string, String oldString, String newString) { + public static String replace(String string, String oldString, String newString) { if (string == null) { return null; } @@ -238,7 +231,7 @@ public static final String replace(String string, String oldString, String newSt char[] string2 = string.toCharArray(); char[] newString2 = newString.toCharArray(); int oLength = oldString.length(); - StringBuffer buf = new StringBuffer(string2.length); + StringBuilder buf = new StringBuilder(string2.length); buf.append(string2, 0, i).append(newString2); i += oLength; int j = i; diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/RoomInformation.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/RoomInformation.java similarity index 94% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/RoomInformation.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/RoomInformation.java index 5038a14af..b1f225180 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/RoomInformation.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/RoomInformation.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,8 +19,8 @@ import org.jivesoftware.fastpath.internal.LiveTitlePane; import org.jivesoftware.fastpath.resources.FastpathRes; import org.jivesoftware.fastpath.workspace.util.RequestUtils; -import org.jivesoftware.smackx.xdata.Form; import org.jivesoftware.smackx.xdata.FormField; +import org.jivesoftware.smackx.xdata.form.Form; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.component.LinkLabel; import org.jivesoftware.spark.component.WrappedLabel; @@ -40,6 +36,7 @@ import java.awt.event.MouseEvent; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import javax.swing.JFrame; @@ -56,9 +53,9 @@ public RoomInformation() { } - public void showAllInformation(Map map) { + public void showAllInformation(Map> map) { if (map == null) { - map = new HashMap(); + map = new HashMap<>(); } LiveTitlePane titlePanel = new LiveTitlePane(FpRes.getString("title.request.information"), FastpathRes.getImageIcon(FastpathRes.FASTPATH_IMAGE_24x24)); @@ -100,8 +97,8 @@ public void showFormInformation(Form form, final RequestUtils utils) { setBackground(Color.white); int count = 1; - for ( final FormField field : form.getFields() ) { - String variable = field.getVariable(); + for ( final FormField field : form.getDataForm().getFields() ) { + String variable = field.getFieldName(); String label = field.getLabel(); if (label != null) { final JLabel nameLabel = new JLabel(label); diff --git a/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/UserHistory.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/UserHistory.java new file mode 100644 index 000000000..73aef7b85 --- /dev/null +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/UserHistory.java @@ -0,0 +1,169 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.fastpath.workspace.assistants; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; + +import javax.swing.DefaultListModel; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JPanel; + +import org.jivesoftware.fastpath.FastpathPlugin; +import org.jivesoftware.fastpath.FpRes; +import org.jivesoftware.fastpath.workspace.panes.ChatViewer; +import org.jivesoftware.fastpath.workspace.panes.HistoryItemRenderer; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.workgroup.packet.Transcript; +import org.jivesoftware.smackx.workgroup.packet.Transcripts; +import org.jivesoftware.smackx.workgroup.packet.Transcripts.TranscriptSummary; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.EntityBareJid; + +public class UserHistory extends JPanel { + private static final long serialVersionUID = -1067239194964815379L; + private final DefaultListModel model = new DefaultListModel<>(); + private final JList list; + private final EntityBareJid userID; + + private JFrame frame; + + public UserHistory(EntityBareJid userID) { + this.userID = userID; + + list = new JList<>(model); + list.setCellRenderer(new HistoryItemRenderer()); + + final JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BorderLayout()); + mainPanel.setBackground(Color.white); + mainPanel.add(list, BorderLayout.CENTER); + + setLayout(new BorderLayout()); + add(mainPanel, BorderLayout.CENTER); + + list.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + UserHistoryItem historyItem = list.getSelectedValue(); + showTranscript(historyItem.getSessionID()); + } + } + }); + + + } + + public void loadHistory() { + + SwingWorker transcriptThread = new SwingWorker() { + final List transcriptList = new ArrayList<>(); + + public Object construct() { + try { + Transcripts transcripts = FastpathPlugin.getAgentSession().getTranscripts(userID); + transcriptList.addAll(transcripts.getSummaries()); + } + catch (XMPPException | SmackException | InterruptedException e) { + Log.error("Error getting transcripts.", e); + } + + transcriptList.sort(timeComparator); + return transcriptList; + } + + public void finished() { + init(transcriptList); + } + }; + + transcriptThread.start(); + } + + public void init(Collection transcriptList) { + model.removeAllElements(); + for (TranscriptSummary summary : transcriptList) { + UserHistoryItem item = new UserHistoryItem(summary.getAgentDetails(), summary.getJoinTime(), summary.getLeftTime()); + item.setSessionID(summary.getSessionID()); + model.addElement(item); + } + + list.validate(); + list.repaint(); + + } + + private void showTranscript(String sessionID) { + if (frame == null) { + frame = new JFrame(FpRes.getString("title.transcript")); + frame.setIconImage(SparkManager.getMainWindow().getIconImage()); + } + + if (frame.isVisible()) { + return; + } + + Transcript transcript = null; + try { + transcript = FastpathPlugin.getAgentSession().getTranscript(sessionID); + } + catch (XMPPException | SmackException | InterruptedException e) { + Log.error("Error showing transcripts.", e); + } + + if (transcript == null) { + return; + } + final ChatViewer chatViewer = new ChatViewer(transcript); + frame.getContentPane().removeAll(); + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(chatViewer, BorderLayout.CENTER); + frame.pack(); + frame.setSize(600, 400); + + frame.setLocationRelativeTo(SparkManager.getMainWindow()); + frame.setVisible(true); + } + + + /** + * Lets make sure that the panel doesn't stretch past the + * scrollpane view pane. + * + * @return the preferred dimension + */ + public Dimension getPreferredSize() { + final Dimension size = super.getPreferredSize(); + size.width = 0; + return size; + } + + private final Comparator timeComparator = (first, second) -> + Long.compare(second.getJoinTime().getTime(), first.getJoinTime().getTime()); +} + + diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/UserHistoryItem.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/UserHistoryItem.java similarity index 94% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/UserHistoryItem.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/UserHistoryItem.java index 283c193bb..6ae057fca 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/UserHistoryItem.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/assistants/UserHistoryItem.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -42,9 +38,9 @@ public class UserHistoryItem extends JPanel { private static final long serialVersionUID = -2251709231519173523L; - private WrappedLabel agentsLabel = new WrappedLabel(); - private JLabel startTimeLabel = new JLabel(); - private JLabel durationLabel = new JLabel(); + private final WrappedLabel agentsLabel = new WrappedLabel(); + private final JLabel startTimeLabel = new JLabel(); + private final JLabel durationLabel = new JLabel(); private String sessionID; @@ -79,7 +75,7 @@ public UserHistoryItem(Collection agentDetails, Date jo add(startTimeLabel, new GridBagConstraints(1, 3, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); startTimeLabel.setText(theDate); - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); Iterator agents = agentDetails.iterator(); while (agents.hasNext()) { Transcripts.AgentDetail agentDetail = agents.next(); diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/invite/InvitationManager.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/invite/InvitationManager.java similarity index 83% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/invite/InvitationManager.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/invite/InvitationManager.java index 4eb4e297b..9ba839a95 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/invite/InvitationManager.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/invite/InvitationManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,9 +15,6 @@ */ package org.jivesoftware.fastpath.workspace.invite; -import java.util.ArrayList; -import java.util.List; - import org.jivesoftware.fastpath.FastpathPlugin; import org.jivesoftware.fastpath.FpRes; import org.jivesoftware.smack.SmackException; @@ -33,10 +26,9 @@ import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.ui.ChatRoom; import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.Jid; public class InvitationManager { - private static List inviteListeners = new ArrayList(); - private InvitationManager() { } @@ -50,8 +42,8 @@ private InvitationManager() { * @param messageText the message to send to the user. * @param transfer true if this is a transfer. */ - public static void transferOrInviteUser(ChatRoom chatRoom, String workgroup, String sessionID, final String jid, String messageText, final boolean transfer) { - String msg = messageText != null ? StringUtils.escapeForXML(messageText).toString() : FpRes.getString("message.please.join.me.in.conference"); + public static void transferOrInviteUser(ChatRoom chatRoom, String workgroup, String sessionID, final Jid jid, String messageText, final boolean transfer) { + String msg = messageText != null ? StringUtils.escapeForXml(messageText).toString() : FpRes.getString("message.please.join.me.in.conference"); try { if (!transfer) { // TODO : CHECK FASHPATH @@ -59,15 +51,15 @@ public static void transferOrInviteUser(ChatRoom chatRoom, String workgroup, Str } else { // TODO : CHECK FASHPATH - FastpathPlugin.getAgentSession().sendRoomTransfer(RoomTransfer.Type.user, jid, sessionID, msg); + FastpathPlugin.getAgentSession().sendRoomTransfer(RoomTransfer.Type.user, jid.toString(), sessionID, msg); } } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error(e); } - String username = SparkManager.getUserManager().getUserNicknameFromJID(jid); + String username = SparkManager.getUserManager().getUserNicknameFromJID(jid.asBareJid()); String notification = FpRes.getString("message.user.has.been.invited", username); if (transfer) { @@ -85,8 +77,8 @@ public static void transferOrInviteUser(ChatRoom chatRoom, String workgroup, Str * @param messageText the message to send to the user. * @param transfer true if this is a transfer. */ - public static void transferOrInviteToQueue(ChatRoom chatRoom, String workgroup, String sessionID, final String jid, String messageText, final boolean transfer) { - String msg = messageText != null ? StringUtils.escapeForXML(messageText).toString() : FpRes.getString("message.please.join.me.in.conference"); + public static void transferOrInviteToQueue(ChatRoom chatRoom, String workgroup, String sessionID, final Jid jid, String messageText, final boolean transfer) { + String msg = messageText != null ? StringUtils.escapeForXml(messageText).toString() : FpRes.getString("message.please.join.me.in.conference"); try { if (!transfer) { // TODO : CHECK FASHPATH @@ -94,15 +86,15 @@ public static void transferOrInviteToQueue(ChatRoom chatRoom, String workgroup, } else { // TODO : CHECK FASHPATH - FastpathPlugin.getAgentSession().sendRoomTransfer(RoomTransfer.Type.queue, jid, sessionID, msg); + FastpathPlugin.getAgentSession().sendRoomTransfer(RoomTransfer.Type.queue, jid.toString(), sessionID, msg); } } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error(e); } - String username = SparkManager.getUserManager().getUserNicknameFromJID(jid); + String username = SparkManager.getUserManager().getUserNicknameFromJID(jid.asBareJid()); String notification = FpRes.getString("message.user.has.been.invited", username); if (transfer) { @@ -120,23 +112,23 @@ public static void transferOrInviteToQueue(ChatRoom chatRoom, String workgroup, * @param messageText the message to send to the user. * @param transfer true if this is a transfer. */ - public static void transferOrInviteToWorkgroup(ChatRoom chatRoom, String workgroup, String sessionID, final String jid, String messageText, final boolean transfer) { - String msg = messageText != null ? StringUtils.escapeForXML(messageText).toString() : FpRes.getString("message.please.join.me.in.conference"); + public static void transferOrInviteToWorkgroup(ChatRoom chatRoom, String workgroup, String sessionID, final Jid jid, String messageText, final boolean transfer) { + String msg = messageText != null ? StringUtils.escapeForXml(messageText).toString() : FpRes.getString("message.please.join.me.in.conference"); try { if (!transfer) { // TODO : CHECK FASHPATH FastpathPlugin.getAgentSession().sendRoomInvitation(RoomInvitation.Type.workgroup, jid, sessionID, msg); } else { - FastpathPlugin.getAgentSession().sendRoomTransfer(RoomTransfer.Type.workgroup, jid, sessionID, msg); + FastpathPlugin.getAgentSession().sendRoomTransfer(RoomTransfer.Type.workgroup, jid.toString(), sessionID, msg); } } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error(e); } - String username = SparkManager.getUserManager().getUserNicknameFromJID(jid); + String username = SparkManager.getUserManager().getUserNicknameFromJID(jid.asBareJid()); String notification = FpRes.getString("message.user.has.been.invited", username); if (transfer) { diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/invite/WorkgroupInvitationDialog.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/invite/WorkgroupInvitationDialog.java similarity index 80% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/invite/WorkgroupInvitationDialog.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/invite/WorkgroupInvitationDialog.java index 719d16f68..56237629d 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/invite/WorkgroupInvitationDialog.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/invite/WorkgroupInvitationDialog.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,8 +36,6 @@ import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; @@ -51,7 +45,6 @@ import org.jivesoftware.fastpath.resources.FastpathRes; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.workgroup.agent.Agent; import org.jivesoftware.smackx.workgroup.agent.AgentRoster; import org.jivesoftware.smackx.workgroup.agent.WorkgroupQueue; @@ -66,6 +59,12 @@ import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.spark.util.ResourceUtils; import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.EntityFullJid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.parts.Localpart; import org.jxmpp.util.XmppStringUtils; @@ -85,9 +84,9 @@ public class WorkgroupInvitationDialog implements PropertyChangeListener { private TitlePanel titlePanel; private JTextArea messageField; - private JTextField jidField = new JTextField(); + private final JTextField jidField = new JTextField(); - private List workgroups = new ArrayList(); + private final List workgroups = new ArrayList<>(); private JLabel inviteLabel; /** @@ -107,16 +106,16 @@ public boolean hasSelectedAgent(ChatRoom chatRoom, boolean transfer) { final JiveTreeNode workgroupsNode = new JiveTreeNode("Workgroups", true); final JiveTreeNode queueNode = new JiveTreeNode("Queues", true); - final String workgroupService = "workgroup." + SparkManager.getSessionManager().getServerAddress(); - final String jid = SparkManager.getSessionManager().getJID(); + final DomainBareJid workgroupService = JidCreate.domainBareFromOrThrowUnchecked("workgroup." + SparkManager.getSessionManager().getServerAddress()); + final EntityFullJid jid = SparkManager.getSessionManager().getJID(); - String room = chatRoom.getRoomname(); - Collection agents = null; + EntityBareJid room = chatRoom.getBareJid(); + Collection agents = null; try { agents = getAvailableAgents( FastpathPlugin.getAgentSession().getAgentRoster(), room); } - catch ( SmackException.NotConnectedException e ) + catch ( SmackException.NotConnectedException | InterruptedException e ) { Log.warning( "Unable to get agent roster.", e ); } @@ -146,22 +145,22 @@ public boolean hasSelectedAgent(ChatRoom chatRoom, boolean transfer) { tree.setExpandsSelectedPaths(true); - tree.addTreeSelectionListener(new TreeSelectionListener() { - public void valueChanged(TreeSelectionEvent e) { - TreePath path = e.getNewLeadSelectionPath(); - Object o = path.getLastPathComponent(); - if (o instanceof JiveTreeNode) { - JiveTreeNode node = (JiveTreeNode)o; - JiveTreeNode parentNode = (JiveTreeNode)node.getParent(); - if (parentNode == workgroupsNode) { - jidField.setText(node.getUserObject().toString() + "@" + workgroupService); - } - else if (parentNode == queueNode) { - jidField.setText(FastpathPlugin.getWorkgroup().getWorkgroupJID() + "/" + node.getUserObject().toString()); - } - else { - String agent = getAgent(); - jidField.setText(agent); + tree.addTreeSelectionListener(e -> { + TreePath path = e.getNewLeadSelectionPath(); + Object o = path.getLastPathComponent(); + if (o instanceof JiveTreeNode) { + JiveTreeNode node = (JiveTreeNode)o; + JiveTreeNode parentNode = (JiveTreeNode)node.getParent(); + if (parentNode == workgroupsNode) { + jidField.setText(node.getUserObject().toString() + "@" + workgroupService); + } + else if (parentNode == queueNode) { + jidField.setText(FastpathPlugin.getWorkgroup().getWorkgroupJID() + "/" + node.getUserObject().toString()); + } + else { + EntityBareJid agent = getAgent(); + if (agent != null) { + jidField.setText(agent.toString()); } } } @@ -192,13 +191,13 @@ else if (parentNode == queueNode) { } // Build Tree - String joinedWorkgroupName = XmppStringUtils.parseLocalpart(FastpathPlugin.getWorkgroup().getWorkgroupJID()); + Localpart joinedWorkgroupName = FastpathPlugin.getWorkgroup().getWorkgroupJID().getLocalpartOrThrow(); final JiveTreeNode workgroupNode = new JiveTreeNode(joinedWorkgroupName, true); - final Iterator agentIter = agents.iterator(); + final Iterator agentIter = agents.iterator(); while (agentIter.hasNext()) { while (agentIter.hasNext()) { - String agentName = UserManager.unescapeJID((String)agentIter.next()); + String agentName = UserManager.unescapeJID(agentIter.next().toString()); final JiveTreeNode agentNode = new JiveTreeNode(agentName, false, FastpathRes.getImageIcon(FastpathRes.GREEN_BALL)); workgroupNode.add(agentNode); } @@ -208,20 +207,17 @@ else if (parentNode == queueNode) { } - Collection workgroupAgents; + Collection workgroupAgents; try { workgroupAgents = Agent.getWorkgroups(workgroupService, jid, SparkManager.getConnection()); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error(e); workgroupAgents = Collections.EMPTY_LIST; } if (workgroupAgents.size() > 0) { // Add workgroups to combobox - Iterator workgroups = workgroupAgents.iterator(); - while (workgroups.hasNext()) { - String workgroup = workgroups.next(); - + for (String workgroup : workgroupAgents) { String workgroupName = XmppStringUtils.parseLocalpart(workgroup); final JiveTreeNode wgNode = new JiveTreeNode(workgroupName, false, FastpathRes.getImageIcon(FastpathRes.FASTPATH_IMAGE_16x16)); workgroupsNode.add(wgNode); @@ -230,11 +226,11 @@ else if (parentNode == queueNode) { } - Iterator iter = FastpathPlugin.getAgentSession().getQueues(); + Iterator iter = FastpathPlugin.getAgentSession().getQueues(); while (iter.hasNext()) { - final WorkgroupQueue queue = (WorkgroupQueue)iter.next(); + final WorkgroupQueue queue = iter.next(); if (queue.getStatus() == WorkgroupQueue.Status.OPEN) { - final JiveTreeNode qNode = new JiveTreeNode(queue.getName(), false, FastpathRes.getImageIcon(FastpathRes.FASTPATH_IMAGE_16x16)); + final JiveTreeNode qNode = new JiveTreeNode(queue.getName().toString(), false, FastpathRes.getImageIcon(FastpathRes.FASTPATH_IMAGE_16x16)); queueNode.add(qNode); } } @@ -243,9 +239,9 @@ else if (parentNode == queueNode) { // New Roster tree. Do not show agents at all. final UserManager userManager = SparkManager.getUserManager(); - Collection jids = userManager.getUserJidsInRoom(room, false); + Collection jids = userManager.getUserJidsInRoom(room, false); - roster = new WorkgroupRosterTree(jids, false, workgroups); + roster = new WorkgroupRosterTree((Collection) jids, false, workgroups); try { rosterTree = roster.getRosterTree(); @@ -311,10 +307,7 @@ else if (parentNode == queueNode) { dlg.toFront(); dlg.requestFocus(); - if (!isValid) { - return false; - } - return true; + return isValid; } @@ -326,7 +319,7 @@ public void propertyChange(PropertyChangeEvent e) { } else if (FpRes.getString("invite").equals(value) || FpRes.getString("transfer").equals(value)) { String agent = jidField.getText(); - boolean isValidJID = agent.indexOf("@") != -1; + boolean isValidJID = agent.contains("@"); if (!ModelUtil.hasLength(agent)) { JOptionPane.showMessageDialog(dlg, FpRes.getString("message.no.agent.selected.error"), @@ -373,21 +366,21 @@ public String getSelectedJID() { * * @return the agents jid. */ - private String getAgent() { - String agentJID; + private EntityBareJid getAgent() { + EntityBareJid agentJID; final DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(); if (node == null || node.getAllowsChildren()) { - return ""; + return null; } agentJID = roster.getAgentJID((JiveTreeNode)node); if (agentJID == null) { final Object nodeInfo = node.getUserObject(); if (!node.isLeaf()) { - return ""; + return null; } - agentJID = nodeInfo.toString(); + agentJID = JidCreate.entityBareFromOrThrowUnchecked(nodeInfo.toString()); } return agentJID; } @@ -399,20 +392,18 @@ private String getAgent() { * @param roomName the name of the room to check. * @return collection of available agents. */ - private Collection getAvailableAgents(AgentRoster roster, String roomName) { - final Set availableAgents = new HashSet(); + private Collection getAvailableAgents(AgentRoster roster, EntityBareJid roomName) { + final Set availableAgents = new HashSet<>(); - final Iterator agents = roster.getAgents().iterator(); - while (agents.hasNext()) { - String agent = agents.next(); + for (EntityBareJid agent : roster.getAgents()) { if (PresenceManager.isAvailable(agent)) { - final Iterator agentsInRoom = SparkManager.getUserManager().getUserJidsInRoom(roomName, false).iterator(); + final Iterator agentsInRoom = SparkManager.getUserManager().getUserJidsInRoom(roomName, false).iterator(); boolean alreadyExists = false; while (agentsInRoom.hasNext()) { - String userid = (String)agentsInRoom.next(); + String userid = agentsInRoom.next(); - if (agent.equalsIgnoreCase(userid)) { + if (agent.equals(userid)) { alreadyExists = true; } } @@ -420,11 +411,8 @@ private Collection getAvailableAgents(AgentRoster roster, String roomNam if (!alreadyExists) { availableAgents.add(agent); } - } } - - return availableAgents; } } diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/invite/WorkgroupRosterTree.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/invite/WorkgroupRosterTree.java similarity index 78% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/invite/WorkgroupRosterTree.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/invite/WorkgroupRosterTree.java index 0d58efcc5..1cac07297 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/invite/WorkgroupRosterTree.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/invite/WorkgroupRosterTree.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,13 +21,15 @@ import org.jivesoftware.smack.roster.RosterEntry; import org.jivesoftware.smack.roster.RosterGroup; import org.jivesoftware.smack.roster.RosterListener; -import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.spark.PresenceManager; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.component.JiveTreeCellRenderer; import org.jivesoftware.spark.component.JiveTreeNode; import org.jivesoftware.spark.component.Tree; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; import javax.swing.BorderFactory; import javax.swing.JPanel; @@ -45,19 +43,17 @@ import java.awt.Insets; import java.util.Collection; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; public final class WorkgroupRosterTree extends JPanel { - private static final long serialVersionUID = -1159008318665938338L; private final JiveTreeNode rootNode = new JiveTreeNode(FpRes.getString("title.contact.list")); private final Tree rosterTree; - private final Map addressMap = new HashMap(); - private boolean showUnavailableAgents = true; - private final List workgroupList; - private Collection exclusionList; + private final Map addressMap = new HashMap<>(); + private final boolean showUnavailableAgents; + private final List workgroupList; + private final Collection exclusionList; /** * Creates a new Roster Tree. @@ -66,7 +62,7 @@ public final class WorkgroupRosterTree extends JPanel { * @param showAgents true if agents should be visible. * @param workgroupList the list of workgroups. */ - public WorkgroupRosterTree(Collection exclusionJIDs, boolean showAgents, List workgroupList) { + public WorkgroupRosterTree(Collection exclusionJIDs, boolean showAgents, List workgroupList) { this.workgroupList = workgroupList; showUnavailableAgents = showAgents; exclusionList = exclusionJIDs; @@ -91,16 +87,13 @@ public WorkgroupRosterTree(Collection exclusionJIDs, boolean showAgents, List wo } } - private void changePresence(String user, Presence presence) { - final Iterator iter = addressMap.keySet().iterator(); - while (iter.hasNext()) { - final JiveTreeNode node = (JiveTreeNode)iter.next(); - final String nodeUser = (String)addressMap.get(node); - if (user.startsWith(nodeUser)) { + private void changePresence(Jid user, Presence presence) { + for (JiveTreeNode node : addressMap.keySet()) { + final BareJid nodeUser = addressMap.get(node); + if (user.isParentOf(nodeUser)) { if (!PresenceManager.isAvailable(presence)) { node.setIcon(FastpathRes.getImageIcon(FastpathRes.RED_BALL)); - } - else { + } else { node.setIcon(FastpathRes.getImageIcon(FastpathRes.GREEN_BALL)); } } @@ -108,22 +101,16 @@ private void changePresence(String user, Presence presence) { } private void buildFromRoster() { - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); + Roster roster = SparkManager.getRoster(); roster.addRosterListener(new RosterListener() { - public void rosterModified() { - } - public void entriesAdded(Collection collection) { - } public void entriesUpdated(Collection collection) { - } public void entriesDeleted(Collection collection) { - } public void presenceChanged(Presence presence) { @@ -146,16 +133,16 @@ public void presenceChanged(Presence presence) { for (RosterEntry entry : group.getEntries()) { String name = entry.getName(); if (name == null) { - name = entry.getUser(); + name = entry.getJid().toString(); } - if (exclusionList.contains(entry.getUser())) { + if (exclusionList.contains(entry.getJid())) { continue; } final JiveTreeNode entryNode = new JiveTreeNode(name, false); - final Presence usersPresence = roster.getPresence(entry.getUser()); - addressMap.put(entryNode, entry.getUser()); + final Presence usersPresence = roster.getPresence(entry.getJid()); + addressMap.put(entryNode, entry.getJid().asEntityBareJidOrThrow()); if (PresenceManager.isAvailable(usersPresence)) { groupNode.add(entryNode); } @@ -163,7 +150,7 @@ else if (showUnavailableAgents) { groupNode.add(entryNode); } - changePresence(entry.getUser(), usersPresence); + changePresence(entry.getJid(), usersPresence); final DefaultTreeModel model = (DefaultTreeModel)rosterTree.getModel(); model.nodeStructureChanged(groupNode); } @@ -172,8 +159,6 @@ else if (showUnavailableAgents) { /** * Returns the Tree representation of the Roster Tree. - * - * @return the tree representation of the Roster Tree. */ public Tree getRosterTree() { return rosterTree; @@ -185,9 +170,8 @@ public Tree getRosterTree() { * @param node the JiveTreeNode. * @return the selected agent nodes userobject. */ - public String getAgentJID(JiveTreeNode node) { - String address = (String)addressMap.get(node); - return address; + public EntityBareJid getAgentJID(JiveTreeNode node) { + return addressMap.get(node); } public String toString() { diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/macros/MacroPanel.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/macros/MacroPanel.java similarity index 92% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/macros/MacroPanel.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/macros/MacroPanel.java index 82d12a1b9..a799eea49 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/macros/MacroPanel.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/macros/MacroPanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,13 +37,13 @@ public class MacroPanel extends JPanel { private static final long serialVersionUID = 1L; - private JLabel titleLabel; - private JLabel typeLabel; - private JLabel responseLabel; + private final JLabel titleLabel; + private final JLabel typeLabel; + private final JLabel responseLabel; - private JTextField titleField; - private JComboBox typeField; - private JTextArea responseField; + private final JTextField titleField; + private final JComboBox typeField; + private final JTextArea responseField; public MacroPanel() { titleLabel = new JLabel(); @@ -57,7 +53,7 @@ public MacroPanel() { titleField = new JTextField(); String[] items = {"Text", "URL", "Image"}; - typeField = new JComboBox(items); + typeField = new JComboBox<>(items); responseField = new JTextArea(); diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/macros/MacrosEditor.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/macros/MacrosEditor.java similarity index 85% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/macros/MacrosEditor.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/macros/MacrosEditor.java index f7e8b32c7..883e5b04c 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/macros/MacrosEditor.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/macros/MacrosEditor.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,9 +21,6 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Iterator; import java.util.List; import java.util.Properties; @@ -60,12 +53,12 @@ public class MacrosEditor extends JPanel { private static final long serialVersionUID = 1L; - private JLabel initialResponseLabel = new JLabel(); - private JTextArea initialResponseField = new JTextArea(); - private RolloverButton newButton = new RolloverButton(FastpathRes.getImageIcon(FastpathRes.SMALL_ADD_IMAGE)); - private RolloverButton deleteButton = new RolloverButton(FastpathRes.getImageIcon(FastpathRes.SMALL_DELETE)); - private JButton saveButton = new JButton(); - private MacroTable table; + private final JLabel initialResponseLabel = new JLabel(); + private final JTextArea initialResponseField = new JTextArea(); + private final RolloverButton newButton = new RolloverButton(FastpathRes.getImageIcon(FastpathRes.SMALL_ADD_IMAGE)); + private final RolloverButton deleteButton = new RolloverButton(FastpathRes.getImageIcon(FastpathRes.SMALL_DELETE)); + private final JButton saveButton = new JButton(); + private final MacroTable table; private MacroGroup personalGroup = null; private JDialog dialog; @@ -95,31 +88,16 @@ public MacrosEditor() { // add table add(pane, new GridBagConstraints(0, 3, 1, 1, 1.0, 0.5, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - - newButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent actionEvent) { - createNewResponse(); - } - }); - - saveButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent actionEvent) { - save(); - } - }); - - deleteButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent actionEvent) { - deleteRow(); - } - }); + newButton.addActionListener(actionEvent -> createNewResponse()); + saveButton.addActionListener(actionEvent -> save()); + deleteButton.addActionListener(actionEvent -> deleteRow()); } public void showEditor(Component parent) { try { personalGroup = FastpathPlugin.getAgentSession().getMacros(false); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error("No personal macros set."); personalGroup = new MacroGroup(); } @@ -131,9 +109,7 @@ public void showEditor(Component parent) { } List macros = personalGroup.getMacros(); - Iterator iter = macros.iterator(); - while (iter.hasNext()) { - Macro macro = (Macro)iter.next(); + for (Macro macro : macros) { String title = macro.getTitle(); String response = macro.getResponse(); diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/AgentConversation.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/AgentConversation.java similarity index 83% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/AgentConversation.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/AgentConversation.java index ea5fcbe35..0a509b671 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/AgentConversation.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/AgentConversation.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,22 +30,21 @@ import java.text.SimpleDateFormat; import java.util.Date; -import org.jivesoftware.spark.UserManager; +import org.jxmpp.jid.EntityBareJid; public class AgentConversation extends JPanel { private static final long serialVersionUID = 4723796422650155313L; - private JLabel agentLabel = new JLabel(); - private JLabel visitorLabel = new JLabel(); - private JLabel emailLabel = new JLabel(); - private JLabel dateLabel = new JLabel(); - private JLabel questionLabel = new JLabel(); + private final JLabel agentLabel = new JLabel(); + private final JLabel visitorLabel = new JLabel(); + private final JLabel emailLabel = new JLabel(); + private final JLabel dateLabel = new JLabel(); + private final JLabel questionLabel = new JLabel(); private String sessionID; - private String agentJID; + private EntityBareJid agentJID; - public AgentConversation(String agent, String visitor, Date date, String email, String question, String sessionID) { - agent = UserManager.unescapeJID(agent); + public AgentConversation( EntityBareJid agent, String visitor, Date date, String email, String question, String sessionID) { this.agentJID = agent; setBackground(Color.white); @@ -93,7 +88,7 @@ public AgentConversation(String agent, String visitor, Date date, String email, final SimpleDateFormat simpleFormat = new SimpleDateFormat("MM/dd/yyyy h:mm a"); String theDate = simpleFormat.format(date); - agentLabel.setText(agent); + agentLabel.setText(agent.asUnescapedString()); visitorLabel.setText(visitor); dateLabel.setText(theDate); emailLabel.setText(email); @@ -102,19 +97,17 @@ public AgentConversation(String agent, String visitor, Date date, String email, setSessionID(sessionID); } - public String getAgentJID() { + public EntityBareJid getAgentJID() { return agentJID; } - public void setAgentJID(String agentJID) { + public void setAgentJID(EntityBareJid agentJID) { this.agentJID = agentJID; } public String getToolTipText() { - StringBuffer buf = new StringBuffer(); - buf.append(""); - buf.append("

      "+FpRes.getString("question") +": " + questionLabel.getText() + "
      "); - return buf.toString(); + return "" + "
      " + FpRes.getString("question") + + ": " + questionLabel.getText() + "
      "; } public void setSessionID(String sessionID) { diff --git a/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/AgentConversations.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/AgentConversations.java new file mode 100644 index 000000000..611279e1f --- /dev/null +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/AgentConversations.java @@ -0,0 +1,377 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.fastpath.workspace.panes; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.DefaultListModel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import org.jivesoftware.fastpath.FastpathPlugin; +import org.jivesoftware.fastpath.FpRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smackx.muc.MultiUserChatManager; +import org.jivesoftware.smackx.xdata.form.FillableForm; +import org.jivesoftware.smackx.muc.Affiliate; +import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jivesoftware.smackx.workgroup.agent.AgentRoster; +import org.jivesoftware.smackx.workgroup.agent.AgentRosterListener; +import org.jivesoftware.smackx.workgroup.packet.AgentStatus; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.tabbedPane.SparkTab; +import org.jivesoftware.spark.component.tabbedPane.SparkTabbedPaneListener; +import org.jivesoftware.spark.ui.conferences.ConferenceUtils; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.util.JidUtil; +import org.jxmpp.stringprep.XmppStringprepException; + +import static org.jivesoftware.smackx.muc.MucConfigFormManager.MUC_ROOMCONFIG_ROOMOWNERS; + +/** + * UI to show all chats occuring. + */ +public final class AgentConversations extends JPanel implements ChangeListener { + + private static final long serialVersionUID = 1L; + private final DefaultListModel model = new DefaultListModel<>(); + private JList list; + + private final Map sessionMap = new HashMap<>(); + + /** + * Add listeners and construct UI. + */ + public AgentConversations() { + FastpathPlugin.getUI().getMainPanel().addSparkTabbedPaneListener(new SparkTabbedPaneListener() { + public void tabRemoved(SparkTab tab, Component component, int index) { + } + + public void tabAdded(SparkTab tab, Component component, int index) { + } + + public void tabSelected(SparkTab tab, Component component, int index) { + stateChanged(null); + } + + public void allTabsRemoved() { + } + + + public boolean canTabClose(SparkTab tab, Component component) { + return true; + } + }); + } + + private void init() { + list = new JList<>(model); + + this.setLayout(new BorderLayout()); + this.setBackground(Color.white); + this.setForeground(Color.white); + + JScrollPane scrollPane = new JScrollPane(list); + scrollPane.setBorder(BorderFactory.createEmptyBorder()); + this.add(scrollPane, BorderLayout.CENTER); + + list.setCellRenderer(new FastpathPanelRenderer()); + + list.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent mouseEvent) { + int index = list.locationToIndex(mouseEvent.getPoint()); + list.setSelectedIndex(index); + checkPopup(mouseEvent); + } + + public void mouseReleased(MouseEvent mouseEvent) { + int index = list.locationToIndex(mouseEvent.getPoint()); + list.setSelectedIndex(index); + checkPopup(mouseEvent); + } + }); + } + + + private void addAgentChat(EntityBareJid agentID, String name, String email, String question, Date startDate, String sessionID) { + if (sessionMap.containsKey(sessionID)) { + return; + } + + AgentConversation item = new AgentConversation(agentID, name, startDate, email, question, sessionID); + model.addElement(item); + sessionMap.put(sessionID, item); + } + + private void removeConversation(String sessionID) { + AgentConversation item = sessionMap.get(sessionID); + if (item != null) { + model.removeElement(item); + } + } + + public void stateChanged(ChangeEvent e) { + if (FastpathPlugin.getUI().getMainPanel().getSelectedComponent() == this && list == null) { + init(); + + SwingWorker agentWorker = new SwingWorker() { + AgentRoster agentRoster; + Collection agentSet; + + public Object construct() { + try + { + agentRoster = FastpathPlugin.getAgentSession().getAgentRoster(); + } + catch ( SmackException.NotConnectedException | InterruptedException e1 ) + { + Log.warning( "Unable to get agent roster.", e1 ); + } + agentSet = agentRoster.getAgents(); + return agentSet; + } + + public void finished() { + agentRoster.addListener(new AgentRosterListener() { + @Override + public void agentAdded(EntityBareJid jid) { + } + + @Override + public void agentRemoved(EntityBareJid jid) { + + } + + @Override + public void presenceChanged(Presence presence) { + EntityBareJid agentJID = presence.getFrom().asEntityBareJidOrThrow(); + AgentStatus agentStatus = presence.getExtension(AgentStatus.class); + + if (agentStatus != null) { + List list = agentStatus.getCurrentChats(); + + removeOldChats(agentJID, list); + + // Add new ones. + for (Object o : list) { + AgentStatus.ChatInfo chatInfo = (AgentStatus.ChatInfo) o; + Date startDate = chatInfo.getDate(); + String username = chatInfo.getUserID(); + + String nickname = chatInfo.getUsername(); + if (!ModelUtil.hasLength(nickname)) { + nickname = "Not specified"; + } + + String question = chatInfo.getQuestion(); + if (!ModelUtil.hasLength(question)) { + question = "No question asked"; + } + + String email = chatInfo.getEmail(); + if (!ModelUtil.hasLength(email)) { + email = "Not specified"; + } + addAgentChat(agentJID, nickname, email, question, startDate, chatInfo.getSessionID()); + } + } + calculateNumberOfChats(agentRoster); + } + }); + } + }; + agentWorker.start(); + } + } + + private void calculateNumberOfChats(AgentRoster agentRoster) { + int counter = 0; + // TODO: CHECK FASTPATH + for (EntityBareJid agent : agentRoster.getAgents()) { + Presence presence = agentRoster.getPresence(agent); + if (presence.isAvailable()) { + AgentStatus agentStatus = presence.getExtension(AgentStatus.class); + if (agentStatus != null) { + counter += agentStatus.getCurrentChats().size(); + } + } + } + + FastpathPlugin.getUI().setTitleForComponent(FpRes.getString("message.current.chats", counter), this); + } + + private boolean newListHasSession(String sessionID, List chatList) { + // Add new ones. + for (AgentStatus.ChatInfo item : chatList) { + String session = item.getSessionID(); + if (session.equalsIgnoreCase(sessionID)) { + return true; + } + } + return false; + } + + private void removeOldChats(EntityBareJid agentJID, List chatList) { + for (AgentConversation agent : sessionMap.values()) { + if (agent.getAgentJID().equals(agentJID)) { + String sessionID = agent.getSessionID(); + boolean listHasID = newListHasSession(sessionID, chatList); + if (!listHasID) { + removeConversation(sessionID); + } + } + } + } + + + private void checkPopup(MouseEvent e) { + if (e.isPopupTrigger()) { + // Check if monitor + try { + AgentConversation item = list.getSelectedValue(); + boolean isMonitor = FastpathPlugin.getAgentSession().hasMonitorPrivileges(SparkManager.getConnection()); + if (isMonitor) { + JPopupMenu menu = new JPopupMenu(); + + final String sessionID = item.getSessionID(); + + + Action joinAction = new AbstractAction() { + private static final long serialVersionUID = 8239167390330425891L; + + public void actionPerformed(ActionEvent actionEvent) { + // Get Conference + try { + final MultiUserChatManager multiUserChatManager = SparkManager.getMucManager(); + List col = multiUserChatManager.getMucServiceDomains(); + if (col.size() == 0) { + return; + } + + DomainBareJid serviceName = col.get(0); + EntityBareJid roomName = JidCreate.entityBareFrom(sessionID + "@" + serviceName); + + MultiUserChat muc = multiUserChatManager.getMultiUserChat( roomName ); + + ConferenceUtils.enterRoomOnSameThread(roomName, roomName, null); + + if (muc.isJoined()) { + // Try and remove myself as an owner if I am one. + Collection owners; + try { + owners = muc.getOwners(); + } + catch (XMPPException | SmackException e1) { + return; + } + Iterator iter = owners.iterator(); + + List list = new ArrayList<>(); + while (iter.hasNext()) { + Affiliate affilitate = iter.next(); + Jid jid = affilitate.getJid(); + if (!jid.equals(SparkManager.getSessionManager().getUserBareAddress())) { + list.add(jid); + } + } + if (list.size() > 0) { + FillableForm form = muc.getConfigurationForm().getFillableForm(); + List listStrings = JidUtil.toStringList(list); + form.setAnswer(MUC_ROOMCONFIG_ROOMOWNERS, listStrings); + + // new DataFormDialog(groupChat, form); + muc.sendConfigurationForm(form); + } + } + } + catch (Exception e1) { + Log.error(e1); + } + } + }; + + joinAction.putValue(Action.NAME, FpRes.getString("menuitem.join.chat")); + menu.add(joinAction); + + Action monitorAction = new AbstractAction() { + private static final long serialVersionUID = -2072254190661466657L; + + public void actionPerformed(ActionEvent actionEvent) { + + // Make user an owner. + try { + FastpathPlugin.getAgentSession().makeRoomOwner(SparkManager.getConnection(), sessionID); + + final MultiUserChatManager multiUserChatManager = SparkManager.getMucManager(); + List col = multiUserChatManager.getMucServiceDomains(); + if (col.isEmpty()) { + return; + } + + DomainBareJid serviceName = col.iterator().next(); + EntityBareJid roomName = JidCreate.entityBareFrom(sessionID + "@" + serviceName); + + MultiUserChat muc = multiUserChatManager.getMultiUserChat( roomName); + + ConferenceUtils.enterRoomOnSameThread(roomName, roomName, null); + + } + catch (XMPPException | SmackException | InterruptedException | XmppStringprepException e1) { + Log.error(e1); + } + } + }; + + monitorAction.putValue(Action.NAME, FpRes.getString("menuitem.monitor.chat")); + menu.add(monitorAction); + menu.show(list, e.getX(), e.getY()); + } + } + catch (XMPPException | SmackException | InterruptedException e1) { + Log.error(e1); + } + } + } + + +} diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/BackgroundPane.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/BackgroundPane.java similarity index 98% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/BackgroundPane.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/BackgroundPane.java index 33d75f6f6..d6e6bf4cc 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/BackgroundPane.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/BackgroundPane.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/ChatHistory.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/ChatHistory.java similarity index 90% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/ChatHistory.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/ChatHistory.java index 8d4163ae3..a5eb081a8 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/ChatHistory.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/ChatHistory.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,7 +26,6 @@ import java.awt.event.MouseEvent; import java.util.Collection; import java.util.Date; -import java.util.Iterator; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; @@ -46,7 +41,6 @@ import org.jivesoftware.fastpath.resources.FastpathRes; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.workgroup.agent.AgentSession; import org.jivesoftware.smackx.workgroup.ext.history.AgentChatHistory; import org.jivesoftware.smackx.workgroup.ext.history.AgentChatSession; @@ -54,19 +48,20 @@ import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.parts.Localpart; public class ChatHistory extends JPanel { private static final long serialVersionUID = 1L; - private DefaultListModel model = new DefaultListModel(); + private final DefaultListModel model = new DefaultListModel<>(); private AgentSession agentSession; - private JList list; + private final JList list; private JFrame mainFrame; private JFrame frame; public ChatHistory() { - list = new JList(model); + list = new JList<>(model); list.setCellRenderer(new HistoryItemRenderer()); @@ -104,7 +99,7 @@ public Dimension getPreferredSize() { list.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { - HistoryItem historyItem = (HistoryItem)list.getSelectedValue(); + HistoryItem historyItem = list.getSelectedValue(); showTranscript(historyItem.getSessionID()); } } @@ -113,7 +108,7 @@ public void mouseClicked(MouseEvent e) { public void showDialog() { AgentSession agentSession = FastpathPlugin.getAgentSession(); - String workgroupName = XmppStringUtils.parseLocalpart(agentSession.getWorkgroupJID()); + Localpart workgroupName = FastpathPlugin.getWorkgroup().getWorkgroupJID().getLocalpartOrThrow(); if (mainFrame == null) { @@ -144,20 +139,19 @@ public void init() { agentSession = FastpathPlugin.getAgentSession(); - String jid = SparkManager.getSessionManager().getBareAddress(); + EntityBareJid jid = SparkManager.getSessionManager().getUserBareAddress(); try { history = agentSession.getAgentHistory(jid, 10, null); } - catch (XMPPException | SmackException e1) { + catch (XMPPException | SmackException | InterruptedException e1) { Log.error("Error retrieving chat history.", e1); } try { model.removeAllElements(); - Collection sessions = history.getAgentChatSessions(); - Iterator iter = sessions.iterator(); - while (iter.hasNext()) { - AgentChatSession chatSession = (AgentChatSession)iter.next(); + Collection sessions = history.getAgentChatSessions(); + for (Object session : sessions) { + AgentChatSession chatSession = (AgentChatSession) session; // Then were in a group chat final String nickname = chatSession.getVisitorsName(); @@ -200,7 +194,7 @@ private void showTranscript(String sessionID) { try { transcript = FastpathPlugin.getAgentSession().getTranscript(sessionID); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error("Error showing transcripts.", e); } diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/ChatQueue.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/ChatQueue.java similarity index 93% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/ChatQueue.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/ChatQueue.java index 7538a251d..c9fb2013f 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/ChatQueue.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/ChatQueue.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,7 +25,7 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.Date; -import java.util.Iterator; +import java.util.List; import java.util.Map; import javax.swing.JLabel; @@ -43,8 +39,8 @@ import org.jivesoftware.fastpath.workspace.util.RequestUtils; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.xdata.Form; import org.jivesoftware.smackx.xdata.FormField; +import org.jivesoftware.smackx.xdata.form.Form; import org.jivesoftware.smackx.workgroup.agent.Offer; import org.jivesoftware.spark.component.LinkLabel; import org.jivesoftware.spark.component.RolloverButton; @@ -57,13 +53,13 @@ public class ChatQueue extends JPanel { private static final long serialVersionUID = 1L; - private JLabel nameLabel = new JLabel(); - private RolloverButton acceptButton; - private RolloverButton declineButton; + private final JLabel nameLabel = new JLabel(); + private final RolloverButton acceptButton; + private final RolloverButton declineButton; private LinkLabel viewLabel; private Offer offer; - private JProgressBar progressBar; + private final JProgressBar progressBar; public ChatQueue() { setLayout(new GridBagLayout()); @@ -93,7 +89,7 @@ private void showInformation() { return; } - Map metadata = offer.getMetaData(); + Map> metadata = offer.getMetaData(); RoomInformation roomInformation = new RoomInformation(); roomInformation.showAllInformation(metadata); roomInformation.showRoomInformation(); @@ -107,7 +103,7 @@ public void offerRecieved(Offer offer) { try { form = FastpathPlugin.getWorkgroup().getWorkgroupForm(); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error("Unable to retrieve Workgroup form.", e); return; } @@ -119,8 +115,8 @@ public void offerRecieved(Offer offer) { Color linkColor = new Color(69, 92, 137); int count = 1; - for ( final FormField field : form.getFields() ) { - String variable = field.getVariable(); + for ( final FormField field : form.getDataForm().getFields() ) { + String variable = field.getFieldName(); String label = field.getLabel(); if (label != null) { final JLabel nameLabel = new JLabel(label); diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/ChatViewer.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/ChatViewer.java similarity index 78% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/ChatViewer.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/ChatViewer.java index 243b2d847..349ae5bd6 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/ChatViewer.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/ChatViewer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,8 +22,6 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.util.*; import javax.swing.BorderFactory; @@ -43,6 +37,7 @@ import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smackx.delay.packet.DelayInformation; import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; import org.jivesoftware.smackx.workgroup.agent.AgentSession; @@ -54,7 +49,7 @@ import org.jivesoftware.spark.ui.ChatPrinter; import org.jivesoftware.spark.ui.TranscriptWindow; import org.jivesoftware.spark.util.GraphicUtils; -import org.jxmpp.util.XmppStringUtils; +import org.jxmpp.jid.impl.JidCreate; /** * Displays Fastpath transcripts. @@ -73,40 +68,36 @@ public ChatViewer(final Transcript transcript) { final TranscriptWindow chatWindow = new TranscriptWindow(); chatWindow.setBackground(Color.white); - final List chatTranscript = new ArrayList(); + final List chatTranscript = new ArrayList<>(); - Iterator iter = stanzas.iterator(); - while (iter.hasNext()) { - Stanza stanza = iter.next(); + for (Stanza stanza : stanzas) { if (stanza instanceof Message) { - Message message = (Message)stanza; - String from = XmppStringUtils.parseResource(message.getFrom()); - DelayInformation delayInformation = message.getExtension("delay", "urn:xmpp:delay"); + Message message = (Message) stanza; + String from = message.getFrom().getResourceOrThrow().toString(); + DelayInformation delayInformation = message.getExtension(DelayInformation.class); Date stamp = null; if (delayInformation != null) { stamp = delayInformation.getStamp(); } - message.removeExtension(delayInformation); + message.removeExtension(delayInformation.getElementName(), delayInformation.getNamespace()); chatWindow.insertMessage(from, message, ChatManager.TO_COLOR); final Map properties = new HashMap<>(); - properties.put( "date", stamp ); - message.addExtension( new JivePropertiesExtension( properties ) ); - message.setFrom(from); + properties.put("date", stamp); + message.addExtension(new JivePropertiesExtension(properties)); + message.setFrom(JidCreate.fromOrThrowUnchecked(from)); chatTranscript.add(message); - } - else { - Presence presence = (Presence)stanza; - String from = XmppStringUtils.parseResource(presence.getFrom()); + } else { + Presence presence = (Presence) stanza; + String from = presence.getFrom().getResourceOrThrow().toString(); if (presence.getType() == Presence.Type.available) { from = FpRes.getString("message.user.joined.room", from); - } - else { + } else { from = FpRes.getString("message.user.left.room", from); } chatWindow.insertNotificationMessage(from, ChatManager.NOTIFICATION_COLOR); - Message message = new Message(); - message.setBody(from); - message.setFrom("Room Notice"); + Message message = StanzaBuilder.buildMessage() + .setBody(from) + .build(); chatTranscript.add(message); } } @@ -132,17 +123,12 @@ public ChatViewer(final Transcript transcript) { this.setLayout(new GridBagLayout()); - saveTranscriptButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - chatWindow.saveTranscript(transcript.getSessionID() + ".html", chatTranscript, null); - } - }); + saveTranscriptButton.addActionListener(e -> + chatWindow.saveTranscript(transcript.getSessionID() + ".html", chatTranscript, null)); - printChatButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - final ChatPrinter printer = new ChatPrinter(); - printer.print(chatWindow); - } + printChatButton.addActionListener(e -> { + final ChatPrinter printer = new ChatPrinter(); + printer.print(chatWindow); }); chatWindow.setCaretPosition(0); @@ -164,7 +150,7 @@ public void actionPerformed(ActionEvent e) { ChatNotes note = agentSession.getNote(transcript.getSessionID()); pane.setText(note.getNotes()); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { pane.setText(""); // Log.error(e); } diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/ConversationItem.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/ConversationItem.java similarity index 89% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/ConversationItem.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/ConversationItem.java index 3dfbdb2cc..684e2cd84 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/ConversationItem.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/ConversationItem.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,11 +32,11 @@ public class ConversationItem extends JPanel { private static final long serialVersionUID = 3596381734502962203L; - private JLabel agentLabel = new JLabel(); - private JLabel visitorLabel = new JLabel(); - private JLabel emailLabel = new JLabel(); - private JLabel dateLabel = new JLabel(); - private JLabel questionLabel = new JLabel(); + private final JLabel agentLabel = new JLabel(); + private final JLabel visitorLabel = new JLabel(); + private final JLabel emailLabel = new JLabel(); + private final JLabel dateLabel = new JLabel(); + private final JLabel questionLabel = new JLabel(); private String sessionID; @@ -92,10 +88,8 @@ public ConversationItem(String agent, String visitor, Date date, String email, S } public String getToolTipText() { - StringBuffer buf = new StringBuffer(); - buf.append(""); - buf.append("
      "+FpRes.getString("question") +": " + questionLabel.getText() + "
      "); - return buf.toString(); + return "" + "
      " + FpRes.getString("question")+ ": " + + questionLabel.getText() + "
      "; } public void setSessionID(String sessionID) { diff --git a/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/CurrentActivity.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/CurrentActivity.java new file mode 100644 index 000000000..a8f9aaba5 --- /dev/null +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/CurrentActivity.java @@ -0,0 +1,345 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.fastpath.workspace.panes; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.DefaultListModel; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; + +import org.jivesoftware.fastpath.FastpathPlugin; +import org.jivesoftware.fastpath.FpRes; +import org.jivesoftware.fastpath.resources.FastpathRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smackx.muc.MultiUserChatManager; +import org.jivesoftware.smackx.xdata.form.FillableForm; +import org.jivesoftware.smackx.muc.Affiliate; +import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jivesoftware.smackx.workgroup.agent.AgentRoster; +import org.jivesoftware.smackx.workgroup.agent.AgentRosterListener; +import org.jivesoftware.smackx.workgroup.packet.AgentStatus; +import org.jivesoftware.smackx.workgroup.packet.AgentStatus.ChatInfo; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.conferences.ConferenceUtils; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.jid.util.JidUtil; + +import static org.jivesoftware.smackx.muc.MucConfigFormManager.MUC_ROOMCONFIG_ROOMOWNERS; + +/** + * UI to show all chats occuring. + */ +public final class CurrentActivity extends JPanel { + + private static final long serialVersionUID = 1L; + private final DefaultListModel model = new DefaultListModel<>(); + private final JList list = new JList<>(model); + private JFrame mainFrame; + private JLabel activeConversations; + private int counter = 0; + + /** + * Add listeners and construct UI. + */ + public CurrentActivity() { + init(); + } + + private void init() { + this.setLayout(new BorderLayout()); + + + final BackgroundPane titlePane = new BackgroundPane() { + private static final long serialVersionUID = 3127229816651522537L; + + public Dimension getPreferredSize() { + final Dimension size = super.getPreferredSize(); + size.width = 0; + return size; + } + }; + + titlePane.setLayout(new GridBagLayout()); + titlePane.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.LIGHT_GRAY)); + + + JLabel userImage = new JLabel(FastpathRes.getImageIcon(FastpathRes.FASTPATH_IMAGE_24x24)); + userImage.setHorizontalAlignment(JLabel.LEFT); + userImage.setText(FpRes.getString("title.current.active.conversation")); + titlePane.add(userImage, new GridBagConstraints(0, 0, 4, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + userImage.setFont(new Font("Dialog", Font.BOLD, 12)); + + activeConversations = new JLabel("0"); + titlePane.add(new JLabel(FpRes.getString("title.number.of.active.conversations") +":"), new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + titlePane.add(activeConversations, new GridBagConstraints(1, 1, 1, 3, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + + + this.add(titlePane, BorderLayout.NORTH); + + this.add(list, BorderLayout.CENTER); + + list.setCellRenderer(new HistoryItemRenderer()); + + // Add current chats + addCurrentChats(); + + list.addMouseListener(new MouseAdapter() { + public void mouseReleased(MouseEvent mouseEvent) { + checkPopup(mouseEvent); + } + + public void mousePressed(MouseEvent mouseEvent) { + checkPopup(mouseEvent); + } + }); + } + + public void addCurrentChats() { + SwingWorker agentWorker = new SwingWorker() { + AgentRoster agentRoster; + Collection agentSet; + + public Object construct() { + try + { + agentRoster = FastpathPlugin.getAgentSession().getAgentRoster(); + } + catch ( SmackException.NotConnectedException | InterruptedException e ) + { + Log.error( "Unable to get agent roster.", e ); + } + agentSet = agentRoster.getAgents(); + return agentSet; + } + + public void finished() { + agentRoster.addListener(new AgentRosterListener() { + @Override + public void agentAdded(EntityBareJid jid) { + } + + @Override + public void agentRemoved(EntityBareJid jid) { + } + + @Override + public void presenceChanged(Presence presence) { + BareJid agentJID = presence.getFrom().asBareJid(); + AgentStatus agentStatus = presence.getExtension(AgentStatus.class); + if (agentStatus != null) { + List list = agentStatus.getCurrentChats(); + + // Add new ones. + for (ChatInfo chatInfo : list) { + Date startDate = chatInfo.getDate(); + String username = chatInfo.getUserID(); + + String nickname = chatInfo.getUsername(); + if (!ModelUtil.hasLength(nickname)) { + nickname = FpRes.getString("message.not.specified"); + } + + String question = chatInfo.getQuestion(); + if (!ModelUtil.hasLength(question)) { + question = "No question asked"; + } + + String email = chatInfo.getEmail(); + if (!ModelUtil.hasLength(email)) { + email = FpRes.getString("message.not.specified"); + } + addAgentChat(agentJID, nickname, email, question, startDate, chatInfo.getSessionID()); + } + } + + } + }); + } + }; + + agentWorker.start(); + } + + + private void addAgentChat(Jid agent, String visitor, String email, String question, Date startDate, String session) { + // Update counter. + counter++; + activeConversations.setText(Integer.toString(counter)); + + // Conversation Item + ConversationItem item = new ConversationItem(agent.asUnescapedString(), visitor, startDate, email, question, session); + model.addElement(item); + } + + private void checkPopup(MouseEvent e) { + if (e.isPopupTrigger()) { + // Check if monitor + try { + boolean isMonitor = FastpathPlugin.getAgentSession().hasMonitorPrivileges(SparkManager.getConnection()); + if (isMonitor) { + JPopupMenu menu = new JPopupMenu(); + + int location = list.locationToIndex(e.getPoint()); + list.setSelectedIndex(location); + ConversationItem item = list.getSelectedValue(); + final String sessionID = item.getSessionID(); + + + Action joinAction = new AbstractAction() { + private static final long serialVersionUID = -3198414924157880065L; + + public void actionPerformed(ActionEvent actionEvent) { + // Get Conference + try { + final MultiUserChatManager multiUserChatManager = SparkManager.getMucManager(); + List col = multiUserChatManager.getMucServiceDomains(); + if (col.isEmpty()) { + return; + } + + DomainBareJid serviceName = col.iterator().next(); + EntityBareJid roomName = JidCreate.entityBareFromOrThrowUnchecked(sessionID + "@" + serviceName); + + MultiUserChat muc = multiUserChatManager.getMultiUserChat(roomName); + + ConferenceUtils.enterRoomOnSameThread(roomName, roomName, null); + + if (muc.isJoined()) { + // Try and remove myself as an owner if I am one. + Collection owners; + try { + owners = muc.getOwners(); + } + catch (XMPPException | SmackException e1) { + return; + } + Iterator iter = owners.iterator(); + + List list = new ArrayList<>(); + while (iter.hasNext()) { + Affiliate affiliate = iter.next(); + Jid jid = affiliate.getJid(); + if (!jid.equals(SparkManager.getSessionManager().getUserBareAddress())) { + list.add(jid); + } + } + if (list.size() > 0) { + FillableForm form = muc.getConfigurationForm().getFillableForm(); + List jidStrings = new ArrayList<>(list.size()); + JidUtil.toStrings(list, jidStrings); + form.setAnswer(MUC_ROOMCONFIG_ROOMOWNERS, jidStrings); + + // new DataFormDialog(groupChat, form); + muc.sendConfigurationForm(form); + } + } + } + catch (Exception e1) { + Log.error(e1); + } + } + }; + + joinAction.putValue(Action.NAME, FpRes.getString("menuitem.join.chat")); + menu.add(joinAction); + + Action monitorAction = new AbstractAction() { + private static final long serialVersionUID = 7292337790553806820L; + + public void actionPerformed(ActionEvent actionEvent) { + + // Make user an owner. + try { + FastpathPlugin.getAgentSession().makeRoomOwner(SparkManager.getConnection(), sessionID); + MultiUserChatManager mucManager = SparkManager.getMucManager(); + List col = mucManager.getMucServiceDomains(); + if (col.isEmpty()) { + return; + } + + DomainBareJid serviceName = col.iterator().next(); + EntityBareJid roomName = JidCreate.entityBareFromOrThrowUnchecked(sessionID + "@" + serviceName); + + MultiUserChat muc = mucManager.getMultiUserChat( roomName ); + + ConferenceUtils.enterRoomOnSameThread(roomName, roomName, null); + } + catch (XMPPException | SmackException | InterruptedException e1) { + Log.error(e1); + } + } + }; + + monitorAction.putValue(Action.NAME, FpRes.getString("menuitem.monitor.chat")); + menu.add(monitorAction); + menu.show(list, e.getX(), e.getY()); + } + } + catch (XMPPException | SmackException | InterruptedException e1) { + Log.error(e1); + } + } + } + + public void showDialog() { + if (mainFrame == null) { + mainFrame = new JFrame(FpRes.getString("title.current.conversations")); + } + if (mainFrame.isVisible()) { + return; + } + mainFrame.setIconImage(SparkManager.getMainWindow().getIconImage()); + mainFrame.getContentPane().setLayout(new BorderLayout()); + mainFrame.getContentPane().add(new JScrollPane(this)); + mainFrame.pack(); + mainFrame.setSize(400, 400); + mainFrame.setLocationRelativeTo(SparkManager.getMainWindow()); + mainFrame.setVisible(true); + } + + +} diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/FastpathPanelRenderer.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/FastpathPanelRenderer.java similarity index 97% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/FastpathPanelRenderer.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/FastpathPanelRenderer.java index e4c4f984a..e31224480 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/FastpathPanelRenderer.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/FastpathPanelRenderer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,7 +24,7 @@ import java.awt.Component; import java.awt.Color; -public class FastpathPanelRenderer extends JPanel implements ListCellRenderer { +public class FastpathPanelRenderer extends JPanel implements ListCellRenderer { private static final long serialVersionUID = 1964407022568150717L; /** diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/HistoryItem.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/HistoryItem.java similarity index 88% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/HistoryItem.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/HistoryItem.java index a3651b76b..104a2b785 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/HistoryItem.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/HistoryItem.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,11 +32,11 @@ public class HistoryItem extends JPanel { private static final long serialVersionUID = -3410684714855388210L; - private JLabel fullNameLabel = new JLabel(); - private JLabel emailLabel = new JLabel(); - private JLabel dateLabel = new JLabel(); - private JLabel questionLabel = new JLabel(); - private JLabel conversationLabel = new JLabel(); + private final JLabel fullNameLabel = new JLabel(); + private final JLabel emailLabel = new JLabel(); + private final JLabel dateLabel = new JLabel(); + private final JLabel questionLabel = new JLabel(); + private final JLabel conversationLabel = new JLabel(); private String sessionID; @@ -89,10 +85,8 @@ public HistoryItem(String fullName, Date date, String email, String question, St } public String getToolTipText() { - StringBuffer buf = new StringBuffer(); - buf.append(""); - buf.append("
      " + FpRes.getString("question") + ": " + questionLabel.getText() + "
      "); - return buf.toString(); + return "" + "
      " + FpRes.getString("question") + ": " + + questionLabel.getText() + "
      "; } public void setSessionID(String sessionID) { diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/HistoryItemRenderer.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/HistoryItemRenderer.java similarity index 97% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/HistoryItemRenderer.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/HistoryItemRenderer.java index 51ae775b5..260cdf3d4 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/HistoryItemRenderer.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/HistoryItemRenderer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,7 +30,7 @@ * * @author Derek DeMoro */ -public class HistoryItemRenderer extends JPanel implements ListCellRenderer { +public class HistoryItemRenderer extends JPanel implements ListCellRenderer { private static final long serialVersionUID = 5290058516051285328L; /** diff --git a/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/InvitationPane.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/InvitationPane.java new file mode 100644 index 000000000..60b916d36 --- /dev/null +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/InvitationPane.java @@ -0,0 +1,292 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.fastpath.workspace.panes; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.jivesoftware.fastpath.FastpathPlugin; +import org.jivesoftware.fastpath.FpRes; +import org.jivesoftware.fastpath.resources.FastpathRes; +import org.jivesoftware.fastpath.workspace.Workpane.RoomState; +import org.jivesoftware.fastpath.workspace.assistants.RoomInformation; +import org.jivesoftware.fastpath.workspace.util.RequestUtils; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smackx.muc.MultiUserChatManager; +import org.jivesoftware.smackx.xdata.form.FillableForm; +import org.jivesoftware.smackx.muc.Affiliate; +import org.jivesoftware.smackx.muc.MultiUserChat; +import org.jivesoftware.smackx.workgroup.MetaData; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.ChatNotFoundException; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.LinkLabel; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.component.WrappedLabel; +import org.jivesoftware.spark.ui.ChatContainer; +import org.jivesoftware.spark.ui.conferences.ConferenceUtils; +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.util.JidUtil; +import org.jxmpp.util.XmppStringUtils; + +import static org.jivesoftware.smackx.muc.MucConfigFormManager.MUC_ROOMCONFIG_ROOMOWNERS; + +public class InvitationPane { + + private Map> metadata = null; + private GroupChatRoom chatRoom; + + public InvitationPane(final RequestUtils request, final EntityBareJid room, final EntityBareJid inviter, String reason, final String password, final Message message) { + final JPanel transcriptAlert = new JPanel(); + transcriptAlert.setBackground(Color.white); + transcriptAlert.setLayout(new GridBagLayout()); + + + JLabel userImage = new JLabel(FastpathRes.getImageIcon(FastpathRes.FASTPATH_IMAGE_16x16)); + userImage.setHorizontalAlignment(JLabel.LEFT); + String title = FpRes.getString("title.fastpath.invitation"); + if (request.isTransfer()) { + title = FpRes.getString("title.fastpath.transfer"); + } + + + userImage.setText(title); + transcriptAlert.add(userImage, new GridBagConstraints(0, 0, 4, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0)); + userImage.setFont(new Font("Dialog", Font.BOLD, 12)); + + final JLabel inviterLabel = new JLabel(FpRes.getString("from") + ":"); + inviterLabel.setFont(new Font("Dialog", Font.BOLD, 11)); + final WrappedLabel inviterValueLabel = new WrappedLabel(); + + String nickname = SparkManager.getUserManager().getUserNicknameFromJID(inviter); + inviterValueLabel.setText(nickname); + transcriptAlert.add(inviterLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); + transcriptAlert.add(inviterValueLabel, new GridBagConstraints(1, 1, 3, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0)); + + + final JLabel nameLabel = new JLabel(FpRes.getString("room") + ":"); + nameLabel.setFont(new Font("Dialog", Font.BOLD, 11)); + final WrappedLabel valueLabel = new WrappedLabel(); + valueLabel.setText(room.toString()); + transcriptAlert.add(nameLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); + transcriptAlert.add(valueLabel, new GridBagConstraints(1, 2, 3, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0)); + + final JLabel messageLabel = new JLabel(FpRes.getString("message") + ":"); + messageLabel.setFont(new Font("Dialog", Font.BOLD, 11)); + final WrappedLabel messageValueLabel = new WrappedLabel(); + messageValueLabel.setText(reason); + transcriptAlert.add(messageLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); + transcriptAlert.add(messageValueLabel, new GridBagConstraints(1, 3, 3, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0)); + + // Add accept button and reject button. + final RolloverButton acceptButton = new RolloverButton("Accept", FastpathRes.getImageIcon(FastpathRes.CIRCLE_CHECK_IMAGE)); + final RolloverButton rejectButton = new RolloverButton("Decline", FastpathRes.getImageIcon(FastpathRes.SMALL_DELETE)); + + ResourceUtils.resButton(acceptButton, FpRes.getString("button.accept")); + ResourceUtils.resButton(rejectButton, FpRes.getString("button.reject")); + + LinkLabel infoButton = new LinkLabel(FpRes.getString("message.view.more.information"), null, Color.blue, Color.red); + transcriptAlert.add(infoButton, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); + transcriptAlert.add(acceptButton, new GridBagConstraints(1, 4, 1, 1, 1.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); + transcriptAlert.add(rejectButton, new GridBagConstraints(2, 4, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); + transcriptAlert.add(new JLabel(), new GridBagConstraints(2, 5, 1, 1, 0.0, 1.0, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); + + + MetaData metaDataExt = message.getExtension(MetaData.class); + if (metaDataExt != null) { + metadata = metaDataExt.getMetaData(); + } + + + infoButton.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + RoomInformation roomInformation = new RoomInformation(); + if (metadata != null) { + roomInformation.showAllInformation(metadata); + roomInformation.showRoomInformation(); + } + + } + }); + + + acceptButton.addActionListener(actionEvent -> { + SwingWorker waiter = new SwingWorker() { + public Object construct() { + try { + Thread.sleep(50); + } + catch (InterruptedException e) { + Log.error(e); + } + return true; + } + + public void finished() { + String roomName = request.getUsername(); + chatRoom.getSplitPane().getRightComponent().setVisible(true); + chatRoom.getBottomPanel().setVisible(true); + + chatRoom.getScrollPaneForTranscriptWindow().setVisible(true); + chatRoom.getEditorBar().setVisible(true); + chatRoom.getChatInputEditor().setEnabled(true); + chatRoom.getToolBar().setVisible(true); + chatRoom.getVerticalSlipPane().setDividerLocation(0.8); + chatRoom.getSplitPane().setDividerLocation(0.8); + transcriptAlert.setVisible(false); + + String name = XmppStringUtils.parseLocalpart(roomName); + + try { + chatRoom.setTabTitle(roomName); + chatRoom.getConferenceRoomInfo().setNicknameChangeAllowed(false); + + chatRoom.getToolBar().setVisible(true); + chatRoom.getEditorBar().setVisible(true); + chatRoom.getChatInputEditor().setEnabled(true); + + ChatContainer chatContainer = SparkManager.getChatManager().getChatContainer(); + chatContainer.setChatRoomTitle(chatRoom, roomName); + if (chatContainer.getActiveChatRoom() == chatRoom) { + chatContainer.getChatFrame().setTitle(roomName); + } + + } + catch (Exception e) { + Log.error(e); + } + + ConferenceUtils.enterRoomOnSameThread(roomName, room, password); + removeOwner(chatRoom.getMultiUserChat()); + + FastpathPlugin.getLitWorkspace().checkForDecoration(chatRoom, request.getSessionID()); + } + }; + + waiter.start(); + }); + + // Add to Chat window + ChatManager chatManager = SparkManager.getChatManager(); + + try { + chatRoom = chatManager.getGroupChat(room); + } + catch (ChatNotFoundException e) { + MultiUserChatManager mucManager = SparkManager.getMucManager(); + MultiUserChat chat = mucManager.getMultiUserChat(room); + chatRoom = new GroupChatRoom(chat); + } + + chatRoom.setTabTitle(title); + chatRoom.setTabIcon(SparkRes.getImageIcon(SparkRes.Icon.FASTPATH_IMAGE_16x16)); + chatRoom.getChatWindowPanel().add(transcriptAlert, new GridBagConstraints(0, 9, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(1, 0, 1, 0), 0, 0)); + + // set invisible + chatRoom.getSplitPane().getRightComponent().setVisible(false); + chatRoom.getBottomPanel().setVisible(false); + chatRoom.getScrollPaneForTranscriptWindow().setVisible(false); + + SparkManager.getChatManager().getChatContainer().addChatRoom(chatRoom); + + FastpathPlugin.getLitWorkspace().addFastpathChatRoom(chatRoom, RoomState.invitationRequest); + + rejectButton.addActionListener(actionEvent -> { + // Add to Chat window + ChatManager chatManager1 = SparkManager.getChatManager(); + chatManager1.removeChat(chatRoom); + + try + { + MultiUserChatManager mucManager = SparkManager.getMucManager(); + mucManager.decline( room, inviter, "No thank you" ); + } + catch ( SmackException.NotConnectedException | InterruptedException e ) + { + Log.warning( "Unable to decline invitation from " + inviter + " to join room " + room, e ); + } + }); + + } + + /** + * Removes oneself as an owner of the room. + * + * @param muc the MultiUserChat of the chat room. + */ + private void removeOwner(MultiUserChat muc) { + if (muc.isJoined()) { + // Try and remove myself as an owner if I am one. + Collection owners; + try { + owners = muc.getOwners(); + } + catch (XMPPException | SmackException | InterruptedException e1) { + return; + } + + if (owners == null) { + return; + } + + Iterator iter = owners.iterator(); + + List list = new ArrayList<>(); + while (iter.hasNext()) { + Affiliate affiliate = iter.next(); + Jid jid = affiliate.getJid(); + if (!jid.equals(SparkManager.getSessionManager().getUserBareAddress())) { + list.add(jid); + } + } + if (list.size() > 0) { + try { + FillableForm form = muc.getConfigurationForm().getFillableForm(); + List jidStrings = new ArrayList<>(list.size()); + JidUtil.toStrings(list, jidStrings); + form.setAnswer(MUC_ROOMCONFIG_ROOMOWNERS, jidStrings); + + // new DataFormDialog(groupChat, form); + muc.sendConfigurationForm(form); + } + catch (XMPPException | SmackException | InterruptedException e) { + Log.error(e); + } + } + } + } +} diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/OnlineAgents.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/OnlineAgents.java similarity index 81% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/OnlineAgents.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/OnlineAgents.java index 0edbdcfe8..32096877c 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/OnlineAgents.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/OnlineAgents.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,11 +36,9 @@ import org.jivesoftware.fastpath.resources.FastpathRes; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.workgroup.agent.AgentRoster; import org.jivesoftware.smackx.workgroup.agent.AgentRosterListener; import org.jivesoftware.smackx.workgroup.packet.AgentStatus; -import org.jivesoftware.smackx.workgroup.packet.AgentStatus.ChatInfo; import org.jivesoftware.spark.ChatManager; import org.jivesoftware.spark.PresenceManager; import org.jivesoftware.spark.SparkManager; @@ -60,7 +54,10 @@ import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.spark.util.SwingWorker; import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.parts.Localpart; +import org.jxmpp.jid.parts.Resourcepart; /** @@ -70,22 +67,22 @@ public final class OnlineAgents extends JPanel { private static final long serialVersionUID = 1L; private AgentRoster agentRoster; - private ContactGroup contactGroup; - private JPanel topToolbar = new JPanel(); + private final ContactGroup contactGroup; public OnlineAgents() { setLayout(new BorderLayout()); + JPanel topToolbar = new JPanel(); topToolbar.setLayout(new GridBagLayout()); topToolbar.setBackground(Color.white); setBackground(Color.white); - final String name = XmppStringUtils.parseLocalpart(FastpathPlugin.getWorkgroup().getWorkgroupJID()); + final Localpart name = FastpathPlugin.getWorkgroup().getWorkgroupJID().getLocalpartOrThrow(); final String title = org.jivesoftware.spark.util.StringUtils.makeFirstWordCaptial(name); contactGroup = new ContactGroup(FpRes.getString("title.workgroup", title)); - contactGroup.getContainerPanel().add(topToolbar, BorderLayout.NORTH); + contactGroup.getContainerPanel().add( topToolbar, BorderLayout.NORTH); contactGroup.setIcon(FastpathRes.getImageIcon(FastpathRes.FASTPATH_IMAGE_16x16)); contactGroup.setBackground(Color.white); contactGroup.setOpaque(false); @@ -102,7 +99,11 @@ public void contactItemRemoved(ContactItem item) { } public void contactItemDoubleClicked(ContactItem item) { - activateChat(item.getJID(), item.getNickname()); + Resourcepart resourcepart = Resourcepart.fromOrThrowUnchecked(item.getNickname()); + // TODO: This is a good indicator that + // - nickname should be of type Resourcepart pretty sure + // - item.getJid() should possibly return an EntityBareJid + activateChat(item.getJid().asEntityBareJidOrThrow(), resourcepart); } public void contactItemClicked(ContactItem item) { @@ -113,7 +114,7 @@ public void showPopup(MouseEvent e, ContactItem item) { } - public void showPopup(MouseEvent e, Collection items) { + public void showPopup(MouseEvent e, Collection items) { } @@ -147,7 +148,7 @@ public void init() { return; } SwingWorker agentWorker = new SwingWorker() { - Collection agentSet; + Collection agentSet; public Object construct() { // Initialize Agent Roster @@ -157,7 +158,7 @@ public Object construct() { agentSet = agentRoster.getAgents(); return agentSet; } - catch ( SmackException.NotConnectedException e ) + catch ( SmackException.NotConnectedException | InterruptedException e ) { Log.error( "Unable to load agent roster.", e); return null; @@ -165,29 +166,30 @@ public Object construct() { } public void finished() { - final List agentList = new ArrayList(agentSet); + final List agentList = new ArrayList<>(agentSet); Collections.sort(agentList); - Iterator agents = agentList.iterator(); - while (agents.hasNext()) { - final String agent = (String)agents.next(); - - String nickname = SparkManager.getUserManager().getUserNicknameFromJID(agent); - if (nickname == null) { - nickname = agent; + for ( EntityBareJid agent : agentList ) + { + String nickname = SparkManager.getUserManager().getUserNicknameFromJID( agent ); + if ( nickname == null ) + { + nickname = agent.toString(); } - ContactItem item = new ContactItem(nickname,nickname, agent) { - private static final long serialVersionUID = -8888899031363239813L; + ContactItem item = new ContactItem( nickname, nickname, agent ) + { + private static final long serialVersionUID = -8888899031363239813L; - public String getToolTipText() { - Presence agentPresence = agentRoster.getPresence(agent); - return buildTooltip(agentPresence); + public String getToolTipText() + { + Presence agentPresence = agentRoster.getPresence( agent ); + return buildTooltip( agentPresence ); } }; - Presence agentPresence = agentRoster.getPresence(agent); - item.setPresence(agentPresence); + Presence agentPresence = agentRoster.getPresence( agent ); + item.setPresence( agentPresence ); } @@ -207,12 +209,12 @@ private String buildTooltip(Presence presence) { return FpRes.getString("message.user.not.logged.in"); } - AgentStatus agentStatus = (AgentStatus)presence.getExtension("agent-status", "http://jabber.org/protocol/workgroup"); + AgentStatus agentStatus = presence.getExtension(AgentStatus.class); List list = agentStatus.getCurrentChats(); // Add new ones. Iterator iter = list.iterator(); - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); buf.append(""); buf.append(""); buf.append(""); @@ -220,7 +222,6 @@ private String buildTooltip(Presence presence) { while (iter.hasNext()) { AgentStatus.ChatInfo chatInfo = iter.next(); Date startDate = chatInfo.getDate(); - String username = chatInfo.getUserID(); String nickname = chatInfo.getUsername(); if (!ModelUtil.hasLength(nickname)) { @@ -262,7 +263,7 @@ private String buildTooltip(Presence presence) { /** * Activate a chat room with the selected user. */ - private void activateChat(final String userJID, final String nickname) { + private void activateChat(final EntityBareJid userJID, final Resourcepart nickname) { if (!ModelUtil.hasLength(userJID)) { return; } @@ -285,7 +286,7 @@ public Object construct() { chatRoom = chatRooms.getChatRoom(userJID); } catch (ChatRoomNotFoundException e) { - + Log.warning( "Room not found for jid: " + userJID, e ); } return chatRoom; } @@ -304,10 +305,11 @@ public void finished() { } public class OnlineAgentListener implements AgentRosterListener { - public void agentAdded(final String agent) { + @Override + public void agentAdded(final EntityBareJid agent) { String nickname = SparkManager.getUserManager().getUserNicknameFromJID(agent); if (nickname == null) { - nickname = agent; + nickname = agent.toString(); } Presence agentPresence = agentRoster.getPresence(agent); @@ -327,14 +329,16 @@ public String getToolTipText() { } } - public void agentRemoved(String jid) { + @Override + public void agentRemoved(EntityBareJid jid) { ContactItem item = contactGroup.getContactItemByJID(jid); contactGroup.removeContactItem(item); contactGroup.fireContactGroupUpdated(); } + @Override public void presenceChanged(Presence presence) { - String jid = XmppStringUtils.parseBareJid(presence.getFrom()); + BareJid jid = presence.getFrom().asBareJid(); ContactItem item = contactGroup.getContactItemByJID(jid); if (item != null) { @@ -352,12 +356,12 @@ else if (presence.getType() == Presence.Type.available) { } else { if (presence.getType() == Presence.Type.available) { - String agent = XmppStringUtils.parseBareJid(presence.getFrom()); + EntityBareJid agent = presence.getFrom().asEntityBareJidOrThrow(); String nickname = SparkManager.getUserManager().getUserNicknameFromJID(agent); if (nickname == null) { - nickname = agent; + nickname = agent.toString(); } - ContactItem contactItem = new ContactItem(nickname,nickname, XmppStringUtils.parseBareJid(presence.getFrom())); + ContactItem contactItem = new ContactItem(nickname,nickname, presence.getFrom().asBareJid()); contactItem.setPresence(presence); contactGroup.addContactItem(contactItem); } diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/QueueActivity.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/QueueActivity.java similarity index 78% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/QueueActivity.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/QueueActivity.java index 6779feaa4..704e9f4ab 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/QueueActivity.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/QueueActivity.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -44,10 +40,10 @@ public final class QueueActivity extends JPanel implements QueueUsersListener { private static final long serialVersionUID = 1L; - private DefaultListModel model = new DefaultListModel(); - private JList list; + private final DefaultListModel model = new DefaultListModel<>(); + private JList list; - private Map queues = new HashMap(); + private final Map queues = new HashMap<>(); /** * Add Listeners and build UI. @@ -62,7 +58,7 @@ public void removeListener() { } private void init() { - list = new JList(model); + list = new JList<>(model); list.setCellRenderer(new FastpathPanelRenderer()); this.setLayout(new BorderLayout()); @@ -112,23 +108,19 @@ public void averageWaitTimeUpdated(WorkgroupQueue queue, int waitTime) { public void statusUpdated(final WorkgroupQueue queue, WorkgroupQueue.Status status) { - EventQueue.invokeLater(new Runnable() { - - public void run() - { - String oldestEntry = queue.getOldestEntry() != null ? queue.getOldestEntry().toString() : ""; - - QueueItem item = queues.get(queue); - if (item != null) { - item.setNumberOfUsersInQueue(queue.getUserCount()); - item.setAverageWaitTime(queue.getAverageWaitTime()); - update(item); - return; - } - item = new QueueItem(queue.getName(), queue.getUserCount(), queue.getAverageWaitTime(), oldestEntry); - queues.put(queue, item); - model.addElement(item); - } - }); + EventQueue.invokeLater( () -> { + String oldestEntry = queue.getOldestEntry() != null ? queue.getOldestEntry().toString() : ""; + + QueueItem item = queues.get(queue); + if (item != null) { + item.setNumberOfUsersInQueue(queue.getUserCount()); + item.setAverageWaitTime(queue.getAverageWaitTime()); + update(item); + return; + } + item = new QueueItem(queue.getName(), queue.getUserCount(), queue.getAverageWaitTime(), oldestEntry); + queues.put(queue, item); + model.addElement(item); + } ); } -} \ No newline at end of file +} diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/QueueItem.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/QueueItem.java similarity index 91% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/QueueItem.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/QueueItem.java index d486b4e77..6c436068b 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/QueueItem.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/QueueItem.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,12 +33,12 @@ public class QueueItem extends JPanel { private static final long serialVersionUID = 1L; - private JLabel queueNameLabel = new JLabel(); - private JLabel numberInQueueLabel = new JLabel(); - private JLabel averageWaitTimeLabel = new JLabel(); - private JLabel lastCustomerLabel = new JLabel(); + private final JLabel queueNameLabel = new JLabel(); + private final JLabel numberInQueueLabel = new JLabel(); + private final JLabel averageWaitTimeLabel = new JLabel(); + private final JLabel lastCustomerLabel = new JLabel(); - public QueueItem(String queueName, int numberInQueue, int waitTime, String lastCustomer) { + public QueueItem(CharSequence queueName, int numberInQueue, int waitTime, String lastCustomer) { setBackground(Color.white); setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.LIGHT_GRAY)); setLayout(new GridBagLayout()); @@ -73,7 +69,7 @@ public QueueItem(String queueName, int numberInQueue, int waitTime, String lastC add(lastCustomerLabel, new GridBagConstraints(1, 4, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 2, 5), 0, 0)); lastLabel.setFont(new Font("Dialog", Font.BOLD, 11)); - queueNameLabel.setText(queueName); + queueNameLabel.setText(queueName.toString()); numberInQueueLabel.setText(Integer.toString(numberInQueue)); lastCustomerLabel.setText(lastCustomer); diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/UserInvitationPane.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/UserInvitationPane.java similarity index 86% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/UserInvitationPane.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/UserInvitationPane.java index 03882c78e..978e6cc56 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/UserInvitationPane.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/panes/UserInvitationPane.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,8 +20,6 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; @@ -49,7 +43,7 @@ import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smackx.muc.MultiUserChatManager; -import org.jivesoftware.smackx.xdata.Form; +import org.jivesoftware.smackx.xdata.form.FillableForm; import org.jivesoftware.smackx.muc.Affiliate; import org.jivesoftware.smackx.muc.MultiUserChat; import org.jivesoftware.smackx.workgroup.agent.Offer; @@ -70,27 +64,26 @@ import org.jivesoftware.spark.util.TaskEngine; import org.jivesoftware.spark.util.log.Log; import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.util.JidUtil; + +import static org.jivesoftware.smackx.muc.MucConfigFormManager.MUC_ROOMCONFIG_ROOMOWNERS; /** * Handles invitations and transfers of Fastpath Requests. */ public class UserInvitationPane { - - private Map metadata; + private Map> metadata; private AcceptListener listener; private Offer offer; - private JProgressBar progressBar; - private SparkToaster toasterManager; - - public UserInvitationPane(final Offer offer, final RequestUtils request, final String fullRoomJID, final String inviter, String reason) { + public UserInvitationPane(final Offer offer, final RequestUtils request, final EntityBareJid fullRoomJID, final EntityBareJid inviter, String reason) { // Add to Chat window ChatManager chatManager = SparkManager.getChatManager(); - - try { GroupChatRoom chatRoom = chatManager.getGroupChat(fullRoomJID); if (chatRoom.isActive()) { @@ -98,12 +91,11 @@ public UserInvitationPane(final Offer offer, final RequestUtils request, final S return; } } - catch ( SmackException.NotConnectedException | ChatNotFoundException e) + catch ( SmackException.NotConnectedException | ChatNotFoundException | InterruptedException e) { Log.warning( "Unable to reject offer " + offer, e ); } - final JPanel transcriptAlert = new JPanel(); transcriptAlert.setBackground(Color.white); transcriptAlert.setLayout(new GridBagLayout()); @@ -113,12 +105,10 @@ public UserInvitationPane(final Offer offer, final RequestUtils request, final S progressBar = new JProgressBar(); progressBar.setFont(new Font("Dialog", Font.BOLD, 11)); - final JPanel topPanel = new JPanel(); topPanel.setBackground(Color.white); topPanel.setLayout(new GridBagLayout()); - JLabel userImage = new JLabel(FastpathRes.getImageIcon(FastpathRes.FASTPATH_IMAGE_16x16)); userImage.setHorizontalAlignment(JLabel.LEFT); String title = FpRes.getString("title.fastpath.invitation"); @@ -126,7 +116,6 @@ public UserInvitationPane(final Offer offer, final RequestUtils request, final S title = FpRes.getString("title.fastpath.transfer"); } - userImage.setText(title); topPanel.add(userImage, new GridBagConstraints(0, 0, 4, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0)); userImage.setFont(new Font("Dialog", Font.BOLD, 12)); @@ -146,7 +135,7 @@ public UserInvitationPane(final Offer offer, final RequestUtils request, final S nameLabel.setFont(new Font("Dialog", Font.BOLD, 11)); final WrappedLabel valueLabel = new WrappedLabel(); valueLabel.setBackground(Color.white); - valueLabel.setText(fullRoomJID); + valueLabel.setText(fullRoomJID.toString()); topPanel.add(nameLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); topPanel.add(valueLabel, new GridBagConstraints(1, 2, 3, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0)); @@ -174,10 +163,8 @@ public UserInvitationPane(final Offer offer, final RequestUtils request, final S transcriptAlert.add(infoButton, new GridBagConstraints(0, 5, 1, 1, 0.0, 1.0, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); transcriptAlert.add(acceptButton, new GridBagConstraints(1, 5, 1, 1, 1.0, 1.0, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); transcriptAlert.add(rejectButton, new GridBagConstraints(2, 5, 1, 1, 0.0, 1.0, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - metadata = offer.getMetaData(); - infoButton.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { RoomInformation roomInformation = new RoomInformation(); @@ -185,40 +172,27 @@ public void mouseClicked(MouseEvent e) { roomInformation.showAllInformation(metadata); roomInformation.showRoomInformation(); } - } }); - - acceptButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent actionEvent) { - - final TimerTask loadRoomTask = new SwingTimerTask() { - public void doRun() { - try - { - offer.accept(); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to accept offer " + offer, e1 ); - } - closeToaster(); - startFastpathChat(fullRoomJID, request.getUsername()); + acceptButton.addActionListener(actionEvent -> { + final TimerTask loadRoomTask = new SwingTimerTask() { + public void doRun() { + try + { + offer.accept(); } - }; - - TaskEngine.getInstance().schedule(loadRoomTask, 100); - } - }); - - - rejectButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent actionEvent) { - rejectOffer(); - } + catch ( SmackException.NotConnectedException | InterruptedException e1 ) + { + Log.warning( "Unable to accept offer " + offer, e1 ); + } + closeToaster(); + startFastpathChat(fullRoomJID, request.getUsername()); + } + }; + TaskEngine.getInstance().schedule(loadRoomTask, 100); }); - + rejectButton.addActionListener(actionEvent -> rejectOffer()); // Start progress bart final Date endTime = offer.getExpiresDate(); Date now = new Date(); @@ -228,7 +202,6 @@ public void actionPerformed(ActionEvent actionEvent) { progressBar.setMaximum(seconds); progressBar.setValue(seconds); - SwingWorker worker = new SwingWorker() { public Object construct() { while (true) { @@ -243,11 +216,8 @@ public Object construct() { catch (InterruptedException e) { Log.error(e); } - progressBar.setValue(progressBar.getValue() - 1); progressBar.setStringPainted(true); - - int seconds = (int)(endTime.getTime() - now.getTime()) / 1000; if (seconds <= 60) { String timeString = seconds + " " + FpRes.getString("seconds"); @@ -256,7 +226,6 @@ public Object construct() { else { long difference = endTime.getTime() - now.getTime(); String timeString = ModelUtil.getTimeFromLong(difference); - progressBar.setString(timeString); } } @@ -287,7 +256,7 @@ public void rejectOffer() { { offer.reject(); } - catch ( SmackException.NotConnectedException e ) + catch ( SmackException.NotConnectedException | InterruptedException e ) { Log.warning( "Unable to reject offer " + offer, e ); } @@ -317,11 +286,11 @@ public void dispose() { private void removeOwner(MultiUserChat muc) { if (muc.isJoined()) { // Try and remove myself as an owner if I am one. - Collection owners = null; + Collection owners; try { owners = muc.getOwners(); } - catch (XMPPException | SmackException e1) { + catch (XMPPException | SmackException | InterruptedException e1) { return; } @@ -331,23 +300,24 @@ private void removeOwner(MultiUserChat muc) { Iterator iter = owners.iterator(); - List list = new ArrayList(); + List list = new ArrayList<>(); while (iter.hasNext()) { - Affiliate affilitate = iter.next(); - String jid = affilitate.getJid(); - if (!jid.equals(SparkManager.getSessionManager().getBareAddress())) { + Affiliate affiliate = iter.next(); + Jid jid = affiliate.getJid(); + if (!jid.equals(SparkManager.getSessionManager().getUserBareAddress())) { list.add(jid); } } if (list.size() > 0) { try { - Form form = muc.getConfigurationForm().createAnswerForm(); - form.setAnswer("muc#roomconfig_roomowners", list); + FillableForm form = muc.getConfigurationForm().getFillableForm(); + List jidStrings = JidUtil.toStringList(list); + form.setAnswer(MUC_ROOMCONFIG_ROOMOWNERS, jidStrings); // new DataFormDialog(groupChat, form); muc.sendConfigurationForm(form); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error(e); } } @@ -384,7 +354,7 @@ private void closeToaster() { toasterManager.close(); } - private void startFastpathChat(String fullRoomJID, String roomName) { + private void startFastpathChat(EntityBareJid fullRoomJID, String roomName) { // Add to Chat window ChatManager chatManager = SparkManager.getChatManager(); @@ -394,7 +364,8 @@ private void startFastpathChat(String fullRoomJID, String roomName) { if (!chatRoom.isActive()) { // Remove old room, add new room. chatManager.removeChat(chatRoom); - MultiUserChat chat = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getMultiUserChat( fullRoomJID ); + MultiUserChatManager mucManager = SparkManager.getMucManager(); + MultiUserChat chat = mucManager.getMultiUserChat(fullRoomJID); chatRoom = new GroupChatRoom(chat); } else { @@ -403,21 +374,20 @@ private void startFastpathChat(String fullRoomJID, String roomName) { { offer.reject(); } - catch ( SmackException.NotConnectedException e ) + catch ( SmackException.NotConnectedException | InterruptedException e ) { Log.warning( "Unable to reject offer " + offer, e ); } return; } - } catch (ChatNotFoundException e) { - MultiUserChat chat = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getMultiUserChat( fullRoomJID ); + MultiUserChatManager mucManager = SparkManager.getMucManager(); + MultiUserChat chat = mucManager.getMultiUserChat(fullRoomJID); chatRoom = new GroupChatRoom(chat); } chatRoom.getSplitPane().setDividerSize(5); - chatRoom.getSplitPane().getRightComponent().setVisible(true); chatRoom.getBottomPanel().setVisible(true); @@ -426,7 +396,6 @@ private void startFastpathChat(String fullRoomJID, String roomName) { chatRoom.getChatInputEditor().setEnabled(true); chatRoom.getToolBar().setVisible(true); - chatRoom.getVerticalSlipPane().setDividerLocation(0.8); chatRoom.getSplitPane().setDividerLocation(0.6); @@ -442,13 +411,10 @@ private void startFastpathChat(String fullRoomJID, String roomName) { chatContainer.addChatRoom(chatRoom); FastpathPlugin.getLitWorkspace().addFastpathChatRoom(chatRoom, Workpane.RoomState.activeRoom); - chatContainer.setChatRoomTitle(chatRoom, roomName); - if (chatContainer.getActiveChatRoom() == chatRoom) { chatContainer.getChatFrame().setTitle(roomName); } - } catch (Exception e) { Log.error(e); @@ -458,14 +424,10 @@ private void startFastpathChat(String fullRoomJID, String roomName) { removeOwner(chatRoom.getMultiUserChat()); FastpathPlugin.getLitWorkspace().checkForDecoration(chatRoom, offer.getSessionID()); - if (listener != null) { listener.yesOption(); listener = null; } } - } - - diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/search/ChatSearch.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/search/ChatSearch.java similarity index 79% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/search/ChatSearch.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/search/ChatSearch.java index 345737bae..502c37575 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/search/ChatSearch.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/search/ChatSearch.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,19 +25,11 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.Date; -import java.util.Iterator; import java.util.List; -import javax.swing.BorderFactory; -import javax.swing.DefaultListModel; -import javax.swing.Icon; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JScrollPane; +import javax.swing.*; import org.jivesoftware.fastpath.FastpathPlugin; import org.jivesoftware.fastpath.FpRes; @@ -51,14 +39,17 @@ import org.jivesoftware.fastpath.workspace.panes.HistoryItemRenderer; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.xdata.Form; import org.jivesoftware.smackx.search.ReportedData; import org.jivesoftware.smackx.workgroup.agent.AgentSession; import org.jivesoftware.smackx.workgroup.packet.Transcript; +import org.jivesoftware.smackx.xdata.form.FillableForm; +import org.jivesoftware.smackx.xdata.form.Form; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.search.Searchable; import org.jivesoftware.spark.util.GraphicUtils; import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.util.JidUtil; public class ChatSearch implements Searchable { @@ -79,19 +70,20 @@ public String getToolTip() { } public void search(String query) { - final List results = new ArrayList(); + final List results = new ArrayList<>(); AgentSession agentSession = FastpathPlugin.getAgentSession(); try { Form form = agentSession.getTranscriptSearchForm(); - Form filledForm = form.createAnswerForm(); + FillableForm filledForm = form.getFillableForm(); filledForm.setAnswer("queryString", query); // Define Workgroups - final List workgroups = new ArrayList(); + final List workgroups = new ArrayList<>(); workgroups.add(FastpathPlugin.getWorkgroup().getWorkgroupJID()); - filledForm.setAnswer("workgroups", workgroups); + List workgroupStrings = JidUtil.toStringList(workgroups); + filledForm.setAnswer("workgroups", workgroupStrings); - ReportedData reportedData = null; + ReportedData reportedData; try { reportedData = agentSession.searchTranscripts(filledForm); for ( final ReportedData.Row row : reportedData.getRows() ) { @@ -99,19 +91,17 @@ public void search(String query) { results.add(result); } } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error(e); } - Collections.sort(results, dateComporator); - DefaultListModel model = new DefaultListModel(); - final JList list = new JList(model); + results.sort(dateComparator); + DefaultListModel model = new DefaultListModel<>(); + final JList list = new JList<>(model); list.setCellRenderer(new HistoryItemRenderer()); - Iterator iter = results.iterator(); - while (iter.hasNext()) { - ChatSearchResult result = iter.next(); + for (ChatSearchResult result : results) { String person = result.getUsername(); String question = result.getQuestion(); String sessionID = result.getSessionID(); @@ -125,13 +115,13 @@ public void search(String query) { list.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { - SearchItem item = (SearchItem)list.getSelectedValue(); + SearchItem item = list.getSelectedValue(); Transcript transcript = null; try { transcript = FastpathPlugin.getAgentSession().getTranscript(item.getSessionID()); } - catch (XMPPException | SmackException ee) { + catch (XMPPException | SmackException | InterruptedException ee) { Log.error("Error showing transcripts.", ee); } @@ -199,7 +189,7 @@ public Dimension getPreferredSize() { GraphicUtils.centerWindowOnScreen(frame); frame.setVisible(true); } - catch (XMPPException | SmackException e) { + catch (XMPPException | SmackException | InterruptedException e) { Log.error(e); } @@ -209,27 +199,11 @@ public Dimension getPreferredSize() { /** * Sorts all SearchResults by Relevance. */ - final Comparator dateComporator = new Comparator() { - public int compare(Object o1, Object o2) { - final ChatSearchResult item1 = (ChatSearchResult)o1; - final ChatSearchResult item2 = (ChatSearchResult)o2; + final Comparator dateComparator = (o1, o2) -> { - long int1 = item1.getStartDate().getTime(); - long int2 = item2.getStartDate().getTime(); + long int1 = o1.getStartDate().getTime(); + long int2 = o2.getStartDate().getTime(); - if (int1 == int2) { - return 0; - } - - if (int1 > int2) { - return -1; - } - - if (int1 < int2) { - return 1; - } - - return 0; - } + return Long.compare(int2, int1); }; } diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/search/ChatSearchResult.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/search/ChatSearchResult.java similarity index 75% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/search/ChatSearchResult.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/search/ChatSearchResult.java index b319c4efd..bad33fb30 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/search/ChatSearchResult.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/search/ChatSearchResult.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,7 +21,6 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; -import java.util.Iterator; import java.util.List; import java.util.TimeZone; @@ -34,15 +29,14 @@ public class ChatSearchResult { private final SimpleDateFormat UTC_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss"); - private String sessionID; + private final String sessionID; private Date creationDate; - private int relevance; - private String question; - private String customerName; - private String email; + private final String question; + private final String customerName; + private final String email; - private List fields = new ArrayList(); + private final List fields = new ArrayList<>(); public ChatSearchResult(ReportedData.Row row, String query) { UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+0")); @@ -59,18 +53,13 @@ public ChatSearchResult(ReportedData.Row row, String query) { sessionID = getFirstValue(row, "sessionID"); - StringBuffer authors = new StringBuffer(); - for ( final String agentJID : row.getValues("agentJIDs") ) + StringBuilder authors = new StringBuilder(); + for ( final CharSequence agentJID : row.getValues("agentJIDs") ) { authors.append(agentJID); authors.append(" "); } - String rell = getFirstValue(row, "relevance"); - Double o = Double.valueOf(rell); - - relevance = ((int)o.doubleValue() * 100); - question = getFirstValue(row, "question"); customerName = getFirstValue(row, "username"); email = getFirstValue(row, "email"); @@ -79,27 +68,27 @@ public ChatSearchResult(ReportedData.Row row, String query) { fields.add(question); fields.add(email); fields.add(authors.toString()); - fields.add(creationDate); + fields.add(creationDate.toString()); } public String getFirstValue(ReportedData.Row row, String key) { - final List values = row.getValues( key ); + final List values = row.getValues( key ); if ( values.isEmpty() ) { return null; } - return values.get(0); + return values.get(0).toString(); } public String getSummary() { - final StringBuffer buf = new StringBuffer(); - buf.append(FpRes.getString("chat.with") + " "); + final StringBuilder buf = new StringBuilder(); + buf.append(FpRes.getString("chat.with")).append(" "); buf.append(customerName); buf.append(" "); if (question != null) { - buf.append(FpRes.getString("question") + ": "); + buf.append(FpRes.getString("question")).append(": "); buf.append(question); } return buf.toString(); diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/search/SearchItem.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/search/SearchItem.java similarity index 88% rename from src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/search/SearchItem.java rename to plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/search/SearchItem.java index e7eb36921..cbb64c2ad 100644 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/search/SearchItem.java +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/search/SearchItem.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,9 +33,9 @@ public class SearchItem extends JPanel { private static final long serialVersionUID = -6319272932605736970L; - private JLabel fullNameLabel = new JLabel(); - private JLabel dateLabel = new JLabel(); - private JLabel questionLabel = new JLabel(); + private final JLabel fullNameLabel = new JLabel(); + private final JLabel dateLabel = new JLabel(); + private final JLabel questionLabel = new JLabel(); private String sessionID; @@ -73,10 +69,8 @@ public SearchItem(String fullName, Date date, String question) { } public String getToolTipText(){ - StringBuffer buf = new StringBuffer(); - buf.append(""); - buf.append("
      "+FpRes.getString("question") + ": "+questionLabel.getText()+"
      "); - return buf.toString(); + return "" + "
      " + FpRes.getString("question") + + ": " + questionLabel.getText() + "
      "; } public void setSessionID(String sessionID) { diff --git a/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/util/RequestUtils.java b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/util/RequestUtils.java new file mode 100644 index 000000000..d435ea228 --- /dev/null +++ b/plugins/fastpath/src/main/java/org/jivesoftware/fastpath/workspace/util/RequestUtils.java @@ -0,0 +1,141 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.fastpath.workspace.util; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.impl.JidCreate; + + +public class RequestUtils { + private final Map> metadata; + + public RequestUtils(Map> requestData) { + this.metadata = requestData; + } + + public Map> getMetadata() { + return metadata; + } + + /** + * Returns a Question if one was asked. + * + * @return the question the visitor asked before joining the queue. If not question + * was asked, null will be returned. + */ + public String getQuestion() { + return getMetadata() == null ? null : getFirstValue("question"); + } + + /** + * Returns the nickname of the Visitor. + * + * @return the nickname of the visitor. + */ + public String getUsername() { + return getMetadata() == null ? null : getFirstValue("username"); + } + + /** + * Return the Users Email address, if specified. + * + * @return the users email address, otherwise will return null if an email + * address was not specified. + */ + public String getEmailAddress() { + return getMetadata() == null ? null : getFirstValue("email"); + } + + /** + * Return the request location. + * + * @return the url (string format) of where the user made the initial request. + */ + public String getRequestLocation() { + return getMetadata() == null ? null : getFirstValue("Location"); + } + + /** + * Returns the Unique Identifier of the user. + * + * @return the unique id of the user or {@code null}. + */ + public EntityBareJid getUserID() { + return getMetadata() == null ? null : JidCreate.entityBareFromUnescapedOrThrowUnchecked( + Objects.requireNonNull(getFirstValue("userID"))); + } + + public String getInviter() { + return getMetadata() == null ? null : getFirstValue("inviter"); + } + + public String getWorkgroup() { + return getMetadata() == null ? null : getFirstValue("workgroup"); + } + + public boolean isTransfer() { + return getMetadata() != null && Boolean.parseBoolean(getFirstValue("transfer")); + } + + public boolean isInviteOrTransfer() { + if (getMetadata() == null) { + return false; + } + + return getMetadata().containsKey("transfer"); //NOTRANS + } + + public String getSessionID() { + return getMetadata() == null ? null : getFirstValue("sessionID"); + } + + public Map> getMap() { + final Map> returnMap = new HashMap<>(metadata); + returnMap.remove("sessionID"); + returnMap.remove("transfer"); + returnMap.remove("workgroup"); + returnMap.remove("inviter"); + returnMap.remove("username"); + returnMap.remove("question"); + returnMap.remove("userID"); + //returnMap.remove("email"); + return returnMap; + } + + public String getValue(String key) { + return getFirstValue(key); + } + + private String getFirstValue(String key) { + Object o = getMetadata().get(key); + if (o instanceof List) { + final List list = (List) o; + if (list.size() > 0) { + return (String) list.get(0); + } + } + else if (o instanceof String) { + return (String) o; + } + return null; + } + +} diff --git a/plugins/fastpath/src/main/plugin-metadata/plugin.xml b/plugins/fastpath/src/main/plugin-metadata/plugin.xml new file mode 100644 index 000000000..b7aa76dd0 --- /dev/null +++ b/plugins/fastpath/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,10 @@ + + ${project.name} + ${project.version} + ${project.description} + https://IgniteRealtime.org + support@IgniteRealtime.org + org.jivesoftware.fastpath.FastpathPlugin + 3.1.0 + 11 + diff --git a/plugins/fastpath/src/main/resources/fastpath.properties b/plugins/fastpath/src/main/resources/fastpath.properties new file mode 100644 index 000000000..e77957ffe --- /dev/null +++ b/plugins/fastpath/src/main/resources/fastpath.properties @@ -0,0 +1,244 @@ +APP_NAME = Spark +VERSION = Version 1.0 Release + +SPARK_IMAGE = images/spark.png +WELCOME = Welcome +ID_CARD_48x48 = images/id_card.png + +# LOGIN DIALOG +LOGIN_DIALOG_LOGIN = &Login +LOGIN_DIALOG_QUIT = &Quit +LOGIN_DIALOG_USERNAME = &Username: +LOGIN_DIALOG_PASSWORD = &Password: +LOGIN_DIALOG_WORKSPACE = &Workgroup: +LOGIN_DIALOG_LOGIN_TITLE = Spark +LOGIN_DIALOG_AUTHENTICATING = Authenticating... + +#MainWindow +MAIN_IMAGE = images/message.png +MAIN_IMAGE_ICO = images/icon_16.ico +SMALL_CHECK = images/icons/accept.png +SMALL_DELETE = images/icons/remove.png +AVAILABLE_USER = images/icons/user.png +AWAY_USER = images/awayUser.png +FIND_IMAGE = images/find.png +SMALL_ADD_IMAGE = images/icons/add.png +DOCUMENT_EXCHANGE_IMAGE = images/document_exchange.png +SMALL_DOCUMENT_ADD = images/document_add.png +SMALL_CIRCLE_DELETE = images/icons/close.png +SMALL_DOCUMENT_VIEW = images/document_view.png +SMALL_USER1_MESSAGE = images/icons/chat_settings.png +USER1_MESSAGE_24x24 = images/icons/chat_settings.png +SMALL_USER1_TIME = images/user1_time.png +SMALL_USER1_NEW = images/icons/create.png +SMALL_USER1_STOPWATCH = images/stopwatch_pause.png +SMALL_USER1_MOBILEPHONE = images/user1_mobilephone.png +SMALL_USER1_INFORMATION = images/icons/subscribe.png +SMALL_ENTRY = images/icons/small_entry.png +SMALL_AGENT_IMAGE = images/small_agent.png +CHATTING_AGENT_IMAGE = images/user1.png +CHATTING_CUSTOMER_IMAGE = images/user2.png +INFORMATION_IMAGE = images/icons/about.png +BLANK_IMAGE = images/blank.gif +USER_HEADSET_24x24 = images/user_headset24.png +FOLDER_CLOSED = images/folder_closed.png +FOLDER = images/folder.png +SMALL_PIN_BLUE = images/pin_blue.png +SMALL_DATA_FIND_IMAGE = images/icons/search.png +SMALL_BUSINESS_MAN_VIEW = images/icons/edit_profile.png +SMALL_ALL_AGENTS_IMAGE = images/user1_earth.png +SMALL_WORKGROUP_QUEUE_IMAGE = images/icons/start_conference.png +SMALL_ALL_CHATS_IMAGE = images/icons/contacts.png +SMALL_CURRENT_AGENTS = images/icons/users.png +HELP2_24x24 = images/icons/help.png +SMALL_ALARM_CLOCK = images/icons/alarmclock.png +SMALL_SCROLL_REFRESH = images/scroll_refresh.png +SMALL_QUESTION = images/icons/help.png +USER1_32x32 = images/User1_32x32.png +DATA_DELETE_16x16 = images/data_delete.png +DATA_REFRESH_16x16 = images/data_refresh.png +USER1_BACK_16x16 = images/user1_back.png +FONT_16x16 = images/font.png +DOCUMENT_FIND_16x16 = images/document_find.png +DOCUMENT_INFO_32x32 = images/document_info.png +DOCUMENT_16x16 = images/icons/note.png +SMALL_CLOSE_BUTTON = images/icons/close.png +COPY_16x16 = images/icons/copy.png +BLANK_24x24 = images/blank_24x24.png +PUSH_URL_16x16 = images/earth_connection-16x16.png +LINK_16x16 = images/icons/link.png +LINK_DELETE_16x16 = images/icons/link_delete.png +EARTH_LOCK_16x16 = images/earth_lock-16x16.png +LOCK_16x16 = images/icons/lock.png +LOCK_UNLOCK_16x16 = images/icons/unlock.png +ONLINE_ICO = images/icon1.ico +OFFLINE_ICO = images/icon2.ico +INFORMATION_ICO = images/icon3.ico +SAVE_AS_16x16 = images/icons/save.png +NOTE_EDIT_16x16 = images/note_edit.png +ADDRESS_BOOK_16x16 = images/icons/address_book.png +MEGAPHONE_16x16 = images/icons/broadcast.png +EARTH_VIEW_16x16 = images/earth_view.png +HISTORY_16x16 = images/icons/history.png +DOWNLOAD_16x16 = images/icons/downloads.png +RED_FLAG_16x16 = images/icons/ban.png +GREEN_FLAG_16x16 = images/flag_green.png +YELLOW_FLAG_16x16 = images/flag_yellow.png +FUNNEL_DOWN_16x16 = images/funnel_down.png +MAIL_16x16 = images/mail_16x16.png +MAIL_FORWARD_16x16 = images/mail_forward_16x16.png +MAIL_INTO_16x16 = images/mail_into_16x16.png +RED_BALL = images/red-ball.png +GREEN_BALL = images/icons/im_available.png +BLUE_BALL = images/blue-ball.png +YELLOW_BALL = images/yellow-ball.png +PAWN_GLASS_GREEN = images/pawn_glass_green.png +PAWN_GLASS_RED = images/pawn_glass_red.png +PAWN_GLASS_WHITE = images/pawn_glass_white.png +PAWN_GLASS_YELLOW = images/pawn_glass_yellow.png +PLUS_SIGN = images/plus-sign.png +MINUS_SIGN = images/minus-sign.png +MAGICIAN_IMAGE = images/magician.png +FIND_TEXT_IMAGE = images/icons/lookup.png +LOGIN_KEY_IMAGE = images/icons/login.png +BRICKWALL_IMAGE = images/icons/block.png +MODERATOR_IMAGE = images/icons/moderator.png +DESKTOP_IMAGE = images/icons/tasklist.png +SPELL_CHECK_IMAGE = images/text_ok.png +BUSY_IMAGE = images/icons/busy.gif +CLOSE_IMAGE = images/icons/close.png +VIEW_IMAGE = images/view.png +MOBILE_PHONE_IMAGE = images/mobilephone.png +ON_PHONE_IMAGE = images/icons/on-phone.png +REFRESH_IMAGE = images/icons/refresh.png +CLOSE_WHITE_X_IMAGE = images/icons/close.png +CLOSE_DARK_X_IMAGE = images/icons/close.png + + +# Global Values +ERROR_INVALID_WORKGROUP = The workgroup is not valid. Please use a valid workgroup. +ERROR_DIALOG_TITLE = Login Error +INVALID_USERNAME_PASSWORD = Invalid username or password. +SERVER_UNAVAILABLE = Can't connect to server: invalid name or server not reachable. +UNRECOVERABLE_ERROR = Invalid username or password. + +#Chat Window Images + + + +#Chat window text +SEND = &Send +ADD_TO_KB = You can assign any response as either a question or an answer add them directly to the knowledge base for future reference. + +#Kbase Window +GO = &Go +ADD_TO_CHAT = &Add document +ADD_LINK_TO_CHAT = Add &link +VIEW = &View +SEARCH = &Search: + +#Chat Queue +ACCEPT_CHAT = &Accept +REJECT_CHAT = &Refuse +TIME_LEFT = Time left: + +#MainWindow +MAIN_TITLE = Spark +TOOLBOX = Toolbox +CHAT_QUEUE = Chat Queue +CURRENT_CHATS = My Chats +CURRENT_AGENTS = Online Agents +ALL_CHATS = All Chats +WORKGROUP_QUEUE = Queues +CHAT_WORKSPACE = Chat Workspace + +#GroupChat +CREATE_FAQ_ENTRY = Create a new FAQ entry? +CREATE_FAQ_TITLE = Create New FAQ +FAQ_TAB_TITLE = Analyzer +KNOWLEDGE_BASE_TAB_TITLE = Search +PROFILE_TAB_TITLE = Profile +CO_BROWSER_TAB_TITLE = Co-Browser +FORUM_TAB_TITLE = Forums + +#Images +CONFERENCE_IMAGE_24x24 = images/icons/invite24.png +CONFERENCE_IMAGE_16x16 = images/icons/conference.png +PROFILE_IMAGE_24x24 = images/icons/profile24.png +SEARCH_USER_16x16 = images/icons/search.png +SEND_FILE_24x24 = images/icons/send_file24.png +ADD_IMAGE_24x24 = images/icons/add_user_24.png +TELEPHONE_24x24 = images/icons/phone.png +IM_DND = images/icons/im_dnd.png +IM_AWAY = images/icons/im_away.png +MESSAGE_AWAY = images/message_away.png +MESSAGE_DND = images/message_dnd.png +ERASER_IMAGE = images/icons/clear.png +TOOLBAR_BACKGROUND = images/toolbar.png +TRAFFIC_LIGHT_IMAGE = images/traffic-light.png +SERVER_ICON = images/icons/conferences.png +BOOKMARK_ICON = images/icons/bookmark.png +ADD_BOOKMARK_ICON = images/icons/bookmark.png +DELETE_BOOKMARK_ICON = images/icons/remove.png +CLEAR_BALL_ICON = images/icons/im_unavailable.png +CALL_ICON = images/call.png +PROFILE_ICON = images/profile.png +SEND_FILE_ICON = images/icons/send_file.png +ADD_CONTACT_IMAGE = images/icons/add_user.png +JOIN_GROUPCHAT_IMAGE = images/icons/join.png +DOWN_ARROW_IMAGE = images/down_arrow.gif +PRINTER_IMAGE_16x16 = images/icons/print.png +SEND_MAIL_IMAGE_16x16 = images/sendmail.png +SEARCH_IMAGE_32x32 = images/icons/search.png +MAIL_IMAGE_32x32 = images/mail_32x32.png +PREFERENCES_IMAGE = images/icons/preferences.png +NOTEBOOK_IMAGE = images/icons/notebook.png +TEXT_BOLD = images/text_bold.png +TEXT_ITALIC = images/text_italics.png +TEXT_UNDERLINE = images/text_underlined.png +TEXT_NORMAL = images/text_normal.png +SMALL_USER_ENTER = images/icons/join.png +SMALL_USER_DELETE = images/icons/remove.png +QUESTIONS_ANSWERS = images/questionsAnswers.png +SMALL_MESSAGE_IMAGE = images/icons/start_chat.png +SMALL_MESSAGE_EDIT_IMAGE = images/icons/edit.png +SMALL_ABOUT_IMAGE = images/icons/about.png +DOOR_IMAGE = images/icons/join.png +STAR_BLUE_IMAGE = images/icons/star_blue.png +STAR_RED_IMAGE = images/icons/star_red.png +STAR_GREY_IMAGE = images/icons/star.png +STAR_YELLOW_IMAGE = images/icons/star_yellow.png +STAR_GREEN_IMAGE = images/icons/star_green.png +LEFT_ARROW_IMAGE = images/arrow_left_green.png +RIGHT_ARROW_IMAGE = images/arrow_right_green.png +BACKGROUND_IMAGE = images/background.png +FREE_TO_CHAT_IMAGE = images/icons/im_free_chat.png +SOUND_PREFERENCES_IMAGE = images/icons/sound.png +SPARK_LOGOUT_IMAGE = images/spark_100.jpg +PHOTO_IMAGE = images/icons/screenshot24.png +PLUGIN_IMAGE = images/icons/plugins.png +SMALL_PROFILE_IMAGE = images/small_profile.png +CHANGELOG_IMAGE = images/doc-changelog-16x16.gif +README_IMAGE = images/doc-readme-16x16.gif +DOWN_OPTION_IMAGE = images/icons/collapse_down.png +STICKY_NOTE_IMAGE = images/sticky.png +HISTORY_24x24 = images/icons/history24.png +PANE_UP_ARROW_IMAGE = images/icons/collapse_up.png +PANE_DOWN_ARROW_IMAGE = images/icons/collapse_down.png + +#Fastpath Icons +FASTPATH_IMAGE_16x16 = images/fastpath16.png +FASTPATH_IMAGE_24x24 = images/fastpath24.png +FASTPATH_IMAGE_32x32 = images/fastpath32.png +FASTPATH_IMAGE-64x63 = images/fastpath64.png +CIRCLE_CHECK_IMAGE = images/check.png +TRANSFER_IMAGE_24x24 = images/icons/add_user_24.png +FASTPATH_OFFLINE_IMAGE_16x16 = images/fastpath16_offline.png +FASTPATH_OFFLINE_IMAGE_24x24 = images/fastpath24_offline.png +USER1_ADD_16x16 = images/icons/add_user.png +END_BUTTON_24x24 = images/end_button_24x24.png +POWERED_BY_IMAGE = images/powered_by.png +CHAT_INVITE_IMAGE_24x24 = images/icon_chatinvite_24x24.png +CHAT_TRANSFER_IMAGE_24x24 = images/icon_chattransfer_24x24.png +CHAT_COBROWSE_IMAGE_24x24 = images/icon_cobrowse_24x24.png +CHAT_ENDED_IMAGE_24x24 = images/icon_endchat1_24x24.png diff --git a/src/plugins/fastpath/src/resources/i18n/fastpath_i18n.properties b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n.properties similarity index 96% rename from src/plugins/fastpath/src/resources/i18n/fastpath_i18n.properties rename to plugins/fastpath/src/main/resources/i18n/fastpath_i18n.properties index 284fbe4fa..544f91907 100644 --- a/src/plugins/fastpath/src/resources/i18n/fastpath_i18n.properties +++ b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n.properties @@ -106,7 +106,7 @@ tab.fastpath = Fastpath tab.current.chats = Current Chats tab.online.agents = Online Agents tab.user.info = User Info -tab.participants Participants +tab.participants = Participants tab.user.history = User History tab.notes = Notes tab.queue.activity = Queue Activity @@ -141,6 +141,11 @@ title.search.results = Search Results title.chat.transcripts.search = Chat Transcripts Search title.number.of.conversations.found = # of conversations found: +time.days = d +time.hours = h +time.minutes = min +time.since = since +time.less.than.one.minute = less than 1 minute tooltip.allow.cobrowsing = Allows current visitor to follow your browser navigation. tooltip.hide.cobrowsing = Hides your browser navigation from the current visitor. @@ -152,4 +157,4 @@ tooltip.print.transcript = Print Chat Transcript # TO DO org.jivesoftware.fastpath.workspace.search -org.jivesoftware.fastpath.workspace.utils \ No newline at end of file +org.jivesoftware.fastpath.workspace.utils diff --git a/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_de.properties b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_de.properties new file mode 100644 index 000000000..660925fe3 --- /dev/null +++ b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_de.properties @@ -0,0 +1,155 @@ +workgroup = Arbeitsgruppe +join = Betreten +logout = Abmelden +cobrowsing.session = Co-Browsing-Sitzung +back = Zurück +go = Go +duration = Dauer +agents = Agents +date = Datum +invite.agent = Einladungen +invite = Einladen +transfer.to.agent = Weiterleitungen +transfer = Weiterleiten +workgroups = Arbeitsgruppe +transfer.to = Weiterleiten an +cancel = Abbrechen +agent = Agent +visitor = Besucher +email = E-Mail +question = Frage +start.time = Startzeit +seconds = Sekunden +name = Name +from = Von +room = Raum +message = Nachricht +number.in.queue = # in der Warteschleife +average.wait.time = Durchschnittliche Wartezeit +last.queue.activity = Letzte Warteschleifen-Aktivität +query = Suche +chat.with = Chat mit + + + +button.logout = Abme&lden +button.history = Verlauf +button.conference = &Konferenz +button.macros = &Makros +button.invite = &Einladen +button.transfer = &Transfer +button.canned.responses = &Vorgefertigte Antworten +button.end = B&eenden +button.co.browse = &Co-Browse +button.edit.canned.responses = Vorgefertigte Antworten b&earbeiten +button.start.cobrowsing.session = Co-Browsing-Sitzung starten +button.save.note = Notiz &speichern +button.new = &Neu +button.delete = &Löschen +button.save = &Speichern +button.accept = &Annehmen +button.reject = &Zurückweisen + + +checkbox.allow.user.to.follow = Nutzer die Nachverfolgung erlauben + +label.notes = &Notizen +label.message.to.agent = Nachricht an Agent +label.select.agent = Agent auswählen +label.title = &Titel +label.type = T&yp +label.response = Antwo&rt +label.initial.response = Ursprüngl&iche Antwort + + + +message.workgroup.logged.into = Angemeldet in der Arbeitsgruppe {0} +message.incoming.request = {0} +message.start.cobrowsing = Co-Browsing-Sitzung mit Seite {0} starten +message.send.cobrowsing.message = Einladung zum Co-Browsing mit Seite {0} senden +message.click.to.add.notes = Klicken Sie hier, um Notizen hinzuzufügen +message.chat.notes = Chat-Notizen werden diesem Chat beigefügt und können über die Chat-Suche durchsucht werden. +message.notes.updated = Notizen wurden aktualisiert +message.unable.to.update.notes = Die Notiz konnte nicht gespeichert werden. Bitte versuchen Sie es erneut. +message.view.more.information = Weitere Informationen anzeigen... +message.conversation.transferred = Das Gespräch wurde weitergeleitet +message.invitation.rejected = Die Einladung zum Gespräch wurde von {0} zurückgewiesen +message.please.join.me.in.conference = Bitte treten Sie der Konferenz bei. +message.user.has.been.invited = {0} wurde in das Gespräch eingeladen. +message.waiting.for.user = Warte auf {0}, den Transfer anzunehmen. +message.transfering.to.user = Ich übergebe dieses Gespräch an Sie. +message.join.me.in.chat = Bitte betreten Sie diesen Chat. +message.transfer.to.another.agent = Dieses Gespräch an einen anderen Agent, eine andere Arbeitsgruppe oder Warteschleife übergeben. +message.invite.another.agent = Andere einladen, dieses Gespräch zu betreten. +message.no.agent.selected.error = Es wurde kein Agent ausgewählt +message.jid.invalid.error = Geben Sie eine gültige JID ein +message.message.required.error = Geben Sie eine Nachricht ein +message.specify.personal.macros = Geben Sie persönliche Makros an, die Sie in Chats mit Ihren Kunden verwenden können. +message.macros.not.saved = Ihre Makros konnten nicht gespeichert werden. +message.add.new.response = Neue Antwort hinzufügen +message.current.chats = Derzeitige Chats ({0}) +message.transcript.not.found.error = Abschrift konnte nicht gefunden werden +message.incoming.chat.request = Eingehende Chat-Anfrage von {0} +message.user.joined.room = {0} hat den Raum betreten. +message.user.left.room = {0} hat den Raum verlassen. +message.not.specified = Nicht angegeben +message.user.not.logged.in = Der Benutzer ist nicht bei der Arbeitsgruppe angemeldet. +message.agent.is.not.in.chat = Agent ist derzeit in keinen Chats. +message.find.previous.conversations = Geben Sie Text ein, den Sie in vorherigen Gesprächen finden möchten + +menuitem.global.canned.responses = Globale vorgefertige Antworten +menuitem.no.entries = Keine Einträge in der Kategorie +menuitem.join.chat = Chat betreten +menuitem.monitor.chat = Chat überwachen + +tab.fastpath = Fastpath +tab.current.chats = Derzeitige Chats +tab.online.agents = Angemeldete Agents +tab.user.info = Benutzerinfo +tab.participants = Teilnehmer +tab.user.history = Benutzerverlauf +tab.notes = Notizen +tab.queue.activity = Warteschleifen-Aktivität +tab.transcript = Abschrift + +title.cobrowsing.for = Co-Browsing für {0} +title.chat.notes = Chatnotizen +title.notes = Notizen +title.request.information = Informationen über die Anfrage +title.information = Informationen +title.transcript = Abschrift +title.transfer = Transfer +title.invitation = Einladung +title.error = Fehler +title.contact.list = Kontaktliste +title.personal.macros = Persönliche Makros +title.response.name = Name der Antwort +title.response.text = Text der Antwort +title.personal = Persönlich +title.create.canned.response = Vorgefertigte Antwort erstellen +title.previous.chats = Vorherige Chats +title.personal.chats = Persönliche Chats +title.chat.transcript = Chatabschrift +title.current.active.conversations = Derzeitig aktive Gespräche +title.number.of.active.conversations = # der aktiven Gespräche +title.current.conversations = Derzeitige Gespräche +title.fastpath.invitation = Fastpath-Einladung +title.fastpath.transfer = Fastpath-Weiterleitung +title.workgroup = {0} Arbeitsgruppe +title.chat.transcripts = Chat-Abschriften +title.search.results = Suchergebnisse +title.chat.transcripts.search = Chatabschrift-Suche +title.number.of.conversations.found = # Gespräche gefunden: + + +tooltip.allow.cobrowsing = Erlaubt dem aktuellen Besucher, die Browsernavigation zu verfolgen. +tooltip.hide.cobrowsing = Browsernavigation dem aktuellen Besucher verbergen. +tooltip.back.one.page = Eine Seite zurückgehen +tooltip.push.url = Einen Link übergeben +tooltip.push.current.page = Aktuelle URL dem Besucher übergeben +tooltip.save.transcript = Chatabschrift speichern +tooltip.print.transcript = Chatabschrift drucken + +# TO DO +org.jivesoftware.fastpath.workspace.search +org.jivesoftware.fastpath.workspace.utils \ No newline at end of file diff --git a/src/plugins/fastpath/src/resources/i18n/fastpath_i18n_es.properties b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_es.properties similarity index 96% rename from src/plugins/fastpath/src/resources/i18n/fastpath_i18n_es.properties rename to plugins/fastpath/src/main/resources/i18n/fastpath_i18n_es.properties index 872b71d53..4e47b8eca 100644 --- a/src/plugins/fastpath/src/resources/i18n/fastpath_i18n_es.properties +++ b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_es.properties @@ -99,7 +99,7 @@ message.find.previous.conversations = Ingrese texto para buscar en conversacione menuitem.global.canned.responses = Autorespuestas Globales menuitem.no.entries = No hay entradas en la Categoria -menuitem.join.chat= Unirse al Chat +menuitem.join.chat = Unirse al Chat menuitem.monitor.chat = Monitor de Chat tab.fastpath = Fastpath @@ -141,6 +141,11 @@ title.search.results = Resultados de Busqueda title.chat.transcripts.search = Busqueda de Transcripciones title.number.of.conversations.found = # de conversaciones encontradas: +time.days = d +time.hours = h +time.minutes = min +time.since = desde +time.less.than.one.minute = menos de 1 minuto tooltip.allow.cobrowsing = * tooltip.hide.cobrowsing = * @@ -152,4 +157,4 @@ tooltip.print.transcript = Imprimir la Transcripcion # TO DO org.jivesoftware.fastpath.workspace.search -org.jivesoftware.fastpath.workspace.utils \ No newline at end of file +org.jivesoftware.fastpath.workspace.utils diff --git a/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_lt.properties b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_lt.properties new file mode 100644 index 000000000..54838899a --- /dev/null +++ b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_lt.properties @@ -0,0 +1,151 @@ +workgroup = Darbo grupÄ— +join = Prisijungti +logout = Atsijungti +cobrowsing.session = NarÅ¡ymas kartu +back = Atgal +go = Pirmyn +duration = TrukmÄ— +agents = Agentai +date = Data +invite.agent = Pakvietimai +invite = Pakviesti +transfer.to.agent = Nukreipimai +transfer = Nukreipimas +workgroups = Darbo grupÄ—s +transfer.to = Nukreipti į +cancel = AtÅ¡aukti +agent = Agentas +visitor = Lankytojas +email = El. paÅ¡tas +question = Klausimas +start.time = Start Time +seconds = Sekundžių +name = Vardas +from = SiuntÄ—jas +room = Kambarys +message = Žinu&tÄ— +number.in.queue = # eilÄ—je +average.wait.time = VidutinÄ— laukimo trukmÄ— +last.queue.activity = Paskutinis įvykis eilÄ—je +query = Užklausa +chat.with = Pokalbis su + + + +button.logout = &Atsijungti +button.history = Ž&urnalai +button.conference = &Grupinis pokalbis +button.macros = &Skriptai +button.invite = &Pakviesti +button.transfer = &Nukreipti +button.canned.responses = &ParuoÅ¡ti atsakymai +button.end = &Pabaigti +button.co.browse = &NarÅ¡yti kartu +button.edit.canned.responses = &Redaguoti paruoÅ¡tus atsakymus +button.start.cobrowsing.session = PradÄ—t narÅ¡ymÄ… kartu +button.save.note = Ä®&raÅ¡yti užrašą +button.new = &Naujas +button.delete = &PaÅ¡alinti +button.save = Ä®&raÅ¡yti +button.accept = &Priimti +button.reject = &Atmesti + + +checkbox.allow.user.to.follow = Leisti abonentui sekti + +label.notes = &UžraÅ¡ai +label.message.to.agent = Žinu&tÄ— agentui +label.select.agent = Pasirinkite agentÄ… +label.title = &Pavadinimas +label.type = &Tipas +label.response = &Atsakymas +label.initial.response = &Pradinis atsakymas + + + +message.workgroup.logged.into = PrisijungÄ™s prie {0} darbo grupÄ—s +message.incoming.request = {0} +message.start.cobrowsing = PradÄ—t narÅ¡ymÄ… kartu puslapyje {0} +message.send.cobrowsing.message = Nusiųstas pakvietimas narÅ¡yti kartu puslapyje {0} +message.click.to.add.notes = Paspauskite Äia, kad pridÄ—ti užraÅ¡us. +message.chat.notes = Pokalbio užraÅ¡ai yra priskirti Å¡iam pokalbiui ir juos galima bus rasti pokalbio paieÅ¡koje. +message.notes.updated = UžraÅ¡ai buvo atnaujinti +message.unable.to.update.notes = Neįmanoma iÅ¡saugoti užraÅ¡o. PraÅ¡ome bandyti dar kartÄ…. +message.view.more.information = PeržiÅ«rÄ—ti daugiau informacijos... +message.conversation.transferred = Pokalbis buvo nukreiptas. +message.invitation.rejected = {0} atmetÄ— pakvietimÄ… į pokalbį. +message.please.join.me.in.conference = PraÅ¡au prisijungi prie manÄ™s konferecijoje +message.user.has.been.invited = {0} buvo pakviestas prisijungti prie Å¡io pokalbio. +message.waiting.for.user = Laukiama kol {0} patvirtins šį nukreipimÄ…. +message.transfering.to.user = Nukreipiu šį pokalbį jums. +message.join.me.in.chat = PraÅ¡au prisijungi prie manÄ™s Å¡iame pokalbyje. +message.transfer.to.another.agent =Nukreipti šį pokalbį į kitÄ… agentÄ…, darbo grupÄ™ ar eilÄ™. +message.invite.another.agent = Pakviesti kitus prisijungti prie Å¡io pokalbio. +message.no.agent.selected.error = Nebuvo pasirinktas agentas +message.jid.invalid.error = Ä®veskite teisingÄ… identifikatorių (JID) +message.message.required.error = Ä®veskite žinutÄ™ +message.specify.personal.macros = Nustatykite asmeninius skriptus naudojimui pokalbiuose su klientais. +message.macros.not.saved = JÅ«sų skriptai nebuvo iÅ¡saugoti. +message.add.new.response = PridÄ—ti naujÄ… atsakymÄ… +message.current.chats = Vykstantys pokalbiai ({0}) +message.transcript.not.found.error = Pokalbio žurnalas nerastas +message.incoming.chat.request = Ä®einanti užklausa iÅ¡ {0} +message.user.joined.room = {0} apsilankÄ— kambaryje. +message.user.left.room = {0} išėjo iÅ¡ kambario. +message.not.specified = Nenurodyta +message.user.not.logged.in = Abonentas neprisijungÄ™s prie darbo grupÄ—s. +message.agent.is.not.in.chat = Å iuo metu agentas nedalyvauja pokalbiuose. +message.find.previous.conversations = Ä®veskite tekstÄ… norimÄ… rasti buvusiuose pokalbiuose. + +menuitem.global.canned.responses = Bendri paruoÅ¡ti atsakymai +menuitem.no.entries = Kategorijoje nÄ—ra įrašų +menuitem.join.chat = Prisijungti prie pokalbio +menuitem.monitor.chat = StebÄ—ti pokalbį + +tab.fastpath = Fastpath +tab.current.chats = Vykstantys pokalbiai +tab.online.agents = PrisijungÄ™ agentai +tab.user.info = Abonento informacija +tab.participants = Dalyviai +tab.user.history = Abonento žurnalas +tab.notes = UžraÅ¡ai +tab.queue.activity = EilÄ—s bÅ«sena +tab.transcript = Pokalbio žurnalas + +title.cobrowsing.for = NarÅ¡ymas kartu su {0} +title.chat.notes = Pokalbio užraÅ¡ai +title.notes = UžraÅ¡ai +title.request.information = Užklausos informacija +title.information = Informacija +title.transcript = Pokalbio žurnalas +title.transfer = Nukreipimas +title.invitation = Pakvietimas +title.error = Klaida +title.contact.list = Adresatų sÄ…raÅ¡as +title.personal.macros = Asmeniniai skriptai +title.response.name = Atsakymo pavadinimas +title.response.text = Atsakymo tekstas +title.personal = Asmeniniai +title.create.canned.response = Sukurti paruoÅ¡tÄ… atsakymÄ… +title.previous.chats = Ä®vykÄ™ pokalbiai +title.personal.chats = Asmeniniai pokalbiai +title.chat.transcript = Pokalbio žurnalas +title.current.active.conversations = Vykstantys pokalbiai +title.number.of.active.conversations = # vyksantys pokalbiai +title.current.conversations = Vykstantys pokalbiai +title.fastpath.invitation = Fastpath pakvietimas +title.fastpath.transfer = Fastpath nukreipimas +title.workgroup = {0} darbo grupÄ— +title.chat.transcripts = Pokalbių žurnalai +title.search.results = PaieÅ¡kos rezultatai +title.chat.transcripts.search = PaieÅ¡ka pokalbių žurnaluose +title.number.of.conversations.found = # rastų pokalbių: + + +tooltip.allow.cobrowsing = Leidžia Å¡iam lankytojui sekti jÅ«sų narÅ¡ymÄ…. +tooltip.hide.cobrowsing = PaslÄ—pia jÅ«sų narÅ¡ymÄ… nuo Å¡io lankytojo. +tooltip.back.one.page = Grįžti į buvusį puslapį +tooltip.push.url = Nusiųsti nuorodÄ… +tooltip.push.current.page = Nusiųsti esamÄ… nuorodÄ… lankytojui +tooltip.save.transcript = Ä®raÅ¡yti pokalbio žurnalÄ… +tooltip.print.transcript = Atspausdinti pokalbio žurnalÄ… diff --git a/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_pl.properties b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_pl.properties new file mode 100644 index 000000000..a5f5af5d9 --- /dev/null +++ b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_pl.properties @@ -0,0 +1,155 @@ +workgroup = Grupa robocza +join = Dołącz +logout = Wyloguj +cobrowsing.session = Sesja jednoczesnego przeglÄ…dania +back = Wstecz +go = Dalej +duration = Czas trwania +agents = Agenci +date = Data +invite.agent = Zaproszenia +invite = ZaproÅ› +transfer.to.agent = Transfery +transfer = Transfer +workgroups = Grupy robocze +transfer.to = Transferuj do +cancel = Anuluj +agent = Agent +visitor = Gość +email = E-mail +question = Pytanie +start.time = Czas poczÄ…tku +seconds = Sekundy +name = Nazwa +from = Z +room = Pokój +message = Wiadomość +number.in.queue = # W kolejce +average.wait.time = Åšredni czas oczekiwania +last.queue.activity = Ostatnia aktywność w kolejce +query = Zapytanie +chat.with = Rozmowa z + + + +button.logout = Wyloguj +button.history = Historia +button.conference = Konferencja +button.macros = Makra +button.invite = ZaproÅ› +button.transfer = Transfer +button.canned.responses = Gotowe odpowiedzi +button.end = ZakoÅ„cz +button.co.browse = PrzeglÄ…d jednoczesny +button.edit.canned.responses = Edytuj gotowe odpowiedzi +button.start.cobrowsing.session = Rozpocznij sesjÄ™ jednoczesnego przeglÄ…dania +button.save.note = Zapisz notatkÄ™ +button.new = Nowy +button.delete = UsuÅ„ +button.save = Zapisz +button.accept = Akceptuj +button.reject = Odrzuć + + +checkbox.allow.user.to.follow = Pozwól użytkownikowi na Å›ledzenie + +label.notes = Notatki +label.message.to.agent = Wiadomość do agenta +label.select.agent = Wybierz agenta +label.title = TytuÅ‚ +label.type = Typ +label.response = Odpowiedź +label.initial.response = Zainicjuj odpowiedź + + + +message.workgroup.logged.into = Zalogowany do {0} grupy roboczej +message.incoming.request = {0} +message.start.cobrowsing = Rozpocznij sesjÄ™ jednoczesnego przeglÄ…dania ze stronÄ… {0} +message.send.cobrowsing.message = WyÅ›lij zaproszenie do jednoczesnego przeglÄ…dania ze stronÄ… {0} +message.click.to.add.notes = Kliknij aby dodać notatki. +message.chat.notes = Notatki sÄ… zwiÄ…zane z tÄ… rozmowÄ… i bÄ™dzie można je wyszukać poprzez szukajkÄ™ rozmowy. +message.notes.updated = Notatki zostaÅ‚y zaktualizowane +message.unable.to.update.notes = Nie można zatwierdzić notatki. Spróbuj ponownie. +message.view.more.information = Zobacz wiÄ™cej informacji... +message.conversation.transferred = Rozmowa zostaÅ‚a przesÅ‚ana. +message.invitation.rejected = Zaproszenie do rozmowy zostaÅ‚o odrzucone przez {0} +message.please.join.me.in.conference = Dołącz do mnie w konferencji +message.user.has.been.invited = {0} zostaÅ‚ zaproszony by dołączyć do tej rozmowy. +message.waiting.for.user = Oczekiwanie na {0} by zaakceptowaÅ‚ ten przesyÅ‚. +message.transfering.to.user = PrzesyÅ‚am tÄ… rozmowÄ™ do Ciebie. +message.join.me.in.chat = Dołącz do mnie w tej rozmowie. +message.transfer.to.another.agent = PrzeÅ›lij tÄ… rozmowÄ™ do innego agenta, grupy roboczej lub kolejki. +message.invite.another.agent = ZaproÅ› innych by dołączyli do tej rozmowy. +message.no.agent.selected.error = Å»aden agent nie zostaÅ‚ wybrany +message.jid.invalid.error = Wprowadź poprawny JID +message.message.required.error = Wpisz wiadomość +message.specify.personal.macros = OkreÅ›l osobiste makra do użycia w Twoich rozmowach z odbiorcÄ…. +message.macros.not.saved = Twoje makra nie zostaÅ‚y zapisane. +message.add.new.response = Dodaj nowÄ… odpowiedź +message.current.chats = Obecne rozmowy ({0}) +message.transcript.not.found.error = Zapis nie mógÅ‚ zostać odnaleziony +message.incoming.chat.request = PrzychodzÄ…ca proÅ›ba rozmowy od {0} +message.user.joined.room = {0} dołączyÅ‚ do pokoju. +message.user.left.room = {0} opuÅ›ciÅ‚ pokój. +message.not.specified = NieokreÅ›lone +message.user.not.logged.in = Użytkownik nie jest zalogowany w grupie roboczej. +message.agent.is.not.in.chat = Agent nie jest obecnie w żadnych rozmowach. +message.find.previous.conversations = Wprowadź tekst by odnaleźć go we wczeÅ›niejszych rozmowach. + +menuitem.global.canned.responses = Ogólne gotowe odpowiedzi +menuitem.no.entries = Brak wpisów w kategorii +menuitem.join.chat = Dołącz do rozmowy +menuitem.monitor.chat = Monitoruj rozmowÄ™ + +tab.fastpath = Fastpath +tab.current.chats = Obecne rozmowy +tab.online.agents = DostÄ™pni agenci +tab.user.info = Informacje o użytkowniku +tab.participants = Uczestnicy +tab.user.history = Historia użytkownika +tab.notes = Notatki +tab.queue.activity = Aktywność kolejki +tab.transcript = Transkrypcja + +title.cobrowsing.for = Jednoczesne przeglÄ…danie dla {0} +title.chat.notes = Notatki z rozmów +title.notes = Notatki +title.request.information = ProÅ›ba o informacje +title.information = Informacja +title.transcript = Transkrypcja +title.transfer = Transfer +title.invitation = Zaproszenie +title.error = Błąd +title.contact.list = Lista kontaktów +title.personal.macros = Osobiste makra +title.response.name = Nazwa odpowiedzi +title.response.text = Tekst odpowiedzi +title.personal = Osobiste +title.create.canned.response = Utwórz gotowÄ… odpowiedź +title.previous.chats = Poprzednie rozmowy +title.personal.chats = Osobiste rozmowy +title.chat.transcript = Transkrypcja rozmowy +title.current.active.conversations = Aktualne aktywne rozmowy +title.number.of.active.conversations = # aktywnych rozmów +title.current.conversations = Aktualne rozmowy +title.fastpath.invitation = Zaproszenie Fastpath +title.fastpath.transfer = Transfer Fastpath +title.workgroup = {0} grupa robocza +title.chat.transcripts = Transkrypty rozmowy +title.search.results = Wyniki wyszukiwania +title.chat.transcripts.search = Wyszukiwanie transkryptów rozmów +title.number.of.conversations.found = # rozmów znaleziono: + + +tooltip.allow.cobrowsing = Pozwala obecnemu goÅ›ciowi na stosowanie Twojej nawigacji przeglÄ…dajÄ…cej. +tooltip.hide.cobrowsing = Ukrywa TwojÄ… nawigacjÄ™ przeglÄ…dajÄ…cÄ… przed obecnym goÅ›ciem. +tooltip.back.one.page = Wraca o jednÄ… stronÄ™ +tooltip.push.url = Wypycha link +tooltip.push.current.page = Wypycha obecny URL do goÅ›cia +tooltip.save.transcript = Zapisuje transkrypt rozmowy +tooltip.print.transcript = Drukuje transkrypt rozmowy + +# TO DO +org.jivesoftware.fastpath.workspace.search +org.jivesoftware.fastpath.workspace.utils diff --git a/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_pt_BR.properties b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_pt_BR.properties new file mode 100644 index 000000000..04fef2981 --- /dev/null +++ b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_pt_BR.properties @@ -0,0 +1,162 @@ +workgroup = Grupo de Trabalho +join = Entrar +logout = Logout +cobrowsing.session = Iniciar Navegação +back = Voltar +go = Ir +duration = Duração +agents = Atendentes +date = Data +invite.agent = Convites +invite = Convidar +transfer.to.agent = Transferências +transfer = Transferência +workgroups = Grupos de Trabalho +transfer.to = Transferir Para +cancel = Cancelar +agent = Atendente +visitor = Visitante +email = Email +question = Questão +start.time = Tempo de Início +seconds = Segundos +name = Nome +from = De +room = Sala +message = Mensagem +number.in.queue = # Em Espera +average.wait.time = Tempo Médio de Espera +last.queue.activity = Atividade da Última Fila +query = Consulta +chat.with = Chat com +# NOVO +ask.assistance = Solicitar Assistência +queues = Filas + +button.logout = &Logout +button.history = &Histórico +button.conference = &Conferência +button.macros = &Macros +button.invite = &Convidar +button.transfer = &Transferência +button.canned.responses = &Respostas Prontas +button.end = &Fim +button.co.browse = &Iniciar Navegação +button.edit.canned.responses = &Editar Respostas Prontas +button.start.cobrowsing.session = Iniciar Navegação Conjunta +button.save.note = &Salvar Nota +button.new = &Novo +button.delete = &Deletar +button.save = &Salvar +button.accept = &Aceitar +button.reject = &Rejeitar +# Novo +button.invite.another.user = Convidar outro atendente para se unir a esta conversa +button.transfer.conversation = Transferir Conversa para outro atendente +button.end.conversation = Terminar Conversa +button.start.cobrowse.user = Iniciar co-browsing com este usuário. + +checkbox.allow.user.to.follow = Permitir Usuário Seguir + +label.notes = &Notas +label.message.to.agent = Mensagem para o atendente +label.select.agent = Selecionar Atendente +label.title = &Título +label.type = T&ipo +label.response = &Resposta +label.initial.response = &Resposta Inicial + + + +message.workgroup.logged.into = Logado no Grupo de Trabalho {0} +message.incoming.request = {0} +message.start.cobrowsing = Iniciar uma sessão de Co-Navegação com a página {0} +message.send.cobrowsing.message = Enviado um convite de Co-Navegação com a página {0} +message.click.to.add.notes = Clique aqui para adicionar notas. +message.chat.notes = Anotações de Chat estão associadas a este chat e serão localizadas pela busca do chat. +message.notes.updated = Notas foram atualizadas. +message.unable.to.update.notes = Incapaz de enviar nota. Por favor tente novamente. +message.view.more.information = Ver mais informações... +message.conversation.transferred = Esta conversação foi transferida. +message.invitation.rejected = O convite de conversa foi rejeitado por {0} +message.please.join.me.in.conference = Por favor junte-se a mim nesta conferência. +message.user.has.been.invited = {0} foi convidado para se juntar a esta conversa. +message.waiting.for.user = Aguardando por {0} para aceitar esta transferência. +message.transfering.to.user = Eu estou transferindo esta conversa para você. +message.join.me.in.chat = Por favor participe comigo deste chat. +message.transfer.to.another.agent = Transfira esta conversa para outro atendente, Grupo de Trabalho ou Fila. +message.invite.another.agent = Convide outras pessoas para se juntar a esta conversa. +message.no.agent.selected.error = Nenhum atendente foi selecionado +message.jid.invalid.error = Deixe um JID válido +message.message.required.error = Deixe uma mensagem +message.specify.personal.macros = Especifique macros pessoais para uso em chats com seus cliente. +message.macros.not.saved = Suas macros não poderão ser salvas. +message.add.new.response = Adicionar nova resposta +message.current.chats = Chats atuais ({0}) +message.transcript.not.found.error = Cópia não pode ser localizada +message.incoming.chat.request = Pedido de Chat vindo de {0} +message.user.joined.room = {0} se juntou a sala. +message.user.left.room = {0} deixou a sala. +message.not.specified = Não especificado +message.user.not.logged.in = O usuário não está conectado ao Grupo de Trabalho. +message.agent.is.not.in.chat = Atendente não está em nenhum bate-papo. +message.find.previous.conversations = Insira o texto para procurar em conversas anteriores. +# Novo +message.less.one.minute = menos de 1 minuto + +menuitem.global.canned.responses = Respostas Prontas Globais +menuitem.no.entries = Sem entradas na Categoria +menuitem.join.chat = Entrar no Chat +menuitem.monitor.chat = Monitorar Chat + +tab.fastpath = Fastpath +tab.current.chats = Chats Atuais +tab.online.agents = Atendente Online +tab.user.info = Informação de Usuário +tab.participants = Participantes +tab.user.history = Histórico de Usuário +tab.notes = Notas +tab.queue.activity = Atividade da Fila +tab.transcript = Cópia + +title.cobrowsing.for = Co-Navegação Para {0} +title.chat.notes = Anotações do Chat +title.notes = Notas +title.request.information = Pedido de Informação +title.information = Informação +title.transcript = Transcript +title.transfer = Transferência +title.invitation = Convite +title.error = Erro +title.contact.list = Lista de Contato +title.personal.macros = Macros Pessoais +title.response.name = Nome de Resposta +title.response.text = Texto Resposta +title.personal = Pessoal +title.create.canned.response = Criar resposta pronta +title.previous.chats = Chats Anteriores +title.personal.chats = Chats Pessoais +title.chat.transcript = Cópia Chat +title.current.active.conversations = Conversas Ativas Atuais +title.number.of.active.conversations = # de conversas atuais +title.current.conversations = Conversas Atuais +title.fastpath.invitation = Convite +title.fastpath.transfer = Transferência +title.workgroup = {0} Grupo de Trabalho +title.chat.transcripts = Cópias de Chats +title.search.results = Buscar Resultados +title.chat.transcripts.search = Pesquisa Cópias de Chat +title.number.of.conversations.found = # conversas encontradas: + + +tooltip.allow.cobrowsing = Permite visitante atual seguir sua navegação. +tooltip.hide.cobrowsing = Mostra a sua navegação ao visitante. +tooltip.back.one.page = Voltar uma página +tooltip.push.url = Envie um link +tooltip.push.current.page = Envie a URL atual visitante +tooltip.save.transcript = Salvar Cópia de Chat +tooltip.print.transcript = Imprimir Cópia de Chat + +# TO DO +org.jivesoftware.fastpath.workspace.search +org.jivesoftware.fastpath.workspace.utils diff --git a/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_pt_PT.properties b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_pt_PT.properties new file mode 100644 index 000000000..23c015e27 --- /dev/null +++ b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_pt_PT.properties @@ -0,0 +1,160 @@ +workgroup = Grupo de trabalho +join = Junte-se +logout = Terminar sessão +cobrowsing.session = Sessão de Navegação Conjunta +back = Voltar +go = Ir +duration = Duração +agents = Agentes +date = Data +invite.agent = Convites +invite = Convidar +transfer.to.agent = Transferências +transfer = Transferir +workgroups = Grupos de trabalho +transfer.to = Transferir Para +cancel = Cancelar +agent = Agente +visitor = Visitante +email = Email +question = Questão +start.time = Hora de Início +seconds = Segundos +name = Nome +from = De +room = Sala +message = Mensagem +number.in.queue = # Na Fila de Espera +average.wait.time = Tempo Médio de Espera +last.queue.activity = Última Atividade na Fila de Espera +query = Consulta +chat.with = Conversar com + + + +button.logout = &Terminar Sessão +button.history = &Histórico +button.conference = &Conferência +button.macros = &Macros +button.invite = &Convidar +button.transfer = &Transferir +button.canned.responses = &Respostas Pré-definidas +button.end = &Fim +button.co.browse = &Co-Navegação +button.edit.canned.responses = &Editar Respostas Pré-definidas +button.start.cobrowsing.session = Iniciar Sessão de Co-Navegação +button.save.note = &Guardar Nota +button.new = &Novo +button.delete = &Eliminar +button.save = &Guardar +button.accept = &Aceitar +button.reject = &Rejeitar + + +checkbox.allow.user.to.follow = Permitir ao Utilizador Seguir + +label.notes = &Notas +label.message.to.agent = Mensagem para o agente +label.select.agent = Selecionar Agente +label.title = &Título +label.type = T&ipo +label.response = &Resposta +label.initial.response = &Resposta Inicial + + + +message.workgroup.logged.into = Entrou no Grupo de Trabalho {0} +message.incoming.request = {0} +message.start.cobrowsing = Iniciar uma sessão de Co-Navegação com a página {0} +message.send.cobrowsing.message = Enviou um convite de Co-Navegação com a página {0} +message.click.to.add.notes = Clique aqui para adicionar notas. +message.chat.notes = As notas de chat estão associadas a este chat e serão pesquisáveis através da pesquisa no chat. +message.notes.updated = Notas foram atualizadas +message.unable.to.update.notes = Não foi possível guardar a nota. Por favor, tente novamente. +message.view.more.information = Ver mais informações... +message.conversation.transferred = A conversação foi transferida. +message.invitation.rejected = O convite para a conversa foi rejeitado por {0} +message.please.join.me.in.conference = Por favor, junte-se a mim numa conferência. +message.user.has.been.invited = {0} foi convidado a participar nesta conversação. +message.waiting.for.user = A aguardar que {0} aceite esta transferência. +message.transfering.to.user = Estou a transferir esta conversação para si. +message.join.me.in.chat = Por favor, junta-te a mim nesta conversação. +message.transfer.to.another.agent = Transferir esta conversação para outro agente, grupo de trabalho ou fila. +message.invite.another.agent = Convide outras pessoas para se juntarem a esta conversação. +message.no.agent.selected.error = Nenhum agente foi selecionado +message.jid.invalid.error = Insira um JID válido +message.message.required.error = Insira uma mensagem +message.specify.personal.macros = Especifique macros pessoais a serem usadas nos seus chats com clientes. +message.macros.not.saved = As suas macros não puderam ser guardadas. +message.add.new.response = Adicionar nova resposta +message.current.chats = Chats atuais ({0}) +message.transcript.not.found.error = Não foi possível localizar a transcrição +message.incoming.chat.request = Pedido de Chat Recebido de {0} +message.user.joined.room = {0} entrou na sala. +message.user.left.room = {0} saiu da sala. +message.not.specified = Não especificado +message.user.not.logged.in = O utilizador não está autenticado no Grupo de Trabalho. +message.agent.is.not.in.chat = O agente não está atualmente em nenhum chat. +message.find.previous.conversations = Digite texto para pesquisar em conversas anteriores. + +menuitem.global.canned.responses = Respostas Pré-definidas Globais +menuitem.no.entries = Sem entradas na Categoria +menuitem.join.chat = Entrar no Chat +menuitem.monitor.chat = Monitorizar Chat + +tab.fastpath = Fastpath +tab.current.chats = Chats Atuais +tab.online.agents = Agentes Online +tab.user.info = Informações do Utilizador +tab.participants = Participantes +tab.user.history = Histórico do Utilizador +tab.notes = Notas +tab.queue.activity = Atividade da Fila de Espera +tab.transcript = Transcrição + +title.cobrowsing.for = Co-Navegação Para {0} +title.chat.notes = Notas do Chat +title.notes = Notas +title.request.information = Solicitar Informação +title.information = Informação +title.transcript = Transcrição +title.transfer = Transferir +title.invitation = Convite +title.error = Erro +title.contact.list = Lista de Contactos +title.personal.macros = Macros Pessoais +title.response.name = Nome da Resposta +title.response.text = Texto de Resposta +title.personal = Pessoal +title.create.canned.response = Criar Resposta Pré-definida +title.previous.chats = Chats Anteriores +title.personal.chats = Chats Pessoais +title.chat.transcript = Transcrição do Chat +title.current.active.conversations = Conversações Ativas Atuais +title.number.of.active.conversations = # de conversações ativas +title.current.conversations = Conversações Atuais +title.fastpath.invitation = Convite para o Fastpath +title.fastpath.transfer = Transferência Fastpath +title.workgroup = {0} Grupo de Trabalho +title.chat.transcripts = Transcrições do Chat +title.search.results = Resultados da Pesquisa +title.chat.transcripts.search = Pesquisa de Transcrições no Chat +title.number.of.conversations.found = # de conversações encontradas: + +time.days = d +time.hours = h +time.minutes = min +time.since = desde +time.less.than.one.minute = menos do que 1 minuto + +tooltip.allow.cobrowsing = Permite ao visitante atual seguir a sua navegação. +tooltip.hide.cobrowsing = Oculta a navegação para o visitante atual. +tooltip.back.one.page = Voltar uma página +tooltip.push.url = Enviar uma ligação +tooltip.push.current.page = Envie o URL atual para o visitante. +tooltip.save.transcript = Guardar Transcrição do Chat +tooltip.print.transcript = Imprimir Transcrição do Chat + +# TO DO +org.jivesoftware.fastpath.workspace.search +org.jivesoftware.fastpath.workspace.utils diff --git a/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_ru_RU.properties b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_ru_RU.properties new file mode 100644 index 000000000..e5c384ad6 --- /dev/null +++ b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_ru_RU.properties @@ -0,0 +1,160 @@ +workgroup = Ð Ð°Ð±Ð¾Ñ‡Ð°Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð° +join = ПриÑоединитьÑÑ +logout = Выход +cobrowsing.session = Ð¡ÐµÐ°Ð½Ñ ÑовмеÑтного ПроÑмотра +back = Ðазад +go = Вперед +duration = ПродолжительноÑть +agents = Ðгенты +date = Дата +invite.agent = ÐŸÑ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ +invite = Приглашать +transfer.to.agent = Переводы +transfer = Перемещение +workgroups = Рабочие группы +transfer.to = Переезд Ð’ +cancel = Отмена +agent = Ðгент +visitor = ПоÑетитель +email = Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð¿Ð¾Ñ‡Ñ‚Ð° +question = Ð’Ð¾Ð¿Ñ€Ð¾Ñ +start.time = Ð’Ñ€ÐµÐ¼Ñ Ð½Ð°Ñ‡Ð°Ð»Ð° +seconds = Секунд +name = Ð˜Ð¼Ñ +from = От +room = Комната +message = Сообщение +number.in.queue = # Ð’ Очереди +average.wait.time = Среднее Ð’Ñ€ÐµÐ¼Ñ ÐžÐ¶Ð¸Ð´Ð°Ð½Ð¸Ñ +last.queue.activity = ПоÑледнее дейÑтвие Очереди +query = Ð—Ð°Ð¿Ñ€Ð¾Ñ +chat.with = ОбщайтеÑÑŒ Ñ + + + +button.logout = &Выход из ÑиÑтемы +button.history = &ИÑÑ‚Ð¾Ñ€Ð¸Ñ +button.conference = &ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ñ +button.macros = &МакроÑÑ‹ +button.invite = &ПриглаÑить +button.transfer = &Передача +button.canned.responses = &КонÑервированные Ответы +button.end = &Конец +button.co.browse = &Co-Обзор +button.edit.canned.responses = &Редактировать КонÑервированные Ответы +button.start.cobrowsing.session = Ðачать Ð¡ÐµÐ°Ð½Ñ Ð¡Ð¾Ð²Ð¼ÐµÑтного ПроÑмотра +button.save.note = &Сохранить заметку +button.new = &Ðовый +button.delete = &Удалить +button.save = &Сохранить +button.accept = &ПринÑть +button.reject = &Отклонить + + +checkbox.allow.user.to.follow = Разрешить пользователю Ñледовать + +label.notes = &ÐŸÑ€Ð¸Ð¼ÐµÑ‡Ð°Ð½Ð¸Ñ +label.message.to.agent = Сообщение агенту +label.select.agent = Выберите агента +label.title = &Ðазвание +label.type = &Тип +label.response = &Ответ +label.initial.response = &Ðачальный Ответ + + + +message.workgroup.logged.into = Logged into the {0} Workgroup +message.incoming.request = {0} +message.start.cobrowsing = Ðачните ÑÐµÐ°Ð½Ñ ÑовмеÑтного проÑмотра Ñо Ñтраницы {0} +message.send.cobrowsing.message = Отправлено приглашение на ÑовмеÑтный проÑмотр Ñо Ñтраницей {0} +message.click.to.add.notes = Ðажмите здеÑÑŒ, чтобы добавить заметки. +message.chat.notes = Заметки чата ÑвÑзаны Ñ Ñтим чатом и будут доÑтупны Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка через поиÑк чата. +message.notes.updated = ÐŸÑ€Ð¸Ð¼ÐµÑ‡Ð°Ð½Ð¸Ñ Ð±Ñ‹Ð»Ð¸ обновлены +message.unable.to.update.notes = Ðе удалоÑÑŒ зафикÑировать заметку. Попробуйте еще раз. +message.view.more.information = ПроÑмотр дополнительной информации... +message.conversation.transferred = Разговор был перенеÑен. +message.invitation.rejected = Приглашение к беÑеде было отклонено {0} +message.please.join.me.in.conference = ПожалуйÑта, приÑоединÑйтеÑÑŒ ко мне на конференции +message.user.has.been.invited = {0} был приглашен приÑоединитьÑÑ Ðº Ñтому разговору. +message.waiting.for.user = Ожидание {0}, чтобы принÑть Ñтот перевод. +message.transfering.to.user = Я передаю Ñтот разговор тебе. +message.join.me.in.chat = ПожалуйÑта, приÑоединÑйтеÑÑŒ ко мне в Ñтом чате. +message.transfer.to.another.agent = Передайте Ñтот разговор другому агенту, рабочей группе или очереди. +message.invite.another.agent = ПриглаÑите других приÑоединитьÑÑ Ðº Ñтому разговору. +message.no.agent.selected.error = Ðи один агент не был выбран +message.jid.invalid.error = Введите дейÑтвительный JID +message.message.required.error = Введите Ñообщение +message.specify.personal.macros = Укажите личные макроÑÑ‹ Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² чатах клиентов. +message.macros.not.saved = Ваши макроÑÑ‹ не удалоÑÑŒ Ñохранить. +message.add.new.response = Добавить новый ответ +message.current.chats = Текущие чаты ({0}) +message.transcript.not.found.error = РаÑшифровка не может быть найдена +message.incoming.chat.request = ВходÑщий Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð§Ð°Ñ‚Ð° От {0} +message.user.joined.room = {0} приÑоединилÑÑ Ðº комнате. +message.user.left.room = {0} вышел из комнаты. +message.not.specified = Ðе указан +message.user.not.logged.in = Пользователь не входит в Рабочую группу. +message.agent.is.not.in.chat = Ðгент в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½Ðµ находитÑÑ Ð½Ð¸ в каких чатах. +message.find.previous.conversations = Введите текÑÑ‚, который вы найдете в предыдущих разговорах. + +menuitem.global.canned.responses = Глобальные КонÑервированные Ответы +menuitem.no.entries = Ðет запиÑей в категории +menuitem.join.chat = ПриÑоединÑйтеÑÑŒ к Чату +menuitem.monitor.chat = Монитор Чата + +tab.fastpath = Fastpath +tab.current.chats = Текущие чаты +tab.online.agents = Онлайн-агенты +tab.user.info = Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ пользователе +tab.participants = УчаÑтники +tab.user.history = ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹ +tab.notes = ÐŸÑ€Ð¸Ð¼ÐµÑ‡Ð°Ð½Ð¸Ñ +tab.queue.activity = ÐктивноÑть очереди +tab.transcript = РаÑшифровка + +title.cobrowsing.for = СовмеÑтный ПроÑмотр Ð”Ð»Ñ {0} +title.chat.notes = Заметки в чате +title.notes = ÐŸÑ€Ð¸Ð¼ÐµÑ‡Ð°Ð½Ð¸Ñ +title.request.information = ЗапроÑить информацию +title.information = Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ +title.transcript = РаÑшифровка +title.transfer = Перемещение +title.invitation = Приглашение +title.error = Ошибка +title.contact.list = СпиÑок контактов +title.personal.macros = Личные макроÑÑ‹ +title.response.name = Ð˜Ð¼Ñ Ð¾Ñ‚Ð²ÐµÑ‚Ð° +title.response.text = ТекÑÑ‚ ответа +title.personal = Личный +title.create.canned.response = Создайте ЗаконÑервированный Ответ +title.previous.chats = Предыдущие Чаты +title.personal.chats = Личные чаты +title.chat.transcript = Стенограмма чата +title.current.active.conversations = Текущие Ðктивные разговоры +title.number.of.active.conversations = # количеÑтво активных разговоров +title.current.conversations = Текущие разговоры +title.fastpath.invitation = Приглашение Fastpath +title.fastpath.transfer = БыÑÑ‚Ñ€Ð°Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ð° Пути +title.workgroup = {0} Ð Ð°Ð±Ð¾Ñ‡Ð°Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð° +title.chat.transcripts = Стенограммы чатов +title.search.results = Результаты поиÑка +title.chat.transcripts.search = ПоиÑк Ñтенограмм чатов +title.number.of.conversations.found = # количеÑтво найденных разговоров: + +time.days = д +time.hours = ч +time.minutes = мин +time.since = Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ +time.less.than.one.minute = меньше чем 1 минута + +tooltip.allow.cobrowsing = ПозволÑет текущему поÑетителю Ñледить за навигацией вашего браузера. +tooltip.hide.cobrowsing = Скрывает навигацию вашего браузера от текущего поÑетителÑ. +tooltip.back.one.page = ВернитеÑÑŒ на одну Ñтраницу назад +tooltip.push.url = Ðажмите на ÑÑылку +tooltip.push.current.page = Ðажмите текущий URL-Ð°Ð´Ñ€ÐµÑ Ð¿Ð¾ÑÐµÑ‚Ð¸Ñ‚ÐµÐ»Ñ +tooltip.save.transcript = Сохранить Стенограмму Чата +tooltip.print.transcript = РаÑпечатайте Стенограмму Чата + +# TO DO +org.jivesoftware.fastpath.workspace.search +org.jivesoftware.fastpath.workspace.utils diff --git a/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_zh_CN.properties b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_zh_CN.properties new file mode 100644 index 000000000..3f6e8451d --- /dev/null +++ b/plugins/fastpath/src/main/resources/i18n/fastpath_i18n_zh_CN.properties @@ -0,0 +1,160 @@ +workgroup = 工作组 +join = 加入 +logout = 登出 +cobrowsing.session = å…±åŒæµè§ˆä¼šè¯ +back = 返回 +go = å‰å¾€ +duration = æ—¶é•¿ +agents = ä»£ç† +date = 日期 +invite.agent = 邀请 +invite = 邀请 +transfer.to.agent = 传输 +transfer = 传输 +workgroups = 工作组 +transfer.to = 传输到 +cancel = å–æ¶ˆ +agent = ä»£ç† +visitor = 访客 +email = 电å­é‚®ä»¶ +question = 问题 +start.time = 开始时间 +seconds = ç§’ +name = åç§° +from = æ¥è‡ª +room = ç¾¤èŠ +message = æ¶ˆæ¯ +number.in.queue = # 在队列中 +average.wait.time = å¹³å‡ç­‰å¾…æ—¶é—´ +last.queue.activity = 最åŽé˜Ÿåˆ—活动 +query = 查询 +chat.with = èŠå¤© + + + +button.logout = 登出(&L) +button.history = 历å²è®°å½•(&H) +button.conference = 群èŠ(&C) +button.macros = 宿Œ‡ä»¤(&M) +button.invite = 邀请(&I) +button.transfer = 传输(&T) +button.canned.responses = 预置回å¤(&C) +button.end = 结æŸ(&E) +button.co.browse = å…±åŒæµè§ˆ(&C) +button.edit.canned.responses = 编辑预置回å¤(&E) +button.start.cobrowsing.session = å¼€å§‹å…±åŒæµè§ˆä¼šè¯ +button.save.note = ä¿å­˜ç¬”è®°(&S) +button.new = æ–°(&N) +button.delete = 删除(&D) +button.save = ä¿å­˜(&S) +button.accept = 接å—(&A) +button.reject = æ‹’ç»(&R) + + +checkbox.allow.user.to.follow = å…许用户关注 + +label.notes = 笔记(&N) +label.message.to.agent = 给代ç†çš„æ¶ˆæ¯ +label.select.agent = é€‰æ‹©ä»£ç† +label.title = 标题(&T) +label.type = 输入(&Y) +label.response = 回å¤(&R) +label.initial.response = åˆå§‹å›žå¤(&I) + + + +message.workgroup.logged.into = 已登录到 {0} 工作组 +message.incoming.request = {0} +message.start.cobrowsing = å¼€å§‹ä¸Žé¡µé¢ {0} çš„å…±åŒæµè§ˆä¼šè¯ +message.send.cobrowsing.message = å·²å‘é€ä¸Žé¡µé¢ {0} çš„å…±åŒæµè§ˆé‚€è¯· +message.click.to.add.notes = å•击此处添加笔记。 +message.chat.notes = èŠå¤©ç¬”记与此èŠå¤©ç›¸å…³ï¼Œå¯é€šè¿‡èŠå¤©æœç´¢è¿›è¡Œæœç´¢ã€‚ +message.notes.updated = 已更新笔记 +message.unable.to.update.notes = 无法æäº¤ç¬”记,请å†è¯•一次。 +message.view.more.information = 查看更多信æ¯â€¦ +message.conversation.transferred = 已传输此对è¯ã€‚ +message.invitation.rejected = 对è¯é‚€è¯·è¢« {0} æ‹’ç» +message.please.join.me.in.conference = è¯·æŠŠæˆ‘åŠ å…¥ç¾¤èŠ +message.user.has.been.invited = {0} å·²å—邀加入此对è¯ã€‚ +message.waiting.for.user = 正在等待 {0} æŽ¥å—æ­¤ä¼ è¾“。 +message.transfering.to.user = 我正在将这次对è¯ä¼ è¾“给您。 +message.join.me.in.chat = 请把我加入此èŠå¤©ã€‚ +message.transfer.to.another.agent = 将此对è¯ä¼ è¾“到其他代ç†ã€å·¥ä½œç»„或队列。 +message.invite.another.agent = 邀请其他人加入此对è¯ã€‚ +message.no.agent.selected.error = æœªé€‰æ‹©ä»»ä½•ä»£ç† +message.jid.invalid.error = 请输入有效的 JID +message.message.required.error = è¯·è¾“å…¥æ¶ˆæ¯ +message.specify.personal.macros = 请指定è¦åœ¨å®¢æˆ·èŠå¤©ä¸­ä½¿ç”¨çš„ä¸ªäººå®æŒ‡ä»¤ã€‚ +message.macros.not.saved = 无法ä¿å­˜æ‚¨çš„宿Œ‡ä»¤ã€‚ +message.add.new.response = æ·»åŠ æ–°å›žå¤ +message.current.chats = 当å‰èŠå¤© ({0}) +message.transcript.not.found.error = 无法定ä½è®°å½• +message.incoming.chat.request = æ¥è‡ª {0} 的传入èŠå¤©è¯·æ±‚ +message.user.joined.room = {0} 加入了群èŠã€‚ +message.user.left.room = {0} 离开了群èŠã€‚ +message.not.specified = 未指定 +message.user.not.logged.in = 用户未登录到工作组。 +message.agent.is.not.in.chat = 代ç†å½“å‰ä¸åœ¨ä»»ä½•èŠå¤©ä¸­ã€‚ +message.find.previous.conversations = 请输入è¦åœ¨ä»¥å‰çš„对è¯ä¸­æŸ¥æ‰¾çš„æ–‡æœ¬ã€‚ + +menuitem.global.canned.responses = å…¨å±€é¢„ç½®å›žå¤ +menuitem.no.entries = 类别中没有æ¡ç›® +menuitem.join.chat = 加入èŠå¤© +menuitem.monitor.chat = 监控èŠå¤© + +tab.fastpath = 快速路径 +tab.current.chats = 当å‰èŠå¤© +tab.online.agents = åœ¨çº¿ä»£ç† +tab.user.info = ç”¨æˆ·ä¿¡æ¯ +tab.participants = å‚与者 +tab.user.history = 用户历å²è®°å½• +tab.notes = 笔记 +tab.queue.activity = 队列活动 +tab.transcript = 记录 + +title.cobrowsing.for = å…±åŒæµè§ˆ {0} +title.chat.notes = èŠå¤©ç¬”è®° +title.notes = 笔记 +title.request.information = è¯·æ±‚ä¿¡æ¯ +title.information = ä¿¡æ¯ +title.transcript = 记录 +title.transfer = 传输 +title.invitation = 邀请 +title.error = 错误 +title.contact.list = è”系人列表 +title.personal.macros = ä¸ªäººå®æŒ‡ä»¤ +title.response.name = 回å¤åç§° +title.response.text = å›žå¤æ–‡æœ¬ +title.personal = 个人 +title.create.canned.response = åˆ›å»ºé¢„ç½®å›žå¤ +title.previous.chats = 以å‰çš„èŠå¤© +title.personal.chats = 个人èŠå¤© +title.chat.transcript = èŠå¤©è®°å½• +title.current.active.conversations = 当剿´»åŠ¨å¯¹è¯ +title.number.of.active.conversations = # çš„æ´»åŠ¨å¯¹è¯ +title.current.conversations = 当å‰å¯¹è¯ +title.fastpath.invitation = 快速路径邀请 +title.fastpath.transfer = 快速路径传输 +title.workgroup = {0} 工作组 +title.chat.transcripts = èŠå¤©è®°å½• +title.search.results = æœç´¢ç»“æžœ +title.chat.transcripts.search = èŠå¤©è®°å½•æœç´¢ +title.number.of.conversations.found = # 的对è¯å·²æ‰¾åˆ°ï¼š + +time.days = 天 +time.hours = æ—¶ +time.minutes = 分 +time.since = 自 +time.less.than.one.minute = å°äºŽ 1 分钟 + +tooltip.allow.cobrowsing = å…许当å‰è®¿å®¢è·Ÿè¸ªæ‚¨çš„æµè§ˆå™¨å¯¼èˆªã€‚ +tooltip.hide.cobrowsing = 对当å‰è®¿å®¢éšè—æµè§ˆå™¨å¯¼èˆªã€‚ +tooltip.back.one.page = 返回一页 +tooltip.push.url = 推é€é“¾æŽ¥ +tooltip.push.current.page = å‘访客推é€å½“å‰ URL +tooltip.save.transcript = ä¿å­˜èŠå¤©è®°å½• +tooltip.print.transcript = 打å°èŠå¤©è®°å½• + +# TO DO +org.jivesoftware.fastpath.workspace.search +org.jivesoftware.fastpath.workspace.utils diff --git a/src/plugins/fastpath/src/resources/images/icon_chatinvite_24x24.png b/plugins/fastpath/src/main/resources/images/icon_chatinvite_24x24.png similarity index 100% rename from src/plugins/fastpath/src/resources/images/icon_chatinvite_24x24.png rename to plugins/fastpath/src/main/resources/images/icon_chatinvite_24x24.png diff --git a/plugins/fastpath/src/main/resources/images/icon_chattransfer_24x24.png b/plugins/fastpath/src/main/resources/images/icon_chattransfer_24x24.png new file mode 100644 index 000000000..04eeb50e8 Binary files /dev/null and b/plugins/fastpath/src/main/resources/images/icon_chattransfer_24x24.png differ diff --git a/plugins/fastpath/src/main/resources/images/icon_cobrowse_24x24.png b/plugins/fastpath/src/main/resources/images/icon_cobrowse_24x24.png new file mode 100644 index 000000000..2c071955f Binary files /dev/null and b/plugins/fastpath/src/main/resources/images/icon_cobrowse_24x24.png differ diff --git a/plugins/fastpath/src/main/resources/images/icon_endchat1_24x24.png b/plugins/fastpath/src/main/resources/images/icon_endchat1_24x24.png new file mode 100644 index 000000000..866288a6a Binary files /dev/null and b/plugins/fastpath/src/main/resources/images/icon_endchat1_24x24.png differ diff --git a/plugins/fileupload/pom.xml b/plugins/fileupload/pom.xml new file mode 100644 index 000000000..ea929cd98 --- /dev/null +++ b/plugins/fileupload/pom.xml @@ -0,0 +1,26 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + fileupload + 0.1 + + Http File Upload Plugin + Allows users to share files by uploading to a server (via XEP-0363). + + + + Dele Olajide + + Author + + + + diff --git a/plugins/fileupload/src/main/java/org/jivesoftware/spark/plugin/fileupload/ChatRoomDecorator.java b/plugins/fileupload/src/main/java/org/jivesoftware/spark/plugin/fileupload/ChatRoomDecorator.java new file mode 100644 index 000000000..bb21d53eb --- /dev/null +++ b/plugins/fileupload/src/main/java/org/jivesoftware/spark/plugin/fileupload/ChatRoomDecorator.java @@ -0,0 +1,183 @@ +/** + * Copyright (C) 2004-2010 Jive Software. 2023 Ignite Realtime Foundation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.spark.plugin.fileupload; + +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.io.entity.FileEntity; +import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smack.packet.StandardExtensionElement; +import org.jivesoftware.spark.SessionManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.util.GraphicUtils; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.updater.AcceptAllCertsConnectionManager; +import org.jxmpp.jid.impl.JidCreate; + +import javax.swing.*; +import java.awt.*; +import java.io.*; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.nio.file.Files; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.hc.core5.http.ContentType.APPLICATION_OCTET_STREAM; +import static org.jivesoftware.smack.packet.Message.Type.groupchat; +import static org.jivesoftware.smack.packet.Message.Type.chat; + +public class ChatRoomDecorator { + private final RolloverButton fileuploadButton; + private final ChatRoom room; + + public ChatRoomDecorator(final ChatRoom room) { + this.room = room; + // Adds file upload button to chat room + fileuploadButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.Icon.UPLOAD_ICON)); + try { + fileuploadButton.setToolTipText(GraphicUtils.createToolTip("Http File Upload")); + fileuploadButton.addActionListener(event -> { + getUploadUrl(room, room.getChatType() == groupchat ? groupchat : chat); + }); + room.getEditorBar().add(fileuploadButton); + } catch (Exception e) { + Log.error("Cannot create file upload icon for the ChatRoomDecorator", e); + } + } + + private static String guessContentType(final File file) { + String result = URLConnection.guessContentTypeFromName(file.getName()); + if (result != null && !result.isEmpty()) { + return result; + } + try { + result = Files.probeContentType(file.toPath()); + if (result != null && !result.isEmpty()) { + return result; + } + try (final InputStream is = new BufferedInputStream(Files.newInputStream(file.toPath()))) { + result = URLConnection.guessContentTypeFromStream(is); + } + return result; + } catch (IOException e) { + return null; + } + } + + public void finished() { + Log.debug("ChatRoomDecorator finished for room: " + room.getBareJid()); + } + + private void getUploadUrl(ChatRoom room, Message.Type type) { + FileDialog fd = new FileDialog((Frame) null, "Choose a file to upload", FileDialog.LOAD); + fd.setMultipleMode(true); + fd.setVisible(true); + File[] files = fd.getFiles(); + + for (File file : files) { + SwingUtilities.invokeLater(() -> handleUpload(file, room, type)); + } + } + + private void handleUpload(File file, ChatRoom room, Message.Type type) { + Log.debug("Uploading file: " + file.getAbsolutePath()); + String fileName = URLEncoder.encode(file.getName(), UTF_8); + String mimeType = guessContentType(file); + try { + UploadRequest request = new UploadRequest(fileName, file.length(), mimeType); + SessionManager sessionManager = SparkManager.getSessionManager(); + sessionManager.getDiscoveredItems().getItems(); + String uploadEndpoint = "httpfileupload." + sessionManager.getServerAddress(); + request.setTo(JidCreate.fromOrThrowUnchecked(uploadEndpoint)); + request.setType(IQ.Type.get); + + IQ result = SparkManager.getConnection().sendIqRequestAndWaitForResponse(request); + UploadRequest response = (UploadRequest) result; + Log.debug("handleUpload response: putUrl=" + response.putUrl + " getUrl=" + response.getUrl); + if (response.putUrl != null) { + uploadFile(file, mimeType, response, room, type); + } + } catch (Exception e) { + Log.error("Error while attempting to uploading file", e); + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(room, + "Upload failed: " + e.getMessage(), + "Http File Upload Plugin", + JOptionPane.ERROR_MESSAGE); + } + } + + private void uploadFile(File file, String mimeType, UploadRequest response, ChatRoom room, Message.Type type) { + Log.debug("About to upload file for room " + room.getBareJid() + " via HTTP PUT to URL " + response.putUrl); + ContentType contentType = mimeType != null ? ContentType.create(mimeType) : APPLICATION_OCTET_STREAM; + try (final CloseableHttpClient httpClient = + HttpClients.custom().useSystemProperties() + .setConnectionManager(AcceptAllCertsConnectionManager.getInstance()) + .setUserAgent("Spark HttpFileUpload") + .build() + ) { + final ClassicHttpRequest request = ClassicRequestBuilder.put(response.putUrl) + .setEntity(new FileEntity(file, contentType)) + .build(); + + httpClient.execute(request, httpResponse -> { + try { + final int statusCode = httpResponse.getCode(); + final String reasonPhrase = httpResponse.getReasonPhrase(); + if ((statusCode >= 200) && (statusCode <= 202)) { + Log.debug("Upload file success. HTTP response: " + statusCode + " " + reasonPhrase); + broadcastUploadUrl(response.getUrl, type); + } else { + throw new IllegalStateException("Server responded to upload request with: " + statusCode + ": " + reasonPhrase); + } + } catch (Exception e) { + Log.error("Error encountered whilst uploading the file", e); + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(room, "Upload failed: " + e.getMessage(), "Http File Upload Plugin", JOptionPane.ERROR_MESSAGE); + } + return null; + }); + } catch (Exception e) { + Log.error("Error encountered whilst uploading the file", e); + UIManager.put("OptionPane.okButtonText", Res.getString("ok")); + JOptionPane.showMessageDialog(room, "Upload failed: " + e.getMessage(), "Http File Upload Plugin", JOptionPane.ERROR_MESSAGE); + } + } + + private void broadcastUploadUrl(String url, Message.Type type) { + MessageBuilder messageBuilder = StanzaBuilder.buildMessage() + .ofType(type) + .setBody(url) + .addExtension( + StandardExtensionElement.builder("x", "jabber:x:oob") + .addElement("url", url) + .build() + ); + room.sendMessage(messageBuilder); + } + +} diff --git a/plugins/fileupload/src/main/java/org/jivesoftware/spark/plugin/fileupload/SparkFileUploadPlugin.java b/plugins/fileupload/src/main/java/org/jivesoftware/spark/plugin/fileupload/SparkFileUploadPlugin.java new file mode 100644 index 000000000..31e3e38c5 --- /dev/null +++ b/plugins/fileupload/src/main/java/org/jivesoftware/spark/plugin/fileupload/SparkFileUploadPlugin.java @@ -0,0 +1,99 @@ +/** + * Copyright (C) 2004-2010 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.jivesoftware.spark.plugin.fileupload; + +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomListener; +import org.jivesoftware.spark.ui.GlobalMessageListener; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.smack.provider.ProviderManager; +import org.jxmpp.jid.EntityJid; + +import java.util.*; + + +public class SparkFileUploadPlugin implements Plugin, ChatRoomListener, GlobalMessageListener { + private ChatManager chatManager; + private final Map decorators = new HashMap<>(); + + @Override + public void initialize() { + ProviderManager.addIQProvider("slot", UploadRequest.NAMESPACE, new UploadRequest.Provider()); + chatManager = SparkManager.getChatManager(); + chatManager.addChatRoomListener(this); + chatManager.addGlobalMessageListener(this); + } + + @Override + public void messageReceived(ChatRoom room, Message message) { + String body = message.getBody(); + if (body != null && (body.startsWith("https://") || body.startsWith("http://")) && body.contains("/httpfileupload/")) { + Log.warning("http file upload get url " + message.getBody()); + } + } + + @Override + public void messageSent(ChatRoom room, Message message) { + } + + @Override + public void shutdown() { + try { + Log.debug("shutdown"); + chatManager.removeChatRoomListener(this); + chatManager.removeGlobalMessageListener(this); + chatManager = null; + ProviderManager.removeIQProvider("slot", UploadRequest.NAMESPACE); + } catch (Exception e) { + Log.warning("shutdown ", e); + } + } + + @Override + public boolean canShutDown() { + return true; + } + + @Override + public void uninstall() { + } + + @Override + public void chatRoomClosed(ChatRoom chatroom) { + EntityJid roomId = chatroom.getJid(); + Log.debug("chatRoomClosed: " + roomId); + if (decorators.containsKey(roomId)) { + ChatRoomDecorator decorator = decorators.remove(roomId); + decorator.finished(); + } + } + + @Override + public void chatRoomOpened(final ChatRoom room) { + EntityJid roomId = room.getJid(); + Log.debug("chatRoomOpened: " + roomId); + if (!decorators.containsKey(roomId)) { + decorators.put(roomId, new ChatRoomDecorator(room)); + } + } + +} diff --git a/plugins/fileupload/src/main/java/org/jivesoftware/spark/plugin/fileupload/UploadRequest.java b/plugins/fileupload/src/main/java/org/jivesoftware/spark/plugin/fileupload/UploadRequest.java new file mode 100644 index 000000000..e6ed347c9 --- /dev/null +++ b/plugins/fileupload/src/main/java/org/jivesoftware/spark/plugin/fileupload/UploadRequest.java @@ -0,0 +1,90 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.fileupload; + +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IqData; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.provider.IqProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.JxmppContext; + +import java.io.IOException; + +/** + * An IQ packet that's a request for an upload slot + */ +public class UploadRequest extends IQ { + public static final String NAMESPACE = "urn:xmpp:http:upload:0"; + + private String filename; + private long filesize; + private String contentType; + + public String getUrl = null; + public String putUrl = null; + + public UploadRequest() { + super("request", NAMESPACE); + } + + public UploadRequest(String filename, long filesize, String contentType) { + super("request", NAMESPACE); + this.filename = filename; + this.filesize = filesize; + this.contentType = contentType; + } + + @Override + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder buf) { + buf.rightAngleBracket(); + buf.element("size", Long.toString(filesize)); + buf.element("filename", filename); + if (contentType != null && !contentType.isEmpty()) { + buf.element("content-type", contentType); + } + return buf; + } + + public static class Provider extends IqProvider { + public Provider() { + super(); + } + + @Override + public UploadRequest parse(XmlPullParser parser, int i, IqData iqData, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException { + final UploadRequest uploadRequest = new UploadRequest(); + boolean done = false; + while (!done) { + XmlPullParser.Event eventType = parser.next(); + if (eventType == XmlPullParser.Event.START_ELEMENT) { + if (parser.getName().equals("put")) { + uploadRequest.putUrl = parser.getAttributeValue(null, "url"); + } else if (parser.getName().equals("get")) { + uploadRequest.getUrl = parser.getAttributeValue(null, "url"); + } + } else if (eventType == XmlPullParser.Event.END_ELEMENT) { + if (parser.getName().equals("slot")) { + done = true; + } + } + } + + return uploadRequest; + } + } +} diff --git a/plugins/fileupload/src/main/plugin-metadata/plugin.xml b/plugins/fileupload/src/main/plugin-metadata/plugin.xml new file mode 100644 index 000000000..e9d484731 --- /dev/null +++ b/plugins/fileupload/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,12 @@ + + ${project.name} + ${project.version} + ${project.description} + Dele Olajide + https://IgniteRealtime.org + support@IgniteRealtime.org + org.jivesoftware.spark.plugin.fileupload.SparkFileUploadPlugin + 3.1.0 + Windows,Linux,Mac + 11 + diff --git a/plugins/fileupload/src/main/resources/images/icon16.png b/plugins/fileupload/src/main/resources/images/icon16.png new file mode 100644 index 000000000..58b702ba3 Binary files /dev/null and b/plugins/fileupload/src/main/resources/images/icon16.png differ diff --git a/plugins/flashing/pom.xml b/plugins/flashing/pom.xml new file mode 100644 index 000000000..9dd26400e --- /dev/null +++ b/plugins/flashing/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + flashing + 1.3 + + Window Flashing Plugin + Flashes window on new messages (Microsoft Windows only). + + + + Michael Will + michael-will@gmx.net + + Author + + + + diff --git a/src/plugins/flashing/src/c/compile_dll_with_cygwin.bat b/plugins/flashing/src/main/c/compile_dll_with_cygwin.bat similarity index 100% rename from src/plugins/flashing/src/c/compile_dll_with_cygwin.bat rename to plugins/flashing/src/main/c/compile_dll_with_cygwin.bat diff --git a/src/plugins/flashing/src/c/org_jivesoftware_spark_plugin_flashing_FlashWindow.c b/plugins/flashing/src/main/c/org_jivesoftware_spark_plugin_flashing_FlashWindow.c similarity index 100% rename from src/plugins/flashing/src/c/org_jivesoftware_spark_plugin_flashing_FlashWindow.c rename to plugins/flashing/src/main/c/org_jivesoftware_spark_plugin_flashing_FlashWindow.c diff --git a/src/plugins/flashing/src/c/org_jivesoftware_spark_plugin_flashing_FlashWindow.h b/plugins/flashing/src/main/c/org_jivesoftware_spark_plugin_flashing_FlashWindow.h similarity index 100% rename from src/plugins/flashing/src/c/org_jivesoftware_spark_plugin_flashing_FlashWindow.h rename to plugins/flashing/src/main/c/org_jivesoftware_spark_plugin_flashing_FlashWindow.h diff --git a/src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashWindow.java b/plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashWindow.java similarity index 78% rename from src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashWindow.java rename to plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashWindow.java index 909a3998f..04f8237f6 100644 --- a/src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashWindow.java +++ b/plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashWindow.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,7 +26,7 @@ import org.jivesoftware.spark.PluginManager; public class FlashWindow { - private HashMap flashings = new HashMap<>(); + private final HashMap flashings = new HashMap<>(); static { @@ -41,13 +37,13 @@ public class FlashWindow { } try { - System.load(PluginManager.PLUGINS_DIRECTORY + File.separator + "flashing" + File.separator + "lib" + System.load(PluginManager.PLUGINS_DIRECTORY + File.separator + "flashing" + File.separator + "native" + File.separator + "FlashWindow" + arch + ".dll"); } catch (UnsatisfiedLinkError e) { - // So, we are on 64bit using 64bit java and you rather wand a 32bit.dll ?? suuuureeee.... + // So, we are on 64bit using 64bit java and you rather want a 32bit.dll ?? if (e.getMessage().contains("Can't load AMD 64-bit .dll on a IA 32-bit platform")) { - System.load(PluginManager.PLUGINS_DIRECTORY + File.separator + "flashing" + File.separator + "lib" - + File.separator + "FlashWindow.dll"); + System.load(PluginManager.PLUGINS_DIRECTORY + File.separator + "flashing" + File.separator + "native" + + File.separator + "FlashWindow.dll" ); } else { e.printStackTrace(); } @@ -84,28 +80,24 @@ public void flash(final Window window, final int intratime, } ).start(); } - public void startFlashing(final Window window) { - if (flashings.get(window) == null) { - Thread t = new Thread() { - public void run() { - try { - while (true) { - Thread.sleep(1500); - // System.out.println("Flash Window"); - if (window instanceof JFrame) - flash(((JFrame) window).getTitle(), true); - } - } catch (Exception ex) { - flash(((JFrame) window).getTitle(), false); - // System.out.println(ex.getMessage()); - } - - } - }; - t.start(); - flashings.put(window, t); - } - } + public void startFlashing(final Window window) { + if (flashings.get(window) == null) { + Thread t = new Thread(() -> { + while (true) { + try { + Thread.sleep(1500); + if (window instanceof JFrame) + flash(((JFrame) window).getTitle(), true); + } catch (Exception ex) { + flash(((JFrame) window).getTitle(), false); + break; + } + } + }); + t.start(); + flashings.put(window, t); + } + } public void stopFlashing(final Window window) { if (flashings.get(window) != null) { @@ -114,7 +106,7 @@ public void stopFlashing(final Window window) { } } - public static void main(String[] args) throws Exception { + public static void main(String[] args) { final JFrame frame = new JFrame(); frame.setTitle("Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); diff --git a/src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingHandler.java b/plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingHandler.java similarity index 93% rename from src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingHandler.java rename to plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingHandler.java index 46b80e462..0532ae35a 100644 --- a/src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingHandler.java +++ b/plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingHandler.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,7 +21,7 @@ import org.jivesoftware.spark.SparkManager; public class FlashingHandler implements NativeHandler { - private FlashWindow flasher; + private final FlashWindow flasher; public FlashingHandler() { flasher = new FlashWindow(); @@ -35,7 +31,7 @@ public FlashingHandler() { public void flashWindow(Window window) { FlashingPreference preference = (FlashingPreference) SparkManager.getPreferenceManager().getPreference(FlashingPreference.NAMESPACE); if (preference.getPreferences().isFlashingEnabled()) { - if (preference.getPreferences().getFlashingType().equals(FlashingPreferences.TYPE_CONTINOUS)) { + if (preference.getPreferences().getFlashingType().equals(FlashingPreferences.TYPE_CONTINUOUS)) { flasher.startFlashing(window); } else if (preference.getPreferences().getFlashingType().equals(FlashingPreferences.TYPE_TEMPORARY)) { diff --git a/src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingPlugin.java b/plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingPlugin.java similarity index 96% rename from src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingPlugin.java rename to plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingPlugin.java index 5917661d2..4df907647 100644 --- a/src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingPlugin.java +++ b/plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingPlugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingPreference.java b/plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingPreference.java similarity index 92% rename from src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingPreference.java rename to plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingPreference.java index 1e16896c1..ea9287cde 100644 --- a/src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingPreference.java +++ b/plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingPreference.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,9 +24,10 @@ import org.jivesoftware.spark.util.log.Log; public class FlashingPreference implements Preference { - public static String NAMESPACE = "flashing"; + public static final String NAMESPACE = "flashing"; + private FlashingPreferenceDialog dialog; - private FlashingPreferences preferences; + private final FlashingPreferences preferences; public FlashingPreference() { preferences = new FlashingPreferences(); @@ -75,7 +72,7 @@ public JComponent getGUI() { @Override public Icon getIcon() { ClassLoader cl = getClass().getClassLoader(); - return new ImageIcon(cl.getResource("lightning16.png")); + return new ImageIcon(cl.getResource("lightning.png")); } @Override diff --git a/src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingPreferenceDialog.java b/plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingPreferenceDialog.java similarity index 92% rename from src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingPreferenceDialog.java rename to plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingPreferenceDialog.java index 9ed045696..a06cf9bba 100644 --- a/src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingPreferenceDialog.java +++ b/plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingPreferenceDialog.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,13 +32,13 @@ public class FlashingPreferenceDialog extends JPanel { private static final long serialVersionUID = -5274539572483246530L; - private JCheckBox flashingEnabled; - private JComboBox flashingType; + private final JCheckBox flashingEnabled; + private final JComboBox flashingType; public FlashingPreferenceDialog() { JPanel flashingPanel = new JPanel(); flashingEnabled = new JCheckBox(); - flashingType = new JComboBox(); + flashingType = new JComboBox<>(); JLabel lTyps = new JLabel(); flashingPanel.setLayout(new GridBagLayout()); @@ -80,7 +76,7 @@ public boolean getFlashing() { } public void setFlashingType(String type) { - if (FlashingPreferences.TYPE_CONTINOUS.equals(type)) { + if (FlashingPreferences.TYPE_CONTINUOUS.equals(type)) { flashingType.setSelectedIndex(0); } else if (FlashingPreferences.TYPE_TEMPORARY.equals(type)) { @@ -93,7 +89,7 @@ else if (FlashingPreferences.TYPE_TEMPORARY.equals(type)) { public String getFlashingType() { if (flashingType.getSelectedIndex() == 0) { - return FlashingPreferences.TYPE_CONTINOUS; + return FlashingPreferences.TYPE_CONTINUOUS; } else if (flashingType.getSelectedIndex() == 1) { return FlashingPreferences.TYPE_TEMPORARY; diff --git a/src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingPreferences.java b/plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingPreferences.java similarity index 91% rename from src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingPreferences.java rename to plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingPreferences.java index 77c94c544..7593c2443 100644 --- a/src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingPreferences.java +++ b/plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingPreferences.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,10 +24,10 @@ import org.jivesoftware.Spark; public class FlashingPreferences { - public static final String TYPE_CONTINOUS = "continuous"; + public static final String TYPE_CONTINUOUS = "continuous"; public static final String TYPE_TEMPORARY = "temporary"; - private Properties props; + private final Properties props; private File configFile; public FlashingPreferences() { @@ -70,7 +66,7 @@ public void setFlashingEnabled(boolean enabled) { } public String getFlashingType() { - return props.getProperty("flashingType", TYPE_CONTINOUS); + return props.getProperty("flashingType", TYPE_CONTINUOUS); } public void setFlashingType(String type) { diff --git a/src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingResources.java b/plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingResources.java similarity index 81% rename from src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingResources.java rename to plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingResources.java index 545642b7d..ccd64f3fb 100644 --- a/src/plugins/flashing/src/java/org/jivesoftware/spark/plugin/flashing/FlashingResources.java +++ b/plugins/flashing/src/main/java/org/jivesoftware/spark/plugin/flashing/FlashingResources.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,18 +18,17 @@ import java.util.PropertyResourceBundle; import java.util.ResourceBundle; +import org.jivesoftware.resource.UTF8Control; import org.jivesoftware.spark.util.log.Log; public class FlashingResources { - private static PropertyResourceBundle prb; + private static final PropertyResourceBundle prb; - static ClassLoader cl = FlashingResources.class.getClassLoader(); - static { - prb = (PropertyResourceBundle)ResourceBundle.getBundle("i18n/flashing_i18n"); + prb = (PropertyResourceBundle)ResourceBundle.getBundle("i18n/flashing_i18n", new UTF8Control()); } - public static final String getString(String propertyName) { + public static String getString(String propertyName) { try { return prb.getString(propertyName); } diff --git a/src/plugins/flashing/build/lib/FlashWindow.dll b/plugins/flashing/src/main/native/FlashWindow.dll similarity index 100% rename from src/plugins/flashing/build/lib/FlashWindow.dll rename to plugins/flashing/src/main/native/FlashWindow.dll diff --git a/src/plugins/flashing/build/lib/FlashWindow64.dll b/plugins/flashing/src/main/native/FlashWindow64.dll similarity index 100% rename from src/plugins/flashing/build/lib/FlashWindow64.dll rename to plugins/flashing/src/main/native/FlashWindow64.dll diff --git a/plugins/flashing/src/main/plugin-metadata/plugin.xml b/plugins/flashing/src/main/plugin-metadata/plugin.xml new file mode 100644 index 000000000..997688ecb --- /dev/null +++ b/plugins/flashing/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,13 @@ + + + ${project.name} + ${project.version} + ${project.description} + Michael Will + https://IgniteRealtime.org + support@IgniteRealtime.org + org.jivesoftware.spark.plugin.flashing.FlashingPlugin + 3.1.0 + Windows + 11 + diff --git a/src/plugins/flashing/resources/i18n/flashing_i18n.properties b/plugins/flashing/src/main/resources/i18n/flashing_i18n.properties similarity index 78% rename from src/plugins/flashing/resources/i18n/flashing_i18n.properties rename to plugins/flashing/src/main/resources/i18n/flashing_i18n.properties index 29a444fe0..661a73319 100644 --- a/src/plugins/flashing/resources/i18n/flashing_i18n.properties +++ b/plugins/flashing/src/main/resources/i18n/flashing_i18n.properties @@ -3,4 +3,4 @@ title.flashing = Taskbar Flashing flashing.enable = &Enable Taskbar flashing flashing.type = &Type flashing.type.continuous = Continuous -flashing.type.temporary = Temporary \ No newline at end of file +flashing.type.temporary = Temporary diff --git a/src/plugins/flashing/resources/i18n/flashing_i18n_de.properties b/plugins/flashing/src/main/resources/i18n/flashing_i18n_de.properties similarity index 81% rename from src/plugins/flashing/resources/i18n/flashing_i18n_de.properties rename to plugins/flashing/src/main/resources/i18n/flashing_i18n_de.properties index db836a779..d6c8e087d 100644 --- a/src/plugins/flashing/resources/i18n/flashing_i18n_de.properties +++ b/plugins/flashing/src/main/resources/i18n/flashing_i18n_de.properties @@ -3,4 +3,4 @@ title.flashing = Blinkende Taskleiste flashing.enable = &Blinken in der Taskleiste aktivieren flashing.type = &Art flashing.type.continuous = Durchgehend -flashing.type.temporary = Temporär \ No newline at end of file +flashing.type.temporary = Temporär \ No newline at end of file diff --git a/plugins/flashing/src/main/resources/i18n/flashing_i18n_fr.properties b/plugins/flashing/src/main/resources/i18n/flashing_i18n_fr.properties new file mode 100644 index 000000000..5713c9355 --- /dev/null +++ b/plugins/flashing/src/main/resources/i18n/flashing_i18n_fr.properties @@ -0,0 +1,6 @@ +title.flashing = Clignotement de la barre des tâches + +flashing.enable = &Activer le clignotement +flashing.type = &Taper +flashing.type.continuous = Continue +flashing.type.temporary = Temporaire diff --git a/plugins/flashing/src/main/resources/i18n/flashing_i18n_lt.properties b/plugins/flashing/src/main/resources/i18n/flashing_i18n_lt.properties new file mode 100644 index 000000000..949697393 --- /dev/null +++ b/plugins/flashing/src/main/resources/i18n/flashing_i18n_lt.properties @@ -0,0 +1,6 @@ +title.flashing = MirgÄ—jimas + +flashing.enable = Ä®jungti informacinį mirgÄ—jimÄ… užduoÄių juostoje +flashing.type = BÅ«das +flashing.type.continuous = MirgÄ—ti be galo +flashing.type.temporary = PamirgÄ—jus nustoti diff --git a/plugins/flashing/src/main/resources/i18n/flashing_i18n_pl.properties b/plugins/flashing/src/main/resources/i18n/flashing_i18n_pl.properties new file mode 100644 index 000000000..da8511d34 --- /dev/null +++ b/plugins/flashing/src/main/resources/i18n/flashing_i18n_pl.properties @@ -0,0 +1,6 @@ +title.flashing = Migotanie paska zadaÅ„ + +flashing.enable = Włącz migotanie paska zadaÅ„ +flashing.type = Rodzaj migotania +flashing.type.continuous = CiÄ…gÅ‚y +flashing.type.temporary = Tymczasowy diff --git a/plugins/flashing/src/main/resources/i18n/flashing_i18n_ru_RU.properties b/plugins/flashing/src/main/resources/i18n/flashing_i18n_ru_RU.properties new file mode 100644 index 000000000..4ae71b455 --- /dev/null +++ b/plugins/flashing/src/main/resources/i18n/flashing_i18n_ru_RU.properties @@ -0,0 +1,6 @@ +title.flashing = Мигание в панели задач + +flashing.enable = &Включить мигание в панели задач +flashing.type = &Тип +flashing.type.continuous = Ðепрерывно +flashing.type.temporary = Временно diff --git a/plugins/flashing/src/main/resources/i18n/flashing_i18n_zh_CN.properties b/plugins/flashing/src/main/resources/i18n/flashing_i18n_zh_CN.properties new file mode 100644 index 000000000..d5f247892 --- /dev/null +++ b/plugins/flashing/src/main/resources/i18n/flashing_i18n_zh_CN.properties @@ -0,0 +1,8 @@ +#Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net) + +flashing.enable = å…许任务æ é—ªåЍ +flashing.type = 类型 +flashing.type.continuous = æŒç»­ +flashing.type.temporary = 临时 + +title.flashing = 任务æ é—ªåЍ diff --git a/plugins/flashing/src/main/resources/i18n/flashing_i18n_zh_TW.properties b/plugins/flashing/src/main/resources/i18n/flashing_i18n_zh_TW.properties new file mode 100644 index 000000000..acb1c02f0 --- /dev/null +++ b/plugins/flashing/src/main/resources/i18n/flashing_i18n_zh_TW.properties @@ -0,0 +1,6 @@ +title.flashing = 工具列閃動 + +flashing.enable = 啟動工具列閃動 +flashing.type = 閃動類型 +flashing.type.continuous = æŒçºŒé–ƒå‹• +flashing.type.temporary = 臨時閃動 diff --git a/plugins/flashing/src/main/resources/lightning.png b/plugins/flashing/src/main/resources/lightning.png new file mode 100644 index 000000000..41331fe2d Binary files /dev/null and b/plugins/flashing/src/main/resources/lightning.png differ diff --git a/src/plugins/flashing/resources/lightning16.png b/plugins/flashing/src/main/resources/lightning16.png similarity index 100% rename from src/plugins/flashing/resources/lightning16.png rename to plugins/flashing/src/main/resources/lightning16.png diff --git a/plugins/growl/pom.xml b/plugins/growl/pom.xml new file mode 100644 index 000000000..3b98c7637 --- /dev/null +++ b/plugins/growl/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + growl + 2.4 + + Growl + Provides Growl notifications (see http://growl.info). + + + + Wolf Posdorfer + 9posdorf@informatik.uni-hamburg.de + + Author + + + + + + + com.google.code.jgntp + jgntp + 1.2.1 + + + + diff --git a/plugins/growl/src/main/java/com/jivesoftware/spark/plugin/growl/GrowlMessageListener.java b/plugins/growl/src/main/java/com/jivesoftware/spark/plugin/growl/GrowlMessageListener.java new file mode 100644 index 000000000..9f3a8012e --- /dev/null +++ b/plugins/growl/src/main/java/com/jivesoftware/spark/plugin/growl/GrowlMessageListener.java @@ -0,0 +1,91 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jivesoftware.spark.plugin.growl; + +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.ChatFrame; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.GlobalMessageListener; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.parts.Localpart; + +import javax.swing.*; +import java.util.Objects; + +/** + * {@link GrowlMessageListener} implements the {@link GlobalMessageListener} and + * creates Growl Notifications on Message received + * + * @author Wolf.Posdorfer + */ +public class GrowlMessageListener implements GlobalMessageListener +{ + private final GrowlTalker talker; + + public GrowlMessageListener( GrowlTalker talker ) + { + this.talker = Objects.requireNonNull(talker); + } + + public void messageReceived( final ChatRoom chatRoom, final Message message ) + { + SwingUtilities.invokeLater( () -> + { + final ChatFrame chatFrame = SparkManager.getChatManager().getChatContainer().getChatFrame(); + + if ( !chatFrame.isInFocus() ) + { + showGrowlNotification( message ); + } + } ); + + } + + /** + * Show a global Growl Notification + * + * @param message + * , {@link Message} containing Body and Sender + */ + private void showGrowlNotification( Message message ) + { + try + { + String name = SparkManager.getUserManager().getUserNicknameFromJID( message.getFrom().asBareJid() ); + Jid jid = message.getFrom(); + + if ( name == null ) + { + Localpart localpart = message.getFrom().getLocalpartOrNull(); + if (localpart != null) { + name = localpart.toString(); + } + } + + talker.sendNotificationWithCallback( name, message.getBody(), jid.toString() ); + } + catch ( Exception e ) + { + Log.error( e.getMessage(), e ); + } + + } + + public void messageSent( ChatRoom room, Message message ) + {} +} diff --git a/plugins/growl/src/main/java/com/jivesoftware/spark/plugin/growl/GrowlPlugin.java b/plugins/growl/src/main/java/com/jivesoftware/spark/plugin/growl/GrowlPlugin.java new file mode 100644 index 000000000..82fde840f --- /dev/null +++ b/plugins/growl/src/main/java/com/jivesoftware/spark/plugin/growl/GrowlPlugin.java @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jivesoftware.spark.plugin.growl; + +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.Plugin; + +/** + * Provides support for Growl Notifications on Mac OS X. Growl can be acquired + * at http://growl.info + * + * + * @author Wolf.Posdorfer + */ +public class GrowlPlugin implements Plugin +{ + private GrowlMessageListener growlListener; + private GrowlTalker growlTalker; + + public synchronized void initialize() + { + growlTalker = new GrowlTalker(); + growlTalker.init(); + growlListener = new GrowlMessageListener( growlTalker ); + SparkManager.getChatManager().addGlobalMessageListener( growlListener ); + } + + public synchronized void shutdown() + { + SparkManager.getChatManager().removeGlobalMessageListener( growlListener ); + growlTalker.destroy(); + } + + public boolean canShutDown() + { + return true; + } + + public synchronized void uninstall() + { + shutdown(); + } +} diff --git a/plugins/growl/src/main/java/com/jivesoftware/spark/plugin/growl/GrowlTalker.java b/plugins/growl/src/main/java/com/jivesoftware/spark/plugin/growl/GrowlTalker.java new file mode 100644 index 000000000..34efe204a --- /dev/null +++ b/plugins/growl/src/main/java/com/jivesoftware/spark/plugin/growl/GrowlTalker.java @@ -0,0 +1,159 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jivesoftware.spark.plugin.growl; + +import com.google.code.jgntp.*; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.impl.JidCreate; + +import static java.util.concurrent.TimeUnit.SECONDS; + +/** + * GrowlTalker Class to send Messages to the GrowlInstance + * + * @author Wolf.Posdorfer + * @author Guus der Kinderen, guus@gmail.com + */ +public class GrowlTalker implements GntpListener +{ + private final GntpApplicationInfo info; + + private GntpClient client = null; + + public GrowlTalker() + { + info = Gntp.appInfo( "Spark" ).build(); + } + + public synchronized void init() + { + Log.debug( "Initializing..." ); + if ( client != null ) + { + Log.warning( "Already initialized before! Destroying previous instance before re-initializing..." ); + destroy(); + } + + client = Gntp.client( info ) + .listener( this ) + .build(); + } + + public synchronized void destroy() + { + Log.debug( "Tearing down..." ); + if ( client != null ) + { + try + { + client.shutdown( 5, SECONDS ); + } + catch ( InterruptedException e ) + { + Log.warning( "An interruption occurred while shutting down.", e ); + } + client = null; + } + } + + /** + * Sends a notification with a CallBackContext + * + * @param title + * the title to display + * @param body + * the body to display + * @param callbackContext + * a callback context + */ + public void sendNotificationWithCallback( String title, String body, String callbackContext ) + { + final GntpNotificationInfo notificationInfo = Gntp.notificationInfo( info, "Notification" ).build(); + final GntpNotification notification = Gntp.notification( notificationInfo, title ) + .text( body ) + .withCallback() + .context( callbackContext ) + .build(); + + try + { + final boolean wasShown = client.notify( notification, 5, SECONDS ); + if (!wasShown ) + { + Log.warning( "Notification did not show within the configured time-out: " + notification ); + } + } + catch ( Exception e ) + { + Log.warning( "An exception occurred while trying to send a notification: " + notification, e ); + } + } + + @Override + public void onRegistrationSuccess() + { + Log.debug( "Registration success." ); + } + + @Override + public void onNotificationSuccess( GntpNotification notification ) + { + Log.debug( "Notification success." ); + } + + @Override + public void onClickCallback( GntpNotification notification ) + { + Log.debug( "Callback clicked: " + notification ); + final EntityBareJid jid = JidCreate.entityBareFromOrThrowUnchecked( (String) notification.getContext() ); + final ChatRoom room = SparkManager.getChatManager().getChatRoom(jid); + SparkManager.getChatManager().getChatContainer().activateChatRoom( room ); + SparkManager.getChatManager().getChatContainer().requestFocusInWindow(); + } + + @Override + public void onCloseCallback( GntpNotification notification ) + { + Log.debug( "Callback closed: " + notification ); + } + + @Override + public void onTimeoutCallback( GntpNotification notification ) + { + Log.debug( "Callback timed out: " + notification ); + } + + @Override + public void onRegistrationError( GntpErrorStatus status, String description ) + { + Log.error( "Registration error: " + description + " (status: " + status + ")" ); + } + + @Override + public void onNotificationError( GntpNotification notification, GntpErrorStatus status, String description ) + { + Log.error( "Notification error: " + description + " (status: " + status + ") for notification: " + notification ); + } + + @Override + public void onCommunicationError( Throwable t ) + { + Log.error( "Communication error.", t ); + } +} diff --git a/plugins/growl/src/main/plugin-metadata/plugin.xml b/plugins/growl/src/main/plugin-metadata/plugin.xml new file mode 100644 index 000000000..581f958c6 --- /dev/null +++ b/plugins/growl/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,12 @@ + + ${project.name} + ${project.version} + ${project.description} + Wolf Posdorfer + https://IgniteRealtime.org + support@IgniteRealtime.org + com.jivesoftware.spark.plugin.growl.GrowlPlugin + 3.1.0 + Mac + 11 + diff --git a/plugins/jingle/pom.xml b/plugins/jingle/pom.xml new file mode 100644 index 000000000..953922b7b --- /dev/null +++ b/plugins/jingle/pom.xml @@ -0,0 +1,50 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + jingle + 2.0.0 + + Jingle Client + Support of audio calls. + + + + Jive Software + spark@jivesoftware.com + + Author + + + + + + + org.igniterealtime.smack + smack-jingle-old + ${dependency.smack.version} + + + org.igniterealtime.smack + smack-extensions + + + org.igniterealtime.smack + smack-core + + + + + org.igniterealtime.spark + phone + 2.0.0 + + + diff --git a/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/CallPanelButton.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/CallPanelButton.java new file mode 100644 index 000000000..c7b9394da --- /dev/null +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/CallPanelButton.java @@ -0,0 +1,142 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.jingle; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Insets; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import javax.swing.Icon; +import javax.swing.JButton; + +public class CallPanelButton extends JButton implements MouseListener { + + private static final long serialVersionUID = -2299269454442767625L; + private final Icon normalIcon; + private final Icon hoverIcon; + private final Icon downIcon; + private final Image backgroundImage; + private final String text; + + private boolean selected; + + public CallPanelButton(Image image, String text) { + super(); + this.text = text; + + normalIcon = JinglePhoneRes.getImageIcon("CALLPANEL_BIG_BUTTON"); + hoverIcon = JinglePhoneRes.getImageIcon("CALLPANEL_BIG_BUTTON_HOVER"); + downIcon = JinglePhoneRes.getImageIcon("CALLPANEL_BIG_BUTTON_DOWN"); + backgroundImage = image; + + setIcon(normalIcon); + decorate(); + addMouseListener(this); + setDisabledIcon(normalIcon); + } + + /** + * Decorates the button with the approriate UI configurations. + */ + private void decorate() { + setBorderPainted(false); + setOpaque(true); + + setContentAreaFilled(false); + setMargin(new Insets(0, 0, 0, 0)); + } + + + @Override + public void mouseClicked(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + setIcon(downIcon); + } + + @Override + public void mouseReleased(MouseEvent e) { + if (!selected) { + setIcon(normalIcon); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + if (!selected) { + setIcon(hoverIcon); + } + setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + if (!selected) { + setIcon(normalIcon); + } + setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + + public void setButtonSelected(boolean selected) { + this.selected = selected; + if (selected) { + setIcon(downIcon); + } else { + setIcon(normalIcon); + } + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + int width = getWidth(); + int height = getHeight(); + + int x = (width - backgroundImage.getWidth(null)) / 2; + int y = (height - backgroundImage.getHeight(null)) / 2; + g.drawImage(backgroundImage, x, y - 5, null); + + if (isEnabled()) { + g.setColor(Color.black); + } else { + g.setColor(Color.lightGray); + } + g.setFont(new Font("Dialog", Font.PLAIN, 11)); + + int stringWidth = g.getFontMetrics().stringWidth(text); + x = (width - stringWidth) / 2; + y = height - 12; + g.drawString(text, x, y); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + if (!enabled) { + removeMouseListener(this); + } else { + addMouseListener(this); + } + } +} + diff --git a/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/ControlPanel.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/ControlPanel.java new file mode 100644 index 000000000..f11d606ed --- /dev/null +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/ControlPanel.java @@ -0,0 +1,51 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.jingle; + +import javax.swing.JPanel; +import javax.swing.BorderFactory; + +import java.awt.Color; +import java.awt.LayoutManager; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GradientPaint; +import java.awt.image.BufferedImage; + +public class ControlPanel extends JPanel { + + private static final long serialVersionUID = -6406576262620829080L; + + public ControlPanel() { + setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230))); + } + + public ControlPanel(LayoutManager layout) { + super(layout); + setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230))); + } + + @Override + public void paintComponent(Graphics g) { + final BufferedImage bufferedImage = new BufferedImage(2, getHeight(), BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = bufferedImage.createGraphics(); + GradientPaint paint = new GradientPaint(0, 0, Color.white, 0, getHeight(), new Color(235, 241, 246), true); + g2d.setPaint(paint); + g2d.fillRect(0, 0, getWidth(), getHeight()); + g2d.dispose(); + g.drawImage(bufferedImage, 0, 0, getWidth(), getHeight(), null); + } +} diff --git a/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/GenericNotification.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/GenericNotification.java new file mode 100644 index 000000000..090735acf --- /dev/null +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/GenericNotification.java @@ -0,0 +1,99 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.jingle; + +import org.jivesoftware.spark.component.FileDragLabel; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; + +import static java.awt.GridBagConstraints.NONE; +import static java.awt.GridBagConstraints.NORTHWEST; + +/** + * UI for simple chat room notifications with Jingle. + */ +public class GenericNotification extends JPanel { + + private static final long serialVersionUID = -90291335105747619L; + private final FileDragLabel imageLabel = new FileDragLabel(); + private final JLabel titleLabel = new JLabel(); + + /** + * Creates a generic notification panel. + * + * @param title the title of the notification. + * @param icon the icon to use in the notification. + */ + public GenericNotification(String title, Icon icon) { + setLayout(new GridBagLayout()); + setBackground(new Color(250, 249, 242)); + Insets insets = new Insets(5, 5, 5, 5); + add(imageLabel, new GridBagConstraints(0, 0, 1, 3, 0, 0, NORTHWEST, NONE, insets, 0, 0)); + add(titleLabel, new GridBagConstraints(1, 0, 2, 1, 1, 0, NORTHWEST, NONE, insets, 0, 0)); + titleLabel.setFont(new Font("Dialog", Font.BOLD, 11)); + titleLabel.setForeground(new Color(211, 174, 102)); + + setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.white)); + + titleLabel.setText(title); + imageLabel.setIcon(icon); + } + + /** + * Sets the title of the notification. + * + * @param title the title. + */ + public void setTitle(String title) { + titleLabel.setText(title); + } + + /** + * Sets the icon. + * + * @param icon the icon. + */ + public void setIcon(Icon icon) { + imageLabel.setIcon(icon); + } + + + /** + * Changes the background color. If the alert is true, + * the background will reflect that the UI needs attention. + * + * @param alert true to notify users that their attention is needed. + */ + public void showAlert(boolean alert) { + if (alert) { + titleLabel.setForeground(new Color(211, 174, 102)); + setBackground(new Color(250, 249, 242)); + } else { + setBackground(new Color(239, 245, 250)); + titleLabel.setForeground(new Color(65, 139, 179)); + } + } + +} diff --git a/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/IncomingCall.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/IncomingCall.java new file mode 100644 index 000000000..e3b7b3df4 --- /dev/null +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/IncomingCall.java @@ -0,0 +1,297 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.jingle; + +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.jingleold.JingleSession; +import org.jivesoftware.smackx.jingleold.JingleSessionRequest; +import org.jivesoftware.smackx.jingleold.listeners.JingleSessionListener; +import org.jivesoftware.smackx.jingleold.media.PayloadType; +import org.jivesoftware.smackx.jingleold.nat.TransportCandidate; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.phone.PhoneManager; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomClosingListener; +import org.jivesoftware.spark.util.SwingTimerTask; +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; + +import javax.swing.*; +import java.awt.*; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.TimerTask; + +import static org.jivesoftware.spark.plugin.jingle.Ringing.*; + +/** + * Incoming call handles a single incoming Jingle call. + */ +public class IncomingCall implements JingleSessionListener, ChatRoomClosingListener { + + private static final long WAIT_FOR_MEDIA_DELAY = 20000; + private SparkToaster toasterManager; + private ChatRoom chatRoom; + private final Map callMap = new HashMap<>(); + private final GenericNotification notificationUI; + private JingleSession session; + private boolean established = false; + private boolean mediaReceived = false; + private TimerTask mediaReceivedTask; + + /** + * Initializes a new IncomingCall with the required JingleSession. + * + * @param request the JingleSessionRequest + */ + public IncomingCall(final JingleSessionRequest request) { + notificationUI = new GenericNotification(JingleResources.getString("label.establishing.call"), SparkRes.getImageIcon(SparkRes.Icons.BUSY_IMAGE)); + // Accept the request + try { + session = request.accept(); + } catch (Exception e) { + Log.error(e); + return; + } + session.addListener(this); + showIncomingCall(request); + } + + /** + * Appends the JingleRoom to the ChatRoom. + */ + private void showCallAnsweredState() { + SwingUtilities.invokeLater(() -> { + final SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy h:mm a"); + notificationUI.setTitle("Voice chat started on " + formatter.format(new Date())); + notificationUI.showAlert(false); + notificationUI.setIcon(null); + + stopRinging(); + + final JingleRoom roomUI = new JingleRoom(session, chatRoom); + Insets insets = new Insets(5, 5, 5, 5); + chatRoom.getChatPanel().add(roomUI, new GridBagConstraints(1, 1, 1, 1, 0.05, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, insets, 0, 0)); + chatRoom.getChatPanel().invalidate(); + chatRoom.getChatPanel().validate(); + chatRoom.getChatPanel().repaint(); + callMap.put(chatRoom, roomUI); + + // Add state + JingleStateManager.getInstance().addJingleSession(chatRoom, JingleStateManager.JingleRoomState.inJingleCall); + + // Notify state change + SparkManager.getChatManager().notifySparkTabHandlers(chatRoom); + }); + } + + /** + * Removes the JingleRoom from the ChatRoom. + */ + private void showCallEndedState(final String reason) { + SwingUtilities.invokeLater(() -> { + stopRinging(); + + notificationUI.setTitle(reason); + notificationUI.setIcon(null); + notificationUI.showAlert(false); + + // Remove JingleRoom from ChatRoom if present + if (chatRoom != null) { + JingleRoom room = callMap.get(chatRoom); + if (room != null) { + chatRoom.getChatPanel().remove(room); + } + + callMap.remove(chatRoom); + chatRoom.getChatPanel().invalidate(); + chatRoom.getChatPanel().validate(); + chatRoom.getChatPanel().repaint(); + } + // Add state + JingleStateManager.getInstance().removeJingleSession(chatRoom); + // Notify state change + SparkManager.getChatManager().notifySparkTabHandlers(chatRoom); + }); + } + + /** + * Called if an incoming Jingle Session is rejected. + */ + public void rejectIncomingCall() { + // Close toaster if it's up. + if (toasterManager != null) { + toasterManager.close(); + } + + if (session != null) { + try { + session.terminate(); + session = null; + } catch (Exception e) { + Log.error(e); + } + } + + stopRinging(); + } + + /** + * Returns the JingleSession associated with this incoming call. + * + * @return the session. + */ + public JingleSession getSession() { + return session; + } + + private void notifyRoom() { + notificationUI.showAlert(true); + chatRoom.getTranscriptWindow().addComponent(notificationUI); + } + + /** + * Notifies user of an incoming call. The UI allows for users to either accept or reject + * the incoming session. + * + * @param request the JingleSession. + */ + private void showIncomingCall(final JingleSessionRequest request) { + toasterManager = new SparkToaster(); + toasterManager.setHidable(false); + + final IncomingCallUI incomingCall = new IncomingCallUI(request.getFrom()); + toasterManager.setToasterHeight(175); + toasterManager.setToasterWidth(300); + toasterManager.setDisplayTime(500000000); + + toasterManager.showToaster("Incoming Voice Chat", incomingCall); + toasterManager.hideTitle(); + + incomingCall.getAcceptButton().addActionListener(e -> acceptSession(request)); + + incomingCall.getRejectButton().addActionListener(e -> rejectIncomingCall()); + + startRinging(); + + // End after 30 seconds max. + TimerTask endTask = new SwingTimerTask() { + @Override + public void doRun() { + if (!session.isFullyEstablished()) { + rejectIncomingCall(); + } + } + }; + + TaskEngine.getInstance().schedule(endTask, 30000); + } + + /** + * Accepts a JingleSessionRequest. + * + * @param request the request. + */ + private void acceptSession(JingleSessionRequest request) { + toasterManager.close(); + + stopRinging(); + + // Start the call + session.startIncoming(); + + if (chatRoom == null) { + chatRoom = SparkManager.getChatManager().getChatRoom(request.getFrom().asEntityBareJidOrThrow()); + SparkManager.getChatManager().getChatContainer().activateChatRoom(chatRoom); + SparkManager.getChatManager().getChatContainer().getChatFrame().toFront(); + notifyRoom(); + } + } + + @Override + public void sessionMediaReceived(JingleSession jingleSession, String participant) { + mediaReceived = true; + TaskEngine.getInstance().cancelScheduledTask(mediaReceivedTask); + showCallAnsweredState(); + } + + @Override + public void sessionEstablished(PayloadType payloadType, TransportCandidate transportCandidate, TransportCandidate transportCandidate1, JingleSession jingleSession) { + + established = true; + mediaReceivedTask = new SwingTimerTask() { + @Override + public void doRun() { + if (!mediaReceived) { + if (session != null) { + try { + session.terminate("No Media Received. This may be caused by firewall configuration problems."); + } catch (Exception e) { + Log.error(e); + } + } + } + } + }; + TaskEngine.getInstance().schedule(mediaReceivedTask, WAIT_FOR_MEDIA_DELAY, WAIT_FOR_MEDIA_DELAY); + } + + @Override + public void sessionDeclined(String string, JingleSession jingleSession) { + showCallEndedState("Voice chat was rejected"); + } + + @Override + public void sessionRedirected(String string, JingleSession jingleSession) { + } + + @Override + public void sessionClosed(String string, JingleSession jingleSession) { + if (established && mediaReceived) { + final SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy h:mm a"); + showCallEndedState("Voice chat ended on " + formatter.format(new Date())); + } else { + showCallEndedState("Voice chat ended: " + string); + } + if (PhoneManager.isUseStaticLocator() && PhoneManager.isUsingMediaLocator()) { + PhoneManager.setUsingMediaLocator(false); + } + } + + @Override + public void sessionClosedOnError(XMPPException xmppException, JingleSession jingleSession) { + showCallEndedState("Voice chat ended due an error: " + xmppException.getMessage()); + if (PhoneManager.isUseStaticLocator() && PhoneManager.isUsingMediaLocator()) { + PhoneManager.setUsingMediaLocator(false); + } + } + + @Override + public void closing() { + if (session != null) { + try { + session.terminate(); + } catch (Exception e) { + Log.error(e); + } + } + JingleStateManager.getInstance().removeJingleSession(chatRoom); + } +} diff --git a/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/IncomingCallUI.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/IncomingCallUI.java new file mode 100644 index 000000000..ab6366b89 --- /dev/null +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/IncomingCallUI.java @@ -0,0 +1,225 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.jingle; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.image.BufferedImage; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smackx.vcardtemp.packet.VCard; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.util.XmppStringUtils; + +import static java.awt.GridBagConstraints.*; +import static java.awt.GridBagConstraints.BOTH; +import static java.awt.GridBagConstraints.CENTER; +import static java.awt.GridBagConstraints.HORIZONTAL; +import static java.awt.GridBagConstraints.NORTHWEST; + +public class IncomingCallUI extends JPanel { + private static final long serialVersionUID = -7758898282948774412L; + private final JLabel avatarLabel = new JLabel(); + private final JLabel titleLabel = new JLabel(); + private final JLabel professionLabel = new JLabel(); + + private RolloverButton acceptButton; + private RolloverButton rejectButton; + + private final VCard vcard; + private final BareJid jid; + + + public IncomingCallUI(Jid jidAddr) { + setLayout(new GridBagLayout()); + jid = jidAddr.asBareJid(); + vcard = SparkManager.getVCardManager().getVCardFromMemory(jid); + + final JLabel topLabel = new JLabel(); + topLabel.setIcon(JinglePhoneRes.getImageIcon("INCOMING_CALL_IMAGE")); + topLabel.setHorizontalTextPosition(JLabel.RIGHT); + topLabel.setFont(new Font("Dialog", Font.BOLD, 15)); + topLabel.setText(JingleResources.getString("label.voice.request.from")); + topLabel.setForeground(Color.DARK_GRAY); + // Add Top Label + add(topLabel, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, CENTER, HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + // Add Caller Block + buildCallerBlock(); + // Add Buttons + addButtons(); + } + + /** + * Builds the part of the incoming call UI with the Callers information. + */ + private void buildCallerBlock() { + final JPanel panel = new JPanel(new GridBagLayout()); + panel.setBackground(Color.white); + panel.setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230), 1)); + + // Add Avatar + panel.add(avatarLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 1.0, NORTHWEST, NONE, new Insets(5, 0, 5, 0), 0, 0)); + + // Add Avatar information + panel.add(titleLabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, NORTHWEST, HORIZONTAL, new Insets(5, 5, 0, 0), 0, 0)); + panel.add(professionLabel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, NORTHWEST, HORIZONTAL, new Insets(0, 7, 0, 0), 0, 0)); + + // Add History labels + // panel.add(lastCalledLabel, new GridBagConstraints(0, 3, 2, 1, 0.0, 0.0, NORTHWEST, HORIZONTAL, new Insets(15, 5, 0, 0), 0, 0)); + // panel.add(durationLabel, new GridBagConstraints(0, 4, 2, 1, 0.0, 0.0, NORTHWEST, HORIZONTAL, new Insets(5, 5, 0, 0), 0, 0)); + + // Set default settings + titleLabel.setForeground(new Color(64, 103, 162)); + titleLabel.setFont(new Font("Dialog", Font.BOLD, 16)); + + if (vcard != null) { + handleVCardInformation(vcard); + } else { + updateWithGenericInfo(); + } + + // Add to panel + Insets insets = new Insets(5, 5, 5, 5); + add(panel, new GridBagConstraints(0, 1, 1, 1, 1, 1, 18, BOTH, insets, 0, 0)); + } + + private void addButtons() { + // Build Accept Button + acceptButton = new RolloverButton(" " + JingleResources.getString("button.accept"), JinglePhoneRes.getImageIcon("TOASTER_ACCEPT_BUTTON")); + acceptButton.setHorizontalTextPosition(JLabel.CENTER); + acceptButton.setFont(new Font("Dialog", Font.BOLD, 11)); + acceptButton.setForeground(new Color(91, 175, 41)); + acceptButton.setMargin(new Insets(0, 0, 0, 0)); + + // Build Reject Button + rejectButton = new RolloverButton(" " + JingleResources.getString("button.accept"), JinglePhoneRes.getImageIcon("TOASTER_REJECT_BUTTON")); + rejectButton.setHorizontalTextPosition(JLabel.CENTER); + rejectButton.setFont(new Font("Dialog", Font.BOLD, 11)); + rejectButton.setForeground(new Color(153, 32, 10)); + rejectButton.setMargin(new Insets(0, 0, 0, 0)); + + final JPanel panel = new JPanel(new GridBagLayout()); + panel.setOpaque(false); + Insets insets = new Insets(5, 5, 5, 5); + panel.add(acceptButton, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, EAST, NONE, insets, 0, 0)); + panel.add(rejectButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, WEST, NONE, insets, 0, 0)); + + add(panel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, CENTER, NONE, insets, 0, 0)); + } + + private void updateWithGenericInfo() { + String title = SparkManager.getUserManager().getUserNicknameFromJID(jid); + Icon icon = PresenceManager.getIconFromPresence(PresenceManager.getPresence(jid)); + + titleLabel.setText(title); + titleLabel.setIcon(icon); + + avatarLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icons.DEFAULT_AVATAR_64x64_IMAGE)); + avatarLabel.invalidate(); + avatarLabel.validate(); + avatarLabel.repaint(); + + invalidate(); + validate(); + repaint(); + } + + private void handleVCardInformation(VCard vcard) { + if (vcard.getError() != null) { + updateWithGenericInfo(); + return; + } + // Nickname label should show presence and nickname. + String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid); + + String firstName = vcard.getFirstName(); + String lastName = vcard.getLastName(); + if (ModelUtil.hasLength(firstName) && ModelUtil.hasLength(lastName)) { + titleLabel.setText(firstName + " " + lastName); + } else if (ModelUtil.hasLength(firstName)) { + titleLabel.setText(firstName); + } else { + titleLabel.setText(nickname); + } + Icon icon = PresenceManager.getIconFromPresence(PresenceManager.getPresence(jid)); + titleLabel.setIcon(icon); + String jobTitle = vcard.getField("TITLE"); + if (jobTitle != null) { + professionLabel.setText(jobTitle); + } + + byte[] avatarBytes = null; + try { + avatarBytes = vcard.getAvatar(); + } catch (Exception e) { + Log.error("Cannot retrieve avatar bytes.", e); + } + + if (avatarBytes != null) { + try { + ImageIcon avatarIcon = new ImageIcon(avatarBytes); + avatarLabel.setIcon(avatarIcon); + avatarLabel.invalidate(); + avatarLabel.validate(); + avatarLabel.repaint(); + } catch (Exception e) { + Log.warning("Unable to generate image from avatar", e); + } + } + invalidate(); + validate(); + repaint(); + } + + public RolloverButton getAcceptButton() { + return acceptButton; + } + + public RolloverButton getRejectButton() { + return rejectButton; + } + + @Override + public void paintComponent(Graphics g) { + BufferedImage cache = new BufferedImage(2, getHeight(), BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = cache.createGraphics(); + GradientPaint paint = new GradientPaint(0, 0, new Color(233, 240, 247), 0, getHeight(), Color.white, true); + g2d.setPaint(paint); + g2d.fillRect(0, 0, getWidth(), getHeight()); + g2d.dispose(); + g.drawImage(cache, 0, 0, getWidth(), getHeight(), null); + } +} + diff --git a/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JavaMixer.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JavaMixer.java new file mode 100644 index 000000000..3c3f07a75 --- /dev/null +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JavaMixer.java @@ -0,0 +1,455 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.jingle; + +import org.jivesoftware.spark.util.log.Log; + +import javax.sound.sampled.*; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeNode; +import javax.swing.*; +import javax.swing.border.TitledBorder; +import javax.swing.border.EtchedBorder; +import java.util.List; +import java.util.ArrayList; +import java.util.Enumeration; +import java.awt.*; + +/** + * Pure Java Audio Mixer. Control Volume and Settings for any Sound device in the OS. + * + * @author Thiago Camargo + */ + +public class JavaMixer { + + private static final Line.Info[] EMPTY_PORT_INFO_ARRAY = new Line.Info[0]; + DefaultMutableTreeNode root = new DefaultMutableTreeNode("Sound Mixers", true); + JTree tree = new JTree(root); + + public JavaMixer() { + List portMixers = getPortMixers(); + if (portMixers.isEmpty()) { + Log.warning("No Mixers Found."); + } + for (Mixer mixer : portMixers) { + JavaMixer.MixerNode mixerNode = new JavaMixer.MixerNode(mixer); + createMixerChildren(mixerNode); + root.add(mixerNode); + } + } + + /** + * Returns whether the type of a FloatControl is BALANCE or PAN. + * + * @param control FloatControl control + * @return boolean is Balance or Pan + */ + private static boolean isBalanceOrPan(FloatControl control) { + Control.Type type = control.getType(); + return type.equals(FloatControl.Type.PAN) || type.equals(FloatControl.Type.BALANCE); + } + + public static void main(String[] args) { + final JavaMixer sm = new JavaMixer(); + final JFrame jf = new JFrame("Mixer Test"); + final JPanel jp = new JPanel(); + jf.add(jp); + jp.add(sm.getTree()); + jf.setSize(600, 500); + jf.setVisible(true); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + sm.getTree().addTreeSelectionListener(e -> { + TreePath path = e.getPath(); + if (path.getLastPathComponent() instanceof ControlNode) { + ControlNode controlNode = (ControlNode) path.getLastPathComponent(); + if (!(controlNode.getControl() instanceof CompoundControl)) { + if (jp.getComponentCount() > 1) { + jp.remove(1); + } + jp.add(controlNode.getComponent(), 1); + jp.repaint(); + } + } + }); + jp.add(sm.getPreferredMasterVolume()); + jp.add(sm.getPreferredMasterVolume()); + jp.add(sm.getPrefferedInputVolume()); + jp.repaint(); + sm.setMicrophoneInput(); + sm.setMuteForMicrophoneOutput(); + } + + public JTree getTree() { + return tree; + } + + public Component getPreferredMasterVolume() { + TreePath path = findByName(new TreePath(root), new String[]{"SPEAKER", "Volume"}); + if (path == null) { + path = findByName(new TreePath(root), new String[]{"Master target", "Master", "Mute"}); + } + if (path != null) { + if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) { + return ((ControlNode) path.getLastPathComponent()).getComponent(); + } + } + return null; + } + + public Component getPrefferedInputVolume() { + TreePath path = findByName(new TreePath(root), new String[]{"MICROPHONE", "Volume"}); + + if (path == null) { + path = findByName(new TreePath(root), new String[]{"Capture source", "Capture", "Volume"}); + } + + if (path != null) { + if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) + return ((JavaMixer.ControlNode) path.getLastPathComponent()).getComponent(); + } + return null; + } + + public void setMicrophoneInput() { + TreePath path = findByName(new TreePath(root), new String[]{"MICROPHONE", "Select"}); + if (path == null) { + path = findByName(new TreePath(root), new String[]{"Capture source", "Capture", "Mute"}); + } + if (path != null) { + if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) { + BooleanControl bControl = (BooleanControl) (((JavaMixer.ControlNode) path.getLastPathComponent()).getControl()); + bControl.setValue(true); + } + } + } + + public void setMuteForMicrophoneOutput() { + TreePath path = findByName(new TreePath(root), new String[]{"SPEAKER", "Microfone", "Mute"}); + if (path == null) { + path = findByName(new TreePath(root), new String[]{"MIC target", "mic", "Mute"}); + } + + if (path != null) { + if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) { + BooleanControl bControl = (BooleanControl) (((JavaMixer.ControlNode) path.getLastPathComponent()).getControl()); + bControl.setValue(true); + } + } + } + + /** + * Returns the Mixers that support Port lines. + * + * @return List Port Mixers + */ + private List getPortMixers() { + List supportingMixers = new ArrayList<>(); + Mixer.Info[] aMixerInfos = AudioSystem.getMixerInfo(); + for (Mixer.Info aMixerInfo : aMixerInfos) { + Mixer mixer = AudioSystem.getMixer(aMixerInfo); + boolean bSupportsPorts = arePortsSupported(mixer); + if (bSupportsPorts) { + supportingMixers.add(mixer); + } + } + return supportingMixers; + } + + private boolean arePortsSupported(Mixer mixer) { + Line.Info[] infos = mixer.getSourceLineInfo(); + for (Line.Info info : infos) { + if (info instanceof Port.Info) { + return true; + } else if (info instanceof DataLine.Info) { + return true; + } + } + infos = mixer.getTargetLineInfo(); + for (Line.Info info : infos) { + if (info instanceof Port.Info) { + return true; + } else if (info instanceof DataLine.Info) { + return true; + } + } + return false; + } + + private void createMixerChildren(JavaMixer.MixerNode mixerNode) { + Mixer mixer = mixerNode.getMixer(); + Line.Info[] infosToCheck = getPortInfo(mixer); + for (Line.Info anInfosToCheck : infosToCheck) { + if (mixer.isLineSupported(anInfosToCheck)) { + Port port = null; + DataLine dLine = null; + + int maxLines = mixer.getMaxLines(anInfosToCheck); + // Workaround to prevent a JVM crash on Mac OS X (Intel) 1.5.0_07 JVM + if (maxLines > 0) { + try { + if (anInfosToCheck instanceof Port.Info) { + port = (Port) mixer.getLine(anInfosToCheck); + port.open(); + } else if (anInfosToCheck instanceof DataLine.Info) { + dLine = (DataLine) mixer.getLine(anInfosToCheck); + if (!dLine.isOpen()) { + dLine.open(); + } + } + } catch (LineUnavailableException e) { + Log.warning("Audio line unavailable: " + e.getMessage()); + } catch (Exception e) { + Log.error("Audio line: ", e); + } + } + if (port != null) { + JavaMixer.PortNode portNode = new JavaMixer.PortNode(port); + createPortChildren(portNode); + mixerNode.add(portNode); + } else if (dLine != null) { + JavaMixer.PortNode portNode = new JavaMixer.PortNode(dLine); + createPortChildren(portNode); + mixerNode.add(portNode); + } + } + } + } + + private Line.Info[] getPortInfo(Mixer mixer) { + Line.Info[] infos; + List portInfoList = new ArrayList<>(); + infos = mixer.getSourceLineInfo(); + for (Line.Info info : infos) { + if (info instanceof Port.Info || info instanceof DataLine.Info) { + portInfoList.add(info); + } + } + infos = mixer.getTargetLineInfo(); + for (Line.Info info1 : infos) { + if (info1 instanceof Port.Info || info1 instanceof DataLine.Info) { + portInfoList.add(info1); + } + } + return portInfoList.toArray(EMPTY_PORT_INFO_ARRAY); + } + + private void createPortChildren(JavaMixer.PortNode portNode) { + Control[] aControls = portNode.getPort().getControls(); + for (Control aControl : aControls) { + JavaMixer.ControlNode controlNode = new JavaMixer.ControlNode(aControl); + createControlChildren(controlNode); + portNode.add(controlNode); + } + } + + private void createControlChildren(JavaMixer.ControlNode controlNode) { + if (controlNode.getControl() instanceof CompoundControl) { + CompoundControl control = (CompoundControl) controlNode.getControl(); + Control[] aControls = control.getMemberControls(); + for (Control con : aControls) { + JavaMixer.ControlNode conNode = new JavaMixer.ControlNode(con); + createControlChildren(conNode); + controlNode.add(conNode); + } + } + } + + public TreePath find(TreePath path, Object[] nodes) { + return find2(path, nodes, 0, false); + } + + public TreePath findByName(TreePath path, String[] names) { + return find2(path, names, 0, true); + } + + private TreePath find2(TreePath parent, Object[] nodes, int depth, boolean byName) { + TreeNode node = (TreeNode) parent.getLastPathComponent(); + if (depth > nodes.length - 1) { + return parent; + } + + if (node.getChildCount() >= 0) { + for (Enumeration e = (Enumeration) node.children(); e.hasMoreElements(); ) { + TreeNode n = e.nextElement(); + TreePath path = parent.pathByAddingChild(n); + boolean find; + if (byName) { + find = n.toString().toUpperCase().contains(nodes[depth].toString().toUpperCase()); + } else { + find = n.equals(nodes[depth]); + } + + if (find) { + TreePath result = find2(path, nodes, depth + 1, byName); + if (result != null) { + return result; + } + } else { + TreePath result = find2(path, nodes, depth, byName); + if (result != null) { + return result; + } + } + } + } + + return null; + } + + public class MixerNode extends DefaultMutableTreeNode { + private static final long serialVersionUID = -987278469391244202L; + private final Mixer mixer; + + public MixerNode(Mixer mixer) { + super(mixer.getMixerInfo(), true); + this.mixer = mixer; + } + + public Mixer getMixer() { + return mixer; + } + + } + + public class PortNode extends DefaultMutableTreeNode { + + private static final long serialVersionUID = -7774055649714159518L; + private final Line port; + + public PortNode(Line port) { + super(port.getLineInfo(), true); + this.port = port; + } + + public Line getPort() { + return port; + } + + } + + public class ControlNode extends DefaultMutableTreeNode { + + private static final long serialVersionUID = 2014062750235264630L; + private final Control control; + private final Component component; + + public ControlNode(Control control) { + super(control.getType(), true); + this.control = control; + if (control instanceof BooleanControl) { + component = createControlComponent((BooleanControl) control); + } else if (control instanceof EnumControl) { + component = createControlComponent((EnumControl) control); + } else if (control instanceof FloatControl) { + component = createControlComponent((FloatControl) control); + } else { + component = null; + } + } + + public Control getControl() { + return control; + } + + public Component getComponent() { + return component; + } + + private JComponent createControlComponent(BooleanControl control) { + AbstractButton button; + String strControlName = control.getType().toString(); + ButtonModel model = new JavaMixer.BooleanControlButtonModel(control); + button = new JCheckBox(strControlName); + button.setModel(model); + return button; + } + + private JComponent createControlComponent(EnumControl control) { + JPanel component = new JPanel(); + String strControlName = control.getType().toString(); + component.setBorder(new TitledBorder(new EtchedBorder(), strControlName)); + return component; + } + + private JComponent createControlComponent(FloatControl control) { + int orientation = isBalanceOrPan(control) ? JSlider.HORIZONTAL : JSlider.VERTICAL; + BoundedRangeModel model = new JavaMixer.FloatControlBoundedRangeModel(control); + JSlider slider = new JSlider(model); + slider.setOrientation(orientation); + slider.setPaintLabels(true); + slider.setPaintTicks(true); + slider.setSize(10, 50); + return slider; + } + + } + + public class BooleanControlButtonModel extends DefaultButtonModel { + private static final long serialVersionUID = -4667054823378068382L; + private final BooleanControl control; + + public BooleanControlButtonModel(BooleanControl control) { + this.control = control; + this.addActionListener(e -> setSelected(!isSelected())); + } + + @Override + public boolean isSelected() { + return control.getValue(); + } + + @Override + public void setSelected(boolean bSelected) { + control.setValue(bSelected); + } + } + + public class FloatControlBoundedRangeModel extends DefaultBoundedRangeModel { + private static final long serialVersionUID = 4469386606588434901L; + private final FloatControl control; + private final float factor; + + public FloatControlBoundedRangeModel(FloatControl control) { + this.control = control; + float range = 100; + float steps = range / 100; + factor = range / steps; + int min = (int) (control.getMinimum() * factor); + int max = (int) (control.getMaximum() * factor); + int value = (int) (control.getValue() * factor); + setRangeProperties(value, 0, min, max, false); + } + + private float getScaleFactor() { + return factor; + } + + @Override + public int getValue() { + return (int) (control.getValue() * getScaleFactor()); + } + + @Override + public void setValue(int nValue) { + super.setValue(nValue); + control.setValue((float) nValue / getScaleFactor()); + } + + } +} diff --git a/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JinglePhoneRes.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JinglePhoneRes.java new file mode 100644 index 000000000..0f05ce955 --- /dev/null +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JinglePhoneRes.java @@ -0,0 +1,61 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.jingle; + +import javax.swing.*; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; +import java.net.URL; + +import org.jivesoftware.spark.util.log.Log; + +/** + * Use for Phone Res Internationalization. + * + * @author Derek DeMoro + */ +public enum JinglePhoneRes { + ; + static ClassLoader cl = JinglePhoneRes.class.getClassLoader(); + private static PropertyResourceBundle prb; + + static { + JinglePhoneRes.prb = (PropertyResourceBundle) ResourceBundle.getBundle("org/jivesoftware/spark/plugin/jingle/jingle"); + } + + public static String getString(String propertyName) { + return JinglePhoneRes.prb.getString(propertyName); + } + + public static ImageIcon getImageIcon(String imageName) { + try { + final String iconURI = JinglePhoneRes.getString(imageName); + final URL imageURL = JinglePhoneRes.cl.getResource(iconURI); + if (imageURL != null) { + return new ImageIcon(imageURL); + } else { + Log.warning(imageName + " not found."); + } + } catch (Exception e) { + Log.warning("Unable to load image " + imageName, e); + } + return null; + } + + public static URL getURL(String propertyName) { + return JinglePhoneRes.cl.getResource(JinglePhoneRes.getString(propertyName)); + } +} diff --git a/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JinglePlugin.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JinglePlugin.java new file mode 100644 index 000000000..f36a945ca --- /dev/null +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JinglePlugin.java @@ -0,0 +1,320 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.jingle; + +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.*; +import org.jivesoftware.smack.filter.StanzaTypeFilter; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; +import org.jivesoftware.smackx.disco.packet.DiscoverInfo; +import org.jivesoftware.smackx.jingleold.JingleManager; +import org.jivesoftware.smackx.jingleold.JingleSession; +import org.jivesoftware.smackx.jingleold.JingleSessionRequest; +import org.jivesoftware.smackx.jingleold.media.JingleMediaManager; +import org.jivesoftware.smackx.jingleold.mediaimpl.jmf.JmfMediaManager; +import org.jivesoftware.smackx.jingleold.mediaimpl.jspeex.SpeexMediaManager; +import org.jivesoftware.smackx.jingleold.nat.BridgedTransportManager; +import org.jivesoftware.smackx.jingleold.nat.ICETransportManager; +import org.jivesoftware.smackx.jingleold.nat.JingleTransportManager; +import org.jivesoftware.smackx.jingleold.nat.STUN; +import org.jivesoftware.spark.PresenceManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.phone.Phone; +import org.jivesoftware.spark.phone.PhoneManager; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.TranscriptWindow; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.gateways.transports.TransportUtils; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.EntityFullJid; +import org.jxmpp.jid.Jid; + +import javax.swing.*; +import javax.swing.text.BadLocationException; +import javax.swing.text.Style; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; +import java.awt.event.ActionEvent; +import java.util.*; + + +/** + * A simple Jingle Plugin for Spark that uses server Media Proxy for the transport and NAT Traversal + */ +public class JinglePlugin implements Plugin, Phone, ConnectionListener { + + private static final String JINGLE_NAMESPACE = "http://www.xmpp.org/extensions/xep-0166.html#ns"; + private JingleManager jingleManager; + private String stunServer = ""; + private int stunPort = 0; + private boolean readyToConnect = false; + private final Map jingleFeature = new HashMap<>(); + private boolean fallbackStunEnabled = false; + private final LocalPreferences pref = SettingsManager.getLocalPreferences(); + + @Override + public void initialize() { + // Add Jingle to a discovered items list. + SparkManager.addFeature(JINGLE_NAMESPACE); + + //If there is a server entered in spark.properties use it as fallback + if (!pref.getStunFallbackHost().isEmpty()) { + fallbackStunEnabled = true; + } + + // Get the default port + stunPort = pref.getStunFallbackPort(); + + // Set Jingle Enabled + JingleManager.setJingleServiceEnabled(); + JingleManager.setServiceEnabled(SparkManager.getConnection(), true); + + // Add to PhoneManager + PhoneManager.getInstance().addPhone(this); + + // Adds a tab handler. + SparkManager.getChatManager().addSparkTabHandler(new JingleTabHandler()); + + final SwingWorker jingleLoadingThread = new SwingWorker() { + @Override + public Object construct() { + if (fallbackStunEnabled) { + stunServer = pref.getStunFallbackHost(); + readyToConnect = true; + } + + try { + if (STUN.serviceAvailable(SparkManager.getConnection())) { + STUN stun = STUN.getSTUNServer(SparkManager.getConnection()); + if (stun != null) { + List servers = stun.getServers(); + if (!servers.isEmpty()) { + stunServer = servers.get(0).getServer(); + stunPort = Integer.parseInt(servers.get(0).getPort()); + readyToConnect = true; + } + } + } + + // Initializes Jingle with STUN and media managers + if (readyToConnect) { + JingleTransportManager transportManager = new ICETransportManager(SparkManager.getConnection(), stunServer, stunPort); + List mediaManagers = new ArrayList<>(); + + // Get the Locator from the Settings + String locator = SettingsManager.getLocalPreferences().getAudioDevice(); + + mediaManagers.add(new JmfMediaManager(locator, transportManager)); + mediaManagers.add(new SpeexMediaManager(transportManager)); + //mediaManagers.add(new ScreenShareMediaManager(transportManager)); + + jingleManager = new JingleManager(SparkManager.getConnection(), mediaManagers); + if (transportManager instanceof BridgedTransportManager) { + jingleManager.addCreationListener((BridgedTransportManager) transportManager); + } else if (transportManager instanceof ICETransportManager) { + jingleManager.addCreationListener((ICETransportManager) transportManager); + } + } + } catch (Exception e) { + Log.error("Unable to initialize", e); + } + return true; + } + + @Override + public void finished() { + addListeners(); + } + }; + + jingleLoadingThread.start(); + + // Add Presence listener for better service discovery. + addPresenceListener(); + + SparkManager.getConnection().addConnectionListener(this); + } + + /** + * Adds Jingle and ChatRoom listeners. + */ + private void addListeners() { + if (jingleManager == null) { + if (readyToConnect) { + Log.error("Unable to resolve Jingle Connection (Host: " + stunServer + " Port: " + stunPort + ")"); + } + return; + } + // Listen in for new incoming Jingle requests. + jingleManager.addJingleSessionRequestListener(request -> SwingUtilities.invokeLater(() -> incomingJingleSession(request))); + } + + @Override + public Collection getPhoneActions(EntityBareJid jid) { + // Do not even disco gateway clients. + if (TransportUtils.isFromGateway(jid) || jingleManager == null) { + return List.of(); + } + + Boolean supportsJingle = jingleFeature.get(jid.toString()); + if (supportsJingle == null) { + // Disco for event. + // Obtain the ServiceDiscoveryManager associated with my XMPPConnection + ServiceDiscoveryManager discoManager = SparkManager.getDiscoManager(); + + EntityFullJid fullJID = PresenceManager.getFullyQualifiedJID(jid); + + // Get the items of a given XMPP entity + DiscoverInfo discoverInfo = null; + try { + discoverInfo = discoManager.discoverInfo(fullJID); + } catch (Exception e) { + Log.debug("Unable to disco " + fullJID); + } + + if (discoverInfo != null) { + // Get the discovered items of the queried XMPP entity + supportsJingle = discoverInfo.containsFeature(JINGLE_NAMESPACE); + jingleFeature.put(jid.toString(), supportsJingle); + } else { + jingleFeature.put(jid.toString(), false); + supportsJingle = false; + } + } + + if (!supportsJingle) { + return Collections.emptyList(); + } + + Action action = new AbstractAction() { + private static final long serialVersionUID = 1467355627829748086L; + + @Override + public void actionPerformed(ActionEvent e) { + try { + placeCall(jid); + } catch (SmackException e1) { + Log.warning("Unable to place call to " + jid, e1); + } + } + }; + + action.putValue(Action.NAME, "" + JingleResources.getString("label.computer.to.computer") + ""); + action.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icons.COMPUTER_IMAGE_16x16)); + List actions = new ArrayList<>(1); + actions.add(action); + return actions; + } + + + public void placeCall(BareJid bareJid) throws SmackException { + // cancel call request if no Media Locator available + if (PhoneManager.isUseStaticLocator() && PhoneManager.isUsingMediaLocator()) { + return; + } + PhoneManager.setUsingMediaLocator(true); + EntityFullJid jid = SparkManager.getUserManager().getFullJID(bareJid); + + ChatRoom room = SparkManager.getChatManager().getChatRoom(jid.asEntityBareJid()); + if (JingleStateManager.getInstance().getJingleRoomState(room) != null) { + return; + } + + SparkManager.getChatManager().getChatContainer().activateChatRoom(room); + // Create a new Jingle Call with a full JID + JingleSession session; + try { + session = jingleManager.createOutgoingJingleSession(jid); + } catch (XMPPException e) { + Log.error(e); + return; + } + + TranscriptWindow transcriptWindow = room.getTranscriptWindow(); + StyledDocument doc = (StyledDocument) transcriptWindow.getDocument(); + Style style = doc.addStyle("StyleName", null); + + OutgoingCall outgoingCall = new OutgoingCall(); + outgoingCall.handleOutgoingCall(session, room, jid); + StyleConstants.setComponent(style, outgoingCall); + + // Insert the image at the end of the text + try { + doc.insertString(doc.getLength(), "ignored text", style); + doc.insertString(doc.getLength(), "\n", null); + } catch (BadLocationException e) { + Log.error(e); + } + + room.scrollToBottom(); + } + + @Override + public void shutdown() { + } + + @Override + public boolean canShutDown() { + return false; + } + + @Override + public void uninstall() { + } + + /** + * Notify user that a new incoming jingle request has been receieved. + * + * @param request the JingleSessionRequest. + */ + private void incomingJingleSession(JingleSessionRequest request) { + if (PhoneManager.isUseStaticLocator() && PhoneManager.isUsingMediaLocator()) { + request.reject(); + } else { + PhoneManager.setUsingMediaLocator(true); + new IncomingCall(request); + } + } + + /** + * Adds a presence listener to remove offline users from discovered features. + */ + private void addPresenceListener() { + // Check presence changes + SparkManager.getConnection().addAsyncStanzaListener(stanza -> { + Presence presence = (Presence) stanza; + if (!presence.isAvailable()) { + Jid from = presence.getFrom(); + if (from != null) { + // Remove from + jingleFeature.remove(from.toString()); + } + } + }, new StanzaTypeFilter(Presence.class)); + } + + @Override + public void connected(XMPPConnection xmppConnection) { + SparkManager.addFeature(JINGLE_NAMESPACE); + } + +} diff --git a/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JingleResources.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JingleResources.java new file mode 100644 index 000000000..6c0188606 --- /dev/null +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JingleResources.java @@ -0,0 +1,46 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.jingle; + +import java.text.MessageFormat; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +import org.jivesoftware.spark.util.log.Log; + +public enum JingleResources { + ; + static ClassLoader cl = JingleResources.class.getClassLoader(); + private static final PropertyResourceBundle prb; + + static { + prb = (PropertyResourceBundle) ResourceBundle.getBundle("i18n/jingle_i18n"); + } + + public static String getString(String propertyName) { + try { + return prb.getString(propertyName); + } catch (Exception e) { + Log.error(e); + return propertyName; + } + } + + public static String getString(String propertyName, Object... obj) { + String str = prb.getString(propertyName); + return MessageFormat.format(str, obj); + } +} diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JingleRoom.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JingleRoom.java similarity index 90% rename from src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JingleRoom.java rename to plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JingleRoom.java index b27d6b5b0..bd6ee6c86 100644 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JingleRoom.java +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JingleRoom.java @@ -1,23 +1,19 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * + *

      * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jivesoftware.sparkplugin; +package org.jivesoftware.spark.plugin.jingle; import java.awt.Color; import java.awt.Component; @@ -51,7 +47,6 @@ import org.jivesoftware.spark.ui.ChatRoom; import org.jivesoftware.spark.util.log.Log; - /** * The UI for calls with Roster members. * @@ -59,51 +54,41 @@ */ public class JingleRoom extends JPanel { - private static final long serialVersionUID = 2910998210426650565L; - private JLabel connectedLabel; - private String phoneNumber; - private PreviousConversationPanel historyPanel; - - private boolean transmitting; - - private CallPanelButton muteButton; - - private RolloverButton hangUpButton; - - private static String CONNECTED = "Connected"; - + private static final long serialVersionUID = 2910998210426650565L; + private static final String CONNECTED = "Connected"; protected final Color greenColor = new Color(91, 175, 41); protected final Color orangeColor = new Color(229, 139, 11); protected final Color blueColor = new Color(64, 103, 162); protected final Color redColor = new Color(211, 0, 0); - + private JLabel connectedLabel; + private String phoneNumber; + private final PreviousConversationPanel historyPanel; + private boolean transmitting; + private CallPanelButton muteButton; + private RolloverButton hangUpButton; private boolean callWasTransferred; - private ChatRoom chatRoom; + private final ChatRoom chatRoom; - private JingleSession session; + private final JingleSession session; - private JavaMixer mixer = new JavaMixer(); + private final JavaMixer mixer = new JavaMixer(); public JingleRoom(JingleSession session, ChatRoom chatRoom) { this.session = session; this.chatRoom = chatRoom; setLayout(new GridBagLayout()); setBorder(BorderFactory.createLineBorder(Color.lightGray)); - // Build Top Layer final JPanel topPanel = buildTopPanel(); add(topPanel, new GridBagConstraints(1, 5, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0)); - // Build Control Panel final JPanel controlPanel = buildControlPanel(); add(controlPanel, new GridBagConstraints(1, 6, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2, 2, 2, 2), 0, 0)); - // Add Previous Conversation historyPanel = new PreviousConversationPanel(); historyPanel.addPreviousConversations(""); // add(historyPanel, new GridBagConstraints(1, 8, 1, 1, 0.0, 1.0, GridBagConstraints.SOUTH, GridBagConstraints.BOTH, new Insets(2, 2, 2, 2), 0, 100)); - // Setup default settings setupDefaults(); } @@ -117,12 +102,11 @@ public JingleRoom(JingleSession session, ChatRoom chatRoom) { private JPanel buildTopPanel() { final JPanel panel = new JPanel(new GridBagLayout()); panel.setOpaque(false); - // Add phone label JLabel phoneLabel = new JLabel(); phoneLabel.setFont(new Font("Arial", Font.BOLD, 13)); phoneLabel.setForeground(new Color(64, 103, 162)); - panel.add( phoneLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 2, 2, 2), 0, 0)); + panel.add(phoneLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 2, 2, 2), 0, 0)); // Add Connected Label connectedLabel = new JLabel(CONNECTED); @@ -154,23 +138,21 @@ private JPanel buildControlPanel() { inputPanel.add(inputIcon, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); mainPanel.add(inputPanel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.2, GridBagConstraints.NORTHWEST, GridBagConstraints.VERTICAL, new Insets(2, 1, 2, 1), 0, 50)); } - } - catch (Exception e) { + } catch (Exception e) { Log.error(e); } // Add master volume control. try { final ControlPanel outputPanel = new ControlPanel(new GridBagLayout()); - Component outputControl = mixer.getPrefferedMasterVolume(); - if (outputControl!=null) { + Component outputControl = mixer.getPreferredMasterVolume(); + if (outputControl != null) { final JLabel outputIcon = new JLabel(JinglePhoneRes.getImageIcon("SPEAKER_IMAGE")); outputPanel.add(outputControl, new GridBagConstraints(0, 0, 1, 1, 0.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, new Insets(2, 2, 2, 2), 0, 0)); outputPanel.add(outputIcon, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); mainPanel.add(outputPanel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.2, GridBagConstraints.NORTHWEST, GridBagConstraints.VERTICAL, new Insets(2, 1, 2, 1), 0, 50)); } - } - catch (Exception e) { + } catch (Exception e) { Log.error(e); } @@ -190,32 +172,28 @@ private JPanel buildControlPanel() { hangUpButton.setMargin(new Insets(0, 0, 0, 0)); mainPanel.add(hangUpButton, new GridBagConstraints(0, 1, 3, 1, 0.0, 0.8, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - return mainPanel; } public void setupDefaults() { muteButton.addMouseListener(new MouseAdapter() { + @Override public void mousePressed(MouseEvent mouseEvent) { toggleMute(); } }); - - - hangUpButton.addActionListener( actionEvent -> { + hangUpButton.addActionListener(actionEvent -> { hangUpButton.setEnabled(false); try { session.terminate(); + } catch (Exception e) { + Log.error(e); } - catch (XMPPException | SmackException e) { - e.printStackTrace(); - } - } ); + }); } - /** * Called when a new call is established. */ @@ -230,11 +208,10 @@ private void callStarted() { muteButton.setEnabled(true); setStatus(CONNECTED, false); - // Add notification to ChatRoom if one exists. + // Add a notification to ChatRoom if one exists. if (chatRoom != null) { final SimpleDateFormat formatter = new SimpleDateFormat("h:mm a"); String time = formatter.format(new Date()); - chatRoom.getTranscriptWindow().insertNotificationMessage("Call started at " + time, ChatManager.NOTIFICATION_COLOR); } } @@ -256,7 +233,7 @@ public void callEnded() { setStatus("Call Ended", redColor); - // Add notification to ChatRoom if one exists. + // Add a notification to ChatRoom if one exists. if (chatRoom != null) { final SimpleDateFormat formatter = new SimpleDateFormat("h:mm a"); String time = formatter.format(new Date()); @@ -300,7 +277,7 @@ private void toggleMute() { } for (JingleMediaManager mediaManager : session.getMediaManagers()) { - session.getMediaSession(mediaManager.getName()).setTrasmit(!transmitting); + session.getMediaSession(mediaManager.getName()).setTransmit(!transmitting); } muteButton.invalidate(); @@ -313,24 +290,22 @@ private void toggleMute() { public void actionPerformed(ActionEvent e) { - } + @Override public void paintComponent(Graphics g) { BufferedImage cache = new BufferedImage(2, getHeight(), BufferedImage.TYPE_INT_RGB); Graphics2D g2d = cache.createGraphics(); - GradientPaint paint = new GradientPaint(0, 0, new Color(241, 245, 250), 0, getHeight(), new Color(244, 250, 255), true); - g2d.setPaint(paint); g2d.fillRect(0, 0, getWidth(), getHeight()); g2d.dispose(); - g.drawImage(cache, 0, 0, getWidth(), getHeight(), null); } + @Override public Dimension getPreferredSize() { Dimension dim = super.getPreferredSize(); dim.width = 200; @@ -341,6 +316,4 @@ public SparkTab getSparkTab() { int index = SparkManager.getChatManager().getChatContainer().indexOfComponent(chatRoom); return SparkManager.getChatManager().getChatContainer().getTabAt(index); } - - -} \ No newline at end of file +} diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JingleStateManager.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JingleStateManager.java similarity index 80% rename from src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JingleStateManager.java rename to plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JingleStateManager.java index 04b63fbde..c54a45d5c 100644 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JingleStateManager.java +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JingleStateManager.java @@ -1,71 +1,33 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * + *

      * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jivesoftware.sparkplugin; +package org.jivesoftware.spark.plugin.jingle; import org.jivesoftware.spark.ui.ChatRoom; import java.util.HashMap; import java.util.Map; -/** - * - */ public class JingleStateManager { - private static JingleStateManager singleton; private static final Object LOCK = new Object(); + private static JingleStateManager singleton; + private final Map jingleRooms = new HashMap<>(); - - private Map jingleRooms = new HashMap<>(); - - /** - * Type of states a jingle call can be in. - */ - public static enum JingleRoomState { - /** - * The room contains a jingle session. - */ - inJingleCall, - - /** - * The rooms contained a jingle session, but the call was ended. - */ - callWasEnded, - - /** - * The room contains an incoming jingle session. - */ - ringing, - - /** - * The jingle session is muted. - */ - muted + private JingleStateManager() { } - /** - * Returns the singleton instance of JingleManager, - * creating it if necessary. - *

      - * - * @return the singleton instance of JingleManager - */ public static JingleStateManager getInstance() { // Synchronize on LOCK to ensure that we don't end up creating // two singletons. @@ -79,10 +41,6 @@ public static JingleStateManager getInstance() { return singleton; } - private JingleStateManager() { - - } - /** * Adds a new JingleRoomState. * @@ -95,8 +53,6 @@ public void addJingleSession(ChatRoom room, JingleRoomState state) { /** * Removes a JingleRoomState. - * - * @param room the room the jingle session was taking place. */ public void removeJingleSession(ChatRoom room) { jingleRooms.remove(room); @@ -107,10 +63,35 @@ public void removeJingleSession(ChatRoom room) { * this method will return null. * * @param room the ChatRoom. - * @return the JingleRoomState.` + * @return the JingleRoomState. */ public JingleRoomState getJingleRoomState(ChatRoom room) { return jingleRooms.get(room); } + /** + * Type of states a jingle call can be in. + */ + public enum JingleRoomState { + /** + * The room contains a jingle session. + */ + inJingleCall, + + /** + * The rooms contained a jingle session, but the call was ended. + */ + callWasEnded, + + /** + * The room contains an incoming jingle session. + */ + ringing, + + /** + * The jingle session is muted. + */ + muted + } + } diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JingleTabHandler.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JingleTabHandler.java similarity index 82% rename from src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JingleTabHandler.java rename to plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JingleTabHandler.java index 79437d375..9f0dd8117 100644 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JingleTabHandler.java +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/JingleTabHandler.java @@ -1,30 +1,26 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * + *

      * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jivesoftware.sparkplugin; +package org.jivesoftware.spark.plugin.jingle; import org.jivesoftware.resource.SparkRes; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.component.tabbedPane.SparkTab; import org.jivesoftware.spark.ui.ChatRoom; import org.jivesoftware.spark.ui.SparkTabHandler; -import org.jivesoftware.sparkplugin.JingleStateManager.JingleRoomState; +import org.jivesoftware.spark.plugin.jingle.JingleStateManager.JingleRoomState; import java.awt.Color; import java.awt.Component; @@ -36,27 +32,24 @@ */ public class JingleTabHandler extends SparkTabHandler { - private JingleStateManager manager; + private final JingleStateManager manager; public JingleTabHandler() { manager = JingleStateManager.getInstance(); } - + @Override public boolean isTabHandled(SparkTab tab, Component component, boolean isSelectedTab, boolean chatFrameFocused) { if (component instanceof ChatRoom) { - JingleRoomState roomState = manager.getJingleRoomState((ChatRoom)component); + JingleRoomState roomState = manager.getJingleRoomState((ChatRoom) component); if (roomState == null) { // This is not a jingle room. return false; } - // This is a room with a jingle session. - handleJingleRoom(roomState, tab, (ChatRoom)component, isSelectedTab, chatFrameFocused); + handleJingleRoom(roomState, tab, (ChatRoom) component, isSelectedTab, chatFrameFocused); return true; } - - return false; } @@ -71,22 +64,17 @@ public boolean isTabHandled(SparkTab tab, Component component, boolean isSelecte */ private void handleJingleRoom(JingleRoomState state, SparkTab tab, ChatRoom room, boolean isSelectedTab, boolean chatFrameFocused) { boolean isTyping = SparkManager.getChatManager().containsTypingNotification(room); - // Check if is typing. if (isTyping) { - tab.setIcon(SparkRes.getImageIcon(SparkRes.SMALL_MESSAGE_EDIT_IMAGE)); - } - else if (JingleRoomState.ringing == state) { + tab.setIcon(SparkRes.getImageIcon(SparkRes.Icons.SMALL_MESSAGE_EDIT_IMAGE)); + } else if (JingleRoomState.ringing == state) { tab.setIcon(JinglePhoneRes.getImageIcon("ANSWER_PHONE_IMAGE")); - } - else if (JingleRoomState.inJingleCall == state) { - tab.setIcon(SparkRes.getImageIcon(SparkRes.HEADSET_IMAGE)); - } - else if (JingleRoomState.callWasEnded == state) { + } else if (JingleRoomState.inJingleCall == state) { + tab.setIcon(SparkRes.getImageIcon(SparkRes.Icons.HEADSET_IMAGE)); + } else if (JingleRoomState.callWasEnded == state) { tab.setIcon(JinglePhoneRes.getImageIcon("HANG_UP_PHONE_16x16_IMAGE")); } - if (!chatFrameFocused || !isSelectedTab) { if (room.getUnreadMessageCount() > 0 || JingleRoomState.ringing == state) { // Make tab red. @@ -100,9 +88,7 @@ else if (JingleRoomState.callWasEnded == state) { if (unreadMessageCount > 1) { appendedMessage = " (" + unreadMessageCount + ")"; } - tab.setTabTitle(room.getTabTitle() + appendedMessage); - } // Should only set the icon to default if the frame is in focus @@ -115,6 +101,5 @@ else if (JingleRoomState.callWasEnded == state) { // Clear unread message count. room.clearUnreadMessageCount(); } - } } diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/OutgoingCall.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/OutgoingCall.java similarity index 81% rename from src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/OutgoingCall.java rename to plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/OutgoingCall.java index 8b9ad6e36..542576e35 100644 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/OutgoingCall.java +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/OutgoingCall.java @@ -1,26 +1,20 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * + *

      * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jivesoftware.sparkplugin; +package org.jivesoftware.spark.plugin.jingle; -import java.applet.Applet; -import java.applet.AudioClip; import java.awt.Color; import java.awt.Cursor; import java.awt.Font; @@ -58,45 +52,32 @@ import org.jivesoftware.spark.util.SwingTimerTask; import org.jivesoftware.spark.util.TaskEngine; import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.EntityFullJid; + +import static org.jivesoftware.spark.plugin.jingle.Ringing.*; /** * Handles UI controls for outgoing jingle calls. */ public class OutgoingCall extends JPanel implements JingleSessionListener, ChatRoomClosingListener { - private static final long serialVersionUID = 7051515951813136423L; - private FileDragLabel imageLabel = new FileDragLabel(); - private JLabel titleLabel = new JLabel(); - private JLabel fileLabel = new JLabel(); - - private CallButton cancelButton = new CallButton(); - + private static final long serialVersionUID = 7051515951813136423L; + private static final long WAIT_FOR_MEDIA_DELAY = 20000; + private final FileDragLabel imageLabel = new FileDragLabel(); + private final JLabel titleLabel = new JLabel(); + private final JLabel fileLabel = new JLabel(); + private final CallButton cancelButton = new CallButton(); private JingleSession session; private JingleRoom jingleRoom; - - private AudioClip ringing; - private ChatRoom chatRoom; - private boolean established = false; - private boolean mediaReceived = false; - private TimerTask mediaReceivedTask; - private static final long WAIT_FOR_MEDIA_DELAY = 20000; - /** * Creates a new instance of OutgoingCall. */ public OutgoingCall() { - try { - ringing = Applet.newAudioClip(JinglePhoneRes.getURL("RINGING")); - } - catch (Exception e) { - Log.error(e); - } - setLayout(new GridBagLayout()); setBackground(new Color(250, 249, 242)); @@ -123,10 +104,8 @@ public OutgoingCall() { * @param chatRoom the room the session is associated with. * @param jid the users jid. */ - public void handleOutgoingCall(final JingleSession session, ChatRoom chatRoom, final String jid) throws SmackException - { + public void handleOutgoingCall(final JingleSession session, ChatRoom chatRoom, final EntityFullJid jid) throws SmackException { this.chatRoom = chatRoom; - JingleStateManager.getInstance().addJingleSession(chatRoom, JingleStateManager.JingleRoomState.ringing); chatRoom.addClosingListener(this); @@ -134,28 +113,31 @@ public void handleOutgoingCall(final JingleSession session, ChatRoom chatRoom, f cancelButton.setVisible(true); this.session = session; - // Start the call - this.session.startOutgoing(); - - fileLabel.setText(jid); + try { + this.session.startOutgoing(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + fileLabel.setText(jid.toString()); ContactList contactList = SparkManager.getWorkspace().getContactList(); ContactItem contactItem = contactList.getContactItemByJID(jid); - - titleLabel.setText(JingleResources.getString("label.outgoing.voicechat", contactItem.getNickname())); cancelButton.addMouseListener(new MouseAdapter() { + @Override public void mousePressed(MouseEvent e) { cancel(); } + @Override public void mouseEntered(MouseEvent e) { cancelButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); } + @Override public void mouseExited(MouseEvent e) { cancelButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } @@ -166,7 +148,6 @@ public void mouseExited(MouseEvent e) { // Notify state change SparkManager.getChatManager().notifySparkTabHandlers(chatRoom); - updateOutgoingCallPanel(); } @@ -175,8 +156,7 @@ public void mouseExited(MouseEvent e) { */ private void updateOutgoingCallPanel() { if (session == null || session.isClosed()) { - } - else if (session instanceof JingleSession) { + } else if (session instanceof JingleSession) { showAlert(false); if (session.getSessionState() instanceof JingleSessionStatePending) { titleLabel.setText("Calling user. Please wait..."); @@ -185,28 +165,23 @@ else if (session instanceof JingleSession) { } } - /** - * Called when the call has been answered. Will append the JingleRoom to the - * associated ChatRoom. + * Called when the call has been answered. + * Will append the JingleRoom to the associated ChatRoom. */ private void showCallAnsweredState() { final SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy h:mm a"); titleLabel.setText("Voice chat started on " + formatter.format(new Date())); cancelButton.setVisible(false); - if (ringing != null) { - ringing.stop(); - } + stopRinging(); jingleRoom = new JingleRoom(session, chatRoom); chatRoom.getChatPanel().add(jingleRoom, new GridBagConstraints(1, 1, 1, 1, 0.05, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); chatRoom.getChatPanel().invalidate(); chatRoom.getChatPanel().validate(); chatRoom.getChatPanel().repaint(); - // Add state JingleStateManager.getInstance().addJingleSession(chatRoom, JingleStateManager.JingleRoomState.inJingleCall); - // Notify state change SparkManager.getChatManager().notifySparkTabHandlers(chatRoom); } @@ -219,9 +194,7 @@ private void showCallEndedState(String reason) { showAlert(true); cancelButton.setVisible(false); - if (ringing != null) { - ringing.stop(); - } + stopRinging(); if (chatRoom != null && jingleRoom != null) { chatRoom.getChatPanel().remove(jingleRoom); @@ -229,49 +202,30 @@ private void showCallEndedState(String reason) { chatRoom.getChatPanel().validate(); chatRoom.getChatPanel().repaint(); } - // Add state JingleStateManager.getInstance().removeJingleSession(chatRoom); - // Notify state change SparkManager.getChatManager().notifySparkTabHandlers(chatRoom); } private void makeClickable(final JComponent component) { component.addMouseListener(new MouseAdapter() { + @Override public void mouseClicked(MouseEvent e) { } + @Override public void mouseEntered(MouseEvent e) { component.setCursor(new Cursor(Cursor.HAND_CURSOR)); } + @Override public void mouseExited(MouseEvent e) { component.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } }); } - private class CallButton extends JButton { - private static final long serialVersionUID = 7083309769944609925L; - - public CallButton() { - decorate(); - } - - /** - * Decorates the button with the approriate UI configurations. - */ - private void decorate() { - setBorderPainted(false); - setOpaque(true); - - setContentAreaFilled(false); - setMargin(new Insets(1, 1, 1, 1)); - } - - } - /** * Changes the background color. If alert is true, the background will reflect that the ui * needs attention. @@ -282,8 +236,7 @@ private void showAlert(boolean alert) { if (alert) { titleLabel.setForeground(new Color(211, 174, 102)); setBackground(new Color(250, 249, 242)); - } - else { + } else { setBackground(new Color(239, 245, 250)); titleLabel.setForeground(new Color(65, 139, 179)); } @@ -297,8 +250,7 @@ public void cancel() { try { session.terminate(); session = null; - } - catch (XMPPException | SmackException e) { + } catch (Exception e) { Log.error(e); } } @@ -306,80 +258,101 @@ public void cancel() { showCallEndedState("Voice chat ended on " + formatter.format(new Date())); } + @Override public void closing() { if (session != null) { try { session.terminate(); - } - catch (XMPPException | SmackException e) { + } catch (Exception e) { Log.error(e); } } - JingleStateManager.getInstance().removeJingleSession(chatRoom); } + @Override public void sessionMediaReceived(JingleSession jingleSession, String participant) { mediaReceived = true; TaskEngine.getInstance().cancelScheduledTask(mediaReceivedTask); showCallAnsweredState(); } + @Override public void sessionEstablished(PayloadType payloadType, TransportCandidate transportCandidate, TransportCandidate transportCandidate1, JingleSession jingleSession) { established = true; mediaReceivedTask = new SwingTimerTask() { + @Override public void doRun() { - if (!mediaReceived) { - if (session != null) { - try { - session.terminate("No Media Received. This may be caused by firewall configuration problems."); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } + if (mediaReceived) { + return; + } + if (session != null) { + try { + session.terminate("No Media Received. This may be caused by firewall configuration problems."); + } catch (Exception e) { + Log.error(e); } } } }; TaskEngine.getInstance().schedule(mediaReceivedTask, WAIT_FOR_MEDIA_DELAY, WAIT_FOR_MEDIA_DELAY); - - SwingUtilities.invokeLater( () -> updateOutgoingCallPanel() ); + SwingUtilities.invokeLater(() -> updateOutgoingCallPanel()); } + @Override public void sessionDeclined(String string, JingleSession jingleSession) { showCallEndedState("The Session was rejected."); - - SwingUtilities.invokeLater( () -> updateOutgoingCallPanel() ); + SwingUtilities.invokeLater(() -> updateOutgoingCallPanel()); } + @Override public void sessionRedirected(String string, JingleSession jingleSession) { - SwingUtilities.invokeLater( () -> updateOutgoingCallPanel() ); + SwingUtilities.invokeLater(() -> updateOutgoingCallPanel()); } + @Override public void sessionClosed(String string, JingleSession jingleSession) { - if (jingleSession instanceof JingleSession) { if (established && mediaReceived) { final SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy h:mm a"); showCallEndedState("Voice chat ended on " + formatter.format(new Date())); - } - else { + } else { showCallEndedState("Session closed due to " + string); } } - if(PhoneManager.isUseStaticLocator()&&PhoneManager.isUsingMediaLocator()){ + if (PhoneManager.isUseStaticLocator() && PhoneManager.isUsingMediaLocator()) { PhoneManager.setUsingMediaLocator(false); } - - SwingUtilities.invokeLater( () -> updateOutgoingCallPanel() ); + SwingUtilities.invokeLater(() -> updateOutgoingCallPanel()); } + @Override public void sessionClosedOnError(XMPPException xmppException, JingleSession jingleSession) { showCallEndedState("Voice chat ended due: " + xmppException.getMessage()); - if(PhoneManager.isUseStaticLocator()&&PhoneManager.isUsingMediaLocator()){ + if (PhoneManager.isUseStaticLocator() && PhoneManager.isUsingMediaLocator()) { PhoneManager.setUsingMediaLocator(false); - } + } + + SwingUtilities.invokeLater(() -> updateOutgoingCallPanel()); + } + + private static class CallButton extends JButton { + private static final long serialVersionUID = 7083309769944609925L; + + public CallButton() { + decorate(); + } + + /** + * Decorates the button with the approriate UI configurations. + */ + private void decorate() { + setBorderPainted(false); + setOpaque(true); + + setContentAreaFilled(false); + setMargin(new Insets(1, 1, 1, 1)); + } - SwingUtilities.invokeLater( () -> updateOutgoingCallPanel() ); } } diff --git a/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/PreviousConversationPanel.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/PreviousConversationPanel.java new file mode 100644 index 000000000..4ce88eb48 --- /dev/null +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/PreviousConversationPanel.java @@ -0,0 +1,187 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.jingle; + +import org.jivesoftware.spark.component.TimeTrackingLabel; +import org.jivesoftware.spark.component.VerticalFlowLayout; + +import javax.swing.BorderFactory; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.Font; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class PreviousConversationPanel extends JPanel { + + private static final long serialVersionUID = -8392478440078855765L; + final JLabel previousLabel = new JLabel("Previous Conversations:"); + private final Color greenColor = new Color(91, 175, 41); + private final JLabel currentCallLabel = new JLabel(); + private final JPanel timePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 0)); + private final JLabel today = new JLabel(); + private final JLabel statusLabel = new JLabel(); + private final JLabel oldConversation = new JLabel(); + private final SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy, h:mm a"); + private final TimeTrackingLabel durationLabel; + + private Date startTime; + + + public PreviousConversationPanel() { + setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 5, 0, true, false)); + + setBackground(Color.white); + setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230))); + + // Set Default Color for Current Call Label + currentCallLabel.setText("Current Call:"); + currentCallLabel.setFont(new Font("Dialog", Font.BOLD, 13)); + currentCallLabel.setForeground(greenColor); + + // Set default color for previous label. + previousLabel.setForeground(new Color(64, 103, 162)); + previousLabel.setFont(new Font("Dialog", Font.BOLD, 13)); + + statusLabel.setFont(new Font("Dialog", Font.BOLD, 12)); + + // Add Duration timer + durationLabel = new TimeTrackingLabel(new Date(), this); + durationLabel.setFont(new Font("Dialog", Font.BOLD, 12)); + durationLabel.stopTimer(); + + // Build Time Panel + + timePanel.setOpaque(false); + + today.setForeground(Color.black); + today.setFont(new Font("Dialog", Font.PLAIN, 12)); + + today.setText(formatter.format(new Date()) + " - Time: "); + timePanel.add(today); + timePanel.add(durationLabel); + + oldConversation.setForeground(new Color(211, 0, 0)); + oldConversation.setFont(new Font("Dialog", Font.BOLD, 12)); + } + + /** + * Builds the previous history list. + * + * @param jid the jid of the user. + */ + public void addPreviousConversations(String jid) { + startTime = new Date(); + + currentCallLabel.setText("Current Call:"); + currentCallLabel.setFont(new Font("Dialog", Font.BOLD, 13)); + currentCallLabel.setForeground(greenColor); + + today.setText(formatter.format(new Date()) + " - Time: "); + + // Add Current Call and Time Panel + add(currentCallLabel); + add(timePanel); + add(statusLabel); + statusLabel.setVisible(false); + + // Give some space. + add(new JLabel()); + add(previousLabel); + add(oldConversation); + + + int count = 0; + /* + final CallList callList = SoftPhoneManager.getInstance().getLogManager().getCallList(); + for (HistoryCall call : callList.getList()) { + String number = TelephoneUtils.getNumbersFromPhone(call.getNumber()); + if (number.equals(TelephoneUtils.getNumbersFromPhone(phoneNumber))) { + count++; + if (count > 4) { + break; + } + + final Date callDate = new Date(call.getTime()); + final long duration = call.getCallLength(); + + StringBuilder builder = new StringBuilder(); + builder.append(formatter.format(callDate)); + builder.append(" "); + builder.append("("); + builder.append(ModelUtil.getTimeFromLong(duration)); + builder.append(")"); + + final JLabel callLabel = new JLabel(builder.toString()); + callLabel.setForeground(Color.black); + callLabel.setFont(new Font("Dialog", Font.PLAIN, 12)); + add(callLabel); + } + } + */ + + if (count == 0) { + final JLabel label = new JLabel("No previous conversations."); + label.setForeground(Color.gray); + add(label); + } + + durationLabel.resetTime(); + durationLabel.startTimer(); + + invalidate(); + validate(); + repaint(); + } + + public void callEnded() { + durationLabel.stopTimer(); + + currentCallLabel.setForeground(Color.black); + currentCallLabel.setText(JingleResources.getString("label.call.ended")); + + today.setText("Time: "); + } + + public void transferring() { + statusLabel.setText("Transferring..."); + statusLabel.setVisible(true); + } + + /** + * Update labels to reflect call transfer to user + */ + public void transfer(String user) { + durationLabel.stopTimer(); + statusLabel.setVisible(false); + + currentCallLabel.setForeground(Color.black); + currentCallLabel.setText(JingleResources.getString("label.call.ended")); + + today.setText("Time: "); + currentCallLabel.setText(JingleResources.getString("label.call.transfer", user)); + + Date now = new Date(); + final SimpleDateFormat timeFormatter = new SimpleDateFormat("h:mm"); + + String end = timeFormatter.format(now); + oldConversation.setText(formatter.format(startTime) + " - " + end + " (" + durationLabel.getText() + ")"); + } + +} diff --git a/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/Ringing.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/Ringing.java new file mode 100644 index 000000000..9d84ff234 --- /dev/null +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/Ringing.java @@ -0,0 +1,54 @@ +package org.jivesoftware.spark.plugin.jingle; + +import org.jivesoftware.spark.util.TaskEngine; +import org.jivesoftware.spark.util.log.Log; + +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import java.net.URL; + +public class Ringing { + private static Clip ringing; + + static { + URL soundFile = JinglePhoneRes.getURL("RINGING"); + try (AudioInputStream originalStream = AudioSystem.getAudioInputStream(soundFile)) { + Clip clip = (Clip) AudioSystem.getClip(); + clip.open(originalStream); + ringing = clip; + } catch (Exception e) { + Log.warning("Unable to load sound: " + soundFile, e); + } + } + + public static void startRinging() { + if (ringing == null) { + return; + } + // Start the ringing. + Runnable ringer = () -> { + try { + if (ringing.isRunning()) { + ringing.stop(); + } + ringing.setFramePosition(0); + ringing.loop(5); + } catch (Exception e) { + Log.error("Unable to play ring sound: " + e); + } + }; + TaskEngine.getInstance().submit(ringer); + } + + public static void stopRinging() { + if (ringing == null) { + return; + } + + if (ringing.isRunning()) { + ringing.stop(); + } + } + +} diff --git a/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/RosterMemberCallButton.java b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/RosterMemberCallButton.java new file mode 100644 index 000000000..9097e0109 --- /dev/null +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/RosterMemberCallButton.java @@ -0,0 +1,127 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.jingle; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Insets; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import javax.swing.Icon; +import javax.swing.JButton; + +public class RosterMemberCallButton extends JButton implements MouseListener { + + private static final long serialVersionUID = 8056708231977922612L; + private final Icon normalIcon; + private final Icon hoverIcon; + private final Icon downIcon; + private final Image backgroundImage; + private final String text; + + private boolean selected; + + public RosterMemberCallButton(Image image, String text) { + super(); + this.text = text; + normalIcon = JinglePhoneRes.getImageIcon("ROSTERPANEL_BUTTON"); + hoverIcon = JinglePhoneRes.getImageIcon("ROSTERPANEL_BUTTON_HOVER"); + downIcon = JinglePhoneRes.getImageIcon("ROSTERPANEL_BUTTON_DOWN"); + backgroundImage = image; + + setIcon(normalIcon); + decorate(); + addMouseListener(this); + } + + /** + * Decorates the button with the approriate UI configurations. + */ + private void decorate() { + setBorderPainted(false); + setOpaque(true); + + setContentAreaFilled(false); + setMargin(new Insets(0, 0, 0, 0)); + } + + + @Override + public void mouseClicked(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + setIcon(downIcon); + } + + @Override + public void mouseReleased(MouseEvent e) { + if (!selected) { + setIcon(normalIcon); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + if (!selected) { + setIcon(hoverIcon); + } + setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + if (!selected) { + setIcon(normalIcon); + } + setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + + public void setButtonSelected(boolean selected) { + this.selected = selected; + if (selected) { + setIcon(downIcon); + } else { + setIcon(normalIcon); + } + } + + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + int width = getWidth(); + int height = getHeight(); + + int x = (width - backgroundImage.getWidth(null)) / 2; + int y = (height - backgroundImage.getHeight(null)) / 2; + g.drawImage(backgroundImage, 5, y, null); + + g.setColor(Color.black); + g.setFont(new Font("Dialog", Font.PLAIN, 11)); + + int stringWidth = g.getFontMetrics().stringWidth(text); + x = (width - stringWidth) / 2; + y = (height + 11) / 2; + g.drawString(text, x, y); + } + +} diff --git a/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/jingle.properties b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/jingle.properties new file mode 100644 index 000000000..d6bdecea6 --- /dev/null +++ b/plugins/jingle/src/main/java/org/jivesoftware/spark/plugin/jingle/jingle.properties @@ -0,0 +1,102 @@ +RINGING=sounds/ringing.wav +# Images +CHAT_ROOM_DIAL_BUTTON=images/phone_call.png +# Images +AT_SYMBOL_IMAGE=images/at.gif +CARD_IMAGE=images/card.gif +COMP_IMAGE=images/comp.gif +ERROR_IMAGE=images/error.gif +INFORM_IMAGE=images/inform.gif +LOGO_IMAGE=images/logo.gif +OFF_IMAGE=images/off.gif +ON_PHONE_IMAGE=images/on-phone.png +ON_IMAGE=images/on.gif +ANSWER_PHONE_IMAGE=images/phone_pick_up.png +HANG_UP_PHONE_IMAGE=images/btn_phone-hangup_24x24.png +HANG_UP_PHONE_77x24_IMAGE=images/btn_phone-hangup.png +HANG_UP_PHONE_16x16_IMAGE=images/icon_phone-hangup_16x16.png +HANG_UP_PHONE_24x24_IMAGE=images/icon_phone-hangup_24x24.png +CLEAR_IMAGE=images/close_dark.png +RECEIVER_IMAGE=images/receiver.png +HISTORY_IMAGE=images/icon_phone-history_16x16.png +ON_HOLD_IMAGE=images/icon_phone-hold_16x16.png +RECEIVER2_IMAGE=images/receiver2.png +MUTE_IMAGE=images/icon_phone-mute_16x16.png +MICROPHONE_IMAGE=images/microphone.png +VOICEMAIL_IMAGE=images/icon_phone-voicemail_16x16.png +VOLUME_IMAGE=images/volume.png +TRANSFER_IMAGE=images/transfer.png +CHAT_IMAGE=images/message.png +TELEPHONE_IMAGE=images/telephone.png +DIAL_PAD_16x16_IMAGE=images/dialpad_16x16.png +CONTACT_48x48_IMAGE=images/contact_48x48.png +CALL_OUT_32x32_IMAGE=images/callOut_32x32.png +HOLD_32x32_IMAGE=images/hold_32x32.png +MUTE_32x32_IMAGE=images/mute_32x32.png +NO_MUTE_32x32_IMAGE=images/noMute_32x32.png +RESUME_CALL_32x32_IMAGE=images/resumeCall_32x32.png +REJECT_32x32_IMAGE=images/reject_32x32.png +VOICEMAIL_16x16_IMAGE=images/voicemail_16x16.png +CALLLIST_16x16_IMAGE=images/callList_16x16.png +CALLIN_16x16_IMAGE=images/callIn_16x16.png +DIAL_24x24_IMAGE=images/CallStart_24x24.png +DIAL_16x16_IMAGE=images/CallStart_16x16.png +DELETE_32x32_IMAGE=images/delete_32x32.png +TITLE_PANE=images/titlePane.png +ICON_NUMBERPAD_IMAGE=images/icon_numberpad_12x15.png +DIAL_BUTTON_IMAGE=images/btn_phone-dial_24x24.png +DIAL_BUTTON_HOVER_IMAGE=images/btn_phone-dial-hover_24x24.png +DIAL_BUTTON_DOWN_IMAGE=images/btn_phone-dial-down_24x24.png +DIAL_BUTTON_DISABLED_IMAGE=images/btn_phone-dial-disabled_24x24.png +DIVIDER_IMAGE=images/divider.png +INCOMING_CALL_IMAGE=images/icon_call-incoming_42x22.png +TOASTER_ACCEPT_BUTTON=images/toaster_btn-accept.png +TOASTER_REJECT_BUTTON=images/toaster_btn-reject.png +CALL_PICKUP_IMAGE=images/icon_phone-pickup_24x24.png +CALL_REJECT_IMAGE=images/icon_phone-reject_24x24.png +SPEAKER_IMAGE=images/icon_speaker_16x16.png +PHONE_CALL_IMAGE=images/icon_phone-call_16x16.png +PHONE_CALL_24x24_IMAGE=images/phone_call.png +DELETE_24x24_IMAGE=images/delete_24x24.png +MUTE_128x128_IMAGE=images/mute_128x128.png +ON_PHONE_128x128_IMAGE=images/on_phone_128x128.png +HOLD_128x128_IMAGE=images/hold_128x128.png +PHONE_HANG_UP_128x128_IMAGE=images/phone_hang_up_128x128.png +MICROPHONE_24x24_IMAGE=images/icon_microphone_24x24.png +ON_HOLD_24x24_IMAGE=images/icon_phone-hold_24x24.png +MUTED_24x24_IMAGE=images/icon_phone-mute_24x24.png +TRANSFER_24x24_IMAGE=images/icon_phone-transfer_24x24.png +BRIEFCASE_IMAGE=images/briefcase.png +# Registartion Panel +CLOSE_BUTTON=images/btn_phone-reg_close.png +CLOSE_BUTTON_DOWN=images/btn_phone-reg_close-down.png +CLOSE_BUTTON_HOVER=images/btn_phone-reg_close-hover.png +NORMAL_PHONE_ICON=images/icon_reciever_22x22.png +RECTANGLE_BUTTON=images/btn_phone-reg_retry.png +RECTANGLE_BUTTON_DOWN=images/btn_phone-reg_retry-down.png +RECTANGLE_BUTTON_HOVER=images/btn_phone-reg_retry-hover.png +# Context Menus +WORK_IMAGE=images/icon_work_16x16.png +MOBILE_IMAGE=images/icon_mobile_16x16.png +HOME_IMAGE=images/home.png +# Personal Panel +HANGUP_BIG_BUTTON=images/btn_phone-hangup-big.png +HANGUP_BIG_BUTTON_DOWN=images/btn_phone-hangup-big-down.png +HANGUP_BIG_BUTTON_HOVER=images/btn_phone-hangup-big-hover.png +CALLPANEL_BIG_BUTTON=images/btn_phone-big.png +CALLPANEL_BIG_BUTTON_HOVER=images/btn_phone-big-hover.png +CALLPANEL_BIG_BUTTON_DOWN=images/btn_phone-big-down.png +# Roster Panel +ROSTERPANEL_BUTTON=images/btn_phone-sm.png +ROSTERPANEL_BUTTON_DOWN=images/btn_phone-sm-down.png +ROSTERPANEL_BUTTON_HOVER=images/btn_phone-sm-hover.png +LARGE_PHONE_ICON=images/receiver2_48x48.png +# Dial Pad +DIALPAD_BUTTON=images/btn_dialpad.png +DIALPAD_BUTTON_DOWN=images/btn_dialpad-down.png +DIALPAD_BUTTON_HOVER=images/btn_dialpad-hover.png +# Redial Button +REDIAL_BUTTON=images/btn_phone-redial-big.png +REDIAL_BUTTON_DOWN=images/btn_phone-redial-big-down.png +REDIAL_BUTTON_HOVER=images/btn_phone-redial-big-hover.png +REDIAL_IMAGE=images/phone_recall.png diff --git a/plugins/jingle/src/main/plugin-metadata/plugin.xml b/plugins/jingle/src/main/plugin-metadata/plugin.xml new file mode 100644 index 000000000..0a20e7ad5 --- /dev/null +++ b/plugins/jingle/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,12 @@ + + ${project.name} + ${project.version} + ${project.description} + Derek DeMoro + https://IgniteRealtime.org + support@IgniteRealtime.org + org.jivesoftware.spark.plugin.jingle.JinglePlugin + 3.1.0 + Windows,mac,linux + 11 + diff --git a/src/plugins/jingle/src/resources/i18n/jingle_i18n.properties b/plugins/jingle/src/main/resources/i18n/jingle_i18n.properties similarity index 88% rename from src/plugins/jingle/src/resources/i18n/jingle_i18n.properties rename to plugins/jingle/src/main/resources/i18n/jingle_i18n.properties index 18f46cbaf..50b94e379 100644 --- a/src/plugins/jingle/src/resources/i18n/jingle_i18n.properties +++ b/plugins/jingle/src/main/resources/i18n/jingle_i18n.properties @@ -9,4 +9,4 @@ label.unmute = Unmute label.establishing.call = Establishing call. Please wait... label.outgoing.voicechat = Outgoing Voice Chat To {0} label.call.ended = Call ended. -label.call.transfer = Call transferred to {0} \ No newline at end of file +label.call.transfer = Call transferred to {0} diff --git a/src/plugins/jingle/src/resources/i18n/jingle_i18n_de.properties b/plugins/jingle/src/main/resources/i18n/jingle_i18n_de.properties similarity index 100% rename from src/plugins/jingle/src/resources/i18n/jingle_i18n_de.properties rename to plugins/jingle/src/main/resources/i18n/jingle_i18n_de.properties diff --git a/plugins/jingle/src/main/resources/i18n/jingle_i18n_lt.properties b/plugins/jingle/src/main/resources/i18n/jingle_i18n_lt.properties new file mode 100644 index 000000000..417853c32 --- /dev/null +++ b/plugins/jingle/src/main/resources/i18n/jingle_i18n_lt.properties @@ -0,0 +1,12 @@ +button.accept = Priimti +button.reject = Atmesti + +label.voice.request.from = Jums skambina ... +label.mute.call = Užtildyti šį skambutį. +label.computer.to.computer = IÅ¡ kompiuterio į kompiuterį +label.mute = Nutildyti +label.unmute = IÅ¡jungti nutildymÄ… +label.establishing.call = Lukterkite, užmezgamas ryÅ¡ys... +label.outgoing.voicechat = Skambutis pokalbiui balsu su abonentu {0} +label.call.ended = Pokalbis baigtas. +label.call.transfer = Skambutis peradresuotas abonentui {0} diff --git a/plugins/jingle/src/main/resources/i18n/jingle_i18n_pl.properties b/plugins/jingle/src/main/resources/i18n/jingle_i18n_pl.properties new file mode 100644 index 000000000..e34cbf107 --- /dev/null +++ b/plugins/jingle/src/main/resources/i18n/jingle_i18n_pl.properties @@ -0,0 +1,12 @@ +button.accept = Akceptuj +button.reject = Odrzuć + +label.voice.request.from = ProÅ›ba o rozmowÄ™ gÅ‚osowÄ… od ... +label.mute.call = Wycisz to połączenie. +label.computer.to.computer = Połączenie komputer-komputer +label.mute = Wycisz +label.unmute = Włącz gÅ‚os +label.establishing.call = Ustanawianie połączenia. ProszÄ™ czekać... +label.outgoing.voicechat = WychodzÄ…ca rozmowa gÅ‚osowa do {0} +label.call.ended = Połączenie zakoÅ„czone. +label.call.transfer = Połączenie przekazane do {0} diff --git a/plugins/jingle/src/main/resources/i18n/jingle_i18n_zh_CN.properties b/plugins/jingle/src/main/resources/i18n/jingle_i18n_zh_CN.properties new file mode 100644 index 000000000..a597c94f9 --- /dev/null +++ b/plugins/jingle/src/main/resources/i18n/jingle_i18n_zh_CN.properties @@ -0,0 +1,14 @@ +#Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net) + +button.accept = æŽ¥å— +button.reject = æ‹’ç» + +label.call.ended = 呼å«ç»“æŸã€‚ +label.call.transfer = 呼å«è½¬ç§»è‡³ {0} +label.computer.to.computer = 计算机对计算机 +label.establishing.call = 正在连接中,请ç¨å€™ +label.mute = é™éŸ³ +label.mute.call = é™éŸ³æ­¤å‘¼å«ã€‚ +label.outgoing.voicechat = 与{0}进行语音交谈 +label.unmute = å–æ¶ˆé™éŸ³ +label.voice.request.from = 语音交谈请求æ¥è‡ª ... diff --git a/plugins/jingle/src/main/resources/i18n/jingle_i18n_zh_TW.properties b/plugins/jingle/src/main/resources/i18n/jingle_i18n_zh_TW.properties new file mode 100644 index 000000000..d48306a98 --- /dev/null +++ b/plugins/jingle/src/main/resources/i18n/jingle_i18n_zh_TW.properties @@ -0,0 +1,12 @@ +button.accept = æŽ¥å— +button.reject = 拒絕 + +label.voice.request.from = 來自 ... 語音èŠå¤©è«‹æ±‚ +label.mute.call = 通話éœéŸ³. +label.computer.to.computer = 電腦å°é›»è…¦ +label.mute = éœéŸ³ +label.unmute = 解除éœéŸ³ +label.establishing.call = 建立語音èŠå¤©. è«‹ç¨å€™... +label.outgoing.voicechat = å³å°‡çµæŸçš„語音èŠå¤© {0} +label.call.ended = é€šè©±çµæŸ. +label.call.transfer = 通話轉接到 {0} diff --git a/src/plugins/jingle/src/resources/images/CallStart_16x16.png b/plugins/jingle/src/main/resources/images/CallStart_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/CallStart_16x16.png rename to plugins/jingle/src/main/resources/images/CallStart_16x16.png diff --git a/src/plugins/jingle/src/resources/images/CallStart_24x24.png b/plugins/jingle/src/main/resources/images/CallStart_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/CallStart_24x24.png rename to plugins/jingle/src/main/resources/images/CallStart_24x24.png diff --git a/src/plugins/jingle/src/resources/images/Error.gif b/plugins/jingle/src/main/resources/images/Error.gif similarity index 100% rename from src/plugins/jingle/src/resources/images/Error.gif rename to plugins/jingle/src/main/resources/images/Error.gif diff --git a/src/plugins/jingle/src/resources/images/Inform.gif b/plugins/jingle/src/main/resources/images/Inform.gif similarity index 100% rename from src/plugins/jingle/src/resources/images/Inform.gif rename to plugins/jingle/src/main/resources/images/Inform.gif diff --git a/src/plugins/sip/src/resources/images/address_book.png b/plugins/jingle/src/main/resources/images/address_book.png similarity index 100% rename from src/plugins/sip/src/resources/images/address_book.png rename to plugins/jingle/src/main/resources/images/address_book.png diff --git a/src/plugins/jingle/src/resources/images/at.gif b/plugins/jingle/src/main/resources/images/at.gif similarity index 100% rename from src/plugins/jingle/src/resources/images/at.gif rename to plugins/jingle/src/main/resources/images/at.gif diff --git a/src/plugins/jingle/src/resources/images/briefcase.png b/plugins/jingle/src/main/resources/images/briefcase.png similarity index 100% rename from src/plugins/jingle/src/resources/images/briefcase.png rename to plugins/jingle/src/main/resources/images/briefcase.png diff --git a/src/plugins/jingle/src/resources/images/btn_dialpad-down.png b/plugins/jingle/src/main/resources/images/btn_dialpad-down.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_dialpad-down.png rename to plugins/jingle/src/main/resources/images/btn_dialpad-down.png diff --git a/src/plugins/jingle/src/resources/images/btn_dialpad-hover.png b/plugins/jingle/src/main/resources/images/btn_dialpad-hover.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_dialpad-hover.png rename to plugins/jingle/src/main/resources/images/btn_dialpad-hover.png diff --git a/src/plugins/jingle/src/resources/images/btn_dialpad.png b/plugins/jingle/src/main/resources/images/btn_dialpad.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_dialpad.png rename to plugins/jingle/src/main/resources/images/btn_dialpad.png diff --git a/src/plugins/jingle/src/resources/images/btn_dialpad_background.png b/plugins/jingle/src/main/resources/images/btn_dialpad_background.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_dialpad_background.png rename to plugins/jingle/src/main/resources/images/btn_dialpad_background.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-big-down.png b/plugins/jingle/src/main/resources/images/btn_phone-big-down.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-big-down.png rename to plugins/jingle/src/main/resources/images/btn_phone-big-down.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-big-hover.png b/plugins/jingle/src/main/resources/images/btn_phone-big-hover.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-big-hover.png rename to plugins/jingle/src/main/resources/images/btn_phone-big-hover.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-big.png b/plugins/jingle/src/main/resources/images/btn_phone-big.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-big.png rename to plugins/jingle/src/main/resources/images/btn_phone-big.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-dial-disabled_24x24.png b/plugins/jingle/src/main/resources/images/btn_phone-dial-disabled_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-dial-disabled_24x24.png rename to plugins/jingle/src/main/resources/images/btn_phone-dial-disabled_24x24.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-dial-down_24x24.png b/plugins/jingle/src/main/resources/images/btn_phone-dial-down_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-dial-down_24x24.png rename to plugins/jingle/src/main/resources/images/btn_phone-dial-down_24x24.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-dial-hover_24x24.png b/plugins/jingle/src/main/resources/images/btn_phone-dial-hover_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-dial-hover_24x24.png rename to plugins/jingle/src/main/resources/images/btn_phone-dial-hover_24x24.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-dial_24x24.png b/plugins/jingle/src/main/resources/images/btn_phone-dial_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-dial_24x24.png rename to plugins/jingle/src/main/resources/images/btn_phone-dial_24x24.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-hangup-big-down.png b/plugins/jingle/src/main/resources/images/btn_phone-hangup-big-down.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-hangup-big-down.png rename to plugins/jingle/src/main/resources/images/btn_phone-hangup-big-down.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-hangup-big-hover.png b/plugins/jingle/src/main/resources/images/btn_phone-hangup-big-hover.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-hangup-big-hover.png rename to plugins/jingle/src/main/resources/images/btn_phone-hangup-big-hover.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-hangup-big.png b/plugins/jingle/src/main/resources/images/btn_phone-hangup-big.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-hangup-big.png rename to plugins/jingle/src/main/resources/images/btn_phone-hangup-big.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-hangup.png b/plugins/jingle/src/main/resources/images/btn_phone-hangup.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-hangup.png rename to plugins/jingle/src/main/resources/images/btn_phone-hangup.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-hangup_24x24.png b/plugins/jingle/src/main/resources/images/btn_phone-hangup_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-hangup_24x24.png rename to plugins/jingle/src/main/resources/images/btn_phone-hangup_24x24.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-redial-big-down.png b/plugins/jingle/src/main/resources/images/btn_phone-redial-big-down.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-redial-big-down.png rename to plugins/jingle/src/main/resources/images/btn_phone-redial-big-down.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-redial-big-hover.png b/plugins/jingle/src/main/resources/images/btn_phone-redial-big-hover.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-redial-big-hover.png rename to plugins/jingle/src/main/resources/images/btn_phone-redial-big-hover.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-redial-big.png b/plugins/jingle/src/main/resources/images/btn_phone-redial-big.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-redial-big.png rename to plugins/jingle/src/main/resources/images/btn_phone-redial-big.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-reg_close-down.png b/plugins/jingle/src/main/resources/images/btn_phone-reg_close-down.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-reg_close-down.png rename to plugins/jingle/src/main/resources/images/btn_phone-reg_close-down.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-reg_close-hover.png b/plugins/jingle/src/main/resources/images/btn_phone-reg_close-hover.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-reg_close-hover.png rename to plugins/jingle/src/main/resources/images/btn_phone-reg_close-hover.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-reg_close.png b/plugins/jingle/src/main/resources/images/btn_phone-reg_close.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-reg_close.png rename to plugins/jingle/src/main/resources/images/btn_phone-reg_close.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-reg_retry-down.png b/plugins/jingle/src/main/resources/images/btn_phone-reg_retry-down.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-reg_retry-down.png rename to plugins/jingle/src/main/resources/images/btn_phone-reg_retry-down.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-reg_retry-hover.png b/plugins/jingle/src/main/resources/images/btn_phone-reg_retry-hover.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-reg_retry-hover.png rename to plugins/jingle/src/main/resources/images/btn_phone-reg_retry-hover.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-reg_retry.png b/plugins/jingle/src/main/resources/images/btn_phone-reg_retry.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-reg_retry.png rename to plugins/jingle/src/main/resources/images/btn_phone-reg_retry.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-sm-down.png b/plugins/jingle/src/main/resources/images/btn_phone-sm-down.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-sm-down.png rename to plugins/jingle/src/main/resources/images/btn_phone-sm-down.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-sm-hover.png b/plugins/jingle/src/main/resources/images/btn_phone-sm-hover.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-sm-hover.png rename to plugins/jingle/src/main/resources/images/btn_phone-sm-hover.png diff --git a/src/plugins/jingle/src/resources/images/btn_phone-sm.png b/plugins/jingle/src/main/resources/images/btn_phone-sm.png similarity index 100% rename from src/plugins/jingle/src/resources/images/btn_phone-sm.png rename to plugins/jingle/src/main/resources/images/btn_phone-sm.png diff --git a/src/plugins/jingle/src/resources/images/callIn_16x16.png b/plugins/jingle/src/main/resources/images/callIn_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/callIn_16x16.png rename to plugins/jingle/src/main/resources/images/callIn_16x16.png diff --git a/src/plugins/jingle/src/resources/images/callList_16x16.png b/plugins/jingle/src/main/resources/images/callList_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/callList_16x16.png rename to plugins/jingle/src/main/resources/images/callList_16x16.png diff --git a/src/plugins/jingle/src/resources/images/callOut_32x32.png b/plugins/jingle/src/main/resources/images/callOut_32x32.png similarity index 100% rename from src/plugins/jingle/src/resources/images/callOut_32x32.png rename to plugins/jingle/src/main/resources/images/callOut_32x32.png diff --git a/src/plugins/jingle/src/resources/images/card.gif b/plugins/jingle/src/main/resources/images/card.gif similarity index 100% rename from src/plugins/jingle/src/resources/images/card.gif rename to plugins/jingle/src/main/resources/images/card.gif diff --git a/src/plugins/jingle/src/resources/images/close_dark.png b/plugins/jingle/src/main/resources/images/close_dark.png similarity index 100% rename from src/plugins/jingle/src/resources/images/close_dark.png rename to plugins/jingle/src/main/resources/images/close_dark.png diff --git a/src/plugins/jingle/src/resources/images/comp.gif b/plugins/jingle/src/main/resources/images/comp.gif similarity index 100% rename from src/plugins/jingle/src/resources/images/comp.gif rename to plugins/jingle/src/main/resources/images/comp.gif diff --git a/src/plugins/jingle/src/resources/images/contact_48x48.png b/plugins/jingle/src/main/resources/images/contact_48x48.png similarity index 100% rename from src/plugins/jingle/src/resources/images/contact_48x48.png rename to plugins/jingle/src/main/resources/images/contact_48x48.png diff --git a/src/plugins/jingle/src/resources/images/delete_24x24.png b/plugins/jingle/src/main/resources/images/delete_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/delete_24x24.png rename to plugins/jingle/src/main/resources/images/delete_24x24.png diff --git a/src/plugins/jingle/src/resources/images/delete_32x32.png b/plugins/jingle/src/main/resources/images/delete_32x32.png similarity index 100% rename from src/plugins/jingle/src/resources/images/delete_32x32.png rename to plugins/jingle/src/main/resources/images/delete_32x32.png diff --git a/src/plugins/jingle/src/resources/images/dial.png b/plugins/jingle/src/main/resources/images/dial.png similarity index 100% rename from src/plugins/jingle/src/resources/images/dial.png rename to plugins/jingle/src/main/resources/images/dial.png diff --git a/src/plugins/jingle/src/resources/images/dialpad_16x16.png b/plugins/jingle/src/main/resources/images/dialpad_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/dialpad_16x16.png rename to plugins/jingle/src/main/resources/images/dialpad_16x16.png diff --git a/src/plugins/sip/src/resources/images/divider.png b/plugins/jingle/src/main/resources/images/divider.png similarity index 100% rename from src/plugins/sip/src/resources/images/divider.png rename to plugins/jingle/src/main/resources/images/divider.png diff --git a/src/plugins/jingle/src/resources/images/hangup_32x32.png b/plugins/jingle/src/main/resources/images/hangup_32x32.png similarity index 100% rename from src/plugins/jingle/src/resources/images/hangup_32x32.png rename to plugins/jingle/src/main/resources/images/hangup_32x32.png diff --git a/src/plugins/jingle/src/resources/images/history.png b/plugins/jingle/src/main/resources/images/history.png similarity index 100% rename from src/plugins/jingle/src/resources/images/history.png rename to plugins/jingle/src/main/resources/images/history.png diff --git a/src/plugins/jingle/src/resources/images/hold_128x128.png b/plugins/jingle/src/main/resources/images/hold_128x128.png similarity index 100% rename from src/plugins/jingle/src/resources/images/hold_128x128.png rename to plugins/jingle/src/main/resources/images/hold_128x128.png diff --git a/src/plugins/jingle/src/resources/images/hold_32x32.png b/plugins/jingle/src/main/resources/images/hold_32x32.png similarity index 100% rename from src/plugins/jingle/src/resources/images/hold_32x32.png rename to plugins/jingle/src/main/resources/images/hold_32x32.png diff --git a/src/plugins/jingle/src/resources/images/home.png b/plugins/jingle/src/main/resources/images/home.png similarity index 100% rename from src/plugins/jingle/src/resources/images/home.png rename to plugins/jingle/src/main/resources/images/home.png diff --git a/src/plugins/jingle/src/resources/images/icon_call-incoming_42x22.png b/plugins/jingle/src/main/resources/images/icon_call-incoming_42x22.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_call-incoming_42x22.png rename to plugins/jingle/src/main/resources/images/icon_call-incoming_42x22.png diff --git a/src/plugins/sip/src/resources/images/icon_computer_16x16.png b/plugins/jingle/src/main/resources/images/icon_computer_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_computer_16x16.png rename to plugins/jingle/src/main/resources/images/icon_computer_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_grey_microphone_16x16.png b/plugins/jingle/src/main/resources/images/icon_grey_microphone_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_grey_microphone_16x16.png rename to plugins/jingle/src/main/resources/images/icon_grey_microphone_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_grey_phone-hangup_24x24.png b/plugins/jingle/src/main/resources/images/icon_grey_phone-hangup_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_grey_phone-hangup_24x24.png rename to plugins/jingle/src/main/resources/images/icon_grey_phone-hangup_24x24.png diff --git a/src/plugins/jingle/src/resources/images/icon_grey_phone-hold_24x24.png b/plugins/jingle/src/main/resources/images/icon_grey_phone-hold_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_grey_phone-hold_24x24.png rename to plugins/jingle/src/main/resources/images/icon_grey_phone-hold_24x24.png diff --git a/src/plugins/jingle/src/resources/images/icon_grey_phone-mute_24x24.png b/plugins/jingle/src/main/resources/images/icon_grey_phone-mute_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_grey_phone-mute_24x24.png rename to plugins/jingle/src/main/resources/images/icon_grey_phone-mute_24x24.png diff --git a/src/plugins/jingle/src/resources/images/icon_grey_phone-redial_24x24.png b/plugins/jingle/src/main/resources/images/icon_grey_phone-redial_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_grey_phone-redial_24x24.png rename to plugins/jingle/src/main/resources/images/icon_grey_phone-redial_24x24.png diff --git a/src/plugins/jingle/src/resources/images/icon_grey_phone-transfer_24x24.png b/plugins/jingle/src/main/resources/images/icon_grey_phone-transfer_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_grey_phone-transfer_24x24.png rename to plugins/jingle/src/main/resources/images/icon_grey_phone-transfer_24x24.png diff --git a/src/plugins/jingle/src/resources/images/icon_grey_speaker_16x16.png b/plugins/jingle/src/main/resources/images/icon_grey_speaker_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_grey_speaker_16x16.png rename to plugins/jingle/src/main/resources/images/icon_grey_speaker_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_home_16x16.png b/plugins/jingle/src/main/resources/images/icon_home_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_home_16x16.png rename to plugins/jingle/src/main/resources/images/icon_home_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_microphone_16x16.png b/plugins/jingle/src/main/resources/images/icon_microphone_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_microphone_16x16.png rename to plugins/jingle/src/main/resources/images/icon_microphone_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_microphone_24x24.png b/plugins/jingle/src/main/resources/images/icon_microphone_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_microphone_24x24.png rename to plugins/jingle/src/main/resources/images/icon_microphone_24x24.png diff --git a/src/plugins/jingle/src/resources/images/icon_mobile_16x16.png b/plugins/jingle/src/main/resources/images/icon_mobile_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_mobile_16x16.png rename to plugins/jingle/src/main/resources/images/icon_mobile_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_numberpad_12x15.png b/plugins/jingle/src/main/resources/images/icon_numberpad_12x15.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_numberpad_12x15.png rename to plugins/jingle/src/main/resources/images/icon_numberpad_12x15.png diff --git a/src/plugins/sip/src/resources/images/icon_phone-call_16x16.png b/plugins/jingle/src/main/resources/images/icon_phone-call_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_phone-call_16x16.png rename to plugins/jingle/src/main/resources/images/icon_phone-call_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_phone-conference_16x16.png b/plugins/jingle/src/main/resources/images/icon_phone-conference_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_phone-conference_16x16.png rename to plugins/jingle/src/main/resources/images/icon_phone-conference_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_phone-hangup_16x16.png b/plugins/jingle/src/main/resources/images/icon_phone-hangup_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_phone-hangup_16x16.png rename to plugins/jingle/src/main/resources/images/icon_phone-hangup_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_phone-hangup_24x24.png b/plugins/jingle/src/main/resources/images/icon_phone-hangup_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_phone-hangup_24x24.png rename to plugins/jingle/src/main/resources/images/icon_phone-hangup_24x24.png diff --git a/src/plugins/jingle/src/resources/images/icon_phone-history_16x16.png b/plugins/jingle/src/main/resources/images/icon_phone-history_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_phone-history_16x16.png rename to plugins/jingle/src/main/resources/images/icon_phone-history_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_phone-hold_16x16.png b/plugins/jingle/src/main/resources/images/icon_phone-hold_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_phone-hold_16x16.png rename to plugins/jingle/src/main/resources/images/icon_phone-hold_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_phone-hold_24x24.png b/plugins/jingle/src/main/resources/images/icon_phone-hold_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_phone-hold_24x24.png rename to plugins/jingle/src/main/resources/images/icon_phone-hold_24x24.png diff --git a/src/plugins/jingle/src/resources/images/icon_phone-mute_16x16.png b/plugins/jingle/src/main/resources/images/icon_phone-mute_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_phone-mute_16x16.png rename to plugins/jingle/src/main/resources/images/icon_phone-mute_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_phone-mute_24x24.png b/plugins/jingle/src/main/resources/images/icon_phone-mute_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_phone-mute_24x24.png rename to plugins/jingle/src/main/resources/images/icon_phone-mute_24x24.png diff --git a/src/plugins/jingle/src/resources/images/icon_phone-pickup_24x24.png b/plugins/jingle/src/main/resources/images/icon_phone-pickup_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_phone-pickup_24x24.png rename to plugins/jingle/src/main/resources/images/icon_phone-pickup_24x24.png diff --git a/src/plugins/jingle/src/resources/images/icon_phone-reject_24x24.png b/plugins/jingle/src/main/resources/images/icon_phone-reject_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_phone-reject_24x24.png rename to plugins/jingle/src/main/resources/images/icon_phone-reject_24x24.png diff --git a/src/plugins/jingle/src/resources/images/icon_phone-transfer_16x16.png b/plugins/jingle/src/main/resources/images/icon_phone-transfer_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_phone-transfer_16x16.png rename to plugins/jingle/src/main/resources/images/icon_phone-transfer_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_phone-transfer_24x24.png b/plugins/jingle/src/main/resources/images/icon_phone-transfer_24x24.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_phone-transfer_24x24.png rename to plugins/jingle/src/main/resources/images/icon_phone-transfer_24x24.png diff --git a/src/plugins/jingle/src/resources/images/icon_phone-voicemail_16x16.png b/plugins/jingle/src/main/resources/images/icon_phone-voicemail_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_phone-voicemail_16x16.png rename to plugins/jingle/src/main/resources/images/icon_phone-voicemail_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_reciever_22x22.png b/plugins/jingle/src/main/resources/images/icon_reciever_22x22.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_reciever_22x22.png rename to plugins/jingle/src/main/resources/images/icon_reciever_22x22.png diff --git a/src/plugins/jingle/src/resources/images/icon_speaker_16x16.png b/plugins/jingle/src/main/resources/images/icon_speaker_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_speaker_16x16.png rename to plugins/jingle/src/main/resources/images/icon_speaker_16x16.png diff --git a/src/plugins/jingle/src/resources/images/icon_work_16x16.png b/plugins/jingle/src/main/resources/images/icon_work_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/icon_work_16x16.png rename to plugins/jingle/src/main/resources/images/icon_work_16x16.png diff --git a/src/plugins/jingle/src/resources/images/log_history.png b/plugins/jingle/src/main/resources/images/log_history.png similarity index 100% rename from src/plugins/jingle/src/resources/images/log_history.png rename to plugins/jingle/src/main/resources/images/log_history.png diff --git a/src/plugins/sip/src/resources/images/message.png b/plugins/jingle/src/main/resources/images/message.png similarity index 100% rename from src/plugins/sip/src/resources/images/message.png rename to plugins/jingle/src/main/resources/images/message.png diff --git a/src/plugins/jingle/src/resources/images/microphone.png b/plugins/jingle/src/main/resources/images/microphone.png similarity index 100% rename from src/plugins/jingle/src/resources/images/microphone.png rename to plugins/jingle/src/main/resources/images/microphone.png diff --git a/src/plugins/jingle/src/resources/images/mute.png b/plugins/jingle/src/main/resources/images/mute.png similarity index 100% rename from src/plugins/jingle/src/resources/images/mute.png rename to plugins/jingle/src/main/resources/images/mute.png diff --git a/src/plugins/jingle/src/resources/images/mute_128x128.png b/plugins/jingle/src/main/resources/images/mute_128x128.png similarity index 100% rename from src/plugins/jingle/src/resources/images/mute_128x128.png rename to plugins/jingle/src/main/resources/images/mute_128x128.png diff --git a/src/plugins/jingle/src/resources/images/mute_32x32.png b/plugins/jingle/src/main/resources/images/mute_32x32.png similarity index 100% rename from src/plugins/jingle/src/resources/images/mute_32x32.png rename to plugins/jingle/src/main/resources/images/mute_32x32.png diff --git a/src/plugins/jingle/src/resources/images/noMute_32x32.png b/plugins/jingle/src/main/resources/images/noMute_32x32.png similarity index 100% rename from src/plugins/jingle/src/resources/images/noMute_32x32.png rename to plugins/jingle/src/main/resources/images/noMute_32x32.png diff --git a/src/plugins/jingle/src/resources/images/off.gif b/plugins/jingle/src/main/resources/images/off.gif similarity index 100% rename from src/plugins/jingle/src/resources/images/off.gif rename to plugins/jingle/src/main/resources/images/off.gif diff --git a/src/plugins/jingle/src/resources/images/on-phone.png b/plugins/jingle/src/main/resources/images/on-phone.png similarity index 100% rename from src/plugins/jingle/src/resources/images/on-phone.png rename to plugins/jingle/src/main/resources/images/on-phone.png diff --git a/src/plugins/jingle/src/resources/images/on.gif b/plugins/jingle/src/main/resources/images/on.gif similarity index 100% rename from src/plugins/jingle/src/resources/images/on.gif rename to plugins/jingle/src/main/resources/images/on.gif diff --git a/src/plugins/jingle/src/resources/images/on_phone_128x128.png b/plugins/jingle/src/main/resources/images/on_phone_128x128.png similarity index 100% rename from src/plugins/jingle/src/resources/images/on_phone_128x128.png rename to plugins/jingle/src/main/resources/images/on_phone_128x128.png diff --git a/src/plugins/jingle/src/resources/images/phone_call.png b/plugins/jingle/src/main/resources/images/phone_call.png similarity index 100% rename from src/plugins/jingle/src/resources/images/phone_call.png rename to plugins/jingle/src/main/resources/images/phone_call.png diff --git a/src/plugins/jingle/src/resources/images/phone_hang_up.png b/plugins/jingle/src/main/resources/images/phone_hang_up.png similarity index 100% rename from src/plugins/jingle/src/resources/images/phone_hang_up.png rename to plugins/jingle/src/main/resources/images/phone_hang_up.png diff --git a/src/plugins/jingle/src/resources/images/phone_hang_up_128x128.png b/plugins/jingle/src/main/resources/images/phone_hang_up_128x128.png similarity index 100% rename from src/plugins/jingle/src/resources/images/phone_hang_up_128x128.png rename to plugins/jingle/src/main/resources/images/phone_hang_up_128x128.png diff --git a/src/plugins/jingle/src/resources/images/phone_hold.png b/plugins/jingle/src/main/resources/images/phone_hold.png similarity index 100% rename from src/plugins/jingle/src/resources/images/phone_hold.png rename to plugins/jingle/src/main/resources/images/phone_hold.png diff --git a/src/plugins/jingle/src/resources/images/phone_pick_up.png b/plugins/jingle/src/main/resources/images/phone_pick_up.png similarity index 100% rename from src/plugins/jingle/src/resources/images/phone_pick_up.png rename to plugins/jingle/src/main/resources/images/phone_pick_up.png diff --git a/src/plugins/jingle/src/resources/images/phone_recall.png b/plugins/jingle/src/main/resources/images/phone_recall.png similarity index 100% rename from src/plugins/jingle/src/resources/images/phone_recall.png rename to plugins/jingle/src/main/resources/images/phone_recall.png diff --git a/src/plugins/jingle/src/resources/images/receiver.png b/plugins/jingle/src/main/resources/images/receiver.png similarity index 100% rename from src/plugins/jingle/src/resources/images/receiver.png rename to plugins/jingle/src/main/resources/images/receiver.png diff --git a/src/plugins/jingle/src/resources/images/receiver2.png b/plugins/jingle/src/main/resources/images/receiver2.png similarity index 100% rename from src/plugins/jingle/src/resources/images/receiver2.png rename to plugins/jingle/src/main/resources/images/receiver2.png diff --git a/src/plugins/jingle/src/resources/images/receiver2_48x48.png b/plugins/jingle/src/main/resources/images/receiver2_48x48.png similarity index 100% rename from src/plugins/jingle/src/resources/images/receiver2_48x48.png rename to plugins/jingle/src/main/resources/images/receiver2_48x48.png diff --git a/src/plugins/jingle/src/resources/images/reject_32x32.png b/plugins/jingle/src/main/resources/images/reject_32x32.png similarity index 100% rename from src/plugins/jingle/src/resources/images/reject_32x32.png rename to plugins/jingle/src/main/resources/images/reject_32x32.png diff --git a/src/plugins/jingle/src/resources/images/resumeCall_32x32.png b/plugins/jingle/src/main/resources/images/resumeCall_32x32.png similarity index 100% rename from src/plugins/jingle/src/resources/images/resumeCall_32x32.png rename to plugins/jingle/src/main/resources/images/resumeCall_32x32.png diff --git a/src/plugins/jingle/src/resources/images/tab_active.png b/plugins/jingle/src/main/resources/images/tab_active.png similarity index 100% rename from src/plugins/jingle/src/resources/images/tab_active.png rename to plugins/jingle/src/main/resources/images/tab_active.png diff --git a/src/plugins/jingle/src/resources/images/telephone.png b/plugins/jingle/src/main/resources/images/telephone.png similarity index 100% rename from src/plugins/jingle/src/resources/images/telephone.png rename to plugins/jingle/src/main/resources/images/telephone.png diff --git a/src/plugins/jingle/src/resources/images/titlePane.png b/plugins/jingle/src/main/resources/images/titlePane.png similarity index 100% rename from src/plugins/jingle/src/resources/images/titlePane.png rename to plugins/jingle/src/main/resources/images/titlePane.png diff --git a/src/plugins/jingle/src/resources/images/toaster_btn-accept.png b/plugins/jingle/src/main/resources/images/toaster_btn-accept.png similarity index 100% rename from src/plugins/jingle/src/resources/images/toaster_btn-accept.png rename to plugins/jingle/src/main/resources/images/toaster_btn-accept.png diff --git a/src/plugins/jingle/src/resources/images/toaster_btn-reject.png b/plugins/jingle/src/main/resources/images/toaster_btn-reject.png similarity index 100% rename from src/plugins/jingle/src/resources/images/toaster_btn-reject.png rename to plugins/jingle/src/main/resources/images/toaster_btn-reject.png diff --git a/src/plugins/jingle/src/resources/images/transfer.png b/plugins/jingle/src/main/resources/images/transfer.png similarity index 100% rename from src/plugins/jingle/src/resources/images/transfer.png rename to plugins/jingle/src/main/resources/images/transfer.png diff --git a/src/plugins/jingle/src/resources/images/voicemail.png b/plugins/jingle/src/main/resources/images/voicemail.png similarity index 100% rename from src/plugins/jingle/src/resources/images/voicemail.png rename to plugins/jingle/src/main/resources/images/voicemail.png diff --git a/src/plugins/jingle/src/resources/images/voicemail_16x16.png b/plugins/jingle/src/main/resources/images/voicemail_16x16.png similarity index 100% rename from src/plugins/jingle/src/resources/images/voicemail_16x16.png rename to plugins/jingle/src/main/resources/images/voicemail_16x16.png diff --git a/src/plugins/jingle/src/resources/images/volume.png b/plugins/jingle/src/main/resources/images/volume.png similarity index 100% rename from src/plugins/jingle/src/resources/images/volume.png rename to plugins/jingle/src/main/resources/images/volume.png diff --git a/src/plugins/jingle/src/resources/sounds/ringing.wav b/plugins/jingle/src/main/resources/sounds/ringing.wav similarity index 100% rename from src/plugins/jingle/src/resources/sounds/ringing.wav rename to plugins/jingle/src/main/resources/sounds/ringing.wav diff --git a/plugins/meet/pom.xml b/plugins/meet/pom.xml new file mode 100644 index 000000000..8159fe1ce --- /dev/null +++ b/plugins/meet/pom.xml @@ -0,0 +1,29 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + meet + 0.3.0 + + Online Meetings Plugin + Allows users to join audio and video conferences supported by XEP-0483: HTTP Online Meetings. + It provides a button from a Multi User Chat (MUC) room or chat window within the Spark client to open a browser window using the URL provided. + Instead of depending on the default browser, it uses Electron. + + + + + Dele Olajide + + Author + + + + diff --git a/plugins/meet/readme.md b/plugins/meet/readme.md new file mode 100644 index 000000000..ba309c5c6 --- /dev/null +++ b/plugins/meet/readme.md @@ -0,0 +1,11 @@ +This is a plugin for Spark that allows users to join audio and video conferences supported by [XEP-0483: HTTP Online Meetings](https://xmpp.org/extensions/xep-0483.html) +See the documentation for more details. It provides a button from a Multi User Chat (MUC) room or chat window within the Spark client, to open a Chrome window using the URL provided. +It uses Electron instead of depending on Chrome installed and configured as the default browser. + + ![](https://user-images.githubusercontent.com/110731/91915397-5d304600-ecb2-11ea-93b1-d822f13f1509.png) + +It is a much better user experience than opening a Chrome browser window out of context somewhere else. +Screen sharing is not yet working. All Electron runtime platforms (windows, Linux & OSX) are supported. I have only tested it at home on my windows desktop. +Feeback will be appreciated from Linux and OSX users. + +![](https://user-images.githubusercontent.com/110731/196530400-a350cc2c-7f53-4148-b230-ebb7b8cc404a.png) \ No newline at end of file diff --git a/plugins/meet/src/main/java/de/mxro/process/ProcessListener.java b/plugins/meet/src/main/java/de/mxro/process/ProcessListener.java new file mode 100644 index 000000000..f9ea69291 --- /dev/null +++ b/plugins/meet/src/main/java/de/mxro/process/ProcessListener.java @@ -0,0 +1,37 @@ +package de.mxro.process; + +/** + * A listener to intercept outputs from the process. + * + * @author Max + * + */ +public interface ProcessListener { + + /** + * When the process wrote a line to its standard output stream. + * + * @param line + */ + void onOutputLine(String line); + + /** + * When the process wrote a line to its error output stream. + * + * @param line + */ + void onErrorLine(String line); + + /** + * When the output stream is closed. + */ + void onProcessQuit(int returnValue); + + /** + * When an unexpected error is thrown while interacting with the process. + * + * @param t + */ + void onError(Throwable t); + +} diff --git a/plugins/meet/src/main/java/de/mxro/process/Spawn.java b/plugins/meet/src/main/java/de/mxro/process/Spawn.java new file mode 100644 index 000000000..017b7f9a0 --- /dev/null +++ b/plugins/meet/src/main/java/de/mxro/process/Spawn.java @@ -0,0 +1,129 @@ +package de.mxro.process; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CountDownLatch; + +import de.mxro.process.internal.Engine; + +public class Spawn { + + /** + * Start a new process. + * + * @param command + * @param listener + * @param folder + * @return + */ + public static XProcess startProcess(final String command, final File folder, final ProcessListener listener) { + return startProcess(command.split(" "), folder, listener); + } + + public static XProcess startProcess(final String[] command, final File folder, final ProcessListener listener) { + return Engine.startProcess(command, listener, folder); + } + + public static String runCommand(final String command, final File folder) { + return runCommand(command.split(" "), folder); + } + + /** + * Runs a command in a new process and stops the process thereafter. + * + * @param command + * @param folder + */ + public static String runCommand(final String[] command, final File folder) { + + final CountDownLatch latch = new CountDownLatch(2); + + final List exceptions = Collections.synchronizedList(new LinkedList<>()); + + final List output = Collections.synchronizedList(new LinkedList<>()); + + latch.countDown(); + final XProcess process = startProcess(command, folder, new ProcessListener() { + + @Override + public void onProcessQuit(final int returnValue) { + latch.countDown(); + } + + @Override + public void onOutputLine(final String line) { + output.add(line); + } + + @Override + public void onErrorLine(final String line) { + output.add(line); + } + + @Override + public void onError(final Throwable t) { + exceptions.add(t); + } + }); + + try { + latch.await(); + // Thread.sleep(300); // just wait for input to gobble in + } catch (final InterruptedException e) { + throw new RuntimeException(e); + } + + if (exceptions.size() > 0) { + throw new RuntimeException(exceptions.get(0)); + } + + final StringBuilder sb = new StringBuilder(); + for (final String line : new ArrayList<>(output)) { + sb.append(line).append("\n"); + } + + process.destory(); + return sb.toString(); + } + + public interface Callback { + void onDone(Type t); + } + + /** + * Runs bash scripts (*.sh) in a UNIX environment. + * + * @param bashScriptFile + * @return + */ + public static String runBashScript(final File bashScriptFile) { + return runCommand("/bin/bash -c " + bashScriptFile.getAbsolutePath(), bashScriptFile.getParentFile()); + } + + public static boolean isWindows() { + return System.getProperty("os.name").startsWith("Windows"); + } + + public static String sh(final File folder, final String bashCommand) { + + if (!isWindows()) { + return runCommand(new String[] { "/bin/bash", "-c", bashCommand }, folder); + } else { + return runCommand(new String[] { "cmd.exe", "/C", bashCommand }, folder); + } + } + + /** + * Executes a bash command. + * + * @param bashCommand + * @return + */ + public static String sh(final String bashCommand) { + return sh(null, bashCommand); + } + +} diff --git a/plugins/meet/src/main/java/de/mxro/process/XProcess.java b/plugins/meet/src/main/java/de/mxro/process/XProcess.java new file mode 100644 index 000000000..9bc7b9577 --- /dev/null +++ b/plugins/meet/src/main/java/de/mxro/process/XProcess.java @@ -0,0 +1,24 @@ +package de.mxro.process; + +/** + * A wrapper for {@link java.lang.Process}. + * + * @author Max Rohde + * + */ +public interface XProcess { + + /** + * Call to push the specified {@link String} into the started processes + * input. + * + * @param line + */ + void sendLine(String line); + + /** + * Try to destroy the process + */ + void destory(); + +} diff --git a/plugins/meet/src/main/java/de/mxro/process/internal/Engine.java b/plugins/meet/src/main/java/de/mxro/process/internal/Engine.java new file mode 100644 index 000000000..e5ada4c47 --- /dev/null +++ b/plugins/meet/src/main/java/de/mxro/process/internal/Engine.java @@ -0,0 +1,169 @@ +package de.mxro.process.internal; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.lang.ProcessBuilder.Redirect; +import java.util.Date; +import java.util.concurrent.atomic.AtomicLong; + +import de.mxro.process.ProcessListener; +import de.mxro.process.XProcess; + +public class Engine { + + public static XProcess startProcess(final String[] command, + final ProcessListener listener, final File folder) { + + final ProcessBuilder pb; + final Process process; + + try { + + pb = new ProcessBuilder(command); + pb.directory(folder); + pb.redirectOutput(Redirect.PIPE); + pb.redirectInput(Redirect.PIPE); + process = pb.start(); + } catch (final IOException e) { + throw new RuntimeException(e); + } + + final AtomicLong lastOutput = new AtomicLong(); + final long startTime = new Date().getTime(); + lastOutput.set(0); + + + + final OutputStream outputStream = process.getOutputStream(); + final InputStream inputStream = process.getInputStream(); + final InputStream errorStream = process.getErrorStream(); + + + //BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + + +// String line; +// try { +// line = reader.readLine(); +// while (line != null && !line.trim().equals("--EOF--")) { +// listener.onOutputLine(line); +// line = reader.readLine(); +// } +// } catch (IOException e1) { +// // TODO Auto-generated catch block +// e1.printStackTrace(); +// } + + + final StreamReader streamReader = new StreamReader(inputStream, + new StreamListener() { + + @Override + public void onOutputLine(final String line) { + //System.out.println("Receiving line"); + lastOutput.set(new Date().getTime()); + listener.onOutputLine(line); + } + + @Override + public void onError(final Throwable t) { + listener.onError(new Exception( + "Error while reading standard output", t)); + } + + @Override + public void onClosed() { + + } + }); + + + + final StreamReader errorStreamReader = new StreamReader(errorStream, + new StreamListener() { + + @Override + public void onOutputLine(final String line) { + lastOutput.set(new Date().getTime()); + listener.onErrorLine(line); + } + + @Override + public void onError(final Throwable t) { + listener.onError(new Exception( + "Error while reading error output", t)); + } + + @Override + public void onClosed() { + + } + }); + + new Thread(errorStreamReader::read).start(); + + new Thread(() -> { + try { + streamReader.read(); + + final int returnValue = process.waitFor(); + + //while (lastOutput.get() == 0 && new Date().getTime() - startTime < 500) { + // Thread.sleep(10); + //} + + //while ( new Date().getTime() - lastOutput.get() < 1000) { + // System.out.println("DELAY ... "+(new Date().getTime() - lastOutput.get())); + // Thread.sleep(500); + //} + //System.out.println("processes finished with "+returnValue); + + listener.onProcessQuit(returnValue); + } catch (final InterruptedException e) { + listener.onError(e); + } + }).start(); + + return new XProcess() { + + @Override + public synchronized void sendLine(final String line) { + final BufferedWriter writer = new BufferedWriter( + new OutputStreamWriter(outputStream)); + try { + writer.append(line); + } catch (final IOException e) { + listener.onError(e); + } + } + + @Override + public void destory() { + process.destroy(); + try { + process.waitFor(); + } catch (final InterruptedException e) { + throw new RuntimeException(e); + } + + try { + errorStreamReader.stop(); + + outputStream.close(); + inputStream.close(); + errorStream.close(); + + } catch (final IOException e) { + listener.onError(e); + } + + } + }; + + } + +} diff --git a/plugins/meet/src/main/java/de/mxro/process/internal/StreamListener.java b/plugins/meet/src/main/java/de/mxro/process/internal/StreamListener.java new file mode 100644 index 000000000..b24a945d5 --- /dev/null +++ b/plugins/meet/src/main/java/de/mxro/process/internal/StreamListener.java @@ -0,0 +1,7 @@ +package de.mxro.process.internal; + +public interface StreamListener { + void onOutputLine(String line); + void onClosed(); + void onError(Throwable t); +} diff --git a/plugins/meet/src/main/java/de/mxro/process/internal/StreamReader.java b/plugins/meet/src/main/java/de/mxro/process/internal/StreamReader.java new file mode 100644 index 000000000..029458989 --- /dev/null +++ b/plugins/meet/src/main/java/de/mxro/process/internal/StreamReader.java @@ -0,0 +1,99 @@ +package de.mxro.process.internal; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; + +public class StreamReader { + + private final class WorkerThread extends Thread { + private final StreamListener listener; + private final InputStream stream; + + private transient int timeout; + + private WorkerThread(final StreamListener listener, + final InputStream stream) { + this.listener = listener; + this.stream = stream; + this.timeout = 10; + } + + @Override + public void run() { + final BufferedReader reader = new BufferedReader( + new InputStreamReader(stream)); + try { + String read; + + this.timeout = 10; + + read = reader.readLine(); + while (!stop && read != null && !read.trim().equals("--EOF--")) { + if (stop) { + stopReader(); + return; + } + + if (read != null) { + listener.onOutputLine(read); + } + // waitForInput(); + read = reader.readLine(); + } + + } catch (final Exception e) { + listener.onError(e); + } + + } + + /** + * Wait longer and longer to not keep CPU busy. + */ + private void waitForInput() { + try { + Thread.sleep(this.timeout); + } catch (final InterruptedException e) { + throw new RuntimeException(); + } + + if (this.timeout < 2000) { + this.timeout = this.timeout + (this.timeout); + } + + } + + private void stopReader() { + //stream.close(); + stopped = true; + listener.onClosed(); + } + } + + private final Thread t; + private volatile boolean stop = false; + private volatile boolean stopped = false; + + public void read() { + t.start(); + } + + public void stop() { + + if (stopped) { + return; + } + stop = true; + //while (!stopped) { + // Thread.yield(); + //} + } + + public StreamReader(final InputStream stream, final StreamListener listener) { + super(); + this.t = new WorkerThread(listener, stream); + + } + +} diff --git a/plugins/meet/src/main/java/org/jitsi/util/OSUtils.java b/plugins/meet/src/main/java/org/jitsi/util/OSUtils.java new file mode 100644 index 000000000..98d934605 --- /dev/null +++ b/plugins/meet/src/main/java/org/jitsi/util/OSUtils.java @@ -0,0 +1,188 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package org.jitsi.util; + +/** + * Utility fields for OS detection. + * + * @author Sebastien Vincent + * @author Lubomir Marinov + */ +public class OSUtils +{ + + /** true if architecture is 32 bit. */ + public static final boolean IS_32_BIT; + + /** true if architecture is 64 bit. */ + public static final boolean IS_64_BIT; + + /** true if OS is Android */ + public static final boolean IS_ANDROID; + + /** true if OS is Linux. */ + public static final boolean IS_LINUX; + + /** true if OS is Linux 32-bit. */ + public static final boolean IS_LINUX32; + + /** true if OS is Linux 64-bit. */ + public static final boolean IS_LINUX64; + + /** true if OS is MacOSX. */ + public static final boolean IS_MAC; + + /** true if OS is MacOSX 32-bit. */ + public static final boolean IS_MAC32; + + /** true if OS is MacOSX 64-bit. */ + public static final boolean IS_MAC64; + + /** true if OS is Windows. */ + public static final boolean IS_WINDOWS; + + /** true if OS is Windows 32-bit. */ + public static final boolean IS_WINDOWS32; + + /** true if OS is Windows 64-bit. */ + public static final boolean IS_WINDOWS64; + + /** true if OS is Windows Vista. */ + public static final boolean IS_WINDOWS_VISTA; + + /** true if OS is Windows 7. */ + public static final boolean IS_WINDOWS_7; + + /** true if OS is Windows 8. */ + public static final boolean IS_WINDOWS_8; + + /** true if OS is FreeBSD. */ + public static final boolean IS_FREEBSD; + + static + { + // OS + String osName = System.getProperty("os.name"); + + if (osName == null) + { + IS_ANDROID = false; + IS_LINUX = false; + IS_MAC = false; + IS_WINDOWS = false; + IS_WINDOWS_VISTA = false; + IS_WINDOWS_7 = false; + IS_WINDOWS_8 = false; + IS_FREEBSD = false; + } + else if (osName.startsWith("Linux")) + { + String javaVmName = System.getProperty("java.vm.name"); + + if ((javaVmName != null) && javaVmName.equalsIgnoreCase("Dalvik")) + { + IS_ANDROID = true; + IS_LINUX = false; + } + else + { + IS_ANDROID = false; + IS_LINUX = true; + } + IS_MAC = false; + IS_WINDOWS = false; + IS_WINDOWS_VISTA = false; + IS_WINDOWS_7 = false; + IS_WINDOWS_8 = false; + IS_FREEBSD = false; + } + else if (osName.startsWith("Mac")) + { + IS_ANDROID = false; + IS_LINUX = false; + IS_MAC = true; + IS_WINDOWS = false; + IS_WINDOWS_VISTA = false; + IS_WINDOWS_7 = false; + IS_WINDOWS_8 = false; + IS_FREEBSD = false; + } + else if (osName.startsWith("Windows")) + { + IS_ANDROID = false; + IS_LINUX = false; + IS_MAC = false; + IS_WINDOWS = true; + IS_WINDOWS_VISTA = (osName.contains("Vista")); + IS_WINDOWS_7 = (osName.contains("7")); + IS_WINDOWS_8 = (osName.contains("8")); + IS_FREEBSD = false; + } + else if (osName.startsWith("FreeBSD")) + { + IS_ANDROID = false; + IS_LINUX = false; + IS_MAC = false; + IS_WINDOWS = false; + IS_WINDOWS_VISTA = false; + IS_WINDOWS_7 = false; + IS_WINDOWS_8 = false; + IS_FREEBSD = true; + } + else + { + IS_ANDROID = false; + IS_LINUX = false; + IS_MAC = false; + IS_WINDOWS = false; + IS_WINDOWS_VISTA = false; + IS_WINDOWS_7 = false; + IS_WINDOWS_8 = false; + IS_FREEBSD = false; + } + + // arch i.e. x86, amd64 + String osArch = System.getProperty("sun.arch.data.model"); + + if(osArch == null) + { + IS_32_BIT = true; + IS_64_BIT = false; + } + else if (osArch.contains("32")) + { + IS_32_BIT = true; + IS_64_BIT = false; + } + else if (osArch.contains("64")) + { + IS_32_BIT = false; + IS_64_BIT = true; + } + else + { + IS_32_BIT = false; + IS_64_BIT = false; + } + + // OS && arch + IS_LINUX32 = IS_LINUX && IS_32_BIT; + IS_LINUX64 = IS_LINUX && IS_64_BIT; + IS_MAC32 = IS_MAC && IS_32_BIT; + IS_MAC64 = IS_MAC && IS_64_BIT; + IS_WINDOWS32 = IS_WINDOWS && IS_32_BIT; + IS_WINDOWS64 = IS_WINDOWS && IS_64_BIT; + } + + /** + * Allows the extending of the OSUtils class but disallows + * initializing non-extended OSUtils instances. + */ + protected OSUtils() + { + } +} diff --git a/plugins/meet/src/main/java/org/jivesoftware/spark/plugin/ofmeet/ChatRoomDecorator.java b/plugins/meet/src/main/java/org/jivesoftware/spark/plugin/ofmeet/ChatRoomDecorator.java new file mode 100644 index 000000000..c412bdf45 --- /dev/null +++ b/plugins/meet/src/main/java/org/jivesoftware/spark/plugin/ofmeet/ChatRoomDecorator.java @@ -0,0 +1,50 @@ +/** + * Copyright (C) 2004-2010 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.spark.plugin.ofmeet; + +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.util.*; +import org.jivesoftware.spark.util.log.*; + +public class ChatRoomDecorator +{ + public RolloverButton ofmeetButton; + public final ChatRoom room; + + public ChatRoomDecorator(final ChatRoom room, final SparkMeetPlugin plugin) + { + this.room = room; + ofmeetButton = new RolloverButton(SparkMeetResource.PLUGIN_ICON); + ofmeetButton.setToolTipText(GraphicUtils.createToolTip(SparkMeetResource.getString("name"))); + final String roomId = room.getBareJid().getLocalpart().toString(); + final String sessionID = String.valueOf(System.currentTimeMillis()); + + ofmeetButton.addActionListener(event -> { + String newUrl, newRoomId = roomId + "-" + sessionID; + newUrl = plugin.url + newRoomId; + plugin.handleClick(newUrl, room, newUrl); + }); + room.getEditorBar().add(ofmeetButton); + } + + public void finished() + { + Log.debug("ChatRoomDecorator: finished " + room.getBareJid()); + } + +} diff --git a/plugins/meet/src/main/java/org/jivesoftware/spark/plugin/ofmeet/QueryRequest.java b/plugins/meet/src/main/java/org/jivesoftware/spark/plugin/ofmeet/QueryRequest.java new file mode 100644 index 000000000..9acd7354e --- /dev/null +++ b/plugins/meet/src/main/java/org/jivesoftware/spark/plugin/ofmeet/QueryRequest.java @@ -0,0 +1,97 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.ofmeet; + +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IqData; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.provider.IqProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.JxmppContext; + +import java.io.IOException; + +/** + * An IQ packet that's a request for an online meeting URL + * according to XEP-0483. + */ +public class QueryRequest extends IQ +{ + public static final String NAMESPACE = "urn:xmpp:http:online-meetings:0"; + public static final String ELEMENT_NAME = "query"; + + + private String type; + public String url = null; + + public QueryRequest() + { + super( "query", NAMESPACE ); + } + + public QueryRequest(String type) + { + super( "query", NAMESPACE ); + this.type = type; + } + + @Override + protected IQChildElementXmlStringBuilder getIQChildElementBuilder( IQChildElementXmlStringBuilder buf ) + { + buf.append(" type=\"" + type + "\""); + buf.rightAngleBracket(); + return buf; + } + + public static class Provider extends IqProvider + { + public Provider() + { + super(); + } + + @Override + public QueryRequest parse(XmlPullParser parser, int i, IqData iqData, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException + { + final QueryRequest queryRequest = new QueryRequest(); + + boolean done = false; + while ( !done ) + { + XmlPullParser.Event eventType = parser.next(); + + if ( eventType == XmlPullParser.Event.START_ELEMENT ) + { + if ( parser.getName().equals( "url" ) ) + { + queryRequest.url = parser.nextText(); + } + } + + else if ( eventType == XmlPullParser.Event.END_ELEMENT ) + { + if ( parser.getName().equals( "query" ) ) + { + done = true; + } + } + } + + return queryRequest; + } + } +} diff --git a/plugins/meet/src/main/java/org/jivesoftware/spark/plugin/ofmeet/SparkMeetPlugin.java b/plugins/meet/src/main/java/org/jivesoftware/spark/plugin/ofmeet/SparkMeetPlugin.java new file mode 100644 index 000000000..9aa39f231 --- /dev/null +++ b/plugins/meet/src/main/java/org/jivesoftware/spark/plugin/ofmeet/SparkMeetPlugin.java @@ -0,0 +1,479 @@ +/** + * Copyright (C) 2004-2010 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.jivesoftware.spark.plugin.ofmeet; + +import java.awt.*; +import javax.swing.*; +import java.util.*; +import java.util.zip.*; +import java.io.*; +import java.net.*; + + +import org.jivesoftware.Spark; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.spark.*; + +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.provider.ProviderManager; +import org.jivesoftware.smack.packet.IQ; + +import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; +import org.jivesoftware.smackx.disco.packet.DiscoverInfo; + +import org.jivesoftware.spark.plugin.*; +import org.jivesoftware.spark.ui.*; +import org.jivesoftware.spark.util.log.*; + +import org.jitsi.util.OSUtils; +import de.mxro.process.*; +import org.jxmpp.jid.DomainBareJid; +import org.jxmpp.jid.parts.*; + +import static java.nio.charset.StandardCharsets.UTF_8; + +public class SparkMeetPlugin implements Plugin, ChatRoomListener, GlobalMessageListener +{ + public Properties props = new Properties(); + public String url = null; + + private org.jivesoftware.spark.ChatManager chatManager; + private final File pluginsettings = new File( Spark.getLogDirectory().getParentFile() + System.getProperty("file.separator") + "ofmeet.properties"); + + private final Map decorators = new HashMap<>(); + private String electronExePath = null; + private String electronHomePath = null; + private XProcess electronThread = null; + private JPanel inviteAlert; + + public void initialize() + { + ProviderManager.addIQProvider("query", QueryRequest.NAMESPACE, new QueryRequest.Provider()); + checkNatives(); + + chatManager = SparkManager.getChatManager(); + + String server = SparkManager.getSessionManager().getServerAddress().toString(); + String port = "7443"; + url = "https://" + server + ":" + port + "/ofmeet/"; + + if (pluginsettings.exists()) + { + Log.debug("ofmeet-info: Properties-file does exist= " + pluginsettings.getPath()); + + try { + props.load(new FileInputStream(pluginsettings)); + + if (props.getProperty("url") != null) + { + url = props.getProperty("url"); + Log.debug("ofmeet-info: ofmeet url from properties-file is= " + url); + } + + } catch (IOException ioe) { + Log.error("ofmeet-Error:", ioe); + } + + } else { + Log.warning("ofmeet-Error: Properties-file does not exist= " + pluginsettings.getPath() + ", using default " + url); + } + + chatManager.addChatRoomListener(this); + chatManager.addGlobalMessageListener(this); + + SparkMeetPreference preference = new SparkMeetPreference(this); + SparkManager.getPreferenceManager().addPreference(preference); + + initializeOnlineMeetings(); + } + + private void initializeOnlineMeetings() { + ServiceDiscoveryManager discoManager = SparkManager.getDiscoManager(); + + DiscoverInfo discoverInfo; + DomainBareJid serverJid = SparkManager.getSessionManager().getServerAddress(); + try { + discoverInfo = discoManager.discoverInfo(serverJid); + } catch (Exception e) { + Log.debug("Unable to disco " + serverJid); + return; + } + if (discoverInfo == null) { + return; + } + + boolean jitsiAvailable = discoverInfo.containsFeature("urn:xmpp:http:online-meetings#jitsi"); + boolean galeneAvailable = discoverInfo.containsFeature("urn:xmpp:http:online-meetings#galene"); + boolean ohunAvailable = discoverInfo.containsFeature("urn:xmpp:http:online-meetings#ohun"); + + String sUrl = null; + if (jitsiAvailable) { + sUrl = getServerUrl("jitsi"); + } else if (galeneAvailable) { + sUrl = getServerUrl("galene"); + } else if (ohunAvailable) { + sUrl = getServerUrl("ohun"); + } + + if (sUrl != null) { + url = sUrl; + } + } + + private String getServerUrl(String app) { + String serverUrl = null; + try { + QueryRequest request = new QueryRequest(app); + request.setTo(SparkManager.getSessionManager().getServerAddress()); + request.setType(IQ.Type.get); + IQ result = SparkManager.getConnection().sendIqRequestAndWaitForResponse(request); + QueryRequest response = (QueryRequest) result; + + Log.debug("SparkMeet response: url=" + response.url); + if (response.url != null) serverUrl = response.url + "/"; + + } catch (Exception e) { + Log.error("Unable to get meet url from server for app type " + app); + } + return serverUrl; + } + + public void commit(String url) { + this.url = url; + props.setProperty("url", url); + try { + FileOutputStream outputStream = new FileOutputStream(pluginsettings); + props.store(outputStream, "Properties"); + outputStream.close(); + } catch (Exception e) { + Log.error("ofmeet-Error:", e); + } + } + + public void shutdown() + { + try + { + Log.debug("shutdown"); + chatManager.removeChatRoomListener(this); + ProviderManager.removeIQProvider("query", QueryRequest.NAMESPACE); + + if (electronThread != null) electronThread.destory(); + electronThread = null; + } + catch(Exception e) + { + Log.error("shutdown ", e); + } + } + + @Override + public void messageReceived(ChatRoom room, Message message) { + try { + Localpart roomId = room.getJid().getLocalpart(); + String body = message.getBody(); + int pos = body.indexOf("https://"); + if (pos > -1 && (body.contains("/" + roomId + "-") || body.contains("meeting"))) { + showInvitationAlert(message.getBody().substring(pos), room, roomId); + } + } catch (Exception ignored) { + } + } + + private void showInvitationAlert(final String meetUrl, final ChatRoom room, final CharSequence roomId) + { + // Got an offer to start a new meet. So, make sure that a chat is + // started with the other + // user and show an invite panel. + + inviteAlert = new JPanel(); + inviteAlert.setLayout(new BorderLayout()); + + JPanel invitePanel = new JPanel(); + invitePanel.setPreferredSize(new Dimension(24, 24)); + inviteAlert.add(invitePanel, BorderLayout.WEST); + JPanel content = new JPanel(new BorderLayout()); + + content.add(new JLabel("Join audio/conference conference ..."), BorderLayout.CENTER); + JPanel buttonPanel = new JPanel(); + + // The accept button. When clicked, accept the meet offer. + final JButton acceptButton = new JButton("Accept"); + final JButton declineButton = new JButton("Decline"); + + acceptButton.addActionListener(e -> { + // Hide the response panel. TODO: make this work. + room.getTranscriptWindow().remove(inviteAlert); + inviteAlert.remove(1); + inviteAlert.add(new JLabel("Meeting at " + meetUrl), BorderLayout.CENTER); + declineButton.setEnabled(false); + acceptButton.setEnabled(false); + + openURL(meetUrl); + }); + buttonPanel.add(acceptButton); + + // The decline button. When clicked, reject the meet offer. + + declineButton.addActionListener(e -> { + // Hide the response panel. TODO: make this work. + room.getTranscriptWindow().remove(inviteAlert); + declineButton.setVisible(false); + acceptButton.setVisible(false); + }); + buttonPanel.add(declineButton); + content.add(buttonPanel, BorderLayout.SOUTH); + inviteAlert.add(content, BorderLayout.CENTER); + + // Add the response panel to the transcript window. + room.getTranscriptWindow().addComponent(inviteAlert); + } + + @Override + public void messageSent(ChatRoom room, Message message) { + + } + + public boolean canShutDown() + { + return true; + } + + public void uninstall() + { + + } + + public void handleClick(String newUrl, ChatRoom room, String url) + { + if (electronThread != null) + { + electronThread.destory(); + electronThread = null; + return; + } + + sendInvite(room, url); + openURL(newUrl); + } + + public void openURL(String newUrl) + { + try { + String username = URLEncoder.encode(SparkManager.getSessionManager().getUsername(), UTF_8); + String password = URLEncoder.encode(SparkManager.getSessionManager().getPassword(), UTF_8); + + electronThread = Spawn.startProcess(electronExePath + " --ignore-certificate-errors " + newUrl, new File(electronHomePath), new ProcessListener() { + + public void onOutputLine(final String line) { + System.out.println(line); + } + + public void onProcessQuit(int code) { + electronThread = null; + } + + public void onOutputClosed() { + System.out.println("process completed"); + } + + public void onErrorLine(final String line) { + + if (!line.contains("Corrupt JPEG data")) + { + Log.warning("Electron error " + line); + } + } + + public void onError(final Throwable t) { + Log.warning("Electron error", t); + } + }); + } catch (Exception t) { + Log.error("Error opening url " + newUrl, t); + } + } + + public void chatRoomClosed(ChatRoom chatroom) + { + String roomId = chatroom.getBareJid().toString(); + Log.debug("chatRoomClosed: " + roomId); + + if (decorators.containsKey(roomId)) + { + ChatRoomDecorator decorator = decorators.remove(roomId); + decorator.finished(); + } + + if (electronThread != null) + { + electronThread.destory(); + electronThread = null; + } + } + + public void chatRoomActivated(ChatRoom chatroom) + { + String roomId = chatroom.getBareJid().toString(); + Log.debug("chatRoomActivated: " + roomId); + } + + public void userHasJoined(ChatRoom room, String s) + { + String roomId = room.getBareJid().toString(); + Log.debug("userHasJoined: " + roomId + " " + s); + } + + public void userHasLeft(ChatRoom room, String s) + { + String roomId = room.getBareJid().toString(); + Log.debug("userHasLeft: " + roomId + " " + s); + } + + public void chatRoomOpened(final ChatRoom room) + { + String roomId = room.getBareJid().toString(); + Log.debug("chatRoomOpened: " + roomId); + + if (roomId.indexOf('/') == -1) + { + decorators.put(roomId, new ChatRoomDecorator(room, this)); + } + } + + private void checkNatives() + { + Log.debug("checkNatives"); + + new Thread() + { + @Override public void run() + { + try + { + String nativeLibsJarPath = Spark.getSparkUserHome() + File.separator + "plugins" + File.separator + "meet" + File.separator + "lib"; + File nativeLibFolder = new File(nativeLibsJarPath, "native"); + + electronHomePath = nativeLibsJarPath + File.separator + "native"; + electronExePath = electronHomePath + File.separator + "electron"; + + if(!nativeLibFolder.exists()) + { + nativeLibFolder.mkdir(); + + String jarFileSuffix = null; + + if(OSUtils.IS_LINUX32) + { + jarFileSuffix = "-linux-ia32.zip"; + } + else if(OSUtils.IS_LINUX64) + { + jarFileSuffix = "-linux-x64.zip"; + } + else if(OSUtils.IS_WINDOWS32) + { + jarFileSuffix = "-win32-ia32.zip"; + } + else if(OSUtils.IS_WINDOWS64) + { + jarFileSuffix = "-win32-x64.zip"; + } + else if(OSUtils.IS_MAC) + { + jarFileSuffix = "-darwin-x64.zip"; + } + + InputStream inputStream = new URL("https://github.com/electron/electron/releases/download/v37.2.3/electron-v37.2.3" + jarFileSuffix).openStream(); + ZipInputStream zipIn = new ZipInputStream(inputStream); + ZipEntry entry = zipIn.getNextEntry(); + + while (entry != null) + { + try + { + String filePath = electronHomePath + File.separator + entry.getName(); + + Log.debug("writing file..." + filePath); + + if (!entry.isDirectory()) + { + File file = new File(filePath); + file.setReadable(true, true); + file.setWritable(true, true); + file.setExecutable(true, true); + + new File(file.getParent()).mkdirs(); + + extractFile(zipIn, filePath); + } + zipIn.closeEntry(); + entry = zipIn.getNextEntry(); + } + catch(Exception e) { + Log.error("Error", e); + } + } + zipIn.close(); + + Log.debug("Native lib folder created and natives extracted"); + } + else { + Log.debug("Native lib folder already exist."); + } + + + String libPath = nativeLibFolder.getCanonicalPath(); + + if (!System.getProperty("java.library.path").contains(libPath)) + { + String newLibPath = libPath + File.pathSeparator + System.getProperty("java.library.path"); + System.setProperty("java.library.path", newLibPath); + + // this will reload the new setting + Log.warning("Unable to modify 'java.library.path' dynamically. Please ensure the library path includes: " + libPath); + } + } + catch (Exception e) + { + Log.error(e.getMessage(), e); + } + } + + }.start(); + } + + private void extractFile(ZipInputStream zipIn, String filePath) throws IOException + { + BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath)); + byte[] bytesIn = new byte[4096]; + int read; + + while ((read = zipIn.read(bytesIn)) != -1) + { + bos.write(bytesIn, 0, read); + } + bos.close(); + } + + private void sendInvite(ChatRoom room, String url) + { + room.sendMessage(url); + } +} diff --git a/plugins/meet/src/main/java/org/jivesoftware/spark/plugin/ofmeet/SparkMeetPreference.java b/plugins/meet/src/main/java/org/jivesoftware/spark/plugin/ofmeet/SparkMeetPreference.java new file mode 100644 index 000000000..b127d8774 --- /dev/null +++ b/plugins/meet/src/main/java/org/jivesoftware/spark/plugin/ofmeet/SparkMeetPreference.java @@ -0,0 +1,117 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.plugin.ofmeet; + +import javax.swing.*; +import java.awt.*; + +import org.jivesoftware.spark.component.VerticalFlowLayout; +import org.jivesoftware.spark.preference.Preference; + +public class SparkMeetPreference implements Preference { + public static final String NAMESPACE = "ofmeet"; + + private SparkMeetPlugin plugin; + private final MeetingPanel panel = new MeetingPanel(); + + public SparkMeetPreference(SparkMeetPlugin plugin) { + this.plugin = plugin; + } + + @Override + public void commit() { + plugin.commit(panel.getUrl()); + } + + @Override + public Object getData() { + return plugin.props; + } + + @Override + public String getErrorMessage() { + return null; + } + + @Override + public JComponent getGUI() { + panel.setUrl(plugin.props.getProperty("url")); + return panel; + } + + @Override + public Icon getIcon() { + return SparkMeetResource.PLUGIN_ICON; + } + + @Override + public String getListName() { + return SparkMeetResource.getString("name"); + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public String getTitle() { + return SparkMeetResource.getString("name"); + } + + @Override + public String getTooltip() { + return SparkMeetResource.getString("name"); + } + + @Override + public boolean isDataValid() { + return true; + } + + @Override + public void load() { + } + + @Override + public void shutdown() { + + } + + private static class MeetingPanel extends JPanel { + private static final long serialVersionUID = -5992704440953686499L; + private final JTextArea txtMessage = new JTextArea(); + private JLabel url = new JLabel(SparkMeetResource.getString("preference.url")); + + MeetingPanel() { + txtMessage.setBorder(UIManager.getLookAndFeelDefaults().getBorder("TextField.border")); + txtMessage.setLineWrap(true); + setLayout(new VerticalFlowLayout()); + setBorder(BorderFactory.createTitledBorder(SparkMeetResource.getString("preference.title"))); + add(url, new GridBagConstraints(0, 0, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + add(txtMessage, new GridBagConstraints(0, 1, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + } + + public void setUrl(String message) { + txtMessage.setText(message); + } + + public String getUrl() { + return txtMessage.getText().trim(); + } + } + +} diff --git a/plugins/meet/src/main/java/org/jivesoftware/spark/plugin/ofmeet/SparkMeetResource.java b/plugins/meet/src/main/java/org/jivesoftware/spark/plugin/ofmeet/SparkMeetResource.java new file mode 100644 index 000000000..d03fbcd8c --- /dev/null +++ b/plugins/meet/src/main/java/org/jivesoftware/spark/plugin/ofmeet/SparkMeetResource.java @@ -0,0 +1,38 @@ +package org.jivesoftware.spark.plugin.ofmeet; + +import org.jivesoftware.resource.UTF8Control; +import org.jivesoftware.spark.util.log.Log; + +import javax.swing.*; +import java.text.MessageFormat; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +public class SparkMeetResource { + private static PropertyResourceBundle prb = (PropertyResourceBundle) ResourceBundle.getBundle("i18n/sparkmeet_i18n", new UTF8Control()); + + private static ClassLoader cl = SparkMeetResource.class.getClassLoader(); + static final ImageIcon PLUGIN_ICON = getImageIcon("images/pade.png"); + + public static String getString(String propertyName) { + try { + return prb.getString(propertyName); + } + catch (Exception e) { + Log.error(e); + return propertyName; + } + } + + public static String getString(String propertyName, Object... obj) { + String str = prb.getString(propertyName); + if (str == null) { + return null; + } + return MessageFormat.format(str, obj); + } + + private static ImageIcon getImageIcon(String icon) { + return new ImageIcon(cl.getResource(icon)); + } +} diff --git a/plugins/meet/src/main/plugin-metadata/plugin.xml b/plugins/meet/src/main/plugin-metadata/plugin.xml new file mode 100644 index 000000000..788b82561 --- /dev/null +++ b/plugins/meet/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,12 @@ + + ${project.name} + ${project.version} + ${project.description} + Dele Olajide + https://IgniteRealtime.org + support@IgniteRealtime.org + org.jivesoftware.spark.plugin.ofmeet.SparkMeetPlugin + 3.1.0 + Windows,Linux,Mac + 11 + diff --git a/plugins/meet/src/main/resources/i18n/sparkmeet_i18n.properties b/plugins/meet/src/main/resources/i18n/sparkmeet_i18n.properties new file mode 100644 index 000000000..3f2a14327 --- /dev/null +++ b/plugins/meet/src/main/resources/i18n/sparkmeet_i18n.properties @@ -0,0 +1,5 @@ +name=Online Meetings + +preference.title=Online Meetings Settings +preference.url=Online Meetings Base URL + diff --git a/plugins/meet/src/main/resources/i18n/sparkmeet_i18n_ru_RU.properties b/plugins/meet/src/main/resources/i18n/sparkmeet_i18n_ru_RU.properties new file mode 100644 index 000000000..5f9b40af4 --- /dev/null +++ b/plugins/meet/src/main/resources/i18n/sparkmeet_i18n_ru_RU.properties @@ -0,0 +1,4 @@ +name=Онлайн вÑтречи + +preference.url=Базовый URL-Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ð¾Ð½Ð»Ð°Ð¹Ð½ вÑтреч +preference.title=ÐаÑтройки онлайн вÑтреч diff --git a/plugins/meet/src/main/resources/i18n/sparkmeet_i18n_uk_UA.properties b/plugins/meet/src/main/resources/i18n/sparkmeet_i18n_uk_UA.properties new file mode 100644 index 000000000..bcc2d61b3 --- /dev/null +++ b/plugins/meet/src/main/resources/i18n/sparkmeet_i18n_uk_UA.properties @@ -0,0 +1,4 @@ +name=Онлайн зуÑтрічі + +preference.url=Базова URL-адреÑа Ð´Ð»Ñ Ð¾Ð½Ð»Ð°Ð¹Ð½ зуÑтрічей +preference.title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð½Ð»Ð°Ð¹Ð½ зуÑтрічей diff --git a/plugins/meet/src/main/resources/images/icon16.png b/plugins/meet/src/main/resources/images/icon16.png new file mode 100644 index 000000000..e356d5d62 Binary files /dev/null and b/plugins/meet/src/main/resources/images/icon16.png differ diff --git a/plugins/meet/src/main/resources/images/pade.png b/plugins/meet/src/main/resources/images/pade.png new file mode 100644 index 000000000..5a11820e4 Binary files /dev/null and b/plugins/meet/src/main/resources/images/pade.png differ diff --git a/plugins/meet/src/main/resources/sounds/incomingMessage.wav b/plugins/meet/src/main/resources/sounds/incomingMessage.wav new file mode 100644 index 000000000..012dbab16 Binary files /dev/null and b/plugins/meet/src/main/resources/sounds/incomingMessage.wav differ diff --git a/plugins/meet/src/main/resources/sounds/joined.wav b/plugins/meet/src/main/resources/sounds/joined.wav new file mode 100644 index 000000000..16ceb80ac Binary files /dev/null and b/plugins/meet/src/main/resources/sounds/joined.wav differ diff --git a/plugins/meet/src/main/resources/sounds/left.wav b/plugins/meet/src/main/resources/sounds/left.wav new file mode 100644 index 000000000..0c9cee0a3 Binary files /dev/null and b/plugins/meet/src/main/resources/sounds/left.wav differ diff --git a/plugins/otr/pom.xml b/plugins/otr/pom.xml new file mode 100644 index 000000000..23fa83757 --- /dev/null +++ b/plugins/otr/pom.xml @@ -0,0 +1,45 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + otr + 0.5 + + OTR Plugin + Off-The-Record (OTR) message encryption. + + + + Holger Bergunde + holger@bergunde.de + http://www.stytrix.de + + Author + + + + + + + org.jitsi + org.otr4j + 0.23 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + diff --git a/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/OTRManager.java b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/OTRManager.java new file mode 100644 index 000000000..023e4ad51 --- /dev/null +++ b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/OTRManager.java @@ -0,0 +1,169 @@ +package org.jivesoftware.spark.plugin.otr; + +import java.awt.*; +import java.io.IOException; + +import java.util.HashMap; + +import java.util.Map; + +import net.java.otr4j.OtrException; +import net.java.otr4j.OtrKeyManager; +import net.java.otr4j.OtrKeyManagerImpl.DefaultPropertiesStore; +import net.java.otr4j.session.Session; +import net.java.otr4j.session.SessionID; + +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.SparkManager; + +import org.jivesoftware.spark.plugin.otr.impl.OTRSession; +import org.jivesoftware.spark.plugin.otr.util.OTRProperties; +import org.jivesoftware.spark.plugin.otr.util.OTRResources; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomListener; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.spark.ui.ContactItemHandler; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.EntityFullJid; + +import javax.swing.*; + +/** + * OTRManager controls the whole OTR process. + * It checks if a new chat window is opened and creates an OTR session if there is no available. + * + * @author Bergunde Holger + */ +public class OTRManager { + + private static OTRManager singleton; + private static final Object LOCK = new Object(); + private final Map _activeSessions = new HashMap<>(); + private static OtrKeyManager _keyManager; + + private OTRManager() { + final ChatManager chatManager = SparkManager.getChatManager(); + chatManager.addChatRoomListener(new ChatRoomListener() { + @Override + public void chatRoomOpened(ChatRoom room) { + if (!(room instanceof ChatRoomImpl)) { + return; + } + ChatRoomImpl chatRoom = (ChatRoomImpl) room; + createOTRSession(chatRoom, chatRoom.getParticipantJID().toString()); + } + + @Override + public void chatRoomClosed(ChatRoom room) { + if (!(room instanceof ChatRoomImpl)) { + return; + } + if (!OTRProperties.getInstance().getOTRCloseOnChatClose()) { + return; + } + ChatRoomImpl myroom = (ChatRoomImpl) room; + OTRSession searchedSession = getOtrSession(myroom.getParticipantJID().toString()); + if (searchedSession == null) { + return; + } + searchedSession.stopSession(); + _activeSessions.remove(myroom.getParticipantJID().toString()); + } + }); + chatManager.addContactItemHandler(new ContactItemHandler() { + @Override + public boolean handlePresence(ContactItem item, Presence presence) { + // check if the buddy went offline and close the session + if (presence.isAvailable()) { + return false; + } + if (OTRProperties.getInstance().getOTRCloseOnDisc()) { + OTRSession otrSession = getOtrSession(item.getJid().toString()); + if (otrSession != null) { + otrSession.stopSession(); + } + } + return false; + } + }); + } + + /** + * OTRManager is a singleton. Use this method to get the instance. + */ + public static OTRManager getInstance() { + // Synchronize on LOCK to ensure that we don't end up creating two singletons. + synchronized (LOCK) { + if (singleton == null) { + singleton = new OTRManager(); + try { + DefaultPropertiesStore store = new DefaultPropertiesStore(SparkManager.getUserDirectory().getPath() + "/otrkey.priv"); + _keyManager = new OtrKeyManagerImpl(store); + // We should generate a local key if there is no available + EntityFullJid userJid = SparkManager.getConnection().getUser(); + String key = _keyManager.getLocalFingerprint(new SessionID(userJid.toString(), "none", "Scytale")); + if (key == null) { + _keyManager.generateLocalKeyPair(new SessionID(userJid.toString(), "none", "Scytale")); + } + } catch (IOException e) { + Log.error(e); + } + } + } + return singleton; + } + + /** + * Starts the OTR session with a buddy. + */ + public void startOtrWithUser(EntityBareJid participantJid) { + OTRSession otrSession = getOtrSession(participantJid.toString()); + if (otrSession != null) { + otrSession.startSession(); + } + } + + + public void authenticateUser(EntityBareJid participantJid) { + OTRSession otrSession = getOtrSession(participantJid.toString()); + if (otrSession != null) { + EventQueue.invokeLater(() -> { + String dlgTitle = OTRResources.getString("otr.authenticate"); + String dlgMsg = OTRResources.getString("otr.authenticate.question"); + String secret = JOptionPane.showInputDialog(null, dlgMsg, dlgTitle, JOptionPane.QUESTION_MESSAGE); + String question = null; // TODO implement an ability to set a question + try { + otrSession.getMySession().initSmp(question, secret); + } catch (OtrException e) { + Log.error(e); + } + }); + } + } + + private void createOTRSession(ChatRoomImpl chatroom, String participantJid) { + OTRSession otrSession = getOtrSession(participantJid); + if (otrSession == null) { + EntityFullJid myJid = SparkManager.getConnection().getUser(); + otrSession = new OTRSession(chatroom, myJid.toString(), participantJid); + _activeSessions.put(participantJid, otrSession); + } else { + otrSession.updateChatRoom(chatroom); + } + } + + public OTRSession getOtrSession(String participantJid) { + return _activeSessions.get(participantJid); + } + + /** + * Returns the OtrKeyManager to store and load keys + */ + public OtrKeyManager getKeyManager() { + return _keyManager; + } + +} diff --git a/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/OTRPlugin.java b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/OTRPlugin.java new file mode 100644 index 000000000..b859be35b --- /dev/null +++ b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/OTRPlugin.java @@ -0,0 +1,39 @@ +package org.jivesoftware.spark.plugin.otr; + +import org.jivesoftware.smackx.eme.ExplicitMessageEncryptionManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.otr.pref.OTRPreferences; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.preference.Preference; + +/** + * OTR Plugin + * + * @author Bergunde Holger + */ +public class OTRPlugin implements Plugin { + + @Override + public void initialize() { + // Create OTRManager singleton + OTRManager.getInstance(); + ExplicitMessageEncryptionManager.getInstanceFor(SparkManager.getConnection()); + // The following will add an Entry into the Spark Preferences Window + Preference mypreference = new OTRPreferences(); + SparkManager.getPreferenceManager().addPreference(mypreference); + } + + @Override + public void shutdown() { + } + + @Override + public boolean canShutDown() { + return false; + } + + @Override + public void uninstall() { + } + +} diff --git a/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/OtrKeyManagerImpl.java b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/OtrKeyManagerImpl.java new file mode 100644 index 000000000..f6b677893 --- /dev/null +++ b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/OtrKeyManagerImpl.java @@ -0,0 +1,45 @@ +package org.jivesoftware.spark.plugin.otr; + +import net.java.otr4j.OtrKeyManagerStore; +import net.java.otr4j.session.SessionID; + +import java.io.IOException;import java.security.*; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +/** + * Fixed version of OtrKeyManagerImpl. + * TODO Remove after https://github.com/jitsi/otr4j/pull/16 merged + */ +class OtrKeyManagerImpl extends net.java.otr4j.OtrKeyManagerImpl { + private final OtrKeyManagerStore store; + + public OtrKeyManagerImpl(OtrKeyManagerStore store) { + super(store); + this.store = store; + } + + @Override + public void generateLocalKeyPair(SessionID sessionID) { + if (sessionID != null) { + String accountID = sessionID.getAccountID(); + + KeyPair keyPair; + try { + final KeyPairGenerator kg = KeyPairGenerator.getInstance("DSA"); + kg.initialize(1024); + keyPair = kg.genKeyPair(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return; + } + + PublicKey pubKey = keyPair.getPublic(); + X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(pubKey.getEncoded()); + this.store.setProperty(accountID + ".publicKey", x509EncodedKeySpec.getEncoded()); + PrivateKey privKey = keyPair.getPrivate(); + PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privKey.getEncoded()); + this.store.setProperty(accountID + ".privateKey", pkcs8EncodedKeySpec.getEncoded()); + } + } +} diff --git a/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/impl/OTREngineHost.java b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/impl/OTREngineHost.java new file mode 100644 index 000000000..c7fc2bcb2 --- /dev/null +++ b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/impl/OTREngineHost.java @@ -0,0 +1,187 @@ +package org.jivesoftware.spark.plugin.otr.impl; + +import static net.java.otr4j.session.FragmenterInstructions.UNLIMITED; + +import java.awt.*; +import java.security.KeyPair; +import java.util.List; + +import net.java.otr4j.crypto.OtrCryptoEngine; +import net.java.otr4j.session.*; +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.otr.OTRManager; +import org.jivesoftware.spark.plugin.otr.util.OTRResources; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; + +import net.java.otr4j.OtrEngineHost; +import net.java.otr4j.OtrException; +import net.java.otr4j.OtrPolicy; +import org.jivesoftware.spark.util.log.Log; + +import javax.net.ssl.HandshakeCompletedEvent; +import javax.swing.*; + +/** + * Implementation of OtrEngineHost provided from otr4j. It handles the message + * injection to specified chat window and handles key pair. + * + * @author Bergunde Holger + */ +public class OTREngineHost implements OtrEngineHost { + + private final ChatRoomImpl _chatRoom; + private final OtrPolicy _policy; + + public OTREngineHost(OtrPolicy policy, ChatRoomImpl chatroom) { + _policy = policy; + _chatRoom = chatroom; + } + + @Override + public KeyPair getLocalKeyPair(SessionID sessionID) { + return OTRManager.getInstance().getKeyManager().loadLocalKeyPair(sessionID); + } + + @Override + public byte[] getLocalFingerprintRaw(SessionID sessionID) { + return OTRManager.getInstance().getKeyManager().getLocalFingerprintRaw(sessionID); + } + + @Override + public void askForSecret(SessionID sessionID, InstanceTag receiverTag, String question) { + String authReqMsg = OTRResources.getString("otr.authentication.request", _chatRoom.getParticipantNickname()); + _chatRoom.getTranscriptWindow().insertNotificationMessage(authReqMsg, Color.orange); + OTRSession otrSession = OTRManager.getInstance().getOtrSession(sessionID.getUserID()); + EventQueue.invokeLater(() -> { + Session mySession = otrSession.getMySession(); + String dlgMsg = authReqMsg + "\n" + OTRResources.getString("otr.authentication.giveAnswer"); + if (question != null) { + dlgMsg += ": " + question; + } + String secret = JOptionPane.showInputDialog(_chatRoom, dlgMsg, authReqMsg, JOptionPane.QUESTION_MESSAGE); + try { + if (secret == null) { + mySession.abortSmp(); + return; + } + mySession.respondSmp(receiverTag, question, secret); + } catch (OtrException e) { + Log.error(e); + _chatRoom.getTranscriptWindow().insertNotificationMessage(e.getMessage(), Color.red); + } + }); + } + + @Override + public void verify(SessionID sessionID, String fingerprint, boolean approved) { + Log.debug("Session authentification finished " + sessionID + " approved: " + approved); + if (approved) { + OTRManager.getInstance().getKeyManager().verify(sessionID); + String msg = OTRResources.getString("otr.authorization.completed"); + _chatRoom.getTranscriptWindow().insertNotificationMessage(msg, Color.green); + } + } + + @Override + public void unverify(SessionID sessionID, String fingerprint) { + String msg = "Session was not verified: " + sessionID + " fingerprint: " + fingerprint; + Log.warning(msg); + _chatRoom.getTranscriptWindow().insertNotificationMessage(msg, Color.red); + } + + @Override + public String getReplyForUnreadableMessage(SessionID sessionID) { + return "You sent me an unreadable encrypted message."; + } + + @Override + public String getFallbackMessage(SessionID sessionID) { + return "Off-the-Record private conversation has been requested. However, you do not have a plugin to support that."; + } + + @Override + public void messageFromAnotherInstanceReceived(SessionID sessionID) { + String msg = "Received message from another instances: " + sessionID; + Log.warning(msg); + _chatRoom.getTranscriptWindow().insertNotificationMessage(msg, Color.red); + } + + @Override + public void multipleInstancesDetected(SessionID sessionID) { + Log.warning("Detected multiple instances: " + sessionID); + } + + @Override + public OtrPolicy getSessionPolicy(SessionID sessionID) { + return _policy; + } + + @Override + public FragmenterInstructions getFragmenterInstructions(SessionID sessionID) { + return new FragmenterInstructions(UNLIMITED, 64*1024); + } + + @Override + public void injectMessage(SessionID sessionID, String msg) { + String threadID = StringUtils.randomString(6); + Message injection = StanzaBuilder.buildMessage() + .ofType(Message.Type.chat) + .setThread(threadID) + .setBody(msg) + .to(_chatRoom.getParticipantJID()) + .from(SparkManager.getSessionManager().getJID()) + .build(); + try + { + SparkManager.getConnection().sendStanza(injection); + } + catch (SmackException.NotConnectedException | InterruptedException e ) + { + Log.warning( "Unable to send injection to " + injection.getTo(), e ); + } + } + + @Override + public void unreadableMessageReceived(SessionID sessionID) throws OtrException { + Log.warning("Unreadable message received from: " + sessionID); + } + + @Override + public void unencryptedMessageReceived(SessionID sessionID, String msg) throws OtrException { + Log.warning("Unencrypted message received: " + msg + " from " + sessionID); + } + + @Override + public void showError(SessionID sessionID, String error) { + // shows error to user + _chatRoom.getTranscriptWindow().insertNotificationMessage(error, Color.red); + } + + @Override + public void smpError(SessionID sessionID, int tlvType, boolean cheated) throws OtrException { + // shows error to user + _chatRoom.getTranscriptWindow().insertNotificationMessage("SM verification error with user: " + sessionID, Color.red); + } + + @Override + public void smpAborted(SessionID sessionID) throws OtrException { + // shows error to user + _chatRoom.getTranscriptWindow().insertNotificationMessage("SM verification has been aborted by user: " + sessionID, Color.red); + } + + @Override + public void finishedSessionMessage(SessionID sessionID, String msgText) throws OtrException { + Log.warning("SM session was finished. You shouldn't send messages to: " + sessionID); + } + + @Override + public void requireEncryptedMessage(SessionID sessionID, String msgText) throws OtrException { + Log.warning("Message can't be sent while encrypted session is not established: " + sessionID); + } + +} diff --git a/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/impl/OTRSession.java b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/impl/OTRSession.java new file mode 100644 index 000000000..7daee4776 --- /dev/null +++ b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/impl/OTRSession.java @@ -0,0 +1,263 @@ +package org.jivesoftware.spark.plugin.otr.impl; + +import java.security.PublicKey; + +import javax.swing.ImageIcon; +import javax.swing.JOptionPane; +import javax.swing.UIManager; + +import net.java.otr4j.*; +import net.java.otr4j.io.SerializationConstants; +import net.java.otr4j.session.Session; +import net.java.otr4j.session.SessionImpl; + +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smackx.eme.element.ExplicitMessageEncryptionElement; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.plugin.otr.OTRManager; +import org.jivesoftware.spark.plugin.otr.ui.OTRConnectionPanel; +import org.jivesoftware.spark.plugin.otr.util.OTRProperties; +import org.jivesoftware.spark.plugin.otr.util.OTRResources; +import org.jivesoftware.spark.ui.ChatRoomButton; +import org.jivesoftware.spark.ui.MessageEventListener; +import org.jivesoftware.resource.Res; + +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.util.UIComponentRegistry; + +import net.java.otr4j.session.SessionID; +import net.java.otr4j.session.SessionStatus; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.impl.JidCreate; + +import static javax.swing.JOptionPane.*; +import static org.jivesoftware.smackx.eme.element.ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.otrV0; +import static org.jivesoftware.spark.plugin.otr.util.OTRResources.ICON_OTR_OFF; +import static org.jivesoftware.spark.plugin.otr.util.OTRResources.ICON_OTR_ON; + +/** + * OTRSession are unique for every conversation. + * It handles the otrEngine for the chat and controls if the chat is encrypted or not. + * + * @author Bergunde Holger + */ +public class OTRSession { + + private static final OtrPolicyImpl OTR_POLICY = new OtrPolicyImpl(OtrPolicy.ALLOW_V2 | OtrPolicy.ALLOW_V3 | OtrPolicy.ERROR_START_AKE); + private ChatRoomImpl _chatRoom; + private final String _remoteJID; + private final SessionID _mySessionID; + private final Session _mySession; + final ChatRoomButton _otrButton = UIComponentRegistry.getButtonFactory().createOtrButton(); + private OTRConnectionPanel _conPanel; + private MessageEventListener _msgEvnt; + private boolean _OtrEnabled = false; + private OtrEngineListener _otrListener; + + /** + * OTRSession Constructor + * + * @param chatroom chat room related to this OTR session + * @param myJID my own JID + * @param remoteJID the JID of the participant + */ + public OTRSession(ChatRoomImpl chatroom, String myJID, String remoteJID) { + _chatRoom = chatroom; + _remoteJID = remoteJID; + OtrEngineHost _otrEngineHost = new OTREngineHost(OTR_POLICY, _chatRoom); + _mySessionID = new SessionID(myJID, _remoteJID, "Scytale"); + + _mySession = new SessionImpl(_mySessionID, _otrEngineHost); + + setUpMessageListener(); + createButton(); + // Only initialize the actionListener once + _otrButton.addActionListener(e -> { + if (_mySession.getSessionStatus() == SessionStatus.ENCRYPTED) { + stopSession(); + } else { + startSession(); + } + }); + _otrButton.setToolTipText(OTRResources.getString("otr.chat.button.tooltip")); + _OtrEnabled = OTRProperties.getInstance().getIsOTREnabled(); + } + + /** + * Maybe you want to update the chat room because it was reopened but the OTR + * session is still alive. + * + * @param chatroom the chat room related to this OTR session + */ + public void updateChatRoom(ChatRoomImpl chatroom) { + _OtrEnabled = OTRProperties.getInstance().getIsOTREnabled(); + _chatRoom = chatroom; + setUpMessageListener(); + createButton(); + } + + private void setUpMessageListener() { + _conPanel = new OTRConnectionPanel(_chatRoom); + _chatRoom.removeMessageEventListener(_msgEvnt); + _msgEvnt = new MessageEventListener() { + + @Override + public void sendingMessage(MessageBuilder message) { + String msgBody = message.getBody(); + if (msgBody == null) { + return; + } + if (_mySession.getSessionStatus() != SessionStatus.ENCRYPTED) { + return; + } + clearMsgBody(message); + try { + String[] encodedMsg = _mySession.transformSending(msgBody); + String encodedMsgBody = encodedMsg.length == 1 ? encodedMsg[0] : String.join("", encodedMsg); + message.setBody(encodedMsgBody); + ExplicitMessageEncryptionElement eme = new ExplicitMessageEncryptionElement(otrV0); + message.addExtension(eme); + } catch (OtrException e) { + _chatRoom.getTranscriptWindow().insertNotificationMessage(OTRResources.getString("otr.failed.to.decode"), ChatManager.ERROR_COLOR); + Log.error("An exception occurred while trying to send a message: " + msgBody, e); + } + } + + @Override + public void receivingMessage(MessageBuilder message) { + String msgBody = message.getBody(); + if (msgBody == null) { + return; + } + if (_OtrEnabled) { + try { + String decoded = _mySession.transformReceiving(msgBody); + // if the message wasn't encrypted, then the decoded will be the same string so compare by a reference + //noinspection StringEquality + if (decoded != msgBody) { + clearMsgBody(message); // clear the body of the original encrypted message + if (decoded != null) { + message.setBody(decoded); + } + } + } catch (OtrException e) { + clearMsgBody(message); + _chatRoom.getTranscriptWindow().insertNotificationMessage(OTRResources.getString("otr.failed.to.decode") + " " + e.getMessage(), ChatManager.ERROR_COLOR); + Log.error("An exception occurred while receiving a message: " + msgBody, e); + } + } else { + if (msgBody.startsWith(SerializationConstants.HEAD)) { + clearMsgBody(message); + _chatRoom.getTranscriptWindow().insertNotificationMessage(OTRResources.getString("otr.not.enabled"), ChatManager.NOTIFICATION_COLOR); + } + } + } + }; + _chatRoom.addMessageEventListener(_msgEvnt); + } + + private static void clearMsgBody(MessageBuilder message) { + // Manually remove the existing body to add a new one. + message.removeExtension(Message.Body.ELEMENT, Message.Body.NAMESPACE); + } + + private void createButton() { + if (!OTRProperties.getInstance().getIsOTREnabled()) { + return; + } + ImageIcon otrIcon; + if (_mySession.getSessionStatus() == SessionStatus.ENCRYPTED) { + otrIcon = ICON_OTR_ON; + _conPanel.successfullyCon(); + } else { + otrIcon = ICON_OTR_OFF; + } + + _otrButton.setIcon(otrIcon); + + _mySession.removeOtrEngineListener(_otrListener); + _chatRoom.getToolBar().addChatRoomButton(_otrButton); + _otrListener = new OtrEngineListener() { + + @Override + public void sessionStatusChanged(SessionID sessionID) { + UIManager.put("OptionPane.yesButtonText", Res.getString("yes")); + UIManager.put("OptionPane.noButtonText", Res.getString("no")); + UIManager.put("OptionPane.cancelButtonText", Res.getString("cancel")); + + if (_mySession.getSessionStatus() == SessionStatus.ENCRYPTED) { + _conPanel.successfullyCon(); + OtrKeyManager keyManager = OTRManager.getInstance().getKeyManager(); + String otrkey = keyManager.getRemoteFingerprint(_mySessionID); + if (otrkey == null) { + PublicKey pubkey = _mySession.getRemotePublicKey(_mySession.getReceiverInstanceTag()); + keyManager.savePublicKey(_mySessionID, pubkey); + otrkey = keyManager.getRemoteFingerprint(_mySessionID); + } + + if (!keyManager.isVerified(_mySessionID)) { + String dialogTitle = OTRResources.getString("otr.key.not.verified.title"); + String dialogMessage = OTRResources.getString("otr.start.session.with", _remoteJID) + "\n" + + OTRResources.getString("otr.key.not.verified.text") + "\n" + + otrkey + "\n" + + OTRResources.getString("otr.question.verify"); + if (JOptionPane.showConfirmDialog(_otrButton, dialogMessage, dialogTitle, YES_NO_OPTION, WARNING_MESSAGE) == YES_OPTION) { + if (JOptionPane.showConfirmDialog(_otrButton, OTRResources.getString("otr.question.authorize"), dialogTitle, YES_NO_OPTION, WARNING_MESSAGE) == YES_OPTION) { + OTRManager.getInstance().authenticateUser(JidCreate.entityBareFromOrNull(_mySessionID.getUserID())); + } else { + keyManager.verify(_mySessionID); + } + } + } + _otrButton.setIcon(ICON_OTR_ON); + } else if (_mySession.getSessionStatus() == SessionStatus.FINISHED || _mySession.getSessionStatus() == SessionStatus.PLAINTEXT) { + stopSession(); + _otrButton.setIcon(ICON_OTR_OFF); + } + } + + @Override + public void multipleInstancesDetected(SessionID sessionID) { + Log.warning("multipleInstancesDetected for OTR session " + sessionID); + } + + @Override + public void outgoingSessionChanged(SessionID sessionID) { + Log.warning("outgoingSessionChanged for OTR session " + sessionID); + } + }; + _mySession.addOtrEngineListener(_otrListener); + } + + /** + * Start the OTR session manually from outside + */ + public void startSession() { + _conPanel.tryToStart(); + try { + _mySession.startSession(); + } catch (OtrException e) { + Log.error("An exception occurred while starting an OTR session.", e); + } + } + + /** + * Stop the OTR session manually from outside + */ + public void stopSession() { + _conPanel.connectionClosed(); + if (_mySession.getSessionStatus() == SessionStatus.ENCRYPTED) { + _otrButton.setIcon(ICON_OTR_OFF); + try { + _mySession.endSession(); + } catch (OtrException e) { + Log.error("An exception occurred while stopping the OTR session.", e); + } + } + } + + public Session getMySession() { + return _mySession; + } +} diff --git a/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/pref/OTRKeyTable.java b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/pref/OTRKeyTable.java new file mode 100644 index 000000000..900a7366f --- /dev/null +++ b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/pref/OTRKeyTable.java @@ -0,0 +1,75 @@ +package org.jivesoftware.spark.plugin.otr.pref; + +import java.awt.BorderLayout; + +import java.util.Vector; + +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; + +import javax.swing.event.TableModelListener; +import javax.swing.table.DefaultTableModel; + +import org.jivesoftware.spark.plugin.otr.util.OTRResources; + +/** + * OTRKeyTable displays a key table. + * You can add keys using the addEntry() method + * + * @author Bergunde Holger + */ +public class OTRKeyTable extends JPanel { + private JTable _table; + private DefaultTableModel _tableModel; + + public OTRKeyTable() { + final String[] header = { OTRResources.getString("otr.table.jid"), OTRResources.getString("otr.table.public.key"), OTRResources.getString("otr.key.verified") }; + + _tableModel = new MyTableModel(header); + _table = new JTable(_tableModel); + _table.getTableHeader().setReorderingAllowed(false); + + this.setLayout(new BorderLayout()); + this.add(new JScrollPane(_table), BorderLayout.CENTER); + } + + static class MyTableModel extends DefaultTableModel { + public MyTableModel(String[] headers) { + super(headers, 0); + } + + @Override + public boolean isCellEditable(int row, int column) { + return column == 2; + } + + @Override + public Class getColumnClass(int columnIndex) { + return columnIndex == 2 ? Boolean.class : String.class; + } + } + + public void addTableChangeListener(TableModelListener listener) { + _tableModel.addTableModelListener(listener); + } + + /** + * Adds a key to the table + */ + public void addEntry(String jid, String hash, boolean verified) { + Vector data = new Vector(3); + data.add(jid); + data.add(hash); + data.add(verified); + _tableModel.addRow(data); + } + + /** + * Returns a specified row + */ + public Object getValueAt(int row, int col) { + return _tableModel.getValueAt(row, col); + } + +} diff --git a/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/pref/OTRPrefPanel.java b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/pref/OTRPrefPanel.java new file mode 100644 index 000000000..0fe5f039e --- /dev/null +++ b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/pref/OTRPrefPanel.java @@ -0,0 +1,167 @@ +package org.jivesoftware.spark.plugin.otr.pref; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import javax.swing.JTextField; + +import net.java.otr4j.OtrKeyManager; +import net.java.otr4j.session.SessionID; + +import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smack.roster.RosterEntry; +import org.jivesoftware.spark.SparkManager; + +import org.jivesoftware.spark.plugin.otr.OTRManager; +import org.jivesoftware.spark.plugin.otr.util.OTRProperties; +import org.jivesoftware.spark.plugin.otr.util.OTRResources; +import org.jxmpp.jid.EntityFullJid; + +/** + * OTR preference panel for Spark Preferences + * + * @author Bergund Holger + */ +public class OTRPrefPanel extends JPanel { + + private OTRManager _manager; + private JCheckBox _enableOTR; + private JCheckBox _closeSessionOff; + private JCheckBox _closeSessionOnWindowClose; + private JLabel _currentKeyLabel; + private JButton _renewPrivateKey; + private OTRKeyTable _keytable; + private JTextField _privateKey; + private OtrKeyManager _keyManager; + private OTRProperties _properties; + + public OTRPrefPanel() { + _manager = OTRManager.getInstance(); + _keyManager = _manager.getKeyManager(); + _properties = OTRProperties.getInstance(); + setLayout(new GridBagLayout()); + init(); + buildGUI(); + OtrEnableSwitch(); + } + + private void OtrEnableSwitch() { + _closeSessionOff.setEnabled(_enableOTR.isSelected()); + _closeSessionOnWindowClose.setEnabled(_enableOTR.isSelected()); + _renewPrivateKey.setEnabled(_enableOTR.isSelected()); + _keytable.setEnabled(_enableOTR.isSelected()); + } + + private void init() { + _enableOTR = new JCheckBox(); + _enableOTR.setText(OTRResources.getString("otr.enable")); + _enableOTR.setSelected(_properties.getIsOTREnabled()); + + _enableOTR.addActionListener(e -> OtrEnableSwitch()); + + _closeSessionOff = new JCheckBox(); + _closeSessionOff.setText(OTRResources.getString("otr.close.session.on.contact.off")); + _closeSessionOff.setSelected(_properties.getOTRCloseOnDisc()); + + _closeSessionOnWindowClose = new JCheckBox(); + _closeSessionOnWindowClose.setText(OTRResources.getString("otr.close.session.on.window.close")); + _closeSessionOnWindowClose.setSelected(_properties.getOTRCloseOnChatClose()); + + _currentKeyLabel = new JLabel(); + _currentKeyLabel.setText(OTRResources.getString("current.priv.key")); + + _renewPrivateKey = new JButton(); + _renewPrivateKey.setText(OTRResources.getString("renew.current.key")); + _renewPrivateKey.addActionListener(e -> { + EntityFullJid userJid = SparkManager.getConnection().getUser(); + SessionID mySession = new SessionID(userJid.toString(), "no one", "Scytale"); + _manager.getKeyManager().generateLocalKeyPair(mySession); + _privateKey.setText(getCurrentLocalKey()); + }); + + _privateKey = new JTextField(); + _privateKey.setEditable(false); + _privateKey.setText(getCurrentLocalKey()); + + _keytable = new OTRKeyTable(); + + loadRemoteKeys(); + } + + private void loadRemoteKeys() { + Roster roster = SparkManager.getRoster(); + for (RosterEntry entry : roster.getEntries()) { + EntityFullJid userJid = SparkManager.getConnection().getUser(); + SessionID curSession = new SessionID(userJid.toString(), entry.getJid().toString(), "Scytale"); + String remoteKey = _keyManager.getRemoteFingerprint(curSession); + if (remoteKey != null) { + boolean isVerified = _keyManager.isVerified(curSession); + _keytable.addEntry(entry.getJid().toString(), remoteKey, isVerified); + } + } + + _keytable.addTableChangeListener(e -> { + int col = e.getColumn(); + int row = e.getFirstRow(); + if (col != 2) { + return; + } + boolean selection = (Boolean) _keytable.getValueAt(row, col); + String JID = (String) _keytable.getValueAt(row, 0); + EntityFullJid userJid = SparkManager.getConnection().getUser(); + SessionID curSelectedSession = new SessionID(userJid.toString(), JID, "Scytale"); + if (!selection) { + _keyManager.verify(curSelectedSession); + } else { + _keyManager.unverify(curSelectedSession); + } + }); + } + + private void buildGUI() { + this.setBorder(BorderFactory.createTitledBorder(OTRResources.getString("otr.settings"))); + this.add(_enableOTR, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + this.add(_closeSessionOff, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(10, 0, 0, 0), 0, 0)); + this.add(_closeSessionOnWindowClose, new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + this.add(_currentKeyLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 5, 0, 0), 0, 0)); + this.add(_privateKey, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(10, 0, 0, 5), 0, 0)); + this.add(_renewPrivateKey, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 5), 0, 0)); + this.add(_keytable, new GridBagConstraints(0, 5, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(20, 5, 10, 5), 0, 0)); + } + + private String getCurrentLocalKey() { + EntityFullJid userJid = SparkManager.getConnection().getUser(); + SessionID mySession = new SessionID(userJid.toString(), "no one", "Scytale"); + String myKey = _keyManager.getLocalFingerprint(mySession); + return myKey; + } + + public JComponent getGUI() { + _keytable = new OTRKeyTable(); + loadRemoteKeys(); + return this; + } + + public boolean isOTREnabled() { + return _enableOTR.isSelected(); + } + + public boolean isCloseOnDisc() { + return _closeSessionOff.isSelected(); + } + + public boolean isCloseOnChatClose() { + return _closeSessionOnWindowClose.isSelected(); + } + +} diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/pref/OTRPreferences.java b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/pref/OTRPreferences.java similarity index 76% rename from src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/pref/OTRPreferences.java rename to plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/pref/OTRPreferences.java index 48a9078d3..dcc50bf1b 100644 --- a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/pref/OTRPreferences.java +++ b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/pref/OTRPreferences.java @@ -1,10 +1,10 @@ -package org.jivesoftware.spark.otrplug.pref; +package org.jivesoftware.spark.plugin.otr.pref; import javax.swing.Icon; import javax.swing.JComponent; -import org.jivesoftware.spark.otrplug.util.OTRProperties; -import org.jivesoftware.spark.otrplug.util.OTRResources; +import org.jivesoftware.spark.plugin.otr.util.OTRProperties; +import org.jivesoftware.spark.plugin.otr.util.OTRResources; import org.jivesoftware.spark.preference.Preference; /** @@ -23,7 +23,7 @@ public String getTitle() { @Override public Icon getIcon() { - return OTRResources.getIcon("otr_pref.png"); + return OTRResources.PLUGIN_ICON; } @Override @@ -33,13 +33,11 @@ public String getTooltip() { @Override public String getListName() { - return OTRResources.getString("otr.list.entry"); } @Override public String getNamespace() { - // TODO Auto-generated method stub return null; } @@ -51,8 +49,6 @@ public JComponent getGUI() { @Override public void load() { - // TODO Auto-generated method stub - } @Override @@ -61,31 +57,25 @@ public void commit() { OTRProperties.getInstance().setOTRCloseOnChatClose(pref.isCloseOnChatClose()); OTRProperties.getInstance().setOTRCloseOnDisc(pref.isCloseOnDisc()); OTRProperties.getInstance().save(); - } @Override public boolean isDataValid() { - // TODO Auto-generated method stub return true; } @Override public String getErrorMessage() { - // TODO Auto-generated method stub return null; } @Override public Object getData() { - // TODO Auto-generated method stub return null; } @Override public void shutdown() { - // TODO Auto-generated method stub - } } diff --git a/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/ui/OTRConnectionPanel.java b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/ui/OTRConnectionPanel.java new file mode 100644 index 000000000..9fcc09cdd --- /dev/null +++ b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/ui/OTRConnectionPanel.java @@ -0,0 +1,151 @@ +package org.jivesoftware.spark.plugin.otr.ui; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.util.Timer; +import java.util.TimerTask; + +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.plugin.otr.OTRManager; +import org.jivesoftware.spark.plugin.otr.impl.OTRSession; +import org.jivesoftware.spark.plugin.otr.util.OTRResources; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; + +import static java.awt.GridBagConstraints.NONE; +import static java.awt.GridBagConstraints.NORTHWEST; + +/** + * Shows StyledDocuments in a transcript window for info if the session established successfully or not. + * + * @author Bergunde Holger + */ +public class OTRConnectionPanel { + + private final ChatRoomImpl _chatRoom; + private JLabel _label; + private ImageIcon _icon; + private JPanel _conPanel; + private int _i; + private final JButton _retry; + private final JButton _authenticate; + private boolean _successful = false; + private boolean _waiting = false; + + public OTRConnectionPanel(ChatRoomImpl chatroom) { + _chatRoom = chatroom; + _retry = new JButton(OTRResources.getString("otr.retry")); + _retry.addActionListener(e -> { + OTRManager.getInstance().startOtrWithUser(_chatRoom.getParticipantJID()); + }); + _retry.setVisible(false); + _authenticate = new JButton(OTRResources.getString("otr.authenticate")); + _authenticate.addActionListener(e -> { + OTRManager.getInstance().authenticateUser(_chatRoom.getParticipantJID()); + _authenticate.setVisible(false); + }); + _authenticate.setVisible(false); + } + + /** + * Indicates that OTR is trying to establish an OTR session. This will inject a styledDocument. + * You have 10 seconds to approve that the connection was successful using the method successfullyCon() + */ + public void tryToStart() { + if (_successful || _waiting) { + return; + } + renewPanel(); + _icon.setImage(SparkRes.getImageIcon(SparkRes.Icon.BUSY_IMAGE).getImage()); + _conPanel.setVisible(true); + _i = 10; + _label.setText(OTRResources.getString("otr.try.to.connect.for.seconds", _i)); + + Timer t = new Timer(); + TimerTask task = new TimerTask() { + + @Override + public void run() { + if (_i > 0 && !_successful) { + _waiting = true; + _label.setText(OTRResources.getString("otr.try.to.connect.for.seconds", _i)); + decI(); + } else if (!_successful) { + _waiting = true; + _icon.setImage(SparkRes.getImageIcon(SparkRes.Icon.SMALL_DELETE).getImage()); + _label.setText(OTRResources.getString("otr.failed.to.establish", _i)); + _retry.setVisible(true); + this.cancel(); + } else { + this.cancel(); + } + } + }; + t.scheduleAtFixedRate(task, 0, 1000); + } + + private void renewPanel() { + _conPanel = new JPanel(new GridBagLayout()); + _label = new JLabel(); + _icon = new ImageIcon(); + + _conPanel.add(new JLabel(_icon), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, NORTHWEST, NONE, new Insets(0, 10, 0, 0), 0, 0)); + _conPanel.add(_label, new GridBagConstraints(1, 0, 1, 1, 0.7, 0.0, NORTHWEST, NONE, new Insets(0, 15, 0, 0), 0, 0)); + _conPanel.add(_retry, new GridBagConstraints(2, 0, 1, 1, 2.0, 0.0, NORTHWEST, NONE, new Insets(0, 10, 0, 0), 0, 0)); + _conPanel.add(_authenticate, new GridBagConstraints(3, 0, 1, 1, 2.0, 0.0, NORTHWEST, NONE, new Insets(0, 10, 0, 0), 0, 0)); + + _chatRoom.getTranscriptWindow().addComponent(_conPanel); + _chatRoom.scrollToBottom(); + } + + /** + * Indicates in the transcript window that the OTR session has been closed + */ + public void connectionClosed() { + if (!_successful) { + return; + } + renewPanel(); + _authenticate.setVisible(false); + _successful = false; + _label.setText(OTRResources.getString("otr.disconnected")); + _icon.setImage(SparkRes.getImageIcon(SparkRes.Icon.SMALL_STOP).getImage()); + _conPanel.setVisible(true); + } + + private void decI() { + --_i; + } + + /** + * Should be called after you called tryToStart(). + * It will indicate that the session is now encrypted + */ + public void successfullyCon() { + if (_successful) { + return; + } + if (!_waiting) { + renewPanel(); + } + _retry.setVisible(false); + OTRManager otrManager = OTRManager.getInstance(); + OTRSession otrSession = otrManager.getOtrSession(_chatRoom.getParticipantJID().toString()); + boolean isVerified = otrManager.getKeyManager().isVerified(otrSession.getMySession().getSessionID()); + if (!isVerified) { + _authenticate.setVisible(true); + } + _conPanel.setVisible(true); + _successful = true; + _waiting = false; + _icon.setImage(SparkRes.getImageIcon(SparkRes.Icon.SMALL_CHECK).getImage()); + String verifiedStatus = OTRResources.getString(isVerified ? "otr.key.is.verified" : "otr.key.not.verified"); + _label.setText(OTRResources.getString("otr.successfull") + " " + verifiedStatus); + } + +} diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/util/OTRProperties.java b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/util/OTRProperties.java similarity index 75% rename from src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/util/OTRProperties.java rename to plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/util/OTRProperties.java index 42157685b..941684026 100644 --- a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/util/OTRProperties.java +++ b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/util/OTRProperties.java @@ -1,4 +1,4 @@ -package org.jivesoftware.spark.otrplug.util; +package org.jivesoftware.spark.plugin.otr.util; import java.io.File; import java.io.FileInputStream; @@ -6,24 +6,21 @@ import java.io.IOException; import java.util.Properties; import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.util.log.Log; /** * OTRProperties file stuff * * @author Bergunde Holger - * */ public class OTRProperties { - private Properties props; - private File configFile; + private final Properties props; private static final Object LOCK = new Object(); private static OTRProperties instance = null; /** * returns the Instance of this Properties file - * - * @return */ public static OTRProperties getInstance() { synchronized (LOCK) { @@ -36,27 +33,21 @@ public static OTRProperties getInstance() { private OTRProperties() { this.props = new Properties(); - try { props.load(new FileInputStream(getConfigFile())); - } catch (IOException e) { - // Can't load ConfigFile + } catch (IOException ignored) { } - } private File getConfigFile() { - if (configFile == null) - configFile = new File(SparkManager.getUserDirectory(), "otr.properties"); - - return configFile; + return new File(SparkManager.getUserDirectory(), "otr.properties"); } public void save() { try { - props.store(new FileOutputStream(getConfigFile()), "Storing OTRPlugin properties"); + props.store(new FileOutputStream(getConfigFile()), null); } catch (Exception e) { - e.printStackTrace(); + Log.error(e); } } @@ -84,9 +75,6 @@ public void setOTRCloseOnChatClose(boolean enabled) { setBoolean("OTRCloseOnChatClose", enabled); } - // =============================================================================== - // =============================================================================== - // =============================================================================== private boolean getBoolean(String property, boolean defaultValue) { return Boolean.parseBoolean(props.getProperty(property, Boolean.toString(defaultValue))); } diff --git a/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/util/OTRResources.java b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/util/OTRResources.java new file mode 100644 index 000000000..1dffbb46d --- /dev/null +++ b/plugins/otr/src/main/java/org/jivesoftware/spark/plugin/otr/util/OTRResources.java @@ -0,0 +1,49 @@ +package org.jivesoftware.spark.plugin.otr.util; + +import java.text.MessageFormat; +import java.util.Objects; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +import javax.swing.ImageIcon; + +/** + * OTRResources needed to load icons and language files into the OTR plugin + * + * @author Bergunde Holger + */ +public class OTRResources { + + private static final PropertyResourceBundle prb = (PropertyResourceBundle) ResourceBundle.getBundle("i18n/otrplugin_i18n"); + private static ClassLoader cl = OTRResources.class.getClassLoader(); + public static final ImageIcon PLUGIN_ICON = getImageIcon("otr_pref.png"); + public static final ImageIcon ICON_OTR_ON = getImageIcon("otr_on.png"); + public static final ImageIcon ICON_OTR_OFF = getImageIcon("otr_off.png"); + + /** + * Returns a string from the language file + */ + public static String getString(String propertyName) { + try { + return prb.getString(propertyName); + } catch (Exception e) { + return propertyName; + } + } + + /** + * Returns a string with wildcards + */ + public static String getString(String propertyName, Object... obj) { + try { + String str = prb.getString(propertyName); + return MessageFormat.format(str, obj); + } catch (Exception e) { + return propertyName; + } + } + + private static ImageIcon getImageIcon(String icon) { + return new ImageIcon(Objects.requireNonNull(cl.getResource(icon))); + } +} diff --git a/plugins/otr/src/main/plugin-metadata/plugin.xml b/plugins/otr/src/main/plugin-metadata/plugin.xml new file mode 100644 index 000000000..60dd5edfe --- /dev/null +++ b/plugins/otr/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,12 @@ + + ${project.name} + ${project.version} + ${project.description} + Holger Bergunde + https://IgniteRealtime.org + support@IgniteRealtime.org + 3.1.0 + 11 + org.jivesoftware.spark.plugin.otr.OTRPlugin + Windows,Linux,Mac + diff --git a/plugins/otr/src/main/resources/i18n/otrplugin_i18n.properties b/plugins/otr/src/main/resources/i18n/otrplugin_i18n.properties new file mode 100644 index 000000000..de0e6ffea --- /dev/null +++ b/plugins/otr/src/main/resources/i18n/otrplugin_i18n.properties @@ -0,0 +1,36 @@ +otr.title = Off-the-Record Messaging +otr.list.entry = OTR Messaging +otr.settings = OTR Settings +otr.enable = OTR Enabled +current.priv.key = Current private key: +renew.current.key = Generate a new key +otr.close.session.on.window.close = Close OTR session when chat window is closed +otr.close.session.on.contact.off = Close OTR session when contact went offline +otr.key.not.verified.title = Key not verified +otr.question.verify = Verify? +otr.question.authorize=Do you want to start authorization verification? +otr.key.not.verified.text = Following key is not verified! +otr.start.session.with = OTR encrypted Session with {0} +otr.not.enabled = You received an OTR request. You should enable OTR in preferences. +otr.chat.button.tooltip = Message encryption + +# SMP verification +otr.authentication.request={0} asked for an authentication +otr.authentication.giveAnswer=Please give an answer or a shared secret +otr.authorization.completed=Authorization completed +otr.authenticate=Authenticate +otr.authenticate.question=Pick a shared secret (password) known only to you and your buddy. + +#Table Columns +otr.table.jid = User's JID +otr.table.public.key = Public key +otr.key.verified = Verified + +#OTR Panel in Chat +otr.retry = Retry +otr.key.not.verified=Key is not verified! +otr.key.is.verified=Key is verified +otr.try.to.connect.for.seconds = Trying to establish an OTR session. {0}s remaining... +otr.failed.to.establish = Failed to establish OTR session. Timeout. +otr.successfull = OTR successfully establish. Messages will be encrypted. +otr.disconnected = OTR session closed. Messages are no longer encrypted. diff --git a/plugins/otr/src/main/resources/i18n/otrplugin_i18n_de.properties b/plugins/otr/src/main/resources/i18n/otrplugin_i18n_de.properties new file mode 100644 index 000000000..216df1bb4 --- /dev/null +++ b/plugins/otr/src/main/resources/i18n/otrplugin_i18n_de.properties @@ -0,0 +1,26 @@ +otr.title = Off-the-Record Nachrichten Verschlüsselung +otr.list.entry = OTR Verschlüsselung +otr.settings = OTR Einstellungen +otr.enable = OTR Aktivieren +current.priv.key = Aktueller privater Schlüssel: +renew.current.key = Neuen Schlüssel generieren +otr.close.session.on.window.close = OTR Sitzung schließen, wenn Chatfenster geschlossen wird +otr.close.session.on.contact.off = OTR Sitzung schließen, wenn Kontakt sich abmeldet +otr.key.not.verified.title = Schlüssel nicht beglaubigt +otr.question.verify = Beglaubigen? +otr.key.not.verified.text = Folgender Schlüssel ist nicht beglaubigt! +otr.start.session.with = OTR Sitzung mit {0} +otr.chat.button.tooltip = Nachrichtenverschlüsselung +otr.not.enabled = Sie haben eine OTR Anfrage empfagen. Sie sollten OTR in den Einstellungen aktivieren. + +#Table Columns +otr.table.jid = Kontakt +otr.table.public.key = Öffentlicher Schlüssel +otr.key.verified = Beglaubigt + +#OTR Panel in Chat +otr.retry = Wiederholen +otr.try.to.connect.for.seconds = Versuche eine OTR Sitzung aufzubauen. {0}s verbleibend... +otr.failed.to.establish = Fehler beim erstellen der Sitzung. Zeit abgelaufen. +otr.successfull = Sitzung erfolgreich erstellt. Nachrichten werden jetzt verschlüsselt. +otr.disconnected = Sitzung geschlossen. Nachrichten sind ab jetzt nicht mehr verschlüsselt. diff --git a/plugins/otr/src/main/resources/i18n/otrplugin_i18n_fr.properties b/plugins/otr/src/main/resources/i18n/otrplugin_i18n_fr.properties new file mode 100644 index 000000000..95d23716f --- /dev/null +++ b/plugins/otr/src/main/resources/i18n/otrplugin_i18n_fr.properties @@ -0,0 +1,26 @@ +otr.title = OTR (Off-The-Record Messaging - Messages Sécurisés) +otr.list.entry = Messagerie Sécurisée OTR +otr.settings = Réglages de l'OTR +otr.enable = OTR Activé +current.priv.key = Clé privée actuelle: +renew.current.key = Générer une nouvelle clé +otr.close.session.on.window.close = Terminer la session OTR quand la fenêtre de conversation est fermée +otr.close.session.on.contact.off = Terminer la session OTR quand le contact se déconnecte +otr.key.not.verified.title = Clé non vérifiée +otr.question.verify = Vérifier? +otr.key.not.verified.text = Cette clé n'est pas vérifiée! +otr.start.session.with = Session cryptée par OTR avec {0} +otr.not.enabled = Vous avez reГ§u une demande de session cryptée OTR. Vous devez activer l'OTR dans le menu Spark/Préférences/OTR. +otr.chat.button.tooltip = Chiffrement du message + +#Table Columns +otr.table.jid = JID de l'utilisateur +otr.table.public.key = Clé publique +otr.key.verified = Vérifié + +#OTR Panel in Chat +otr.retry = Réessayer +otr.try.to.connect.for.seconds = Démarrage d'une session chiffrée OTR. {0}s restantes... +otr.failed.to.establish = Echec lors du démarrage de la session OTR. Timeout. +otr.successfull = La session OTR a démarré avec succГÐs. Les messages seront chiffrés. +otr.disconnected = La session OTR a été arrêtée. Les messages ne seront plus chiffrés. diff --git a/plugins/otr/src/main/resources/i18n/otrplugin_i18n_lt.properties b/plugins/otr/src/main/resources/i18n/otrplugin_i18n_lt.properties new file mode 100644 index 000000000..77827a90e --- /dev/null +++ b/plugins/otr/src/main/resources/i18n/otrplugin_i18n_lt.properties @@ -0,0 +1,26 @@ +otr.title = Konfidencialus (OTR) susiraÅ¡inÄ—jimas +otr.list.entry = OTR susiraÅ¡inÄ—jimas +otr.settings = OTR nustatymai +otr.enable = OTR įjungtas +current.priv.key = Einamas privatus raktas: +renew.current.key = Generuoti naujÄ… raktÄ… +otr.close.session.on.window.close = Užbaigti OTR sesijÄ…, kai uždaromas pokalbio langas +otr.close.session.on.contact.off = Užbaigti OTR sesijÄ…, kai adresatas atsijungia +otr.key.not.verified.title = Raktas nepatikrintas +otr.question.verify = Patikrinti? +otr.key.not.verified.text = Raktas nÄ—ra patikrintas! +otr.start.session.with = OTR užšifruota sesija su {0} +otr.not.enabled = JÅ«s gavote OTR užklausÄ…. JÅ«s turite įjungti OTR nustatymuose. +otr.chat.button.tooltip = Pokalbio Å¡ifravimas + +#Table Columns +otr.table.jid = Vartotojo JID +otr.table.public.key = VieÅ¡as raktas +otr.key.verified = Patikrintas + +#OTR Panel in Chat +otr.retry = Pakartoti +otr.try.to.connect.for.seconds = Bandoma užmegzti OTR sesijÄ…. {0} s liko... +otr.failed.to.establish = Nepavyko užmegzti OTR sesijos. BaigÄ—si laikas. +otr.successfull = OTR sesija sÄ—kmingai užmegzta. ŽinutÄ—s bus užšifruotos. +otr.disconnected = OTR sesija uzdaryta. ŽinutÄ—s daugiau nebus Å¡ifruojamos. diff --git a/plugins/otr/src/main/resources/i18n/otrplugin_i18n_pl.properties b/plugins/otr/src/main/resources/i18n/otrplugin_i18n_pl.properties new file mode 100644 index 000000000..396896b9f --- /dev/null +++ b/plugins/otr/src/main/resources/i18n/otrplugin_i18n_pl.properties @@ -0,0 +1,26 @@ +otr.title = Komunikacja szyfrowana +otr.list.entry = Szyfrowana komunikacja +otr.settings = Ustawienia OTR +otr.enable = OTR Włączona +current.priv.key = Bieżący prywatny klucz: +renew.current.key = Generuj nowy klucz +otr.close.session.on.window.close = Zamknij sesjÄ™ OTR gdy okno rozmowy zostanie zamkniÄ™te +otr.close.session.on.contact.off = Zamknij sesjÄ™ OTR gdy kontakt siÄ™ wyloguje +otr.key.not.verified.title = Klucz niezweryfikowany +otr.question.verify = Zweryfikować? +otr.key.not.verified.text = Podany klucz nie zostaÅ‚ zweryfikowany! +otr.start.session.with = Szyfrowana sesja OTR z {0} +otr.not.enabled = OtrzymaÅ‚eÅ› żądanie szyfrowanej sesji OTR. Włącz szyfrowanÄ… komunikacjÄ™ OTR w ustawieniach. +otr.chat.button.tooltip = Wiadomość szyfrowana + +#Table Columns +otr.table.jid = JID użytkownika +otr.table.public.key = Klucz publiczny +otr.key.verified = Zweryfikowany klucz + +#OTR Panel in Chat +otr.retry = Ponów +otr.try.to.connect.for.seconds = PróbujÄ™ ustanowić sesjÄ™ OTR. PozostaÅ‚o {0}s ... +otr.failed.to.establish = Nie ustanowiono sesji OTR. Przekroczono czas. +otr.successfull = Ustanowiono sesjÄ™ szyfrowanÄ… OTR. WiadomoÅ›ci bÄ™dÄ… szyfrowane. +otr.disconnected = Sesja szyfrowana OTR zostaÅ‚a zamkniÄ™ta. WiadomoÅ›ci nie bÄ™dÄ… szyfrowane. diff --git a/plugins/otr/src/main/resources/i18n/otrplugin_i18n_zh_TW.properties b/plugins/otr/src/main/resources/i18n/otrplugin_i18n_zh_TW.properties new file mode 100644 index 000000000..ab9c2ce3e --- /dev/null +++ b/plugins/otr/src/main/resources/i18n/otrplugin_i18n_zh_TW.properties @@ -0,0 +1,26 @@ +otr.title = åŠ å¯†è¨Šæ¯ +otr.list.entry = åŠ å¯†è¨Šæ¯ +otr.settings = 加密訊æ¯è¨­å®š +otr.enable = 啟動加密功能 +current.priv.key = ç›®å‰ç§é‘°: +renew.current.key = 產生一個新的ç§é‘° +otr.close.session.on.window.close = ç•¶èŠå¤©è¦–窗關閉時,關閉加密會議 +otr.close.session.on.contact.off = ç•¶è¯çµ¡äººé›¢ç·šæ™‚,關閉加密會議 +otr.key.not.verified.title = ç§é‘°æœªé©—è­‰ +otr.question.verify = 是å¦é©—è­‰? +otr.key.not.verified.text = 以下ç§é‘°æœªé©—è­‰! +otr.start.session.with = 與 {0} 進行ä¸å…¬é–‹çš„加密會議 +otr.not.enabled = 您收到一個是å¦åŠ å¯†çš„è©¢å•. 您應該在設定中啟動加密功能. +otr.chat.button.tooltip = 訊æ¯åР坆 + +#Table Columns +otr.table.jid = è¯çµ¡äººçš„ JID +otr.table.public.key = 公鑰 +otr.key.verified = é©—è­‰ + +#OTR Panel in Chat +otr.retry = é‡è©¦ +otr.try.to.connect.for.seconds = 嘗試建立一個加密會議. 剩下 {0}ç§’ ... +otr.failed.to.establish = 無法建立加密會議. 建立時間逾時. +otr.successfull = æˆåŠŸå»ºç«‹åŠ å¯†ç‹€æ…‹. 訊æ¯å°‡è¢«åР坆. +otr.disconnected = 關閉加密會議. 訊æ¯ä¸åœ¨åŠ å¯†ç‹€æ…‹. diff --git a/src/plugins/otr/src/resources/otr_off.png b/plugins/otr/src/main/resources/otr_off.png similarity index 100% rename from src/plugins/otr/src/resources/otr_off.png rename to plugins/otr/src/main/resources/otr_off.png diff --git a/plugins/otr/src/main/resources/otr_on.png b/plugins/otr/src/main/resources/otr_on.png new file mode 100644 index 000000000..0415edaad Binary files /dev/null and b/plugins/otr/src/main/resources/otr_on.png differ diff --git a/plugins/otr/src/main/resources/otr_pref.png b/plugins/otr/src/main/resources/otr_pref.png new file mode 100644 index 000000000..efce07de1 Binary files /dev/null and b/plugins/otr/src/main/resources/otr_pref.png differ diff --git a/plugins/phone/pom.xml b/plugins/phone/pom.xml new file mode 100644 index 000000000..14f5523cd --- /dev/null +++ b/plugins/phone/pom.xml @@ -0,0 +1,41 @@ + + 4.0.0 + + + org.igniterealtime.spark + parent + 3.1.0-SNAPSHOT + ../../pom.xml + + + phone + 2.0.0 + + Phone manager + Handles general phone behavior in Spark + + + + Jive Software + spark@jivesoftware.com + + Author + + + + + + org.igniterealtime.spark + spark-core + ${project.parent.version} + provided + + + javax.media + jmf + 2.1.1e + provided + + + diff --git a/src/java/org/jivesoftware/spark/phone/Phone.java b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/Phone.java similarity index 84% rename from src/java/org/jivesoftware/spark/phone/Phone.java rename to plugins/phone/src/main/java/org/jivesoftware/spark/phone/Phone.java index e87b3b1cd..f8ec86d6f 100644 --- a/src/java/org/jivesoftware/spark/phone/Phone.java +++ b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/Phone.java @@ -1,16 +1,12 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * + *

      * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,12 +15,13 @@ */ package org.jivesoftware.spark.phone; +import org.jxmpp.jid.EntityBareJid; + import javax.swing.Action; import java.util.Collection; /** - * */ public interface Phone { @@ -34,6 +31,6 @@ public interface Phone { * @param jid the jid of the user. * @return a collection of actions. */ - Collection getPhoneActions(String jid); + Collection getPhoneActions(EntityBareJid jid); } diff --git a/plugins/phone/src/main/java/org/jivesoftware/spark/phone/PhoneManager.java b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/PhoneManager.java new file mode 100644 index 000000000..4717b400c --- /dev/null +++ b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/PhoneManager.java @@ -0,0 +1,369 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.phone; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Vector; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.media.CaptureDeviceInfo; +import javax.media.CaptureDeviceManager; +import javax.media.MediaLocator; +import javax.media.format.AudioFormat; +import javax.media.format.VideoFormat; +import javax.media.protocol.DataSource; +import javax.swing.Action; +import javax.swing.JMenu; +import javax.swing.JPopupMenu; + +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.ContextMenuListener; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomButton; +import org.jivesoftware.spark.ui.ChatRoomListener; +import org.jivesoftware.spark.ui.ContactItem; +import org.jivesoftware.spark.ui.ContactList; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.sparkimpl.plugin.phone.JMFInit; + +/** + * Handles general phone behavior in Spark. + * This allows for many different phone systems to plug into Spark in a more elegant way. + */ +public class PhoneManager implements ChatRoomListener, ContextMenuListener { + private static final Object LOCK = new Object(); + private static PhoneManager singleton; + // Static Media Locator + static private MediaLocator mediaLocator = null; + // Static Media Locator Preference + static private boolean useStaticLocator = false; + // Static using MediaLocator + static private boolean usingMediaLocator = false; + // Static DataSource + static private DataSource ds; + private final List phones = new CopyOnWriteArrayList<>(); + private final List currentCalls = new ArrayList<>(); + + private PhoneManager() { + JMFInit.start(false); + if (Spark.isWindows() || Spark.isLinux()) { + setUseStaticLocator(true); + } + } + + /** + * Returns the singleton instance of PhoneManager, + * creating it if necessary. + *

      + * + * @return the singleton instance of PhoneManager + */ + public static PhoneManager getInstance() { + // Synchronize on LOCK to ensure that we don't end up creating + // two singletons. + synchronized (LOCK) { + if (null == singleton) { + PhoneManager controller = new PhoneManager(); + singleton = controller; + return controller; + } + } + return singleton; + } + + public static String getNumbersFromPhone(String number) { + if (number == null) { + return null; + } + + number = number.replace("-", ""); + number = number.replace("(", ""); + number = number.replace(")", ""); + number = number.replace(" ", ""); + if (number.startsWith("1")) { + number = number.substring(1); + } + + return number; + } + + public static MediaLocator getMediaLocator(String locator) { + MediaLocator auxLocator; + + System.out.println("--------------------------------"); + System.out.println("locator: " + locator); + + Vector vectorAudioDevices = CaptureDeviceManager.getDeviceList(new AudioFormat(AudioFormat.LINEAR)); + for (CaptureDeviceInfo infoCaptureDevice : vectorAudioDevices) { + System.out.println(infoCaptureDevice.getLocator() + "-" + locator); + if (infoCaptureDevice.getLocator().toString().equals(locator)) { + System.out.println("Found: " + locator); + return infoCaptureDevice.getLocator(); + } + } + + Vector vectorVideoDevices = CaptureDeviceManager.getDeviceList(new VideoFormat(VideoFormat.RGB)); + for (CaptureDeviceInfo infoCaptureDevice : vectorVideoDevices) { + System.out.println(infoCaptureDevice.getLocator() + "-" + locator); + if (infoCaptureDevice.getLocator().toString().equals(locator)) { + System.out.println("Found: " + locator); + return infoCaptureDevice.getLocator(); + } + } + + + if (useStaticLocator) { + if (mediaLocator == null) { + mediaLocator = new MediaLocator(locator); + } + auxLocator = mediaLocator; + //usingMediaLocator=true; + } else { + auxLocator = new MediaLocator(locator); + } + + return auxLocator; + } + + public static DataSource getDataSource(String locator) { + + if (ds == null) { + + try { + ds = javax.media.Manager.createDataSource(getMediaLocator(locator)); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + } + + return ds; + } + + public static DataSource getDataSource(MediaLocator locator) { + + if (ds == null) { + + try { + ds = javax.media.Manager.createDataSource(locator); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + } + + return ds; + } + + public static boolean isUsingMediaLocator() { + return usingMediaLocator; + } + + public static void setUsingMediaLocator(boolean usingMediaLocator) { + PhoneManager.usingMediaLocator = usingMediaLocator; + } + + public static boolean isUseStaticLocator() { + return useStaticLocator; + } + + public static void setUseStaticLocator(boolean useStaticLocator) { + PhoneManager.useStaticLocator = useStaticLocator; + } + + private void addListeners() { + // Handle ChatRooms. + final ChatManager chatManager = SparkManager.getChatManager(); + chatManager.addChatRoomListener(this); + + // Handle ContextMenus. + final ContactList contactList = SparkManager.getWorkspace().getContactList(); + contactList.addContextMenuListener(this); + } + + public void addPhone(Phone phone) { + if (phones.isEmpty()) { + addListeners(); + } + + phones.add(phone); + } + + public void removePhone(Phone phone) { + phones.remove(phone); + } + + @Override + public void chatRoomOpened(final ChatRoom room) { + if (!phones.isEmpty() && room instanceof ChatRoomImpl) { + final ChatRoomImpl chatRoomImpl = (ChatRoomImpl) room; + final ChatRoomButton dialButton = new ChatRoomButton(SparkRes.getImageIcon(SparkRes.Icons.DIAL_PHONE_IMAGE_24x24)); + dialButton.setToolTipText(Res.getString("tooltip.place.voice.call")); + + final List actions = new ArrayList<>(); + SwingWorker actionWorker = new SwingWorker() { + @Override + public Object construct() { + for (Phone phone : phones) { + final Collection phoneActions = phone.getPhoneActions(chatRoomImpl.getParticipantJID()); + if (phoneActions != null) { + actions.addAll(phoneActions); + } + } + return actions; + } + + @Override + public void finished() { + if (!actions.isEmpty()) { + room.addChatRoomButton(dialButton, true); + } + } + }; + + actionWorker.start(); + dialButton.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(final MouseEvent e) { + SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + try { + Thread.sleep(50); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + return true; + } + + @Override + public void finished() { + // Handle actions. + if (!actions.isEmpty()) { + // Display PopupMenu + final JPopupMenu menu = new JPopupMenu(); + for (Action action : actions) { + menu.add(action); + } + menu.show(dialButton, e.getX(), e.getY()); + } + } + }; + worker.start(); + + } + }); + } + } + + @Override + public void chatRoomLeft(ChatRoom room) { + } + + @Override + public void chatRoomClosed(ChatRoom room) { + } + + @Override + public void chatRoomActivated(ChatRoom room) { + } + + @Override + public void userHasJoined(ChatRoom room, String userid) { + } + + @Override + public void userHasLeft(ChatRoom room, String userid) { + } + + @Override + public void poppingUp(Object object, final JPopupMenu popup) { + if (phones.isEmpty()) { + return; + } + if (object instanceof ContactItem) { + final ContactItem contactItem = (ContactItem) object; + final List actions = new ArrayList<>(); + + SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + for (Phone phone : phones) { + final Collection itemActions = phone.getPhoneActions(contactItem.getJid().asEntityBareJidIfPossible()); + actions.addAll(itemActions); + } + return null; + } + + @Override + public void finished() { + // Add phone actions to a popup menu + if (actions.isEmpty()) { + return; + } + final JMenu dialMenu = new JMenu(Res.getString("title.dial.phone")); + dialMenu.setIcon(SparkRes.getImageIcon(SparkRes.Icons.DIAL_PHONE_IMAGE_16x16)); + + for (Action action : actions) { + dialMenu.add(action); + } + + int count = popup.getComponentCount(); + if (count > 2) { + popup.insert(dialMenu, 2); + } + + popup.invalidate(); + popup.validate(); + popup.repaint(); + } + }; + worker.start(); + } + } + + @Override + public void poppingDown(JPopupMenu popup) { + } + + @Override + public boolean handleDefaultAction(MouseEvent e) { + return false; + } + + public void addCurrentCall(String phoneNumber) { + currentCalls.add(phoneNumber); + } + + public void removeCurrentCall(String phoneNumber) { + currentCalls.remove(phoneNumber); + } + + public boolean containsCurrentCall(String phoneNumber) { + return currentCalls.contains(phoneNumber); + } +} diff --git a/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/PhoneClient.java b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/PhoneClient.java new file mode 100644 index 000000000..036159a65 --- /dev/null +++ b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/PhoneClient.java @@ -0,0 +1,31 @@ +package org.jivesoftware.spark.phone.client; + +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.spark.phone.client.event.BasePhoneEventListener; +import org.jivesoftware.sparkimpl.plugin.phone.PhonePlugin; +import org.jxmpp.jid.BareJid; + +import java.util.concurrent.CopyOnWriteArrayList; + +public class PhoneClient { + private final XMPPConnection connection; + private final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList(); + + public PhoneClient(XMPPConnection conn) { + this.connection = conn; + } + + public boolean isPhoneEnabled(BareJid bareJid) { + return true; + } + + public void addEventListener(BasePhoneEventListener phoneListener) { + listeners.addIfAbsent(phoneListener); + } + + public void dialByExtension(String number) { + } + + public void dialByJID(BareJid jid) { + } +} diff --git a/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/action/PhoneActionIQProvider.java b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/action/PhoneActionIQProvider.java new file mode 100644 index 000000000..1cf1d482a --- /dev/null +++ b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/action/PhoneActionIQProvider.java @@ -0,0 +1,4 @@ +package org.jivesoftware.spark.phone.client.action; + +public class PhoneActionIQProvider { +} diff --git a/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/event/BasePhoneEventListener.java b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/event/BasePhoneEventListener.java new file mode 100644 index 000000000..85d84f044 --- /dev/null +++ b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/event/BasePhoneEventListener.java @@ -0,0 +1,9 @@ +package org.jivesoftware.spark.phone.client.event; + +public interface BasePhoneEventListener { + void handleOnPhone(OnPhoneEvent event); + + void handleHangUp(HangUpEvent event); + + void handleRing(RingEvent event); +} diff --git a/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/event/HangUpEvent.java b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/event/HangUpEvent.java new file mode 100644 index 000000000..84a10f9c1 --- /dev/null +++ b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/event/HangUpEvent.java @@ -0,0 +1,4 @@ +package org.jivesoftware.spark.phone.client.event; + +public class HangUpEvent { +} diff --git a/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/event/OnPhoneEvent.java b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/event/OnPhoneEvent.java new file mode 100644 index 000000000..b59cb05b4 --- /dev/null +++ b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/event/OnPhoneEvent.java @@ -0,0 +1,4 @@ +package org.jivesoftware.spark.phone.client.event; + +public class OnPhoneEvent { +} diff --git a/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/event/PhoneEventPacketExtensionProvider.java b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/event/PhoneEventPacketExtensionProvider.java new file mode 100644 index 000000000..755ba5ce6 --- /dev/null +++ b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/event/PhoneEventPacketExtensionProvider.java @@ -0,0 +1,4 @@ +package org.jivesoftware.spark.phone.client.event; + +public class PhoneEventPacketExtensionProvider { +} diff --git a/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/event/RingEvent.java b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/event/RingEvent.java new file mode 100644 index 000000000..cabf99f14 --- /dev/null +++ b/plugins/phone/src/main/java/org/jivesoftware/spark/phone/client/event/RingEvent.java @@ -0,0 +1,11 @@ +package org.jivesoftware.spark.phone.client.event; + +public class RingEvent { + public String getCallerIDName() { + return "TODO CallerIDName"; + } + + public String getCallerID() { + return "TODO CallerID"; + } +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/phone/DialPanel.java b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/DialPanel.java similarity index 91% rename from src/java/org/jivesoftware/sparkimpl/plugin/phone/DialPanel.java rename to plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/DialPanel.java index 2a24a85fe..ec3263330 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/phone/DialPanel.java +++ b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/DialPanel.java @@ -1,16 +1,12 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * + *

      * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -36,11 +32,11 @@ import java.awt.Insets; public class DialPanel extends JPanel { - private static final long serialVersionUID = 2460254947711336776L; - private JButton dialButton; - private JTextField dialField; + private static final long serialVersionUID = 2460254947711336776L; final JLabel iconLabel; final JPanel dialPanel = new JPanel(); + private final JButton dialButton; + private final JTextField dialField; public DialPanel() { setLayout(new GridBagLayout()); @@ -51,7 +47,7 @@ public DialPanel() { imagePanel.setBackground(Color.white); - iconLabel = new JLabel(SparkRes.getImageIcon(SparkRes.TELEPHONE_24x24)); + iconLabel = new JLabel(SparkRes.getImageIcon(SparkRes.Icons.TELEPHONE_24x24)); iconLabel.setHorizontalAlignment(JLabel.CENTER); iconLabel.setVerticalTextPosition(JLabel.BOTTOM); iconLabel.setHorizontalTextPosition(JLabel.CENTER); diff --git a/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/IncomingCall.java b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/IncomingCall.java new file mode 100644 index 000000000..af1164d94 --- /dev/null +++ b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/IncomingCall.java @@ -0,0 +1,88 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.phone; + +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.resource.Res; + +import javax.swing.JLabel; +import javax.swing.JPanel; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; + +/** + * UI to display incoming call information + */ +public class IncomingCall extends JPanel { + private static final long serialVersionUID = -5840942759253687771L; + private final JLabel callerNameLabel; + private final JLabel callerNumberLabel; + + public IncomingCall() { + setLayout(new GridBagLayout()); + setBackground(Color.white); + + callerNameLabel = new JLabel(); + callerNameLabel.setFont(new Font("Dialog", Font.BOLD, 13)); + callerNameLabel.setHorizontalAlignment(JLabel.CENTER); + + callerNumberLabel = new JLabel(); + callerNumberLabel.setFont(new Font("Dialog", Font.PLAIN, 12)); + callerNumberLabel.setHorizontalAlignment(JLabel.CENTER); + + final JLabel phoneImage = new JLabel(SparkRes.getImageIcon(SparkRes.Icons.TELEPHONE_24x24)); + phoneImage.setHorizontalAlignment(JLabel.CENTER); + phoneImage.setVerticalTextPosition(JLabel.BOTTOM); + phoneImage.setHorizontalTextPosition(JLabel.CENTER); + phoneImage.setText(Res.getString("title.incoming.call")); + phoneImage.setFont(new Font("Dialog", Font.BOLD, 16)); + add(phoneImage, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 10, 0, 10), 0, 0)); + add(callerNameLabel, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 0, 0, 0), 0, 0)); + add(callerNumberLabel, new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 0, 10, 0), 0, 0)); + } + + public void setCallerName(String user) { + callerNameLabel.setText(user); + } + + public void setCallerNumber(String number) { + String buf = ""; + if (number == null) { + return; + } + + if (number.trim().length() == 10) { + buf += "("; + String areaCode = number.substring(0, 3); + buf += areaCode; + buf += ") "; + + String nextThree = number.substring(3, 6); + buf += " "; + buf += nextThree; + buf += "-"; + + String lastThree = number.substring(6, 10); + buf += lastThree; + } + + callerNumberLabel.setText(buf); + } +} diff --git a/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/JMFInit.java b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/JMFInit.java new file mode 100644 index 000000000..b322736cc --- /dev/null +++ b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/JMFInit.java @@ -0,0 +1,250 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.phone; + +import com.sun.media.ExclusiveUse; +import com.sun.media.util.Registry; +import org.jivesoftware.spark.util.log.Log; + +import javax.media.Format; +import javax.media.PlugInManager; +import javax.media.Renderer; +import javax.media.format.AudioFormat; + +import java.awt.Frame; +import java.util.Vector; + +public class JMFInit extends Frame implements Runnable { + private static final long serialVersionUID = 6591937615313371376L; + + public JMFInit(String[] args, boolean visible) { + super("Initializing JMF..."); + Registry.set("secure.allowCaptureFromApplets", true); + Registry.set("secure.allowSaveFileFromApplets", true); + + updateTemp(args); + try { + Registry.commit(); + } catch (Exception e) { + Log.warning("Failed to commit to JMFRegistry!"); + } + + Thread detectThread = new Thread(this); + detectThread.run(); + + /* + * int slept = 0; while (!done && slept < 60 * 1000 * 2) { try { + * Thread.currentThread().sleep(500); } catch (InterruptedException ie) { } + * slept += 500; } + * + * if (!done) { console.error("Detection is taking too long! + * Aborting!"); message("Detection is taking too long! Aborting!"); } + * + * try { Thread.currentThread().sleep(2000); } catch + * (InterruptedException ie) { } + */ + } + + public static void start(boolean visible) { + new JMFInit(null, visible); + } + + @Override + public void run() { + detectDirectAudio(); + detectS8DirectAudio(); + detectCaptureDevices(); + } + + private void updateTemp(String[] args) { + if (args != null && args.length > 0) { + String tempDir = args[0]; + + Log.warning("Setting cache directory to " + tempDir); + try { + Registry.set("secure.cacheDir", tempDir); + Registry.commit(); + + Log.warning("Updated registry"); + } catch (Exception e) { + Log.warning("Couldn't update registry!"); + } + } + } + + private void detectCaptureDevices() { + // check if JavaSound capture is available + Log.warning("Looking for Audio capturer"); + try { + Class dsauto = Class.forName("DirectSoundAuto"); + dsauto.newInstance(); + Log.warning("Finished detecting DirectSound capturer"); + } catch (ThreadDeath td) { + throw td; + } catch (Exception ignored) { + Log.warning("JavaSound capturer detection failed!"); + } + + try { + Class jsauto = Class.forName("JavaSoundAuto"); + jsauto.newInstance(); + Log.warning("Finished detecting javasound capturer"); + } catch (ThreadDeath td) { + throw td; + } catch (Exception ignored) { + Log.warning("JavaSound capturer detection failed!"); + } + + /* + // Check if VFWAuto or SunVideoAuto is available + Log.debug("Looking for video capture devices"); + Class auto = null; + Class autoPlus = null; + try { + auto = Class.forName("VFWAuto"); + } + catch (Exception ignored) { + } + if (auto == null) { + try { + auto = Class.forName("SunVideoAuto"); + } + catch (Exception ignored) { + } + try { + autoPlus = Class.forName("SunVideoPlusAuto"); + } + catch (Exception ignored) { + } + } + if (auto == null) { + try { + auto = Class.forName("V4LAuto"); + } + catch (Exception ignored) { + } + } + try { + Object instance = auto.newInstance(); + if (autoPlus != null) { + Object instancePlus = autoPlus.newInstance(); + } + Log.debug("Finished detecting video capture devices"); + } + catch (ThreadDeath td) { + throw td; + } + catch (Throwable ignored) { + Log.warning("Capture device detection failed!"); + } + */ + } + + private void detectDirectAudio() { + Class cls; + int plType = PlugInManager.RENDERER; + String dar = "com.sun.media.renderer.audio.DirectAudioRenderer"; + try { + // Check if this is the Windows Performance Pack - hack + Class.forName("VFWAuto"); + // Check if DS capture is supported, otherwise fail DS renderer + // since NT doesn't have capture + Class.forName("com.sun.media.protocol.dsound.DSound"); + // Find the renderer class and instantiate it. + cls = Class.forName(dar); + + Renderer rend = (Renderer) cls.newInstance(); + try { + // Set the format and open the device + AudioFormat af = new AudioFormat(AudioFormat.LINEAR, 44100, 16, + 2); + rend.setInputFormat(af); + rend.open(); + Format[] inputFormats = rend.getSupportedInputFormats(); + // Register the device + PlugInManager.addPlugIn(dar, inputFormats, new Format[0], plType); + // Move it to the top of the list + Vector rendList = PlugInManager.getPlugInList(null, null, plType); + int listSize = rendList.size(); + if (rendList.elementAt(listSize - 1).equals(dar)) { + rendList.removeElementAt(listSize - 1); + rendList.insertElementAt(dar, 0); + PlugInManager.setPlugInList(rendList, plType); + PlugInManager.commit(); + Log.debug("registered"); + } + rend.close(); + } catch (Throwable t) { + Log.error("Error ", t); + } + } catch (Throwable tt) { + // Nothing to do + Log.error(tt.getMessage()); + } + } + + private void detectS8DirectAudio() { + int plType = PlugInManager.RENDERER; + String dar = "com.sun.media.renderer.audio.DirectAudioRenderer"; + try { + // Check if this is the solaris Performance Pack - hack + Class.forName("SunVideoAuto"); + // Find the renderer class and instantiate it. + Class cls = Class.forName(dar); + Renderer rend = (Renderer) cls.newInstance(); + if (rend instanceof ExclusiveUse + && !((ExclusiveUse) rend).isExclusive()) { + // sol8+, DAR supports mixing + Vector rendList = PlugInManager.getPlugInList(null, null, plType); + int listSize = rendList.size(); + boolean found = false; + String rname; + for (int i = 0; i < listSize; i++) { + rname = rendList.elementAt(i); + if (rname.equals(dar)) { // DAR is in the registry + found = true; + rendList.removeElementAt(i); + break; + } + } + + if (found) { + rendList.insertElementAt(dar, 0); + PlugInManager.setPlugInList(rendList, plType); + PlugInManager.commit(); + } + } + } catch (Throwable tt) { + // Nothing to do + Log.error(tt); + } + } + +// private void createGUI() { +// TextArea textBox = new TextArea(5, 50); +// add("Center", textBox); +// textBox.setEditable(false); +// addNotify(); +// pack(); +// +// int scrWidth = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth(); +// int scrHeight = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight(); +// +// setLocation((scrWidth - getWidth()) / 2, (scrHeight - getHeight()) / 2); +// setVisible(visible); +// } + +} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/phone/OnPhone.java b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/OnPhone.java similarity index 87% rename from src/java/org/jivesoftware/sparkimpl/plugin/phone/OnPhone.java rename to plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/OnPhone.java index c60254e00..d5b5152d4 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/phone/OnPhone.java +++ b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/OnPhone.java @@ -1,16 +1,12 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * + *

      * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -34,22 +30,23 @@ import java.awt.Insets; import java.util.Date; +/** + * UI showing icon and tracking time + */ public class OnPhone extends JPanel { - private static final long serialVersionUID = -7344123390643812061L; - private JLabel iconLabel; - private TimeTrackingLabel timeLabel; + private static final long serialVersionUID = -7344123390643812061L; + private final JLabel iconLabel; + private final TimeTrackingLabel timeLabel; public OnPhone() { setLayout(new BorderLayout()); final JPanel imagePanel = new JPanel(); imagePanel.setLayout(new GridBagLayout()); - - imagePanel.setBackground(Color.white); // Handle Icon Label - iconLabel = new JLabel(SparkRes.getImageIcon(SparkRes.TELEPHONE_24x24)); + iconLabel = new JLabel(SparkRes.getImageIcon(SparkRes.Icons.TELEPHONE_24x24)); iconLabel.setHorizontalAlignment(JLabel.CENTER); iconLabel.setVerticalTextPosition(JLabel.BOTTOM); iconLabel.setHorizontalTextPosition(JLabel.CENTER); @@ -65,10 +62,8 @@ public OnPhone() { // Add Icon Label imagePanel.add(iconLabel, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.7, GridBagConstraints.SOUTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); - // Add Time Label imagePanel.add(timeLabel, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.3, GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); - add(imagePanel, BorderLayout.CENTER); } diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/phone/PhoneDialog.java b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/PhoneDialog.java similarity index 87% rename from src/java/org/jivesoftware/sparkimpl/plugin/phone/PhoneDialog.java rename to plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/PhoneDialog.java index 7c17c5971..e39c3a27f 100644 --- a/src/java/org/jivesoftware/sparkimpl/plugin/phone/PhoneDialog.java +++ b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/PhoneDialog.java @@ -1,16 +1,12 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * + *

      * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -33,7 +29,7 @@ public class PhoneDialog { public static JFrame invoke(JComponent comp, String title, String description, ImageIcon icon) { final JFrame frame = new JFrame(); - frame.setIconImage(SparkRes.getImageIcon(SparkRes.TELEPHONE_24x24).getImage()); + frame.setIconImage(SparkRes.getImageIcon(SparkRes.Icons.TELEPHONE_24x24).getImage()); frame.setTitle(title); frame.getContentPane().setLayout(new BorderLayout()); diff --git a/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/PhonePlugin.java b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/PhonePlugin.java new file mode 100644 index 000000000..20fd5186b --- /dev/null +++ b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/plugin/phone/PhonePlugin.java @@ -0,0 +1,347 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.plugin.phone; + +import org.jivesoftware.spark.phone.client.PhoneClient; +import org.jivesoftware.spark.phone.client.action.PhoneActionIQProvider; +import org.jivesoftware.spark.phone.client.event.*; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smack.provider.ProviderManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.phone.PhoneManager; +import org.jivesoftware.spark.plugin.ContextMenuListener; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.*; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.util.*; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; +import org.jxmpp.jid.BareJid; + +import javax.swing.*; +import java.awt.event.*; +import java.util.TimerTask; + +/** + * Adds phone-pbx capabilities within Spark. + * Users can make calls, take incoming calls and be notified of presence changes + * @author Derek DeMoro + */ +public class PhonePlugin implements Plugin { + public static PhoneClient phoneClient; + public static Presence offPhonePresence; + public static Presence onPhonePresence; + private DialPanel dialPanel; + // private Alert incomingDialog; + private JFrame dialDialog; + + public static PhoneClient getPhoneClient() { + return phoneClient; + } + + @Override + public void initialize() { + ProviderManager.addExtensionProvider("phone-event", "http://jivesoftware.com/xmlns/phone", new PhoneEventPacketExtensionProvider()); + ProviderManager.addIQProvider("phone-action", "http://jivesoftware.com/xmlns/phone", new PhoneActionIQProvider()); + final XMPPConnection con = SparkManager.getConnection(); + SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + try { + phoneClient = new PhoneClient(con); + // Add BaseListener + phoneClient.addEventListener(new PhoneListener()); + } catch (Exception e) { + // Ignore because the user does not have support. + Log.warning(e.getMessage()); + } + return phoneClient; + } + + @Override + public void finished() { + if (phoneClient != null) { + setupPhoneSystem(); + } + } + }; + + worker.start(); + } + + private void setupPhoneSystem() { + // Add Dial Menu + final JMenu viewMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions")); + JMenuItem dialNumberMenu = new JMenuItem(SparkRes.getImageIcon(SparkRes.Icons.ON_PHONE_IMAGE)); + ResourceUtils.resButton(dialNumberMenu, Res.getString("button.dial.number")); + + // Add Listener + dialNumberMenu.addActionListener(e -> { + dialPanel = new DialPanel(); + dialPanel.getDialButton().addActionListener(e1 -> { + String number = dialPanel.getNumberToDial(); + if (ModelUtil.hasLength(number)) { + dialPanel.setText(Res.getString("message.calling", number)); + dialPanel.changeToRinging(); + callExtension(number); + } + }); + + dialDialog = PhoneDialog.invoke(dialPanel, Res.getString("title.dial.phone"), Res.getString("message.number.to.call"), null); + dialPanel.getDialField().requestFocusInWindow(); + + dialPanel.getDialField().addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyChar() == KeyEvent.VK_ENTER) { + try { + String number = dialPanel.getNumberToDial(); + if (ModelUtil.hasLength(number)) { + dialPanel.setText(Res.getString("message.calling", number)); + dialPanel.changeToRinging(); + callExtension(number); + } + e.consume(); + } catch (Exception ex) { + Log.error(ex); + } + } + } + }); + }); + viewMenu.add(dialNumberMenu); + + // Add ChatRoomListener to call users based on JID + SparkManager.getChatManager().addChatRoomListener(new ChatRoomListenerAdapter() { + @Override + public void chatRoomOpened(final ChatRoom room) { + if (room instanceof ChatRoomImpl) { + final ChatRoomButton callButton = new ChatRoomButton("", SparkRes.getImageIcon(SparkRes.Icons.TELEPHONE_24x24)); + callButton.setToolTipText(Res.getString("tooltip.place.a.call")); + final ChatRoomImpl chatRoom = (ChatRoomImpl) room; + boolean phoneEnabled = false; + try { + phoneEnabled = phoneClient.isPhoneEnabled(chatRoom.getParticipantJID()); + } catch (Exception e) { + Log.error(e); + } + if (phoneEnabled) { + room.addChatRoomButton(callButton); + callButton.addActionListener(e -> callJID(chatRoom.getParticipantJID())); + } + } + } + }); + + ContactList contactList = SparkManager.getWorkspace().getContactList(); + contactList.addContextMenuListener(new ContextMenuListener() { + @Override + public void poppingUp(Object object, final JPopupMenu popup) { + if (object instanceof ContactItem) { + final ContactItem item = (ContactItem) object; + boolean phoneEnabled = false; + try { + phoneEnabled = phoneClient.isPhoneEnabled(item.getJid()); + } catch (Exception e) { + Log.error("There was an error retrieving phone information.", e); + } + // Add call action to contact popup + if (phoneEnabled) { + Action callAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + callJID(item.getJid()); + } + }; + + callAction.putValue(Action.NAME, "Call"); + callAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.Icons.ON_PHONE_IMAGE)); + popup.add(callAction); + } + } + } + + @Override + public void poppingDown(JPopupMenu popup) { + } + + @Override + public boolean handleDefaultAction(MouseEvent e) { + return false; + } + }); + } + + private void displayRingUI(RingEvent event) { + IncomingCall incomingCall = new IncomingCall(); + boolean idExists = false; + if (ModelUtil.hasLength(event.getCallerIDName())) { + incomingCall.setCallerName(event.getCallerIDName()); + idExists = true; + } + if (ModelUtil.hasLength(event.getCallerID())) { + incomingCall.setCallerNumber(event.getCallerID()); + idExists = true; + } + if (!idExists) { + incomingCall.setCallerName(Res.getString("message.no.caller.id")); + } + displayIncomingCallNotification(incomingCall); + } + + private static void displayIncomingCallNotification(IncomingCall incomingCall) { + if (!SettingsManager.getLocalPreferences().getDisableAsteriskToasterPopup()) { + SparkToaster toasterManager = new SparkToaster(); + toasterManager.setTitle("Incoming Phone Call"); + toasterManager.setDisplayTime(15000); + toasterManager.showToaster(SparkRes.getImageIcon(SparkRes.Icons.ON_PHONE_IMAGE)); + toasterManager.setComponent(incomingCall); + } + } + + + public void callExtension(final String number) { + final Runnable caller = () -> { + try { + phoneClient.dialByExtension(number); + } catch (Exception e) { + Log.error(e); + } + }; + TaskEngine.getInstance().submit(caller); + } + + public void callJID(final BareJid jid) { + final Runnable caller = () -> { + try { + phoneClient.dialByJID(jid); + } catch (Exception e) { + Log.error(e); + } + }; + TaskEngine.getInstance().submit(caller); + } + + @Override + public void shutdown() { + } + + @Override + public boolean canShutDown() { + return true; + } + + @Override + public void uninstall() { + } + + private class PhoneListener implements BasePhoneEventListener { + @Override + public void handleOnPhone(OnPhoneEvent event) { + if (dialDialog != null) { + dialDialog.setVisible(false); + } + // Get current presence if necessary. + offPhonePresence = SparkManager.getWorkspace().getStatusBar().getPresence(); + // Send "on the phone" presence + onPhonePresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .setStatus("On the phone") + .setPriority(1) + .setMode(Presence.Mode.away) + .build(); + SparkManager.getSessionManager().changePresence(onPhonePresence); + } + + @Override + public void handleHangUp(HangUpEvent event) { + onPhonePresence = null; + if (dialDialog != null) { + dialDialog.setVisible(false); + } + +/* + if (offPhonePresence != null) { + // Reconcile presence after phone call based on lock status + if (((offPhonePresence.getMode() == Presence.Mode.away) && (!UserIdlePlugin.getDesktopLockStatus()) + && (UserIdlePlugin.latestPresence != null)) && (!UserIdlePlugin.latestPresence.getStatus().contentEquals("On the Phone"))) { + SparkManager.getSessionManager().changePresence(UserIdlePlugin.latestPresence); + Log.debug("PhonePlugin: Setting presence from UserIdlePlugin"); + } else if ((UserIdlePlugin.getDesktopLockStatus()) && ((offPhonePresence.getStatus().equals("Online")) + || (offPhonePresence.getStatus().equals("Free to chat")))) { + Presence presence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .setStatus(UserIdlePlugin.pref.getIdleMessage()) + .setPriority(1) + .setMode(Presence.Mode.away) + .build(); + SparkManager.getSessionManager().changePresence(presence); + Log.debug("PhonePlugin: Desktop is Locked - Setting presence from pref.idle message"); + } else if (UserIdlePlugin.getDesktopLockStatus() && (!offPhonePresence.isAway())) { + Presence presence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .setStatus(offPhonePresence.getStatus()) + .setPriority(1) + .setMode(Presence.Mode.away) + .build(); + SparkManager.getSessionManager().changePresence(presence); + Log.debug("PhonePlugin: Desktop is Locked - Setting presence from user defined presence"); + } else { + // Set user to previous presence state when all phone calls are hung up. + SparkManager.getSessionManager().changePresence(offPhonePresence); + Log.debug("PhonePlugin: Setting Presence from PhonePlugin."); + } + } else { + // If no previous state available, set status to Available + Presence availablePresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .setStatus("Online") + .setPriority(1) + .setMode(Presence.Mode.available) + .build(); + + SparkManager.getSessionManager().changePresence(availablePresence); + Log.debug("no previous state available from Phone Plugin..setting to Online"); + } +*/ + } + + @Override + public void handleRing(RingEvent event) { + final TimerTask task = new SwingTimerTask() { + @Override + public void doRun() { + String callerID = event.getCallerID(); + if (ModelUtil.hasLength(callerID)) { + String number = PhoneManager.getNumbersFromPhone(callerID); + if (PhoneManager.getInstance().containsCurrentCall(number)) { + return; + } + } + displayRingUI(event); + } + }; + TaskEngine.getInstance().schedule(task, 1000); + } + } + +} diff --git a/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/preference/media/MediaPreference.java b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/preference/media/MediaPreference.java new file mode 100644 index 000000000..e2a96ec81 --- /dev/null +++ b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/preference/media/MediaPreference.java @@ -0,0 +1,105 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.preference.media; + +import javax.swing.Icon; +import javax.swing.JComponent; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.preference.Preference; +import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; +import org.jivesoftware.sparkimpl.settings.local.SettingsManager; + +public class MediaPreference implements Preference { + + public static final String NAMESPACE = "http://www.jivesoftware.org/spark/media"; + private final MediaPreferencePanel panel = new MediaPreferencePanel(); + + @Override + public Object getData() { + return null; + } + + @Override + public String getErrorMessage() { + return null; + } + + @Override + public JComponent getGUI() { + return panel; + } + + @Override + public Icon getIcon() { + return SparkRes.getImageIcon(SparkRes.Icons.HEADSET_IMAGE); + } + + @Override + public String getListName() { + return Res.getString("title.general.media"); + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public String getTitle() { + return Res.getString("title.general.media"); + } + + @Override + public String getTooltip() { + return Res.getString("title.general.media"); + } + + @Override + public boolean isDataValid() { + return true; + } + + @Override + public void load() { + LocalPreferences localPreferences = SettingsManager.getLocalPreferences(); + panel.setAudioSystem(localPreferences.getAudioSystem()); + panel.setVideoDevice(localPreferences.getVideoDevice()); + panel.setAudioDevice(localPreferences.getAudioDevice()); + panel.setStunServer(localPreferences.getStunFallbackHost()); + panel.setStunPort(localPreferences.getStunFallbackPort()); + panel.setPlaybackDevice(localPreferences.getPlaybackDevice()); + } + + @Override + public void commit() { + LocalPreferences pref = SettingsManager.getLocalPreferences(); + pref.setAudioSystem(panel.getAudioSystem()); + pref.setAudioDevice(panel.getAudioDevice()); + pref.setVideoDevice(panel.getVideoDevice()); + pref.setStunFallbackHost(panel.getStunServer()); + pref.setStunFallbackPort(panel.getStunPort()); + pref.setPlaybackDevice(panel.getPlaybackDevice()); + SettingsManager.saveSettings(); + } + + @Override + public void shutdown() { + commit(); + } + +} diff --git a/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/preference/media/MediaPreferencePanel.java b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/preference/media/MediaPreferencePanel.java new file mode 100644 index 000000000..f46f950b1 --- /dev/null +++ b/plugins/phone/src/main/java/org/jivesoftware/sparkimpl/preference/media/MediaPreferencePanel.java @@ -0,0 +1,298 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkimpl.preference.media; + +//import org.jitsi.impl.neomedia.MediaServiceImpl; +//import org.jitsi.impl.neomedia.codec.video.AVFrameFormat; +//import org.jitsi.impl.neomedia.device.AudioSystem; +//import org.jitsi.impl.neomedia.device.AudioSystem.DataFlow; +//import org.jitsi.impl.neomedia.device.CaptureDeviceInfo2; +//import org.jitsi.service.configuration.ConfigurationService; +//import org.jitsi.service.libjitsi.LibJitsi; +//import org.jitsi.service.neomedia.MediaService; +//import org.jitsi.service.neomedia.MediaType; +//import org.jitsi.service.neomedia.MediaUseCase; +//import org.jitsi.service.neomedia.device.MediaDevice; +import org.jivesoftware.Spark; +import org.jivesoftware.resource.Res; +import org.jivesoftware.spark.component.VerticalFlowLayout; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.log.Log; + +import javax.media.CaptureDeviceInfo; +import javax.media.CaptureDeviceManager; +import javax.media.Format; +import javax.media.format.AudioFormat; +import javax.swing.*; +import java.awt.*; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Vector; + +public class MediaPreferencePanel extends JPanel { + private static final long serialVersionUID = 8297469864676223072L; +// private Vector vectorAudioDevices; + private Vector vectorVideoDevices; +// private final Vector vectorAudioSystem = new Vector<>(); +// private final Vector vectorPlaybackDevices = new Vector<>(); + + private final JComboBox audioDevice = new JComboBox(); + private final JComboBox audioSystem = new JComboBox(); + private final JComboBox playbackDevice = new JComboBox(); + private final JComboBox videoDevice = new JComboBox(); + private final JTextField _stunServerInput = new JTextField(); + private final JTextField _stunPortInput = new JTextField(); + + public MediaPreferencePanel() { + setLayout(new VerticalFlowLayout()); + + JPanel panel = new JPanel(); + panel.setBorder(BorderFactory.createTitledBorder(Res.getString("title.general.media"))); + add(panel); + + panel.setLayout(new GridBagLayout()); + + JLabel lAudioSystem = new JLabel(); // Res.getString("label.audio.device")); + panel.add(lAudioSystem, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); + panel.add(audioSystem, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); + + JLabel lPlaybackAudio = new JLabel(); // Res.getString("label.audio.device")); + panel.add(lPlaybackAudio, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); + panel.add(playbackDevice, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); + + + JLabel lAudio = new JLabel(); // Res.getString("label.audio.device")); + panel.add(lAudio, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); + panel.add(audioDevice, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); + + + JLabel lVideo = new JLabel(); // Res.getString("label.video.device")); + panel.add(lVideo, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); + panel.add(videoDevice, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); + + JButton redetect = new JButton(); // Res.getString("button.re.detect") ); + redetect.addActionListener(event -> scanDevices()); + + panel.add(redetect, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); + + // Setup Mnemonics + ResourceUtils.resButton(redetect, Res.getString("button.re.detect")); + ResourceUtils.resLabel(lVideo, videoDevice, Res.getString("label.video.device") + ":"); + ResourceUtils.resLabel(lPlaybackAudio, playbackDevice, Res.getString("label.audio.device") + ":"); + ResourceUtils.resLabel(lAudio, audioDevice, Res.getString("label.audio.device") + ":"); + + scanDevices(); + createSTUNPanel(); + } + + private String convertSysString(String src) { + String res = new String(src.getBytes(StandardCharsets.ISO_8859_1), Charset.defaultCharset()); + return res; + } + + @SuppressWarnings("unchecked") + public void scanDevices() { + // Remove all Items + audioDevice.removeAllItems(); + videoDevice.removeAllItems(); + playbackDevice.removeAllItems(); + audioSystem.removeAllItems(); + +/* + vectorPlaybackDevices.removeAllElements(); + vectorAudioSystem.removeAllElements(); + // FMJ + System.setProperty(ConfigurationService.PNAME_SC_HOME_DIR_LOCATION, Spark.getUserHome()); + System.setProperty(ConfigurationService.PNAME_SC_HOME_DIR_NAME, "."); + System.setProperty(ConfigurationService.PNAME_SC_CACHE_DIR_LOCATION, Spark.getUserHome()); + System.setProperty(ConfigurationService.PNAME_SC_LOG_DIR_LOCATION, Spark.getUserHome()); + + LibJitsi.start(); + + MediaType[] mediaTypes = MediaType.values(); + MediaService mediaService = LibJitsi.getMediaService(); + for (MediaType mediaType : mediaTypes) { + System.err.println("================================"); + System.err.println("MediaType: " + mediaType); + System.out.println(mediaService); + + MediaDevice device = mediaService.getDefaultDevice(mediaType, MediaUseCase.CALL); + if (device != null) { + System.out.println(device.getDirection()); + } + System.err.println("Device: " + device); + System.err.println("================================"); + } + + + vectorAudioDevices = CaptureDeviceManager.getDeviceList(new AudioFormat(AudioFormat.LINEAR)); + for (CaptureDeviceInfo infoCaptureDevice : vectorAudioDevices) { + String protocol = infoCaptureDevice.getLocator().getProtocol(); + audioDevice.addItem("[" + protocol + "]" + convertSysString(infoCaptureDevice.getName())); + } + + vectorVideoDevices = CaptureDeviceManager.getDeviceList(new AVFrameFormat()); + for (CaptureDeviceInfo infoCaptureDevice : vectorVideoDevices) { + videoDevice.addItem(convertSysString(infoCaptureDevice.getName())); + } + vectorVideoDevices.add(null); + videoDevice.addItem(""); + + AudioSystem mediaAudioSystem = ((MediaServiceImpl) LibJitsi.getMediaService()).getDeviceConfiguration().getAudioSystem(); + for (AudioSystem system : AudioSystem.getAudioSystems()) { + System.out.println(system); + vectorAudioSystem.add(system); + audioSystem.addItem(system); + } + + for (CaptureDeviceInfo2 device : mediaAudioSystem.getDevices(DataFlow.PLAYBACK)) { + playbackDevice.addItem(convertSysString(device.getName())); + vectorPlaybackDevices.add(device); + } +*/ + } + + private void createSTUNPanel() { + JPanel stunPanel = new JPanel(new GridBagLayout()); + stunPanel.setBorder(BorderFactory.createTitledBorder(Res.getString("stun.border.label"))); + add(stunPanel); + + JLabel stunServer = new JLabel(Res.getString("stun.server.addr")); + JLabel stunPort = new JLabel(Res.getString("stun.server.port")); + + _stunServerInput.setPreferredSize(new Dimension(120, 20)); + _stunPortInput.setPreferredSize(new Dimension(120, 20)); + + stunPanel.add(stunServer, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); + stunPanel.add(_stunServerInput, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); + stunPanel.add(stunPort, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); + stunPanel.add(_stunPortInput, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); + } + + public String getAudioDevice() { +/* + if (audioDevice.getSelectedIndex() >= 0) { + return vectorAudioDevices.get(audioDevice.getSelectedIndex()).getLocator().toExternalForm(); + } +*/ + return ""; + } + + public void setAudioDevice(String device) { +/* + AudioSystem audioSystem = ((MediaServiceImpl) LibJitsi.getMediaService()).getDeviceConfiguration().getAudioSystem(); + for (CaptureDeviceInfo2 infoCaptureDevice : vectorAudioDevices) { + System.out.println(device); + if (infoCaptureDevice.getLocator().toExternalForm().equals(device)) { + audioDevice.setSelectedIndex(vectorAudioDevices.indexOf(infoCaptureDevice)); + audioSystem.setDevice(DataFlow.CAPTURE, infoCaptureDevice, true); + } + } +*/ + } + + public String getPlaybackDevice() { +/* + if (playbackDevice.getSelectedIndex() >= 0) { + return vectorPlaybackDevices.get(playbackDevice.getSelectedIndex()).getLocator().toExternalForm(); + } +*/ + return ""; + } + + public void setPlaybackDevice(String device) { +/* + AudioSystem audioSystem = ((MediaServiceImpl) LibJitsi.getMediaService()).getDeviceConfiguration().getAudioSystem(); + for (CaptureDeviceInfo2 infoCaptureDevice : vectorPlaybackDevices) { + if (infoCaptureDevice.getLocator().toExternalForm().equals(device)) { + playbackDevice.setSelectedItem(infoCaptureDevice.getName()); + audioSystem.setDevice(DataFlow.PLAYBACK, infoCaptureDevice, true); + audioSystem.setDevice(DataFlow.NOTIFY, infoCaptureDevice, true); + } + } +*/ + } + + public String getAudioSystem() { +/* + if (audioSystem.getSelectedIndex() >= 0) { + return vectorAudioSystem.get(audioSystem.getSelectedIndex()).getLocatorProtocol(); + } +*/ + return null; + } + + public void setAudioSystem(String selectedAudioSystem) { +/* + for (AudioSystem system : vectorAudioSystem) { + if (system.getLocatorProtocol().equals(selectedAudioSystem)) { + Log.debug("setAudioSystem:" + system); + audioSystem.setSelectedIndex(vectorAudioSystem.indexOf(system)); + ((MediaServiceImpl) LibJitsi.getMediaService()).getDeviceConfiguration().setAudioSystem(system, true); + } + } + Log.debug("AudioSystem:" + ((MediaServiceImpl) LibJitsi.getMediaService()).getDeviceConfiguration().getAudioSystem()); +*/ + } + + public String getVideoDevice() { + if (videoDevice.getSelectedIndex() >= 0) { + if (vectorVideoDevices.get(videoDevice.getSelectedIndex()) == null) { + return ""; + } + return vectorVideoDevices.get(videoDevice.getSelectedIndex()).getLocator().toExternalForm(); + } + return ""; + } + + public void setVideoDevice(String device) { + for (CaptureDeviceInfo infoCaptureDevice : vectorVideoDevices) { + if (infoCaptureDevice != null && + infoCaptureDevice.getLocator().toExternalForm().equals(device)) { + videoDevice.setSelectedItem(infoCaptureDevice.getName()); + } + } + } + + public String getStunServer() { + return _stunServerInput.getText(); + } + + public void setStunServer(String server) { + this._stunServerInput.setText(server); + } + + public int getStunPort() { + return Integer.valueOf(_stunPortInput.getText()); + } + + public void setStunPort(int port) { + this._stunPortInput.setText(String.valueOf(port)); + } + + /** + * Logs the audio devices + */ + public void logAudioDevices() { + final Vector vectorDevices = CaptureDeviceManager.getDeviceList(null); + for (CaptureDeviceInfo infoCaptureDevice : vectorDevices) { + System.err.println(convertSysString(infoCaptureDevice.getName())); + for (Format format : infoCaptureDevice.getFormats()) { + System.err.println(" " + format); + } + } + } +} diff --git a/plugins/plugin/pom.xml b/plugins/plugin/pom.xml new file mode 100644 index 000000000..2f5362269 --- /dev/null +++ b/plugins/plugin/pom.xml @@ -0,0 +1,70 @@ + + 4.0.0 + + + org.igniterealtime.spark + parent + 3.1.0-SNAPSHOT + ../../ + + + org.igniterealtime.spark.plugins + plugin + pom + + Spark Plugin (parent) + + This Maven module can be used as a parent for Maven modules that contain a Spark plugin. It provides much of the + boilerplate structure that is typically used for Spark plugin modules. + + + + + org.igniterealtime.spark + spark-core + ${project.parent.version} + provided + + + + + + + src/main/resources + + + src/main/plugin-metadata + true + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + org.igniterealtime.spark.plugins + assembly-descriptor + ${project.parent.version} + + + + + spark-plugin + + + + + make-assembly + package + + single + + + + + + + + diff --git a/plugins/reversi/pom.xml b/plugins/reversi/pom.xml new file mode 100644 index 000000000..7fc2f4e7e --- /dev/null +++ b/plugins/reversi/pom.xml @@ -0,0 +1,41 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + reversi + 1.7 + + Reversi + Multiplayer game of Reversi. + + + + Holger Bergunde + holger@bergunde.de + http://www.stytrix.de + + Author + + + + Matt Tucker + + Author + + + + Bill Lynch + + Author + + + + + diff --git a/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/GameForfeit.java b/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/GameForfeit.java new file mode 100644 index 000000000..3d1bc9b11 --- /dev/null +++ b/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/GameForfeit.java @@ -0,0 +1,95 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.game.reversi; + +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.provider.ExtensionElementProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.JxmppContext; + +import javax.xml.namespace.QName; +import java.io.IOException; + +/** + * A packet extension sent to indicate that the player forfeits the game. + */ +public class GameForfeit implements ExtensionElement { + public static final String ELEMENT_NAME = "reversi-forfeit"; + public static final String NAMESPACE = "http://jivesoftware.org/protocol/game/reversi"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT_NAME); + + private int gameID; + + @Override + public String getElementName() { + return ELEMENT_NAME; + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public String toXML(XmlEnvironment xmlEnvironment) { + return "<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">" + + "" + gameID + "" + + ""; + } + + /** + * Returns the game ID that this forfeit pertains to. + * + * @return the game ID. + */ + public int getGameID() { + return gameID; + } + + /** + * Sets the game ID that this forfeit pertains to. + * + * @param gameID the game ID. + */ + public void setGameID(int gameID) { + this.gameID = gameID; + } + + + public static class Provider extends ExtensionElementProvider { + @Override + public GameForfeit parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException { + final GameForfeit gameForfeit = new GameForfeit(); + boolean done = false; + while (!done) { + final XmlPullParser.Event eventType = parser.next(); + if (eventType == XmlPullParser.Event.START_ELEMENT) { + if ("gameID".equals(parser.getName())) { + final int gameID = Integer.parseInt(parser.nextText()); + gameForfeit.setGameID(gameID); + } + } else if (eventType == XmlPullParser.Event.END_ELEMENT) { + if (ELEMENT_NAME.equals(parser.getName())) { + done = true; + } + } + } + return gameForfeit; + } + } +} diff --git a/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/GameMove.java b/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/GameMove.java new file mode 100644 index 000000000..5ded04c39 --- /dev/null +++ b/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/GameMove.java @@ -0,0 +1,128 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.game.reversi; + +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.provider.ExtensionElementProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.JxmppContext; + +import javax.xml.namespace.QName; +import java.io.IOException; + +/** + * A packet extension that represents an individual game move. Each move is simply an integer + * indicating the position on the board the user wishes to place their stone. It's assumed that + * both players maintain their own copy of the game model and only send valid moves. If an + * invalid move is received from the opponent, the player should immediately terminate the game.

      + * + * The game board is 64 squares; see {@link ReversiModel} for full details. + * + * @author Matt Tucker + */ +public class GameMove implements ExtensionElement { + + public static final String ELEMENT_NAME = "reversi-move"; + public static final String NAMESPACE = "http://jivesoftware.org/protocol/game/reversi"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT_NAME); + + private int gameID; + private int position; + + public String getElementName() { + return ELEMENT_NAME; + } + + public String getNamespace() { + return NAMESPACE; + } + + @Override + public String toXML(XmlEnvironment xmlEnvironment) { + return "<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">" + + "" + gameID + "" + + "" + position + "" + + ""; + } + + /** + * Returns the game ID that this move pertains to. + * + * @return the game ID. + */ + public int getGameID() { + return gameID; + } + + /** + * Sets the game ID that this move pertains to. + * + * @param gameID the game ID. + */ + public void setGameID(int gameID) { + this.gameID = gameID; + } + + /** + * Returns the move position; an integer between 0 and 63. + * + * @return the move position. + */ + public int getPosition() { + return position; + } + + /** + * Sets the move position; an integer between 0 and 63. + * + * @param position the move position. + */ + public void setPosition(int position) { + if (position < 0 || position > 63) { + throw new IllegalArgumentException("Position " + position + " invalid; must be between 0 and 63."); + } + this.position = position; + } + + public static class Provider extends ExtensionElementProvider { + + @Override + public GameMove parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException { + final GameMove gameMove = new GameMove(); + boolean done = false; + while (!done) { + final XmlPullParser.Event eventType = parser.next(); + if (eventType == XmlPullParser.Event.START_ELEMENT) { + if ("gameID".equals(parser.getName())) { + final int gameID = Integer.parseInt(parser.nextText()); + gameMove.setGameID(gameID); + } + if ("position".equals(parser.getName())) { + final int position = Integer.parseInt(parser.nextText()); + gameMove.setPosition(position); + } + } else if (eventType == XmlPullParser.Event.END_ELEMENT) { + if (ELEMENT_NAME.equals(parser.getName())) { + done = true; + } + } + } + return gameMove; + } + } +} diff --git a/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/GameOffer.java b/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/GameOffer.java new file mode 100644 index 000000000..4d7c9406a --- /dev/null +++ b/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/GameOffer.java @@ -0,0 +1,131 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.game.reversi; + +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IqData; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.provider.IqProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.JxmppContext; + +import java.io.IOException; +import java.util.Random; + +/** + * An IQ packet that's an offer to start a new Reversi game. The offer indicates whether the player + * making the offer will be the starting player (black). The starting player is selected randomly + * by default, which is recommended. + * + * @author Matt Tucker + */ +public class GameOffer extends IQ { + public static final String ELEMENT_NAME = "reversi"; + public static final String NAMESPACE = "http://jivesoftware.org/protocol/game/reversi"; + + private static final Random random = new Random(); + private int gameID; + + private boolean startingPlayer; + + /** + * Constructs a new game offer with a random game ID and random value for the starting player. + */ + public GameOffer() { + super(ELEMENT_NAME, NAMESPACE); + // Randomly choose if the user making the game offer will be the starting player (black). + startingPlayer = random.nextBoolean(); + gameID = Math.abs(random.nextInt()); + } + + /** + * Returns the game ID. + * + * @return the game ID. + */ + public int getGameID() { + return gameID; + } + + /** + * Sets the game ID. + * + * @param gameID the game ID. + */ + public void setGameID(int gameID) { + this.gameID = gameID; + } + + /** + * Returns true if the user making the game invitation is the starting player. + * + * @return true if the user making the game invite is the starting player. + */ + public boolean isStartingPlayer() { + return startingPlayer; + } + + /** + * Sets whether the user making the game invitation is the starting player. + * + * @param startingPlayer true if the user making the game invite is the starting player. + */ + public void setStartingPlayer(boolean startingPlayer) { + this.startingPlayer = startingPlayer; + } + + @Override + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder buf) { + buf.rightAngleBracket(); + buf.append("<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">"); + buf.element("gameID", String.valueOf(gameID)); + buf.element("startingPlayer", String.valueOf(startingPlayer)); + buf.append(""); + return buf; + } + + public static class Provider extends IqProvider { + public Provider() { + super(); + } + + @Override + public GameOffer parse(XmlPullParser parser, int i, IqData iqData, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException { + final GameOffer gameOffer = new GameOffer(); + + boolean done = false; + while (!done) { + XmlPullParser.Event eventType = parser.next(); + if (eventType == XmlPullParser.Event.START_ELEMENT) { + if (parser.getName().equals("gameID")) { + final int gameID = Integer.parseInt(parser.nextText()); + gameOffer.setGameID(gameID); + } else if (parser.getName().equals("startingPlayer")) { + boolean startingPlayer = Boolean.parseBoolean(parser.nextText()); + gameOffer.setStartingPlayer(startingPlayer); + } + } else if (eventType == XmlPullParser.Event.END_ELEMENT) { + if (parser.getName().equals(ELEMENT_NAME)) { + done = true; + } + } + } + return gameOffer; + } + + } +} diff --git a/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/ReversiModel.java b/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/ReversiModel.java similarity index 80% rename from src/plugins/reversi/src/java/org/jivesoftware/game/reversi/ReversiModel.java rename to plugins/reversi/src/main/java/org/jivesoftware/game/reversi/ReversiModel.java index 98076fd06..b8710175a 100644 --- a/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/ReversiModel.java +++ b/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/ReversiModel.java @@ -1,16 +1,12 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * + *

      * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -40,22 +36,22 @@ public class ReversiModel { /** * Blank. */ - public static int BLANK = 0; + public static final int BLANK = 0; /** * White. */ - public static int WHITE = 1; + public static final int WHITE = 1; /** * Black. */ - public static int BLACK = 2; + public static final int BLACK = 2; - private int[] board; + private final int[] board; private int currentPlayer; private boolean gameFinished = false; - private int[] flipBuffer = new int[7]; + private final int[] flipBuffer = new int[7]; private int flipBufferSize = 0; /** @@ -105,7 +101,7 @@ public boolean isValidMove(int position) { public int getBoardValue(int position) { if (position < 0 || position > 63) { throw new IllegalArgumentException("Invalid position: " + position + ". Valid board " + - "positions are 0 through 63"); + "positions are 0 through 63"); } return board[position]; } @@ -168,9 +164,9 @@ public boolean makeMove(int position) { getFlipCount(position, currentPlayer, true); // See if other user has a valid move. If so, switch to other player. - int otherPlayer = currentPlayer==WHITE ? BLACK: WHITE; + int otherPlayer = currentPlayer == WHITE ? BLACK : WHITE; boolean hasMove = false; - for (int i=0; i 0; } } @@ -266,17 +259,16 @@ private synchronized int getFlipCount(int position, int player, boolean doFlips) // Going left horizontally. - boolean edge; - - if (position%8 > 1) { - edge = false; - for (int i=position-1; !edge; i--) { - if (i % 8 == 0) edge = true; + boolean edge; + + if (position % 8 > 1) { + edge = false; + for (int i = position - 1; !edge; i--) { + if (i % 8 == 0) edge = true; if (board[i] == BLANK) { break; - } - else if (board[i] == player) { - for (int j=0; j 15) { - for (int i=position-8; i >= 0; i-=8) { + for (int i = position - 8; i >= 0; i -= 8) { if (board[i] == BLANK) { break; - } - else if (board[i] == player) { - for (int j=0; j 15 && position%8 > 1) { - edge = false; - for (int i=position-9; !edge; i-=9) { - if (i < 8 || i%8==0) edge = true; + if (position > 15 && position % 8 > 1) { + edge = false; + for (int i = position - 9; !edge; i -= 9) { + if (i < 8 || i % 8 == 0) edge = true; if (board[i] == BLANK) { break; - } - else if (board[i] == player) { - for (int j=0; j 15 && position%8 < 6) { - edge = false; - for (int i=position-7; !edge; i-=7) { - if (i < 8 || i%8==7) edge = true; + if (position > 15 && position % 8 < 6) { + edge = false; + for (int i = position - 7; !edge; i -= 7) { + if (i < 8 || i % 8 == 7) edge = true; if (board[i] == BLANK) { break; - } - else if (board[i] == player) { - for (int j=0; j 1) { - edge = false; - for (int i=position+7; !edge; i+=7) { - if (i > 55 || i%8==0) edge = true; + if (position < 48 && position % 8 > 1) { + edge = false; + for (int i = position + 7; !edge; i += 7) { + if (i > 55 || i % 8 == 0) edge = true; if (board[i] == BLANK) { break; - } - else if (board[i] == player) { - for (int j=0; j 55 || i%8==7) edge=true; + if (position < 48 && position % 8 < 6) { + edge = false; + for (int i = position + 9; !edge; i += 9) { + if (i > 55 || i % 8 == 7) edge = true; if (board[i] == BLANK) { break; - } - else if (board[i] == player) { - for (int j=0; j + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.game.reversi; + +import javax.swing.*; + +import java.util.*; +import java.util.List; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.StanzaListener; +import org.jivesoftware.smack.filter.StanzaExtensionFilter; +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StandardExtensionElement; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.Jid; + +/** + * The game UI, which is created after both players have accepted a new game. + * + * @author Bill Lynch + */ +public class ReversiPanel extends JPanel { + + private static final long serialVersionUID = 3591458286918924065L; + private static final int BOARD_SIZE = 320; + private static final int INFO_PANEL_HEIGHT = 50; + private static final int BORDER_SIZE = 5; + public static final int TOTAL_WIDTH = BOARD_SIZE + (BORDER_SIZE * 2); + public static final int TOTAL_HEIGHT = TOTAL_WIDTH + INFO_PANEL_HEIGHT; // frame width + 50 for the info panel + private static final int NUM_BLOCKS = 8; + private static final int BLOCK_SIZE = BOARD_SIZE / NUM_BLOCKS; + + private static final int DISC_SIZE = (int) (BLOCK_SIZE * 0.8); // 80% of block size + + private final XMPPConnection connection; + private final int otherPlayer; + private final int gameID; + private final Jid opponentJID; + private StanzaListener gameMoveListener; + + private final List blocks = new ArrayList<>(); + // Main game object + private final ReversiModel reversi; + + // All images used by the game. + + private final Image imageBackground = ReversiRes.getImageIcon(ReversiRes.REVERSI_BOARD).getImage(); + private final Image imageScoreWhite = ReversiRes.getImageIcon(ReversiRes.REVERSI_SCORE_WHITE).getImage(); + private final Image imageScoreBlack = ReversiRes.getImageIcon(ReversiRes.REVERSI_SCORE_BLACK).getImage(); + private final Image imageTurnBlack = ReversiRes.getImageIcon(ReversiRes.REVERSI_LABEL_BLACK).getImage(); + private final Image imageTurnWhite = ReversiRes.getImageIcon(ReversiRes.REVERSI_LABEL_WHITE).getImage(); + private final Image imageButtonResign = ReversiRes.getImageIcon(ReversiRes.REVERSI_RESIGN).getImage(); + private final Image imageYou = ReversiRes.getImageIcon(ReversiRes.REVERSI_YOU).getImage(); + private final Image imageThem = ReversiRes.getImageIcon(ReversiRes.REVERSI_THEM).getImage(); + + /** + * Creates a new Reversi panel. + * + * @param connection Connection associated. + * @param gameID Game ID number + * @param startingPlayer Whether we are the starting player or not + * @param opponentJID JID of opponent + */ + public ReversiPanel(XMPPConnection connection, final int gameID, boolean startingPlayer, Jid opponentJID) { + this.connection = connection; + this.gameID = gameID; + this.opponentJID = opponentJID; + otherPlayer = startingPlayer ? ReversiModel.WHITE : ReversiModel.BLACK; + + // Load all images. + + // Start the game + reversi = new ReversiModel(); + + if (connection != null) { + gameMoveListener = stanza -> { + GameMove move = stanza.getExtension(GameMove.class); + // If this is a move for the current game. + if (move.getGameID() == gameID) { + int position = move.getPosition(); + // Make sure that the other player is allowed to make the move right now. + if (reversi.getCurrentPlayer() == otherPlayer && reversi.isValidMove(position)) { + reversi.makeMove(position); + // Redraw board. + ReversiPanel.this.repaint(); + } + // TODO: other user automatically forfeits! + // else { + // } + // Execute move. + } + }; + + connection.addAsyncStanzaListener(gameMoveListener, + new StanzaExtensionFilter(GameMove.ELEMENT_NAME, GameMove.NAMESPACE)); + // TODO: at end of game, remove listener. + } + + setOpaque(false); + + // Use absolute layout + setLayout(null); + // Set its size: + setPreferredSize(new Dimension(TOTAL_WIDTH, TOTAL_HEIGHT)); + + // Make a new panel which is the game board grid: + JPanel reversiBoard = new JPanel(new GridLayout(NUM_BLOCKS, NUM_BLOCKS, 0, 0)); + reversiBoard.setOpaque(false); + for (int i = 0; i < NUM_BLOCKS * NUM_BLOCKS; i++) { + ReversiBlock block = new ReversiBlock(this, i); + blocks.add(block); + reversiBoard.add(block); + } + // Add the reversi board to the main panel: + add(reversiBoard); + // Position it: + reversiBoard.setBounds(BORDER_SIZE, BORDER_SIZE, BOARD_SIZE, BOARD_SIZE); + // TODO: listen for click on resign button!! + } + + /** + * Sends a forfeit message to the other player. + */ + public void sendForfeit() throws SmackException.NotConnectedException { + StandardExtensionElement forfeit = StandardExtensionElement.builder(GameForfeit.ELEMENT_NAME, GameForfeit.NAMESPACE) + .addElement("gameID", Integer.toString(gameID)) + .build(); + Message message = connection.getStanzaFactory() + .buildMessageStanza() + .to(opponentJID) + .addExtension(forfeit) + .build(); + + try { + connection.sendStanza(message); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } finally { + connection.removeAsyncStanzaListener(gameMoveListener); + } + } + + @Override + public void paintComponent(Graphics g) { + // Turn on anti-aliasing. + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint( + RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON + ); + + // Background + g.drawImage(imageBackground, 0, 0, null); + + // Draw info panel components. + + // Draw the score. + g.drawImage(imageScoreWhite, 3, BOARD_SIZE + BORDER_SIZE * 2 + 7, null); + g.drawImage(imageScoreBlack, 3, BOARD_SIZE + BORDER_SIZE * 2 + 27, null); + g.setFont(new Font("SansSerif", Font.BOLD, 12)); + String whiteScore = String.valueOf(reversi.getWhiteScore()); + String blackScore = String.valueOf(reversi.getBlackScore()); + FontMetrics fm = g.getFontMetrics(); + int width = Math.max(fm.stringWidth(whiteScore), fm.stringWidth(blackScore)); + g.drawString(whiteScore, imageScoreBlack.getWidth(null) + 7 + width - fm.stringWidth(whiteScore), + BOARD_SIZE + BORDER_SIZE * 2 + 22); + g.drawString(blackScore, imageScoreWhite.getWidth(null) + 7 + width - fm.stringWidth(blackScore), + BOARD_SIZE + BORDER_SIZE * 2 + 42); + + // Draw who's turn it is. + if (!reversi.isGameFinished()) { + if (reversi.getCurrentPlayer() == ReversiModel.BLACK) { + g.drawImage(imageTurnBlack, 116, BOARD_SIZE + BORDER_SIZE * 2 + 11, null); + } else { + g.drawImage(imageTurnWhite, 116, BOARD_SIZE + BORDER_SIZE * 2 + 11, null); + } + } else { + int me = otherPlayer == ReversiModel.BLACK ? ReversiModel.WHITE : ReversiModel.BLACK; + String whoWins = "Draw"; + if (reversi.getBlackScore() > reversi.getWhiteScore()) { + if (me == ReversiModel.BLACK) + whoWins = "YOU WIN!"; + else + whoWins = "YOU LOST!"; + } else if (reversi.getBlackScore() < reversi.getWhiteScore()) { + if (me == ReversiModel.WHITE) + whoWins = "YOU WIN!"; + else + whoWins = "YOU LOST!"; + } + g.drawString(whoWins, 130, BOARD_SIZE + BORDER_SIZE * 2 + 20); + } + if (reversi.getCurrentPlayer() == otherPlayer) { + g.drawImage(imageThem, 163, BOARD_SIZE + BORDER_SIZE * 2 + 31, null); + } else { + g.drawImage(imageYou, 163, BOARD_SIZE + BORDER_SIZE * 2 + 31, null); + } + + // The resign button. + g.drawImage(imageButtonResign, 281, BOARD_SIZE + BORDER_SIZE * 2 + 17, null); + } + + /** + * A Reversi block (one of the squares of the grid). + */ + public class ReversiBlock extends JPanel { + + private static final long serialVersionUID = -8504469339731900770L; + private final ReversiPanel ui; + private final int index; + + public ReversiBlock(ReversiPanel ui, int index) { + super(); + this.ui = ui; + this.index = index; + setPreferredSize(new Dimension(BLOCK_SIZE, BLOCK_SIZE)); + addMouseListener(new ReversiBlockMouseListener(this)); + setOpaque(false); + } + + /** + * Returns a handle on the game UI. + * + * @return ReversiPanel of block. + */ + public ReversiPanel getReversiUI() { + return ui; + } + + /** + * This block's index (0->63). + * + * @return Index of block + */ + public int getIndex() { + return index; + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + + // Turn on anti-aliasing: + ((Graphics2D) g).setRenderingHint( + RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON + ); + + // Draw a disc in the block if the game says we should. + int boardValue = reversi.getBoardValue(index); + if (boardValue == org.jivesoftware.game.reversi.ReversiModel.BLACK) { + drawDisc(g, Color.BLACK); + } else if (reversi.getBoardValue(index) == org.jivesoftware.game.reversi.ReversiModel.WHITE) { + drawDisc(g, Color.WHITE); + } + } + + /** + * Draws the disc. + * + * @param g Graphics to draw + * @param color Color + */ + private void drawDisc(Graphics g, Color color) { + int position = BLOCK_SIZE - ((BLOCK_SIZE + DISC_SIZE) / 2); + g.setColor(color); + g.fillOval(position, position, DISC_SIZE, DISC_SIZE); + } + } + + /** + * A mouse listener for a Reversi block. + */ + public class ReversiBlockMouseListener extends MouseAdapter { + + private final ReversiBlock block; + + public ReversiBlockMouseListener(ReversiBlock block) { + this.block = block; + } + + /** + * Highlight the block if this block is a valid move. + */ + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + if (reversi.getCurrentPlayer() != otherPlayer && reversi.isValidMove(block.getIndex())) { + block.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + block.setBorder(BorderFactory.createLineBorder(Color.WHITE)); + } + } + + /** + * Set the block color back to the default. + */ + @Override + public void mouseExited(MouseEvent e) { + super.mouseExited(e); + block.setCursor(Cursor.getDefaultCursor()); + block.setBorder(null); + } + + /** + * If the click box is a valid move, register a move in this box. + */ + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + // Make sure that it's our turn and that it's a valid move. + if (reversi.getCurrentPlayer() != otherPlayer && reversi.isValidMove(block.getIndex())) { + // Update the game model. + reversi.makeMove(block.getIndex()); + + // Send the move to the other player. + GameMove move = new GameMove(); + move.setGameID(gameID); + move.setPosition(block.getIndex()); + Message message = StanzaBuilder.buildMessage() + .addExtension(move) + .build(); + message.setTo(opponentJID); + try { + connection.sendStanza(message); + } catch (SmackException.NotConnectedException | InterruptedException e1) { + Log.warning("Unable to send move to " + message.getTo(), e1); + } + // Repaint board. + ReversiPanel.this.repaint(); + // Repaint all blocks. +// for (Iterator it = block.getReversiUI().getBlocks().iterator(); it.hasNext();) { +// ReversiBlock component = (ReversiBlock)it.next(); +// component.repaint(); +// } + + } + } + } + + public List getBlocks() { + return blocks; + } +} diff --git a/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/ReversiPlugin.java b/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/ReversiPlugin.java new file mode 100644 index 000000000..37e445685 --- /dev/null +++ b/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/ReversiPlugin.java @@ -0,0 +1,378 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + *

      + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

      + * http://www.apache.org/licenses/LICENSE-2.0 + *

      + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.game.reversi; + +import java.awt.*; +import java.util.concurrent.ConcurrentHashMap; + +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSplitPane; + +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.filter.StanzaIdFilter; +import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler; +import org.jivesoftware.smack.iqrequest.IQRequestHandler; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaError; +import org.jivesoftware.smack.provider.ProviderManager; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.BackgroundPanel; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomButton; +import org.jivesoftware.spark.ui.ChatRoomListener; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.EntityFullJid; +import org.jxmpp.jid.Jid; + +/** + * Reversi plugin. Reversi is a two-player, turn-based game. See + * {@link ReversiModel} for more details on how the game works. + * + * @author Matt Tucker + * @author Bill Lynch + */ +public class ReversiPlugin implements Plugin { + + private ChatRoomListener chatRoomListener; + private IQRequestHandler gameOfferHandler; + + private ConcurrentHashMap gameOffers; + private ConcurrentHashMap gameInvitations; + + private JPanel inviteAlert; + + @Override + public void initialize() { + // Offers and invitations hold all pending game offers we've sent to + // other users or incoming invitations. + // The map key is always the opponent's JID. + // The map value is a transcript alert UI component. + gameOffers = new ConcurrentHashMap<>(0); + gameInvitations = new ConcurrentHashMap<>(0); + + // Add Reversi item to the chat toolbar. + addToolbarButton(); + + // Add Smack providers. + // The plugin uses custom XMPP extensions to communicate game offers and current game state. + // Adding the Smack providers lets us use the custom protocol. + ProviderManager.addIQProvider(GameOffer.ELEMENT_NAME, GameOffer.NAMESPACE, new GameOffer.Provider()); + ProviderManager.addExtensionProvider(GameMove.ELEMENT_NAME, GameMove.NAMESPACE, new GameMove.Provider()); + ProviderManager.addExtensionProvider(GameForfeit.ELEMENT_NAME, GameForfeit.NAMESPACE, new GameForfeit.Provider()); + + // Add the IQ listener to listen for incoming game invitations. + gameOfferHandler = new AbstractIqRequestHandler( + GameOffer.ELEMENT_NAME, + GameOffer.NAMESPACE, + IQ.Type.get, + IQRequestHandler.Mode.async) { + @Override + public IQ handleIQRequest(IQ request) { + showInvitationAlert((GameOffer) request); + return null; + } + }; + + SparkManager.getConnection().registerIQRequestHandler(gameOfferHandler); + } + + @Override + public void shutdown() { + // Remove Reversi button from chat toolbar. + removeToolbarButton(); + // Remove IQ listener + SparkManager.getConnection().unregisterIQRequestHandler(gameOfferHandler); +// // See if there are any pending offers or invitations. If so, cancel them. +// gameOffers.forEach((k, v) -> { +// System.out.println("gameoffer " + k); +// }); +// System.out.println(gameInvitations.keySet()); + gameOffers.clear(); + gameInvitations.clear(); + + // Remove Smack providers. + ProviderManager.removeIQProvider(GameOffer.ELEMENT_NAME, GameOffer.NAMESPACE); + ProviderManager.removeExtensionProvider(GameMove.ELEMENT_NAME, GameMove.NAMESPACE); + ProviderManager.removeExtensionProvider(GameForfeit.ELEMENT_NAME, GameForfeit.NAMESPACE); + } + + @Override + public boolean canShutDown() { + // The plugin is able to fully clean itself up, so return true. + return true; + } + + @Override + public void uninstall() { + // Do nothing. Reversi has no permanent resources so shutdown can + // already do a full cleanup. + } + + /** + * Display an alert that allows the user to accept or reject a game + * invitation. + * + * @param invitation the game invitation. + */ + private void showInvitationAlert(final GameOffer invitation) { + // Got an offer to start a new game. So, make sure that a chat is + // started with the other + // user and show an invite panel. + final ChatRoom room = SparkManager.getChatManager().getChatRoom(invitation.getFrom().asEntityBareJidOrThrow()); + + inviteAlert = new JPanel(); + inviteAlert.setLayout(new BorderLayout()); + + JPanel invitePanel = new JPanel() { + private static final long serialVersionUID = 5942001917654498678L; + + @Override + protected void paintComponent(Graphics g) { + ImageIcon imageIcon = ReversiRes.getImageIcon(ReversiRes.REVERSI_ICON); + Image image = imageIcon.getImage(); + g.drawImage(image, 0, 0, null); + } + }; + invitePanel.setPreferredSize(new Dimension(24, 24)); + inviteAlert.add(invitePanel, BorderLayout.WEST); + JPanel content = new JPanel(new BorderLayout()); + Jid opponentName = invitation.getFrom(); // TODO: convert to more + // readable name. + content.add(new JLabel(opponentName + " is requesting a Reversi game ..."), BorderLayout.CENTER); + JPanel buttonPanel = new JPanel(); + + // The accept button. When clicked, accept the game offer. + final JButton acceptButton = new JButton("Accept"); + final JButton declineButton = new JButton("Decline"); + + acceptButton.addActionListener(e -> { + // Accept the game offer by sending a positive reply packet. + GameOffer reply = new GameOffer(); + reply.setTo(invitation.getFrom()); + reply.setStanzaId(invitation.getStanzaId()); + reply.setType(IQ.Type.result); + try { + SparkManager.getConnection().sendStanza(reply); + } catch (SmackException.NotConnectedException | InterruptedException e1) { + Log.warning("Unable to accept game offer from " + invitation.getFrom(), e1); + } + + // Hide the response panel. TODO: make this work. + room.getTranscriptWindow().remove(inviteAlert); + inviteAlert.remove(1); + inviteAlert.add(new JLabel("Starting game..."), BorderLayout.CENTER); + declineButton.setEnabled(false); + acceptButton.setEnabled(false); + // Remove the invitation from the map. + gameInvitations.remove(invitation.getFrom()); + // Show the game board. + showReversiBoard(invitation.getGameID(), room, !invitation.isStartingPlayer(), invitation.getFrom()); + }); + buttonPanel.add(acceptButton); + + // The decline button. When clicked, reject the game offer. + + declineButton.addActionListener(e -> { + // Reject the game offer by sending an error packet. + GameOffer reply = new GameOffer(); + reply.setTo(invitation.getFrom()); + reply.setStanzaId(invitation.getStanzaId()); + reply.setType(IQ.Type.error); + reply.setError(StanzaError.getBuilder().setCondition(StanzaError.Condition.undefined_condition).setDescriptiveEnText("User declined your request.").build()); + try { + SparkManager.getConnection().sendStanza(reply); + } catch (SmackException.NotConnectedException | InterruptedException e1) { + Log.warning("Unable to decline game offer from " + invitation.getFrom(), e1); + } + + // Hide the response panel. TODO: make this work. + room.getTranscriptWindow().remove(inviteAlert); + + declineButton.setVisible(false); + acceptButton.setVisible(false); + // Remove the invitation from the map. + gameInvitations.remove(invitation.getFrom()); + }); + buttonPanel.add(declineButton); + content.add(buttonPanel, BorderLayout.SOUTH); + inviteAlert.add(content, BorderLayout.CENTER); + + // Add the invitation to the Map of invites. If there's a pending + // invite, remove it + // before adding the new one (possible if the opponent sends two invites + // in a row). + Object oldInvitation = gameInvitations.put(invitation.getFrom(), inviteAlert); + // TODO: clean it up by removing it from the transcript window. + // if (oldInvitation != null) { + // } + + // Add the response panel to the transcript window. + room.getTranscriptWindow().addComponent(inviteAlert); + } + + /** + * Adds the Reversi toolbar button. + */ + private void addToolbarButton() { + ChatManager manager = SparkManager.getChatManager(); + chatRoomListener = new ChatRoomListener() { + final ImageIcon icon = ReversiRes.getImageIcon(ReversiRes.REVERSI_ICON); + + @Override + public void chatRoomOpened(final ChatRoom room) { + if (!(room instanceof ChatRoomImpl)) { + // Don't do anything if this is not a 1on1-Chat + return; + } + ChatRoomButton button = new ChatRoomButton(icon); + button.setToolTipText("Reversi"); + room.getToolBar().addChatRoomButton(button); + + // Add a button listener that sends out a game invite on a user + // click. + button.addActionListener(e -> { + EntityFullJid opponentJID = ((ChatRoomImpl) room).getJidOnline(); + //If the opponent is offline, then you should not start the game + if (opponentJID == null) { + return; + } + + // Show "requesting a game panel" + final JPanel request = new JPanel(); + request.setLayout(new BorderLayout()); + JPanel requestPanel = new JPanel() { + private static final long serialVersionUID = 4490592207923738251L; + + @Override + protected void paintComponent(Graphics g) { + g.drawImage(icon.getImage(), 0, 0, null); + } + }; + requestPanel.setPreferredSize(new Dimension(24, 24)); + request.add(requestPanel, BorderLayout.WEST); + + String opponentName = "[" + opponentJID + "]"; // TODO: + // convert to more readable name. + final JPanel content = new JPanel(new BorderLayout()); + final JLabel label = new JLabel("Requesting a Reversi game with " + opponentName + ", please wait..."); + content.add(label, BorderLayout.CENTER); + JPanel buttonPanel = new JPanel(); + final JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(e12 -> { + GameOffer reply = new GameOffer(); + reply.setTo(opponentJID); + reply.setType(IQ.Type.error); + reply.setError(StanzaError.getBuilder().setCondition(StanzaError.Condition.undefined_condition).setDescriptiveEnText("User cancelled the invitation.").build()); + + try { + SparkManager.getConnection().sendStanza(reply); + } catch (SmackException.NotConnectedException | InterruptedException e1) { + Log.warning("Unable to send invitation cancellation to " + reply.getTo(), e1); + } + cancelButton.setText("Canceled"); + cancelButton.setEnabled(false); + }); + buttonPanel.add(cancelButton, BorderLayout.SOUTH); + content.add(buttonPanel, BorderLayout.SOUTH); + request.add(content, BorderLayout.CENTER); + room.getTranscriptWindow().addComponent(request); + + final GameOffer offer = new GameOffer(); + offer.setTo(opponentJID); + + // Add a listener for a reply to our offer. + SparkManager.getConnection().addAsyncStanzaListener(stanza -> { + if (stanza.getError() != null) { + cancelButton.setVisible(false); + JPanel userDeclinedPanel = new JPanel(new BorderLayout()); + JLabel userDeclined = new JLabel("User declined..."); + userDeclinedPanel.add(userDeclined, BorderLayout.SOUTH); + request.add(userDeclinedPanel, BorderLayout.SOUTH); + return; + } + + GameOffer offerReply = ((GameOffer) stanza); + if (offerReply.getType() == IQ.Type.result) { + // Remove the offer panel + room.getTranscriptWindow().remove(request); + content.remove(1); + label.setText("Starting game..."); + // Show game board (using original offer!). + showReversiBoard(offer.getGameID(), room, offer.isStartingPlayer(), offerReply.getFrom()); + } else if (offerReply.getType() == IQ.Type.error) { + cancelButton.setVisible(false); + JPanel userDeclinedPanel = new JPanel(new BorderLayout()); + JLabel userDeclined = new JLabel("User declined..."); + userDeclinedPanel.add(userDeclined, BorderLayout.SOUTH); + request.add(userDeclinedPanel, BorderLayout.SOUTH); + } + }, new StanzaIdFilter(offer.getStanzaId())); + + try { + SparkManager.getConnection().sendStanza(offer); + } catch (SmackException.NotConnectedException | InterruptedException e1) { + Log.warning("Unable to send invitation to " + offer.getTo(), e1); + } + }); + } + + @Override + public void chatRoomClosed(ChatRoom room) { + // TODO: if game is in progress, close it down. What we need is + // an API that lets us see + // TODO: if there's a transcript alert currently there. + } + }; + manager.addChatRoomListener(chatRoomListener); + } + + /** + * Displays the game board. This is called after an offer has been accepted + * or after accepting an invitation. + * + * @param gameID the game ID. + * @param room the chat room to display the game board in. + * @param startingPlayer true if this player is the starting player (black). + * @param opponentJID the opponent's JID. + */ + private void showReversiBoard(int gameID, ChatRoom room, boolean startingPlayer, Jid opponentJID) { + JSplitPane pane = room.getSplitPane(); + pane.setResizeWeight(1.0); + BackgroundPanel reversiBackground = new BackgroundPanel(); + reversiBackground.setLayout(new BorderLayout()); + reversiBackground.setOpaque(false); + ReversiPanel reversi = new ReversiPanel(SparkManager.getConnection(), gameID, startingPlayer, opponentJID); + reversiBackground.add(reversi, BorderLayout.CENTER); + pane.setRightComponent(reversiBackground); + reversi.setMinimumSize(new Dimension(ReversiPanel.TOTAL_WIDTH, ReversiPanel.TOTAL_HEIGHT)); + } + + /** + * Removes the Reversi toolbar button. + */ + private void removeToolbarButton() { + ChatManager manager = SparkManager.getChatManager(); + manager.removeChatRoomListener(chatRoomListener); + // TODO: remove actual buttons from toolbar. + } +} diff --git a/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/ReversiRes.java b/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/ReversiRes.java new file mode 100644 index 000000000..eaaeef85e --- /dev/null +++ b/plugins/reversi/src/main/java/org/jivesoftware/game/reversi/ReversiRes.java @@ -0,0 +1,56 @@ +package org.jivesoftware.game.reversi; + +import org.jivesoftware.resource.UTF8Control; +import org.jivesoftware.spark.util.log.Log; + +import java.net.URL; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +import javax.swing.ImageIcon; + +public class ReversiRes { + private static PropertyResourceBundle prb; + public static final String REVERSI_ICON = "REVERSI_ICON"; + public static final String REVERSI_BOARD = "REVERSI_BOARD"; + public static final String REVERSI_SCORE_WHITE = "REVERSI_SCORE_WHITE"; + public static final String REVERSI_SCORE_BLACK = "REVERSI_SCORE_BLACK"; + public static final String REVERSI_LABEL_BLACK = "REVERSI_LABEL_BLACK"; + public static final String REVERSI_LABEL_WHITE = "REVERSI_LABEL_WHITE"; + public static final String REVERSI_RESIGN = "REVERSI_RESIGN"; + public static final String REVERSI_YOU = "REVERSI_YOU"; + public static final String REVERSI_THEM = "REVERSI_THEM"; + + private ReversiRes() { + + } + + private static final ClassLoader cl = ReversiRes.class.getClassLoader(); + + static { + ReversiRes.prb = (PropertyResourceBundle) ResourceBundle.getBundle("reversi", new UTF8Control()); + } + + public static String getString(String propertyName) { + return ReversiRes.prb.getString(propertyName); + } + + public static ImageIcon getImageIcon(String imageName) { + try { + final String iconURI = ReversiRes.getString(imageName); + final URL imageURL = ReversiRes.cl.getResource(iconURI); + if (imageURL != null) { + return new ImageIcon(imageURL); + } else { + Log.warning(imageName + " not found."); + } + } catch (Exception e) { + Log.warning("Unable to load image " + imageName, e); + } + return null; + } + + public static URL getURL(String propertyName) { + return ReversiRes.cl.getResource(ReversiRes.getString(propertyName)); + } +} diff --git a/plugins/reversi/src/main/plugin-metadata/plugin.xml b/plugins/reversi/src/main/plugin-metadata/plugin.xml new file mode 100644 index 000000000..bde04db73 --- /dev/null +++ b/plugins/reversi/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,13 @@ + + + ${project.name} + ${project.version} + ${project.description} + Matt Tucker, Bill Lynch, Holger Bergunde + https://IgniteRealtime.org + support@IgniteRealtime.org + org.jivesoftware.game.reversi.ReversiPlugin + 3.1.0 + 11 + + diff --git a/plugins/reversi/src/main/resources/images/button-resign.png b/plugins/reversi/src/main/resources/images/button-resign.png new file mode 100644 index 000000000..878fe2bc4 Binary files /dev/null and b/plugins/reversi/src/main/resources/images/button-resign.png differ diff --git a/plugins/reversi/src/main/resources/images/reversi-board.png b/plugins/reversi/src/main/resources/images/reversi-board.png new file mode 100644 index 000000000..a932dd7a2 Binary files /dev/null and b/plugins/reversi/src/main/resources/images/reversi-board.png differ diff --git a/plugins/reversi/src/main/resources/images/reversi-icon.png b/plugins/reversi/src/main/resources/images/reversi-icon.png new file mode 100644 index 000000000..385098bd9 Binary files /dev/null and b/plugins/reversi/src/main/resources/images/reversi-icon.png differ diff --git a/plugins/reversi/src/main/resources/images/score-button-black.png b/plugins/reversi/src/main/resources/images/score-button-black.png new file mode 100644 index 000000000..7c99df242 Binary files /dev/null and b/plugins/reversi/src/main/resources/images/score-button-black.png differ diff --git a/plugins/reversi/src/main/resources/images/score-button-white.png b/plugins/reversi/src/main/resources/images/score-button-white.png new file mode 100644 index 000000000..32364cfed Binary files /dev/null and b/plugins/reversi/src/main/resources/images/score-button-white.png differ diff --git a/plugins/reversi/src/main/resources/images/them.png b/plugins/reversi/src/main/resources/images/them.png new file mode 100644 index 000000000..73789bcc4 Binary files /dev/null and b/plugins/reversi/src/main/resources/images/them.png differ diff --git a/plugins/reversi/src/main/resources/images/turn-label-black.png b/plugins/reversi/src/main/resources/images/turn-label-black.png new file mode 100644 index 000000000..463b19664 Binary files /dev/null and b/plugins/reversi/src/main/resources/images/turn-label-black.png differ diff --git a/plugins/reversi/src/main/resources/images/turn-label-white.png b/plugins/reversi/src/main/resources/images/turn-label-white.png new file mode 100644 index 000000000..adb3916f9 Binary files /dev/null and b/plugins/reversi/src/main/resources/images/turn-label-white.png differ diff --git a/plugins/reversi/src/main/resources/images/you.png b/plugins/reversi/src/main/resources/images/you.png new file mode 100644 index 000000000..0840302f7 Binary files /dev/null and b/plugins/reversi/src/main/resources/images/you.png differ diff --git a/src/plugins/reversi/src/resources/reversi.properties b/plugins/reversi/src/main/resources/reversi.properties similarity index 100% rename from src/plugins/reversi/src/resources/reversi.properties rename to plugins/reversi/src/main/resources/reversi.properties diff --git a/plugins/roar/pom.xml b/plugins/roar/pom.xml new file mode 100644 index 000000000..9c1658b15 --- /dev/null +++ b/plugins/roar/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + roar + 1.1 + + Roar!!! + Provides customizable popup/notification functionality. + + + + Wolf Posdorfer + 9posdorf@informatik.uni-hamburg.de + + Author + + + + + diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/Roar.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/Roar.java similarity index 96% rename from src/plugins/roar/src/java/org/jivesoftware/spark/roar/Roar.java rename to plugins/roar/src/main/java/org/jivesoftware/spark/roar/Roar.java index 6cd9e2e19..c0b4bf86e 100644 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/Roar.java +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/Roar.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/plugins/roar/src/main/java/org/jivesoftware/spark/roar/RoarMessageListener.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/RoarMessageListener.java new file mode 100644 index 000000000..7c587c622 --- /dev/null +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/RoarMessageListener.java @@ -0,0 +1,119 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.roar; + +import java.awt.*; + +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.roar.displaytype.PropertyBundle; +import org.jivesoftware.spark.roar.displaytype.RoarDisplayType; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomNotFoundException; +import org.jivesoftware.spark.ui.GlobalMessageListener; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.ui.rooms.GroupChatRoom; +import org.jivesoftware.spark.util.log.Log; + +/** + * Message Listener
      + * + * @author wolf.posdorfer + * + */ +public class RoarMessageListener implements GlobalMessageListener { + + private final RoarProperties _properties; + + public RoarMessageListener() { + _properties = RoarProperties.getInstance(); + } + + @Override + public void messageReceived(ChatRoom room, Message message) { + + try { + ChatRoom activeroom = SparkManager.getChatManager().getChatContainer().getActiveChatRoom(); + final int framestate = SparkManager.getChatManager().getChatContainer().getChatFrame().getState(); + final boolean frameisactive = SparkManager.getChatManager().getChatContainer().getChatFrame().isActive(); + + // If the message is for a chat that's currently active and showing, do not popup. + if (activeroom.equals(room) && framestate == Frame.NORMAL && frameisactive) { + Log.debug( "Surpressing popup: chat is currently active and showing."); + return; + } + + // If the message is sent by the local user (potentially using a different client), do not popup. + if ( (room instanceof GroupChatRoom && message.getFrom().getResourceOrEmpty().equals(activeroom.getNickname())) + || SparkManager.getSessionManager().getJID().equals(message.getFrom())) { + Log.debug( "Surpressing popup: sender of message is the local user."); + return; + } + + // When none of the exceptions above are true, do a popup! + decideForRoomAndMessage(room, message); + + } catch (ChatRoomNotFoundException e) { + // i don't care + } + + } + + private void decideForRoomAndMessage(ChatRoom room, Message message) { + final RoarDisplayType displayType = RoarProperties.getInstance().getDisplayTypeClass(); + if (room instanceof ChatRoomImpl && !isSingleRoomDisabled()) { + displayType.messageReceived(room, message, getSingleBundle()); + } else if (room instanceof GroupChatRoom && !isMutliRoomDisabled()) { + displayType.messageReceived(room, message, isMultiRoomDifferent() ? getMultiBundle() : getSingleBundle()); + } + } + + + private boolean isSingleRoomDisabled() + { + return _properties.getBoolean("roar.disable.single", false); + } + + private boolean isMutliRoomDisabled() + { + return _properties.getBoolean("group.disable", false); + } + + private boolean isMultiRoomDifferent() + { + return _properties.getBoolean("group.different.enabled", false); + } + + private PropertyBundle getSingleBundle() { + return new PropertyBundle(_properties.getBackgroundColor(), _properties.getHeaderColor(), + _properties.getTextColor(), _properties.getDuration()); + } + + private PropertyBundle getMultiBundle() { + return new PropertyBundle( + _properties.getColor(RoarProperties.BACKGROUNDCOLOR_GROUP, _properties.getBackgroundColor()), + _properties.getColor(RoarProperties.HEADERCOLOR_GROUP, _properties.getHeaderColor()), + _properties.getColor(RoarProperties.TEXTCOLOR_GROUP, _properties.getTextColor()), + _properties.getDuration("group.duration")); + } + + @Override + public void messageSent(ChatRoom room, Message message) { + final RoarDisplayType displayType = RoarProperties.getInstance().getDisplayTypeClass(); + displayType.messageSent(room, message); + } + +} diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/RoarPreference.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/RoarPreference.java similarity index 94% rename from src/plugins/roar/src/java/org/jivesoftware/spark/roar/RoarPreference.java rename to plugins/roar/src/main/java/org/jivesoftware/spark/roar/RoarPreference.java index 6fe8f5166..4938165fb 100644 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/RoarPreference.java +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/RoarPreference.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,7 +34,7 @@ public class RoarPreference implements Preference { private RoarPreferencePanel _prefPanel; - private RoarProperties _props; + private final RoarProperties _props; public RoarPreference() { @@ -64,7 +60,7 @@ public String getTitle() { @Override public Icon getIcon() { ClassLoader cl = getClass().getClassLoader(); - return new ImageIcon(cl.getResource("roar-logo.png")); + return new ImageIcon(cl.getResource("roar.png")); } @Override diff --git a/plugins/roar/src/main/java/org/jivesoftware/spark/roar/RoarProperties.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/RoarProperties.java new file mode 100644 index 000000000..5154a4d87 --- /dev/null +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/RoarProperties.java @@ -0,0 +1,251 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.roar; + +import java.awt.Color; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Properties; +import java.util.stream.Collectors; + +import org.jivesoftware.Spark; +import org.jivesoftware.spark.roar.displaytype.BottomRight; +import org.jivesoftware.spark.roar.displaytype.SystemNotification; +import org.jivesoftware.spark.roar.displaytype.RoarDisplayType; +import org.jivesoftware.spark.roar.displaytype.SparkToasterHandler; +import org.jivesoftware.spark.roar.displaytype.TopRight; + +/** + * RoarProperties file stuff + * + * @author wolf.posdorfer + * + */ +public class RoarProperties { + private final Properties props; + private File configFile; + + public static final String ACTIVE = "active"; + public static final String AMOUNT = "amount"; + public static final String ROARDISPLAYTYPE = "roardisplaytype"; + + public static final String BACKGROUNDCOLOR = "backgroundcolor"; + public static final String HEADERCOLOR = "headercolor"; + public static final String TEXTCOLOR = "textcolor"; + public static final String DURATION = "duration"; + + public static final String BACKGROUNDCOLOR_GROUP = "backgroundcolor.group"; + public static final String HEADERCOLOR_GROUP = "headercolor.group"; + public static final String TEXTCOLOR_GROUP = "textcolor.group"; + public static final String DURATION_GROUP = "duration.group"; + + private static final Object LOCK = new Object(); + private static RoarProperties instance = null; + + private final RoarDisplayType[] displayTypes = new RoarDisplayType[]{new TopRight(), new BottomRight(), new SparkToasterHandler(), new SystemNotification()}; + + + /** + * returns the Instance of this Properties file + * + * @return + */ + public static RoarProperties getInstance() { + synchronized (LOCK) { + if (instance == null) { + instance = new RoarProperties(); + } + return instance; + } + } + + private RoarProperties() { + this.props = new Properties(); + + try { + props.load(new FileInputStream(getConfigFile())); + } catch (IOException e) { + // Can't load ConfigFile + } + + } + + private File getConfigFile() { + if (configFile == null) + configFile = new File(Spark.getSparkUserHome(), "roar.properties"); + + return configFile; + } + + public void save() { + try { + props.store(new FileOutputStream(getConfigFile()), "Storing ROAR properties"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public List getDisplayTypes() { + return Arrays.stream(displayTypes).filter(RoarDisplayType::isSupported).collect(Collectors.toList()); + } + + public boolean getShowingPopups() { + return getBoolean(ACTIVE, false); + } + + public void setShowingPopups(boolean popups) { + setBoolean(ACTIVE, popups); + } + + public Color getBackgroundColor() { + return getColor(BACKGROUNDCOLOR, Color.WHITE); + } + + public void setBackgroundColor(Color c) { + setColor(BACKGROUNDCOLOR, c); + } + + public Color getHeaderColor() { + return getColor(HEADERCOLOR, new Color(255,85,0)); + } + + public void setHeaderColor(Color c) { + setColor(HEADERCOLOR, c); + } + + public Color getTextColor() { + return getColor(TEXTCOLOR, Color.BLACK); + } + + public void setTextColor(Color c) { + setColor(TEXTCOLOR, c); + } + + public int getDuration() { + int dur = getDuration(DURATION); + return dur < 0 ? 3000 : getDuration(DURATION); + } + + public void setDuration(int dur) { + setDuration(DURATION, dur); + } + + public int getMaximumPopups() { + return getAmount(AMOUNT); + } + + public void setMaximumPopups(int amount) { + setAmount(AMOUNT, amount); + } + + public void setDisplayType(String classstring) { + System.out.println("setting displaytype to: "+ classstring); + props.setProperty(ROARDISPLAYTYPE, classstring); + } + + public String getDisplayType() { + return props.getProperty(ROARDISPLAYTYPE, displayTypes[0].getName()); // TopRight is default + } + + public RoarDisplayType getDisplayTypeClass() { + + String stringInProperty = getDisplayType(); + for (RoarDisplayType type : displayTypes) { + if (type.getName().equals(stringInProperty)) { + return type; + } + } + return displayTypes[0]; // TopRight is default + } + + // =============================================================================== + // =============================================================================== + // =============================================================================== + public boolean getBoolean(String property, boolean defaultValue) { + return Boolean.parseBoolean(props.getProperty(property, Boolean.toString(defaultValue))); + } + + public void setBoolean(String property, boolean value) { + props.setProperty(property, Boolean.toString(value)); + } + + public int getDuration(String property) { + return Integer.parseInt(props.getProperty(property, "3000")); + } + + public void setDuration(String property, int integer) { + props.setProperty(property, "" + integer); + } + + public int getAmount(String property) { + return Integer.parseInt(props.getProperty(property, "4")); + } + + public void setAmount(String property, int integer) { + props.setProperty(property, "" + integer); + } + + public void setColor(String property, Color color) { + props.setProperty(property, convertColor(color)); + } + + public Color getColor(String property, Color defaultcolor) { + try { + return convertString(props.getProperty(property)); + } catch (Exception e) { + return defaultcolor; + } + + } + + public String getProperty(String property) { + return props.getProperty(property); + } + + public void setProperty(String property, String value) { + props.setProperty(property, value); + } + + /** + * Converts a {@link String} matching xxx,xxx,xxx to a {@link Color}
      + * where xxx is a number from 0 to 255 + * + * @param s + * @return + */ + public static Color convertString(String s) { + String[] arr = s.split(","); + return new Color(Integer.parseInt(arr[0]), Integer.parseInt(arr[1]), Integer.parseInt(arr[2])); + } + + /** + * Converts a {@link Color} to a {@link String} in this format:
      + * xxx,xxx,xxx
      + * where xxx is a number from 0 to 255 + * + * @param color + * @return + */ + public static String convertColor(Color color) { + return color.getRed() + "," + color.getGreen() + "," + color.getBlue(); + } + +} diff --git a/plugins/roar/src/main/java/org/jivesoftware/spark/roar/RoarResources.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/RoarResources.java new file mode 100644 index 000000000..471a19e21 --- /dev/null +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/RoarResources.java @@ -0,0 +1,26 @@ +package org.jivesoftware.spark.roar; + +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +import org.jivesoftware.resource.UTF8Control; +import org.jivesoftware.spark.util.log.Log; + +public class RoarResources { + + private static final PropertyResourceBundle prb; + + static { + prb = (PropertyResourceBundle) ResourceBundle.getBundle("i18n/roar_i18n", new UTF8Control()); + } + + public static String getString(String propertyName) { + try { + return prb.getString(propertyName); + } catch (Exception e) { + Log.error(e); + return propertyName; + } + } + +} diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/BottomRight.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/BottomRight.java similarity index 90% rename from src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/BottomRight.java rename to plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/BottomRight.java index e28dff244..4b2ed8e7b 100644 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/BottomRight.java +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/BottomRight.java @@ -28,14 +28,14 @@ public class BottomRight implements RoarDisplayType { private int _lastusedXpos; private int _lastusedYpos; - private int _defaultx; - private int _defaulty; + private final int _defaultx; + private final int _defaulty; private int _amount; private final int WIDTH = RoarPanel.WIDTH; private final int HEIGHT = RoarPanel.HEIGHT; - private AbstractAction _customaction; + private final AbstractAction _customaction; private static final int TASKBAR = 35; @@ -56,8 +56,10 @@ public BottomRight() { @Override public void actionPerformed(ActionEvent e) { ChatFrame chatFrame = SparkManager.getChatManager().getChatContainer().getChatFrame(); - chatFrame.setState(Frame.NORMAL); - chatFrame.setVisible(true); + if(chatFrame != null){ + chatFrame.setState(Frame.NORMAL); + chatFrame.setVisible(true); + } } }; } @@ -68,7 +70,7 @@ public void messageReceived(ChatRoom room, Message message, PropertyBundle prope if (props.getShowingPopups() && (_amount < props.getMaximumPopups() || props.getMaximumPopups() == 0)) { - ImageIcon icon = SparkRes.getImageIcon(SparkRes.SPARK_IMAGE_32x32); + ImageIcon icon = SparkRes.getImageIcon(SparkRes.Icon.SPARK_IMAGE_32x32); String nickname = RoarPopupHelper.getNickname(room, message); RoarPanel.popupWindow(this, icon, nickname, message.getBody(), _lastusedXpos, _lastusedYpos, diff --git a/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/MacNotificationCenter.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/MacNotificationCenter.java new file mode 100644 index 000000000..0d1c18b67 --- /dev/null +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/MacNotificationCenter.java @@ -0,0 +1,35 @@ +package org.jivesoftware.spark.roar.displaytype; + +import java.io.File; + +import org.jivesoftware.Spark; + +import com.sun.jna.Library; +import com.sun.jna.Native; + +/** + * Provides Notification-Center integration for OSX 10.8+
      + *
      + * + * NSUserNotificationsBridge is based on + * https://github.com/petesh/OSxNotificationCenter + * + * @author wolf.posdorfer + */ +public class MacNotificationCenter { + + interface NSUserNotificationsBridge extends Library { + + File dylib = new File(Spark.getPluginDirectory().getAbsolutePath() + + File.separator + "roar" + File.separator + "native" + File.separator + "NSUserNotificationsBridge.dylib" ); + + NSUserNotificationsBridge instance = Native.load(dylib.getAbsolutePath(), NSUserNotificationsBridge.class); + + int sendNotification(String title, String subtitle, String text, int timeoffset, String sound); + } + + public static void sendNotification(String title, String bodyText) { + NSUserNotificationsBridge.instance.sendNotification(title, "", bodyText, 0, "Ping"); + } + +} diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/PropertyBundle.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/PropertyBundle.java similarity index 77% rename from src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/PropertyBundle.java rename to plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/PropertyBundle.java index 5d1d1bf33..73c8b34d7 100644 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/PropertyBundle.java +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/PropertyBundle.java @@ -9,10 +9,10 @@ */ public class PropertyBundle { - public Color backgroundColor; - public Color headerColor; - public Color textColor; - public int duration; + public final Color backgroundColor; + public final Color headerColor; + public final Color textColor; + public final int duration; public PropertyBundle(Color backgroundColor, Color headerColor, Color textColor, int duration) { this.backgroundColor = backgroundColor; @@ -20,5 +20,4 @@ public PropertyBundle(Color backgroundColor, Color headerColor, Color textColor, this.textColor = textColor; this.duration = duration; } - } diff --git a/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/RoarDisplayType.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/RoarDisplayType.java new file mode 100644 index 000000000..818c48e78 --- /dev/null +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/RoarDisplayType.java @@ -0,0 +1,37 @@ +package org.jivesoftware.spark.roar.displaytype; + +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.spark.ui.ChatRoom; + +public interface RoarDisplayType { + + /** + * Do stuff when a message is received + */ + void messageReceived(ChatRoom room, Message message, PropertyBundle bundle); + + /** + * Do stuff when a message is sent + */ + void messageSent(ChatRoom room, Message message); + + /** + * Do stuff when the Popup closes + */ + void closingRoarPanel(int x, int y); + + String getName(); + + String getLocalizedName(); + + String getWarningMessage(); + + /** + * Checks if the display type is supported on this platform. + * + * @return true if supported, otherwise false. + */ + default boolean isSupported() { + return true; + } +} diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/RoarPopupHelper.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/RoarPopupHelper.java similarity index 81% rename from src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/RoarPopupHelper.java rename to plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/RoarPopupHelper.java index be5a87b08..7099cb4da 100644 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/RoarPopupHelper.java +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/RoarPopupHelper.java @@ -5,7 +5,6 @@ import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.ui.ChatRoom; -import org.jxmpp.util.XmppStringUtils; /** * Utility methods for popups @@ -24,12 +23,12 @@ public final class RoarPopupHelper { * @return nickname */ public static String getNickname(ChatRoom room, Message message) { - String nickname = SparkManager.getUserManager().getUserNicknameFromJID(message.getFrom()); + String nickname = SparkManager.getUserManager().getUserNicknameFromJID(message.getFrom().asBareJid()); if (room.getChatType() == Message.Type.groupchat) { - nickname = XmppStringUtils.parseResource(nickname); + nickname = message.getFrom().getResourceOrEmpty().toString(); } - final JivePropertiesExtension extension = ((JivePropertiesExtension) message.getExtension( JivePropertiesExtension.NAMESPACE )); + final JivePropertiesExtension extension = message.getExtension(JivePropertiesExtension.class); final boolean broadcast = extension != null && extension.getProperty( "broadcast" ) != null; if ((broadcast || message.getType() == Message.Type.normal || message.getType() == Message.Type.headline) diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/SparkToasterHandler.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/SparkToasterHandler.java similarity index 94% rename from src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/SparkToasterHandler.java rename to plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/SparkToasterHandler.java index 6e9cb3157..2e3ffac6a 100644 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/SparkToasterHandler.java +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/SparkToasterHandler.java @@ -1,5 +1,6 @@ package org.jivesoftware.spark.roar.displaytype; +import java.awt.Color; import java.awt.Frame; import java.awt.event.ActionEvent; @@ -31,7 +32,7 @@ public void messageReceived(ChatRoom room, Message message, PropertyBundle prope SparkToaster toaster = new SparkToaster(); toaster.setDisplayTime(property.duration); - toaster.setBorder(BorderFactory.createBevelBorder(0)); + toaster.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true)); toaster.setTitle(room.getTabTitle()); toaster.setCustomAction(new AbstractAction() { diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/SystemNotification.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/SystemNotification.java similarity index 93% rename from src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/SystemNotification.java rename to plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/SystemNotification.java index 06bf7ef77..125c3e588 100644 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/SystemNotification.java +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/SystemNotification.java @@ -55,4 +55,8 @@ public String getWarningMessage() { } } + @Override + public boolean isSupported() { + return WindowsNotification.isSupported(); + } } diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/TopRight.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/TopRight.java similarity index 95% rename from src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/TopRight.java rename to plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/TopRight.java index dbeed5869..64e06af8d 100644 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/TopRight.java +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/TopRight.java @@ -28,14 +28,14 @@ public class TopRight implements RoarDisplayType { private int _lastusedXpos; private int _lastusedYpos; - private Dimension _screensize; + private final Dimension _screensize; private int _amount; private final int WIDTH = RoarPanel.WIDTH; private final int HEIGHT = RoarPanel.HEIGHT; - private Action _customaction; + private final Action _customaction; public TopRight() { _screensize = Toolkit.getDefaultToolkit().getScreenSize(); @@ -62,7 +62,7 @@ public void messageReceived(ChatRoom room, Message message, PropertyBundle prope if (props.getShowingPopups() && (_amount < props.getMaximumPopups() || props.getMaximumPopups() == 0)) { - ImageIcon icon = SparkRes.getImageIcon(SparkRes.SPARK_IMAGE_32x32); + ImageIcon icon = SparkRes.getImageIcon(SparkRes.Icon.SPARK_IMAGE_32x32); String nickname = RoarPopupHelper.getNickname(room, message); RoarPanel.popupWindow(this, icon, nickname, message.getBody(), _lastusedXpos, _lastusedYpos, diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/WindowsNotification.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/WindowsNotification.java similarity index 78% rename from src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/WindowsNotification.java rename to plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/WindowsNotification.java index cc8dc3e21..136948194 100644 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/WindowsNotification.java +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/displaytype/WindowsNotification.java @@ -9,9 +9,12 @@ public static void sendNotification(String title, String bodyText) { TrayIcon[] trayIcon = SystemTray.getSystemTray().getTrayIcons(); if (trayIcon.length == 1) { - trayIcon[0].displayMessage(title, bodyText, TrayIcon.MessageType.INFO); + trayIcon[0].displayMessage(title, bodyText, TrayIcon.MessageType.NONE); } } + public static boolean isSupported() { + return SystemTray.isSupported(); + } } diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/gui/RoarPanel.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/gui/RoarPanel.java similarity index 77% rename from src/plugins/roar/src/java/org/jivesoftware/spark/roar/gui/RoarPanel.java rename to plugins/roar/src/main/java/org/jivesoftware/spark/roar/gui/RoarPanel.java index c1865ee44..d32b1606e 100644 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/gui/RoarPanel.java +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/gui/RoarPanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,11 +15,7 @@ */ package org.jivesoftware.spark.roar.gui; -import java.awt.Color; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; +import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.RoundRectangle2D; @@ -38,11 +30,9 @@ import org.jivesoftware.spark.roar.displaytype.RoarDisplayType; -import com.sun.awt.AWTUtilities; - public class RoarPanel { - public static int WIDTH = 300; - public static int HEIGHT = 80; + public static final int WIDTH = 300; + public static final int HEIGHT = 80; /** * Creates the WindowGui @@ -62,11 +52,10 @@ private static JWindow createWindow(Icon icon, String head, String body, int pos final JWindow window = new JWindow(); JPanel windowpanel = new JPanel(new GridBagLayout()); - windowpanel.setBackground(backgroundcolor); - - AWTUtilities.setWindowShape(window, new RoundRectangle2D.Float(0, 0, WIDTH, HEIGHT, 20, 20)); - AWTUtilities.setWindowOpaque(window, true); + // Make background opaque + windowpanel.setBackground( opacityAdjusted(backgroundcolor, 255) ); + window.setShape(new RoundRectangle2D.Double(0, 0, WIDTH, HEIGHT, 20, 20)); JLabel text = new JLabel("" + body + ""); text.setForeground(messageColor); @@ -96,9 +85,10 @@ private static JWindow createWindow(Icon icon, String head, String body, int pos * @param window */ private static void fadein(JWindow window) { - AWTUtilities.setWindowOpacity(window, 0.3f); - AWTUtilities.setWindowOpacity(window, 0.5f); - AWTUtilities.setWindowOpacity(window, 0.9f); + final boolean supportsTranslucency = window.getGraphicsConfiguration().getDevice().isWindowTranslucencySupported( GraphicsDevice.WindowTranslucency.TRANSLUCENT ); + window.setBackground( opacityAdjusted(window.getBackground(), supportsTranslucency ? 76 : 255) ); + window.setBackground( opacityAdjusted(window.getBackground(), supportsTranslucency ? 127 : 255) ); + window.setBackground( opacityAdjusted(window.getBackground(), supportsTranslucency ? 229 : 255) ); window.setVisible(true); } @@ -158,4 +148,18 @@ public static void closePanel(RoarDisplayType owner, JWindow window) { } } + /** + * Returns a new color, similar to the input color, but with a level of opacity set. + * + * @param color The original color. + * @param opacity The desired amount of opacity. + * @return A new color, combining the original color and opacity level. + */ + public static Color opacityAdjusted( final Color color, final int opacity ) { + if ( color == null ) { + return new Color(0, 0, 0, opacity); + } + + return new Color(color.getRed(), color.getGreen(), color.getBlue(), 255); + } } diff --git a/plugins/roar/src/main/java/org/jivesoftware/spark/roar/gui/RoarPreferencePanel.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/gui/RoarPreferencePanel.java new file mode 100644 index 000000000..fe75f2b6c --- /dev/null +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/gui/RoarPreferencePanel.java @@ -0,0 +1,414 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.roar.gui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.HashMap; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.DefaultListModel; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSlider; +import javax.swing.JTextField; +import javax.swing.event.ChangeEvent; + +import org.jivesoftware.spark.component.VerticalFlowLayout; +import org.jivesoftware.spark.roar.RoarProperties; +import org.jivesoftware.spark.roar.RoarResources; +import org.jivesoftware.spark.roar.displaytype.RoarDisplayType; +import org.jivesoftware.spark.util.ColorPick; + +/** + * Super Awesome Preference Panel + * + * @author wolf.posdorfer + * + */ +public class RoarPreferencePanel extends JPanel { + + private static final long serialVersionUID = -5334936099931215962L; + + private final JTextField _duration; + private final JTextField _amount; + private final JCheckBox _enabledCheckbox; + + private final JComboBox _typelist; + + private final JList _singleColorlist; + private final ColorPick _singleColorpicker; + + private final HashMap _colormap; + + private final HashMap _components; + + private final Insets INSETS = new Insets(5, 5, 5, 5); + + public RoarPreferencePanel() { + + _components = new HashMap<>(); + _colormap = new HashMap<>(); + for (ColorTypes e : ColorTypes.values()) { + _colormap.put(e, Color.BLACK); + } + + this.setLayout(new BorderLayout()); + + + _duration = new JTextField(); + _amount = new JTextField(); + _enabledCheckbox = new JCheckBox(RoarResources.getString("roar.enabled")); + + _singleColorpicker = new ColorPick(false); + _singleColorpicker.addChangeListener(this::stateChangedSingleColorPicker); + + DefaultListModel listModel = new DefaultListModel<>(); + listModel.addElement(ColorTypes.BACKGROUNDCOLOR); + listModel.addElement(ColorTypes.HEADERCOLOR); + listModel.addElement(ColorTypes.TEXTCOLOR); + _singleColorlist = new JList<>(listModel); + + List roarDisplayTypes = RoarProperties.getInstance().getDisplayTypes(); + String[] _typelistdata = new String[ roarDisplayTypes.size() ]; + for (int i = 0; i < roarDisplayTypes.size(); i++) { + _typelistdata[i] = roarDisplayTypes.get(i).getLocalizedName(); + } + + _typelist = new JComboBox<>( _typelistdata ); + _typelist.addActionListener( e -> { + updateWarningLabel(getDisplayTypeClass().getWarningMessage()); + + switch (_typelist.getSelectedIndex()){ + case 2: + _amount.setEnabled(false); + _singleColorlist.setEnabled(false); + _singleColorpicker.setEnabled(false); + _duration.setEnabled(true); + break; + case 3: + _amount.setEnabled(false); + _singleColorlist.setEnabled(false); + _singleColorpicker.setEnabled(false); + _duration.setEnabled(false); + break; + default: + _amount.setEnabled(true); + _singleColorlist.setEnabled(true); + _singleColorpicker.setEnabled(true); + _duration.setEnabled(true); + break; + } + }); + + add(makeGeneralSettingsPanel()); + _singleColorlist.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + colorListMouseClicked(e); + } + }); + } + + private JComponent makeGeneralSettingsPanel() { + JPanel generalPanel = new JPanel(); + generalPanel.setLayout(new GridBagLayout()); + generalPanel.setBorder(BorderFactory.createTitledBorder(RoarResources.getString("roar.settings"))); + + int rowcount = 0; + generalPanel.add(_enabledCheckbox, + new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); + + rowcount++; + generalPanel.add(new JLabel(RoarResources.getString("roar.amount")), + new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); + generalPanel.add(_amount, + new GridBagConstraints(1, rowcount, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); + + rowcount++; + generalPanel.add(new JLabel(RoarResources.getString("roar.location")), + new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); + generalPanel.add(_typelist, + new GridBagConstraints(1, rowcount, 1, 1, 0.8, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); + + + rowcount++; + JLabel warningLabel = new JLabel("placeholder :-)"); + generalPanel.add(warningLabel, + new GridBagConstraints(1, rowcount, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); + rowcount++; + generalPanel.add(_singleColorlist, + new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); + generalPanel.add(_singleColorpicker, + new GridBagConstraints(1, rowcount, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); + + + _components.put("label.warning", warningLabel); + + JPanel panel = new JPanel(new VerticalFlowLayout()); + panel.add(generalPanel); + panel.add(makeSinglePanel()); + panel.add(makeGroupChatPanel()); + + return new JScrollPane(panel); + } + + private JPanel makeSinglePanel() { + JPanel singlePanel = new JPanel(); + singlePanel.setLayout(new GridBagLayout()); + singlePanel.setBorder(BorderFactory.createTitledBorder(RoarResources.getString("roar.single"))); + JCheckBox disableSingle = new JCheckBox(RoarResources.getString("roar.single.disable")); + + // row + int rowcount = 0; + + singlePanel.add(new JLabel(RoarResources.getString("roar.duration")), + new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); + singlePanel.add(_duration, + new GridBagConstraints(1, rowcount, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); + + rowcount++; + singlePanel.add(disableSingle, + new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); + + _components.put("roar.disable.single", disableSingle); + return singlePanel; + } + + private JPanel makeGroupChatPanel() { + JPanel groupPanel = new JPanel(); + groupPanel.setLayout(new GridBagLayout()); + groupPanel.setBorder(BorderFactory.createTitledBorder(RoarResources.getString("roar.group"))); + + final JCheckBox enableDifferentGroup = new JCheckBox(RoarResources.getString("roar.group.different")); + JCheckBox disableGroup = new JCheckBox(RoarResources.getString("roar.group.disable")); + JTextField durationGroup = new JTextField(); + + enableDifferentGroup.addActionListener( e -> toggleDifferentSettingsForGroup(enableDifferentGroup.isSelected()) ); + + int rowcount = 0; + groupPanel.add(enableDifferentGroup, + new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); + + rowcount++; + groupPanel.add(new JLabel(RoarResources.getString("roar.duration")), + new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); + groupPanel.add(durationGroup, + new GridBagConstraints(1, rowcount, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); + + rowcount++; + groupPanel.add(disableGroup, + new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); + + _components.put("group.different.enabled", enableDifferentGroup); + _components.put("group.duration", durationGroup); + _components.put("group.disable", disableGroup); + + return groupPanel; + } + + public void initializeValues() { + RoarProperties props = RoarProperties.getInstance(); + + _enabledCheckbox.setSelected(props.getShowingPopups()); + _amount.setText("" + props.getMaximumPopups()); + setDisplayType(props.getDisplayType()); + + setColor(ColorTypes.BACKGROUNDCOLOR, props.getBackgroundColor()); + setColor(ColorTypes.BACKGROUNDCOLOR_GROUP, props.getColor(RoarProperties.BACKGROUNDCOLOR_GROUP, props.getBackgroundColor())); + setColor(ColorTypes.HEADERCOLOR, props.getHeaderColor()); + setColor(ColorTypes.HEADERCOLOR_GROUP, props.getColor(RoarProperties.HEADERCOLOR_GROUP, props.getHeaderColor())); + setColor(ColorTypes.TEXTCOLOR, props.getTextColor()); + setColor(ColorTypes.TEXTCOLOR_GROUP, props.getColor(RoarProperties.TEXTCOLOR_GROUP, props.getTextColor())); + + retrieveComponent("roar.disable.single", JCheckBox.class).setSelected(props.getBoolean("roar.disable.single", false)); + _duration.setText("" + props.getDuration()); + retrieveComponent("group.duration", JTextField.class).setText("" + props.getDuration("group.duration")); + + retrieveComponent("group.disable", JCheckBox.class).setSelected(props.getBoolean("group.disable", false)); + + boolean group_different_enabled = props.getBoolean("group.different.enabled", false); + retrieveComponent("group.different.enabled", JCheckBox.class).setSelected(group_different_enabled); + toggleDifferentSettingsForGroup(group_different_enabled); + } + + public void storeValues() { + RoarProperties props = RoarProperties.getInstance(); + props.setShowingPopups(_enabledCheckbox.isSelected()); + props.setDisplayType(this.getDisplayType()); + props.setMaximumPopups(this.getAmount()); + + props.setDuration(this.getDuration()); + props.setDuration("group.duration", getIntFromTextField("group.duration")); + + props.setBackgroundColor(getColor(ColorTypes.BACKGROUNDCOLOR)); + props.setColor(RoarProperties.BACKGROUNDCOLOR_GROUP, getColor(ColorTypes.BACKGROUNDCOLOR_GROUP)); + props.setTextColor(getColor(ColorTypes.TEXTCOLOR)); + props.setColor(RoarProperties.TEXTCOLOR_GROUP, getColor(ColorTypes.TEXTCOLOR_GROUP)); + props.setHeaderColor(getColor(ColorTypes.HEADERCOLOR)); + props.setColor(RoarProperties.HEADERCOLOR_GROUP, getColor(ColorTypes.HEADERCOLOR_GROUP)); + + props.setBoolean("roar.disable.single", retrieveComponent("roar.disable.single", JCheckBox.class).isSelected()); + props.setBoolean("group.different.enabled", retrieveComponent("group.different.enabled", JCheckBox.class).isSelected()); + props.setBoolean("group.disable", retrieveComponent("group.disable", JCheckBox.class).isSelected()); + + props.save(); + } + + @SuppressWarnings("unchecked") + private K retrieveComponent(String key, Class classs) { + return (K) _components.get(key); + } + + private int getIntFromTextField(String key) { + JTextField field = retrieveComponent(key, JTextField.class); + + try { + return Integer.parseInt(field.getText()); + } catch (Exception e) { + return 3000; + } + } + + /** + * returns the popup duration + * + * @return int + */ + public int getDuration() { + try { + return Integer.parseInt(_duration.getText()); + } catch (Exception e) { + return 3000; + } + } + + /** + * Amount of Windows on Screen + * + * @return int + */ + public int getAmount() { + return Integer.parseInt(_amount.getText()); + } + + public Color getColor(ColorTypes type) { + return _colormap.get(type); + } + + public void setColor(ColorTypes type, Color color) { + _colormap.put(type, color); + } + + private void colorListMouseClicked(MouseEvent e) { + if (e.getSource() == _singleColorlist) { + ColorTypes key = _singleColorlist.getSelectedValue(); + _singleColorpicker.setColor(_colormap.get(key)); + } + } + + public void setDisplayType(String t) { + for (RoarDisplayType type : RoarProperties.getInstance().getDisplayTypes()) { + if (type.getName().equals(t)) { + _typelist.setSelectedItem(type.getLocalizedName()); + updateWarningLabel(type.getWarningMessage()); + return; + } + } + } + + + public void updateWarningLabel(String text) { + retrieveComponent("label.warning", JLabel.class).setText("" + text + ""); + } + + + public RoarDisplayType getDisplayTypeClass() { + String o = (String) _typelist.getSelectedItem(); + + for (RoarDisplayType type : RoarProperties.getInstance().getDisplayTypes()) { + if (type.getLocalizedName().equals(o)) { + return type; + } + } + return RoarProperties.getInstance().getDisplayTypes().get(0); + // topright is default + } + + public String getDisplayType() { + return getDisplayTypeClass().getName(); + } + + private void toggleDifferentSettingsForGroup(boolean isSelected) { + + DefaultListModel model = (DefaultListModel) _singleColorlist.getModel(); + JTextField duration = retrieveComponent("group.duration", JTextField.class); + + if (isSelected) { + if (!model.contains(ColorTypes.BACKGROUNDCOLOR_GROUP)) { + model.addElement(ColorTypes.BACKGROUNDCOLOR_GROUP); + model.addElement(ColorTypes.HEADERCOLOR_GROUP); + model.addElement(ColorTypes.TEXTCOLOR_GROUP); + } + duration.setEnabled(true); + } else { + model.removeElement(ColorTypes.BACKGROUNDCOLOR_GROUP); + model.removeElement(ColorTypes.HEADERCOLOR_GROUP); + model.removeElement(ColorTypes.TEXTCOLOR_GROUP); + duration.setEnabled(false); + duration.setText(_duration.getText()); + } + } + + private void stateChangedSingleColorPicker(ChangeEvent e) { + if (e.getSource() instanceof JSlider) { + _colormap.put( _singleColorlist.getSelectedValue(), _singleColorpicker.getColor()); + } + } + + public enum ColorTypes { + BACKGROUNDCOLOR(RoarResources.getString("roar.background")), + HEADERCOLOR(RoarResources.getString("roar.header")), + TEXTCOLOR(RoarResources.getString("roar.text")), + + BACKGROUNDCOLOR_GROUP(RoarResources.getString("roar.background.group")), + HEADERCOLOR_GROUP(RoarResources.getString("roar.header.group")), + TEXTCOLOR_GROUP(RoarResources.getString("roar.text.group")); + + + private final String string; + + ColorTypes(String c) { + string = c; + } + + public String toString() { + return string; + } + + } + +} diff --git a/plugins/roar/src/main/java/org/jivesoftware/spark/roar/gui/SparkToaster.java b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/gui/SparkToaster.java new file mode 100644 index 000000000..f8f475eef --- /dev/null +++ b/plugins/roar/src/main/java/org/jivesoftware/spark/roar/gui/SparkToaster.java @@ -0,0 +1,678 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.roar.gui; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.EventQueue; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsEnvironment; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Image; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.geom.AffineTransform; + +import javax.swing.*; +import javax.swing.border.Border; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.util.ImageCombiner; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.settings.Sizes; + +/** + * Class to show tosters in multiplatform + * + * @author daniele piras + */ +public class SparkToaster { + + /** + * The default Hand cursor. + */ + public static final Cursor HAND_CURSOR = new Cursor(Cursor.HAND_CURSOR); + + /** + * The default Text Cursor. + */ + public static final Cursor DEFAULT_CURSOR = new Cursor( + Cursor.DEFAULT_CURSOR); + + // Width of the toster + private int toasterWidth = 200; + + // Height of the toster + private int toasterHeight = 150; + + // Step for the toaster + private int step = 20; + + // Step time + private int stepTime = 20; + + // Show time + private int displayTime = 3000; + + // Current number of toaster... + private int currentNumberOfToaster = 0; + + // Last opened toaster + private int maxToaster = 0; + + // Font used to display message + private Font font; + + // Color for border + private Color borderColor; + + // Color for toaster + private Color toasterColor; + + // Set message color + private Color messageColor; + + // Set the margin + private int margin; + + // Flag that indicate if use alwaysOnTop or not. + // method always on top start only SINCE JDK 5 ! + private final boolean useAlwaysOnTop; + + private String title; + + private Border border; + + private Action customAction; + + private Window window; + + private final JPanel mainPanel = new JPanel(); + + private TitleLabel titleLabel; + + private boolean hideable = true; + + /** + * Constructor to initialized toaster component... + */ + public SparkToaster() { + // Set default font... + font = new Font("Dialog", Font.PLAIN, 11); + + // Border color + borderColor = new Color(245, 153, 15); + toasterColor = Color.WHITE; + messageColor = Color.BLACK; + useAlwaysOnTop = true; + } + + /** + * Class that rappresent a single toaster + * + * @author daniele piras + */ + class SingleToaster extends javax.swing.JWindow { + private static final long serialVersionUID = 1L; + + // Label to store Icon + + // Text area for the message + private final JTextArea message = new JTextArea(); + + /** + * Simple costructor that initialized components... + */ + public SingleToaster() { + initComponents(); + } + + /** + * Function to initialized components + */ + private void initComponents() { + message.setFont(getToasterMessageFont()); + + mainPanel.setBackground(Color.white); + message.setOpaque(false); + mainPanel.setLayout(new GridBagLayout()); + message.setMargin(new Insets(2, 2, 2, 2)); + message.setLineWrap(true); + message.setWrapStyleWord(true); + + message.setForeground(getMessageColor()); + titleLabel = new TitleLabel(getTitle(), true); + titleLabel.setForeground(new Color(87, 166, 211)); + titleLabel.setFont(new Font("Dialog", Font.BOLD, 13)); + + mainPanel.add(titleLabel, + new GridBagConstraints(0, 0, 3, 1, 1.0, 0.0, + GridBagConstraints.NORTHWEST, + GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, + 0), 0, 0)); + + titleLabel.getCloseButton().addActionListener( e -> { + setVisible(false); + dispose(); + } ); + + if (border != null) { + mainPanel.setBorder(border); + } + + message.setForeground(Color.BLACK); + + message.setOpaque(false); + + getContentPane().add(mainPanel); + + mainPanel.addMouseListener(new PaneMouseListener()); + message.addMouseListener(new PaneMouseListener()); + + pack(); + setSize(toasterWidth, toasterHeight); + mainPanel + .setBorder(BorderFactory.createLineBorder(Color.lightGray)); + } + + /** + * Start toaster animation... + */ + public void animate() { + (new Animation(this)).start(); + } + + private class PaneMouseListener extends MouseAdapter { + + public void mouseClicked(MouseEvent e) { + if (customAction != null) { + customAction.actionPerformed(null); + } + + if (hideable) { + setVisible(false); + dispose(); + } + } + + public void mouseEntered(MouseEvent e) { + message.setCursor(HAND_CURSOR); + setCursor(HAND_CURSOR); + } + + public void mouseExited(MouseEvent e) { + message.setCursor(DEFAULT_CURSOR); + setCursor(DEFAULT_CURSOR); + } + } + } + + /** + * Class that manage the animation + */ + class Animation extends Thread { + private final SingleToaster toaster; + + public Animation(SingleToaster toaster) { + this.toaster = toaster; + } + + /** + * Animate vertically the toaster. The toaster could be moved from + * bottom to upper or to upper to bottom + * + * @param posx + * X position for toaster. + * @param fromY + * Y from position + * @param toY + * Y to position + * @throws InterruptedException + * if animation is interrupted + */ + protected void animateVertically(int posx, int fromY, int toY) + throws InterruptedException { + + toaster.setLocation(posx, fromY); + if (toY < fromY) { + for (int i = fromY; i > toY; i -= step) { + toaster.setLocation(posx, i); + Thread.sleep(stepTime); + } + } else { + for (int i = fromY; i < toY; i += step) { + toaster.setLocation(posx, i); + Thread.sleep(stepTime); + } + } + toaster.setLocation(posx, toY); + toaster.invalidate(); + toaster.validate(); + toaster.repaint(); + } + + public void run() { + try { + boolean animateFromBottom = true; + GraphicsEnvironment ge = GraphicsEnvironment + .getLocalGraphicsEnvironment(); + Rectangle screenRect = ge.getMaximumWindowBounds(); + + int screenHeight = screenRect.height; + + int startYPosition; + int stopYPosition; + + if (screenRect.y > 0) { + animateFromBottom = false; // Animate from top! + } + + int maxToasterInSceen = screenHeight / toasterHeight; + + int posx = screenRect.width - toasterWidth - 1; + + toaster.setLocation(posx, screenHeight); + try { + EventQueue.invokeAndWait( () -> toaster.setVisible(true) ); + } catch (Exception e) { + Log.error(e); + } + if (useAlwaysOnTop) { + toaster.setAlwaysOnTop(true); + } + + if (animateFromBottom) { + startYPosition = screenHeight; + stopYPosition = startYPosition - toasterHeight - 1; + if (currentNumberOfToaster > 0) { + stopYPosition = stopYPosition + - (maxToaster % maxToasterInSceen * toasterHeight); + } else { + maxToaster = 0; + } + } else { + startYPosition = screenRect.y - toasterHeight; + stopYPosition = screenRect.y; + + if (currentNumberOfToaster > 0) { + stopYPosition = stopYPosition + + (maxToaster % maxToasterInSceen * toasterHeight); + } else { + maxToaster = 0; + } + } + + currentNumberOfToaster++; + maxToaster++; + + animateVertically(posx, startYPosition, stopYPosition); + Thread.sleep(displayTime); + animateVertically(posx, stopYPosition, startYPosition); + + currentNumberOfToaster--; + toaster.setVisible(false); + toaster.dispose(); + } catch (Exception e) { + Log.error(e); + } + } + } + + /** + * Show a toaster with the specified message and the associated icon. + * + * @param icon + * Icon to show in toaster popup. + * @param msg + * Message to show in toaster popup. + */ + public void showToaster(Icon icon, String msg) { + SingleToaster singleToaster = new SingleToaster(); + final JScrollPane pane = new JScrollPane(singleToaster.message); + pane.setOpaque(false); + pane.setBorder(BorderFactory.createEmptyBorder()); + pane.getViewport().setBackground(Color.white); + mainPanel.add(pane, new GridBagConstraints(1, 2, 3, 1, 1.0, 1.0, + GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, + 5, 2, 5), 0, 0)); + + if (icon != null) { + titleLabel.setIcon(icon); + } + if (ModelUtil.hasLength(msg) && msg.startsWith("/me ")) { + msg = msg.replaceFirst("/me", getTitle()); + singleToaster.message.setForeground(Color.MAGENTA); + } + singleToaster.message.setText(msg); + singleToaster.message.setCaretPosition(0); + singleToaster.animate(); + window = singleToaster; + } + + /** + * Show a toaster with the specified message and the associated icon. + * + * @param title + * Title to use in toaster popup + * @param comp + * Component to add to toaster popup + */ + public void showToaster(final String title, final Component comp) { + SingleToaster singleToaster = new SingleToaster(); + mainPanel.add(comp, new GridBagConstraints(1, 2, 3, 1, 1.0, 1.0, + GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, + 0, 0, 0), 0, 0)); + + titleLabel.setTitle(title); + singleToaster.animate(); + window = singleToaster; + } + + public void showToaster(Icon icon) { + SingleToaster singleToaster = new SingleToaster(); + if (icon != null) { + titleLabel.setIcon(icon); + } + singleToaster.animate(); + window = singleToaster; + } + + public void showToaster() { + SingleToaster singleToaster = new SingleToaster(); + singleToaster.animate(); + window = singleToaster; + } + + /** + * Show a toaster with the specified message. + * + * @param msg + * Message to display. + */ + public void showToaster(String msg) { + showToaster(null, msg); + } + + /** + * @return Returns the font + */ + public Font getToasterMessageFont() { + return font; + } + + /** + * Set the font for the message + * + * @param f + * Font to set on toaster messages. + */ + public void setToasterMessageFont(Font f) { + font = f; + } + + /** + * @return Returns the borderColor. + */ + public Color getBorderColor() { + return borderColor; + } + + /** + * @param borderColor + * The borderColor to set. + */ + public void setBorderColor(Color borderColor) { + this.borderColor = borderColor; + } + + /** + * @return Returns the displayTime. + */ + public int getDisplayTime() { + return displayTime; + } + + /** + * @param displayTime + * The displayTime to set. + */ + public void setDisplayTime(int displayTime) { + this.displayTime = displayTime; + } + + /** + * @return Returns the margin. + */ + public int getMargin() { + return margin; + } + + /** + * @param margin + * The margin to set. + */ + public void setMargin(int margin) { + this.margin = margin; + } + + /** + * @return Returns the messageColor. + */ + public Color getMessageColor() { + return messageColor; + } + + /** + * @param messageColor + * The messageColor to set. + */ + public void setMessageColor(Color messageColor) { + this.messageColor = messageColor; + } + + /** + * @return Returns the step. + */ + public int getStep() { + return step; + } + + /** + * @param step + * The step to set. + */ + public void setStep(int step) { + this.step = step; + } + + /** + * @return Returns the stepTime. + */ + public int getStepTime() { + return stepTime; + } + + /** + * @param stepTime + * The stepTime to set. + */ + public void setStepTime(int stepTime) { + this.stepTime = stepTime; + } + + /** + * @return Returns the toasterColor. + */ + public Color getToasterColor() { + return toasterColor; + } + + /** + * @param toasterColor + * The toasterColor to set. + */ + public void setToasterColor(Color toasterColor) { + this.toasterColor = toasterColor; + } + + /** + * @return Returns the toasterHeight. + */ + public int getToasterHeight() { + return toasterHeight; + } + + /** + * @param toasterHeight + * The toasterHeight to set. + */ + public void setToasterHeight(int toasterHeight) { + this.toasterHeight = toasterHeight; + } + + /** + * @return Returns the toasterWidth. + */ + public int getToasterWidth() { + return toasterWidth; + } + + /** + * @param toasterWidth + * The toasterWidth to set. + */ + public void setToasterWidth(int toasterWidth) { + this.toasterWidth = toasterWidth; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Border getBorder() { + return border; + } + + public void setBorder(Border border) { + this.border = border; + } + + public void setCustomAction(Action action) { + this.customAction = action; + } + + public void setComponent(Component comp) { + mainPanel.add(comp, new GridBagConstraints(1, 2, 3, 1, 1.0, 1.0, + GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, + 5, 2, 5), 0, 0)); + } + + public void close() { + if (window != null) { + window.dispose(); + } + } + + public Window getWindow() { + return window; + } + + public void hideTitle() { + titleLabel.setVisible(false); + } + + static class TitleLabel extends JPanel { + private static final long serialVersionUID = -5163519932953987400L; + private final JLabel label; + private final RolloverButton closeButton; + + public TitleLabel(String text, final boolean showCloseIcon) { + setLayout(new GridBagLayout()); + label = new JLabel(text); + label.setFont(new Font("Dialog", Font.BOLD, 11)); + label.setHorizontalTextPosition(JLabel.LEFT); + label.setHorizontalAlignment(JLabel.LEFT); + + add(label, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, + GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, + new Insets(5, 5, 5, 5), 0, 0)); + + closeButton = new RolloverButton( + SparkRes.getImageIcon(SparkRes.Icon.CLOSE_IMAGE)); + if (showCloseIcon) { + add(closeButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.EAST, GridBagConstraints.NONE, + new Insets(5, 5, 5, 5), 0, 0)); + } + + setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, + Color.lightGray)); + } + + public void setIcon(Icon icon) { + try { + if (icon.getIconHeight() > Sizes.Toaster.ICON || icon.getIconWidth() > Sizes.Toaster.ICON) { + Image image = ImageCombiner.iconToImage(icon); + label.setIcon(new ImageIcon(image.getScaledInstance(-1, Sizes.Toaster.ICON, Image.SCALE_SMOOTH))); + } else{ + label.setIcon(icon); + } + } catch (Exception e) { + Log.warning("Unable to set icon in toaster", e); + } + } + + public RolloverButton getCloseButton() { + return closeButton; + } + + public void setTitle(String title) { + label.setText(title); + } + + public void paintComponent(Graphics g) { + final Image backgroundImage = Default.getImageIcon( + Default.TOP_BOTTOM_BACKGROUND_IMAGE).getImage(); + double scaleX = getWidth() + / (double) backgroundImage.getWidth(null); + double scaleY = getHeight() + / (double) backgroundImage.getHeight(null); + AffineTransform xform = AffineTransform.getScaleInstance(scaleX, + scaleY); + ((Graphics2D) g).drawImage(backgroundImage, xform, this); + } + } + + public void setHidable(boolean hideable) { + this.hideable = hideable; + } + + +} diff --git a/src/plugins/roar/src/lib/NsUserNotificationsBridge.dylib b/plugins/roar/src/main/native/NsUserNotificationsBridge.dylib similarity index 100% rename from src/plugins/roar/src/lib/NsUserNotificationsBridge.dylib rename to plugins/roar/src/main/native/NsUserNotificationsBridge.dylib diff --git a/plugins/roar/src/main/plugin-metadata/plugin.xml b/plugins/roar/src/main/plugin-metadata/plugin.xml new file mode 100644 index 000000000..6cc793c98 --- /dev/null +++ b/plugins/roar/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,12 @@ + + ${project.name} + ${project.version} + ${project.description} + org.jivesoftware.spark.roar.Roar + Wolf Posdorfer + https://IgniteRealtime.org + support@IgniteRealtime.org + 3.1.0 + Windows,Linux,Mac + 11 + diff --git a/plugins/roar/src/main/resources/background2.png b/plugins/roar/src/main/resources/background2.png new file mode 100644 index 000000000..e4c4ee954 Binary files /dev/null and b/plugins/roar/src/main/resources/background2.png differ diff --git a/src/plugins/roar/src/resources/i18n/roar_i18n.properties b/plugins/roar/src/main/resources/i18n/roar_i18n.properties similarity index 78% rename from src/plugins/roar/src/resources/i18n/roar_i18n.properties rename to plugins/roar/src/main/resources/i18n/roar_i18n.properties index 94db425b6..9f2ee9f9d 100644 --- a/src/plugins/roar/src/resources/i18n/roar_i18n.properties +++ b/plugins/roar/src/main/resources/i18n/roar_i18n.properties @@ -1,31 +1,24 @@ - # Roar language file roar.settings = Roar Settings roar.enabled = Popups enabled roar.duration = Duration in ms (0 = infinite): roar.amount = Maximum popups on screen (0 = infinite): -roar.location = Change popup starting location (requires restart) +roar.location = Change popup starting location roar.display.topright = Top Right roar.display.bottomright = Bottom Right roar.background = Background color roar.background.group = Background color multi-user -roar.background.keyword = Background color keyword roar.header = Header color roar.header.group = Header color multi-user -roar.header.keyword = Header color keyword roar.text = Text color roar.text.group = Text color multi-user -roar.text.keyword = Text color keyword roar.single = Single-User roar.single.disable = Disable Roar for single-user chats roar.group = Multi-User roar.group.different = Use different settings for multi-user chats roar.group.disable = Disable Roar for multi-user chats -roar.keyword = Keyword Matching -roar.keyword.different = Use different settings for keyword matching -roar.keyword.keyword = Keywords (comma separated) roar.display.system = Operating System Notification @@ -33,4 +26,4 @@ roar.warning.topright = Custom Roar notification style. Fully customizable. roar.warning.bottomright = Custom Roar notification style. Fully customizable. roar.warning.toaster = Spark notification style. Colors are not customizable. roar.warning.system = System-dependent notification. Colors and duration are not customizable. -roar.warning.system.mac = Uses the Notification-Center (OSX 10.8 and above).
      Colors and duration are not customizable.
      See Mac-Systemsettings -> Notifications for more settings. \ No newline at end of file +roar.warning.system.mac = Uses the Notification-Center (OSX 10.8 and above).
      Colors and duration are not customizable.
      See Mac-Systemsettings -> Notifications for more settings. diff --git a/plugins/roar/src/main/resources/i18n/roar_i18n_de.properties b/plugins/roar/src/main/resources/i18n/roar_i18n_de.properties new file mode 100644 index 000000000..7a038721b --- /dev/null +++ b/plugins/roar/src/main/resources/i18n/roar_i18n_de.properties @@ -0,0 +1,29 @@ +# Roar language file + +roar.settings = Roar Einstellungen +roar.enabled = Popups aktiv +roar.duration = Dauer in ms (0 = unbegrenzt): +roar.amount = Maximale Anzahl von Popups (0 = unbegrenzt): +roar.location = Popupecke auswählen +roar.display.topright = oben rechts +roar.display.bottomright = unten rechts +roar.background = Hintergrundfarbe +roar.background.group = Hintergrundfarbe Gruppenchat +roar.header = Überschrift +roar.header.group = Überschrift Gruppenchat +roar.text = Textfarbe +roar.text.group = Textfarbe Gruppenchat + +roar.single = Einzelchat +roar.single.disable = Roar für Einzelchats deaktivieren +roar.group = Gruppenchat +roar.group.different = Andere Einstellungen für Gruppenchats verwenden +roar.group.disable = Roar für Gruppenchats deaktivieren + +roar.display.system = Betriebssystem-Mitteilung + +roar.warning.topright = Roar-spezifische Popups. Flexibel anpassbar. +roar.warning.bottomright = Roar-spezifische Popups. Flexibel anpassbar. +roar.warning.toaster = Spark Toaster Popups. Farben sind nicht anpassbar. +roar.warning.system = Betriebssystemabhängige Popups. Farben und Dauer sind nicht anpassbar. +roar.warning.system.mac = Benutzt das Mitteilungs-Center (OSX 10.8 und neuer).
      Farben und Dauer sind nicht anpassbar.
      Weitere Einstellungen unter: Mac-Systemeinstellungen -> Mitteilungen. diff --git a/plugins/roar/src/main/resources/i18n/roar_i18n_fr.properties b/plugins/roar/src/main/resources/i18n/roar_i18n_fr.properties new file mode 100644 index 000000000..a8ac5e162 --- /dev/null +++ b/plugins/roar/src/main/resources/i18n/roar_i18n_fr.properties @@ -0,0 +1,29 @@ +# Roar language file + +roar.settings = Paramètres Roar +roar.enabled = Popups activés +roar.duration = Durée en ms (0 = infini): +roar.amount = Popups maximals affichés à l'écran (0 = infini): +roar.location = Changer l'emplacement de départ du popup +roar.display.topright = En haut à droite +roar.display.bottomright = En bas à droite +roar.background = Couleur de fond +roar.background.group = Couleur de fond multi-utilisateurs +roar.header = Couleur de l'entête +roar.header.group = Couleur d'en-tête multi-utilisateurs +roar.text = Couleur du texte +roar.text.group = Couleur du texte multi-utilisateurs + +roar.single = Utilisateur unique +roar.single.disable = Désactiver Roar pour les discussions mono-utilisateur +roar.group = Multi-utilisateur +roar.group.different = Utiliser différents paramètres pour les chats multi-utilisateurs +roar.group.disable = Désactiver Roar pour les discussions multi-utilisateurs + +roar.display.system = Notification du système d'exploitation + +roar.warning.topright = Style de notification Roar personnalisé. Entièrement personnalisable. +roar.warning.bottomright = Style de notification Roar personnalisé. Entièrement personnalisable. +roar.warning.toaster = Style de notification d'étincelle. Les couleurs ne sont pas personnalisables. +roar.warning.system = Notification dépendante du système. Les couleurs et la durée ne sont pas personnalisables. +roar.warning.system.mac = Utilise le Notification-Center (OSX 10.8 et supérieur).
      Les couleurs et la durée ne sont pas personnalisables.
      Voir Mac-Systemsettings -> Notifications pour plus de paramètres. diff --git a/plugins/roar/src/main/resources/i18n/roar_i18n_lt.properties b/plugins/roar/src/main/resources/i18n/roar_i18n_lt.properties new file mode 100644 index 000000000..4a55bfa03 --- /dev/null +++ b/plugins/roar/src/main/resources/i18n/roar_i18n_lt.properties @@ -0,0 +1,29 @@ +# Roar language file + +roar.settings = Roar Nustatymai +roar.enabled = Ä®jungti iššokanÄius langus +roar.duration = Rodymo trukmÄ— (ms) (0 = neribojama): +roar.amount = Maksimalus langų skaiÄius ekrane (0 = neribojama): +roar.location = Pakeisti langų atsiradymo pradžios vietÄ… +roar.display.topright = VirÅ¡uje deÅ¡inÄ—je +roar.display.bottomright = ApaÄioje deÅ¡inÄ—je +roar.background = Fono spalva +roar.background.group = Fono spalva grupiniam pokalbiui +roar.header = AntraÅ¡tÄ—s spalva +roar.header.group = AntraÅ¡tÄ—s spalva grupiniam pokalbiui +roar.text = Teksto spalva +roar.text.group = Teksto spalva grupiniam pokalbiui + +roar.single = Paprastas pokalbis +roar.single.disable = IÅ¡jungti Roar paprastuose pokalbiuose (su vienu adresatu) +roar.group = Grupinis pokalbis +roar.group.different = Naudoti skirtingus nustatymus grupiniuose pokalbiuose +roar.group.disable = iÅ¡jungti Roar grupiniuose pokalbiuose + +roar.display.system = OperacinÄ—s sistemos praneÅ¡imas + +roar.warning.topright = Roar praneÅ¡imo stilius. Viskas koreguojama. +roar.warning.bottomright = Roar praneÅ¡imo stilius. Viskas koreguojama. +roar.warning.toaster = Spark praneÅ¡imo stilius. Spalvų negalima pakeisti. +roar.warning.system = Sisteminis praneÅ¡imo stilius. Spalvų ir rodymo trukmÄ—s negalima pakeisti. +roar.warning.system.mac = Naudojamas Notification-Center (OSX 10.8 ir naujesnÄ—s).
      Spalvų ir rodymo trukmės negalima pakeisti.
      Papildomų nustatymų ieškoti Mac-Systemsettings -> Notifications. diff --git a/plugins/roar/src/main/resources/i18n/roar_i18n_pl.properties b/plugins/roar/src/main/resources/i18n/roar_i18n_pl.properties new file mode 100644 index 000000000..82bb4b641 --- /dev/null +++ b/plugins/roar/src/main/resources/i18n/roar_i18n_pl.properties @@ -0,0 +1,29 @@ +# Roar language file + +roar.settings = Ustawienia ROAR +roar.enabled = Włącz wyskakujące powiadomienia +roar.duration = Czas trwania w ms (0 = bez limitu): +roar.amount = Maksymalna ilość powiadomień na ekranie (0 = bez limitu): +roar.location = Zmiana miejsca wyskakujących powiadomień +roar.display.topright = Górna prawa +roar.display.bottomright = Dolna prawa +roar.background = Kolor tła +roar.background.group = Kolor tła multi użytkownika +roar.header = Kolor nagłówka +roar.header.group = Kolor nagłówka multi użytkownika +roar.text = Kolor tekstu +roar.text.group = Kolor tekstu multi użytkownika + +roar.single = Pojedynczy Użytkownik +roar.single.disable = Wyłącz Roar dla czatów pojedynczego użytkownika +roar.group = Multi Użytkownik +roar.group.different = Używaj różnych ustawień dla czatów multi użytkownika +roar.group.disable = Wyłącz Roar dla czatów multi użytkownika + +roar.display.system = Powiadomienia systemu operacyjnego + +roar.warning.topright = Niestandardowe style powiadamiania. W pełni konfigurowalne. +roar.warning.bottomright = Niestandardowe style powiadamiania. W pełni konfigurowalne. +roar.warning.toaster = Style powiadamiania Sparka. Kolory nie są konfigurowalne. +roar.warning.system = Powiadamiania zależne od systemu. Kolory i czas trwania nie są konfigurowalne. +roar.warning.system.mac = Używanie Centrum Powiadamiania (OSX 10.8 i powyżej).
      Kolory i czas trwania nie sÄ… konfigurowalne.
      Zobacz ustawienia systemu Mac -> Notifications for more settings. diff --git a/plugins/roar/src/main/resources/i18n/roar_i18n_pt_PT.properties b/plugins/roar/src/main/resources/i18n/roar_i18n_pt_PT.properties new file mode 100644 index 000000000..56e76ec3b --- /dev/null +++ b/plugins/roar/src/main/resources/i18n/roar_i18n_pt_PT.properties @@ -0,0 +1,29 @@ +# Roar language file + +roar.settings = Definições de Roar +roar.enabled = Popups ativados +roar.duration = Duração em ms (0 = infinito): +roar.amount = Máximo de pop-ups no ecrã (0 = infinito): +roar.location = Alterar localização de início do pop-up +roar.display.topright = Topo Direito +roar.display.bottomright = Inferior Direito +roar.background = Cor de fundo +roar.background.group = Cor de fundo multi-utilizador +roar.header = Cor do cabeçalho +roar.header.group = Cor do cabeçalho multi-utilizador +roar.text = Cor do texto +roar.text.group = Cor do texto multi-utilizador + +roar.single = Utilizador Único +roar.single.disable = Desativar Roar para chats de utilizador único +roar.group = Multi-Utilizador +roar.group.different = Utilize configurações diferentes para chats multi-utilizador +roar.group.disable = Desativar Roar para chats multi-utilizador + +roar.display.system = Notificação do Sistema Operativo + +roar.warning.topright = Estilo de notificação personalizado Roar. Totalmente personalizável. +roar.warning.bottomright = Estilo de notificação personalizado Roar. Totalmente personalizável. +roar.warning.toaster = Estilo de notificação do Spark. As cores não são personalizáveis. +roar.warning.system = Notificação dependente do sistema. As cores e a duração não são personalizáveis. +roar.warning.system.mac = Utiliza o Centro de Notificações (OSX 10.8 e superior).
      As cores e a duração não são personalizáveis.
      Consulte as Definições do Sistema Mac -> Notificações para mais configurações. diff --git a/plugins/roar/src/main/resources/i18n/roar_i18n_ru_RU.properties b/plugins/roar/src/main/resources/i18n/roar_i18n_ru_RU.properties new file mode 100644 index 000000000..40c2604c4 --- /dev/null +++ b/plugins/roar/src/main/resources/i18n/roar_i18n_ru_RU.properties @@ -0,0 +1,29 @@ +# Roar language file + +roar.settings = ÐаÑтройки Roar +roar.enabled = Ð’Ñплывающие окна включены +roar.duration = ПродолжительноÑть в Ð¼Ñ (0 = беÑконечно): +roar.amount = МакÑимальное кол-во вÑп. окон на Ñкране (0 = беÑконечно): +roar.location = МеÑтоположение вÑп.окна +roar.display.topright = Правый верхнем +roar.display.bottomright = Ðижний правый +roar.background = Фоновый цвет +roar.background.group = Цвет фона Ð´Ð»Ñ Ð¼Ð½Ð¾Ð³Ð¾Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒÑких чатов +roar.header = Цвет заголовка +roar.header.group = Цвет заголовка Ð´Ð»Ñ Ð¼Ð½Ð¾Ð³Ð¾Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒÑких чатов +roar.text = Цвет текÑта +roar.text.group = Цвет текÑта Ð´Ð»Ñ Ð¼Ð½Ð¾Ð³Ð¾Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒÑких чатов + +roar.single = Один пользователь +roar.single.disable = Отключить Roar Ð´Ð»Ñ Ð¾Ð´Ð½Ð¾Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒÑких чатов +roar.group = МногопользовательÑкий чат +roar.group.different = ИÑпользовать разные наÑтройки Ð´Ð»Ñ Ð¼Ð½Ð¾Ð³Ð¾Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒÑких чатов +roar.group.disable = Отключить Roar Ð´Ð»Ñ Ð¼Ð½Ð¾Ð³Ð¾Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒÑких чатов + +roar.display.system = Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¾Ð¹ ÑиÑтемы + +roar.warning.topright = ПользовательÑкий Ñтиль ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Roar +roar.warning.bottomright = ПользовательÑкий Ñтиль ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Roar +roar.warning.toaster = Стиль ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Spark. Цвета ÐЕ наÑтраиваютÑÑ. +roar.warning.system = Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ñ‚ операционной ÑиÑтемы, цвета и продолжительноÑть ÐЕ наÑтраиваютÑÑ. +roar.warning.system.mac = ИÑпользует Центр уведомлений (OS X 10.8 и выше).
      Цвета и продолжительноÑть ÐЕ наÑтраиваютÑÑ.
      См. "СиÑтемные наÑтройки Mac" -> Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ñ… наÑтроек. diff --git a/plugins/roar/src/main/resources/i18n/roar_i18n_zh_CN.properties b/plugins/roar/src/main/resources/i18n/roar_i18n_zh_CN.properties new file mode 100644 index 000000000..2ed251157 --- /dev/null +++ b/plugins/roar/src/main/resources/i18n/roar_i18n_zh_CN.properties @@ -0,0 +1,29 @@ +# Roar language file + +roar.settings = 铃声设置 +roar.enabled = 弹窗已å¯ç”¨ +roar.duration = æŒç»­æ—¶é—´(毫秒)(0 = æ— é™): +roar.amount = å±å¹•上的最大弹窗数(0 = æ— é™): +roar.location = 更改弹窗起始ä½ç½® +roar.display.topright = å³ä¸Šè§’ +roar.display.bottomright = å³ä¸‹è§’ +roar.background = 背景颜色 +roar.background.group = 背景颜色多用户 +roar.header = 标题颜色 +roar.header.group = 标题颜色多用户 +roar.text = 文本颜色 +roar.text.group = 文本颜色多用户 + +roar.single = å•用户 +roar.single.disable = ç¦ç”¨å•用户èŠå¤©çš„铃声 +roar.group = 多用户 +roar.group.different = 对多用户èŠå¤©ä½¿ç”¨ä¸åŒçš„设置 +roar.group.disable = ç¦ç”¨å¤šç”¨æˆ·èŠå¤©çš„铃声 + +roar.display.system = æ“作系统通知 + +roar.warning.topright = 自定义铃声通知样å¼ï¼Œå¯å®Œå…¨è‡ªå®šä¹‰ã€‚ +roar.warning.bottomright = 自定义铃声通知样å¼ï¼Œå¯å®Œå…¨è‡ªå®šä¹‰ã€‚ +roar.warning.toaster = Spark 通知样å¼ï¼Œé¢œè‰²ä¸å¯è‡ªå®šä¹‰ã€‚ +roar.warning.system = 系统相关通知,颜色和æŒç»­æ—¶é—´ä¸å¯è‡ªå®šä¹‰ã€‚ +roar.warning.system.mac = 使用通知中心(OSX 10.8 åŠä»¥ä¸Šç‰ˆæœ¬ï¼‰ï¼Œ
      颜色和æŒç»­æ—¶é—´ä¸å¯è‡ªå®šä¹‰ã€‚
      请å‚阅 Mac 系统设置 ->;有关更多设置的通知。 diff --git a/plugins/roar/src/main/resources/i18n/roar_i18n_zh_TW.properties b/plugins/roar/src/main/resources/i18n/roar_i18n_zh_TW.properties new file mode 100644 index 000000000..4596109ce --- /dev/null +++ b/plugins/roar/src/main/resources/i18n/roar_i18n_zh_TW.properties @@ -0,0 +1,29 @@ +# Roar language file + +roar.settings = 便利貼設定 +roar.enabled = 啟動彈出便利貼 +roar.duration = 便利貼顯示時間為多少毫秒 (0 = ç„¡é™æ™‚): +roar.amount = ä¾¿åˆ©è²¼å½ˆå‡ºåœ¨èž¢å¹•ä¸Šçš„æœ€å¤§ç¯„åœ (0 = ç„¡é™æ™‚): +roar.location = 變更便利貼彈出ä½ç½® +roar.display.topright = å³ä¸Šæ–¹ +roar.display.bottomright = å³ä¸‹æ–¹ +roar.background = 便利貼背景é¡è‰² +roar.background.group = 背景é¡è‰²å¤šç”¨æˆ¶ +roar.header = 便利貼標題é¡è‰² +roar.header.group = 標題é¡è‰²å¤šç”¨æˆ¶ +roar.text = 便利貼訊æ¯é¡è‰² +roar.text.group = 文本é¡è‰²å¤šç”¨æˆ¶ + +roar.single = 單用戶 +roar.single.disable = 為單用戶èŠå¤©ç¦ç”¨ Roar +roar.group = 多用戶 +roar.group.different = å°å¤šç”¨æˆ¶èŠå¤©ä½¿ç”¨ä¸åŒçš„設置 +roar.group.disable = 為多用戶èŠå¤©ç¦ç”¨ Roar + +roar.display.system = æ“作系統通知 + +roar.warning.topright = 自定義 Roar 通知樣å¼ã€‚完全å¯å®šåˆ¶ã€‚ +roar.warning.bottomright = 自定義 Roar 通知樣å¼ã€‚完全å¯å®šåˆ¶ +roar.warning.toaster = Spark 通知樣å¼ã€‚é¡è‰²ä¸å¯è‡ªå®šç¾© +roar.warning.system = ä¾è³´æ–¼ç³»çµ±çš„通知。é¡è‰²å’ŒæŒçºŒæ™‚é–“ä¸å¯è‡ªå®šç¾© +roar.warning.system.mac = 使用通知中心(OSX 10.8 åŠæ›´é«˜ç‰ˆæœ¬ï¼‰ã€‚
      é¡è‰²å’ŒæŒçºŒæ™‚é–“ä¸å¯è‡ªå®šç¾©ã€‚
      è«‹åƒé–± Mac 系統設置 ->更多設置的通知。 diff --git a/src/plugins/roar/src/resources/roar-logo.png b/plugins/roar/src/main/resources/roar-logo.png similarity index 100% rename from src/plugins/roar/src/resources/roar-logo.png rename to plugins/roar/src/main/resources/roar-logo.png diff --git a/plugins/roar/src/main/resources/roar.png b/plugins/roar/src/main/resources/roar.png new file mode 100644 index 000000000..900c0ff7a Binary files /dev/null and b/plugins/roar/src/main/resources/roar.png differ diff --git a/plugins/sip/build/build.xml b/plugins/sip/build/build.xml new file mode 100644 index 000000000..431f0c2bf --- /dev/null +++ b/plugins/sip/build/build.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/sip/build/lib/jain-sdp.jar b/plugins/sip/build/lib/jain-sdp.jar similarity index 100% rename from src/plugins/sip/build/lib/jain-sdp.jar rename to plugins/sip/build/lib/jain-sdp.jar diff --git a/src/plugins/sip/build/lib/jain-sip-api.jar b/plugins/sip/build/lib/jain-sip-api.jar similarity index 100% rename from src/plugins/sip/build/lib/jain-sip-api.jar rename to plugins/sip/build/lib/jain-sip-api.jar diff --git a/src/plugins/sip/build/lib/jain-sip-ri.jar b/plugins/sip/build/lib/jain-sip-ri.jar similarity index 100% rename from src/plugins/sip/build/lib/jain-sip-ri.jar rename to plugins/sip/build/lib/jain-sip-ri.jar diff --git a/src/plugins/sip/build/lib/jain-sip-sdp.jar b/plugins/sip/build/lib/jain-sip-sdp.jar similarity index 100% rename from src/plugins/sip/build/lib/jain-sip-sdp.jar rename to plugins/sip/build/lib/jain-sip-sdp.jar diff --git a/src/plugins/sip/build/lib/version.txt b/plugins/sip/build/lib/version.txt similarity index 100% rename from src/plugins/sip/build/lib/version.txt rename to plugins/sip/build/lib/version.txt diff --git a/plugins/sip/pom.xml b/plugins/sip/pom.xml new file mode 100644 index 000000000..b549941be --- /dev/null +++ b/plugins/sip/pom.xml @@ -0,0 +1,35 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + sip + 1.4.0 + + Phone Client + Adds SIP Softphone functionality to Spark. + + + + Thiago Camargo + + Author + + + + + + + javax.sip + jain-sip-ri + 1.2.324 + + + + diff --git a/src/plugins/sip/src/java/net/java/sipmack/common/AlertManager.java b/plugins/sip/src/main/java/net/java/sipmack/common/AlertManager.java similarity index 97% rename from src/plugins/sip/src/java/net/java/sipmack/common/AlertManager.java rename to plugins/sip/src/main/java/net/java/sipmack/common/AlertManager.java index b8c9ce043..41fe99b15 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/common/AlertManager.java +++ b/plugins/sip/src/main/java/net/java/sipmack/common/AlertManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/common/DialSoundManager.java b/plugins/sip/src/main/java/net/java/sipmack/common/DialSoundManager.java similarity index 98% rename from src/plugins/sip/src/java/net/java/sipmack/common/DialSoundManager.java rename to plugins/sip/src/main/java/net/java/sipmack/common/DialSoundManager.java index 1d3f74ee6..2eaa3694c 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/common/DialSoundManager.java +++ b/plugins/sip/src/main/java/net/java/sipmack/common/DialSoundManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/plugins/sip/src/main/java/net/java/sipmack/common/Log.java b/plugins/sip/src/main/java/net/java/sipmack/common/Log.java new file mode 100644 index 000000000..78080b349 --- /dev/null +++ b/plugins/sip/src/main/java/net/java/sipmack/common/Log.java @@ -0,0 +1,57 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.sipmack.common; + +/** + * Creates and writes out messages. + */ +public class Log { + + private static boolean debugger = Boolean.parseBoolean(System.getProperty("debugger")); + + public static void debug(String message) { + if (debugger) + System.out.println((message != null ? message : "")); + } + + public static void debug(String method, String message) { + if (debugger) + System.out.println((method != null ? method : "") + " - " + + (message != null ? message : "")); + } + + public static void error(String method, Exception e) { + System.out.println((method != null ? method : "") + " - " + + (e != null ? e.toString() : "")); + e.printStackTrace(); + } + + public static void error(Exception e) { + error("", e); + } + + public static void error(String method, Error e) { + System.out.println((method != null ? method : "") + " - " + + (e != null ? e.toString() : "")); + } + + public static void error(String method, Throwable e) { + System.out.println((method != null ? method : "") + " - " + + (e != null ? e.toString() : "")); + } + +} diff --git a/src/plugins/sip/src/java/net/java/sipmack/common/Scheduler.java b/plugins/sip/src/main/java/net/java/sipmack/common/Scheduler.java similarity index 98% rename from src/plugins/sip/src/java/net/java/sipmack/common/Scheduler.java rename to plugins/sip/src/main/java/net/java/sipmack/common/Scheduler.java index 454fe12bb..61815b6ee 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/common/Scheduler.java +++ b/plugins/sip/src/main/java/net/java/sipmack/common/Scheduler.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/common/Utils.java b/plugins/sip/src/main/java/net/java/sipmack/common/Utils.java similarity index 97% rename from src/plugins/sip/src/java/net/java/sipmack/common/Utils.java rename to plugins/sip/src/main/java/net/java/sipmack/common/Utils.java index b9f5fdb59..e260236f0 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/common/Utils.java +++ b/plugins/sip/src/main/java/net/java/sipmack/common/Utils.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/common/scheduler/Timer.java b/plugins/sip/src/main/java/net/java/sipmack/common/scheduler/Timer.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/common/scheduler/Timer.java rename to plugins/sip/src/main/java/net/java/sipmack/common/scheduler/Timer.java index 9b821e94a..b835d7fa9 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/common/scheduler/Timer.java +++ b/plugins/sip/src/main/java/net/java/sipmack/common/scheduler/Timer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/common/scheduler/TimerTask.java b/plugins/sip/src/main/java/net/java/sipmack/common/scheduler/TimerTask.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/common/scheduler/TimerTask.java rename to plugins/sip/src/main/java/net/java/sipmack/common/scheduler/TimerTask.java index 1d0bccefd..b67635f8e 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/common/scheduler/TimerTask.java +++ b/plugins/sip/src/main/java/net/java/sipmack/common/scheduler/TimerTask.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/events/UserActionListener.java b/plugins/sip/src/main/java/net/java/sipmack/events/UserActionListener.java similarity index 96% rename from src/plugins/sip/src/java/net/java/sipmack/events/UserActionListener.java rename to plugins/sip/src/main/java/net/java/sipmack/events/UserActionListener.java index a1abd8aeb..4bd53ebe3 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/events/UserActionListener.java +++ b/plugins/sip/src/main/java/net/java/sipmack/events/UserActionListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/events/UserCallControlEvent.java b/plugins/sip/src/main/java/net/java/sipmack/events/UserCallControlEvent.java similarity index 95% rename from src/plugins/sip/src/java/net/java/sipmack/events/UserCallControlEvent.java rename to plugins/sip/src/main/java/net/java/sipmack/events/UserCallControlEvent.java index 0cea3cdd3..4575dc267 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/events/UserCallControlEvent.java +++ b/plugins/sip/src/main/java/net/java/sipmack/events/UserCallControlEvent.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/media/AudioChannel.java b/plugins/sip/src/main/java/net/java/sipmack/media/AudioChannel.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/media/AudioChannel.java rename to plugins/sip/src/main/java/net/java/sipmack/media/AudioChannel.java index 074910ce7..747eaa694 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/media/AudioChannel.java +++ b/plugins/sip/src/main/java/net/java/sipmack/media/AudioChannel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/media/AudioFormatUtils.java b/plugins/sip/src/main/java/net/java/sipmack/media/AudioFormatUtils.java similarity index 98% rename from src/plugins/sip/src/java/net/java/sipmack/media/AudioFormatUtils.java rename to plugins/sip/src/main/java/net/java/sipmack/media/AudioFormatUtils.java index 03ec80e02..6b666d9d9 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/media/AudioFormatUtils.java +++ b/plugins/sip/src/main/java/net/java/sipmack/media/AudioFormatUtils.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/media/AudioMediaSession.java b/plugins/sip/src/main/java/net/java/sipmack/media/AudioMediaSession.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/media/AudioMediaSession.java rename to plugins/sip/src/main/java/net/java/sipmack/media/AudioMediaSession.java index 9618d34d1..ed35d1eb4 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/media/AudioMediaSession.java +++ b/plugins/sip/src/main/java/net/java/sipmack/media/AudioMediaSession.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/media/AudioReceiver.java b/plugins/sip/src/main/java/net/java/sipmack/media/AudioReceiver.java similarity index 98% rename from src/plugins/sip/src/java/net/java/sipmack/media/AudioReceiver.java rename to plugins/sip/src/main/java/net/java/sipmack/media/AudioReceiver.java index 17282bb33..bec9a83db 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/media/AudioReceiver.java +++ b/plugins/sip/src/main/java/net/java/sipmack/media/AudioReceiver.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/media/AudioReceiverChannel.java b/plugins/sip/src/main/java/net/java/sipmack/media/AudioReceiverChannel.java similarity index 98% rename from src/plugins/sip/src/java/net/java/sipmack/media/AudioReceiverChannel.java rename to plugins/sip/src/main/java/net/java/sipmack/media/AudioReceiverChannel.java index 2a1917049..353908a03 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/media/AudioReceiverChannel.java +++ b/plugins/sip/src/main/java/net/java/sipmack/media/AudioReceiverChannel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/media/JmfMediaManager.java b/plugins/sip/src/main/java/net/java/sipmack/media/JmfMediaManager.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/media/JmfMediaManager.java rename to plugins/sip/src/main/java/net/java/sipmack/media/JmfMediaManager.java index 273a3c8f8..9d4ea8592 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/media/JmfMediaManager.java +++ b/plugins/sip/src/main/java/net/java/sipmack/media/JmfMediaManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -729,8 +725,7 @@ private AudioFormat getPreferredFormat(ArrayList formate){ for(String codec: codecs) { for(String format : formate) { - if(format != null - && format.toLowerCase().equals(codec.toLowerCase())) + if (format != null && format.equalsIgnoreCase(codec)) return new AudioFormat(format); } } @@ -746,7 +741,7 @@ private List getSelectedFormats(){ String[] codecs = localPreferences.getSelectedCodecs().split("\\^"); for(AudioFormat form : all) { for(String codec: codecs) { - if(form.getEncoding().toLowerCase().equals(codec.toLowerCase())){ + if (form.getEncoding().equalsIgnoreCase(codec)) { format.add(form); } } diff --git a/src/plugins/sip/src/java/net/java/sipmack/media/MediaException.java b/plugins/sip/src/main/java/net/java/sipmack/media/MediaException.java similarity index 95% rename from src/plugins/sip/src/java/net/java/sipmack/media/MediaException.java rename to plugins/sip/src/main/java/net/java/sipmack/media/MediaException.java index c6c9c0888..d26a0767b 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/media/MediaException.java +++ b/plugins/sip/src/main/java/net/java/sipmack/media/MediaException.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/media/TransportCandidate.java b/plugins/sip/src/main/java/net/java/sipmack/media/TransportCandidate.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/media/TransportCandidate.java rename to plugins/sip/src/main/java/net/java/sipmack/media/TransportCandidate.java index 455b61ab1..21a35ac81 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/media/TransportCandidate.java +++ b/plugins/sip/src/main/java/net/java/sipmack/media/TransportCandidate.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/media/VideoChannel.java b/plugins/sip/src/main/java/net/java/sipmack/media/VideoChannel.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/media/VideoChannel.java rename to plugins/sip/src/main/java/net/java/sipmack/media/VideoChannel.java index 9c63b9cee..e5f4734e4 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/media/VideoChannel.java +++ b/plugins/sip/src/main/java/net/java/sipmack/media/VideoChannel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/media/VideoMediaSession.java b/plugins/sip/src/main/java/net/java/sipmack/media/VideoMediaSession.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/media/VideoMediaSession.java rename to plugins/sip/src/main/java/net/java/sipmack/media/VideoMediaSession.java index 82898d505..1f7adc171 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/media/VideoMediaSession.java +++ b/plugins/sip/src/main/java/net/java/sipmack/media/VideoMediaSession.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/media/VideoReceiver.java b/plugins/sip/src/main/java/net/java/sipmack/media/VideoReceiver.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/media/VideoReceiver.java rename to plugins/sip/src/main/java/net/java/sipmack/media/VideoReceiver.java index e06579ed8..87bf8293d 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/media/VideoReceiver.java +++ b/plugins/sip/src/main/java/net/java/sipmack/media/VideoReceiver.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/media/event/MediaErrorEvent.java b/plugins/sip/src/main/java/net/java/sipmack/media/event/MediaErrorEvent.java similarity index 95% rename from src/plugins/sip/src/java/net/java/sipmack/media/event/MediaErrorEvent.java rename to plugins/sip/src/main/java/net/java/sipmack/media/event/MediaErrorEvent.java index 3d7884f92..4e9601855 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/media/event/MediaErrorEvent.java +++ b/plugins/sip/src/main/java/net/java/sipmack/media/event/MediaErrorEvent.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/media/event/MediaEvent.java b/plugins/sip/src/main/java/net/java/sipmack/media/event/MediaEvent.java similarity index 95% rename from src/plugins/sip/src/java/net/java/sipmack/media/event/MediaEvent.java rename to plugins/sip/src/main/java/net/java/sipmack/media/event/MediaEvent.java index 7dc7f96fb..ec0dc5017 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/media/event/MediaEvent.java +++ b/plugins/sip/src/main/java/net/java/sipmack/media/event/MediaEvent.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/media/event/MediaListener.java b/plugins/sip/src/main/java/net/java/sipmack/media/event/MediaListener.java similarity index 94% rename from src/plugins/sip/src/java/net/java/sipmack/media/event/MediaListener.java rename to plugins/sip/src/main/java/net/java/sipmack/media/event/MediaListener.java index a223fbaec..6eb29bef6 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/media/event/MediaListener.java +++ b/plugins/sip/src/main/java/net/java/sipmack/media/event/MediaListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/Call.java b/plugins/sip/src/main/java/net/java/sipmack/sip/Call.java similarity index 94% rename from src/plugins/sip/src/java/net/java/sipmack/sip/Call.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/Call.java index 1fcb34ac9..e5ea1720e 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/Call.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/Call.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -103,7 +99,7 @@ public class Call implements ReceiveStreamListener { private String callState = ""; // Event Management - List listeners = new CopyOnWriteArrayList(); + private final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList(); public SessionDescription getLocalSdpDescription() { return localSdpDescription; @@ -320,15 +316,23 @@ public void onHoldCam(boolean h) { // ====================== EVENTS =========================== public void addStateChangeListener(CallListener listener) { Log.debug(listener.getClass().getCanonicalName()); - listeners.add(listener); + listeners.addIfAbsent(listener); } public void fireCallStatusChangedEvent(String oldStatus) { Log.debug(this.getState()); CallStateEvent evt = new CallStateEvent(this); evt.setOldState(oldStatus); - for (CallListener callListener : listeners) { - callListener.callStateChanged(evt); + for ( final CallListener listener : listeners ) + { + try + { + listener.callStateChanged( evt ); + } + catch ( Exception e ) + { + Log.error( "A CallListener (" + listener + ") threw an exception while processing a 'callStateChanged' event (old status: " + oldStatus + ").", e ); + } } } @@ -352,4 +356,4 @@ public void setVideoMediaSession(VideoMediaSession videoMediaSession) { public void update(ReceiveStreamEvent receiveStreamEvent) { } -} \ No newline at end of file +} diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/CallDispatcher.java b/plugins/sip/src/main/java/net/java/sipmack/sip/CallDispatcher.java similarity index 98% rename from src/plugins/sip/src/java/net/java/sipmack/sip/CallDispatcher.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/CallDispatcher.java index 9240c9eaa..4a82018f4 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/CallDispatcher.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/CallDispatcher.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/CallProcessing.java b/plugins/sip/src/main/java/net/java/sipmack/sip/CallProcessing.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/sip/CallProcessing.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/CallProcessing.java index a379ed13c..ea731d0dd 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/CallProcessing.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/CallProcessing.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/CommunicationsException.java b/plugins/sip/src/main/java/net/java/sipmack/sip/CommunicationsException.java similarity index 97% rename from src/plugins/sip/src/java/net/java/sipmack/sip/CommunicationsException.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/CommunicationsException.java index e5022a107..7a3403cd7 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/CommunicationsException.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/CommunicationsException.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/ErrorProcessing.java b/plugins/sip/src/main/java/net/java/sipmack/sip/ErrorProcessing.java similarity index 95% rename from src/plugins/sip/src/java/net/java/sipmack/sip/ErrorProcessing.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/ErrorProcessing.java index f2b49cff0..f0c3db365 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/ErrorProcessing.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/ErrorProcessing.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/Interlocutor.java b/plugins/sip/src/main/java/net/java/sipmack/sip/Interlocutor.java similarity index 98% rename from src/plugins/sip/src/java/net/java/sipmack/sip/Interlocutor.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/Interlocutor.java index e89588148..004484e9d 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/Interlocutor.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/Interlocutor.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/InterlocutorUI.java b/plugins/sip/src/main/java/net/java/sipmack/sip/InterlocutorUI.java similarity index 96% rename from src/plugins/sip/src/java/net/java/sipmack/sip/InterlocutorUI.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/InterlocutorUI.java index 880495344..12bf8217f 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/InterlocutorUI.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/InterlocutorUI.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/NetworkAddressManager.java b/plugins/sip/src/main/java/net/java/sipmack/sip/NetworkAddressManager.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/sip/NetworkAddressManager.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/NetworkAddressManager.java index 662882b66..984d5e6de 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/NetworkAddressManager.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/NetworkAddressManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/RegisterProcessing.java b/plugins/sip/src/main/java/net/java/sipmack/sip/RegisterProcessing.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/sip/RegisterProcessing.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/RegisterProcessing.java index 2b9cc3bae..8ae2851e2 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/RegisterProcessing.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/RegisterProcessing.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/SIPConfig.java b/plugins/sip/src/main/java/net/java/sipmack/sip/SIPConfig.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/sip/SIPConfig.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/SIPConfig.java index b53057aa7..7f53f363e 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/SIPConfig.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/SIPConfig.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/SipCommHop.java b/plugins/sip/src/main/java/net/java/sipmack/sip/SipCommHop.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/sip/SipCommHop.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/SipCommHop.java index a28f57924..562bcf47d 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/SipCommHop.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/SipCommHop.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/SipCommRouter.java b/plugins/sip/src/main/java/net/java/sipmack/sip/SipCommRouter.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/sip/SipCommRouter.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/SipCommRouter.java index 75caa793f..6c05e17da 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/SipCommRouter.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/SipCommRouter.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/SipManager.java b/plugins/sip/src/main/java/net/java/sipmack/sip/SipManager.java similarity index 96% rename from src/plugins/sip/src/java/net/java/sipmack/sip/SipManager.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/SipManager.java index 43186d1f0..a7c8dcb7f 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/SipManager.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/SipManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -1249,11 +1245,15 @@ void fireCallEnded(Call call) { // ------------ call received dispatch void fireMessageReceived(Request message) { - - MessageEvent evt = new MessageEvent(message); - for (int i = listeners.size() - 1; i >= 0; i--) { - ((CommunicationsListener) listeners.get(i)) - .messageReceived(evt); + try { + MessageEvent evt = new MessageEvent( message ); + for ( int i = listeners.size() - 1; i >= 0; i-- ) + { + ( (CommunicationsListener) listeners.get( i ) ) + .messageReceived( evt ); + } + } catch ( Exception e ) { + Log.error("fireMessageReceived", e); } } // call received @@ -1268,7 +1268,11 @@ void fireRegistered(String address) { } RegistrationEvent evt = new RegistrationEvent(address); for (int i = listeners.size() - 1; i >= 0; i--) { - ((CommunicationsListener) listeners.get(i)).registered(evt); + try { + ( (CommunicationsListener) listeners.get( i ) ).registered( evt ); + } catch ( Exception e ) { + Log.error("fireRegistered", e); + } } } // call received @@ -1276,7 +1280,11 @@ void fireRegistered(String address) { void fireRegistering(String address) { RegistrationEvent evt = new RegistrationEvent(address); for (int i = listeners.size() - 1; i >= 0; i--) { - ((CommunicationsListener) listeners.get(i)).registering(evt); + try { + ( (CommunicationsListener) listeners.get( i ) ).registering( evt ); + } catch ( Exception e ) { + Log.error("fireRegistering", e); + } } } // call received @@ -1284,7 +1292,11 @@ void fireRegistering(String address) { public void fireUnregistered(String address) { RegistrationEvent evt = new RegistrationEvent(address); for (int i = listeners.size() - 1; i >= 0; i--) { - ((CommunicationsListener) listeners.get(i)).unregistered(evt); + try { + ((CommunicationsListener) listeners.get(i)).unregistered(evt); + } catch ( Exception e ) { + Log.error("fireUnregistere", e); + } } } @@ -1292,7 +1304,11 @@ void fireRegistrationFailed(String address, RegistrationEvent.Type type) { if (registrationFailed(type)) { RegistrationEvent evt = new RegistrationEvent(address, type); for (int i = listeners.size() - 1; i >= 0; i--) { - ((CommunicationsListener) listeners.get(i)).registrationFailed(evt); + try { + ((CommunicationsListener) listeners.get(i)).registrationFailed(evt); + } catch ( Exception e ) { + Log.error("fireRegistrationFailed", e); + } } } } @@ -1300,7 +1316,11 @@ void fireRegistrationFailed(String address, RegistrationEvent.Type type) { void fireUnregistering(String address) { RegistrationEvent evt = new RegistrationEvent(address); for (int i = listeners.size() - 1; i >= 0; i--) { - ((CommunicationsListener) listeners.get(i)).unregistering(evt); + try { + ((CommunicationsListener) listeners.get(i)).unregistering(evt); + } catch ( Exception e ) { + Log.error("fireUnregistering", e); + } } } @@ -1308,8 +1328,11 @@ void fireUnregistering(String address) { void fireUnknownMessageReceived(Message message) { UnknownMessageEvent evt = new UnknownMessageEvent(message); for (int i = listeners.size() - 1; i >= 0; i--) { - ((CommunicationsListener) listeners.get(i)) - .receivedUnknownMessage(evt); + try { + ((CommunicationsListener) listeners.get(i)).receivedUnknownMessage(evt); + } catch ( Exception e ) { + Log.error("fireUnknownMessageReceived", e); + } } } @@ -1317,16 +1340,22 @@ void fireUnknownMessageReceived(Message message) { public void fireCallRejectedLocally(String reason, Message invite, Call call) { CallRejectedEvent evt = new CallRejectedEvent(reason, invite, call); for (int i = listeners.size() - 1; i >= 0; i--) { - ((CommunicationsListener) listeners.get(i)) - .callRejectedLocally(evt); + try { + ((CommunicationsListener) listeners.get(i)).callRejectedLocally(evt); + } catch ( Exception e ) { + Log.error("fireCallRejectedLocally", e); + } } } void fireCallRejectedRemotely(String reason, Message invite, Call call) { CallRejectedEvent evt = new CallRejectedEvent(reason, invite, call); for (int i = listeners.size() - 1; i >= 0; i--) { - ((CommunicationsListener) listeners.get(i)) - .callRejectedRemotely(evt); + try { + ((CommunicationsListener) listeners.get(i)).callRejectedRemotely(evt); + } catch ( Exception e ) { + Log.error("fireCallRejectedRemotely", e); + } } } @@ -1334,17 +1363,14 @@ void fireCallRejectedRemotely(String reason, Message invite, Call call) { // call rejected // ---------------- error occurred public void fireCommunicationsError(Throwable throwable) { - try { - CommunicationsErrorEvent evt = new CommunicationsErrorEvent( - throwable); - for (int i = listeners.size() - 1; i >= 0; i--) { + CommunicationsErrorEvent evt = new CommunicationsErrorEvent(throwable); + for (int i = listeners.size() - 1; i >= 0; i--) { + try { ((CommunicationsListener) listeners.get(i)).communicationsErrorOccurred(evt); + } catch ( Exception e ) { + Log.error("fireCommunicationsError", e); } } - catch (Throwable e) { - Log.error("fireCommunicationsError", e); - } - } // error occurred // ============================= SIP LISTENER METHODS ============================== diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/SipRegisterStatus.java b/plugins/sip/src/main/java/net/java/sipmack/sip/SipRegisterStatus.java similarity index 94% rename from src/plugins/sip/src/java/net/java/sipmack/sip/SipRegisterStatus.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/SipRegisterStatus.java index 751f29180..d6619843a 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/SipRegisterStatus.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/SipRegisterStatus.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/TransferProcessing.java b/plugins/sip/src/main/java/net/java/sipmack/sip/TransferProcessing.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/sip/TransferProcessing.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/TransferProcessing.java index 46faaf062..b5b75800a 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/TransferProcessing.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/TransferProcessing.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/event/CallEvent.java b/plugins/sip/src/main/java/net/java/sipmack/sip/event/CallEvent.java similarity index 95% rename from src/plugins/sip/src/java/net/java/sipmack/sip/event/CallEvent.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/event/CallEvent.java index f247bc1b7..da9e1d964 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/event/CallEvent.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/event/CallEvent.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/event/CallListener.java b/plugins/sip/src/main/java/net/java/sipmack/sip/event/CallListener.java similarity index 96% rename from src/plugins/sip/src/java/net/java/sipmack/sip/event/CallListener.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/event/CallListener.java index c54df8091..9813bf9d3 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/event/CallListener.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/event/CallListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/event/CallRejectedEvent.java b/plugins/sip/src/main/java/net/java/sipmack/sip/event/CallRejectedEvent.java similarity index 96% rename from src/plugins/sip/src/java/net/java/sipmack/sip/event/CallRejectedEvent.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/event/CallRejectedEvent.java index 4481f8623..5f9a579ae 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/event/CallRejectedEvent.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/event/CallRejectedEvent.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/event/CallStateEvent.java b/plugins/sip/src/main/java/net/java/sipmack/sip/event/CallStateEvent.java similarity index 96% rename from src/plugins/sip/src/java/net/java/sipmack/sip/event/CallStateEvent.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/event/CallStateEvent.java index 1c2183a5e..1d7b07025 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/event/CallStateEvent.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/event/CallStateEvent.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/event/CommunicationsErrorEvent.java b/plugins/sip/src/main/java/net/java/sipmack/sip/event/CommunicationsErrorEvent.java similarity index 95% rename from src/plugins/sip/src/java/net/java/sipmack/sip/event/CommunicationsErrorEvent.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/event/CommunicationsErrorEvent.java index d6cf8b4ac..39cdb1ccc 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/event/CommunicationsErrorEvent.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/event/CommunicationsErrorEvent.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/event/CommunicationsListener.java b/plugins/sip/src/main/java/net/java/sipmack/sip/event/CommunicationsListener.java similarity index 97% rename from src/plugins/sip/src/java/net/java/sipmack/sip/event/CommunicationsListener.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/event/CommunicationsListener.java index b6d8b8fe9..98c12a3c0 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/event/CommunicationsListener.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/event/CommunicationsListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/event/MessageEvent.java b/plugins/sip/src/main/java/net/java/sipmack/sip/event/MessageEvent.java similarity index 97% rename from src/plugins/sip/src/java/net/java/sipmack/sip/event/MessageEvent.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/event/MessageEvent.java index a24162064..57edc2904 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/event/MessageEvent.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/event/MessageEvent.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/event/RegistrationEvent.java b/plugins/sip/src/main/java/net/java/sipmack/sip/event/RegistrationEvent.java similarity index 96% rename from src/plugins/sip/src/java/net/java/sipmack/sip/event/RegistrationEvent.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/event/RegistrationEvent.java index 619811ea0..da7a4a785 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/event/RegistrationEvent.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/event/RegistrationEvent.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/event/UnknownMessageEvent.java b/plugins/sip/src/main/java/net/java/sipmack/sip/event/UnknownMessageEvent.java similarity index 96% rename from src/plugins/sip/src/java/net/java/sipmack/sip/event/UnknownMessageEvent.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/event/UnknownMessageEvent.java index 085064d4d..6d23d759c 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/event/UnknownMessageEvent.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/event/UnknownMessageEvent.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/security/Credentials.java b/plugins/sip/src/main/java/net/java/sipmack/sip/security/Credentials.java similarity index 97% rename from src/plugins/sip/src/java/net/java/sipmack/sip/security/Credentials.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/security/Credentials.java index a657544d9..680e054a6 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/security/Credentials.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/security/Credentials.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/security/CredentialsCache.java b/plugins/sip/src/main/java/net/java/sipmack/sip/security/CredentialsCache.java similarity index 98% rename from src/plugins/sip/src/java/net/java/sipmack/sip/security/CredentialsCache.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/security/CredentialsCache.java index c2ebaeb6e..8f7a433f4 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/security/CredentialsCache.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/security/CredentialsCache.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/security/CredentialsCacheEntry.java b/plugins/sip/src/main/java/net/java/sipmack/sip/security/CredentialsCacheEntry.java similarity index 97% rename from src/plugins/sip/src/java/net/java/sipmack/sip/security/CredentialsCacheEntry.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/security/CredentialsCacheEntry.java index a71d818b7..cc63fb060 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/security/CredentialsCacheEntry.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/security/CredentialsCacheEntry.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/security/MessageDigestAlgorithm.java b/plugins/sip/src/main/java/net/java/sipmack/sip/security/MessageDigestAlgorithm.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/sip/security/MessageDigestAlgorithm.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/security/MessageDigestAlgorithm.java index 051368bb5..9150fb34f 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/security/MessageDigestAlgorithm.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/security/MessageDigestAlgorithm.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/security/SecurityAuthority.java b/plugins/sip/src/main/java/net/java/sipmack/sip/security/SecurityAuthority.java similarity index 96% rename from src/plugins/sip/src/java/net/java/sipmack/sip/security/SecurityAuthority.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/security/SecurityAuthority.java index d586b9914..c25b08cab 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/security/SecurityAuthority.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/security/SecurityAuthority.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/security/SipSecurityException.java b/plugins/sip/src/main/java/net/java/sipmack/sip/security/SipSecurityException.java similarity index 95% rename from src/plugins/sip/src/java/net/java/sipmack/sip/security/SipSecurityException.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/security/SipSecurityException.java index f17f7b575..1c21d3ca2 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/security/SipSecurityException.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/security/SipSecurityException.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/security/SipSecurityManager.java b/plugins/sip/src/main/java/net/java/sipmack/sip/security/SipSecurityManager.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/sip/security/SipSecurityManager.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/security/SipSecurityManager.java index f8d3d9e82..785373aa1 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/security/SipSecurityManager.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/security/SipSecurityManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/simple/ContactUri.java b/plugins/sip/src/main/java/net/java/sipmack/sip/simple/ContactUri.java similarity index 98% rename from src/plugins/sip/src/java/net/java/sipmack/sip/simple/ContactUri.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/simple/ContactUri.java index 3f557b2bf..d535f9147 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/simple/ContactUri.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/simple/ContactUri.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/simple/GenericURI.java b/plugins/sip/src/main/java/net/java/sipmack/sip/simple/GenericURI.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/sip/simple/GenericURI.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/simple/GenericURI.java index 4e32d8c42..3eabfcc2a 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/simple/GenericURI.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/simple/GenericURI.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/sip/simple/MessageProcessing.java b/plugins/sip/src/main/java/net/java/sipmack/sip/simple/MessageProcessing.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/sip/simple/MessageProcessing.java rename to plugins/sip/src/main/java/net/java/sipmack/sip/simple/MessageProcessing.java index 963030e24..fc7d2bde1 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/sip/simple/MessageProcessing.java +++ b/plugins/sip/src/main/java/net/java/sipmack/sip/simple/MessageProcessing.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/softphone/SoftPhone.java b/plugins/sip/src/main/java/net/java/sipmack/softphone/SoftPhone.java similarity index 98% rename from src/plugins/sip/src/java/net/java/sipmack/softphone/SoftPhone.java rename to plugins/sip/src/main/java/net/java/sipmack/softphone/SoftPhone.java index c9be6d8a6..f7ab11c0f 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/softphone/SoftPhone.java +++ b/plugins/sip/src/main/java/net/java/sipmack/softphone/SoftPhone.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/softphone/SoftPhoneManager.java b/plugins/sip/src/main/java/net/java/sipmack/softphone/SoftPhoneManager.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/softphone/SoftPhoneManager.java rename to plugins/sip/src/main/java/net/java/sipmack/softphone/SoftPhoneManager.java index 6292fb8eb..909b99fc3 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/softphone/SoftPhoneManager.java +++ b/plugins/sip/src/main/java/net/java/sipmack/softphone/SoftPhoneManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/softphone/SoftPhoneMedia.java b/plugins/sip/src/main/java/net/java/sipmack/softphone/SoftPhoneMedia.java similarity index 97% rename from src/plugins/sip/src/java/net/java/sipmack/softphone/SoftPhoneMedia.java rename to plugins/sip/src/main/java/net/java/sipmack/softphone/SoftPhoneMedia.java index 3ac240299..8106354c6 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/softphone/SoftPhoneMedia.java +++ b/plugins/sip/src/main/java/net/java/sipmack/softphone/SoftPhoneMedia.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/softphone/SoftPhoneSecurity.java b/plugins/sip/src/main/java/net/java/sipmack/softphone/SoftPhoneSecurity.java similarity index 97% rename from src/plugins/sip/src/java/net/java/sipmack/softphone/SoftPhoneSecurity.java rename to plugins/sip/src/main/java/net/java/sipmack/softphone/SoftPhoneSecurity.java index 4f70b3f94..dd5d20c5d 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/softphone/SoftPhoneSecurity.java +++ b/plugins/sip/src/main/java/net/java/sipmack/softphone/SoftPhoneSecurity.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/softphone/VoiceMail.java b/plugins/sip/src/main/java/net/java/sipmack/softphone/VoiceMail.java similarity index 98% rename from src/plugins/sip/src/java/net/java/sipmack/softphone/VoiceMail.java rename to plugins/sip/src/main/java/net/java/sipmack/softphone/VoiceMail.java index 91aab158a..4481e4853 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/softphone/VoiceMail.java +++ b/plugins/sip/src/main/java/net/java/sipmack/softphone/VoiceMail.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/softphone/gui/DefaultGuiManager.java b/plugins/sip/src/main/java/net/java/sipmack/softphone/gui/DefaultGuiManager.java similarity index 97% rename from src/plugins/sip/src/java/net/java/sipmack/softphone/gui/DefaultGuiManager.java rename to plugins/sip/src/main/java/net/java/sipmack/softphone/gui/DefaultGuiManager.java index e335f51c7..22e21a92a 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/softphone/gui/DefaultGuiManager.java +++ b/plugins/sip/src/main/java/net/java/sipmack/softphone/gui/DefaultGuiManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/softphone/gui/GuiCallback.java b/plugins/sip/src/main/java/net/java/sipmack/softphone/gui/GuiCallback.java similarity index 97% rename from src/plugins/sip/src/java/net/java/sipmack/softphone/gui/GuiCallback.java rename to plugins/sip/src/main/java/net/java/sipmack/softphone/gui/GuiCallback.java index b24dacb5b..5c8aa6e22 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/softphone/gui/GuiCallback.java +++ b/plugins/sip/src/main/java/net/java/sipmack/softphone/gui/GuiCallback.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/softphone/gui/GuiManager.java b/plugins/sip/src/main/java/net/java/sipmack/softphone/gui/GuiManager.java similarity index 99% rename from src/plugins/sip/src/java/net/java/sipmack/softphone/gui/GuiManager.java rename to plugins/sip/src/main/java/net/java/sipmack/softphone/gui/GuiManager.java index 807caaa40..a979203d0 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/softphone/gui/GuiManager.java +++ b/plugins/sip/src/main/java/net/java/sipmack/softphone/gui/GuiManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/softphone/listeners/InterlocutorListener.java b/plugins/sip/src/main/java/net/java/sipmack/softphone/listeners/InterlocutorListener.java similarity index 94% rename from src/plugins/sip/src/java/net/java/sipmack/softphone/listeners/InterlocutorListener.java rename to plugins/sip/src/main/java/net/java/sipmack/softphone/listeners/InterlocutorListener.java index 07608e050..c50486b54 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/softphone/listeners/InterlocutorListener.java +++ b/plugins/sip/src/main/java/net/java/sipmack/softphone/listeners/InterlocutorListener.java @@ -3,10 +3,6 @@ import net.java.sipmack.sip.InterlocutorUI; /** - * $RCSfile$ - * $Revision: $ - * $Date: 01/12/2006 - * * Copyright 2003-2006 Jive Software. * * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/softphone/listeners/RegisterEvent.java b/plugins/sip/src/main/java/net/java/sipmack/softphone/listeners/RegisterEvent.java similarity index 96% rename from src/plugins/sip/src/java/net/java/sipmack/softphone/listeners/RegisterEvent.java rename to plugins/sip/src/main/java/net/java/sipmack/softphone/listeners/RegisterEvent.java index 82bd5abb1..44eb823ee 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/softphone/listeners/RegisterEvent.java +++ b/plugins/sip/src/main/java/net/java/sipmack/softphone/listeners/RegisterEvent.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/net/java/sipmack/softphone/listeners/SoftPhoneListener.java b/plugins/sip/src/main/java/net/java/sipmack/softphone/listeners/SoftPhoneListener.java similarity index 97% rename from src/plugins/sip/src/java/net/java/sipmack/softphone/listeners/SoftPhoneListener.java rename to plugins/sip/src/main/java/net/java/sipmack/softphone/listeners/SoftPhoneListener.java index 235e05fb8..2e0814ec0 100644 --- a/src/plugins/sip/src/java/net/java/sipmack/softphone/listeners/SoftPhoneListener.java +++ b/plugins/sip/src/main/java/net/java/sipmack/softphone/listeners/SoftPhoneListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/PhoneRes.java b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/PhoneRes.java similarity index 80% rename from src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/PhoneRes.java rename to plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/PhoneRes.java index 8c593219d..d506df97e 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/PhoneRes.java +++ b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/PhoneRes.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -62,8 +58,8 @@ public static final ImageIcon getImageIcon(String imageName) { final URL imageURL = cl.getResource(iconURI); return new ImageIcon(imageURL); } - catch (Exception ex) { - System.out.println(imageName + " not found."); + catch (Throwable t) { + Log.warn(imageName + " not found.", t); } return null; } @@ -73,14 +69,18 @@ public static final URL getURL(String propertyName) { } public static final Image getImage(String imageName) { - try { - final String iconURI = getString(imageName); - final URL imageURL = cl.getResource(iconURI); - return new ImageIcon(imageURL).getImage(); - } - catch (Exception ex) { - Log.error(imageName + " not found."); - } - return null; - } -} \ No newline at end of file + try { + final String iconURI = getString(imageName); + final URL imageURL = cl.getResource(iconURI); + if (imageURL != null) { + return new ImageIcon(imageURL); + } else { + Log.warning(imageName + " not found."); + } + } + catch (Exception e) { + Log.warning("Unable to load image " + imageName, e); + } + return null; + } +} diff --git a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/phone.properties b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/phone.properties similarity index 97% rename from src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/phone.properties rename to plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/phone.properties index 8b26b2ddd..841805b93 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/phone.properties +++ b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/phone.properties @@ -69,9 +69,7 @@ TOASTER_ACCEPT_BUTTON = images/toaster_btn-accept2.png TOASTER_REJECT_BUTTON = images/toaster_btn-reject2.png CALL_PICKUP_IMAGE = images/icon_phone-pickup_24x24.png CALL_REJECT_IMAGE = images/icon_phone-reject_24x24.png -MICROPHONE_IMAGE = images/icon_microphone_16x16.png SPEAKER_IMAGE = images/icon_speaker_16x16.png -TRANSFER_IMAGE = images/icon_phone-transfer_16x16.png PHONE_CALL_IMAGE = images/icon_phone-call_16x16.png PHONE_CALL_24x24_IMAGE = images/phone_call.png DELETE_24x24_IMAGE = images/delete_24x24.png @@ -127,4 +125,4 @@ DIALPAD_BUTTON_HOVER = images/btn_dialpad-hover.png REDIAL_BUTTON = images/btn_phone-redial-big.png REDIAL_BUTTON_DOWN = images/btn_phone-redial-big-down.png REDIAL_BUTTON_HOVER = images/btn_phone-redial-big-hover.png -REDIAL_IMAGE = images/phone_recall.png \ No newline at end of file +REDIAL_IMAGE = images/phone_recall.png diff --git a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n.properties b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n.properties similarity index 96% rename from src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n.properties rename to plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n.properties index ba586e4d8..4a79f4c23 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n.properties +++ b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n.properties @@ -108,9 +108,9 @@ book.noEntry = "No Entry Selected!" book.fillFields = "Please fill all Fields" book.warning = "Attention" title.sip.codecs.title = Codecs -codecs.select = \u21E6 Select -codecs.unselect = Unselect \u21E8 -codecs.up = Up \u21E7 -codecs.down = Down \u21E9 +codecs.select = ⇦ Select +codecs.unselect = Unselect ⇨ +codecs.up = Up ⇧ +codecs.down = Down ⇩ codecs.audio.selected = Selected Audio Codecs codecs.audio.avail = Available Audio Codecs diff --git a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_de.properties b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_de.properties similarity index 81% rename from src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_de.properties rename to plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_de.properties index f73a434fd..e34d2e4e4 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_de.properties +++ b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_de.properties @@ -32,11 +32,11 @@ phone.tryagain = Nochmal versuchen phone.call = Anrufen phone.voicemail = Sprachmitteilung phone.viewcallhistory = Anrufliste anschauen -phone.placecall = Anruf tätigen +phone.placecall = Anruf tätigen phone.hangup = Anruf beenden phone.tips.hangup = Auflegen phone.home = Privat -phone.work = Geschäftlich +phone.work = Geschäftlich phone.cell = Mobil phone.currentcall = Aktiver Anruf phone.incomingcall = Eingehender Anruf @@ -49,14 +49,14 @@ phone.never = Noch nie phone.duration = Daur phone.accept = Annehmen phone.reject = Ablehnen -phone.callback = Zurückrufen -phone.delete = Löschen +phone.callback = Zurückrufen +phone.delete = Löschen phone.enternumber = Nummer zum Anrufen angeben -phone.invalidnumber = Ungültige Nummer +phone.invalidnumber = Ungültige Nummer phone.outgoingcall = Ausgehender Anruf an phone.callhistory = Anrufliste -phone.dialed = Gewählt -phone.dialedcalls = Gewählte Nummern +phone.dialed = Gewählt +phone.dialedcalls = Gewählte Nummern phone.received = Eingegangen phone.receivedcalls = Eingegangene Anrufe phone.missed = Verpasst @@ -67,7 +67,7 @@ phone.receivedcallfrom = Anruf erhalten von phone.missedcallfrom = Verpasster Anruf von phone.incomingcallfrom = Eingehender Anruf von phone.contactdetails = Kontakt Details -phone.noinfo = Keine Informationen verfügbar +phone.noinfo = Keine Informationen verfügbar phone.viewfullprofile = Komplettes Profil ansehen phone.tips.mute = Diesen Anruf stummschalten phone.mute = Stummschalten @@ -85,31 +85,31 @@ phone.callendedat = Anruf beendet: phone.onphonewith = Am Telefon mit phone.callendedwith = Anruf beendet mit phone.previousconversations = Vorherige Konversation -phone.closeconfirm = Das Schließen dieses Raumes beendet den Anruf. Trotzdem fortfahren? -phone.confirmation = Bestätigung +phone.closeconfirm = Das Schließen dieses Raumes beendet den Anruf. Trotzdem fortfahren? +phone.confirmation = Bestätigung phone.all = Alle phone.allcalls = Alle Anrufe phone.tocall = Anruf -btn.add = Hinzufügen +btn.add = Hinzufügen btn.edit = Bearbeiten -btn.del = Löschen -btn.dial = Wählen +btn.del = Löschen +btn.dial = Wählen book.name = Name book.number = Nummer frame.title = Telefonbuch book.search = Suche btn.ok = OK btn.cancel = Abbrechen -frame.add = Eintrag hinzufügen +frame.add = Eintrag hinzufügen frame.edit = Eintrag bearbeiten book.exists = Der Telefonbuch Eintrag exisitert bereits. -book.noEntry = Kein Eintrag ausgewählt -book.fillFields = Bitte alle Felder ausfüllen +book.noEntry = Kein Eintrag ausgewählt +book.fillFields = Bitte alle Felder ausfüllen book.warning = Achtung title.sip.codecs.title = Codecs -codecs.select = \u21E6 Auswählen -codecs.unselect = Abwählen \u21E8 +codecs.select = \u21E6 Auswählen +codecs.unselect = Abwählen \u21E8 codecs.up = Rauf \u21E7 codecs.down = Runter \u21E9 -codecs.audio.selected = Ausgewählte Codecs -codecs.audio.avail = Verfügbare Codecs \ No newline at end of file +codecs.audio.selected = Ausgewählte Codecs +codecs.audio.avail = Verfügbare Codecs \ No newline at end of file diff --git a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_es.properties b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_es.properties similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_es.properties rename to plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_es.properties index ec8a28032..2c6a84af2 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_es.properties +++ b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_es.properties @@ -112,4 +112,4 @@ codecs.unselect = Unselect > codecs.up = Up ^ codecs.down = Down v codecs.audio.selected = Selected Audio Codecs -codecs.audio.avail = Available Audio Codecs \ No newline at end of file +codecs.audio.avail = Available Audio Codecs diff --git a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_fr.properties b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_fr.properties similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_fr.properties rename to plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_fr.properties index ec8a28032..2c6a84af2 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_fr.properties +++ b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_fr.properties @@ -112,4 +112,4 @@ codecs.unselect = Unselect > codecs.up = Up ^ codecs.down = Down v codecs.audio.selected = Selected Audio Codecs -codecs.audio.avail = Available Audio Codecs \ No newline at end of file +codecs.audio.avail = Available Audio Codecs diff --git a/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_it.properties b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_it.properties new file mode 100644 index 000000000..82e808d2e --- /dev/null +++ b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_it.properties @@ -0,0 +1,115 @@ +## +## Spark Resource Bundle +## +## Additional locales can be specified by creating a new resource file in this +## directory using the following conventions: +## +## spark_i18n "_" language "_" country ".properties" +## spark_i18n "_" language ".properties" +## +## e.g. +## spark_i18n_en.propertis <- English resources +## spark_i18n_en_US.properties <- American US resources +## spark_i18n_de.properties <- German resources +## spark_i18n_ja.properties <- Japanese resources +## +## Please note that the two digit language code should be lower case, and the +## two digit country code should be in uppercase. Often, it is not necessary to +## specify the country code. +## +## A full list of language codes can be found at +## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt +## and a full list of country codes can be found at +## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html +## +## In property strings that are parameterized, single quotes can be used to +## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. +## + +phone.starting = Avvio del telefono... +phone.failed = Errore di avvio del telefono +phone.tryagain = Riprova +phone.call = Chiama +phone.voicemail = Mail vocale +phone.viewcallhistory = Vedi storico chiamate +phone.placecall = Esegui la chiamata. +phone.hangup = Fine chiamata +phone.tips.hangup = Riagganciare la chiamata. +phone.home = Casa +phone.work = Lavoro +phone.cell = Cellulare +phone.currentcall = Chiamata in corso +phone.incomingcall = Chiamata entrante +phone.noprevious = Nessuna conversazione precedente. +phone.callended = Chiamata terminata +phone.transferto = Chiamata trasferita +phone.connected = Connesso +phone.lastcalled = Ultime chiamate +phone.never = Mai +phone.duration = Durata +phone.accept = Accetta +phone.reject = Rifiuta +phone.callback = Richiama +phone.delete = Cancella +phone.enternumber = Inserisci il numero da chiamare. +phone.invalidnumber = Numero invalido +phone.outgoingcall = Chimata in uscita verso +phone.callhistory = Storico chiamate +phone.dialed = Chiamato +phone.dialedcalls = Chiamate eseguite +phone.received = Ricevuto +phone.receivedcalls = Chiamate ricevute +phone.missed = Perso +phone.missedcalls = Chiamate perse +phone.unknown = Sconosciuto +phone.placecallto = Esegui chiamata a +phone.receivedcallfrom = Chiamata ricevuta da +phone.missedcallfrom = Chiamata persa da +phone.incomingcallfrom = Chiamata entrante da +phone.contactdetails = Dettagli contatto +phone.noinfo = Nessuna informazione disponibile +phone.viewfullprofile = Vedi profilo completo +phone.tips.mute = Silenzia la chiamata +phone.mute = Silenzio +phone.unmute = Attiva +phone.tips.hold = Metti la chiamata in attesa +phone.hold = Attesa +phone.onhold = In attesa +phone.time = Tempo +phone.tips.transfer = Trasferimento chiamata +phone.transfer = Trasferisci +phone.transferring = Trasferimento +phone.transfered = Trasferita +phone.callstartedat = Chiamata iniziata alle +phone.callendedat = Chiamata terminata alle +phone.onphonewith = Al telefono con +phone.callendedwith = Chiamata terminata con +phone.previousconversations = Precedenti conversazioni +phone.closeconfirm = La chiusura della stanza terminerà la chiamata. Prosegui? +phone.confirmation = Conferma +phone.all = Tutto +phone.allcalls = Tutte le chiamate +phone.tocall = Chiama +btn.add = Aggiungi +btn.edit = Modifica +btn.del = Cancella +btn.dial = Chiama +book.name = Nome +book.number = Numero +frame.title = Rubrica +book.search = Cerca +btn.ok = OK +btn.cancel = Cancella +frame.add = "Aggiungi voce" +frame.edit = "Modifica voce" +book.exists = "La voce che vuoi inserire, esiste già." +book.noEntry = "Nessuna voce selezionata!" +book.fillFields = "Prego inserire tutti i campi" +book.warning = "Attenzione" +title.sip.codecs.title = Codecs = Available Audio Codecs +codecs.select = < Seleziona +codecs.unselect = Deseleziona > +codecs.up = Su ^ +codecs.down = Giù v +codecs.audio.selected = Codecs Audio selezionati +codecs.audio.avail = Codecs Audio disponibili diff --git a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_ja.properties b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_ja.properties similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_ja.properties rename to plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_ja.properties index ec8a28032..2c6a84af2 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_ja.properties +++ b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_ja.properties @@ -112,4 +112,4 @@ codecs.unselect = Unselect > codecs.up = Up ^ codecs.down = Down v codecs.audio.selected = Selected Audio Codecs -codecs.audio.avail = Available Audio Codecs \ No newline at end of file +codecs.audio.avail = Available Audio Codecs diff --git a/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_lt.properties b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_lt.properties new file mode 100644 index 000000000..4c7721d67 --- /dev/null +++ b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_lt.properties @@ -0,0 +1,116 @@ +## +## Spark Resource Bundle +## +## Additional locales can be specified by creating a new resource file in this +## directory using the following conventions: +## +## spark_i18n "_" language "_" country ".properties" +## spark_i18n "_" language ".properties" +## +## e.g. +## spark_i18n_en.propertis <- English resources +## spark_i18n_en_US.properties <- American US resources +## spark_i18n_de.properties <- German resources +## spark_i18n_ja.properties <- Japanese resources +## +## Please note that the two digit language code should be lower case, and the +## two digit country code should be in uppercase. Often, it is not necessary to +## specify the country code. +## +## A full list of language codes can be found at +## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt +## and a full list of country codes can be found at +## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html +## +## In property strings that are parameterized, single quotes can be used to +## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. +## + +phone.starting = Telefonas startuoja... +phone.failed = Nepavyko paleist telefono +phone.tryagain = Bandykit dar kartÄ… +phone.call = Skambutis +phone.voicemail = Balso paÅ¡tas +phone.viewcallhistory = PeržiÅ«rÄ—ti skambuÄių istorijÄ… +phone.placecall = Paskambinti telefonu +phone.hangup = Užbaigti skambutį +phone.tips.hangup = Nutraukt telefono pokalbį +phone.home = Namai +phone.work = Darbas +phone.cell = Mobilus +phone.currentcall = Einamasis skambutis +phone.incomingcall = Ä®einantis skambutis +phone.noprevious = PrieÅ¡ tai pokalbių nebuvo +phone.callended = Skambutis nutruko +phone.transferto = Skambutis peradresuotas +phone.connected = Susijungta +phone.lastcalled = Paskutinį kartÄ… skambinta +phone.never = Niekada +phone.duration = TrukmÄ— +phone.accept = Priimti +phone.reject = Atsisakyti +phone.callback = Perskambinti +phone.delete = IÅ¡trinti +phone.enternumber = Ä®veskite numerį skambuÄiui +phone.invalidnumber = Neteisingas numeris +phone.outgoingcall = IÅ¡einantis skambutis +phone.callhistory = SkambuÄių istorija +phone.dialed = Skambinta +phone.dialedcalls = Rinkti numeriai +phone.received = Gauta +phone.receivedcalls = Gauti skambuÄiai +phone.missed = Praleista +phone.missedcalls = Praleisti skambuÄiai +phone.unknown = Nežinomas +phone.placecallto = Paskambinta +phone.receivedcallfrom = Skambutis gautas iÅ¡ +phone.missedcallfrom = Praleistas skambutis nuo +phone.incomingcallfrom = Ä®einantis skambutis nuo +phone.contactdetails = Adresato informacija +phone.noinfo = NÄ—ra informacijos +phone.viewfullprofile = PeržiÅ«reti pilnÄ… profilį +phone.tips.mute = Nutildinti šį skambutį +phone.mute = Nutildinti +phone.unmute = Nuimti nutildinimÄ… +phone.tips.hold = Perjungti šį skambutį į laukimo bÅ«senÄ… +phone.hold = Laukti +phone.onhold = Laukimo bÅ«senoje +phone.time = Laikas +phone.tips.transfer = Peradresuoti šį skambutį +phone.transfer = Peradresuoti +phone.transferring = Skambutis peradresuojamas +phone.transfered = Skambutis peradresuotas +phone.callstartedat = Pokalbis pradÄ—tas +phone.callendedat = Pokalbis baigtas +phone.onphonewith = Kalba telefonu su +phone.callendedwith = BaigÄ—si pokalbis su +phone.previousconversations = Senesni pokalbiai +phone.closeconfirm = Uždarius šį kambarį, pokalbis bus nutrauktas. TÄ™sti? +phone.confirmation = Patvirtinimas +phone.all = Visi +phone.allcalls = Visi skambuÄiai +phone.tocall = Skambinti +phone.enabled = Telefonas įjungtas +btn.add = PridÄ—ti +btn.edit = Redaguoti +btn.del = IÅ¡trinti +btn.dial = Skambinti +book.name = Vardas +book.number = Numeris +frame.title = Telefonų knyga +book.search = PaieÅ¡ka +btn.ok = Gerai +btn.cancel = AtÅ¡aukti +frame.add = "PridÄ—ti įrašą" +frame.edit = "Redaguoti įrašą" +book.exists = "Telefonų knygos įraįas, kurį jÅ«s norite pridÄ—ti, jau egzistuoja." +book.noEntry = "Nepasirinktas įraįas!" +book.fillFields = "Praįome užpildyti visus laukus" +book.warning = "DÄ—mesio" +title.sip.codecs.title = Kodekai +codecs.select = ⇦ Pasirinkti +codecs.unselect = IÅ¡mesti ⇨ +codecs.up = VirÅ¡un ⇧ +codecs.down = Žemyn ⇩ +codecs.audio.selected = Pasirinkti garso kodekai +codecs.audio.avail = Turimi garso kodekai diff --git a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_nl.properties b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_nl.properties similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_nl.properties rename to plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_nl.properties index ec8a28032..2c6a84af2 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_nl.properties +++ b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_nl.properties @@ -112,4 +112,4 @@ codecs.unselect = Unselect > codecs.up = Up ^ codecs.down = Down v codecs.audio.selected = Selected Audio Codecs -codecs.audio.avail = Available Audio Codecs \ No newline at end of file +codecs.audio.avail = Available Audio Codecs diff --git a/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_pl.properties b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_pl.properties new file mode 100644 index 000000000..fb366502f --- /dev/null +++ b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_pl.properties @@ -0,0 +1,116 @@ +## +## Spark Resource Bundle +## +## Additional locales can be specified by creating a new resource file in this +## directory using the following conventions: +## +## spark_i18n "_" language "_" country ".properties" +## spark_i18n "_" language ".properties" +## +## e.g. +## spark_i18n_en.propertis <- English resources +## spark_i18n_en_US.properties <- American US resources +## spark_i18n_de.properties <- German resources +## spark_i18n_ja.properties <- Japanese resources +## +## Please note that the two digit language code should be lower case, and the +## two digit country code should be in uppercase. Often, it is not necessary to +## specify the country code. +## +## A full list of language codes can be found at +## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt +## and a full list of country codes can be found at +## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html +## +## In property strings that are parameterized, single quotes can be used to +## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. +## + +phone.starting = Uruchamianie telefonu... +phone.failed = Błąd uruchomienia telefonu +phone.tryagain = Spróbuj ponownie +phone.call = DzwoÅ„ +phone.voicemail = Wiadomość gÅ‚osowa +phone.viewcallhistory = PrzeglÄ…dnij historiÄ™ rozmów +phone.placecall = DzwoÅ„. +phone.hangup = Odłóż sÅ‚uchawkÄ™ +phone.tips.hangup = ZakoÅ„cz rozmowÄ™ telefonicznÄ… +phone.home = Dom +phone.work = Praca +phone.cell = Komórka +phone.currentcall = Bieżące połączenie +phone.incomingcall = PrzychodzÄ…ce połączenie +phone.noprevious = Brak wczeÅ›niejszych rozmów. +phone.callended = Połączenie zakoÅ„czono +phone.transferto = Połączenie przekazano do +phone.connected = Połączono +phone.lastcalled = Ostatni dzwoniÄ…cy +phone.never = Nigdy +phone.duration = Czas trwania +phone.accept = Akceptuj +phone.reject = Odrzuć +phone.callback = OddzwoÅ„ +phone.delete = UsuÅ„ +phone.enternumber = Podaj numer telefonu. +phone.invalidnumber = Niepoprawny numer +phone.outgoingcall = Połączenie wychodzÄ…ce do +phone.callhistory = Historia rozmów +phone.dialed = Wybrany +phone.dialedcalls = Wybrane połączenia +phone.received = Odebrane +phone.receivedcalls = Odebrane połączenia +phone.missed = Nieodebrane +phone.missedcalls = Nieodebrane połączenia +phone.unknown = Nieznane +phone.placecallto = Dzwoniono do +phone.receivedcallfrom = Odebrane połączenie od +phone.missedcallfrom = Nieodebrane połączenie od +phone.incomingcallfrom = PrzychodzÄ…ce połączenie od +phone.contactdetails = Szczegóły kontaktu +phone.noinfo = Brak dostÄ™pnych informacji +phone.viewfullprofile = Zobacz peÅ‚ny profil +phone.tips.mute = Wycisz te połączenie +phone.mute = Wycisz +phone.unmute = Włącz dźwiÄ™k +phone.tips.hold = ZawieÅ› obecne połączenie odbierajÄ…c oczekujÄ…ce +phone.hold = Wstrzymaj +phone.onhold = Wstrzymane +phone.time = Czas +phone.tips.transfer = Przekaż to połączenie +phone.transfer = Przekaz +phone.transferring = PrzekazujÄ™ +phone.transfered = Przekazano +phone.callstartedat = Połączenie rozpoczÄ™to o +phone.callendedat = Połączenie zakoÅ„czono o +phone.onphonewith = połączenie z +phone.callendedwith = ZakoÅ„czono połączenie z +phone.previousconversations = Poprzednie rozmowy +phone.closeconfirm = ZamkniÄ™cie pokoju zakoÅ„czy połączenie. Kontynuować? +phone.confirmation = Potwierdzenie +phone.all = Wszystkie +phone.allcalls = Wszystkie połączenia +phone.tocall = Połącz +phone.enabled = Telefon włączony +btn.add = Dodaj +btn.edit = Edytuj +btn.del = UsuÅ„ +btn.dial = ZadzwoÅ„ +book.name = Nazwa +book.number = Numer +frame.title = Książka telefoniczna +book.search = Szukaj +btn.ok = OK +btn.cancel = Anuluj +frame.add = "Dodaj wpis" +frame.edit = "Edytuj wpis" +book.exists = "Wpis, który chcesz dodać już istnieje." +book.noEntry = "Brak wybranych wpisów!" +book.fillFields = "ProszÄ™ wypeÅ‚nić wszystkie pola" +book.warning = "Uwaga" +title.sip.codecs.title = Kodeki +codecs.select = ⇦ Zaznacz +codecs.unselect = Odznacz ⇨ +codecs.up = W górÄ™ ⇧ +codecs.down = W dół ⇩ +codecs.audio.selected = Wybierz kodeki dźwiÄ™ku +codecs.audio.avail = DostÄ™pne kodeki dźwiÄ™ku diff --git a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_pt_BR.properties b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_pt_BR.properties similarity index 85% rename from src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_pt_BR.properties rename to plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_pt_BR.properties index 9d96e1744..864a5f5ae 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_pt_BR.properties +++ b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_pt_BR.properties @@ -31,31 +31,31 @@ phone.failed = Falha ao iniciar phone phone.tryagain = Conectar phone.call = Chamada phone.voicemail = Voice Mail -phone.viewcallhistory = Ver histórico de chamadas +phone.viewcallhistory = Ver histórico de chamadas phone.placecall = Fazer Chamada phone.hangup = Desligar phone.tips.hangup = Desliga a Chamada -phone.home = Residência +phone.home = Residência phone.work = Trabalho phone.cell = Celular phone.currentcall = Chamada Atual -phone.noprevious = Não há chamadas anteriores +phone.noprevious = Não há chamadas anteriores phone.callended = Fim da Chamada phone.transferto = Chamada transferida para phone.connected = Conectado phone.incomingcall = Chamada recebida de... -phone.lastcalled = Última Chamada +phone.lastcalled = Última Chamada phone.never = Nunca -phone.duration = Duração +phone.duration = Duração phone.accept = Aceitar phone.reject = Rejeitar phone.callback = Chamar de volta phone.delete = Deletar phone.missedcalls = Chamadas Perdidas -phone.enternumber = Entre com o número -phone.invalidnumber = Número Inválido +phone.enternumber = Entre com o número +phone.invalidnumber = Número Inválido phone.outgoingcall = Chamada para -phone.callhistory = Histórico de Chamadas +phone.callhistory = Histórico de Chamadas phone.dialed = Realizadas phone.dialedcalls = Chamadas Realizadas phone.received = Recebidas @@ -67,7 +67,7 @@ phone.receivedcallfrom = Chamada Recebidade de phone.missedcallfrom = Chamada Perdida de phone.incomingcallfrom = Chamada Recebida de phone.contactdetails = Detalhes do Contato -phone.noinfo = Informação Indisponível +phone.noinfo = Informação Indisponível phone.viewfullprofile = Ver Detalhes phone.tips.mute = Mudo phone.mute = Mudo @@ -80,13 +80,13 @@ phone.tips.transfer = Transfere a chamada phone.transfer = Transferir phone.transferring = Transferindo phone.transfered = Transferido -phone.callstartedat = Chamada iniciada às -phone.callendedat = Chamada finalizada às +phone.callstartedat = Chamada iniciada às +phone.callendedat = Chamada finalizada às phone.onphonewith = Conversando com phone.callendedwith = Chamada Finalidada com phone.previousconversations = Conversar Anteriores -phone.closeconfirm = Fechando a janela você irá desligar a chamada. Continuar? -phone.confirmation = Confirmação +phone.closeconfirm = Fechando a janela você irá desligar a chamada. Continuar? +phone.confirmation = Confirmação phone.all = Todas phone.allcalls = Todas Chamadas phone.tocall = Chamar diff --git a/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_zh_TW.properties b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_zh_TW.properties new file mode 100644 index 000000000..707103d44 --- /dev/null +++ b/plugins/sip/src/main/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_zh_TW.properties @@ -0,0 +1,115 @@ +## +## Spark Resource Bundle +## +## Additional locales can be specified by creating a new resource file in this +## directory using the following conventions: +## +## spark_i18n "_" language "_" country ".properties" +## spark_i18n "_" language ".properties" +## +## e.g. +## spark_i18n_en.propertis <- English resources +## spark_i18n_en_US.properties <- American US resources +## spark_i18n_de.properties <- German resources +## spark_i18n_ja.properties <- Japanese resources +## +## Please note that the two digit language code should be lower case, and the +## two digit country code should be in uppercase. Often, it is not necessary to +## specify the country code. +## +## A full list of language codes can be found at +## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt +## and a full list of country codes can be found at +## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html +## +## In property strings that are parameterized, single quotes can be used to +## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. +## + +phone.starting = 開啟通話中... +phone.failed = 開啟通話失敗 +phone.tryagain = é‡è©¦ +phone.call = å‘¼å« +phone.voicemail = 語音郵件 +phone.viewcallhistory = 查看通話紀錄 +phone.placecall = 撥打電話 +phone.hangup = çµæŸé€šè©± +phone.tips.hangup = 掛掉此通語音èŠå¤© +phone.home = é¦–é  +phone.work = 工作 +phone.cell = 元件 +phone.currentcall = ç›®å‰å‘¼å« +phone.incomingcall = 來電 +phone.noprevious = 沒有以å‰çš„å°è©±. +phone.callended = é€šè©±çµæŸ +phone.transferto = 轉接電話到 +phone.connected = 連接 +phone.lastcalled = 最後通話 +phone.never = 從未 +phone.duration = æŒçºŒæ™‚é–“ +phone.accept = æŽ¥å— +phone.reject = 拒絕 +phone.callback = 回覆電話 +phone.delete = 刪除 +phone.enternumber = è¼¸å…¥è¦æ’¥æ‰“的號碼. +phone.invalidnumber = 無效的號碼 +phone.outgoingcall = 已撥出 +phone.callhistory = 通話紀錄 +phone.dialed = 已撥 +phone.dialedcalls = 已撥電話 +phone.received = æŽ¥è½ +phone.receivedcalls = 接è½é›»è©± +phone.missed = æ¼æŽ¥ +phone.missedcalls = æ¼æŽ¥é›»è©± +phone.unknown = 䏿˜Žé›»è©± +phone.placecallto = 已撥電話到 +phone.receivedcallfrom = 從哪裡接到電話 +phone.missedcallfrom = å¾žå“ªè£¡æ¼æŽ¥é›»è©± +phone.incomingcallfrom = 從哪裡來電 +phone.contactdetails = è¯çµ¡æ–¹å¼ +phone.noinfo = ç„¡å¯ç”¨è³‡æ–™ +phone.viewfullprofile = 查看完整個人資料 +phone.tips.mute = éœéŸ³é€šè©± +phone.mute = éœéŸ³ +phone.unmute = å–æ¶ˆéœéŸ³ +phone.tips.hold = é€™é€šé›»è©±ç­‰å¾…æŽ¥è½ +phone.hold = 通話ä¿ç•™ +phone.onhold = ç­‰å€™æŽ¥è½ +phone.time = 時間 +phone.tips.transfer = 將這通電話轉接 +phone.transfer = 轉接 +phone.transferring = 轉接中 +phone.transfered = 已轉接 +phone.callstartedat = åœ¨å“ªè£¡é–‹å§‹å‘¼å« +phone.callendedat = åœ¨å“ªè£¡çµæŸå‘¼å« +phone.onphonewith = 和誰通話中 +phone.callendedwith = å’Œèª°é€šè©±çµæŸ +phone.previousconversations = 之å‰çš„通話 +phone.closeconfirm = é›¢é–‹é€™å€‹æœƒè­°å®¤å°‡çµæŸé€šè©±,繼續嗎? +phone.confirmation = ç¢ºèª +phone.all = 全部 +phone.allcalls = å…¨éƒ¨å‘¼å« +phone.tocall = å‘¼å« +phone.enabled = 啟動電話 +btn.add = 新增 +btn.edit = 編輯 +btn.del = 刪除 +btn.dial = 撥號 +book.name = å§“å +book.number = 電話號碼 +frame.title = 電話簿 +book.search = æœå°‹ +btn.ok = 確定 +btn.cancel = å–æ¶ˆ +frame.add = "新增項目" +frame.edit = "編輯項目" +book.exists = "æ‚¨æƒ³è¦æ–°å¢žçš„電話簿已經存在." +book.noEntry = "沒有入å£é¸æ“‡!" +book.fillFields = "請填寫所有å€åŸŸ" +book.warning = "注æ„" +title.sip.codecs.title = 編碼解碼器 +codecs.select = < 鏿“‡ +codecs.unselect = å–æ¶ˆé¸æ“‡ > +codecs.up = å‘上 ^ +codecs.down = å‘下 v +codecs.audio.selected = 鏿“‡çš„音頻編碼解碼器 diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/SoftPhonePlugin.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/SoftPhonePlugin.java similarity index 95% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/SoftPhonePlugin.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/SoftPhonePlugin.java index 3d3ede340..5b297ad5c 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/SoftPhonePlugin.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/SoftPhonePlugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,6 +35,8 @@ import net.java.sipmack.softphone.listeners.SoftPhoneListener; import org.jivesoftware.smack.ConnectionListener; +import org.jivesoftware.smack.ReconnectionListener; +import org.jivesoftware.smack.ReconnectionManager; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.roster.Roster; import org.jivesoftware.smack.roster.RosterEntry; @@ -135,13 +133,22 @@ public void run() { TaskEngine.getInstance().schedule(registerTask, 15000); } + @Override public void connectionClosed() { //softPhone.handleUnregisterRequest(); } + @Override public void connectionClosedOnError(Exception exception) { softPhone.handleUnregisterRequest(); } + }); + + ReconnectionManager.getInstanceFor(SparkManager.getConnection()).addReconnectionListener(new ReconnectionListener() { + + @Override + public void reconnectionFailed(Exception e) { + } public void reconnectingIn(int i) { // Wait a bit before registering @@ -153,15 +160,7 @@ public void run() { TaskEngine.getInstance().schedule(registerTask, 15000); } - - public void reconnectionSuccessful() { - } - - public void reconnectionFailed(Exception exception) { - - } - - }); + }); } /** @@ -273,10 +272,10 @@ public void callRejectedRemotely(CallRejectedEvent evt) { private void loadVCards() { // Load vCard information. - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); + Roster roster = SparkManager.getRoster(); for (RosterEntry entry : roster.getEntries()) { SparkManager.getVCardManager().getVCardFromMemory(entry.getUser()); } } -} \ No newline at end of file +} diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/callhistory/CallList.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/callhistory/CallList.java similarity index 95% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/callhistory/CallList.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/callhistory/CallList.java index 92e67a4f8..d4abb6285 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/callhistory/CallList.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/callhistory/CallList.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/callhistory/HistoryCall.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/callhistory/HistoryCall.java similarity index 97% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/callhistory/HistoryCall.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/callhistory/HistoryCall.java index 5e1a4510a..4fae97c87 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/callhistory/HistoryCall.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/callhistory/HistoryCall.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +18,6 @@ /** - * */ public class HistoryCall { private String callerName; diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/callhistory/TelephoneUtils.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/callhistory/TelephoneUtils.java similarity index 97% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/callhistory/TelephoneUtils.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/callhistory/TelephoneUtils.java index 388de2ff7..db02aa09a 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/callhistory/TelephoneUtils.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/callhistory/TelephoneUtils.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/calllog/CallLog.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/calllog/CallLog.java similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/calllog/CallLog.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/calllog/CallLog.java index 370a09dff..fca9a13aa 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/calllog/CallLog.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/calllog/CallLog.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/calllog/CallLogExtension.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/calllog/CallLogExtension.java similarity index 96% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/calllog/CallLogExtension.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/calllog/CallLogExtension.java index aaa2e6c01..057e08295 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/calllog/CallLogExtension.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/calllog/CallLogExtension.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/calllog/LogManager.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/calllog/LogManager.java similarity index 100% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/calllog/LogManager.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/calllog/LogManager.java diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/calllog/LogManagerImpl.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/calllog/LogManagerImpl.java similarity index 94% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/calllog/LogManagerImpl.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/calllog/LogManagerImpl.java index c409190b3..f0d06d80e 100755 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/calllog/LogManagerImpl.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/calllog/LogManagerImpl.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,21 +15,6 @@ */ package org.jivesoftware.sparkplugin.calllog; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.text.DateFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.TimerTask; - import net.java.sipmack.common.Log; import net.java.sipmack.sip.Call; import net.java.sipmack.sip.event.CallRejectedEvent; @@ -44,7 +25,6 @@ import net.java.sipmack.softphone.SoftPhoneManager; import net.java.sipmack.softphone.listeners.RegisterEvent; import net.java.sipmack.softphone.listeners.SoftPhoneListener; - import org.jivesoftware.Spark; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; @@ -55,6 +35,12 @@ import org.xmlpull.mxp1.MXParser; import org.xmlpull.v1.XmlPullParser; +import java.io.*; +import java.text.DateFormat; +import java.util.*; + +import static java.nio.charset.StandardCharsets.UTF_8; + /** * Title: SIPark * Description:JAIN-SIP Audio/Video phone application @@ -204,7 +190,7 @@ public void commit() { // Write out new File try { getHistoryFile().getParentFile().mkdirs(); - BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(getHistoryFile()), "UTF-8")); + BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(getHistoryFile()), UTF_8)); out.write(builder.toString()); out.close(); } @@ -231,7 +217,7 @@ private void loadCallHistory() { try { final MXParser parser = new MXParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(historyFile), "UTF-8")); + BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(historyFile), UTF_8)); parser.setInput(in); boolean done = false; while (!done) { @@ -243,6 +229,7 @@ else if (eventType == XmlPullParser.END_TAG && "calls".equals(parser.getName())) done = true; } } + in.close(); } catch (Exception e) { Log.error(e); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/calllog/LogPacket.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/calllog/LogPacket.java similarity index 94% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/calllog/LogPacket.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/calllog/LogPacket.java index 90280c0f3..804ae0b9f 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/calllog/LogPacket.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/calllog/LogPacket.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +19,7 @@ import org.jivesoftware.smack.filter.PacketIDFilter; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.ExtensionElement; -import org.jivesoftware.smack.packet.XMPPError; +import org.jivesoftware.smack.packet.StanzaError; import org.jivesoftware.smack.provider.IQProvider; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -132,11 +128,11 @@ public static LogPacket logEvent(XMPPConnection connection, ExtensionElement ext LogPacket lp = new LogPacket(); lp.addExtension(ext); - lp.setTo(NAME + "." + connection.getServiceName()); + lp.setTo(NAME + "." + connection.getXMPPServiceDomain()); lp.setType(IQ.Type.set); - PacketCollector collector = connection - .createPacketCollector(new PacketIDFilter(lp.getPacketID())); + StanzaCollector collector = connection + .createStanzaCollector(new PacketIDFilter(lp.getPacketID())); connection.sendStanza(lp); LogPacket response = (LogPacket)collector diff --git a/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/CallPanelButton.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/CallPanelButton.java new file mode 100644 index 000000000..bbe7ee371 --- /dev/null +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/CallPanelButton.java @@ -0,0 +1,159 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkplugin.components; + +import org.jivesoftware.spark.plugin.phone.resource.PhoneRes; + +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JFrame; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Insets; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +/** + */ +public class CallPanelButton extends JButton implements MouseListener { + + private static final long serialVersionUID = 3376625276352251288L; + private Icon normalIcon; + private Icon hoverIcon; + private Icon downIcon; + private Image backgroundImage; + private String text; + + private boolean selected; + + public CallPanelButton(Image image, String text) { + super(); + + this.text = text; + + normalIcon = PhoneRes.getImageIcon("CALLPANEL_BIG_BUTTON"); + hoverIcon = PhoneRes.getImageIcon("CALLPANEL_BIG_BUTTON_HOVER"); + downIcon = PhoneRes.getImageIcon("CALLPANEL_BIG_BUTTON_DOWN"); + backgroundImage = image; + + setIcon(normalIcon); + + decorate(); + + addMouseListener(this); + + setDisabledIcon(normalIcon); + } + + /** + * Decorates the button with the approriate UI configurations. + */ + private void decorate() { + setBorderPainted(false); + setOpaque(true); + + setContentAreaFilled(false); + setMargin(new Insets(0, 0, 0, 0)); + } + + + public void mouseClicked(MouseEvent e) { + } + + public void mousePressed(MouseEvent e) { + setIcon(downIcon); + } + + public void mouseReleased(MouseEvent e) { + if (!selected) { + setIcon(normalIcon); + } + + } + + public void mouseEntered(MouseEvent e) { + if (!selected) { + setIcon(hoverIcon); + } + setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + public void mouseExited(MouseEvent e) { + if (!selected) { + setIcon(normalIcon); + } + setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + + public void setButtonSelected(boolean selected) { + this.selected = selected; + if (selected) { + setIcon(downIcon); + } + else { + setIcon(normalIcon); + } + } + + + public void paintComponent(Graphics g) { + super.paintComponent(g); + int width = getWidth(); + int height = getHeight(); + + int x = (width - backgroundImage.getWidth(null)) / 2; + int y = (height - backgroundImage.getHeight(null)) / 2; + g.drawImage(backgroundImage, x, y - 5, null); + + if (isEnabled()) { + g.setColor(Color.black); + } + else { + g.setColor(Color.lightGray); + } + g.setFont(new Font("Dialog", Font.PLAIN, 11)); + + + int stringWidth = g.getFontMetrics().stringWidth(text); + + x = (width - stringWidth) / 2; + y = height - 12; + g.drawString(text, x, y); + + } + + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + if (!enabled) { + removeMouseListener(this); + } + else { + addMouseListener(this); + } + } + + + public static void main(String args[]) { + JFrame frame = new JFrame(); + frame.add(new EndCallButton()); + frame.pack(); + frame.setVisible(true); + } +} diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/CloseButton.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/CloseButton.java similarity index 97% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/CloseButton.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/CloseButton.java index 68f217240..fe85bb985 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/CloseButton.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/CloseButton.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,7 +27,6 @@ import javax.swing.JButton; /** - * */ public class CloseButton extends JButton implements MouseListener { diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/DialButton.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/DialButton.java similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/DialButton.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/DialButton.java index 1db9a9b03..a20c811e7 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/DialButton.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/DialButton.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,7 +33,6 @@ import javax.swing.AbstractAction; /** - * */ public class DialButton extends JButton implements MouseListener { diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/EndCallButton.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/EndCallButton.java similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/EndCallButton.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/EndCallButton.java index abf7fb2f6..350dc5331 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/EndCallButton.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/EndCallButton.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,7 +31,6 @@ import java.awt.event.MouseListener; /** - * */ public class EndCallButton extends JButton implements MouseListener { diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/RedialButton.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/RedialButton.java similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/RedialButton.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/RedialButton.java index d1c2297f8..35fb7eac9 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/RedialButton.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/RedialButton.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,7 +31,6 @@ import java.awt.event.MouseListener; /** - * */ public class RedialButton extends JButton implements MouseListener { diff --git a/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/RosterMemberCallButton.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/RosterMemberCallButton.java new file mode 100644 index 000000000..cf4690b3d --- /dev/null +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/components/RosterMemberCallButton.java @@ -0,0 +1,141 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkplugin.components; + +import org.jivesoftware.spark.plugin.phone.resource.PhoneRes; + +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JFrame; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Insets; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +/** + */ +public class RosterMemberCallButton extends JButton implements MouseListener { + + private static final long serialVersionUID = 6038719724559294212L; + private Icon normalIcon; + private Icon hoverIcon; + private Icon downIcon; + private Image backgroundImage; + private String text; + + private boolean selected; + + public RosterMemberCallButton(Image image, String text) { + super(); + + this.text = text; + + normalIcon = PhoneRes.getImageIcon("ROSTERPANEL_BUTTON"); + hoverIcon = PhoneRes.getImageIcon("ROSTERPANEL_BUTTON_HOVER"); + downIcon = PhoneRes.getImageIcon("ROSTERPANEL_BUTTON_DOWN"); + backgroundImage = image; + + setIcon(normalIcon); + + decorate(); + + addMouseListener(this); + } + + /** + * Decorates the button with the approriate UI configurations. + */ + private void decorate() { + setBorderPainted(false); + setOpaque(true); + + setContentAreaFilled(false); + setMargin(new Insets(0, 0, 0, 0)); + } + + + public void mouseClicked(MouseEvent e) { + } + + public void mousePressed(MouseEvent e) { + setIcon(downIcon); + } + + public void mouseReleased(MouseEvent e) { + if (!selected) { + setIcon(normalIcon); + } + + } + + public void mouseEntered(MouseEvent e) { + if (!selected) { + setIcon(hoverIcon); + } + setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + public void mouseExited(MouseEvent e) { + if (!selected) { + setIcon(normalIcon); + } + setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + + public void setButtonSelected(boolean selected) { + this.selected = selected; + if (selected) { + setIcon(downIcon); + } + else { + setIcon(normalIcon); + } + } + + + public void paintComponent(Graphics g) { + super.paintComponent(g); + int width = getWidth(); + int height = getHeight(); + + int x = (width - backgroundImage.getWidth(null)) / 2; + int y = (height - backgroundImage.getHeight(null)) / 2; + g.drawImage(backgroundImage, 5, y, null); + + g.setColor(Color.black); + g.setFont(new Font("Dialog", Font.PLAIN, 11)); + + + int stringWidth = g.getFontMetrics().stringWidth(text); + + x = (width - stringWidth) / 2; + y = (height + 11) / 2; + g.drawString(text, x, y); + + } + + public static void main(String args[]) { + JFrame frame = new JFrame(); + frame.add(new RosterMemberCallButton(PhoneRes.getImageIcon("MUTE_IMAGE").getImage(), "Mute")); + frame.pack(); + frame.setVisible(true); + } +} diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/phonebook/BookManager.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/phonebook/BookManager.java similarity index 100% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/phonebook/BookManager.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/phonebook/BookManager.java diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/phonebook/PhoneNumber.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/phonebook/PhoneNumber.java similarity index 100% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/phonebook/PhoneNumber.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/phonebook/PhoneNumber.java diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/phonebook/PhonebookManager.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/phonebook/PhonebookManager.java similarity index 95% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/phonebook/PhonebookManager.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/phonebook/PhonebookManager.java index 9f03f4768..bca10db97 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/phonebook/PhonebookManager.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/phonebook/PhonebookManager.java @@ -16,10 +16,13 @@ import net.java.sipmack.common.Log; import org.jivesoftware.Spark; +import org.jivesoftware.spark.util.log.Log; import org.jivesoftware.spark.plugin.phone.resource.PhoneRes; import org.xmlpull.mxp1.MXParser; import org.xmlpull.v1.XmlPullParser; +import static java.nio.charset.StandardCharsets.UTF_8; + public class PhonebookManager implements BookManager { private static final PhonebookManager instance = new PhonebookManager(); @@ -110,7 +113,7 @@ private void loadPhonebook() { try { final MXParser parser = new MXParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(bookFile), "UTF-8")); + BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(bookFile), UTF_8)); parser.setInput(in); boolean done = false; while (!done) { @@ -122,6 +125,7 @@ else if (eventType == XmlPullParser.END_TAG && "book".equals(parser.getName())) done = true; } } + in.close(); } catch (Exception e) { Log.error(e); @@ -176,12 +180,12 @@ public void commit() { // Write out new File try { getPhonebookFile().getParentFile().mkdirs(); - BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(getPhonebookFile()), "UTF-8")); + BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(getPhonebookFile()), UTF_8)); out.write(builder.toString()); out.close(); } catch (IOException e) { - org.jivesoftware.spark.util.log.Log.error(e); + Log.error(e); } } diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/phonebook/ui/EntryFrame.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/phonebook/ui/EntryFrame.java similarity index 97% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/phonebook/ui/EntryFrame.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/phonebook/ui/EntryFrame.java index 03d7f1f0f..90ef243ed 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/phonebook/ui/EntryFrame.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/phonebook/ui/EntryFrame.java @@ -103,7 +103,7 @@ else if(!manager.add(tfName.getText(), tfNumber.getText())) { this.add(pBtn); this.setResizable(false); - this.setIconImage(SparkRes.getImageIcon(SparkRes.ADDRESS_BOOK_16x16).getImage()); + this.setIconImage(SparkRes.getImageIcon(SparkRes.Icons.ADDRESS_BOOK_16x16).getImage()); this.setSize(new Dimension(250,130)); if(typ == TYP_ADD) { this.setTitle(PhoneRes.getIString("frame.add")); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/phonebook/ui/PhonebookUI.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/phonebook/ui/PhonebookUI.java similarity index 99% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/phonebook/ui/PhonebookUI.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/phonebook/ui/PhonebookUI.java index 7596aa771..5f4233e93 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/phonebook/ui/PhonebookUI.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/phonebook/ui/PhonebookUI.java @@ -217,7 +217,7 @@ public void keyReleased(KeyEvent evt) frame.add(this, BorderLayout.CENTER); frame.setTitle(PhoneRes.getIString("frame.title")); frame.setSize(new Dimension(400,300)); - frame.setIconImage(SparkRes.getImageIcon(SparkRes.ADDRESS_BOOK_16x16).getImage()); + frame.setIconImage(SparkRes.getImageIcon(SparkRes.Icons.ADDRESS_BOOK_16x16).getImage()); } /** diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/AudioPreferenceDialog.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/AudioPreferenceDialog.java similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/AudioPreferenceDialog.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/AudioPreferenceDialog.java index 44800b76e..73f0c062b 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/AudioPreferenceDialog.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/AudioPreferenceDialog.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/SipCodecs.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/SipCodecs.java similarity index 100% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/SipCodecs.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/SipCodecs.java diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/SipCodecsPreference.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/SipCodecsPreference.java similarity index 96% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/SipCodecsPreference.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/SipCodecsPreference.java index d20b6d992..8597650f2 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/SipCodecsPreference.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/SipCodecsPreference.java @@ -40,7 +40,7 @@ public JComponent getGUI() { @Override public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.DIAL_PHONE_IMAGE_24x24); + return SparkRes.getImageIcon(SparkRes.Icons.DIAL_PHONE_IMAGE_24x24); } @Override diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/SipPreference.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/SipPreference.java similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/SipPreference.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/SipPreference.java index f6680e687..6973306ff 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/SipPreference.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/SipPreference.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -240,6 +236,9 @@ public void saveSipFile() { private XStream getXStream() { if (xstream == null) { xstream = new XStream(); + xstream.allowTypes(new Class[] { + SipPreferences.class, + }); xstream.alias("sip", SipPreferences.class); } return xstream; diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/SipPreferencePanel.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/SipPreferencePanel.java similarity index 99% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/SipPreferencePanel.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/SipPreferencePanel.java index f2c590376..196da20ba 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/SipPreferencePanel.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/SipPreferencePanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/SipPreferences.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/SipPreferences.java similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/SipPreferences.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/SipPreferences.java index c1274ab2f..aca9db833 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/preferences/SipPreferences.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/preferences/SipPreferences.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/sipaccount/SipAccount.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/sipaccount/SipAccount.java similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/sipaccount/SipAccount.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/sipaccount/SipAccount.java index d3b1e7155..89a614ddf 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/sipaccount/SipAccount.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/sipaccount/SipAccount.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/sipaccount/SipAccountPacket.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/sipaccount/SipAccountPacket.java similarity index 92% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/sipaccount/SipAccountPacket.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/sipaccount/SipAccountPacket.java index 6372adb83..911e9278d 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/sipaccount/SipAccountPacket.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/sipaccount/SipAccountPacket.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -168,10 +164,10 @@ public static SipAccountPacket getSipSettings(XMPPConnection connection) throws { SipAccountPacket sp = new SipAccountPacket(); - sp.setTo("sipark." + connection.getServiceName()); + sp.setTo("sipark." + connection.getXMPPServiceDomain()); sp.setType(IQ.Type.get); - PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(sp.getPacketID())); + StanzaCollector collector = connection.createStanzaCollector(new PacketIDFilter(sp.getPacketID())); connection.sendStanza(sp); SipAccountPacket response = (SipAccountPacket)collector.nextResult(SmackConfiguration.getDefaultPacketReplyTimeout()); @@ -198,12 +194,12 @@ public static void setSipRegisterStatus(XMPPConnection connection, SipRegisterSt } SipAccountPacket sp = new SipAccountPacket(SipAccountPacket.Type.status); - sp.setTo("sipark." + connection.getServiceName()); + sp.setTo("sipark." + connection.getXMPPServiceDomain()); sp.setType(IQ.Type.set); sp.setContent(register.name()); - PacketCollector collector = connection - .createPacketCollector(new PacketIDFilter(sp.getPacketID())); + StanzaCollector collector = connection + .createStanzaCollector(new PacketIDFilter(sp.getPacketID())); connection.sendStanza(sp); SipAccountPacket response = (SipAccountPacket)collector @@ -228,24 +224,14 @@ public static boolean isSoftPhonePluginInstalled(XMPPConnection con) { if (!con.isConnected()) { return false; } - - ServiceDiscoveryManager disco = ServiceDiscoveryManager - .getInstanceFor(con); - try { - DiscoverItems items = disco.discoverItems(con.getServiceName()); + DiscoverItems items = SparkManager.getSessionManager().getDiscoveredItems(); for ( DiscoverItems.Item item : items.getItems() ) { if ("SIP Controller".equals(item.getName())) { Log.debug("SIP Controller Found"); return true; } } - } - catch (XMPPException | SmackException e) { - Log.error("isSparkPluginInstalled", e); - } - return false; - } public SipAccount getSipAccount() { diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/Backdrop.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/Backdrop.java similarity index 96% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/Backdrop.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/Backdrop.java index 404ae5fa1..59a5e5a42 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/Backdrop.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/Backdrop.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,7 +25,6 @@ import java.awt.geom.AffineTransform; /** - * */ public class Backdrop extends JPanel { private static final long serialVersionUID = -1062382698141913525L; diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/CallHistoryRenderer.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/CallHistoryRenderer.java similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/CallHistoryRenderer.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/CallHistoryRenderer.java index 8702d3497..c220bdb94 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/CallHistoryRenderer.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/CallHistoryRenderer.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/ContactDialControl.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/ContactDialControl.java similarity index 99% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/ContactDialControl.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/ContactDialControl.java index d198c1906..0e88ecfde 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/ContactDialControl.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/ContactDialControl.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -70,7 +66,6 @@ import org.jivesoftware.sparkplugin.ui.call.CallManager; /** - * */ public class ContactDialControl extends JPanel implements InterlocutorListener, Phone { private static final long serialVersionUID = 8848248512306073866L; diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/PhoneControl.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/PhoneControl.java similarity index 99% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/PhoneControl.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/PhoneControl.java index cf06e20f3..8021531b2 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/PhoneControl.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/PhoneControl.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -47,7 +43,6 @@ import org.jivesoftware.sparkplugin.ui.components.JavaMixer; /** - * */ public class PhoneControl extends JPanel { diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/PhonePad.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/PhonePad.java similarity index 99% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/PhonePad.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/PhonePad.java index cb787ebf2..5de314718 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/PhonePad.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/PhonePad.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,7 +37,6 @@ import javax.swing.JPopupMenu; /** - * */ public class PhonePad extends BackgroundPanel { private static final long serialVersionUID = 1059979750263197335L; diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/RegistrationStatusPanel.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/RegistrationStatusPanel.java similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/RegistrationStatusPanel.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/RegistrationStatusPanel.java index 410ceb573..25a2a3001 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/RegistrationStatusPanel.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/RegistrationStatusPanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/TelephoneTextField.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/TelephoneTextField.java similarity index 99% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/TelephoneTextField.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/TelephoneTextField.java index 9fe777424..81f2eb9e7 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/TelephoneTextField.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/TelephoneTextField.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -42,7 +38,6 @@ import java.awt.event.KeyEvent; /** - * */ /** diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/TopLabel.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/TopLabel.java similarity index 97% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/TopLabel.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/TopLabel.java index 57fc433a9..7a7e4a5bb 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/TopLabel.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/TopLabel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,7 +29,6 @@ import javax.swing.JPanel; /** - * */ public class TopLabel extends JPanel { diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/CallHistoryUI.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/CallHistoryUI.java similarity index 99% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/CallHistoryUI.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/CallHistoryUI.java index ddc0dfe49..3ead16edc 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/CallHistoryUI.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/CallHistoryUI.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -50,7 +46,6 @@ import java.util.List; /** - * */ public class CallHistoryUI extends JPanel implements ActionListener, ListSelectionListener { @@ -76,7 +71,7 @@ public CallHistoryUI() { renderer = new CallHistoryRenderer(); callHistoryFrame = new JFrame(PhoneRes.getIString("phone.callhistory")); - callHistoryFrame.setIconImage(SparkRes.getImageIcon(SparkRes.HISTORY_16x16).getImage()); + callHistoryFrame.setIconImage(SparkRes.getImageIcon(SparkRes.Icons.HISTORY_16x16).getImage()); callHistoryFrame.add(this); callHistoryFrame.pack(); callHistoryFrame.setSize(300, 300); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/CallManager.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/CallManager.java similarity index 96% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/CallManager.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/CallManager.java index b302c1558..d0572b4d9 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/CallManager.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/CallManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,6 +23,7 @@ import net.java.sipmack.softphone.listeners.InterlocutorListener; import org.jivesoftware.resource.Res; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smackx.vcardtemp.packet.VCard; import org.jivesoftware.spark.ChatManager; import org.jivesoftware.spark.SparkManager; @@ -48,7 +45,6 @@ import java.util.Map; /** - * */ public class CallManager implements InterlocutorListener { @@ -223,7 +219,13 @@ public void interlocutorAdded(final InterlocutorUI interlocutorUI) { } // Send on phone presence - Presence onPhonePresence = new Presence(Presence.Type.available, "On the phone", 1, Presence.Mode.away); + Presence onPhonePresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .setStatus("On the phone") + .setPriority(1) + .setMode(Presence.Mode.away) + .build(); + SparkManager.getSessionManager().changePresence(onPhonePresence); interlocutorUI.getCall().addStateChangeListener(new CallListener() { @@ -323,7 +325,12 @@ public void interlocutorRemoved(final InterlocutorUI interlocutorUI) { if (offPhonePresence == null) { // Set user to available when all phone calls are hung up. - Presence availablePresence = new Presence(Presence.Type.available, "Online", 1, Presence.Mode.available); + Presence availablePresence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .setStatus("Online") + .setPriority(1) + .setMode(Presence.Mode.available) + .build(); SparkManager.getSessionManager().changePresence(availablePresence); } else { diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/ContactDetailsPanel.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/ContactDetailsPanel.java similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/ContactDetailsPanel.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/ContactDetailsPanel.java index 83507c313..207d1e16a 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/ContactDetailsPanel.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/ContactDetailsPanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -82,7 +78,7 @@ public ContactDetailsPanel(InterlocutorUI ic) { add(jobTitleLabel, new GridBagConstraints(1, 3, 2, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 2, 2), 0, 0)); // Add Avatar Label - // avatarLabel = new JLabel(SparkRes.getImageIcon(SparkRes.DEFAULT_AVATAR_64x64_IMAGE)); + // avatarLabel = new JLabel(SparkRes.getImageIcon(SparkRes.Icons.DEFAULT_AVATAR_64x64_IMAGE)); // add(avatarLabel, new GridBagConstraints(2, 4, 1, 1, 0.0, 1.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); viewProfileLabel = new LinkLabel(PhoneRes.getIString("phone.viewfullprofile"), "", Color.LIGHT_GRAY, Color.BLUE); diff --git a/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/IncomingCallUI.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/IncomingCallUI.java new file mode 100644 index 000000000..1996b502f --- /dev/null +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/IncomingCallUI.java @@ -0,0 +1,255 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkplugin.ui.call; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.image.BufferedImage; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import net.java.sipmack.sip.InterlocutorUI; +import net.java.sipmack.softphone.SoftPhoneManager; + +import org.jivesoftware.smackx.vcardtemp.packet.VCard; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.component.RolloverButton; +import org.jivesoftware.spark.plugin.phone.resource.PhoneRes; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkplugin.callhistory.HistoryCall; +import org.jivesoftware.sparkplugin.callhistory.TelephoneUtils; + + +public class IncomingCallUI extends JPanel { + + private static final long serialVersionUID = -7451049865930942296L; + private JLabel avatarLabel = new JLabel(); + private JLabel titleLabel = new JLabel(); + private JLabel professionLabel = new JLabel(); + private JLabel phoneLabel = new JLabel(); + private JLabel lastCalledLabel = new JLabel(); + private JLabel durationLabel = new JLabel(); + + private RolloverButton acceptButton; + private RolloverButton rejectButton; + + private final SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); + + + public IncomingCallUI(InterlocutorUI ic) { + setLayout(new GridBagLayout()); + + final JLabel topLabel = new JLabel(); + topLabel.setIcon(PhoneRes.getImageIcon("INCOMING_CALL_IMAGE")); + topLabel.setHorizontalTextPosition(JLabel.RIGHT); + topLabel.setFont(new Font("Dialog", Font.BOLD, 15)); + topLabel.setText(PhoneRes.getIString("phone.incomingcallfrom")+"..."); + topLabel.setForeground(Color.gray); + + + final String phoneNumber = ic.getCall().getNumber(); + + // Add Top Label + add(topLabel, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + boolean callerID = !ic.getCall().getNumber().equals(ic.getCall().getRemoteName()); + String title = ic.getCall().getRemoteName(); + if(!callerID){ + title = phoneNumber; + } + + // Add Caller Block + buildCallerBlock(title, phoneNumber); + + // Add Buttons + addButtons(); + } + + + /** + * Builds the part of the incoming call UI with the Callers information. + */ + private void buildCallerBlock(String callerID, String phoneNumber) { + final JPanel panel = new JPanel(new GridBagLayout()); + panel.setBackground(Color.white); + panel.setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230), 1)); + + // Add Avatar + panel.add(avatarLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 0, 5, 0), 0, 0)); + + // Add Avatar information + panel.add(titleLabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 0), 0, 0)); + panel.add(professionLabel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 0, 0), 0, 0)); + panel.add(phoneLabel, new GridBagConstraints(1, 2, 1, 1, 0.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 0, 0), 0, 0)); + + // Add History labels + panel.add(lastCalledLabel, new GridBagConstraints(0, 3, 2, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(15, 5, 0, 0), 0, 0)); + panel.add(durationLabel, new GridBagConstraints(0, 4, 2, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 0), 0, 0)); + + // Set default settings + titleLabel.setForeground(new Color(64, 103, 162)); + titleLabel.setFont(new Font("Dialog", Font.BOLD, 16)); + + final VCard vcard = SparkManager.getVCardManager().searchPhoneNumber(phoneNumber); + if (vcard != null) { + handleVCardInformation(vcard, phoneNumber); + } + else { + avatarLabel.setVisible(false); + professionLabel.setVisible(false); + phoneLabel.setVisible(true); + + titleLabel.setText(callerID); + phoneLabel.setText(phoneNumber); + } + + // Update with previous call history. + Date lastDate = null; + long callLength = 0; + for (HistoryCall call : SoftPhoneManager.getInstance().getLogManager().getCallHistory()) { + String number = TelephoneUtils.removeInvalidChars(call.getNumber()); + if (number.equals(TelephoneUtils.removeInvalidChars(phoneNumber))) { + lastDate = new Date(call.getTime()); + } + + callLength = call.getCallLength(); + } + + final StringBuilder builder = new StringBuilder(); + builder.append(PhoneRes.getIString("phone.lastcalled")+": "); + if (lastDate == null) { + builder.append(PhoneRes.getIString("phone.never")); + durationLabel.setVisible(false); + } + else { + builder.append(formatter.format(lastDate)); + durationLabel.setText(PhoneRes.getIString("phone.duration")+": " + ModelUtil.getTimeFromLong(callLength*1000)); + } + + lastCalledLabel.setText(builder.toString()); + + // Add To Panel + add(panel, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); + } + + private void addButtons() { + // Build Accept Button + acceptButton = new RolloverButton(" "+PhoneRes.getIString("phone.accept"), PhoneRes.getImageIcon("TOASTER_ACCEPT_BUTTON")); + acceptButton.setHorizontalTextPosition(JLabel.CENTER); + acceptButton.setFont(new Font("Dialog", Font.BOLD, 11)); + acceptButton.setForeground(new Color(91, 175, 41)); + acceptButton.setMargin(new Insets(0, 0, 0, 0)); + + // Build Reject Button + rejectButton = new RolloverButton(" "+PhoneRes.getIString("phone.reject"), PhoneRes.getImageIcon("TOASTER_REJECT_BUTTON")); + rejectButton.setHorizontalTextPosition(JLabel.CENTER); + rejectButton.setFont(new Font("Dialog", Font.BOLD, 11)); + rejectButton.setForeground(new Color(153, 32, 10)); + rejectButton.setMargin(new Insets(0, 0, 0, 0)); + + final JPanel panel = new JPanel(new GridBagLayout()); + panel.setOpaque(false); + panel.add(acceptButton, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + panel.add(rejectButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + + add(panel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + } + + private void handleVCardInformation(VCard vcard, String phoneNumber) { + if (vcard.getError() != null) { + return; + } + + + String firstName = vcard.getFirstName(); + String lastName = vcard.getLastName(); + if (ModelUtil.hasLength(firstName) && ModelUtil.hasLength(lastName)) { + titleLabel.setText(firstName + " " + lastName); + } + else if (ModelUtil.hasLength(firstName)) { + titleLabel.setText(firstName); + } + + phoneLabel.setText(phoneNumber); + + + String jobTitle = vcard.getField("TITLE"); + if (jobTitle != null) { + professionLabel.setText(jobTitle); + } + + + byte[] avatarBytes = null; + try { + avatarBytes = vcard.getAvatar(); + } + catch (Exception e) { + Log.error("Cannot retrieve avatar bytes.", e); + } + + if (avatarBytes != null) { + try { + ImageIcon avatarIcon = new ImageIcon(avatarBytes); + avatarLabel.setIcon(avatarIcon); + avatarLabel.invalidate(); + avatarLabel.validate(); + avatarLabel.repaint(); + } + catch (Exception e) { + Log.warning("Unable to generate image from avatar", e); + } + } + + + invalidate(); + validate(); + repaint(); + } + + public RolloverButton getAcceptButton() { + return acceptButton; + } + + public RolloverButton getRejectButton() { + return rejectButton; + } + + + public void paintComponent(Graphics g) { + BufferedImage cache = new BufferedImage(2, getHeight(), BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = cache.createGraphics(); + + GradientPaint paint = new GradientPaint(0, 0, new Color(233, 240, 247), 0, getHeight(), Color.white, true); + + g2d.setPaint(paint); + g2d.fillRect(0, 0, getWidth(), getHeight()); + g2d.dispose(); + + g.drawImage(cache, 0, 0, getWidth(), getHeight(), null); + } +} diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/MissedCalls.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/MissedCalls.java similarity index 99% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/MissedCalls.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/MissedCalls.java index a59e21522..c48586bfb 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/MissedCalls.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/MissedCalls.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/NonRosterPanel.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/NonRosterPanel.java similarity index 99% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/NonRosterPanel.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/NonRosterPanel.java index 47018cb26..d9945dfc4 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/NonRosterPanel.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/NonRosterPanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/OutgoingCallUI.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/OutgoingCallUI.java similarity index 99% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/OutgoingCallUI.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/OutgoingCallUI.java index ccf7a1297..e41b31824 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/OutgoingCallUI.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/OutgoingCallUI.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -208,7 +204,7 @@ else if (ModelUtil.hasLength(firstName)) { avatarLabel.repaint(); } catch (Exception e) { - // no issue + Log.warning("Unable to generate image from avatar", e); } } diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/PhonePanel.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/PhonePanel.java similarity index 96% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/PhonePanel.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/PhonePanel.java index a1ea092b2..903f245b4 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/PhonePanel.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/PhonePanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,7 +23,6 @@ import java.awt.Color; /** - * */ public abstract class PhonePanel extends JPanel implements ContainerComponent { diff --git a/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/PreviousConversationPanel.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/PreviousConversationPanel.java new file mode 100644 index 000000000..48e9561b2 --- /dev/null +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/PreviousConversationPanel.java @@ -0,0 +1,224 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.sparkplugin.ui.call; + +import org.jivesoftware.sparkplugin.callhistory.HistoryCall; +import org.jivesoftware.sparkplugin.callhistory.TelephoneUtils; +import org.jivesoftware.spark.plugin.phone.resource.PhoneRes; +import net.java.sipmack.softphone.SoftPhoneManager; +import org.jivesoftware.spark.component.TimeTrackingLabel; +import org.jivesoftware.spark.component.VerticalFlowLayout; +import org.jivesoftware.spark.util.ModelUtil; + +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.Font; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.JLabel; +import javax.swing.JPanel; + +/** + */ +public class PreviousConversationPanel extends JPanel { + + + private static final long serialVersionUID = -3462528114523564888L; + + private final Color greenColor = new Color(91, 175, 41); + + private final JLabel currentCallLabel = new JLabel(); + private final JPanel timePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 0)); + + private final JLabel today = new JLabel(); + private final JLabel statusLabel = new JLabel(); + + final JLabel previousLabel = new JLabel(PhoneRes.getIString("phone.previousconversations")+":"); + private final JLabel oldConversation = new JLabel(); + + private final SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy, h:mm a"); + + + private TimeTrackingLabel durationLabel; + + private Date startTime; + + + public PreviousConversationPanel() { + setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 5, 0, true, false)); + + setBackground(Color.white); + setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230))); + + // Set Default Color for Current Call Label + currentCallLabel.setText(PhoneRes.getIString("phone.currentcall")+":"); + currentCallLabel.setFont(new Font("Dialog", Font.BOLD, 13)); + currentCallLabel.setForeground(greenColor); + + // Set default color for previous label. + previousLabel.setForeground(new Color(64, 103, 162)); + previousLabel.setFont(new Font("Dialog", Font.BOLD, 13)); + + statusLabel.setFont(new Font("Dialog", Font.BOLD, 12)); + + // Add Duration timer + durationLabel = new TimeTrackingLabel(new Date(), this); + durationLabel.setFont(new Font("Dialog", Font.BOLD, 12)); + durationLabel.stopTimer(); + + // Build Time Panel + + timePanel.setOpaque(false); + + today.setForeground(Color.black); + today.setFont(new Font("Dialog", Font.PLAIN, 12)); + + today.setText(formatter.format(new Date()) + " - "+PhoneRes.getIString("phone.time")+": "); + timePanel.add(today); + timePanel.add(durationLabel); + + oldConversation.setForeground(new Color(211, 0, 0)); + oldConversation.setFont(new Font("Dialog", Font.BOLD, 12)); + + } + + /** + * Builds the previous history list. + * + * @param phoneNumber the phone number to use for history checking. + */ + public void addPreviousConversations(String phoneNumber) { + startTime = new Date(); + + currentCallLabel.setText(PhoneRes.getIString("phone.currentcall")+":"); + currentCallLabel.setFont(new Font("Dialog", Font.BOLD, 13)); + currentCallLabel.setForeground(greenColor); + + today.setText(formatter.format(new Date()) + " - "+PhoneRes.getIString("phone.time")+": "); + + // Add Current Call and Time Panel + add(currentCallLabel); + add(timePanel); + add(statusLabel); + statusLabel.setVisible(false); + + // Give some space. + add(new JLabel()); + + add(previousLabel); + + add(oldConversation); + + + int count = 0; + final List calls = new ArrayList(SoftPhoneManager.getInstance().getLogManager().getCallHistory()); + Collections.sort(calls, itemComparator); + + for (HistoryCall call : calls){ + String number = TelephoneUtils.removeInvalidChars(call.getNumber()); + if (number.equals(TelephoneUtils.removeInvalidChars(phoneNumber))) { + count++; + if (count > 4) { + break; + } + + final Date callDate = new Date(call.getTime()); + final long duration = call.getCallLength(); + + StringBuilder builder = new StringBuilder(); + builder.append(formatter.format(callDate)); + builder.append(" "); + builder.append("("); + builder.append(ModelUtil.getTimeFromLong(duration*1000)); + builder.append(")"); + + final JLabel callLabel = new JLabel(builder.toString()); + callLabel.setForeground(Color.black); + callLabel.setFont(new Font("Dialog", Font.PLAIN, 12)); + add(callLabel); + } + } + + if (count == 0) { + final JLabel label = new JLabel(PhoneRes.getIString("phone.noprevious")); + label.setForeground(Color.gray); + add(label); + } + + durationLabel.resetTime(); + durationLabel.startTimer(); + + invalidate(); + validate(); + repaint(); + } + + public void callEnded() { + durationLabel.stopTimer(); + + currentCallLabel.setForeground(Color.black); + currentCallLabel.setText(PhoneRes.getIString("phone.callended")); + + today.setText(PhoneRes.getIString("phone.time")+": "); + } + + public void transferring() { + statusLabel.setText(PhoneRes.getIString("phone.transferring")); + statusLabel.setVisible(true); + } + + public void transfer(String user) { + durationLabel.stopTimer(); + statusLabel.setVisible(false); + + currentCallLabel.setForeground(Color.black); + currentCallLabel.setText(PhoneRes.getIString("phone.callended")); + + today.setText(PhoneRes.getIString("phone.time")+": "); + currentCallLabel.setText(PhoneRes.getIString("phone.transferto") + " " + user); + + Date now = new Date(); + final SimpleDateFormat timeFormatter = new SimpleDateFormat("h:mm"); + + + String end = timeFormatter.format(now); + + oldConversation.setText(formatter.format(startTime) + " - " + end + " (" + durationLabel.getText() + ")"); + } + + final Comparator itemComparator = new Comparator() { + public int compare(HistoryCall contactItemOne, HistoryCall contactItemTwo) { + final HistoryCall time1 = contactItemOne; + final HistoryCall time2 = contactItemTwo; + if (time1.getTime() < time2.getTime()) { + return 1; + } + else if (time1.getTime() > time2.getTime()) { + return -1; + } + return 0; + + } + }; + +} diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/RecentCallsPanel.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/RecentCallsPanel.java similarity index 97% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/RecentCallsPanel.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/RecentCallsPanel.java index b6cb7fe31..96387aab9 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/RecentCallsPanel.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/RecentCallsPanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -92,7 +88,7 @@ public CallEntry(String title, Date time) { descriptionLabel.setForeground(Color.gray); descriptionLabel.setFont(new Font("Dialog", Font.PLAIN, 11)); - final JLabel imageLabel = new JLabel(SparkRes.getImageIcon(SparkRes.SMALL_PIN_BLUE)); + final JLabel imageLabel = new JLabel(SparkRes.getImageIcon(SparkRes.Icons.SMALL_PIN_BLUE)); imageLabel.setHorizontalTextPosition(JLabel.LEFT); imageLabel.setHorizontalAlignment(JLabel.LEFT); add(imageLabel, new GridBagConstraints(0, 0, 1, 2, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/RosterMemberPanel.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/RosterMemberPanel.java similarity index 99% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/RosterMemberPanel.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/RosterMemberPanel.java index 951909e2d..a6afb87da 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/RosterMemberPanel.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/RosterMemberPanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/SoftPhoneTabHandler.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/SoftPhoneTabHandler.java similarity index 97% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/SoftPhoneTabHandler.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/SoftPhoneTabHandler.java index e12aaf8e7..08d0a1a6e 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/SoftPhoneTabHandler.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/call/SoftPhoneTabHandler.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,7 +29,6 @@ import java.awt.Component; /** - * */ public class SoftPhoneTabHandler extends SparkTabHandler { private SoftPhoneManager manager; @@ -71,7 +66,7 @@ private void handlePhoneCall(CallRoomState state, SparkTab tab, Component compon // Check if is typing. if (isTyping) { - tab.setIcon(SparkRes.getImageIcon(SparkRes.SMALL_MESSAGE_EDIT_IMAGE)); + tab.setIcon(SparkRes.getImageIcon(SparkRes.Icons.SMALL_MESSAGE_EDIT_IMAGE)); } else if (CallRoomState.inCall == state) { tab.setIcon(PhoneRes.getImageIcon("RECEIVER2_IMAGE")); diff --git a/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/components/ControlPanel.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/components/ControlPanel.java new file mode 100644 index 000000000..b50697fc8 --- /dev/null +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/components/ControlPanel.java @@ -0,0 +1,58 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkplugin.ui.components; + +import java.awt.Color; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.LayoutManager; +import java.awt.image.BufferedImage; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; + +/** + * Base Panel for Controls. + * + * @author Derek DeMoro + */ +public class ControlPanel extends JPanel { + + private static final long serialVersionUID = -8596701082529183291L; + + public ControlPanel() { + setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230))); + } + + public ControlPanel(LayoutManager layout) { + super(layout); + setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230))); + } + + public void paintComponent(Graphics g) { + final BufferedImage bufferedImage = new BufferedImage(2, getHeight(), BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = bufferedImage.createGraphics(); + + GradientPaint paint = new GradientPaint(0, 0, Color.white, 0, getHeight(), new Color(235, 241, 246), true); + + g2d.setPaint(paint); + g2d.fillRect(0, 0, getWidth(), getHeight()); + g2d.dispose(); + + g.drawImage(bufferedImage, 0, 0, getWidth(), getHeight(), null); + } +} diff --git a/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/components/JavaMixer.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/components/JavaMixer.java new file mode 100644 index 000000000..7c0e820d1 --- /dev/null +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/components/JavaMixer.java @@ -0,0 +1,488 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.sparkplugin.ui.components; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.BooleanControl; +import javax.sound.sampled.CompoundControl; +import javax.sound.sampled.Control; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.EnumControl; +import javax.sound.sampled.FloatControl; +import javax.sound.sampled.Line; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.Port; +import javax.swing.AbstractButton; +import javax.swing.BoundedRangeModel; +import javax.swing.ButtonModel; +import javax.swing.DefaultBoundedRangeModel; +import javax.swing.DefaultButtonModel; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.JTree; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; + +/** + * Pure Java Audio Mixer. Control Volume and Settings for any Sound device in the OS. + * + * @author Thiago Camargo + */ + +public class JavaMixer { + + private static final Line.Info[] EMPTY_PORT_INFO_ARRAY = new Line.Info[0]; + DefaultMutableTreeNode root = new DefaultMutableTreeNode("Sound Mixers", true); + JTree tree = new JTree(root); + + public JavaMixer() { + List portMixers = getPortMixers(); + if (portMixers.size() == 0) System.err.println("No Mixers Found."); + for (Mixer mixer : portMixers) { + JavaMixer.MixerNode mixerNode = new JavaMixer.MixerNode(mixer); + createMixerChildren(mixerNode); + root.add(mixerNode); + } + } + + public JTree getTree() { + return tree; + } + + public Component getPrefferedMasterVolume() { + TreePath path = findByName(new TreePath(root), new String[]{"SPEAKER", "Volume"}); + + if (path == null) { + path = findByName(new TreePath(root), new String[]{"Master target", "Master", "Mute"}); + } + + if (path != null) { + if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) + return ((JavaMixer.ControlNode) path.getLastPathComponent()).getComponent(); + } + return null; + } + + public Component getPrefferedInputVolume() { + TreePath path = findByName(new TreePath(root), new String[]{"MICROPHONE", "Volume"}); + + if (path == null) { + path = findByName(new TreePath(root), new String[]{"Capture source", "Capture", "Volume"}); + } + + if (path != null) { + if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) + return ((JavaMixer.ControlNode) path.getLastPathComponent()).getComponent(); + } + return null; + } + + public void setMicrophoneInput() { + TreePath path = findByName(new TreePath(root), new String[]{"MICROPHONE", "Select"}); + + if (path == null) { + path = findByName(new TreePath(root), new String[]{"Capture source", "Capture", "Mute"}); + } + + if (path != null) { + if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) { + BooleanControl bControl = (BooleanControl) (((JavaMixer.ControlNode) path.getLastPathComponent()).getControl()); + bControl.setValue(true); + } + } + } + + public void setMuteForMicrophoneOutput() { + TreePath path = findByName(new TreePath(root), new String[]{"SPEAKER", "Microfone", "Mute"}); + + if (path == null) { + path = findByName(new TreePath(root), new String[]{"MIC target", "mic", "Mute"}); + } + + if (path != null) { + if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) { + BooleanControl bControl = (BooleanControl) (((JavaMixer.ControlNode) path.getLastPathComponent()).getControl()); + bControl.setValue(true); + } + } + } + + /** + * Returns the Mixers that support Port lines. + * + * @return List Port Mixers + */ + private List getPortMixers() { + List supportingMixers = new ArrayList(); + Mixer.Info[] aMixerInfos = AudioSystem.getMixerInfo(); + for (Mixer.Info aMixerInfo : aMixerInfos) { + Mixer mixer = AudioSystem.getMixer(aMixerInfo); + boolean bSupportsPorts = arePortsSupported(mixer); + if (bSupportsPorts) { + supportingMixers.add(mixer); + } + } + return supportingMixers; + } + + private boolean arePortsSupported(Mixer mixer) { + Line.Info[] infos; + infos = mixer.getSourceLineInfo(); + for (Line.Info info : infos) { + if (info instanceof Port.Info) { + return true; + } else if (info instanceof DataLine.Info) { + return true; + } + } + infos = mixer.getTargetLineInfo(); + for (Line.Info info : infos) { + if (info instanceof Port.Info) { + return true; + } else if (info instanceof DataLine.Info) { + return true; + } + } + return false; + } + + private void createMixerChildren(JavaMixer.MixerNode mixerNode) { + Mixer mixer = mixerNode.getMixer(); + Line.Info[] infosToCheck = getPortInfo(mixer); + + for (Line.Info anInfosToCheck : infosToCheck) { + if (mixer.isLineSupported(anInfosToCheck)) { + Port port = null; + DataLine dLine = null; + + int maxLines = mixer.getMaxLines(anInfosToCheck); + // Workaround to prevent a JVM crash on Mac OS X (Intel) 1.5.0_07 JVM + if (maxLines > 0) { + try { + if (anInfosToCheck instanceof Port.Info) { + port = (Port) mixer.getLine(anInfosToCheck); + port.open(); + } + else if (anInfosToCheck instanceof DataLine.Info) { + dLine = (DataLine) mixer.getLine(anInfosToCheck); + if (!dLine.isOpen()) { + dLine.open(); + } + } + } + catch (LineUnavailableException e) { + // Do Nothing + } + catch (Exception e) { + // Do Nothing + } + } + if (port != null) { + JavaMixer.PortNode portNode = new JavaMixer.PortNode(port); + createPortChildren(portNode); + mixerNode.add(portNode); + } else if (dLine != null) { + JavaMixer.PortNode portNode = new JavaMixer.PortNode(dLine); + createPortChildren(portNode); + mixerNode.add(portNode); + } + } + } + } + + private Line.Info[] getPortInfo(Mixer mixer) { + Line.Info[] infos; + List portInfoList = new ArrayList(); + infos = mixer.getSourceLineInfo(); + for (Line.Info info : infos) { + if (info instanceof Port.Info || info instanceof DataLine.Info) { + portInfoList.add((Line.Info) info); + } + } + infos = mixer.getTargetLineInfo(); + for (Line.Info info1 : infos) { + if (info1 instanceof Port.Info || info1 instanceof DataLine.Info) { + portInfoList.add((Line.Info) info1); + } + } + return portInfoList.toArray(EMPTY_PORT_INFO_ARRAY); + } + + private void createPortChildren(JavaMixer.PortNode portNode) { + Control[] aControls = portNode.getPort().getControls(); + for (Control aControl : aControls) { + JavaMixer.ControlNode controlNode = new JavaMixer.ControlNode(aControl); + createControlChildren(controlNode); + portNode.add(controlNode); + } + } + + private void createControlChildren(JavaMixer.ControlNode controlNode) { + if (controlNode.getControl() instanceof CompoundControl) { + CompoundControl control = (CompoundControl) controlNode.getControl(); + Control[] aControls = control.getMemberControls(); + for (Control con : aControls) { + JavaMixer.ControlNode conNode = new JavaMixer.ControlNode(con); + createControlChildren(conNode); + controlNode.add(conNode); + } + } + } + + /** + * Returns whether the type of a FloatControl is BALANCE or PAN. + * + * @param control FloatControl control + * @return boolean is Balance or Pan + */ + private static boolean isBalanceOrPan(FloatControl control) { + Control.Type type = control.getType(); + return type.equals(FloatControl.Type.PAN) || type.equals(FloatControl.Type.BALANCE); + } + + public class MixerNode extends DefaultMutableTreeNode { + + private static final long serialVersionUID = 5514718793497318648L; + Mixer mixer; + + public MixerNode(Mixer mixer) { + super(mixer.getMixerInfo(), true); + this.mixer = mixer; + } + + public Mixer getMixer() { + return mixer; + } + + } + + public class PortNode extends DefaultMutableTreeNode { + + private static final long serialVersionUID = -4388437363589688167L; + Line port; + + public PortNode(Line port) { + super(port.getLineInfo(), true); + this.port = port; + } + + public Line getPort() { + return port; + } + + } + + public class ControlNode extends DefaultMutableTreeNode { + + private static final long serialVersionUID = 8840473247266403685L; + Control control; + Component component; + + public ControlNode(Control control) { + super(control.getType(), true); + this.control = control; + if (control instanceof BooleanControl) { + component = createControlComponent((BooleanControl) control); + } else if (control instanceof EnumControl) { + component = createControlComponent((EnumControl) control); + } else if (control instanceof FloatControl) { + component = createControlComponent((FloatControl) control); + } else { + component = null; + } + } + + public Control getControl() { + return control; + } + + public Component getComponent() { + return component; + } + + private JComponent createControlComponent(BooleanControl control) { + AbstractButton button; + String strControlName = control.getType().toString(); + ButtonModel model = new JavaMixer.BooleanControlButtonModel(control); + button = new JCheckBox(strControlName); + button.setModel(model); + return button; + } + + private JComponent createControlComponent(EnumControl control) { + JPanel component = new JPanel(); + String strControlName = control.getType().toString(); + component.setBorder(new TitledBorder(new EtchedBorder(), strControlName)); + return component; + } + + private JComponent createControlComponent(FloatControl control) { + int orientation = isBalanceOrPan(control) ? JSlider.HORIZONTAL : JSlider.VERTICAL; + BoundedRangeModel model = new JavaMixer.FloatControlBoundedRangeModel(control); + JSlider slider = new JSlider(model); + slider.setOrientation(orientation); + slider.setPaintLabels(true); + slider.setPaintTicks(true); + slider.setSize(10, 50); + return slider; + } + + } + + public class BooleanControlButtonModel extends DefaultButtonModel { + private static final long serialVersionUID = -8264153878420797906L; + private BooleanControl control; + + public BooleanControlButtonModel(BooleanControl control) { + this.control = control; + this.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setSelected(!isSelected()); + } + }); + } + + public void setSelected(boolean bSelected) { + control.setValue(bSelected); + } + + public boolean isSelected() { + return control.getValue(); + } + } + + public class FloatControlBoundedRangeModel extends DefaultBoundedRangeModel { + + private static final long serialVersionUID = 7826447995854231838L; + private FloatControl control; + private float factor; + + public FloatControlBoundedRangeModel(FloatControl control) { + this.control = control; + float range = 100; + float steps = range / 100; + factor = range / steps; + int min = (int) (control.getMinimum() * factor); + int max = (int) (control.getMaximum() * factor); + int value = (int) (control.getValue() * factor); + setRangeProperties(value, 0, min, max, false); + } + + private float getScaleFactor() { + return factor; + } + + public void setValue(int nValue) { + super.setValue(nValue); + control.setValue((float) nValue / getScaleFactor()); + } + + public int getValue() { + return (int) (control.getValue() * getScaleFactor()); + } + + } + + public static void main(String[] args) { + final JavaMixer sm = new JavaMixer(); + final JFrame jf = new JFrame("Mixer Test"); + final JPanel jp = new JPanel(); + jf.add(jp); + jp.add(sm.getTree()); + jf.setSize(600, 500); + jf.setVisible(true); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + sm.getTree().addTreeSelectionListener(new TreeSelectionListener() { + public void valueChanged(TreeSelectionEvent e) { + TreePath path = e.getPath(); + if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) { + JavaMixer.ControlNode controlNode = (JavaMixer.ControlNode) path.getLastPathComponent(); + if (!(controlNode.getControl() instanceof CompoundControl)) { + if (jp.getComponentCount() > 1) + jp.remove(1); + jp.add(controlNode.getComponent(), 1); + jp.repaint(); + } + } + } + }); + jp.add(sm.getPrefferedMasterVolume()); + jp.add(sm.getPrefferedMasterVolume()); + jp.add(sm.getPrefferedInputVolume()); + jp.repaint(); + sm.setMicrophoneInput(); + sm.setMuteForMicrophoneOutput(); + } + + public TreePath find(TreePath path, Object[] nodes) { + return find2(path, nodes, 0, false); + } + + public TreePath findByName(TreePath path, String[] names) { + return find2(path, names, 0, true); + } + + private TreePath find2(TreePath parent, Object[] nodes, int depth, boolean byName) { + TreeNode node = (TreeNode) parent.getLastPathComponent(); + if (depth > nodes.length - 1) { + return parent; + } + + if (node.getChildCount() >= 0) { + for (Enumeration e = node.children(); e.hasMoreElements();) { + TreeNode n = e.nextElement(); + TreePath path = parent.pathByAddingChild(n); + boolean find; + + if (byName) { + find = n.toString().toUpperCase().indexOf(nodes[depth].toString().toUpperCase()) > -1; + } else { + find = n.equals(nodes[depth]); + } + + if (find) { + TreePath result = find2(path, nodes, depth + 1, byName); + if (result != null) { + return result; + } + } else { + TreePath result = find2(path, nodes, depth, byName); + if (result != null) { + return result; + } + } + } + } + + return null; + } +} diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/components/RectangleButton.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/components/RectangleButton.java similarity index 97% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/components/RectangleButton.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/components/RectangleButton.java index 1accf6934..96c54623a 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/components/RectangleButton.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/components/RectangleButton.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,7 +29,6 @@ import javax.swing.JLabel; /** - * */ public class RectangleButton extends JButton implements MouseListener { diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/components/RoundLabel.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/components/RoundLabel.java similarity index 99% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/components/RoundLabel.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/components/RoundLabel.java index 2ba9b727c..69ac68eff 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/components/RoundLabel.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/components/RoundLabel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/components/SnapWindow.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/components/SnapWindow.java similarity index 98% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/components/SnapWindow.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/components/SnapWindow.java index 81625fd64..a6f8d079c 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/components/SnapWindow.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/components/SnapWindow.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/transfer/TransferGroupUI.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/transfer/TransferGroupUI.java similarity index 90% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/transfer/TransferGroupUI.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/transfer/TransferGroupUI.java index faa7ad6bf..c5567134a 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/transfer/TransferGroupUI.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/transfer/TransferGroupUI.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,25 +15,23 @@ */ package org.jivesoftware.sparkplugin.ui.transfer; -import org.jivesoftware.spark.plugin.phone.resource.PhoneRes; -import org.jivesoftware.sparkplugin.callhistory.TelephoneUtils; import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.roster.Roster; import org.jivesoftware.smack.roster.RosterEntry; import org.jivesoftware.smack.roster.RosterGroup; -import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smackx.vcardtemp.packet.VCard; import org.jivesoftware.spark.PresenceManager; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.component.RolloverButton; import org.jivesoftware.spark.component.VerticalFlowLayout; +import org.jivesoftware.spark.plugin.phone.resource.PhoneRes; +import org.jivesoftware.spark.util.log.Log; import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.sparkplugin.callhistory.TelephoneUtils; -import java.awt.Color; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; +import javax.swing.*; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; @@ -46,14 +40,6 @@ import java.util.Comparator; import java.util.List; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.Icon; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.UIManager; - /** * The UI that represents one group within the users Roster. */ @@ -73,7 +59,7 @@ public TransferGroupUI(String groupName) { setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); setBackground(Color.white); - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); + Roster roster = SparkManager.getRoster(); final RosterGroup rosterGroup = roster.getGroup(groupName); final List entries = new ArrayList(rosterGroup.getEntries()); @@ -93,7 +79,6 @@ public TransferGroupUI(String groupName) { private class UserEntry extends JPanel { /** - * */ private static final long serialVersionUID = 1L; private String name; @@ -103,7 +88,7 @@ private class UserEntry extends JPanel { public UserEntry(RosterEntry entry) { setLayout(new GridBagLayout()); - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); + Roster roster = SparkManager.getRoster(); Presence presence = roster.getPresence(entry.getUser()); Icon icon = PresenceManager.getIconFromPresence(presence); @@ -270,9 +255,18 @@ public void removeTransferListener(TransferListener listener) { /** * Notifies all TransferListeners that a number has been selected. */ - public void fireTransferListeners(String number) { - for (TransferListener listener : listeners) { - listener.numberSelected(number); + public void fireTransferListeners( String number ) + { + for ( TransferListener listener : listeners ) + { + try + { + listener.numberSelected( number ); + } + catch ( Exception e ) + { + Log.error( "A TransferListener (" + listener + ") threw an exception while processing a 'numberSelected' event (number: " + number + ").", e ); + } } } @@ -281,9 +275,7 @@ public void fireTransferListeners(String number) { */ final Comparator entryComparator = new Comparator() { public int compare(RosterEntry one, RosterEntry two) { - final RosterEntry entryOne = one; - final RosterEntry entryTwo = two; - return entryOne.getName().toLowerCase().compareTo(entryTwo.getName().toLowerCase()); + return one.getName().compareToIgnoreCase(two.getName()); } }; diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/transfer/TransferListener.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/transfer/TransferListener.java similarity index 95% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/transfer/TransferListener.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/transfer/TransferListener.java index e25516192..4ef330292 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/transfer/TransferListener.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/transfer/TransferListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/transfer/TransferManager.java b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/transfer/TransferManager.java similarity index 97% rename from src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/transfer/TransferManager.java rename to plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/transfer/TransferManager.java index 0c3cafb3c..4f0857e84 100644 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/transfer/TransferManager.java +++ b/plugins/sip/src/main/java/org/jivesoftware/sparkplugin/ui/transfer/TransferManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -69,7 +65,7 @@ public TransferManager() { setLayout(new GridBagLayout()); setBackground(Color.white); - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); + Roster roster = SparkManager.getRoster(); callField = new TelephoneTextField(); diff --git a/plugins/sip/src/main/plugin-metadata/plugin.xml b/plugins/sip/src/main/plugin-metadata/plugin.xml new file mode 100644 index 000000000..de7ca6b7f --- /dev/null +++ b/plugins/sip/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,14 @@ + + + ${project.name} + ${project.version} + ${project.description} + Thiago + https://IgniteRealtime.org + support@IgniteRealtime.org + org.jivesoftware.sparkplugin.SoftPhonePlugin + 3.1.0 + Windows,Mac,Linux + 11 + + diff --git a/src/plugins/sip/src/resources/images/CallStart_16x16.png b/plugins/sip/src/main/resources/images/CallStart_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/CallStart_16x16.png rename to plugins/sip/src/main/resources/images/CallStart_16x16.png diff --git a/src/plugins/sip/src/resources/images/CallStart_24x24.png b/plugins/sip/src/main/resources/images/CallStart_24x24.png similarity index 100% rename from src/plugins/sip/src/resources/images/CallStart_24x24.png rename to plugins/sip/src/main/resources/images/CallStart_24x24.png diff --git a/src/plugins/sip/src/resources/images/Error.gif b/plugins/sip/src/main/resources/images/Error.gif similarity index 100% rename from src/plugins/sip/src/resources/images/Error.gif rename to plugins/sip/src/main/resources/images/Error.gif diff --git a/src/plugins/sip/src/resources/images/Inform.gif b/plugins/sip/src/main/resources/images/Inform.gif similarity index 100% rename from src/plugins/sip/src/resources/images/Inform.gif rename to plugins/sip/src/main/resources/images/Inform.gif diff --git a/plugins/sip/src/main/resources/images/add_number.png b/plugins/sip/src/main/resources/images/add_number.png new file mode 100644 index 000000000..51fad3aa0 Binary files /dev/null and b/plugins/sip/src/main/resources/images/add_number.png differ diff --git a/src/resources/images/address_book.png b/plugins/sip/src/main/resources/images/address_book.png similarity index 100% rename from src/resources/images/address_book.png rename to plugins/sip/src/main/resources/images/address_book.png diff --git a/src/plugins/sip/src/resources/images/at.gif b/plugins/sip/src/main/resources/images/at.gif similarity index 100% rename from src/plugins/sip/src/resources/images/at.gif rename to plugins/sip/src/main/resources/images/at.gif diff --git a/src/plugins/sip/src/resources/images/briefcase.png b/plugins/sip/src/main/resources/images/briefcase.png similarity index 100% rename from src/plugins/sip/src/resources/images/briefcase.png rename to plugins/sip/src/main/resources/images/briefcase.png diff --git a/src/plugins/sip/src/resources/images/btn_dialpad-down.png b/plugins/sip/src/main/resources/images/btn_dialpad-down.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_dialpad-down.png rename to plugins/sip/src/main/resources/images/btn_dialpad-down.png diff --git a/src/plugins/sip/src/resources/images/btn_dialpad-hover.png b/plugins/sip/src/main/resources/images/btn_dialpad-hover.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_dialpad-hover.png rename to plugins/sip/src/main/resources/images/btn_dialpad-hover.png diff --git a/src/plugins/sip/src/resources/images/btn_dialpad.png b/plugins/sip/src/main/resources/images/btn_dialpad.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_dialpad.png rename to plugins/sip/src/main/resources/images/btn_dialpad.png diff --git a/plugins/sip/src/main/resources/images/btn_dialpad_background.png b/plugins/sip/src/main/resources/images/btn_dialpad_background.png new file mode 100644 index 000000000..16f74140d Binary files /dev/null and b/plugins/sip/src/main/resources/images/btn_dialpad_background.png differ diff --git a/src/plugins/sip/src/resources/images/btn_phone-big-down.png b/plugins/sip/src/main/resources/images/btn_phone-big-down.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-big-down.png rename to plugins/sip/src/main/resources/images/btn_phone-big-down.png diff --git a/src/plugins/sip/src/resources/images/btn_phone-big-hover.png b/plugins/sip/src/main/resources/images/btn_phone-big-hover.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-big-hover.png rename to plugins/sip/src/main/resources/images/btn_phone-big-hover.png diff --git a/src/plugins/sip/src/resources/images/btn_phone-big.png b/plugins/sip/src/main/resources/images/btn_phone-big.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-big.png rename to plugins/sip/src/main/resources/images/btn_phone-big.png diff --git a/plugins/sip/src/main/resources/images/btn_phone-dial-disabled_24x24.png b/plugins/sip/src/main/resources/images/btn_phone-dial-disabled_24x24.png new file mode 100644 index 000000000..4f999fea6 Binary files /dev/null and b/plugins/sip/src/main/resources/images/btn_phone-dial-disabled_24x24.png differ diff --git a/src/plugins/sip/src/resources/images/btn_phone-dial-down_24x24.png b/plugins/sip/src/main/resources/images/btn_phone-dial-down_24x24.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-dial-down_24x24.png rename to plugins/sip/src/main/resources/images/btn_phone-dial-down_24x24.png diff --git a/src/plugins/sip/src/resources/images/btn_phone-dial-hover_24x24.png b/plugins/sip/src/main/resources/images/btn_phone-dial-hover_24x24.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-dial-hover_24x24.png rename to plugins/sip/src/main/resources/images/btn_phone-dial-hover_24x24.png diff --git a/src/plugins/sip/src/resources/images/btn_phone-dial_24x24.png b/plugins/sip/src/main/resources/images/btn_phone-dial_24x24.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-dial_24x24.png rename to plugins/sip/src/main/resources/images/btn_phone-dial_24x24.png diff --git a/src/plugins/sip/src/resources/images/btn_phone-hangup-big-down.png b/plugins/sip/src/main/resources/images/btn_phone-hangup-big-down.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-hangup-big-down.png rename to plugins/sip/src/main/resources/images/btn_phone-hangup-big-down.png diff --git a/src/plugins/sip/src/resources/images/btn_phone-hangup-big-hover.png b/plugins/sip/src/main/resources/images/btn_phone-hangup-big-hover.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-hangup-big-hover.png rename to plugins/sip/src/main/resources/images/btn_phone-hangup-big-hover.png diff --git a/src/plugins/sip/src/resources/images/btn_phone-hangup-big.png b/plugins/sip/src/main/resources/images/btn_phone-hangup-big.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-hangup-big.png rename to plugins/sip/src/main/resources/images/btn_phone-hangup-big.png diff --git a/plugins/sip/src/main/resources/images/btn_phone-hangup.png b/plugins/sip/src/main/resources/images/btn_phone-hangup.png new file mode 100644 index 000000000..df529a5fa Binary files /dev/null and b/plugins/sip/src/main/resources/images/btn_phone-hangup.png differ diff --git a/plugins/sip/src/main/resources/images/btn_phone-hangup_24x24.png b/plugins/sip/src/main/resources/images/btn_phone-hangup_24x24.png new file mode 100644 index 000000000..0550f7321 Binary files /dev/null and b/plugins/sip/src/main/resources/images/btn_phone-hangup_24x24.png differ diff --git a/src/plugins/sip/src/resources/images/btn_phone-redial-big-down.png b/plugins/sip/src/main/resources/images/btn_phone-redial-big-down.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-redial-big-down.png rename to plugins/sip/src/main/resources/images/btn_phone-redial-big-down.png diff --git a/src/plugins/sip/src/resources/images/btn_phone-redial-big-hover.png b/plugins/sip/src/main/resources/images/btn_phone-redial-big-hover.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-redial-big-hover.png rename to plugins/sip/src/main/resources/images/btn_phone-redial-big-hover.png diff --git a/plugins/sip/src/main/resources/images/btn_phone-redial-big.png b/plugins/sip/src/main/resources/images/btn_phone-redial-big.png new file mode 100644 index 000000000..ee7f29d8f Binary files /dev/null and b/plugins/sip/src/main/resources/images/btn_phone-redial-big.png differ diff --git a/src/plugins/sip/src/resources/images/btn_phone-reg_close-down.png b/plugins/sip/src/main/resources/images/btn_phone-reg_close-down.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-reg_close-down.png rename to plugins/sip/src/main/resources/images/btn_phone-reg_close-down.png diff --git a/plugins/sip/src/main/resources/images/btn_phone-reg_close-hover.png b/plugins/sip/src/main/resources/images/btn_phone-reg_close-hover.png new file mode 100644 index 000000000..18984613f Binary files /dev/null and b/plugins/sip/src/main/resources/images/btn_phone-reg_close-hover.png differ diff --git a/plugins/sip/src/main/resources/images/btn_phone-reg_close.png b/plugins/sip/src/main/resources/images/btn_phone-reg_close.png new file mode 100644 index 000000000..ba3289bdf Binary files /dev/null and b/plugins/sip/src/main/resources/images/btn_phone-reg_close.png differ diff --git a/src/plugins/sip/src/resources/images/btn_phone-reg_retry-down.png b/plugins/sip/src/main/resources/images/btn_phone-reg_retry-down.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-reg_retry-down.png rename to plugins/sip/src/main/resources/images/btn_phone-reg_retry-down.png diff --git a/src/plugins/sip/src/resources/images/btn_phone-reg_retry-hover.png b/plugins/sip/src/main/resources/images/btn_phone-reg_retry-hover.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-reg_retry-hover.png rename to plugins/sip/src/main/resources/images/btn_phone-reg_retry-hover.png diff --git a/src/plugins/sip/src/resources/images/btn_phone-reg_retry.png b/plugins/sip/src/main/resources/images/btn_phone-reg_retry.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-reg_retry.png rename to plugins/sip/src/main/resources/images/btn_phone-reg_retry.png diff --git a/src/plugins/sip/src/resources/images/btn_phone-sm-down.png b/plugins/sip/src/main/resources/images/btn_phone-sm-down.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-sm-down.png rename to plugins/sip/src/main/resources/images/btn_phone-sm-down.png diff --git a/src/plugins/sip/src/resources/images/btn_phone-sm-hover.png b/plugins/sip/src/main/resources/images/btn_phone-sm-hover.png similarity index 100% rename from src/plugins/sip/src/resources/images/btn_phone-sm-hover.png rename to plugins/sip/src/main/resources/images/btn_phone-sm-hover.png diff --git a/plugins/sip/src/main/resources/images/btn_phone-sm.png b/plugins/sip/src/main/resources/images/btn_phone-sm.png new file mode 100644 index 000000000..8335166df Binary files /dev/null and b/plugins/sip/src/main/resources/images/btn_phone-sm.png differ diff --git a/src/plugins/sip/src/resources/images/callIn_16x16.png b/plugins/sip/src/main/resources/images/callIn_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/callIn_16x16.png rename to plugins/sip/src/main/resources/images/callIn_16x16.png diff --git a/plugins/sip/src/main/resources/images/callList_16x16.png b/plugins/sip/src/main/resources/images/callList_16x16.png new file mode 100644 index 000000000..2c4923aed Binary files /dev/null and b/plugins/sip/src/main/resources/images/callList_16x16.png differ diff --git a/plugins/sip/src/main/resources/images/callOut_32x32.png b/plugins/sip/src/main/resources/images/callOut_32x32.png new file mode 100644 index 000000000..9b05e15b7 Binary files /dev/null and b/plugins/sip/src/main/resources/images/callOut_32x32.png differ diff --git a/src/plugins/sip/src/resources/images/card.gif b/plugins/sip/src/main/resources/images/card.gif similarity index 100% rename from src/plugins/sip/src/resources/images/card.gif rename to plugins/sip/src/main/resources/images/card.gif diff --git a/plugins/sip/src/main/resources/images/close_dark.png b/plugins/sip/src/main/resources/images/close_dark.png new file mode 100644 index 000000000..9bd280724 Binary files /dev/null and b/plugins/sip/src/main/resources/images/close_dark.png differ diff --git a/src/plugins/sip/src/resources/images/comp.gif b/plugins/sip/src/main/resources/images/comp.gif similarity index 100% rename from src/plugins/sip/src/resources/images/comp.gif rename to plugins/sip/src/main/resources/images/comp.gif diff --git a/plugins/sip/src/main/resources/images/contact_48x48.png b/plugins/sip/src/main/resources/images/contact_48x48.png new file mode 100644 index 000000000..2f398cf1f Binary files /dev/null and b/plugins/sip/src/main/resources/images/contact_48x48.png differ diff --git a/plugins/sip/src/main/resources/images/del_number.png b/plugins/sip/src/main/resources/images/del_number.png new file mode 100644 index 000000000..0a163888c Binary files /dev/null and b/plugins/sip/src/main/resources/images/del_number.png differ diff --git a/plugins/sip/src/main/resources/images/delete_24x24.png b/plugins/sip/src/main/resources/images/delete_24x24.png new file mode 100644 index 000000000..0a163888c Binary files /dev/null and b/plugins/sip/src/main/resources/images/delete_24x24.png differ diff --git a/plugins/sip/src/main/resources/images/delete_32x32.png b/plugins/sip/src/main/resources/images/delete_32x32.png new file mode 100644 index 000000000..25854d688 Binary files /dev/null and b/plugins/sip/src/main/resources/images/delete_32x32.png differ diff --git a/plugins/sip/src/main/resources/images/dial.png b/plugins/sip/src/main/resources/images/dial.png new file mode 100644 index 000000000..bf0014f9a Binary files /dev/null and b/plugins/sip/src/main/resources/images/dial.png differ diff --git a/src/plugins/sip/src/resources/images/dial_number.png b/plugins/sip/src/main/resources/images/dial_number.png similarity index 100% rename from src/plugins/sip/src/resources/images/dial_number.png rename to plugins/sip/src/main/resources/images/dial_number.png diff --git a/src/plugins/sip/src/resources/images/dialpad_16x16.png b/plugins/sip/src/main/resources/images/dialpad_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/dialpad_16x16.png rename to plugins/sip/src/main/resources/images/dialpad_16x16.png diff --git a/src/resources/images/divider.png b/plugins/sip/src/main/resources/images/divider.png similarity index 100% rename from src/resources/images/divider.png rename to plugins/sip/src/main/resources/images/divider.png diff --git a/src/plugins/sip/src/resources/images/edit_number.png b/plugins/sip/src/main/resources/images/edit_number.png similarity index 100% rename from src/plugins/sip/src/resources/images/edit_number.png rename to plugins/sip/src/main/resources/images/edit_number.png diff --git a/plugins/sip/src/main/resources/images/hangup_32x32.png b/plugins/sip/src/main/resources/images/hangup_32x32.png new file mode 100644 index 000000000..0fec0bbd4 Binary files /dev/null and b/plugins/sip/src/main/resources/images/hangup_32x32.png differ diff --git a/plugins/sip/src/main/resources/images/history.png b/plugins/sip/src/main/resources/images/history.png new file mode 100644 index 000000000..7ef475bcb Binary files /dev/null and b/plugins/sip/src/main/resources/images/history.png differ diff --git a/plugins/sip/src/main/resources/images/hold_128x128.png b/plugins/sip/src/main/resources/images/hold_128x128.png new file mode 100644 index 000000000..68e101121 Binary files /dev/null and b/plugins/sip/src/main/resources/images/hold_128x128.png differ diff --git a/src/plugins/sip/src/resources/images/hold_32x32.png b/plugins/sip/src/main/resources/images/hold_32x32.png similarity index 100% rename from src/plugins/sip/src/resources/images/hold_32x32.png rename to plugins/sip/src/main/resources/images/hold_32x32.png diff --git a/src/plugins/sip/src/resources/images/home.png b/plugins/sip/src/main/resources/images/home.png similarity index 100% rename from src/plugins/sip/src/resources/images/home.png rename to plugins/sip/src/main/resources/images/home.png diff --git a/src/plugins/sip/src/resources/images/icon_book.png b/plugins/sip/src/main/resources/images/icon_book.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_book.png rename to plugins/sip/src/main/resources/images/icon_book.png diff --git a/plugins/sip/src/main/resources/images/icon_call-incoming_42x22.png b/plugins/sip/src/main/resources/images/icon_call-incoming_42x22.png new file mode 100644 index 000000000..bfd454ecd Binary files /dev/null and b/plugins/sip/src/main/resources/images/icon_call-incoming_42x22.png differ diff --git a/src/resources/images/icon_computer_16x16.png b/plugins/sip/src/main/resources/images/icon_computer_16x16.png similarity index 100% rename from src/resources/images/icon_computer_16x16.png rename to plugins/sip/src/main/resources/images/icon_computer_16x16.png diff --git a/plugins/sip/src/main/resources/images/icon_grey_microphone_16x16.png b/plugins/sip/src/main/resources/images/icon_grey_microphone_16x16.png new file mode 100644 index 000000000..e8f72d0f2 Binary files /dev/null and b/plugins/sip/src/main/resources/images/icon_grey_microphone_16x16.png differ diff --git a/plugins/sip/src/main/resources/images/icon_grey_phone-hangup_24x24.png b/plugins/sip/src/main/resources/images/icon_grey_phone-hangup_24x24.png new file mode 100644 index 000000000..edb7e8d83 Binary files /dev/null and b/plugins/sip/src/main/resources/images/icon_grey_phone-hangup_24x24.png differ diff --git a/plugins/sip/src/main/resources/images/icon_grey_phone-hold_24x24.png b/plugins/sip/src/main/resources/images/icon_grey_phone-hold_24x24.png new file mode 100644 index 000000000..69b0671b5 Binary files /dev/null and b/plugins/sip/src/main/resources/images/icon_grey_phone-hold_24x24.png differ diff --git a/plugins/sip/src/main/resources/images/icon_grey_phone-mute_24x24.png b/plugins/sip/src/main/resources/images/icon_grey_phone-mute_24x24.png new file mode 100644 index 000000000..dbdf2961d Binary files /dev/null and b/plugins/sip/src/main/resources/images/icon_grey_phone-mute_24x24.png differ diff --git a/plugins/sip/src/main/resources/images/icon_grey_phone-redial_24x24.png b/plugins/sip/src/main/resources/images/icon_grey_phone-redial_24x24.png new file mode 100644 index 000000000..299340283 Binary files /dev/null and b/plugins/sip/src/main/resources/images/icon_grey_phone-redial_24x24.png differ diff --git a/plugins/sip/src/main/resources/images/icon_grey_phone-transfer_24x24.png b/plugins/sip/src/main/resources/images/icon_grey_phone-transfer_24x24.png new file mode 100644 index 000000000..a43bb5c21 Binary files /dev/null and b/plugins/sip/src/main/resources/images/icon_grey_phone-transfer_24x24.png differ diff --git a/plugins/sip/src/main/resources/images/icon_grey_speaker_16x16.png b/plugins/sip/src/main/resources/images/icon_grey_speaker_16x16.png new file mode 100644 index 000000000..b2713ff83 Binary files /dev/null and b/plugins/sip/src/main/resources/images/icon_grey_speaker_16x16.png differ diff --git a/src/plugins/sip/src/resources/images/icon_home_16x16.png b/plugins/sip/src/main/resources/images/icon_home_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_home_16x16.png rename to plugins/sip/src/main/resources/images/icon_home_16x16.png diff --git a/plugins/sip/src/main/resources/images/icon_microphone_16x16.png b/plugins/sip/src/main/resources/images/icon_microphone_16x16.png new file mode 100644 index 000000000..e4803ed36 Binary files /dev/null and b/plugins/sip/src/main/resources/images/icon_microphone_16x16.png differ diff --git a/plugins/sip/src/main/resources/images/icon_microphone_24x24.png b/plugins/sip/src/main/resources/images/icon_microphone_24x24.png new file mode 100644 index 000000000..df1a7599c Binary files /dev/null and b/plugins/sip/src/main/resources/images/icon_microphone_24x24.png differ diff --git a/src/plugins/sip/src/resources/images/icon_mobile_16x16.png b/plugins/sip/src/main/resources/images/icon_mobile_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_mobile_16x16.png rename to plugins/sip/src/main/resources/images/icon_mobile_16x16.png diff --git a/src/plugins/sip/src/resources/images/icon_numberpad_12x15.png b/plugins/sip/src/main/resources/images/icon_numberpad_12x15.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_numberpad_12x15.png rename to plugins/sip/src/main/resources/images/icon_numberpad_12x15.png diff --git a/src/resources/images/icon_phone-call_16x16.png b/plugins/sip/src/main/resources/images/icon_phone-call_16x16.png similarity index 100% rename from src/resources/images/icon_phone-call_16x16.png rename to plugins/sip/src/main/resources/images/icon_phone-call_16x16.png diff --git a/src/plugins/sip/src/resources/images/icon_phone-conference_16x16.png b/plugins/sip/src/main/resources/images/icon_phone-conference_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_phone-conference_16x16.png rename to plugins/sip/src/main/resources/images/icon_phone-conference_16x16.png diff --git a/src/plugins/sip/src/resources/images/icon_phone-hangup_16x16.png b/plugins/sip/src/main/resources/images/icon_phone-hangup_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_phone-hangup_16x16.png rename to plugins/sip/src/main/resources/images/icon_phone-hangup_16x16.png diff --git a/src/plugins/sip/src/resources/images/icon_phone-hangup_24x24.png b/plugins/sip/src/main/resources/images/icon_phone-hangup_24x24.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_phone-hangup_24x24.png rename to plugins/sip/src/main/resources/images/icon_phone-hangup_24x24.png diff --git a/src/plugins/sip/src/resources/images/icon_phone-history_16x16.png b/plugins/sip/src/main/resources/images/icon_phone-history_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_phone-history_16x16.png rename to plugins/sip/src/main/resources/images/icon_phone-history_16x16.png diff --git a/src/plugins/sip/src/resources/images/icon_phone-hold_16x16.png b/plugins/sip/src/main/resources/images/icon_phone-hold_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_phone-hold_16x16.png rename to plugins/sip/src/main/resources/images/icon_phone-hold_16x16.png diff --git a/plugins/sip/src/main/resources/images/icon_phone-hold_24x24.png b/plugins/sip/src/main/resources/images/icon_phone-hold_24x24.png new file mode 100644 index 000000000..999430c04 Binary files /dev/null and b/plugins/sip/src/main/resources/images/icon_phone-hold_24x24.png differ diff --git a/src/plugins/sip/src/resources/images/icon_phone-mute_16x16.png b/plugins/sip/src/main/resources/images/icon_phone-mute_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_phone-mute_16x16.png rename to plugins/sip/src/main/resources/images/icon_phone-mute_16x16.png diff --git a/plugins/sip/src/main/resources/images/icon_phone-mute_24x24.png b/plugins/sip/src/main/resources/images/icon_phone-mute_24x24.png new file mode 100644 index 000000000..c862b5c30 Binary files /dev/null and b/plugins/sip/src/main/resources/images/icon_phone-mute_24x24.png differ diff --git a/src/plugins/sip/src/resources/images/icon_phone-pickup_24x24.png b/plugins/sip/src/main/resources/images/icon_phone-pickup_24x24.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_phone-pickup_24x24.png rename to plugins/sip/src/main/resources/images/icon_phone-pickup_24x24.png diff --git a/plugins/sip/src/main/resources/images/icon_phone-reject_24x24.png b/plugins/sip/src/main/resources/images/icon_phone-reject_24x24.png new file mode 100644 index 000000000..8f140179b Binary files /dev/null and b/plugins/sip/src/main/resources/images/icon_phone-reject_24x24.png differ diff --git a/src/plugins/sip/src/resources/images/icon_phone-transfer_16x16.png b/plugins/sip/src/main/resources/images/icon_phone-transfer_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_phone-transfer_16x16.png rename to plugins/sip/src/main/resources/images/icon_phone-transfer_16x16.png diff --git a/plugins/sip/src/main/resources/images/icon_phone-transfer_24x24.png b/plugins/sip/src/main/resources/images/icon_phone-transfer_24x24.png new file mode 100644 index 000000000..d869f84bc Binary files /dev/null and b/plugins/sip/src/main/resources/images/icon_phone-transfer_24x24.png differ diff --git a/src/plugins/sip/src/resources/images/icon_phone-voicemail_16x16.png b/plugins/sip/src/main/resources/images/icon_phone-voicemail_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_phone-voicemail_16x16.png rename to plugins/sip/src/main/resources/images/icon_phone-voicemail_16x16.png diff --git a/src/plugins/sip/src/resources/images/icon_reciever_22x22.png b/plugins/sip/src/main/resources/images/icon_reciever_22x22.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_reciever_22x22.png rename to plugins/sip/src/main/resources/images/icon_reciever_22x22.png diff --git a/src/plugins/sip/src/resources/images/icon_speaker_16x16.png b/plugins/sip/src/main/resources/images/icon_speaker_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_speaker_16x16.png rename to plugins/sip/src/main/resources/images/icon_speaker_16x16.png diff --git a/src/plugins/sip/src/resources/images/icon_work_16x16.png b/plugins/sip/src/main/resources/images/icon_work_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/icon_work_16x16.png rename to plugins/sip/src/main/resources/images/icon_work_16x16.png diff --git a/plugins/sip/src/main/resources/images/log_history.png b/plugins/sip/src/main/resources/images/log_history.png new file mode 100644 index 000000000..7ef475bcb Binary files /dev/null and b/plugins/sip/src/main/resources/images/log_history.png differ diff --git a/src/resources/images/message.png b/plugins/sip/src/main/resources/images/message.png similarity index 100% rename from src/resources/images/message.png rename to plugins/sip/src/main/resources/images/message.png diff --git a/plugins/sip/src/main/resources/images/microphone.png b/plugins/sip/src/main/resources/images/microphone.png new file mode 100644 index 000000000..e4803ed36 Binary files /dev/null and b/plugins/sip/src/main/resources/images/microphone.png differ diff --git a/src/plugins/sip/src/resources/images/mute.png b/plugins/sip/src/main/resources/images/mute.png similarity index 100% rename from src/plugins/sip/src/resources/images/mute.png rename to plugins/sip/src/main/resources/images/mute.png diff --git a/plugins/sip/src/main/resources/images/mute_128x128.png b/plugins/sip/src/main/resources/images/mute_128x128.png new file mode 100644 index 000000000..1988c1ced Binary files /dev/null and b/plugins/sip/src/main/resources/images/mute_128x128.png differ diff --git a/plugins/sip/src/main/resources/images/mute_32x32.png b/plugins/sip/src/main/resources/images/mute_32x32.png new file mode 100644 index 000000000..e952efdb5 Binary files /dev/null and b/plugins/sip/src/main/resources/images/mute_32x32.png differ diff --git a/plugins/sip/src/main/resources/images/noMute_32x32.png b/plugins/sip/src/main/resources/images/noMute_32x32.png new file mode 100644 index 000000000..b778a0b44 Binary files /dev/null and b/plugins/sip/src/main/resources/images/noMute_32x32.png differ diff --git a/src/plugins/sip/src/resources/images/off.gif b/plugins/sip/src/main/resources/images/off.gif similarity index 100% rename from src/plugins/sip/src/resources/images/off.gif rename to plugins/sip/src/main/resources/images/off.gif diff --git a/src/plugins/sip/src/resources/images/on-phone.png b/plugins/sip/src/main/resources/images/on-phone.png similarity index 100% rename from src/plugins/sip/src/resources/images/on-phone.png rename to plugins/sip/src/main/resources/images/on-phone.png diff --git a/src/plugins/sip/src/resources/images/on.gif b/plugins/sip/src/main/resources/images/on.gif similarity index 100% rename from src/plugins/sip/src/resources/images/on.gif rename to plugins/sip/src/main/resources/images/on.gif diff --git a/plugins/sip/src/main/resources/images/on_phone_128x128.png b/plugins/sip/src/main/resources/images/on_phone_128x128.png new file mode 100644 index 000000000..4c7aabe91 Binary files /dev/null and b/plugins/sip/src/main/resources/images/on_phone_128x128.png differ diff --git a/plugins/sip/src/main/resources/images/phone_call.png b/plugins/sip/src/main/resources/images/phone_call.png new file mode 100644 index 000000000..0d3769506 Binary files /dev/null and b/plugins/sip/src/main/resources/images/phone_call.png differ diff --git a/src/plugins/sip/src/resources/images/phone_hang_up.png b/plugins/sip/src/main/resources/images/phone_hang_up.png similarity index 100% rename from src/plugins/sip/src/resources/images/phone_hang_up.png rename to plugins/sip/src/main/resources/images/phone_hang_up.png diff --git a/plugins/sip/src/main/resources/images/phone_hang_up_128x128.png b/plugins/sip/src/main/resources/images/phone_hang_up_128x128.png new file mode 100644 index 000000000..fe04e3203 Binary files /dev/null and b/plugins/sip/src/main/resources/images/phone_hang_up_128x128.png differ diff --git a/plugins/sip/src/main/resources/images/phone_hold.png b/plugins/sip/src/main/resources/images/phone_hold.png new file mode 100644 index 000000000..999430c04 Binary files /dev/null and b/plugins/sip/src/main/resources/images/phone_hold.png differ diff --git a/src/plugins/sip/src/resources/images/phone_pick_up.png b/plugins/sip/src/main/resources/images/phone_pick_up.png similarity index 100% rename from src/plugins/sip/src/resources/images/phone_pick_up.png rename to plugins/sip/src/main/resources/images/phone_pick_up.png diff --git a/plugins/sip/src/main/resources/images/phone_recall.png b/plugins/sip/src/main/resources/images/phone_recall.png new file mode 100644 index 000000000..ceefe8e87 Binary files /dev/null and b/plugins/sip/src/main/resources/images/phone_recall.png differ diff --git a/src/plugins/sip/src/resources/images/receiver.png b/plugins/sip/src/main/resources/images/receiver.png similarity index 100% rename from src/plugins/sip/src/resources/images/receiver.png rename to plugins/sip/src/main/resources/images/receiver.png diff --git a/plugins/sip/src/main/resources/images/receiver2.png b/plugins/sip/src/main/resources/images/receiver2.png new file mode 100644 index 000000000..b9a2e4f14 Binary files /dev/null and b/plugins/sip/src/main/resources/images/receiver2.png differ diff --git a/plugins/sip/src/main/resources/images/receiver2_48x48.png b/plugins/sip/src/main/resources/images/receiver2_48x48.png new file mode 100644 index 000000000..866c64248 Binary files /dev/null and b/plugins/sip/src/main/resources/images/receiver2_48x48.png differ diff --git a/plugins/sip/src/main/resources/images/reject_32x32.png b/plugins/sip/src/main/resources/images/reject_32x32.png new file mode 100644 index 000000000..b4593e46b Binary files /dev/null and b/plugins/sip/src/main/resources/images/reject_32x32.png differ diff --git a/plugins/sip/src/main/resources/images/resumeCall_32x32.png b/plugins/sip/src/main/resources/images/resumeCall_32x32.png new file mode 100644 index 000000000..0ac289f4f Binary files /dev/null and b/plugins/sip/src/main/resources/images/resumeCall_32x32.png differ diff --git a/src/plugins/sip/src/resources/images/tab_active.png b/plugins/sip/src/main/resources/images/tab_active.png similarity index 100% rename from src/plugins/sip/src/resources/images/tab_active.png rename to plugins/sip/src/main/resources/images/tab_active.png diff --git a/src/plugins/sip/src/resources/images/telephone.png b/plugins/sip/src/main/resources/images/telephone.png similarity index 100% rename from src/plugins/sip/src/resources/images/telephone.png rename to plugins/sip/src/main/resources/images/telephone.png diff --git a/plugins/sip/src/main/resources/images/titlePane.png b/plugins/sip/src/main/resources/images/titlePane.png new file mode 100644 index 000000000..556e94ae7 Binary files /dev/null and b/plugins/sip/src/main/resources/images/titlePane.png differ diff --git a/plugins/sip/src/main/resources/images/toaster_btn-accept.png b/plugins/sip/src/main/resources/images/toaster_btn-accept.png new file mode 100644 index 000000000..9e33b2caa Binary files /dev/null and b/plugins/sip/src/main/resources/images/toaster_btn-accept.png differ diff --git a/plugins/sip/src/main/resources/images/toaster_btn-reject.png b/plugins/sip/src/main/resources/images/toaster_btn-reject.png new file mode 100644 index 000000000..8fda4efef Binary files /dev/null and b/plugins/sip/src/main/resources/images/toaster_btn-reject.png differ diff --git a/src/plugins/sip/src/resources/images/transfer.png b/plugins/sip/src/main/resources/images/transfer.png similarity index 100% rename from src/plugins/sip/src/resources/images/transfer.png rename to plugins/sip/src/main/resources/images/transfer.png diff --git a/plugins/sip/src/main/resources/images/voicemail.png b/plugins/sip/src/main/resources/images/voicemail.png new file mode 100644 index 000000000..d69c054b5 Binary files /dev/null and b/plugins/sip/src/main/resources/images/voicemail.png differ diff --git a/src/plugins/sip/src/resources/images/voicemail_16x16.png b/plugins/sip/src/main/resources/images/voicemail_16x16.png similarity index 100% rename from src/plugins/sip/src/resources/images/voicemail_16x16.png rename to plugins/sip/src/main/resources/images/voicemail_16x16.png diff --git a/src/plugins/sip/src/resources/images/volume.png b/plugins/sip/src/main/resources/images/volume.png similarity index 100% rename from src/plugins/sip/src/resources/images/volume.png rename to plugins/sip/src/main/resources/images/volume.png diff --git a/src/plugins/sip/src/resources/sounds/DTMF0.wav b/plugins/sip/src/main/resources/sounds/DTMF0.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/DTMF0.wav rename to plugins/sip/src/main/resources/sounds/DTMF0.wav diff --git a/src/plugins/sip/src/resources/sounds/DTMF1.wav b/plugins/sip/src/main/resources/sounds/DTMF1.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/DTMF1.wav rename to plugins/sip/src/main/resources/sounds/DTMF1.wav diff --git a/src/plugins/sip/src/resources/sounds/DTMF10.wav b/plugins/sip/src/main/resources/sounds/DTMF10.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/DTMF10.wav rename to plugins/sip/src/main/resources/sounds/DTMF10.wav diff --git a/src/plugins/sip/src/resources/sounds/DTMF11.wav b/plugins/sip/src/main/resources/sounds/DTMF11.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/DTMF11.wav rename to plugins/sip/src/main/resources/sounds/DTMF11.wav diff --git a/src/plugins/sip/src/resources/sounds/DTMF12.wav b/plugins/sip/src/main/resources/sounds/DTMF12.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/DTMF12.wav rename to plugins/sip/src/main/resources/sounds/DTMF12.wav diff --git a/src/plugins/sip/src/resources/sounds/DTMF2.wav b/plugins/sip/src/main/resources/sounds/DTMF2.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/DTMF2.wav rename to plugins/sip/src/main/resources/sounds/DTMF2.wav diff --git a/src/plugins/sip/src/resources/sounds/DTMF3.wav b/plugins/sip/src/main/resources/sounds/DTMF3.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/DTMF3.wav rename to plugins/sip/src/main/resources/sounds/DTMF3.wav diff --git a/src/plugins/sip/src/resources/sounds/DTMF4.wav b/plugins/sip/src/main/resources/sounds/DTMF4.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/DTMF4.wav rename to plugins/sip/src/main/resources/sounds/DTMF4.wav diff --git a/src/plugins/sip/src/resources/sounds/DTMF5.wav b/plugins/sip/src/main/resources/sounds/DTMF5.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/DTMF5.wav rename to plugins/sip/src/main/resources/sounds/DTMF5.wav diff --git a/src/plugins/sip/src/resources/sounds/DTMF6.wav b/plugins/sip/src/main/resources/sounds/DTMF6.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/DTMF6.wav rename to plugins/sip/src/main/resources/sounds/DTMF6.wav diff --git a/src/plugins/sip/src/resources/sounds/DTMF7.wav b/plugins/sip/src/main/resources/sounds/DTMF7.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/DTMF7.wav rename to plugins/sip/src/main/resources/sounds/DTMF7.wav diff --git a/src/plugins/sip/src/resources/sounds/DTMF8.wav b/plugins/sip/src/main/resources/sounds/DTMF8.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/DTMF8.wav rename to plugins/sip/src/main/resources/sounds/DTMF8.wav diff --git a/src/plugins/sip/src/resources/sounds/DTMF9.wav b/plugins/sip/src/main/resources/sounds/DTMF9.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/DTMF9.wav rename to plugins/sip/src/main/resources/sounds/DTMF9.wav diff --git a/src/plugins/sip/src/resources/sounds/alerting.mp3 b/plugins/sip/src/main/resources/sounds/alerting.mp3 similarity index 100% rename from src/plugins/sip/src/resources/sounds/alerting.mp3 rename to plugins/sip/src/main/resources/sounds/alerting.mp3 diff --git a/src/plugins/sip/src/resources/sounds/alerting.wav b/plugins/sip/src/main/resources/sounds/alerting.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/alerting.wav rename to plugins/sip/src/main/resources/sounds/alerting.wav diff --git a/src/plugins/sip/src/resources/sounds/busy.wav b/plugins/sip/src/main/resources/sounds/busy.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/busy.wav rename to plugins/sip/src/main/resources/sounds/busy.wav diff --git a/src/plugins/sip/src/resources/sounds/error.wav b/plugins/sip/src/main/resources/sounds/error.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/error.wav rename to plugins/sip/src/main/resources/sounds/error.wav diff --git a/src/plugins/sip/src/resources/sounds/ring.mp3 b/plugins/sip/src/main/resources/sounds/ring.mp3 similarity index 100% rename from src/plugins/sip/src/resources/sounds/ring.mp3 rename to plugins/sip/src/main/resources/sounds/ring.mp3 diff --git a/src/plugins/sip/src/resources/sounds/ringing.wav b/plugins/sip/src/main/resources/sounds/ringing.wav similarity index 100% rename from src/plugins/sip/src/resources/sounds/ringing.wav rename to plugins/sip/src/main/resources/sounds/ringing.wav diff --git a/src/plugins/sip/src/resources/sounds/string.mp3 b/plugins/sip/src/main/resources/sounds/string.mp3 similarity index 100% rename from src/plugins/sip/src/resources/sounds/string.mp3 rename to plugins/sip/src/main/resources/sounds/string.mp3 diff --git a/plugins/spelling/pom.xml b/plugins/spelling/pom.xml new file mode 100644 index 000000000..c090998c9 --- /dev/null +++ b/plugins/spelling/pom.xml @@ -0,0 +1,41 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + spelling + 0.9 + + Spellchecker Plugin + Provides spellchecker functionality. + + + + Michael Will + michael-will@gmx.net + + Author + + + + + + + org.jitsi + jmyspell-core + 1.0-jitsi-1 + + + org.jitsi + jmyspell-swing + 1.0-jitsi-1 + + + + diff --git a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckChatRoomDecorator.java b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckChatRoomDecorator.java similarity index 87% rename from src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckChatRoomDecorator.java rename to plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckChatRoomDecorator.java index b8514f54a..85323c7f9 100644 --- a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckChatRoomDecorator.java +++ b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckChatRoomDecorator.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -47,7 +43,7 @@ public class SpellcheckChatRoomDecorator implements ActionListener, private JTextComponentSpellChecker _sc; private RolloverButton _spellingButton; private ChatRoom _room; - private JComboBox _languageSelection = new JComboBox(); + private JComboBox _languageSelection = new JComboBox<>(); private Map _languages; public SpellcheckChatRoomDecorator(ChatRoom room) { @@ -145,26 +141,22 @@ public void closing() { private void languagestoLocales() { String spellLanguage = SpellcheckManager.getInstance().getSpellcheckerPreference().getPreferences().getSpellLanguage(); - _languages = new HashMap(); + _languages = new HashMap<>(); Locale[] locales = Locale.getAvailableLocales(); ArrayList languages = SpellcheckManager.getInstance().getSupportedLanguages(); - for (int i = 0; i < languages.size(); i++) { + for (String language : languages) { for (final Locale locale : locales) { - if (locale.toString().equals(languages.get(i))) { - String label = locale.getDisplayLanguage(Locale - .getDefault()); - if (locale.getDisplayCountry(locale) != null - && locale.getDisplayCountry(locale).trim().length() > 0) { - label = label + "-" - + locale.getDisplayCountry(locale).trim(); + if (locale.toString().equals(language)) { + String label = locale.getDisplayLanguage(Locale.getDefault()); + if (!locale.getDisplayCountry(locale).isEmpty()) { + label = label + "-" + locale.getDisplayCountry(locale); } - _languages.put(label, languages.get(i)); + _languages.put(label, language); _languageSelection.addItem(label); - if (languages.get(i).equals(spellLanguage)) - { + if (language.equals(spellLanguage)) { _languageSelection.setSelectedItem(label); } - + } } } diff --git a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckChatRoomListener.java b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckChatRoomListener.java similarity index 76% rename from src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckChatRoomListener.java rename to plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckChatRoomListener.java index 3a5cc642c..b9f9ca231 100644 --- a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckChatRoomListener.java +++ b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckChatRoomListener.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,28 +30,7 @@ public class SpellcheckChatRoomListener implements ChatRoomListener { public SpellcheckChatRoomListener() { } - public void chatRoomActivated(ChatRoom room) { - - } - - public void chatRoomClosed(ChatRoom room) { - - } - - public void chatRoomLeft(ChatRoom room) { - - } - public void chatRoomOpened(ChatRoom room) { new SpellcheckChatRoomDecorator(room); } - - public void userHasJoined(ChatRoom room, String userid) { - - } - - public void userHasLeft(ChatRoom room, String userid) { - - } - } diff --git a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckManager.java b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckManager.java similarity index 98% rename from src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckManager.java rename to plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckManager.java index 5654bf54b..e444aa0b2 100644 --- a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckManager.java +++ b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckManager.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckerPlugin.java b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckerPlugin.java similarity index 96% rename from src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckerPlugin.java rename to plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckerPlugin.java index c33cf219c..9f6e95672 100644 --- a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckerPlugin.java +++ b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckerPlugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckerPreference.java b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckerPreference.java similarity index 98% rename from src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckerPreference.java rename to plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckerPreference.java index ebbd7c2bd..48e40cf37 100644 --- a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckerPreference.java +++ b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckerPreference.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckerPreferenceDialog.java b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckerPreferenceDialog.java similarity index 90% rename from src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckerPreferenceDialog.java rename to plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckerPreferenceDialog.java index 3bfab31df..247b7d05e 100644 --- a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckerPreferenceDialog.java +++ b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckerPreferenceDialog.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -42,7 +38,7 @@ public class SpellcheckerPreferenceDialog extends JPanel implements private JCheckBox spellcheckingEnabled; private JCheckBox autospellcheckingEnabled; - private JComboBox spellLanguages; + private JComboBox spellLanguages; private JCheckBox ignoreCase; private JCheckBox showLanguages; private JPanel spellPanel; @@ -56,7 +52,7 @@ public SpellcheckerPreferenceDialog(ArrayList languages) { spellPanel = new JPanel(); spellcheckingEnabled = new JCheckBox(); autospellcheckingEnabled = new JCheckBox(); - spellLanguages = new JComboBox(); + spellLanguages = new JComboBox<>(); showLanguages = new JCheckBox(); spellPanel.setLayout(new GridBagLayout()); @@ -76,20 +72,17 @@ public void actionPerformed(ActionEvent e) { // autospellcheckingEnabled.setText(SpellcheckerResource.getString("preference.autoSpellcheckingEnabled")); - for (int i = 0; i < languages.size(); i++) { - for (final Locale locale : locales) { - if (locale.toString().equals(languages.get(i))) { - String label = locale.getDisplayLanguage(Locale - .getDefault()); - if (locale.getDisplayCountry(locale) != null - && locale.getDisplayCountry(locale).trim().length() > 0) { - label = label + "-" - + locale.getDisplayCountry(locale).trim(); - } - spellLanguages.addItem(label); - } - } - } + for (String language : languages) { + for (final Locale locale : locales) { + if (locale.toString().equals(language)) { + String label = locale.getDisplayLanguage(Locale.getDefault()); + if (!locale.getDisplayCountry(locale).isEmpty()) { + label = label + "-" + locale.getDisplayCountry(locale); + } + spellLanguages.addItem(label); + } + } + } spellPanel.add(spellcheckingEnabled, new GridBagConstraints(0, 0, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); spellPanel.add(autospellcheckingEnabled, new GridBagConstraints(0, 1, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); diff --git a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckerPreferences.java b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckerPreferences.java similarity index 98% rename from src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckerPreferences.java rename to plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckerPreferences.java index 3b5b04f0f..58a871b10 100644 --- a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckerPreferences.java +++ b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckerPreferences.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckerResource.java b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckerResource.java new file mode 100644 index 000000000..add72603d --- /dev/null +++ b/plugins/spelling/src/main/java/org/jivesoftware/spellchecker/SpellcheckerResource.java @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spellchecker; + +import java.text.MessageFormat; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +import org.jivesoftware.resource.UTF8Control; +import org.jivesoftware.spark.util.log.Log; + +public class SpellcheckerResource { + private static PropertyResourceBundle prb; + + static ClassLoader cl = SpellcheckerResource.class.getClassLoader(); + + static { + prb = (PropertyResourceBundle) ResourceBundle.getBundle("i18n/spellchecker_i18n", new UTF8Control()); + } + + public static String getString(String propertyName) { + try { + return prb.getString(propertyName); + } + catch (Exception e) { + Log.error(e); + return propertyName; + } + } + + public static String getString(String propertyName, Object... obj) { + String str = prb.getString(propertyName); + if (str == null) { + return null; + } + return MessageFormat.format(str, obj); + } + +} diff --git a/plugins/spelling/src/main/plugin-metadata/plugin.xml b/plugins/spelling/src/main/plugin-metadata/plugin.xml new file mode 100755 index 000000000..8a25eaceb --- /dev/null +++ b/plugins/spelling/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,14 @@ + + + ${project.name} + ${project.version} + ${project.description} + Michael Will + https://IgniteRealtime.org + support@IgniteRealtime.org + org.jivesoftware.spellchecker.SpellcheckerPlugin + 3.1.0 + Windows,Mac,Linux + 11 + + diff --git a/src/plugins/spelling/src/resources/dictionary/de.zip b/plugins/spelling/src/main/resources/dictionary/de.zip similarity index 100% rename from src/plugins/spelling/src/resources/dictionary/de.zip rename to plugins/spelling/src/main/resources/dictionary/de.zip diff --git a/src/plugins/spelling/src/resources/dictionary/en.zip b/plugins/spelling/src/main/resources/dictionary/en.zip similarity index 100% rename from src/plugins/spelling/src/resources/dictionary/en.zip rename to plugins/spelling/src/main/resources/dictionary/en.zip diff --git a/src/plugins/spelling/src/resources/dictionary/es.zip b/plugins/spelling/src/main/resources/dictionary/es.zip similarity index 100% rename from src/plugins/spelling/src/resources/dictionary/es.zip rename to plugins/spelling/src/main/resources/dictionary/es.zip diff --git a/plugins/spelling/src/main/resources/dictionary/fr.zip b/plugins/spelling/src/main/resources/dictionary/fr.zip new file mode 100644 index 000000000..3b1878b2a Binary files /dev/null and b/plugins/spelling/src/main/resources/dictionary/fr.zip differ diff --git a/src/plugins/spelling/src/resources/dictionary/lt.zip b/plugins/spelling/src/main/resources/dictionary/lt.zip similarity index 100% rename from src/plugins/spelling/src/resources/dictionary/lt.zip rename to plugins/spelling/src/main/resources/dictionary/lt.zip diff --git a/plugins/spelling/src/main/resources/dictionary/pl.zip b/plugins/spelling/src/main/resources/dictionary/pl.zip new file mode 100644 index 000000000..7bf2a25a8 Binary files /dev/null and b/plugins/spelling/src/main/resources/dictionary/pl.zip differ diff --git a/src/plugins/spelling/src/resources/dictionary/pt_BR.zip b/plugins/spelling/src/main/resources/dictionary/pt_BR.zip similarity index 100% rename from src/plugins/spelling/src/resources/dictionary/pt_BR.zip rename to plugins/spelling/src/main/resources/dictionary/pt_BR.zip diff --git a/plugins/spelling/src/main/resources/dictionary/ru.zip b/plugins/spelling/src/main/resources/dictionary/ru.zip new file mode 100644 index 000000000..d40fce739 Binary files /dev/null and b/plugins/spelling/src/main/resources/dictionary/ru.zip differ diff --git a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n.properties b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n.properties similarity index 90% rename from src/plugins/spelling/src/resources/i18n/spellchecker_i18n.properties rename to plugins/spelling/src/main/resources/i18n/spellchecker_i18n.properties index b3b5c764d..f4109f04d 100644 --- a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n.properties +++ b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n.properties @@ -6,4 +6,4 @@ preference.language = &Language preference.ignore.uppercasedword = &Ignore upper and lowercase preference.show.langauage.in.chat.windows = Allow language selection in chat window dialog.no.mistakes = No spelling mistakes -button.check.spelling = Check spelling \ No newline at end of file +button.check.spelling = Check spelling diff --git a/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_de.properties b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_de.properties new file mode 100644 index 000000000..7b1566560 --- /dev/null +++ b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_de.properties @@ -0,0 +1,9 @@ +title.spellchecker = Rechtschreibprüfung + +preference.spellcheckingEnabled = &Rechtschreibprüfung aktivieren +preference.autoSpellcheckingEnabled = &Automatische Rechtschreibprüfung aktivieren +preference.language = &Sprache +preference.ignore.uppercasedword = &Groß- und Kleinschreibung ignorieren +preference.show.langauage.in.chat.windows = Erlaube Auswahl der Sprache im Chatfenster +dialog.no.mistakes = Keine Rechtschreibfehler +button.check.spelling = Rechtschreibung überprüfen diff --git a/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_es.properties b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_es.properties new file mode 100644 index 000000000..6cc41baf8 --- /dev/null +++ b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_es.properties @@ -0,0 +1,9 @@ +title.spellchecker = Corrector ortográfico + +preference.spellcheckingEnabled = Activar revisión &ortográfica +preference.autoSpellcheckingEnabled = Habilitar la revisión ortográfica &Automática +preference.language = &Idioma +preference.ignore.uppercasedword = &Ignorar mayúsculas y minúsculas +preference.show.langauage.in.chat.windows = Permitir la selección de idioma en la ventana de chat +dialog.no.mistakes = Sin faltas de ortografía +button.check.spelling = Revisar ortografía diff --git a/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_fr.properties b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_fr.properties new file mode 100644 index 000000000..889ce2cec --- /dev/null +++ b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_fr.properties @@ -0,0 +1,9 @@ +title.spellchecker = Correcteur + +preference.spellcheckingEnabled = Activer le &correcteur +preference.autoSpellcheckingEnabled = Activer la correction &automatique +preference.language = &Langue +preference.ignore.uppercasedword = &Ignorer les majuscules +preference.show.langauage.in.chat.windows = Autoriser la sélection de langue dans la fenêtre de chat +dialog.no.mistakes = Aucune faute d'ortographe +button.check.spelling = Vérifier l'orthographe diff --git a/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_lt.properties b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_lt.properties new file mode 100644 index 000000000..7fead3bc4 --- /dev/null +++ b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_lt.properties @@ -0,0 +1,9 @@ +title.spellchecker = RaÅ¡ybos tikrinimas + +preference.spellcheckingEnabled = Ä®jungti raÅ¡ybos tikrinimÄ… +preference.autoSpellcheckingEnabled = Ä®jungti automatinį raÅ¡ybos tikrinimÄ… +preference.language = &Kalba +preference.ignore.uppercasedword = &Neskirti didžiųjų ir mažųjų raidžių +preference.show.langauage.in.chat.windows = Leisti pasirinkti kalbÄ… pokalbio lange +dialog.no.mistakes = Nerasta raÅ¡ybos klaidų +button.check.spelling = Patikrint raÅ¡ybÄ… diff --git a/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_pl.properties b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_pl.properties new file mode 100644 index 000000000..d5a6361bd --- /dev/null +++ b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_pl.properties @@ -0,0 +1,9 @@ +title.spellchecker = Sprawdzanie pisowni + +preference.spellcheckingEnabled = Włącz sprawdzanie pisowni +preference.autoSpellcheckingEnabled = Włącz automatyczne sprawdzanie pisowni +preference.language = JÄ™zyk - sÅ‚ownik +preference.ignore.uppercasedword = Ignoruj górne i dolne sÅ‚owa +preference.show.langauage.in.chat.windows = Zezwalaj na wybór jÄ™zyka w oknie rozmowy +dialog.no.mistakes = Brak bęłdów +button.check.spelling = Sprawdź pisowniÄ™ diff --git a/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_pt_PT.properties b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_pt_PT.properties new file mode 100644 index 000000000..6bc4aa1e0 --- /dev/null +++ b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_pt_PT.properties @@ -0,0 +1,9 @@ +title.spellchecker = Corretor Ortográfico + +preference.spellcheckingEnabled = Ativar &Verificação Ortográfica +preference.autoSpellcheckingEnabled = Ativar &Verificação Ortográfica Automática +preference.language = &Idioma +preference.ignore.uppercasedword = &Ignorar maiúsculas e minúsculas +preference.show.langauage.in.chat.windows = Permitir seleção de idioma na janela de chat +dialog.no.mistakes = Sem erros ortográficos +button.check.spelling = Verificar a ortografia diff --git a/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_ru_RU.properties b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_ru_RU.properties new file mode 100644 index 000000000..5e42bfd82 --- /dev/null +++ b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_ru_RU.properties @@ -0,0 +1,9 @@ +title.spellchecker = Проверка правопиÑÐ°Ð½Ð¸Ñ + +preference.spellcheckingEnabled = Включить проверку правопиÑÐ°Ð½Ð¸Ñ +preference.autoSpellcheckingEnabled = Включить автопроверку правопиÑÐ°Ð½Ð¸Ñ +preference.language = &Язык +preference.ignore.uppercasedword = Игнорировать заглавные и Ñтрочные +preference.show.langauage.in.chat.windows = Разрешить выбор Ñзыка в окне чата +dialog.no.mistakes = Ðет орфографичеÑких ошибок +button.check.spelling = ПроверÑть правопиÑание diff --git a/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_zh_CN.properties b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_zh_CN.properties new file mode 100644 index 000000000..dd509e5ac --- /dev/null +++ b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_zh_CN.properties @@ -0,0 +1,9 @@ +title.spellchecker = 拼写检查 + +preference.spellcheckingEnabled = å¯ç”¨æ‹¼å†™æ£€æŸ¥(&S) +preference.autoSpellcheckingEnabled = å¯ç”¨è‡ªåŠ¨æ‹¼å†™æ£€æŸ¥(&A) +preference.language = 语言(&L) +preference.ignore.uppercasedword = 忽略大å°å†™(&I) +preference.show.langauage.in.chat.windows = å…许在èŠå¤©çª—å£ä¸­é€‰æ‹©è¯­è¨€ +dialog.no.mistakes = 没有拼写错误 +button.check.spelling = 检查拼写 diff --git a/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_zh_TW.properties b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_zh_TW.properties new file mode 100644 index 000000000..0101122c5 --- /dev/null +++ b/plugins/spelling/src/main/resources/i18n/spellchecker_i18n_zh_TW.properties @@ -0,0 +1,9 @@ +title.spellchecker = 拼寫檢查 + +preference.spellcheckingEnabled = 啟動拼寫檢查 +preference.autoSpellcheckingEnabled = 啟動自動拼寫檢查 +preference.language = 語言 +preference.ignore.uppercasedword = 忽略大寫和å°å¯«å·®ç•° +preference.show.langauage.in.chat.windows = å…許在èŠå¤©è¦–çª—é¸æ“‡èªžè¨€ +dialog.no.mistakes = 沒有拼寫錯誤 +button.check.spelling = 拼寫檢查 diff --git a/plugins/spelling/src/main/resources/text_ok.png b/plugins/spelling/src/main/resources/text_ok.png new file mode 100644 index 000000000..0b3e013e9 Binary files /dev/null and b/plugins/spelling/src/main/resources/text_ok.png differ diff --git a/plugins/tictactoe/pom.xml b/plugins/tictactoe/pom.xml new file mode 100644 index 000000000..75475d732 --- /dev/null +++ b/plugins/tictactoe/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + tictactoe + 0.4 + + TicTacToe + The most sophisticated TicTacToe Game ever created. + + + + Wolf Posdorfer + 9posdorf@informatik.uni-hamburg.de + + Author + + + + diff --git a/plugins/tictactoe/src/main/java/tic/tac/toe/GameBoard.java b/plugins/tictactoe/src/main/java/tic/tac/toe/GameBoard.java new file mode 100644 index 000000000..a9e0f3622 --- /dev/null +++ b/plugins/tictactoe/src/main/java/tic/tac/toe/GameBoard.java @@ -0,0 +1,208 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tic.tac.toe; + +import java.util.ArrayList; +import java.util.Arrays; + +/** + * Class to represent the TicTacToe gameboard + * + * @author wolf.posdorfer + * @version 16.06.2011 + */ +public class GameBoard { + + private final int[][] _board; + + private int _currentPlayer; + + private int _winner; + + public GameBoard() { + + _board = new int[3][3]; + + for (int[] x : _board) { + Arrays.fill(x, Mark.BLANK.ordinal()); + } + + _currentPlayer = Mark.X.ordinal(); + _winner = 0; + + } + + public boolean isGameFinished() { + return _winner != 0; + } + + public int getWinner() + { + return _winner; + } + + public Mark getMarkAtPos(int x, int y) { + + return Mark.valueOf(_board[x][y]); + } + + public Mark getCurrentPlayer() { + return Mark.valueOf(_currentPlayer); + } + + public void placeMark(int x, int y) { + _board[x][y] = _currentPlayer; + + if (didCurrentPlayerWin()) { + _winner = _currentPlayer; + } + + if (isBoardFull() && _winner < 1) { + // Setting to Tie + _winner = -1; + } + + _currentPlayer = _currentPlayer == 1 ? 2 : 1; + + } + + /** + * Checks if the Currentplayer has won the game + * + * @return current player won the game? + */ + private boolean didCurrentPlayerWin() { + + for (int x = 0; x < 3; x++) { + + if (_board[x][0] == _currentPlayer + && _board[x][1] == _currentPlayer + && _board[x][2] == _currentPlayer) { + return true; + } + + } + + for (int y = 0; y < 3; y++) { + if (_board[0][y] == _currentPlayer + && _board[1][y] == _currentPlayer + && _board[2][y] == _currentPlayer) { + return true; + } + } + + if (_board[0][0] == _currentPlayer && _board[1][1] == _currentPlayer && _board[2][2] == _currentPlayer) { + return true; + } else { + return _board[2][0] == _currentPlayer && _board[1][1] == _currentPlayer && _board[0][2] == _currentPlayer; + } + } + + /** + * Checks if the Board is Full + * + * @return board is full? + */ + private boolean isBoardFull() { + + for (int x = 0; x < 3; x++) { + for (int y = 0; y < 3; y++) { + + if (_board[x][y] == 0) { + return false; + } + } + } + + return true; + + } + /** + * Returns the winning positions in an arraylist of Pairs + * @return ArrayList with 3 entries + */ + public Pair[] getWinningPositions() + { + ArrayList liste = new ArrayList<>(); + + if(_winner == -1) + { + // TIE + return null; + } + + Mark m = Mark.valueOf(_winner); + + for (int x = 0; x < 3; x++) { + + if (_board[x][0] == _winner + && _board[x][1] == _winner + && _board[x][2] == _winner) { + new Pair(x, 0,m); + + liste.add(new Pair(x, 0, m)); + liste.add(new Pair(x, 1, m)); + liste.add(new Pair(x, 2, m)); + return liste.toArray(new Pair[3]); + + } + + } + + for (int y = 0; y < 3; y++) { + if (_board[0][y] == _winner + && _board[1][y] == _winner + && _board[2][y] == _winner) { + + liste.add(new Pair(0, y, m)); + liste.add(new Pair(1, y, m)); + liste.add(new Pair(2, y, m)); + return liste.toArray(new Pair[3]); + } + } + + if (_board[0][0] == _winner && _board[1][1] == _winner + && _board[2][2] == _winner) { + + liste.add(new Pair(0, 0, m)); + liste.add(new Pair(1, 1, m)); + liste.add(new Pair(2, 2, m)); + + return liste.toArray(new Pair[3]); + } + if (_board[2][0] == _winner && _board[1][1] == _winner + && _board[0][2] == _winner) { + liste.add(new Pair(2, 0, m)); + liste.add(new Pair(1, 1, m)); + liste.add(new Pair(0, 2, m)); + return liste.toArray(new Pair[3]); + } + + return null; + + } + + /** + * Checks if the placed move is Valid + * @param x + * @param y + * @return + */ + public boolean isValidMove(Mark markplaced, int x , int y) + { + return _board[x][y] == 0 && _currentPlayer == markplaced.getValue(); + } +} diff --git a/plugins/tictactoe/src/main/java/tic/tac/toe/Mark.java b/plugins/tictactoe/src/main/java/tic/tac/toe/Mark.java new file mode 100644 index 000000000..3a86b64af --- /dev/null +++ b/plugins/tictactoe/src/main/java/tic/tac/toe/Mark.java @@ -0,0 +1,65 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tic.tac.toe; + +import javax.swing.ImageIcon; + +import static tic.tac.toe.TTTRes.*; + +/** + * The Variations of Marks + * + * @author wolf.posdorfer + * @version 16.06.2011 + */ +public enum Mark { + BLANK(0, ICON_EMPTY, ICON_EMPTY), + X(1, ICON_X, ICON_X_BLUE), + O(2, ICON_O, ICON_O_BLUE); + + private final int value; + private final ImageIcon icon; + private final ImageIcon redicon; + + public static Mark valueOf(int x) { + switch (x) { + case 1: + return X; + case 2: + return O; + default: + return BLANK; + } + } + + public ImageIcon getImage() { + return icon; + } + + public ImageIcon getRedImage() { + return redicon; + } + + public int getValue() { + return value; + } + + Mark(int value, ImageIcon icon, ImageIcon redicon) { + this.value = value; + this.icon = icon; + this.redicon = redicon; + } +} diff --git a/src/plugins/tictactoe/src/java/tic/tac/toe/Pair.java b/plugins/tictactoe/src/main/java/tic/tac/toe/Pair.java similarity index 90% rename from src/plugins/tictactoe/src/java/tic/tac/toe/Pair.java rename to plugins/tictactoe/src/main/java/tic/tac/toe/Pair.java index a12f66e5f..6cadd5604 100644 --- a/src/plugins/tictactoe/src/java/tic/tac/toe/Pair.java +++ b/plugins/tictactoe/src/main/java/tic/tac/toe/Pair.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,9 +23,9 @@ */ public class Pair { - private int _x; - private int _y; - private Mark _m; + private final int _x; + private final int _y; + private final Mark _m; public Pair(int x, int y, Mark m) { _x = x; diff --git a/plugins/tictactoe/src/main/java/tic/tac/toe/TTTRes.java b/plugins/tictactoe/src/main/java/tic/tac/toe/TTTRes.java new file mode 100644 index 000000000..74769586f --- /dev/null +++ b/plugins/tictactoe/src/main/java/tic/tac/toe/TTTRes.java @@ -0,0 +1,65 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tic.tac.toe; + +import java.text.MessageFormat; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +import org.jivesoftware.resource.UTF8Control; +import org.jivesoftware.spark.util.log.Log; + +import javax.swing.*; + +/** + * Resource Bundle for TicTacToe + * + * @author wolf.posdorfer + * @version 16.06.2011 + */ +public class TTTRes { + private static ClassLoader cl = Mark.class.getClassLoader(); + public static final ImageIcon ICON_EMPTY = getImageIcon("empty.png"); + public static final ImageIcon ICON_X = getImageIcon("x.png"); + public static final ImageIcon ICON_X_BLUE = getImageIcon("x.blue.png"); + public static final ImageIcon ICON_O = getImageIcon("o.png"); + public static final ImageIcon ICON_O_BLUE = getImageIcon("o.blue.png"); + public static final ImageIcon ICON_BUTTON = getImageIcon("ttt.button.png"); + public static final ImageIcon ICON_BOARD = getImageIcon("board.png"); + + private static final PropertyResourceBundle prb = (PropertyResourceBundle) ResourceBundle.getBundle("i18n/tictactoe_i18n", new UTF8Control()); + + public static String getString(String propertyName) { + try { + return prb.getString(propertyName); + } catch (Exception e) { + Log.error(e); + return propertyName; + } + } + + public static String getString(String propertyName, Object... obj) { + String str = prb.getString(propertyName); + if (str == null) { + return propertyName; + } + return MessageFormat.format(str, obj); + } + + static ImageIcon getImageIcon(String icon) { + return new ImageIcon(cl.getResource(icon)); + } +} diff --git a/plugins/tictactoe/src/main/java/tic/tac/toe/TicTacToePlugin.java b/plugins/tictactoe/src/main/java/tic/tac/toe/TicTacToePlugin.java new file mode 100644 index 000000000..7632cb52c --- /dev/null +++ b/plugins/tictactoe/src/main/java/tic/tac/toe/TicTacToePlugin.java @@ -0,0 +1,272 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tic.tac.toe; + +import java.awt.Color; +import java.awt.Font; +import java.util.HashSet; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.jivesoftware.resource.Res; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.filter.StanzaIdFilter; +import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler; +import org.jivesoftware.smack.iqrequest.IQRequestHandler; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.StanzaError; +import org.jivesoftware.smack.provider.ProviderManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ChatRoomButton; +import org.jivesoftware.spark.ui.ChatRoomListener; +import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.EntityFullJid; +import org.jxmpp.jid.parts.Localpart; +import tic.tac.toe.packet.GameOfferPacket; +import tic.tac.toe.packet.InvalidMove; +import tic.tac.toe.packet.MovePacket; +import tic.tac.toe.ui.GamePanel; + +import static tic.tac.toe.TTTRes.ICON_BUTTON; + + +/** + * Tic Tac Toe plugin for Spark + * + * @author wolf.posdorfer + * @version 16.06.2011 + */ +public class TicTacToePlugin implements Plugin { + + private ChatRoomListener _chatRoomListener; + private IQRequestHandler _gameOfferHandler; + + private HashSet _currentInvitations; + + @Override + public void initialize() { + _currentInvitations = new HashSet<>(); + + ProviderManager.addIQProvider(GameOfferPacket.ELEMENT_NAME, GameOfferPacket.NAMESPACE, new GameOfferPacket.Provider() ); + ProviderManager.addExtensionProvider(MovePacket.ELEMENT_NAME, MovePacket.NAMESPACE, new MovePacket.Provider() ); + ProviderManager.addExtensionProvider(InvalidMove.ELEMENT_NAME, InvalidMove.NAMESPACE, new InvalidMove.Provider() ); + + // Add IQ listener to listen for incoming game invitations. + _gameOfferHandler = new AbstractIqRequestHandler( + GameOfferPacket.ELEMENT_NAME, + GameOfferPacket.NAMESPACE, + IQ.Type.get, + IQRequestHandler.Mode.async) + { + public IQ handleIQRequest(IQ request) { + showInvitationAlert((GameOfferPacket) request); + return null; + } + }; + + SparkManager.getConnection().registerIQRequestHandler(_gameOfferHandler); + addButtonToToolBar(); + + } + /** + * Add the TTT-Button to every opening Chatroom + * and create Listeners for it + */ + private void addButtonToToolBar() { + + + _chatRoomListener = new ChatRoomListener() { + @Override + public void chatRoomOpened(final ChatRoom room) { + + if(!(room instanceof ChatRoomImpl)) + { + // Don't do anything if this is not a 1on1-Chat + return; + } + final ChatRoomButton sendGameButton = new ChatRoomButton(ICON_BUTTON); + room.getToolBar().addChatRoomButton(sendGameButton); + sendGameButton.addActionListener(e -> { + final EntityFullJid opponentJID = ((ChatRoomImpl) room).getJidOnline(); + // If the opponent is offline, then you should not start the game + if (opponentJID == null) { + return; + } + if (_currentInvitations.contains(opponentJID.asEntityBareJid())) { + return; + } + + final GameOfferPacket offer = new GameOfferPacket(); + offer.setTo(opponentJID); + offer.setType(IQ.Type.get); + + _currentInvitations.add(opponentJID.asEntityBareJid()); + room.getTranscriptWindow().insertCustomText + (TTTRes.getString("ttt.request.sent"), false, false, Color.BLUE); + try { + SparkManager.getConnection().sendStanza(offer); + } catch (SmackException.NotConnectedException | InterruptedException e1) { + Log.warning("Unable to send offer to " + opponentJID, e1); + } + + SparkManager.getConnection().addAsyncStanzaListener( + stanza -> { + if (stanza.getError() != null) { + room.getTranscriptWindow().insertCustomText + (TTTRes.getString("ttt.request.decline"), false, false, Color.RED); + _currentInvitations.remove(opponentJID.asBareJid()); + return; + } + + GameOfferPacket answer = (GameOfferPacket) stanza; + answer.setStartingPlayer(offer.isStartingPlayer()); + answer.setGameID(offer.getGameID()); + if (answer.getType() == IQ.Type.result) { + // ACCEPT + _currentInvitations.remove(opponentJID.asBareJid()); + + room.getTranscriptWindow().insertCustomText + (TTTRes.getString("ttt.request.accept"), false, false, Color.BLUE); + + createTTTWindow(answer, opponentJID); + } else { + // DECLINE + room.getTranscriptWindow().insertCustomText + (TTTRes.getString("ttt.request.decline"), false, false, Color.RED); + _currentInvitations.remove(opponentJID.asBareJid()); + } + }, new StanzaIdFilter(offer)); + // TODO: Just filtering by stanza id is insure, should use Smack's IQ send-response mechanisms. + }); + } + + @Override + public void chatRoomClosed(ChatRoom room) { + if (room instanceof ChatRoomImpl) { + ChatRoomImpl cri = (ChatRoomImpl) room; + _currentInvitations.remove(cri.getParticipantJID()); + } + } + }; + + + SparkManager.getChatManager().addChatRoomListener(_chatRoomListener); + + } + + @Override + public void shutdown() { + + _currentInvitations.clear(); + SparkManager.getChatManager().removeChatRoomListener(_chatRoomListener); + SparkManager.getConnection().unregisterIQRequestHandler(_gameOfferHandler); + } + + @Override + public boolean canShutDown() { + return false; + } + + @Override + public void uninstall() { + + } + + /** + * insert the Invitation Dialog into the Chat + * + * @param invitation + */ + private void showInvitationAlert(final GameOfferPacket invitation) { + invitation.setType(IQ.Type.result); + invitation.setTo(invitation.getFrom()); + + final ChatRoom room = SparkManager.getChatManager().getChatRoom(invitation.getFrom().asEntityBareJidOrThrow()); + + Localpart name = invitation.getFrom().getLocalpartOrThrow(); + + final JPanel panel = new JPanel(); + JLabel text = new JLabel(TTTRes.getString("ttt.game.request", name)); + JLabel game = new JLabel(TTTRes.getString("ttt.game.name")); + game.setFont(new Font("Dialog", Font.BOLD, 24)); + game.setForeground(Color.RED); + JButton accept = new JButton(Res.getString("button.accept").replace("&", "")); + JButton decline = new JButton(Res.getString("button.decline").replace("&", "")); + panel.add(text); + panel.add(game); + panel.add(accept); + panel.add(decline); + + room.getTranscriptWindow().addComponent(panel); + + accept.addActionListener(e -> { + try { + SparkManager.getConnection().sendStanza(invitation); + } catch (SmackException.NotConnectedException | InterruptedException e1) { + Log.warning("Unable to send invitation accept to " + invitation.getTo(), e1); + } + invitation.setStartingPlayer(!invitation.isStartingPlayer()); + createTTTWindow(invitation, invitation.getTo().asEntityFullJidOrThrow()); + panel.remove(3); + panel.remove(2); + panel.repaint(); + panel.revalidate(); + }); + + decline.addActionListener(e -> { + invitation.setType(IQ.Type.error); + invitation.setError(StanzaError.getBuilder().setCondition(StanzaError.Condition.undefined_condition).setDescriptiveEnText("User declined your request.").build()); + try { + SparkManager.getConnection().sendStanza(invitation); + } catch (SmackException.NotConnectedException | InterruptedException e1) { + Log.warning("Unable to send invitation decline to " + invitation.getTo(), e1); + } + panel.remove(3); + panel.remove(2); + panel.repaint(); + panel.revalidate(); + }); + } + + /** + * Creates The TicTacToe Window and starts the Game + * @param gop + * @param opponentJID + */ + private void createTTTWindow(GameOfferPacket gop, EntityFullJid opponentJID) { + + Localpart name = opponentJID.getLocalpart(); + + // tictactoe versus ${name} + JFrame f = new JFrame(TTTRes.getString("ttt.window.title", TTTRes.getString("ttt.game.name"),name.toString() )); + f.setIconImage(ICON_BUTTON.getImage()); + GamePanel gp = new GamePanel(SparkManager.getConnection(), + gop.getGameID(), gop.isStartingPlayer(), opponentJID,f); + f.add(gp); + f.pack(); + f.setLocationRelativeTo(SparkManager.getChatManager().getChatContainer()); + f.setVisible(true); + + } + +} diff --git a/plugins/tictactoe/src/main/java/tic/tac/toe/packet/GameOfferPacket.java b/plugins/tictactoe/src/main/java/tic/tac/toe/packet/GameOfferPacket.java new file mode 100644 index 000000000..fddb67e91 --- /dev/null +++ b/plugins/tictactoe/src/main/java/tic/tac/toe/packet/GameOfferPacket.java @@ -0,0 +1,142 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tic.tac.toe.packet; + +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IqData; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.provider.IqProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.JxmppContext; + +import java.io.IOException; +import java.util.Random; + +/** + * The Game Offer Packet + * + * @author wolf.posdorfer + * @version 16.06.2011 + */ +public class GameOfferPacket extends IQ { + + public static final String ELEMENT_NAME = "tictactoe"; + public static final String NAMESPACE = "tictactoe"; + + private int gameID; + private boolean imTheStartingPlayer; + + public GameOfferPacket() { + super( ELEMENT_NAME, NAMESPACE ); + imTheStartingPlayer = new Random().nextBoolean(); + gameID = Math.abs(new Random().nextInt()); + } + + /** + * Returns the game ID. + * + * @return the game ID. + */ + public int getGameID() { + return gameID; + } + + /** + * Sets the game ID. + * + * @param gameID + * the game ID. + */ + public void setGameID(int gameID) { + this.gameID = gameID; + } + + /** + * Returns true if the user making the game invitation is the starting + * player. + * + * @return true if the user making the game invite is the starting player. + */ + public boolean isStartingPlayer() { + return imTheStartingPlayer; + } + + /** + * Sets whether the user making the game invitation is the starting player. + * + * @param startingPlayer + * true if the user making the game invite is the starting + * player. + */ + public void setStartingPlayer(boolean startingPlayer) { + this.imTheStartingPlayer = startingPlayer; + } + + @Override + protected IQChildElementXmlStringBuilder getIQChildElementBuilder( IQChildElementXmlStringBuilder buf ) + { + buf.rightAngleBracket(); + buf.append( "<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">" ); + buf.element( "gameID", Integer.toString( gameID ) ); + buf.element( "startingPlayer", Boolean.toString( imTheStartingPlayer ) ); + buf.append( "" ); + return buf; + } + public static class Provider extends IqProvider + { + public Provider() + { + super(); + } + + @Override + public GameOfferPacket parse(XmlPullParser parser, int i, IqData iqData, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException + { + final GameOfferPacket gameOffer = new GameOfferPacket(); + + boolean done = false; + while ( !done ) + { + XmlPullParser.Event eventType = parser.next(); + if ( eventType == XmlPullParser.Event.START_ELEMENT ) + { + if ( parser.getName().equals( "gameID" ) ) + { + final int gameID = Integer.parseInt( parser.nextText() ); + gameOffer.setGameID( gameID ); + } + else if ( parser.getName().equals( "startingPlayer" ) ) + { + boolean startingPlayer = Boolean.parseBoolean( parser.nextText() ); + gameOffer.setStartingPlayer( startingPlayer ); + } + } + + else if ( eventType == XmlPullParser.Event.END_ELEMENT ) + { + if ( parser.getName().equals( ELEMENT_NAME ) ) + { + done = true; + } + } + } + + return gameOffer; + } + } + +} diff --git a/plugins/tictactoe/src/main/java/tic/tac/toe/packet/InvalidMove.java b/plugins/tictactoe/src/main/java/tic/tac/toe/packet/InvalidMove.java new file mode 100644 index 000000000..3844dbaf5 --- /dev/null +++ b/plugins/tictactoe/src/main/java/tic/tac/toe/packet/InvalidMove.java @@ -0,0 +1,108 @@ +package tic.tac.toe.packet; + +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.provider.ExtensionElementProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.JxmppContext; + +import javax.xml.namespace.QName; +import java.io.IOException; + +public class InvalidMove implements ExtensionElement { + + public static final String ELEMENT_NAME = "ttt-invalid"; + public static final String NAMESPACE = "tictactoe"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT_NAME); + + private int _gameID; + private int _posx; + private int _posy; + + @Override + public String getElementName() { + return ELEMENT_NAME; + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + public int getGameID() { + return _gameID; + } + + public void setGameID(int gameID) { + _gameID = gameID; + } + + public int getPositionX() { + return _posx; + } + + public int getPositionY() { + return _posy; + } + + public void setPositionX(int x) { + _posx = x; + } + + public void setPositionY(int y) { + _posy = y; + } + + @Override + public String toXML(XmlEnvironment xmlEnvironment) { + + return "<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">" + + "" + _gameID + "" + + "" + _posx + "" + + "" + _posy + "" + + ""; + } + + public static class Provider extends ExtensionElementProvider + { + @Override + public InvalidMove parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException + { + final InvalidMove gameMove = new InvalidMove(); + boolean done = false; + while ( !done ) + { + final XmlPullParser.Event eventType = parser.next(); + + if ( eventType == XmlPullParser.Event.START_ELEMENT ) + { + if ( "gameID".equals( parser.getName() ) ) + { + final int gameID = Integer.parseInt( parser.nextText() ); + gameMove.setGameID( gameID ); + } + if ( "positionX".equals( parser.getName() ) ) + { + final int position = Integer.parseInt( parser.nextText() ); + gameMove.setPositionX( position ); + } + if ( "positionY".equals( parser.getName() ) ) + { + final int position = Integer.parseInt( parser.nextText() ); + gameMove.setPositionY( position ); + } + } + else if ( eventType == XmlPullParser.Event.END_ELEMENT ) + { + if ( ELEMENT_NAME.equals( parser.getName() ) ) + { + done = true; + } + } + } + + return gameMove; + } + } +} diff --git a/plugins/tictactoe/src/main/java/tic/tac/toe/packet/MovePacket.java b/plugins/tictactoe/src/main/java/tic/tac/toe/packet/MovePacket.java new file mode 100644 index 000000000..957685d22 --- /dev/null +++ b/plugins/tictactoe/src/main/java/tic/tac/toe/packet/MovePacket.java @@ -0,0 +1,128 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tic.tac.toe.packet; + +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.provider.ExtensionElementProvider; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.JxmppContext; + +import javax.xml.namespace.QName; +import java.io.IOException; + +/** + * The Move Packet extension + * + * @author wolf.posdorfer + * @version 16.06.2011 + */ +public class MovePacket implements ExtensionElement { + + public static final String ELEMENT_NAME = "ttt-move"; + public static final String NAMESPACE = "tictactoe"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT_NAME); + + private int posx; + private int posy; + private int gameID; + + public int getGameID() { + return gameID; + } + + public void setGameID(int gameID) { + this.gameID = gameID; + } + + @Override + public String getElementName() { + return ELEMENT_NAME; + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + public int getPositionX() { + return posx; + } + + public void setPositionX(int posx) { + this.posx = posx; + } + + public int getPositionY() { + return posy; + } + + public void setPositionY(int posy) { + this.posy = posy; + } + + @Override + public String toXML(XmlEnvironment xmlEnvironment) { + return "<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">" + + "" + gameID + "" + + "" + posx + "" + + "" + posy + "" + + ""; + } + + public static class Provider extends ExtensionElementProvider + { + @Override + public MovePacket parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException + { + final MovePacket gameMove = new MovePacket(); + boolean done = false; + while ( !done ) + { + final XmlPullParser.Event eventType = parser.next(); + + if ( eventType == XmlPullParser.Event.START_ELEMENT ) + { + if ( "gameID".equals( parser.getName() ) ) + { + final int gameID = Integer.parseInt( parser.nextText() ); + gameMove.setGameID( gameID ); + } + if ( "positionX".equals( parser.getName() ) ) + { + final int position = Integer.parseInt( parser.nextText() ); + gameMove.setPositionX( position ); + } + if ( "positionY".equals( parser.getName() ) ) + { + final int position = Integer.parseInt( parser.nextText() ); + gameMove.setPositionY( position ); + } + } + else if ( eventType == XmlPullParser.Event.END_ELEMENT ) + { + if ( ELEMENT_NAME.equals( parser.getName() ) ) + { + done = true; + } + } + } + + return gameMove; + } + } +} diff --git a/plugins/tictactoe/src/main/java/tic/tac/toe/ui/GameBoardPanel.java b/plugins/tictactoe/src/main/java/tic/tac/toe/ui/GameBoardPanel.java new file mode 100644 index 000000000..3bbd57dc0 --- /dev/null +++ b/plugins/tictactoe/src/main/java/tic/tac/toe/ui/GameBoardPanel.java @@ -0,0 +1,105 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tic.tac.toe.ui; + +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Image; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.geom.AffineTransform; + +import javax.swing.JLabel; +import javax.swing.JPanel; + +import tic.tac.toe.Mark; +import tic.tac.toe.Pair; + +import static tic.tac.toe.TTTRes.ICON_BOARD; + +/** + * The Gui to the Logical Board + * + * @author wolf.posdorfer + * @version 16.06.2011 + */ +public class GameBoardPanel extends JPanel { + private final Image _backgroundimage = ICON_BOARD.getImage(); + private final JLabel[][] _labels; + private final GamePanel _owner; + + public GameBoardPanel(GamePanel gamepanel) { + _owner = gamepanel; + setLayout(new GridLayout(3, 3)); + _labels = new JLabel[3][3]; + for (int x = 0; x < 3; x++) { + for (int y = 0; y < 3; y++) { + JLabel toadd = new JLabel(Mark.BLANK.getImage()); + toadd.setOpaque(false); + final int xx = x; + final int yy = y; + toadd.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (_owner.myTurn() && _owner.isFree(xx, yy)) { + placeMark(_owner.getMyMark(), xx, yy); + } + } + + }); + _labels[x][y] = toadd; + add(_labels[x][y]); + } + } + + setPreferredSize(new Dimension(500, 500)); + } + + /** + * Places the Mark, and tells the Owner to place the mark on the logical board + */ + public void placeMark(Mark m, int x, int y) { + _labels[x][y].setIcon(m.getImage()); + // Notify the Owner about Change + _owner.onGameBoardPlaceMark(m, x, y); + this.invalidate(); + this.repaint(); + this.revalidate(); + } + + public void colorizeWinners(Pair[] pairs) { + if (pairs != null) { + for (Pair p : pairs) { + _labels[p.getX()][p.getY()].setIcon(p.getMark().getRedImage()); + } + } + this.repaint(); + this.revalidate(); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Image backgroundImage = _backgroundimage; + double scaleX = getWidth() / (double) backgroundImage.getWidth(null); + double scaleY = getHeight() / (double) backgroundImage.getHeight(null); + AffineTransform xform = AffineTransform.getScaleInstance(scaleX, scaleY); + ((Graphics2D) g).drawImage(backgroundImage, xform, this); + } + +} diff --git a/src/plugins/tictactoe/src/java/tic/tac/toe/ui/GameEndsUI.java b/plugins/tictactoe/src/main/java/tic/tac/toe/ui/GameEndsUI.java similarity index 95% rename from src/plugins/tictactoe/src/java/tic/tac/toe/ui/GameEndsUI.java rename to plugins/tictactoe/src/main/java/tic/tac/toe/ui/GameEndsUI.java index 096901c7e..922cee7a1 100644 --- a/src/plugins/tictactoe/src/java/tic/tac/toe/ui/GameEndsUI.java +++ b/plugins/tictactoe/src/main/java/tic/tac/toe/ui/GameEndsUI.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,7 +29,6 @@ public class GameEndsUI extends JPanel { /** - * */ private static final long serialVersionUID = -5947922803585454129L; diff --git a/plugins/tictactoe/src/main/java/tic/tac/toe/ui/GamePanel.java b/plugins/tictactoe/src/main/java/tic/tac/toe/ui/GamePanel.java new file mode 100644 index 000000000..416dc70f9 --- /dev/null +++ b/plugins/tictactoe/src/main/java/tic/tac/toe/ui/GamePanel.java @@ -0,0 +1,214 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tic.tac.toe.ui; + +import java.awt.BorderLayout; +import java.awt.Color; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.filter.StanzaExtensionFilter; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.ui.ChatRoom; +import org.jivesoftware.spark.ui.ShakeWindow; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.EntityFullJid; +import tic.tac.toe.GameBoard; +import tic.tac.toe.Mark; +import tic.tac.toe.TTTRes; +import tic.tac.toe.packet.InvalidMove; +import tic.tac.toe.packet.MovePacket; + +/** + * Holds the GameBoard and the Playerdisplay + * + * @author wolf.posdorfer + * @version 16.06.2011 + */ +public class GamePanel extends JPanel { + + private static final long serialVersionUID = 5481864290352375841L; + + private final GameBoardPanel _gameboardpanel; + + private final PlayerDisplay _playerdisplay; + + private final Mark me; + + private final GameBoard _gameboard; + + private final XMPPConnection _connection; + + private final int _gameID; + + private final EntityFullJid _opponent; + private final JFrame _frame; + + public GamePanel(XMPPConnection connection, final int gameID, + boolean imStarting, EntityFullJid opponentJID, JFrame frame) { + + _frame = frame; + + _opponent = opponentJID; + + _gameID = gameID; + _gameboard = new GameBoard(); + _connection = connection; + _gameboardpanel = new GameBoardPanel(this); + + if (imStarting) { + me = Mark.X; + } else { + me = Mark.O; + } + + _playerdisplay = new PlayerDisplay(me, opponentJID); + + setLayout(new BorderLayout()); + + add(_gameboardpanel, BorderLayout.CENTER); + add(_playerdisplay, BorderLayout.SOUTH); + _connection.addAsyncStanzaListener(stanza -> { + + MovePacket move = stanza.getExtension(MovePacket.class); + if (move.getGameID() == _gameID) { + if (_gameboard.isValidMove(getYourMark(), move.getPositionX(), move.getPositionY())) { + _gameboardpanel.placeMark(getYourMark(), move.getPositionX(), move.getPositionY()); + } else { + InvalidMove inval = new InvalidMove(); + inval.setGameID(move.getGameID()); + inval.setPositionX(move.getPositionX()); + inval.setPositionY(move.getPositionY()); + Message message = StanzaBuilder.buildMessage() + .addExtension(inval) + .build(); + message.setTo(_opponent); + _connection.sendStanza(message); + + ChatRoom cr = SparkManager.getChatManager().getChatRoom(_opponent.asEntityBareJid()); + cr.getTranscriptWindow().insertCustomText(_opponent + "seems to be cheating\n" + + "He tried placing a wrong Move", true, false, Color.red); + } + } + }, new StanzaExtensionFilter(MovePacket.ELEMENT_NAME, MovePacket.NAMESPACE)); + + _connection.addAsyncStanzaListener(stanza -> { + //InvalidMove im = packet.getExtension(InvalidMove.class); + ChatRoom cr = SparkManager.getChatManager().getChatRoom(_opponent.asEntityBareJid()); + cr.getTranscriptWindow().insertCustomText("You seem to be Cheating\n" + + "You placed a wrong Move", true, false, Color.red); + ShakeWindow sw = new ShakeWindow(_frame); + sw.startRandomMovement(10); + }, new StanzaExtensionFilter(InvalidMove.ELEMENT_NAME, InvalidMove.NAMESPACE)); + + } + + public PlayerDisplay getPlayerDisplay() { + return _playerdisplay; + } + + public GameBoardPanel getGameBoardPanel() { + return _gameboardpanel; + } + + /** + * being called from GameBoardPanel, places the Mark on the Logical Board + * and sends the Move if it was one + * + * @param m + * @param x + * @param y + */ + public void onGameBoardPlaceMark(Mark m, int x, int y) { + + _gameboard.placeMark(x, y); + _playerdisplay.setCurrentPlayer(_gameboard.getCurrentPlayer()); + + if (m == getMyMark()) { + + MovePacket move = new MovePacket(); + move.setGameID(_gameID); + move.setPositionX(x); + move.setPositionY(y); + + Message message = StanzaBuilder.buildMessage() + .addExtension(move) + .build(); + message.setTo(_opponent); + try + { + _connection.sendStanza(message); + } + catch ( SmackException.NotConnectedException | InterruptedException e ) + { + Log.warning( "Unable to send move to " + message.getTo(), e ); + } + + } + + if (_gameboard.isGameFinished()) { + _gameboardpanel.colorizeWinners(_gameboard.getWinningPositions()); + + if (_gameboard.getWinner() == getMyMark().getValue()) { + + remove(_playerdisplay); + add(new GameEndsUI(TTTRes.getString("ttt.win"), Color.GREEN), BorderLayout.SOUTH); + + } + if (_gameboard.getWinner() == getYourMark().getValue()) { + remove(_playerdisplay); + add(new GameEndsUI(TTTRes.getString("ttt.lose"), Color.RED), BorderLayout.SOUTH); + } + if (_gameboard.getWinner() == -1) { + remove(_playerdisplay); + add(new GameEndsUI(TTTRes.getString("ttt.tie"), Color.BLACK), BorderLayout.SOUTH); + } + + + ShakeWindow sw = new ShakeWindow(_frame); + sw.startShake(); + repaint(); + revalidate(); + + } + } + + public Mark getMyMark() { + return me; + } + + public Mark getYourMark() { + if (me == Mark.X) + return Mark.O; + else + return Mark.X; + } + + public boolean myTurn() { + return _playerdisplay.getCurrentPlayer() == getMyMark() + && !_gameboard.isGameFinished(); + } + + public boolean isFree(int x, int y) { + return _gameboard.getMarkAtPos(x, y) == Mark.BLANK; + } + +} diff --git a/src/plugins/tictactoe/src/java/tic/tac/toe/ui/PlayerDisplay.java b/plugins/tictactoe/src/main/java/tic/tac/toe/ui/PlayerDisplay.java similarity index 89% rename from src/plugins/tictactoe/src/java/tic/tac/toe/ui/PlayerDisplay.java rename to plugins/tictactoe/src/main/java/tic/tac/toe/ui/PlayerDisplay.java index 8133d02bb..3116d5c01 100644 --- a/src/plugins/tictactoe/src/java/tic/tac/toe/ui/PlayerDisplay.java +++ b/plugins/tictactoe/src/main/java/tic/tac/toe/ui/PlayerDisplay.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,9 +21,8 @@ import javax.swing.JLabel; import javax.swing.JPanel; -import org.jivesoftware.smack.util.StringUtils; - -import org.jxmpp.util.XmppStringUtils; +import org.jxmpp.jid.EntityFullJid; +import org.jxmpp.jid.parts.Localpart; import tic.tac.toe.Mark; import tic.tac.toe.TTTRes; @@ -47,10 +42,10 @@ public class PlayerDisplay extends JPanel { private static final long serialVersionUID = -8025502708415186558L; - private JLabel _currentplayer; + private final JLabel _currentplayer; private Mark _currentMark; - public PlayerDisplay(Mark myself, String opponent) { + public PlayerDisplay(Mark myself, EntityFullJid opponent) { _currentplayer = new JLabel(" | "+TTTRes.getString("ttt.display.current")); @@ -70,7 +65,7 @@ public PlayerDisplay(Mark myself, String opponent) { else you = Mark.X; - String name = XmppStringUtils.parseLocalpart(opponent); + Localpart name = opponent.getLocalpart(); JLabel yourlabel = new JLabel(" | "+name); yourlabel.setIcon(new ImageIcon(you.getImage().getImage() .getScaledInstance(16, 16, Image.SCALE_SMOOTH))); diff --git a/plugins/tictactoe/src/main/plugin-metadata/plugin.xml b/plugins/tictactoe/src/main/plugin-metadata/plugin.xml new file mode 100644 index 000000000..ae2d1b787 --- /dev/null +++ b/plugins/tictactoe/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,12 @@ + + ${project.name} + ${project.version} + ${project.description} + tic.tac.toe.TicTacToePlugin + Wolf Posdorfer + https://IgniteRealtime.org + support@IgniteRealtime.org + 3.1.0 + Windows,Linux,Mac + 11 + diff --git a/plugins/tictactoe/src/main/resources/board.png b/plugins/tictactoe/src/main/resources/board.png new file mode 100644 index 000000000..9a19ee1e9 Binary files /dev/null and b/plugins/tictactoe/src/main/resources/board.png differ diff --git a/plugins/tictactoe/src/main/resources/empty.png b/plugins/tictactoe/src/main/resources/empty.png new file mode 100644 index 000000000..ef3a7fcbe Binary files /dev/null and b/plugins/tictactoe/src/main/resources/empty.png differ diff --git a/src/plugins/tictactoe/src/resources/i18n/tictactoe_i18n.properties b/plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n.properties similarity index 91% rename from src/plugins/tictactoe/src/resources/i18n/tictactoe_i18n.properties rename to plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n.properties index 2a52092eb..32e99d2f2 100644 --- a/src/plugins/tictactoe/src/resources/i18n/tictactoe_i18n.properties +++ b/plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n.properties @@ -13,4 +13,4 @@ ttt.display.me = I am: ttt.display.current = currently playing: ttt.request.decline = The game request has been denied. ttt.request.accept = The game is starting. -ttt.request.sent = Sending game request... \ No newline at end of file +ttt.request.sent = Sending game request... diff --git a/src/plugins/tictactoe/src/resources/i18n/tictactoe_i18n_de.properties b/plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n_de.properties similarity index 78% rename from src/plugins/tictactoe/src/resources/i18n/tictactoe_i18n_de.properties rename to plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n_de.properties index 277d1d782..1d292d7c7 100644 --- a/src/plugins/tictactoe/src/resources/i18n/tictactoe_i18n_de.properties +++ b/plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n_de.properties @@ -6,11 +6,11 @@ ttt.game.request = {0} fordert eine Partie ttt.game.name = Tic Tac Toe des Verderbens ttt.window.title ={0} gegen {1} -ttt.win = Glückwunsch, Du hast gewonnen! -ttt.lose = Leider verloren. +ttt.win = Glückwunsch, Du hast gewonnen! +ttt.lose = Leider verloren! ttt.tie = Unentschieden. ttt.display.me = Ich bin: ttt.display.current = Zurzeit spielt: ttt.request.decline = Die Spielanfrage wurde abgelehnt. ttt.request.accept = Das Spiel beginnt. -ttt.request.sent = Sende Spielanfrage... \ No newline at end of file +ttt.request.sent = Sende Spielanfrage... diff --git a/plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n_lt.properties b/plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n_lt.properties new file mode 100644 index 000000000..f884d2e09 --- /dev/null +++ b/plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n_lt.properties @@ -0,0 +1,16 @@ +########################### +# Tic Tac Toe # +# by wolf.posdorfer # +########################### + +ttt.game.request = {0} užklausÄ— Kryžiukai-nuliukai žaidimo +ttt.game.name = Kryžiukai-nuliukai +ttt.window.title = {0} prieÅ¡ {1} +ttt.win = Sveikiname, jÅ«s laimÄ—jote! +ttt.lose = ApgailÄ—staujame, jÅ«s pralaimÄ—jote! +ttt.tie = Žaidimas baigÄ—si lygiosiomis. +ttt.display.me = AÅ¡ esu: +ttt.display.current = Å¡iuo metu žaidžia: +ttt.request.decline = Žaidimas praÅ¡ymas buvo atmestas. +ttt.request.accept = Žaidimas prasideda. +ttt.request.sent = SiunÄiama žaidimo užklausa... diff --git a/src/plugins/tictactoe/src/resources/i18n/tictactoe_i18n_nl.properties b/plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n_nl.properties similarity index 92% rename from src/plugins/tictactoe/src/resources/i18n/tictactoe_i18n_nl.properties rename to plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n_nl.properties index 8838408ed..46c1ec822 100644 --- a/src/plugins/tictactoe/src/resources/i18n/tictactoe_i18n_nl.properties +++ b/plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n_nl.properties @@ -13,4 +13,4 @@ ttt.display.me = Ik ben: ttt.display.current = op dit moment spelen: ttt.request.decline = Het spel verzoek is afgewezen. ttt.request.accept = Het spel begint. -ttt.request.sent = Verzenden spel verzoek ... \ No newline at end of file +ttt.request.sent = Verzenden spel verzoek ... diff --git a/src/plugins/tictactoe/src/resources/i18n/tictactoe_i18n_pt.properties b/plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n_pt.properties similarity index 91% rename from src/plugins/tictactoe/src/resources/i18n/tictactoe_i18n_pt.properties rename to plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n_pt.properties index 500cc9d48..47049b118 100644 --- a/src/plugins/tictactoe/src/resources/i18n/tictactoe_i18n_pt.properties +++ b/plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n_pt.properties @@ -13,4 +13,4 @@ ttt.display.me = I am: ttt.display.current = a jogar agora: ttt.request.decline = O pedido foi negado jogo. ttt.request.accept = O jogo está comecando. -ttt.request.sent = Enviando pedido jogo ... \ No newline at end of file +ttt.request.sent = Enviando pedido jogo ... diff --git a/plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n_ru_RU.properties b/plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n_ru_RU.properties new file mode 100644 index 000000000..60af2202b --- /dev/null +++ b/plugins/tictactoe/src/main/resources/i18n/tictactoe_i18n_ru_RU.properties @@ -0,0 +1,16 @@ +########################### +# Tic Tac Toe # +# by wolf.posdorfer # +########################### + +ttt.game.request = {0} запрашивает игру +ttt.game.name = КреÑтики-нолики Ñудьбы +ttt.window.title = {0} против {1} +ttt.win = ПоздравлÑÑŽ, вы победили! +ttt.lose = ПроÑти, ты проиграл! +ttt.tie = Игра закончилаÑÑŒ вничью. +ttt.display.me = Я: +ttt.display.current = в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð¸Ð³Ñ€Ð°ÐµÑ‚: +ttt.request.decline = Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° игру был отклонен. +ttt.request.accept = Игра начинаетÑÑ. +ttt.request.sent = Отправка запроÑа на игру... diff --git a/plugins/tictactoe/src/main/resources/o.blue.png b/plugins/tictactoe/src/main/resources/o.blue.png new file mode 100644 index 000000000..7752cf1b6 Binary files /dev/null and b/plugins/tictactoe/src/main/resources/o.blue.png differ diff --git a/plugins/tictactoe/src/main/resources/o.png b/plugins/tictactoe/src/main/resources/o.png new file mode 100644 index 000000000..2144c5f8f Binary files /dev/null and b/plugins/tictactoe/src/main/resources/o.png differ diff --git a/plugins/tictactoe/src/main/resources/ttt.button.png b/plugins/tictactoe/src/main/resources/ttt.button.png new file mode 100644 index 000000000..6fbc831ac Binary files /dev/null and b/plugins/tictactoe/src/main/resources/ttt.button.png differ diff --git a/src/plugins/tictactoe/src/resources/ttt.button.png b/plugins/tictactoe/src/main/resources/ttt.button2.png similarity index 100% rename from src/plugins/tictactoe/src/resources/ttt.button.png rename to plugins/tictactoe/src/main/resources/ttt.button2.png diff --git a/plugins/tictactoe/src/main/resources/ttt.button3.png b/plugins/tictactoe/src/main/resources/ttt.button3.png new file mode 100644 index 000000000..2e4a058b4 Binary files /dev/null and b/plugins/tictactoe/src/main/resources/ttt.button3.png differ diff --git a/plugins/tictactoe/src/main/resources/x.blue.png b/plugins/tictactoe/src/main/resources/x.blue.png new file mode 100644 index 000000000..2e04fc32e Binary files /dev/null and b/plugins/tictactoe/src/main/resources/x.blue.png differ diff --git a/plugins/tictactoe/src/main/resources/x.png b/plugins/tictactoe/src/main/resources/x.png new file mode 100644 index 000000000..94a210dd3 Binary files /dev/null and b/plugins/tictactoe/src/main/resources/x.png differ diff --git a/plugins/transferguard/pom.xml b/plugins/transferguard/pom.xml new file mode 100644 index 000000000..ff5afd0b9 --- /dev/null +++ b/plugins/transferguard/pom.xml @@ -0,0 +1,34 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + transferguard + 1.3 + + Transfer Guard + Adds the ability to automatically reject file transfers based on preference configuration. + + + + Pete Matern + Jive Software + pete@jivesoftware.com + + Author + + + + Tim Jentz + + Author + + + + diff --git a/src/plugins/transferguard/src/java/org/jivesoftware/spark/plugins/transfersettings/FileTransferSettings.java b/plugins/transferguard/src/main/java/org/jivesoftware/spark/plugins/transfersettings/FileTransferSettings.java similarity index 87% rename from src/plugins/transferguard/src/java/org/jivesoftware/spark/plugins/transfersettings/FileTransferSettings.java rename to plugins/transferguard/src/main/java/org/jivesoftware/spark/plugins/transfersettings/FileTransferSettings.java index 6fc8aff9a..1792020ff 100644 --- a/src/plugins/transferguard/src/java/org/jivesoftware/spark/plugins/transfersettings/FileTransferSettings.java +++ b/plugins/transferguard/src/main/java/org/jivesoftware/spark/plugins/transfersettings/FileTransferSettings.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,19 +23,25 @@ import java.util.Iterator; import java.util.List; import java.util.Properties; +import java.util.Set; import java.util.StringTokenizer; +import org.jivesoftware.Spark; +import org.jivesoftware.spark.util.log.Log; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.util.JidUtil; + /** * Bean whose properties are the various preference settings for file transfer. */ public class FileTransferSettings { private List extensions = new ArrayList<>(); - private List JIDs = new ArrayList<>(); + private List JIDs = new ArrayList<>(); private int kb; private boolean checkSize = false; String cannedRejectionMessage; - private static File BACKING_STORE = new File(System.getProperty("user.home") + "/.sparkExt.properties"); + private static final File BACKING_STORE = new File(Spark.getSparkUserHome(), "/transferguard.properties"); /** @@ -62,7 +64,7 @@ public void setBlockedExtensions(List extensions){ * Returns a {@link List} of blocked JIDs. File transfers from users with those JIDs will be automaticlly rejected. * @return a {@link List} of blocked JIDs. */ - public List getBlockedJIDs() { + public List getBlockedJIDs() { return JIDs; } @@ -70,7 +72,7 @@ public List getBlockedJIDs() { * Sets the {@link List} of blocked JIDs. * @param JIDs the {@link List} of blocked JIDs. */ - public void setBlockedJIDS(List JIDs){ + public void setBlockedJIDS(List JIDs){ this.JIDs = JIDs; } @@ -143,12 +145,14 @@ public void load() { String users = props.getProperty("jids"); if (users != null) { - this.JIDs = convertSettingsStringToList(users); + List jidStrings = convertSettingsStringToList(users); + Set jidSet = JidUtil.entityBareJidSetFrom(jidStrings); + this.JIDs = new ArrayList<>(jidSet); } String ignore = props.getProperty("checkFileSize"); if (ignore != null) { - this.checkSize = Boolean.valueOf(ignore); + this.checkSize = Boolean.parseBoolean(ignore); } String maxSize = props.getProperty("maxSize"); @@ -183,7 +187,7 @@ public void store() { props.store(new FileOutputStream(BACKING_STORE), BACKING_STORE.getAbsolutePath()); } catch (IOException ioe) { - System.err.println(ioe); + Log.error(ioe); } } @@ -192,9 +196,9 @@ public void store() { * @param settings the {@link List} of strings. * @return a comma separated string. */ - public static String convertSettingsListToString(List settings) { + public static String convertSettingsListToString(List settings) { StringBuilder buffer = new StringBuilder(); - for (Iterator iter=settings.iterator(); iter.hasNext(); ) { + for (Iterator iter = settings.iterator(); iter.hasNext(); ) { buffer.append(iter.next()); if (iter.hasNext()) { buffer.append(","); @@ -217,4 +221,4 @@ public static List convertSettingsStringToList(String settings) { } return list; } -} \ No newline at end of file +} diff --git a/src/plugins/transferguard/src/java/org/jivesoftware/spark/plugins/transfersettings/FileTransferSettingsPlugin.java b/plugins/transferguard/src/main/java/org/jivesoftware/spark/plugins/transfersettings/FileTransferSettingsPlugin.java similarity index 82% rename from src/plugins/transferguard/src/java/org/jivesoftware/spark/plugins/transfersettings/FileTransferSettingsPlugin.java rename to plugins/transferguard/src/main/java/org/jivesoftware/spark/plugins/transfersettings/FileTransferSettingsPlugin.java index b7fa1cc7e..6afab4c53 100644 --- a/src/plugins/transferguard/src/java/org/jivesoftware/spark/plugins/transfersettings/FileTransferSettingsPlugin.java +++ b/plugins/transferguard/src/main/java/org/jivesoftware/spark/plugins/transfersettings/FileTransferSettingsPlugin.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +17,7 @@ import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smackx.filetransfer.FileTransferRequest; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.filetransfer.FileTransferListener; @@ -81,14 +78,10 @@ private boolean requestContainsBannedFile(FileTransferRequest request, FileTrans if (settings.getCheckFileSize() && request.getFileSize() > settings.getMaxFileSize()) { return true; } - if (settings.getBlockedJIDs().contains(trimJID(request.getRequestor()))) { + if (settings.getBlockedJIDs().contains(request.getRequestor().asBareJid())) { return true; } - if (settings.getBlockedExtensions().contains(getFileExtensionFromName(request.getFileName()))) { - return true; - } - return false; - + return settings.getBlockedExtensions().contains(getFileExtensionFromName(request.getFileName())); } /** @@ -107,24 +100,6 @@ private String getFileExtensionFromName(String filename) { return null; } - /** - * Trims the resource off the end of the supplied JID. For example, 'dude@jivesoftware.com/spark' would return - * 'dude@jivesoftware.com' - * - * @param completeJID the JID which possibly includes a resource. - * @return the JID without the resource. - */ - private String trimJID(String completeJID) { - int slashIDX = completeJID.indexOf('/'); - if (slashIDX > 0) { - return completeJID.substring(0, slashIDX); - } - else { - return completeJID; - } - } - - /** * Adds a {@link FileTransferListener} to allow this plugin to intercept {@link FileTransferRequest}s. */ @@ -144,9 +119,10 @@ private void addTransferListener() { String responseMessage = settings.getCannedRejectionMessage(); if ( responseMessage != null && responseMessage.length() > 0 ) { - Message message = new Message(); + Message message = StanzaBuilder.buildMessage() + .setBody( responseMessage ) + .build(); message.setTo( request.getRequestor() ); - message.setBody( responseMessage ); SparkManager.getConnection().sendStanza( message ); } return true; @@ -156,11 +132,11 @@ private void addTransferListener() { return false; } } - catch (SmackException ex) + catch (SmackException | InterruptedException ex) { Log.warning( "Unable to handle file transfer.", ex ); return false; } } ); } -} \ No newline at end of file +} diff --git a/plugins/transferguard/src/main/java/org/jivesoftware/spark/plugins/transfersettings/TGuardRes.java b/plugins/transferguard/src/main/java/org/jivesoftware/spark/plugins/transfersettings/TGuardRes.java new file mode 100644 index 000000000..51aea5694 --- /dev/null +++ b/plugins/transferguard/src/main/java/org/jivesoftware/spark/plugins/transfersettings/TGuardRes.java @@ -0,0 +1,36 @@ +package org.jivesoftware.spark.plugins.transfersettings; + +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +import org.jivesoftware.resource.UTF8Control; +import org.jivesoftware.spark.util.log.Log; + +/** + * Use for Transferguard Ressource Internationalization. + * + * @author tim.jentz + */ +public class TGuardRes { + private static final PropertyResourceBundle prb; + + private TGuardRes() { + + } + + static { + prb = (PropertyResourceBundle) ResourceBundle + .getBundle("i18n/transferguard_i18n", new UTF8Control()); + } + + public static String getString(String propertyName) { + try { + return prb.getString(propertyName); + } catch (Exception e) { + Log.error(e); + return propertyName; + } + } + + +} diff --git a/src/plugins/transferguard/src/java/org/jivesoftware/spark/plugins/transfersettings/TransferSettingsPanel.java b/plugins/transferguard/src/main/java/org/jivesoftware/spark/plugins/transfersettings/TransferSettingsPanel.java similarity index 82% rename from src/plugins/transferguard/src/java/org/jivesoftware/spark/plugins/transfersettings/TransferSettingsPanel.java rename to plugins/transferguard/src/main/java/org/jivesoftware/spark/plugins/transfersettings/TransferSettingsPanel.java index 3f107e6fb..ff2d30966 100644 --- a/src/plugins/transferguard/src/java/org/jivesoftware/spark/plugins/transfersettings/TransferSettingsPanel.java +++ b/plugins/transferguard/src/main/java/org/jivesoftware/spark/plugins/transfersettings/TransferSettingsPanel.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,22 +16,26 @@ package org.jivesoftware.spark.plugins.transfersettings; import org.jivesoftware.spark.component.VerticalFlowLayout; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.util.JidUtil; import javax.swing.*; import java.awt.*; import javax.swing.border.*; +import java.util.ArrayList; import java.util.List; +import java.util.Set; /** * UI for the file transfer preferences. It displays all the various preference settings for editing. */ public class TransferSettingsPanel extends JPanel { private static final long serialVersionUID = -2481011951921919518L; - private BlockedTypesPanel pnlTypes = new BlockedTypesPanel(); - private BlockedPeoplePanel pnlPeople = new BlockedPeoplePanel(); - private FileSizePanel pnlSize = new FileSizePanel(); - private CannedResponsePanel pnlResponse = new CannedResponsePanel(); + private final BlockedTypesPanel pnlTypes = new BlockedTypesPanel(); + private final BlockedPeoplePanel pnlPeople = new BlockedPeoplePanel(); + private final FileSizePanel pnlSize = new FileSizePanel(); + private final CannedResponsePanel pnlResponse = new CannedResponsePanel(); public TransferSettingsPanel() { setLayout(new VerticalFlowLayout()); @@ -69,9 +69,9 @@ public void storeSettings(FileTransferSettings settings) { settings.setCannedRejectionMessage(pnlResponse.getCannedResponse()); } - private class BlockedTypesPanel extends JPanel { + private static class BlockedTypesPanel extends JPanel { private static final long serialVersionUID = 6152402556852606706L; - private JTextArea txtBlockedTypes = new JTextArea(2, 0); + private final JTextArea txtBlockedTypes = new JTextArea(2, 0); BlockedTypesPanel() { txtBlockedTypes.setBorder(UIManager.getLookAndFeelDefaults().getBorder("TextField.border")); @@ -92,9 +92,9 @@ public List getBlockedTypes() { } } - private class BlockedPeoplePanel extends JPanel { + private static class BlockedPeoplePanel extends JPanel { private static final long serialVersionUID = -1069560705582838620L; - private JTextArea txtBlockedPeople = new JTextArea(2, 0); + private final JTextArea txtBlockedPeople = new JTextArea(2, 0); BlockedPeoplePanel() { txtBlockedPeople.setBorder(UIManager.getLookAndFeelDefaults().getBorder("TextField.border")); @@ -105,19 +105,21 @@ private class BlockedPeoplePanel extends JPanel { add(txtBlockedPeople, BorderLayout.CENTER); } - public void setBlockedPeople(List people) { + public void setBlockedPeople(List people) { txtBlockedPeople.setText(FileTransferSettings.convertSettingsListToString(people)); } - public List getBlockedPeople() { - return FileTransferSettings.convertSettingsStringToList(txtBlockedPeople.getText()); + public List getBlockedPeople() { + List jidStrings = FileTransferSettings.convertSettingsStringToList(txtBlockedPeople.getText()); + Set jidSet = JidUtil.entityBareJidSetFrom(jidStrings); + return new ArrayList<>(jidSet); } } - private class FileSizePanel extends JPanel { + private static class FileSizePanel extends JPanel { private static final long serialVersionUID = -8457074359832858639L; - private JSpinner spinMaxSize = new JSpinner(); - private JCheckBox chkMaxEnabled = new JCheckBox(TGuardRes.getString("guard.settings.limitcheck")); + private final JSpinner spinMaxSize = new JSpinner(); + private final JCheckBox chkMaxEnabled = new JCheckBox(TGuardRes.getString("guard.settings.limitcheck")); FileSizePanel() { setLayout(new VerticalFlowLayout()); @@ -157,9 +159,9 @@ public boolean getCheckFileSize() { } } - private class CannedResponsePanel extends JPanel { + private static class CannedResponsePanel extends JPanel { private static final long serialVersionUID = -5992704440953686488L; - private JTextArea txtMessage = new JTextArea(2, 0); + private final JTextArea txtMessage = new JTextArea(2, 0); CannedResponsePanel() { txtMessage.setBorder(UIManager.getLookAndFeelDefaults().getBorder("TextField.border")); @@ -178,4 +180,4 @@ public String getCannedResponse() { return txtMessage.getText().trim(); } } -} \ No newline at end of file +} diff --git a/src/plugins/transferguard/src/java/org/jivesoftware/spark/plugins/transfersettings/TransferSettingsPreference.java b/plugins/transferguard/src/main/java/org/jivesoftware/spark/plugins/transfersettings/TransferSettingsPreference.java similarity index 92% rename from src/plugins/transferguard/src/java/org/jivesoftware/spark/plugins/transfersettings/TransferSettingsPreference.java rename to plugins/transferguard/src/main/java/org/jivesoftware/spark/plugins/transfersettings/TransferSettingsPreference.java index a48379c53..20f97e155 100644 --- a/src/plugins/transferguard/src/java/org/jivesoftware/spark/plugins/transfersettings/TransferSettingsPreference.java +++ b/plugins/transferguard/src/main/java/org/jivesoftware/spark/plugins/transfersettings/TransferSettingsPreference.java @@ -1,8 +1,4 @@ /** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,8 +25,8 @@ * Preference object for file transfer settings. Used by Spark to show the associated UI and commit changes to preference settings. */ public class TransferSettingsPreference implements Preference { - private TransferSettingsPanel gui = new TransferSettingsPanel(); - private FileTransferSettings settings = new FileTransferSettings(); + private final TransferSettingsPanel gui = new TransferSettingsPanel(); + private final FileTransferSettings settings = new FileTransferSettings(); /** * Called when preference settings should be persisted. @@ -55,7 +51,7 @@ public Object getData() { * @return an error message to display if calls to {@link #isDataValid} return false. */ public String getErrorMessage() { - return "What happend here?"; + return "What happened here?"; } /** @@ -74,7 +70,7 @@ public javax.swing.JComponent getGUI() { * @return the {@link Icon} to show in the preferences ui. */ public javax.swing.Icon getIcon() { - return new ImageIcon(getClass().getResource("/images/knight.png")); + return new ImageIcon(getClass().getResource("/images/guard.png")); } /** @@ -124,7 +120,7 @@ public boolean isDataValid() { } /** - * Called when data should be loaded from the persistent stor. + * Called when data should be loaded from the persistent store. */ public void load() { settings.load(); @@ -135,4 +131,4 @@ public void load() { */ public void shutdown() { } -} \ No newline at end of file +} diff --git a/plugins/transferguard/src/main/plugin-metadata/plugin.xml b/plugins/transferguard/src/main/plugin-metadata/plugin.xml new file mode 100644 index 000000000..b5c8e6832 --- /dev/null +++ b/plugins/transferguard/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,13 @@ + + + ${project.name} + ${project.version} + ${project.description} + Pete Matern, Tim Jentz + https://IgniteRealtime.org + support@IgniteRealtime.org + org.jivesoftware.spark.plugins.transfersettings.FileTransferSettingsPlugin + 3.1.0 + 11 + + diff --git a/src/plugins/transferguard/changelog.html b/plugins/transferguard/src/main/resources/changelog.html similarity index 100% rename from src/plugins/transferguard/changelog.html rename to plugins/transferguard/src/main/resources/changelog.html diff --git a/src/plugins/transferguard/src/resources/i18n/transferguard_i18n.properties b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n.properties similarity index 96% rename from src/plugins/transferguard/src/resources/i18n/transferguard_i18n.properties rename to plugins/transferguard/src/main/resources/i18n/transferguard_i18n.properties index 876ac10c9..a6b2b8e77 100644 --- a/src/plugins/transferguard/src/resources/i18n/transferguard_i18n.properties +++ b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n.properties @@ -8,7 +8,7 @@ ## spark_i18n "_" language ".properties" ## ## e.g. -## spark_i18n_en.propertis <- English resources +## spark_i18n_en.properties <- English resources ## spark_i18n_en_US.properties <- American US resources ## spark_i18n_de.properties <- German resources ## spark_i18n_ja.properties <- Japanese resources @@ -51,4 +51,4 @@ guard.settings.title.person = Blocked Senders guard.settings.title.rejectresponse = Automated Rejection Response guard.settings.label.maxsize = Maximum Size in KB: guard.settings.title.filesize = File Size -guard.settings.limitcheck = Limit File Size \ No newline at end of file +guard.settings.limitcheck = Limit File Size diff --git a/src/plugins/transferguard/src/resources/i18n/transferguard_i18n_de.properties b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_de.properties similarity index 81% rename from src/plugins/transferguard/src/resources/i18n/transferguard_i18n_de.properties rename to plugins/transferguard/src/main/resources/i18n/transferguard_i18n_de.properties index 6f5092720..1d3ff6da6 100644 --- a/src/plugins/transferguard/src/resources/i18n/transferguard_i18n_de.properties +++ b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_de.properties @@ -8,7 +8,7 @@ ## spark_i18n "_" language ".properties" ## ## e.g. -## spark_i18n_en.propertis <- English resources +## spark_i18n_en.properties <- English resources ## spark_i18n_en_US.properties <- American US resources ## spark_i18n_de.properties <- German resources ## spark_i18n_ja.properties <- Japanese resources @@ -42,12 +42,12 @@ ## guard.settings.title.settings = File Transfer Einstellungen -guard.settings.tooltips.blockedtypes = Bitte geben Sie Dateiendungen ein, die blockiert werden sollen (z.B. '*.doc'). Mehrere Eingaben mit Komma getrennt möglich. -guard.settings.tooltips.blockedperson = Bitte geben Sie die JIDs der Benutzer ein, von denen Sie den Dateitransfer blockieren wollen (z.B. 'loser@domain.com'). Mehrere Eingaben mit Komma getrennt möglich. -guard.settings.tooltips.textarea = Bitte geben Sie eine Nachricht für die Nutzer ein, deren Dateien durch Ihre Einstellungen blockiert wurden. Lassen Sie dieses feld frei, wenn Sie keine Nachricht senden wollen. +guard.settings.tooltips.blockedtypes = Bitte geben Sie Dateiendungen ein, die blockiert werden sollen (z.B. '*.doc'). Mehrere Eingaben mit Komma getrennt möglich. +guard.settings.tooltips.blockedperson = Bitte geben Sie die JIDs der Benutzer ein, von denen Sie den Dateitransfer blockieren wollen (z.B. 'loser@domain.com'). Mehrere Eingaben mit Komma getrennt möglich. +guard.settings.tooltips.textarea = Bitte geben Sie eine Nachricht für die Nutzer ein, deren Dateien durch Ihre Einstellungen blockiert wurden. Lassen Sie dieses feld frei, wenn Sie keine Nachricht senden wollen. guard.settings.title.extensions = Blockierte Dateiendungen guard.settings.title.person = Blockierte Sender -guard.settings.title.rejectresponse = Nachricht für automatisches Abweisen -guard.settings.label.maxsize = Maximale Größe in KB: -guard.settings.title.filesize = Dateigröße -guard.settings.limitcheck = Limit für Dateigröße \ No newline at end of file +guard.settings.title.rejectresponse = Nachricht für automatisches Abweisen +guard.settings.label.maxsize = Maximale Größe in KB: +guard.settings.title.filesize = Dateigröße +guard.settings.limitcheck = Limit für Dateigröße diff --git a/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_fr.properties b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_fr.properties new file mode 100644 index 000000000..73aa5f710 --- /dev/null +++ b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_fr.properties @@ -0,0 +1,54 @@ +## +## Transferguard Language File +## +## Additional locales can be specified by creating a new resource file in this +## directory using the following conventions: +## +## spark_i18n "_" language "_" country ".properties" +## spark_i18n "_" language ".properties" +## +## e.g. +## spark_i18n_en.properties <- English resources +## spark_i18n_en_US.properties <- American US resources +## spark_i18n_de.properties <- German resources +## spark_i18n_ja.properties <- Japanese resources +## +## Please note that the two digit language code should be lower case, and the +## two digit country code should be in uppercase. Often, it is not necessary to +## specify the country code. +## +## A full list of language codes can be found at +## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt +## and a full list of country codes can be found at +## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html +## +## In property strings that are parameterized, single quotes can be used to +## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. +## +## +## REVISION HISTORY (by Transferguard version): +## +## 1.0.1 +## Added key: 'guard.settings.tooltips.blockedtypes' +## Added key: 'guard.settings.tooltips.blockedperson' +## Added key: 'guard.settings.tooltips.textarea' +## Added key: 'guard.settings.title.extensions' +## Added key: 'guard.settings.title.person' +## Added key: 'guard.settings.title.rejectresponse' +## Added key: 'guard.settings.label.maxsize' +## Added key: 'guard.settings.title.filesize' +## Added key: 'guard.settings.limitcheck' +## Added key: 'guard.settings.title.settings' +## + +guard.settings.title.list = protection de transfert +guard.settings.title.settings = Paramètres de transfert de fichiers +guard.settings.tooltips.blockedtypes = Saisissez les extensions de fichier que vous souhaitez bloquer (par ex. '*.doc'), séparées par des virgules +guard.settings.tooltips.blockedperson = Entrez le JID des utilisateurs dont vous souhaitez bloquer les transferts de fichiers (par exemple, 'loser@domain.com'), séparés par des virgules +guard.settings.tooltips.textarea = Entrez un message que vous souhaitez envoyer à ceux dont les fichiers sont bloqués par vos paramètres. Laissez cet espace vide si vous ne souhaitez pas leur envoyer de message. +guard.settings.title.extensions = Extensions de fichiers bloquées +guard.settings.title.person = Expéditeurs bloqués +guard.settings.title.rejectresponse = Réponse automatique de rejet +guard.settings.label.maxsize = Taille maximale en Ko : +guard.settings.title.filesize = Taille du Fichier +guard.settings.limitcheck = Limiter la taille du fichier diff --git a/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_lt.properties b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_lt.properties new file mode 100644 index 000000000..88923a323 --- /dev/null +++ b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_lt.properties @@ -0,0 +1,54 @@ +## +## Transferguard Language File +## +## Additional locales can be specified by creating a new resource file in this +## directory using the following conventions: +## +## spark_i18n "_" language "_" country ".properties" +## spark_i18n "_" language ".properties" +## +## e.g. +## spark_i18n_en.properties <- English resources +## spark_i18n_en_US.properties <- American US resources +## spark_i18n_de.properties <- German resources +## spark_i18n_ja.properties <- Japanese resources +## +## Please note that the two digit language code should be lower case, and the +## two digit country code should be in uppercase. Often, it is not necessary to +## specify the country code. +## +## A full list of language codes can be found at +## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt +## and a full list of country codes can be found at +## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html +## +## In property strings that are parameterized, single quotes can be used to +## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. +## +## +## REVISION HISTORY (by Transferguard version): +## +## 1.0.1 +## Added key: 'guard.settings.tooltips.blockedtypes' +## Added key: 'guard.settings.tooltips.blockedperson' +## Added key: 'guard.settings.tooltips.textarea' +## Added key: 'guard.settings.title.extensions' +## Added key: 'guard.settings.title.person' +## Added key: 'guard.settings.title.rejectresponse' +## Added key: 'guard.settings.label.maxsize' +## Added key: 'guard.settings.title.filesize' +## Added key: 'guard.settings.limitcheck' +## Added key: 'guard.settings.title.settings' +## + +guard.settings.title.list = Persiuntimų apsauga +guard.settings.title.settings = Bylų persiuntimo nustatymai +guard.settings.tooltips.blockedtypes = Ä®veskite bylų iÅ¡plÄ—timus, kuriuos norite blokuoti (pvz. '*.doc'), atskiriant kableliais +guard.settings.tooltips.blockedperson = Ä®veskite "JID'us" vartotojų iÅ¡ kurių nenorite gauti bylų persiuntimų (pvz. 'kazkas@domain.com'), atskiriant kableliais +guard.settings.tooltips.textarea = Ä®veskite praneÅ¡imo tekstÄ…, kuris bus parodytas vartotojams, kurių siuntimus blokuosite. Palikite šį laukelį tuÅ¡ÄiÄ…, jei nenorite siųsti jiems praneÅ¡imo. +guard.settings.title.extensions = Blokuojami bylų iÅ¡plÄ—timai +guard.settings.title.person = Blokuojami siuntÄ—jai +guard.settings.title.rejectresponse = Automatinis siuntimo blokavimo praneÅ¡imas +guard.settings.label.maxsize = Maksimalus dydis kilobaitais (KB): +guard.settings.title.filesize = Bylos dydis +guard.settings.limitcheck = Apriboti bylos dydį diff --git a/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_pl.properties b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_pl.properties new file mode 100644 index 000000000..e5b2af7fe --- /dev/null +++ b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_pl.properties @@ -0,0 +1,54 @@ +## +## Transferguard Language File +## +## Additional locales can be specified by creating a new resource file in this +## directory using the following conventions: +## +## spark_i18n "_" language "_" country ".properties" +## spark_i18n "_" language ".properties" +## +## e.g. +## spark_i18n_en.properties <- English resources +## spark_i18n_en_US.properties <- American US resources +## spark_i18n_de.properties <- German resources +## spark_i18n_ja.properties <- Japanese resources +## +## Please note that the two digit language code should be lower case, and the +## two digit country code should be in uppercase. Often, it is not necessary to +## specify the country code. +## +## A full list of language codes can be found at +## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt +## and a full list of country codes can be found at +## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html +## +## In property strings that are parameterized, single quotes can be used to +## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. +## +## +## REVISION HISTORY (by Transferguard version): +## +## 1.0.1 +## Added key: 'guard.settings.tooltips.blockedtypes' +## Added key: 'guard.settings.tooltips.blockedperson' +## Added key: 'guard.settings.tooltips.textarea' +## Added key: 'guard.settings.title.extensions' +## Added key: 'guard.settings.title.person' +## Added key: 'guard.settings.title.rejectresponse' +## Added key: 'guard.settings.label.maxsize' +## Added key: 'guard.settings.title.filesize' +## Added key: 'guard.settings.limitcheck' +## Added key: 'guard.settings.title.settings' +## + +guard.settings.title.list = Strażnik transferu plików +guard.settings.title.settings = Ustawienia transferu plików +guard.settings.tooltips.blockedtypes = Wpisz rozszerzenia plików, których przesyÅ‚ chcesz blokować (np. '*.doc'), oddzielajÄ…c je przecinkami +guard.settings.tooltips.blockedperson = Wpisz identyfikator JID użytkowników, od których chcesz blokować przesyÅ‚ plików, oddzielajÄ…c je przecinkami +guard.settings.tooltips.textarea = Wpisz wiadomość, którÄ… chcesz wysyÅ‚ać tym którym blokujesz przesyÅ‚anie plików. Pozostaw puste jeÅ›li nie chcesz wysyÅ‚ać im wiadomoÅ›ci. +guard.settings.title.extensions = Blokowane rozszerzenia plików +guard.settings.title.person = Zablokowani przesyÅ‚ajÄ…cy pliki +guard.settings.title.rejectresponse = Automatyczna odpowiedź odrzucenia +guard.settings.label.maxsize = Maksymalna wielkość w KB: +guard.settings.title.filesize = Rozmiar pliku +guard.settings.limitcheck = Ograniczenie wielkoÅ›ci pliku diff --git a/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_pt_PT.properties b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_pt_PT.properties new file mode 100644 index 000000000..0a497041d --- /dev/null +++ b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_pt_PT.properties @@ -0,0 +1,54 @@ +## +## Transferguard Language File +## +## Additional locales can be specified by creating a new resource file in this +## directory using the following conventions: +## +## spark_i18n "_" language "_" country ".properties" +## spark_i18n "_" language ".properties" +## +## e.g. +## spark_i18n_en.properties <- English resources +## spark_i18n_en_US.properties <- American US resources +## spark_i18n_de.properties <- German resources +## spark_i18n_ja.properties <- Japanese resources +## +## Please note that the two digit language code should be lower case, and the +## two digit country code should be in uppercase. Often, it is not necessary to +## specify the country code. +## +## A full list of language codes can be found at +## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt +## and a full list of country codes can be found at +## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html +## +## In property strings that are parameterized, single quotes can be used to +## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. +## +## +## REVISION HISTORY (by Transferguard version): +## +## 1.0.1 +## Added key: 'guard.settings.tooltips.blockedtypes' +## Added key: 'guard.settings.tooltips.blockedperson' +## Added key: 'guard.settings.tooltips.textarea' +## Added key: 'guard.settings.title.extensions' +## Added key: 'guard.settings.title.person' +## Added key: 'guard.settings.title.rejectresponse' +## Added key: 'guard.settings.label.maxsize' +## Added key: 'guard.settings.title.filesize' +## Added key: 'guard.settings.limitcheck' +## Added key: 'guard.settings.title.settings' +## + +guard.settings.title.list = Transfer Guard +guard.settings.title.settings = Definições de Transferência de Ficheiros +guard.settings.tooltips.blockedtypes = Insira as extensões de ficheiros que deseja bloquear (por ex., '*.doc'), separadas por vírgulas +guard.settings.tooltips.blockedperson = Insira o JID dos utilizadores de quem pretende bloquear as transferências de ficheiros (por ex., 'loser@domain.com'), separados por vírgulas +guard.settings.tooltips.textarea = Insira uma mensagem que gostaria de enviar para aqueles cujos ficheiros estão bloqueados pelas suas configurações. Deixe este espaço em branco se não desejar lhes enviar uma mensagem. +guard.settings.title.extensions = Extensões de Ficheiros Bloqueados +guard.settings.title.person = Remetentes Bloqueados +guard.settings.title.rejectresponse = Resposta de Rejeição Automatizada +guard.settings.label.maxsize = Tamanho Máximo em KB: +guard.settings.title.filesize = Tamanho do Ficheiro +guard.settings.limitcheck = Limitar Tamanho do Ficheiro diff --git a/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_ru_RU.properties b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_ru_RU.properties new file mode 100644 index 000000000..b291bd4f5 --- /dev/null +++ b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_ru_RU.properties @@ -0,0 +1,54 @@ +## +## Transferguard Language File +## +## Additional locales can be specified by creating a new resource file in this +## directory using the following conventions: +## +## spark_i18n "_" language "_" country ".properties" +## spark_i18n "_" language ".properties" +## +## e.g. +## spark_i18n_en.properties <- English resources +## spark_i18n_en_US.properties <- American US resources +## spark_i18n_de.properties <- German resources +## spark_i18n_ja.properties <- Japanese resources +## +## Please note that the two digit language code should be lower case, and the +## two digit country code should be in uppercase. Often, it is not necessary to +## specify the country code. +## +## A full list of language codes can be found at +## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt +## and a full list of country codes can be found at +## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html +## +## In property strings that are parameterized, single quotes can be used to +## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. +## +## +## REVISION HISTORY (by Transferguard version): +## +## 1.0.1 +## Added key: 'guard.settings.tooltips.blockedtypes' +## Added key: 'guard.settings.tooltips.blockedperson' +## Added key: 'guard.settings.tooltips.textarea' +## Added key: 'guard.settings.title.extensions' +## Added key: 'guard.settings.title.person' +## Added key: 'guard.settings.title.rejectresponse' +## Added key: 'guard.settings.label.maxsize' +## Added key: 'guard.settings.title.filesize' +## Added key: 'guard.settings.limitcheck' +## Added key: 'guard.settings.title.settings' +## + +guard.settings.title.list = Transfer Guard +guard.settings.title.settings = Параметры передачи файлов +guard.settings.tooltips.blockedtypes = Ведите раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð², которые вы хотите заблокировать (например,'*. doc'), разделенные запÑтыми +guard.settings.tooltips.blockedperson = Введите JID пользователей, от которых вы хотите заблокировать передачу файлов (например. 'loser@domain.com'), разделенные запÑтыми +guard.settings.tooltips.textarea = Введите Ñообщение, которое вы хотели бы отправить тем, чьи файлы заблокированы вашими наÑтройками. ОÑтавьте Ñто меÑто пуÑтым, еÑли вы не хотите отправлÑть им Ñообщение. +guard.settings.title.extensions = Заблокированные РаÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ð¤Ð°Ð¹Ð»Ð¾Ð² +guard.settings.title.person = Заблокированные Отправители +guard.settings.title.rejectresponse = ÐвтоматичеÑкий Ответ Ðа Отказ +guard.settings.label.maxsize = МакÑимальный размер в КБ: +guard.settings.title.filesize = Размер файла +guard.settings.limitcheck = Ограничить Размер Файла diff --git a/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_zh_CN.properties b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_zh_CN.properties new file mode 100644 index 000000000..a6a1491b8 --- /dev/null +++ b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_zh_CN.properties @@ -0,0 +1,54 @@ +## +## Transferguard Language File +## +## Additional locales can be specified by creating a new resource file in this +## directory using the following conventions: +## +## spark_i18n "_" language "_" country ".properties" +## spark_i18n "_" language ".properties" +## +## e.g. +## spark_i18n_en.properties <- English resources +## spark_i18n_en_US.properties <- American US resources +## spark_i18n_de.properties <- German resources +## spark_i18n_ja.properties <- Japanese resources +## +## Please note that the two digit language code should be lower case, and the +## two digit country code should be in uppercase. Often, it is not necessary to +## specify the country code. +## +## A full list of language codes can be found at +## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt +## and a full list of country codes can be found at +## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html +## +## In property strings that are parameterized, single quotes can be used to +## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. +## +## +## REVISION HISTORY (by Transferguard version): +## +## 1.0.1 +## Added key: 'guard.settings.tooltips.blockedtypes' +## Added key: 'guard.settings.tooltips.blockedperson' +## Added key: 'guard.settings.tooltips.textarea' +## Added key: 'guard.settings.title.extensions' +## Added key: 'guard.settings.title.person' +## Added key: 'guard.settings.title.rejectresponse' +## Added key: 'guard.settings.label.maxsize' +## Added key: 'guard.settings.title.filesize' +## Added key: 'guard.settings.limitcheck' +## Added key: 'guard.settings.title.settings' +## + +guard.settings.title.list = 传输防护 +guard.settings.title.settings = 文件传输设置 +guard.settings.tooltips.blockedtypes = 输入è¦é˜»æ­¢çš„æ–‡ä»¶æ‰©å±•å(例如,'*.doc'),用逗å·åˆ†éš” +guard.settings.tooltips.blockedperson = 输入è¦é˜»æ­¢æ–‡ä»¶ä¼ è¾“的用户的 JID(例如,'loser@domain.com'),用逗å·åˆ†éš” +guard.settings.tooltips.textarea = 输入è¦å‘é€ç»™é‚£äº›æ–‡ä»¶è¢«æ‚¨çš„设置阻止的人的消æ¯ã€‚å¦‚æžœæ‚¨ä¸æƒ³ç»™ä»–们呿¶ˆæ¯ï¼Œè¯·å°†æ­¤ç©ºæ ¼ç•™ç©ºã€‚ +guard.settings.title.extensions = 阻止的文件扩展å +guard.settings.title.person = 阻止的å‘é€è€… +guard.settings.title.rejectresponse = 自动拒ç»å“应 +guard.settings.label.maxsize = 最大大å°(KB): +guard.settings.title.filesize = æ–‡ä»¶å¤§å° +guard.settings.limitcheck = é™åˆ¶æ–‡ä»¶å¤§å° diff --git a/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_zh_TW.properties b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_zh_TW.properties new file mode 100644 index 000000000..63f080011 --- /dev/null +++ b/plugins/transferguard/src/main/resources/i18n/transferguard_i18n_zh_TW.properties @@ -0,0 +1,54 @@ +## +## Transferguard Language File +## +## Additional locales can be specified by creating a new resource file in this +## directory using the following conventions: +## +## spark_i18n "_" language "_" country ".properties" +## spark_i18n "_" language ".properties" +## +## e.g. +## spark_i18n_en.properties <- English resources +## spark_i18n_en_US.properties <- American US resources +## spark_i18n_de.properties <- German resources +## spark_i18n_ja.properties <- Japanese resources +## +## Please note that the two digit language code should be lower case, and the +## two digit country code should be in uppercase. Often, it is not necessary to +## specify the country code. +## +## A full list of language codes can be found at +## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt +## and a full list of country codes can be found at +## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html +## +## In property strings that are parameterized, single quotes can be used to +## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. +## +## +## REVISION HISTORY (by Transferguard version): +## +## 1.0.1 +## Added key: 'guard.settings.tooltips.blockedtypes' +## Added key: 'guard.settings.tooltips.blockedperson' +## Added key: 'guard.settings.tooltips.textarea' +## Added key: 'guard.settings.title.extensions' +## Added key: 'guard.settings.title.person' +## Added key: 'guard.settings.title.rejectresponse' +## Added key: 'guard.settings.label.maxsize' +## Added key: 'guard.settings.title.filesize' +## Added key: 'guard.settings.limitcheck' +## Added key: 'guard.settings.title.settings' +## + +guard.settings.title.list = 檔案傳輸設定 +guard.settings.title.settings = 檔案傳輸設定 +guard.settings.tooltips.blockedtypes = 輸入您希望阻擋的檔案維碼 (例如. '*.doc'), 用逗號分隔 +guard.settings.tooltips.blockedperson = 輸入è¦é˜»æ“‹å¾žå“ªä½è¯çµ¡äººçš„ JID 所傳輸的檔案 (例如. 'loser@domain.com'), 用逗號分隔 +guard.settings.tooltips.textarea = 輸入您想發é€çµ¦é‚£äº›è¢«æ‚¨é˜»æ“‹çš„æª”案的訊æ¯. å¦‚æžœæ‚¨ä¸æƒ³ç™¼é€è¨Šæ¯,下方欄ä½ä¸éœ€è¼¸å…¥. +guard.settings.title.extensions = 阻擋檔案維碼 +guard.settings.title.person = 阻擋傳輸者 +guard.settings.title.rejectresponse = è‡ªå‹•å›žè¦†é˜»æ“‹çš„è¨Šæ¯ +guard.settings.label.maxsize = æª”æ¡ˆå¤§å°æœ€å¤§ç‚ºå¤šå°‘ KB: +guard.settings.title.filesize = æª”æ¡ˆå¤§å° +guard.settings.limitcheck = é™åˆ¶æª”æ¡ˆå¤§å° diff --git a/plugins/transferguard/src/main/resources/images/guard.png b/plugins/transferguard/src/main/resources/images/guard.png new file mode 100644 index 000000000..de1fc79f1 Binary files /dev/null and b/plugins/transferguard/src/main/resources/images/guard.png differ diff --git a/plugins/transferguard/src/main/resources/images/knight.png b/plugins/transferguard/src/main/resources/images/knight.png new file mode 100644 index 000000000..e6dbcfe83 Binary files /dev/null and b/plugins/transferguard/src/main/resources/images/knight.png differ diff --git a/src/plugins/transferguard/readme.html b/plugins/transferguard/src/main/resources/readme.html similarity index 100% rename from src/plugins/transferguard/readme.html rename to plugins/transferguard/src/main/resources/readme.html diff --git a/plugins/translator/pom.xml b/plugins/translator/pom.xml new file mode 100644 index 000000000..c8886e2f6 --- /dev/null +++ b/plugins/translator/pom.xml @@ -0,0 +1,48 @@ + + 4.0.0 + + + org.igniterealtime.spark.plugins + plugin + 3.1.0-SNAPSHOT + ../plugin/pom.xml + + + translator + 3.0 + + Translator Plugin + Translates messages between users using LibreTranslate Service. + + + + Jive Software + + Author + + + + + + + junit + junit + 4.13.2 + test + + + com.github.stokito + libretranslate-java + 1.2.2 + + + + + + jitpack.io + https://jitpack.io + + + + diff --git a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPlugin.java b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPlugin.java new file mode 100644 index 000000000..173557306 --- /dev/null +++ b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPlugin.java @@ -0,0 +1,231 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.translator; + +import java.awt.*; +import java.util.Locale; + +import javax.swing.JCheckBox; +import javax.swing.JComboBox; + +import org.jivesoftware.spark.util.log.Log; +import space.dynomake.libretranslate.Language; +import space.dynomake.libretranslate.Translator; +import org.apache.commons.lang3.StringUtils; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.spark.ChatManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.plugin.Plugin; +import org.jivesoftware.spark.ui.*; + +import static org.apache.commons.lang3.StringUtils.isEmpty; + +/** + * A plugin that uses external translation service API to translate instant messages between two users. + * + * @author Jive Software + */ +public class TranslatorPlugin implements Plugin { + private TranslatorPreference pref; + private MessageFilter translationMessageFilter; + private TranslationChatRoomListener translationChatRoomListener; + + @Override + public void initialize() { + pref = new TranslatorPreference(); + SparkManager.getPreferenceManager().addPreference(pref); + + // Retrieve ChatManager from the SparkManager + final ChatManager chatManager = SparkManager.getChatManager(); + // Add to a new ChatRoom when the ChatRoom opens. + translationChatRoomListener = new TranslationChatRoomListener(); + translationMessageFilter = new TranslationMessageFilter(); + chatManager.addChatRoomListener(translationChatRoomListener); + chatManager.addMessageFilter(translationMessageFilter); + } + + @Override + public void shutdown() { + final ChatManager chatManager = SparkManager.getChatManager(); + chatManager.removeChatRoomListener(translationChatRoomListener); + chatManager.removeMessageFilter(translationMessageFilter); + translationChatRoomListener = null; + translationMessageFilter = null; + SparkManager.getPreferenceManager().removePreference(pref); + pref = null; + } + + @Override + public boolean canShutDown() { + return true; + } + + @Override + public void uninstall() { + // Remove all resources belonging to this plugin. + } + + private static class TranslationChatRoomListener implements org.jivesoftware.spark.ui.ChatRoomListener { + @Override + public void chatRoomOpened(ChatRoom room) { + TranslatorProperties properties = TranslatorProperties.getInstance(); + if (!properties.getEnabledTranslator()) { + return; + } + // Set server LibreTranslate API + if (properties.getUseCustomUrl() && !StringUtils.isBlank(properties.getUrl())) { + Translator.setUrlApi(properties.getUrl()); + Translator.setApiKey(properties.getApiKey()); + } else { + Translator.setUrlApi(TranslatorUtil.getDefaultUrl()); + Translator.setApiKey(null); + } + + // Create a new ChatRoomButton. + final JComboBox translatorBox = new JComboBox<>(TranslatorUtil.getLanguage()); + translatorBox.setName("translatorBox"); + translatorBox.setToolTipText(TranslatorResource.getString("translator.translateOutcomingLang") + + " " +TranslatorResource.getString("translator.externalServiceWarning")); + + translatorBox.addActionListener(e -> { + // Set the focus back to the message box. + room.getChatInputEditor().requestFocusInWindow(); + }); + + room.addChatRoomComponent(translatorBox); + + final JCheckBox translatorIncoming = new JCheckBox(TranslatorResource.getString("translator.translateIncoming")); + translatorIncoming.setName("translatorIncoming"); + translatorIncoming.setToolTipText(TranslatorResource.getString("translator.translateIncoming") + + " " +TranslatorResource.getString("translator.externalServiceWarning")); + translatorIncoming.addActionListener(e -> { + // Set the focus back to the message box. + room.getChatInputEditor().requestFocusInWindow(); + }); + room.addChatRoomComponent(translatorIncoming); + } + } + + private static class TranslationMessageFilter implements MessageFilter { + private Language localeLanguage; + + public TranslationMessageFilter() { + localeLanguage = Language.fromCode(Locale.getDefault().toLanguageTag()); + if (localeLanguage == Language.NONE) { + localeLanguage = Language.fromCode(Locale.getDefault().getLanguage()); + } + } + + @Override + public void filterOutgoing(ChatRoom room, MessageBuilder messageBuilder) { + String currentBody = messageBuilder.getBody(); + if (currentBody == null) { + return; + } + if (!TranslatorProperties.getInstance().getEnabledTranslator()) { + return; + } + @SuppressWarnings("unchecked") + JComboBox translatorBox = (JComboBox) findTranslatorComponent(room, "translatorBox"); + if (translatorBox == null) { + return; + } + Language lang = (Language) translatorBox.getSelectedItem(); + if (lang == null || lang == Language.NONE) { + return; + } + // do the translation for outgoing messages. + TranscriptWindow transcriptWindow = room.getTranscriptWindow(); + try { + String translatedBody = TranslatorUtil.translate(currentBody, lang); + transcriptWindow.insertNotificationMessage("-> " + translatedBody, Color.gray); + /* + * We'll include the translation along with the original message. + * But we need to flip the order of the body elements so that the translation is first. + *

      +                 * 
      +                 * 	привет
      +                 * 	hi
      +                 * 
      +                 * 
      + * This is needed because XMPP clients show a message the in a user's locale or the first body. + */ + // Manually remove the existing body to add a new one. + messageBuilder.removeExtension(Message.Body.ELEMENT, Message.Body.NAMESPACE); + messageBuilder.addBody(lang.getCode(), translatedBody); + messageBuilder.addBody(null, currentBody); // keep the original message + } catch (Exception e) { + Log.warning(e.getMessage()); + transcriptWindow.insertNotificationMessage(TranslatorResource.getString("translator.error"), ChatManager.ERROR_COLOR); + } + } + + @Override + public void filterIncoming(ChatRoom room, MessageBuilder messageBuilder) { + String currentBody = messageBuilder.getBody(); + if (currentBody == null) { + return; + } + if (!TranslatorProperties.getInstance().getEnabledTranslator()) { + return; + } + JCheckBox translatorIncoming = (JCheckBox) findTranslatorComponent(room, "translatorIncoming"); + if (translatorIncoming == null) { + return; + } + if (!translatorIncoming.isSelected()) { + return; + } + Language myLanguage = getMyLanguage(); + if (myLanguage == null) { + return; + } + + TranscriptWindow transcriptWindow = room.getTranscriptWindow(); + try { + String translatedBody = TranslatorUtil.translate(currentBody, myLanguage); + transcriptWindow.insertNotificationMessage("-> " + currentBody, Color.gray); + // Manually remove the existing body to add a new one. + messageBuilder.removeExtension(Message.Body.ELEMENT, Message.Body.NAMESPACE); + messageBuilder.addBody(myLanguage.getCode(), translatedBody); + messageBuilder.addBody(null, translatedBody); // keep the original message + } catch (Exception e) { + Log.warning(e.getMessage()); + transcriptWindow.insertNotificationMessage(TranslatorResource.getString("translator.error"), ChatManager.ERROR_COLOR); + } + } + + /** + * Determine own language for translation incoming messages. + */ + private Language getMyLanguage() { + // the setting may be changed any time, so we have to always check it + String myLanguageSetting = TranslatorProperties.getInstance().getMyLanguage(); + return !isEmpty(myLanguageSetting) ? Language.fromCode(myLanguageSetting) : localeLanguage; + } + + private Component findTranslatorComponent(ChatRoom room, String compName) { + Component[] comps = room.getEditorBar().getComponents(); + for (Component component : comps) { + if (compName.equals(component.getName())) { + return component; + } + } + return null; + } + } +} diff --git a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPreference.java b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPreference.java new file mode 100644 index 000000000..375819df9 --- /dev/null +++ b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPreference.java @@ -0,0 +1,88 @@ +package org.jivesoftware.spark.translator; + +import org.jivesoftware.spark.preference.Preference; +import org.jivesoftware.spark.util.log.Log; + +import javax.swing.*; +import java.awt.*; + +public class TranslatorPreference implements Preference { + + private TranslatorPreferencePanel _prefPanel; + private final TranslatorProperties _props; + + public TranslatorPreference() { + _props = TranslatorProperties.getInstance(); + + try { + if (EventQueue.isDispatchThread()) { + _prefPanel = new TranslatorPreferencePanel(); + } else { + EventQueue.invokeAndWait( () -> _prefPanel = new TranslatorPreferencePanel() ); + } + } catch (Exception e) { + Log.error(e); + } + } + + @Override + public String getTitle() { + return TranslatorResource.getString("translator.title"); + } + + @Override + public Icon getIcon() { + ClassLoader cl = getClass().getClassLoader(); + return new ImageIcon(cl.getResource("translator.png")); + } + + @Override + public String getTooltip() { + return TranslatorResource.getString("translator.title"); + } + + @Override + public String getListName() { + return TranslatorResource.getString("translator.title"); + } + + @Override + public String getNamespace() { + return TranslatorResource.getString("translator.title"); + } + + @Override + public JComponent getGUI() { + return _prefPanel; + } + + @Override + public void load() { + _prefPanel.initializeValues(); + } + + @Override + public void commit() { + _prefPanel.storeValues(); + } + + @Override + public boolean isDataValid() { + return true; + } + + @Override + public String getErrorMessage() { + return null; + } + + @Override + public Object getData() { + return _props; + } + + @Override + public void shutdown() { + + } +} diff --git a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPreferencePanel.java b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPreferencePanel.java new file mode 100644 index 000000000..dedd0578a --- /dev/null +++ b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorPreferencePanel.java @@ -0,0 +1,129 @@ +package org.jivesoftware.spark.translator; + +import org.jivesoftware.spark.component.VerticalFlowLayout; +import space.dynomake.libretranslate.Language; + +import javax.swing.*; +import java.awt.*; + +import static java.awt.GridBagConstraints.BOTH; +import static java.awt.GridBagConstraints.WEST; + +public class TranslatorPreferencePanel extends JPanel { + + private final JCheckBox _enabledCheckbox; + private final JComboBox _myLanguage; + private final JTextField _url; + private final JTextField _apiKey; + private final JCheckBox _useCustomUrl; + private final Insets INSETS = new Insets(5, 5, 5, 5); + + public TranslatorPreferencePanel() { + + this.setLayout(new BorderLayout()); + + _enabledCheckbox = new JCheckBox(TranslatorResource.getString("translator.enabled")); + _myLanguage = new JComboBox<>(Language.values()); + _useCustomUrl = new JCheckBox(TranslatorResource.getString("translator.custom.url")); + _url = new JTextField(); + _apiKey = new JTextField(); + updateGUI(); + add(makeGeneralSettingsPanel()); + } + + private JComponent makeGeneralSettingsPanel() { + + JPanel generalPanel = new JPanel(); + generalPanel.setLayout(new GridBagLayout()); + generalPanel.setBorder(BorderFactory.createTitledBorder(TranslatorResource.getString("translator.settings"))); + int rowcount = 0; + generalPanel.add(_enabledCheckbox, + new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); + rowcount++; + generalPanel.add(new JLabel(TranslatorResource.getString("translator.myLanguage")), + new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); + generalPanel.add(_myLanguage, + new GridBagConstraints(1, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); + rowcount++; + generalPanel.add(_useCustomUrl, + new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); + rowcount++; + generalPanel.add(new JLabel(TranslatorResource.getString("translator.url")), + new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); + generalPanel.add(_url, + new GridBagConstraints(1, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); + rowcount++; + generalPanel.add(new JLabel(TranslatorResource.getString("translator.apiKey")), + new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); + generalPanel.add(_apiKey, + new GridBagConstraints(1, rowcount, 1, 1, 0.0, 0.0, WEST, BOTH, INSETS, 0, 0)); + rowcount++; + JLabel placeHolder = new JLabel(); + generalPanel.add(placeHolder, + new GridBagConstraints(1, rowcount, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, BOTH, INSETS, 0, 0)); + + JPanel panel = new JPanel(new VerticalFlowLayout()); + panel.add(generalPanel); + + return new JScrollPane(panel); + } + + public void initializeValues() { + TranslatorProperties props = TranslatorProperties.getInstance(); + _enabledCheckbox.setSelected(props.getEnabledTranslator()); + Language myLanguage = Language.fromCode(props.getMyLanguage()); + _myLanguage.setSelectedItem(myLanguage); + _useCustomUrl.setSelected(props.getUseCustomUrl()); + _url.setText(props.getUrl()); + _apiKey.setText(props.getApiKey()); + } + + public void storeValues(){ + TranslatorProperties props = TranslatorProperties.getInstance(); + props.setEnabledTranslator(_enabledCheckbox.isSelected()); + Language selectedMyLanguage = (Language) _myLanguage.getSelectedItem(); + props.setMyLanguage(selectedMyLanguage != null && selectedMyLanguage != Language.NONE ? selectedMyLanguage.getCode() : ""); + props.setUseCustomUrl(_useCustomUrl.isSelected()); + props.setUrl(_url.getText()); + props.setApiKey(_apiKey.getText()); + props.save(); + } + + private void updateGUI(){ + _enabledCheckbox.addActionListener( e -> { + if (_enabledCheckbox.isSelected()) { + _myLanguage.setEnabled(true); + _useCustomUrl.setEnabled(true); + _url.setEnabled(_useCustomUrl.isSelected()); + _apiKey.setEnabled(_useCustomUrl.isSelected()); + } else { + _myLanguage.setEnabled(false); + _url.setEnabled(false); + _apiKey.setEnabled(false); + _useCustomUrl.setEnabled(false); + } + }); + + _useCustomUrl.addActionListener( e -> { + if (_useCustomUrl.isSelected()){ + _url.setEnabled(true); + _apiKey.setEnabled(true); + } else { + _url.setEnabled(false); + _apiKey.setEnabled(false); + } + }); + + if (!TranslatorProperties.getInstance().getEnabledTranslator()) { + _myLanguage.setEnabled(false); + _url.setEnabled(false); + _apiKey.setEnabled(false); + _useCustomUrl.setEnabled(false); + } + + if(!TranslatorProperties.getInstance().getUseCustomUrl()){ + _url.setEnabled(false); + _apiKey.setEnabled(false); + } + } +} diff --git a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorProperties.java b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorProperties.java new file mode 100644 index 000000000..095a3eef0 --- /dev/null +++ b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorProperties.java @@ -0,0 +1,99 @@ +package org.jivesoftware.spark.translator; + +import org.jivesoftware.Spark; +import org.jivesoftware.spark.util.log.Log; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Properties; + +public class TranslatorProperties { + private final Properties props; + private static final Object LOCK = new Object(); + private static TranslatorProperties instance = null; + + /** + * returns the Instance of this Properties file + */ + public static TranslatorProperties getInstance() { + synchronized (LOCK) { + if (instance == null) { + instance = new TranslatorProperties(); + } + return instance; + } + } + + private TranslatorProperties() { + this.props = new Properties(); + + try { + props.load(new FileInputStream(getConfigFile())); + } catch (IOException e) { + // Can't load ConfigFile + } + } + + private File getConfigFile() { + File configFile = new File(Spark.getSparkUserHome(), "translator.properties"); + return configFile; + } + + public void save() { + try { + props.store(new FileOutputStream(getConfigFile()), "Storing Translator properties"); + } catch (Exception e) { + Log.error(e); + } + } + + public boolean getEnabledTranslator() { + return getBoolean("active", false); + } + + public void setEnabledTranslator(boolean enable) { + setBoolean("active", enable); + } + + public boolean getUseCustomUrl() { + return getBoolean("useCustomUrl", false); + } + + public void setUseCustomUrl(boolean enable) { + setBoolean("useCustomUrl", enable); + } + + public String getUrl() { + return props.getProperty("url"); + } + + public void setUrl(String url) { + props.setProperty("url", url); + } + + public String getApiKey() { + return props.getProperty("apiKey"); + } + + public void setApiKey(String apiKey) { + props.setProperty("apiKey", apiKey); + } + + public String getMyLanguage() { + return props.getProperty("myLanguage"); + } + + public void setMyLanguage(String language) { + props.setProperty("myLanguage", language); + } + + private boolean getBoolean(String property, boolean defaultValue) { + return Boolean.parseBoolean(props.getProperty(property, Boolean.toString(defaultValue))); + } + + public void setBoolean(String property, boolean value) { + props.setProperty(property, Boolean.toString(value)); + } +} diff --git a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorResource.java b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorResource.java new file mode 100644 index 000000000..fd072f6bf --- /dev/null +++ b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorResource.java @@ -0,0 +1,37 @@ +package org.jivesoftware.spark.translator; + +import org.jivesoftware.resource.UTF8Control; +import org.jivesoftware.spark.util.log.Log; + +import java.text.MessageFormat; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +public class TranslatorResource { + private static PropertyResourceBundle prb; + + static ClassLoader cl = TranslatorResource.class.getClassLoader(); + + static { + prb = (PropertyResourceBundle) ResourceBundle.getBundle("i18n/translator_i18n", new UTF8Control()); + } + + public static String getString(String propertyName) { + try { + return prb.getString(propertyName); + } + catch (Exception e) { + Log.error(e); + return propertyName; + } + } + + public static String getString(String propertyName, Object... obj) { + String str = prb.getString(propertyName); + if (str == null) { + return null; + } + return MessageFormat.format(str, obj); + } + +} diff --git a/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorUtil.java b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorUtil.java new file mode 100644 index 000000000..9360d90f1 --- /dev/null +++ b/plugins/translator/src/main/java/org/jivesoftware/spark/translator/TranslatorUtil.java @@ -0,0 +1,42 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.spark.translator; + +import space.dynomake.libretranslate.ApiProviders; +import space.dynomake.libretranslate.Language; +import space.dynomake.libretranslate.Translator; + +/** + * A utility class that uses external translation service API to translate text to various languages. + */ +public class TranslatorUtil { + private TranslatorUtil() { + } + + public static String translate(String text, Language language) { + return Translator.translate(language,text); + } + + public static Language[] getLanguage(){ + return Language.values(); + } + + public static String getDefaultUrl(){ + return ApiProviders.API_URL_FEDILAB; + } + +} + diff --git a/plugins/translator/src/main/plugin-metadata/plugin.xml b/plugins/translator/src/main/plugin-metadata/plugin.xml new file mode 100644 index 000000000..81a99f521 --- /dev/null +++ b/plugins/translator/src/main/plugin-metadata/plugin.xml @@ -0,0 +1,11 @@ + + + ${project.name} + ${project.version} + ${project.description} + org.jivesoftware.spark.translator.TranslatorPlugin + https://IgniteRealtime.org + support@IgniteRealtime.org + 3.1.0 + 11 + diff --git a/plugins/translator/src/main/resources/changelog.html b/plugins/translator/src/main/resources/changelog.html new file mode 100644 index 000000000..e5611e191 --- /dev/null +++ b/plugins/translator/src/main/resources/changelog.html @@ -0,0 +1,83 @@ + + + + + Translator Spark Plug Log + + + + +

      +Translator Spark plugin Changelog +

      +

      3.0 -- March 13, 2026

      +
        +
      • Upgrade LibreTranslate API SDK
      • +
      • SPARK-1610 Add translation controls to MUC
      • +
      • Allow translating of incoming messages
      • +
      +

      2.0 -- December 30th, 2022

      +
        +
      • Replace Google API with LibreTranslate API
      • +
      • Add Preference panel
      • +
      • Add defaults and i18n
      • +
      +

      1.4 -- March 17th, 2011

      +
        +
      • Adjusted to Google's new translator layout for Spark 2.6.x
      • +
      + +

      1.3 -- February 7th, 2007

      +
        +
      • Fixed issue with Spark 2.5 Beta and Higher
      • +
      + +

      1.0.1 -- September 19th, 2006

      +
        +
      • Moved over to Spark 2.0 code base.
      • +
      + + +

      1.0.0 -- February 9th, 2006

      +
        +
      • Initial release.
      • +
      + + + + + + diff --git a/plugins/translator/src/main/resources/i18n/translator_i18n.properties b/plugins/translator/src/main/resources/i18n/translator_i18n.properties new file mode 100644 index 000000000..d9319e937 --- /dev/null +++ b/plugins/translator/src/main/resources/i18n/translator_i18n.properties @@ -0,0 +1,12 @@ +translator.title = Translator + +translator.enabled = Enable Translator +translator.myLanguage = My own language +translator.custom.url = Use custom url LibreTranslate +translator.url = URL +translator.apiKey = API Key +translator.settings = Translator settings +translator.error = Could not translate! +translator.translateOutcomingLang=Translate the message to this language. +translator.translateIncoming=Translate incoming messages. +translator.externalServiceWarning=Warning: text will be leaked to an external service. diff --git a/plugins/translator/src/main/resources/i18n/translator_i18n_es.properties b/plugins/translator/src/main/resources/i18n/translator_i18n_es.properties new file mode 100644 index 000000000..2e880bce5 --- /dev/null +++ b/plugins/translator/src/main/resources/i18n/translator_i18n_es.properties @@ -0,0 +1,7 @@ +translator.title = Traductor + +translator.enabled = Habilitar traductor +translator.custom.url = Usar URL personalizada LibreTranslate +translator.url = URL: +translator.settings = Configuración del traductor +translator.error = ¡No se pudo traducir! diff --git a/plugins/translator/src/main/resources/i18n/translator_i18n_fr.properties b/plugins/translator/src/main/resources/i18n/translator_i18n_fr.properties new file mode 100644 index 000000000..298d9ca49 --- /dev/null +++ b/plugins/translator/src/main/resources/i18n/translator_i18n_fr.properties @@ -0,0 +1,7 @@ +translator.title = Traducteur + +translator.enabled = Activer le traducteur +translator.custom.url = Utiliser l'URL personnalisée LibreTranslate +translator.url = URL: +translator.settings = Paramètres du traducteur +translator.error = Impossible de traduire ! diff --git a/plugins/translator/src/main/resources/i18n/translator_i18n_pt_PT.properties b/plugins/translator/src/main/resources/i18n/translator_i18n_pt_PT.properties new file mode 100644 index 000000000..e34dfa83d --- /dev/null +++ b/plugins/translator/src/main/resources/i18n/translator_i18n_pt_PT.properties @@ -0,0 +1,7 @@ +translator.title = Tradutor + +translator.enabled = Ativar Tradutor +translator.custom.url = Usar url personalizado LibreTranslate +translator.url = URL: +translator.settings = Definições do tradutor +translator.error = Não foi possível traduzir! diff --git a/plugins/translator/src/main/resources/i18n/translator_i18n_ru_RU.properties b/plugins/translator/src/main/resources/i18n/translator_i18n_ru_RU.properties new file mode 100644 index 000000000..95c5c77ec --- /dev/null +++ b/plugins/translator/src/main/resources/i18n/translator_i18n_ru_RU.properties @@ -0,0 +1,12 @@ +translator.title = Переводчик + +translator.enabled = Включить переводчик +translator.myLanguage=Мой ÑобÑтвенный Ñзык +translator.custom.url=Свой URL-Ð°Ð´Ñ€ÐµÑ LibreTranslate +translator.url = URL-Ð°Ð´Ñ€ÐµÑ +translator.apiKey = Ключ API +translator.settings = ÐаÑтройки переводчика +translator.error = Ðе удалоÑÑŒ перевеÑти! +translator.translateOutcomingLang=Переводить Ñообщение на Ñтот Ñзык. +translator.translateIncoming=Переводить входÑщие ÑообщениÑ. +translator.externalServiceWarning=Внимание: текÑÑ‚ будет передан во внешний ÑервиÑ. diff --git a/plugins/translator/src/main/resources/i18n/translator_i18n_zh_CN.properties b/plugins/translator/src/main/resources/i18n/translator_i18n_zh_CN.properties new file mode 100644 index 000000000..3e06008a3 --- /dev/null +++ b/plugins/translator/src/main/resources/i18n/translator_i18n_zh_CN.properties @@ -0,0 +1,7 @@ +translator.title = 翻译 + +translator.enabled = å¯ç”¨ç¿»è¯‘ +translator.custom.url = 使用自定义 url LibreTranslate +translator.url = URL: +translator.settings = 翻译设置 +translator.error = æ— æ³•ç¿»è¯‘ï¼ diff --git a/plugins/translator/src/main/resources/readme.html b/plugins/translator/src/main/resources/readme.html new file mode 100644 index 000000000..7b7ba1896 --- /dev/null +++ b/plugins/translator/src/main/resources/readme.html @@ -0,0 +1,67 @@ + + + + + Translator Spark Plug Readme + + + + +

      +Translator Plugin Readme +

      + +

      Overview

      + +

      +The plugin allows for translation messages between users using LibreTranslate Service. +Note: text will be leaked to an external service. +You better set up your own instance of the LibreTranslate service and configure it in settings. +

      + +

      Installation

      + +

      Install plugin via the Plugin Viewer in Spark

      + + + diff --git a/plugins/translator/src/main/resources/translator.png b/plugins/translator/src/main/resources/translator.png new file mode 100644 index 000000000..892d60dde Binary files /dev/null and b/plugins/translator/src/main/resources/translator.png differ diff --git a/plugins/translator/src/test/java/com/jivesoftware/spark/translator/TestTranslator.java b/plugins/translator/src/test/java/com/jivesoftware/spark/translator/TestTranslator.java new file mode 100644 index 000000000..f12b5247f --- /dev/null +++ b/plugins/translator/src/test/java/com/jivesoftware/spark/translator/TestTranslator.java @@ -0,0 +1,104 @@ +/** + * Copyright (C) 2004-2011 Jive Software. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jivesoftware.spark.translator; + +import space.dynomake.libretranslate.Language; +import org.jivesoftware.spark.translator.TranslatorUtil; +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.IOException; +import java.util.*; + +/** + * A simple class to test translation functionality. + */ +public class TestTranslator { + + @Test + public void test() { + // Dummy test to avoid Maven confusion. + } + + public static void main(String[] args) { + Map translationMap = initalizeTranslationMap(); + + boolean again = true; + while (again) { + System.out.println("Please enter some text"); + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + String text = ""; + try { + text = reader.readLine(); + } catch (IOException e) { + System.out.println("Could not read text:" + e); + } + + if (text == null) { + System.out.println("Sorry, I didn't get that."); + continue; + } + + System.out.println("Great, now enter the translation id. Below are the following choices:"); + + for (Map.Entry o : translationMap.entrySet()) { + System.out.println(o.getKey() + " - " + o.getValue()); + } + + String translationID = ""; + try { + translationID = reader.readLine(); + } catch (IOException e) { + System.out.println("Could not read translationID:" + e); + } + + Integer id = Integer.valueOf(translationID); + Language type = translationMap.get(id); + + if (type == null) { + System.out.println("Not a valid translation type."); + continue; + } + + String result = TranslatorUtil.translate(text, type); + + System.out.println("Your original text:\n" + text); + System.out.println("Has been translated from: " + type); + System.out.println("The result is:\n" + result); + + System.out.println("Do you want to continue testing?"); + String cont; + try { + cont = reader.readLine(); + again = "yes".equals(cont.toLowerCase().trim()) || "y".equals(cont.toLowerCase().trim()); + } catch (IOException e) { + System.out.println("Could not read text:" + e); + } + } + } + + private static Map initalizeTranslationMap() { + Language[] types = Language.values(); + Map map = new TreeMap<>(Integer::compareTo); + + for (int i = 1; i < types.length; i++) { + map.put(i, types[i]); + } + + return map; + } +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 000000000..8bb019c94 --- /dev/null +++ b/pom.xml @@ -0,0 +1,131 @@ + + 4.0.0 + + org.igniterealtime.spark + parent + 3.1.0-SNAPSHOT + pom + + Spark (parent) + + Spark is an Open Source, cross-platform IM client optimized for businesses and organizations. It features + built-in support for group chat, telephony integration, and strong security. It also offers a great end-user + experience with features like in-line spell checking, group chat room bookmarks, and tabbed conversations. + Combined with the Openfire server, Spark is the easiest and best alternative to using un-secure public IM + networks. + + http://www.igniterealtime.org/projects/spark/ + 2006 + + + Ignite Realtime + http://www.igniterealtime.org + + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + repo + + + + + jira + http://www.igniterealtime.org/issues/browse/SPARK + + + + https://github.com/igniterealtime/Spark.git + https://github.com/igniterealtime/Spark.git + https://github.com/igniterealtime/Spark + + + + + Vacant + + Project Lead + + Ignite Realtime + http://www.igniterealtime.org + + + + + + Guus der Kinderen + + Developer + + guus.der.kinderen@gmail.com + +1 + Ignite Realtime + http://www.igniterealtime.org + + + + + core + emoticons + plugins/assembly-descriptor + + plugins/apple + plugins/fastpath + plugins/fileupload + plugins/flashing + plugins/growl + + + plugins/meet + plugins/otr + plugins/reversi + plugins/roar + plugins/tictactoe + plugins/spelling + + plugins/transferguard + plugins/translator + distribution + + + + UTF-8 + 4.5.0-rc1 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.14.1 + + 11 + 11 + + + + + org.codehaus.mojo + native2ascii-maven-plugin + 1.0-beta-1 + + + native2ascii + + native2ascii + + + + + + + + diff --git a/src/commercial/README.txt b/src/commercial/README.txt deleted file mode 100644 index c29d28546..000000000 --- a/src/commercial/README.txt +++ /dev/null @@ -1 +0,0 @@ -All plugins contained within this directory are built using commercial products licensed by Jive Software. \ No newline at end of file diff --git a/src/commercial/idlelinux.jar b/src/commercial/idlelinux.jar deleted file mode 100644 index 0a6279d9e..000000000 Binary files a/src/commercial/idlelinux.jar and /dev/null differ diff --git a/src/commercial/jniwrapper.jar b/src/commercial/jniwrapper.jar deleted file mode 100644 index 42fb7b4a5..000000000 Binary files a/src/commercial/jniwrapper.jar and /dev/null differ diff --git a/src/commercial/roar.jar b/src/commercial/roar.jar deleted file mode 100644 index 80e6843a3..000000000 Binary files a/src/commercial/roar.jar and /dev/null differ diff --git a/src/commercial/spelling-plugin.jar b/src/commercial/spelling-plugin.jar deleted file mode 100644 index e3125e18c..000000000 Binary files a/src/commercial/spelling-plugin.jar and /dev/null differ diff --git a/src/docbook/book.sgml b/src/docbook/book.sgml deleted file mode 100644 index 357c38b32..000000000 --- a/src/docbook/book.sgml +++ /dev/null @@ -1,9 +0,0 @@ - - - - Spark - - - - diff --git a/src/docbook/developer-branding.sgml b/src/docbook/developer-branding.sgml deleted file mode 100644 index 8b9e991df..000000000 --- a/src/docbook/developer-branding.sgml +++ /dev/null @@ -1,10 +0,0 @@ - -
      - - <phrase lang="en">Branding Spark</phrase> - - - - - -
      \ No newline at end of file diff --git a/src/docbook/developer-patch.sgml b/src/docbook/developer-patch.sgml deleted file mode 100644 index 2364ec4f4..000000000 --- a/src/docbook/developer-patch.sgml +++ /dev/null @@ -1,34 +0,0 @@ - -
      - - <phrase lang="en">Create Patch</phrase> - - - - This documents explain how to create a patch for Spark. - - - -
      - - <phrase lang="en">Create Patch via SVN</phrase> - - - svn diff > SPARK.patch - or - svn diff > SPARK-917.patch # SPARK-[ISSUE-ID].patch - -
      - -
      - - <phrase lang="en">Create Patch via CommandLine</phrase> - - - - diff -Nurwb sparkdir sparkdir_mod > SPARK.patch - or - diff -Nurwb sparkdir sparkdir_mod > SPARK-917.patch # SPARK-[ISSUE-ID].patch - -
      -
      \ No newline at end of file diff --git a/src/docbook/developer-plugin.sgml b/src/docbook/developer-plugin.sgml deleted file mode 100644 index bba9413ad..000000000 --- a/src/docbook/developer-plugin.sgml +++ /dev/null @@ -1,74 +0,0 @@ - -
      - - <phrase lang="en">Spark Plugin</phrase> - - - -
      - - <phrase lang="en">What Are Sparkplugs?</phrase> - - - - Sparkplugs dynamically extend the features of the Spark instant messaging client. Use Sparkplugs to customize Spark for your business or organization or to add an innovative twist to instant messaging. The extensive plugin API allows for complete client flexibility but is still simple and (we hope!) fun to use. - -
      - -
      - - <phrase lang="en">Structure of a Plugin</phrase> - - - - - - - The plugin.xml file specifies the main Plugin class. A sample file might look like the following: - - - - - MyPlugin Plugin - com.examples.plugins.MyPlugin - The Author - 1.0 - description from the plugin. - developer@mail.org - 2.0.6 - - ]]> - - - - - The plugin.xml with dependencies on other plugins: - - - - - MyPlugin Plugin - com.examples.plugins.MyPlugin - The Author - 1.0 - description from the plugin. - developer@mail.org - 2.0.6 - Windows,Mac,Linux - - - Phone Client - 1.0.1 - - - - ]]> - -
      -
      \ No newline at end of file diff --git a/src/docbook/developer-source.sgml b/src/docbook/developer-source.sgml deleted file mode 100644 index 8c0738825..000000000 --- a/src/docbook/developer-source.sgml +++ /dev/null @@ -1,72 +0,0 @@ - -
      - - <phrase lang="en">Building the Source</phrase> - <phrase lang="de">Quellcode kompilieren</phrase> - - - - This chapter provides detailed information for developers that wish to compile and make changes to the Spark source code. - Dieses Kapitel enthält detaillierte Informationen für Entwickler, die den Spark kompilieren und Änderungen vornehmen wollen. - - -
      - - <phrase lang="en">Get the Spark Source</phrase> - <phrase lang="de">Spark Quellcode besorgen</phrase> - - - svn co http://svn.igniterealtime.org/svn/repos/spark/trunk spark - - -
      - -
      - - <phrase lang="en">Build Obelisk</phrase> - <phrase lang="de">Obelisk kompilieren</phrase> - - - The Spark build process uses Ant, so that tool must be installed and configured on your computer - Spark nutzt den Apache Ant Compiler, so dass das Programm auf Ihrem Computer installiert und konfiguriert sein muss. - - - - Run the Build Tool to compile the Source Code - Führen Sie das Build Programm mit folgendem Befehl aus, um den Source Code zu kompilieren: - - ant - -
      - -
      - - <phrase lang="en">Ant Build Tasks</phrase> - <phrase lang="de">Ant Build Tasks</phrase> - - - To execute a build task, type anttargetname where "targetname" is one of the targets listed below: - Um einen Build Task auszuführen, nutze anttargetname. Ersetzte "targetname" mit einem der unten aufgeführten Ziele: - - - - base => Produces Base Jars For Jive Spark - changelog => Generates an incremental changelog file based upon the XML/RSS feed from JIRA - checkcode.pmd => Checkcode with pmd. - clean => Deletes files generated during the build. - development => Creates a development environment for Sparkplugs - dist.src => Creates a source distribution package - docbook => Create the Docbook - installer.debian => build release deb file for the Debian,Ubuntu - installer.innosetup => build release a izpack installer - installer.install4j => build Install4J release executable and docs dirs for Windows - installer.izpack => build release a izpack installer - installer.izpack.exe => build release executable izpack installer - installer.mac => build release dmg file for the Macintosh - installer.rpm => Builds a rpm of spark. - release.javadocs => creates javadocs version for developer source builds - -
      - -
      - diff --git a/src/docbook/developer.sgml b/src/docbook/developer.sgml deleted file mode 100644 index 16f8894a6..000000000 --- a/src/docbook/developer.sgml +++ /dev/null @@ -1,10 +0,0 @@ - - - Developer - - - - - - - diff --git a/src/docbook/installation-debian.sgml b/src/docbook/installation-debian.sgml deleted file mode 100644 index f1deb08ef..000000000 --- a/src/docbook/installation-debian.sgml +++ /dev/null @@ -1,17 +0,0 @@ - -
      - - <phrase lang="en">Install Spark on Debian/Ubuntu</phrase> - - - - - For Ubuntu/Debian System use the Spark Debian Package. - To install Spark execute the follow commands as root: - - - apt-get install java-6-sun - dpkg -i spark_X.X.X_all.deb - - -
      \ No newline at end of file diff --git a/src/docbook/installation-izpack.sgml b/src/docbook/installation-izpack.sgml deleted file mode 100644 index 8882408f9..000000000 --- a/src/docbook/installation-izpack.sgml +++ /dev/null @@ -1,34 +0,0 @@ - -
      - - <phrase lang="en">Install Spark with IzPack</phrase> - - - -
      - - <phrase lang="en">Install Spark with IzPack Automated Installer</phrase> - - - - - At the ende of the installation, - the user can save the data for an automatic installation. - With this data, he will be able to run the same installation on another similar machine. - In an environment where many computers need to be supported this can save a lot of time. - - - - - So run once the installation on a machine and save your automatic installation data in auto-install.xml. - Then put this file in the same directory as the installer on another machine. Run it with: - - - - - - java -jar spark-installer.jar auto-install.xml - - Y -
      -
      \ No newline at end of file diff --git a/src/docbook/installation.sgml b/src/docbook/installation.sgml deleted file mode 100644 index 54c033f9e..000000000 --- a/src/docbook/installation.sgml +++ /dev/null @@ -1,11 +0,0 @@ - - - - <phrase lang="en">Install Spark</phrase> - <phrase lang="de">Installation von Spark</phrase> - - - - - - \ No newline at end of file diff --git a/src/docbook/user.sgml b/src/docbook/user.sgml deleted file mode 100644 index 7bae41816..000000000 --- a/src/docbook/user.sgml +++ /dev/null @@ -1,20 +0,0 @@ - - - - <phrase lang="en">User</phrase> - <phrase lang="en">Benutzer</phrase> - - -
      - - <phrase lang="en">Get Started</phrase> - - - - - After you install Spark, you'll get going by logging in and adding contacts. Try out a chat with one of your contacts! - - -
      -
      - diff --git a/src/java/org/jivesoftware/AccountCreationWizard.java b/src/java/org/jivesoftware/AccountCreationWizard.java deleted file mode 100644 index 88d32f827..000000000 --- a/src/java/org/jivesoftware/AccountCreationWizard.java +++ /dev/null @@ -1,377 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.jivesoftware; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.smack.*; -import org.jivesoftware.smack.packet.XMPPError; -import org.jivesoftware.smack.tcp.XMPPTCPConnection; -import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; -import org.jivesoftware.smackx.iqregister.AccountManager; -import org.jivesoftware.spark.component.TitlePanel; -import org.jivesoftware.spark.util.DummySSLSocketFactory; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.io.IOException; - -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPasswordField; -import javax.swing.JProgressBar; -import javax.swing.JTextField; -import javax.swing.UIManager; - -/** - * Allows the creation of accounts on an XMPP server. - */ -public class AccountCreationWizard extends JPanel { - private static final long serialVersionUID = -7808507939643878212L; - private JTextField usernameField = new JTextField(); - - private JPasswordField passwordField = new JPasswordField(); - - private JPasswordField confirmPasswordField = new JPasswordField(); - - private JTextField serverField = new JTextField(); - - private JButton createAccountButton = new JButton(); - - private JDialog dialog; - - private boolean registered; - private XMPPConnection connection = null; - private JProgressBar progressBar; - - /** - * Construct the AccountCreationWizard UI. - */ - public AccountCreationWizard() { - // Associate Mnemonics - JLabel usernameLabel = new JLabel(); - ResourceUtils.resLabel( usernameLabel, usernameField, Res.getString("label.username") + ":"); - JLabel passwordLabel = new JLabel(); - ResourceUtils.resLabel( passwordLabel, passwordField, Res.getString("label.password") + ":"); - JLabel confirmPasswordLabel = new JLabel(); - ResourceUtils.resLabel( confirmPasswordLabel, confirmPasswordField, Res.getString("label.confirm.password") + ":"); - JLabel serverLabel = new JLabel(); - ResourceUtils.resLabel( serverLabel, serverField, Res.getString("label.server") + ":"); - ResourceUtils.resButton(createAccountButton, Res.getString("button.create.account")); - - setLayout(new GridBagLayout()); - - // Add component to UI - add( usernameLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(usernameField, new GridBagConstraints(1, 0, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 150, 0)); - - add( passwordLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(passwordField, new GridBagConstraints(1, 1, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - add( confirmPasswordLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(confirmPasswordField, new GridBagConstraints(1, 2, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - add( serverLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(serverField, new GridBagConstraints(1, 3, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - progressBar = new JProgressBar(); - - - add(progressBar, new GridBagConstraints(1, 4, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - progressBar.setVisible(false); - add(createAccountButton, new GridBagConstraints(2, 5, 1, 1, 1.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - - JButton closeButton = new JButton(); - ResourceUtils.resButton( closeButton, Res.getString("button.close")); - add( closeButton, new GridBagConstraints(3, 5, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - - createAccountButton.addActionListener( actionEvent -> createAccount() ); - - closeButton.addActionListener( actionEvent -> dialog.dispose() ); - } - - /** - * Returns the username to use for the new account. - * - * @return the username. - */ - public String getUsername() { - return XmppStringUtils.escapeLocalpart(usernameField.getText().toLowerCase()); - } - - /** - * Returns the username to use for the new account. - * - * @return the username. - */ - public String getUsernameWithoutEscape() { - return usernameField.getText(); - } - - /** - * Returns the password to use for the new account. - * - * @return the password to use for the new account. - */ - public String getPassword() { - return new String(passwordField.getPassword()); - } - - /** - * Returns the confirmation password to use for the new account. - * - * @return the password to use for the new account. - */ - public String getConfirmPassword() { - return new String(confirmPasswordField.getPassword()); - } - - /** - * Returns the server to use with the new account. - * - * @return the server to use. - */ - public String getServer() { - return serverField.getText(); - } - - /** - * Returns true if the passwords match. - * - * @return true if the passwords match. - */ - public boolean isPasswordValid() { - return getPassword().equals(getConfirmPassword()); - } - - /** - * Creates the new account using the supplied information. - */ - private void createAccount() { - boolean errors = false; - String errorMessage = ""; - - if (!ModelUtil.hasLength(getUsername())) { - errors = true; - usernameField.requestFocus(); - errorMessage = Res.getString("message.username.error"); - } - else if (!ModelUtil.hasLength(getPassword())) { - errors = true; - errorMessage = Res.getString("message.password.error"); - } - else if (!ModelUtil.hasLength(getConfirmPassword())) { - errors = true; - errorMessage = Res.getString("message.confirmation.password.error"); - } - else if (!ModelUtil.hasLength(getServer())) { - errors = true; - errorMessage = Res.getString("message.account.error"); - } - else if (!isPasswordValid()) { - errors = true; - errorMessage = Res.getString("message.confirmation.password.error"); - } - - if (errors) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(this, errorMessage, Res.getString("title.create.problem"), JOptionPane.ERROR_MESSAGE); - return; - } - - final Component ui = this; - progressBar.setIndeterminate(true); - progressBar.setStringPainted(true); - progressBar.setString(Res.getString("message.registering", getServer())); - progressBar.setVisible(true); - - final SwingWorker worker = new SwingWorker() { - XMPPError.Condition condition = null; - - - public Object construct() { - try { - createAccountButton.setEnabled(false); - connection = getConnection(); - } - catch (SmackException | IOException | XMPPException e) { - return e; - } - try { - final AccountManager accountManager = AccountManager.getInstance(connection); - accountManager.createAccount(getUsername(), getPassword()); - } - catch (XMPPException | SmackException e) { - - if ( e instanceof XMPPException.XMPPErrorException ) { - condition = ( (XMPPException.XMPPErrorException) e ).getXMPPError().getCondition(); - } - - if ( condition == null ) { - condition = XMPPError.Condition.internal_server_error; - } - } - return "ok"; - } - - public void finished() { - progressBar.setVisible(false); - if (connection == null) { - if (ui.isShowing()) { - createAccountButton.setEnabled(true); - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(ui, Res.getString("message.connection.failed", getServer()), Res.getString("title.create.problem"), JOptionPane.ERROR_MESSAGE); - createAccountButton.setEnabled(true); - } - return; - } - - if (condition == null) { - accountCreationSuccessful(); - } - else { - accountCreationFailed(condition); - } - } - }; - - worker.start(); - } - - /** - * Called if the account creation failed. - * - * @param condition the error code. - */ - private void accountCreationFailed( XMPPError.Condition condition ) { - String message = Res.getString("message.create.account"); - if (condition == XMPPError.Condition.conflict) { - message = Res.getString("message.already.exists"); - usernameField.setText(""); - usernameField.requestFocus(); - } - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(this, message, Res.getString("title.create.problem"), JOptionPane.ERROR_MESSAGE); - createAccountButton.setEnabled(true); - } - - /** - * Called if the account was created succesfully. - */ - private void accountCreationSuccessful() { - registered = true; - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(this, Res.getString("message.account.created"), Res.getString("title.account.created"), JOptionPane.INFORMATION_MESSAGE); - dialog.dispose(); - } - - /** - * Invokes the AccountCreationWizard. - * - * @param parent the parent frame to use. - */ - public void invoke(JFrame parent) { - dialog = new JDialog(parent, Res.getString("title.create.new.account"), true); - - TitlePanel titlePanel = new TitlePanel(Res.getString("title.account.create.registration"), Res.getString("message.account.create"), null, true); - dialog.getContentPane().setLayout(new BorderLayout()); - dialog.getContentPane().add(titlePanel, BorderLayout.NORTH); - dialog.getContentPane().add(this, BorderLayout.CENTER); - dialog.pack(); - dialog.setSize(400, 300); - dialog.setLocationRelativeTo(parent); - dialog.setVisible(true); - } - - /** - * Creates an XMPPConnection based on the users settings. - * - * @return the XMPPConnection created. - */ - private XMPPConnection getConnection() throws SmackException, IOException, XMPPException - { - final LocalPreferences localPreferences = SettingsManager.getLocalPreferences(); - - int port = localPreferences.getXmppPort(); - - String serverName = getServer(); - - int checkForPort = serverName.indexOf(":"); - if (checkForPort != -1) { - String portString = serverName.substring(checkForPort + 1); - if (ModelUtil.hasLength(portString)) { - // Set new port. - port = Integer.valueOf(portString); - } - } - - boolean useSSL = localPreferences.isSSL(); - boolean hostPortConfigured = localPreferences.isHostAndPortConfigured(); - - final XMPPTCPConnectionConfiguration.Builder builder = XMPPTCPConnectionConfiguration.builder() - .setUsernameAndPassword( "username", "password" ) - .setServiceName( serverName ) - .setPort( port ) - .setCompressionEnabled( localPreferences.isCompressionEnabled() ); - - if ( hostPortConfigured ) { - builder.setHost( localPreferences.getXmppHost() ); - } - if (useSSL) { - if (!hostPortConfigured) { - builder.setPort( 5223 ); - } - builder.setSocketFactory( new DummySSLSocketFactory() ); - } - - final XMPPTCPConnectionConfiguration configuration = builder.build(); - - final AbstractXMPPConnection connection = new XMPPTCPConnection( configuration ); - connection.connect(); - - return connection; - } - - /** - * Returns true if the user is registered. - * - * @return true if the user is registered. - */ - public boolean isRegistered() { - return registered; - } -} - diff --git a/src/java/org/jivesoftware/GSSAPIConfiguration.java b/src/java/org/jivesoftware/GSSAPIConfiguration.java deleted file mode 100644 index e3f0ba209..000000000 --- a/src/java/org/jivesoftware/GSSAPIConfiguration.java +++ /dev/null @@ -1,101 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware; - -import javax.security.auth.login.AppConfigurationEntry; -import javax.security.auth.login.Configuration; - -import java.util.HashMap; -import java.util.Map; -import java.util.Vector; - - -public class GSSAPIConfiguration extends Configuration { - - Map> configs; - - GSSAPIConfiguration() { - super(); - init(true); - } - - GSSAPIConfiguration(boolean config_from_file) { - super(); - init(config_from_file); - } - - - private void init(boolean config_from_file) { - - configs = new HashMap<>(); - - //The structure of the options is not well documented in terms of - //data types. Since the file version of the Configuration object - //puts things in quotes, String is assumed. But boolean options - //do not have quotes, and my represent different types internally. - HashMap c_options = new HashMap<>(); - - //If Kerberos config is not from a file, it's not possible to (re-)read the config file. - //So don't set refreshKrb5Config - if (config_from_file) { - c_options.put("refreshKrb5Config", "true"); - } - c_options.put("doNotPrompt", "true"); - c_options.put("useTicketCache", "true"); - c_options.put("debug", "true"); - - - putAppConfigurationEntry("com.sun.security.jgss.initiate", "com.sun.security.auth.module.Krb5LoginModule", AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, c_options); - putAppConfigurationEntry("com.sun.security.jgss.krb5.initiate", "com.sun.security.auth.module.Krb5LoginModule", AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, c_options); - - } - - public AppConfigurationEntry[] getAppConfigurationEntry(String name) { - AppConfigurationEntry[] a = new AppConfigurationEntry[1]; - if (configs.containsKey(name)) { - Vector v = configs.get(name); - a = v.toArray(a); - return a; - } - else { - return null; - } - } - - public boolean putAppConfigurationEntry(String name, String module, AppConfigurationEntry.LoginModuleControlFlag controlFlag, Map options) { - Vector v; - if (configs.containsKey(name)) { - v = configs.get(name); - } - else { - v = new Vector<>(); - configs.put(name, v); - } - - return v.add(new AppConfigurationEntry(module, controlFlag, options)); - } - - - public void refresh() { - } - - -} diff --git a/src/java/org/jivesoftware/LoginDialog.java b/src/java/org/jivesoftware/LoginDialog.java deleted file mode 100644 index 9e43b8cd2..000000000 --- a/src/java/org/jivesoftware/LoginDialog.java +++ /dev/null @@ -1,1524 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware; - -import java.awt.BorderLayout; -import java.awt.CardLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.EventQueue; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Image; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.awt.geom.AffineTransform; -import java.io.File; -import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.security.Principal; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.List; -import javax.naming.NamingException; -import javax.naming.directory.Attribute; -import javax.naming.directory.Attributes; -import javax.naming.directory.DirContext; -import javax.naming.directory.InitialDirContext; -import javax.security.auth.Subject; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.NameCallback; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.login.Configuration; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; -import javax.swing.ImageIcon; -import javax.swing.JCheckBox; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPasswordField; -import javax.swing.JPopupMenu; -import javax.swing.JSplitPane; -import javax.swing.JTextField; -import javax.swing.UIManager; -import javax.swing.text.JTextComponent; - -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.io.SAXReader; -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.*; -import org.jivesoftware.smack.proxy.ProxyInfo; -import org.jivesoftware.smack.sasl.javax.SASLExternalMechanism; -import org.jivesoftware.smack.tcp.XMPPTCPConnection; -import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; -import org.jivesoftware.smackx.chatstates.ChatStateManager; -import org.jivesoftware.spark.SessionManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.Workspace; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.util.BrowserLauncher; -import org.jivesoftware.spark.util.DummySSLSocketFactory; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.JiveInfo; -import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettings; -import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettingsManager; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -/** - * Dialog to log in a user into the Spark Server. The LoginDialog is used only - * for login in registered users into the Spark Server. - */ -public class LoginDialog { - private JFrame loginDialog; - private static final String BUTTON_PANEL = "buttonpanel"; // NOTRANS - private static final String PROGRESS_BAR = "progressbar"; // NOTRANS - private LocalPreferences localPref; - private ArrayList _usernames = new ArrayList<>(); - private String loginUsername; - private String loginPassword; - private String loginServer; - - /** - * Empty Constructor - */ - public LoginDialog() { - localPref = SettingsManager.getLocalPreferences(); - - // Check if upgraded needed. - try { - checkForOldSettings(); - } - catch (Exception e) { - Log.error(e); - } - } - - /** - * Invokes the LoginDialog to be visible. - * - * @param parentFrame the parentFrame of the Login Dialog. This is used - * for correct parenting. - */ - public void invoke(final JFrame parentFrame) { - // Before creating any connections. Update proxy if needed. - try { - updateProxyConfig(); - } - catch (Exception e) { - Log.error(e); - } - - - // Construct Dialog - EventQueue.invokeLater( () -> { - loginDialog = new JFrame(Default.getString(Default.APPLICATION_NAME)); - loginDialog.setIconImage(SparkManager.getApplicationImage().getImage()); - LoginPanel loginPanel = new LoginPanel(); - final JPanel mainPanel = new LoginBackgroundPanel(); - final GridBagLayout mainLayout = new GridBagLayout(); - mainPanel.setLayout(mainLayout); - - final ImagePanel imagePanel = new ImagePanel(); - - mainPanel.add(imagePanel, - new GridBagConstraints(0, 0, 4, 1, - 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, - new Insets(0, 0, 0, 0), 0, 0)); - - final String showPoweredBy = Default.getString(Default.SHOW_POWERED_BY); - if (ModelUtil.hasLength(showPoweredBy) && "true".equals(showPoweredBy)) { - // Handle Powered By for custom clients. - final JLabel poweredBy = new JLabel(SparkRes.getImageIcon(SparkRes.POWERED_BY_IMAGE)); - mainPanel.add(poweredBy, - new GridBagConstraints(0, 1, 4, 1, - 1.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.HORIZONTAL, - new Insets(0, 0, 2, 0), 0, 0)); - - } - - loginPanel.setOpaque(false); - mainPanel.add(loginPanel, - new GridBagConstraints(0, 2, 2, 1, - 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, - new Insets(0, 0, 0, 0), 0, 0)); - - loginDialog.setContentPane(mainPanel); - loginDialog.setLocationRelativeTo(parentFrame); - - loginDialog.setResizable(false); - loginDialog.pack(); - - // Center dialog on screen - GraphicUtils.centerWindowOnScreen(loginDialog); - - // Show dialog - loginDialog.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - quitLogin(); - } - }); - if (loginPanel.getUsername().trim().length() > 0) { - loginPanel.getPasswordField().requestFocus(); - } - - if (!localPref.isStartedHidden() || !localPref.isAutoLogin()) { - // Make dialog top most. - loginDialog.setVisible(true); - } - } ); - - - } - - //This method can be overwritten by subclasses to provide additional validations - //(such as certificate download functionality when connecting) - protected boolean beforeLoginValidations() { - return true; - } - - protected void afterLogin() { - // Does noting by default - but can be overwritten by subclasses to provide additional - // settings - } - - protected XMPPTCPConnectionConfiguration retrieveConnectionConfiguration() { - int port = localPref.getXmppPort(); - - int checkForPort = loginServer.indexOf(":"); - if (checkForPort != -1) { - String portString = loginServer.substring(checkForPort + 1); - if (ModelUtil.hasLength(portString)) { - // Set new port. - port = Integer.valueOf(portString); - } - } - - boolean useSSL = localPref.isSSL(); - boolean hostPortConfigured = localPref.isHostAndPortConfigured(); - - ProxyInfo proxyInfo = null; - if (localPref.isProxyEnabled()) { - ProxyInfo.ProxyType pType = localPref.getProtocol().equals("SOCKS") ? - ProxyInfo.ProxyType.SOCKS5 : ProxyInfo.ProxyType.HTTP; - String pHost = ModelUtil.hasLength(localPref.getHost()) ? - localPref.getHost() : null; - int pPort = ModelUtil.hasLength(localPref.getPort()) ? - Integer.parseInt(localPref.getPort()) : 0; - String pUser = ModelUtil.hasLength(localPref.getProxyUsername()) ? - localPref.getProxyUsername() : null; - String pPass = ModelUtil.hasLength(localPref.getProxyPassword()) ? - localPref.getProxyPassword() : null; - - if (pHost != null && pPort != 0) { - - if (pUser == null || pPass == null) { - - proxyInfo = new ProxyInfo(pType, pHost, pPort, null, null); - } else { - - proxyInfo = new ProxyInfo(pType, pHost, pPort, pUser, pPass); - - } - } else { - Log.error("No proxy info found but proxy type is enabled!"); - } - } - - final XMPPTCPConnectionConfiguration.Builder builder = XMPPTCPConnectionConfiguration.builder() - .setUsernameAndPassword( "username", "password" ) - .setServiceName( loginServer ) - .setPort( port ) - .setSendPresence( false ) - .setCompressionEnabled( localPref.isCompressionEnabled() ); - - if ( hostPortConfigured ) { - builder.setHost( localPref.getXmppHost() ); - } - - if ( localPref.isProxyEnabled() ) - { - builder.setProxyInfo( proxyInfo ); - } - - if (useSSL) { - if (!hostPortConfigured) { - builder.setPort( 5223 ); - } - builder.setSocketFactory( new DummySSLSocketFactory() ); - } - - final XMPPTCPConnectionConfiguration configuration = builder.build(); - - if (localPref.isPKIEnabled()) { - SASLAuthentication.registerSASLMechanism( new SASLExternalMechanism() ); - builder.setKeystoreType(localPref.getPKIStore()); - if(localPref.getPKIStore().equals("PKCS11")) { - builder.setPKCS11Library(localPref.getPKCS11Library()); - } - else if(localPref.getPKIStore().equals("JKS")) { - builder.setKeystoreType("JKS"); - builder.setKeystorePath(localPref.getJKSPath()); - - } - else if(localPref.getPKIStore().equals("X509")) { - //do something - } - else if(localPref.getPKIStore().equals("Apple")) { - builder.setKeystoreType("Apple"); - } - } - - // TODO These were used in Smack 3. Find Smack 4 alternative. -// config.setReconnectionAllowed(true); -// config.setRosterLoadedAtLogin(true); -// if(ModelUtil.hasLength(localPref.getTrustStorePath())) { -// config.setTruststorePath(localPref.getTrustStorePath()); -// config.setTruststorePassword(localPref.getTrustStorePassword()); -// } - return builder.build(); - } - - /** - * Define Login Panel implementation. - */ - private final class LoginPanel extends JPanel implements KeyListener, ActionListener, FocusListener, CallbackHandler { - private static final long serialVersionUID = 2445523786538863459L; - private final JLabel usernameLabel = new JLabel(); - private final JTextField usernameField = new JTextField(); - - private final JLabel passwordLabel = new JLabel(); - private final JPasswordField passwordField = new JPasswordField(); - - private final JLabel serverLabel = new JLabel(); - private final JTextField serverField = new JTextField(); - - private final JCheckBox savePasswordBox = new JCheckBox(); - private final JCheckBox autoLoginBox = new JCheckBox(); - private final RolloverButton loginButton = new RolloverButton(); - private final RolloverButton advancedButton = new RolloverButton(); - private final RolloverButton quitButton = new RolloverButton(); - private final JCheckBox loginAsInvisibleBox = new JCheckBox(); - - private final RolloverButton createAccountButton = new RolloverButton(); - private final RolloverButton passwordResetButton = new RolloverButton(); - - private final JLabel progressBar = new JLabel(); - - // Panel used to hold buttons - private final CardLayout cardLayout = new CardLayout(0, 5); - final JPanel cardPanel = new JPanel(cardLayout); - - final JPanel buttonPanel = new JPanel(new GridBagLayout()); - private final GridBagLayout GRIDBAGLAYOUT = new GridBagLayout(); - private AbstractXMPPConnection connection = null; - - private JLabel headerLabel = new JLabel(); - private JLabel accountLabel = new JLabel(); - private JLabel accountNameLabel = new JLabel(); - private JLabel serverNameLabel = new JLabel(); - private JLabel ssoServerLabel = new JLabel(); - - private RolloverButton otherUsers = new RolloverButton(SparkRes.getImageIcon(SparkRes.PANE_UP_ARROW_IMAGE)); - - - LoginPanel() { - //setBorder(BorderFactory.createTitledBorder("Sign In Now")); - ResourceUtils.resButton(savePasswordBox, Res.getString("checkbox.save.password")); - ResourceUtils.resButton(autoLoginBox, Res.getString("checkbox.auto.login")); - ResourceUtils.resLabel(serverLabel, serverField, Res.getString("label.server")); - ResourceUtils.resButton(createAccountButton, Res.getString("label.accounts")); - ResourceUtils.resButton(passwordResetButton, Res.getString("label.passwordreset")); - ResourceUtils.resButton(loginAsInvisibleBox, Res.getString("checkbox.login.as.invisible")); - - savePasswordBox.setOpaque(false); - autoLoginBox.setOpaque(false); - loginAsInvisibleBox.setOpaque(false); - setLayout(GRIDBAGLAYOUT); - - // Set default visibility - headerLabel.setVisible(false); - accountLabel.setVisible(false); - accountNameLabel.setVisible(false); - serverNameLabel.setVisible(false); - - headerLabel.setText(Res.getString("title.advanced.connection.sso")); - headerLabel.setFont(headerLabel.getFont().deriveFont(Font.BOLD)); - accountLabel.setText("Account:"); - ssoServerLabel.setText("Server:"); - accountNameLabel.setFont(accountLabel.getFont().deriveFont(Font.BOLD)); - serverNameLabel.setFont(ssoServerLabel.getFont().deriveFont(Font.BOLD)); - - - accountNameLabel.setForeground(new Color(106, 127, 146)); - serverNameLabel.setForeground(new Color(106, 127, 146)); - - otherUsers.setFocusable(false); - - - add(usernameLabel, - new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 0, 5), 0, 0)); - add(usernameField, - new GridBagConstraints(1, 0, 2, 1, - 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(5, 5, 0, 0), 0, 0)); - - add(otherUsers, new GridBagConstraints(3, 0, 1, 1, - 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(5, 0, 0, 0), 0, 0)); - - add(accountLabel, - new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 0, 5), 0, 0)); - add(accountNameLabel, - new GridBagConstraints(1, 1, 1, 1, - 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(5, 5, 0, 5), 0, 0)); - - add(passwordLabel, - new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 0, 5), 5, 0)); - add(passwordField, - new GridBagConstraints(1, 1, 2, 1, - 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(5, 5, 0, 0), 0, 0)); - - - // Add Server Field Properties - add(serverLabel, - new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 0, 5), 5, 0)); - add(serverField, - new GridBagConstraints(1, 2, 2, 1, - 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(5, 5, 0, 0), 0, 0)); - - add(serverNameLabel, - new GridBagConstraints(1, 2, 2, 1, - 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(5, 5, 0, 5), 0, 0)); - - add(headerLabel, - new GridBagConstraints(0, 5, 2, 1, 1.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - if(!Default.getBoolean("HIDE_SAVE_PASSWORD_AND_AUTOLOGIN")) { - add(savePasswordBox, - new GridBagConstraints(1, 5, 2, 1, 1.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 5), 0, 0)); - add(autoLoginBox, - new GridBagConstraints(1, 6, 2, 1, 1.0, 0.0, - GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 5), 0, 0)); - } - add(loginAsInvisibleBox, - new GridBagConstraints(1, 7, 2, 1, 1.0, 0.0, - GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 5), 0, 0)); - - // Add button but disable the login button initially - savePasswordBox.addActionListener(this); - autoLoginBox.addActionListener(this); - loginAsInvisibleBox.addActionListener(this); - - if (!Default.getBoolean(Default.ACCOUNT_DISABLED)) { - buttonPanel.add(createAccountButton, - new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, - GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 0, 5), 0, 0)); - } - - if (Default.getBoolean(Default.PASSWORD_RESET_ENABLED)) { - buttonPanel.add(passwordResetButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 0, 5), 0, 0)); - passwordResetButton.addActionListener(new ActionListener() { - final String url = Default.getString(Default.PASSWORD_RESET_URL); - private static final long serialVersionUID = 2680369963282231348L; - - public void actionPerformed(ActionEvent actionEvent) { - try { - - BrowserLauncher.openURL(url); - } catch (Exception e) { - Log.error("Unable to load password " + - "reset.", e); - } - } - }); - } - - if(!Default.getBoolean(Default.ADVANCED_DISABLED)){ - buttonPanel.add(advancedButton, - new GridBagConstraints(2, 0, 1, 1, 1.0, 0.0, - GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 0, 5), 0, 0)); - } - buttonPanel.add(loginButton, - new GridBagConstraints(3, 0, 4, 1, 1.0, 0.0, - GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 0, 5), 0, 0)); - - cardPanel.add(buttonPanel, BUTTON_PANEL); - - cardPanel.setOpaque(false); - buttonPanel.setOpaque(false); - - ImageIcon icon = new ImageIcon(getClass().getClassLoader().getResource("images/ajax-loader.gif")); - progressBar.setIcon(icon); - cardPanel.add(progressBar, PROGRESS_BAR); - - - add(cardPanel, new GridBagConstraints(0, 8, 4, 1, - 1.0, 1.0, GridBagConstraints.SOUTH, GridBagConstraints.HORIZONTAL, - new Insets(2, 2, 2, 2), 0, 0)); - loginButton.setEnabled(false); - - // Add KeyListener - usernameField.addKeyListener(this); - passwordField.addKeyListener(this); - serverField.addKeyListener(this); - - passwordField.addFocusListener(this); - usernameField.addFocusListener(this); - serverField.addFocusListener(this); - - // Add ActionListener - quitButton.addActionListener(this); - loginButton.addActionListener(this); - advancedButton.addActionListener(this); - - otherUsers.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - getPopup().show(otherUsers, e.getX(), e.getY()); - } - }); - - // Make same size - GraphicUtils.makeSameSize(usernameField, passwordField); - - // Set progress bar description - progressBar.setText(Res.getString("message.autenticating")); - progressBar.setVerticalTextPosition(JLabel.BOTTOM); - progressBar.setHorizontalTextPosition(JLabel.CENTER); - progressBar.setHorizontalAlignment(JLabel.CENTER); - - // Set Resources - ResourceUtils.resLabel(usernameLabel, usernameField, Res.getString("label.username")); - ResourceUtils.resLabel(passwordLabel, passwordField, Res.getString("label.password")); - ResourceUtils.resButton(quitButton, Res.getString("button.quit")); - ResourceUtils.resButton(loginButton, Res.getString("button.login")); - ResourceUtils.resButton(advancedButton, Res.getString("button.advanced")); - - // Load previous instances - String userProp = localPref.getLastUsername(); - String serverProp = localPref.getServer(); - - File file = new File(Spark.getSparkUserHome(), "/user/"); - File[] userprofiles = file.listFiles(); - - for (File f : userprofiles) { - - if (f.getName().contains("@")) { - _usernames.add(f.getName()); - } else { - Log.error("Profile contains wrong format: \"" + f.getName() - + "\" located at: " + f.getAbsolutePath()); - } - - } - - - if (userProp != null) { - usernameField.setText( XmppStringUtils.unescapeLocalpart(userProp)); - } - if (serverProp != null) { - serverField.setText(serverProp); - serverNameLabel.setText(serverProp); - } - - // Check Settings - if (localPref.isSavePassword()) { - - String encryptedPassword = localPref.getPasswordForUser(getBareJid()); - if (encryptedPassword != null) { - passwordField.setText(encryptedPassword); - } - savePasswordBox.setSelected(true); - loginButton.setEnabled(true); - } - autoLoginBox.setSelected(localPref.isAutoLogin()); - loginAsInvisibleBox.setSelected(localPref.isLoginAsInvisible()); - useSSO(localPref.isSSOEnabled()); - if (autoLoginBox.isSelected()) { - savePasswordBox.setEnabled(false); - autoLoginBox.setEnabled(false); - loginAsInvisibleBox.setEnabled(false); - validateLogin(); - return; - } - - // Handle arguments - String username = Spark.getArgumentValue("username"); - String password = Spark.getArgumentValue("password"); - String server = Spark.getArgumentValue("server"); - - if (username != null) { - usernameField.setText(username); - } - - if (password != null) { - passwordField.setText(password); - } - - if (server != null) { - serverField.setText(server); - } - - if (username != null && server != null && password != null) { - savePasswordBox.setEnabled(false); - autoLoginBox.setEnabled(false); - loginAsInvisibleBox.setEnabled(false); - validateLogin(); - } - - createAccountButton.addActionListener(this); - - final String lockedDownURL = Default.getString(Default.HOST_NAME); - if (ModelUtil.hasLength(lockedDownURL)) { - serverField.setText(lockedDownURL); - } - if (Default.getBoolean("HOST_NAME_CHANGE_DISABLED")) - serverField.setEnabled(false); - - - - } - - /** - * Returns the username the user defined. - * - * @return the username. - */ - private String getUsername() { - return XmppStringUtils.escapeLocalpart(usernameField.getText().trim()); - } - - /** - * Returns the resulting bareJID from username and server - * @return - */ - private String getBareJid() - { - return usernameField.getText()+"@"+serverField.getText(); - } - - /** - * Returns the password specified by the user. - * - * @return the password. - */ - private String getPassword() { - return new String(passwordField.getPassword()); - } - - /** - * Returns the server name specified by the user. - * - * @return the server name. - */ - private String getServerName() { - return serverField.getText().trim(); - } - - /** - * Return whether user wants to login as invisible or not. - * - * @return the true if user wants to login as invisible. - */ - boolean isLoginAsInvisible() { - return loginAsInvisibleBox.isSelected(); - } - - /** - * ActionListener implementation. - * - * @param e the ActionEvent - */ - public void actionPerformed(ActionEvent e) { - - if (e.getSource() == quitButton) { - quitLogin(); - } - else if (e.getSource() == createAccountButton) { - AccountCreationWizard createAccountPanel = new AccountCreationWizard(); - createAccountPanel.invoke(loginDialog); - - if (createAccountPanel.isRegistered()) { - usernameField.setText(createAccountPanel.getUsernameWithoutEscape()); - passwordField.setText(createAccountPanel.getPassword()); - serverField.setText(createAccountPanel.getServer()); - loginButton.setEnabled(true); - } - } - else if (e.getSource() == loginButton) { - - - validateLogin(); - - - } - else if (e.getSource() == advancedButton) { - final LoginSettingDialog loginSettingsDialog = new LoginSettingDialog(); - loginSettingsDialog.invoke(loginDialog); - useSSO(localPref.isSSOEnabled()); - } - else if (e.getSource() == savePasswordBox) { - autoLoginBox.setEnabled(savePasswordBox.isSelected()); - - if (!savePasswordBox.isSelected()) { - autoLoginBox.setSelected(false); - } - } - else if (e.getSource() == autoLoginBox) { - if (autoLoginBox.isSelected()) { - savePasswordBox.setSelected(true); - } - } - } - - private JPopupMenu getPopup() - { - JPopupMenu popup = new JPopupMenu(); - for(final String key : _usernames) - { - - JMenuItem menu = new JMenuItem(key); - - final String username = key.split("@")[0]; - final String host = key.split("@")[1]; - menu.addActionListener( e -> { - usernameField.setText(username); - serverField.setText(host); - - try { - passwordField.setText(localPref.getPasswordForUser(getBareJid())); - if(passwordField.getPassword().length<1) { - loginButton.setEnabled(false); - } - else { - loginButton.setEnabled(true); - } - } catch (Exception e1) { - } - - } ); - - popup.add(menu); - } - return popup; - } - - /** - * KeyListener implementation. - * - * @param e the KeyEvent to process. - */ - public void keyTyped(KeyEvent e) { - validate(e); - } - - public void keyPressed(KeyEvent e) { - if(e.getKeyCode() == KeyEvent.VK_RIGHT && - ((JTextField)e.getSource()).getCaretPosition()==((JTextField)e.getSource()).getText().length()) - { - getPopup().show(otherUsers,0,0); - } - } - - public void keyReleased(KeyEvent e) { - validateDialog(); - } - - /** - * Checks the users input and enables/disables the login button depending on state. - */ - private void validateDialog() { - loginButton.setEnabled( - ModelUtil.hasLength(getUsername()) && - ( ModelUtil.hasLength(getPassword()) || localPref.isSSOEnabled() ) && - ModelUtil.hasLength(getServerName()) ); - } - - /** - * Validates key input. - * - * @param e the keyEvent. - */ - private void validate(KeyEvent e) { - if (loginButton.isEnabled() && e.getKeyChar() == KeyEvent.VK_ENTER) { - validateLogin(); - } - } - - public void focusGained(FocusEvent e) { - Object o = e.getSource(); - if (o instanceof JTextComponent) { - ((JTextComponent)o).selectAll(); - } - } - - public void focusLost(FocusEvent e) { - } - - /** - * Enables/Disables the editable components in the login screen. - * - * @param editable true to enable components, otherwise false to disable. - */ - private void enableComponents(boolean editable) { - - // Need to set both editable and enabled for best behavior. - usernameField.setEditable(editable); - usernameField.setEnabled(editable); - - passwordField.setEditable(editable); - passwordField.setEnabled(editable); - - final String lockedDownURL = Default.getString(Default.HOST_NAME); - if (!ModelUtil.hasLength(lockedDownURL)) { - serverField.setEditable(editable); - serverField.setEnabled(editable); - } - - - if (editable) { - // Reapply focus to username field - passwordField.requestFocus(); - } - } - - /** - * Displays the progress bar. - * - * @param visible true to display progress bar, false to hide it. - */ - private void setProgressBarVisible(boolean visible) { - if (visible) { - cardLayout.show(cardPanel, PROGRESS_BAR); - // progressBar.setIndeterminate(true); - } - else { - cardLayout.show(cardPanel, BUTTON_PANEL); - } - } - - /** - * Validates the users login information. - */ - private void validateLogin() { - final SwingWorker loginValidationThread = new SwingWorker() { - public Object construct() { - setLoginUsername(getUsername()); - setLoginPassword(getPassword()); - setLoginServer(getServerName()); - boolean loginSuccessfull = beforeLoginValidations() && login(); - if (loginSuccessfull) { - afterLogin(); - progressBar.setText(Res.getString("message.connecting.please.wait")); - - // Startup Spark - startSpark(); - - // dispose login dialog - loginDialog.dispose(); - - // Show ChangeLog if we need to. - // new ChangeLogDialog().showDialog(); - } - else { - EventQueue.invokeLater( () -> { - savePasswordBox.setEnabled(true); - autoLoginBox.setEnabled(true); - loginAsInvisibleBox.setVisible(true); - enableComponents(true); - setProgressBarVisible(false); - } ); - - } - return loginSuccessfull; - } - }; - - // Start the login process in seperate thread. - // Disable textfields - enableComponents(false); - - // Show progressbar - setProgressBarVisible(true); - - loginValidationThread.start(); - } - - public JPasswordField getPasswordField() { - return passwordField; - } - - public Dimension getPreferredSize() { - final Dimension dim = super.getPreferredSize(); - dim.height = 230; - return dim; - } - - public void useSSO(boolean use) { - if (use) { - usernameLabel.setVisible(true); - usernameField.setVisible(true); - - passwordLabel.setVisible(false); - passwordField.setVisible(false); - - savePasswordBox.setVisible(false); - - accountLabel.setVisible(true); - accountNameLabel.setVisible(true); - - serverField.setVisible(true); - - autoLoginBox.setVisible(true); - serverLabel.setVisible(true); - loginAsInvisibleBox.setVisible(true); - - headerLabel.setVisible(true); - - if(localPref.getDebug()) { - System.setProperty("java.security.krb5.debug","true"); - System.setProperty("sun.security.krb5.debug","true"); - } else { - System.setProperty("java.security.krb5.debug","false"); - System.setProperty("sun.security.krb5.debug","false"); - } - - String ssoMethod = localPref.getSSOMethod(); - if(!ModelUtil.hasLength(ssoMethod)) { - ssoMethod = "file"; - } - - System.setProperty("javax.security.auth.useSubjectCredsOnly", "false"); - GSSAPIConfiguration config = new GSSAPIConfiguration( ssoMethod.equals("file") ); - Configuration.setConfiguration(config); - - LoginContext lc; - String princName = localPref.getLastUsername(); - String princRealm = null; - try { - lc = new LoginContext("com.sun.security.jgss.krb5.initiate"); - lc.login(); - Subject mySubject = lc.getSubject(); - - - for (Principal p : mySubject.getPrincipals()) { - //TODO: check if principal is a kerberos principal first... - String name = p.getName(); - int indexOne = name.indexOf("@"); - if (indexOne != -1) { - princName = name.substring(0, indexOne); - accountNameLabel.setText(name); - princRealm = name.substring(indexOne+1); - } - loginButton.setEnabled(true); - } - } - catch (LoginException le) { - Log.debug(le.getMessage()); - accountNameLabel.setText(Res.getString("title.login.no.account")); - //useSSO(false); - } - - String ssoKdc; - if(ssoMethod.equals("dns")) { - if (princRealm != null) { //princRealm is null if we got a LoginException above. - ssoKdc = getDnsKdc(princRealm); - System.setProperty("java.security.krb5.realm",princRealm); - System.setProperty("java.security.krb5.kdc",ssoKdc); - } - } else if(ssoMethod.equals("manual")) { - princRealm = localPref.getSSORealm(); - ssoKdc = localPref.getSSOKDC(); - System.setProperty("java.security.krb5.realm",princRealm); - System.setProperty("java.security.krb5.kdc",ssoKdc); - } else { - //Assume "file" method. We don't have to do anything special, - //java takes care of it for us. Unset the props if they are set - System.clearProperty("java.security.krb5.realm"); - System.clearProperty("java.security.krb5.kdc"); - } - - String userName = localPref.getLastUsername(); - if (ModelUtil.hasLength(userName)) { - usernameField.setText(userName); - } else { - usernameField.setText(princName); - } - } - else { - autoLoginBox.setVisible(true); - usernameField.setVisible(true); - passwordField.setVisible(true); - savePasswordBox.setVisible(true); - usernameLabel.setVisible(true); - passwordLabel.setVisible(true); - serverLabel.setVisible(true); - serverField.setVisible(true); - loginAsInvisibleBox.setVisible(true); - - headerLabel.setVisible(false); - accountLabel.setVisible(false); - serverNameLabel.setVisible(false); - accountNameLabel.setVisible(false); - - Configuration.setConfiguration(null); - - validateDialog(); - } - - - } - - /** - * Login to the specified server using username, password, and workgroup. - * Handles error representation as well as logging. - * - * @return true if login was successful, false otherwise - */ - private boolean login() { - final SessionManager sessionManager = SparkManager.getSessionManager(); - - boolean hasErrors = false; - String errorMessage = null; - - localPref.setLoginAsInvisible(loginAsInvisibleBox.isSelected()); - - // Handle specifyed Workgroup - String serverName = getServerName(); - - - if (!hasErrors) { - localPref = SettingsManager.getLocalPreferences(); - if (localPref.isDebuggerEnabled()) { - SmackConfiguration.DEBUG = true; - } - - SmackConfiguration.setDefaultPacketReplyTimeout(localPref.getTimeOut() * 1000); - - // Get connection - try { - connection = new XMPPTCPConnection(retrieveConnectionConfiguration()); - //If we want to use the debug version of smack, we have to check if - //we are on the dispatch thread because smack will create an UI - if (localPref.isDebuggerEnabled()) { - if (EventQueue.isDispatchThread()) { - connection.connect(); - } else { - EventQueue.invokeAndWait( () -> { - try { - connection.connect(); - } catch (IOException | XMPPException | SmackException e) { - Log.error("connection error",e); - } - - } ); - } - } else { - connection.connect(); - } - - String resource = localPref.getResource(); - if (Default.getBoolean("HOSTNAME_AS_RESOURCE")) { - try { - resource = InetAddress.getLocalHost().getHostName(); - } catch(UnknownHostException e) { - Log.error("unable to retrieve hostname",e); - } - } else if (localPref.isUseHostnameAsResource()) { - try { - resource = InetAddress.getLocalHost().getHostName(); - } catch(UnknownHostException e) { - Log.error("unable to retrieve hostname",e); - } - } else if (Default.getBoolean("VERSION_AS_RESOURCE")) { - resource = Default.getString(Default.APPLICATION_NAME) + " " + JiveInfo.getVersion() + "." + Default.getString(Default.BUILD_NUMBER); - } else if (localPref.isUseVersionAsResource()) { - resource = Default.getString(Default.APPLICATION_NAME) + " " + JiveInfo.getVersion() + "." + Default.getString(Default.BUILD_NUMBER); - } - connection.login(getLoginUsername(), getLoginPassword(), - org.jivesoftware.spark.util.StringUtils.modifyWildcards(resource).trim()); - - sessionManager.setServerAddress(connection.getServiceName()); - sessionManager.initializeSession(connection, getLoginUsername(), getLoginPassword()); - sessionManager.setJID(connection.getUser()); - } - catch (Exception xee) { - - errorMessage = SparkRes.getString(SparkRes.UNRECOVERABLE_ERROR); - hasErrors = true; - - if (!loginDialog.isVisible()) { - loginDialog.setVisible(true); - } - if (xee instanceof XMPPException.XMPPErrorException) { - - XMPPException.XMPPErrorException xe = (XMPPException.XMPPErrorException)xee; - switch ( xe.getXMPPError().getCondition() ) - { - case conflict: - errorMessage = Res.getString("label.conflict.error"); - break; - - case not_authorized: - errorMessage = Res.getString("message.invalid.username.password"); - break; - - case remote_server_not_found: - errorMessage = Res.getString("message.server.unavailable"); - break; - - case remote_server_timeout: - errorMessage = Res.getString("message.server.unavailable"); - break; - - default: - errorMessage = Res.getString("message.unrecoverable.error"); - break; - } - } - - // Log Error - Log.warning("Exception in Login:", xee); - } - } - - if (hasErrors) { - - final String finalerrorMessage = errorMessage; - EventQueue.invokeLater( () -> { - progressBar.setVisible(false); - //progressBar.setIndeterminate(false); - - // Show error dialog - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - if (loginDialog.isVisible()) { - if (!localPref.isSSOEnabled()) { -JOptionPane.showMessageDialog(loginDialog, finalerrorMessage, Res.getString("title.login.error"), -JOptionPane.ERROR_MESSAGE); - } - else { -JOptionPane.showMessageDialog(loginDialog, Res.getString("title.advanced.connection.sso.unable"), Res.getString("title.login.error"), -JOptionPane.ERROR_MESSAGE); -//useSSO(false); -//localPref.setSSOEnabled(false); - } - } - } ); - - setEnabled(true); - return false; - } - - // Since the connection and workgroup are valid. Add a ConnectionListener - connection.addConnectionListener(SparkManager.getSessionManager()); - //Initialize chat state notification mechanism in smack - ChatStateManager.getInstance(SparkManager.getConnection()); - - // Persist information - localPref.setLastUsername(getLoginUsername()); - - // Check to see if the password should be saved. - if (savePasswordBox.isSelected()) { - try { - localPref.setPasswordForUser(getBareJid(), getPassword()); - } - catch (Exception e) { - Log.error("Error encrypting password.", e); - } - } - - localPref.setSavePassword(savePasswordBox.isSelected()); - localPref.setAutoLogin(autoLoginBox.isSelected()); - -// if (localPref.isSSOEnabled()) { -// localPref.setAutoLogin(true); -// } - - localPref.setServer(serverField.getText()); - - - SettingsManager.saveSettings(); - - return !hasErrors; - } - - public void handle(Callback[] callbacks) throws IOException { - for (Callback callback : callbacks) { - if (callback instanceof NameCallback) { - NameCallback ncb = (NameCallback) callback; - ncb.setName(getLoginUsername()); - } else if (callback instanceof PasswordCallback) { - PasswordCallback pcb = (PasswordCallback) callback; - pcb.setPassword(getPassword().toCharArray()); - } else { - Log.error("Unknown callback requested: " + callback.getClass().getSimpleName()); - } - } - } - } - - /** - * If the user quits, just shut down the - * application. - */ - private void quitLogin() { - System.exit(1); - } - - /** - * Initializes Spark and initializes all plugins. - */ - private void startSpark() { - // Invoke the MainWindow. - try - { - EventQueue.invokeLater( () -> { - final MainWindow mainWindow = MainWindow.getInstance(); - - - /* - if (tray != null) { - // Remove trayIcon - tray.removeTrayIcon(trayIcon); - } - */ - // Creates the Spark Workspace and add to MainWindow - Workspace workspace = Workspace.getInstance(); - - LayoutSettings settings = LayoutSettingsManager.getLayoutSettings(); - int x = settings.getMainWindowX(); - int y = settings.getMainWindowY(); - int width = settings.getMainWindowWidth(); - int height = settings.getMainWindowHeight(); - - LocalPreferences pref = SettingsManager.getLocalPreferences(); - if (pref.isDockingEnabled()) { - JSplitPane splitPane = mainWindow.getSplitPane(); - workspace.getCardPanel().setMinimumSize(null); - splitPane.setLeftComponent(workspace.getCardPanel()); - SparkManager.getChatManager().getChatContainer().setMinimumSize(null); - splitPane.setRightComponent(SparkManager.getChatManager().getChatContainer()); - int dividerLoc = settings.getSplitPaneDividerLocation(); - if (dividerLoc != -1) { - mainWindow.getSplitPane().setDividerLocation(dividerLoc); - } - else { - mainWindow.getSplitPane().setDividerLocation(240); - } - - mainWindow.getContentPane().add(splitPane, BorderLayout.CENTER); - } - else { - mainWindow.getContentPane().add(workspace.getCardPanel(), BorderLayout.CENTER); - } - - if (x == 0 && y == 0) { - // Use Default size - mainWindow.setSize(310, 520); - - // Center Window on Screen - GraphicUtils.centerWindowOnScreen(mainWindow); - } - else { - mainWindow.setBounds(x, y, width, height); - } - - if (loginDialog.isVisible()) { - mainWindow.setVisible(true); - } - - loginDialog.setVisible(false); - - // Build the layout in the workspace - workspace.buildLayout(); - } ); - } - catch (Exception e) - { - e.printStackTrace(); - } - - - } - - /** - * Updates System properties with Proxy configuration. - * - * @throws Exception thrown if an exception occurs. - */ - private void updateProxyConfig() throws Exception { - if (ModelUtil.hasLength(Default.getString(Default.PROXY_PORT)) && ModelUtil.hasLength(Default.getString(Default.PROXY_HOST))) { - String port = Default.getString(Default.PROXY_PORT); - String host = Default.getString(Default.PROXY_HOST); - System.setProperty("socksProxyHost", host); - System.setProperty("socksProxyPort", port); - return; - } - - boolean proxyEnabled = localPref.isProxyEnabled(); - if (proxyEnabled) { - String host = localPref.getHost(); - String port = localPref.getPort(); - String username = localPref.getProxyUsername(); - String password = localPref.getProxyPassword(); - String protocol = localPref.getProtocol(); - - if (protocol.equals("SOCKS")) { - System.setProperty("socksProxyHost", host); - System.setProperty("socksProxyPort", port); - - if (ModelUtil.hasLength(username) && ModelUtil.hasLength(password)) { - System.setProperty("java.net.socks.username", username); - System.setProperty("java.net.socks.password", password); - } - } - else { - System.setProperty("http.proxyHost", host); - System.setProperty("http.proxyPort", port); - System.setProperty("https.proxyHost", host); - System.setProperty("https.proxyPort", port); - - - if (ModelUtil.hasLength(username) && ModelUtil.hasLength(password)) { - System.setProperty("http.proxyUser", username); - System.setProperty("http.proxyPassword", password); - } - - } - } - } - - /** - * Defines the background to use with the Login panel. - */ - public class LoginBackgroundPanel extends JPanel { - private static final long serialVersionUID = -2449309600851007447L; - final ImageIcon icons = Default.getImageIcon(Default.LOGIN_DIALOG_BACKGROUND_IMAGE); - - /** - * Empty constructor. - */ - public LoginBackgroundPanel() { - - } - - /** - * Uses an image to paint on background. - * - * @param g the graphics. - */ - public void paintComponent(Graphics g) { - Image backgroundImage = icons.getImage(); - double scaleX = getWidth() / (double)backgroundImage.getWidth(null); - double scaleY = getHeight() / (double)backgroundImage.getHeight(null); - AffineTransform xform = AffineTransform.getScaleInstance(scaleX, scaleY); - ((Graphics2D)g).drawImage(backgroundImage, xform, this); - } - } - - /** - * The image panel to display the Spark Logo. - */ - public class ImagePanel extends JPanel { - - private static final long serialVersionUID = -1778389077647562606L; - private final ImageIcon icons = Default.getImageIcon(Default.MAIN_IMAGE); - - /** - * Uses the Spark logo to paint as the background. - * - * @param g the graphics to use. - */ - public void paintComponent(Graphics g) { - final Image backgroundImage = icons.getImage(); - final double scaleX = getWidth() / (double)backgroundImage.getWidth(null); - final double scaleY = getHeight() / (double)backgroundImage.getHeight(null); - AffineTransform xform = AffineTransform.getScaleInstance(scaleX, scaleY); - ((Graphics2D)g).drawImage(backgroundImage, xform, this); - } - - public Dimension getPreferredSize() { - final Dimension size = super.getPreferredSize(); - size.width = icons.getIconWidth(); - size.height = icons.getIconHeight(); - return size; - } - } - - /** - * Checks for historic Spark settings and upgrades the user. - * - * @throws Exception thrown if an error occurs. - */ - private void checkForOldSettings() throws Exception { - // Check for old settings.xml - File settingsXML = new File(Spark.getSparkUserHome(), "/settings.xml"); - if (settingsXML.exists()) { - SAXReader saxReader = new SAXReader(); - Document pluginXML; - try { - pluginXML = saxReader.read(settingsXML); - } - catch (DocumentException e) { - Log.error(e); - return; - } - - List plugins = pluginXML.selectNodes("/settings"); - for (Object plugin1 : plugins) { - Element plugin = (Element) plugin1; - - String username = plugin.selectSingleNode("username").getText(); - localPref.setLastUsername(username); - - String server = plugin.selectSingleNode("server").getText(); - localPref.setServer(server); - - String autoLogin = plugin.selectSingleNode("autoLogin").getText(); - localPref.setAutoLogin(Boolean.parseBoolean(autoLogin)); - - String savePassword = plugin.selectSingleNode("savePassword").getText(); - localPref.setSavePassword(Boolean.parseBoolean(savePassword)); - - String password = plugin.selectSingleNode("password").getText(); - localPref.setPasswordForUser(username+"@"+server, password); - - SettingsManager.saveSettings(); - } - - // Delete settings File - settingsXML.delete(); - } - } - - /** - * Use DNS to lookup a KDC - * @param realm The realm to look up - * @return the KDC hostname - */ - private String getDnsKdc(String realm) { - //Assumption: the KDC will be found with the SRV record - // _kerberos._udp.$realm - try { - Hashtable env= new Hashtable<>(); - env.put("java.naming.factory.initial","com.sun.jndi.dns.DnsContextFactory"); - DirContext context = new InitialDirContext(env); - Attributes dnsLookup = context.getAttributes("_kerberos._udp."+realm, new String[]{"SRV"}); - - ArrayList priorities = new ArrayList<>(); - HashMap> records = new HashMap<>(); - for (Enumeration e = dnsLookup.getAll() ; e.hasMoreElements() ; ) { - Attribute record = (Attribute)e.nextElement(); - for (Enumeration e2 = record.getAll() ; e2.hasMoreElements() ; ) { - String sRecord = (String)e2.nextElement(); - String [] sRecParts = sRecord.split(" "); - Integer pri = Integer.valueOf(sRecParts[0]); - if(priorities.contains(pri)) { - List recs = records.get(pri); - if(recs == null) recs = new ArrayList<>(); - recs.add(sRecord); - } else { - priorities.add(pri); - List recs = new ArrayList<>(); - recs.add(sRecord); - records.put(pri,recs); - } - } - } - Collections.sort(priorities); - List l = records.get(priorities.get(0)); - String toprec = l.get(0); - String [] sRecParts = toprec.split(" "); - return sRecParts[3]; - } catch (NamingException e){ - return ""; - } - } - - protected String getLoginUsername() { - return loginUsername; - } - - protected void setLoginUsername(String loginUsername) { - this.loginUsername = loginUsername; - } - - protected String getLoginPassword() { - return loginPassword; - } - - protected void setLoginPassword(String loginPassword) { - this.loginPassword = loginPassword; - } - - protected String getLoginServer() { - return loginServer; - } - - protected void setLoginServer(String loginServer) { - this.loginServer = loginServer; - } - - protected ArrayList getUsernames() { - return _usernames; - } - - -} diff --git a/src/java/org/jivesoftware/LoginSettingDialog.java b/src/java/org/jivesoftware/LoginSettingDialog.java deleted file mode 100644 index c00e7934a..000000000 --- a/src/java/org/jivesoftware/LoginSettingDialog.java +++ /dev/null @@ -1,1219 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware; - -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.component.TitlePanel; -import org.jivesoftware.spark.component.WrappedLabel; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.JiveInfo; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -import javax.security.auth.Subject; -import javax.security.auth.login.Configuration; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; -import javax.swing.BorderFactory; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPasswordField; -import javax.swing.JTabbedPane; -import javax.swing.JTextField; -import javax.swing.JRadioButton; -import javax.swing.ButtonGroup; -import javax.swing.JFileChooser; -import javax.swing.JButton; -import javax.swing.UIManager; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.security.Principal; -import java.util.Properties; -import java.io.File; - -/** - * Allows users to configure startup options. - * - * @author Derek DeMoro - * @author Jay Kline - */ -public class LoginSettingDialog implements PropertyChangeListener { - - private LocalPreferences localPreferences; - - private JDialog optionsDialog; - private JOptionPane optionPane; - - private GeneralPanel generalPanel; - private ProxyPanel proxyPanel; - private PkiPanel pkiPanel; - private SsoPanel ssoPanel; - - /** - * Empty Constructor. - */ - public LoginSettingDialog() { - localPreferences = SettingsManager.getLocalPreferences(); - generalPanel = new GeneralPanel(); - proxyPanel = new ProxyPanel(); - ssoPanel = new SsoPanel(); - pkiPanel = new PkiPanel(); - } - - /** - * Invokes the OptionsDialog. - * - * @param owner - * the parent owner of this dialog. This is used for correct - * parenting. - * @return true if the options have been changed. - */ - public boolean invoke(JFrame owner) { - JTabbedPane tabbedPane = new JTabbedPane(); - TitlePanel titlePanel; - - // Create the title panel for this dialog - titlePanel = new TitlePanel( - Res.getString("title.advanced.connection.preferences"), "", - SparkRes.getImageIcon(SparkRes.BLANK_24x24), true); - - tabbedPane.addTab(Res.getString("tab.general"), generalPanel); - if (!Default.getBoolean(Default.PROXY_DISABLED)) - tabbedPane.addTab(Res.getString("tab.proxy"), proxyPanel); - if (!Default.getBoolean(Default.SSO_DISABLED)) - tabbedPane.addTab(Res.getString("tab.sso"), ssoPanel); - if (!Default.getBoolean(Default.PKI_DISABLED)) - tabbedPane.addTab(Res.getString("tab.pki"), pkiPanel); - - // Construct main panel w/ layout. - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(titlePanel, BorderLayout.NORTH); - - // The user should only be able to close this dialog. - Object[] options = { Res.getString("ok"), Res.getString("cancel"), - Res.getString("use.default") }; - optionPane = new JOptionPane(tabbedPane, JOptionPane.PLAIN_MESSAGE, - JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); - - mainPanel.add(optionPane, BorderLayout.CENTER); - - optionsDialog = new JDialog(owner, Res.getString("title.preferences"), - true); - optionsDialog.setContentPane(mainPanel); - optionsDialog.pack(); - - optionsDialog.setLocationRelativeTo(owner); - optionPane.addPropertyChangeListener(this); - - optionsDialog.setResizable(true); - optionsDialog.setVisible(true); - optionsDialog.toFront(); - optionsDialog.requestFocus(); - - return true; - } - - /** - * PropertyChangeEvent is called when the user either clicks the Cancel or - * OK button. - * - * @param e - * the property change event. - */ - public void propertyChange(PropertyChangeEvent e) { - String value = (String) optionPane.getValue(); - if (Res.getString("cancel").equals(value)) { - optionsDialog.setVisible(false); - } else if (Res.getString("ok").equals(value)) { - - boolean valid = generalPanel.validate_settings(); - valid = valid && proxyPanel.validate_settings(); - valid = valid && ssoPanel.validate_settings(); - valid = valid && pkiPanel.validate_settings(); - - if (valid) { - generalPanel.saveSettings(); - proxyPanel.saveSettings(); - ssoPanel.saveSettings(); - pkiPanel.saveSettings(); - SettingsManager.saveSettings(); - optionsDialog.setVisible(false); - } else { - optionPane.removePropertyChangeListener(this); - optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE); - optionPane.addPropertyChangeListener(this); - } - } else { - // Some unknown operation happened - optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE); - } - } - - /** - * Internal class to set General settings - */ - private class GeneralPanel extends JPanel implements ActionListener { - private static final long serialVersionUID = -3628642430429935901L; - private JCheckBox autoDiscoverBox = new JCheckBox(); - private JLabel portLabel = new JLabel(); - private JTextField portField = new JTextField(); - private JLabel xmppHostLabel = new JLabel(); - private JTextField xmppHostField = new JTextField(); - private JLabel timeOutLabel = new JLabel(); - private JTextField timeOutField = new JTextField(); - private JLabel resourceLabel = new JLabel(); - private JTextField resourceField = new JTextField(); - private JCheckBox useHostnameAsResourceBox = new JCheckBox(); - private JCheckBox useVersionAsResourceBox = new JCheckBox(); - private JCheckBox autoLoginBox = new JCheckBox(); - private JCheckBox useSSLBox = new JCheckBox(); - private JCheckBox compressionBox = new JCheckBox(); - private JCheckBox debuggerBox = new JCheckBox(); - - public GeneralPanel() { - ResourceUtils.resLabel(portLabel, portField, - Res.getString("label.port")); - ResourceUtils.resLabel(timeOutLabel, timeOutField, - Res.getString("label.response.timeout")); - ResourceUtils.resButton(autoLoginBox, - Res.getString("label.auto.login")); - ResourceUtils.resButton(useSSLBox, Res.getString("label.old.ssl")); - ResourceUtils.resLabel(xmppHostLabel, xmppHostField, - Res.getString("label.host")); - ResourceUtils.resButton(autoDiscoverBox, - Res.getString("checkbox.auto.discover.port")); - ResourceUtils.resLabel(resourceLabel, resourceField, - Res.getString("label.resource")); - ResourceUtils.resButton(useHostnameAsResourceBox, - Res.getString("checkbox.use.hostname.as.resource")); - ResourceUtils.resButton(useVersionAsResourceBox, - Res.getString("checkbox.use.version.as.resource")); - ResourceUtils.resButton(compressionBox, - Res.getString("checkbox.use.compression")); - ResourceUtils.resButton(debuggerBox, - Res.getString("checkbox.use.debugger.on.startup")); - - portField.setText(Integer.toString(localPreferences.getXmppPort())); - timeOutField - .setText(Integer.toString(localPreferences.getTimeOut())); - autoLoginBox.setSelected(localPreferences.isAutoLogin()); - useSSLBox.setSelected(localPreferences.isSSL()); - xmppHostField.setText(localPreferences.getXmppHost()); - resourceField.setText(localPreferences.getResource()); - - useHostnameAsResourceBox.addActionListener(this); - useHostnameAsResourceBox.setSelected(localPreferences.isUseHostnameAsResource()); - updateResourceHostname(); - - useVersionAsResourceBox.addActionListener(this); - useVersionAsResourceBox.setSelected(localPreferences.isUseVersionAsResource()); - updateResourceVersion(); - - autoDiscoverBox.addActionListener(this); - - autoDiscoverBox.setSelected(!localPreferences - .isHostAndPortConfigured()); - updateAutoDiscovery(); - - compressionBox.setSelected(localPreferences.isCompressionEnabled()); - - debuggerBox.setSelected(localPreferences.isDebuggerEnabled()); - - final JPanel connectionPanel = new JPanel(); - connectionPanel.setLayout(new GridBagLayout()); - connectionPanel.setBorder(BorderFactory.createTitledBorder(Res - .getString("group.connection"))); - - setLayout(new GridBagLayout()); - add(autoDiscoverBox, new GridBagConstraints(0, 0, 2, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - connectionPanel.add(xmppHostLabel, new GridBagConstraints(0, 0, 2, - 1, 0.0, 0.0, GridBagConstraints.WEST, - GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - connectionPanel.add(xmppHostField, new GridBagConstraints(2, 0, 1, - 1, 0.0, 0.0, GridBagConstraints.WEST, - GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 200, 0)); - connectionPanel.add(portLabel, new GridBagConstraints(0, 1, 2, 1, - 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - connectionPanel.add(portField, new GridBagConstraints(2, 1, 1, 1, - 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 50, 0)); - add(connectionPanel, new GridBagConstraints(0, 1, 3, 1, 1.0, 1.0, - GridBagConstraints.WEST, GridBagConstraints.BOTH, - new Insets(5, 5, 5, 5), 0, 0)); - if (Default.getBoolean(Default.HOSTNAME_AS_RESOURCE) == Default.getBoolean(Default.VERSION_AS_RESOURCE)) { - add(resourceLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - add(resourceField, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 100, 0)); - add(useHostnameAsResourceBox, new GridBagConstraints(0, 3, 2, 1, 0.0, 1.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - add(useVersionAsResourceBox, new GridBagConstraints(0, 4, 2, 1, 0.0, 1.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - } - add(timeOutLabel, new GridBagConstraints(0, 5, 1, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - add(timeOutField, new GridBagConstraints(1, 5, 1, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 50, 0)); - add(useSSLBox, new GridBagConstraints(0, 6, 2, 1, 0.0, 1.0, - GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(5, 5, 5, 5), 0, 0)); - add(compressionBox, new GridBagConstraints(0, 7, 2, 1, 0.0, 1.0, - GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(5, 5, 5, 5), 0, 0)); - add(debuggerBox, new GridBagConstraints(0, 8, 2, 1, 0.0, 1.0, - GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(5, 5, 5, 5), 0, 0)); - } - - /** - * Updates local preferences with auto discovery settings. - */ - private void updateAutoDiscovery() { - boolean isSelected = autoDiscoverBox.isSelected(); - xmppHostField.setEnabled(!isSelected); - portField.setEnabled(!isSelected); - localPreferences.setHostAndPortConfigured(!isSelected); - SettingsManager.saveSettings(); - } - - /** - * Updates resource settings. - */ - private void updateResourceHostname() { - boolean isSelected = useHostnameAsResourceBox.isSelected(); - try { - if (isSelected) { - String resource = InetAddress.getLocalHost().getHostName(); - resourceField.setText(resource); - } - resourceField.setEnabled(!isSelected); - } catch (UnknownHostException e) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane - .showMessageDialog(optionsDialog, - Res.getString("message.unable.to.use.hostname.as.resource"), - Res.getString("title.error"), - JOptionPane.ERROR_MESSAGE); - } - //localPreferences.setHostAndPortConfigured(!isSelected); - SettingsManager.saveSettings(); - } - - private void updateResourceVersion() { - boolean isSelected = useVersionAsResourceBox.isSelected(); - if (isSelected) { - String resource = Default.getString(Default.APPLICATION_NAME) + " " + JiveInfo.getVersion() + "." + Default.getString(Default.BUILD_NUMBER); - resourceField.setText(resource); - } - resourceField.setEnabled(!isSelected); - //localPreferences.setHostAndPortConfigured(!isSelected); - SettingsManager.saveSettings(); - } - - public void actionPerformed(ActionEvent e) { - if (e.getSource() == autoDiscoverBox) { - updateAutoDiscovery(); - } - else if (e.getSource() == useHostnameAsResourceBox) { - updateResourceHostname(); - } - else if (e.getSource() == useVersionAsResourceBox) { - updateResourceVersion(); - } - } - - public boolean validate_settings() { - String timeOut = timeOutField.getText(); - String port = portField.getText(); - String resource = resourceField.getText(); - - boolean valid = true; - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - - try { - Integer.valueOf(timeOut); - } catch (NumberFormatException numberFormatException) { - JOptionPane - .showMessageDialog(optionsDialog, - Res.getString("message.supply.valid.timeout"), - Res.getString("title.error"), - JOptionPane.ERROR_MESSAGE); - timeOutField.requestFocus(); - valid = false; - } - - try { - Integer.valueOf(port); - } catch (NumberFormatException numberFormatException) { - JOptionPane - .showMessageDialog(optionsDialog, - Res.getString("message.supply.valid.port"), - Res.getString("title.error"), - JOptionPane.ERROR_MESSAGE); - portField.requestFocus(); - valid = false; - } - - if (!ModelUtil.hasLength(resource)) { - JOptionPane - .showMessageDialog(optionsDialog, - Res.getString("message.supply.resource"), - Res.getString("title.error"), - JOptionPane.ERROR_MESSAGE); - resourceField.requestFocus(); - valid = false; - } - - return valid; - } - - public void saveSettings() { - - localPreferences - .setTimeOut(Integer.parseInt(timeOutField.getText())); - localPreferences.setXmppPort(Integer.parseInt(portField.getText())); - localPreferences.setSSL(useSSLBox.isSelected()); - localPreferences.setXmppHost(xmppHostField.getText()); - localPreferences.setCompressionEnabled(compressionBox.isSelected()); - localPreferences.setDebuggerEnabled(debuggerBox.isSelected()); - localPreferences.setResource(resourceField.getText()); - localPreferences.setUseHostnameAsResource(useHostnameAsResourceBox.isSelected()); - localPreferences.setUseVersionAsResource(useVersionAsResourceBox.isSelected()); - SettingsManager.saveSettings(); - } - } - - /** - * Internal class to allow setting of proxies within Spark. - */ - private class ProxyPanel extends JPanel { - private static final long serialVersionUID = 4652063977305639878L; - private JCheckBox useProxyBox = new JCheckBox(); - private JComboBox protocolBox = new JComboBox(); - private JTextField hostField = new JTextField(); - private JTextField portField = new JTextField(); - private JTextField usernameField = new JTextField(); - private JPasswordField passwordField = new JPasswordField(); - - /** - * Construct UI. - */ - public ProxyPanel() { - JLabel protocolLabel = new JLabel(); - JLabel hostLabel = new JLabel(); - JLabel portLabel = new JLabel(); - JLabel usernameLabel = new JLabel(); - JLabel passwordLabel = new JLabel(); - - protocolBox.addItem("SOCKS"); - protocolBox.addItem("HTTP"); - - // Add ResourceUtils - ResourceUtils.resButton(useProxyBox, - Res.getString("checkbox.use.proxy.server")); - ResourceUtils.resLabel(protocolLabel, protocolBox, - Res.getString("label.protocol")); - ResourceUtils.resLabel(hostLabel, hostField, - Res.getString("label.host")); - ResourceUtils.resLabel(portLabel, portField, - Res.getString("label.port")); - ResourceUtils.resLabel(usernameLabel, usernameField, - Res.getString("label.username")); - ResourceUtils.resLabel(passwordLabel, passwordField, - Res.getString("label.password")); - - setLayout(new GridBagLayout()); - add(useProxyBox, new GridBagConstraints(0, 0, 2, 1, 1.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - add(protocolLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - add(protocolBox, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(5, 5, 5, 5), 0, 0)); - add(hostLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - add(hostField, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(5, 5, 5, 5), 0, 0)); - add(portLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - add(portField, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(5, 5, 5, 5), 0, 0)); - add(usernameLabel, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - add(usernameField, new GridBagConstraints(1, 4, 1, 1, 1.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(5, 5, 5, 5), 0, 0)); - add(passwordLabel, new GridBagConstraints(0, 5, 1, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - add(passwordField, new GridBagConstraints(1, 5, 1, 1, 1.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(5, 5, 5, 5), 0, 0)); - - useProxyBox.addActionListener( e -> enableFields(useProxyBox.isSelected()) ); - - // Check localSettings - if (localPreferences.isProxyEnabled()) { - useProxyBox.setSelected(true); - } - - enableFields(useProxyBox.isSelected()); - - if (ModelUtil.hasLength(localPreferences.getHost())) { - hostField.setText(localPreferences.getHost()); - } - - if (ModelUtil.hasLength(localPreferences.getPort())) { - portField.setText(localPreferences.getPort()); - } - - if (ModelUtil.hasLength(localPreferences.getProxyPassword())) { - passwordField.setText(localPreferences.getProxyPassword()); - } - - if (ModelUtil.hasLength(localPreferences.getProxyUsername())) { - usernameField.setText(localPreferences.getProxyUsername()); - } - - if (ModelUtil.hasLength(localPreferences.getProtocol())) { - protocolBox.setSelectedItem(localPreferences.getProtocol()); - } - - if(Default.getString("PROXY_PROTOCOL").length()>0) - { - protocolBox.setSelectedItem(Default.getString("PROXY_PROTOCOL")); - protocolBox.setEnabled(false); - useProxyBox.setSelected(true); - useProxyBox.setVisible(false); - } - if(Default.getString("PROXY_HOST").length()>0) - { - hostField.setText(Default.getString("PROXY_HOST")); - hostField.setEnabled(false); - useProxyBox.setSelected(true); - useProxyBox.setVisible(false); - } - if(Default.getString("PROXY_PORT").length()>0) - { - portField.setText(Default.getString("PROXY_PORT")); - portField.setEnabled(false); - } - - } - - /** - * Enables the fields of the proxy panel. - * - * @param enable - * true if all fields should be enabled, otherwise false. - */ - private void enableFields(boolean enable) { - Component[] comps = getComponents(); - for (Component comp1 : comps) { - if (comp1 instanceof JTextField || comp1 instanceof JComboBox) { - JComponent comp = (JComponent) comp1; - comp.setEnabled(enable); - } - } - } - - /** - * Returns true if a proxy is set. - * - * @return true if a proxy is set. - */ - //TODO REMOVE - @SuppressWarnings("unused") - public boolean useProxy() { - return useProxyBox.isSelected(); - } - - /** - * Returns the protocol to use for this proxy. - * - * @return the protocol. - */ - public String getProtocol() { - return (String) protocolBox.getSelectedItem(); - } - - /** - * Returns the host to use for this proxy. - * - * @return the host. - */ - public String getHost() { - return hostField.getText(); - } - - /** - * Returns the port to use with this proxy. - * - * @return the port to use. - */ - public String getPort() { - return portField.getText(); - } - - /** - * Returns the username to use with this proxy. - * - * @return the username. - */ - public String getUsername() { - return usernameField.getText(); - } - - /** - * Returns the password to use with this proxy. - * - * @return the password. - */ - public String getPassword() { - return new String(passwordField.getPassword()); - } - - public boolean validate_settings() { - boolean valid = true; - - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - - if (useProxyBox.isSelected()) { - try { - Integer.valueOf(portField.getText()); - } catch (NumberFormatException numberFormatException) { - JOptionPane.showMessageDialog(optionsDialog, - Res.getString("message.supply.valid.port"), - Res.getString("title.error"), - JOptionPane.ERROR_MESSAGE); - portField.requestFocus(); - valid = false; - } - - if (!ModelUtil.hasLength(hostField.getText())) { - JOptionPane.showMessageDialog(optionsDialog, - Res.getString("message.supply.valid.host"), - Res.getString("title.error"), - JOptionPane.ERROR_MESSAGE); - hostField.requestFocus(); - valid = false; - } - } - return valid; - } - - /** - * Persist the proxy settings to local preferences. - */ - public void saveSettings() { - localPreferences.setProxyEnabled(useProxyBox.isSelected()); - if (ModelUtil.hasLength(getProtocol())) { - localPreferences.setProtocol(getProtocol()); - } - - if (ModelUtil.hasLength(getHost())) { - localPreferences.setHost(getHost()); - } - - if (ModelUtil.hasLength(getPort())) { - localPreferences.setPort(getPort()); - } - if(getUsername().equals("") || getUsername()== null) - { - localPreferences.setProxyUsername(""); - } - if (ModelUtil.hasLength(getUsername())) { - localPreferences.setProxyUsername(getUsername()); - } - if(getPassword().equals("") || getPassword()== null) - { - localPreferences.setProxyPassword(""); - } - - - if (ModelUtil.hasLength(getPassword())) { - localPreferences.setProxyPassword(getPassword()); - } - - if (!localPreferences.isProxyEnabled()) { - Properties props = System.getProperties(); - props.remove("socksProxyHost"); - props.remove("socksProxyPort"); - props.remove("http.proxyHost"); - props.remove("http.proxyPort"); - props.remove("http.proxySet"); - } else { - String host = localPreferences.getHost(); - String port = localPreferences.getPort(); - String protocol = localPreferences.getProtocol(); - - boolean isValid = ModelUtil.hasLength(host) - && ModelUtil.hasLength(port); - - if (isValid) { - if (protocol.equals("SOCKS")) { - System.setProperty("socksProxyHost", host); - System.setProperty("socksProxyPort", port); - } else { - System.setProperty("http.proxySet", "true"); - - // Set https settings - System.setProperty("https.proxyHost", host); - System.setProperty("https.proxyPort", port); - - // Set http settings - System.setProperty("http.proxyHost", host); - System.setProperty("http.proxyPort", port); - } - } else { - localPreferences.setProxyEnabled(false); - } - } - SettingsManager.saveSettings(); - } - } - - /** - * Internal class to set SSO settings - */ - private class SsoPanel extends JPanel implements ActionListener { - private static final long serialVersionUID = 3661245275095536202L; - private JCheckBox useSSOBox = new JCheckBox(); - private JPanel settingsPanel = new JPanel(); - private JCheckBox showAdvBox = new JCheckBox(); - private JLabel ssoRealmLabel = new JLabel(); - private JTextField ssoRealmField = new JTextField(); - private JLabel ssoKDCLabel = new JLabel(); - private JTextField ssoKDCField = new JTextField(); - private JLabel ssoMethodFileLabel = new JLabel(); - private JRadioButton ssoMethodFileRadio = new JRadioButton(); - private JLabel ssoMethodDNSLabel = new JLabel(); - private JRadioButton ssoMethodDNSRadio = new JRadioButton(); - private JLabel ssoMethodManualLabel = new JLabel(); - private JRadioButton ssoMethodManualRadio = new JRadioButton(); - private ButtonGroup ssoMethodRadio = new ButtonGroup(); - - public SsoPanel() { - ResourceUtils.resButton(useSSOBox, - Res.getString("title.advanced.connection.usesso")); - ResourceUtils.resButton(showAdvBox, - Res.getString("title.advanced.connection.preferences")); - - useSSOBox.addActionListener(this); - showAdvBox.addActionListener(this); - - final WrappedLabel wrappedLabel = new WrappedLabel(); - String principalName = null; - try { - principalName = getPrincipalName(); - } catch (Exception e) { - // Ignore - } - - if (ModelUtil.hasLength(principalName)) { - wrappedLabel.setText(Res.getString("title.advanced.connection.sso.account",principalName)); - } else { - wrappedLabel.setText(Res.getString("title.advanced.connection.sso.noprincipal")); - } - wrappedLabel.setBackground(Color.white); - - String method = localPreferences.getSSOMethod(); - if (ModelUtil.hasLength(method)) { - if (method.equals("file")) { - ssoMethodFileRadio.setSelected(true); - } else if (method.equals("dns")) { - ssoMethodDNSRadio.setSelected(true); - } else if (method.equals("manual")) { - ssoMethodManualRadio.setSelected(true); - } else { - ssoMethodFileRadio.setSelected(true); - } - } else { - ssoMethodFileRadio.setSelected(true); - } - - if (ModelUtil.hasLength(localPreferences.getSSORealm())) { - ssoRealmField.setText(localPreferences.getSSORealm()); - } - if (ModelUtil.hasLength(localPreferences.getSSOKDC())) { - ssoKDCField.setText(localPreferences.getSSOKDC()); - } - - ssoMethodFileLabel.setText(Res.getString("checkbox.use.krbconf")); - ssoMethodDNSLabel.setText(Res.getString("checkbox.use.krb.dns")); - ssoMethodManualLabel.setText(Res - .getString("checkbox.use.specify.below")); - ssoRealmLabel.setText(" " + Res.getString("label.krb.realm")); - ssoKDCLabel.setText(" " + Res.getString("label.krb.kdc")); - - ssoMethodRadio.add(ssoMethodFileRadio); - ssoMethodRadio.add(ssoMethodDNSRadio); - ssoMethodRadio.add(ssoMethodManualRadio); - - useSSOBox.setSelected(localPreferences.isSSOEnabled()); - - ssoMethodFileRadio.setEnabled(localPreferences.isSSOEnabled()); - ssoMethodDNSRadio.setEnabled(localPreferences.isSSOEnabled()); - ssoMethodManualRadio.setEnabled(localPreferences.isSSOEnabled()); - ssoRealmField.setEnabled(localPreferences.isSSOEnabled()); - ssoKDCField.setEnabled(localPreferences.isSSOEnabled()); - - showAdvBox.setSelected(localPreferences.getSSOAdv()); - settingsPanel.setVisible(localPreferences.getSSOAdv()); - - setLayout(new GridBagLayout()); - add(useSSOBox, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, - GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - add(showAdvBox, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, - GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - add(wrappedLabel, - new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0, - GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, - 5), 0, 0)); - settingsPanel.setLayout(new GridBagLayout()); - settingsPanel.add(ssoMethodFileLabel, new GridBagConstraints(0, 0, - 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, - GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - settingsPanel.add(ssoMethodFileRadio, - new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, - GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, - 5), 0, 0)); - settingsPanel.add(ssoMethodDNSLabel, new GridBagConstraints(0, 1, - 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, - GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - settingsPanel.add(ssoMethodDNSRadio, - new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, - GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, - 5), 0, 0)); - settingsPanel.add(ssoMethodManualLabel, new GridBagConstraints(0, - 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, - GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - settingsPanel.add(ssoMethodManualRadio, - new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, - GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, - 5), 0, 0)); - settingsPanel.add(ssoRealmLabel, new GridBagConstraints(0, 3, 1, 1, - 0.0, 0.0, GridBagConstraints.NORTHWEST, - GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - settingsPanel.add(ssoRealmField, - new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0, - GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, - 5), 0, 0)); - settingsPanel.add(ssoKDCLabel, new GridBagConstraints(0, 4, 1, 1, - 0.0, 0.0, GridBagConstraints.NORTHWEST, - GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - settingsPanel.add(ssoKDCField, - new GridBagConstraints(1, 5, 1, 1, 0.0, 0.0, - GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, - 5), 0, 0)); - add(settingsPanel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, - GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 100, - 0)); - - } - - /** - * Returns the principal name if one exists. - * - * @return the name (ex. derek) of the principal. - * @throws Exception - * thrown if a Principal was not found. - */ - private String getPrincipalName() throws Exception { - if (localPreferences.getDebug()) { - System.setProperty("java.security.krb5.debug", "true"); - } - System.setProperty("javax.security.auth.useSubjectCredsOnly", - "false"); - GSSAPIConfiguration config = new GSSAPIConfiguration(false); - Configuration.setConfiguration(config); - - LoginContext lc; - try { - lc = new LoginContext("com.sun.security.jgss.krb5.initiate"); - lc.login(); - } catch (LoginException le) { - Log.debug(le.getMessage()); - return null; - } - - Subject mySubject = lc.getSubject(); - - for (Principal p : mySubject.getPrincipals()) { - String name = p.getName(); - int indexOne = name.indexOf("@"); - if (indexOne != -1) { - return name; - } - } - return null; - } - - public void actionPerformed(ActionEvent e) { - if (e.getSource() == useSSOBox) { - ssoMethodFileRadio.setEnabled(useSSOBox.isSelected()); - ssoMethodDNSRadio.setEnabled(useSSOBox.isSelected()); - ssoMethodManualRadio.setEnabled(useSSOBox.isSelected()); - ssoRealmField.setEnabled(useSSOBox.isSelected()); - ssoKDCField.setEnabled(useSSOBox.isSelected()); - } else if (e.getSource() == showAdvBox) { - settingsPanel.setVisible(showAdvBox.isSelected()); - } - } - - public boolean validate_settings() { - - boolean valid = true; - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - - if (useSSOBox.isSelected() && showAdvBox.isSelected()) { - if (ssoMethodManualRadio.isSelected()) { - if (!ModelUtil.hasLength(ssoRealmField.getText())) { - JOptionPane.showMessageDialog(optionsDialog, - "You must specify a realm", - Res.getString("title.error"), - JOptionPane.ERROR_MESSAGE); - ssoRealmField.requestFocus(); - valid = false; - } - if (!ModelUtil.hasLength(ssoKDCField.getText())) { - JOptionPane.showMessageDialog(optionsDialog, - "You must specify a KDC", - Res.getString("title.error"), - JOptionPane.ERROR_MESSAGE); - ssoKDCField.requestFocus(); - valid = false; - } - } - } - - return valid; - } - - public void saveSettings() { - localPreferences.setSSOEnabled(useSSOBox.isSelected()); - if (ssoMethodFileRadio.isSelected()) { - localPreferences.setSSOMethod("file"); - } else if (ssoMethodDNSRadio.isSelected()) { - localPreferences.setSSOMethod("dns"); - } else if (ssoMethodManualRadio.isSelected()) { - localPreferences.setSSOMethod("manual"); - localPreferences.setSSORealm(ssoRealmField.getText()); - localPreferences.setSSOKDC(ssoKDCField.getText()); - } else { - localPreferences.setSSOMethod("file"); - } - SettingsManager.saveSettings(); - } - } - - /** - * Internal class to set PKI settings - */ - - private class PkiPanel extends JPanel implements ActionListener { - private static final long serialVersionUID = 2872543055208753622L; - private JLabel usePKILabel = new JLabel(); - private JCheckBox usePKIBox = new JCheckBox(); - private JLabel pkiStoreLabel = new JLabel(); - private JComboBox pkiStore = new JComboBox(); - private JFileChooser fileChooser = new JFileChooser(); - private JButton fileButton = new JButton(); - private JTextField fileField = new JTextField(); - private JPanel filePanel = new JPanel(); - private JLabel trustStorePasswordLabel = new JLabel(); - private JPasswordField trustStorePassword = new JPasswordField(); - private JTextField trustStoreField = new JTextField(); - private JButton trustStoreButton = new JButton(); - private JPanel trustStorePanel = new JPanel(); - - public PkiPanel() { - ResourceUtils.resButton(usePKIBox, - Res.getString("checkbox.use.pki.authentication")); - ResourceUtils.resLabel(pkiStoreLabel, pkiStore, - Res.getString("label.which.pki.method")); - ResourceUtils.resButton(fileButton, - Res.getString("label.choose.file")); - ResourceUtils.resButton(trustStoreButton, - Res.getString("label.choose.file")); - ResourceUtils.resLabel(trustStorePasswordLabel, trustStorePassword, - Res.getString("label.trust.store.password")); - - pkiStore.addItem("Java Keystore"); - pkiStore.addItem("PKCS#11"); - // pkiStore.addItem("X.509 PEM File"); - pkiStore.addItem("Apple KeyChain"); - - usePKIBox.setSelected(localPreferences.isPKIEnabled()); - - if (ModelUtil.hasLength(localPreferences.getPKIStore())) { - if (localPreferences.getPKIStore().equals("PKCS11")) { - pkiStore.setSelectedItem("PKCS#11"); - if (ModelUtil - .hasLength(localPreferences.getPKCS11Library())) { - fileField.setText(localPreferences.getPKCS11Library()); - } else { - fileField.setText(""); - } - } else if (localPreferences.getPKIStore().equals("X509")) { - pkiStore.setSelectedItem("X.509 PEM File"); - // if(ModelUtil.hasLength(localPreferences.getPEMFile())) { - // fileField.setText(localPreferences.getPEMFile()); - // } - // else { - fileField.setText(""); - // } - } else if (localPreferences.getPKIStore().equals( - "Apple KeyChain")) { - fileField.setText(""); - } else { - pkiStore.setSelectedItem("Java Keystore"); - if (ModelUtil.hasLength(localPreferences.getJKSPath())) { - fileField.setText(localPreferences.getJKSPath()); - } else { - fileField.setText(""); - } - } - } else { - pkiStore.setSelectedItem("Java Keystore"); - if (ModelUtil.hasLength(localPreferences.getJKSPath())) { - fileField.setText(localPreferences.getJKSPath()); - } else { - fileField.setText(""); - } - } - - if (ModelUtil.hasLength(localPreferences.getTrustStorePath())) { - trustStoreField.setText(localPreferences.getTrustStorePath()); - } - - if (ModelUtil.hasLength(localPreferences.getTrustStorePassword())) { - trustStorePassword.setText(localPreferences - .getTrustStorePassword()); - } - - pkiStore.setEnabled(usePKIBox.isSelected()); - filePanel.setEnabled(usePKIBox.isSelected()); - fileField.setEnabled(usePKIBox.isSelected()); - fileButton.setEnabled(usePKIBox.isSelected()); - - setLayout(new GridBagLayout()); - - add(usePKIBox, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, - GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - add(usePKILabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, - GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - add(pkiStoreLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, - GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - add(pkiStore, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, - GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - - filePanel.setLayout(new GridBagLayout()); - filePanel.setBorder(BorderFactory.createTitledBorder(Res - .getString("label.keystore.location"))); - filePanel.add(fileField, new GridBagConstraints(0, 0, 1, 1, 0.0, - 0.0, GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 100, - 0)); - filePanel.add(fileButton, new GridBagConstraints(1, 0, 1, 1, 0.0, - 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - add(filePanel, new GridBagConstraints(0, 2, 2, 1, 0.0, 0.0, - GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 150, - 0)); - - trustStorePanel.setLayout(new GridBagLayout()); - trustStorePanel.setBorder(BorderFactory.createTitledBorder(Res - .getString("label.truststore.location"))); - trustStorePanel.add(trustStoreField, new GridBagConstraints(0, 0, - 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 100, - 0)); - trustStorePanel.add(trustStoreButton, new GridBagConstraints(1, 0, - 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, - GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - trustStorePanel.add(trustStorePasswordLabel, - new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, - GridBagConstraints.NORTHWEST, - GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, - 0)); - trustStorePanel.add(trustStorePassword, new GridBagConstraints(1, - 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 100, - 0)); - add(trustStorePanel, new GridBagConstraints(0, 3, 2, 1, 0.0, 0.0, - GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 150, - 0)); - - usePKIBox.addActionListener(this); - pkiStore.addActionListener(this); - fileButton.addActionListener(this); - trustStoreButton.addActionListener(this); - - } - - public void actionPerformed(ActionEvent e) { - - if (e.getSource() == usePKIBox) { - pkiStore.setEnabled(usePKIBox.isSelected()); - filePanel.setEnabled(usePKIBox.isSelected()); - fileField.setEnabled(usePKIBox.isSelected()); - fileButton.setEnabled(usePKIBox.isSelected()); - } else if (e.getSource() == pkiStore) { - if ((pkiStore.getSelectedItem()).equals("PKCS#11")) { - filePanel.setBorder(BorderFactory.createTitledBorder(Res - .getString("label.pkcs.library.file"))); - if (ModelUtil - .hasLength(localPreferences.getPKCS11Library())) { - fileField.setText(localPreferences.getPKCS11Library()); - } else { - fileField.setText(""); - } - } else if ((pkiStore.getSelectedItem()) - .equals("X.509 PEM File")) { - filePanel.setBorder(BorderFactory.createTitledBorder(Res - .getString("label.x509.certificate"))); - // if(ModelUtil.hasLength(localPreferences.getPEMFile())) { - // fileField.setText(localPreferences.getPEMFile()); - // } else { - // fileField.setText(""); - // } - } else if ((pkiStore.getSelectedItem()) - .equals("Apple KeyChain")) { - filePanel.setBorder(BorderFactory.createTitledBorder(Res - .getString("label.apple.keychain"))); - } else { - filePanel.setBorder(BorderFactory.createTitledBorder(Res - .getString("label.keystore.location"))); - if (ModelUtil.hasLength(localPreferences.getJKSPath())) { - fileField.setText(localPreferences.getJKSPath()); - } else { - fileField.setText(""); - } - } - } else if (e.getSource() == fileButton) { - int retval = fileChooser.showOpenDialog(this); - if (retval == JFileChooser.APPROVE_OPTION) { - File file = fileChooser.getSelectedFile(); - fileField.setText(file.getAbsolutePath()); - } - } else if (e.getSource() == trustStoreButton) { - int retval = fileChooser.showOpenDialog(this); - if (retval == JFileChooser.APPROVE_OPTION) { - File file = fileChooser.getSelectedFile(); - trustStoreField.setText(file.getAbsolutePath()); - } - } - } - - public boolean validate_settings() { - - boolean valid = true; - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - - if (usePKIBox.isSelected()) { - if (!ModelUtil.hasLength(fileField.getText())) { - JOptionPane.showMessageDialog(optionsDialog, - "You must specify a file location", - Res.getString("title.error"), - JOptionPane.ERROR_MESSAGE); - fileField.requestFocus(); - valid = false; - } - } - return valid; - } - - public void saveSettings() { - - localPreferences.setPKIEnabled(usePKIBox.isSelected()); - localPreferences.setPKIStore((String) pkiStore.getSelectedItem()); - if ((pkiStore.getSelectedItem()).equals("PKCS#11")) { - localPreferences.setPKIStore("PKCS11"); - localPreferences.setPKCS11Library(fileField.getText()); - } else if ((pkiStore.getSelectedItem()).equals("X.509 Certificate")) { - localPreferences.setPKIStore("X509"); - // localPreferences.setPEMFile(fileField.getText()); - } else if ((pkiStore.getSelectedItem()).equals("Apple KeyChain")) { - localPreferences.setPKIStore("Apple"); - } else { - localPreferences.setPKIStore("JKS"); - localPreferences.setJKSPath(fileField.getText()); - } - localPreferences.setTrustStorePath(trustStoreField.getText()); - localPreferences.setTrustStorePassword(new String( - trustStorePassword.getPassword())); - SettingsManager.saveSettings(); - } - } -} diff --git a/src/java/org/jivesoftware/MainWindow.java b/src/java/org/jivesoftware/MainWindow.java deleted file mode 100644 index 50ac25972..000000000 --- a/src/java/org/jivesoftware/MainWindow.java +++ /dev/null @@ -1,969 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.awt.event.WindowFocusListener; -import java.io.File; -import java.io.IOException; -import java.util.HashSet; -import java.util.Set; -import java.util.TimerTask; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JEditorPane; -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JTextPane; -import javax.swing.JToolBar; -import javax.swing.UIManager; -import javax.swing.event.HyperlinkEvent; - -import org.jivesoftware.launcher.Startup; -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.AbstractXMPPConnection; -import org.jivesoftware.smack.SmackConfiguration; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.ui.ChatFrame; -import org.jivesoftware.spark.ui.RawPacketSender; -import org.jivesoftware.spark.util.BrowserLauncher; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingTimerTask; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.URLFileSystem; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.alerts.InputTextAreaDialog; -import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettings; -import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettingsManager; -import org.jivesoftware.sparkimpl.settings.JiveInfo; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jivesoftware.sparkimpl.updater.CheckUpdates; - -/** - * The MainWindow class acts as both the DockableHolder and the proxy - * to the Workspace in Spark. - * - * @version 1.0, 03/12/14 - */ -public final class MainWindow extends ChatFrame implements ActionListener { - private static final long serialVersionUID = -6062104959613603510L; - - private final Set listeners = new HashSet<>(); - - private final JMenu connectMenu = new JMenu(); - private final JMenu contactsMenu = new JMenu(); - private final JMenu actionsMenu = new JMenu(); - private final JMenu pluginsMenu = new JMenu(); - private final JMenu helpMenu = new JMenu(); - - private JMenuItem preferenceMenuItem; - private JCheckBoxMenuItem alwaysOnTopItem; - - private final JMenuItem menuAbout = new JMenuItem(SparkRes.getImageIcon(SparkRes.INFORMATION_IMAGE)); - private final JMenuItem sparkforumItem = new JMenuItem(); - - private final JMenuBar mainWindowBar = new JMenuBar(); - - private boolean focused; - - private JToolBar topToolbar = new JToolBar(); - - private JSplitPane splitPane; - - private JEditorPane aboutBoxPane; - - private static MainWindow singleton; - private static final Object LOCK = new Object(); - - /** - * Returns the singleton instance of MainWindow, - * creating it if necessary. - *

      - * - * @return the singleton instance of MainWindow - */ - public static MainWindow getInstance() { - // Synchronize on LOCK to ensure that we don't end up creating - // two singletons. - - - synchronized (LOCK) { - if (null == singleton) { - MainWindow controller = new MainWindow(Default.getString(Default.APPLICATION_NAME), SparkManager.getApplicationImage()); - singleton = controller; - } - } - return singleton; - } - - - /** - * Constructs the UI for the MainWindow. The MainWindow UI is the container for the - * entire Spark application. - * - * @param title the title of the frame. - * @param icon the icon used in the frame. - */ - private MainWindow(String title, ImageIcon icon) { - - - // Initialize and dock the menus - buildMenu(); - - - - // Add Workspace Container - getContentPane().setLayout(new BorderLayout()); - - LayoutSettings settings = LayoutSettingsManager.getLayoutSettings(); - if (settings.getMainWindowX() == 0 && settings.getMainWindowY() == 0) { - // Use default settings. - setSize(300, 500); - GraphicUtils.centerWindowOnScreen(this); - } - else { - setBounds(settings.getMainWindowX(), settings.getMainWindowY(), settings.getMainWindowWidth(), settings.getMainWindowHeight()); - } - - // Add menubar - this.setJMenuBar(mainWindowBar); - this.getContentPane().add(topToolbar, BorderLayout.NORTH); - - setTitle(title); - setIconImage(icon.getImage()); - - - - // Setup WindowListener to be the proxy to the actual window listener - // which cannot normally be used outside of the Window component because - // of protected access. - addWindowListener(new WindowAdapter() { - - /** - * This event fires when the window has become active. - * - * @param e WindowEvent is not used. - */ - public void windowActivated(WindowEvent e) { - fireWindowActivated(); - } - - /** - * Invoked when a window is de-activated. - */ - public void windowDeactivated(WindowEvent e) { - } - - /** - * This event fires whenever a user minimizes the window - * from the toolbar. - * - * @param e WindowEvent is not used. - */ - public void windowIconified(WindowEvent e) { - } - - /** - * This event fires when the application is closing. - * This allows Plugins to do any persistence or other - * work before exiting. - * - * @param e WindowEvent is never used. - */ - public void windowClosing(WindowEvent e) { - saveLayout(); - setVisible(false); - } - }); - - this.addWindowFocusListener(new MainWindowFocusListener()); - } - - /** - * Adds a MainWindow listener to {@link MainWindow}. The - * listener will be called when either the MainWindow has been minimized, maximized, - * or is shutting down. - * - * @param listener the MainWindowListener to register - */ - public void addMainWindowListener(MainWindowListener listener) { - listeners.add(listener); - } - - /** - * Removes the specified {@link MainWindowListener}. - * - * @param listener the MainWindowListener to remove. - */ - public void removeMainWindowListener(MainWindowListener listener) { - listeners.remove(listener); - } - - /** - * Notifies all {@link MainWindowListener}s that the MainWindow - * has been activated. - */ - private void fireWindowActivated() { - for (MainWindowListener listener : listeners) { - listener.mainWindowActivated(); - } - - if (Spark.isMac()) { - setJMenuBar(mainWindowBar); - } - } - - /** - * Notifies all {@link MainWindowListener}s that the MainWindow - * is shutting down. - */ - private void fireWindowShutdown() { - for (MainWindowListener listener : listeners) { - listener.shutdown(); - } - } - - /** - * Invokes the Preferences Dialog. - * - * @param e the ActionEvent - */ - public void actionPerformed(ActionEvent e) { - if (e.getSource().equals(preferenceMenuItem)) { - SparkManager.getPreferenceManager().showPreferences(); - } - } - - /** - * Prepares Spark for shutting down by first calling all {@link MainWindowListener}s and - * setting the Agent to be offline. - */ - public void shutdown() { - final XMPPConnection con = SparkManager.getConnection(); - - if (con.isConnected()) { - // Send disconnect. - ((AbstractXMPPConnection)con).disconnect(); - } - - // Notify all MainWindowListeners - try { - fireWindowShutdown(); - } - catch (Exception ex) { - Log.error(ex); - } - // Close application. - if(!Default.getBoolean("DISABLE_EXIT")) - System.exit(1); - - } - - /** - * Prepares Spark for shutting down by first calling all {@link MainWindowListener}s and - * setting the Agent to be offline. - * - * @param sendStatus true if Spark should send a presence with a status message. - */ - public void logout(boolean sendStatus) { - final XMPPConnection con = SparkManager.getConnection(); - String status = null; - - if (con.isConnected() && sendStatus) { - final InputTextAreaDialog inputTextDialog = new InputTextAreaDialog(); - status = inputTextDialog.getInput(Res.getString("title.status.message"), Res.getString("message.current.status"), - SparkRes.getImageIcon(SparkRes.USER1_MESSAGE_24x24), this); - } - - if (status != null || !sendStatus) - { - // Notify all MainWindowListeners - try { - // Set auto-login to false; - SettingsManager.getLocalPreferences().setAutoLogin(false); - SettingsManager.saveSettings(); - - fireWindowShutdown(); - setVisible(false); - } - finally { - closeConnectionAndInvoke(status); - } - } - } - - /** - * Closes the current connection and restarts Spark. - * - * @param reason the reason for logging out. This can be if user gave no reason. - */ - public void closeConnectionAndInvoke(String reason) { - final XMPPConnection con = SparkManager.getConnection(); - if (con.isConnected()) { - if (reason != null) { - Presence byePresence = new Presence(Presence.Type.unavailable, reason, -1, null); - try - { - ((AbstractXMPPConnection)con).disconnect(byePresence); - } - catch ( SmackException.NotConnectedException e ) - { - Log.error( "Unable to sign out with presence.", e); - ((AbstractXMPPConnection)con).disconnect(); - } - } - else { - ((AbstractXMPPConnection)con).disconnect(); - } - } - if (!restartApplicationWithScript()) { - restartApplicationWithJava(); - } - } - - private File getLibDirectory() throws IOException { - File jarFile; - try{ - jarFile = new File(Startup.class.getProtectionDomain().getCodeSource().getLocation().toURI()); - } catch(Exception e) { - Log.error("Cannot get jar file containing the startup class", e); - return null; - } - if ( !jarFile.getName().endsWith(".jar") ) { - Log.error("The startup class is not packaged in a jar file"); - return null; - } - File libDir = jarFile.getParentFile(); - return libDir; - } - - private String getClasspath() throws IOException { - File libDir = getLibDirectory(); - String libPath = libDir.getCanonicalPath(); - String[] files = libDir.list(); - StringBuilder classpath = new StringBuilder(); - for (String file : files) { - if (file.endsWith(".jar")) { - classpath.append(libPath + File.separatorChar + file + File.pathSeparatorChar); - } - } - return classpath.toString(); - } - - private String getCommandPath() throws IOException{ - return getLibDirectory().getParentFile().getCanonicalPath(); - } - - public boolean restartApplicationWithScript() { - String command = null; - try { - if (Spark.isWindows()) { - String sparkExe = getCommandPath() + File.separator + Default.getString(Default.SHORT_NAME) + ".exe"; - if (!new File(sparkExe).exists()) { - Log.warning("Client EXE file does not exist"); - return false; - } - String starterExe = getCommandPath() + File.separator + "starter.exe"; - if (!new File(starterExe).exists()) { - Log.warning("Starter EXE file does not exist"); - return false; - } - command = starterExe + " \"" + sparkExe + "\""; - } else if (Spark.isLinux()) { - command = getCommandPath() + File.separator + Default.getString(Default.SHORT_NAME); - if (!new File(command).exists()) { - Log.warning("Client startup script does not exist"); - return false; - } - } else if (Spark.isMac()) { - command = "open -a " + Default.getString(Default.SHORT_NAME); - } - - Runtime.getRuntime().exec(command); - System.exit(0); - return true; - } catch (IOException e) { - Log.error("Error trying to restart application with script", e); - return false; - } - } - - public boolean restartApplicationWithJava() { - String javaBin = System.getProperty("java.home") + File.separatorChar + "bin" + File.separatorChar + "java"; - try { - String toExec[] = new String[] { - javaBin, "-cp", getClasspath(), "org.jivesoftware.launcher.Startup"}; - Runtime.getRuntime().exec(toExec); - } catch (Exception e) { - Log.error("Error trying to restart application with java", e); - return false; - } - System.exit(0); - return true; - } - - /** - * Setup the Main Toolbar with File, Tools and Help. - */ - private void buildMenu() { - - // setup file menu - final JMenuItem exitMenuItem = new JMenuItem(); - - // Setup ResourceUtils - ResourceUtils.resButton(connectMenu, "&" + Res.getString("menuitem.connect")); - ResourceUtils.resButton(contactsMenu, Res.getString("menuitem.contacts")); - ResourceUtils.resButton(actionsMenu, Res.getString("menuitem.actions")); - ResourceUtils.resButton(exitMenuItem, Res.getString("menuitem.exit")); - ResourceUtils.resButton(pluginsMenu, Res.getString("menuitem.plugins")); - - exitMenuItem.setIcon(null); - - mainWindowBar.add(connectMenu); - mainWindowBar.add(contactsMenu); - mainWindowBar.add(actionsMenu); - //mainWindowBar.add(pluginsMenu); - mainWindowBar.add(helpMenu); - - - preferenceMenuItem = new JMenuItem(SparkRes.getImageIcon(SparkRes.PREFERENCES_IMAGE)); - preferenceMenuItem.setText(Res.getString("title.spark.preferences")); - preferenceMenuItem.addActionListener(this); - connectMenu.add(preferenceMenuItem); - - - alwaysOnTopItem = new JCheckBoxMenuItem(); - ResourceUtils.resButton(alwaysOnTopItem, Res.getString("menuitem.always.on.top")); - alwaysOnTopItem.addActionListener( actionEvent -> { - if (alwaysOnTopItem.isSelected()) - { - SettingsManager.getLocalPreferences().setMainWindowAlwaysOnTop(true); - MainWindow.getInstance().setAlwaysOnTop(true); - } - else - { - SettingsManager.getLocalPreferences().setMainWindowAlwaysOnTop(false); - MainWindow.getInstance().setAlwaysOnTop(false); - } - } ); - - if (SettingsManager.getLocalPreferences().isMainWindowAlwaysOnTop()) - { - alwaysOnTopItem.setSelected(true); - this.setAlwaysOnTop(true); - } - connectMenu.add(alwaysOnTopItem); - - if(!Default.getBoolean("DISABLE_EXIT")) - connectMenu.addSeparator(); - - //EventQueue.invokeLater(new Runnable() { - // public void run() { - - JMenuItem logoutMenuItem = new JMenuItem(); - ResourceUtils.resButton(logoutMenuItem, Res.getString("menuitem.logout.no.status")); - logoutMenuItem.addActionListener( e -> logout(false) ); - - JMenuItem logoutWithStatus = new JMenuItem(); - ResourceUtils.resButton(logoutWithStatus, Res.getString("menuitem.logout.with.status")); - logoutWithStatus.addActionListener( e -> logout(true) ); - - if ((Spark.isWindows() || Spark.isLinux() || Spark.isMac()) && !Default.getBoolean("DISABLE_EXIT")) { - connectMenu.add(logoutMenuItem); - connectMenu.add(logoutWithStatus); - connectMenu.addSeparator(); - } - - if (!Default.getBoolean("DISABLE_EXIT")) { - connectMenu.add(exitMenuItem); - } - - JMenuItem updateMenu= new JMenuItem("", SparkRes.getImageIcon(SparkRes.DOWNLOAD_16x16)); - ResourceUtils.resButton(updateMenu, Res.getString("menuitem.check.for.updates")); - updateMenu.addActionListener( e -> checkForUpdates(true) ); - - // Add Error Dialog Viewer - final Action viewErrors = new AbstractAction() { - private static final long serialVersionUID = -420926784631340112L; - - public void actionPerformed(ActionEvent e) { - File logDir = new File(Spark.getLogDirectory(), "errors.log"); - if (!logDir.exists()) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), "No error logs found.", "Error Log", JOptionPane.INFORMATION_MESSAGE); - } - else { - showErrorLog(); - } - } - }; - - viewErrors.putValue(Action.NAME, Res.getString("menuitem.view.logs")); - - final Action viewHelpGuideAction = new AbstractAction() { - - final String url = Default.getString(Default.HELP_USER_GUIDE); - private static final long serialVersionUID = 2680369963282231348L; - - public void actionPerformed(ActionEvent actionEvent) { - try { - - BrowserLauncher.openURL(url); - } - catch (Exception e) { - Log.error("Unable to load online help.", e); - } - } - }; - - - if (!Default.getBoolean("HELP_USER_GUIDE_DISABLED")) { - viewHelpGuideAction.putValue(Action.NAME, - Res.getString("menuitem.user.guide")); - viewHelpGuideAction.putValue(Action.SMALL_ICON, - SparkRes.getImageIcon(SparkRes.SMALL_QUESTION)); - helpMenu.add(viewHelpGuideAction); - } - if (!Default.getBoolean("HELP_FORUM_DISABLED")) { - helpMenu.add(sparkforumItem); - } - - // Build Help Menu - if(!Default.getBoolean(Default.DISABLE_UPDATES)){ - helpMenu.add(updateMenu); - } - helpMenu.addSeparator(); - helpMenu.add(viewErrors); - helpMenu.add(menuAbout); - - // ResourceUtils - Adds mnemonics - ResourceUtils.resButton(preferenceMenuItem, Res.getString("menuitem.preferences")); - ResourceUtils.resButton(helpMenu, Res.getString("menuitem.help")); - ResourceUtils.resButton(menuAbout, Res.getString("menuitem.about")); - - if (Default.getString("HELP_FORUM_TEXT").length() > 0) { - ResourceUtils.resButton(sparkforumItem, Default.getString("HELP_FORUM_TEXT")); - } else { - ResourceUtils.resButton(sparkforumItem, Res.getString("menuitem.online.help")); - } - // Register shutdown with the exit menu. - exitMenuItem.addActionListener(new AbstractAction() { - private static final long serialVersionUID = -2301236575241532698L; - - public void actionPerformed(ActionEvent e) { - shutdown(); - } - }); - - sparkforumItem.addActionListener(new AbstractAction() { - private static final long serialVersionUID = -1423433460333010339L; - - final String url = Default.getString("HELP_FORUM"); - - public void actionPerformed(ActionEvent e) { - try { - BrowserLauncher.openURL(url); - } catch (Exception browserException) { - Log.error("Error launching browser:", browserException); - } - } - }); - - // Show About Box - menuAbout.addActionListener(new AbstractAction() { - private static final long serialVersionUID = -7173666373051354502L; - - public void actionPerformed(ActionEvent e) { - showAboutBox(); - } - }); - - if (!Default.getBoolean("DISABLE_UPDATES")) { - // Execute spark update checker after one minute. - final TimerTask task = new SwingTimerTask() { - public void doRun() { - checkForUpdates(false); - } - }; - - TaskEngine.getInstance().schedule(task, 60000); - } - - if(SettingsManager.getLocalPreferences().isDebuggerEnabled()) - { - JMenuItem rawPackets = new JMenuItem(SparkRes.getImageIcon(SparkRes.TRAY_IMAGE)); - rawPackets.setText("Send Packets"); - rawPackets.addActionListener( e -> new RawPacketSender() ); - - connectMenu.add(rawPackets,2); - } - - } - - /** - * Returns the JMenuBar for the MainWindow. You would call this if you - * wished to add or remove menu items to the main menubar. (File | Tools | Help) - * - * @return the Jive Talker Main Window MenuBar - */ - public JMenuBar getMenu() { - return mainWindowBar; - } - - /** - * Returns the Menu in the JMenuBar by it's name. For example:

      - *

      -     * JMenu toolsMenu = getMenuByName("Tools");
      -     * 
      - *

      - * - * @param name the name of the Menu. - * @return the JMenu item with the requested name. - */ - public JMenu getMenuByName(String name) { - for (int i = 0; i < getMenu().getMenuCount(); i++) { - JMenu menu = getMenu().getMenu(i); - if (menu.getText().equals(name)) { - return menu; - } - } - return null; - } - - /** - * Returns true if the Spark window is in focus. - * - * @return true if the Spark window is in focus. - */ - public boolean isInFocus() { - return focused; - } - - private class MainWindowFocusListener implements WindowFocusListener { - - public void windowGainedFocus(WindowEvent e) { - focused = true; - } - - public void windowLostFocus(WindowEvent e) { - focused = false; - } - } - - /** - * Return the top toolbar in the Main Window to allow for customization. - * - * @return the MainWindows top toolbar. - */ - public JToolBar getTopToolBar() { - return topToolbar; - } - - /** - * Checks for the latest update on the server. - * - * @param forced true if you want to bypass the normal checking security. - */ - private void checkForUpdates(final boolean forced) { - final CheckUpdates updater = new CheckUpdates(); - try { - final SwingWorker updateThread = new SwingWorker() { - public Object construct() { - try { - Thread.sleep(50); - } - catch (InterruptedException e) { - Log.error(e); - } - return "ok"; - } - - public void finished() { - try { - updater.checkForUpdate(forced); - } - catch (Exception e) { - Log.error("There was an error while checking for a new update.", e); - } - } - }; - - updateThread.start(); - - } - catch (Exception e) { - Log.warning("Error updating.", e); - } - } - - /** - * Sets About Box Pane for Spark. - */ - private void setAboutBoxPane() { - - // Get values from default.properties file - final String BUILD_NUMBER = Default.getString(Default.BUILD_NUMBER); - final String APPLICATION_INFO1 = Default.getString(Default.APPLICATION_INFO1); - final String APPLICATION_INFO2 = Default.getString(Default.APPLICATION_INFO2); - final String APPLICATION_INFO3 = Default.getString(Default.APPLICATION_INFO3); - final String APPLICATION_LICENSE_LINK = Default.getString(Default.APPLICATION_LICENSE_LINK); - final String APPLICATION_LICENSE_LINK_TXT = Default.getString(Default.APPLICATION_LICENSE_LINK_TXT); - final String APPLICATION_INFO4 = Default.getString(Default.APPLICATION_INFO4); - final String APPLICATION_LINK = Default.getString(Default.APPLICATION_LINK); - final String APPLICATION_LINK_TXT = Default.getString(Default.APPLICATION_LINK_TXT); - final boolean DISPLAY_DEV_INFO = Default.getBoolean(Default.DISPLAY_DEV_INFO); - final String SMACK_VERSION = Default.getString(Default.SMACK_VERSION); - final String JAVA_VERSION = Default.getString(Default.JAVA_VERSION); - - // Construct About Box text - StringBuilder aboutBoxText = new StringBuilder(); - aboutBoxText.append( - Default.getString(Default.APPLICATION_NAME) + " " + JiveInfo.getVersion()); - - // Add BUILD_NUMBER if not empty - if (!("".equals(BUILD_NUMBER))) { - aboutBoxText.append( - "
      " - + "Build: " + BUILD_NUMBER); - } - - // Add APPLICATION_INFO1 if not empty - if (!("".equals(APPLICATION_INFO1))) { - aboutBoxText.append( - "
      " - + APPLICATION_INFO1); - } - - // Add APPLICATION_INFO2 if not empty - if (!( "".equals(APPLICATION_INFO2))) { - aboutBoxText.append( - "
      " - + APPLICATION_INFO2); - } - - // Add APPLICATION_INFO3 if not empty - if (!("".equals(APPLICATION_INFO3))) { - aboutBoxText.append( - "
      " - + APPLICATION_INFO3); - } - - // Add APPLICATION_LICENSE_LINK if not empty - if (!( "".equals(APPLICATION_LICENSE_LINK))) { - aboutBoxText.append( - "
      " - + "" + APPLICATION_LICENSE_LINK_TXT + ""); - } - - // Add APPLICATION_LINK if not empty - if (!( "".equals(APPLICATION_LINK))) { - aboutBoxText.append( - "
      " - + "" + APPLICATION_LINK_TXT + ""); - } - - // Add APPLICATION_INFO4 if not empty - if (!( "".equals(APPLICATION_INFO4))) { - aboutBoxText.append( - "
      " - + APPLICATION_INFO4); - } - - if (DISPLAY_DEV_INFO) { - // Add Smack Version # if is empty - if ("".equals(SMACK_VERSION)) { - aboutBoxText.append( - "
      " - + "Smack Version: " + SmackConfiguration.getVersion()); - } - - // Add Java JRE Version if is empty - if ("".equals(JAVA_VERSION)) { - aboutBoxText.append( - "
      " - + "JRE Version: " + System.getProperty("java.version")); - } - } - - // copy window style - JPanel p = new JPanel(); - Font font = p.getFont(); - - // create some css from the JPanel's font - String style = ( "font-family:" + font.getFamily() + ";" ) + - "font-weight:" + ( font.isBold() ? "bold" : "normal" ) + ";" + - "font-size:" + font.getSize() + "pt;"; - - // assemble html - JEditorPane ep = new JEditorPane("text/html", ( "" + aboutBoxText.toString() + "" ) ); - - // handle link events - ep.addHyperlinkListener( e -> { - // if a link is clicked, and it is the APPLICATION_LICENSE_LINK, then load that page - if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED) - && e.getURL().toString().equalsIgnoreCase(Default.getString(Default.APPLICATION_LICENSE_LINK))) { - try { - - BrowserLauncher.openURL(Default.getString(Default.APPLICATION_LICENSE_LINK)); - - } catch (Exception f) { - Log.error("There was an error loading the URL", f); - } - - // else if a link is clicked, and it is the APPLICATION_LINK, then load that page - } else if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED) - && e.getURL().toString().equalsIgnoreCase(Default.getString(Default.APPLICATION_LINK))) { - try { - - BrowserLauncher.openURL(Default.getString(Default.APPLICATION_LINK)); - - } catch (Exception f) { - Log.error("There was an error loading the URL", f); - } - } - - } ); - ep.setEditable(false); - ep.setBackground(p.getBackground()); - this.aboutBoxPane = ep; - - } - - /** - * Returns About Box Pane. - * @return JEditorPane About Box - */ - private JEditorPane getAboutBoxPane() { - if (null == this.aboutBoxPane) { - setAboutBoxPane(); - } - return this.aboutBoxPane; - } - - /** - * Displays the About Box for Spark. - */ - private static void showAboutBox() { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), SparkManager.getMainWindow().getAboutBoxPane(), - Res.getString("title.about"), JOptionPane.INFORMATION_MESSAGE, SparkRes.getImageIcon(SparkRes.MAIN_IMAGE)); - } - - /** - * Displays the Spark error log. - */ - private void showErrorLog() { - final File logDir = new File(Spark.getLogDirectory(), "errors.log"); - - // Read file and show - final String errorLogs = URLFileSystem.getContents(logDir); - - final JFrame frame = new JFrame(Res.getString("title.client.logs")); - frame.setLayout(new BorderLayout()); - frame.setIconImage(SparkManager.getApplicationImage().getImage()); - - final JTextPane pane = new JTextPane(); - pane.setBackground(Color.white); - pane.setFont(new Font("Dialog", Font.PLAIN, 12)); - pane.setEditable(false); - pane.setText(errorLogs); - - frame.add(new JScrollPane(pane), BorderLayout.CENTER); - - final JButton copyButton = new JButton(Res.getString("button.copy.to.clipboard")); - frame.add(copyButton, BorderLayout.SOUTH); - - copyButton.addActionListener( e -> { - SparkManager.setClipboard(errorLogs); - copyButton.setEnabled(false); - } ); - - frame.pack(); - frame.setSize(600, 400); - - GraphicUtils.centerWindowOnScreen(frame); - frame.setVisible(true); - } - - /** - * Saves the layout on closing of the main window. - */ - public void saveLayout() { - try { - LayoutSettings settings = LayoutSettingsManager.getLayoutSettings(); - settings.setMainWindowHeight(getHeight()); - settings.setMainWindowWidth(getWidth()); - settings.setMainWindowX(getX()); - settings.setMainWindowY(getY()); - LayoutSettingsManager.saveLayoutSettings(); - } - catch (Exception e) { - // Don't let this cause a real problem shutting down. - } - } - - /** - * Return true if the MainWindow is docked. - * - * @return true if the window is docked. - */ - public boolean isDocked() { - LocalPreferences preferences = SettingsManager.getLocalPreferences(); - return preferences.isDockingEnabled(); - } - - /** - * Returns the inner split pane. - * - * @return the split pane. - */ - public JSplitPane getSplitPane() { - // create the split pane only if required. - if (splitPane == null) { - splitPane = new JSplitPane(); - } - return this.splitPane; - } -} diff --git a/src/java/org/jivesoftware/Spark.java b/src/java/org/jivesoftware/Spark.java deleted file mode 100644 index a8adf19f2..000000000 --- a/src/java/org/jivesoftware/Spark.java +++ /dev/null @@ -1,526 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.jivesoftware; - -import java.awt.Color; -import java.awt.EventQueue; -import java.awt.Font; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.Collection; -import java.util.HashSet; -import java.util.Locale; -import java.util.Properties; - -import javax.swing.BorderFactory; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; -import javax.swing.UIDefaults; -import javax.swing.UIManager; - -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.spark.PluginManager; -import org.jivesoftware.spark.ui.themes.ColorSettingManager; -import org.jivesoftware.spark.ui.themes.ColorSettings; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.UIComponentRegistry; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - - - -/** - * In many cases, you will need to know the structure of the Spark installation, such as the directory structures, what - * type of system Spark is running on, and also the arguments which were passed into Spark on startup. The Spark - * class provides some simple static calls to retrieve this information. - * - * @version 1.0, 11/17/2005 - */ -public final class Spark { - - - - private static String USER_SPARK_HOME; - - - - public static String ARGUMENTS; - - private static File RESOURCE_DIRECTORY; - private static File BIN_DIRECTORY; - private static File LOG_DIRECTORY; - private static File PLUGIN_DIRECTORY; - - - /** - * Private constructor that invokes the LoginDialog and - * the Spark Main Application. - */ - public Spark() { - - } - - private static synchronized File initializeDirectory(File directoryHome, String directoryName){ - File targetDir = new File(directoryHome, directoryName).getAbsoluteFile(); - if(!targetDir.exists()){ - targetDir.mkdirs(); - } - return targetDir; - } - - - private static synchronized File initializeDirectory(String directoryName){ - return initializeDirectory(new File(USER_SPARK_HOME), directoryName); - } - - public void startup() { - if (System.getenv("APPDATA") != null && !System.getenv("APPDATA").equals("")) { - USER_SPARK_HOME = System.getenv("APPDATA") + "/" + getUserConf(); - } else { - USER_SPARK_HOME = System.getProperties().getProperty("user.home") + "/" + getUserConf(); - } - - String current = System.getProperty("java.library.path"); - String classPath = System.getProperty("java.class.path"); - - // Set UIManager properties for JTree - System.setProperty("apple.laf.useScreenMenuBar", "true"); - - /** Update Library Path **/ - StringBuilder buf = new StringBuilder(); - buf.append(current); - buf.append(";"); - - SparkCompatibility sparkCompat = new SparkCompatibility(); - try { - // Absolute paths to a collection of files or directories to skip - Collection skipFiles = new HashSet<>(); - skipFiles.add(new File(USER_SPARK_HOME, "plugins").getAbsolutePath()); - - sparkCompat.transferConfig(USER_SPARK_HOME, skipFiles); - } catch (IOException e) { - // Do nothing - } - - - RESOURCE_DIRECTORY = initializeDirectory("resources"); - BIN_DIRECTORY = initializeDirectory("bin"); - LOG_DIRECTORY = initializeDirectory("logs"); - File USER_DIRECTORY = initializeDirectory( "user" ); - PLUGIN_DIRECTORY = initializeDirectory("plugins"); - File XTRA_DIRECTORY = initializeDirectory( "xtra" ); - // TODO implement copyEmoticonFiles(); - final String workingDirectory = System.getProperty("appdir"); - - if (workingDirectory == null) { - - if (!RESOURCE_DIRECTORY.exists() || !LOG_DIRECTORY.exists() || !USER_DIRECTORY.exists() || !PLUGIN_DIRECTORY.exists() || !XTRA_DIRECTORY.exists()) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(new JFrame(), "Unable to create directories necessary for runtime.", "Spark Error", JOptionPane.ERROR_MESSAGE); - System.exit(1); - } - } - // This is the Spark.exe or Spark.dmg installed executable. - - else { - // This is the installed executable. - File workingDir = new File(workingDirectory); - RESOURCE_DIRECTORY = initializeDirectory(workingDir, "resources"); - BIN_DIRECTORY = initializeDirectory(workingDir, "bin"); - File emoticons = new File( XTRA_DIRECTORY, "emoticons").getAbsoluteFile(); - if(!emoticons.exists()){ - - //Copy emoticon files from install directory to the spark user home directory - } - - LOG_DIRECTORY = initializeDirectory("logs"); - LOG_DIRECTORY = new File(USER_SPARK_HOME, "logs").getAbsoluteFile(); - LOG_DIRECTORY.mkdirs(); - try { - buf.append(RESOURCE_DIRECTORY.getCanonicalPath()).append(";"); - } - catch (IOException e) { - e.printStackTrace(); - } - } - - // Set default language set by the user. - loadLanguage(); - - /** - * Loads the LookandFeel - */ - loadLookAndFeel(); - - - buf.append(classPath); - buf.append(";").append(RESOURCE_DIRECTORY.getAbsolutePath()); - - // Update System Properties - System.setProperty("java.library.path", buf.toString()); - - - System.setProperty("sun.java2d.noddraw", "true"); - System.setProperty("file.encoding", "UTF-8"); - - SwingUtilities.invokeLater( () -> { - // Start Application - new Spark(); - } ); - - //load plugins before Workspace initialization to avoid any UI delays - //during plugin rendering - final PluginManager pluginManager = PluginManager.getInstance(); - pluginManager.loadPlugins(); - - installBaseUIProperties(); - - if (Default.getBoolean("CHANGE_COLORS_DISABLED")) { - ColorSettingManager.restoreDefault(); - } - - try { - EventQueue.invokeAndWait( () -> { - final LoginDialog dialog = UIComponentRegistry.createLoginDialog(); - dialog.invoke(new JFrame()); - } ); - } - catch(Exception ex) { - ex.printStackTrace(); - } - } - - private String getLookandFeel(LocalPreferences preferences) { - String result; - - String whereToLook = isMac() ? Default.DEFAULT_LOOK_AND_FEEL_MAC - : Default.DEFAULT_LOOK_AND_FEEL; - - if (!Default.getBoolean(Default.LOOK_AND_FEEL_DISABLED)) { - result = preferences.getLookAndFeel(); - } else if (Default.getString(whereToLook).length() > 0) { - result = Default.getString(whereToLook); - } else { - result = UIManager.getSystemLookAndFeelClassName(); - } - - return result; - - } - - /** - * Handles the Loading of the Look And Feel - */ - private void loadLookAndFeel() { - final LocalPreferences preferences = SettingsManager.getLocalPreferences(); - final String laf = getLookandFeel(preferences); - - try { - if (laf.toLowerCase().contains("substance")) { - EventQueue.invokeLater( () -> { - try { - if (Spark.isWindows()) { - JFrame.setDefaultLookAndFeelDecorated(true); - JDialog.setDefaultLookAndFeelDecorated(true); - } - UIManager.setLookAndFeel(laf); - } catch (Exception e) { - // dont care - e.printStackTrace(); - } - } ); - } else { - try { - if(Spark.isWindows()) { - JFrame.setDefaultLookAndFeelDecorated(true); - JDialog.setDefaultLookAndFeelDecorated(true); - } - UIManager.setLookAndFeel(laf); - - - } catch (Exception e) { - e.printStackTrace(); - } - } - } catch (Exception e) { - Log.error(e); - } - - if (laf.contains("jtattoo")) { - Properties props = new Properties(); - String menubar = Default.getString(Default.MENUBAR_TEXT) == null ? "" - : Default.getString(Default.MENUBAR_TEXT); - props.put("logoString", menubar); - try { - Class c = Thread.currentThread().getContextClassLoader().loadClass(laf); - Method m = c.getMethod("setCurrentTheme", Properties.class); - m.invoke(c.newInstance(), props); - } catch (Exception e) { - Log.error("Error Setting JTattoo ", e); - } - } - } - - - // Setup the look and feel of this application. - static { - com.install4j.api.launcher.StartupNotification.registerStartupListener(new SparkStartupListener()); - } - - /** - * Return if we are running on windows. - * - * @return true if we are running on windows, false otherwise. - */ - public static boolean isWindows() { - final String osName = System.getProperty("os.name").toLowerCase(); - return osName.startsWith("windows"); - } - - /** - * Returns true if Spark is running on vista. - * - * @return true if running on Vista. - */ - public static boolean isVista() { - final String osName = System.getProperty("os.name").toLowerCase(); - return osName.contains("vista"); - } - - /** - * Return if we are running on a mac. - * - * @return true if we are running on a mac, false otherwise. - */ - public static boolean isMac() { - String lcOSName = System.getProperty("os.name").toLowerCase(); - return lcOSName.contains( "mac" ); - } - - - /** - * Returns the value associated with a passed in argument. Spark - * accepts HTTP style attributes to allow for name-value pairing. - * ex. username=foo&password=pwd. - * To retrieve the value of username, you would do the following: - *
      -     * String value = Spark.getArgumentValue("username");
      -     * 
      - * - * @param argumentName the name of the argument to retrieve. - * @return the value of the argument. If no argument was found, null - * will be returned. - */ - public static String getArgumentValue(String argumentName) { - if (ARGUMENTS == null) { - return null; - } - - String arg = argumentName + "="; - - int index = ARGUMENTS.indexOf(arg); - if (index == -1) { - return null; - } - - String value = ARGUMENTS.substring(index + arg.length()); - int index2 = value.indexOf("&"); - if (index2 != -1) { - // Must be the last argument - value = value.substring(0, index2); - } - - - return value; - } - - public void setArgument(String arguments) { - ARGUMENTS = arguments; - } - - /** - * Returns the bin directory of the Spark install. The bin directory contains the startup scripts needed - * to start Spark. - * - * @return the bin directory. - */ - public static File getBinDirectory() { - if (BIN_DIRECTORY == null ) BIN_DIRECTORY = initializeDirectory("bin"); - return BIN_DIRECTORY; - } - - /** - * Returns the resource directory of the Spark install. The resource directory contains all native - * libraries needed to run os specific operations, such as tray support. You may place other native - * libraries within this directory if you wish to have them placed into the system.library.path. - * - * @return the resource directory. - */ - public static File getResourceDirectory() { - if (RESOURCE_DIRECTORY == null) RESOURCE_DIRECTORY = initializeDirectory("resources"); - return RESOURCE_DIRECTORY; - - } - - /** - * Returns the plugins directory of the Spark install. THe plugins-dir contains all the third-party plugins. - * - * @return the plugins directory - */ - public static File getPluginDirectory() { - if (PLUGIN_DIRECTORY == null) PLUGIN_DIRECTORY = initializeDirectory("plugins"); - return PLUGIN_DIRECTORY; - } - - /** - * Returns the log directory. The log directory contains all debugging and error files for Spark. - * - * @return the log directory. - */ - public static File getLogDirectory() { - if (LOG_DIRECTORY == null )LOG_DIRECTORY = initializeDirectory("logs"); - return LOG_DIRECTORY; - } - - /** - * Return if we are running on Linux. - * - * @return true if we are running on Linux, false otherwise. - */ - - public static boolean isLinux() { - final String osName = System.getProperty("os.name").toLowerCase(); - return osName.startsWith("linux"); - } - - /** - * Keep track of the users configuration directory. - * - * @return Directory name depending on Operating System. - */ - public static String getUserConf() { - if (isLinux()) { - return Default.getString(Default.USER_DIRECTORY_LINUX); - } - else if(isMac()) - { - return Default.getString(Default.USER_DIRECTORY_MAC); - } - else - return Default.getString(Default.USER_DIRECTORY_WINDOWS); - } - - - /** - * Returns the Spark directory for the current user (user.home). The user home is where all user specific - * files are placed to run Spark within a multi-user system. - * - * @return the user home / Spark; - */ - public static String getSparkUserHome() { - return USER_SPARK_HOME; - } - - /** - * Return the base user home. - * - * @return the user home. - */ - public static String getUserHome() { - return System.getProperties().getProperty("user.home"); - } - - public static boolean disableUpdatesOnCustom() { - return Default.getBoolean("DISABLE_UPDATES"); - } - - public static void setApplicationFont(Font f) { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - synchronized(defaults) { - for (Object ui_property: defaults.keySet()) { - if (ui_property.toString().endsWith(".font")) { - UIManager.put(ui_property, f); - } - } - } - } - - /** - * Sets Spark specific colors - */ - public static void installBaseUIProperties() { - setApplicationFont(new Font("Dialog", Font.PLAIN, 11)); - UIManager.put("ContactItem.border", BorderFactory.createLineBorder(Color.white)); - //UIManager.put("TextField.font", new Font("Dialog", Font.PLAIN, 11)); - //UIManager.put("Label.font", new Font("Dialog", Font.PLAIN, 11)); - - ColorSettings colorsettings = ColorSettingManager.getColorSettings(); - - for(String property : colorsettings.getKeys()) - { - Color c = colorsettings.getColorFromProperty(property); - UIManager.put(property, c); - } - - - } - - /** - * Loads the language set by the user. If no language is set, then the default implementation will be used. - */ - private void loadLanguage() { - final LocalPreferences preferences = SettingsManager.getLocalPreferences(); - final String setLanguage = preferences.getLanguage(); - if (ModelUtil.hasLength(setLanguage)) { - Locale[] locales = Locale.getAvailableLocales(); - for (Locale locale : locales) { - if (locale.toString().equals(setLanguage)) { - Locale.setDefault(locale); - break; - } - } - } - } - /* public void copyEmoticonFiles() { - // Current Plugin directory - File newEmoticonDir = new File(Spark.getLogDirectory().getParentFile(), "xtra/emoticons").getAbsoluteFile(); - newEmoticonDir.mkdirs(); - //TODO emoticondirectory anpassen - File EMOTICON_DIRECTORY = new File("D:/workspace/Spark 2.6 beta/src","xtra/emoticons"); - File[] files = EMOTICON_DIRECTORY.listFiles(); - - - for (File file : files) { - if (file.isFile()) { - - // Copy over - File newFile = new File(newEmoticonDir, file.getName()); - - } - } - }*/ -} diff --git a/src/java/org/jivesoftware/SparkCompatibility.java b/src/java/org/jivesoftware/SparkCompatibility.java deleted file mode 100644 index 10c80a068..000000000 --- a/src/java/org/jivesoftware/SparkCompatibility.java +++ /dev/null @@ -1,143 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Collection; -import java.util.HashSet; - - - -public class SparkCompatibility { - - /** - * Old Spark settings directory - */ - private final String OLD_USER_SPARK_HOME = System.getProperties().getProperty("user.home") + "/" + getUserConf(); - - private final String OLD_USER_SPARK_HOME_MAC = System.getProperties().getProperty("user.home") + "/Spark"; - public SparkCompatibility() { - } - - - /** - * Copies the old USER_SPARK_HOME to the new directory if it does not exist - * @param userSparkHome - * The previous directory to copy from - * @param skipFiles - * The files to skip - * @throws IOException - */ - public void transferConfig(String userSparkHome, Collection skipFiles) - throws IOException { - File newSparkHomeDir = new File(userSparkHome); - File oldSparkHomeDir; - if (System.getProperty("os.name").toLowerCase().contains("mac")) { - oldSparkHomeDir = new File(OLD_USER_SPARK_HOME_MAC); - } else { - oldSparkHomeDir = new File(OLD_USER_SPARK_HOME); - - } - - if (!newSparkHomeDir.exists() && oldSparkHomeDir.exists()) { - copyDirectory(oldSparkHomeDir, newSparkHomeDir, skipFiles); - } - } - /** - * Copies the directories / files recursively - * @param src - * The source dir/file to copy - * @param dest - * The destination dir/file to copy - * @param skipFiles - * A colleciton of files to skip - * @throws IOException - */ - private void copyDirectory(File src , File dest, Collection skipFiles) throws IOException { - if (src.isDirectory()) { - if (!dest.exists()) { - dest.mkdir(); - } - String[] children = src.list(); - for (int i=0; i()); - } - } - } else { - InputStream in; - OutputStream out; - - try { - in = new FileInputStream(src); - out = new FileOutputStream(dest); - } catch (FileNotFoundException e) { - IOException wrapper = new IOException("copyDirectory: Unable to open handle on file: " - + src.getAbsolutePath() + "and" + dest.getAbsolutePath() + "."); - wrapper.initCause(e); - wrapper.setStackTrace(e.getStackTrace()); - throw wrapper; - } catch (SecurityException e) { - IOException wrapper = new IOException("copyDirectory: access denied to copy file: " - + src.getAbsolutePath() + "and" + dest.getAbsolutePath() + "."); - wrapper.initCause(e); - wrapper.setStackTrace(e.getStackTrace()); - throw wrapper; - } - try { - // Copy the bits from instream to outstream - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - } catch (IOException e) { - IOException wrapper = new IOException("copyDirectory: Unable to copy file: " - + src.getAbsolutePath() + "to" + dest.getAbsolutePath() + "."); - wrapper.initCause(e); - wrapper.setStackTrace(e.getStackTrace()); - throw wrapper; - } finally { - in.close(); - out.close(); - } - } - } - - - - /** - * Keep track of the users configuration directory. - * - * @return Directory name depending on Operating System. - */ - private static String getUserConf() { - return Spark.getUserConf(); - } -} diff --git a/src/java/org/jivesoftware/launcher/Startup.java b/src/java/org/jivesoftware/launcher/Startup.java deleted file mode 100644 index 0cce31ab3..000000000 --- a/src/java/org/jivesoftware/launcher/Startup.java +++ /dev/null @@ -1,173 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.launcher; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.lang.reflect.Method; -import java.util.jar.JarOutputStream; -import java.util.jar.Pack200; - -/** - * - */ -public class Startup { - - /** - * Default to this location if one has not been specified - */ - private static final String DEFAULT_LIB_DIR = "../lib"; - - public static void main(String[] args) { - new Startup().start(args); - } - - /** - * Starts the server by loading and instantiating the bootstrap - * container. Once the start method is called, the server is - * started and the server starter should not be used again. - * - * @param args the arguments passed into this initial instance of Spark. - */ - private void start(String[] args) { - // Setup the classpath using JiveClassLoader - try { - // Load up the bootstrap container - final ClassLoader parent = findParentClassLoader(); - - File libDir; - final String workingDirectory = System.getProperty("appdir"); - if (workingDirectory == null) { - libDir = new File(DEFAULT_LIB_DIR); - } - else { - libDir = new File(new File(workingDirectory), "lib"); - } - - File pluginDir = new File(libDir.getParentFile(), "plugins"); - - // Unpack any pack files in lib. - unpackArchives(libDir, true); - - // Unpack plugins. - unpackArchives(pluginDir, true); - - // Load them into the classloader - final ClassLoader loader = new JiveClassLoader(parent, libDir); - - Thread.currentThread().setContextClassLoader(loader); - - // Get class - Class sparkClass = loader.loadClass("org.jivesoftware.Spark"); - Object instanceOfSpark = sparkClass.newInstance(); - - // Handle arguments - if (args.length > 0) { - String argument = args[0]; - Method setArgument = sparkClass.getMethod("setArgument", String.class); - setArgument.invoke(instanceOfSpark, argument); - } - - Method startupMethod = sparkClass.getMethod("startup"); - startupMethod.invoke(instanceOfSpark); - } - catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Locates the best class loader based on context (see class description). - * - * @return The best parent classloader to use - */ - private ClassLoader findParentClassLoader() { - ClassLoader parent = Thread.currentThread().getContextClassLoader(); - if (parent == null) { - parent = this.getClass().getClassLoader(); - if (parent == null) { - parent = ClassLoader.getSystemClassLoader(); - } - } - return parent; - } - - /** - * Converts any pack files in a directory into standard JAR files. Each - * pack file will be deleted after being converted to a JAR. If no - * pack files are found, this method does nothing. - * - * @param libDir the directory containing pack files. - * @param printStatus true if status ellipses should be printed when unpacking. - */ - private void unpackArchives(File libDir, boolean printStatus) { - // Get a list of all packed files in the lib directory. - File[] packedFiles = libDir.listFiles( ( dir, name ) -> { - return name.endsWith(".pack"); - } ); - - if (packedFiles == null) { - // Do nothing since no .pack files were found - return; - } - - // Unpack each. - boolean unpacked = false; - for (File packedFile : packedFiles) { - try { - String jarName = packedFile.getName().substring(0, - packedFile.getName().length() - ".pack".length()); - // Delete JAR file with same name if it exists (could be due to upgrade - // from old Wildfire release). - File jarFile = new File(libDir, jarName); - if (jarFile.exists()) { - jarFile.delete(); - } - - InputStream in = new BufferedInputStream(new FileInputStream(packedFile)); - JarOutputStream out = new JarOutputStream(new BufferedOutputStream( - new FileOutputStream(new File(libDir, jarName)))); - Pack200.Unpacker unpacker = Pack200.newUnpacker(); - // Print something so the user knows something is happening. - if (printStatus) { - System.out.print("."); - } - // Call the unpacker - unpacker.unpack(in, out); - - in.close(); - out.close(); - packedFile.delete(); - unpacked = true; - } - catch (Exception e) { - e.printStackTrace(); - } - } - // Print newline if unpacking happened. - if (unpacked && printStatus) { - System.out.println(); - } - } -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/resource/ConfigurationRes.java b/src/java/org/jivesoftware/resource/ConfigurationRes.java deleted file mode 100644 index e96fe3faa..000000000 --- a/src/java/org/jivesoftware/resource/ConfigurationRes.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.resource; - -import javax.swing.ImageIcon; - -import java.net.URL; -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; - -public class ConfigurationRes { - private static PropertyResourceBundle prb; - public static final String GLOBAL_ELEMENT_NAME = "GLOBAL_ELEMENT_NAME"; - public static final String DELETE_IMAGE = "DELETE_IMAGE"; - public static final String PERSONAL_NAMESPACE = "PERSONAL_NAMESPACE"; - public static final String HEADER_FILE = "HEADER_FILE"; - public static final String CHECK_IMAGE = "CHECK_IMAGE"; - - public static final String SPELLING_PROPERTIES = "SPELLING_PROPERTIES"; - public static final String PERSONAL_ELEMENT_NAME = "PERSONAL_ELEMENT_NAME"; - static ClassLoader cl = ConfigurationRes.class.getClassLoader(); - - static { - prb = (PropertyResourceBundle)ResourceBundle.getBundle("org/jivesoftware/resource/configuration"); - } - - public static String getString(String propertyName) { - return prb.getString(propertyName); - } - - public static ImageIcon getImageIcon(String imageName) { - final String iconURI = getString(imageName); - final URL imageURL = cl.getResource(iconURI); - return new ImageIcon(imageURL); - } - - public static URL getURL(String propertyName) { - return cl.getResource(getString(propertyName)); - } -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/resource/Default.java b/src/java/org/jivesoftware/resource/Default.java deleted file mode 100644 index 38389c2f8..000000000 --- a/src/java/org/jivesoftware/resource/Default.java +++ /dev/null @@ -1,214 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.resource; - -import org.jivesoftware.spark.PluginRes; -import org.jivesoftware.spark.util.log.Log; - -import javax.swing.ImageIcon; - -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; -import java.util.StringTokenizer; - -public class Default { - private static PropertyResourceBundle prb; - - private static Map customMap = new HashMap<>(); - - private static Map cache = new HashMap<>(); - - public static final String MAIN_IMAGE = "MAIN_IMAGE"; - public static final String APPLICATION_NAME = "APPLICATION_NAME"; - public static final String APPLICATION_INFO1 = "APPLICATION_INFO1"; - public static final String APPLICATION_INFO2 = "APPLICATION_INFO2"; - public static final String APPLICATION_INFO3 = "APPLICATION_INFO3"; - public static final String APPLICATION_LICENSE_LINK = "APPLICATION_LICENSE_LINK"; - public static final String APPLICATION_LICENSE_LINK_TXT = "APPLICATION_LICENSE_LINK_TXT"; - public static final String APPLICATION_INFO4 = "APPLICATION_INFO4"; - public static final String APPLICATION_LINK = "APPLICATION_LINK"; - public static final String APPLICATION_LINK_TXT = "APPLICATION_LINK_TXT"; - public static final String DISPLAY_DEV_INFO = "DISPLAY_DEV_INFO"; - public static final String SMACK_VERSION = "SMACK_VERSION"; - public static final String JAVA_VERSION = "JAVA_VERSION"; - public static final String SHORT_NAME = "SHORT_NAME"; - public static final String APPLICATION_VERSION = "APPLICATION_VERSION"; - public static final String BUILD_NUMBER = "BUILD_NUMBER"; - public static final String LOGIN_DIALOG_BACKGROUND_IMAGE = "LOGIN_DIALOG_BACKGROUND_IMAGE"; - public static final String HOST_NAME = "HOST_NAME"; - public static final String HOST_NAME_CHANGE_DISABLED = "HOST_NAME_CHANGE_DISABLED"; - public static final String SHOW_POWERED_BY = "SHOW_POWERED_BY"; - public static final String TOP_BOTTOM_BACKGROUND_IMAGE = "TOP_BOTTOM_BACKGROUND_IMAGE"; - public static final String BRANDED_IMAGE = "BRANDED_IMAGE"; - public static final String DISABLE_UPDATES = "DISABLE_UPDATES"; - public static final String SECONDARY_BACKGROUND_IMAGE = "SECONDARY_BACKGROUND_IMAGE"; - public static final String HOVER_TEXT_COLOR = "HOVER_TEXT_COLOR"; - public static final String TEXT_COLOR = "TEXT_COLOR"; - public static final String TAB_START_COLOR = "TAB_START_COLOR"; - public static final String TAB_END_COLOR = "TAB_END_COLOR"; - public static final String CONTACT_GROUP_START_COLOR = "CONTACT_GROUP_START_COLOR"; - public static final String CONTACT_GROUP_END_COLOR = "CONTACT_GROUP_END_COLOR"; - public static final String PROXY_HOST = "PROXY_HOST"; - public static final String PROXY_PORT = "PROXY_PORT"; - public static final String ACCOUNT_DISABLED = "ACCOUNT_DISABLED"; - public static final String PASSWORD_RESET_ENABLED = "PASSWORD_RESET_ENABLED"; - public static final String PASSWORD_RESET_URL = "PASSWORD_RESET_URL"; - public static final String ADD_CONTACT_DISABLED = "ADD_CONTACT_DISABLED"; - public static final String CHANGE_PASSWORD_DISABLED = "CHANGE_PASSWORD_DISABLED"; - public static final String TRAY_IMAGE = "TRAY_IMAGE"; - public static final String FRAME_IMAGE = "FRAME_IMAGE"; - public static final String LOOK_AND_FEEL_DISABLED = "LOOK_AND_FEEL_DISABLED"; - public static final String DEFAULT_LOOK_AND_FEEL = "DEFAULT_LOOK_AND_FEEL"; - public static final String DEFAULT_LOOK_AND_FEEL_MAC = "DEFAULT_LOOK_AND_FEEL_MAC"; - public static final String INSTALL_PLUGINS_DISABLED = "INSTALL_PLUGINS_DISABLED"; - public static final String DEINSTALL_PLUGINS_DISABLED = "DEINSTALL_PLUGINS_DISABLED"; - public static final String ADVANCED_DISABLED = "ADVANCED_DISABLED"; - public static final String SSO_DISABLED = "SSO_DISABLED"; - public static final String PROXY_DISABLED = "PROXY_DISABLED"; - public static final String PKI_DISABLED = "PKI_DISABLED"; - public static final String HELP_USER_GUIDE = "HELP_USER_GUIDE"; - public static final String BROADCAST_IN_CHATWINDOW = "BROADCAST_IN_CHATWINDOW"; - public static final String MENUBAR_TEXT = "MENUBAR_TEXT"; - public static final String FILE_TRANSFER_WARNING_SIZE = "FILE_TRANSFER_WARNING_SIZE"; - public static final String FILE_TRANSFER_MAXIMUM_SIZE = "FILE_TRANSFER_MAXIMUM_SIZE"; - public static final String TABS_PLACEMENT_TOP = "TABS_PLACEMENT_TOP"; - public static final String HIDE_PERSON_SEARCH_FIELD = "HIDE_PERSON_SEARCH_FIELD"; - public static final String USER_DIRECTORY_WINDOWS = "USER_DIRECTORY_WINDOWS"; - public static final String USER_DIRECTORY_LINUX = "USER_DIRECTORY_LINUX"; - public static final String USER_DIRECTORY_MAC = "USER_DIRECTORY_MAC"; - public static final String HOSTNAME_AS_RESOURCE = "HOSTNAME_AS_RESOURCE"; - public static final String VERSION_AS_RESOURCE = "VERSION_AS_RESOURCE"; - public static final String HISTORY_DISABLED = "HISTORY_DISABLED"; - public static final String HIDE_HISTORY_SETTINGS = "HIDE_HISTORY_SETTINGS"; - public static final String HIDE_SAVE_PASSWORD_AND_AUTOLOGIN = "HIDE_SAVE_PASSWORD_AND_AUTOLOGIN"; - - static ClassLoader cl = SparkRes.class.getClassLoader(); - - static { - prb = (PropertyResourceBundle)ResourceBundle.getBundle("org/jivesoftware/resource/default"); - } - - public static void putCustomValue(String value, Object object) { - customMap.put(value, object); - } - - public static void removeCustomValue(String value) { - customMap.remove(value); - } - - public static void clearCustomValues() { - customMap.clear(); - } - - public static String getString(String propertyName) { - String pluginString = PluginRes.getDefaultRes(propertyName); - return pluginString != null ? pluginString : prb.getString(propertyName); - } - - public static boolean getBoolean(String propertyName) { - return getString(propertyName).replace(" ","").equals("true"); - } - - public static ImageIcon getImageIcon(String imageName) { - // Check custom map - Object o = customMap.get(imageName); - if (o != null && o instanceof ImageIcon) { - return (ImageIcon)o; - } - - // Otherwise check cache - o = cache.get(imageName); - if (o != null && o instanceof ImageIcon) { - return (ImageIcon)o; - } - - // Otherwise, load and add to cache. - try { - final URL imageURL = getURL(imageName); - - final ImageIcon icon = new ImageIcon(imageURL); - cache.put(imageName, icon); - return icon; - } - catch (Exception ex) { - Log.debug(imageName + " not found."); - } - return null; - } - - public static URL getURL(String propertyName) { - URL pluginUrl = PluginRes.getDefaultURL(propertyName); - return pluginUrl != null ? pluginUrl : cl.getResource(getString(propertyName)); - } - - - public static URL getURLWithoutException(String propertyName) { - // Otherwise, load and add to cache. - try { - return getURL(propertyName); - } - catch (Exception ex) { - Log.debug(propertyName + " not found."); - } - return null; - } - - /** - * Returns a Collection of Plugins on the Blacklist
      - * Containing the Name and also if specified the entrypoint-class - * @return Collection - */ - public static Collection getPluginBlacklist() { - String pluginlist = getString("PLUGIN_BLACKLIST").replace(" ", "") - .toLowerCase(); - StringTokenizer tokenizer = new StringTokenizer(pluginlist, ","); - ArrayList list = new ArrayList<>(); - - while (tokenizer.hasMoreTokens()) { - list.add(tokenizer.nextToken()); - } - - StringTokenizer clazztokenz = new StringTokenizer( - getString("PLUGIN_BLACKLIST_CLASS").replace(" ", ""), ","); - - while (clazztokenz.hasMoreTokens()) { - list.add(clazztokenz.nextToken()); - } - - return list; - - } - - /** - * Returns all Keys stored in the default.properties file - * @return {@link Enumeration}<{@link String}> - */ - public static Enumeration getAllKeys() - { - return prb.getKeys(); - } - -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/resource/SoundsRes.java b/src/java/org/jivesoftware/resource/SoundsRes.java deleted file mode 100644 index 7fd0fad6d..000000000 --- a/src/java/org/jivesoftware/resource/SoundsRes.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.resource; - -import javax.swing.ImageIcon; - -import java.net.URL; -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; - -public class SoundsRes { - private static PropertyResourceBundle prb; - public static final String INCOMING_USER = "INCOMING_USER"; - public static final String TRAY_SHOWING = "TRAY_SHOWING"; - public static final String OPENING = "OPENING"; - public static final String CLOSING = "CLOSING"; - - - static ClassLoader cl = SoundsRes.class.getClassLoader(); - - static { - prb = (PropertyResourceBundle)ResourceBundle.getBundle("org/jivesoftware/resource/sounds"); - } - - public static String getString(String propertyName) { - return prb.getString(propertyName); - } - - public static ImageIcon getImageIcon(String imageName) { - final String iconURI = getString(imageName); - final URL imageURL = cl.getResource(iconURI); - return new ImageIcon(imageURL); - } - - public static URL getURL(String propertyName) { - return cl.getResource(getString(propertyName)); - } -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/resource/SparkRes.java b/src/java/org/jivesoftware/resource/SparkRes.java deleted file mode 100644 index 0420c3328..000000000 --- a/src/java/org/jivesoftware/resource/SparkRes.java +++ /dev/null @@ -1,431 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.resource; - -import org.jivesoftware.spark.PluginRes; -import org.jivesoftware.spark.util.log.Log; - -import javax.swing.ImageIcon; -import javax.swing.JEditorPane; -import javax.swing.JFrame; -import javax.swing.JScrollPane; - -import java.awt.BorderLayout; -import java.io.File; -import java.net.URL; -import java.util.Enumeration; -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; - -public class SparkRes { - private static PropertyResourceBundle prb; - - public static final String ACCEPT_CHAT = "ACCEPT_CHAT"; - public static final String ACCEPT_INVITE_IMAGE = "ACCEPT_INVITE_IMAGE"; - public static final String ADDRESS_BOOK_16x16 = "ADDRESS_BOOK_16x16"; - public static final String ADD_BOOKMARK_ICON = "ADD_BOOKMARK_ICON"; - public static final String ADD_CONTACT_IMAGE = "ADD_CONTACT_IMAGE"; - public static final String ADD_IMAGE_24x24 = "ADD_IMAGE_24x24"; - public static final String ADD_LINK_TO_CHAT = "ADD_LINK_TO_CHAT"; - public static final String ADD_TO_CHAT = "ADD_TO_CHAT"; - public static final String ADD_TO_KB = "ADD_TO_KB"; - public static final String AIM_TRANSPORT_ACTIVE_IMAGE = "AIM_TRANSPORT_ACTIVE_IMAGE"; - public static final String AIM_TRANSPORT_INACTIVE_IMAGE = "AIM_TRANSPORT_INACTIVE_IMAGE"; - public static final String ALERT = "ALERT"; - public static final String ALL_CHATS = "ALL_CHATS"; - public static final String APP_NAME = "APP_NAME"; - public static final String AVAILABLE_USER = "AVAILABLE_USER"; - public static final String AWAY_USER = "AWAY_USER"; - public static final String BACKGROUND_IMAGE = "BACKGROUND_IMAGE"; - public static final String BLANK_24x24 = "BLANK_24x24"; - public static final String BLANK_IMAGE = "BLANK_IMAGE"; - public static final String BLOCK_CONTACT_16x16 = "BLOCK_CONTACT_16x16"; - public static final String BLUE_BALL = "BLUE_BALL"; - public static final String BOOKMARK_ICON = "BOOKMARK_ICON"; - public static final String BRICKWALL_IMAGE = "BRICKWALL_IMAGE"; - public static final String BUSY_IMAGE = "BUSY_IMAGE"; - public static final String BUZZ_IMAGE = "BUZZ_IMAGE"; - public static final String CALENDAR_IMAGE = "CALENDAR_IMAGE"; - public static final String CALL_ICON = "CALL_ICON"; - public static final String CANCEL_IMAGE = "CANCEL_IMAGE"; - public static final String CHANGELOG_IMAGE = "CHANGELOG_IMAGE"; - public static final String CHATTING_AGENT_IMAGE = "CHATTING_AGENT_IMAGE"; - public static final String CHATTING_CUSTOMER_IMAGE = "CHATTING_CUSTOMER_IMAGE"; - public static final String CHAT_QUEUE = "CHAT_QUEUE"; - public static final String CHAT_WORKSPACE = "CHAT_WORKSPACE"; - public static final String CIRCLE_CHECK_IMAGE = "CIRCLE_CHECK_IMAGE"; - public static final String CLEAR_BALL_ICON = "CLEAR_BALL_ICON"; - public static final String CLOSE_DARK_X_IMAGE = "CLOSE_DARK_X_IMAGE"; - public static final String CLOSE_IMAGE = "CLOSE_IMAGE"; - public static final String CLOSE_WHITE_X_IMAGE = "CLOSE_WHITE_X_IMAGE"; - public static final String COLOR_ICON = "COLOR_ICON"; - public static final String COMPUTER_IMAGE_16x16 = "COMPUTER_IMAGE_16x16"; - public static final String CONFERENCE_IMAGE_16x16 = "CONFERENCE_IMAGE_16x16"; - public static final String CONFERENCE_IMAGE_24x24 = "CONFERENCE_IMAGE_24x24"; - public static final String CONFERENCE_IMAGE_48x48 = "CONFERENCE_IMAGE_48x48"; - public static final String COPY_16x16 = "COPY_16x16"; - public static final String CO_BROWSER_TAB_TITLE = "CO_BROWSER_TAB_TITLE"; - public static final String CREATE_FAQ_ENTRY = "CREATE_FAQ_ENTRY"; - public static final String CREATE_FAQ_TITLE = "CREATE_FAQ_TITLE"; - public static final String CURRENT_AGENTS = "CURRENT_AGENTS"; - public static final String CURRENT_CHATS = "CURRENT_CHATS"; - public static final String DATA_DELETE_16x16 = "DATA_DELETE_16x16"; - public static final String DATA_REFRESH_16x16 = "DATA_REFRESH_16x16"; - public static final String DEFAULT_AVATAR_16x16_IMAGE = "DEFAULT_AVATAR_16x16_IMAGE"; - public static final String DEFAULT_AVATAR_32x32_IMAGE = "DEFAULT_AVATAR_32x32_IMAGE"; - public static final String DEFAULT_AVATAR_64x64_IMAGE = "DEFAULT_AVATAR_64x64_IMAGE"; - public static final String DELETE_BOOKMARK_ICON = "DELETE_BOOKMARK_ICON"; - public static final String DESKTOP_IMAGE = "DESKTOP_IMAGE"; - public static final String DIAL_PHONE_IMAGE_16x16 = "DIAL_PHONE_IMAGE_16x16"; - public static final String DIAL_PHONE_IMAGE_24x24 = "DIAL_PHONE_IMAGE_24x24"; - public static final String DOCUMENT_16x16 = "DOCUMENT_16x16"; - public static final String DOCUMENT_EXCHANGE_IMAGE = "DOCUMENT_EXCHANGE_IMAGE"; - public static final String DOCUMENT_FIND_16x16 = "DOCUMENT_FIND_16x16"; - public static final String DOCUMENT_INFO_32x32 = "DOCUMENT_INFO_32x32"; - public static final String DOOR_IMAGE = "DOOR_IMAGE"; - public static final String DOWNLOAD_16x16 = "DOWNLOAD_16x16"; - public static final String DOWN_ARROW_IMAGE = "DOWN_ARROW_IMAGE"; - public static final String DOWN_OPTION_IMAGE = "DOWN_OPTION_IMAGE"; - public static final String DUMMY_CONTACT_IMAGE = "DUMMY_CONTACT_IMAGE"; - public static final String EARTH_LOCK_16x16 = "EARTH_LOCK_16x16"; - public static final String EARTH_VIEW_16x16 = "EARTH_VIEW_16x16"; - public static final String END_BUTTON_24x24 = "END_BUTTON_24x24"; - public static final String ERASER_IMAGE = "ERASER_IMAGE"; - public static final String ERROR_DIALOG_TITLE = "ERROR_DIALOG_TITLE"; - public static final String ERROR_INVALID_WORKGROUP = "ERROR_INVALID_WORKGROUP"; - public static final String FACEBOOK_TRANSPORT_ACTIVE_IMAGE = "FACEBOOK_TRANSPORT_ACTIVE_IMAGE"; - public static final String FACEBOOK_TRANSPORT_INACTIVE_IMAGE = "FACEBOOK_TRANSPORT_INACTIVE_IMAGE"; - public static final String FAQ_TAB_TITLE = "FAQ_TAB_TITLE"; - public static final String FASTPATH_IMAGE_16x16 = "FASTPATH_IMAGE_16x16"; - public static final String FASTPATH_IMAGE_24x24 = "FASTPATH_IMAGE_24x24"; - public static final String FASTPATH_IMAGE_32x32 = "FASTPATH_IMAGE_32x32"; - public static final String FASTPATH_IMAGE_64x64 = "FASTPATH_IMAGE_64x64"; - public static final String FASTPATH_OFFLINE_IMAGE_16x16 = "FASTPATH_OFFLINE_IMAGE_16x16"; - public static final String FASTPATH_OFFLINE_IMAGE_24x24 = "FASTPATH_OFFLINE_IMAGE_24x24"; - public static final String FILTER_LABEL = "FILTER_LABEL"; - public static final String FIND_IMAGE = "FIND_IMAGE"; - public static final String FIND_TEXT_IMAGE = "FIND_TEXT_IMAGE"; - public static final String FOLDER = "FOLDER"; - public static final String FOLDER_CLOSED = "FOLDER_CLOSED"; - public static final String FONT_16x16 = "FONT_16x16"; - public static final String FORUM_TAB_TITLE = "FORUM_TAB_TITLE"; - public static final String FREE_TO_CHAT_IMAGE = "FREE_TO_CHAT_IMAGE"; - public static final String FUNNEL_DOWN_16x16 = "FUNNEL_DOWN_16x16"; - public static final String GADUGADU_TRANSPORT_ACTIVE_IMAGE = "GADUGADU_TRANSPORT_ACTIVE_IMAGE"; - public static final String GADUGADU_TRANSPORT_INACTIVE_IMAGE = "GADUGADU_TRANSPORT_INACTIVE_IMAGE"; - public static final String GO = "GO"; - public static final String GREEN_BALL = "GREEN_BALL"; - public static final String GREEN_FLAG_16x16 = "GREEN_FLAG_16x16"; - public static final String GTALK_TRANSPORT_ACTIVE_IMAGE = "GTALK_TRANSPORT_ACTIVE_IMAGE"; - public static final String GTALK_TRANSPORT_INACTIVE_IMAGE = "GTALK_TRANSPORT_INACTIVE_IMAGE"; - public static final String HEADSET_IMAGE = "HEADSET_IMAGE"; - public static final String HELP2_24x24 = "HELP2_24x24"; - public static final String HISTORY_16x16 = "HISTORY_16x16"; - public static final String HISTORY_24x24_IMAGE = "HISTORY_24x24"; - public static final String ICQ_TRANSPORT_ACTIVE_IMAGE = "ICQ_TRANSPORT_ACTIVE_IMAGE"; - public static final String ICQ_TRANSPORT_INACTIVE_IMAGE = "ICQ_TRANSPORT_INACTIVE_IMAGE"; - public static final String ID_CARD_48x48 = "ID_CARD_48x48"; - public static final String IM_AVAILABLE_STALE_IMAGE = "IM_AVAILABLE_STALE_IMAGE"; - public static final String IM_AWAY = "IM_AWAY"; - public static final String IM_AWAY_STALE_IMAGE = "IM_AWAY_STALE_IMAGE"; - public static final String IM_DND = "IM_DND"; - public static final String IM_DND_STALE_IMAGE = "IM_AWAY_STALE_IMAGE"; - public static final String IM_FREE_CHAT_STALE_IMAGE = "IM_FREE_CHAT_STALE_IMAGE"; - public static final String IM_UNAVAILABLE_STALE_IMAGE = "IM_UNAVAILABLE_STALE_IMAGE"; - public static final String INFORMATION_ICO = "INFORMATION_ICO"; - public static final String INFORMATION_IMAGE = "INFORMATION_IMAGE"; - public static final String INVALID_USERNAME_PASSWORD = "INVALID_USERNAME_PASSWORD"; - public static final String INVITE_MORE_IMAGE = "INVITE_MORE_IMAGE"; - public static final String IRC_TRANSPORT_ACTIVE_IMAGE = "IRC_TRANSPORT_ACTIVE_IMAGE"; - public static final String IRC_TRANSPORT_INACTIVE_IMAGE = "IRC_TRANSPORT_INACTIVE_IMAGE"; - public static final String JOIN_GROUPCHAT_IMAGE = "JOIN_GROUPCHAT_IMAGE"; - public static final String KNOWLEDGE_BASE_TAB_TITLE = "KNOWLEDGE_BASE_TAB_TITLE"; - public static final String LEFT_ARROW_IMAGE = "LEFT_ARROW_IMAGE"; - public static final String LIGHTBULB_ON_16x16_IMAGE = "LIGHTBULB_ON_16x16_IMAGE"; - public static final String LIGHTING_BOLT_IMAGE = "LIGHTING_BOLT_IMAGE"; - public static final String LINK_16x16 = "LINK_16x16"; - public static final String LINK_DELETE_16x16 = "LINK_DELETE_16x16"; - public static final String LOCK_16x16 = "LOCK_16x16"; - public static final String LOCK_UNLOCK_16x16 = "LOCK_UNLOCK_16x16"; - public static final String LOGIN_DIALOG_AUTHENTICATING = "LOGIN_DIALOG_AUTHENTICATING"; - public static final String LOGIN_DIALOG_LOGIN = "LOGIN_DIALOG_LOGIN"; - public static final String LOGIN_DIALOG_LOGIN_TITLE = "LOGIN_DIALOG_LOGIN_TITLE"; - public static final String LOGIN_DIALOG_PASSWORD = "LOGIN_DIALOG_PASSWORD"; - public static final String LOGIN_DIALOG_QUIT = "LOGIN_DIALOG_QUIT"; - public static final String LOGIN_DIALOG_USERNAME = "LOGIN_DIALOG_USERNAME"; - public static final String LOGIN_DIALOG_WORKSPACE = "LOGIN_DIALOG_WORKSPACE"; - public static final String LOGIN_KEY_IMAGE = "LOGIN_KEY_IMAGE"; - public static final String MAGICIAN_IMAGE = "MAGICIAN_IMAGE"; - public static final String MAIL_16x16 = "MAIL_16x16"; - public static final String MAIL_FORWARD_16x16 = "MAIL_FORWARD_16x16"; - public static final String MAIL_IMAGE_32x32 = "MAIL_IMAGE_32x32"; - public static final String MAIL_INTO_16x16 = "MAIL_INTO_16x16"; - public static final String MAIN_ICNS_FILE = "MAIN_ICNS_FILE"; - public static final String MAIN_IMAGE = "MAIN_IMAGE"; - public static final String MAIN_IMAGE_ICO = "MAIN_IMAGE_ICO"; - public static final String MAIN_TITLE = "MAIN_TITLE"; - public static final String MEGAPHONE_16x16 = "MEGAPHONE_16x16"; - public static final String MESSAGE_AWAY = "MESSAGE_AWAY"; - public static final String MESSAGE_DND = "MESSAGE_DND"; - public static final String MESSAGE_NEW_TRAY = "MESSAGE_NEW_TRAY"; - public static final String MESSAGE_NEW_TRAY_LINUX = "MESSAGE_NEW_TRAY_LINUX"; - public static final String MINUS_SIGN = "MINUS_SIGN"; - public static final String MOBILE_PHONE_IMAGE = "MOBILE_PHONE_IMAGE"; - public static final String MODERATOR_IMAGE = "MODERATOR_IMAGE"; - public static final String MSN_TRANSPORT_ACTIVE_IMAGE = "MSN_TRANSPORT_ACTIVE_IMAGE"; - public static final String MSN_TRANSPORT_INACTIVE_IMAGE = "MSN_TRANSPORT_INACTIVE_IMAGE"; - public static final String MYSPACE_TRANSPORT_ACTIVE_IMAGE = "MYSPACE_TRANSPORT_ACTIVE_IMAGE"; - public static final String MYSPACE_TRANSPORT_INACTIVE_IMAGE = "MYSPACE_TRANSPORT_INACTIVE_IMAGE"; - public static final String NOTEBOOK_IMAGE = "NOTEBOOK_IMAGE"; - public static final String NOTE_EDIT_16x16 = "NOTE_EDIT_16x16"; - public static final String OFFLINE_ICO = "OFFLINE_ICO"; - public static final String OFFLINE_IMAGE = "OFFLINE_IMAGE"; - public static final String ONLINE_ICO = "ONLINE_ICO"; - public static final String ON_PHONE_IMAGE = "ON_PHONE_IMAGE"; - public static final String PALETTE_24x24_IMAGE = "PALETTE_24x24_IMAGE"; - public static final String PANE_DOWN_ARROW_IMAGE = "PANE_DOWN_ARROW_IMAGE"; - public static final String PANE_UP_ARROW_IMAGE = "PANE_UP_ARROW_IMAGE"; - public static final String PAWN_GLASS_GREEN = "PAWN_GLASS_GREEN"; - public static final String PAWN_GLASS_RED = "PAWN_GLASS_RED"; - public static final String PAWN_GLASS_WHITE = "PAWN_GLASS_WHITE"; - public static final String PAWN_GLASS_YELLOW = "PAWN_GLASS_YELLOW"; - public static final String PEOPLE_IMAGE = "PEOPLE_IMAGE"; - public static final String PHOTO_IMAGE = "PHOTO_IMAGE"; - public static final String PLUGIN_IMAGE = "PLUGIN_IMAGE"; - public static final String PLUS_SIGN = "PLUS_SIGN"; - public static final String POWERED_BY_IMAGE = "POWERED_BY_IMAGE"; - public static final String PREFERENCES_IMAGE = "PREFERENCES_IMAGE"; - public static final String PRINTER_IMAGE_16x16 = "PRINTER_IMAGE_16x16"; - public static final String PROFILE_ICON = "PROFILE_ICON"; - public static final String PROFILE_IMAGE_16x16 = "PROFILE_IMAGE_16x16"; - public static final String PROFILE_IMAGE_24x24 = "PROFILE_IMAGE_24x24"; - public static final String PROFILE_TAB_TITLE = "PROFILE_TAB_TITLE"; - public static final String PUSH_URL_16x16 = "PUSH_URL_16x16"; - public static final String QQ_TRANSPORT_ACTIVE_IMAGE = "QQ_TRANSPORT_ACTIVE_IMAGE"; - public static final String QQ_TRANSPORT_INACTIVE_IMAGE = "QQ_TRANSPORT_INACTIVE_IMAGE"; - public static final String QUESTIONS_ANSWERS = "QUESTIONS_ANSWERS"; - public static final String README_IMAGE = "README_IMAGE"; - public static final String RED_BALL = "RED_BALL"; - public static final String RED_FLAG_16x16 = "RED_FLAG_16x16"; - public static final String REFRESH_IMAGE = "REFRESH_IMAGE"; - public static final String REJECT_CHAT = "REJECT_CHAT"; - public static final String REJECT_INVITE_IMAGE = "REJECT_INVITE_IMAGE"; - public static final String RIGHT_ARROW_IMAGE = "RIGHT_ARROW_IMAGE"; - public static final String SAMETIME_TRANSPORT_ACTIVE_IMAGE = "SAMETIME_TRANSPORT_ACTIVE_IMAGE"; - public static final String SAMETIME_TRANSPORT_INACTIVE_IMAGE = "SAMETIME_TRANSPORT_INACTIVE_IMAGE"; - public static final String SAVE_AS_16x16 = "SAVE_AS_16x16"; - public static final String SEARCH = "SEARCH"; - public static final String SEARCH_IMAGE_32x32 = "SEARCH_IMAGE_32x32"; - public static final String SEARCH_USER_16x16 = "SEARCH_USER_16x16"; - public static final String SEND = "SEND"; - public static final String SEND_FILE_24x24 = "SEND_FILE_24x24"; - public static final String SEND_FILE_ICON = "SEND_FILE_ICON"; - public static final String SEND_MAIL_IMAGE_16x16 = "SEND_MAIL_IMAGE_16x16"; - public static final String SERVER_ICON = "SERVER_ICON"; - public static final String SERVER_UNAVAILABLE = "SERVER_UNAVAILABLE"; - public static final String SETTINGS_IMAGE_16x16 = "SETTINGS_IMAGE_16x16"; - public static final String SETTINGS_IMAGE_24x24 = "SETTINGS_IMAGE_24x24"; - public static final String SIMPLE_TRANSPORT_ACTIVE_IMAGE = "SIMPLE_TRANSPORT_ACTIVE_IMAGE"; - public static final String SIMPLE_TRANSPORT_INACTIVE_IMAGE = "SIMPLE_TRANSPORT_INACTIVE_IMAGE"; - public static final String SMALL_ABOUT_IMAGE = "SMALL_ABOUT_IMAGE"; - public static final String SMALL_ADD_IMAGE = "SMALL_ADD_IMAGE"; - public static final String SMALL_AGENT_IMAGE = "SMALL_AGENT_IMAGE"; - public static final String SMALL_ALARM_CLOCK = "SMALL_ALARM_CLOCK"; - public static final String SMALL_ALL_AGENTS_IMAGE = "SMALL_ALL_AGENTS_IMAGE"; - public static final String SMALL_ALL_CHATS_IMAGE = "SMALL_ALL_CHATS_IMAGE"; - public static final String SMALL_BUSINESS_MAN_VIEW = "SMALL_BUSINESS_MAN_VIEW"; - public static final String SMALL_CHECK = "SMALL_CHECK"; - public static final String SMALL_CIRCLE_DELETE = "SMALL_CIRCLE_DELETE"; - public static final String SMALL_CLOSE_BUTTON = "SMALL_CLOSE_BUTTON"; - public static final String SMALL_CURRENT_AGENTS = "SMALL_CURRENT_AGENTS"; - public static final String SMALL_DATA_FIND_IMAGE = "SMALL_DATA_FIND_IMAGE"; - public static final String SMALL_DELETE = "SMALL_DELETE"; - public static final String SMALL_DOCUMENT_ADD = "SMALL_DOCUMENT_ADD"; - public static final String SMALL_DOCUMENT_VIEW = "SMALL_DOCUMENT_VIEW"; - public static final String SMALL_ENTRY = "SMALL_ENTRY"; - public static final String SMALL_MESSAGE_EDIT_IMAGE = "SMALL_MESSAGE_EDIT_IMAGE"; - public static final String SMALL_MESSAGE_IMAGE = "SMALL_MESSAGE_IMAGE"; - public static final String SMALL_PIN_BLUE = "SMALL_PIN_BLUE"; - public static final String SMALL_PROFILE_IMAGE = "SMALL_PROFILE_IMAGE"; - public static final String SMALL_QUESTION = "SMALL_QUESTION"; - public static final String SMALL_SCROLL_REFRESH = "SMALL_SCROLL_REFRESH"; - public static final String SMALL_STOP = "SMALL_STOP"; - public static final String SMALL_USER1_INFORMATION = "SMALL_USER1_INFORMATION"; - public static final String SMALL_USER1_MESSAGE = "SMALL_USER1_MESSAGE"; - public static final String SMALL_USER1_MOBILEPHONE = "SMALL_USER1_MOBILEPHONE"; - public static final String SMALL_USER1_NEW = "SMALL_USER1_NEW"; - public static final String SMALL_USER1_STOPWATCH = "SMALL_USER1_STOPWATCH"; - public static final String SMALL_USER1_TIME = "SMALL_USER1_TIME"; - public static final String SMALL_USER_DELETE = "SMALL_USER_DELETE"; - public static final String SMALL_USER_ENTER = "SMALL_USER_ENTER"; - public static final String SMALL_WORKGROUP_QUEUE_IMAGE = "SMALL_WORKGROUP_QUEUE_IMAGE"; - public static final String SOUND_PREFERENCES_IMAGE = "SOUND_PREFERENCES_IMAGE"; - public static final String SPARK_IMAGE = "SPARK_IMAGE"; - public static final String SPARK_IMAGE_32x32 = "SPARK_IMAGE_32x32"; - public static final String SPARK_LOGOUT_IMAGE = "SPARK_LOGOUT_IMAGE"; - public static final String SPELL_CHECK_IMAGE = "SPELL_CHECK_IMAGE"; - public static final String STAR_ADMIN = "STAR_ADMIN"; - public static final String STAR_BLUE_IMAGE = "STAR_BLUE_IMAGE"; - public static final String STAR_GREEN_IMAGE = "STAR_GREEN_IMAGE"; - public static final String STAR_GREY_IMAGE = "STAR_GREY_IMAGE"; - public static final String STAR_MODERATOR ="STAR_MODERATOR"; - public static final String STAR_OWNER = "STAR_OWNER"; - public static final String STAR_RED_IMAGE = "STAR_RED_IMAGE"; - public static final String STAR_YELLOW_IMAGE = "STAR_YELLOW_IMAGE"; - public static final String STICKY_NOTE_IMAGE = "STICKY_NOTE_IMAGE"; - public static final String TASK_DELETE_IMAGE = "TASK_DELETE_IMAGE"; - public static final String TELEPHONE_24x24 = "TELEPHONE_24x24"; - public static final String TEXT_BOLD = "TEXT_BOLD"; - public static final String TEXT_ITALIC = "TEXT_ITALIC"; - public static final String TEXT_NORMAL = "TEXT_NORMAL"; - public static final String TEXT_UNDERLINE = "TEXT_UNDERLINE"; - public static final String TIME_LEFT = "TIME_LEFT"; - public static final String TOOLBAR_BACKGROUND = "TOOLBAR_BACKGROUND"; - public static final String TOOLBOX = "TOOLBOX"; - public static final String TRAFFIC_LIGHT_IMAGE = "TRAFFIC_LIGHT_IMAGE"; - public static final String TRANSFER_IMAGE_24x24 = "TRANSFER_IMAGE_24x24"; - public static final String TRANSPORT_ICON = "TRANSPORT_ICON"; - public static final String TRAY_AWAY = "TRAY_AWAY"; - public static final String TRAY_AWAY_LINUX = "TRAY_AWAY_LINUX"; - public static final String TRAY_CONNECTING = "TRAY_CONNECTING"; - public static final String TRAY_CONNECTING_LINUX = "TRAY_CONNECTING_LINUX"; - public static final String TRAY_DND = "TRAY_DND"; - public static final String TRAY_DND_LINUX = "TRAY_DND_LINUX"; - public static final String TRAY_IMAGE = "TRAY_IMAGE"; - public static final String TRAY_IMAGE_LINUX = "TRAY_IMAGE_LINUX"; - public static final String TRAY_OFFLINE = "TRAY_OFFLINE"; - public static final String TRAY_OFFLINE_LINUX = "TRAY_OFFLINE_LINUX"; - public static final String TYPING_TRAY = "TYPING_TRAY"; - public static final String TYPING_TRAY_LINUX = "TYPING_TRAY_LINUX"; - public static final String UNBLOCK_CONTACT_16x16 = "UNBLOCK_CONTACT_16x16"; - public static final String UNRECOVERABLE_ERROR = "UNRECOVERABLE_ERROR"; - public static final String USER1_32x32 = "USER1_32x32"; - public static final String USER1_ADD_16x16 = "USER1_ADD_16x16"; - public static final String USER1_BACK_16x16 = "USER1_BACK_16x16"; - public static final String USER1_MESSAGE_24x24 = "USER1_MESSAGE_24x24"; - public static final String USER_HEADSET_24x24 = "USER_HEADSET_24x24"; - public static final String VERSION = "VERSION"; - public static final String VIEW = "VIEW"; - public static final String VIEW_IMAGE = "VIEW_IMAGE"; - public static final String WELCOME = "WELCOME"; - public static final String WORKGROUP_QUEUE = "WORKGROUP_QUEUE"; - public static final String XMPP_TRANSPORT_ACTIVE_IMAGE = "XMPP_TRANSPORT_ACTIVE_IMAGE"; - public static final String XMPP_TRANSPORT_INACTIVE_IMAGE = "XMPP_TRANSPORT_INACTIVE_IMAGE"; - public static final String YAHOO_TRANSPORT_ACTIVE_IMAGE = "YAHOO_TRANSPORT_ACTIVE_IMAGE"; - public static final String YAHOO_TRANSPORT_INACTIVE_IMAGE = "YAHOO_TRANSPORT_INACTIVE_IMAGE"; - public static final String YELLOW_BALL = "YELLOW_BALL"; - public static final String YELLOW_FLAG_16x16 = "YELLOW_FLAG_16x16"; - public static final String EXECUTABLE_NAME = "EXECUTABLE_NAME"; - public static final String INVISIBLE = "INVISIBLE"; - - - static ClassLoader cl = SparkRes.class.getClassLoader(); - - static { - prb = (PropertyResourceBundle)ResourceBundle.getBundle("org/jivesoftware/resource/spark"); - } - - public static String getString(String propertyName) { - String pluginString = PluginRes.getSparkRes(propertyName); - return pluginString != null ? pluginString : prb.getString(propertyName); - } - - public static ImageIcon getImageIcon(String imageName) { - try { - final URL imageURL = getURL(imageName); - return new ImageIcon(imageURL); - } - catch (Exception ex) { - Log.error(imageName + " not found."); - } - return null; - } - - public static URL getURL(String propertyName) { - URL pluginUrl = PluginRes.getSparkURL(propertyName); - return pluginUrl != null ? pluginUrl : cl.getResource(getString(propertyName)); - } - - public static void main(String args[]) { - - JFrame frame = new JFrame(); - frame.getContentPane().setLayout(new BorderLayout()); - - JEditorPane pane = new JEditorPane(); - frame.getContentPane().add(new JScrollPane(pane)); - - StringBuilder buf = new StringBuilder(); - Enumeration enumeration = prb.getKeys(); - while (enumeration.hasMoreElements()) { - String token = enumeration.nextElement(); - String value = prb.getString(token).toLowerCase(); - if (value.endsWith(".gif") || value.endsWith(".png") || value.endsWith(".jpg") || value.endsWith("jpeg")) { - SparkRes.getImageIcon(token); - } - String str = "public static final String " + token + " = \"" + token + "\";\n"; - buf.append(str); - } - - checkImageDir(); - pane.setText(buf.toString()); - frame.pack(); - frame.setVisible(true); - } - - private static void checkImageDir() { - File[] files = new File("c:\\code\\liveassistant\\client\\resources\\images").listFiles(); - final int no = files != null ? files.length : 0; - for (int i = 0; i < no; i++) { - try { - File imageFile = files[i]; - String name = imageFile.getName(); - - // Check to see if the name of the file exists - boolean exists = false; - Enumeration enumeration = prb.getKeys(); - while (enumeration.hasMoreElements()) { - String token = enumeration.nextElement(); - String value = prb.getString(token); - if (value.endsWith(name)) { - exists = true; - } - } - - if (!exists) { - Log.error(imageFile.getAbsolutePath() + " is not used."); - } - } - catch (NullPointerException e) { - // TODO: Should we worry about this? - } - } - } - - public static URL getURLWithoutException(String propertyName) { - // Otherwise, load and add to cache. - try { - return getURL(propertyName); - } - catch (Exception ex) { - Log.debug(propertyName + " not found."); - } - return null; - } -} diff --git a/src/java/org/jivesoftware/resource/configuration.properties b/src/java/org/jivesoftware/resource/configuration.properties deleted file mode 100644 index 6cf7975eb..000000000 --- a/src/java/org/jivesoftware/resource/configuration.properties +++ /dev/null @@ -1,16 +0,0 @@ -# Default configurations for Live Assistant -DEFAULT_APP_RESOURCE_NAME = Live Assistant - -#Images -CHECK_IMAGE = images/check.png -DELETE_IMAGE = images/delete.png -HEADER_FILE = images/header.png - -#Namespaces -PERSONAL_ELEMENT_NAME = private_macros -PERSONAL_NAMESPACE = liveassistant:private - -GLOBAL_ELEMENT_NAME = global_macros -GLOBAL_ELEMENT_NAME = liveassistant:global - -SPELLING_PROPERTIES = spelling/spelling.properties diff --git a/src/java/org/jivesoftware/resource/default.properties b/src/java/org/jivesoftware/resource/default.properties deleted file mode 100644 index 40d5fb3cc..000000000 --- a/src/java/org/jivesoftware/resource/default.properties +++ /dev/null @@ -1,292 +0,0 @@ -################################################# -################# Login Window ################# -################################################# -# The Login image -# suggested image dimensions 244 x 188 pixels -MAIN_IMAGE = images/spark.gif -APPLICATION_NAME = Spark -SHORT_NAME = Spark - -############# Auto Set During Build ############# -APPLICATION_VERSION = 2.7.7 -# Passed into ant via cmd line argument: -# -Dbuild.number= -# If not passed in, this field is ignored. -BUILD_NUMBER = -################################################# - -USER_DIRECTORY_WINDOWS = Spark -USER_DIRECTORY_LINUX = .Spark -USER_DIRECTORY_MAC = Library/Application Support/Spark - -LOGIN_DIALOG_BACKGROUND_IMAGE = images/login_dialog_background.png -TOP_BOTTOM_BACKGROUND_IMAGE = images/top_bottom_background_image.png -SECONDARY_BACKGROUND_IMAGE = images/steel.png - -# Specify a fixed Hostname -# Changing the Hostname will also be prohibited if set -HOST_NAME = -# Set true if you dont want user to change the server -HOST_NAME_CHANGE_DISABLED = false -# Proxy Settings -# Protocols are HTTP or SOCKS , case sensitive!!! -PROXY_PROTOCOL = -PROXY_HOST = -PROXY_PORT = - -# Remove account creation Button from Loginwindow -# Users wont be able to register new Accounts from within Spark -ACCOUNT_DISABLED = -# Remove Advanced Configuration Button from Loginwindow -# Users wont be able to access the advanced configuration -ADVANCED_DISABLED = - -# Force using hostname or version as a resource (both are "false" by default; only one can be -# "true" at a time; if both are "true", then hostname will be used as a resource) -HOSTNAME_AS_RESOURCE = false -VERSION_AS_RESOURCE = false - -# When enabled, it removes history from the chat window and doesn't save history into transcript files. Also removes history -# settings from the preferences, removes history button from the chat window and contact's history context menu. -HISTORY_DISABLED = false -# When enabled, it hides history settings from the preferences and removes Clear button from the context menu in the Chat window -HIDE_HISTORY_SETTINGS = false - -#If Advanded preferences is enabled you are able to remove tabs, except the "General" tab -#Removes SSO Tab -SSO_DISABLED = false -#Removes PKI Tab -PKI_DISABLED = false -#Removes Proxy Tab -PROXY_DISABLED = false - - -# Show Password Reset Button on LoginDialog. -# !!!! This will repleace the "register new user" button, please set ACCOUNT_DISABLED = true !!!! -PASSWORD_RESET_ENABLED = false -# URL to your password reset html -PASSWORD_RESET_URL = -# Hides Save Password and Auto Login checkboxes on the Login screen and in the Preferences -HIDE_SAVE_PASSWORD_AND_AUTOLOGIN = false - -# Branding only -# Branded images appear in the Top-Right corner, and must be included in the classpath -# place them in src/resource/images and path will be "images/file.jpg" -# BRANDED_IMAGE = images/my-corporation-logo.png -BRANDED_IMAGE = - -# Shows a powered by logo below the Main Image of Spark -SHOW_POWERED_BY = -# Disables updateability, you should set this, if you have a custom Spark-build -# or are in an environment where installfiles are distributed via network -DISABLE_UPDATES = - -# If true, Spark cannot shut down -# users wont be able to shut down Spark -DISABLE_EXIT = - -################################################# -################## File Transfer ################ -################################################# - -# Specify a size on which Users will get a -# warning of a possibly too big file -# 10MB = 10485760 -# 100MB = 104857600 -# 1GB = 1073741824 -# default = -1 (infinity) -# maximum is 9223372036854775806 byte = 8388608TB -FILE_TRANSFER_WARNING_SIZE = -1 - -# Specify the Maximum file size to be permitted to send -# 10MB = 10485760 -# 100MB = 104857600 -# 1GB = 1073741824 -# default = -1 (infinity) -# maximum is 9223372036854775806 byte = 8.388.608 TB -FILE_TRANSFER_MAXIMUM_SIZE = -1 - - -################################################# -################## Main Window ################## -################################################# -# [Not yet implemented:] -# Changing this wont have any effect -# Roster Management -#HOVER_TEXT_COLOR = -#TEXT_COLOR = -#CONTACT_GROUP_START_COLOR = -#CONTACT_GROUP_END_COLOR = -#TAB_START_COLOR = -#TAB_END_COLOR = -# [/NYI] -################################################# -################ Settings Window ################ -################################################# - -# Disables adding of contacts -# The User wont be able to add contacts, -# usefull for shared roster management -ADD_CONTACT_DISABLED = -# Disables adding contact groups -# The User wont be able to add contact groups, -# usefull for shared roster management -ADD_CONTACT_GROUP_DISABLED = - -# Change Password Disabled -# Users wont be able to change their password -CHANGE_PASSWORD_DISABLED = - -# Sets the Location of the Userguide -#Default is http://www.igniterealtime.org/builds/spark/docs/spark_user_guide.pdf -HELP_USER_GUIDE = https://community.igniterealtime.org/docs/DOC-5213 -# Set to true, if you dont want this displayed -HELP_USER_GUIDE_DISABLED = -# Sets the Location of the Help-Forum -#Default is http://www.igniterealtime.org/forum/forum.jspa?forumID=49 -HELP_FORUM = http://www.igniterealtime.org/forum/forum.jspa?forumID=49 -# Set to true, if you dont want this displayed -HELP_FORUM_DISABLED = -# Following Text will be displayed instead of "Spark forum" -# leave blank for default -HELP_FORUM_TEXT = - -################################################# -############### About Box Window ################ -################################################# - -# Version and Developer Info -# Note: Application name and Version are always displayed - -# Display Version and Developer Info -# 'true' or 'false' -DISPLAY_DEV_INFO = true -# Leave blank for auto-detect -SMACK_VERSION = -JAVA_VERSION = - -# Set additional About Box information -# About Box dynamically resizes depending on number of lines and length of text -# Leave blank to omit line and shift lines upwards -APPLICATION_INFO1 = Ignite Realtime -APPLICATION_INFO2 = -APPLICATION_INFO3 = -# Clickable Link - must be a valid and complete URL -# Ex: http://www.igniterealtime.org/ -APPLICATION_LICENSE_LINK = http://www.igniterealtime.org/builds/spark/docs/latest/LICENSE.html -APPLICATION_LICENSE_LINK_TXT = Apache License, Version 2.0 -APPLICATION_INFO4 = -# Clickable Link - must be a valid and complete URL -# Ex: http://www.igniterealtime.org/ -APPLICATION_LINK = http://www.igniterealtime.org/ -APPLICATION_LINK_TXT = www.igniterealtime.org - -################################################# -################ Plugins ################ -################################################# - -# This is the default location where Plugins can be downloaded from -# for a sample structure see trunk/documentation/sample_plugin_repository.xml -# default: http://www.igniterealtime.org/updater/plugins.jsp -PLUGIN_REPOSITORY = http://www.igniterealtime.org/updater/plugins.jsp -# Use Sparks global Proxy to connect to the repository? -# if your repository lies within your network, this probably needs to be disabled -# default: true -PLUGIN_REPOSITORY_USE_PROXY = true -#http://www.igniterealtime.org/updater/plugins.jsp -# Disable Installing of Plugins -# set true if you want to disable installing of Plugins -INSTALL_PLUGINS_DISABLED = -# Disable deleting of Plugins -# set true if you want to disable deinstalling of Plugins -DEINSTALL_PLUGINS_DISABLED = -# Put plugins here that you dont want enabled -# comma separated, case insensitive -# names of plugins can be found in the plugin.xml -# example: Fastpath,Jingle Client,Phone Client,Window Flashing Plugin -# default is empty -PLUGIN_BLACKLIST = -# Disable Plugins by entrypoint Class -# Comma seperated, case sensitive -# example org.jivesoftware.fastpath.FastpathPlugin -# default is empty -PLUGIN_BLACKLIST_CLASS = - - -################################################# -######### Color + LookandFeel ########### -################################################# - -# by Default Server-Broadcast get their own JFrame containing the Message -# also HTML tags like can be used -# if you want server broadcasts handled like every other message including transcripts -# set this to true -BROADCAST_IN_CHATWINDOW = false -# Disable Look&Feel change || "true" = disabled , anything else = enabled -# By Default the user can Change his Look&Feel in the Preferences Menu, -# if you dont want this then set it to true -# Preferences -> Appearence -> Customization Tab -LOOK_AND_FEEL_DISABLED = -# Disable if you dont want Users to be able to Change the Textcolors in the Preference Menu -# the colors will be loaded from below -# Preferences -> Appearence -> ColorTab -CHANGE_COLORS_DISABLED = -# Changes the Default Look&Feel, if empty it will load the SystemSkin -# Default Spark skin is com.jtattoo.plaf.luna.LunaLookAndFeel -# other nice skin is org.jvnet.substance.skin.SubstanceBusinessBlueSteelLookAndFeel -DEFAULT_LOOK_AND_FEEL = com.jtattoo.plaf.luna.LunaLookAndFeel -DEFAULT_LOOK_AND_FEEL_MAC = -# in JTatto Menubars can have Texts, default is empty -MENUBAR_TEXT = - -# tabs are placed on bottom by default. if set to true will be placed on top -TABS_PLACEMENT_TOP = - -# the person search field is displayed by default. if set to true the search field will -# not be displayed -HIDE_PERSON_SEARCH_FIELD = - -# Below are Single Color Elements -# They are Stored as Redvalue,Greenvalue,Bluevalue,Alphavalue -# Ranging from 0 - 255 -# an Alpha value of 255 means it is completly opaque -# an Alpha value of 0 means it is transparent -# all values must be set or it will produce errors -# they are preconfigured to look nice with the Windowstheme or the SubstanceBusinessBlueSteel Look -ChatInput.SelectedTextColor = 255,255,255,255 -ChatInput.SelectionColor = 10,36,106,255 -ContactItemNickname.foreground = 0,0,0,255 -ContactItemDescription.foreground = 128,128,128,255 -ContactItem.background = 240,243,253,255 -ContactItemOffline.color = 128,128,128,255 -Link.foreground = 0,0,255,255 -List.selectionBackground = 217,232,250,255 -List.selectionForeground = 0,0,0,255 -List.selectionBorder = 187,195,215,255 -List.foreground = 0,0,0,255 -List.background = 255,255,255,255 -TextField.lightforeground = 128,128,128,255 -TextField.foreground = 0,0,0,255 -TextField.caretForeground = 0,0,0,255 -TextPane.foreground = 0,0,0,255 -TextPane.background = 255,255,255,255 -TextPane.inactiveForeground = 255,255,255,255 -TextPane.caretForeground = 0,0,0,255 -MenuItem.selectionBackground = 217,232,250,255 -MenuItem.selectionForeground = 0,0,0,255 -Table.foreground = 0,0,0,255 -Table.background = 255,255,255,255 -## ChatWindow Colors: ## -Address.foreground = 212,160,0,255 -User.foreground = 0,0,255,255 -OtherUser.foreground = 255,0,0,255 -Notification.foreground = 0,128,0,255 -Error.foreground = 255,0,0,255 -Question.foreground = 255,0,0,255 -History.foreground = 64,64,64,255 -SparkTabbedPane.startColor = 236,236,236,255 -SparkTabbedPane.endColor = 236,236,236,255 -SparkTabbedPane.borderColor = 192,192,192,255 -Chat.activeTabColor = 0,0,0,255 -Chat.inactiveTabColor = 80,80,80,255 -Chat.unreadMessageColor = 255,0,0,255 diff --git a/src/java/org/jivesoftware/resource/sounds.properties b/src/java/org/jivesoftware/resource/sounds.properties deleted file mode 100644 index dfce29d45..000000000 --- a/src/java/org/jivesoftware/resource/sounds.properties +++ /dev/null @@ -1,5 +0,0 @@ -# List all sound files -INCOMING_USER = sounds/chat_request.wav -TRAY_SHOWING = sounds/bell.wav -OPENING = sounds/opening.wav -CLOSING = sounds/close.wav diff --git a/src/java/org/jivesoftware/resource/spark.properties b/src/java/org/jivesoftware/resource/spark.properties deleted file mode 100644 index d7117c5ef..000000000 --- a/src/java/org/jivesoftware/resource/spark.properties +++ /dev/null @@ -1,356 +0,0 @@ -APP_NAME = Spark -VERSION = Version 1.0 Release - -SPARK_IMAGE = images/spark.png -WELCOME = Welcome -ID_CARD_48x48 = images/id_card.png - -# LOGIN DIALOG -LOGIN_DIALOG_LOGIN = &Login -LOGIN_DIALOG_QUIT = &Quit -LOGIN_DIALOG_USERNAME = &Username: -LOGIN_DIALOG_PASSWORD = &Password: -LOGIN_DIALOG_WORKSPACE = &Workgroup: -LOGIN_DIALOG_LOGIN_TITLE = Spark -LOGIN_DIALOG_AUTHENTICATING = Authenticating... - - -# PrivacyPlugin -PRIVACY_QUERY_DENY = images/privacy_query_deny.png -PRIVACY_QUERY_ALLOW = images/privacy_query_allow.png -PRIVACY_POUT_DENY = images/privacy_presence_out_deny.png -PRIVACY_POUT_ALLOW = images/privacy_presence_out_allow.png -PRIVACY_PIN_DENY = images/privacy_presence_in_deny.png -PRIVACY_PIN_ALLOW = images/privacy_presence_in_allow.png -PRIVACY_MSG_DENY = images/privacy_message_deny.png -PRIVACY_MSG_ALLOW = images/privacy_message_allow.png -CLIPBOARD = images/clipboard.png -PRIVACY_ICON = images/privacy_icon.png -PRIVACY_ICON_SMALL = images/privacy_icon_small.png -PRIVACY_LIGHTNING = images/privacy_lightning.png -PRIVACY_CHECK = images/privacy_check.png -PRIVACY_DEACTIVATE_LIST = images/privacy_list_deactivate.png - - - -#MainWindow -MAIN_IMAGE = images/spark-64x64.png -TRAY_IMAGE = images/spark-16x16.png -TRAY_AWAY = images/Away.png -TRAY_DND = images/DoNotDisturb.png -TRAY_OFFLINE = images/spark_tray_offline-16x16.png -TRAY_CONNECTING = images/spark_tray_connecting-16x16.png -TRAY_IMAGE_LINUX = images/spark-24x24.png -TRAY_AWAY_LINUX = images/Away-24x24.png -TRAY_DND_LINUX = images/DoNotDisturb-24x24.png -TRAY_OFFLINE_LINUX = images/spark_tray_offline-24x24.png -TRAY_CONNECTING_LINUX = images/spark_tray_connecting-24x24.png -SPARK_IMAGE_32x32 = images/spark-32x32.png -MAIN_IMAGE_ICO = images/icon_16.ico -MAIN_ICNS_FILE = images/message.icns -SMALL_CHECK = images/smallCheck.png -SMALL_DELETE = images/smallDelete.png -AVAILABLE_USER = images/availableUser.png -AWAY_USER = images/awayUser.png -FIND_IMAGE = images/find.png -SMALL_ADD_IMAGE = images/small_add.png -DOCUMENT_EXCHANGE_IMAGE = images/document_exchange.png -SMALL_DOCUMENT_ADD = images/document_add.png -SMALL_CIRCLE_DELETE = images/small_delete.png -SMALL_DOCUMENT_VIEW = images/document_view.png -SMALL_USER1_MESSAGE = images/user1_message-16x16.png -USER1_MESSAGE_24x24 = images/user1_message-24x24.png -SMALL_USER1_TIME = images/user1_time.png -SMALL_USER1_NEW = images/user1_new.png -SMALL_USER1_STOPWATCH = images/stopwatch_pause.png -SMALL_USER1_MOBILEPHONE = images/user1_mobilephone.png -SMALL_USER1_INFORMATION = images/user1_information.png -SMALL_ENTRY = images/small_entry.gif -SMALL_AGENT_IMAGE = images/small_agent.png -CHATTING_AGENT_IMAGE = images/user1.png -CHATTING_CUSTOMER_IMAGE = images/user2.png -INFORMATION_IMAGE = images/information.png -BLANK_IMAGE = images/blank.gif -USER_HEADSET_24x24 = images/user_headset24.png -FOLDER_CLOSED = images/folder_closed.png -FOLDER = images/folder.png -SMALL_PIN_BLUE = images/pin_blue.png -SMALL_DATA_FIND_IMAGE = images/data_find.png -SMALL_BUSINESS_MAN_VIEW = images/businessman_view.png -SMALL_ALL_AGENTS_IMAGE = images/user1_earth.png -SMALL_WORKGROUP_QUEUE_IMAGE = images/users_into.png -SMALL_ALL_CHATS_IMAGE = images/users_family.png -SMALL_CURRENT_AGENTS = images/users2.png -HELP2_24x24 = images/help_24x24.png -SMALL_ALARM_CLOCK = images/alarmclock.png -SMALL_SCROLL_REFRESH = images/scroll_refresh.png -SMALL_QUESTION = images/help_16x16.png -USER1_32x32 = images/User1_32x32.png -DATA_DELETE_16x16 = images/data_delete.png -DATA_REFRESH_16x16 = images/data_refresh.png -USER1_BACK_16x16 = images/user1_back.png -FONT_16x16 = images/font.png -DOCUMENT_FIND_16x16 = images/document_find.png -DOCUMENT_INFO_32x32 = images/document_info.png -DOCUMENT_16x16 = images/document.png -SMALL_CLOSE_BUTTON = images/deleteitem.gif -COPY_16x16 = images/copy.png -BLANK_24x24 = images/blank_24x24.png -PUSH_URL_16x16 = images/earth_connection-16x16.png -LINK_16x16 = images/link-16x16.png -LINK_DELETE_16x16 = images/link_delete.png -EARTH_LOCK_16x16 = images/earth_lock-16x16.png -LOCK_16x16 = images/lock-16x16.png -BLOCK_CONTACT_16x16 = images/privacy_block_16x16.png -UNBLOCK_CONTACT_16x16 = images/privacy_unblock_16x16.png -LOCK_UNLOCK_16x16 = images/lock_unlock-16x16.png -ONLINE_ICO = images/icon1.ico -OFFLINE_ICO = images/icon2.ico -INFORMATION_ICO = images/icon3.ico -SAVE_AS_16x16 = images/save_as.png -NOTE_EDIT_16x16 = images/note_edit.png -ADDRESS_BOOK_16x16 = images/address_book.png -MEGAPHONE_16x16 = images/megaphone.png -EARTH_VIEW_16x16 = images/earth_view.png -HISTORY_16x16 = images/history.png -DOWNLOAD_16x16 = images/download.png -RED_FLAG_16x16 = images/flag_red.png -GREEN_FLAG_16x16 = images/flag_green.png -YELLOW_FLAG_16x16 = images/flag_yellow.png -FUNNEL_DOWN_16x16 = images/funnel_down.png -MAIL_16x16 = images/mail_16x16.png -MAIL_FORWARD_16x16 = images/mail_forward_16x16.png -MAIL_INTO_16x16 = images/mail_into_16x16.png -RED_BALL = images/red-ball.png -GREEN_BALL = images/im_available.png -BLUE_BALL = images/blue-ball.png -YELLOW_BALL = images/yellow-ball.png -PAWN_GLASS_GREEN = images/pawn_glass_green.png -PAWN_GLASS_RED = images/pawn_glass_red.png -PAWN_GLASS_WHITE = images/pawn_glass_white.png -PAWN_GLASS_YELLOW = images/pawn_glass_yellow.png -PLUS_SIGN = images/plus-sign.png -MINUS_SIGN = images/minus-sign.png -MAGICIAN_IMAGE = images/magician.png -FIND_TEXT_IMAGE = images/find_text.png -LOGIN_KEY_IMAGE = images/login-key.png -BRICKWALL_IMAGE = images/brickwall.png -MODERATOR_IMAGE = images/moderator.gif -DESKTOP_IMAGE = images/desktop.png -SPELL_CHECK_IMAGE = images/spellcheck_16x16.png -BUSY_IMAGE = images/busy.gif -CLOSE_IMAGE = images/close.png -VIEW_IMAGE = images/view.png -MOBILE_PHONE_IMAGE = images/mobilephone.png -ON_PHONE_IMAGE = images/on-phone.png -REFRESH_IMAGE = images/refresh.png -CLOSE_WHITE_X_IMAGE = images/close_white.png -CLOSE_DARK_X_IMAGE = images/close_dark.png -PALETTE_24x24_IMAGE = images/palette_24x24.png -COLOR_ICON = images/colors.png -DEFAULT_AVATAR_16x16_IMAGE = images/default_avatar_16x16.png -DEFAULT_AVATAR_32x32_IMAGE = images/default_avatar_32x32.png -DEFAULT_AVATAR_64x64_IMAGE = images/default_avatar_64x64.png - -# Global Values -ERROR_INVALID_WORKGROUP = The workgroup is not valid. Please use a valid workgroup. -ERROR_DIALOG_TITLE = Login Error -INVALID_USERNAME_PASSWORD = Invalid username or password. -SERVER_UNAVAILABLE = Can't connect to server: invalid name or server not reachable. -UNRECOVERABLE_ERROR = Invalid username or password. - -#Chat Window Images -ALERT = images/alert.png -FRAME_ALWAYS_ON_TOP_ACTIVE = images/window_to_front_active.png -FRAME_ALWAYS_ON_TOP_DEACTIVE = images/window_to_front_deactive.png - - -#Chat window text -SEND = &Send -ADD_TO_KB = You can assign any response as either a question or an answer add them directly to the knowledge base for future reference. - -#Kbase Window -GO = &Go -ADD_TO_CHAT = &Add document -ADD_LINK_TO_CHAT = Add &link -VIEW = &View -SEARCH = &Search: - -#Chat Queue -ACCEPT_CHAT = &Accept -REJECT_CHAT = &Refuse -TIME_LEFT = Time left: - -#MainWindow -MAIN_TITLE = Spark -TOOLBOX = Toolbox -CHAT_QUEUE = Chat Queue -CURRENT_CHATS = My Chats -CURRENT_AGENTS = Online Agents -ALL_CHATS = All Chats -WORKGROUP_QUEUE = Queues -CHAT_WORKSPACE = Chat Workspace - -#GroupChat -CREATE_FAQ_ENTRY = Create a new FAQ entry? -CREATE_FAQ_TITLE = Create New FAQ -FAQ_TAB_TITLE = Analyzer -KNOWLEDGE_BASE_TAB_TITLE = Search -PROFILE_TAB_TITLE = Profile -CO_BROWSER_TAB_TITLE = Co-Browser -FORUM_TAB_TITLE = Forums - -#Images -CANCEL_IMAGE = images/cancel.gif -CONFERENCE_IMAGE_24x24 = images/conference_24x24.png -CONFERENCE_IMAGE_16x16 = images/conference_16x16.png -PROFILE_IMAGE_24x24 = images/profile_24x24.png -SEARCH_USER_16x16 = images/search_user_16x16.png -SEND_FILE_24x24 = images/send_file_24x24.png -ADD_IMAGE_24x24 = images/add_24x24.png -TELEPHONE_24x24 = images/telephone_24x24.png -IM_DND = images/im_dnd.png -IM_AWAY = images/im_away.png -INVISIBLE = images/im_invisible.png -MESSAGE_AWAY = images/Away.png -MESSAGE_DND = images/DoNotDisturb.png -MESSAGE_NEW_TRAY = images/spark_tray_message-16x16.png -MESSAGE_NEW_TRAY_LINUX = images/spark_tray_message-24x24.png -TYPING_TRAY = images/message_edit.png -TYPING_TRAY_LINUX = images/spark_tray_typing-24x24.png -OFFLINE_IMAGE = images/Offline.png -ERASER_IMAGE = images/eraser.png -TOOLBAR_BACKGROUND = images/toolbar.png -TRAFFIC_LIGHT_IMAGE = images/traffic-light.png -SERVER_ICON = images/server.png -BOOKMARK_ICON = images/bookmark.png -ADD_BOOKMARK_ICON = images/bookmark_add.png -DELETE_BOOKMARK_ICON = images/bookmark_delete.png -CLEAR_BALL_ICON = images/im_unavailable.png -CALL_ICON = images/call.png -PROFILE_ICON = images/profile.png -SEND_FILE_ICON = images/document_into.png -ADD_CONTACT_IMAGE = images/add_contact.png -JOIN_GROUPCHAT_IMAGE = images/join_groupchat.png -PEOPLE_IMAGE = images/people-icon.png -DOWN_ARROW_IMAGE = images/down_arrow.gif -PRINTER_IMAGE_16x16 = images/printer.png -SEND_MAIL_IMAGE_16x16 = images/sendmail.png -SEARCH_IMAGE_32x32 = images/search_32x32.png -MAIL_IMAGE_32x32 = images/mail_32x32.png -PREFERENCES_IMAGE = images/preferences.png -NOTEBOOK_IMAGE = images/notebook.png -TEXT_BOLD = images/text_bold.png -TEXT_ITALIC = images/text_italics.png -TEXT_UNDERLINE = images/text_underlined.png -TEXT_NORMAL = images/text_normal.png -SMALL_USER_ENTER = images/smallUserEnter.png -SMALL_USER_DELETE = images/smallUserDelete.png -QUESTIONS_ANSWERS = images/questionsAnswers.png -SMALL_MESSAGE_IMAGE = images/message.png -SMALL_MESSAGE_EDIT_IMAGE = images/message_edit.png -SMALL_ABOUT_IMAGE = images/about.png -DOOR_IMAGE = images/door.gif -STAR_BLUE_IMAGE = images/star_blue.png -STAR_RED_IMAGE = images/star_red.png -STAR_GREY_IMAGE = images/star_grey.png -STAR_YELLOW_IMAGE = images/star_yellow.png -STAR_GREEN_IMAGE = images/star_green.png -STAR_OWNER = images/star_owner.png -STAR_ADMIN = images/star_admin.png -STAR_MODERATOR = images/star_moderator.png -LEFT_ARROW_IMAGE = images/arrow_left_green.png -RIGHT_ARROW_IMAGE = images/arrow_right_green.png -BACKGROUND_IMAGE = images/background.png -FREE_TO_CHAT_IMAGE = images/im_free_chat.png -SOUND_PREFERENCES_IMAGE = images/text_loudspeaker.png -SPARK_LOGOUT_IMAGE = images/spark_100.jpg -PHOTO_IMAGE = images/photo_scenery.png -PLUGIN_IMAGE = images/plugin-16x16.gif -SMALL_PROFILE_IMAGE = images/small_profile.png -CHANGELOG_IMAGE = images/doc-changelog-16x16.gif -README_IMAGE = images/doc-readme-16x16.gif -DOWN_OPTION_IMAGE = images/option.png -STICKY_NOTE_IMAGE = images/sticky.png -HISTORY_24x24 = images/history-24x24.png -PANE_UP_ARROW_IMAGE = images/blueArrowRight.png -PANE_DOWN_ARROW_IMAGE = images/blueArrowDown.png -PROFILE_IMAGE_16x16 = images/profile_16x16.png -LIGHTBULB_ON_16x16_IMAGE = images/lightbulb_on.png -DUMMY_CONTACT_IMAGE = images/dummyContact.png -CALENDAR_IMAGE = images/icon_calendarpicker.gif -TASK_DELETE_IMAGE = images/delete.png - -#Fastpath Icons -FASTPATH_IMAGE_16x16 = images/fastpath16.png -FASTPATH_IMAGE_24x24 = images/fastpath24.png -FASTPATH_IMAGE_32x32 = images/fastpath32.png -FASTPATH_IMAGE-64x63 = images/fastpath64.png -CIRCLE_CHECK_IMAGE = images/check.png -TRANSFER_IMAGE_24x24 = images/transfer-24x24.png -FASTPATH_OFFLINE_IMAGE_16x16 = images/fastpath16_offline.png -FASTPATH_OFFLINE_IMAGE_24x24 = images/fastpath24_offline.png -USER1_ADD_16x16 = images/user1_add.png -END_BUTTON_24x24 = images/end_button_24x24.png -POWERED_BY_IMAGE = images/powered_by.png - -# Transport images -AIM_TRANSPORT_ACTIVE_IMAGE = images/aim.gif -AIM_TRANSPORT_INACTIVE_IMAGE = images/aim-gray.gif -MSN_TRANSPORT_ACTIVE_IMAGE = images/msn.png -MSN_TRANSPORT_INACTIVE_IMAGE = images/msn-gray.png -YAHOO_TRANSPORT_ACTIVE_IMAGE = images/yahoo.png -YAHOO_TRANSPORT_INACTIVE_IMAGE = images/yahoo-gray.png -ICQ_TRANSPORT_ACTIVE_IMAGE = images/icq.png -ICQ_TRANSPORT_INACTIVE_IMAGE = images/icq-gray.png -GTALK_TRANSPORT_ACTIVE_IMAGE = images/gtalk.png -GTALK_TRANSPORT_INACTIVE_IMAGE = images/gtalk-gray.png -XMPP_TRANSPORT_ACTIVE_IMAGE = images/xmpp.png -XMPP_TRANSPORT_INACTIVE_IMAGE = images/xmpp-gray.png -IRC_TRANSPORT_ACTIVE_IMAGE = images/irc.png -IRC_TRANSPORT_INACTIVE_IMAGE = images/irc-gray.png -GADUGADU_TRANSPORT_ACTIVE_IMAGE = images/gadugadu.gif -GADUGADU_TRANSPORT_INACTIVE_IMAGE = images/gadugadu-gray.gif -SIMPLE_TRANSPORT_ACTIVE_IMAGE = images/simple.png -SIMPLE_TRANSPORT_INACTIVE_IMAGE = images/simple-gray.png -QQ_TRANSPORT_ACTIVE_IMAGE = images/qq.gif -QQ_TRANSPORT_INACTIVE_IMAGE = images/qq-gray.gif -FACEBOOK_TRANSPORT_ACTIVE_IMAGE= images/facebook.gif -FACEBOOK_TRANSPORT_INACTIVE_IMAGE= images/facebook-gray.gif -MYSPACE_TRANSPORT_ACTIVE_IMAGE= images/myspaceim.gif -MYSPACE_TRANSPORT_INACTIVE_IMAGE= images/myspaceim-gray.gif -SAMETIME_TRANSPORT_ACTIVE_IMAGE= images/sametime.gif -SAMETIME_TRANSPORT_INACTIVE_IMAGE= images/sametime-gray.gif -TRANSPORT_ICON = images/transport.png -SMALL_STOP = images/smallStop.png - -#Stale Images -IM_AVAILABLE_STALE_IMAGE = images/im_available_stale.png -IM_AWAY_STALE_IMAGE = images/im_away_stale.png -IM_DND_STALE_IMAGE = images/im_dnd_stale.png -IM_FREE_CHAT_STALE_IMAGE = images/im_free_chat_stale.png -IM_UNAVAILABLE_STALE_IMAGE = images/im_unavailable_stale.png - -#Misc -DIVIDER_IMAGE = images/divider.png -LIGHTING_BOLT_IMAGE = images/lightning16.png -HEADSET_IMAGE = images/headset.png -BUZZ_IMAGE = images/bell.png -SETTINGS_IMAGE_16x16 = images/settings16x16.png -SETTINGS_IMAGE_24x24 = images/settings24x24.png - -#Phone -DIAL_PHONE_IMAGE_24x24 = images/phone_call.png -DIAL_PHONE_IMAGE_16x16 = images/icon_phone-call_16x16.png -COMPUTER_IMAGE_16x16 = images/icon_computer_16x16.png - -# Conferences -CONFERENCE_IMAGE_48x48 = images/messages_48x48.png -ACCEPT_INVITE_IMAGE = images/accept.png -REJECT_INVITE_IMAGE = images/reject.png -INVITE_MORE_IMAGE = images/invitemore.png -FILTER_LABEL = Search - -# Lanuage -LANGUAGE_ICON = images/language_plugin.png -EXECUTABLE_NAME = Spark.exe diff --git a/src/java/org/jivesoftware/spark/ButtonFactory.java b/src/java/org/jivesoftware/spark/ButtonFactory.java deleted file mode 100644 index 4074118e9..000000000 --- a/src/java/org/jivesoftware/spark/ButtonFactory.java +++ /dev/null @@ -1,114 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2011 eZuce Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark; - -import java.net.URL; - -import javax.swing.ImageIcon; -import javax.swing.JLabel; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.ui.ChatRoomButton; -import org.jivesoftware.sparkimpl.plugin.emoticons.Emoticon; -import org.jivesoftware.sparkimpl.plugin.emoticons.EmoticonManager; - -public class ButtonFactory { - - private static ButtonFactory instance = new ButtonFactory(); - - protected ButtonFactory() { - // nothing - } - - public static ButtonFactory getInstance() { - return instance; - } - - public ChatRoomButton createChatTranscriptButton() { - return new ChatRoomButton(SparkRes.getImageIcon(SparkRes.HISTORY_24x24_IMAGE)); - } - - public ChatRoomButton createSendFileButton() { - return new ChatRoomButton("", SparkRes.getImageIcon(SparkRes.SEND_FILE_24x24)); - } - - public ChatRoomButton createScreenshotButton() { - return new ChatRoomButton("", SparkRes.getImageIcon(SparkRes.PHOTO_IMAGE)); - } - - public ChatRoomButton createInviteConferenceButton() { - return new ChatRoomButton("", SparkRes.getImageIcon(SparkRes.CONFERENCE_IMAGE_24x24)); - } - - public RolloverButton createBuzzButton() { - return new RolloverButton(SparkRes.getImageIcon(SparkRes.BUZZ_IMAGE)); - } - - public RolloverButton createEmoticonButton() { - final EmoticonManager emoticonManager = EmoticonManager.getInstance(); - final String activeEmoticonSetName = emoticonManager.getActiveEmoticonSetName(); - final Emoticon smileEmoticon = emoticonManager.getEmoticon(activeEmoticonSetName, ":)"); - URL smileURL = emoticonManager.getEmoticonURL(smileEmoticon); - ImageIcon icon = new ImageIcon(smileURL); - - return new RolloverButton(icon); - } - - public JLabel createDivider() { - return new JLabel(SparkRes.getImageIcon("DIVIDER_IMAGE")); - } - - public RolloverButton createSettingsButton() { - RolloverButton settings = new RolloverButton(SparkRes.getImageIcon(SparkRes.SETTINGS_IMAGE_16x16)); - settings.setToolTipText(Res.getString("title.configure.room")); - return settings; - } - - public RolloverButton createTemaButton() { - RolloverButton thema = new RolloverButton(SparkRes.getImageIcon(SparkRes.TYPING_TRAY)); - thema.setToolTipText(Res.getString("menuitem.change.subject")); - return thema; - } - - public RolloverButton createRegisterButton() { - RolloverButton register = new RolloverButton(SparkRes.getImageIcon(SparkRes.PEOPLE_IMAGE)); - register.setToolTipText(Res.getString("button.register").replace("&", "")); - return register; - } - - public RolloverButton createAlwaysOnTop(boolean isAlwaysOnTopActive) { - RolloverButton alwaysOnTopItem = new RolloverButton(); - if (isAlwaysOnTopActive) { - alwaysOnTopItem.setIcon(SparkRes.getImageIcon("FRAME_ALWAYS_ON_TOP_ACTIVE")); - } else { - alwaysOnTopItem.setIcon(SparkRes.getImageIcon("FRAME_ALWAYS_ON_TOP_DEACTIVE")); - } - - alwaysOnTopItem.setToolTipText(Res.getString("menuitem.always.on.top")); - return alwaysOnTopItem; - - } - - public ChatRoomButton createOtrButton() { - return new ChatRoomButton(); - } -} diff --git a/src/java/org/jivesoftware/spark/ChatManager.java b/src/java/org/jivesoftware/spark/ChatManager.java deleted file mode 100644 index 82bb5cf38..000000000 --- a/src/java/org/jivesoftware/spark/ChatManager.java +++ /dev/null @@ -1,889 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.chat.Chat; -import org.jivesoftware.smack.chat.ChatManagerListener; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smackx.chatstates.ChatState; -import org.jivesoftware.smackx.chatstates.ChatStateListener; -import org.jivesoftware.smackx.muc.MultiUserChatManager; -import org.jivesoftware.smackx.xdata.Form; -import org.jivesoftware.smackx.muc.MultiUserChat; -import org.jivesoftware.smackx.xdata.packet.DataForm; -import org.jivesoftware.spark.component.tabbedPane.SparkTab; -import org.jivesoftware.spark.decorator.DefaultTabHandler; -import org.jivesoftware.spark.ui.ChatContainer; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomListener; -import org.jivesoftware.spark.ui.ChatRoomNotFoundException; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactItemHandler; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.ui.GlobalMessageListener; -import org.jivesoftware.spark.ui.MessageFilter; -import org.jivesoftware.spark.ui.SparkTabHandler; -import org.jivesoftware.spark.ui.TranscriptWindowInterceptor; -import org.jivesoftware.spark.ui.conferences.RoomInvitationListener; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.ui.rooms.GroupChatRoom; -import org.jivesoftware.spark.uri.UriManager; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.UIComponentRegistry; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -import java.awt.Color; -import java.awt.Component; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArrayList; - -import javax.swing.Icon; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; - -/** - * Handles the Chat Management of each individual Workspace. The ChatManager is responsible - * for creation and removal of chat rooms, transcripts, and transfers and room invitations. - */ -public class ChatManager implements ChatManagerListener { - - private static ChatManager singleton; - private static final Object LOCK = new Object(); - - // Define Default Colors - public static Color TO_COLOR = (Color)UIManager.get("User.foreground"); - public static Color FROM_COLOR = (Color)UIManager.get("OtherUser.foreground"); - public static Color NOTIFICATION_COLOR = (Color)UIManager.get("Notification.foreground"); - public static Color ERROR_COLOR = (Color)UIManager.get("Error.foreground"); - - public static Color[] COLORS = {Color.red, Color.blue, Color.gray, Color.magenta, new Color(238, 153, 247), new Color(128, 128, 0), new Color(173, 205, 50), - new Color(181, 0, 0), new Color(0, 100, 0), new Color(237, 150, 122), new Color(0, 139, 139), new Color(218, 14, 0), new Color(147, 112, 219), - new Color(205, 133, 63), new Color(163, 142, 35), new Color(72, 160, 237), new Color(255, 140, 0), new Color(106, 90, 205), new Color(224, 165, 32), - new Color(255, 69, 0), new Color(255, 99, 72), new Color(109, 130, 180), new Color(233, 0, 0), new Color(139, 69, 19), new Color(255, 127, 80), - new Color(140, 105, 225)}; - - private List messageFilters = new ArrayList<>(); - - private List globalMessageListeners = new ArrayList<>(); - - private List invitationListeners = new ArrayList<>(); - - private List interceptors = new ArrayList<>(); - - private List sparkTabHandlers = new CopyOnWriteArrayList<>(); - - - private final ChatContainer chatContainer; - - private String conferenceService; - - private List contactItemHandlers = new ArrayList<>(); - - private Set typingNotificationList = new HashSet<>(); - - private UriManager _uriManager = new UriManager(); - - private List chatMessageHandlers = new ArrayList<>(); - - /** - * The listener instance that we use to track chat states according to - * XEP-0085; - */ - private SmackChatStateListener smackChatStateListener = null; - - /** - * Returns the singleton instance of ChatManager, - * creating it if necessary. - *

      - * - * @return the singleton instance of ChatManager - */ - public static ChatManager getInstance() { - // Synchronize on LOCK to ensure that we don't end up creating - // two singletons. - synchronized (LOCK) { - if (null == singleton) { - ChatManager controller = new ChatManager(); - singleton = controller; - return controller; - } - } - return singleton; - } - - - /** - * Create a new instance of ChatManager. - */ - private ChatManager() { - chatContainer = UIComponentRegistry.createChatContainer(); - - // Add Default Chat Room Decorator - addSparkTabHandler(new DefaultTabHandler()); - // Add a Message Handler - org.jivesoftware.smack.chat.ChatManager.getInstanceFor( SparkManager.getConnection() ).addChatListener(this); - } - - - /** - * Used to listen for rooms opening, closing or being - * activated( already opened, but tabbed to ) - * - * @param listener the ChatRoomListener to add - */ - public void addChatRoomListener(ChatRoomListener listener) { - getChatContainer().addChatRoomListener(listener); - } - - /** - * Simplace facade for chatroom. Removes a listener - * - * @param listener the ChatRoomListener to remove - */ - public void removeChatRoomListener(ChatRoomListener listener) { - getChatContainer().removeChatRoomListener(listener); - } - - - /** - * Removes the personal 1 to 1 chat from the ChatFrame. - * - * @param chatRoom the ChatRoom to remove. - */ - public void removeChat(ChatRoom chatRoom) { - chatContainer.closeTab(chatRoom); - } - - - /** - * Returns all ChatRooms currently active. - * - * @return all ChatRooms. - */ - public ChatContainer getChatContainer() { - return chatContainer; - } - - /** - * Returns the MultiUserChat associated with the specified roomname. - * - * @param roomName the name of the chat room. - * @return the MultiUserChat found for that room. - * @throws ChatNotFoundException thrown if no ChatRoom is found. - */ - public GroupChatRoom getGroupChat(String roomName) throws ChatNotFoundException { - for (ChatRoom chatRoom : getChatContainer().getChatRooms()) { - if (chatRoom instanceof GroupChatRoom) { - GroupChatRoom groupChat = (GroupChatRoom)chatRoom; - if (groupChat.getRoomname().equals(roomName)) { - return groupChat; - } - } - - } - - throw new ChatNotFoundException("Could not locate Group Chat Room - " + roomName); - } - - - /** - * Creates and/or opens a chat room with the specified user. - * - * @param userJID the jid of the user to chat with. - * @param nickname the nickname to use for the user. - * @param title the title to use for the room. - * @return the newly created ChatRoom. - */ - public ChatRoom createChatRoom(String userJID, String nickname, String title) { - ChatRoom chatRoom; - try { - chatRoom = getChatContainer().getChatRoom(userJID); - } - catch (ChatRoomNotFoundException e) { - chatRoom = UIComponentRegistry.createChatRoom(userJID, nickname, title); - getChatContainer().addChatRoom(chatRoom); - } - - return chatRoom; - } - - /** - * Returns the ChatRoom for the giving jid. If the ChatRoom is not found, - * a new ChatRoom will be created. - * - * @param jid the jid of the user to chat with. - * @return the ChatRoom. - */ - public ChatRoom getChatRoom(String jid) { - ChatRoom chatRoom; - try { - chatRoom = getChatContainer().getChatRoom(jid); - } - catch (ChatRoomNotFoundException e) { - ContactList contactList = SparkManager.getWorkspace().getContactList(); - ContactItem item = contactList.getContactItemByJID(jid); - if (item != null) { - String nickname = item.getDisplayName(); - chatRoom = UIComponentRegistry.createChatRoom(jid, nickname, nickname); - } - else { - chatRoom = UIComponentRegistry.createChatRoom(jid, jid, jid); - } - - - getChatContainer().addChatRoom(chatRoom); - } - - return chatRoom; - } - - /** - * Creates a new public Conference Room. - * - * @param roomName the name of the room. - * @param serviceName the service name to use (ex.conference.jivesoftware.com) - * @return the new ChatRoom created. If an error occured, null will be returned. - */ - public ChatRoom createConferenceRoom(String roomName, String serviceName) { - final MultiUserChat chatRoom = MultiUserChatManager.getInstanceFor( SparkManager.getConnection()).getMultiUserChat( roomName + "@" + serviceName ); - - final GroupChatRoom room = UIComponentRegistry.createGroupChatRoom(chatRoom); - - try { - LocalPreferences pref = SettingsManager.getLocalPreferences(); - chatRoom.create(pref.getNickname()); - - // Send an empty room configuration form which indicates that we want - // an instant room - chatRoom.sendConfigurationForm(new Form( DataForm.Type.submit )); - } - catch (XMPPException | SmackException e1) { - Log.error("Unable to send conference room chat configuration form.", e1); - return null; - } - - getChatContainer().addChatRoom(room); - return room; - } - - /** - * Activate a chat room with the selected user. - * - * @param jid the jid of the user to chat with. - * @param nickname the nickname of the user. - */ - public void activateChat(final String jid, final String nickname) { - if (!ModelUtil.hasLength(jid)) { - return; - } - - SwingWorker worker = new SwingWorker() { - final ChatManager chatManager = SparkManager.getChatManager(); - ChatRoom chatRoom; - - public Object construct() { - try { - Thread.sleep(10); - } - catch (InterruptedException e) { - Log.error("Error in activate chat.", e); - } - - ChatContainer chatRooms = chatManager.getChatContainer(); - - try { - chatRoom = chatRooms.getChatRoom(jid); - } - catch (ChatRoomNotFoundException e) { - // Do nothing - } - return chatRoom; - } - - public void finished() { - if (chatRoom == null) { - chatRoom = UIComponentRegistry.createChatRoom(jid, nickname, nickname); - chatManager.getChatContainer().addChatRoom(chatRoom); - } - chatManager.getChatContainer().activateChatRoom(chatRoom); - } - }; - - worker.start(); - - } - - /** - * Checks if a ChatRoom exists. - * - * @param jid the jid of the user. - * @return true if the ChatRoom exists. - */ - public boolean chatRoomExists(String jid) { - try { - getChatContainer().getChatRoom(jid); - } - catch (ChatRoomNotFoundException e) { - return false; - } - return true; - } - - /** - * Adds a new MessageFilter. - * - * @param filter the MessageFilter. - */ - public void addMessageFilter(MessageFilter filter) { - messageFilters.add(filter); - } - - /** - * Removes a MessageFilter. - * - * @param filter the MessageFilter. - */ - public void removeMessageFilter(MessageFilter filter) { - messageFilters.remove(filter); - } - - /** - * Returns a Collection of MessageFilters registered to Spark. - * - * @return the Collection of MessageFilters. - */ - public Collection getMessageFilters() { - return messageFilters; - } - - /** - * Adds a new GlobalMessageListener. - * - * @param listener the listener. - */ - public void addGlobalMessageListener(GlobalMessageListener listener) { - globalMessageListeners.add(listener); - } - - /** - * Removes a GlobalMessageListener. - * - * @param listener the listener. - */ - public void removeGlobalMessageListener(GlobalMessageListener listener) { - globalMessageListeners.remove(listener); - } - - /** - * Notifies all GlobalMessageListeners of a new incoming message. - * - * @param chatRoom the ChatRoom where the message was sent to. - * @param message the Message - */ - public void fireGlobalMessageReceievedListeners(ChatRoom chatRoom, Message message) { - for (GlobalMessageListener listener : globalMessageListeners) { - listener.messageReceived(chatRoom, message); - } - } - - /** - * Notifies all GlobalMessageListeners of a new message sent. - * - * @param chatRoom the ChatRoom where the message was sent from. - * @param message the Message sent. - */ - public void fireGlobalMessageSentListeners(ChatRoom chatRoom, Message message) { - for (GlobalMessageListener listener : globalMessageListeners) { - listener.messageSent(chatRoom, message); - } - } - - /** - * Filters all incoming messages. - * - * @param room the room the message belongs to. - * @param message the message to filter. - */ - public void filterIncomingMessage(ChatRoom room, Message message) { - // Fire Message Filters - final ChatManager chatManager = SparkManager.getChatManager(); - Iterator filters = chatManager.getMessageFilters().iterator(); - try { - cancelledNotification(message.getFrom(), ChatState.paused); - } - catch (Exception e) { - Log.error(e); - } - - // Notify MessageFilters. - while (filters.hasNext()) { - (filters.next()).filterIncoming(room, message); - } - } - - /** - * Notifies all MessageFilters about a new outgoing message. - * - * @param room the ChatRoom the message belongs too. - * @param message the Message being sent. - */ - public void filterOutgoingMessage(ChatRoom room, Message message) { - // Fire Message Filters - final ChatManager chatManager = SparkManager.getChatManager(); - for (Object o : chatManager.getMessageFilters()) { - ((MessageFilter) o).filterOutgoing(room, message); - } - } - - /** - * Adds a RoomInvitationListener. A RoomInvitationListener is - * - * @param listener the listener. - */ - public void addInvitationListener(RoomInvitationListener listener) { - invitationListeners.add(listener); - } - - /** - * Removes a RoomInvitationListener. - * - * @param listener the listener to remove. - */ - public void removeInvitationListener(RoomInvitationListener listener) { - invitationListeners.remove(listener); - } - - /** - * Returns all registered RoomInvitationListeners. - * - * @return the Collection of listeners. - */ - public Collection getInvitationListeners() { - return Collections.unmodifiableCollection(invitationListeners); - } - - /** - * Returns the default conference service. (ex. conference.jivesoftware.com) - * - * @return the default conference service to interact with MUC. - */ - public String getDefaultConferenceService() { - if (conferenceService == null) { - try { - final MultiUserChatManager multiUserChatManager = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ); - Collection col = multiUserChatManager.getServiceNames(); - if (col.size() > 0) { - conferenceService = col.iterator().next(); - } - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - } - - return conferenceService; - } - - /** - * Adds a new ContactItemHandler. - * - * @param handler the ContactItemHandler to add. - */ - public void addContactItemHandler(ContactItemHandler handler) { - contactItemHandlers.add(handler); - } - - public void addChatMessageHandler(ChatMessageHandler handler) { - chatMessageHandlers.add(handler); - } - - public void removeChatMessageHandler(ChatMessageHandler handler) { - chatMessageHandlers.remove(handler); - } - - /** - * Removes a ContactItemHandler. - * - * @param handler the ContactItemHandler to remove. - */ - public void removeContactItemHandler(ContactItemHandler handler) { - contactItemHandlers.remove(handler); - } - - public void fireMessageReceived(Message message) { - for (ChatMessageHandler handler : chatMessageHandlers) { - handler.messageReceived(message); - } - } - - /** - * Notifies all ContactItemHandlers of presence changes. - * - * @param item the ContactItem where the presence changed. - * @param presence the new presence. - * @return true if it was handled. - */ - public boolean fireContactItemPresenceChanged(ContactItem item, Presence presence) { - for (ContactItemHandler handler : contactItemHandlers) { - if (handler.handlePresence(item, presence)) { - return true; - } - } - - return false; - } - - /** - * Notifies all ContactItemHandlers that a ContactItem was double-clicked. - * - * @param item the ContactItem that was double clicked. - * @return true if the event was intercepted and handled. - */ - public boolean fireContactItemDoubleClicked(ContactItem item) { - for (ContactItemHandler handler : contactItemHandlers) { - if (handler.handleDoubleClick(item)) { - return true; - } - } - - return false; - } - - /** - * Returns the icon from a ContactItemHandler. - * - * @param jid the jid. - * @return the icon of the handler. - */ - public Icon getIconForContactHandler(String jid) { - for (ContactItemHandler handler : contactItemHandlers) { - Icon icon = handler.getIcon(jid); - if (icon != null) { - return icon; - } - } - - return null; - } - - /** - * Returns the icon to use in the tab. - * - * @param presence the presence. - * @return the icon. - */ - public Icon getTabIconForContactHandler(Presence presence) { - for (ContactItemHandler handler : contactItemHandlers) { - Icon icon = handler.getTabIcon(presence); - if (icon != null) { - return icon; - } - } - - return null; - } - - public void composingNotification(final String from) { - SwingUtilities.invokeLater( () -> { - final ContactList contactList = SparkManager.getWorkspace().getContactList(); - - ChatRoom chatRoom; - try { - chatRoom = getChatContainer().getChatRoom( XmppStringUtils.parseBareJid(from)); - if (chatRoom != null && chatRoom instanceof ChatRoomImpl) { - typingNotificationList.add(chatRoom); - // Notify Decorators - notifySparkTabHandlers(chatRoom); - ((ChatRoomImpl)chatRoom).notifyChatStateChange(ChatState.composing); - } - } - catch (ChatRoomNotFoundException e) { - // Do nothing - } - contactList.setIconFor(from, SparkRes.getImageIcon(SparkRes.SMALL_MESSAGE_EDIT_IMAGE)); - } ); - } - - public void cancelledNotification(final String from, final ChatState state) { - SwingUtilities.invokeLater( () -> { - ContactList contactList = SparkManager.getWorkspace().getContactList(); - - ChatRoom chatRoom; - try { - chatRoom = getChatContainer().getChatRoom(XmppStringUtils.parseBareJid(from)); - if (chatRoom != null && chatRoom instanceof ChatRoomImpl) { - typingNotificationList.remove(chatRoom); - // Notify Decorators - notifySparkTabHandlers(chatRoom); - ((ChatRoomImpl)chatRoom).notifyChatStateChange(state); - } - } - catch (ChatRoomNotFoundException e) { - // Do nothing - } - contactList.useDefaults(from); - } ); - } - - /** - * Adds a room where the user is typing. - * - * @param chatRoom the room where the user is typing. - */ - public void addTypingNotification(ChatRoom chatRoom) { - typingNotificationList.add(chatRoom); - } - - /** - * Removes a room from the typing notification list. - * - * @param chatRoom the room to remove. - */ - public void removeTypingNotification(ChatRoom chatRoom) { - typingNotificationList.remove(chatRoom); - } - - /** - * Returns true if the ChatRoom state is in typing mode. - * - * @param chatRoom the ChatRoom to check. - * @return true if in typing mode. - */ - public boolean containsTypingNotification(ChatRoom chatRoom) { - return typingNotificationList.contains(chatRoom); - } - - /** - * Returns true if the room is "stale". A stale room is a room that has - * not been active for a specific amount of time. - * - * @param chatRoom the ChatRoom. - * @return true if the room is stale. - */ - public boolean isStaleRoom(ChatRoom chatRoom) { - // Check if room is stale - return chatContainer.getStaleChatRooms().contains(chatRoom); - } - - /** - * Adds a TranscriptWindowInterceptor. - * - * @param interceptor the interceptor. - */ - public void addTranscriptWindowInterceptor(TranscriptWindowInterceptor interceptor) { - interceptors.add(interceptor); - } - - /** - * Removes a TranscriptWindowInterceptor. - * - * @param interceptor the interceptor. - */ - public void removeTranscriptWindowInterceptor(TranscriptWindowInterceptor interceptor) { - interceptors.remove(interceptor); - } - - /** - * Returns the list of TranscriptWindowInterceptors. - * - * @return the list of interceptors. - */ - public Collection getTranscriptWindowInterceptors() { - return interceptors; - } - - /** - * Adds a new ContainerDecorator. The ContainerDecorator will be added to the top of the stack and will therefore - * take priority on notification calls. If all decorators return false, the DefaultChatRoomDecorator will be used. - * - * @param decorator the decorator to add. - */ - public void addSparkTabHandler(SparkTabHandler decorator) { - sparkTabHandlers.add(0, decorator); - } - - /** - * Removes a ContainerDecorator - * - * @param decorator the decorator to remove. - */ - public void removeSparkTabHandler(SparkTabHandler decorator) { - sparkTabHandlers.remove(decorator); - } - - /** - * Notifies all ContainerDecorator - * - * @param component the component within the tab. - */ - public void notifySparkTabHandlers(Component component) { - final SparkTab tab = chatContainer.getTabContainingComponent(component); - if (tab == null) { - return; - } - boolean isChatFrameInFocus = getChatContainer().getChatFrame().isInFocus(); - boolean isSelectedTab = getChatContainer().getSelectedComponent() == component; - for (SparkTabHandler decorator : sparkTabHandlers) { - boolean isHandled = decorator.isTabHandled(tab, component, isSelectedTab, isChatFrameInFocus); - if (isHandled) { - tab.validateTab(); - return; - } - } - } - - /** - * Returns all selected users in the ContactList. - * - * @return all selected ContactItem in the ContactList. - */ - public Collection getSelectedContactItems() { - final ContactList contactList = SparkManager.getWorkspace().getContactList(); - return contactList.getSelectedUsers(); - } - - /** - * Handles XMPP URI Mappings. - * - * @param arguments - * the arguments passed into Spark. - */ - public void handleURIMapping(String arguments) { - if (arguments == null) { - return; - } - - URI uri; - try { - uri = new URI(arguments); - } catch (URISyntaxException e) { - Log.error("error parsing uri: "+arguments,e); - return; - } - if (!"xmpp".equalsIgnoreCase(uri.getScheme())) { - return; - } - - String query = uri.getQuery(); - if (query == null) { - // No query string, so assume the URI is xmpp:JID - String jid = _uriManager.retrieveJID(uri); - - UserManager userManager = SparkManager.getUserManager(); - String nickname = userManager.getUserNicknameFromJID(jid); - if (nickname == null) { - nickname = jid; - } - - ChatManager chatManager = SparkManager.getChatManager(); - ChatRoom chatRoom = chatManager.createChatRoom(jid, nickname, - nickname); - chatManager.getChatContainer().activateChatRoom(chatRoom); - } else if (query.startsWith(UriManager.uritypes.message.getXML())) { - try { - _uriManager.handleMessage(uri); - } catch (Exception e) { - Log.error("error with ?message URI", e); - } - } else if (query.startsWith(UriManager.uritypes.join.getXML())) { - try { - _uriManager.handleConference(uri); - } catch (Exception e) { - Log.error("error with ?join URI", e); - } - } else if (query.startsWith(UriManager.uritypes.subscribe.getXML())) { - try { - _uriManager.handleSubscribe(uri); - } catch (Exception e) { - Log.error("error with ?subscribe URI", e); - } - } else if (query.startsWith(UriManager.uritypes.unsubscribe.getXML())) { - try { - _uriManager.handleUnsubscribe(uri); - } catch (Exception e) { - Log.error("error with ?unsubscribe URI", e); - } - } else if (query.startsWith(UriManager.uritypes.roster.getXML())) { - try { - _uriManager.handleRoster(uri); - } catch (Exception e) { - Log.error("error with ?roster URI", e); - } - } else if (query.startsWith(UriManager.uritypes.remove.getXML())) { - try { - _uriManager.handleRemove(uri); - } catch (Exception e) { - Log.error("error with ?remove URI", e); - } - } - } - - @Override - public void chatCreated(Chat chat, boolean isLocal) { - if(smackChatStateListener == null) { - smackChatStateListener = new SmackChatStateListener(); - } - chat.addMessageListener(smackChatStateListener); - } - - /** - * The listener that we use to track chat state notifications according - * to XEP-0085. - */ - private class SmackChatStateListener implements ChatStateListener { - /** - * Called by smack when the state of a chat changes. - * - * @param chat the chat that is concerned by this event. - * @param state the new state of the chat. - */ - @Override - public void stateChanged(Chat chat, ChatState state) { - String participant = chat.getParticipant(); - if (ChatState.composing.equals(state)) { - composingNotification(participant); - } else { - cancelledNotification(participant, state); - } - - } - - @Override - public void processMessage(Chat arg0, Message arg1) { - // TODO Auto-generated method stub - } - } -} diff --git a/src/java/org/jivesoftware/spark/PluginManager.java b/src/java/org/jivesoftware/spark/PluginManager.java deleted file mode 100644 index 6c3cf7a14..000000000 --- a/src/java/org/jivesoftware/spark/PluginManager.java +++ /dev/null @@ -1,964 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark; - -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.Node; -import org.dom4j.io.SAXReader; -import org.jivesoftware.MainWindowListener; -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Default; -import org.jivesoftware.spark.PluginRes.ResourceType; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.plugin.PluginClassLoader; -import org.jivesoftware.spark.plugin.PluginDependency; -import org.jivesoftware.spark.plugin.PublicPlugin; -import org.jivesoftware.spark.util.StringUtils; -import org.jivesoftware.spark.util.URLFileSystem; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.JiveInfo; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -import java.awt.*; -import java.io.*; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.*; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -/** - * This manager is responsible for the loading of all Plugins and Workspaces within Spark environment. - * - * @author Derek DeMoro - */ -public class PluginManager implements MainWindowListener { - private final List plugins = new ArrayList<>(); - - private final List publicPlugins = new CopyOnWriteArrayList<>(); - private static PluginManager singleton; - private static final Object LOCK = new Object(); - /** - * The root Plugins Directory. - */ - public static File PLUGINS_DIRECTORY = new File(Spark.getBinDirectory().getParent(), "plugins").getAbsoluteFile(); - - private Plugin pluginClass; - private PluginClassLoader classLoader; - - private Collection _blacklistPlugins; - - /** - * Returns the singleton instance of PluginManager, - * creating it if necessary. - *

      - * - * @return the singleton instance of PluginManager - */ - public static PluginManager getInstance() { - // Synchronize on LOCK to ensure that we don't end up creating - // two singletons. - synchronized (LOCK) { - if (null == singleton) { - PluginManager controller = new PluginManager(); - singleton = controller; - return controller; - } - } - return singleton; - } - - private PluginManager() { - try { - PLUGINS_DIRECTORY = new File(Spark.getBinDirectory().getParentFile(), "plugins").getCanonicalFile(); - } - catch (IOException e) { - Log.error(e); - } - // Do not use deployable plugins if not installed. - if (System.getProperty("plugin") == null) { - movePlugins(); - } - - - // Create the extension directory if one does not exist. - if (!PLUGINS_DIRECTORY.exists()) { - PLUGINS_DIRECTORY.mkdirs(); - } - - _blacklistPlugins = Default.getPluginBlacklist(); - } - - private void movePlugins() { - // Current Plugin directory - File newPlugins = new File(Spark.getLogDirectory().getParentFile(), "plugins").getAbsoluteFile(); - newPlugins.mkdirs(); - deleteOldPlugins(newPlugins); - - File[] files = PLUGINS_DIRECTORY.listFiles(); - if (files != null) { - final int no = files.length; - for (int i = 0; i < no; i++) { - File file = files[i]; - if (file.isFile()) { - // Copy over - File newFile = new File(newPlugins, file.getName()); - - if (newFile.lastModified() >= file.lastModified()) { - continue; - } - - try { - URLFileSystem.copy(file.toURI().toURL(), newFile); - } - catch (IOException e) { - Log.error(e); - } - - } - } - } - - PLUGINS_DIRECTORY = newPlugins; - } - - /** - * Deletes Plugins in pathtosearch that have a different md5-hash than - * its correspondant in install\spark\plugins\ - * @param pathtosearch - */ - public void deleteOldPlugins(File pathtosearch) { - - String installPath = Spark.getBinDirectory().getParentFile() - + File.separator + "plugins" + File.separator; - - List installerFiles = Arrays.asList(new File(installPath) - .listFiles()); - - File[] oldFiles = pathtosearch.listFiles(); - if (oldFiles != null) { - for (File file : oldFiles) { - - if (file.isDirectory()) { - File jarFile = new File(pathtosearch, file.getName() - + ".jar"); - if (!jarFile.exists()) { - uninstall(file); - } else { - try { - File f = new File(installPath + jarFile.getName()); - if (installerFiles.contains(f)) { - String oldfile = StringUtils.getMD5Checksum(jarFile.getAbsolutePath()); - String newfile = StringUtils.getMD5Checksum(f.getAbsolutePath()); - - Log.debug(f.getAbsolutePath() + " " + jarFile.getAbsolutePath()); - Log.debug(newfile + " " + oldfile + " equal:" + oldfile.equals(newfile)); - - if (!oldfile.equals(newfile)) { - Log.debug("deleting: "+ file.getAbsolutePath() + "," + jarFile.getAbsolutePath()); - uninstall(file); - jarFile.delete(); - } - - } - - } catch (Exception e) { - Log.error("No such file", e); - } - } - - } - } - } - - } - - /** - * Loads all {@link Plugin} from the agent plugins.xml and extension lib. - */ - public void loadPlugins() { - // Delete all old plugins - File[] oldFiles = PLUGINS_DIRECTORY.listFiles(); - if (oldFiles != null) { - for (File file : oldFiles) { - if (file.isDirectory()) { - // Check to see if it has an associated .jar - File jarFile = new File(PLUGINS_DIRECTORY, file.getName() + ".jar"); - if (!jarFile.exists()) { - uninstall(file); - } - } - } - } - - updateClasspath(); - - // At the moment, the plug list is hardcode internally until I begin - // using external property files. All depends on deployment. - final URL url = getClass().getClassLoader().getResource("META-INF/plugins.xml"); - try { - InputStreamReader reader = new InputStreamReader(url.openStream()); - loadInternalPlugins(reader); - } - catch (IOException e) { - Log.error("Could not load plugins.xml file."); - } - - // Load extension plugins - loadPublicPlugins(); - - // For development purposes, load the plugin specified by -Dplugin=... - String plugin = System.getProperty("plugin"); - if (plugin != null) { - final StringTokenizer st = new StringTokenizer(plugin, ",", false); - while (st.hasMoreTokens()) { - String token = st.nextToken(); - File pluginXML = new File(token); - loadPublicPlugin(pluginXML.getParentFile()); - } - } - - loadPluginResources(); - } - - private boolean hasDependencies(File pluginFile) { - SAXReader saxReader = new SAXReader(); - Document pluginXML; - try { - pluginXML = saxReader.read(pluginFile); - List dependencies = pluginXML.selectNodes("plugin/depends/plugin"); - return dependencies != null && dependencies.size() > 0 ? true : false; - } catch (DocumentException e) { - Log.error(e); - return false; - } - } - - /** - * Loads public plugins. - * - * @param pluginDir the directory of the expanded public plugin. - * @return the new Plugin model for the Public Plugin. - */ - private Plugin loadPublicPlugin(File pluginDir) { - - File pluginFile = new File(pluginDir, "plugin.xml"); - SAXReader saxReader = new SAXReader(); - Document pluginXML = null; - try { - pluginXML = saxReader.read(pluginFile); - } - catch (DocumentException e) { - Log.error(e); - } - - Plugin pluginClass = null; - - List plugins = pluginXML.selectNodes("/plugin"); - for (Node plugin1 : plugins) { - PublicPlugin publicPlugin = new PublicPlugin(); - - String clazz = null; - String name; - String minVersion; - - try { - - name = plugin1.selectSingleNode("name").getText(); - clazz = plugin1.selectSingleNode("class").getText(); - - try { - String lower = name.replaceAll("[^0-9a-zA-Z]","").toLowerCase(); - // Dont load the plugin if its on the Blacklist - if(_blacklistPlugins.contains(lower) || _blacklistPlugins.contains(clazz) - || SettingsManager.getLocalPreferences().getDeactivatedPlugins().contains(name)) - { - return null; - } - } catch (Exception e) { - // Whatever^^ - return null; - } - - // Check for minimum Spark version - try { - minVersion = plugin1.selectSingleNode("minSparkVersion").getText(); - - String buildNumber = JiveInfo.getVersion(); - boolean ok = buildNumber.compareTo(minVersion) >= 0; - - if (!ok) { - return null; - } - } - catch (Exception e) { - Log.error("Unable to load plugin " + name + " due to missing -Tag in plugin.xml."); - return null; - } - - // Check for minimum Java version - try { - String javaversion = plugin1.selectSingleNode("java").getText().replaceAll("[^0-9]", ""); - javaversion = javaversion == null? "0" : javaversion; - int jv = Integer.parseInt(attachMissingZero(javaversion)); - - String myversion = System.getProperty("java.version").replaceAll("[^0-9]", ""); - int mv = Integer.parseInt(attachMissingZero(myversion)); - - boolean ok = (mv >= jv); - - if (!ok) { - Log.error("Unable to load plugin " + name + - " due to old JavaVersion.\nIt Requires "+plugin1.selectSingleNode("java").getText()+ - " you have "+ System.getProperty("java.version")); - return null; - } - - } - catch (NullPointerException e) { - Log.warning("Plugin "+name+" has no -Tag, consider getting a newer Version"); - } - - // set dependencies - try { - List dependencies = plugin1.selectNodes("depends/plugin"); - for (Node depend1 : dependencies) { - Element depend = (Element) depend1; - PluginDependency dependency = new PluginDependency(); - dependency.setVersion(depend.selectSingleNode("version").getText()); - dependency.setName(depend.selectSingleNode("name").getText()); - publicPlugin.addDependency(dependency); - } - } - catch (Exception e) { - e.printStackTrace(); - } - - - // Do operating system check. - boolean operatingSystemOK = isOperatingSystemOK(plugin1); - if (!operatingSystemOK) { - return null; - } - - publicPlugin.setPluginClass(clazz); - publicPlugin.setName(name); - - try { - String version = plugin1.selectSingleNode("version").getText(); - publicPlugin.setVersion(version); - - String author = plugin1.selectSingleNode("author").getText(); - publicPlugin.setAuthor(author); - - String email = plugin1.selectSingleNode("email").getText(); - publicPlugin.setEmail(email); - - String description = plugin1.selectSingleNode("description").getText(); - publicPlugin.setDescription(description); - - String homePage = plugin1.selectSingleNode("homePage").getText(); - publicPlugin.setHomePage(homePage); - } - catch (Exception e) { - Log.debug("We can ignore these."); - } - - - try { - pluginClass = (Plugin) getParentClassLoader().loadClass(clazz).newInstance(); - Log.debug(name + " has been loaded."); - publicPlugin.setPluginDir(pluginDir); - publicPlugins.add(publicPlugin); - - - registerPlugin(pluginClass); - } - catch (Throwable e) { - Log.error("Unable to load plugin " + clazz + ".", e); - } - } - catch (Exception ex) { - Log.error("Unable to load plugin " + clazz + ".", ex); - } - - - } - - return pluginClass; - } - - private String attachMissingZero(String value) - { - while(value.length()<5) - { - value = value+"0"; - } - return value; - } - - /** - * Loads an internal plugin. - * - * @param reader the inputstreamreader for an internal plugin. - */ - private void loadInternalPlugins(InputStreamReader reader) { - SAXReader saxReader = new SAXReader(); - Document pluginXML = null; - try { - pluginXML = saxReader.read(reader); - } - catch (DocumentException e) { - Log.error(e); - } - List plugins = pluginXML.selectNodes("/plugins/plugin"); - for (final Object plugin1 : plugins) { - - EventQueue.invokeLater( () -> { -String clazz = null; -String name; -try { -Element plugin = (Element) plugin1; - -name = plugin.selectSingleNode("name").getText(); -clazz = plugin.selectSingleNode("class").getText(); -Plugin pluginClass1 = (Plugin) Class.forName(clazz).newInstance(); -Log.debug(name + " has been loaded. Internal plugin."); - -registerPlugin( pluginClass1 ); -} -catch (Throwable ex) { -Log.error("Unable to load plugin " + clazz + ".", ex); -} - } ); - - - } - } - - private void updateClasspath() { - try { - classLoader = new PluginClassLoader(getParentClassLoader(), PLUGINS_DIRECTORY); - PluginRes.setClassLoader(classLoader); - } - catch (MalformedURLException e) { - Log.error("Error updating classpath.", e); - } - Thread.currentThread().setContextClassLoader(classLoader); - } - - private void loadPluginResources(String resourceName, ResourceType type) { - try { - PropertyResourceBundle prbPlugin = (PropertyResourceBundle) ResourceBundle.getBundle(resourceName, - Locale.getDefault(), classLoader); - for (String key : prbPlugin.keySet()) { - PluginRes.putRes(key, prbPlugin.getString(key), type); - } - } catch (Exception ex) { - Log.debug(resourceName + "is not overwritten in plugin "); - } - } - - /** - * Loads property resources from spark.properties, default.properties, spark_i18n.properties (properly localized) - * located in plugin jar, if any - * In case the plugin contains preferences.properties, plugin specific defaults will be loaded instead of spark defaults for preferences - * This method is called right after all plugins are loaded, specifically after plugins class - * loader is initialized and plugins jars are loaded in classpath - */ - private void loadPluginResources() { - loadPluginResources("spark", ResourceType.SPARK); - loadPluginResources("default", ResourceType.DEFAULT); - loadPluginResources("preferences", ResourceType.PREFERENCES); - loadPluginResources("spark_i18n", ResourceType.I18N); - } - - /** - * Returns the plugin classloader. - * - * @return the plugin classloader. - */ - public ClassLoader getPluginClassLoader() { - return classLoader; - } - - /** - * Registers a plugin. - * - * @param plugin the plugin to register. - */ - public void registerPlugin(Plugin plugin) { - plugins.add(plugin); - } - - /** - * Removes a plugin from the plugin list. - * - * @param plugin the plugin to remove. - */ - public void removePlugin(Plugin plugin) { - plugins.remove(plugin); - } - - /** - * Returns a Collection of Plugins. - * - * @return a Collection of Plugins. - */ - public Collection getPlugins() { - return plugins; - } - - /** - * Returns the instance of the plugin class initialized during startup. - * - * @param communicatorPlugin the plugin to find. - * @return the instance of the plugin. - */ - public Plugin getPlugin(Class communicatorPlugin) { - for (Object o : getPlugins()) { - Plugin plugin = (Plugin) o; - if (plugin.getClass() == communicatorPlugin) { - return plugin; - } - } - return null; - } - - /** - * Loads and initalizes all Plugins. - * - * @see Plugin - */ - public void initializePlugins() { - try - { - int j; - boolean dependsfound; - - // Dependency check - for (int i = 0; i< publicPlugins.size(); i++) { - // if dependencies are available, check these - if((publicPlugins.get(i)).getDependency().size()>0) { - List dependencies = (publicPlugins.get(i)).getDependency(); - - // go trough all dependencies - for( PluginDependency dependency : dependencies) { - j = 0; - dependsfound = false; - // look for the specific plugin - for(PublicPlugin plugin1 :publicPlugins) { - - if(plugin1.getName()!= null - && plugin1.getName().equals(dependency.getName())) { - // if the version is compatible then reorder - if(dependency.compareVersion(plugin1.getVersion())){ - dependsfound = true; - // when depended Plugin hadn't been installed yet - if(j>i){ - - // find the position of plugins-List because it has more entries - int counter = 0, x = 0, z = 0; - for(Plugin plug : plugins) { - // find the position of the aim-object - if(plug.getClass().toString().substring(6).equals(publicPlugins.get(j).getPluginClass())) { - x = counter; - } - // find the change-position - else if(plug.getClass().toString().substring(6).equals(publicPlugins.get(i).getPluginClass())) { - z = counter; - } - counter ++; - } - // change the order - publicPlugins.add(i, publicPlugins.get(j)); - publicPlugins.remove(j+1); - - plugins.add(z, plugins.get(x)); - plugins.remove(x+1); - - // start again, to check the other dependencies - i--; - } - } - // else don't load the plugin and show an error - else { - Log.error("Depended Plugin " + dependency.getName() + " hasn't the right version (" + dependency.getVersion() + "<>" + plugin1.getVersion()); - } - break; - } - j++; - } - // if the depended Plugin wasn't found, then show error - if(!dependsfound) { - Log.error("Depended Plugin " + dependency.getName() + " is missing for the Plugin " + (publicPlugins.get(i)).getName()); - - // find the posiion of plugins-List because it has more entries - int counter = 0; - for(Plugin plug : plugins) { - // find the delete-position - if(plug.getClass().toString().substring(6).equals(publicPlugins.get(i).getPluginClass())) { - break; - } - counter ++; - } - // delete the Plugin, because the depended Plugin is missing - publicPlugins.remove(i); - plugins.remove(counter); - i--; - break; - } - } - } - } - - EventQueue.invokeLater( () -> { - for (Plugin plugin1 : plugins) { - long start = System.currentTimeMillis(); - Log.debug("Trying to initialize " + plugin1); - try { - plugin1.initialize(); - } - catch (Throwable e) { - Log.error(e); - } - - long end = System.currentTimeMillis(); - Log.debug("Took " + (end - start) + " ms. to load " + plugin1); - } - } ); - } - catch (Exception e) - { - e.printStackTrace(); - } - - } - - public void shutdown() { - for (Plugin plugin1 : plugins) { - try { - plugin1.shutdown(); - } - catch (Exception e) { - Log.warning("Exception on shutdown of plugin.", e); - } - } - } - - public void mainWindowActivated() { - } - - public void mainWindowDeactivated() { - } - - /** - * Locates the best class loader based on context (see class description). - * - * @return The best parent classloader to use - */ - private ClassLoader getParentClassLoader() { - ClassLoader parent = Thread.currentThread().getContextClassLoader(); - if (parent == null) { - parent = this.getClass().getClassLoader(); - if (parent == null) { - parent = ClassLoader.getSystemClassLoader(); - } - } - return parent; - } - - /** - * Expands all plugin packs (.jar files located in the plugin dir with plugin.xml). - */ - private void expandNewPlugins() { - File[] jars = PLUGINS_DIRECTORY.listFiles( ( dir, name ) -> { - boolean accept = false; - String smallName = name.toLowerCase(); - if (smallName.endsWith(".jar")) { - accept = true; - } - return accept; - } ); - - // Do nothing if no jar or zip files were found - if (jars == null) { - return; - } - - - for (File jar : jars) { - if (jar.isFile()) { - - URL url = null; - try { - url = jar.toURI().toURL(); - } - catch (MalformedURLException e) { - Log.error(e); - } - String name = URLFileSystem.getName(url); - File directory = new File(PLUGINS_DIRECTORY, name); - if (directory.exists() && directory.isDirectory()) { - // Check to see if directory contains the plugin.xml file. - // If not, delete directory. - File pluginXML = new File(directory, "plugin.xml"); - if (pluginXML.exists()) { - if (pluginXML.lastModified() < jar.lastModified()) { - uninstall(directory); - unzipPlugin(jar, directory); - } - continue; - } - - uninstall(directory); - } else { - // Unzip contents into directory - unzipPlugin(jar, directory); - } - } - } - } - - private void loadPublicPlugins() { - // First, expand all plugins that have yet to be expanded. - expandNewPlugins(); - - File[] files = PLUGINS_DIRECTORY.listFiles( ( dir, name ) -> { - return dir.isDirectory(); - } ); - - // Do nothing if no jar or zip files were found - if (files == null) { - return; - } - //Make sure to load first the plugins with no dependencies - //If a plugin with dependencies gets loaded before one of dependencies, - //class not found exception may be thrown if a dependency class is used during plugin creation - List dependencies = new ArrayList<>(); - List nodependencies = new ArrayList<>(); - for (File file : files) { - File pluginXML = new File(file, "plugin.xml"); - if (pluginXML.exists()) { - if (hasDependencies(pluginXML)) { - dependencies.add(file); - } else { - nodependencies.add(file); - } - } - } - - try { - for (File file : nodependencies) { - loadPlugin(classLoader, file); - } - for(File file : dependencies) { - loadPlugin(classLoader, file); - } - } catch (Throwable e) { - Log.error("Unable to load dirs", e); - } - } - - private void loadPlugin(PluginClassLoader classLoader, File file) throws MalformedURLException { - classLoader.addPlugin(file); - loadPublicPlugin(file); - } - - /** - * Adds and installs a new plugin into Spark. - * - * @param plugin the plugin to install. - * @throws Exception thrown if there was a problem loading the plugin. - */ - public void addPlugin(PublicPlugin plugin) throws Exception { - expandNewPlugins(); - - URL url = new URL(plugin.getDownloadURL()); - String name = URLFileSystem.getName(url); - File pluginDownload = new File(PluginManager.PLUGINS_DIRECTORY, name); - - ((PluginClassLoader) getParentClassLoader()).addPlugin(pluginDownload); - - pluginClass = loadPublicPlugin(pluginDownload); - - try { - EventQueue.invokeAndWait( () -> { - - Log.debug("Trying to initialize " + pluginClass); - pluginClass.initialize(); - } ); - } catch (Exception e) { - Log.error(e); - } - - } - - /** - * Unzips a plugin from a JAR file into a directory. If the JAR file - * isn't a plugin, this method will do nothing. - * - * @param file the JAR file - * @param dir the directory to extract the plugin to. - */ - private void unzipPlugin(File file, File dir) { - try { - ZipFile zipFile = new JarFile(file); - // Ensure that this JAR is a plugin. - if (zipFile.getEntry("plugin.xml") == null) { - return; - } - dir.mkdir(); - for (Enumeration e = zipFile.entries(); e.hasMoreElements();) { - JarEntry entry = (JarEntry)e.nextElement(); - File entryFile = new File(dir, entry.getName()); - // Ignore any manifest.mf entries. - if (entry.getName().toLowerCase().endsWith("manifest.mf")) { - continue; - } - if (!entry.isDirectory()) { - entryFile.getParentFile().mkdirs(); - FileOutputStream out = new FileOutputStream(entryFile); - InputStream zin = zipFile.getInputStream(entry); - byte[] b = new byte[512]; - int len; - while ((len = zin.read(b)) != -1) { - out.write(b, 0, len); - } - out.flush(); - out.close(); - zin.close(); - } - } - zipFile.close(); - } - catch (Throwable e) { - Log.error("Error unzipping plugin", e); - } - } - - /** - * Returns a collection of all public plugins. - * - * @return the collection of public plugins. - */ - public List getPublicPlugins() { - return publicPlugins; - } - - private void uninstall(File pluginDir) { - File[] files = pluginDir.listFiles(); - for (File f : files) { - if (f.isFile()) { - f.delete(); - } - } - - File libDir = new File(pluginDir, "lib"); - - File[] libs = libDir.listFiles(); - if (libs != null) { - for (File f : libs) { - f.delete(); - } - } - - libDir.delete(); - - pluginDir.delete(); - } - - /** - * Removes and uninstall a plugin from Spark. - * - * @param plugin the plugin to uninstall. - */ - public void removePublicPlugin(PublicPlugin plugin) { - for (PublicPlugin publicPlugin : getPublicPlugins()) { - if (plugin.getName().equals(publicPlugin.getName())) { - publicPlugins.remove(plugin); - } - } - } - - /** - * Returns true if the specified plugin is installed. - * - * @param plugin the PublicPlugin plugin to check. - * @return true if installed. - */ - public boolean isInstalled(PublicPlugin plugin) { - for (PublicPlugin publicPlugin : getPublicPlugins()) { - if (plugin.getName().equals(publicPlugin.getName())) { - return true; - } - } - - return false; - } - - /** - * Checks the plugin for required operating system. - * - * @param plugin the Plugin element to check. - * @return true if the operating system is ok for the plugin to run on. - */ - private boolean isOperatingSystemOK(Node plugin) { - // Check for operating systems - try { - - final Element osElement = (Element)plugin.selectSingleNode("os"); - if (osElement != null) { - String operatingSystem = osElement.getText(); - - boolean ok = false; - - final String currentOS = JiveInfo.getOS().toLowerCase(); - - // Iterate through comma delimited string - StringTokenizer tkn = new StringTokenizer(operatingSystem, ","); - while (tkn.hasMoreTokens()) { - String os = tkn.nextToken().toLowerCase(); - if (currentOS.contains(os) || currentOS.equalsIgnoreCase(os)) { - ok = true; - } - } - - if (!ok) { - Log.debug("Unable to load plugin " + plugin.selectSingleNode("name").getText() + " due to invalid operating system. Required OS = " + operatingSystem); - return false; - } - } - } - catch (Exception e) { - Log.error(e); - } - - return true; - } - - -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/spark/PresenceManager.java b/src/java/org/jivesoftware/spark/PresenceManager.java deleted file mode 100644 index c0e93edf7..000000000 --- a/src/java/org/jivesoftware/spark/PresenceManager.java +++ /dev/null @@ -1,263 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.packet.ExtensionElement; -import org.jivesoftware.smack.roster.Roster; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smackx.muc.packet.MUCUser; -import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; - -import javax.swing.Icon; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Handles the most common presence checks. - * - * @author Derek DeMoro - */ -public class PresenceManager { - - private static final List PRESENCES = new ArrayList<>(); - - - static { - // Add Available Presence - final Presence availablePresence = new Presence(Presence.Type.available, Res.getString("status.online"), 1, Presence.Mode.available); - final Presence freeToChatPresence = new Presence(Presence.Type.available, Res.getString("status.free.to.chat"), 1, Presence.Mode.chat); - final Presence awayPresence = new Presence(Presence.Type.available, Res.getString("status.away"), 0, Presence.Mode.away); - final Presence phonePresence = new Presence(Presence.Type.available, Res.getString("status.on.phone"), 0, Presence.Mode.away); - final Presence dndPresence = new Presence(Presence.Type.available, Res.getString("status.do.not.disturb"), 0, Presence.Mode.dnd); - final Presence extendedAway = new Presence(Presence.Type.available, Res.getString("status.extended.away"), 0, Presence.Mode.xa); - final Presence invisible = new Presence(Presence.Type.unavailable, Res.getString("status.invisible"), 0, Presence.Mode.available); - - PRESENCES.add(freeToChatPresence); - PRESENCES.add(availablePresence); - PRESENCES.add(awayPresence); - PRESENCES.add(extendedAway); - PRESENCES.add(phonePresence); - PRESENCES.add(dndPresence); - PRESENCES.add(invisible); - } - - /** - * Building Presence related data. - */ - private PresenceManager() { - - } - - /** - * Returns true if the user is online. - * - * @param jid the jid of the user. - * @return true if online. - */ - public static boolean isOnline(String jid) { - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - Presence presence = roster.getPresence(jid); - return presence.isAvailable(); - } - - /** - * Returns true if the user is online and their status is available or free to chat. - * - * @param jid the jid of the user. - * @return true if the user is online and available. - */ - public static boolean isAvailable(String jid) { - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - Presence presence = roster.getPresence(jid); - return presence.isAvailable() && !presence.isAway(); - } - - /** - * Returns true if the user is online and their mode is available or free to chat. - * - * @param presence the users presence. - * @return true if the user is online and their mode is available or free to chat. - */ - public static boolean isAvailable(Presence presence) { - return presence.isAvailable() && !presence.isAway(); - } - - /** - * Returns the presence of a user. - * - * @param jid the users jid. - * @return the users presence. - */ - public static Presence getPresence(String jid) { - if ( jid == null ) { - Log.error( "Unable to get the presence of a null jid!" ); - return null; - } - if (jid.equals(SparkManager.getSessionManager().getBareAddress())) { - return SparkManager.getWorkspace().getStatusBar().getPresence(); - } else { - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - return roster.getPresence(jid); - } - } - - /** - * Returns the fully qualified jid of a user. - * - * @param jid the users bare jid (ex. derek@jivesoftware.com) - * @return the fully qualified jid of a user (ex. derek@jivesoftware.com --> derek@jivesoftware.com/spark) - */ - public static String getFullyQualifiedJID(String jid) { - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - Presence presence = roster.getPresence(jid); - return presence.getFrom(); - } - - public static String getJidFromMUCPresence(Presence presence) { - Collection extensions = presence.getExtensions(); - for (ExtensionElement extension : extensions) { - if (extension instanceof MUCUser) { - final MUCUser mucUser = (MUCUser) extension; - String fullJid = mucUser.getItem().getJid(); - if ( fullJid == null) { - return null; - } - String userJid = XmppStringUtils.parseBareJid(fullJid); - return userJid; - } - } - return null; - } - - /** - * Returns the icon associated with a users presence. - * - * @param presence the users presence. - * @return the icon associated with it. - */ - public static Icon getIconFromPresence(Presence presence) { - if (isInvisible(presence)) { - return SparkRes.getImageIcon(SparkRes.INVISIBLE); - } - - // Handle offline presence - if (!presence.isAvailable()) { - return SparkRes.getImageIcon(SparkRes.CLEAR_BALL_ICON); - } - - Presence.Mode presenceMode = presence.getMode(); - if (presenceMode == null) { - presenceMode = Presence.Mode.available; - } - - Icon icon = null; - - if (presenceMode.equals(Presence.Mode.available)) { - icon = SparkRes.getImageIcon(SparkRes.GREEN_BALL); - } - else if (presenceMode.equals(Presence.Mode.chat)) { - icon = SparkRes.getImageIcon(SparkRes.FREE_TO_CHAT_IMAGE); - } - else if (isOnPhone(presence)) { - icon = SparkRes.getImageIcon(SparkRes.ON_PHONE_IMAGE); - } - else if (presenceMode.equals(Presence.Mode.away)) { - icon = SparkRes.getImageIcon(SparkRes.IM_AWAY); - } - else if (presenceMode.equals(Presence.Mode.dnd)) { - icon = SparkRes.getImageIcon(SparkRes.IM_DND); - } - else if (presenceMode.equals(Presence.Mode.xa)) { - icon = SparkRes.getImageIcon(SparkRes.IM_AWAY); - } - - // Check For ContactItem handlers - Icon handlerIcon = SparkManager.getChatManager().getTabIconForContactHandler(presence); - if (handlerIcon != null) { - icon = handlerIcon; - } - - - return icon; - } - - /** - * Returns the Presence Map. - * - * @return the Presence Map. - */ - public static List getPresences() { - return PRESENCES; - } - - public static boolean isOnPhone(Presence presence) { - Presence.Mode presenceMode = presence.getMode(); - if (presenceMode == null) { - presenceMode = Presence.Mode.available; - } - if (presence.getStatus() != null && - presence.getStatus().contains(Res.getString("status.on.phone")) && - presenceMode.equals(Presence.Mode.away)) { - return true; - } - return false; - } - - public static boolean isInvisible(Presence presence) { - return presence != null && presence.getType() == Presence.Type.unavailable - && (Res.getString("status.invisible").equalsIgnoreCase(presence.getStatus()) - || Res.getString("status.offline").equalsIgnoreCase(presence.getStatus())) - && Presence.Mode.available == presence.getMode(); - } - - public static Presence getAvailablePresence() { - return PRESENCES.get(1); - } - - public static Presence getUnavailablePresence() { - return PRESENCES.get(6); - } - - public static boolean areEqual(Presence p1, Presence p2) { - if (p1 == p2) - return true; - - if (p1 == null || p2 == null) - return false; - - return p1.getType() == p2.getType() && p1.getMode() == p2.getMode() - && p1.getStatus().equals(p2.getStatus()); - } - - public static Presence copy(Presence presence) { - if (presence == null) - return null; - Presence copy = new Presence(presence.getType()); - copy.setMode(presence.getMode()); - copy.setStatus(presence.getStatus()); - copy.setPriority(presence.getPriority()); - return copy; - } -} diff --git a/src/java/org/jivesoftware/spark/SessionManager.java b/src/java/org/jivesoftware/spark/SessionManager.java deleted file mode 100644 index fbde7449b..000000000 --- a/src/java/org/jivesoftware/spark/SessionManager.java +++ /dev/null @@ -1,285 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark; - -import org.jivesoftware.smack.*; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.provider.ProviderManager; -import org.jivesoftware.smackx.iqprivate.PrivateDataManager; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; -import org.jivesoftware.smackx.disco.packet.DiscoverItems; -import org.jivesoftware.spark.ui.PresenceListener; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.manager.Features; -import org.jxmpp.util.XmppStringUtils; - -import javax.swing.SwingUtilities; - -import java.util.ArrayList; -import java.util.List; - -/** - * This manager is responsible for the handling of the XMPPConnection used within Spark. This is used - * for the changing of the users presence, the handling of connection errors and the ability to add - * presence listeners and retrieve the connection used in Spark. - * - * @author Derek DeMoro - */ -public final class SessionManager implements ConnectionListener { - private AbstractXMPPConnection connection; - private PrivateDataManager personalDataManager; - - private String serverAddress; - private String username; - private String password; - - private String JID; - - private List presenceListeners = new ArrayList<>(); - - private String userBareAddress; - private DiscoverItems discoverItems; - - public SessionManager() { - } - - /** - * Initializes session. - * - * @param connection the XMPPConnection used in this session. - * @param username the agents username. - * @param password the agents password. - */ - public void initializeSession( AbstractXMPPConnection connection, String username, String password) { - this.connection = connection; - this.username = username; - this.password = password; - this.userBareAddress = XmppStringUtils.parseBareJid(connection.getUser()); - - // create workgroup session - personalDataManager = PrivateDataManager.getInstanceFor( getConnection() ); - - // Discover items - discoverItems(); - - - ProviderManager.addExtensionProvider("event", "http://jabber.org/protocol/disco#info", new Features.Provider()); - } - - /** - * Does the initial service discovery. - */ - private void discoverItems() { - ServiceDiscoveryManager disco = ServiceDiscoveryManager.getInstanceFor(SparkManager.getConnection()); - try { - discoverItems = disco.discoverItems(SparkManager.getConnection().getServiceName()); - } - catch (XMPPException | SmackException e) { - Log.error(e); - discoverItems = new DiscoverItems(); - } - } - - /** - * Returns the XMPPConnection used for this session. - * - * @return the XMPPConnection used for this session. - */ - public XMPPConnection getConnection() { - return connection; - } - - - /** - * Returns the PrivateDataManager responsible for handling all private data for individual - * agents. - * - * @return the PrivateDataManager responsible for handling all private data for individual - * agents. - */ - public PrivateDataManager getPersonalDataManager() { - return personalDataManager; - } - - - /** - * Returns the host for this connection. - * - * @return the connection host. - */ - public String getServerAddress() { - return serverAddress; - } - - /** - * Set the server address - * - * @param address the address of the server. - */ - public void setServerAddress(String address) { - this.serverAddress = address; - } - - /** - * Notify agent the connection was closed due to an exception. - * - * @param ex the Exception that took place. - */ - public void connectionClosedOnError(final Exception ex) { - SwingUtilities.invokeLater( () -> { - final Presence presence = new Presence(Presence.Type.unavailable); - changePresence(presence); - - Log.debug("Connection closed on error.: " + ex.getMessage()); - } ); - } - - @Override - public void connected( XMPPConnection xmppConnection ) - { - - } - - @Override - public void authenticated( XMPPConnection xmppConnection, boolean b ) - { - - } - - /** - * Notify agent that the connection has been closed. - */ - public void connectionClosed() { - } - - /** - * Return the username associated with this session. - * - * @return the username associated with this session. - */ - public String getUsername() { - return XmppStringUtils.unescapeLocalpart(username); - } - - /** - * Return the password associated with this session. - * - * @return the password assoicated with this session. - */ - public String getPassword() { - return password; - } - - /** - * Update the current availability of the user - * - * @param presence the current presence of the user. - */ - public void changePresence(Presence presence) { - // Fire Presence Listeners - for (PresenceListener listener : new ArrayList<>( this.presenceListeners )) { - listener.presenceChanged(presence); - } - - // Do NOT send presence if disconnected. - if (SparkManager.getConnection().isConnected()) { - // Send Presence Packet - try - { - SparkManager.getConnection().sendStanza(presence); - } - catch ( SmackException.NotConnectedException e ) - { - Log.error( "Unable to send presence to " + presence.getTo(), e ); - } - } - } - - /** - * Returns the jid of the Spark user. - * - * @return the jid of the Spark user. - */ - public String getJID() { - return JID; - } - - /** - * Sets the jid of the current Spark user. - * - * @param jid the jid of the current Spark user. - */ - public void setJID(String jid) { - this.JID = jid; - } - - /** - * Adds a PresenceListener to Spark. PresenceListener's are used - * to allow notification of when the Spark users changes their presence. - * - * @param listener the listener. - */ - public void addPresenceListener(PresenceListener listener) { - presenceListeners.add(listener); - } - - /** - * Remove a PresenceListener from Spark. - * - * @param listener the listener. - */ - public void removePresenceListener(PresenceListener listener) { - presenceListeners.remove(listener); - } - - /** - * Returns the users bare address. A bare-address is the address without a resource (ex. derek@jivesoftware.com/spark would - * be derek@jivesoftware.com) - * - * @return the users bare address. - */ - public String getBareAddress() { - return userBareAddress; - } - - - /** - * Returns the Discovered Items. - * - * @return the discovered items found on startup. - */ - public DiscoverItems getDiscoveredItems() { - return discoverItems; - } - - public void setConnection(AbstractXMPPConnection con) { - this.connection = con; - } - - public void reconnectingIn(int i) { - } - - public void reconnectionSuccessful() { - } - - public void reconnectionFailed(Exception exception) { - } - -} diff --git a/src/java/org/jivesoftware/spark/SoundManager.java b/src/java/org/jivesoftware/spark/SoundManager.java deleted file mode 100644 index 0c96ffff0..000000000 --- a/src/java/org/jivesoftware/spark/SoundManager.java +++ /dev/null @@ -1,147 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark; - -import org.jivesoftware.resource.SoundsRes; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.log.Log; - -import java.applet.Applet; -import java.applet.AudioClip; -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; - -/** - * This manager is responsible for the playing, stopping and caching of sounds within Spark. You would - * use this manager when you wish to play audio without adding too much memory overhead. - */ -public class SoundManager { - - private final Map clipMap = new HashMap<>(); - private final Map fileMap = new HashMap<>(); - - /** - * Default constructor - */ - public SoundManager() { - } - - /** - * Plays an audio clip of local clips deployed with Spark. - * - * @param clip the properties value found in la.properties. - * @return the AudioClip found. If no audio clip was found, returns null. - */ - public AudioClip getClip(String clip) { - if (!clipMap.containsKey(clip)) { - // Add new clip - final AudioClip newClip = loadClipForURL(clip); - if (newClip != null) { - clipMap.put(clip, newClip); - } - } - - return clipMap.get(clip); - } - - /** - * Plays an AudioClip. - * - * @param clip the audioclip to play. - */ - public void playClip(final AudioClip clip) { - - final Runnable playThread = () -> { - try { - clip.play(); - } - catch (Exception ex) { - System.err.println("Unable to load sound file"); - } - }; - - TaskEngine.getInstance().submit(playThread); - } - - /** - * Plays an AudioClip. - * - * @param clipToPlay the properties value found in la.properties. - */ - public void playClip(String clipToPlay) { - AudioClip clip = getClip(clipToPlay); - try { - clip.play(); - } - catch (Exception ex) { - System.err.println("Unable to load sound file"); - } - } - - /** - * Plays a sound file. - * - * @param soundFile the File object representing the wav file. - */ - public void playClip(final File soundFile) { - final Runnable playThread = () -> { - try { - final URL url = soundFile.toURI().toURL(); - AudioClip ac = fileMap.get(url); - if (ac == null) { - ac = Applet.newAudioClip(url); - fileMap.put(url, ac); - } - ac.play(); - } - catch (MalformedURLException e) { - Log.error(e); - } - }; - - TaskEngine.getInstance().submit(playThread); - } - - /** - * Creates an AudioClip from a URL. - * - * @param clipOfURL the url of the AudioClip to play. We only support .wav files at the moment. - * @return the AudioFile found. If no audio file was found,returns null. - */ - private AudioClip loadClipForURL(String clipOfURL) { - final URL url = SoundsRes.getURL(clipOfURL); - AudioClip clip = null; - - try { - clip = Applet.newAudioClip(url); - - } - catch (Exception e) { - Log.error("Unable to load sound url: " + url + "\n\t: " + e); - } - - return clip; - } - - -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/spark/UserManager.java b/src/java/org/jivesoftware/spark/UserManager.java deleted file mode 100644 index a2a5482c7..000000000 --- a/src/java/org/jivesoftware/spark/UserManager.java +++ /dev/null @@ -1,501 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smackx.muc.MUCAffiliation; -import org.jivesoftware.smackx.muc.MUCRole; -import org.jivesoftware.smackx.muc.Occupant; -import org.jivesoftware.smackx.vcardtemp.packet.VCard; -import org.jivesoftware.spark.component.JContactItemField; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ContactGroup; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.ui.rooms.GroupChatRoom; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.SwingTimerTask; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.profile.VCardManager; -import org.jxmpp.util.XmppStringUtils; - -import javax.swing.BorderFactory; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TimerTask; - -/** - * Handles all users in the agent application. Each user or chatting user can be referenced from the User - * Manager. You would use the UserManager to get visitors in a chat room or secondary agents. - */ -public class UserManager { - - private Map parents = new HashMap<>(); - - public UserManager() { - } - - public String getNickname() { - final VCardManager vCardManager = SparkManager.getVCardManager(); - VCard vcard = vCardManager.getVCard(); - if (vcard == null) { - return SparkManager.getSessionManager().getUsername(); - } - else { - String nickname = vcard.getNickName(); - if (ModelUtil.hasLength(nickname)) { - return nickname; - } - else { - String firstName = vcard.getFirstName(); - if (ModelUtil.hasLength(firstName)) { - return firstName; - } - } - } - - // Default to node if nothing. - String username = SparkManager.getSessionManager().getUsername(); - username = XmppStringUtils.unescapeLocalpart(username); - - return username; - } - - public String getNickname(String fullJID) { - String vcardNickname = null; - VCard vCard = SparkManager.getVCardManager().getVCard(fullJID); - if (vCard != null && vCard.getError() == null) { - String firstName = vCard.getFirstName(); - String lastName = vCard.getLastName(); - String nickname = vCard.getNickName(); - if (ModelUtil.hasLength(nickname)) { - vcardNickname = nickname; - } - else if (ModelUtil.hasLength(firstName) && ModelUtil.hasLength(lastName)) { - vcardNickname = firstName + " " + lastName; - } - else if (ModelUtil.hasLength(firstName)) { - vcardNickname = firstName; - } - } - - return vcardNickname; - } - - - /** - * Return a Collection of all user jids found in the specified room. - * - * @param room the name of the chatroom - * @param fullJID set to true if you wish to have the full jid with resource, otherwise false - * for the bare jid. - * @return a Collection of jids found in the room. - */ - public Collection getUserJidsInRoom(String room, boolean fullJID) { - return new ArrayList<>(); - } - - /** - * Checks to see if the user is an owner of the specified room. - * - * @param groupChatRoom the group chat room. - * @param nickname the user's nickname. - * @return true if the user is an owner. - */ - public boolean isOwner(GroupChatRoom groupChatRoom, String nickname) - { - return isOwner( getOccupant( groupChatRoom, nickname ) ); - } - - /** - * Checks to see if the Occupant is the owner of the room. - * - * @param occupant the occupant of a room. - * @return true if the user is an owner. - */ - public boolean isOwner(Occupant occupant) - { - return occupant != null && occupant.getAffiliation() == MUCAffiliation.owner; - } - - /** - * Checks if the Occupant is a Member in this Room
      - * admins and owners are also members!!! - * @param occupant - * @return true if member, else false - */ - public boolean isMember(Occupant occupant) - { - return occupant != null && ( occupant.getAffiliation() == MUCAffiliation.owner || occupant.getAffiliation() == MUCAffiliation.member || occupant.getAffiliation() == MUCAffiliation.admin ); - } - - /** - * Checks to see if the Occupant is a moderator. - * - * @param groupChatRoom the group chat room. - * @param nickname the nickname of the user. - * @return true if the user is a moderator. - */ - public boolean isModerator(GroupChatRoom groupChatRoom, String nickname) - { - return isModerator( getOccupant( groupChatRoom, nickname ) ); - } - - /** - * Checks to see if the Occupant is a moderator. - * - * @param occupant the Occupant of a room. - * @return true if the user is a moderator. - */ - public boolean isModerator(Occupant occupant) { - return occupant != null && occupant.getRole() == MUCRole.moderator; - } - - /** - * Checks to see if the user is either an owner or admin of a room. - * - * @param groupChatRoom the group chat room. - * @param nickname the user's nickname. - * @return true if the user is either an owner or admin of the room. - */ - public boolean isOwnerOrAdmin(GroupChatRoom groupChatRoom, String nickname) { - return isOwnerOrAdmin( getOccupant(groupChatRoom, nickname) ); - } - - /** - * Checks to see if the user is either an owner or admin of the given room. - * - * @param occupant the Occupant to check. - * @return true if the user is either an owner or admin of the room. - */ - public boolean isOwnerOrAdmin(Occupant occupant) { - return isOwner( occupant ) || isAdmin( occupant ); - } - - /** - * Returns the occupant of the room identified by their nickname. - * - * @param groupChatRoom the GroupChatRoom. - * @param nickname the users nickname. - * @return the Occupant found. - */ - public Occupant getOccupant(GroupChatRoom groupChatRoom, String nickname) { - String userJID = groupChatRoom.getRoomname() + "/" + nickname; - Occupant occ = null; - try { - occ = groupChatRoom.getMultiUserChat().getOccupant(userJID); - } - catch (Exception e) { - Log.error(e); - } - return occ; - } - - /** - * Checks the nickname of a user in a room and determines if they are an - * administrator of the room. - * - * @param groupChatRoom the GroupChatRoom. - * @param nickname the nickname of the user. Note: In MultiUserChats, users nicknames - * are defined by the resource(ex.theroom@conference.jivesoftware.com/derek) would have - * derek as a nickname. - * @return true if the user is an admin. - */ - public boolean isAdmin(GroupChatRoom groupChatRoom, String nickname) { - return isAdmin( getOccupant(groupChatRoom, nickname) ); - } - - /** - * Checks to see if the Occupant is an admin. - * - * @param occupant the occupant of a room. - * @return true if the user is an admin. - */ - public boolean isAdmin(Occupant occupant) - { - return occupant != null && occupant.getAffiliation() == MUCAffiliation.admin; - } - - public boolean hasVoice(GroupChatRoom groupChatRoom, String nickname) { - Occupant occupant = getOccupant(groupChatRoom, nickname); - if (occupant != null) { - if ( MUCRole.visitor == occupant.getRole()) { - return false; - } - } - return true; - } - - - /** - * Returns a Collection of all ChatUsers in a ChatRoom. - * - * @param chatRoom the ChatRoom to inspect. - * @return the Collection of all ChatUsers. - * @see ChatUser - */ - public Collection getAllParticipantsInRoom(ChatRoom chatRoom) { - return new ArrayList<>(); - } - - - public String getUserNicknameFromJID(String jid) { - ContactList contactList = SparkManager.getWorkspace().getContactList(); - ContactItem item = contactList.getContactItemByJID(jid); - if (item != null) { - return item.getDisplayName(); - } - - return unescapeJID(jid); - } - - /** - * Escapes a complete JID by examing the Node itself and escaping - * when neccessary. - * - * @param jid the users JID - * @return the escaped JID. - */ - public static String escapeJID(String jid) { - if (jid == null) { - return null; - } - - final StringBuilder builder = new StringBuilder(); - String node = XmppStringUtils.parseLocalpart(jid); - String restOfJID = jid.substring(node.length()); - builder.append(XmppStringUtils.escapeLocalpart(node)); - builder.append(restOfJID); - return builder.toString(); - } - - /** - * Unescapes a complete JID by examing the node itself and unescaping when necessary. - * - * @param jid the users jid. - * @return the unescaped JID. - */ - public static String unescapeJID(String jid) { - if (jid == null) { - return null; - } - - final StringBuilder builder = new StringBuilder(); - String node = XmppStringUtils.parseLocalpart(jid); - String restOfJID = jid.substring(node.length()); - builder.append(XmppStringUtils.unescapeLocalpart(node)); - builder.append(restOfJID); - return builder.toString(); - } - - /** - * Returns the full jid w/ resource of a user by their display name - * in the ContactList. - * - * @param displayName the displayed name of the user. - * @return the full jid w/ resource of the user. - */ - public String getJIDFromDisplayName(String displayName) { - ContactList contactList = SparkManager.getWorkspace().getContactList(); - ContactItem item = contactList.getContactItemByDisplayName(displayName); - if (item != null) { - return getFullJID(item.getJID()); - } - - return null; - } - - /** - * Returns the full jid (with resource) based on the user's jid. - * - * @param jid the users bare jid. - * @return the full jid with resource. - */ - public String getFullJID(String jid) { - Presence presence = PresenceManager.getPresence(jid); - return presence.getFrom(); - } - - - public void searchContacts(String contact, final JFrame parent) { - if (parents.get(parent) == null && parent.getGlassPane() !=null) { - parents.put(parent, parent.getGlassPane()); - } - - // Make sure we are using the default glass pane - final Component glassPane = parents.get(parent); - parent.setGlassPane(glassPane); - - final Map contactMap = new HashMap<>(); - final List contacts = new ArrayList<>(); - - final ContactList contactList = SparkManager.getWorkspace().getContactList(); - - for (ContactGroup contactGroup : contactList.getContactGroups()) { - contactGroup.clearSelection(); - for (ContactItem contactItem : contactGroup.getContactItems()) { - if (!contactMap.containsKey(contactItem.getJID())) { - contacts.add(contactItem); - contactMap.put(contactItem.getJID(), contactItem); - } - } - } - - // Sort - Collections.sort(contacts, itemComparator); - - final JContactItemField contactField = new JContactItemField( new ArrayList<>( contacts )); - - - JPanel layoutPanel = new JPanel(); - layoutPanel.setLayout(new GridBagLayout()); - JLabel enterLabel = new JLabel(Res.getString("label.contact.to.find")); - enterLabel.setFont(new Font("dialog", Font.BOLD, 10)); - layoutPanel.add(enterLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 5), 0, 0)); - layoutPanel.add(contactField, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); - layoutPanel.setBorder(BorderFactory.createBevelBorder(0)); - - contactField.addKeyListener(new KeyAdapter() { - public void keyReleased(KeyEvent keyEvent) { - if (keyEvent.getKeyChar() == KeyEvent.VK_ENTER) { - if (ModelUtil.hasLength(contactField.getText())) { - ContactItem item = contactMap.get(contactField.getText()); - if (item == null) { - item = contactField.getSelectedContactItem(); - } - if (item != null) { - parent.setGlassPane(glassPane); - parent.getGlassPane().setVisible(false); - contactField.dispose(); - SparkManager.getChatManager().activateChat(item.getJID(), item.getDisplayName()); - } - } - - } - else if (keyEvent.getKeyChar() == KeyEvent.VK_ESCAPE) { - parent.setGlassPane(glassPane); - parent.getGlassPane().setVisible(false); - contactField.dispose(); - } - } - }); - - contactField.getList().addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if(SwingUtilities.isRightMouseButton(e)) - { - contactField.setSelectetIndex(e); - ContactItem item = contactField.getSelectedContactItem(); - MouseEvent exx = new MouseEvent((Component) e.getSource(),e.getID(), e.getWhen(),e.getModifiers(),e.getX()+20, e.getY(), e.getClickCount(), false); - SparkManager.getContactList().setSelectedUser(item.getJID()); - SparkManager.getContactList().showPopup(contactField.getPopup(),exx,item); - } - - if (e.getClickCount() == 2) { - if (ModelUtil.hasLength(contactField.getText())) { - ContactItem item = contactMap.get(contactField.getText()); - if (item == null) { - item = contactField.getSelectedContactItem(); - } - if (item != null) { - parent.setGlassPane(glassPane); - parent.getGlassPane().setVisible(false); - contactField.dispose(); - SparkManager.getChatManager().activateChat(item.getJID(), item.getDisplayName()); - } - } - } - } - }); - - - final JPanel mainPanel = new JPanel(new BorderLayout()); - mainPanel.setLayout(new GridBagLayout()); - mainPanel.add(layoutPanel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 200, 0)); - mainPanel.setOpaque(false); - - contactField.setText(contact); - parent.setGlassPane(mainPanel); - parent.getGlassPane().setVisible(true); - contactField.focus(); - - mainPanel.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent mouseEvent) { - parent.setGlassPane(glassPane); - parent.getGlassPane().setVisible(false); - contactField.dispose(); - } - }); - - parent.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent windowEvent) { - parent.setGlassPane(glassPane); - parent.getGlassPane().setVisible(false); - contactField.dispose(); - parent.removeWindowListener(this); - } - - public void windowDeactivated(final WindowEvent windowEvent) { - TimerTask task = new SwingTimerTask() { - public void doRun() { - if (contactField.canClose()) { - windowClosing(windowEvent); - } - } - }; - - TaskEngine.getInstance().schedule(task, 250); - } - }); - } - - /** - * Sorts ContactItems. - */ - final Comparator itemComparator = ( item1, item2 ) -> item1.getDisplayName().toLowerCase().compareTo(item2.getDisplayName().toLowerCase()); - -} - - - diff --git a/src/java/org/jivesoftware/spark/Workspace.java b/src/java/org/jivesoftware/spark/Workspace.java deleted file mode 100644 index c790394c8..000000000 --- a/src/java/org/jivesoftware/spark/Workspace.java +++ /dev/null @@ -1,505 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark; - -import java.awt.CardLayout; -import java.awt.Color; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.util.TimerTask; - -import javax.swing.AbstractAction; -import javax.swing.BorderFactory; -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.JTabbedPane; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; - -import org.jivesoftware.MainWindow; -import org.jivesoftware.MainWindowListener; -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Default; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.StanzaListener; -import org.jivesoftware.smack.roster.Roster; -import org.jivesoftware.smack.filter.StanzaFilter; -import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Stanza; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smackx.debugger.EnhancedDebuggerWindow; -import org.jivesoftware.smackx.delay.packet.DelayInformation; -import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; -import org.jivesoftware.smackx.vcardtemp.packet.VCard; -import org.jivesoftware.spark.component.tabbedPane.SparkTabbedPane; -import org.jivesoftware.spark.filetransfer.SparkTransferManager; -import org.jivesoftware.spark.search.SearchManager; -import org.jivesoftware.spark.ui.ChatContainer; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomNotFoundException; -import org.jivesoftware.spark.ui.CommandPanel; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.ui.conferences.ConferenceServices; -import org.jivesoftware.spark.ui.status.StatusBar; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.UIComponentRegistry; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.alerts.BroadcastPlugin; -import org.jivesoftware.sparkimpl.plugin.bookmarks.BookmarkPlugin; -import org.jivesoftware.sparkimpl.plugin.gateways.GatewayPlugin; -import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; -import org.jivesoftware.sparkimpl.plugin.transcripts.ChatTranscriptPlugin; -import org.jxmpp.util.XmppStringUtils; - -/** - * The inner Container for Spark. The Workspace is the container for all plugins into the Spark - * install. Plugins would use this for the following: - *

      - *

        - *
      • Add own tab to the main tabbed pane. ex. - *

        - *

        - * Workspace workspace = SparkManager.getWorkspace(); - * JButton button = new JButton("HELLO SPARK USERS"); - * workspace.getWorkspacePane().addTab("MyPlugin", button); - *

        - *

        - *

      • Retrieve the ContactList. - */ -public class Workspace extends JPanel implements StanzaListener { - - private static final long serialVersionUID = 7076407890063933765L; - private SparkTabbedPane workspacePane; - private StatusBar statusBox; - - private ContactList contactList; - private ConferenceServices conferences; - private GatewayPlugin gatewayPlugin; - private BookmarkPlugin bookmarkPlugin; - private ChatTranscriptPlugin transcriptPlugin; - private BroadcastPlugin broadcastPlugin; - - private static Workspace singleton; - private static final Object LOCK = new Object(); - - private JPanel cardPanel; - private CardLayout cardLayout; - - public static final String WORKSPACE_PANE = "WORKSPACE_PANE"; - - - /** - * Returns the singleton instance of Workspace, - * creating it if necessary. - *

        - * - * @return the singleton instance of Workspace - */ - public static Workspace getInstance() { - // Synchronize on LOCK to ensure that we don't end up creating - // two singletons. - synchronized (LOCK) { - if (null == singleton) { - Workspace controller = new Workspace(); - singleton = controller; - return controller; - } - } - return singleton; - } - - - /** - * Creates the instance of the SupportChatWorkspace. - */ - private Workspace() { - final MainWindow mainWindow = SparkManager.getMainWindow(); - - // Add MainWindow listener - mainWindow.addMainWindowListener(new MainWindowListener() { - public void shutdown() { - final ChatContainer container = SparkManager.getChatManager().getChatContainer(); - // Close all Chats. - for (ChatRoom chatRoom : container.getChatRooms()) { - // Leave ChatRoom - container.leaveChatRoom(chatRoom); - } - - conferences.shutdown(); - gatewayPlugin.shutdown(); - bookmarkPlugin.shutdown(); - broadcastPlugin.shutdown(); - } - - public void mainWindowActivated() { - - } - - public void mainWindowDeactivated() { - - } - }); - - - // Initialize workspace pane, defaulting the tabs to the bottom. - boolean top = Default.getBoolean(Default.TABS_PLACEMENT_TOP); - workspacePane = UIComponentRegistry.createWorkspaceTabPanel(top ? JTabbedPane.TOP : JTabbedPane.BOTTOM); - workspacePane.setBorder(BorderFactory.createEmptyBorder()); - // Add Panels. - cardLayout = new CardLayout(); - cardPanel = new JPanel(cardLayout); - cardPanel.setOpaque(false); - cardPanel.add(WORKSPACE_PANE, this); - - statusBox = UIComponentRegistry.createStatusBar(); - - // Build default workspace - this.setLayout(new GridBagLayout()); - add(workspacePane, new GridBagConstraints(0, 9, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); - add(statusBox, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); - - - this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("F12"), "showDebugger"); - this.getActionMap().put("showDebugger", new AbstractAction("showDebugger") { - private static final long serialVersionUID = 4066886679016416923L; - - public void actionPerformed(ActionEvent evt) { - EnhancedDebuggerWindow window = EnhancedDebuggerWindow.getInstance(); - window.setVisible(true); - } - }); - - // Set background - setBackground(new Color(235, 239, 254)); - } - - /** - * Builds the Workspace layout. - */ - public void buildLayout() { - new Enterprise(); - - // Initialize Contact List - contactList = UIComponentRegistry.createContactList(); - conferences = UIComponentRegistry.createConferenceServices(); - - // Init contact list. - contactList.initialize(); - - // Load VCard information for status box - statusBox.loadVCard(); - - // Initialise TransferManager - SparkTransferManager.getInstance(); - } - - /** - * Starts the Loading of all Spark Plugins. - */ - public void loadPlugins() { - - // Send Available status - SparkManager.getSessionManager().changePresence(statusBox.getPresence()); - - // Add presence and message listeners - // we listen for these to force open a 1-1 peer chat window from other operators if - // one isn't already open - StanzaFilter workspaceMessageFilter = new StanzaTypeFilter(Message.class); - - // Add the packetListener to this instance - SparkManager.getSessionManager().getConnection().addAsyncStanzaListener(this, workspaceMessageFilter); - - // Make presence available to anonymous requests, if from anonymous user in the system. - StanzaListener workspacePresenceListener = stanza -> { - Presence presence = (Presence)stanza; - JivePropertiesExtension extension = (JivePropertiesExtension) presence.getExtension( JivePropertiesExtension.NAMESPACE ); - if (extension != null && extension.getProperty("anonymous") != null) { - boolean isAvailable = statusBox.getPresence().getMode() == Presence.Mode.available; - Presence reply = new Presence(Presence.Type.available); - if (!isAvailable) { - reply.setType(Presence.Type.unavailable); - } - reply.setTo(presence.getFrom()); - try - { - SparkManager.getSessionManager().getConnection().sendStanza(reply); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to send presence reply to " + reply.getTo(), e ); - } - } - }; - - SparkManager.getSessionManager().getConnection().addAsyncStanzaListener(workspacePresenceListener, new StanzaTypeFilter(Presence.class)); - - // Until we have better plugin management, will init after presence updates. - gatewayPlugin = new GatewayPlugin(); - gatewayPlugin.initialize(); - - // Load all non-presence related items. - conferences.loadConferenceBookmarks(); - SearchManager.getInstance(); - transcriptPlugin = new ChatTranscriptPlugin(); - - // Load Broadcast Plugin - broadcastPlugin = new BroadcastPlugin(); - broadcastPlugin.initialize(); - - // Load BookmarkPlugin - bookmarkPlugin = new BookmarkPlugin(); - bookmarkPlugin.initialize(); - - // Schedule loading of the plugins after two seconds. - TaskEngine.getInstance().schedule(new TimerTask() { - public void run() { - final PluginManager pluginManager = PluginManager.getInstance(); - - SparkManager.getMainWindow().addMainWindowListener(pluginManager); - pluginManager.initializePlugins(); - - // Subscriptions are always manual - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - roster.setSubscriptionMode(Roster.SubscriptionMode.manual); - } - }, 2000); - - // Check URI Mappings - SparkManager.getChatManager().handleURIMapping(Spark.ARGUMENTS); - } - - - /** - * Returns the status box for the User. - * - * @return the status box for the user. - */ - public StatusBar getStatusBar() { - return statusBox; - } - - /** - * This is to handle agent to agent conversations. - * - * @param stanza the smack packet to process. - */ - public void processPacket(final Stanza stanza) { - SwingUtilities.invokeLater( () -> { - try - { - handleIncomingPacket(stanza); - } - catch ( SmackException.NotConnectedException e ) - { - // This would be odd: not being connected while receiving a stanza... - Log.warning( "Unable to handle incoming stanza: " + stanza , e ); - } - } ); - } - - - private void handleIncomingPacket(Stanza stanza) throws SmackException.NotConnectedException - { - // We only handle message packets here. - if (stanza instanceof Message) { - final Message message = (Message)stanza; - boolean isGroupChat = message.getType() == Message.Type.groupchat; - - // Check if Conference invite. If so, do not handle here. - if (message.getExtension("x", "jabber:x:conference") != null) { - return; - } - - final String body = message.getBody(); - final JivePropertiesExtension extension = ((JivePropertiesExtension) message.getExtension( JivePropertiesExtension.NAMESPACE )); - final boolean broadcast = extension != null && extension.getProperty( "broadcast" ) != null; - - // Handle offline message. - DelayInformation offlineInformation = message.getExtension("delay", "urn:xmpp:delay"); - if (offlineInformation != null && (Message.Type.chat == message.getType() || - Message.Type.normal == message.getType())) { - handleOfflineMessage(message); - } - - if (body == null || - isGroupChat || - broadcast || - message.getType() == Message.Type.normal || - message.getType() == Message.Type.headline || - message.getType() == Message.Type.error) { - return; - } - - // Create new chat room for Agent Invite. - final String from = stanza.getFrom(); - final String host = SparkManager.getSessionManager().getServerAddress(); - - // Don't allow workgroup notifications to come through here. - final String bareJID = XmppStringUtils.parseBareJid(from); - if (host.equalsIgnoreCase(from) || from == null) { - return; - } - - - ChatRoom room = null; - try { - room = SparkManager.getChatManager().getChatContainer().getChatRoom(bareJID); - } - catch (ChatRoomNotFoundException e) { - // Ignore - } - - // Check for non-existent rooms. - if (room == null) { - createOneToOneRoom(bareJID, message); - } - } - } - - /** - * Creates a new room if necessary and inserts an offline message. - * - * @param message The Offline message. - */ - private void handleOfflineMessage(Message message) throws SmackException.NotConnectedException - { - if(!ModelUtil.hasLength(message.getBody())){ - return; - } - - String bareJID = XmppStringUtils.parseBareJid(message.getFrom()); - ContactItem contact = contactList.getContactItemByJID(bareJID); - String nickname = XmppStringUtils.parseLocalpart(bareJID); - if (contact != null) { - nickname = contact.getDisplayName(); - } - - // Create the room if it does not exist. - ChatRoom room = SparkManager.getChatManager().createChatRoom(bareJID, nickname, nickname); - if(!SparkManager.getChatManager().getChatContainer().getChatFrame().isVisible()) - { - SparkManager.getChatManager().getChatContainer().getChatFrame().setVisible(true); - } - - // Insert offline message - room.getTranscriptWindow().insertMessage(nickname, message, ChatManager.FROM_COLOR, Color.white); - room.addToTranscript(message, true); - - // Send display and notified message back. - SparkManager.getMessageEventManager().sendDeliveredNotification(message.getFrom(), message.getStanzaId()); - SparkManager.getMessageEventManager().sendDisplayedNotification(message.getFrom(), message.getStanzaId()); - } - - /** - * Creates a new room based on an anonymous user. - * - * @param bareJID the bareJID of the anonymous user. - * @param message the message from the anonymous user. - */ - private void createOneToOneRoom(String bareJID, Message message) { - ContactItem contact = contactList.getContactItemByJID(bareJID); - String nickname = XmppStringUtils.parseLocalpart(bareJID); - if (contact != null) { - nickname = contact.getDisplayName(); - } - else { - // Attempt to load VCard from users who we are not subscribed to. - VCard vCard = SparkManager.getVCardManager().getVCard(bareJID); - if (vCard != null && vCard.getError() == null) { - String firstName = vCard.getFirstName(); - String lastName = vCard.getLastName(); - String userNickname = vCard.getNickName(); - if (ModelUtil.hasLength(userNickname)) { - nickname = userNickname; - } - else if (ModelUtil.hasLength(firstName) && ModelUtil.hasLength(lastName)) { - nickname = firstName + " " + lastName; - } - else if (ModelUtil.hasLength(firstName)) { - nickname = firstName; - } - } - } - - SparkManager.getChatManager().createChatRoom(bareJID, nickname, nickname); - try { - insertMessage(bareJID, message); - } - catch (ChatRoomNotFoundException e) { - Log.error("Could not find chat room.", e); - } - } - - - private void insertMessage(final String bareJID, final Message message) throws ChatRoomNotFoundException { - ChatRoom chatRoom = SparkManager.getChatManager().getChatContainer().getChatRoom(bareJID); - chatRoom.insertMessage(message); - int chatLength = chatRoom.getTranscriptWindow().getDocument().getLength(); - chatRoom.getTranscriptWindow().setCaretPosition(chatLength); - chatRoom.getChatInputEditor().requestFocusInWindow(); - } - - - /** - * Returns the Workspace TabbedPane. If you wish to add your - * component, simply use addTab( name, icon, component ) call. - * - * @return the workspace JideTabbedPane - */ - public SparkTabbedPane getWorkspacePane() { - return workspacePane; - } - - - /** - * Returns the ContactList associated with this workspace. - * - * @return the ContactList associated with this workspace. - */ - public ContactList getContactList() { - return contactList; - } - - public void changeCardLayout(String layout) { - cardLayout.show(cardPanel, layout); - } - - public JPanel getCardPanel() { - return cardPanel; - } - - /** - * Returns the CommandPanel of this Workspace. - * - * @return the CommandPanel. - */ - public CommandPanel getCommandPanel() { - return statusBox.getCommandPanel(); - } - - public ChatTranscriptPlugin getTranscriptPlugin() { - return transcriptPlugin; - } -} diff --git a/src/java/org/jivesoftware/spark/component/JContactItemField.java b/src/java/org/jivesoftware/spark/component/JContactItemField.java deleted file mode 100644 index 7b91d1cf6..000000000 --- a/src/java/org/jivesoftware/spark/component/JContactItemField.java +++ /dev/null @@ -1,326 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.component; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.util.ModelUtil; - -import javax.swing.DefaultListModel; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextField; -import javax.swing.JWindow; -import javax.swing.ListCellRenderer; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Point; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.List; - -/** - * Implementation of a popup field from a TextField. - * - * @author Derek DeMoro - */ -public class JContactItemField extends JPanel { - - private static final long serialVersionUID = -8556694682789891531L; - private JTextField textField = new JTextField(); - private DefaultListModel model = new DefaultListModel(); - private JList list; - private JWindow popup; - private List items; - - public JContactItemField(List items) { - setLayout(new BorderLayout()); - list = new JList(model) { - private static final long serialVersionUID = -9031169221430835595L; - - public String getToolTipText(MouseEvent e) { - int row = locationToIndex(e.getPoint()); - if (row >= 0) - { - final ContactItem item = (ContactItem)getModel().getElementAt(row); - if (item != null) { - return item.getJID(); - } - } - return null; - } - }; - - this.items = items; - - add(textField, BorderLayout.CENTER); - - - textField.addKeyListener(new KeyAdapter() { - public void keyReleased(KeyEvent keyEvent) { - char ch = keyEvent.getKeyChar(); - if (validateChar(ch)) { - showPopupMenu(); - } - - if (keyEvent.getKeyCode() == KeyEvent.VK_ENTER) { - int index = list.getSelectedIndex(); - if (index >= 0) { - ContactItem selection = (ContactItem)list.getSelectedValue(); - textField.setText(selection.getDisplayName()); - popup.setVisible(false); - } - } - - if (keyEvent.getKeyCode() == KeyEvent.VK_ESCAPE) { - popup.setVisible(false); - } - dispatchEvent(keyEvent); - } - - public void keyPressed(KeyEvent e) { - if (isArrowKey(e)) { - list.dispatchEvent(e); - } - - } - }); - - - textField.addFocusListener(new FocusListener() { - public void focusGained(FocusEvent e) { - } - - public void focusLost(FocusEvent e) { - textField.requestFocusInWindow(); - } - }); - - - popup = new JWindow(); - - - popup.getContentPane().add(new JScrollPane(list)); - popup.setAlwaysOnTop(true); - - - list.setCellRenderer(new PopupRenderer()); - list.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - int index = list.getSelectedIndex(); - if (index >= 0) { - ContactItem selection = (ContactItem)list.getSelectedValue(); - textField.setText(selection.getDisplayName()); - popup.setVisible(false); - } - } - } - }); - } - - public void dispose() { - popup.dispose(); - } - - public void setItems(List list) { - this.items = list; - } - - public JList getList() { - return list; - } - - private void showPopupMenu() { - model.removeAllElements(); - - String typedItem = textField.getText(); - - final List validItems = new ArrayList<>(); - for (ContactItem contactItem : items) { - String nickname = contactItem.getDisplayName().toLowerCase(); - if (nickname.startsWith(typedItem.toLowerCase())) { - validItems.add(contactItem); - } else if (typedItem.length() > 2 && nickname.contains(typedItem.toLowerCase())) { - validItems.add(contactItem); - } - } - - - if (validItems.size() > 0) { - for (final ContactItem label : validItems) { - model.addElement(label); - } - } - - if (validItems.size() != 0 && !popup.isVisible()) { - popup.pack(); - popup.setSize(textField.getWidth(), 200); - Point pt = textField.getLocationOnScreen(); - pt.translate(0, textField.getHeight()); - popup.setLocation(pt); - popup.toFront(); - popup.setVisible(true); - } - - // set initial selection - if (validItems.size() > 0) { - list.setSelectedIndex(0); - } - - } - - /** - * Validate the given text - to pass it must contain letters, digits, '@', '-', '_', '.', ',' - * or a space character. - * - * @param text the text to check - * @return true if the given text is valid, false otherwise. - */ - public boolean validateChars(String text) { - if (!ModelUtil.hasLength(text)) { - return false; - } - - for (int i = 0; i < text.length(); i++) { - char ch = text.charAt(i); - if (!Character.isLetterOrDigit(ch) && ch != '@' && ch != '-' && ch != '_' - && ch != '.' && ch != ',' && ch != ' ') { - return false; - } - } - - - return true; - } - - /** - * Validate the given text - to pass it must contain letters, digits, '@', '-', '_', '.', ',' - * or a space character. - * - * @param ch the character - * @return true if the given text is valid, false otherwise. - */ - public boolean validateChar(char ch) { - if (!Character.isLetterOrDigit(ch) && ch != '@' && ch != '-' && ch != '_' - && ch != '.' && ch != ',' && ch != ' ' && ch != KeyEvent.VK_BACK_SPACE && ch != KeyEvent.CTRL_DOWN_MASK - && ch != KeyEvent.CTRL_MASK) { - return false; - } - - return true; - } - - public boolean isArrowKey(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN) { - return true; - } - return false; - } - - public String getText() { - return textField.getText(); - } - - public ContactItem getSelectedContactItem() { - return (ContactItem)list.getSelectedValue(); - } - - public void setText(String text) { - textField.setText(text); - } - - public void focus() { - textField.requestFocus(); - } - - public JTextField getTextField() { - return textField; - } - - public JWindow getPopup() { - return popup; - } - - class PopupRenderer extends JLabel implements ListCellRenderer { - private static final long serialVersionUID = 239608430590852355L; - - /** - * Construct Default JLabelIconRenderer. - */ - public PopupRenderer() { - setOpaque(true); - this.setHorizontalTextPosition(JLabel.RIGHT); - this.setHorizontalAlignment(JLabel.LEFT); - } - - public Component getListCellRendererComponent(JList list, - Object value, - int index, - boolean isSelected, - boolean cellHasFocus) { - if (isSelected) { - setBackground(list.getSelectionBackground()); - setForeground(list.getSelectionForeground()); - } - else { - setBackground(list.getBackground()); - setForeground(list.getForeground()); - } - - - ContactItem contactItem = (ContactItem)value; - setText(contactItem.getDisplayName()); - if (contactItem.getIcon() == null) { - setIcon(SparkRes.getImageIcon(SparkRes.CLEAR_BALL_ICON)); - } - else { - setIcon(contactItem.getIcon()); - } - setFont(contactItem.getNicknameLabel().getFont()); - setForeground(contactItem.getForeground()); - - return this; - } - } - - public boolean canClose() { - return !textField.hasFocus(); - } - - /** - * sets the selected Index using the Point of a given {@link MouseEvent} - * @param mouseevent - {@link MouseEvent} to get The {@link Point} from - */ - public void setSelectetIndex(MouseEvent mouseevent) - { - list.setSelectedIndex(list.locationToIndex(mouseevent.getPoint())); - } - - -} diff --git a/src/java/org/jivesoftware/spark/component/MessageDialog.java b/src/java/org/jivesoftware/spark/component/MessageDialog.java deleted file mode 100644 index 223064771..000000000 --- a/src/java/org/jivesoftware/spark/component/MessageDialog.java +++ /dev/null @@ -1,274 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.component; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.EventQueue; -import java.awt.Font; -import java.beans.PropertyChangeListener; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.Writer; -import java.util.Arrays; -import java.util.List; - -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextPane; - -import org.jivesoftware.MainWindow; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.SparkManager; - - -/** - * MessageDialog class is used to easily display the most commonly used dialogs. - */ -public final class MessageDialog { - - private MessageDialog() { - - } - - /** - * Display a dialog with an exception. - * - * @param throwable the throwable object to display. - */ - public static void showErrorDialog(final Throwable throwable) { - EventQueue.invokeLater( () -> { - JTextPane textPane; - final JOptionPane pane; - final JDialog dlg; - - TitlePanel titlePanel; - - textPane = new JTextPane(); - textPane.setFont(new Font("Dialog", Font.PLAIN, 12)); - textPane.setEditable(false); - - String message = getStackTrace(throwable); - textPane.setText(message); - // Create the title panel for this dialog - titlePanel = new TitlePanel(Res.getString("message.default.error"), null, SparkRes.getImageIcon(SparkRes.SMALL_DELETE), true); - - // Construct main panel w/ layout. - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(titlePanel, BorderLayout.NORTH); - - // The user should only be able to close this dialog. - Object[] options = {Res.getString("close")}; - pane = new JOptionPane(new JScrollPane(textPane), JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); - - mainPanel.add(pane, BorderLayout.CENTER); - - MainWindow mainWindow = SparkManager.getMainWindow(); - dlg = new JDialog(mainWindow, Res.getString("title.error"), false); - dlg.pack(); - dlg.setSize(600, 400); - dlg.setContentPane(mainPanel); - dlg.setLocationRelativeTo(mainWindow); - - PropertyChangeListener changeListener = e -> { -String value = (String)pane.getValue(); -if (Res.getString("close").equals(value)) { -dlg.setVisible(false); -} -}; - - pane.addPropertyChangeListener(changeListener); - - dlg.setVisible(true); - dlg.toFront(); - dlg.requestFocus(); - } ); - } - - /** - * Display an alert dialog. - * - * @param message the message to display. - * @param header the header/title of the dialog. - * @param title the title to display. - * @param icon the icon for the alert dialog. - */ - public static void showAlert(final String message,final String header, final String title, final Icon icon) { - EventQueue.invokeLater( () -> { - JTextPane textPane; - final JOptionPane pane; - final JDialog dlg; - - TitlePanel titlePanel; - - textPane = new JTextPane(); - textPane.setFont(new Font("Dialog", Font.PLAIN, 12)); - textPane.setEditable(false); - textPane.setText(message); - textPane.setBackground(Color.white); - - // Create the title panel for this dialog - titlePanel = new TitlePanel(header, null, icon, true); - - // Construct main panel w/ layout. - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(titlePanel, BorderLayout.NORTH); - - // The user should only be able to close this dialog. - Object[] options = {Res.getString("close")}; - pane = new JOptionPane(new JScrollPane(textPane), JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); - - mainPanel.add(pane, BorderLayout.CENTER); - - MainWindow mainWindow = SparkManager.getMainWindow(); - dlg = new JDialog(mainWindow, title, false); - dlg.pack(); - dlg.setSize(300, 300); - dlg.setContentPane(mainPanel); - dlg.setLocationRelativeTo(SparkManager.getMainWindow()); - - PropertyChangeListener changeListener = e -> { -String value = (String)pane.getValue(); -if (Res.getString("close").equals(value)) { -dlg.setVisible(false); -} -}; - - pane.addPropertyChangeListener(changeListener); - - dlg.setVisible(true); - dlg.toFront(); - dlg.requestFocus(); - - } ); - - } - - /** - * Display a dialog with a specified component. - * - * @param title the title of the dialog. - * @param description the description to display. - * @param icon the icon. - * @param comp the component to display. - * @param parent the parent of this dialog. - * @param width the width of this dialog. - * @param height the height of this dialog. - * @param modal true if it is modal. - * @return the JDialog created. - */ - public static JDialog showComponent(String title, String description, Icon icon, JComponent comp, Component parent, int width, int height, boolean modal) { - final JOptionPane pane; - final JDialog dlg; - - TitlePanel titlePanel; - - // Create the title panel for this dialog - titlePanel = new TitlePanel(title, description, icon, true); - - // Construct main panel w/ layout. - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(titlePanel, BorderLayout.NORTH); - - // The user should only be able to close this dialog. - Object[] options = {Res.getString("close")}; - pane = new JOptionPane(comp, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); - - mainPanel.add(pane, BorderLayout.CENTER); - - JOptionPane p = new JOptionPane(); - dlg = p.createDialog(parent, title); - dlg.setModal(modal); - - dlg.pack(); - dlg.setSize(width, height); - dlg.setResizable(true); - dlg.setContentPane(mainPanel); - dlg.setLocationRelativeTo(parent); - - PropertyChangeListener changeListener = e -> { - String value; - try { - value= (String)pane.getValue(); - if (Res.getString("close").equals(value)) { - dlg.setVisible(false); - } - } catch (Exception ex) { - // probably pressed ;-) - } - - }; - - pane.addPropertyChangeListener(changeListener); - - dlg.setVisible(true); - dlg.toFront(); - dlg.requestFocus(); - return dlg; - } - - /** - * Returns the String representation of a StackTrace. - * - * @param aThrowable the throwable object. - * @return the string. - */ - public static String getStackTrace(Throwable aThrowable) { - final Writer result = new StringWriter(); - final PrintWriter printWriter = new PrintWriter(result); - aThrowable.printStackTrace(printWriter); - return result.toString(); - } - - /** - * Defines a custom format for the stack trace as String. - * - * @param heading the title of the stack trace. - * @param aThrowable the throwable object. - * @return the string. - */ - public static String getCustomStackTrace(String heading, Throwable aThrowable) { - //add the class name and any message passed to constructor - final StringBuilder result = new StringBuilder(heading); - result.append(aThrowable.toString()); - final String lineSeperator = System.getProperty("line.separator"); - result.append(lineSeperator); - - //add each element of the stack trace - StackTraceElement[] stackTrace = aThrowable.getStackTrace(); - final List traceElements = Arrays.asList(stackTrace); - for (StackTraceElement traceElement : traceElements) { - result.append(traceElement); - result.append(lineSeperator); - } - return result.toString(); - } - - -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/spark/component/PasswordDialog.java b/src/java/org/jivesoftware/spark/component/PasswordDialog.java deleted file mode 100644 index f099b1553..000000000 --- a/src/java/org/jivesoftware/spark/component/PasswordDialog.java +++ /dev/null @@ -1,184 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.component; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.spark.SparkManager; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.GridBagLayout; -import java.awt.GridBagConstraints; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.Icon; -import javax.swing.JDialog; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPasswordField; -import javax.swing.JLabel; - - -/** - * PasswordDialog class is used to retrieve information from a user. - * - * @author Derek DeMoro - */ -public final class PasswordDialog implements PropertyChangeListener { - private JPasswordField passwordField; - private JOptionPane optionPane; - private JDialog dialog; - - private String stringValue; - private int width = 400; - private int height = 200; - - /** - * Empty Constructor. - */ - public PasswordDialog() { - } - - /** - * Returns the input from a user. - * - * @param title the title of the dialog. - * @param description the dialog description. - * @param icon the icon to use. - * @param width the dialog width - * @param height the dialog height - * @return the users input. - */ - public String getInput(String title, String description, Icon icon, int width, int height) { - this.width = width; - this.height = height; - - return getPassword(title, description, icon, SparkManager.getMainWindow()); - } - - /** - * Prompt and return input. - * - * @param title the title of the dialog. - * @param description the dialog description. - * @param icon the icon to use. - * @param parent the parent to use. - * @return the user input. - */ - public String getPassword(String title, String description, Icon icon, Component parent) { - passwordField = new JPasswordField(); - - TitlePanel titlePanel = new TitlePanel(title, description, icon, true); - - // Construct main panel w/ layout. - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(titlePanel, BorderLayout.NORTH); - - final JPanel passwordPanel = new JPanel(new GridBagLayout()); - JLabel passwordLabel = new JLabel(Res.getString("label.enter.password") + ":"); - passwordPanel.add(passwordLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - passwordPanel.add(passwordField, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - - // The user should only be able to close this dialog. - final Object[] options = {Res.getString("ok"), Res.getString("cancel")}; - optionPane = new JOptionPane(passwordPanel, JOptionPane.PLAIN_MESSAGE, - JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); - - mainPanel.add(optionPane, BorderLayout.CENTER); - - // Lets make sure that the dialog is modal. Cannot risk people - // losing this dialog. - JOptionPane p = new JOptionPane(); - dialog = p.createDialog(parent, title); - dialog.setModal(true); - dialog.pack(); - dialog.setSize(width, height); - dialog.setContentPane(mainPanel); - dialog.setLocationRelativeTo(parent); - optionPane.addPropertyChangeListener(this); - - // Add Key Listener to Send Field - passwordField.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { - if (e.getKeyChar() == KeyEvent.VK_TAB) { - optionPane.requestFocus(); - } - else if (e.getKeyChar() == KeyEvent.VK_ESCAPE) { - dialog.dispose(); - } - } - }); - - passwordField.requestFocus(); - - - dialog.setVisible(true); - return stringValue; - } - - /** - * Move to focus forward action. - */ - public Action nextFocusAction = new AbstractAction(Res.getString("label.move.focus.forwards")) { - private static final long serialVersionUID = 6465350147231073505L; - - public void actionPerformed(ActionEvent evt) { - ((Component)evt.getSource()).transferFocus(); - } - }; - - /** - * Moves the focus backwards in the dialog. - */ - public Action prevFocusAction = new AbstractAction(Res.getString("label.move.focus.backwards")) { - private static final long serialVersionUID = -91177056113094990L; - - public void actionPerformed(ActionEvent evt) { - ((Component)evt.getSource()).transferFocusBackward(); - } - }; - - public void propertyChange(PropertyChangeEvent e) { - String value = (String)optionPane.getValue(); - if (Res.getString("cancel").equals(value)) { - stringValue = null; - dialog.setVisible(false); - } - else if (Res.getString("ok").equals(value)) { - stringValue = String.valueOf(passwordField.getPassword()); - if (stringValue.trim().length() == 0) { - stringValue = null; - } - else { - stringValue = stringValue.trim(); - } - dialog.setVisible(false); - } - } -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/spark/component/TitlePanel.java b/src/java/org/jivesoftware/spark/component/TitlePanel.java deleted file mode 100644 index febe9530e..000000000 --- a/src/java/org/jivesoftware/spark/component/TitlePanel.java +++ /dev/null @@ -1,155 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.component; - -import org.jivesoftware.resource.Default; - -import java.awt.Color; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Image; -import java.awt.Insets; -import java.awt.LayoutManager; -import java.awt.geom.AffineTransform; - -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; - -/** - * TitlePanel class is the top panel displayed in this application. This - * should be used to identify the application to users using a title, brief description, - * and the company's logo. - * - * @author Derek DeMoro - */ -public final class TitlePanel extends JPanel { - private static final long serialVersionUID = -967166058268240672L; - private final JLabel titleLabel = new JLabel(); - private final JLabel descriptionLabel = new JLabel(); - - /** - * Create a new TitlePanel. - * - * @param title the title to use with the panel. - * @param description the panel description. - * @param icon the icon to use with the panel. - * @param showDescription true if the descrption should be shown. - */ - public TitlePanel(String title, String description, Icon icon, boolean showDescription) { - - // Set the icon - JLabel iconLabel = new JLabel(); - iconLabel.setIcon(icon); - - // Set the title - setTitle(title); - - // Set the description - setDescription(description); - - GridBagLayout gridBagLayout = new GridBagLayout(); - setLayout( gridBagLayout ); - - descriptionLabel.setBackground(Color.white); - - if (showDescription) { - add( iconLabel, new GridBagConstraints(2, 0, 1, 2, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(descriptionLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 9, 5, 5), 0, 0)); - add(titleLabel, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - setBackground(Color.white); - - titleLabel.setFont(new Font("dialog", Font.BOLD, 11)); - descriptionLabel.setFont(new Font("dialog", 0, 10)); - } - else { - final JPanel panel = new ImagePanel(); - panel.setBorder(BorderFactory.createEtchedBorder()); - - panel.setLayout(new GridBagLayout()); - panel.add(titleLabel, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0)); - panel.add( iconLabel, new GridBagConstraints(2, 0, 1, 2, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - - titleLabel.setVerticalTextPosition(JLabel.CENTER); - titleLabel.setFont(new Font("dialog", Font.BOLD, 14)); - titleLabel.setForeground(Color.black); - descriptionLabel.setFont(new Font("dialog", 0, 10)); - add(panel, new GridBagConstraints(0, 0, 1, 0, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 2, 2, 2), 0, 0)); - } - - } - - - /** - * Set the icon for the panel. - * - * @param icon - the relative icon based on classpath. ex. /com/jivesoftware/images/Foo.gif. - */ - public final void setIcon(Icon icon) { - titleLabel.setIcon(icon); - } - - /** - * Set the main title for this panel. - * - * @param title - main title. - */ - public final void setTitle(String title) { - titleLabel.setText(title); - } - - /** - * Set a brief description which will be displayed below the main title. - * - * @param desc - brief description - */ - public final void setDescription(String desc) { - desc = ""+desc+""; - descriptionLabel.setText(desc); - } - - public class ImagePanel extends JPanel { - private static final long serialVersionUID = 5155908601530113727L; - final ImageIcon icons = Default.getImageIcon(Default.SECONDARY_BACKGROUND_IMAGE); - - public ImagePanel() { - - } - - public ImagePanel(LayoutManager layout) { - super(layout); - } - - public void paintComponent(Graphics g) { - Image backgroundImage = icons.getImage(); - double scaleX = getWidth() / (double)backgroundImage.getWidth(null); - double scaleY = getHeight() / (double)backgroundImage.getHeight(null); - AffineTransform xform = AffineTransform.getScaleInstance(scaleX, scaleY); - ((Graphics2D)g).drawImage(backgroundImage, xform, this); - } - } - - -} diff --git a/src/java/org/jivesoftware/spark/component/browser/BrowserViewer.java b/src/java/org/jivesoftware/spark/component/browser/BrowserViewer.java deleted file mode 100644 index ed82a7466..000000000 --- a/src/java/org/jivesoftware/spark/component/browser/BrowserViewer.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.component.browser; - -import javax.swing.JPanel; - -import java.util.ArrayList; -import java.util.List; - -/** - * Abstract class describing a particular type of component capable of rendering html. - * - * @author Derek DeMoro - * @see NativeBrowserViewer - */ -public abstract class BrowserViewer extends JPanel { - private static final long serialVersionUID = -5389246902135069702L; - private List listeners = new ArrayList<>(); - - /** - * Add a BrowserListener. - * - * @param listener the listener. - */ - public void addBrowserListener(BrowserListener listener) { - listeners.add(listener); - } - - /** - * Remove a BrowserListener. - * - * @param listener the listener. - */ - public void removeBrowserListener(BrowserListener listener) { - listeners.remove(listener); - } - - /** - * Fire all BrowserListeners. - * - * @param document the document that has been downloaded. - */ - public void fireBrowserListeners(String document) { - for (BrowserListener listener : listeners) { - listener.documentLoaded(document); - } - } - - - public void documentLoaded(String document) { - fireBrowserListeners(document); - } - - /** - * Should create the UI necessary to display html. - */ - public abstract void initializeBrowser(); - - /** - * Should load the given url. - * - * @param url the url to load. - */ - public abstract void loadURL(String url); - - /** - * Should go back in history one page. - */ - public abstract void goBack(); - -} diff --git a/src/java/org/jivesoftware/spark/component/browser/EmbeddedBrowserViewer.java b/src/java/org/jivesoftware/spark/component/browser/EmbeddedBrowserViewer.java deleted file mode 100644 index ae3e87767..000000000 --- a/src/java/org/jivesoftware/spark/component/browser/EmbeddedBrowserViewer.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.component.browser; - -import java.awt.BorderLayout; -import java.net.MalformedURLException; - -import javax.swing.JFrame; -import javax.swing.LookAndFeel; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; - -import org.lobobrowser.gui.ContentEvent; -import org.lobobrowser.gui.ContentListener; -import org.lobobrowser.gui.FramePanel; -import org.lobobrowser.main.PlatformInit; - -public class EmbeddedBrowserViewer extends BrowserViewer implements ContentListener { - - private static final long serialVersionUID = -8055149462713514766L; - private FramePanel browser; - - /** - * Constructs a new LobobrowserViewer - */ - public EmbeddedBrowserViewer() { - LookAndFeel laf = UIManager.getLookAndFeel(); - try { - PlatformInit.getInstance().init(false, false); - } catch (Exception e) { - e.printStackTrace(); - } - - browser = new FramePanel(); - //substance look and feel - try { - UIManager.setLookAndFeel(laf); - } - catch (UnsupportedLookAndFeelException e) { - e.printStackTrace(); - } - browser.addContentListener(this); - } - - /** - * Implementation of "Back"-button - */ - public void goBack() { - browser.back(); - } - - /** - * Initialization of the BrowserViewer - */ - public void initializeBrowser() { - this.setLayout(new BorderLayout()); - this.add(browser, BorderLayout.CENTER); - } - - /** - * Load the given URL - */ - public void loadURL(String url) { - try { - browser.navigate(url); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - } - - /** - * React to an event by updating the address bar - */ - public void contentSet(ContentEvent event) { - if (browser == null || browser.getCurrentNavigationEntry() == null) { - return; - } - String url = browser.getCurrentNavigationEntry().getUrl().toExternalForm(); - documentLoaded(url); - } - - public static void main(String[] args) { - EmbeddedBrowserViewer viewer = new EmbeddedBrowserViewer(); - viewer.initializeBrowser(); - JFrame frame = new JFrame("Test"); - - frame.getContentPane().setLayout(new BorderLayout()); - frame.getContentPane().add(viewer, BorderLayout.CENTER); - frame.setVisible(true); - frame.pack(); - frame.setSize(600, 400); - viewer.loadURL("http://igniterealtime.org"); - } -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/spark/component/panes/CollapsiblePane.java b/src/java/org/jivesoftware/spark/component/panes/CollapsiblePane.java deleted file mode 100644 index 8a6ffea80..000000000 --- a/src/java/org/jivesoftware/spark/component/panes/CollapsiblePane.java +++ /dev/null @@ -1,159 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.component.panes; - -import org.jivesoftware.spark.util.ModelUtil; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import javax.swing.Icon; -import javax.swing.JPanel; - -/** - * CollapsiblePane provides a component which can collapse or expand its content area - * with animation and fade in/fade out effects. It also acts as a standard container for - * other Swing components. - * - * @author Derek DeMoro - */ -/** - * - */ -public class CollapsiblePane extends JPanel { - - private static final long serialVersionUID = -6770924580102536726L; - private BaseCollapsibleTitlePane titlePane; - private JPanel mainPanel; - - private List listeners = new ArrayList<>(); - - private boolean subPane; - - public CollapsiblePane() { - setLayout(new BorderLayout()); - - titlePane = new CollapsibleTitlePane(); - mainPanel = new JPanel(); - - - add(titlePane, BorderLayout.NORTH); - add(mainPanel, BorderLayout.CENTER); - - mainPanel.setLayout(new BorderLayout()); - - titlePane.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if (e.isPopupTrigger()) { - return; - } - boolean isCollapsed = titlePane.isCollapsed(); - setCollapsed(!isCollapsed); - } - }); - } - - /** - * Creates a CollapsiblePane. - * @param title the title to use. - */ - public CollapsiblePane(String title) { - this(); - setTitle(title); - } - - /** - * Set the title of the Collapsible Pane. - * @param title the collapsible pane title. - */ - public void setTitle(String title) { - titlePane.setTitle(title); - } - - public void setIcon(Icon icon) { - titlePane.setIcon(icon); - } - - public void setCollapsed(boolean collapsed) { - titlePane.setCollapsed(collapsed); - mainPanel.setVisible(!collapsed); - - if (collapsed) { - firePaneCollapsed(); - } - else { - firePaneExpanded(); - } - } - - public void setContentPane(Component comp) { - mainPanel.add(comp); - } - - public void addCollapsiblePaneListener(CollapsiblePaneListener listener) { - listeners.add(listener); - } - - public void removeCollapsiblePaneListener(CollapsiblePaneListener listener) { - listeners.remove(listener); - } - - private void firePaneExpanded() { - final Iterator iter = ModelUtil.reverseListIterator(listeners.listIterator()); - while (iter.hasNext()) { - (iter.next()).paneExpanded(); - } - } - - private void firePaneCollapsed() { - final Iterator iter = ModelUtil.reverseListIterator(listeners.listIterator()); - while (iter.hasNext()) { - (iter.next()).paneCollapsed(); - } - } - - - public BaseCollapsibleTitlePane getTitlePane() { - return titlePane; - } - - protected void setTitlePane(BaseCollapsibleTitlePane titlePane) { - this.titlePane = titlePane; - } - - public boolean isCollapsed() { - return titlePane.isCollapsed(); - } - - public boolean isSubPane() { - return subPane; - } - - public void setSubPane(boolean subPane) { - this.subPane = subPane; - - titlePane.setSubPane(subPane); - } -} diff --git a/src/java/org/jivesoftware/spark/component/renderer/JLabelIconRenderer.java b/src/java/org/jivesoftware/spark/component/renderer/JLabelIconRenderer.java deleted file mode 100644 index c33e7b6bf..000000000 --- a/src/java/org/jivesoftware/spark/component/renderer/JLabelIconRenderer.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.component.renderer; - - -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.ListCellRenderer; - -import java.awt.Component; - -/** - * The JLabelIconRenderer is the an implementation of ListCellRenderer - * to add icons w/ associated text in JComboBox and JList. - * - * @author Derek DeMoro - */ -public class JLabelIconRenderer extends JLabel implements ListCellRenderer { - private static final long serialVersionUID = -694803906607554443L; - - /** - * Construct Default JLabelIconRenderer. - */ - public JLabelIconRenderer() { - setOpaque(true); - this.setVerticalTextPosition(JLabel.BOTTOM); - this.setHorizontalTextPosition(JLabel.CENTER); - this.setHorizontalAlignment(JLabel.CENTER); - } - - public Component getListCellRendererComponent(JList list, - Object value, - int index, - boolean isSelected, - boolean cellHasFocus) { - if (isSelected) { - setBackground(list.getSelectionBackground()); - setForeground(list.getSelectionForeground()); - } - else { - setBackground(list.getBackground()); - setForeground(list.getForeground()); - } - - this.setVerticalTextPosition(JLabel.BOTTOM); - this.setHorizontalTextPosition(JLabel.CENTER); - - JLabel label = (JLabel)value; - setText(label.getText()); - setIcon(label.getIcon()); - return this; - } -} - diff --git a/src/java/org/jivesoftware/spark/component/tabbedPane/SparkTab.java b/src/java/org/jivesoftware/spark/component/tabbedPane/SparkTab.java deleted file mode 100644 index ee692e43a..000000000 --- a/src/java/org/jivesoftware/spark/component/tabbedPane/SparkTab.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.component.tabbedPane; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Font; - -import javax.swing.Icon; -import javax.swing.JPanel; - -public class SparkTab extends JPanel -{ - private static final long serialVersionUID = 2027267184472260195L; - private SparkTabbedPane pane = null; - private Component component = null; - - public SparkTab(SparkTabbedPane pane, Component comp) - { - this.pane = pane; - this.component = comp; - this.setLayout(new BorderLayout()); - add(comp); - } - - public void setTabTitle(String title) - { - pane.setTitleAt(pane.getTabPosition(this),title); - } - - public void setIcon(Icon icon) - { - pane.setIconAt(pane.getTabPosition(this), icon); - } - - public Component getComponent() - { - return component; - } - - public String getTitleLabel() - { - return pane.getTitleAt(pane.getTabPosition(this)); - } - - public String getActualText() - { - return pane.getTitleAt(pane.getTabPosition(this)); - } - - public void setTitleColor(Color color) - { - pane.setTitleColorAt(pane.getTabPosition(this),color); - } - - public void setTabBold(boolean bold) - { - pane.setTitleBoldAt(pane.getTabPosition(this),bold); - } - - public Font getDefaultFont() - { - return pane.getDefaultFontAt(pane.getTabPosition(this)); - } - - public void setTabFont(Font font) - { - pane.setTitleFontAt(pane.getTabPosition(this),font); - } - - public void validateTab() - { - invalidate(); - validate(); - repaint(); - } -} diff --git a/src/java/org/jivesoftware/spark/component/tabbedPane/SparkTabbedPane.java b/src/java/org/jivesoftware/spark/component/tabbedPane/SparkTabbedPane.java deleted file mode 100644 index f2ec35516..000000000 --- a/src/java/org/jivesoftware/spark/component/tabbedPane/SparkTabbedPane.java +++ /dev/null @@ -1,609 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.component.tabbedPane; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.Transferable; -import java.awt.datatransfer.UnsupportedFlavorException; -import java.awt.dnd.DnDConstants; -import java.awt.dnd.DragGestureListener; -import java.awt.dnd.DragSource; -import java.awt.dnd.DragSourceDragEvent; -import java.awt.dnd.DragSourceDropEvent; -import java.awt.dnd.DragSourceEvent; -import java.awt.dnd.DragSourceListener; -import java.awt.dnd.DropTarget; -import java.awt.dnd.DropTargetDragEvent; -import java.awt.dnd.DropTargetDropEvent; -import java.awt.dnd.DropTargetEvent; -import java.awt.dnd.DropTargetListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import javax.swing.Icon; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTabbedPane; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.event.ChangeListener; - -import org.jivesoftware.Spark; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.ui.ChatRoomNotFoundException; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; - -public class SparkTabbedPane extends JPanel { - private static final long serialVersionUID = -9007068462231539973L; - private static final String NAME = "SparkTabbedPane"; - private List listeners = new ArrayList<>(); - private JTabbedPane pane = null; - private Icon closeInactiveButtonIcon; - private Icon closeActiveButtonIcon; - private boolean closeEnabled = false; - private int dragTabIndex = -1; - - /** - * The default Hand cursor. - */ - public static final Cursor HAND_CURSOR = new Cursor(Cursor.HAND_CURSOR); - - /** - * The default Text Cursor. - */ - public static final Cursor DEFAULT_CURSOR = new Cursor( - Cursor.DEFAULT_CURSOR); - - public SparkTabbedPane() { - this(JTabbedPane.TOP); - } - - public SparkTabbedPane(final Integer type) { - this(type.intValue()); - } - public SparkTabbedPane(final int type) { - - pane = buildTabbedPane(type); - pane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); - - setLayout(new BorderLayout()); - add(pane); - ChangeListener changeListener = changeEvent -> { - JTabbedPane sourceTabbedPane = (JTabbedPane) changeEvent.getSource(); - int index = sourceTabbedPane.getSelectedIndex(); - if (index >= 0) { - fireTabSelected(getTabAt(index), getTabAt(index).getComponent(), index); - } - }; - pane.addChangeListener(changeListener); - - closeInactiveButtonIcon = SparkRes.getImageIcon(SparkRes.CLOSE_WHITE_X_IMAGE); - closeActiveButtonIcon = SparkRes.getImageIcon(SparkRes.CLOSE_DARK_X_IMAGE); - - } - - public SparkTab getTabContainingComponent(Component component) { - for (Component comp : pane.getComponents()) { - if (comp instanceof SparkTab) { - SparkTab tab = (SparkTab) comp; - if (tab.getComponent() == component) - return tab; - } - } - return null; - } - - public SparkTab addTab(String title, Icon icon, final Component component) { - return addTab(title, icon, component, null); - } - - public SparkTab addTab(String title, Icon icon, final Component component, - String tip) { - final SparkTab sparktab = new SparkTab(this, component); - - TabPanel tabpanel = new TabPanel(sparktab, title, icon); - pane.addTab(null, null, sparktab, tip); - - pane.setTabComponentAt(pane.getTabCount() - 1, tabpanel); - fireTabAdded(sparktab, component, getTabPosition(sparktab)); - - return sparktab; - } - - public SparkTab getTabAt(int index) { - return ((SparkTab) pane.getComponentAt(index)); - } - - public int getTabPosition(SparkTab tab) { - return pane.indexOfComponent(tab); - } - - public Component getComponentInTab(SparkTab tab) { - return tab.getComponent(); - } - - public void setIconAt(int index, Icon icon) { - Component com = pane.getTabComponentAt(index); - if (com instanceof TabPanel) { - TabPanel panel = (TabPanel) com; - panel.setIcon(icon); - } - } - - public void setTitleAt(int index, String title) { - if (index > 0) { - Component com = pane.getTabComponentAt(index); - if (com instanceof TabPanel) { - TabPanel panel = (TabPanel) com; - panel.setTitle(title); - } - } - } - - public void setTitleColorAt(int index, Color color) { - - Component com = pane.getTabComponentAt(index); - if (com instanceof TabPanel) { - TabPanel panel = (TabPanel) com; - panel.setTitleColor(color); - } - } - - /* - * Updates the tab colors for unread,active and inactive tabs - */ - public void updateActiveTab() - { - for (int i = 0; i < pane.getTabCount(); ++i) { - Component com = pane.getTabComponentAt(i); - TabPanel panel = (TabPanel) com; - Font oldFont = panel.getFont(); - try { - if (SparkManager.getChatManager().getChatContainer().getChatRoom(i).getUnreadMessageCount() == 0) - { - if (i == getSelectedIndex()) { - panel.setTitleFont(new Font(oldFont.getFontName(), Font.BOLD, - oldFont.getSize())); - panel.setTitleColor((Color) UIManager.get("Chat.activeTabColor")); - } else { - panel.setTitleFont(new Font(oldFont.getFontName(), Font.PLAIN, - oldFont.getSize())); - panel.setTitleColor((Color) UIManager.get("Chat.inactiveTabColor")); - } - } - - } catch (ChatRoomNotFoundException e) { - //Do nothing - } - - } - - - - - } - - public void setTitleBoldAt(int index, boolean bold) { - Component com = pane.getTabComponentAt(index); - if (com instanceof TabPanel) { - TabPanel panel = (TabPanel) com; - panel.setTitleBold(bold); - } - } - - public void setTitleFontAt(int index, Font font) { - Component com = pane.getTabComponentAt(index); - if (com instanceof TabPanel) { - TabPanel panel = (TabPanel) com; - panel.setTitleFont(font); - } - } - - public Font getDefaultFontAt(int index) { - Component com = pane.getTabComponentAt(index); - if (com instanceof TabPanel) { - TabPanel panel = (TabPanel) com; - return panel.getDefaultFont(); - } - return null; - } - - public String getTitleAt(int index) { - return pane.getTitleAt(index); - } - - public int getTabCount() { - return pane.getTabCount(); - } - - public void setSelectedIndex(int index) { - pane.setSelectedIndex(index); - } - - public int indexOfComponent(Component component) { - for (Component comp : pane.getComponents()) { - if (comp instanceof SparkTab) { - SparkTab tab = (SparkTab) comp; - if (tab.getComponent() == component) - return pane.indexOfComponent(tab); - } - } - return -1; - } - - public Component getComponentAt(int index) { - return ((SparkTab) pane.getComponentAt(index)).getComponent(); - } - - public Component getTabComponentAt(int index) { - return pane.getTabComponentAt(index); - } - - public Component getTabComponentAt(SparkTab tab) { - return pane.getTabComponentAt(indexOfComponent(tab)); - } - - public Component getSelectedComponent() { - if (pane.getSelectedComponent() instanceof SparkTab) { - SparkTab tab = (SparkTab) pane.getSelectedComponent(); - return tab.getComponent(); - } - return null; - } - - public void removeTabAt(int index) { - pane.remove(index); - } - - public int getSelectedIndex() { - return pane.getSelectedIndex(); - } - - public void setCloseButtonEnabled(boolean enable) { - closeEnabled = enable; - } - - public void addSparkTabbedPaneListener(SparkTabbedPaneListener listener) { - listeners.add(listener); - } - - public void removeSparkTabbedPaneListener(SparkTabbedPaneListener listener) { - listeners.remove(listener); - } - - protected void fireTabAdded(SparkTab tab, Component component, int index) { - final Iterator list = ModelUtil.reverseListIterator(listeners - .listIterator()); - while (list.hasNext()) { - (list.next()).tabAdded(tab, component, - index); - } - } - - public JPanel getMainPanel() { - return this; - } - - public void removeComponent(Component comp) { - int index = indexOfComponent(comp); - if (index != -1) { - removeTabAt(index); - } - } - - protected void fireTabRemoved(SparkTab tab, Component component, int index) { - final Iterator list = ModelUtil.reverseListIterator(listeners - .listIterator()); - while (list.hasNext()) { - (list.next()).tabRemoved(tab, component, - index); - } - } - - protected void fireTabSelected(SparkTab tab, Component component, int index) { - final Iterator list = ModelUtil.reverseListIterator(listeners - .listIterator()); - while (list.hasNext()) { - (list.next()).tabSelected(tab, component, - index); - } - } - - protected void allTabsClosed() { - final Iterator list = ModelUtil.reverseListIterator(listeners - .listIterator()); - while (list.hasNext()) { - list.next().allTabsRemoved(); - } - } - - public void close(SparkTab sparktab) { - int closeTabNumber = pane.indexOfComponent(sparktab); - pane.removeTabAt(closeTabNumber); - fireTabRemoved(sparktab, sparktab.getComponent(), closeTabNumber); - - if (pane.getTabCount() == 0) { - allTabsClosed(); - } - } - - private class TabPanel extends JPanel { - private static final long serialVersionUID = -8249981130816404360L; - private final BorderLayout layout = new BorderLayout(5, 5); - private final Font defaultFontPlain = new Font("Dialog", Font.PLAIN, 11); - private final Font defaultFontBold = new Font("Dialog", Font.BOLD, 11); - private JLabel iconLabel; - private JLabel titleLabel; - private JLabel tabCloseButton = new JLabel(closeInactiveButtonIcon); - - public TabPanel(final SparkTab sparktab, String title, Icon icon) { - setOpaque(false); - this.setLayout(layout); - titleLabel = new JLabel(title); - - titleLabel.setFont(closeEnabled ? defaultFontBold - : defaultFontPlain); - if (icon != null) { - iconLabel = new JLabel(icon); - add(iconLabel, BorderLayout.WEST); - } - - add(titleLabel, BorderLayout.CENTER); - if (closeEnabled) { - tabCloseButton.addMouseListener(new MouseAdapter() { - public void mouseEntered(MouseEvent mouseEvent) { - if (Spark.isWindows()) { - tabCloseButton.setIcon(closeActiveButtonIcon); - } - setCursor(HAND_CURSOR); - } - - public void mouseExited(MouseEvent mouseEvent) { - if (Spark.isWindows()) { - tabCloseButton.setIcon(closeInactiveButtonIcon); - } - setCursor(DEFAULT_CURSOR); - } - - public void mousePressed(MouseEvent mouseEvent) { - final SwingWorker closeTimerThread = new SwingWorker() { - public Object construct() { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - Log.error(e); - } - return true; - } - - public void finished() { - close(sparktab); - } - }; - closeTimerThread.start(); - } - }); - add(tabCloseButton, BorderLayout.EAST); - } - } - - @Override - public Dimension getPreferredSize() { - Dimension dim = super.getPreferredSize(); - - if (closeEnabled && titleLabel.getText() != null && titleLabel.getText().length() < 6 - && dim.getWidth() < 80) { - return new Dimension(80, dim.height); - - } else { - return dim; - } - - } - - public Font getDefaultFont() { - return defaultFontPlain; - } - - public void setIcon(Icon icon) { - iconLabel.setIcon(icon); - } - - public void setTitle(String title) { - titleLabel.setText(title); - } - - public void setTitleColor(Color color) { - titleLabel.setForeground(color); - titleLabel.validate(); - titleLabel.repaint(); - } - - public void setTitleBold(boolean bold) { - Font oldFont = titleLabel.getFont(); - Font newFont; - if (bold) { - newFont = new Font(oldFont.getFontName(), Font.BOLD, - oldFont.getSize()); - } else { - newFont = new Font(oldFont.getFontName(), Font.PLAIN, - oldFont.getSize()); - } - - titleLabel.setFont(newFont); - titleLabel.validate(); - titleLabel.repaint(); - titleLabel.revalidate(); - } - - public void setTitleFont(Font font) { - titleLabel.setFont(font); - titleLabel.validate(); - titleLabel.repaint(); - titleLabel.revalidate(); - } - - } - - /** - * Drag and Drop - */ - public void enableDragAndDrop() { - final DragSourceListener dsl = new DragSourceListener() { - - @Override - public void dragDropEnd(DragSourceDropEvent event) { - dragTabIndex = -1; - } - - @Override - public void dragEnter(DragSourceDragEvent event) { - event.getDragSourceContext().setCursor(DragSource.DefaultMoveDrop); - } - - @Override - public void dragExit(DragSourceEvent event) {} - - @Override - public void dragOver(DragSourceDragEvent event) {} - - @Override - public void dropActionChanged(DragSourceDragEvent event) {} - - }; - - final Transferable t = new Transferable() { - private final DataFlavor FLAVOR = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType, NAME); - @Override - public Object getTransferData(DataFlavor flavor) - throws UnsupportedFlavorException, IOException { - return pane; - } - - @Override - public DataFlavor[] getTransferDataFlavors() { - DataFlavor[] f = new DataFlavor[1]; - f[0] = this.FLAVOR; - return f; - } - - @Override - public boolean isDataFlavorSupported(DataFlavor flavor) { - return flavor.getHumanPresentableName().equals(NAME); - } - - }; - - final DragGestureListener dgl = event -> { -dragTabIndex = pane.indexAtLocation(event.getDragOrigin().x, event.getDragOrigin().y); -try { -event.startDrag(DragSource.DefaultMoveDrop, t, dsl); -} catch(Exception idoe) { -Log.error(idoe); -} - }; - - final DropTargetListener dtl = new DropTargetListener() { - - @Override - public void dragEnter(DropTargetDragEvent event) {} - - @Override - public void dragExit(DropTargetEvent event) {} - - @Override - public void dragOver(DropTargetDragEvent event) {} - - @Override - public void drop(DropTargetDropEvent event) { - int dropTabIndex = getTargetTabIndex(event.getLocation()); - moveTab(dragTabIndex,dropTabIndex); - } - - @Override - public void dropActionChanged(DropTargetDragEvent event) {} - - }; - - new DropTarget(pane, DnDConstants.ACTION_COPY_OR_MOVE, dtl, true); - new DragSource().createDefaultDragGestureRecognizer(pane, DnDConstants.ACTION_COPY_OR_MOVE, dgl); - } - - - private void moveTab(int prev, int next) { - if (next < 0 || prev == next) { - return; - } - Component cmp = pane.getComponentAt(prev); - Component tab = pane.getTabComponentAt(prev); - String str = pane.getTitleAt(prev); - Icon icon = pane.getIconAt(prev); - String tip = pane.getToolTipTextAt(prev); - boolean flg = pane.isEnabledAt(prev); - int tgtindex = prev > next ? next : next - 1; - pane.remove(prev); - pane.insertTab(str, icon, cmp, tip, tgtindex); - pane.setEnabledAt(tgtindex, flg); - - if (flg) - pane.setSelectedIndex(tgtindex); - - pane.setTabComponentAt(tgtindex, tab); - } - - private int getTargetTabIndex(Point point) { - Point tabPt = SwingUtilities.convertPoint(pane, point, pane); - boolean isTB = pane.getTabPlacement()==JTabbedPane.TOP || pane.getTabPlacement()==JTabbedPane.BOTTOM; - for(int i=0;i < getTabCount();i++) { - Rectangle r = pane.getBoundsAt(i); - if(isTB) r.setRect(r.x-r.width/2, r.y, r.width, r.height); - else r.setRect(r.x, r.y-r.height/2, r.width, r.height); - if(r.contains(tabPt)) return i; - } - Rectangle r = pane.getBoundsAt(getTabCount()-1); - if(isTB) r.setRect(r.x+r.width/2, r.y, r.width, r.height); - else r.setRect(r.x, r.y+r.height/2, r.width, r.height); - return r.contains(tabPt)?getTabCount():-1; - } - - protected JTabbedPane buildTabbedPane(final int type) { - return new JTabbedPane(type); - } - - protected JTabbedPane getTabbedPane() { - return pane; - } - -} diff --git a/src/java/org/jivesoftware/spark/decorator/DefaultTabHandler.java b/src/java/org/jivesoftware/spark/decorator/DefaultTabHandler.java deleted file mode 100644 index a7747090f..000000000 --- a/src/java/org/jivesoftware/spark/decorator/DefaultTabHandler.java +++ /dev/null @@ -1,115 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.decorator; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.spark.PresenceManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.tabbedPane.SparkTab; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.SparkTabHandler; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; - -import java.awt.Color; -import java.awt.Component; - -import javax.swing.Icon; -import javax.swing.UIManager; - -/** - * - */ -public class DefaultTabHandler extends SparkTabHandler { - - public DefaultTabHandler() { - - } - - public boolean isTabHandled(SparkTab tab, Component component, boolean isSelectedTab, boolean chatFrameFocused) { - - if (component instanceof ChatRoom) { - ChatRoom room = (ChatRoom)component; - - boolean isStaleRoom = SparkManager.getChatManager().isStaleRoom(room); - - boolean isTyping = SparkManager.getChatManager().containsTypingNotification((ChatRoom)component); - - // Check if is typing. - if (isTyping) { - tab.setIcon(SparkRes.getImageIcon(SparkRes.SMALL_MESSAGE_EDIT_IMAGE)); - } - else if (room instanceof ChatRoomImpl && !isStaleRoom) { - // User is not typing, therefore show default presence icon. - String participantJID = ((ChatRoomImpl)room).getParticipantJID(); - Presence presence = PresenceManager.getPresence(participantJID); - Icon icon = PresenceManager.getIconFromPresence(presence); - tab.setIcon(icon); - } - - - if (!chatFrameFocused || !isSelectedTab) { - if (room.getUnreadMessageCount() > 0) { - // Make tab red. - tab.setTitleColor((Color) UIManager.get("Chat.unreadMessageColor")); - tab.setTabBold(true); - } - - // Handle unread message count. - int unreadMessageCount = room.getUnreadMessageCount(); - String appendedMessage = ""; - if (unreadMessageCount > 1) { - appendedMessage = " (" + unreadMessageCount + ")"; - } - - tab.setTabTitle(room.getTabTitle() + appendedMessage); - } - - // Check if the room is stale. - if (isStaleRoom && component instanceof ChatRoomImpl) { - decorateStaleTab(tab, (ChatRoom)component); - } - // Should only set the icon to default if the frame is in focus - // and the tab is the selected component. - else if (isSelectedTab && chatFrameFocused) { - tab.setTitleColor(Color.black); - // tab.setTabFont(tab.getDefaultFont()); - tab.setTabTitle(room.getTabTitle()); - - // Clear unread message count. - room.clearUnreadMessageCount(); - } - } - else { - if (!chatFrameFocused || !isSelectedTab) { - // Make tab red. - tab.setTitleColor((Color) UIManager.get("Chat.unreadMessageColor")); - tab.setTabBold(true); - } - if (isSelectedTab && chatFrameFocused) { - tab.setTitleColor(Color.black); - tab.setTabFont(tab.getDefaultFont()); - } - } - return true; - } - - -} diff --git a/src/java/org/jivesoftware/spark/filetransfer/preferences/FileTransferPreference.java b/src/java/org/jivesoftware/spark/filetransfer/preferences/FileTransferPreference.java deleted file mode 100644 index 64b4918ec..000000000 --- a/src/java/org/jivesoftware/spark/filetransfer/preferences/FileTransferPreference.java +++ /dev/null @@ -1,123 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.filetransfer.preferences; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.resource.Res; -import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer; -import org.jivesoftware.spark.preference.Preference; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import javax.swing.Icon; -import javax.swing.JComponent; - -/** - * - */ -public class FileTransferPreference implements Preference { - - private FileTransferPreferencePanel ui; - private LocalPreferences localPreferences; - - public FileTransferPreference() { - localPreferences = SettingsManager.getLocalPreferences(); - int timeout = localPreferences.getFileTransferTimeout(); - - timeout = timeout * 60 * 1000; - - OutgoingFileTransfer.setResponseTimeout(timeout); - - ui = new FileTransferPreferencePanel(); - } - - public String getTitle() { - return Res.getString("title.file.transfer.preferences"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.SEND_FILE_24x24); - } - - public String getTooltip() { - return Res.getString("tooltip.file.transfer"); - } - - public String getListName() { - return Res.getString("title.file.transfer"); - } - - public String getNamespace() { - return "FILE_TRANSFER"; - } - - public JComponent getGUI() { - return ui; - } - - public void load() { - int timeout = localPreferences.getFileTransferTimeout(); - ui.setDownloadDirectory(localPreferences.getDownloadDir()); - ui.setTimeout(Integer.toString(timeout)); - } - - public void commit() { - LocalPreferences pref = SettingsManager.getLocalPreferences(); - - String downloadDir = ui.getDownloadDirectory(); - if (ModelUtil.hasLength(downloadDir)) { - pref.setDownloadDir(downloadDir); - } - - String timeout = ui.getTimeout(); - if (ModelUtil.hasLength(timeout)) { - int tout = 1; - try { - tout = Integer.parseInt(timeout); - } catch (NumberFormatException e) { - // Nothing to do - } - - pref.setFileTransferTimeout(tout); - - final int timeOutMs = tout * (60 * 1000); - OutgoingFileTransfer.setResponseTimeout(timeOutMs); - } - - SettingsManager.saveSettings(); - - } - - public boolean isDataValid() { - return true; - } - - public String getErrorMessage() { - return null; - } - - public Object getData() { - return null; - } - - public void shutdown() { - commit(); - } -} diff --git a/src/java/org/jivesoftware/spark/filetransfer/preferences/FileTransferPreferencePanel.java b/src/java/org/jivesoftware/spark/filetransfer/preferences/FileTransferPreferencePanel.java deleted file mode 100644 index 08516e192..000000000 --- a/src/java/org/jivesoftware/spark/filetransfer/preferences/FileTransferPreferencePanel.java +++ /dev/null @@ -1,113 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.filetransfer.preferences; - -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Res; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.WindowsFileSystemView; - -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; - -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.io.File; - -/** - * FileTransferPreferencePanel is the UI for handling File Transfer Preferences. - * - * @author Derek DeMoro - */ -public class FileTransferPreferencePanel extends JPanel { - - private static final long serialVersionUID = -2404221882867691253L; - private JTextField timeoutField; - private JTextField downloadDirectoryField; - - private JFileChooser fc; - - - public FileTransferPreferencePanel() { - setLayout(new GridBagLayout()); - setBorder(BorderFactory.createTitledBorder(Res.getString("title.file.transfer.preferences"))); - - timeoutField = new JTextField(); - downloadDirectoryField = new JTextField(); - - JLabel timeoutLabel = new JLabel(); - JLabel downloadDirectoryLabel = new JLabel(); - - ResourceUtils.resLabel(timeoutLabel, timeoutField, Res.getString("label.transfer.timeout")); - ResourceUtils.resLabel(downloadDirectoryLabel, downloadDirectoryField, Res.getString("label.transfer.download.directory")); - - add(timeoutLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(timeoutField, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 100, 0)); - - add(downloadDirectoryLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(downloadDirectoryField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - final JButton button = new JButton(); - ResourceUtils.resButton(button, Res.getString("button.browse")); - add(button, new GridBagConstraints(2, 1, 1, 1, 0.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - button.addActionListener( e -> pickFile(Res.getString("title.choose.directory"), downloadDirectoryField) ); - - } - - public void setTimeout(String minutes) { - timeoutField.setText(minutes); - } - - public String getTimeout() { - return timeoutField.getText(); - } - - public void setDownloadDirectory(String dir) { - downloadDirectoryField.setText(dir); - } - - public String getDownloadDirectory() { - return downloadDirectoryField.getText(); - } - - private void pickFile(String title, JTextField field) { - if (fc == null) { - fc = new JFileChooser(); - fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - if (Spark.isWindows()) { - fc.setFileSystemView(new WindowsFileSystemView()); - } - } - fc.setDialogTitle(title); - int returnVal = fc.showOpenDialog(this); - - if (returnVal == JFileChooser.APPROVE_OPTION) { - File file = fc.getSelectedFile(); - field.setText(file.getAbsolutePath()); - } - } - -} diff --git a/src/java/org/jivesoftware/spark/phone/PhoneManager.java b/src/java/org/jivesoftware/spark/phone/PhoneManager.java deleted file mode 100644 index b371dccfe..000000000 --- a/src/java/org/jivesoftware/spark/phone/PhoneManager.java +++ /dev/null @@ -1,371 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.phone; - -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Vector; -import java.util.concurrent.CopyOnWriteArrayList; - -import javax.media.CaptureDeviceInfo; -import javax.media.CaptureDeviceManager; -import javax.media.MediaLocator; -import javax.media.format.AudioFormat; -import javax.media.format.VideoFormat; -import javax.media.protocol.DataSource; -import javax.swing.Action; -import javax.swing.JMenu; -import javax.swing.JPopupMenu; - -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.ContextMenuListener; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomButton; -import org.jivesoftware.spark.ui.ChatRoomListener; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.sparkimpl.plugin.phone.JMFInit; - -/** - * Handles general phone behavior in Spark. This allows for many different phone systems - * to plug into Spark in a more elegant way. - */ -public class PhoneManager implements ChatRoomListener, ContextMenuListener { - private static PhoneManager singleton; - private static final Object LOCK = new Object(); - - private List phones = new CopyOnWriteArrayList<>(); - private List currentCalls = new ArrayList<>(); - // Static Media Locator - static private MediaLocator mediaLocator = null; - // Static Media Locator Preference - static private boolean useStaticLocator = false; - // Static using MediaLocator - static private boolean usingMediaLocator = false; - // Static DataSource - static private DataSource ds; - - /** - * Returns the singleton instance of PhoneManager, - * creating it if necessary. - *

        - * - * @return the singleton instance of PhoneManager - */ - public static PhoneManager getInstance() { - // Synchronize on LOCK to ensure that we don't end up creating - // two singletons. - synchronized (LOCK) { - if (null == singleton) { - PhoneManager controller = new PhoneManager(); - singleton = controller; - return controller; - } - } - return singleton; - } - - private PhoneManager() { - JMFInit.start(false); - if (Spark.isVista() || Spark.isLinux()) { - setUseStaticLocator(true); - } - } - - private void addListeners() { - // Handle ChatRooms. - final ChatManager chatManager = SparkManager.getChatManager(); - chatManager.addChatRoomListener(this); - - // Handle ContextMenus. - final ContactList contactList = SparkManager.getWorkspace().getContactList(); - contactList.addContextMenuListener(this); - } - - public void addPhone(Phone phone) { - if (phones.isEmpty()) { - addListeners(); - } - - phones.add(phone); - } - - public void removePhone(Phone phone) { - phones.remove(phone); - } - - public void chatRoomOpened(final ChatRoom room) { - if (!phones.isEmpty() && room instanceof ChatRoomImpl) { - final ChatRoomImpl chatRoomImpl = (ChatRoomImpl) room; - final ChatRoomButton dialButton = new ChatRoomButton(SparkRes.getImageIcon(SparkRes.DIAL_PHONE_IMAGE_24x24)); - dialButton.setToolTipText(Res.getString("tooltip.place.voice.call")); - - final List actions = new ArrayList<>(); - SwingWorker actionWorker = new SwingWorker() { - public Object construct() { - for (Phone phone : phones) { - final Collection phoneActions = phone.getPhoneActions(chatRoomImpl.getParticipantJID()); - if (phoneActions != null) { - for (Action action : phoneActions) { - actions.add(action); - } - } - } - return actions; - } - - public void finished() { - if (!actions.isEmpty()) { - room.addChatRoomButton(dialButton, true); - } - } - }; - - actionWorker.start(); - - - dialButton.addMouseListener(new MouseAdapter() { - public void mousePressed(final MouseEvent e) { - SwingWorker worker = new SwingWorker() { - public Object construct() { - try { - Thread.sleep(50); - } - catch (InterruptedException e1) { - e1.printStackTrace(); - } - return true; - } - - public void finished() { - // Handle actions. - if (actions.size() > 0) { - // Display PopupMenu - final JPopupMenu menu = new JPopupMenu(); - for (Action action : actions) { - menu.add(action); - } - - menu.show(dialButton, e.getX(), e.getY()); - } - } - }; - worker.start(); - - } - }); - } - } - - public void chatRoomLeft(ChatRoom room) { - } - - public void chatRoomClosed(ChatRoom room) { - } - - public void chatRoomActivated(ChatRoom room) { - } - - public void userHasJoined(ChatRoom room, String userid) { - } - - public void userHasLeft(ChatRoom room, String userid) { - } - - public void poppingUp(Object object, final JPopupMenu popup) { - if (!phones.isEmpty()) { - if (object instanceof ContactItem) { - final ContactItem contactItem = (ContactItem) object; - final List actions = new ArrayList<>(); - - SwingWorker worker = new SwingWorker() { - public Object construct() { - for (Phone phone : phones) { - final Collection itemActions = phone.getPhoneActions(contactItem.getJID()); - for (Action action : itemActions) { - actions.add(action); - } - } - return null; - } - - public void finished() { - - if (actions.size() > 0) { - final JMenu dialMenu = new JMenu(Res.getString("title.dial.phone")); - dialMenu.setIcon(SparkRes.getImageIcon(SparkRes.DIAL_PHONE_IMAGE_16x16)); - - for (Action action : actions) { - dialMenu.add(action); - } - - int count = popup.getComponentCount(); - if (count > 2) { - popup.insert(dialMenu, 2); - } - - popup.invalidate(); - popup.validate(); - popup.repaint(); - } - } - }; - - worker.start(); - - - } - } - } - - public void poppingDown(JPopupMenu popup) { - } - - public boolean handleDefaultAction(MouseEvent e) { - return false; - } - - public void addCurrentCall(String phoneNumber) { - currentCalls.add(phoneNumber); - } - - public void removeCurrentCall(String phoneNumber) { - currentCalls.remove(phoneNumber); - } - - public boolean containsCurrentCall(String phoneNumber) { - return currentCalls.contains(phoneNumber); - } - - public static String getNumbersFromPhone(String number) { - if (number == null) { - return null; - } - - number = number.replace("-", ""); - number = number.replace("(", ""); - number = number.replace(")", ""); - number = number.replace(" ", ""); - if (number.startsWith("1")) { - number = number.substring(1); - } - - return number; - } - - public static MediaLocator getMediaLocator(String locator) { - MediaLocator auxLocator; - - System.out.println("--------------------------------"); - System.out.println("locator: " + locator); - - Vector vectorAudioDevices = CaptureDeviceManager.getDeviceList(new AudioFormat(AudioFormat.LINEAR)); - for ( CaptureDeviceInfo infoCaptureDevice : vectorAudioDevices) - { - System.out.println(infoCaptureDevice.getLocator() + "-" + locator); - if (infoCaptureDevice.getLocator().toString().equals(locator)) - { - System.out.println("Found: " + locator); - return infoCaptureDevice.getLocator(); - } - } - - Vector vectorVideoDevices = CaptureDeviceManager.getDeviceList(new VideoFormat(VideoFormat.RGB)); - for ( CaptureDeviceInfo infoCaptureDevice : vectorVideoDevices ) - { - System.out.println(infoCaptureDevice.getLocator() + "-" + locator); - if (infoCaptureDevice.getLocator().toString().equals(locator)) - { - System.out.println("Found: " + locator); - return infoCaptureDevice.getLocator(); - } - } - - - if (useStaticLocator) { - if (mediaLocator == null) { - mediaLocator = new MediaLocator(locator); - } - auxLocator = mediaLocator; - //usingMediaLocator=true; - } else { - auxLocator = new MediaLocator(locator); - } - - return auxLocator; - } - - public static DataSource getDataSource(String locator) { - - if (ds == null) { - - try { - ds = javax.media.Manager.createDataSource(getMediaLocator(locator)); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - - } - - return ds; - } - - public static DataSource getDataSource(MediaLocator locator) { - - if (ds == null) { - - try { - ds = javax.media.Manager.createDataSource(locator); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - - } - - return ds; - } - - public static boolean isUsingMediaLocator() { - return usingMediaLocator; - } - - public static void setUsingMediaLocator(boolean usingMediaLocator) { - PhoneManager.usingMediaLocator = usingMediaLocator; - } - - public static boolean isUseStaticLocator() { - return useStaticLocator; - } - - public static void setUseStaticLocator(boolean useStaticLocator) { - PhoneManager.useStaticLocator = useStaticLocator; - } -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/spark/plugin/PluginDependency.java b/src/java/org/jivesoftware/spark/plugin/PluginDependency.java deleted file mode 100644 index 97fe70848..000000000 --- a/src/java/org/jivesoftware/spark/plugin/PluginDependency.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.jivesoftware.spark.plugin; - -import org.jivesoftware.spark.util.log.Log; - -public class PluginDependency -{ - private String name; - private String version; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public boolean compareVersion(String version) { - - if(version != null && getVersion() != null) { - String checkVersion[] = version.split("\\."); - String originalVersion[] = getVersion().split("\\."); - int maxlength = (originalVersion.length >= checkVersion.length)?originalVersion.length:checkVersion.length; - - - // go through all Version-parts - for(int i= 0; i < maxlength; i++) { - // if the checked version is too short - if ( checkVersion.length <= i - && originalVersion[i].equals(0)) - return true; - else if (checkVersion.length <= i) - return false; - // if the original version is long enough - if(originalVersion.length > i) { - - // convert to integer - try { - int originalVersNumber = Integer.valueOf(originalVersion[i]).intValue(); - int checkVersNumber = Integer.valueOf(checkVersion[i]).intValue(); - - // check the numbers - if(checkVersNumber > originalVersNumber) { - return true; - } - else if(checkVersNumber < originalVersNumber) { - return false; - } - } - catch(Exception e) { - Log.error("Version " + checkVersion + " contains letters.", e); - return false; - } - } - else { - return true; - } - } - return true; - } - return false; - } -} diff --git a/src/java/org/jivesoftware/spark/plugin/package.html b/src/java/org/jivesoftware/spark/plugin/package.html deleted file mode 100644 index f005bfd90..000000000 --- a/src/java/org/jivesoftware/spark/plugin/package.html +++ /dev/null @@ -1 +0,0 @@ -Provides the API for creating and registring Plugins. diff --git a/src/java/org/jivesoftware/spark/ui/ChatArea.java b/src/java/org/jivesoftware/spark/ui/ChatArea.java deleted file mode 100644 index cf296cc67..000000000 --- a/src/java/org/jivesoftware/spark/ui/ChatArea.java +++ /dev/null @@ -1,794 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.StringTokenizer; - -import javax.swing.AbstractAction; -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; -import javax.swing.JSeparator; -import javax.swing.JTextPane; -import javax.swing.KeyStroke; -import javax.swing.UIManager; -import javax.swing.text.AttributeSet; -import javax.swing.text.BadLocationException; -import javax.swing.text.Document; -import javax.swing.text.Element; -import javax.swing.text.SimpleAttributeSet; -import javax.swing.text.StyleConstants; -import javax.swing.text.StyledDocument; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.ContextMenuListener; -import org.jivesoftware.spark.util.BrowserLauncher; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.emoticons.EmoticonManager; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -/** - * The ChatArea class handles proper chat text formatting such as url handling. Use ChatArea for proper - * formatting of bold, italics, underlined and urls. - */ -public class ChatArea extends JTextPane implements MouseListener, MouseMotionListener, ActionListener { - private static final long serialVersionUID = -2155445968040220072L; - - /** - * The SimpleAttributeSet used within this instance of JTextPane. - */ - public final SimpleAttributeSet styles = new SimpleAttributeSet(); - - /** - * The default Hand cursor. - */ - public static final Cursor HAND_CURSOR = new Cursor(Cursor.HAND_CURSOR); - - /** - * The default Text Cursor. - */ - public static final Cursor DEFAULT_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR); - - /** - * The currently selected Font Family to use. - */ - private String fontFamily; - - /** - * The currently selected Font Size to use. - */ - private int fontSize; - - private List contextMenuListener = new ArrayList<>(); - - private JPopupMenu popup; - - - private JMenuItem cutMenu; - private JMenuItem copyMenu; - private JMenuItem pasteMenu; - private JMenuItem selectAll; - - private List interceptors = new ArrayList<>(); - - protected EmoticonManager emoticonManager; - - protected Boolean forceEmoticons = false; - - protected Boolean emoticonsAvailable = true; - - /** - * ChatArea Constructor. - */ - public ChatArea() { - emoticonManager = EmoticonManager.getInstance(); - - Collection emoticonPacks; - emoticonPacks = emoticonManager.getEmoticonPacks(); - - if(emoticonPacks == null) { - emoticonsAvailable = false; - } - - // Set Default Font - final LocalPreferences pref = SettingsManager.getLocalPreferences(); - int fs = pref.getChatRoomFontSize(); - fontSize = fs; - setFontSize(fs); - - - cutMenu = new JMenuItem(Res.getString("action.cut")); - cutMenu.addActionListener(this); - - copyMenu = new JMenuItem(Res.getString("action.copy")); - copyMenu.addActionListener(this); - - pasteMenu = new JMenuItem(Res.getString("action.paste")); - pasteMenu.addActionListener(this); - - selectAll = new JMenuItem(Res.getString("action.select.all")); - selectAll.addActionListener(this); - - // Set Default Font - setFont(new Font("Dialog", Font.PLAIN, 12)); - - - getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("Ctrl x"), "cut"); - - getActionMap().put("cut", new AbstractAction("cut") { - private static final long serialVersionUID = 9117190151545566922L; - - public void actionPerformed(ActionEvent evt) { - cutAction(); - } - }); - - getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("Ctrl c"), "copy"); - - getActionMap().put("copy", new AbstractAction("copy") { - private static final long serialVersionUID = 4949716854440264528L; - - public void actionPerformed(ActionEvent evt) { - SparkManager.setClipboard(getSelectedText()); - } - }); - - getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("Ctrl v"), "paste"); - - getActionMap().put("paste", new AbstractAction("paste") { - private static final long serialVersionUID = -8767763580660683678L; - - public void actionPerformed(ActionEvent evt) { - pasteAction(); - } - }); - - setEditorKit( new WrapEditorKit() ); // SPARK-1613 Ensure that long text wraps. - } - - /** - * Set the current text of the ChatArea. - * - * @param message inserts the text directly into the ChatArea - */ - public void setText(String message) { - // By default, use the hand cursor for link selection - // and scrolling. - // setCursor(HAND_CURSOR); - - // Make sure the message is not null. - // message = message.trim(); - // Why? -// message = message.replaceAll("/\"", ""); - if (ModelUtil.hasLength(message)) { - try { - insert(message); - } - catch (BadLocationException e) { - Log.error(e); - } - } - } - /** - * setText is a core JTextPane method that can beused to inject a different Document type - * for instance HTMLDocument (setText("") - * We should keep the functionality - it is useful when we want to inject a different Document type - * instead of StyleDocument - * @param content - */ - public void setInitialContent(String content) { - super.setText(content); - } - - - /** - * Removes the last appearance of word from the TextArea - * @param word - */ - public void removeLastWord(String word) - { - select(getText().lastIndexOf(word),getText().length()); - replaceSelection(""); - } - - /** - * Removes everything in between begin and end - * @param begin - * @param end - */ - public void removeWordInBetween(int begin, int end){ - select(begin, end); - replaceSelection(""); - } - - /** - * Clear the current document. This will remove all text and element - * attributes such as bold, italics, and underlining. Note that the font family and - * font size will be persisted. - */ - public void clear() { - super.setText(""); - if (fontFamily != null) { - setFont(fontFamily); - } - - if (fontSize != 0) { - setFontSize(fontSize); - } - - StyleConstants.setUnderline(styles, false); - StyleConstants.setBold(styles, false); - StyleConstants.setItalic(styles, false); - setCharacterAttributes(styles, false); - } - - - /** - * Does the actual insertion of text, adhering to the styles - * specified during message creation in either the thin or thick client. - * - * @param text - the text to insert. - * @throws BadLocationException if location is not available to insert into. - */ - public void insert(String text) throws BadLocationException { - boolean bold = false; - boolean italic = false; - boolean underlined = false; - final StringTokenizer tokenizer = new StringTokenizer(text, " \n \t", true); - while (tokenizer.hasMoreTokens()) { - String textFound = tokenizer.nextToken(); - if ((textFound.startsWith("http://") || textFound.startsWith("ftp://") - || textFound.startsWith("https://") || textFound.startsWith("www.") || textFound.startsWith("file:/") ) && - textFound.indexOf(".") > 1) { - insertLink(textFound); - } - else if ( textFound.startsWith("\\\\") || (textFound.indexOf("://") > 0 && textFound.indexOf(".") < 1) ) { - insertAddress(textFound); - } - else if (!insertImage(textFound)) { - insertText(textFound); - } - } - - // By default, always have decorations off. - StyleConstants.setBold(styles, bold); - StyleConstants.setItalic(styles, italic); - StyleConstants.setUnderline(styles, underlined); - } - - /** - * Inserts text into the current document. - * - * @param text the text to insert - * @throws BadLocationException if the location is not available for insertion. - */ - public void insertText(String text) throws BadLocationException { - final Document doc = getDocument(); - styles.removeAttribute("link"); - doc.insertString(doc.getLength(), text, styles); - setCaretPosition(doc.getLength()); - } - - /** - * Inserts text into the current document. - * - * @param text the text to insert - * @param color the color of the text - * @throws BadLocationException if the location is not available for insertion. - */ - public void insertText(String text, Color color) throws BadLocationException { - final Document doc = getDocument(); - StyleConstants.setForeground(styles, color); - doc.insertString(doc.getLength(), text, styles); - setCaretPosition(doc.getLength()); - } - - /** - * Inserts a link into the current document. - * - * @param link - the link to insert( ex. http://www.javasoft.com ) - * @throws BadLocationException if the location is not available for insertion. - */ - public void insertLink(String link) throws BadLocationException { - final Document doc = getDocument(); - styles.addAttribute("link", link); - - StyleConstants.setForeground(styles, (Color)UIManager.get("Link.foreground")); - StyleConstants.setUnderline(styles, true); - doc.insertString(doc.getLength(), link, styles); - StyleConstants.setUnderline(styles, false); - StyleConstants.setForeground(styles, (Color)UIManager.get("TextPane.foreground")); - styles.removeAttribute("link"); - setCharacterAttributes(styles, false); - setCaretPosition(doc.getLength()); - - } - - /** - * Inserts a network address into the current document. - * - * @param address - the address to insert( ex. \superpc\etc\file\ OR http://localhost/ ) - * @throws BadLocationException if the location is not available for insertion. - */ - public void insertAddress(String address) throws BadLocationException { - final Document doc = getDocument(); - styles.addAttribute("link", address); - - StyleConstants.setForeground(styles, (Color)UIManager.get("Address.foreground")); - StyleConstants.setUnderline(styles, true); - doc.insertString(doc.getLength(), address, styles); - StyleConstants.setUnderline(styles, false); - StyleConstants.setForeground(styles, (Color)UIManager.get("TextPane.foreground")); - styles.removeAttribute("link"); - setCharacterAttributes(styles, false); - setCaretPosition(doc.getLength()); - - } - - /** - * Inserts an emotion icon into the current document. - * - * @param imageKey - the smiley representation of the image.( ex. :) ) - * @return true if the image was found, otherwise false. - */ - public boolean insertImage(String imageKey) { - - if(!forceEmoticons && !SettingsManager.getLocalPreferences().areEmoticonsEnabled() || !emoticonsAvailable){ - return false; - } - final Document doc = getDocument(); - Icon emotion = emoticonManager.getEmoticonImage(imageKey.toLowerCase()); - if (emotion == null) { - return false; - } - - select(doc.getLength(), doc.getLength()); - insertIcon(emotion); - setCaretPosition(doc.getLength()); - - return true; - } - - /** - * Inserts horizontal line - */ - public void insertHorizontalLine() { - try { - insertComponent( new JSeparator() ); - insertText("\n"); - } - catch (BadLocationException e) { - Log.error("Error message.", e); - } - } - - /** - * Sets the current element to be either bold or not depending - * on the current state. If the element is currently set as bold, - * it will be set to false, and vice-versa. - */ - public void setBold() { - final Element element = getStyledDocument().getCharacterElement(getCaretPosition() - 1); - if (element != null) { - AttributeSet as = element.getAttributes(); - boolean isBold = StyleConstants.isBold(as); - StyleConstants.setBold(styles, !isBold); - try { - setCharacterAttributes(styles, true); - } - catch (Exception ex) { - Log.error("Error settings bold:", ex); - } - } - } - - /** - * Sets the current element to be either italicized or not depending - * on the current state. If the element is currently set as italic, - * it will be set to false, and vice-versa. - */ - public void setItalics() { - final Element element = getStyledDocument().getCharacterElement(getCaretPosition() - 1); - if (element != null) { - AttributeSet as = element.getAttributes(); - boolean isItalic = StyleConstants.isItalic(as); - StyleConstants.setItalic(styles, !isItalic); - try { - setCharacterAttributes(styles, true); - } - catch (Exception fontException) { - Log.error("Error settings italics:", fontException); - } - } - } - - /** - * Sets the current document to be either underlined or not depending - * on the current state. If the element is currently set as underlined, - * it will be set to false, and vice-versa. - */ - public void setUnderlined() { - final Element element = getStyledDocument().getCharacterElement(getCaretPosition() - 1); - if (element != null) { - AttributeSet as = element.getAttributes(); - boolean isUnderlined = StyleConstants.isUnderline(as); - StyleConstants.setUnderline(styles, !isUnderlined); - try { - setCharacterAttributes(styles, true); - } - catch (Exception underlineException) { - Log.error("Error settings underline:", underlineException); - } - } - } - - /** - * Set the font on the current element. - * - * @param font the font to use with the current element - */ - public void setFont(String font) { - StyleConstants.setFontFamily(styles, font); - try { - setCharacterAttributes(styles, false); - } - catch (Exception fontException) { - Log.error("Error settings font:", fontException); - } - - fontFamily = font; - } - - /** - * Set the current font size. - * - * @param size the current font size. - */ - public void setFontSize(int size) { - StyleConstants.setFontSize(styles, size); - try { - setCharacterAttributes(styles, false); - } - catch (Exception fontException) { - Log.error("Error settings font:", fontException); - } - - fontSize = size; - } - - public void mouseClicked(MouseEvent e) { - try { - final int pos = viewToModel(e.getPoint()); - final Element element = getStyledDocument().getCharacterElement(pos); - - if (element != null) { - final AttributeSet as = element.getAttributes(); - final Object o = as.getAttribute("link"); - - if (o != null) { - try { - final String url = (String)o; - boolean handled = fireLinkInterceptors(e, url); - if (!handled) { - if(e.getButton() == MouseEvent.BUTTON1) - BrowserLauncher.openURL(url); - else if (e.getButton() == MouseEvent.BUTTON3) { - JPopupMenu popupmenu = new JPopupMenu(); - JMenuItem linkcopy = new JMenuItem( - Res.getString("action.copy")); - linkcopy.addActionListener( e1 -> SparkManager.setClipboard(url) ); - linkcopy.setEnabled(true); - popupmenu.add(linkcopy); - popupmenu.show(this, e.getX(), e.getY()); - } - } - } - catch (Exception ioe) { - Log.error("Error launching browser:", ioe); - } - } - } - } - catch (Exception ex) { - Log.error("Visible Error", ex); - } - } - - public void mousePressed(MouseEvent e) { - if (e.isPopupTrigger()) { - handlePopup(e); - } - } - - /** - * This launches the BrowserLauncher with the URL - * located in ChatArea. Note that the url will - * automatically be clickable when added to ChatArea - * - * @param e - the MouseReleased event - */ - public void mouseReleased(MouseEvent e) { - if (e.isPopupTrigger()) { - handlePopup(e); - } - - - } - - public void mouseEntered(MouseEvent e) { - } - - public void mouseExited(MouseEvent e) { - } - - public void mouseDragged(MouseEvent e) { - } - - /** - * Checks to see if the mouse is located over a browseable - * link. - * - * @param e - the current MouseEvent. - */ - public void mouseMoved(MouseEvent e) { - checkForLink(e); - } - - /** - * Checks to see if the mouse is located over a browseable - * link. - * - * @param e - the current MouseEvent. - */ - private void checkForLink(MouseEvent e) { - try { - final int pos = viewToModel(e.getPoint()); - final Element element = getStyledDocument().getCharacterElement(pos); - - if (element != null) { - final AttributeSet as = element.getAttributes(); - final Object o = as.getAttribute("link"); - - if (o != null) { - setCursor(HAND_CURSOR); - } - else { - setCursor(DEFAULT_CURSOR); - } - } - } - catch (Exception ex) { - Log.error("Error in CheckLink:", ex); - } - } - - /** - * Examines the chatInput text pane, and returns a string containing the text with any markup - * (jive markup in our case). This will strip any terminating new line from the input. - * - * @return a string of marked up text. - */ - public String getMarkup() { - final StringBuilder buf = new StringBuilder(); - final String text = getText(); - final StyledDocument doc = getStyledDocument(); - final Element rootElem = doc.getDefaultRootElement(); - - // MAY RETURN THIS BLOCK - if (text.trim().length() <= 0) { - return null; - } - - boolean endsInNewline = text.charAt(text.length() - 1) == '\n'; - for (int j = 0; j < rootElem.getElementCount(); j++) { - final Element pElem = rootElem.getElement(j); - - for (int i = 0; i < pElem.getElementCount(); i++) { - final Element e = pElem.getElement(i); - final AttributeSet as = e.getAttributes(); - final boolean bold = StyleConstants.isBold(as); - final boolean italic = StyleConstants.isItalic(as); - final boolean underline = StyleConstants.isUnderline(as); - int end = e.getEndOffset(); - - if (end > text.length()) { - end = text.length(); - } - - if (endsInNewline && end >= text.length() - 1) { - end--; - } - - // swing text.. :-/ - if (j == rootElem.getElementCount() - 1 - && i == pElem.getElementCount() - 1) { - end = text.length(); - } - - final String current = text.substring(e.getStartOffset(), end); - if (bold) { - buf.append("[b]"); - } - if (italic) { - buf.append("[i]"); - } - if (underline) { - buf.append("[u]"); - } - //buf.append( "[font face=/\"" + fontFamily + "/\" size=/\"" + fontSize + "/\"/]" ); - - // Iterator over current string to find url tokens - final StringTokenizer tkn = new StringTokenizer(current, " ", true); - while (tkn.hasMoreTokens()) { - final String token = tkn.nextToken(); - if (token.startsWith("http://") || token.startsWith("ftp://") - || token.startsWith("https://")) { - buf.append("[url]").append(token).append("[/url]"); - } - else if (token.startsWith("www")) { - buf.append("[url "); - buf.append("http://").append(token); - buf.append("]"); - buf.append(token); - buf.append("[/url]"); - } - else { - buf.append(token); - } - } - - // Always add end tags for markup - if (underline) { - buf.append("[/u]"); - } - if (italic) { - buf.append("[/i]"); - } - if (bold) { - buf.append("[/b]"); - } - // buf.append( "[/font]" ); - } - } - - return buf.toString(); - } - - private void handlePopup(MouseEvent e) { - popup = new JPopupMenu(); - popup.add(cutMenu); - popup.add(copyMenu); - popup.add(pasteMenu); - fireContextMenuListeners(); - popup.addSeparator(); - popup.add(selectAll); - - // Handle enable - boolean textSelected = ModelUtil.hasLength(getSelectedText()); - String clipboard = SparkManager.getClipboard(); - cutMenu.setEnabled(textSelected && isEditable()); - copyMenu.setEnabled(textSelected); - pasteMenu.setEnabled(ModelUtil.hasLength(clipboard) && isEditable()); - - popup.show(this, e.getX(), e.getY()); - } - - /** - * Adds a ContextMenuListener to ChatArea. - * - * @param listener the ContextMenuListener. - */ - public void addContextMenuListener(ContextMenuListener listener) { - contextMenuListener.add(listener); - } - - /** - * Remove a ContextMenuListener to ChatArea. - * - * @param listener the ContextMenuListener. - */ - public void removeContextMenuListener(ContextMenuListener listener) { - contextMenuListener.remove(listener); - } - - private void fireContextMenuListeners() { - for (ContextMenuListener listener : new ArrayList<>( contextMenuListener )) { - listener.poppingUp(this, popup); - } - } - - public void addLinkInterceptor(LinkInterceptor interceptor) { - interceptors.add(interceptor); - } - - public void removeLinkInterceptor(LinkInterceptor interceptor) { - interceptors.remove(interceptor); - } - - public boolean fireLinkInterceptors(MouseEvent event, String link) { - for (LinkInterceptor linkInterceptor : new ArrayList<>( interceptors )) { - boolean handled = linkInterceptor.handleLink(event, link); - if (handled) { - return true; - } - } - - return false; - } - - - public void actionPerformed(ActionEvent e) { - if (e.getSource() == cutMenu) { - cutAction(); - } - else if (e.getSource() == copyMenu) { - SparkManager.setClipboard(getSelectedText()); - } - else if (e.getSource() == pasteMenu) { - pasteAction(); - } - else if (e.getSource() == selectAll) { - requestFocus(); - selectAll(); - } - } - - private void cutAction() { - String selectedText = getSelectedText(); - replaceSelection(""); - SparkManager.setClipboard(selectedText); - } - - private void pasteAction() { - String text = SparkManager.getClipboard(); - if (text != null) { - replaceSelection(text); - } - } - - protected void releaseResources() { - getActionMap().remove("copy"); - getActionMap().remove("cut"); - getActionMap().remove("paste"); - } - - public Boolean getForceEmoticons() { - return forceEmoticons; - } - - public void setForceEmoticons(Boolean forceEmoticons) { - this.forceEmoticons = forceEmoticons; - } -} diff --git a/src/java/org/jivesoftware/spark/ui/ChatContainer.java b/src/java/org/jivesoftware/spark/ui/ChatContainer.java deleted file mode 100644 index 8c0dd299d..000000000 --- a/src/java/org/jivesoftware/spark/ui/ChatContainer.java +++ /dev/null @@ -1,1465 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Frame; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.TimerTask; -import java.util.regex.Pattern; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JOptionPane; -import javax.swing.JPopupMenu; -import javax.swing.JTabbedPane; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import org.jivesoftware.MainWindow; -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.StanzaListener; -import org.jivesoftware.smack.filter.AndFilter; -import org.jivesoftware.smack.filter.FromMatchesFilter; -import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.tabbedPane.SparkTab; -import org.jivesoftware.spark.component.tabbedPane.SparkTabbedPane; -import org.jivesoftware.spark.component.tabbedPane.SparkTabbedPaneListener; -import org.jivesoftware.spark.ui.conferences.GroupChatRoomListener; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.ui.rooms.GroupChatRoom; -import org.jivesoftware.spark.util.SwingTimerTask; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -/** - * Contains all ChatRoom objects within Spark. - * - * @author Derek DeMoro - */ -public class ChatContainer extends SparkTabbedPane implements MessageListener, ChangeListener, KeyListener { - private static final long serialVersionUID = 3725711237490056136L; - - /** - * List of all ChatRoom Listeners. - */ - private final List chatRoomListeners = new ArrayList<>(); - private final List chatRoomList = new ArrayList<>(); - private final Map presenceMap = new HashMap<>(); - private static final String WELCOME_TITLE = SparkRes.getString(SparkRes.WELCOME); - private ChatFrame chatFrame; - private final TimerTask focusTask; - - - /** - * Creates the ChatContainer to hold all ChatRooms. - */ - public ChatContainer() { - // Assign location - super(SettingsManager.getLocalPreferences().isTabTopPosition() ? JTabbedPane.TOP : JTabbedPane.BOTTOM); - - // Set minimum size - setMinimumSize(new Dimension(400, 200)); - // Don't allow tabs to shrink and allow scrolling. - - enableDragAndDrop(); - //add Group chat room listener - addChatRoomListener(new GroupChatRoomListener()); - addSparkTabbedPaneListener(new SparkTabbedPaneListener() { - public void tabRemoved(SparkTab tab, Component component, int index) { - stateChanged(null); - if (component instanceof ChatRoom) { - cleanupChatRoom((ChatRoom)component); - } - else if (component instanceof ContainerComponent) { - ((ContainerComponent)component).closing(); - } - } - - public void tabAdded(SparkTab tab, Component component, int index) { - stateChanged(null); - } - - public void tabSelected(SparkTab tab, Component component, int index) { - stateChanged(null); - - // Notify ChatRoomListeners that the tab has been activated. - if (component instanceof ChatRoom) { - fireChatRoomActivated((ChatRoom)component); - } - } - - public void allTabsRemoved() { - - if (chatFrame != null) { - chatFrame.setTitle(""); - chatFrame.setVisible(false); - chatFrame = null; - } - - } - - - public boolean canTabClose(SparkTab tab, Component component) { - return true; - } - }); - - setCloseButtonEnabled(true); - - // Add Key Navigation - addKeyNavigation(); - - this.setFocusable(false); - - setOpaque(true); - - setBackground(Color.white); - - // Create task for focusing chat. - focusTask = new SwingTimerTask() { - public void doRun() { - try { - //chatFrame.requestFocus(); - ChatRoom chatRoom = getActiveChatRoom(); - chatRoom.getChatInputEditor().requestFocusInWindow(); - updateActiveTab(); - - } - catch (ChatRoomNotFoundException e1) { - // Ignore. There may legitamtly not be a chat room. - } - } - }; - - } - - - - - /** - * Adds navigation capability to chat rooms. Users can navigate using the alt-left or right arrow keys. - */ - private void addKeyNavigation() { - KeyStroke leftStroke = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0); - String leftStrokeString = org.jivesoftware.spark.util.StringUtils.keyStroke2String(leftStroke); - - // Handle Left Arrow - this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("alt " + leftStrokeString + ""), "navigateLeft"); - this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("alt " + leftStrokeString + ""), "navigateLeft"); - this.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("alt " + leftStrokeString + ""), "navigateLeft"); - this.getActionMap().put("navigateLeft", new AbstractAction("navigateLeft") { - private static final long serialVersionUID = -8677467560602512074L; - - public void actionPerformed(ActionEvent evt) { - navigateLeft(); - } - }); - - KeyStroke rightStroke = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0); - String rightStrokeString = org.jivesoftware.spark.util.StringUtils.keyStroke2String(rightStroke); - - // Handle Right Arrow - this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("alt " + rightStrokeString + ""), "navigateRight"); - this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("alt " + rightStrokeString + ""), "navigateRight"); - this.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("alt " + rightStrokeString + ""), "navigateRight"); - - - this.getActionMap().put("navigateRight", new AbstractAction("navigateRight") { - private static final long serialVersionUID = -7676330627598261416L; - - public void actionPerformed(ActionEvent evt) { - navigateRight(); - } - }); - - this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("ESCAPE"), "escape"); - this.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("ESCAPE"), "escape"); - - this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("Ctrl W"), "escape"); - this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "escape"); - - this.getActionMap().put("escape", new AbstractAction("escape") { - private static final long serialVersionUID = 5165074248488666495L; - - public void actionPerformed(ActionEvent evt) { - closeActiveRoom(); - } - }); - - this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | InputEvent.SHIFT_MASK), "shiftCmdW"); - this.getActionMap().put("shiftCmdW", new AbstractAction("shiftCmdW") { - private static final long serialVersionUID = -1179625099164632251L; - - public void actionPerformed(ActionEvent evt) { - closeAllChatRooms(); - } - }); - - // Add KeyMappings - getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "searchContacts"); - getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("control F"), "searchContacts"); - getActionMap().put("searchContacts", new AbstractAction("searchContacts") { - private static final long serialVersionUID = -6904085783599775675L; - - public void actionPerformed(ActionEvent evt) { - SwingWorker worker = new SwingWorker() { - - @Override - public Object construct() { - return 42; - } - @Override - public void finished() { - SparkManager.getUserManager() - .searchContacts("", SparkManager.getChatManager() - .getChatContainer().getChatFrame()); - } - }; - worker.start(); - } - }); - } - - - /** - * Adds a new ChatRoom to Spark. - * - * @param room the ChatRoom to add. - */ - public synchronized void addChatRoom(final ChatRoom room) { - createFrameIfNeeded(); - - room.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.LIGHT_GRAY)); - AndFilter presenceFilter = new AndFilter(new StanzaTypeFilter(Presence.class), FromMatchesFilter.createBare( room.getRoomname())); - - // Next, create a packet listener. We use an anonymous inner class for brevity. - StanzaListener myListener = stanza -> SwingUtilities.invokeLater( () -> handleRoomPresence((Presence)stanza) ); - - room.registeredToFrame(chatFrame); - - SparkManager.getConnection().addAsyncStanzaListener(myListener, presenceFilter); - - // Add to PresenceMap - presenceMap.put(room.getRoomname(), myListener); - - String tooltip; - if (room instanceof ChatRoomImpl) { - tooltip = ((ChatRoomImpl)room).getParticipantJID(); - String nickname = SparkManager.getUserManager().getUserNicknameFromJID(((ChatRoomImpl)room).getParticipantJID()); - - tooltip = "Contact: " + nickname + "
        JID: " + tooltip; - } - else { - tooltip = room.getRoomname(); - } - - // Create ChatRoom UI and dock - SparkTab tab = addTab(room.getTabTitle(), room.getTabIcon(), room, tooltip); - tab.addMouseListener(new MouseAdapter() { - public void mouseReleased(MouseEvent e) { - checkTabPopup(e); - } - - public void mousePressed(MouseEvent e) { - checkTabPopup(e); - } - }); - - room.addMessageListener(this); - - // Remove brand panel - final String title = getTabAt(0).getActualText(); - if (title.equals(WELCOME_TITLE)) { - chatFrame.setTitle(room.getRoomTitle()); - } - - - final TimerTask visibleTask = new SwingTimerTask() { - public void doRun() { - checkVisibility(room); - } - }; - - TaskEngine.getInstance().schedule(visibleTask, 100); - - // Add to ChatRoomList - chatRoomList.add(room); - - // Notify users that the chat room has been opened. - fireChatRoomOpened(room); - - // Focus Chat - focusChat(); - - // Add Room listeners to override issue with input maps and keybinding on the mac. - if (Spark.isMac()) { - room.getChatInputEditor().addKeyListener(this); - } - } - - public void addContainerComponent(ContainerComponent comp) { - createFrameIfNeeded(); - - addTab(comp.getTabTitle(), comp.getTabIcon(), comp.getGUI(), comp.getToolTipDescription()); - chatFrame.setTitle(comp.getFrameTitle()); - checkVisibility(comp.getGUI()); - - if (getSelectedComponent() != comp) { - // Notify Decorators - SparkManager.getChatManager().notifySparkTabHandlers(comp.getGUI()); - } - } - - /** - * Handles the presence of a one to one chat room. - * - * @param p the presence to handle. - */ - private void handleRoomPresence(final Presence p) { - final String roomname = XmppStringUtils.parseBareJid(p.getFrom()); - ChatRoom chatRoom; - try { - chatRoom = getChatRoom(roomname); - } - catch (ChatRoomNotFoundException e1) { - Log.debug("Could not locate chat room " + roomname); - return; - } - - final String userid = XmppStringUtils.parseResource(p.getFrom()); - if (p.getType() == Presence.Type.unavailable) { - fireUserHasLeft(chatRoom, userid); - } - else if (p.getType() == Presence.Type.available) { - fireUserHasJoined(chatRoom, userid); - } - - // Change tab icon - if (chatRoom instanceof ChatRoomImpl) { - // Notify state change. - int tabLoc = indexOfComponent(chatRoom); - if (tabLoc != -1) { - SparkManager.getChatManager().notifySparkTabHandlers(chatRoom); - } - } - } - - private void checkVisibility(Component component) { - if (!chatFrame.isVisible() && SparkManager.getMainWindow().isFocusOwner()) { - chatFrame.setState(Frame.NORMAL); - chatFrame.setVisible(true); - } - else if (chatFrame.isVisible() && !chatFrame.isInFocus()) { - startFlashing(component, false, null, null); - } - else if (chatFrame.isVisible() && chatFrame.getState() == Frame.ICONIFIED) { - // Set to new tab. - int tabLocation = indexOfComponent(component); - setSelectedIndex(tabLocation); - - // If the ContactList is in the tray, we need better notification by flashing - // the chatframe. - startFlashing(component, false, null, null); - } - - // Handle when chat frame is visible but the Contact List is not. - else if (chatFrame.isVisible() && !SparkManager.getMainWindow().isVisible()) { - startFlashing(component, false, null, null); - } - else if (!chatFrame.isVisible()) { - // Set to new tab. - int tabLocation = indexOfComponent(component); - setSelectedIndex(tabLocation); - - if (Spark.isWindows()) { - chatFrame.setFocusableWindowState(false); - chatFrame.setState(Frame.ICONIFIED); - } - chatFrame.setFocusableWindowState(true); - - // If the ContactList is in the tray, we need better notification by flashing - // the chatframe. - if (!SparkManager.getMainWindow().isVisible()) { - startFlashing(component, false, null, null); - } - else if (chatFrame.getState() == Frame.ICONIFIED) { - startFlashing(component, false, null, null); - } - - if (component instanceof ChatRoom) { - chatFrame.setTitle(((ChatRoom)component).getRoomTitle()); - } - } - } - - - - private void handleMessageNotification(final ChatRoom chatRoom, boolean customMsg, String customMsgText, String customMsgTitle) { - ChatRoom activeChatRoom = null; - boolean groupMessageChecked = false; - try { - activeChatRoom = getActiveChatRoom(); - } - catch (ChatRoomNotFoundException e1) { - Log.error(e1); - } - - if (chatFrame.isVisible() && (chatFrame.getState() == Frame.ICONIFIED || chatFrame.getInactiveTime() > 20000)) { - int tabLocation = indexOfComponent(chatRoom); - setSelectedIndex(tabLocation); - groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); - return; - } - if(chatFrame.isVisible() && chatFrame.getState()== Frame.NORMAL) - { - groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); - groupMessageChecked = true; - } - - if (!chatFrame.isVisible() && SparkManager.getMainWindow().isFocusOwner()) { - chatFrame.setState(Frame.NORMAL); - chatFrame.setVisible(true); - } - else if (chatFrame.isVisible() && !chatFrame.isInFocus()) { - if (!groupMessageChecked) { - groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); - } - } - else if (chatFrame.isVisible() && chatFrame.getState() == Frame.ICONIFIED) { - // Set to new tab. - int tabLocation = indexOfComponent(chatRoom); - setSelectedIndex(tabLocation); - - // If the ContactList is in the tray, we need better notification by flashing - // the chatframe. - if (!groupMessageChecked) { - groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); - } - } - - // Handle when chat frame is visible but the Contact List is not. - else if (chatFrame.isVisible() && !SparkManager.getMainWindow().isVisible() && !chatFrame.isInFocus()) { - if (!groupMessageChecked) { - groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); - } - } - else if (!chatFrame.isVisible()) { - // Set to new tab. - int tabLocation = indexOfComponent(chatRoom); - setSelectedIndex(tabLocation); - - if (Spark.isWindows()) { - chatFrame.setExtendedState(Frame.ICONIFIED); - } - chatFrame.setVisible(true); - - // If the ContactList is in the tray, we need better notification by flashing - // the chatframe. - if (!SparkManager.getMainWindow().isVisible()) { - if (!groupMessageChecked) { - groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); - } - } - else if (chatFrame.getState() == Frame.ICONIFIED) { - if (!groupMessageChecked) { - groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); - } - } - - chatFrame.setTitle(chatRoom.getRoomTitle()); - } - else if (chatRoom != activeChatRoom) { - if (!groupMessageChecked) { - groupChatMessageCheck(chatRoom, customMsg, customMsgText, customMsgTitle); - } - } - } - - /** - * Removes the ChatRoom resources. - * - * @param room the room to remove. - */ - private void cleanupChatRoom(ChatRoom room) { - if (room.isActive()) { - room.leaveChatRoom(); - room.closeChatRoom(); - } - - final StanzaListener listener = presenceMap.get(room.getRoomname()); - if (listener != null) { - SparkManager.getConnection().removeAsyncStanzaListener(listener); - } - - fireChatRoomClosed(room); - room.removeMessageListener(this); - - // Remove mappings - presenceMap.remove(room.getRoomname()); - - chatRoomList.remove(room); - - room.getChatInputEditor().removeKeyListener(this); - - // Clear all Text :) - room.getTranscriptWindow().cleanup(); - } - - /** - * Close all chat rooms. - */ - public void closeAllChatRooms() { - LocalPreferences pref = SettingsManager.getLocalPreferences(); - - if (MainWindow.getInstance().isDocked() || !pref.isAutoCloseChatRoomsEnabled()) { - return; - } - - for (ChatRoom chatRoom : new ArrayList<>( chatRoomList )) { - closeTab(chatRoom); - chatRoom.closeChatRoom(); - } - - for (int i = 0; i < getTabCount(); i++) { - Component comp = getComponentAt(i); - if (comp instanceof ContainerComponent) { - ((ContainerComponent)comp).closing(); - } - - closeTab(comp); - } - } - - /** - * Leaves a ChatRoom. Leaving a chat room does everything but close the room itself. - * - * @param room the room to leave. - */ - public void leaveChatRoom(ChatRoom room) { - // Notify that the chatroom has been left. - fireChatRoomLeft(room); - room.leaveChatRoom(); - - final StanzaListener listener = presenceMap.get(room.getRoomname()); - if (listener != null && SparkManager.getConnection().isConnected()) { - SparkManager.getConnection().removeAsyncStanzaListener(listener); - } - } - - /** - * Returns a ChatRoom by name. - * - * @param roomName the name of the ChatRoom. - * @return the ChatRoom - * @throws ChatRoomNotFoundException if the room was not found. - */ - public ChatRoom getChatRoom(String roomName) throws ChatRoomNotFoundException { - for (int i = 0; i < getTabCount(); i++) { - ChatRoom room = null; - try { - room = getChatRoom(i); - } - catch (ChatRoomNotFoundException e1) { - // Ignore - } - - if (room != null && room.getRoomname().equalsIgnoreCase(roomName) && room.isActive()) { - return room; - } - } - throw new ChatRoomNotFoundException(roomName + " not found."); - } - - /** - * Returns a ChatRoom in the specified tab location. - * - * @param location the tab location. - * @return the ChatRoom found. - * @throws ChatRoomNotFoundException thrown if the room is not found. - */ - public ChatRoom getChatRoom(int location) throws ChatRoomNotFoundException { - if (getTabCount() < location) { - throw new ChatRoomNotFoundException(); - } - try { - Component comp = getComponentAt(location); - if (comp instanceof ChatRoom) { - return (ChatRoom)comp; - } - } - catch (ArrayIndexOutOfBoundsException outOfBoundsEx) { - Log.error("Error getting Chat Room", outOfBoundsEx); - } - - throw new ChatRoomNotFoundException(); - } - - /** - * Returns the Active ChatRoom. - * - * @return the ChatRoom active in the tabbed pane. - * @throws ChatRoomNotFoundException is thrown if no chat room is found. - */ - public ChatRoom getActiveChatRoom() throws ChatRoomNotFoundException { - int location = getSelectedIndex(); - if (location != -1) { - return getChatRoom(location); - } - throw new ChatRoomNotFoundException(); - } - - /** - * Returns the Active Component. - * - * @return the Component active in the tabbed pane. - */ - public Component getActiveRoom() { - int location = getSelectedIndex(); - if (location != -1) { - return getComponentAt(location); - } - - return null; - } - - /** - * Activates the specified ChatRoom. - * - * @param room the ChatRoom to activate. - */ - public void activateChatRoom(ChatRoom room) { - int tabLocation = indexOfComponent(room); - setSelectedIndex(tabLocation); - - chatFrame.bringFrameIntoFocus(); - focusChat(); - } - - /** - * Activates the component in tabbed pane. - * - * @param component the component contained within the tab to activate. - */ - public void activateComponent(Component component) { - int tabLocation = indexOfComponent(component); - if (tabLocation != -1) { - setSelectedIndex(tabLocation); - } - - chatFrame.bringFrameIntoFocus(); - focusChat(); - } - - /** - * Used for Tray Notifications. - * - * @param room the ChatRoom where the message was received. - * @param message the message received. - */ - public void messageReceived(ChatRoom room, Message message) { - room.increaseUnreadMessageCount(); - SparkManager.getWorkspace().getTranscriptPlugin().persistChatRoom(room); - fireNotifyOnMessage(room, false, null, null); - ChatManager.getInstance().fireMessageReceived(message); - } - - /** - * Used for Tray Notifications. - * - * @param chatRoom the ChatRoom where the message was received. - * @param customMsg - * @param customMsgText - * @param customMsgTitle - */ - public void fireNotifyOnMessage(final ChatRoom chatRoom, final boolean customMsg, final String customMsgText, final String customMsgTitle) { - SwingUtilities.invokeLater( () -> handleMessageNotification(chatRoom, customMsg, customMsgText, customMsgTitle) ); - } - - /*** - * - * @param room - * @param message - */ - public void messageSent(ChatRoom room, Message message) { - fireChatRoomStateUpdated(room); - } - - /** - * Notification that the tab pane has been modified. Generally by changing of the tabs. - * - * @param e the ChangeEvent. - */ - public void stateChanged(ChangeEvent e) { - // Stop the flashing only if the chat frame is in focus. - if (chatFrame.isInFocus()) { - stopFlashing(); - } - - final Object o = getSelectedComponent(); - if (o instanceof ChatRoom) { - final ChatRoom room = (ChatRoom)o; - focusChat(); - - // Set the title of the room. - chatFrame.setTitle(room.getRoomTitle()); - chatFrame.setIconImage(SparkManager.getMainWindow().getIconImage()); - } - else if (o instanceof ContainerComponent) { - final ContainerComponent comp = (ContainerComponent)o; - chatFrame.setTitle(comp.getFrameTitle()); - chatFrame.setIconImage(comp.getTabIcon().getImage()); - - SparkManager.getChatManager().notifySparkTabHandlers(comp.getGUI()); - } - } - - - private void stopFlashing() { - try { - // Get current tab - int selectedIndex = getSelectedIndex(); - if (selectedIndex != -1) { - Component comp = getComponentAt(selectedIndex); - if (comp != null) { - stopFlashing(comp); - } - } - } - catch (Exception e) { - Log.error(e); - } - } - - - /** - * Closes a tab of a room. - * - * @param component the component inside of the tab to close. - */ - public void closeTab(Component component) { - int location = indexOfComponent(component); - if (location == -1) { - return; - } - - if (getTabCount() == 0) { - chatFrame.setTitle(""); - } - - this.close(this.getTabAt(location)); - } - - public void closeActiveRoom() { - ChatRoom room; - try { - room = getActiveChatRoom(); - } - catch (ChatRoomNotFoundException e1) { - Component comp = getActiveRoom(); - if (comp != null) { - boolean canClose = ((ContainerComponent)comp).closing(); - if (canClose) { - closeTab(comp); - } - } - - return; - } - - // Confirm end session - boolean isGroupChat = room.getChatType() == Message.Type.groupchat; - if (isGroupChat) { - final int ok = JOptionPane.showConfirmDialog(chatFrame, Res.getString("message.end.conversation"), - Res.getString("title.confirmation"), JOptionPane.YES_NO_OPTION); - if (ok == JOptionPane.OK_OPTION) { - room.closeChatRoom(); - } - } - else { - room.closeChatRoom(); - } - - - } - - public String toString() { - StringBuilder buf = new StringBuilder(); - for (ChatRoom room : chatRoomList) { - buf.append("Roomname=").append(room.getRoomname()).append("\n"); - } - return buf.toString(); - } - - - /** - * Returns true if there are any Rooms present. - * - * @return true if Rooms are present, otherwise false. - */ - public boolean hasRooms() { - int count = getSelectedIndex(); - return count != -1; - } - - /** - * Adds a ChatRoom listener to ChatRooms. The - * listener will be called when either a ChatRoom has been - * added, removed, or activated. - * - * @param listener the ChatRoomListener to register - */ - public void addChatRoomListener(ChatRoomListener listener) { - if (!chatRoomListeners.contains(listener)) { - chatRoomListeners.add(listener); - } - } - - /** - * Removes the specified ChatRoomListener. - * - * @param listener the ChatRoomListener to remove - */ - public void removeChatRoomListener(ChatRoomListener listener) { - chatRoomListeners.remove(listener); - } - - /** - * Notifies users that a ChatRoom has been opened. - * - * @param room - the ChatRoom that has been opened. - */ - protected void fireChatRoomOpened(ChatRoom room) { - for (ChatRoomListener chatRoomListener : new ArrayList<>( chatRoomListeners )) { - chatRoomListener.chatRoomOpened(room); - } - } - - /** - * Notifies users that a ChatRoom has been left. - * - * @param room - the ChatRoom that has been left - */ - protected void fireChatRoomLeft(ChatRoom room) { - for (ChatRoomListener chatRoomListener : new HashSet<>( chatRoomListeners )) { - chatRoomListener.chatRoomLeft(room); - } - } - - /** - * Notifies users that a ChatRoom has been closed. - * - * @param room - the ChatRoom that has been closed. - */ - protected void fireChatRoomClosed(ChatRoom room) { - for (ChatRoomListener chatRoomListener : new HashSet<>( chatRoomListeners )) { - chatRoomListener.chatRoomClosed(room); - } - } - - /** - * Notifies users that a ChatRoom has been activated. - * - * @param room - the ChatRoom that has been activated. - */ - protected void fireChatRoomActivated(ChatRoom room) { - for (ChatRoomListener chatRoomListener : new HashSet<>( chatRoomListeners )) { - chatRoomListener.chatRoomActivated(room); - } - } - - /** - * Notifies users that a user has joined a ChatRoom. - * - * @param room - the ChatRoom that a user has joined. - * @param userid - the userid of the person. - */ - protected void fireUserHasJoined(final ChatRoom room, final String userid) { - SwingUtilities.invokeLater( () -> { - for (ChatRoomListener chatRoomListener : new HashSet<>( chatRoomListeners )) { - chatRoomListener.userHasJoined(room, userid); - } - } ); - - } - - /** - * Notifies users that a user has left a ChatRoom. - * - * @param room - the ChatRoom that a user has left. - * @param userid - the userid of the person. - */ - protected void fireUserHasLeft(final ChatRoom room, final String userid) { - SwingUtilities.invokeLater( () -> { - for (ChatRoomListener chatRoomListener : new HashSet<>( chatRoomListeners )) { - chatRoomListener.userHasLeft(room, userid); - } - } ); - - } - - /** - * Starts flashing of MainWindow. - * - * @param comp the Component to check if a message has been inserted - * but the room is not the selected room. - */ - public void startFlashing(final Component comp, final boolean customMsg, - final String customMsgText, final String customMsgTitle) { - - SwingUtilities.invokeLater( () -> { - try { - final int index = indexOfComponent(comp); - if (index != -1) { - // Check notifications. - if (SettingsManager.getLocalPreferences().isChatRoomNotificationsOn()|| !(comp instanceof GroupChatRoom)) { - if (comp instanceof ChatRoom) { - if (comp instanceof GroupChatRoom) { - if (((GroupChatRoom) comp).getLastMessage() != null) - if (!((GroupChatRoom) comp).isBlocked(((GroupChatRoom) comp).getLastMessage().getFrom())) - checkNotificationPreferences((ChatRoom) comp,customMsg,customMsgText,customMsgTitle); - } else { - checkNotificationPreferences((ChatRoom) comp, customMsg,customMsgText, customMsgTitle); - } - } - } - // Notify decorators - SparkManager.getChatManager().notifySparkTabHandlers(comp); - } - - boolean flashAllowed = SettingsManager.getLocalPreferences().isChatRoomNotificationsOn() - || !(comp instanceof GroupChatRoom); - - if (!chatFrame.isInFocus() && flashAllowed) { - SparkManager.getNativeManager().flashWindow(chatFrame); - } - } catch (Exception ex) { - Log.error("Issue in ChatRooms with tab location.", ex); - } - } ); - } - - - public void fireChatRoomStateUpdated(final ChatRoom room) { - final int index = indexOfComponent(room); - if (index != -1) { - SparkManager.getChatManager().notifySparkTabHandlers(room); - } - } - - /** - * Checks to see if the ChatFrame should stop flashing. - * - * @param component the component that should be notified. - */ - public void stopFlashing(final Component component) { - SwingUtilities.invokeLater( () -> { - try { - // Stop the flashing - SparkManager.getNativeManager().stopFlashing(chatFrame); - - // Notify decorators - SparkManager.getChatManager().notifySparkTabHandlers(component); - } - catch (Exception ex) { - Log.error("Could not stop flashing because " + ex.getMessage(), ex); - } - - - } ); - } - - /** - * Handles Notification preferences for incoming messages and rooms. - * - * @param room the chat room. - * @param fileTransfer if it is a file transfer then true - * @param fileTName the file name being transfered (if fileTransfer applies) - * - */ - private void checkNotificationPreferences(final ChatRoom room, boolean customMsg, String customMsgText, String customMsgTitle) { - LocalPreferences pref = SettingsManager.getLocalPreferences(); - - if (pref.getWindowTakesFocus()) { - chatFrame.setState(Frame.NORMAL); - chatFrame.setVisible(true); - } - - if (pref.getShowToasterPopup()) { - SparkToaster toaster = new SparkToaster(); - toaster.setCustomAction(new AbstractAction() { - private static final long serialVersionUID = -2759404307378067515L; - - public void actionPerformed(ActionEvent actionEvent) { - chatFrame.setState(Frame.NORMAL); - chatFrame.setVisible(true); - int tabLocation = indexOfComponent(room); - if (tabLocation != -1) { - setSelectedIndex(tabLocation); - } - } - }); - - toaster.setDisplayTime(5000); - toaster.setBorder(BorderFactory.createBevelBorder(0)); - - String nickname = room.getRoomTitle(); - - toaster.setToasterHeight(150); - toaster.setToasterWidth(200); - - int size = room.getTranscripts().size(); - if(customMsg) { - toaster.setTitle(customMsgTitle); - toaster.showToaster(room.getTabIcon(), customMsgText); - } else { - toaster.setTitle(nickname); - if (size > 0) { - Message message = room.getTranscripts().get(size - 1); - toaster.showToaster(room.getTabIcon(), message.getBody()); - } - } - } - } - - /** - * Performs several group chat checks - * - * chatRoom the chat room that needs to be passed - * customMsg whether or not this is a custom message - * customMsgText if any custom message should appear in the popup - * customMsgTitle whether or not the toaster should have any popup - * - **/ - private void groupChatMessageCheck(ChatRoom chatRoom, boolean customMsg, String customMsgText, String customMsgTitle) { - // predefine if this is a group chat message or not - LocalPreferences localPref = SettingsManager.getLocalPreferences(); - boolean isGroupChat = chatRoom.getChatType() == Message.Type.groupchat; - int size = chatRoom.getTranscripts().size(); - - // is this a group chat message and is my name in it? - if (isGroupChat) { - // is a group chat, perform some functions - String fromNickName=""; - Message lastChatMessage= new Message(); - String mucNickNameT; - String finalRoomName =""; - if(size>0) - { - lastChatMessage = chatRoom.getTranscripts().get(size - 1); - mucNickNameT = lastChatMessage.getFrom(); - String[] mucNickName = mucNickNameT.split("/"); - finalRoomName = chatRoom.getRoomTitle(); - if (mucNickName.length < 2) { // We have no name after "/" in mucNickNameT (must be like: test@conference.jabber.kg/kos) - fromNickName = finalRoomName; //Res.getString("label.message"); - } else { - fromNickName = mucNickName[1]; - } - } - if ( localPref.isMucHighToastEnabled()) { - // allowed to check for new messages containing name - String myNickName = chatRoom.getNickname(); - String myUserName = SparkManager.getSessionManager().getUsername(); - Pattern usernameMatch = Pattern.compile(myUserName, Pattern.CASE_INSENSITIVE); - Pattern nicknameMatch = Pattern.compile(myNickName, Pattern.CASE_INSENSITIVE); - - if (usernameMatch.matcher(lastChatMessage.getBody()).find() || nicknameMatch.matcher(lastChatMessage.getBody()).find()) { - // match, send new message - boolean customMsgS = true; - String customMsgTextS = Res.getString("group.chat.name.match") + " " + finalRoomName + " by " + fromNickName + " (" + lastChatMessage.getBody() + ")"; - String customMsgTitleS = Res.getString("group.chat.name.notification"); - - startFlashing(chatRoom, customMsgS, customMsgTextS, customMsgTitleS); - } else { - // regular group message - boolean customMsgS = true; - String customMsgTextS = fromNickName + " says: " + lastChatMessage.getBody(); - String customMsgTitleS = finalRoomName; - - startFlashing(chatRoom, customMsgS, customMsgTextS, customMsgTitleS); - } - } else { - // regular group message - boolean customMsgS = true; - String customMsgTextS = fromNickName + " says: " + lastChatMessage.getBody(); - String customMsgTitleS = finalRoomName; - - startFlashing(chatRoom, customMsgS, customMsgTextS, customMsgTitleS); - } - } else if (customMsg) { - // probablt a file transfer request - boolean customMsgS = customMsg; - String customMsgTextS = customMsgText; - String customMsgTitleS = customMsgTitle; - - startFlashing(chatRoom, customMsgS, customMsgTextS, customMsgTitleS); - } else { - // normal personal chat - Message lastChatMessage = null; - if(size > 0) - lastChatMessage = chatRoom.getTranscripts().get(size - 1); - String finalRoomName = chatRoom.getRoomTitle(); - - String customMsgTextS = ""; - boolean customMsgS = true; - String customMsgTitleS = finalRoomName; - - if(lastChatMessage != null) { - customMsgTextS = lastChatMessage.getBody(); - } - - startFlashing(chatRoom, customMsgS, customMsgTextS, customMsgTitleS); - } - } - - public void setChatRoomTitle(ChatRoom room, String title) { - int index = indexOfComponent(room); - if (index != -1) { - SparkTab tab = getTabAt(index); - fireChatRoomStateUpdated(room); - tab.setTabTitle(room.getTabTitle()); - } - } - - private void createFrameIfNeeded() { - if (chatFrame != null) { - return; - } - - LocalPreferences pref = SettingsManager.getLocalPreferences(); - - if (pref.isDockingEnabled()) { - chatFrame = MainWindow.getInstance(); - } else { - chatFrame = new ChatFrame(); - } - - - if (SparkManager.getMainWindow().isActive() || pref.getWindowTakesFocus()) { - chatFrame.setState(Frame.NORMAL); - - } else { - chatFrame.setAutoRequestFocus(false); - chatFrame.setState(Frame.ICONIFIED); - } - - - chatFrame.setVisible(true); - - chatFrame.addWindowListener(new WindowAdapter() { - public void windowActivated(WindowEvent windowEvent) { - stopFlashing(); - int sel = getSelectedIndex(); - if (sel == -1) { - return; - } - final ChatRoom room; - try { - room = getChatRoom(sel); - focusChat(); - - // Set the title of the room. - chatFrame.setTitle(room.getRoomTitle()); - } - catch (ChatRoomNotFoundException e1) { - // Nothing to do - } - - } - - public void windowDeactivated(WindowEvent windowEvent) { - } - - - public void windowClosing(WindowEvent windowEvent) { - // Save layout - chatFrame.saveLayout(); - SparkManager.getChatManager().getChatContainer() - .closeAllChatRooms(); - - } - }); - - // Start timer - handleStaleChats(); - } - - - /** - * Brings the chat into focus. - */ - public void focusChat() { - - - TaskEngine.getInstance().schedule(focusTask, 50); - } - - public Collection getChatRooms() { - return new ArrayList<>( chatRoomList ); - } - - public ChatFrame getChatFrame() { - return chatFrame; - } - - public void blinkFrameIfNecessary(final JFrame frame) { - - final MainWindow mainWindow = SparkManager.getMainWindow(); - - if (mainWindow.isFocusOwner()) { - frame.setVisible(true); - } - else { - // Set to new tab. - if (Spark.isWindows()) { - frame.setState(Frame.ICONIFIED); - SparkManager.getNativeManager().flashWindow(frame); - - frame.setVisible(true); - frame.addWindowListener(new WindowAdapter() { - public void windowActivated(WindowEvent e) { - SparkManager.getNativeManager().stopFlashing(frame); - } - }); - } - } - } - - - private void checkTabPopup(MouseEvent e) { - final SparkTab tab = (SparkTab)e.getSource(); - if (!e.isPopupTrigger()) { - return; - } - - final JPopupMenu popup = new JPopupMenu(); - - // Handle closing this room. - Action closeThisAction = new AbstractAction() { - private static final long serialVersionUID = 5002889397735856123L; - - public void actionPerformed(ActionEvent e) { - ChatRoom chatRoom = (ChatRoom)getComponentInTab(tab); - if (chatRoom != null) { - closeTab(chatRoom); - } - } - }; - closeThisAction.putValue(Action.NAME, Res.getString("message.close.this.chat")); - popup.add(closeThisAction); - - - if (getChatRooms().size() > 1) { - // Handle closing other rooms. - Action closeOthersAction = new AbstractAction() { - private static final long serialVersionUID = 1869236917427431585L; - - public void actionPerformed(ActionEvent e) { - ChatRoom chatRoom = (ChatRoom)getComponentInTab(tab); - if (chatRoom != null) { - for (ChatRoom cRoom : getChatRooms()) { - if (chatRoom != cRoom) { - closeTab(cRoom); - } - } - } - } - }; - - closeOthersAction.putValue(Action.NAME, Res.getString("message.close.other.chats")); - popup.add(closeOthersAction); - - Action closeOldAction = new AbstractAction() { - private static final long serialVersionUID = 1L; - - public void actionPerformed(ActionEvent e) { - for (ChatRoom rooms : getStaleChatRooms()) { - closeTab(rooms); - } - } - }; - closeOldAction.putValue(Action.NAME, Res.getString("message.close.stale.chats")); - popup.add(closeOldAction); - - } - - - popup.show(tab, e.getX(), e.getY()); - - } - - /** - * Returns a Collection of stale chat rooms. - * - * @return a collection of stale chat rooms. - */ - public Collection getStaleChatRooms() { - final List staleRooms = new ArrayList<>(); - for (ChatRoom chatRoom : getChatRooms()) { - long lastActivity = chatRoom.getLastActivity(); - long currentTime = System.currentTimeMillis(); - - long diff = currentTime - lastActivity; - int minutes = (int)(diff / (60 * 1000F)); - - LocalPreferences pref = SettingsManager.getLocalPreferences(); - int timeoutMinutes = pref.getChatLengthDefaultTimeout(); - - int unreadCount = chatRoom.getUnreadMessageCount(); - - if (timeoutMinutes <= minutes && unreadCount == 0) { - staleRooms.add(chatRoom); - } - } - - return staleRooms; - } - - /** - * Checks every room every 30 seconds to see if it's timed out. - */ - private void handleStaleChats() { - int delay = 1000; // delay for 1 second. - int period = 60000; // repeat every minute. - - final TimerTask task = new SwingTimerTask() { - public void doRun() { - for (ChatRoom chatRoom : getStaleChatRooms()) { - // Notify decorators - SparkManager.getChatManager().notifySparkTabHandlers(chatRoom); - } - } - }; - - - TaskEngine.getInstance().scheduleAtFixedRate(task, delay, period); - } - - private void navigateRight() { - int selectedIndex = getSelectedIndex(); - if (selectedIndex > -1) { - int count = getTabCount(); - if (selectedIndex == (count - 1)) { - setSelectedIndex(0); - } - else { - setSelectedIndex(selectedIndex + 1); - } - } - } - - private void navigateLeft() { - int selectedIndex = getSelectedIndex(); - if (selectedIndex > 0) { - setSelectedIndex(selectedIndex - 1); - } - else { - setSelectedIndex(getTabCount() - 1); - } - } - - // Handle key listener events for mac only :) - public void keyTyped(KeyEvent keyEvent) { - // Nothing to do. - } - - public void keyPressed(KeyEvent keyEvent) { - if (keyEvent.isMetaDown()) { - if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) { - navigateRight(); - } - else if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) { - navigateLeft(); - } - - } - } - - public void keyReleased(KeyEvent keyEvent) { - // Nothing to do. - } - - /** - * Returns the total number of unread messages in Spark. - * - * @return the total number of unread messages in Spark. - */ - public int getTotalNumberOfUnreadMessages() { - int messageCount = 0; - for (ChatRoom chatRoom : chatRoomList) { - messageCount += chatRoom.getUnreadMessageCount(); - } - - return messageCount; - } - - public void closeAllGroupChatRooms() { - for (ChatRoom chatRoom : new ArrayList<>( chatRoomList )) { - boolean isGroup = chatRoom.getChatType() == Message.Type.groupchat; - if (isGroup) - { - closeTab(chatRoom); - chatRoom.closeChatRoom(); - } - } - } - - public boolean hasGroupChatRooms() { - for (ChatRoom chatRoom : new ArrayList<>( chatRoomList )) { - boolean isGroup = chatRoom.getChatType() == Message.Type.groupchat; - if (isGroup) - return true; - } - return false; - } -} - diff --git a/src/java/org/jivesoftware/spark/ui/ChatFrame.java b/src/java/org/jivesoftware/spark/ui/ChatFrame.java deleted file mode 100644 index bfa1289ab..000000000 --- a/src/java/org/jivesoftware/spark/ui/ChatFrame.java +++ /dev/null @@ -1,276 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import java.awt.BorderLayout; -import java.awt.Frame; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.awt.event.WindowFocusListener; -import java.util.ArrayList; -import java.util.Collection; - - -import javax.swing.JCheckBox; - -import javax.swing.JFrame; - -import org.jivesoftware.MainWindow; -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Res; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettings; -import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettingsManager; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -/** - * The Window used to display the ChatRoom container. - */ -public class ChatFrame extends JFrame implements WindowFocusListener { - - private static final long serialVersionUID = -7789413067818105293L; - private long inactiveTime; - private boolean focused; - private JCheckBox alwaysOnTopItem; - private ChatFrame chatFrame = this; - private Collection _windowToFrontListeners = new ArrayList<>(); - - /** - * Creates default ChatFrame. - */ - public ChatFrame() { - this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - - - - alwaysOnTopItem = new JCheckBox(); - alwaysOnTopItem.setToolTipText(Res.getString("menuitem.always.on.top")); - alwaysOnTopItem.addActionListener( actionEvent -> { - if (alwaysOnTopItem.isSelected()) - { - SettingsManager.getLocalPreferences().setChatWindowAlwaysOnTop(true); - chatFrame.setAlwaysOnTop(true); - } - else - { - SettingsManager.getLocalPreferences().setChatWindowAlwaysOnTop(false); - chatFrame.setAlwaysOnTop(false); - } - } ); - - if (SettingsManager.getLocalPreferences().isChatWindowAlwaysOnTop()) - { - alwaysOnTopItem.setSelected(true); - chatFrame.setAlwaysOnTop(true); - } - - - - - setIconImage(SparkManager.getApplicationImage().getImage()); - - getContentPane().setLayout(new BorderLayout()); - getContentPane().add(SparkManager.getChatManager().getChatContainer(), BorderLayout.CENTER); - - LayoutSettings settings = LayoutSettingsManager.getLayoutSettings(); - if (settings.getChatFrameX() == 0 && settings.getChatFrameY() == 0) { - // Use default settings. - setSize(500, 400); - GraphicUtils.centerWindowOnScreen(this); - } - else { - setBounds(settings.getChatFrameX(), settings.getChatFrameY(), settings.getChatFrameWidth(), settings.getChatFrameHeight()); - } - - - addWindowFocusListener(this); - - // Setup WindowListener to be the proxy to the actual window listener - // which cannot normally be used outside of the Window component because - // of protected access. - addWindowListener(new WindowAdapter() { - - /** - * This event fires when the window has become active. - * - * @param e WindowEvent is not used. - */ - public void windowActivated(WindowEvent e) { - inactiveTime = 0; - if (Spark.isMac()) { - setJMenuBar(MainWindow.getInstance().getMenu()); - } - } - - /** - * Invoked when a window is de-activated. - */ - public void windowDeactivated(WindowEvent e) { - inactiveTime = System.currentTimeMillis(); - } - - /** - * This event fires whenever a user minimizes the window - * from the toolbar. - * - * @param e WindowEvent is not used. - */ - public void windowIconified(WindowEvent e) { - } - - public void windowDeiconified(WindowEvent e) { - setFocusableWindowState(true); - } - }); - - // Adding a Resize Listener to validate component sizes in a Chat Room. - addComponentListener(new ComponentAdapter() { - public void componentResized(ComponentEvent e) { - try { - ChatRoom chatRoom = SparkManager.getChatManager().getChatContainer().getActiveChatRoom(); - chatRoom.getVerticalSlipPane().setDividerLocation(-1); - } - catch (ChatRoomNotFoundException e1) { - // Ignore, because I don't care if it's not a chat room. - } - } - }); - - - } - - - - - public void windowGainedFocus(WindowEvent e) { - focused = true; - - if(this instanceof MainWindow){ - return; - } - - - SparkManager.getChatManager().getChatContainer().focusChat(); - } - - public void windowLostFocus(WindowEvent e) { - focused = false; - } - - /** - * Returns true if the frame is in focus, otherwise returns false. - * - * @return true if the frame is in focus, otherwise returns false. - */ - public boolean isInFocus() { - return focused; - } - - /** - * Returns time the ChatFrame has not been in focus. - * - * @return the time in milliseconds. - */ - public long getInactiveTime() { - if (inactiveTime == 0) { - return 0; - } - - return System.currentTimeMillis() - inactiveTime; - } - - /** - * Saves the layout on closing of the chat frame. - */ - public void saveLayout() { - LayoutSettings settings = LayoutSettingsManager.getLayoutSettings(); - settings.setChatFrameHeight(getHeight()); - settings.setChatFrameWidth(getWidth()); - settings.setChatFrameX(getX()); - settings.setChatFrameY(getY()); - LayoutSettingsManager.saveLayoutSettings(); - } - - /** - * Brings the ChatFrame into focus on the desktop. - */ - public void bringFrameIntoFocus() { - if (!isVisible()) { - setVisible(true); - } - - if (getState() == Frame.ICONIFIED) { - setState(Frame.NORMAL); - } - - toFront(); - requestFocus(); - } - - /** - * Shake it, come on now, shake that frame. - */ - public void buzz() { - ShakeWindow d = new ShakeWindow(this); - d.startShake(); - } - - - /** - * set if the chatFrame should always stay on top - * @param active - */ - public void setWindowAlwaysOnTop(boolean active) { - SettingsManager.getLocalPreferences().setChatWindowAlwaysOnTop(active); - chatFrame.setAlwaysOnTop(active); - this.fireWindowOnTopListeners(active); - } - - - private void fireWindowOnTopListeners(boolean active) { - for (ChatFrameToFrontListener fl: _windowToFrontListeners) - { - fl.updateStatus(active); - } - - } - - /** - * removes the Window to Front Listener for specified {@link ChatRoom} - * @param chatRoom - */ - public void removeWindowToFrontListener(ChatRoom chatRoom) { - _windowToFrontListeners.remove(chatRoom); - } - - /** - * - * Remove listeners from the "window-alway-on-top" information - * @param chatRoom - */ - public void addWindowToFronListener(ChatRoom chatRoom) { - _windowToFrontListeners.add(chatRoom); - fireWindowOnTopListeners(chatFrame.isAlwaysOnTop()); - } - -} diff --git a/src/java/org/jivesoftware/spark/ui/ChatInputEditor.java b/src/java/org/jivesoftware/spark/ui/ChatInputEditor.java deleted file mode 100644 index 1e5a57179..000000000 --- a/src/java/org/jivesoftware/spark/ui/ChatInputEditor.java +++ /dev/null @@ -1,302 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import java.awt.Color; -import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.KeyStroke; -import javax.swing.UIManager; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.text.BadLocationException; -import javax.swing.text.Document; -import javax.swing.text.StyleConstants; -import javax.swing.undo.CannotUndoException; -import javax.swing.undo.UndoManager; - -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -/** - * This is implementation of ChatArea that should be used as the sendField - * in any chat room implementation. - */ -public class ChatInputEditor extends ChatArea implements DocumentListener { - private static final long serialVersionUID = -3085035737908538581L; - private final UndoManager undoManager; - private KeyStroke undoKeyStroke; - private KeyStroke ctrlbackspaceKeyStroke; - private KeyStroke escapeKeyStroke; - - /** - * Creates a new Default ChatSendField. - */ - public ChatInputEditor() { - undoManager = new UndoManager(); - - this.setDragEnabled(true); - this.getDocument().addUndoableEditListener(undoManager); - Action undo = new AbstractAction() { - private static final long serialVersionUID = -8897769620508545403L; - public void actionPerformed(ActionEvent e) { - try { - undoManager.undo(); - } catch (CannotUndoException cue) { - // no more undoing for you - } - } - }; - - Action escape = new AbstractAction() { - private static final long serialVersionUID = -2973535045376312313L; - @Override - public void actionPerformed(ActionEvent e) { - SparkManager.getChatManager().getChatContainer().closeActiveRoom(); - } - }; - - Action ctrlbackspace = new AbstractAction() { - private static final long serialVersionUID = -2973535045376312313L; - - @Override - public void actionPerformed(ActionEvent e) { - - // We have Text selected, remove it - if (getSelectedText() != null && getSelectedText().length() > 0) { - ChatInputEditor.this.removeWordInBetween(getSelectionStart(), - getSelectionEnd()); - - // We are somewhere in betwee 0 and str.length - } else if (getCaretPosition() < getText().length()) { - - String preCaret = getText() - .substring(0, getCaretPosition()); - - int lastSpace = preCaret.lastIndexOf(" ") != -1 ? preCaret - .lastIndexOf(" ") : 0; - - if (lastSpace != -1 && lastSpace!=0) - { - // Do we have anymore spaces before the current one? - for (int i = lastSpace; getText().charAt(i) == ' '; --i) { - lastSpace--; - } - lastSpace++; - } - ChatInputEditor.this.removeWordInBetween(lastSpace, - getCaretPosition()); - - if (lastSpace <= getText().length()) { - setCaretPosition(lastSpace); - } else { - setCaretPosition(getText().length()); - } - - // We are at the end and will remove until the next SPACE - } else if (getText().contains(" ")) { - int untilhere = getText().lastIndexOf(" "); - - // Do we have anymore spaces before the last one? - for (int i = untilhere; getText().charAt(i) == ' '; --i) { - untilhere--; - } - untilhere++; - ChatInputEditor.this.removeLastWord(getText().substring( - untilhere)); - } else { - ChatInputEditor.this.removeLastWord(getText()); - } - } - }; - - undoKeyStroke = KeyStroke.getKeyStroke('z', ActionEvent.CTRL_MASK); - ctrlbackspaceKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, KeyEvent.CTRL_MASK); - escapeKeyStroke = KeyStroke.getKeyStroke("ESCAPE"); - - getInputMap().put(ctrlbackspaceKeyStroke, "ctrlbackspace"); - getInputMap().put(undoKeyStroke, "undo"); - getInputMap().put(escapeKeyStroke, "escape"); - getInputMap().put(KeyStroke.getKeyStroke("Ctrl W"), "escape"); - - registerKeyboardAction(undo, KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_MASK), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); - registerKeyboardAction(ctrlbackspace, KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, KeyEvent.CTRL_MASK), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); - registerKeyboardAction(escape, KeyStroke.getKeyStroke("ESCAPE"), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); - - getDocument().addDocumentListener(this); - - addMouseListener(this); - } - - public void insertUpdate(DocumentEvent e) { - // this.setCaretPosition(e.getOffset()); - this.requestFocusInWindow(); - } - - /** - * Appends the Text at the end - */ - public void setText(String str) { - super.setText(str); - } - - public void removeUpdate(DocumentEvent e) { - } - - public void changedUpdate(DocumentEvent e) { - } - - /** - * Remove dependices when no longer in use. - */ - public void close() { - getDocument().removeDocumentListener(this); - getDocument().removeUndoableEditListener(undoManager); - removeMouseListener(this); - getInputMap().remove(undoKeyStroke); - getInputMap().remove(ctrlbackspaceKeyStroke); - getInputMap().remove(escapeKeyStroke); - getInputMap().remove(KeyStroke.getKeyStroke("Ctrl W")); - } - - /** - * Disables the Chat Editor, rendering it to the system default - * color. - */ - public void showAsDisabled() { - this.setEditable(false); - this.setEnabled(false); - - clear(); - - final Color disabledColor = (Color)UIManager.get("Button.disabled"); - - this.setBackground(disabledColor); - } - - /** - * Enable the Chat Editor. - */ - public void showEnabled() { - this.setEditable(true); - this.setEnabled(true); - - this.setBackground(Color.white); - } - - /** - * Inserts text into the current document. - * - * @param text the text to insert - * @throws BadLocationException if the location is not available for insertion. - */ - @Override - public void insertText(String text) throws BadLocationException { - final Document doc = getDocument(); - styles.removeAttribute("link"); - doc.insertString(this.getCaret().getDot(), text, styles); - } - - /** - * Inserts text into the current document. - * - * @param text the text to insert - * @param color the color of the text - * @throws BadLocationException if the location is not available for insertion. - */ - @Override - public void insertText(String text, Color color) throws BadLocationException { - final Document doc = getDocument(); - StyleConstants.setForeground(styles, color); - doc.insertString(this.getCaret().getDot(), text, styles); - } - - /** - * Inserts a link into the current document. - * - * @param link - the link to insert( ex. http://www.javasoft.com ) - * @throws BadLocationException if the location is not available for insertion. - */ - @Override - public void insertLink(String link) throws BadLocationException { - final Document doc = getDocument(); - styles.addAttribute("link", link); - - StyleConstants.setForeground(styles, (Color)UIManager.get("Link.foreground")); - StyleConstants.setUnderline(styles, true); - doc.insertString(this.getCaret().getDot(), link, styles); - StyleConstants.setUnderline(styles, false); - StyleConstants.setForeground(styles, (Color)UIManager.get("TextPane.foreground")); - styles.removeAttribute("link"); - setCharacterAttributes(styles, false); - - } - - /** - * Inserts a network address into the current document. - * - * @param address - the address to insert( ex. \superpc\etc\file\ OR http://localhost/ ) - * @throws BadLocationException if the location is not available for insertion. - */ - @Override - public void insertAddress(String address) throws BadLocationException { - final Document doc = getDocument(); - styles.addAttribute("link", address); - - StyleConstants.setForeground(styles, (Color)UIManager.get("Address.foreground")); - StyleConstants.setUnderline(styles, true); - doc.insertString(this.getCaret().getDot(), address, styles); - StyleConstants.setUnderline(styles, false); - StyleConstants.setForeground(styles, (Color)UIManager.get("TextPane.foreground")); - styles.removeAttribute("link"); - setCharacterAttributes(styles, false); - - } - - /** - * Inserts an emotion icon into the current document. - * - * @param imageKey - the smiley representation of the image.( ex. :) ) - * @return true if the image was found, otherwise false. - */ - @Override - public boolean insertImage(String imageKey) { - - if(!forceEmoticons && !SettingsManager.getLocalPreferences().areEmoticonsEnabled() || !emoticonsAvailable){ - return false; - } - final Document doc = getDocument(); - Icon emotion = emoticonManager.getEmoticonImage(imageKey.toLowerCase()); - if (emotion == null) { - return false; - } - - select(doc.getLength(), doc.getLength()); - insertIcon(emotion); - - return true; - } - -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/spark/ui/ChatRoom.java b/src/java/org/jivesoftware/spark/ui/ChatRoom.java deleted file mode 100644 index 49776e598..000000000 --- a/src/java/org/jivesoftware/spark/ui/ChatRoom.java +++ /dev/null @@ -1,1320 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.EventQueue; -import java.awt.FlowLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.AdjustmentEvent; -import java.awt.event.AdjustmentListener; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.File; -import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollBar; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.KeyStroke; -import javax.swing.UIManager; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.text.BadLocationException; -import javax.swing.text.Document; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.ConnectionListener; -import org.jivesoftware.smack.StanzaListener; -import org.jivesoftware.smack.roster.Roster; -import org.jivesoftware.smack.roster.RosterEntry; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Stanza; -import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; -import org.jivesoftware.spark.ChatAreaSendField; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.BackgroundPanel; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.plugin.ContextMenuListener; -import org.jivesoftware.spark.ui.rooms.GroupChatRoom; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.UIComponentRegistry; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -/** - * The base implementation of all ChatRoom conversations. You would implement this class to have most types of Chat. - */ -public abstract class ChatRoom extends BackgroundPanel implements ActionListener, StanzaListener, DocumentListener, ConnectionListener, FocusListener, ContextMenuListener, ChatFrameToFrontListener { - private static final long serialVersionUID = 7981019929515888299L; - private final JPanel chatPanel; - private final JSplitPane splitPane; - private JSplitPane verticalSplit; - - private final JLabel notificationLabel; - private final TranscriptWindow transcriptWindow; - private final ChatAreaSendField chatAreaButton; - private final ChatToolBar toolbar; - private final JScrollPane textScroller; - private final JPanel bottomPanel; - - private final JPanel editorWrapperBar; - private final JPanel editorBarRight; - private final JPanel editorBarLeft; - private JPanel chatWindowPanel; - - private int unreadMessageCount; - - private boolean mousePressed; - - private List closingListeners = new CopyOnWriteArrayList<>(); - - - private ChatRoomTransferHandler transferHandler; - - private final List packetIDList; - private final List messageListeners; - private List transcript; - private List fileDropListeners; - - private MouseAdapter transcriptWindowMouseListener; - - private KeyAdapter chatEditorKeyListener; - private ChatFrame _chatFrame; - private RolloverButton _alwaysOnTopItem; - private boolean _isAlwaysOnTopActive; - - /** - * Initializes the base layout and base background color. - */ - protected ChatRoom() { - chatPanel = new JPanel(new GridBagLayout()); - transcriptWindow = UIComponentRegistry.createTranscriptWindow(); - splitPane = new JSplitPane(); - packetIDList = new ArrayList<>(); - notificationLabel = new JLabel(); - toolbar = new ChatToolBar(); - bottomPanel = new JPanel(); - - messageListeners = new ArrayList<>(); - transcript = new ArrayList<>(); - - editorWrapperBar = new JPanel(new BorderLayout()); - editorBarLeft = new JPanel(new FlowLayout(FlowLayout.LEFT, 1, 1)); - editorBarRight = new JPanel(new FlowLayout(FlowLayout.RIGHT, 1, 1)); - editorWrapperBar.add(editorBarLeft, BorderLayout.WEST); - editorWrapperBar.add(editorBarRight, BorderLayout.EAST); - fileDropListeners = new ArrayList<>(); - - transcriptWindowMouseListener = new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - - if(e.getClickCount()!=2){ - getChatInputEditor().requestFocus(); - } - } - - public void mouseReleased(MouseEvent e) { - mousePressed = false; - if (transcriptWindow.getSelectedText() == null) { - getChatInputEditor().requestFocus(); - } - } - - public void mousePressed(MouseEvent e) { - mousePressed = true; - } - }; - - transcriptWindow.addMouseListener(transcriptWindowMouseListener); - - chatAreaButton = new ChatAreaSendField(Res.getString("button.send")); - /*{ - public Dimension getPreferredSize() { - Dimension dim = super.getPreferredSize(); - - int windowHeight = getChatRoom().getHeight(); - - if (dim.getHeight() > windowHeight - 200) { - dim.height = windowHeight - 200; - } - - return dim; - } - }; - */ - - - textScroller = new JScrollPane(transcriptWindow); - - textScroller.setBackground(transcriptWindow.getBackground()); - textScroller.getViewport().setBackground(Color.white); - transcriptWindow.setBackground(Color.white); - - getChatInputEditor().setSelectedTextColor((Color)UIManager.get("ChatInput.SelectedTextColor")); - getChatInputEditor().setSelectionColor((Color)UIManager.get("ChatInput.SelectionColor")); - - - init(); - - // Initally, set the right pane to null to keep it empty. - getSplitPane().setRightComponent(null); - - notificationLabel.setIcon(SparkRes.getImageIcon(SparkRes.BLANK_IMAGE)); - - - getTranscriptWindow().addContextMenuListener(this); - - transferHandler = new ChatRoomTransferHandler(this); - - getTranscriptWindow().setTransferHandler(transferHandler); - getChatInputEditor().setTransferHandler(transferHandler); - - addToolbar(); - - // Add Connection Listener - SparkManager.getConnection().addConnectionListener(this); - - // Add Focus Listener - addFocusListener(this); - - scrollToBottom(); - - } - - // Setup base layout. - private void init() { - setLayout(new GridBagLayout()); - - // Remove Default Beveled Borders - splitPane.setBorder(null); - splitPane.setOneTouchExpandable(false); - - // Add Vertical Split Pane - verticalSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT); - add(verticalSplit, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); - - verticalSplit.setBorder(null); - verticalSplit.setOneTouchExpandable(false); - - verticalSplit.setTopComponent(splitPane); - - textScroller.setAutoscrolls(true); - - // For the first 5*150ms we wait for transcript to load and move - // scrollpane to max postion if size of scrollpane changed - textScroller.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() { - - private boolean scrollAtStart = false; - - @Override - public void adjustmentValueChanged(AdjustmentEvent e) { - - if (!scrollAtStart) { - scrollAtStart = true; - SwingWorker thread = new SwingWorker() { - - @Override - public Object construct() { - int start = textScroller.getVerticalScrollBar().getMaximum(); - int second; - int i = 0; - do { - try { - - Thread.sleep(150); - second = textScroller.getVerticalScrollBar().getMaximum(); - if (start == second) { - ++i; - } else { - scrollToBottom(); - getTranscriptWindow().repaint(); - } - start = second; - } catch (InterruptedException e) { - e.printStackTrace(); - } - } while (i < 5); - return null; - } - }; - thread.start(); - } - } - }); - - - // Speed up scrolling. It was way too slow. - textScroller.getVerticalScrollBar().setBlockIncrement(200); - textScroller.getVerticalScrollBar().setUnitIncrement(20); - - chatWindowPanel = new JPanel(); - chatWindowPanel.setLayout(new GridBagLayout()); - chatWindowPanel.add(textScroller, new GridBagConstraints(0, 10, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); - chatWindowPanel.setOpaque(false); - - // Layout Components - chatPanel.add(chatWindowPanel, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, - GridBagConstraints.BOTH, getChatPanelInsets(), 0, 0)); - - // Add Chat Panel to Split Pane - splitPane.setLeftComponent(chatPanel); - - // Add edit buttons to Chat Room - editorBarLeft.setOpaque(false); - chatPanel.setOpaque(false); - - - bottomPanel.setOpaque(false); - splitPane.setOpaque(false); - bottomPanel.setLayout(new GridBagLayout()); - bottomPanel.add(chatAreaButton, new GridBagConstraints(0, 1, 5, 1, 1.0, 1.0, GridBagConstraints.WEST, - GridBagConstraints.BOTH, getChatAreaInsets(), 0, 35)); - bottomPanel.add(editorWrapperBar, new GridBagConstraints(0, 0, 5, 1, 0.0, 0.0, GridBagConstraints.WEST, - GridBagConstraints.HORIZONTAL, getEditorWrapperInsets(), 0, 0)); - - // Set bottom panel border - bottomPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(197, 213, 230))); - verticalSplit.setOpaque(false); - - verticalSplit.setBottomComponent(bottomPanel); - verticalSplit.setResizeWeight(1.0); - verticalSplit.setDividerSize(2); - - // Add listener to send button - chatAreaButton.getButton().addActionListener(this); - - // Add Key Listener to Send Field - getChatInputEditor().getDocument().addDocumentListener(this); - - // Add Key Listener to Send Field - chatEditorKeyListener = new KeyAdapter() { - public void keyPressed(KeyEvent e) { - checkForEnter(e); - } - }; - - getChatInputEditor().addKeyListener(chatEditorKeyListener); - - getChatInputEditor().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ctrl F4"), "closeTheRoom"); - getChatInputEditor().getActionMap().put("closeTheRoom", new AbstractAction("closeTheRoom") { - private static final long serialVersionUID = 1L; - - public void actionPerformed(ActionEvent evt) { - // Leave this chat. - closeChatRoom(); - } - }); - - getChatInputEditor().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ctrl SPACE"), "handleCompletion"); - getChatInputEditor().getActionMap().put("handleCompletion", new AbstractAction("handleCompletion") { - private static final long serialVersionUID = 1L; - - public void actionPerformed(ActionEvent evt) { - // handle name completion. - try { - handleNickNameCompletion(); - } catch (ChatRoomNotFoundException e) { - Log.error("ctlr-space nickname find", e); - } - } - }); - - _isAlwaysOnTopActive = SettingsManager.getLocalPreferences().isChatWindowAlwaysOnTop(); - _alwaysOnTopItem = UIComponentRegistry.getButtonFactory().createAlwaysOnTop(_isAlwaysOnTopActive); - - _alwaysOnTopItem.addActionListener( actionEvent -> { - if (!_isAlwaysOnTopActive) - { - SettingsManager.getLocalPreferences().setChatWindowAlwaysOnTop(true); - _chatFrame.setWindowAlwaysOnTop(true); - _isAlwaysOnTopActive = true; - _alwaysOnTopItem.setIcon(SparkRes.getImageIcon("FRAME_ALWAYS_ON_TOP_ACTIVE")); - - } - else - { - SettingsManager.getLocalPreferences().setChatWindowAlwaysOnTop(false); - _chatFrame.setWindowAlwaysOnTop(false); - _isAlwaysOnTopActive = false; - _alwaysOnTopItem.setIcon(SparkRes.getImageIcon("FRAME_ALWAYS_ON_TOP_DEACTIVE")); - } - } ); - - - editorBarRight.add(_alwaysOnTopItem); - } - - - /** - * Handles the Nickname Completion dialog, when Pressing CTRL + SPACE
        - * it searches for matches in the current GroupchatList and also in the - * Roster - * - * @throws ChatRoomNotFoundException - * when for some reason the GroupChatRoom cannot be found, this - * should not happen, since we retrieve it from the - * ActiveWindowTab and thus can be ignored - * @author wolf.posdorfer - */ - private void handleNickNameCompletion() throws ChatRoomNotFoundException { - - String name = getChatInputEditor().getText(); - if (name.length() < 1) - return; - else if (name.contains(" ")) { - if (name.substring(name.lastIndexOf(" ") + 1).length() > 0) { - name = name.substring(name.lastIndexOf(" ") + 1); - } - } - - Collection groupchatlist = new ArrayList<>(); - Collection rosterlist = Roster.getInstanceFor( SparkManager.getConnection() ).getEntries(); - - if(SparkManager.getChatManager().getChatContainer().getActiveChatRoom() instanceof GroupChatRoom) - { - groupchatlist =((GroupChatRoom) SparkManager.getChatManager().getChatContainer().getActiveChatRoom()).getParticipants(); - } - String newname = null; - ArrayList namelist = new ArrayList<>(); - - for (String lol : groupchatlist) { - lol = lol.substring(lol.lastIndexOf("/") + 1); - if (lol.toLowerCase().startsWith(name.toLowerCase())) { - if (newname == null) { - newname = lol; - } - namelist.add(lol); - } - } - - for (RosterEntry re : rosterlist) { - try { - if (re.getName().toLowerCase().startsWith(name.toLowerCase()) && !namelist.contains(re.getName())) { - if (newname == null) { - newname = re.getName(); - } - namelist.add(re.getName()); - } - } catch (NullPointerException npe) { - // AWESOME!!! - // happens on shared rosters - // or when no vcard is set - } - } - - if (newname == null) { - newname = ""; - } else { - newname = newname.substring(name.length()); - } - - if (namelist.size() <= 1) { - // If we only have 1 match, use newname - getChatInputEditor().setText(newname); - } else { - // create Popupmenu creating all other matches - final JPopupMenu popup = new JPopupMenu(); - final String namefinal = name; - for (final String s : namelist) { - JMenuItem temp = new JMenuItem(s); - popup.add(temp); - temp.addActionListener(new AbstractAction() { - private static final long serialVersionUID = 168886428519741638L; - - @Override - public void actionPerformed(ActionEvent e) { - getChatInputEditor().setText( - s.substring(namefinal.length())); - popup.setVisible(false); - - } - }); - - } - popup.show(SparkManager.getChatManager() - .getChatContainer(), getChatInputEditor().getCaret() - .getMagicCaretPosition().x, SparkManager.getChatManager() - .getChatContainer().getHeight() - 20); - } - - } - - // I would normally use the command pattern, but - // have no real use when dealing with just a couple options. - public void actionPerformed(ActionEvent e) { - sendMessage(); - - // Clear send field and disable send button - getChatInputEditor().clear(); - chatAreaButton.getButton().setEnabled(false); - } - - /** - * Creates and sends a message object from the text in - * the Send Field, using the default nickname specified in your - * Chat Preferences. - */ - protected abstract void sendMessage(); - - /** - * Creates a Message object from the given text and delegates to the room - * for sending. - * - * @param text the text to send. - */ - protected abstract void sendMessage(String text); - - /** - * Sends the current message. - * - * @param message - the message to send. - */ - public abstract void sendMessage(Message message); - - /** - * Returns the nickname of the current agent as specified in Chat - * Preferences. - * - * @return the nickname of the agent. - */ - public String getNickname() { - LocalPreferences pref = SettingsManager.getLocalPreferences(); - return pref.getNickname(); - } - - - /** - * The main entry point when receiving any messages. This will - * either handle a message from a customer or delegate itself - * as an agent handler. - * - * @param message - the message receieved. - */ - public void insertMessage(Message message) { - // Fire Message Filters - - SparkManager.getChatManager().filterIncomingMessage(this, message); - - SparkManager.getChatManager().fireGlobalMessageReceievedListeners(this, message); - - addToTranscript(message, true); - - fireMessageReceived(message); - - SparkManager.getWorkspace().getTranscriptPlugin().persistChatRoom(this); - } - - - /** - * Add a ChatResponse to the current discussion chat area. - * - * @param message the message to add to the transcript list - * @param updateDate true if you wish the date label to be updated with the - * date and time the message was received. - */ - public void addToTranscript(Message message, boolean updateDate) { - // Create message to persist. - final Message newMessage = new Message(); - newMessage.setTo(message.getTo()); - newMessage.setFrom(message.getFrom()); - newMessage.setBody(message.getBody()); - final Map properties = new HashMap<>(); - properties.put( "date", new Date() ); - newMessage.addExtension( new JivePropertiesExtension( properties ) ); - - transcript.add(newMessage); - - // Add current date if this is the current agent - if (updateDate && transcriptWindow.getLastUpdated() != null) { - // Set new label date - notificationLabel.setIcon(SparkRes.getImageIcon(SparkRes.SMALL_ABOUT_IMAGE)); - notificationLabel.setText(Res.getString("message.last.message.received", SparkManager.DATE_SECOND_FORMATTER.format(transcriptWindow.getLastUpdated()))); - } - - scrollToBottom(); - } - - /** - * Adds a new message to the transcript history. - * - * @param to who the message is to. - * @param from who the message was from. - * @param body the body of the message. - * @param date when the message was received. - */ - public void addToTranscript(String to, String from, String body, Date date) { - final Message newMessage = new Message(); - newMessage.setTo(to); - newMessage.setFrom(from); - newMessage.setBody(body); - final Map properties = new HashMap<>(); - properties.put( "date", new Date() ); - newMessage.addExtension( new JivePropertiesExtension( properties ) ); - transcript.add(newMessage); - } - - /** - * Scrolls the chat window to the bottom. - */ - public void scrollToBottom() { - if (mousePressed) { - return; - } - - int lengthOfChat = transcriptWindow.getDocument().getLength(); - transcriptWindow.setCaretPosition(lengthOfChat); - - try { - final JScrollBar scrollBar = textScroller.getVerticalScrollBar(); - EventQueue.invokeLater( () -> scrollBar.setValue(scrollBar.getMaximum()) ); - - - } - catch (Exception e) { - Log.error(e); - } - } - - - /** - * Checks to see if the Send button should be enabled. - * - * @param e - the documentevent to react to. - */ - protected void checkForText(DocumentEvent e) { - final int length = e.getDocument().getLength(); - if (length > 0) { - chatAreaButton.getButton().setEnabled(true); - } - else { - chatAreaButton.getButton().setEnabled(false); - } - } - - /** - * Requests valid focus to the SendField. - */ - public void positionCursor() { - getChatInputEditor().setCaretPosition(getChatInputEditor().getCaretPosition()); - chatAreaButton.getChatInputArea().requestFocusInWindow(); - } - - - /** - * Disable the chat room. This is called when a chat has been either transfered over or - * the customer has left the chat room. - */ - public abstract void leaveChatRoom(); - - - /** - * Process incoming packets. - * - * @param stanza - the packet to process - */ - public void processPacket(Stanza stanza) { - } - - - /** - * Returns the SendField component. - * - * @return the SendField ChatSendField. - */ - public ChatInputEditor getChatInputEditor() { - return chatAreaButton.getChatInputArea(); - } - - /** - * Returns the chatWindow components. - * - * @return the ChatWindow component. - */ - public TranscriptWindow getTranscriptWindow() { - return transcriptWindow; - } - - - /** - * Checks to see if enter was pressed and validates room. - * - * @param e the KeyEvent - */ - private void checkForEnter(KeyEvent e) { - final KeyStroke keyStroke = KeyStroke.getKeyStroke(e.getKeyCode(), e.getModifiers()); - if (!keyStroke.equals(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.SHIFT_DOWN_MASK)) && - e.getKeyChar() == KeyEvent.VK_ENTER) { - e.consume(); - sendMessage(); - getChatInputEditor().setText(""); - getChatInputEditor().setCaretPosition(0); - - SparkManager.getWorkspace().getTranscriptPlugin().persistChatRoom(this); - } - else if (keyStroke.equals(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.SHIFT_DOWN_MASK))) { - final Document document = getChatInputEditor().getDocument(); - try { - document.insertString(getChatInputEditor().getCaretPosition(), "\n", null); - getChatInputEditor().requestFocusInWindow(); - chatAreaButton.getButton().setEnabled(true); - } - catch (BadLocationException badLoc) { - Log.error("Error when checking for enter:", badLoc); - } - } - } - - /** - * Add a {@link MessageListener} to the current ChatRoom. - * - * @param listener - the MessageListener to add to the current ChatRoom. - */ - public void addMessageListener(MessageListener listener) { - messageListeners.add(listener); - } - - /** - * Remove the specified {@link MessageListener } from the current ChatRoom. - * - * @param listener - the MessageListener to remove from the current ChatRoom. - */ - public void removeMessageListener(MessageListener listener) { - messageListeners.remove(listener); - } - - /** - * Notifies all message listeners that - * - * @param message the message received. - */ - private void fireMessageReceived(Message message) { - for (MessageListener messageListener : messageListeners) { - messageListener.messageReceived(this, message); - } - } - - /** - * Notifies all MessageListener that a message has been sent. - * - * @param message the message sent. - */ - protected void fireMessageSent(Message message) { - for (MessageListener messageListener : messageListeners) { - messageListener.messageSent(this, message); - } - } - - /** - * Returns a map of the current Chat Transcript which is a list of all - * ChatResponses and their order. You should retrieve this map to get - * any current chat transcript state. - * - * @return - the map of current chat responses. - */ - public List getTranscripts() { - return transcript; - } - - /** - * Disables the ChatRoom toolbar. - */ - public void disableToolbar() { - final int count = editorBarLeft.getComponentCount(); - for (int i = 0; i < count; i++) { - final Object o = editorBarLeft.getComponent(i); - if (o instanceof RolloverButton) { - final RolloverButton rb = (RolloverButton)o; - rb.setEnabled(false); - } - } - } - - /** - * Enable the ChatRoom toolbar. - */ - public void enableToolbar() { - final int count = editorBarLeft.getComponentCount(); - for (int i = 0; i < count; i++) { - final Object o = editorBarLeft.getComponent(i); - if (o instanceof RolloverButton) { - final RolloverButton rb = (RolloverButton)o; - rb.setEnabled(true); - } - } - } - - - /** - * Checks to see if the Send Button should be enabled depending on the - * current update in SendField. - * - * @param event the DocumentEvent from the sendField. - */ - public void removeUpdate(DocumentEvent event) { - checkForText(event); - } - - /** - * Checks to see if the Send button should be enabled. - * - * @param docEvent the document event. - */ - public void changedUpdate(DocumentEvent docEvent) { - // Do nothing. - } - - /** - * Return the splitpane used in this chat room. - * - * @return the splitpane used in this chat room. - */ - public JSplitPane getSplitPane() { - return splitPane; - } - - /** - * Returns the ChatPanel that contains the ChatWindow and SendField. - * - * @return the ChatPanel. - */ - public JPanel getChatPanel() { - return chatPanel; - } - - /** - * Close the ChatRoom. - */ - public void closeChatRoom() { - fireClosingListeners(); - - getTranscriptWindow().removeContextMenuListener(this); - getTranscriptWindow().removeMouseListener(transcriptWindowMouseListener); - getChatInputEditor().removeKeyListener(chatEditorKeyListener); - this.removeAll(); - - textScroller.getViewport().remove(transcriptWindow); - - // Remove Connection Listener - SparkManager.getConnection().removeConnectionListener(this); - getTranscriptWindow().setTransferHandler(null); - getChatInputEditor().setTransferHandler(null); - - transferHandler = null; - - packetIDList.clear(); - messageListeners.clear(); - fileDropListeners.clear(); - getChatInputEditor().close(); - - getChatInputEditor().getActionMap().remove("closeTheRoom"); - chatAreaButton.getButton().removeActionListener(this); - bottomPanel.remove(chatAreaButton); - _chatFrame.removeWindowToFrontListener(this); - - } - - /** - * Get the Icon to be used in the tab holding - * this ChatRoom. - * - * @return - Icon to use - */ - public abstract Icon getTabIcon(); - - /** - * Get the roomname to use for this ChatRoom. - * - * @return - the Roomname of this ChatRoom. - */ - public abstract String getRoomname(); - - /** - * Get the title to use in the tab holding this ChatRoom. - * - * @return - the title to use. - */ - public abstract String getTabTitle(); - - /** - * Returns the title of this room to use. The title - * will be used in the title bar of the ChatRoom. - * - * @return - the title of this ChatRoom. - */ - public abstract String getRoomTitle(); - - /** - * Returns the Message.Type specific to this - * chat room. - * GroupChat is Message.Type.groupchat - * Normal Chat is Message.TYPE.NORMAL - * - * @return the ChatRooms Message.TYPE - */ - public abstract Message.Type getChatType(); - - - /** - * Returns whether or not this ChatRoom is active. Note: carrying - * a conversation rather than being disabled, as it would be - * transcript mode. - * - * @return true if the chat room is active. - */ - public abstract boolean isActive(); - - - /** - * Returns the notification label. The notification label notifies the - * user of chat room activity, such as the date of the last message - * and typing notifications. - * - * @return the notification label. - */ - public JLabel getNotificationLabel() { - return notificationLabel; - } - - /** - * Adds a packetID to the packedIDList. The packetIDLlist - * keeps track of all messages coming into the chatroom. - * - * @param packetID the packetID to add. - */ - public void addPacketID(String packetID) { - packetIDList.add(packetID); - } - - /** - * Checks if the packetID has already been used. - * - * @param packetID the packetID to check for. - * @return true if the packetID already exists. - */ - public boolean packetIDExists(String packetID) { - return packetIDList.contains(packetID); - } - - /** - * Returns this instance of the chatroom. - * - * @return the current ChatRoom instance. - */ - public ChatRoom getChatRoom() { - return this; - } - - /** - * Returns the toolbar used on top of the chat room. - * - * @return the toolbar used on top of this chat room. - */ - public ChatToolBar getToolBar() { - return toolbar; - } - - protected void addToolbar() { - add(toolbar, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); - } - - - public void insertUpdate(DocumentEvent e) { - // Meant to be overriden - checkForText(e); - } - - - /** - * Override to save transcript in preferred room style. - */ - public void saveTranscript() { - getTranscriptWindow().saveTranscript(getTabTitle() + ".html", getTranscripts(), null); - } - - - /** - * Used for the top toolbar. - */ - public class ChatToolBar extends JPanel { - private static final long serialVersionUID = 5926527530611601841L; - private JPanel buttonPanel; - - - /** - * Default Constructor. - */ - public ChatToolBar() { - buttonPanel = new JPanel(); - buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 2, 0)); - - // Set Layout - setLayout(new GridBagLayout()); - - buttonPanel.setOpaque(false); - add(buttonPanel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); - setOpaque(false); - } - - /** - * Adds a new ChatRoomButton the CommandBar. - * - * @param button the button. - */ - public void addChatRoomButton(ChatRoomButton button) { - buttonPanel.add(button); - - // Make all JButtons the same size - Component[] comps = buttonPanel.getComponents(); - final int no = comps != null ? comps.length : 0; - - final List buttons = new ArrayList<>(); - for (int i = 0; i < no; i++) { - try { - Component component = comps[i]; - if (component instanceof JButton) { - buttons.add(component); - } - } - catch (NullPointerException e) { - Log.error(e); - } - } - - GraphicUtils.makeSameSize(buttons.toArray(new JComponent[buttons.size()])); - } - - /** - * Removes the ChatRoomButton from the CommandBar. - * - * @param button the button. - */ - public void removeChatRoomButton(ChatRoomButton button) { - buttonPanel.remove(button); - } - } - - /** - * Returns the number of unread messages in this ChatRoom. - * - * @return the number of unread messages. - */ - public int getUnreadMessageCount() { - return unreadMessageCount; - } - - /** - * Increases the number of unread messages by 1. - */ - public void increaseUnreadMessageCount() { - unreadMessageCount++; - } - - /** - * Resets the number of unread messages. - */ - public void clearUnreadMessageCount() { - unreadMessageCount = 0; - } - - /** - * Returns the bottom panel used in the ChatRoom. - * - * @return the bottomPane; - */ - public JPanel getBottomPanel() { - return bottomPanel; - } - - /** - * Returns the Container which holds the ChatWindow. - * - * @return the Container. - */ - public JPanel getChatWindowPanel() { - return chatWindowPanel; - } - - /** - * Adds a new FileDropListener to allow for Drag and Drop notifications - * of objects onto the ChatWindow. - * - * @param listener the listener. - */ - public void addFileDropListener(FileDropListener listener) { - fileDropListeners.add(listener); - } - - /** - * Remove the FileDropListener from ChatRoom. - * - * @param listener the listener. - */ - public void removeFileDropListener(FileDropListener listener) { - fileDropListeners.remove(listener); - } - - /** - * Notify all users that a collection of files has been dropped onto the ChatRoom. - * - * @param files the files dropped. - */ - public void fireFileDropListeners(Collection files) { - for (FileDropListener fileDropListener : fileDropListeners) { - fileDropListener.filesDropped(files, this); - } - } - - /** - * Returns the panel which contains the toolbar items, such as spell checker. - * - * @return the panel which contains the lower toolbar items. - */ - public JPanel getEditorBar() { - return editorBarLeft; - } - - /** - * Returns the panel next to the editor bar
        - * for use with system buttons, like room controlling or toggle stay-on-top - * - * @return - */ - public JPanel getRoomControllerBar() { - return editorBarRight; - } - - /** - * Adds a ChatRoomClosingListener to this ChatRoom. A ChatRoomClosingListener - * is notified whenever this room is closing. - * - * @param listener the ChatRoomClosingListener. - */ - public void addClosingListener(ChatRoomClosingListener listener) { - closingListeners.add(listener); - } - - /** - * Removes a ChatRoomClosingListener from this ChatRoom. - * - * @param listener the ChatRoomClosingListener. - */ - public void removeClosingListener(ChatRoomClosingListener listener) { - closingListeners.remove(listener); - } - - /** - * Notifies all ChatRoomClosingListener that this ChatRoom is closing. - */ - private void fireClosingListeners() { - for (ChatRoomClosingListener chatRoomClosingListener : closingListeners) { - chatRoomClosingListener.closing(); - removeClosingListener(chatRoomClosingListener); - } - } - - /** - * Returns the ScrollPane that contains the TranscriptWindow. - * - * @return the TranscriptWindow ScrollPane. - */ - public JScrollPane getScrollPaneForTranscriptWindow() { - return textScroller; - } - - /** - * Return the "Send" button. - * - * @return the send button. - */ - public JButton getSendButton() { - return chatAreaButton.getButton(); - } - - /** - * Returns the VerticalSplitPane used in this ChatRoom. - * - * @return the VerticalSplitPane. - */ - public JSplitPane getVerticalSlipPane() { - return verticalSplit; - } - - - public void focusGained(FocusEvent focusEvent) { - validate(); - invalidate(); - repaint(); - } - - public void poppingUp(Object component, JPopupMenu popup) { - Action saveAction = new AbstractAction() { - private static final long serialVersionUID = -3582301239832606653L; - - public void actionPerformed(ActionEvent actionEvent) { - saveTranscript(); - } - }; - saveAction.putValue(Action.NAME, Res.getString("action.save")); - saveAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SAVE_AS_16x16)); - - - popup.add(saveAction); - } - - public void poppingDown(JPopupMenu popup) { - - } - - public boolean handleDefaultAction(MouseEvent e) { - return false; - } - - - public void focusLost(FocusEvent focusEvent) { - } - - - /** - * Implementation of this method should return the last time this chat room - * sent or recieved a message. - * - * @return the last time (in system milliseconds) that the room last recieved a message. - */ - public abstract long getLastActivity(); - - - public void connectionClosed() { - } - - public void connectionClosedOnError(Exception e) { - } - - public void reconnectingIn(int seconds) { - } - - public void reconnectionSuccessful() { - } - - public void reconnectionFailed(Exception e) { - } - - - public void updateStatus(boolean active) - { - _alwaysOnTopItem.setSelected(active); - } - - public void registeredToFrame(ChatFrame chatframe) - { - this._chatFrame = chatframe; - _chatFrame.addWindowToFronListener(this); - } - - protected JPanel getEditorWrapperBar() { - return editorWrapperBar; - } - - protected JPanel getEditorBarRight() { - return editorBarRight; - } - - protected JPanel getEditorBarLeft() { - return editorBarLeft; - } - - protected JScrollPane getTextScroller() { - return textScroller; - } - - protected Insets getChatPanelInsets() { - return new Insets(0, 5, 0, 5); - } - - protected Insets getChatAreaInsets() { - return new Insets(0, 5, 5, 5); - } - - protected Insets getEditorWrapperInsets() { - return new Insets(0, 5, 0, 5); - } - - public void addChatRoomComponent(JComponent component) { - editorBarLeft.add(component); - } - - public void addChatRoomButton(ChatRoomButton button) { - addChatRoomButton(button, false); - } - - public void addChatRoomButton(ChatRoomButton button, boolean forceRepaint) { - toolbar.addChatRoomButton(button); - if (forceRepaint) { - toolbar.invalidate(); - toolbar.repaint(); - } - } - - public void showToolbar() { - toolbar.setVisible(true); - } - - public void hideToolbar() { - toolbar.setVisible(false); - } - - public void addEditorComponent(JComponent component) { - editorBarLeft.add(component); - } - - public void removeEditorComponent(JComponent component) { - editorBarLeft.remove(component); - } - - public void addControllerButton(RolloverButton button) { - editorBarRight.add(button, 0); - } -} - - diff --git a/src/java/org/jivesoftware/spark/ui/ChatRoomListener.java b/src/java/org/jivesoftware/spark/ui/ChatRoomListener.java deleted file mode 100644 index 3ceaa8d35..000000000 --- a/src/java/org/jivesoftware/spark/ui/ChatRoomListener.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -/** - * The ChatRoomListener interface is one of the interfaces extension - * writers use to add functionality to Spark. - *

        - * In general, you implement this interface in order to listen - * for ChatRoom activity, such as a ChatRoom opening, closing, or being - * activated. - */ -public interface ChatRoomListener { - - /** - * Invoked by ChatRooms when a new ChatRoom has been opened. - * - * @param room - the ChatRoom that has been opened. - * @see ChatContainer - */ - void chatRoomOpened(ChatRoom room); - - /** - * Invoked by ChatRooms when a ChatRoom has been left, but not - * closed. - * - * @param room - the ChatRoom that has been left. - * @see ChatContainer - */ - void chatRoomLeft(ChatRoom room); - - /** - * Invoke by ChatRooms when a ChatRoom has been closed. - * - * @param room - the ChatRoom that has been closed. - */ - void chatRoomClosed(ChatRoom room); - - /** - * Invoked by ChatRooms when a ChatRoom has been activated. - * i.e. it has already been opened, but was deactivated when the user - * selected a new chat room, but now has selected the old one. - * - * @param room - the ChatRoom that has been selected. - */ - void chatRoomActivated(ChatRoom room); - - /** - * Invoked by ChatRooms when a person has joined a chat room. - * - * @param room - the chat room the person has joined - * @param userid - the userid of the person who has joined - */ - void userHasJoined(ChatRoom room, String userid); - - /** - * Invoked by ChatRooms when a person has left a chat room. - * - * @param room - the chat room the person has left - * @param userid - the userid of the person who has left - */ - void userHasLeft(ChatRoom room, String userid); - - -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/spark/ui/ChatRoomListenerAdapter.java b/src/java/org/jivesoftware/spark/ui/ChatRoomListenerAdapter.java deleted file mode 100644 index df68713ea..000000000 --- a/src/java/org/jivesoftware/spark/ui/ChatRoomListenerAdapter.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -/** - * An abstract adapter class for receiving Chat Room Events. - * The methods in this class are empty. This class exists as - * convenience for creating listener objects. - *

        - * Chat Room events let you track when a room is opened, closed, joined, left and activated. - *

        - * Extend this class to methods for the events of interest. (If you implement the - * ChatRoomListener interface, you have to define all of - * the methods in it. This abstract class defines null methods for them - * all, so you can only have to define methods for events you care about.) - *

        - * Create a listener object using the extended class and then register it with - * the ChatManager's addChatRoomListener method. - * - * @author Derek DeMoro - * @see ChatRoomListener - */ -public abstract class ChatRoomListenerAdapter implements ChatRoomListener { - - public void chatRoomOpened(ChatRoom room) { - - } - - public void chatRoomLeft(ChatRoom room) { - - } - - public void chatRoomClosed(ChatRoom room) { - - } - - public void chatRoomActivated(ChatRoom room) { - - } - - public void userHasJoined(ChatRoom room, String userid) { - - } - - public void userHasLeft(ChatRoom room, String userid) { - - } -} diff --git a/src/java/org/jivesoftware/spark/ui/ChatRoomTransferHandler.java b/src/java/org/jivesoftware/spark/ui/ChatRoomTransferHandler.java deleted file mode 100644 index 8f7153df0..000000000 --- a/src/java/org/jivesoftware/spark/ui/ChatRoomTransferHandler.java +++ /dev/null @@ -1,138 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.Transferable; -import java.awt.datatransfer.UnsupportedFlavorException; -import java.io.File; -import java.io.IOException; -import java.util.Collection; - -import javax.swing.JComponent; -import javax.swing.TransferHandler; - -import org.jivesoftware.spark.util.log.Log; - -/** - * Handler for drag and dropping of files unto a ChatWindow. - */ -public class ChatRoomTransferHandler extends TransferHandler { - private static final long serialVersionUID = 6941570710627039031L; - private ChatRoom chatRoom; - - private static final DataFlavor flavors[] = {DataFlavor.javaFileListFlavor, DataFlavor.stringFlavor}; - - public ChatRoomTransferHandler(ChatRoom chatRoom) { - this.chatRoom = chatRoom; - } - - public int getSourceActions(JComponent c) { - return TransferHandler.COPY_OR_MOVE; - } - - - public boolean canImport(JComponent comp, DataFlavor flavor[]) { - for (int i = 0, n = flavor.length; i < n; i++) { - for (int j = 0, m = flavors.length; j < m; j++) { - if (flavor[i].equals(flavors[j])) { - return true; - } - } - } - return false; - } - - protected void exportDone(JComponent c, Transferable data, int action) { - - } - - - public Transferable createTransferable(JComponent comp) { - if (comp instanceof TranscriptWindow) { - return new TranscriptWindowTransferable((TranscriptWindow)comp); - } - - return null; - } - - public boolean importData(JComponent comp, Transferable t) { - if (t.isDataFlavorSupported(flavors[0])) { - try { - Object o = t.getTransferData(flavors[0]); - if (o instanceof Collection) { - Collection files = (Collection)o; - - // Otherwise fire files dropped event. - chatRoom.fireFileDropListeners(files); - return true; - } - } - catch (UnsupportedFlavorException e) { - Log.error(e); - } - catch (IOException e) { - Log.error(e); - } - } - else if (t.isDataFlavorSupported(flavors[1])) { - try { - Object o = t.getTransferData(flavors[1]); - if (o instanceof String) { - // Otherwise fire files dropped event. - chatRoom.getChatInputEditor().insert((String)o); - return true; - } - } - catch (Exception e) { - Log.error(e); - } - - } - return false; - } - - public class TranscriptWindowTransferable implements Transferable { - - private TranscriptWindow item; - - public TranscriptWindowTransferable(TranscriptWindow item) { - this.item = item; - } - - // Returns supported flavors - public DataFlavor[] getTransferDataFlavors() { - return new DataFlavor[]{DataFlavor.stringFlavor}; - } - - // Returns true if flavor is supported - public boolean isDataFlavorSupported(DataFlavor flavor) { - return DataFlavor.stringFlavor.equals(flavor); - } - - // Returns Selected Text - public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { - if (!DataFlavor.stringFlavor.equals(flavor)) { - throw new UnsupportedFlavorException(flavor); - } - return item.getSelectedText(); - } - } -} diff --git a/src/java/org/jivesoftware/spark/ui/ContactGroup.java b/src/java/org/jivesoftware/spark/ui/ContactGroup.java deleted file mode 100644 index 46c429569..000000000 --- a/src/java/org/jivesoftware/spark/ui/ContactGroup.java +++ /dev/null @@ -1,1059 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.spark.PresenceManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.Workspace; -import org.jivesoftware.spark.component.VerticalFlowLayout; -import org.jivesoftware.spark.component.panes.CollapsiblePane; -import org.jivesoftware.spark.component.renderer.JContactItemRenderer; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.SwingTimerTask; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.UIComponentRegistry; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.EventQueue; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionAdapter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import javax.swing.DefaultListModel; -import javax.swing.JList; -import javax.swing.JPanel; - -/** - * Container representing a RosterGroup within the Contact List. - */ -public class ContactGroup extends CollapsiblePane implements MouseListener { - private static final long serialVersionUID = 6578057848913010799L; - private List contactItems = new ArrayList<>(); - private List contactGroups = new ArrayList<>(); - private List listeners = new ArrayList<>(); - private List offlineContacts = new ArrayList<>(); - - private String groupName; - private DefaultListModel model; - private JList contactItemList; - private boolean sharedGroup; - private JPanel listPanel; - - // Used to display no contacts in list. - private final ContactItem noContacts = UIComponentRegistry.createContactItem( - Res.getString("group.empty"), null, null); - - private final ListMotionListener motionListener = new ListMotionListener(); - - private boolean canShowPopup; - - private boolean mouseDragged = false; - - private LocalPreferences preferences; - - private ContactList contactList = Workspace.getInstance().getContactList(); - - private DisplayWindowTask timerTask = null; - - /** - * Create a new ContactGroup. - * - * @param groupName the name of the new ContactGroup. - */ - public ContactGroup(String groupName) { - // Initialize Model and UI - model = new DefaultListModel(); - contactItemList = new JList(model); - - preferences = SettingsManager.getLocalPreferences(); - - setTitle(getGroupTitle(groupName)); - - // Use JPanel Renderer - contactItemList.setCellRenderer(new JContactItemRenderer()); - - this.groupName = groupName; - - listPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); - listPanel.add(contactItemList, listPanel); - this.setContentPane(listPanel); - - if (!isOfflineGroup()) { - contactItemList.setDragEnabled(true); - contactItemList.setTransferHandler(new ContactGroupTransferHandler()); - } - - // Allow for mouse events to take place on the title bar - getTitlePane().addMouseListener(new MouseAdapter() { - public void mousePressed(MouseEvent e) { - checkPopup(e); - - } - - public void mouseReleased(MouseEvent e) { - checkPopup(e); - } - - public void mouseClicked(MouseEvent e) { - if(e.getButton() == MouseEvent.BUTTON1) - { - contactList = Workspace.getInstance().getContactList(); - contactList.saveState(); - } - } - - public void checkPopup(MouseEvent e) { - if (e.isPopupTrigger()) - { - e.consume(); - fireContactGroupPopupEvent(e); - } - } - }); - - // Items should have selection listener - contactItemList.addMouseListener(this); - - contactItemList.addKeyListener(new KeyListener() { - public void keyTyped(KeyEvent keyEvent) { - - } - - public void keyPressed(KeyEvent keyEvent) { - if (keyEvent.getKeyChar() == KeyEvent.VK_ENTER) { - ContactItem item = (ContactItem)contactItemList.getSelectedValue(); - fireContactItemDoubleClicked(item); - } - - ContactList.activeKeyEvent = keyEvent; - } - - public void keyReleased(KeyEvent keyEvent) { - ContactList.activeKeyEvent = null; - } - }); - - noContacts.getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, 11)); - noContacts.getNicknameLabel().setForeground(Color.GRAY); - model.addElement(noContacts); - - // Add Popup Window - addPopupWindow(); - - - } - - /** - * Adds a new offline contact. - * - * @param alias the alias of the offline contact. - * @param nickname the nickname of the offline contact. - * @param jid the jid of the offline contact. - * @param status the current status of the offline contact. - */ - public void addOfflineContactItem(final String alias, final String nickname, final String jid, final String status) { - if(EventQueue.isDispatchThread()) { - // Build new ContactItem - final ContactItem offlineItem = UIComponentRegistry.createContactItem(alias, nickname, jid); - offlineItem.setGroupName(getGroupName()); - - final Presence offlinePresence = PresenceManager.getPresence(jid); - offlineItem.setPresence(offlinePresence); - - // set offline icon - offlineItem.setIcon(PresenceManager.getIconFromPresence(offlinePresence)); - - // Set status if applicable. - if (ModelUtil.hasLength(status)) { - offlineItem.setStatusText(status); - } - // Add to offline contacts. - offlineContacts.add(offlineItem); - - insertOfflineContactItem(offlineItem); - } - else { - try { - // invokeAndWait, because the contacts must be added before they can moved to offline group - EventQueue.invokeAndWait( () -> { - // Build new ContactItem - final ContactItem offlineItem = UIComponentRegistry.createContactItem(alias, nickname, jid); - offlineItem.setGroupName(getGroupName()); - - final Presence offlinePresence = PresenceManager.getPresence(jid); - offlineItem.setPresence(offlinePresence); - - // set offline icon - offlineItem.setIcon(PresenceManager.getIconFromPresence(offlinePresence)); - - // Set status if applicable. - if (ModelUtil.hasLength(status)) { - offlineItem.setStatusText(status); - } - // Add to offline contacts. - offlineContacts.add(offlineItem); - - insertOfflineContactItem(offlineItem); - } ); - } - catch(Exception ex) { - Log.error(ex); - } - } - } - - /** - * Inserts a new offline ContactItem into the ui model. - * - * @param offlineItem the ContactItem to add. - */ - public void insertOfflineContactItem(ContactItem offlineItem) { - if (model.contains(offlineItem)) { - return; - } - - if (!preferences.isOfflineGroupVisible()) { - Collections.sort(offlineContacts, itemComparator); - int index = offlineContacts.indexOf(offlineItem); - - int totalListSize = contactItems.size(); - int newPos = totalListSize + index; - - if (newPos > model.size()) { - newPos = model.size(); - } - - model.insertElementAt(offlineItem, newPos); - - if (model.contains(noContacts)) { - model.removeElement(noContacts); - } - } - } - - /** - * Removes an offline ContactItem from the Offline contact - * model and ui. - * - * @param item the offline contact item to remove. - */ - public void removeOfflineContactItem(ContactItem item) { - offlineContacts.remove(item); - //removeContactItem(item); - } - - /** - * Removes an offline ContactItem from the offline contact model and ui. - * - * @param jid the offline contact item to remove. - */ - public void removeOfflineContactItem(String jid) { - final List items = new ArrayList<>( offlineContacts ); - for (ContactItem item : items) { - if (item.getJID().equals(jid)) { - removeOfflineContactItem(item); - } - } - } - - /** - * Toggles the visibility of Offline Contacts. - * - * @param show true if offline contacts should be shown, otherwise false. - */ - public void toggleOfflineVisibility(boolean show) { - final List items = new ArrayList<>( offlineContacts ); - for (ContactItem item : items) { - if (show) { - insertOfflineContactItem(item); - } - else { - model.removeElement(item); - } - } - if (model.getSize() == 0) { - model.addElement(noContacts); - } - } - - - /** - * Adds a ContactItem to the ContactGroup. - * - * @param item the ContactItem. - */ - public void addContactItem(ContactItem item) { - // Remove from offline group if it exists - removeOfflineContactItem(item.getJID()); - - if (model.contains(noContacts)) { - model.remove(0); - } - - if (Res.getString("group.offline").equals(groupName)) { - setOfflineGroupNameFont(item); - } - - item.setGroupName(getGroupName()); - contactItems.add(item); - - List tempItems = getContactItems(); - - - Collections.sort(tempItems, itemComparator); - - - int index = tempItems.indexOf(item); - - - Object[] objs = contactItemList.getSelectedValues(); - - model.insertElementAt(item, index); - - int[] intList = new int[objs.length]; - for (int i = 0; i < objs.length; i++) { - ContactItem contact = (ContactItem)objs[i]; - intList[i] = model.indexOf(contact); - } - - if (intList.length > 0) { - contactItemList.setSelectedIndices(intList); - } - - fireContactItemAdded(item); - } - - protected void setOfflineGroupNameFont(ContactItem item) { - item.getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, item.fontSize)); - item.getNicknameLabel().setForeground(Color.GRAY); - } - - /** - * Call whenever the UI needs to be updated. - */ - public void fireContactGroupUpdated() { - contactItemList.validate(); - contactItemList.repaint(); - updateTitle(); - } - - /** - * Adds a sub group to this Contact group. - * - * @param contactGroup - * that should be the new subgroup - */ - public void addContactGroup(ContactGroup contactGroup) { - final JPanel panel = new JPanel(new GridBagLayout()); - panel.add(contactGroup, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2, 15, 0, 0), 0, 0)); - panel.setBackground(Color.white); - contactGroup.setSubPane(true); - - // contactGroup.setStyle(CollapsiblePane.TREE_STYLE); - contactGroups.add(contactGroup); - Collections.sort(contactGroups, ContactList.GROUP_COMPARATOR); - listPanel.add(panel, contactGroups.indexOf(contactGroup)); - } - - /** - * Removes a child ContactGroup. - * - * @param contactGroup the contact group to remove. - */ - public void removeContactGroup(ContactGroup contactGroup) { - Component[] comps = listPanel.getComponents(); - for (Component comp : comps) { - if (comp instanceof JPanel) { - JPanel panel = (JPanel) comp; - ContactGroup group = (ContactGroup) panel.getComponent(0); - if (group == contactGroup) { - listPanel.remove(panel); - break; - } - } - } - - - contactGroups.remove(contactGroup); - } - - public void setPanelBackground(Color color) { - Component[] comps = listPanel.getComponents(); - for (Component comp : comps) { - if (comp instanceof JPanel) { - JPanel panel = (JPanel) comp; - panel.setBackground(color); - } - } - - } - - /** - * Returns a ContactGroup based on it's name. - * - * @param groupName the name of the group. - * @return the ContactGroup. - */ - public ContactGroup getContactGroup(String groupName) { - for (ContactGroup group : new ArrayList<>( contactGroups )) { - if (group.getGroupName().equals(groupName)) { - return group; - } - } - - return null; - } - - /** - * Removes a ContactItem. - * - * @param item the ContactItem to remove. - */ - public void removeContactItem(ContactItem item) { - contactItems.remove(item); - if (contactItems.isEmpty()) { - removeContactGroup(this); - } - - model.removeElement(item); - updateTitle(); - - fireContactItemRemoved(item); - } - - /** - * Returns a ContactItem by the displayed name the user has been assigned. - * - * @param displayName the displayed name of the user. - * @return the ContactItem. - */ - public ContactItem getContactItemByDisplayName(String displayName) { - for (ContactItem item : new ArrayList<>( contactItems )) { - if (item.getDisplayName().equals(displayName)) { - return item; - } - } - return null; - } - - /** - * Returns a ContactItem from offlineContacts by the displayed name the user has been assigned. - * - * @param displayName the displayed name of the user. - * @return the ContactItem. - */ - public ContactItem getOfflineContactItemByDisplayName(String displayName) { - for (ContactItem item : new ArrayList<>( offlineContacts )) { - if (item.getDisplayName().equals(displayName)) { - return item; - } - } - return null; - } - - /** - * Returns a ContactItem by the displayed name the user has been assigned. - * - * @param displayName the displayed name of the user. - * @param searchInOffline should we search ContactItem in offline contacts - * @return the ContactItem. - */ - public ContactItem getContactItemByDisplayName(String displayName, boolean searchInOffline) { - if (searchInOffline) { - ContactItem item = getContactItemByDisplayName(displayName); - if (item == null) { - item = getOfflineContactItemByDisplayName(displayName); - } - return item; - } - return getContactItemByDisplayName(displayName); - } - - /** - * Returns a ContactItem by the users bare bareJID. - * - * @param bareJID the bareJID of the user. - * @return the ContactItem. - */ - public ContactItem getContactItemByJID(String bareJID) { - for (ContactItem item : new ArrayList<>( contactItems )) { - if (item != null && item.getJID().equals(bareJID)) { - return item; - } - } - return null; - } - - /** - * Returns a ContactItem from offlineContacts by the users bare bareJID. - * - * @param bareJID the bareJID of the user. - * @return the ContactItem. - */ - public ContactItem getOfflineContactItemByJID(String bareJID) { - for (ContactItem item : new ArrayList<>( offlineContacts )) { - if (item.getJID().equals(bareJID)) { - return item; - } - } - return null; - } - - /** - * Returns a ContactItem by the users bare bareJID. - * - * @param bareJID the bareJID of the user. - * @param searchInOffline should we search ContactItem in offline contacts - * @return the ContactItem. - */ - public ContactItem getContactItemByJID(String bareJID, boolean searchInOffline) { - if (searchInOffline) { - ContactItem item = getContactItemByJID(bareJID); - if (item == null) { - item = getOfflineContactItemByJID(bareJID); - } - return item; - } - return getContactItemByJID(bareJID); - } - - /** - * Returns all ContactItems in the ContactGroup. - * - * @return all ContactItems. - */ - public List getContactItems() { - final List list = new ArrayList<>( contactItems ); - Collections.sort(list, itemComparator); - return list; - } - - /** - * Returns the name of the ContactGroup. - * - * @return the name of the ContactGroup. - */ - public String getGroupName() { - return groupName; - } - - - public void mouseClicked(MouseEvent e) { - - Object o = contactItemList.getSelectedValue(); - if (!(o instanceof ContactItem)) { - return; - } - - // Iterator through rest - ContactItem item = (ContactItem)o; - - if (e.getClickCount() == 2) { - fireContactItemDoubleClicked(item); - } - else if (e.getClickCount() == 1) { - fireContactItemClicked(item); - } - } - - public void mouseEntered(MouseEvent e) { - int loc = contactItemList.locationToIndex(e.getPoint()); - - Object o = model.getElementAt(loc); - if (!(o instanceof ContactItem)) { - return; - } - - contactItemList.setCursor(GraphicUtils.HAND_CURSOR); - } - - public void mouseExited(MouseEvent e) { - Object o; - try { - int loc = contactItemList.locationToIndex(e.getPoint()); - if (loc == -1) { - return; - } - - o = model.getElementAt(loc); - if (!(o instanceof ContactItem)) { - UIComponentRegistry.getContactInfoWindow().dispose(); - return; - } - } - catch (Exception e1) { - Log.error(e1); - return; - } - - contactItemList.setCursor(GraphicUtils.DEFAULT_CURSOR); - - } - - public void mousePressed(MouseEvent e) { - checkPopup(e); - } - - public void mouseReleased(MouseEvent e) { - checkPopup(e); - } - - private void checkPopup(MouseEvent e) { - if (e.isPopupTrigger()) { - // Otherwise, handle single selection - int index = contactItemList.locationToIndex(e.getPoint()); - if (index != -1) { - int[] indexes = contactItemList.getSelectedIndices(); - boolean selected = false; - for (int o : indexes) { - if (index == o) { - selected = true; - } - } - - if (!selected) { - contactItemList.setSelectedIndex(index); - fireContactItemClicked((ContactItem)contactItemList.getSelectedValue()); - } - } - - - final Collection selectedItems = SparkManager.getChatManager().getSelectedContactItems(); - if (selectedItems.size() > 1) { - firePopupEvent(e, selectedItems); - } - else if (selectedItems.size() == 1) { - final ContactItem contactItem = selectedItems.iterator().next(); - firePopupEvent(e, contactItem); - } - } - } - - /** - * Add a ContactGroupListener. - * - * @param listener the ContactGroupListener. - */ - public void addContactGroupListener(ContactGroupListener listener) { - listeners.add(listener); - } - - /** - * Removes a ContactGroupListener. - * - * @param listener the ContactGroupListener. - */ - public void removeContactGroupListener(ContactGroupListener listener) { - listeners.remove(listener); - } - - private void fireContactItemClicked(ContactItem item) { - for (ContactGroupListener contactGroupListener : new ArrayList<>( listeners )) { - contactGroupListener.contactItemClicked(item); - } - } - - private void fireContactItemDoubleClicked(ContactItem item) { - for (ContactGroupListener contactGroupListener : new ArrayList<>( listeners )) { - contactGroupListener.contactItemDoubleClicked(item); - } - } - - - private void firePopupEvent(MouseEvent e, ContactItem item) { - for (ContactGroupListener contactGroupListener : new ArrayList<>( listeners )) { - contactGroupListener.showPopup(e, item); - } - } - - private void firePopupEvent(MouseEvent e, Collection items) { - for (ContactGroupListener contactGroupListener : new ArrayList<>( listeners )) { - contactGroupListener.showPopup(e, items); - } - } - - private void fireContactGroupPopupEvent(MouseEvent e) { - for (ContactGroupListener contactGroupListener : new ArrayList<>( listeners )) { - contactGroupListener.contactGroupPopup(e, this); - } - } - - private void fireContactItemAdded(ContactItem item) { - for (ContactGroupListener contactGroupListener : new ArrayList<>( listeners )) { - contactGroupListener.contactItemAdded(item); - } - } - - private void fireContactItemRemoved(ContactItem item) { - for (ContactGroupListener contactGroupListener : new ArrayList<>( listeners )) { - contactGroupListener.contactItemRemoved(item); - } - } - - private void updateTitle() { - if (Res.getString("group.offline").equals(groupName)) { - setTitle(Res.getString("group.offline")); - return; - } - - int count = 0; - List list = new ArrayList<>( getContactItems() ); - int size = list.size(); - for (int i = 0; i < size; i++) { - ContactItem it = list.get(i); - if (it.isAvailable()) { - count++; - } - } - - setTitle(getGroupTitle(groupName) + " (" + count + " " + Res.getString("online") + ")"); - - - if (model.getSize() == 0) { - model.addElement(noContacts); - } - } - - /** - * Returns the containing JList of the ContactGroup. - * - * @return the JList. - */ - public JList getList() { - return contactItemList; - } - - /** - * Clears all selections within this group. - */ - public void clearSelection() { - contactItemList.clearSelection(); - } - - public void removeAllContacts() { - // Remove all users from online group. - for (ContactItem item : new ArrayList<>( getContactItems() )) { - removeContactItem(item); - } - - // Remove all users from offline group. - for (ContactItem item : getOfflineContacts()) { - removeOfflineContactItem(item); - } - } - - /** - * Returns true if the ContactGroup contains available users. - * - * @return true if the ContactGroup contains available users. - */ - public boolean hasAvailableContacts() { - for (ContactGroup group : contactGroups) { - if (group.hasAvailableContacts()) { - return true; - } - } - - for (ContactItem item : getContactItems()) { - if (item.getPresence() != null) { - return true; - } - } - return false; - } - - public Collection getOfflineContacts() { - return new ArrayList<>( offlineContacts ); - } - - /** - * Sorts ContactItems. - */ - final protected Comparator itemComparator = ( item1, item2 ) -> item1.getDisplayName().toLowerCase().compareTo(item2.getDisplayName().toLowerCase()); - - /** - * Returns true if this ContactGroup is the Offline Group. - * - * @return true if OfflineGroup. - */ - public boolean isOfflineGroup() { - return Res.getString("group.offline").equals(getGroupName()); - } - - /** - * Returns true if this ContactGroup is the Unfiled Group. - * - * @return true if UnfiledGroup. - */ - public boolean isUnfiledGroup() { - //TODO: Don't identify the unfiled group by name, because the user - //could have a custom group of that name. - - return Res.getString("unfiled").equals(getGroupName()); - } - - public String toString() { - return getGroupName(); - } - - /** - * Returns true if ContactGroup is a Shared Group. - * - * @return true if Shared Group. - */ - public boolean isSharedGroup() { - return sharedGroup; - } - - /** - * Set to true if this ContactGroup is a shared Group. - * - * @param sharedGroup true if shared group. - */ - protected void setSharedGroup(boolean sharedGroup) { - this.sharedGroup = sharedGroup; - if (sharedGroup) { - setToolTipText(Res.getString("message.is.shared.group", getGroupName())); - } - } - - /** - * Returns all Selected Contacts within the ContactGroup. - * - * @return all selected ContactItems. - */ - public List getSelectedContacts() { - final List items = new ArrayList<>(); - Object[] selections = contactItemList.getSelectedValues(); - final int no = selections != null ? selections.length : 0; - for (int i = 0; i < no; i++) { - try { - ContactItem item = (ContactItem)selections[i]; - items.add(item); - } - catch (NullPointerException e) { - // TODO: Evaluate if we should do something here. - } - } - return items; - } - - public JPanel getContainerPanel() { - return listPanel; - } - - public Collection getContactGroups() { - return contactGroups; - } - - /** - * Lets make sure that the panel doesn't stretch past the - * scrollpane view pane. - * - * @return the preferred dimension - */ - public Dimension getPreferredSize() { - final Dimension size = super.getPreferredSize(); - size.width = 0; - return size; - } - - /** - * Sets the name of group. - * - * @param groupName the contact group name. - */ - public void setGroupName(String groupName) { - this.groupName = groupName; - } - - /** - * Returns the "pretty" title of the ContactGroup. - * - * @param title the title. - * @return the new title. - */ - public String getGroupTitle(String title) { - int lastIndex = title.lastIndexOf("::"); - if (lastIndex != -1) { - title = title.substring(lastIndex + 2); - } - - return title; - } - - /** - * Returns true if the group is nested. - * - * @param groupName the name of the group. - * @return true if the group is nested. - */ - public boolean isSubGroup(String groupName) { - return groupName.contains( "::" ); - } - - /** - * Returns true if this group is nested. - * - * @return true if nested. - */ - public boolean isSubGroup() { - return isSubGroup(getGroupName()); - } - - /** - * Returns the underlying container for the JList. - * - * @return the underlying container of the JList. - */ - public JPanel getListPanel() { - return listPanel; - } - - /** - * Adds an internal popup listesner. - */ - private void addPopupWindow() { - contactItemList.addMouseListener(new MouseAdapter() { - public void mouseEntered(MouseEvent mouseEvent) { - canShowPopup = true; - timerTask = new DisplayWindowTask(mouseEvent); - TaskEngine.getInstance().schedule(timerTask, 500, 1000); - } - - public void mouseExited(MouseEvent mouseEvent) { - if (timerTask != null) { - TaskEngine.getInstance().cancelScheduledTask(timerTask); - } - canShowPopup = false; - UIComponentRegistry.getContactInfoWindow().dispose(); - } - }); - - - contactItemList.addMouseMotionListener(motionListener); - } - - private class DisplayWindowTask extends SwingTimerTask { - private MouseEvent event; - private boolean newPopupShown = false; - - public DisplayWindowTask(MouseEvent e) { - event = e; - } - - @Override - public void doRun() { - if (canShowPopup) { - if (!newPopupShown && !mouseDragged) { - displayWindow(event); - newPopupShown = true; - } - } - } - - public void setEvent(MouseEvent event) { - this.event = event; - } - - public void setNewPopupShown(boolean popupChanged) { - this.newPopupShown = popupChanged; - } - - public boolean isNewPopupShown() { - return newPopupShown; - } - } - - private class ListMotionListener extends MouseMotionAdapter { - - @Override - public void mouseMoved(MouseEvent e) { - if (!canShowPopup) { - return; - } - - if (e == null) { - return; - } - timerTask.setEvent(e); - if (needToChangePopup(e) && timerTask.isNewPopupShown()) { - UIComponentRegistry.getContactInfoWindow().dispose(); - timerTask.setNewPopupShown(false); - } - mouseDragged = false; - } - - @Override - public void mouseDragged(MouseEvent e) { - if(timerTask.isNewPopupShown()) { - UIComponentRegistry.getContactInfoWindow().dispose(); - } - mouseDragged = true; - } - } - - - /** - * Displays the ContactInfoWindow. - * - * @param e the mouseEvent that triggered this event. - */ - private void displayWindow(MouseEvent e) { - if(preferences.areVCardsVisible()) { - UIComponentRegistry.getContactInfoWindow().display(this, e); - } - } - - private boolean needToChangePopup(MouseEvent e) { - ContactInfoWindow contact = UIComponentRegistry.getContactInfoWindow(); - int loc = getList().locationToIndex(e.getPoint()); - ContactItem item = (ContactItem)getList().getModel().getElementAt(loc); - return item == null || contact == null || contact.getContactItem() == null ? true : !contact.getContactItem().getJID().equals(item.getJID()); - } - - protected DefaultListModel getModel() { - return model; - } - - protected JList getContactItemList() { - return contactItemList; - } -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/spark/ui/ContactItem.java b/src/java/org/jivesoftware/spark/ui/ContactItem.java deleted file mode 100644 index 307eae354..000000000 --- a/src/java/org/jivesoftware/spark/ui/ContactItem.java +++ /dev/null @@ -1,641 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; - -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.UIManager; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.roster.Roster; -import org.jivesoftware.smack.roster.RosterEntry; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.roster.packet.RosterPacket; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.PresenceManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettings; -import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettingsManager; -import org.jivesoftware.sparkimpl.profile.ext.VCardUpdateExtension; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -/** - * Represent a single contact within the ContactList. - */ -public class ContactItem extends JPanel { - - private static final long serialVersionUID = 1514044406550293152L; - private JLabel imageLabel; - private JLabel displayNameLabel; - private JLabel descriptionLabel; - private String nickname; - private String alias; - private final String fullyQualifiedJID; - private JLabel specialImageLabel; - private Icon icon; - - private String status; - private String groupName; - - boolean available; - - private Presence presence; - - private String hash = ""; - - private File contactsDir; - - private JLabel sideIcon; - - int fontSize; - - private int iconSize; - - private boolean avatarsShowing; - - public ContactItem(String alias, String nickname, String fullyQualifiedJID) { - this(alias, nickname, fullyQualifiedJID, true); - } - - /** - * Creates a new instance of a contact. - * - * @param alias the alias of the contact - * @param nickname the nickname of the contact. - * @param fullyQualifiedJID the fully-qualified jid of the contact (ex. derek@jivesoftware.com) - */ - public ContactItem(String alias, String nickname, String fullyQualifiedJID, boolean initUi) { - setLayout(new GridBagLayout()); - - // Set Default Font - final LocalPreferences pref = SettingsManager.getLocalPreferences(); - fontSize = pref.getContactListFontSize(); - iconSize = pref.getContactListIconSize(); - avatarsShowing = pref.areAvatarsVisible(); - - // Set default presence - presence = new Presence(Presence.Type.unavailable); - - contactsDir = new File(SparkManager.getUserDirectory(), "contacts"); - - this.alias = alias; - this.nickname = nickname; - this.fullyQualifiedJID = fullyQualifiedJID; - - if (initUi) { - displayNameLabel = new JLabel(); - descriptionLabel = new JLabel(); - imageLabel = new JLabel(); - specialImageLabel = new JLabel(); - sideIcon = new JLabel(); - if (avatarsShowing) { - sideIcon.setMinimumSize(new Dimension(iconSize, iconSize)); - sideIcon.setMaximumSize(new Dimension(iconSize, iconSize)); - sideIcon.setPreferredSize(new Dimension(iconSize, iconSize)); - } - - displayNameLabel.setHorizontalTextPosition(JLabel.LEFT); - displayNameLabel.setHorizontalAlignment(JLabel.LEFT); - //displayNameLabel.setText(nickname); - - - descriptionLabel.setFont(new Font("Dialog", Font.PLAIN, fontSize)); - descriptionLabel.setForeground((Color)UIManager.get("ContactItemDescription.foreground")); - descriptionLabel.setHorizontalTextPosition(JLabel.LEFT); - descriptionLabel.setHorizontalAlignment(JLabel.LEFT); - - - this.setOpaque(true); - - add(imageLabel, new GridBagConstraints(0, 0, 1, 2, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 15, 0, 0), 0, 0)); - add(displayNameLabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 0, 0), 0, 0)); - add(descriptionLabel, new GridBagConstraints(2, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 2, 0), 0, 0)); - add(specialImageLabel, new GridBagConstraints(3, 0, 1, 2, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 0, 0), 0, 0)); - add(sideIcon, new GridBagConstraints(4, 0, 1, 2, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 0, 0), 0, 0)); - - setDisplayName(); - } - } - - /** - * Returns the name that should be displayed to represent the the contact. - * If an alias has been set, this alias will be returned. If no alias has - * been set, the nickname will be returned. If that hasn't been set either, - * the JID will be returned. - * - * @return a name suitable to be displayed - */ - public String getDisplayName() { - final String displayName; - if (alias != null && !alias.trim().isEmpty()) { - displayName = alias.trim(); - } else if (nickname != null && !nickname.trim().isEmpty()) { - displayName = nickname.trim(); - } else { - displayName = getJID(); - } - - if (displayName != null) { - return displayName; - } else { - return ""; // weird, but happens. - } - } - - /** - * Returns the nickname of the contact. Note that for typical user-interface - * related tasks, you probably should use {@link #getDisplayName()} instead. - * - * @return the contact nickname. - */ - public String getNickname() { - return nickname; - } - - /** - * Sets the nickname of the contact. - * - * @param nickname the contact nickname. - */ - public void setNickname(String nickname) { - this.nickname = nickname; - if (alias == null) { - setDisplayName(); - } - } - - /** - * Returns the alias of the contact. Note that for typical user-interface - * related tasks, you probably should use {@link #getDisplayName()} instead. - * - * @return the contact alias. - */ - public String getAlias() { - return alias; - } - - /** - * Sets the alias of the contact. - * - * @param alias the contact alias. - */ - public void setAlias(String alias) { - this.alias = alias; - setDisplayName(); - } - - /** - * Updates the displayed name for the contact. This method tries to use an - * alias first. If that's not set, the nickname will be used instead. If - * that's not set either, the JID of the user will be used. - */ - protected void setDisplayName() { - final String displayName = getDisplayName(); - - int nickLength = displayName.length(); - - LayoutSettings settings = LayoutSettingsManager.getLayoutSettings(); - int windowWidth = settings.getMainWindowWidth(); - - if (nickLength > windowWidth) { - displayNameLabel.setText(XmppStringUtils.unescapeLocalpart(displayName).substring(0, windowWidth) + "..."); - } else { - displayNameLabel.setText(XmppStringUtils.unescapeLocalpart(displayName)); - } - } - - /** - * Returns the fully qualified JID of the contact. (If available). Otherwise will - * return the bare jid. - * - * @return the fully qualified jid (ex. derek@jivesoftware.com). - */ - public String getJID() { - return fullyQualifiedJID; - } - - /** - * Returns the icon showing the contacts current state or presence. - * - * @return the icon. - */ - public Icon getIcon() { - return icon; - } - - /** - * Sets the current icon to use. - * - * @param icon the current icon to use. - */ - public void setIcon(Icon icon) { - this.icon = icon; - imageLabel.setIcon(icon); - } - - /** - * Returns the contacts current status based on their presence. - * - * @return the contacts current status. - */ - public String getStatus() { - return status; - } - - /** - * Sets the contacts current status. - * - * @param status the contacts current status. - */ - public void setStatus(String status) { - this.status = status; - } - - /** - * Returns the name of the ContactGroup that this contact belongs to. - * - * @return the name of the ContactGroup. - */ - public String getGroupName() { - return groupName; - } - - /** - * Sets the name of the ContactGrouop that this contact belongs to. - * - * @param groupName the name of the ContactGroup. - */ - public void setGroupName(String groupName) { - this.groupName = groupName; - } - - public boolean isAvailable() { - return available; - } - - public void setAvailable(boolean available) { - this.available = available; - } - - /** - * Returns the JLabel showing the users nickname. - * - * @return the nickname label. - */ - public JLabel getNicknameLabel() { - return displayNameLabel; - } - - /** - * Returns the JLabel representing the description. - * - * @return the description label. - */ - public JLabel getDescriptionLabel() { - return descriptionLabel; - } - - /** - * Returns the current presence of the contact. - * - * @return the users current presence. - */ - public Presence getPresence() { - return presence; - } - - /** - * Sets the current presence on this contact item. - * - * @param presence the presence. - */ - public void setPresence(Presence presence) { - - this.presence = presence; - - final VCardUpdateExtension extension = presence.getExtension("x", "vcard-temp:x:update"); - - // Handle vCard update packet. - if (extension != null) { - String hash = extension.getPhotoHash(); - if (hash != null) { - this.hash = hash; - - if (!hashExists(hash)) { - updateAvatar(); - updateAvatarInSideIcon(); - } - } - } - - - updatePresenceIcon(presence); - } - - /** - * Checks to see if the hash already exists. - * - * @param hash the hash. - * @return true if the hash exists, otherwise false. - */ - private boolean hashExists(String hash) { - contactsDir.mkdirs(); - - final File imageFile = new File(contactsDir, hash); - return imageFile.exists(); - } - - /** - * Returns the url of the avatar belonging to this contact. - * - * @return the url of the avatar. - * @throws MalformedURLException thrown if the address is invalid. - */ - public URL getAvatarURL() throws MalformedURLException { - contactsDir.mkdirs(); - - if (ModelUtil.hasLength(hash)) { - final File imageFile = new File(contactsDir, hash); - if (imageFile.exists()) { - return imageFile.toURI().toURL(); - } - } - - return SparkManager.getVCardManager().getAvatarURLIfAvailable(getJID()); - } - - /** - * Persists the avatar locally based on the new hash. - */ - private void updateAvatar() { - SparkManager.getVCardManager().addToQueue(getJID()); - } - - public String toString() { - return displayNameLabel.getText(); - } - - - /** - * Updates the icon of the user based on their presence. - * - * @param presence the users presence. - */ - public void updatePresenceIcon(Presence presence) { - ChatManager chatManager = SparkManager.getChatManager(); - boolean handled = chatManager.fireContactItemPresenceChanged(this, presence); - if (handled) { - return; - } - - String status = presence.getStatus(); - Icon statusIcon = SparkRes.getImageIcon(SparkRes.GREEN_BALL); - boolean isAvailable = false; - if (status == null && presence.isAvailable()) { - Presence.Mode mode = presence.getMode(); - if (mode == Presence.Mode.available) { - status = Res.getString("status.online"); - isAvailable = true; - } - else if (mode == Presence.Mode.away) { - status = Res.getString("status.away"); - statusIcon = SparkRes.getImageIcon(SparkRes.IM_AWAY); - } - else if (mode == Presence.Mode.chat) { - status = Res.getString("status.free.to.chat"); - } - else if (mode == Presence.Mode.dnd) { - status = Res.getString("status.do.not.disturb"); - statusIcon = SparkRes.getImageIcon(SparkRes.IM_AWAY); - } - else if (mode == Presence.Mode.xa) { - status = Res.getString("status.extended.away"); - statusIcon = SparkRes.getImageIcon(SparkRes.IM_AWAY); - } - } - - if (presence.isAvailable() && (presence.getMode() == Presence.Mode.dnd || presence.getMode() == Presence.Mode.away || presence.getMode() == Presence.Mode.xa)) { - statusIcon = SparkRes.getImageIcon(SparkRes.IM_AWAY); - } - else if (presence.isAvailable()) { - isAvailable = true; - } - else if (!presence.isAvailable()) { - getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, fontSize)); - getNicknameLabel().setForeground((Color)UIManager.get("ContactItemOffline.color")); - - RosterEntry entry = Roster.getInstanceFor( SparkManager.getConnection() ).getEntry(getJID()); - if (entry != null && (entry.getType() == RosterPacket.ItemType.none || entry.getType() == RosterPacket.ItemType.from) - && RosterPacket.ItemStatus.SUBSCRIPTION_PENDING == entry.getStatus()) { - // Do not move out of group. - setIcon(SparkRes.getImageIcon(SparkRes.SMALL_QUESTION)); - getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, fontSize)); - setStatusText(Res.getString("status.pending")); - } - else { - //We should keep the offline bullet (not available) instead of putting icon null. - setIcon(SparkRes.getImageIcon(SparkRes.CLEAR_BALL_ICON)); - setFont(new Font("Dialog", Font.PLAIN, fontSize)); - getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, fontSize)); - setAvailable(false); - if (ModelUtil.hasLength(status)) { - setStatusText(status); - } - else { - setStatusText(""); - } - } - - sideIcon.setIcon(null); - setAvailable(false); - return; - } - - Icon sIcon = PresenceManager.getIconFromPresence(presence); - if (sIcon != null) { - setIcon(sIcon); - } - else { - setIcon(statusIcon); - } - if (status != null) { - setStatus(status); - } - - if (PresenceManager.isOnPhone(presence)) { - statusIcon = SparkRes.getImageIcon(SparkRes.ON_PHONE_IMAGE); - setIcon(statusIcon); - } - - // Always change nickname label to black. - getNicknameLabel().setForeground((Color)UIManager.get("ContactItemNickname.foreground")); - - - if (isAvailable) { - getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, fontSize)); - if (Res.getString("status.online").equals(status) || Res.getString("available").equalsIgnoreCase(status)) { - setStatusText(""); - } - else { - setStatusText(status); - } - } - else if (presence.isAvailable()) { - LocalPreferences pref = SettingsManager.getLocalPreferences(); - if(pref.isGrayingOutEnabled()) - { - getNicknameLabel().setFont(new Font("Dialog", Font.ITALIC, fontSize)); - getNicknameLabel().setForeground(Color.gray); - } - else - { - getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, fontSize)); - getNicknameLabel().setForeground(Color.black); - } - if (status != null) { - setStatusText(status); - } - } - - setAvailable(true); - } - - /** - * Sets the status label text based on the users status. - * - * @param status the users status. - */ - public void setStatusText(String status) { - setStatus(status); - - if (ModelUtil.hasLength(status)) { - getDescriptionLabel().setText(" - " + status); - } - else { - getDescriptionLabel().setText(""); - } - } - - /** - * The icon should only be used to display avatars in contact list. if you want to add an icon - * to indicated that this contact is a transport e.g you should use setSpecialIcon() - * - * @param icon the icon to use. - */ - public void setSideIcon(Icon icon) { - sideIcon.setIcon(icon); - } - - - /** - * The icon to use to show extra information about this contact. An example would be to - * represent that this user is from a 3rd party transport. - * - * @param icon the icon to use. - */ - public void setSpecialIcon(Icon icon) - { - specialImageLabel.setIcon(icon); - } - - /** - * Shows that the user is coming online. - */ - public void showUserComingOnline() { - // Change Font - getNicknameLabel().setFont(new Font("Dialog", Font.BOLD, fontSize)); - getNicknameLabel().setForeground(new Color(255, 128, 0)); - } - - /** - * Shows that the user is going offline. - */ - public void showUserGoingOfflineOnline() { - // Change Font - getNicknameLabel().setFont(new Font("Dialog", Font.BOLD, fontSize)); - getNicknameLabel().setForeground(Color.red); - } - - /** - * Update avatar icon. - */ - public void updateAvatarInSideIcon() { - try { - final URL url = getAvatarURL(); - if (url != null) { - if (!avatarsShowing) { - setSideIcon(null); - } else { - ImageIcon icon = new ImageIcon(url); - icon = GraphicUtils.scale(icon, iconSize, iconSize); - setSideIcon(icon); - } - } - } catch (MalformedURLException e) { - Log.error(e); - } - } - - protected JLabel getDisplayNameLabel() { - return displayNameLabel; - } - - protected String getFullyQualifiedJID() { - return fullyQualifiedJID; - } - - protected void setDisplayNameLabel(JLabel displayNameLabel) { - this.displayNameLabel = displayNameLabel; - } - - protected void setDescriptionLabel(JLabel descriptionLabel) { - this.descriptionLabel = descriptionLabel; - } - - public JLabel getSpecialImageLabel() { - return specialImageLabel; - } - - protected void setSpecialImageLabel(JLabel specialImageLabel) { - this.specialImageLabel = specialImageLabel; - } - - public JLabel getSideIcon() { - return sideIcon; - } -} diff --git a/src/java/org/jivesoftware/spark/ui/ContactList.java b/src/java/org/jivesoftware/spark/ui/ContactList.java deleted file mode 100644 index f0b62692d..000000000 --- a/src/java/org/jivesoftware/spark/ui/ContactList.java +++ /dev/null @@ -1,2535 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.EventQueue; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.*; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JComponent; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JToolBar; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; - -import org.jivesoftware.MainWindowListener; -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.*; -import org.jivesoftware.smack.packet.*; -import org.jivesoftware.smack.roster.Roster; -import org.jivesoftware.smack.roster.RosterEntry; -import org.jivesoftware.smack.roster.RosterGroup; -import org.jivesoftware.smack.roster.RosterListener; -import org.jivesoftware.smack.filter.StanzaFilter; -import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.roster.packet.RosterPacket; -import org.jivesoftware.smackx.iqlast.LastActivityManager; -import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; -import org.jivesoftware.smackx.sharedgroups.SharedGroupManager; -import org.jivesoftware.smackx.iqlast.packet.LastActivity; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.PresenceManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.Workspace; -import org.jivesoftware.spark.component.InputDialog; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.component.VerticalFlowLayout; -import org.jivesoftware.spark.plugin.ContextMenuListener; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingTimerTask; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.UIComponentRegistry; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; -import org.jivesoftware.sparkimpl.profile.VCardManager; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - - -public class ContactList extends JPanel implements ActionListener, - ContactGroupListener, Plugin, RosterListener, ConnectionListener { - - private static final long serialVersionUID = -4391111935248627078L; - private JPanel mainPanel = new JPanel(); - private JScrollPane contactListScrollPane; - private final List groupList = new ArrayList<>(); - private final RolloverButton addingGroupButton; - - private ContactItem activeItem; - private ContactGroup activeGroup; - private ContactGroup unfiledGroup; - - - // Create Menus - private JMenuItem addContactMenu; - private JMenuItem addContactGroupMenu; - private JMenuItem removeContactFromGroupMenu; - private JMenuItem chatMenu; - private JMenuItem renameMenu; - - private ContactGroup offlineGroup; - private final JCheckBoxMenuItem showHideMenu = new JCheckBoxMenuItem(); - private final JCheckBoxMenuItem showOfflineGroupMenu = new JCheckBoxMenuItem(); - private final JCheckBoxMenuItem showOfflineUsersMenu = new JCheckBoxMenuItem(); - - private List sharedGroups = new ArrayList<>(); - - private final List contextListeners = new ArrayList<>(); - - private List initialPresences = new ArrayList<>(); - private final List dndListeners = new ArrayList<>(); - private final List contactListListeners = new ArrayList<>(); - private Properties props; - private File propertiesFile; - - private LocalPreferences localPreferences; - - private ContactItem contactItem; - - private String name, user; - - - public static final String RETRY_PANEL = "RETRY_PANEL"; - - - private ReconnectPanel _reconnectPanel; - private ReconnectPanelSmall _reconnectpanelsmall; - private ReconnectPanelIcon _reconnectpanelicon; - - private Workspace workspace; - - public static KeyEvent activeKeyEvent; - - /** - * Creates a new instance of ContactList. - */ - public ContactList() { - // Load Local Preferences - localPreferences = SettingsManager.getLocalPreferences(); - - offlineGroup = UIComponentRegistry.createContactGroup(Res.getString("group.offline")); - - JToolBar toolbar = new JToolBar(); - toolbar.setFloatable(false); - addContactMenu = new JMenuItem(Res.getString("menuitem.add.contact"), SparkRes.getImageIcon(SparkRes.USER1_ADD_16x16)); - addContactGroupMenu = new JMenuItem(Res.getString("menuitem.add.contact.group"), SparkRes.getImageIcon(SparkRes.SMALL_ADD_IMAGE)); - - removeContactFromGroupMenu = new JMenuItem(Res.getString("menuitem.remove.from.group"), SparkRes.getImageIcon(SparkRes.SMALL_DELETE)); - chatMenu = new JMenuItem(Res.getString("menuitem.start.a.chat"), SparkRes.getImageIcon(SparkRes.SMALL_MESSAGE_IMAGE)); - renameMenu = new JMenuItem(Res.getString("menuitem.rename"), SparkRes.getImageIcon(SparkRes.DESKTOP_IMAGE)); - - addContactMenu.addActionListener(this); - removeContactFromGroupMenu.addActionListener(this); - chatMenu.addActionListener(this); - renameMenu.addActionListener(this); - - - setLayout(new BorderLayout()); - - addingGroupButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.ADD_CONTACT_IMAGE)); - - RolloverButton groupChatButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.JOIN_GROUPCHAT_IMAGE)); - toolbar.add(addingGroupButton); - toolbar.add(groupChatButton); - - addingGroupButton.addActionListener(this); - - mainPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); - mainPanel.setBackground((Color)UIManager.get("ContactItem.background")); - contactListScrollPane = new JScrollPane(mainPanel); - contactListScrollPane.setAutoscrolls(true); - - contactListScrollPane.setBorder(BorderFactory.createEmptyBorder()); - contactListScrollPane.getVerticalScrollBar().setBlockIncrement(200); - contactListScrollPane.getVerticalScrollBar().setUnitIncrement(20); - - _reconnectPanel = new ReconnectPanel(); - - _reconnectpanelsmall = new ReconnectPanelSmall(Res.getString("button.reconnect2")); - - _reconnectpanelicon = new ReconnectPanelIcon(); - - workspace = SparkManager.getWorkspace(); - - workspace.getCardPanel().add(RETRY_PANEL, _reconnectPanel); - - - add(contactListScrollPane, BorderLayout.CENTER); - - - // Load Properties file - props = new Properties(); - // Save to properties file. - propertiesFile = new File(Spark.getSparkUserHome() + "/groups.properties"); - try { - props.load(new FileInputStream(propertiesFile)); - } - catch (IOException e) { - // File does not exist. - } - - // Add ActionListener(s) to menus -// addContactGroup(unfiledGroup); - addContactGroup(offlineGroup); - - showHideMenu.setSelected(false); - - // Add KeyMappings - SparkManager.getMainWindow().getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control F"), "searchContacts"); - SparkManager.getMainWindow().getRootPane().getActionMap().put("searchContacts", new AbstractAction("searchContacts") { - private static final long serialVersionUID = -5956142123453578689L; - - public void actionPerformed(ActionEvent evt) { - SparkManager.getUserManager().searchContacts("", SparkManager.getMainWindow()); - } - }); - - // Handle Command-F on Macs - SparkManager.getMainWindow().getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "appleStrokeF"); - SparkManager.getMainWindow().getRootPane().getActionMap().put("appleStrokeF", new AbstractAction("appleStrokeF") { - private static final long serialVersionUID = 7883006402414136652L; - - public void actionPerformed(ActionEvent evt) { - SparkManager.getUserManager().searchContacts("", SparkManager.getMainWindow()); - } - }); - - // Save state on shutdown. - SparkManager.getMainWindow().addMainWindowListener(new MainWindowListener() { - public void shutdown() { - saveState(); - } - - public void mainWindowActivated() { - - } - - public void mainWindowDeactivated() { - - } - }); - - SparkManager.getConnection().addConnectionListener(this); - - // Get command panel and add View Online/Offline, Add Contact -// StatusBar statusBar = SparkManager.getWorkspace().getStatusBar(); - -// final JPanel commandPanel = SparkManager.getWorkspace().getCommandPanel(); -// -// -// final RolloverButton addContactButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.USER1_ADD_16x16)); -// if (!Default.getBoolean(Default.ADD_CONTACT_DISABLED)) { -// commandPanel.add(addContactButton); -// } -// addContactButton.setToolTipText(Res.getString("message.add.a.contact")); -// addContactButton.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// new RosterDialog().showRosterDialog(); -// } -// }); - - } - - /** - * Switches all users to Offline and Creates a Reconnection Group - */ - private synchronized void switchAllUserOffline(final boolean onError) - { - SwingWorker worker = new SwingWorker() { - - @Override - public Object construct() { - mainPanel.add(_reconnectpanelsmall,0); - _reconnectpanelsmall.setClosedOnError(onError); - final Collection roster = Roster.getInstanceFor( SparkManager.getConnection() ).getEntries(); - - for(RosterEntry r : roster) - { - Presence p = new Presence(Presence.Type.unavailable); - moveToOfflineGroup(p, r.getUser()); - } - return true; - } - }; - worker.start(); - } - - /** - * Switches all Users to Offline and Creates an Icon in the CommandBar - */ - private synchronized void switchAllUserOfflineNoGroupEntry(final boolean onError) { - SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - _reconnectpanelicon.getPanel().add(_reconnectpanelicon.getButton(), 0); - _reconnectpanelicon.getPanel().revalidate(); - _reconnectpanelicon.setClosedOnError(onError); - final Collection roster = Roster.getInstanceFor( SparkManager.getConnection()).getEntries(); - for (RosterEntry r : roster) { - Presence p = new Presence(Presence.Type.unavailable); - moveToOfflineGroup(p, r.getUser()); - } - return true; - } - }; - worker.start(); - } - - /** - * Updates the users presence. - * - * @param presence the user to update. - * @throws Exception if there is a problem while updating the user's presence. - */ - private synchronized void updateUserPresence(Presence presence) throws Exception { - if (presence.getError() != null) { - // We ignore this. - return; - } - - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - - final String bareJID = XmppStringUtils.parseBareJid(presence.getFrom()); - - RosterEntry entry = roster.getEntry(bareJID); - boolean isPending = entry != null && (entry.getType() == RosterPacket.ItemType.none || entry.getType() == RosterPacket.ItemType.from) - && RosterPacket.ItemStatus.SUBSCRIPTION_PENDING == entry.getStatus(); - - // If online, check to see if they are in the offline group. - // If so, remove from offline group and add to all groups they - // belong to. - - if (presence.getType() == Presence.Type.available && offlineGroup.getContactItemByJID(bareJID) != null || ( presence.getFrom().contains( "workgroup." ) )) { - changeOfflineToOnline(bareJID, entry, presence); - } - else if (presence.getType() == Presence.Type.available) { - updateContactItemsPresence(presence, entry, bareJID); - } - else if (presence.getType() == Presence.Type.unavailable && !isPending) { - // If not available, move to offline group. - Presence rosterPresence = PresenceManager.getPresence(bareJID); - if (!rosterPresence.isAvailable()) { - moveToOfflineGroup(presence, bareJID); - } - else { - updateContactItemsPresence(rosterPresence, entry, bareJID); - } - } - - } - - /** - * Updates the presence of one individual based on their JID. - * - * @param presence the users presence. - * @param entry the roster entry being updated. - * @param bareJID the bare jid of the user. - */ - private void updateContactItemsPresence(Presence presence, RosterEntry entry, String bareJID) { - for (ContactGroup group : groupList) { - ContactItem item = group.getContactItemByJID(bareJID); - if (item != null) { - if (group == offlineGroup) { - changeOfflineToOnline(bareJID, entry, presence); - continue; - } - item.setPresence(presence); - group.fireContactGroupUpdated(); - } - } - } - - /** - * Moves every ContactItem associated with the given bareJID to offline. - * - * @param presence the users presence. - * @param bareJID the bareJID of the user. - */ - private void moveToOfflineGroup(final Presence presence, final String bareJID) { - for (ContactGroup grpItem : new ArrayList<>( groupList )) { - final ContactGroup group = grpItem; - final ContactItem item = group.getContactItemByJID(bareJID); - if (item != null) { - int numberOfMillisecondsInTheFuture = 3000; - Date timeToRun = new Date(System.currentTimeMillis() + numberOfMillisecondsInTheFuture); - - // Only run through if the users presence was online before. - if (item.getPresence().isAvailable()) { - item.showUserGoingOfflineOnline(); - item.setIcon(SparkRes.getImageIcon(SparkRes.CLEAR_BALL_ICON)); - group.fireContactGroupUpdated(); - - TaskEngine.getInstance().schedule(new SwingTimerTask() { - @Override - public void doRun() { - // Check to see if the user is offline, if so, move them to the offline group. - Presence userPresence = PresenceManager.getPresence(bareJID); - if (userPresence.isAvailable()) { - return; - } - - item.setPresence(presence); - - // Check for ContactItemHandler. - group.removeContactItem(item); - checkGroup(group); - - if (offlineGroup.getContactItemByJID(item.getJID()) == null) { - moveToOffline(item); - offlineGroup.fireContactGroupUpdated(); - } - } - }, timeToRun); - } - } else { - final ContactItem offlineItem = offlineGroup.getContactItemByJID(bareJID); - if (offlineItem != null) { - offlineItem.setPresence(presence); - } - } - } - } - - /** - * Moves a user to each group they belong to. - * - * @param bareJID the bareJID of the user to show as online. - * @param entry the RosterEntry of the user. - * @param presence the users presence. - */ - private void changeOfflineToOnline(String bareJID, final RosterEntry entry, Presence presence) { - // Move out of offline group. Add to all groups. - final ContactItem offlineItem = offlineGroup.getContactItemByJID(bareJID); - - if (offlineItem == null) { - return; - } - offlineGroup.removeContactItem(offlineItem); - - // Add To all groups it belongs to. - boolean isFiled = false; - - for (RosterGroup rosterGroup : entry.getGroups()) { - isFiled = true; - ContactGroup contactGroup = getContactGroup(rosterGroup.getName()); - if (contactGroup == null) { - // Create Contact Group - contactGroup = addContactGroup(rosterGroup.getName()); - } - - if (contactGroup != null) { - ContactItem changeContactItem; - if (contactGroup.getContactItemByJID(entry.getUser()) == null) { - ContactItem offlineCurrentItem = contactGroup.getOfflineContactItemByJID(bareJID); - //prevents from duplicating roster contacts when users going offline and online with Offline Group invisible - contactGroup.removeContactItem(offlineCurrentItem); - - // If we are reconnecting we have to check if we are on the - // dispatch thread - if (EventQueue.isDispatchThread()) { - - changeContactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getUser()); - contactGroup.addContactItem(changeContactItem); - changeContactItem.setAvailable(true); - changeContactItem.setPresence(presence); - changeContactItem.updateAvatarInSideIcon(); - changeContactItem.showUserComingOnline(); - changeContactItem.setSpecialIcon(offlineItem.getSpecialImageLabel().getIcon()); - //contactItem.updatePresenceIcon(contactItem.getPresence()); - toggleGroupVisibility(contactGroup.getGroupName(), true); - //contactGroup.fireContactGroupUpdated(); - - int numberOfMillisecondsInTheFuture = 5000; - Date timeToRun = new Date(System.currentTimeMillis() - + numberOfMillisecondsInTheFuture); - - final ContactItem staticItem = changeContactItem; - final ContactGroup staticGroup = contactGroup; - TaskEngine.getInstance().schedule(new SwingTimerTask() { - @Override - public void doRun() { - staticItem.updatePresenceIcon(staticItem.getPresence()); - staticGroup.fireContactGroupUpdated(); - } - }, timeToRun); - - } else { - - final ContactGroup staticContactGroup = contactGroup; - final Presence staticItemPrecense = presence; - - //Reconnection and not in dispatch Thread -> Add to EVentQueue - EventQueue.invokeLater( () -> { - - final ContactItem changeContact = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getUser()); - staticContactGroup.addContactItem(changeContact); - changeContact.setPresence(staticItemPrecense); - changeContact.setAvailable(true); - changeContact.updateAvatarInSideIcon(); - changeContact.showUserComingOnline(); - changeContact.setSpecialIcon(offlineItem.getSpecialImageLabel().getIcon()); - changeContact.updatePresenceIcon(changeContact.getPresence()); - toggleGroupVisibility(staticContactGroup.getGroupName(), true); - staticContactGroup.fireContactGroupUpdated(); - - } ); - } - } - } - } - - if (!isFiled) { - - - if (unfiledGroup.getContactItemByJID(entry.getUser()) == null) { - // If we are reconnecting we have to check if we are on the - // dispatch thread - if (EventQueue.isDispatchThread()) { - - contactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getUser()); - ContactGroup unfiledGrp = getUnfiledGroup(); - unfiledGrp.addContactItem(contactItem); - contactItem.setPresence(presence); - contactItem.setAvailable(true); - unfiledGrp.setVisible(true); - unfiledGrp.fireContactGroupUpdated(); - - - - - - } else { - final Presence staticItemPrecense = presence; - EventQueue.invokeLater( () -> { - contactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getUser()); - ContactGroup unfiledGrp = getUnfiledGroup(); - - contactItem.setPresence(staticItemPrecense); - contactItem.setAvailable(true); - unfiledGrp.addContactItem(contactItem); - contactItem.updatePresenceIcon(contactItem.getPresence()); - unfiledGrp.fireContactGroupUpdated(); - - - } ); - - } - - } - } - } - - /** - * Called to build the initial ContactList. - */ - private void buildContactList() { - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - - roster.addRosterListener(this); - - // Add All Groups to List - for (RosterGroup group : roster.getGroups()) { - addContactGroup(group.getName()); - } - - for (RosterGroup group : roster.getGroups()) { - - if(group.getName() == null || Objects.equals( group.getName(), "" ) ){ - for(RosterEntry entry : group.getEntries()){ - - ContactItem buildContactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getUser()); - moveToOffline(buildContactItem); - } - }else{ - - ContactGroup contactGroup = getContactGroup(group.getName()); - if (contactGroup == null) { - contactGroup = getUnfiledGroup(); - } - - for (RosterEntry entry : group.getEntries()) { - contactItem = null; - name = entry.getName(); - user = entry.getUser(); - // in case of connection lost, the creation must be done in eventqueue - if(EventQueue.isDispatchThread()) { - contactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getUser()); - } - else { - try { - EventQueue.invokeAndWait( () -> contactItem = UIComponentRegistry.createContactItem(name, null, user) ); - } catch(Exception ex) { - ex.printStackTrace(); - } - } - - // if there was something wrong, try an other - if(contactItem == null) - continue; - - contactItem.setPresence(new Presence(Presence.Type.unavailable)); - if ((entry.getType() == RosterPacket.ItemType.none || entry.getType() == RosterPacket.ItemType.from) - && RosterPacket.ItemStatus.SUBSCRIPTION_PENDING == entry.getStatus()) { - // Add to contact group. - contactGroup.addContactItem(contactItem); - contactGroup.setVisible(true); - } - else { - if (offlineGroup.getContactItemByJID(entry.getUser()) == null) { - moveToOffline(contactItem); - } - } - } - } - } - - if (EventQueue.isDispatchThread()) { - // Add Unfiled Group - for (RosterEntry entry : roster.getUnfiledEntries()) { - ContactItem moveToOfflineContactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getUser()); - moveToOffline(moveToOfflineContactItem); - } - } - else - { - try { - EventQueue.invokeAndWait( () -> { -for (RosterEntry entry : roster.getUnfiledEntries()) { -ContactItem moveToOfflineContactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getUser()); -moveToOffline(moveToOfflineContactItem); -} - } ); - } catch (Exception e) { - Log.error("moveToOffilne",e); - } - } - - } - - /** - * Called when NEW entries are added. - * - * @param addresses the address added. - */ - public void entriesAdded(final Collection addresses) { - SwingUtilities.invokeLater( () -> { - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - - for (String jid : addresses) { - RosterEntry entry = roster.getEntry(jid); - addUser(entry); - } - } ); - } - - /** - * Adds a single user to the ContactList. - * - * @param entry the RosterEntry of the the user. - */ - private void addUser(RosterEntry entry) { - ContactItem newContactItem = UIComponentRegistry.createContactItem(entry.getName(), null, entry.getUser()); - - if (entry.getType() == RosterPacket.ItemType.none || entry.getType() == RosterPacket.ItemType.from) { - // Ignore, since the new user is pending to be added. - for (RosterGroup group : entry.getGroups()) { - ContactGroup contactGroup = getContactGroup(group.getName()); - if (contactGroup == null) { - contactGroup = addContactGroup(group.getName()); - } - - boolean isPending = entry.getType() == RosterPacket.ItemType.none || entry.getType() == RosterPacket.ItemType.from - && RosterPacket.ItemStatus.SUBSCRIPTION_PENDING == entry.getStatus(); - if (isPending) { - contactGroup.setVisible(true); - } - contactGroup.addContactItem(newContactItem); - - } - return; - } - else { - moveToOffline(newContactItem); - } - - // Update users icon - Presence presence = Roster.getInstanceFor( SparkManager.getConnection() ).getPresence(entry.getUser()); - try { - updateUserPresence(presence); - } - catch (Exception e) { - Log.error(e); - } - } - - /** - * Handle when the Roster changes based on subscription notices. - * - * @param addresses List of entries that were updated. - */ - public void entriesUpdated(final Collection addresses) { - handleEntriesUpdated(addresses); - } - - /** - * Called when users are removed from the roster. - * - * @param addresses the addresses removed from the roster. - */ - public void entriesDeleted(final Collection addresses) { - SwingUtilities.invokeLater( () -> { - for (String jid : addresses) { - removeContactItem(jid); - } - } ); - - } - - /** - * Handles any presence modifications of a user(s). - * - * @param addresses the Collection of addresses that have been modified within the Roster. - */ - private synchronized void handleEntriesUpdated(final Collection addresses) { - SwingUtilities.invokeLater( () -> { - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - - Iterator jids = addresses.iterator(); - while (jids.hasNext()) { - String jid = jids.next(); - RosterEntry rosterEntry = roster.getEntry(jid); - if (rosterEntry != null) { - // Check for new Roster Groups and add them if they do not exist. - boolean isUnfiled = true; - for (RosterGroup group : rosterEntry.getGroups()) { - isUnfiled = false; - - // Handle if this is a new Entry in a new Group. - if (getContactGroup(group.getName()) == null) { - // Create group. - ContactGroup contactGroup = addContactGroup(group.getName()); - contactGroup.setVisible(false); - contactGroup = getContactGroup(group.getName()); - ContactItem contactItem1 = UIComponentRegistry.createContactItem(rosterEntry.getName(), null, rosterEntry.getUser()); - contactGroup.addContactItem( contactItem1 ); - Presence presence = PresenceManager.getPresence(jid); - contactItem1.setPresence(presence); - if (presence.isAvailable()) { - contactGroup.setVisible(true); - } - } - else { - ContactGroup contactGroup = getContactGroup(group.getName()); - ContactItem item = offlineGroup.getContactItemByJID(jid); - if (item == null) { - item = contactGroup.getContactItemByJID(jid); - } - // Check to see if this entry is new to a pre-existing group. - if (item == null) { - item = UIComponentRegistry.createContactItem(rosterEntry.getName(), null, rosterEntry.getUser()); - Presence presence = PresenceManager.getPresence(jid); - item.setPresence(presence); - if (presence.isAvailable()) { - contactGroup.addContactItem(item); - contactGroup.fireContactGroupUpdated(); - } - else { - moveToOffline(item); - offlineGroup.fireContactGroupUpdated(); - } - } - - // If not, just update their presence. - else { - RosterEntry entry = roster.getEntry(jid); - Presence presence = PresenceManager.getPresence(jid); - item.setPresence(presence); - try { - updateUserPresence(presence); - } - catch (Exception e) { - Log.error(e); - } - - if (entry != null && (entry.getType() == RosterPacket.ItemType.none || entry.getType() == RosterPacket.ItemType.from) - && RosterPacket.ItemStatus.SUBSCRIPTION_PENDING == entry.getStatus()) { - contactGroup.setVisible(true); - - } - contactGroup.fireContactGroupUpdated(); - } - } - } - - // Now check to see if groups have been modified or removed. This is used - // to check if Contact Groups have been renamed or removed. - final Set userGroupSet = new HashSet<>(); - jids = addresses.iterator(); - while (jids.hasNext()) { - jid = jids.next(); - rosterEntry = roster.getEntry(jid); - - boolean unfiled = true; - for (RosterGroup g : rosterEntry.getGroups()) { - userGroupSet.add(g.getName()); - unfiled = false; - } - - for (ContactGroup group : new ArrayList<>( getContactGroups() )) { - ContactItem itemFound = group.getContactItemByJID(jid); - if (itemFound != null && !unfiled && group != getUnfiledGroup() && group != offlineGroup) { - if (!userGroupSet.contains(group.getGroupName())) { - if (group.getContactItems().isEmpty()) { - removeContactGroup(group); - } else { - group.removeContactItem(itemFound); - } - } - } - - } - } - - - if (!isUnfiled) { - return; - } - - ContactGroup unfiledGrp = getUnfiledGroup(); - ContactItem unfiledItem = unfiledGrp.getContactItemByJID(jid); - if (unfiledItem != null) { - - } - else { - ContactItem offlineItem = offlineGroup.getContactItemByJID(jid); - if (offlineItem != null) { - if ((rosterEntry.getType() == RosterPacket.ItemType.none || rosterEntry.getType() == RosterPacket.ItemType.from) - && RosterPacket.ItemStatus.SUBSCRIPTION_PENDING == rosterEntry.getStatus()) { - // Remove from offlineItem and add to unfiledItem. - offlineGroup.removeContactItem(offlineItem); - unfiledGrp.addContactItem(offlineItem); - unfiledGrp.fireContactGroupUpdated(); - unfiledGrp.setVisible(true); - } - } - } - } - } - } ); - } - - public void presenceChanged(Presence presence) { - - } - - /** - * Retrieve the ContactItem by it's jid. - * - * @param jid the JID of the user. - * @return the "first" contact item found. - */ - public ContactItem getContactItemByJID(String jid) { - for (ContactGroup group : getContactGroups()) { - ContactItem item = group.getContactItemByJID(XmppStringUtils.parseBareJid(jid)); - if (item != null) { - return item; - } - } - return null; - } - - /** - * Returns a Collection of ContactItems in a ContactList. - * - * @param jid the users JID. - * @return a Collection of ContactItem items. - */ - public Collection getContactItemsByJID(String jid) { - final List list = new ArrayList<>(); - for (ContactGroup group : getContactGroups()) { - ContactItem item = group.getContactItemByJID(XmppStringUtils.parseBareJid(jid)); - if (item != null) { - list.add(item); - } - } - /** - * We have to search ContactItems into offline contacts. - * Standart getContactItemByJID() method search ContactItems only in OfflineGroup or into inline cantacts - */ - for( ContactGroup group : getContactGroups() ) { - for (ContactItem offlineItem : group.getOfflineContacts() ) { - if ( offlineItem != null && offlineItem.getJID().equalsIgnoreCase(XmppStringUtils.parseBareJid(jid)) ) { - if ( !list.contains(offlineItem) ) { - list.add(offlineItem); - } - } - } - } - - return list; - } - - /** - * Set an Icon for all ContactItems that match the given jid. - * - * @param jid the users jid. - * @param icon the icon to use. - */ - public void setIconFor(String jid, Icon icon) { - for (ContactGroup group : getContactGroups()) { - ContactItem item = group.getContactItemByJID(XmppStringUtils.parseBareJid(jid)); - if (item != null) { - item.setIcon(icon); - group.fireContactGroupUpdated(); - } - } - } - - /** - * Sets the default settings for a ContactItem. - * - * @param jid the users jid. - */ - public void useDefaults(String jid) { - for (ContactGroup group : getContactGroups()) { - ContactItem item = group.getContactItemByJID(XmppStringUtils.parseBareJid(jid)); - if (item != null) { - item.updatePresenceIcon(item.getPresence()); - group.fireContactGroupUpdated(); - } - } - } - - - /** - * Retrieve the ContactItem by their displayed name (either alias, nickname or username). - * - * @param displayName the users nickname in the contact list. - * @return the "first" contact item found. - */ - public ContactItem getContactItemByDisplayName(String displayName) { - for (ContactGroup contactGroup : getContactGroups()) { - ContactItem item = contactGroup.getContactItemByDisplayName(displayName); - if (item != null) { - return item; - } - } - return null; - } - - /** - * Adds a new ContactGroup to the ContactList. - * - * @param group the group to add. - */ - private void addContactGroup(ContactGroup group) { - groupList.add(group); - - Collections.sort(groupList, GROUP_COMPARATOR); - - try { - mainPanel.add(group, groupList.indexOf(group)); - } - catch (Exception e) { - Log.error(e); - } - - group.addContactGroupListener(this); - - fireContactGroupAdded(group); - - // Check state - String prop = props.getProperty(group.getGroupName()); - if (prop != null) { - boolean isCollapsed = Boolean.valueOf(prop); - group.setCollapsed(isCollapsed); - } - } - - /** - * Creates and adds a new ContactGroup to the ContactList. - * - * @param groupName the name of the ContactGroup to add. - * @return the newly created ContactGroup. - */ - private ContactGroup addContactGroup(String groupName) { - StringTokenizer tkn = new StringTokenizer(groupName, "::"); - - ContactGroup rootGroup = null; - ContactGroup lastGroup = null; - StringBuilder buf = new StringBuilder(); - - boolean groupAdded = false; - while (tkn.hasMoreTokens()) { - String group = tkn.nextToken(); - buf.append(group); - if (tkn.hasMoreTokens()) { - buf.append("::"); - } - - String name = buf.toString(); - if (name.endsWith("::")) { - name = name.substring(0, name.length() - 2); - } - - ContactGroup newContactGroup = getContactGroup(name); - - - if (newContactGroup == null) { - newContactGroup = UIComponentRegistry.createContactGroup(group); - - String realGroupName = buf.toString(); - if (realGroupName.endsWith("::")) { - realGroupName = realGroupName.substring(0, realGroupName.length() - 2); - } - - newContactGroup.setGroupName(realGroupName); - } - else { - if (newContactGroup != offlineGroup && newContactGroup != getUnfiledGroup()) { - rootGroup = newContactGroup; - continue; - } - } - - - if (lastGroup != null) { - lastGroup.addContactGroup(newContactGroup); - groupList.add(newContactGroup); - } - else if (rootGroup != null) { - rootGroup.addContactGroup(newContactGroup); - groupList.add(newContactGroup); - } - else { - rootGroup = newContactGroup; - } - - lastGroup = newContactGroup; - - - newContactGroup.addContactGroupListener(this); - - if (sharedGroups != null) { - boolean isSharedGroup = sharedGroups.contains(newContactGroup.getGroupName()); - newContactGroup.setSharedGroup(isSharedGroup); - } - - fireContactGroupAdded(newContactGroup); - - // Check state - - String prop = props.getProperty(newContactGroup.getGroupName()); - if (prop != null) { - boolean isCollapsed = Boolean.valueOf(prop); - newContactGroup.setCollapsed(isCollapsed); - } - - - groupAdded = true; - } - - if (!groupAdded) { - return getContactGroup(groupName); - } - - - final List tempList = new ArrayList<>(); - final Component[] comps = mainPanel.getComponents(); - for (Component c : comps) { - if (c instanceof ContactGroup && c != offlineGroup) { - tempList.add((ContactGroup)c); - } - } - tempList.add(rootGroup); - - - groupList.add(rootGroup); - - Collections.sort(tempList, GROUP_COMPARATOR); - - int loc = tempList.indexOf(rootGroup); - - - try { - mainPanel.add(rootGroup, loc); - } - catch (Exception e) { - Log.error(e); - } - - //Check if i should show groups with no users online - if (null != getContactGroup(groupName) && !getContactGroup(groupName).hasAvailableContacts()) - { - showEmptyGroups(localPreferences.isEmptyGroupsShown()); - } - - - return getContactGroup(groupName); - - } - - /** - * Removes a ContactGroup from the group model and ContactList. - * - * @param contactGroup the ContactGroup to remove. - */ - private void removeContactGroup(ContactGroup contactGroup) { - contactGroup.removeContactGroupListener(this); - groupList.remove(contactGroup); - mainPanel.remove(contactGroup); - - ContactGroup parent = getParentGroup(contactGroup.getGroupName()); - if (parent != null) { - parent.removeContactGroup(contactGroup); - } - - contactListScrollPane.validate(); - mainPanel.invalidate(); - mainPanel.repaint(); - - fireContactGroupRemoved(contactGroup); - } - - - /** - * Returns a ContactGroup based on its name. - * - * @param groupName the name of the ContactGroup. - * @return the ContactGroup. If no ContactGroup is found, null is returned. - */ - public ContactGroup getContactGroup(String groupName) { - ContactGroup cGroup = null; - - for (ContactGroup contactGroup : groupList) { - if (contactGroup.getGroupName().equals(groupName)) { - cGroup = contactGroup; - break; - } - else { - cGroup = getSubContactGroup(contactGroup, groupName); - if (cGroup != null) { - break; - } - } - } - - return cGroup; - } - - /** - * For traversing of a nested group. Allows users to find the owning parent of a given contact group. - * - * @param groupName the name of the nested contact group. - * @return the parent ContactGroup. If no parent, null will be returned. - */ - public ContactGroup getParentGroup(String groupName) { - // Check if there is even a parent group - if (!groupName.contains("::")) { - return null; - } - - final ContactGroup group = getContactGroup(groupName); - if (group == null) { - return null; - } - - // Otherwise, find parent - int index = groupName.lastIndexOf("::"); - String parentGroupName = groupName.substring(0, index); - return getContactGroup(parentGroupName); - } - - /** - * Returns the nested ContactGroup of a given ContactGroup with associated name. - * - * @param group the parent ContactGroup. - * @param groupName the name of the nested group. - * @return the nested ContactGroup. If not found, null will be returned. - */ - private ContactGroup getSubContactGroup(ContactGroup group, String groupName) { - final Iterator contactGroups = group.getContactGroups().iterator(); - ContactGroup grp = null; - - while (contactGroups.hasNext()) { - ContactGroup contactGroup = contactGroups.next(); - if (contactGroup.getGroupName().equals(groupName)) { - grp = contactGroup; - break; - } - else if (contactGroup.getContactGroups().size() > 0) { - grp = getSubContactGroup(contactGroup, groupName); - if (grp != null) { - break; - } - } - - } - return grp; - } - - /** - * Toggles the visiblity of a ContactGroup. - * - * @param groupName the name of the ContactGroup. - * @param visible true to show, otherwise false. - */ - public void toggleGroupVisibility(String groupName, boolean visible) { - StringTokenizer tkn = new StringTokenizer(groupName, "::"); - while (tkn.hasMoreTokens()) { - String group = tkn.nextToken(); - ContactGroup contactGroup = getContactGroup(group); - if (contactGroup != null) { - contactGroup.setVisible(visible); - } - } - - ContactGroup group = getContactGroup(groupName); - if (group != null) { - group.setVisible(visible); - } - } - - public void actionPerformed(ActionEvent e) { - if (e.getSource() == addingGroupButton) { - new RosterDialog().showRosterDialog(); - } - else if (e.getSource() == chatMenu) { - if (activeItem != null) { - SparkManager.getChatManager().activateChat(activeItem.getJID(), activeItem.getDisplayName()); - } - } - else if (e.getSource() == addContactMenu) { - RosterDialog rosterDialog = new RosterDialog(); - if (activeGroup != null) { - rosterDialog.setDefaultGroup(activeGroup); - } - rosterDialog.showRosterDialog(); - } - else if (e.getSource() == removeContactFromGroupMenu) { - if (activeItem != null) { - removeContactFromGroup(activeItem); - } - } - else if (e.getSource() == renameMenu) { - if (activeItem == null) { - return; - } - - String oldAlias = activeItem.getAlias(); - String newAlias = JOptionPane.showInputDialog(this, Res.getString("label.rename.to") + ":", oldAlias); - - // if user pressed 'cancel', output will be null. - // if user removed alias, output will be an empty String. - if (newAlias != null) { - if (!ModelUtil.hasLength(newAlias)) { - newAlias = null; // allows you to remove an alias. - } - - String address = activeItem.getJID(); - ContactGroup contactGroup = getContactGroup(activeItem.getGroupName()); - ContactItem contactItem = contactGroup.getContactItemByDisplayName(activeItem.getDisplayName()); - contactItem.setAlias(newAlias); - - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - RosterEntry entry = roster.getEntry(address); - try - { - entry.setName(newAlias); - - final String user = XmppStringUtils.parseBareJid(address); - for ( ContactGroup cg : groupList ) { - ContactItem ci = cg.getContactItemByJID(user); - if (ci != null) { - ci.setAlias(newAlias); - } - } - } - catch ( XMPPException.XMPPErrorException| SmackException.NotConnectedException | SmackException.NoResponseException e1 ) - { - Log.warning( "Unable to set new alias '" + newAlias + "' for roster entry " + address, e1 ); - } - } - } - } - - - /** - * Removes a contact item from the group. - * - * @param item the ContactItem to remove. - */ - private void removeContactFromGroup(ContactItem item) { - String groupName = item.getGroupName(); - ContactGroup contactGroup = getContactGroup(groupName); - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - RosterEntry entry = roster.getEntry(item.getJID()); - if (entry != null && contactGroup != offlineGroup) { - try { - RosterGroup rosterGroup = roster.getGroup(groupName); - if (rosterGroup != null) { - RosterEntry rosterEntry = rosterGroup.getEntry(entry.getUser()); - if (rosterEntry != null) { - rosterGroup.removeEntry(rosterEntry); - } - } - contactGroup.removeContactItem(contactGroup.getContactItemByJID(item.getJID())); - checkGroup(contactGroup); - } - catch (Exception e) { - Log.error("Error removing user from contact list.", e); - } - } - } - - private void removeContactFromRoster(ContactItem item) { - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - RosterEntry entry = roster.getEntry(item.getJID()); - if (entry != null) { - try { - roster.removeEntry(entry); - } - catch (XMPPException | SmackException e) { - Log.warning("Unable to remove roster entry.", e); - } - } - } - - private void removeContactItem(String jid) { - for (ContactGroup group : new ArrayList<>( getContactGroups() )) { - ContactItem item = group.getContactItemByJID(jid); - group.removeOfflineContactItem(jid); - if (item != null) { - group.removeContactItem(item); - checkGroup(group); - } - } - } - - public void contactItemClicked(ContactItem item) { - activeItem = item; - - if (activeKeyEvent == null || ((activeKeyEvent.getModifiers() & KeyEvent.CTRL_MASK) == 0)) { - clearSelectionList(item); - } - - - fireContactItemClicked(item); - activeKeyEvent = null; - } - - public void contactItemDoubleClicked(ContactItem item) { - activeItem = item; - - ChatManager chatManager = SparkManager.getChatManager(); - boolean handled = chatManager.fireContactItemDoubleClicked(item); - - if (!handled) { - chatManager.activateChat(item.getJID(), item.getDisplayName()); - } - - clearSelectionList(item); - - fireContactItemDoubleClicked(item); - } - - public void contactGroupPopup(MouseEvent e, final ContactGroup group) { - // Do nothing with offline group - if (group == offlineGroup || group == getUnfiledGroup()) { - return; - } - - - final JPopupMenu popup = new JPopupMenu(); - if (!Default.getBoolean(Default.ADD_CONTACT_DISABLED)) { - popup.add(addContactMenu); - } - - if(!Default.getBoolean("ADD_CONTACT_GROUP_DISABLED")){ - popup.add(addContactGroupMenu); - } - popup.addSeparator(); - - fireContextMenuListenerPopup(popup, group); - - JMenuItem delete = new JMenuItem(Res.getString("menuitem.delete")); - JMenuItem rename = new JMenuItem(Res.getString("menuitem.rename")); - JMenuItem expand = new JMenuItem(Res.getString("menuitem.expand.all.groups")); - JMenuItem collapse = new JMenuItem(Res.getString("menuitem.collapse.all.groups")); - - if (!group.isSharedGroup()) { - popup.addSeparator(); - popup.add(delete); - popup.add(rename); - } - - popup.addSeparator(); - popup.add(expand); - popup.add(collapse); - - delete.addActionListener( e1 -> { - UIManager.put("OptionPane.yesButtonText", Res.getString("yes")); - UIManager.put("OptionPane.noButtonText", Res.getString("no")); - UIManager.put("OptionPane.cancelButtonText", Res.getString("cancel")); - int ok = JOptionPane.showConfirmDialog(group, Res.getString("message.delete.confirmation", group.getGroupName()), Res.getString("title.confirmation"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); - if (ok == JOptionPane.YES_OPTION) { - String groupName = group.getGroupName(); - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - - RosterGroup rosterGroup = roster.getGroup(groupName); - if (rosterGroup != null) { - for (RosterEntry entry : rosterGroup.getEntries()) { - try { - rosterGroup.removeEntry(entry); - } - catch (XMPPException | SmackException ex) { - Log.error("Error removing entry", ex); - } - } - } - - // Remove from UI - removeContactGroup(group); - invalidate(); - repaint(); - } - - } ); - - - rename.addActionListener( e1 -> { - String newName = JOptionPane.showInputDialog(group, Res.getString("label.rename.to") + ":", Res.getString("title.rename.roster.group"), JOptionPane.QUESTION_MESSAGE); - if (!ModelUtil.hasLength(newName)) { - return; - } - String groupName = group.getGroupName(); - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - - RosterGroup rosterGroup = roster.getGroup(groupName); - //Do not remove ContactGroup if the name entered was the same - if (rosterGroup != null && !groupName.equals(newName)) { - try - { - rosterGroup.setName(newName); - removeContactGroup(group); - addContactGroup(newName); - toggleGroupVisibility(newName, true); - getContactGroup(newName).setCollapsed( group.isCollapsed()); - } - catch ( XMPPException.XMPPErrorException| SmackException.NotConnectedException | SmackException.NoResponseException ex ) - { - Log.warning( "Unable to set new name '" + newName + "' for roster group" + groupName, ex ); - } - } - - } ); - expand.addActionListener( e1 -> { - Collection groups = getContactGroups(); - for (ContactGroup group1 : groups) { - group1.setCollapsed(false); - } - } ); - - collapse.addActionListener( e1 -> { - Collection groups = getContactGroups(); - for (ContactGroup group1 : groups) { - group1.setCollapsed(true); - } - } ); - - // popup.add(inviteFirstAcceptor); - popup.show(group, e.getX(), e.getY()); - - activeGroup = group; - } - - - public void showPopup(MouseEvent e, final ContactItem item) - { - showPopup(null,e,item); - } - /** - * Shows popup for right-clicking of ContactItem. - * - * @param e the MouseEvent - * @param item the ContactItem - * @param component the owning component - */ - public void showPopup(Component component, MouseEvent e, final ContactItem item) { - if (item.getJID() == null) { - return; - } - - activeItem = item; - - final JPopupMenu popup = new JPopupMenu(); - - // Add Start Chat Menu - popup.add(chatMenu); - - // Add Send File Action - Action sendAction = new AbstractAction() { - private static final long serialVersionUID = -7519717310558205566L; - - public void actionPerformed(ActionEvent actionEvent) { - SparkManager.getTransferManager().sendFileTo(item); - } - }; - - sendAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.DOCUMENT_16x16)); - sendAction.putValue(Action.NAME, Res.getString("menuitem.send.a.file")); - - if ((item.getPresence() != null) && Enterprise.containsFeature(Enterprise.FILE_TRANSFER_FEATURE)) { - popup.add(sendAction); - } - - popup.addSeparator(); - - - String groupName = item.getGroupName(); - ContactGroup contactGroup = getContactGroup(groupName); - - // Only show "Remove Contact From Group" if the user belongs to more than one group. - if (!contactGroup.isSharedGroup() && !contactGroup.isOfflineGroup() && contactGroup != getUnfiledGroup()) { - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - RosterEntry entry = roster.getEntry(item.getJID()); - if (entry != null) { - int groupCount = entry.getGroups().size(); - - //todo: It should be possible to remove a user from the only group they're in - // which would put them into the unfiled group. - if (groupCount > 1) { - popup.add(removeContactFromGroupMenu); - } - - } - } - - // Define remove entry action - Action removeAction = new AbstractAction() { - private static final long serialVersionUID = -2565914214685979320L; - - public void actionPerformed(ActionEvent e) { - removeContactFromRoster(item); - } - }; - - removeAction.putValue(Action.NAME, Res.getString("menuitem.remove.from.roster")); - removeAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_CIRCLE_DELETE)); - - // Check if user is in shared group. - boolean isInSharedGroup = false; - for (ContactGroup cGroup : new ArrayList<>( getContactGroups() )) { - if (cGroup.isSharedGroup()) { - ContactItem it = cGroup.getContactItemByJID(item.getJID()); - if (it != null) { - isInSharedGroup = true; - } - } - } - - - if (!contactGroup.isSharedGroup() && !isInSharedGroup) { - popup.add(removeAction); - } - - popup.add(renameMenu); - - - Action viewProfile = new AbstractAction() { - private static final long serialVersionUID = -2562731455090634805L; - - public void actionPerformed(ActionEvent e) { - VCardManager vcardSupport = SparkManager.getVCardManager(); - String jid = item.getJID(); - vcardSupport.viewProfile(jid, SparkManager.getWorkspace()); - } - }; - viewProfile.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.PROFILE_IMAGE_16x16)); - viewProfile.putValue(Action.NAME, Res.getString("menuitem.view.profile")); - - popup.add(viewProfile); - - - popup.addSeparator(); - - Action lastActivityAction = new AbstractAction() { - private static final long serialVersionUID = -4884230635430933060L; - - public void actionPerformed(ActionEvent actionEvent) { - try { - String client = ""; - if (item.getPresence().getType() != Presence.Type.unavailable) { - client = item.getPresence().getFrom(); - if ((client != null) && (client.lastIndexOf("/") != -1)) { - client = client.substring(client.lastIndexOf("/")); - } else client = "/"; - } - - LastActivity activity = LastActivityManager.getInstanceFor( SparkManager.getConnection() ).getLastActivity(item.getJID()+client); - long idleTime = (activity.getIdleTime() * 1000); - String time = ModelUtil.getTimeFromLong(idleTime); - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(getGUI(), Res.getString("message.idle.for", time), Res.getString("title.last.activity"), JOptionPane.INFORMATION_MESSAGE); - } - catch (Exception e1) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(getGUI(), Res.getString("message.unable.to.retrieve.last.activity", item.getJID()), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - } - - } - }; - - lastActivityAction.putValue(Action.NAME, Res.getString("menuitem.view.last.activity")); - lastActivityAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_USER1_STOPWATCH)); - - if (contactGroup == offlineGroup || item.getPresence().isAway() || (item.getPresence().getType() == Presence.Type.unavailable) || (item.getPresence().getType() == null)) { - popup.add(lastActivityAction); - } - - Action subscribeAction = new AbstractAction() { - private static final long serialVersionUID = -7754905015338902300L; - - public void actionPerformed(ActionEvent e) { - String jid = item.getJID(); - Presence response = new Presence(Presence.Type.subscribe); - response.setTo(jid); - - try - { - SparkManager.getConnection().sendStanza(response); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to send subscribe to " + jid, e1 ); - } - } - }; - - subscribeAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_USER1_INFORMATION)); - subscribeAction.putValue(Action.NAME, Res.getString("menuitem.subscribe.to")); - - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - RosterEntry entry = roster.getEntry(item.getJID()); - if (entry != null && entry.getType() == RosterPacket.ItemType.from) { - popup.add(subscribeAction); - } - else if( entry!=null && entry.getType() != RosterPacket.ItemType.both && entry.getStatus() == RosterPacket.ItemStatus.SUBSCRIPTION_PENDING) - { - popup.add(subscribeAction); - } - - // Fire Context Menu Listener - fireContextMenuListenerPopup(popup, item); - - ContactGroup group = getContactGroup(item.getGroupName()); - if (component == null) { - popup.show(group.getList(), e.getX(), e.getY()); - } else { - popup.show(component, e.getX(), e.getY()); - popup.requestFocus(); - } - } - - public void showPopup(MouseEvent e, final Collection items) { - ContactGroup group = null; - for (ContactItem item : items) { - group = getContactGroup(item.getGroupName()); - break; - } - - - final JPopupMenu popup = new JPopupMenu(); - final JMenuItem sendMessagesMenu = new JMenuItem(Res.getString("menuitem.send.a.message"), SparkRes.getImageIcon(SparkRes.SMALL_MESSAGE_IMAGE)); - - - fireContextMenuListenerPopup(popup, items); - - popup.add(sendMessagesMenu); - - sendMessagesMenu.addActionListener( e1 -> sendMessages(items) ); - - try { - popup.show(group.getList(), e.getX(), e.getY()); - } - catch (NullPointerException ee) { - // Nothing we can do here - } - } - - private void clearSelectionList(ContactItem selectedItem) { - // Check for null. In certain cases the event triggering the model might - // not find the selected object. - if (selectedItem == null) { - return; - } - - final ContactGroup owner = getContactGroup(selectedItem.getGroupName()); - for (ContactGroup contactGroup : new ArrayList<>( groupList )) { - if (owner != contactGroup) { - contactGroup.clearSelection(); - } - } - } - - - private void sendMessages(Collection items) { - StringBuilder buf = new StringBuilder(); - InputDialog dialog = new InputDialog(); - final String messageText = dialog.getInput(Res.getString("title.broadcast.message"), Res.getString("message.enter.broadcast.message"), SparkRes.getImageIcon(SparkRes.BLANK_IMAGE), SparkManager.getMainWindow()); - if (ModelUtil.hasLength(messageText)) { - - final Map broadcastMessages = new HashMap<>(); - for (ContactItem item : items) { - final Message message = new Message(); - message.setTo(item.getJID()); - final Map properties = new HashMap<>(); - properties.put( "broadcast", true ); - message.addExtension( new JivePropertiesExtension( properties ) ); - message.setBody(messageText); - if (!broadcastMessages.containsKey(item.getJID())) { - buf.append(item.getDisplayName()).append("\n"); - broadcastMessages.put(item.getJID(), message); - } - } - - for (Message message : broadcastMessages.values()) { - try - { - SparkManager.getConnection().sendStanza(message); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to send broadcast to " + message.getTo(), e ); - } - } - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), Res.getString("message.broadcasted.to", buf.toString()), Res.getString("title.notification"), JOptionPane.INFORMATION_MESSAGE); - } - - - } - - // For plugin use only - - public void initialize() { - this.setBorder(BorderFactory.createEmptyBorder()); - - // Add Contact List - addContactListToWorkspace(); - - // Hide top toolbar - SparkManager.getMainWindow().getTopToolBar().setVisible(false); - - final Runnable sharedGroupLoader = () -> { -// Retrieve shared group list. -try { -sharedGroups = SharedGroupManager.getSharedGroups(SparkManager.getConnection()); -} -catch (XMPPException | SmackException e) { -Log.error("Unable to contact shared group info.", e); -} - -SwingUtilities.invokeLater( () -> loadContactList() ); - -}; - - TaskEngine.getInstance().submit(sharedGroupLoader); - } - - private void loadContactList() { - - // Build the initial contact list. - buildContactList(); - - boolean show = localPreferences.isEmptyGroupsShown(); - - // Hide all groups initially - showEmptyGroups(show); - - // Hide all Offline Users - showOfflineUsers(localPreferences.isOfflineUsersShown()); - - // Add a subscription listener. - addSubscriptionListener(); - - // Load all plugins - SparkManager.getWorkspace().loadPlugins(); - - } - - public void addSubscriptionListener() { - // Add subscription listener - StanzaFilter stanzaFilter = new StanzaTypeFilter(Presence.class); - StanzaListener subscribeListener = stanza -> { - final Presence presence = (Presence)stanza; - if (presence.getType() == Presence.Type.subscribe) { - SwingUtilities.invokeLater( () -> { - try - { - subscriptionRequest(presence.getFrom()); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to subscribe to " + presence.getFrom(), e ); - } - } ); - } - else if (presence.getType() == Presence.Type.unsubscribe) { - SwingUtilities.invokeLater( () -> { - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - RosterEntry entry = roster.getEntry(presence.getFrom()); - if (entry != null) { - try { - removeContactItem(presence.getFrom()); - roster.removeEntry(entry); - } - catch (XMPPException | SmackException e) { - Presence unsub = new Presence(Presence.Type.unsubscribed); - unsub.setTo(presence.getFrom()); - try - { - SparkManager.getConnection().sendStanza(unsub); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to unsubscribe from " + unsub.getTo(), e1 ); - } - Log.error(e); - } - } - } ); - - - } - else if (presence.getType() == Presence.Type.subscribe) { - // Find Contact in Contact List - String jid = XmppStringUtils.parseBareJid(presence.getFrom()); - ContactItem item = getContactItemByJID(jid); - - // If item is not in the Contact List, add them. - if (item == null) { - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - RosterEntry entry = roster.getEntry(jid); - if (entry != null) { - item = UIComponentRegistry.createContactItem(entry.getName(), null, jid); - moveToOffline(item); - offlineGroup.fireContactGroupUpdated(); - } - } - } - else if (presence.getType() == Presence.Type.unsubscribed) { - SwingUtilities.invokeLater( () -> { - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - RosterEntry entry = roster.getEntry(presence.getFrom()); - if (entry != null) { - try { - removeContactItem(presence.getFrom()); - roster.removeEntry(entry); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - } - String jid = XmppStringUtils.parseBareJid(presence.getFrom()); - removeContactItem(jid); - } ); - } - else { - - try { - initialPresences.add(presence); - } - catch (Exception e) { - Log.error(e); - } - - int numberOfMillisecondsInTheFuture = 1000; - - TaskEngine.getInstance().schedule(new TimerTask() { - @Override - public void run() { - SwingUtilities.invokeLater( () -> { - for (Presence userToUpdate : new ArrayList<>( initialPresences )) { - initialPresences.remove(userToUpdate); - try { - updateUserPresence(userToUpdate); - } - catch (Exception e) { - Log.error(e); - } - } - } ); - } - }, numberOfMillisecondsInTheFuture); - } - }; - - SparkManager.getConnection().addAsyncStanzaListener(subscribeListener, stanzaFilter); - } - - - public void shutdown() { - saveState(); - } - - public boolean canShutDown() { - return true; - } - - private void addContactListToWorkspace() { - Workspace workspace = SparkManager.getWorkspace(); - workspace.getWorkspacePane().addTab(Res.getString("tab.contacts"), SparkRes.getImageIcon(SparkRes.SMALL_ALL_CHATS_IMAGE), this); - // Add To Contacts Menu - final JMenu contactsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.contacts")); - JMenuItem addContactsMenu = new JMenuItem("", SparkRes.getImageIcon(SparkRes.USER1_ADD_16x16)); - ResourceUtils.resButton(addContactsMenu, Res.getString("menuitem.add.contact")); - ResourceUtils.resButton(addContactGroupMenu, Res.getString("menuitem.add.contact.group")); - - if (!Default.getBoolean(Default.ADD_CONTACT_DISABLED)) { - contactsMenu.add(addContactsMenu); - } - if(!Default.getBoolean("ADD_CONTACT_GROUP_DISABLED")){ - contactsMenu.add(addContactGroupMenu); - } - - addContactsMenu.addActionListener( e -> new RosterDialog().showRosterDialog() ); - - addContactGroupMenu.addActionListener( e -> { - String groupName = JOptionPane.showInputDialog(getGUI(), Res.getString("message.name.of.group") + ":", Res.getString("title.add.new.group"), JOptionPane.QUESTION_MESSAGE); - if (ModelUtil.hasLength(groupName)) { - ContactGroup contactGroup = getContactGroup(groupName); - if (contactGroup == null) { - contactGroup = addContactGroup(groupName); - contactGroup.setVisible(true); - //validateTree(); - repaint(); - } - } - } ); - - // Add Toggle Contacts Menu - ResourceUtils.resButton(showHideMenu, Res.getString("menuitem.show.empty.groups")); - contactsMenu.add(showHideMenu); - - showHideMenu.addActionListener( e -> showEmptyGroups(showHideMenu.isSelected()) ); - - ResourceUtils.resButton(showOfflineGroupMenu, Res.getString("menuitem.show.offline.group")); - contactsMenu.add(showOfflineGroupMenu); - - showOfflineGroupMenu.addActionListener( actionEvent -> showOfflineGroup(showOfflineGroupMenu.isSelected()) ); - - ResourceUtils.resButton(showOfflineUsersMenu, Res.getString("menuitem.show.offline.users")); - contactsMenu.add(showOfflineUsersMenu); - - showOfflineUsersMenu.addActionListener( actionEvent -> showOfflineUsers(showOfflineUsersMenu.isSelected()) ); - - // Show or Hide Offline Group - showOfflineGroupMenu.setSelected(localPreferences.isOfflineGroupVisible()); - showOfflineGroup(localPreferences.isOfflineGroupVisible()); - - // sets showOfflineUsersMenu selected or not selected - showOfflineUsersMenu.setSelected(localPreferences.isOfflineUsersShown()); - - // Initialize vcard support - SparkManager.getVCardManager(); - } - - /** - * Toggles the visibility of empty groups. - * - * @param show true to display empty contact groups within the ContactList, otherwise false. - */ - private void showEmptyGroups(boolean show) { - for (ContactGroup group : getContactGroups()) { - if (group != offlineGroup) { - if (show) { - group.setVisible(true); - } else { - // Never hide offline group. - group.setVisible(group.hasAvailableContacts()); - } - } - } - - localPreferences.setEmptyGroupsShown(show); - showHideMenu.setSelected(show); - SettingsManager.saveSettings(); - } - - private void showOfflineUsers(boolean show) { - for (ContactGroup group : getContactGroups()) - { - if(group != offlineGroup) - { - group.toggleOfflineVisibility(show); - } - - if (group == offlineGroup) { - if (show) - { - group.setVisible(true); - showOfflineGroupMenu.setEnabled(true); - showOfflineGroupMenu.setSelected(localPreferences.isOfflineGroupVisible()); - showOfflineGroup(showOfflineGroupMenu.isSelected()); - } - else - { - group.setVisible(false); - showOfflineGroupMenu.setEnabled(false); - } - } - } - localPreferences.setOfflineUsersShown(show); - SettingsManager.saveSettings(); - } - - /** - * Toggles the visiblity of the Offline Group. - * - * @param show true to display the offline group, otherwise false. - */ - private void showOfflineGroup(boolean show) { - // Save in preferences - localPreferences.setOfflineGroupVisible(show); - SettingsManager.saveSettings(); - - // Toggle Visibility of Offline Group. - offlineGroup.setVisible(show); - - if (show) { - // Remove offline items from all groups. - for (ContactGroup group : getContactGroups()) { - group.toggleOfflineVisibility(false); - } - } - else { - // Remove offline items from all groups. - for (ContactGroup group : getContactGroups()) { - group.toggleOfflineVisibility(true); - } - } - } - - - /** - * Sorts ContactGroups - */ - public static final Comparator GROUP_COMPARATOR = ( group1, group2 ) -> { - // Make sure that offline group is always on bottom. - if (group2.isOfflineGroup()) { - return -1; - } - - return group1.getGroupName().trim().toLowerCase().compareTo(group2.getGroupName().trim().toLowerCase()); - }; - - public JPanel getMainPanel() { - return mainPanel; - } - - public List getContactGroups() { - final List gList = new ArrayList<>( groupList ); - Collections.sort(gList, GROUP_COMPARATOR); - return gList; - } - - private void subscriptionRequest(final String jid) throws SmackException.NotConnectedException - { - final SubscriptionDialog subscriptionDialog = new SubscriptionDialog(); - subscriptionDialog.invoke(jid); - } - - public void addContextMenuListener(ContextMenuListener listener) { - contextListeners.add(listener); - } - - public void removeContextMenuListener(ContextMenuListener listener) { - contextListeners.remove(listener); - } - - public void fireContextMenuListenerPopup(JPopupMenu popup, Object object) { - for (ContextMenuListener listener : new ArrayList<>( contextListeners )) { - listener.poppingUp(object, popup); - } - } - - public JComponent getGUI() { - return this; - } - - public ContactGroup getActiveGroup() { - return activeGroup; - } - - public Collection getSelectedUsers() { - final List list = new ArrayList<>(); - - for (ContactGroup group : getContactGroups()) { - for (ContactItem item : group.getSelectedContacts()) { - list.add(item); - } - } - return list; - } - - /** - * Selects the first user found with specified jid - * @param jid, the Users JID - */ - public void setSelectedUser(String jid) { - for (ContactGroup group : getContactGroups()) { - if (group.getContactItemByJID(jid) != null) { - - ContactItem item = group.getContactItemByJID(jid); - group.getList().setSelectedValue(item, false); - return; - } - } - } - - private void checkGroup(final ContactGroup group) { - try { - EventQueue.invokeLater( () -> { - if (!group.hasAvailableContacts() && group != offlineGroup && group != getUnfiledGroup() && !showHideMenu.isSelected()) { - group.setVisible(false); - } - } ); - } catch (Exception e) { - e.printStackTrace(); - } - - } - - public void addFileDropListener(FileDropListener listener) { - dndListeners.add(listener); - } - - public void removeFileDropListener(FileDropListener listener) { - dndListeners.remove(listener); - } - - public void fireFilesDropped(Collection files, ContactItem item) { - for (FileDropListener fileDropListener : new ArrayList<>( dndListeners )) { - fileDropListener.filesDropped(files, item); - } - } - - public void contactItemAdded(ContactItem item) { - fireContactItemAdded(item); - } - - public void contactItemRemoved(ContactItem item) { - fireContactItemRemoved(item); - } - - /* - Adding ContactListListener support. - */ - - public void addContactListListener(ContactListListener listener) { - contactListListeners.add(listener); - } - - public void removeContactListListener(ContactListListener listener) { - contactListListeners.remove(listener); - } - - public void fireContactItemAdded(ContactItem item) { - for (ContactListListener contactListListener : new ArrayList<>( contactListListeners )) { - contactListListener.contactItemAdded(item); - } - } - - public void fireContactItemRemoved(ContactItem item) { - for (ContactListListener contactListListener : new ArrayList<>( contactListListeners )) { - contactListListener.contactItemRemoved(item); - } - } - - public void fireContactGroupAdded(ContactGroup group) { - for (ContactListListener contactListListener : new ArrayList<>( contactListListeners )) { - contactListListener.contactGroupAdded(group); - } - } - - public void fireContactGroupRemoved(ContactGroup group) { - for (ContactListListener contactListListener : new ArrayList<>( contactListListeners )) { - contactListListener.contactGroupRemoved(group); - } - } - - public void fireContactItemClicked(ContactItem contactItem) { - for (ContactListListener contactListListener : new ArrayList<>( contactListListeners )) { - contactListListener.contactItemClicked(contactItem); - } - } - - public void fireContactItemDoubleClicked(ContactItem contactItem) { - for (ContactListListener contactListListener : new ArrayList<>( contactListListeners )) { - contactListListener.contactItemDoubleClicked(contactItem); - } - } - - - public void uninstall() { - // Do nothing. - } - - public void saveState() { - if (props == null) { - return; - } - for (ContactGroup contactGroup : getContactGroups()) { - props.put(contactGroup.getGroupName(), Boolean.toString(contactGroup.isCollapsed())); - } - - try { - props.store(new FileOutputStream(propertiesFile), "Tracks the state of groups."); - } - catch (IOException e) { - Log.error("Unable to save group properties.", e); - } - - } - - - @Override - public void connected( XMPPConnection xmppConnection ) - { - - } - - @Override - public void authenticated( XMPPConnection xmppConnection, boolean b ) - { - - } - - public void connectionClosed() { - // No reason to reconnect. - - // Show MainWindow - SparkManager.getMainWindow().setVisible(true); - - // Flash That Window. - SparkManager.getNativeManager().flashWindowStopOnFocus( - SparkManager.getMainWindow()); - - String errorMessage = Res.getString("message.disconnected.error"); - - switch (localPreferences.getReconnectPanelType()) { - case 0: - _reconnectPanel.setClosedOnError(false); - _reconnectPanel.setDisconnectReason(errorMessage); - removeAllUsers(); - workspace.changeCardLayout(RETRY_PANEL); - break; - case 1: - switchAllUserOffline(false); - _reconnectpanelsmall.setReconnectText(errorMessage); - break; - - case 2: - switchAllUserOfflineNoGroupEntry(false); - _reconnectpanelicon.setReconnectText(errorMessage); - break; - } - - } - - - - /** - * Reconnect using the Panel with Message - * @param message - */ - private void reconnect(final String message) { - // Show MainWindow - SparkManager.getMainWindow().setVisible(true); - - // Flash That Window. - SparkManager.getNativeManager().flashWindowStopOnFocus( - SparkManager.getMainWindow()); - - switch (localPreferences.getReconnectPanelType()) { - case 0: - workspace.changeCardLayout(RETRY_PANEL); - _reconnectPanel.setDisconnectReason(message); - break; - case 1: - switchAllUserOffline(true); - _reconnectpanelsmall.startReconnecting(); - break; - - case 2: - switchAllUserOfflineNoGroupEntry(true); - _reconnectpanelicon.startReconnecting(); - break; - default: - workspace.changeCardLayout(RETRY_PANEL); - } - - removeAllUsers(); - } - - public void clientReconnected() { - - switch (localPreferences.getReconnectPanelType()) { - case 0: - workspace.changeCardLayout(Workspace.WORKSPACE_PANE); - break; - case 1: - mainPanel.remove(_reconnectpanelsmall); - break; - - case 2: - SwingWorker sw = new SwingWorker() { - @Override - public Object construct() { - _reconnectpanelicon.remove(); - _reconnectpanelicon.getPanel().revalidate(); - return 42; - } - }; - sw.start(); - break; - } - - offlineGroup.fireContactGroupUpdated(); - buildContactList(); - - final Presence myPresence = SparkManager.getWorkspace().getStatusBar() - .getPresence(); - SparkManager.getSessionManager().changePresence(myPresence); - - } - - public void connectionClosedOnError(final Exception ex) { - String errorMessage = Res.getString("message.disconnected.error"); - - if (ex != null && ex instanceof XMPPException.StreamErrorException) { - XMPPException.StreamErrorException xmppEx = (XMPPException.StreamErrorException) ex; - switch (xmppEx.getStreamError().getCondition()) - { - case conflict: - errorMessage = Res.getString("message.disconnected.conflict.error"); - break; - - case system_shutdown: - errorMessage = Res.getString("message.disconnected.shutdown"); - break; - - default: - errorMessage = Res.getString("message.general.error", xmppEx.getStreamError().getConditionText()); - break; - } - } - - switch (localPreferences.getReconnectPanelType()) { - case 0: - final String message = errorMessage; - SwingUtilities.invokeLater( () -> { - _reconnectPanel.setClosedOnError(true); - reconnect(message); - } ); - break; - case 1: - switchAllUserOffline(true); - _reconnectpanelsmall.setReconnectText(errorMessage); - break; - - case 2: - switchAllUserOfflineNoGroupEntry(true); - _reconnectpanelicon.setReconnectText(errorMessage); - break; - - } - } - - private void removeAllUsers() { - // Behind the scenes, move everyone to the offline group. - for (ContactGroup contactGroup : new ArrayList<>( getContactGroups() )) { - contactGroup.removeAllContacts(); - } - - } - - public void reconnectingIn(int i) { - - switch (localPreferences.getReconnectPanelType()) { - case 0: - if (i == 0) { - _reconnectPanel.setReconnectText(Res - .getString("message.reconnect.attempting")); - } else { - _reconnectPanel.setReconnectText(Res.getString( - "message.reconnect.wait", i)); - } - break; - - case 1: - if (i == 0) { - _reconnectpanelsmall.setReconnectText(Res - .getString("message.reconnect.attempting")); - } else { - _reconnectpanelsmall.setReconnectText(Res.getString( - "message.reconnect.wait", i)); - } - break; - - case 2: - if (i == 0) { - _reconnectpanelicon.setReconnectText(Res - .getString("message.reconnect.attempting")); - } else { - _reconnectpanelicon.setReconnectText(Res.getString( - "message.reconnect.wait", i)); - } - break; - } - - } - - public void reconnectionSuccessful() { - clientReconnected(); - } - - public void reconnectionFailed(Exception exception) { - - switch (localPreferences.getReconnectPanelType()) { - - case 0: - _reconnectPanel.setReconnectText(Res - .getString("message.reconnect.failed")); - break; - case 1: - _reconnectpanelsmall.setReconnectText(Res - .getString("message.reconnect.failed")); - break; - case 2: - _reconnectpanelicon.setReconnectText(Res - .getString("message.reconnect.failed")); - break; - } - - } - - /** - * Moves a ContactItem to an offline state. - * - * @param contactItem the ContactItem. - */ - private void moveToOffline(ContactItem contactItem) { - offlineGroup.addContactItem(contactItem); - - String jid = contactItem.getJID(); - Boolean isFiled = false; - - final Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - for (RosterGroup group : roster.getEntry(jid).getGroups()) { - ContactGroup contactGroup = getContactGroup(group.getName()); - if(contactGroup == null && !Objects.equals( group.getName(), "" ) ){ - contactGroup = addContactGroup(group.getName()); - } - if (contactGroup != null) { - isFiled = true; - contactGroup.addOfflineContactItem(contactItem.getAlias(), contactItem.getNickname(), contactItem.getJID(), contactItem.getStatus()); - } - } - if (!isFiled) { - getUnfiledGroup().addOfflineContactItem(contactItem.getAlias(), contactItem.getNickname(), contactItem.getJID(), contactItem.getStatus()); - } - - if( !localPreferences.isOfflineUsersShown() ) - { - for (ContactGroup group : getContactGroups()) - { - if(group != offlineGroup) - { - group.toggleOfflineVisibility(false); - } - } - } - } - - private ContactGroup getUnfiledGroup() { - if (unfiledGroup == null) { - // Add Unfiled Group - if(EventQueue.isDispatchThread()) { - unfiledGroup = UIComponentRegistry.createContactGroup(Res.getString("unfiled")); - addContactGroup(unfiledGroup); - } - else { - try { - EventQueue.invokeAndWait( () -> { - unfiledGroup = UIComponentRegistry.createContactGroup(Res.getString("unfiled")); - addContactGroup(unfiledGroup); - } ); - }catch(Exception ex) { - ex.printStackTrace(); - } - } - } - return unfiledGroup; - } - - /** - * Sorts ContactItems. - */ - public final static Comparator ContactItemComparator = ( item1, item2 ) -> item1.getDisplayName().toLowerCase().compareTo(item2.getDisplayName().toLowerCase()); - public void showAddContact(String contact) - { - addContactMenu.doClick(); - }; - - public ContactItem getActiveItem() { - return activeItem; - } -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/spark/ui/ContainerComponent.java b/src/java/org/jivesoftware/spark/ui/ContainerComponent.java deleted file mode 100644 index 92f000c63..000000000 --- a/src/java/org/jivesoftware/spark/ui/ContainerComponent.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import javax.swing.ImageIcon; -import javax.swing.JComponent; - -/** - * - */ -public interface ContainerComponent { - - public abstract String getTabTitle(); - - public abstract String getFrameTitle(); - - public abstract ImageIcon getTabIcon(); - - public abstract JComponent getGUI(); - - public abstract String getToolTipDescription(); - - public abstract boolean closing(); -} diff --git a/src/java/org/jivesoftware/spark/ui/DataFormUI.java b/src/java/org/jivesoftware/spark/ui/DataFormUI.java deleted file mode 100644 index 604f7145f..000000000 --- a/src/java/org/jivesoftware/spark/ui/DataFormUI.java +++ /dev/null @@ -1,215 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import org.jivesoftware.smackx.xdata.Form; -import org.jivesoftware.smackx.xdata.FormField; -import org.jivesoftware.spark.component.CheckBoxList; -import org.jivesoftware.spark.util.ModelUtil; - -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JPasswordField; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.JTextField; - -import java.awt.Component; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.StringTokenizer; - -/** - * Builds the UI for any DataForm (JEP-0004: Data Forms), and allow for creation - * of an answer form to send back the the server. - */ -public class DataFormUI extends JPanel { - private static final long serialVersionUID = -6313707846021436765L; - private final Map valueMap = new HashMap<>(); - private int row = 5; - private Form searchForm; - - /** - * Creates a new DataFormUI - * - * @param form the DataForm to build a UI with. - */ - public DataFormUI(Form form) { - this.setLayout(new GridBagLayout()); - this.searchForm = form; - - buildUI(form); - - this.add(new JLabel(), new GridBagConstraints(0, row, 3, 1, 0.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); - } - - - private void buildUI(Form form) { - // Add default answers to the form to submit - for ( final FormField field : form.getFields() ) { - String variable = field.getVariable(); - String label = field.getLabel(); - FormField.Type type = field.getType(); - - - List valueList =field.getValues(); - - if (type.equals(FormField.Type.bool)) { - String o = valueList.get(0); - boolean isSelected = o.equals("1"); - JCheckBox box = new JCheckBox(label); - box.setSelected(isSelected); - addField(label, box, variable); - } - else if (type.equals(FormField.Type.text_single) || type.equals(FormField.Type.jid_single)) { - String v = ""; - if (valueList.size() > 0) { - v = valueList.get(0); - } - addField(label, new JTextField(v), variable); - } - else if (type.equals(FormField.Type.text_multi) || - type.equals(FormField.Type.jid_multi)) { - StringBuilder buf = new StringBuilder(); - for ( FormField.Option option : field.getOptions() ) { - buf.append(option); - } - addField(label, new JTextArea(buf.toString()), variable); - } - else if (type.equals(FormField.Type.text_private)) { - addField(label, new JPasswordField(), variable); - } - else if (type.equals(FormField.Type.list_single)) { - JComboBox box = new JComboBox(); - for ( final FormField.Option option : field.getOptions() ) { - box.addItem(option); - } - if (valueList.size() > 0) { - String defaultValue = valueList.get(0); - box.setSelectedItem(defaultValue); - } - - addField(label, box, variable); - } - else if (type.equals(FormField.Type.list_multi)) { - CheckBoxList checkBoxList = new CheckBoxList(); - for ( final String value : field.getValues() ) { - checkBoxList.addCheckBox(new JCheckBox(value), value); - } - addField(label, checkBoxList, variable); - } - } - } - - /** - * Returns the answered DataForm. - * - * @return the answered DataForm. - */ - public Form getFilledForm() { - // Now submit all information - Iterator valueIter = valueMap.keySet().iterator(); - Form answerForm = searchForm.createAnswerForm(); - while (valueIter.hasNext()) { - String answer = valueIter.next(); - Object o = valueMap.get(answer); - if (o instanceof JCheckBox) { - boolean isSelected = ((JCheckBox)o).isSelected(); - answerForm.setAnswer(answer, isSelected); - } - else if (o instanceof JTextArea) { - List list = new ArrayList<>(); - String value = ((JTextArea)o).getText(); - StringTokenizer tokenizer = new StringTokenizer(value, ", ", false); - while (tokenizer.hasMoreTokens()) { - list.add(tokenizer.nextToken()); - } - if (list.size() > 0) { - answerForm.setAnswer(answer, list); - } - } - else if (o instanceof JTextField) { - String value = ((JTextField)o).getText(); - if (ModelUtil.hasLength(value)) { - answerForm.setAnswer(answer, value); - } - } - else if (o instanceof JComboBox) { - Object v = ((JComboBox)o).getSelectedItem(); - String value; - if (v instanceof FormField.Option) { - value = ((FormField.Option)v).getValue(); - } - else { - value = (String)v; - } - List list = new ArrayList<>(); - list.add(value); - if (list.size() > 0) { - answerForm.setAnswer(answer, list); - } - } - else if (o instanceof CheckBoxList) { - List list = ((CheckBoxList)o).getSelectedValues(); - if (list.size() > 0) { - answerForm.setAnswer(answer, list); - } - } - } - - return answerForm; - } - - - private void addField(String label, JComponent comp, String variable) { - if (!(comp instanceof JCheckBox)) { - this.add(new JLabel(label), new GridBagConstraints(0, row, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - } - if (comp instanceof JTextArea) { - this.add(new JScrollPane(comp), new GridBagConstraints(1, row, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 100, 50)); - } - else if (comp instanceof JCheckBox) { - this.add(comp, new GridBagConstraints(0, row, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - } - else if (comp instanceof CheckBoxList) { - this.add(comp, new GridBagConstraints(1, row, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 50)); - } - else { - this.add(comp, new GridBagConstraints(1, row, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - } - valueMap.put(variable, comp); - row++; - } - - public Component getComponent(String label) { - return valueMap.get(label); - } -} - diff --git a/src/java/org/jivesoftware/spark/ui/GroupChatRoomTransferHandler.java b/src/java/org/jivesoftware/spark/ui/GroupChatRoomTransferHandler.java deleted file mode 100644 index caffedd83..000000000 --- a/src/java/org/jivesoftware/spark/ui/GroupChatRoomTransferHandler.java +++ /dev/null @@ -1,92 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import org.jivesoftware.spark.ui.rooms.GroupChatRoom; -import org.jivesoftware.spark.util.log.Log; - -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.Transferable; - -import javax.swing.JComponent; -import javax.swing.TransferHandler; - -/** - * Handler for drag and dropping of files unto a ChatWindow. - */ -public class GroupChatRoomTransferHandler extends TransferHandler { - private static final long serialVersionUID = -192689038331188379L; - private GroupChatRoom groupChatRoom; - private static final DataFlavor flavors[] = {DataFlavor.imageFlavor}; - - /** - * Creates a transfer handler for the given GroupChatRoom - * - * @param chatRoom the GroupChatRoom. - */ - public GroupChatRoomTransferHandler(GroupChatRoom chatRoom) { - this.groupChatRoom = chatRoom; - } - - public int getSourceActions(JComponent c) { - return TransferHandler.COPY; - } - - - public boolean canImport(JComponent comp, DataFlavor flavor[]) { - for (int i = 0, n = flavor.length; i < n; i++) { - for (int j = 0, m = flavors.length; j < m; j++) { - if (flavor[i].equals(flavors[j])) { - return true; - } - } - } - return false; - } - - protected void exportDone(JComponent c, Transferable data, int action) { - } - - - public Transferable createTransferable(JComponent comp) { - return null; - } - - public boolean importData(JComponent comp, Transferable t) { - if (t.isDataFlavorSupported(flavors[0])) { - try { - final Object o = t.getTransferData(flavors[0]); - if (o instanceof ContactItem) { - // Invite User - final ContactItem contactItem = (ContactItem)o; - String jid = contactItem.getJID(); - groupChatRoom.inviteUser(jid, "Please join the conference room."); - - return true; - } - } - catch (Exception e) { - Log.error(e); - } - } - - return false; - } -} diff --git a/src/java/org/jivesoftware/spark/ui/RawPacketSender.java b/src/java/org/jivesoftware/spark/ui/RawPacketSender.java deleted file mode 100644 index 0be08bb65..000000000 --- a/src/java/org/jivesoftware/spark/ui/RawPacketSender.java +++ /dev/null @@ -1,131 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.FlowLayout; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.packet.Stanza; -import org.jivesoftware.spark.SparkManager; - -/** - * Class to Send Raw packets useful when debugging - * - * @author wolf.posdorfer - * - */ -public class RawPacketSender implements ActionListener { - - private JFrame _mainframe; - private JPanel _mainpanel; - - private JScrollPane _textscroller; - - private JTextArea _textarea; - private JTextArea _inputarea; - private JButton _sendButton; - private JButton _clear; - - public RawPacketSender() { - - _mainframe = new JFrame("Send Raw Packets"); - _mainframe.setIconImage(SparkRes.getImageIcon(SparkRes.MAIN_IMAGE) - .getImage()); - _mainpanel = new JPanel(); - _mainpanel.setLayout(new GridLayout(2, 1)); - _textarea = new JTextArea(); - _inputarea = new JTextArea(); - _textscroller = new JScrollPane(_textarea); - _sendButton = new JButton("Send", - SparkRes.getImageIcon(SparkRes.SMALL_CHECK)); - _clear = new JButton("Clear", - SparkRes.getImageIcon(SparkRes.SMALL_DELETE)); - - createGUI(); - - } - - private void createGUI() { - - JPanel southpanel = new JPanel(new BorderLayout()); - southpanel.add(_inputarea, BorderLayout.CENTER); - - JPanel buttonpanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); - buttonpanel.add(_clear); - buttonpanel.add(_sendButton); - southpanel.add(buttonpanel, BorderLayout.SOUTH); - - _sendButton.addActionListener(this); - _clear.addActionListener(this); - - _textarea.setBackground(Color.LIGHT_GRAY); - _mainpanel.add(_textscroller); - _mainpanel.add(southpanel); - - _mainframe.add(_mainpanel); - _mainframe.setSize(500, 500); - _mainframe.setLocationRelativeTo(null); - _mainframe.setVisible(true); - - } - - @Override - public void actionPerformed(ActionEvent e) { - - if (e.getSource().equals(_sendButton)) { - Stanza stanza = new Stanza() { - - @Override - public String toXML() { - return _inputarea.getText(); - } - }; - - try { - SparkManager.getConnection().sendStanza(stanza); - _textarea.append("\n" + _inputarea.getText()); - } catch (Exception exc) { - - } - } - else if (e.getSource().equals(_clear)) { - _textarea.setText(""); - } - - } - -// -// BUUUUUZ and Attention -// -// -// - -} diff --git a/src/java/org/jivesoftware/spark/ui/ReconnectPanel.java b/src/java/org/jivesoftware/spark/ui/ReconnectPanel.java deleted file mode 100644 index c33cc3e52..000000000 --- a/src/java/org/jivesoftware/spark/ui/ReconnectPanel.java +++ /dev/null @@ -1,193 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import java.awt.Color; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.util.TimerTask; - -import javax.swing.JEditorPane; -import javax.swing.JPanel; -import javax.swing.text.html.HTMLEditorKit; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.AbstractXMPPConnection; -import org.jivesoftware.smack.ConnectionListener; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.SwingTimerTask; -import org.jivesoftware.spark.util.TaskEngine; - -/** - * RetryPanel is the UI/Function class to handle reconnection logic. This allows for a simple card layout to replace the current - * roster when the connection has been lost. - * - * @author Derek DeMoro - */ -public class ReconnectPanel extends JPanel implements ConnectionListener { - private static final long serialVersionUID = -7099075581561760774L; - private JEditorPane pane; - private RolloverButton retryButton; - private boolean closedOnError; - - /** - * Construct the RetryPanel. - */ - public ReconnectPanel() { - setLayout(new GridBagLayout()); - - // Init Components - pane = new JEditorPane(); - pane.setBackground(Color.white); - pane.setEditorKit(new HTMLEditorKit()); - pane.setEditable(false); - - retryButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.SMALL_CHECK)); - - layoutComponents(); - - retryButton.addActionListener( actionEvent -> attemptReconnection() ); - - - setBackground(Color.white); - - retryButton.setText(Res.getString("button.reconnect2")); - - SparkManager.getConnection().addConnectionListener(this); - } - - private void attemptReconnection() { - retryButton.setText(Res.getString("message.reconnect.attempting")); - retryButton.setEnabled(false); - - TimerTask task = new SwingTimerTask() { - public void doRun() { - reconnect(); - } - }; - - TaskEngine.getInstance().schedule(task, 100); - } - - private void reconnect() { - try { - if (closedOnError) { - ((AbstractXMPPConnection)SparkManager.getConnection()).connect(); - } - else { - SparkManager.getMainWindow().logout(false); - } - } - catch (Exception ex) { - ex.printStackTrace(); - } - } - - - /** - * Sets the reason the user was disconnected from the server. - * - * @param reason the reason the user was disconnected from the server. - */ - public void setDisconnectReason(String reason) { - if (!ModelUtil.hasLength(reason)) { - reason = Res.getString("message.generic.reconnect.message"); - } - - String builder = "
        " + - "" + - reason + - "" + - "
        "; - - pane.setText( builder ); - } - - private void layoutComponents() { - add(pane, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - - add(retryButton, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - } - - /** - * Starts the countdown to the next retry attempt. The retry attemp is set for every 45 seconds or what is set - * as the default in preferences. - * - * @param text the text to display on the reconnect button. - */ - protected void setReconnectText(String text) { - retryButton.setVisible(true); - retryButton.setText(text); - } - - /** - * Changes the UI to handle when a conflict occurs on the server. - */ - public void showConflict() { - retryButton.setVisible(false); - } - - public void setClosedOnError(boolean onError) { - closedOnError = onError; - } - - - @Override - public void connected( XMPPConnection xmppConnection ) - { - retryButton.setVisible(false); - retryButton.setEnabled(true); - } - - @Override - public void authenticated( XMPPConnection xmppConnection, boolean b ) - { - retryButton.setVisible(false); - retryButton.setEnabled(true); - } - - public void connectionClosed() { - retryButton.setVisible(true); - retryButton.setEnabled(true); - } - - public void connectionClosedOnError(Exception e) { - retryButton.setVisible(true); - retryButton.setEnabled(true); - } - - public void reconnectingIn(int seconds) { - } - - public void reconnectionSuccessful() { - retryButton.setVisible(false); - retryButton.setEnabled(true); - } - - public void reconnectionFailed(Exception e) { - retryButton.setVisible(true); - retryButton.setEnabled(true); - } -} diff --git a/src/java/org/jivesoftware/spark/ui/ReconnectPanelIcon.java b/src/java/org/jivesoftware/spark/ui/ReconnectPanelIcon.java deleted file mode 100644 index 63328bc4c..000000000 --- a/src/java/org/jivesoftware/spark/ui/ReconnectPanelIcon.java +++ /dev/null @@ -1,155 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import java.util.TimerTask; - -import javax.swing.JButton; -import javax.swing.JPanel; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.AbstractXMPPConnection; -import org.jivesoftware.smack.ConnectionListener; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.util.SwingTimerTask; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.TaskEngine; - -/** - * Used for silent reconnecting
        - * Displays a little Icon at first position in commandpanel - * - * @author wolf.posdorfer - * - */ -public class ReconnectPanelIcon implements ConnectionListener { - - private static final long serialVersionUID = 437696141257704105L; - private RolloverButton _button; - private JPanel _commandpanel; - private boolean _closedOnError; - - /** - * creates a new Panel - */ - public ReconnectPanelIcon() { - - _commandpanel = SparkManager.getWorkspace().getCommandPanel(); - - _button = new RolloverButton(SparkRes.getImageIcon(SparkRes.BUSY_IMAGE)); - - _button.addActionListener( e -> startReconnecting() ); - } - - public JPanel getPanel() { - return _commandpanel; - } - - public JButton getButton() { - return _button; - } - - /** - * Starts the Timer for Icon-reconnection - */ - public void startReconnecting() { - if (!SparkManager.getConnection().isConnected()) { - TimerTask task = new SwingTimerTask() { - public void doRun() { - reconnect(); - } - }; - TaskEngine.getInstance().schedule(task, 100); - } - - SparkManager.getPreferenceManager(); - - } - - public void setClosedOnError(boolean onError) { - _closedOnError = onError; - } - - /** - * Reconnect Thread - */ - private void reconnect() { - try { - if (_closedOnError) { - ((AbstractXMPPConnection) SparkManager.getConnection()).connect(); - } else { - SparkManager.getMainWindow().logout(false); - } - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public void setReconnectText(String text) { - _button.setToolTipText(text); - } - - public void remove() { - SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - return 42; - } - - @Override - public void finished() { - _commandpanel.remove(_button); - } - }; - worker.start(); - - } - - @Override - public void connected( XMPPConnection xmppConnection ) { - } - - @Override - public void authenticated( XMPPConnection xmppConnection, boolean b ) { - } - - @Override - public void connectionClosed() { - } - - @Override - public void connectionClosedOnError(Exception e) { - } - - @Override - public void reconnectingIn(int seconds) { - } - - @Override - public void reconnectionSuccessful() { - } - - @Override - public void reconnectionFailed(Exception e) { - } - -} diff --git a/src/java/org/jivesoftware/spark/ui/ReconnectPanelSmall.java b/src/java/org/jivesoftware/spark/ui/ReconnectPanelSmall.java deleted file mode 100644 index 6e4c81c68..000000000 --- a/src/java/org/jivesoftware/spark/ui/ReconnectPanelSmall.java +++ /dev/null @@ -1,179 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import java.awt.Component; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.util.TimerTask; - -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; -import javax.swing.SwingUtilities; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.AbstractXMPPConnection; -import org.jivesoftware.smack.ConnectionListener; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.util.SwingTimerTask; -import org.jivesoftware.spark.util.TaskEngine; - -/** - * Used for silent reconnecting
        - * Displays a reconnection dialog as a ContactGroup at the Top - * - * @author wolf.posdorfer - * - */ -public class ReconnectPanelSmall extends ContactGroup implements - ConnectionListener { - - private static final long serialVersionUID = 437696141257704105L; - private JLabel _reconnectionlabel = new JLabel( - Res.getString("message.reconnect.attempting"), - SparkRes.getImageIcon(SparkRes.BUSY_IMAGE), 0); - private Component thiscomp; - private boolean _closedOnError; - - /** - * creates a new Panel - * - * @param groupName - */ - public ReconnectPanelSmall(String groupName) { - super(groupName); - this.add(_reconnectionlabel); - this.setIcon(SparkRes.getImageIcon(SparkRes.BUSY_IMAGE)); - thiscomp = this; - - _reconnectionlabel.addMouseListener(new MouseListener() { - - @Override - public void mouseReleased(MouseEvent e) { - } - - @Override - public void mousePressed(MouseEvent e) { - } - - @Override - public void mouseExited(MouseEvent e) { - } - - @Override - public void mouseEntered(MouseEvent e) { - } - - @Override - public void mouseClicked(MouseEvent e) { - - if (SwingUtilities.isLeftMouseButton(e)) { - reconnect(); - } else if (SwingUtilities.isRightMouseButton(e)) { - - int x = e.getX(); - int y = e.getY(); - - final JPopupMenu popupmenu = new JPopupMenu(); - final JMenuItem reconnect = new JMenuItem(Res.getString( - "button.reconnect").replace("&", "")); - reconnect.setIcon(SparkRes - .getImageIcon(SparkRes.SMALL_CHECK)); - popupmenu.add(reconnect); - - reconnect.addActionListener( e1 -> reconnect() ); - - popupmenu.show(thiscomp, x, y); - } - } - }); - } - - /** - * Starts the Timer for no-panel-reconnection - */ - public void startReconnecting() { - - if (!SparkManager.getConnection().isConnected()) { - TimerTask task = new SwingTimerTask() { - public void doRun() { - reconnect(); - } - }; - TaskEngine.getInstance().schedule(task, 100); - } - } - - public void setClosedOnError(boolean onError) { - _closedOnError = onError; - } - - /** - * Reconnect Thread - */ - private void reconnect() { - try { - if (_closedOnError) { - ((AbstractXMPPConnection) SparkManager.getConnection()).connect(); - } else { - SparkManager.getMainWindow().logout(false); - } - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public void setReconnectText(String text) { - String s = "" + text + ""; - _reconnectionlabel.setText(s); - } - - @Override - public void connected( XMPPConnection xmppConnection ) { - } - - @Override - public void authenticated( XMPPConnection xmppConnection, boolean b ) { - } - - @Override - public void connectionClosed() { - } - - @Override - public void connectionClosedOnError(Exception e) { - } - - @Override - public void reconnectingIn(int seconds) { - } - - @Override - public void reconnectionSuccessful() { - } - - @Override - public void reconnectionFailed(Exception e) { - } - -} diff --git a/src/java/org/jivesoftware/spark/ui/RosterDialog.java b/src/java/org/jivesoftware/spark/ui/RosterDialog.java deleted file mode 100644 index c8d9e6658..000000000 --- a/src/java/org/jivesoftware/spark/ui/RosterDialog.java +++ /dev/null @@ -1,686 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Vector; - -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JTextField; -import javax.swing.UIManager; - -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.roster.Roster; -import org.jivesoftware.smack.roster.RosterEntry; -import org.jivesoftware.smack.roster.RosterGroup; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.xdata.Form; -import org.jivesoftware.smackx.search.ReportedData; -import org.jivesoftware.smackx.vcardtemp.packet.VCard; -import org.jivesoftware.smackx.search.UserSearchManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.UserManager; -import org.jivesoftware.spark.component.TitlePanel; -import org.jivesoftware.spark.component.borders.ComponentTitledBorder; -import org.jivesoftware.spark.component.renderer.JPanelRenderer; -import org.jivesoftware.spark.search.SearchManager; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.gateways.Gateway; -import org.jivesoftware.sparkimpl.plugin.gateways.transports.Transport; -import org.jivesoftware.sparkimpl.plugin.gateways.transports.TransportUtils; -import org.jxmpp.util.XmppStringUtils; - - -/** - * The RosterDialog is used to add new users to the users XMPP Roster. - */ -public class RosterDialog implements ActionListener { - private JPanel panel; - private JTextField jidField; - private JTextField nicknameField; - private final Vector groupModel = new Vector<>(); - - private JComboBox groupBox; - private JComboBox accounts; - private JDialog dialog; - private ContactList contactList; - private JCheckBox publicBox; - private JButton _searchForName ; - private Collection _usersearchservice; - - /** - * Create a new instance of RosterDialog. - */ - public RosterDialog() { - contactList = SparkManager.getWorkspace().getContactList(); - - _usersearchservice = SearchManager.getInstance().getSearchServicesAsString(); - - panel = new JPanel(); - JLabel contactIDLabel = new JLabel(); - jidField = new JTextField(); - JLabel nicknameLabel = new JLabel(); - nicknameField = new JTextField(); - JLabel groupLabel = new JLabel(); - groupBox = new JComboBox(groupModel); - - JButton newGroupButton = new JButton(); - - JLabel accountsLabel = new JLabel(); - accounts = new JComboBox(); - publicBox = new JCheckBox(Res.getString("label.user.on.public.network")); - - ResourceUtils.resLabel(accountsLabel, publicBox, Res.getString("label.network")); - - _searchForName = new JButton(); - _searchForName.setIcon(SparkRes.getImageIcon(SparkRes.TRANSFER_IMAGE_24x24)); - - _searchForName.addMouseListener(new MouseListener() { - @Override - public void mouseClicked(MouseEvent e) { - try { - searchForContact(jidField.getText(), e); - } catch (XMPPException | SmackException e1) { - Log.error("search contact", e1); - } - } - - @Override - public void mouseReleased(MouseEvent e) { - } - - @Override - public void mousePressed(MouseEvent e) { - } - - @Override - public void mouseExited(MouseEvent e) { - } - - @Override - public void mouseEntered(MouseEvent e) { - } - }); - - dialog = null; - panel.setLayout(new GridBagLayout()); - panel.add(contactIDLabel, new GridBagConstraints(0, 0, 1, 1, 0.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); - panel.add(jidField , new GridBagConstraints(1, 0, 1, 1, 1.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); - panel.add(_searchForName, new GridBagConstraints(2, 0, 1, 1, 0.0D, 0.0D, 17, 0, new Insets(5, 5, 5, 5), 0, 0)); - - - panel.add(nicknameLabel, new GridBagConstraints(0, 1, 1, 1, 0.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); - panel.add(nicknameField, new GridBagConstraints(1, 1, 1, 1, 1.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); - - - JPanel networkPanel = new JPanel( new GridBagLayout() ); - ComponentTitledBorder componentBorder = new ComponentTitledBorder(publicBox, networkPanel - , BorderFactory.createEtchedBorder()); - - - networkPanel.add(accountsLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); - networkPanel.add(accounts, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); - - networkPanel.setBorder(componentBorder); - - networkPanel.setVisible(false); - accounts.setEnabled(false); - - - panel.add(groupLabel, new GridBagConstraints(0, 4, 1, 1, 0.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); - - panel.add(groupBox, new GridBagConstraints(1, 4, 1, 1, 1.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); - - if(!Default.getBoolean("ADD_CONTACT_GROUP_DISABLED")){ - panel.add(newGroupButton, new GridBagConstraints(2, 4, 1, 1, 0.0D, 0.0D, 17, 1, new Insets(5, 5, 5, 5), 0, 0)); - } - newGroupButton.addActionListener(this); - - panel.add( networkPanel, new GridBagConstraints(0, 5, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - - ResourceUtils.resLabel(contactIDLabel, jidField, Res.getString("label.username") + ":"); - ResourceUtils.resLabel(nicknameLabel, nicknameField, Res.getString("label.nickname") + ":"); - ResourceUtils.resLabel(groupLabel, groupBox, Res.getString("label.group") + ":"); - ResourceUtils.resButton(newGroupButton, Res.getString("button.new")); - - accounts.setRenderer(new JPanelRenderer()); - - for (ContactGroup group : contactList.getContactGroups()) { - if (!group.isOfflineGroup() && !Res.getString("unfiled").equalsIgnoreCase(group.getGroupName()) && !group.isSharedGroup()) { - groupModel.add(group.getGroupName()); - } - } - - - groupBox.setEditable(true); - - if (groupModel.size() == 0) { - groupBox.addItem("Friends"); - } - - if (groupModel.size() > 0) { - groupBox.setSelectedIndex(0); - } - - jidField.addFocusListener(new FocusListener() { - public void focusGained(FocusEvent e) { - - } - - public void focusLost(FocusEvent e) { - String jid = getJID(); - String vcardNickname = null; - - if (!publicBox.isSelected()) { - // This is not a transport. - String fullJID = getJID(); - if ( !fullJID.contains( "@" ) ) { - fullJID = fullJID + "@" + SparkManager.getConnection().getServiceName(); - } - - vcardNickname = SparkManager.getUserManager().getNickname(fullJID); - } - - String nickname = nicknameField.getText(); - if (!ModelUtil.hasLength(nickname) && ModelUtil.hasLength(jid)) { - nickname = XmppStringUtils.parseLocalpart(jid); - if (!ModelUtil.hasLength(nickname)) { - nickname = jid; - } - - nicknameField.setText(vcardNickname != null ? vcardNickname : nickname); - } - } - }); - - final List accountCol = getAccounts(); - for (AccountItem item : accountCol) { - accounts.addItem(item); - } - - if (accountCol.size() > 0) { - accountsLabel.setVisible(true); - accounts.setVisible(true); - publicBox.setVisible(true); - networkPanel.setVisible(true); - } - - publicBox.addActionListener( actionEvent -> accounts.setEnabled(publicBox.isSelected()) ); - - - } - - /** - * Sets the default ContactGroup to display in the combo box. - * - * @param contactGroup the default ContactGroup. - */ - public void setDefaultGroup(ContactGroup contactGroup) { - String groupName = contactGroup.getGroupName(); - if (groupModel.contains(groupName)) { - groupBox.setSelectedItem(groupName); - } - else if (groupModel.size() > 0) { - groupBox.addItem(groupName); - groupBox.setSelectedItem(groupName); - } - } - - /** - * Sets the default jid to show in the jid field. - * - * @param jid the jid. - */ - public void setDefaultJID(String jid) { - jidField.setText(jid); - } - - /** - * Sets the default nickname to show in the nickname field. - * - * @param nickname the nickname. - */ - public void setDefaultNickname(String nickname) { - nicknameField.setText(nickname); - } - - - public void actionPerformed(ActionEvent e) { - String group = JOptionPane.showInputDialog(dialog, Res.getString("label.enter.group.name") + ":", Res.getString("title.new.roster.group"), 3); - if (group != null && group.length() > 0 && !groupModel.contains(group)) { - Roster.getInstanceFor( SparkManager.getConnection() ).createGroup(group); - groupModel.add(group); - int size = groupModel.size(); - groupBox.setSelectedIndex(size - 1); - } - } - - /** - * Display the RosterDialog using a parent container. - * - * @param parent the parent Frame. - */ - public void showRosterDialog(JFrame parent) { - TitlePanel titlePanel = new TitlePanel(Res.getString("title.add.contact"), Res.getString("message.add.contact.to.list"), null, true); - - - JPanel mainPanel = new JPanel() { - private static final long serialVersionUID = -7489967438182277375L; - - public Dimension getPreferredSize() { - final Dimension size = super.getPreferredSize(); - size.width = 450; - return size; - } - }; - - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(titlePanel, BorderLayout.NORTH); - mainPanel.add(panel, BorderLayout.CENTER); - - JButton addbutton = new JButton(Res.getString("add")); - - addbutton.addActionListener( e -> addContactButton() ); - - JButton cancelbutton = new JButton(Res.getString("cancel")); - cancelbutton.addActionListener( e -> dialog.dispose() ); - - - JPanel buttonpanel = new JPanel(new FlowLayout()); - buttonpanel.add(addbutton); - buttonpanel.add(cancelbutton); - mainPanel.add(buttonpanel, BorderLayout.SOUTH); - - dialog = new JDialog(parent, Res.getString("title.add.contact"), false); - dialog.setContentPane(mainPanel); - dialog.pack(); - - dialog.setLocationRelativeTo(parent); - - dialog.setVisible(true); - dialog.toFront(); - dialog.requestFocus(); - - jidField.requestFocus(); - } - - /** - * Display the RosterDialog using the MainWindow as the parent. - */ - public void showRosterDialog() { - showRosterDialog(SparkManager.getMainWindow()); - } - - private void addEntry() { - Transport transport = null; - AccountItem item; - if (publicBox.isSelected()) { - item = (AccountItem)accounts.getSelectedItem(); - transport = item.getTransport(); - } - if (transport == null) { - String jid = getJID(); - if ( !jid.contains( "@" ) ) { - jid = jid + "@" + SparkManager.getConnection().getServiceName(); - } - String nickname = nicknameField.getText(); - String group = (String)groupBox.getSelectedItem(); - - jid = UserManager.escapeJID(jid); - - // Add as a new entry - addRosterEntry(jid, nickname, group); - } - else { - String jid = getJID(); - try { - jid = Gateway.getJID(transport.getServiceName(), jid); - } - catch (SmackException e) { - Log.error(e); - } - - String nickname = nicknameField.getText(); - String group = (String)groupBox.getSelectedItem(); - addRosterEntry(jid, nickname, group); - } - } - - /** - * Returns the trimmed version of the JID. - * - * @return the trimmed version. - */ - private String getJID() { - return jidField.getText().trim(); - } - - private void addRosterEntry(final String jid, final String nickname, final String group) { - final SwingWorker rosterEntryThread = new SwingWorker() { - public Object construct() { - return addEntry(jid, nickname, group); - } - - public void finished() { - if (get() == null) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(dialog, Res.getString("label.unable.to.add.contact"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - } - } - - }; - - rosterEntryThread.start(); - } - - /** - * Creates a Popupdialog above the Search Button displaying matching - * Contacts - * - * @param byname - * , the Searchname, atleast 5 Chars long - * @param event - * , the MouseEvent which triggered it - * @throws XMPPException - */ - public void searchForContact(String byname, MouseEvent event) - throws XMPPException, SmackException.NotConnectedException, SmackException.NoResponseException - { - - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - - if (byname.contains("@")) { - byname = byname.substring(0, byname.indexOf("@")); - } - - if (byname.length() <= 4) { - JOptionPane.showMessageDialog(jidField, - Res.getString("message.search.input.short"), - Res.getString("title.notification"), - JOptionPane.ERROR_MESSAGE); - - } else { - - JPopupMenu popup = new JPopupMenu(); - JMenuItem header = new JMenuItem( - Res.getString("group.search.results") + ":"); - header.setBackground(UIManager.getColor("List.selectionBackground")); - header.setForeground(Color.red); - popup.add(header); - - for (String search : _usersearchservice) { - - ReportedData data; - UserSearchManager usersearchManager = new UserSearchManager( - SparkManager.getConnection()); - - Form f = usersearchManager.getSearchForm(search); - - Form answer = f.createAnswerForm(); - answer.setAnswer("Name", true); - answer.setAnswer("Email", true); - answer.setAnswer("Username", true); - answer.setAnswer("search", byname); - - data = usersearchManager.getSearchResults(answer, search); - - ArrayList columnnames = new ArrayList<>(); - for ( ReportedData.Column column : data.getColumns() ) { - String label = column.getLabel(); - columnnames.add(label); - } - - for (ReportedData.Row row : data.getRows() ) { - if (!row.getValues(columnnames.get(0)).isEmpty()) { - String s = row.getValues(columnnames.get(0)) - .get(0); - final JMenuItem item = new JMenuItem(s); - popup.add(item); - item.addActionListener( e -> { - jidField.setText(item.getText()); - nicknameField.setText(XmppStringUtils - .parseLocalpart(item.getText())); - } ); - } - - } - } - - if (popup.getComponentCount() > 2) { - popup.setVisible(true); - popup.show(_searchForName, event.getX(), event.getY()); - } else if (popup.getComponentCount() == 2) { - jidField.setText(((JMenuItem) popup.getComponent(1)).getText()); - nicknameField.setText(XmppStringUtils.parseLocalpart(((JMenuItem) popup - .getComponent(1)).getText())); - } else { - JOptionPane.showMessageDialog(jidField, - Res.getString("message.no.results.found"), - Res.getString("title.notification"), - JOptionPane.ERROR_MESSAGE); - } - } - } - - - /** - * Adds a new entry to the users Roster. - * - * @param jid the jid. - * @param nickname the nickname. - * @param group the contact group. - * @return the new RosterEntry. - */ - public RosterEntry addEntry(String jid, String nickname, String group) { - String[] groups = {group}; - - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - RosterEntry userEntry = roster.getEntry(jid); - - boolean isSubscribed = true; - if (userEntry != null) { - isSubscribed = userEntry.getGroups().size() == 0; - } - - if (isSubscribed) { - try { - roster.createEntry(jid, nickname, new String[]{group}); - } - catch (XMPPException | SmackException e) { - Log.error("Unable to add new entry " + jid, e); - } - return roster.getEntry(jid); - } - - - try { - RosterGroup rosterGroup = roster.getGroup(group); - if (rosterGroup == null) { - rosterGroup = roster.createGroup(group); - } - - if (userEntry == null) { - roster.createEntry(jid, nickname, groups); - userEntry = roster.getEntry(jid); - } - else { - userEntry.setName(nickname); - rosterGroup.addEntry(userEntry); - } - - userEntry = roster.getEntry(jid); - } - catch (XMPPException | SmackException ex) { - Log.error(ex); - } - return userEntry; - } - - public List getAccounts() { - List list = new ArrayList<>(); - - for (Transport transport : TransportUtils.getTransports()) { - if (TransportUtils.isRegistered(SparkManager.getConnection(), transport)) { - AccountItem item = new AccountItem(transport.getIcon(), transport.getName(), transport); - list.add(item); - } - } - - return list; - } - - /** - * Method to handle the Add-Button - */ - private void addContactButton() { - String errorMessage = Res.getString("title.error"); - String jid = getJID(); - - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - - if(jid.length()==0) - { - JOptionPane.showMessageDialog(dialog, Res.getString("message.invalid.jid.error"), - Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - return; - } - - String contact = UserManager.escapeJID(jid); - String nickname = nicknameField.getText(); - String group = (String) groupBox.getSelectedItem(); - - Transport transport = null; - if (publicBox.isSelected()) { - AccountItem item = (AccountItem) accounts.getSelectedItem(); - transport = item.getTransport(); - } - - if (transport == null) { - if (!contact.contains("@")) { - contact = contact + "@" - + SparkManager.getConnection().getServiceName(); - } - } else { - if (!contact.contains("@")) { - contact = contact + "@" + transport.getServiceName(); - } - } - - if (!ModelUtil.hasLength(nickname) && ModelUtil.hasLength(contact)) { - // Try to load nickname from VCard - VCard vcard = new VCard(); - try { - vcard.load(SparkManager.getConnection(), contact); - nickname = vcard.getNickName(); - } catch (XMPPException | SmackException e1) { - Log.error(e1); - } - // If no nickname, use first name. - if (!ModelUtil.hasLength(nickname)) { - nickname = XmppStringUtils.parseLocalpart(contact); - } - nicknameField.setText(nickname); - } - - ContactGroup contactGroup = contactList.getContactGroup(group); - boolean isSharedGroup = contactGroup != null - && contactGroup.isSharedGroup(); - - if (isSharedGroup) { - errorMessage = Res - .getString("message.cannot.add.contact.to.shared.group"); - } else if (!ModelUtil.hasLength(contact)) { - errorMessage = Res.getString("message.specify.contact.jid"); - } else if (!XmppStringUtils.parseBareJid(contact).contains("@")) { - errorMessage = Res.getString("message.invalid.jid.error"); - } else if (!ModelUtil.hasLength(group)) { - errorMessage = Res.getString("message.specify.group"); - } else if (ModelUtil.hasLength(contact) && ModelUtil.hasLength(group) - && !isSharedGroup) { - addEntry(); - dialog.setVisible(false); - } else { - - JOptionPane.showMessageDialog(dialog, errorMessage, - Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - } - } - - class AccountItem extends JPanel { - private static final long serialVersionUID = -7657731912529801653L; - private Transport transport; - - public AccountItem(Icon icon, String name, Transport transport) { - setLayout(new GridBagLayout()); - this.transport = transport; - - JLabel iconLabel = new JLabel(); - iconLabel.setIcon(icon); - - JLabel label = new JLabel(); - label.setText(name); - label.setFont(new Font("Dialog", Font.PLAIN, 11)); - label.setHorizontalTextPosition(JLabel.CENTER); - - add(iconLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); - add(label, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 10, 0, 0), 0, 0)); - - setBackground(Color.white); - } - - public Transport getTransport() { - return transport; - } - } -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/spark/ui/SparkTabHandler.java b/src/java/org/jivesoftware/spark/ui/SparkTabHandler.java deleted file mode 100644 index 915121840..000000000 --- a/src/java/org/jivesoftware/spark/ui/SparkTabHandler.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import org.jivesoftware.spark.component.tabbedPane.SparkTab; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.PresenceManager; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.resource.SparkRes; - -import java.awt.Component; -import java.awt.Color; - -/** - * Allows users to control the decoration of a SparkTab component within the ChatContainer. - */ -public abstract class SparkTabHandler { - - public abstract boolean isTabHandled(SparkTab tab, Component component, boolean isSelectedTab, boolean chatFrameFocused); - - /** - * Updates the SparkTab to show it is in a stale state. - * - * @param tab the SparkTab. - * @param chatRoom the ChatRoom of the SparkTab. - */ - protected void decorateStaleTab(SparkTab tab, ChatRoom chatRoom) { - tab.setTitleColor(Color.gray); - tab.setTabFont(tab.getDefaultFont()); - - String jid = ((ChatRoomImpl)chatRoom).getParticipantJID(); - Presence presence = PresenceManager.getPresence(jid); - - if (!presence.isAvailable()) { - tab.setIcon(SparkRes.getImageIcon(SparkRes.IM_UNAVAILABLE_STALE_IMAGE)); - } - else { - Presence.Mode mode = presence.getMode(); - if (mode == Presence.Mode.available || mode == null) { - tab.setIcon(SparkRes.getImageIcon(SparkRes.IM_AVAILABLE_STALE_IMAGE)); - } - else if (mode == Presence.Mode.away) { - tab.setIcon(SparkRes.getImageIcon(SparkRes.IM_AWAY_STALE_IMAGE)); - } - else if (mode == Presence.Mode.chat) { - tab.setIcon(SparkRes.getImageIcon(SparkRes.IM_FREE_CHAT_STALE_IMAGE)); - } - else if (mode == Presence.Mode.dnd) { - tab.setIcon(SparkRes.getImageIcon(SparkRes.IM_DND_STALE_IMAGE)); - } - else if (mode == Presence.Mode.xa) { - tab.setIcon(SparkRes.getImageIcon(SparkRes.IM_DND_STALE_IMAGE)); - } - } - - tab.validateTab(); - } - -} diff --git a/src/java/org/jivesoftware/spark/ui/TranscriptWindow.java b/src/java/org/jivesoftware/spark/ui/TranscriptWindow.java deleted file mode 100644 index f78c6c8ec..000000000 --- a/src/java/org/jivesoftware/spark/ui/TranscriptWindow.java +++ /dev/null @@ -1,641 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Font; -import java.awt.Toolkit; -import java.awt.datatransfer.StringSelection; -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Iterator; -import java.util.List; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.JComponent; -import javax.swing.JFileChooser; -import javax.swing.JOptionPane; -import javax.swing.JPopupMenu; -import javax.swing.KeyStroke; -import javax.swing.UIManager; -import javax.swing.text.BadLocationException; -import javax.swing.text.Document; -import javax.swing.text.SimpleAttributeSet; -import javax.swing.text.Style; -import javax.swing.text.StyleConstants; -import javax.swing.text.StyledDocument; - -import org.jdesktop.swingx.calendar.DateUtils; -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smackx.delay.packet.DelayInformation; -import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.ContextMenuListener; -import org.jivesoftware.spark.ui.history.HistoryWindow; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -/** - * The TranscriptWindow class. Provides a default implementation - * of a Chat Window. In general, extensions could override this class - * to offer more support within the chat, but should not be necessary. - */ -public class TranscriptWindow extends ChatArea implements ContextMenuListener { - - private static final long serialVersionUID = -2168845249388070573L; - private final SimpleDateFormat notificationDateFormatter; - - //code from SPARK-905 patch; it brakes message receiving when there is no old message in the window - //also related code on 181-186 lines - //private SimpleDateFormat myDateFormat = new SimpleDateFormat("dd.MM.yyyy"); - - private Date lastUpdated; - - /** - * The default font used in the chat window for all messages. - */ - private Font defaultFont; - - private Date lastPost; - - /** - * Creates a default instance of TranscriptWindow. - */ - public TranscriptWindow() { - setEditable(false); - - // Set Default Font - final LocalPreferences pref = SettingsManager.getLocalPreferences(); - int fontSize = pref.getChatRoomFontSize(); - defaultFont = new Font("Dialog", Font.PLAIN, fontSize); - - - addMouseListener(this); - addMouseMotionListener(this); - setDragEnabled(true); - addContextMenuListener(this); - - // Make sure ctrl-c works - getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("Ctrl c"), "copy"); - - getActionMap().put("copy", new AbstractAction("copy") { - private static final long serialVersionUID = 1797491846835591379L; - - public void actionPerformed(ActionEvent evt) { - StringSelection stringSelection = new StringSelection(getSelectedText()); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stringSelection, null); - } - }); - - String notificationDateFormat = ( (SimpleDateFormat) SimpleDateFormat.getDateInstance( SimpleDateFormat.FULL ) ).toPattern(); - notificationDateFormatter = new SimpleDateFormat( notificationDateFormat ); - } - - /** - * Inserts a component into the transcript window. - * - * @param component the component to insert. - */ - public void addComponent(Component component) { - final StyledDocument doc = (StyledDocument)getDocument(); - - // The image must first be wrapped in a style - Style style = doc.addStyle("StyleName", null); - - - StyleConstants.setComponent(style, component); - - // Insert the image at the end of the text - try { - doc.insertString(doc.getLength(), "ignored text", style); - doc.insertString(doc.getLength(), "\n", null); - } - catch (BadLocationException e) { - Log.error(e); - } - } - - /** - * Create and insert a message from the current user. - * - * @param nickname the nickname of the current user. - * @param message the message to insert. - * @param foreground the color to use for the message foreground. - */ - public void insertMessage(String nickname, Message message, Color foreground) { - insertMessage(nickname, message, foreground, Color.white); - } - - /** - * Create and insert a message from the current user. - * - * @param nickname the nickname of the current user. - * @param message the message to insert. - * @param foreground the color to use for the message foreground. - * @param background the color to use for the message background. - */ - public void insertMessage(String nickname, Message message, Color foreground, Color background) { - // Check interceptors. - for (TranscriptWindowInterceptor interceptor : SparkManager.getChatManager().getTranscriptWindowInterceptors()) { - boolean handled = interceptor.isMessageIntercepted(this, nickname, message); - if (handled) { - // Do nothing. - return; - } - } - - String body = message.getBody(); - - //code from SPARK-905 patch; it brakes message receiving when there is no old message in the window - //also related code on 80 line - /*Date dateToday = new Date(); - if(myDateFormat.format(lastPost).compareTo(myDateFormat.format(dateToday)) != 0) - { - insertCustomText(notificationDateFormatter.format(dateToday), true, true, Color.BLACK); - lastPost = dateToday; - }*/ - - try { - DelayInformation inf = message.getExtension("delay", "urn:xmpp:delay"); - Date sentDate; - if (inf != null) { - sentDate = inf.getStamp(); - - body = "(" + Res.getString("offline") + ") " + body; - } - else { - sentDate = new Date(); - } - - String date = getDate(sentDate); - - // Agent color is always blue - StyleConstants.setBold(styles, false); - StyleConstants.setForeground(styles, foreground); - StyleConstants.setBackground(styles, background); - final Document doc = getDocument(); - styles.removeAttribute("link"); - - StyleConstants.setFontSize(styles, defaultFont.getSize()); - doc.insertString(doc.getLength(), date + nickname + ": ", styles); - - // Reset Styles for message - StyleConstants.setBold(styles, false); - - StyleConstants.setForeground(styles, getMessageColor()); - setText(body); - insertText("\n"); - } - catch (BadLocationException e) { - Log.error("Error message.", e); - } - } - - /** - * Inserts a full line using a prefix and message. - * - * @param prefix the prefix to use. If null is used, then only the message will be inserted. - * @param message the message to insert. - * @param foreground the foreground color for the message. - */ - public void insertPrefixAndMessage(String prefix, String message, Color foreground) { - try { - // Agent color is always blue - StyleConstants.setBold(styles, false); - StyleConstants.setForeground(styles, foreground); - final Document doc = getDocument(); - styles.removeAttribute("link"); - - StyleConstants.setFontSize(styles, defaultFont.getSize()); - if (prefix != null) { - doc.insertString(doc.getLength(), prefix + ": ", styles); - } - - // Reset Styles for message - StyleConstants.setBold(styles, false); - - StyleConstants.setForeground(styles, getMessageColor()); - setText(message); - insertText("\n"); - } - catch (BadLocationException e) { - Log.error("Error message.", e); - } - } - - protected Color getMessageColor() { - return Color.BLACK; - } - - - /** - * Create and insert a notification message. A notification message generally is a - * presence update, but can be used for most anything related to the room. - * - * @param message the information message to insert. - * @param foregroundColor the foreground color to use. - */ - public synchronized void insertNotificationMessage(String message, Color foregroundColor) { - try { - // Agent color is always blue - StyleConstants.setBold(styles, false); - StyleConstants.setForeground(styles, foregroundColor); - final Document doc = getDocument(); - styles.removeAttribute("link"); - - StyleConstants.setFontSize(styles, defaultFont.getSize()); - doc.insertString(doc.getLength(), "", styles); - - // Reset Styles for message - StyleConstants.setBackground(styles, new Color(0,0,0,0)); - StyleConstants.setBold(styles, false); - StyleConstants.setForeground(styles, foregroundColor); - setText(message); - insertText("\n"); - - // Default back to black - StyleConstants.setForeground(styles, Color.black); - } - catch (BadLocationException ex) { - Log.error("Error message.", ex); - } - } - - /** - * Create and insert a notification message. A notification message generally is a - * presence update, but can be used for most anything related to the room. - * - * @param text the text to insert. - * @param bold true to use bold text. - * @param underline true to have text underlined. - * @param foreground the foreground color. - */ - public synchronized void insertCustomText(String text, boolean bold, boolean underline, Color foreground) { - try { - // Agent color is always blue - StyleConstants.setBold(styles, true); - StyleConstants.setForeground(styles, foreground); - final Document doc = getDocument(); - styles.removeAttribute("link"); - - StyleConstants.setFontSize(styles, defaultFont.getSize()); - doc.insertString(doc.getLength(), "", styles); - - // Reset Styles for message - StyleConstants.setBold(styles, bold); - StyleConstants.setUnderline(styles, underline); - StyleConstants.setForeground(styles, foreground); - setText(text); - insertText("\n"); - StyleConstants.setUnderline(styles, false); - StyleConstants.setForeground(styles, Color.black); - } - catch (BadLocationException ex) { - Log.error("Error message.", ex); - } - } - - - /** - * Returns the formatted date. - * - * @param insertDate the date to format. - * @return the formatted date. - */ - private String getDate(Date insertDate) { - final LocalPreferences pref = SettingsManager.getLocalPreferences(); - - if (insertDate == null) { - insertDate = new Date(); - } - - StyleConstants.setFontFamily(styles, defaultFont.getFontName()); - StyleConstants.setFontSize(styles, defaultFont.getSize()); - - if (pref.isTimeDisplayedInChat()) { - - final SimpleDateFormat formatter = new SimpleDateFormat(pref.getTimeFormat()); - final String date = formatter.format(insertDate); - - return "(" + date + ") "; - } - lastUpdated = insertDate; - return ""; - } - - - /** - * Return the last time the TranscriptWindow was updated. - * - * @return the last time the TranscriptWindow was updated. - */ - public Date getLastUpdated() { - return lastUpdated; - } - - /** - * Inserts a history message. - * - * @param userid the userid of the sender. - * @param message the message to insert. - * @param date the Date object created when the message was delivered. - */ - public void insertHistoryMessage(String userid, String message, Date date) { - try { - String value; - - long lastPostTime = lastPost != null ? lastPost.getTime() : 0; - long lastPostStartOfDay = DateUtils.startOfDayInMillis(lastPostTime); - long newPostStartOfDay = DateUtils.startOfDayInMillis(date.getTime()); - - int diff = DateUtils.getDaysDiff(lastPostStartOfDay, newPostStartOfDay); - if (diff != 0) { - insertCustomText(notificationDateFormatter.format(date), true, true, Color.BLACK); - } - - value = getDate(date); - value = value + userid + ": "; - - - lastPost = date; - - // Agent color is always blue - StyleConstants.setBold(styles, false); - StyleConstants.setForeground(styles, Color.BLACK); - final Document doc = getDocument(); - styles.removeAttribute("link"); - - StyleConstants.setFontSize(styles, defaultFont.getSize()); - doc.insertString(doc.getLength(), value, styles); - - // Reset Styles for message - StyleConstants.setBold(styles, false); - StyleConstants.setForeground(styles, (Color)UIManager.get("History.foreground")); - setText(message); - StyleConstants.setForeground(styles, Color.BLACK); - insertText("\n"); - } - catch (BadLocationException ex) { - Log.error("Error message.", ex); - } - } - - /** - * Disable the entire TranscriptWindow and visually represent - * it as disabled. - */ - public void showWindowDisabled() { - final Document document = getDocument(); - final SimpleAttributeSet attrs = new SimpleAttributeSet(); - StyleConstants.setForeground(attrs, Color.LIGHT_GRAY); - - final int length = document.getLength(); - StyledDocument styledDocument = getStyledDocument(); - styledDocument.setCharacterAttributes(0, length, attrs, false); - } - - /** - * Persist a current transcript. - * - * @param fileName the name of the file to save the transcript as. Note: This can be modified by the user. - * @param transcript the collection of transcript. - * @param headerData the string to prepend to the transcript. - * @see ChatRoom#getTranscripts() - */ - public void saveTranscript(String fileName, List transcript, String headerData) { - final LocalPreferences pref = SettingsManager.getLocalPreferences(); - - try { - SimpleDateFormat formatter; - - File defaultSaveFile = new File(Spark.getSparkUserHome() + "/" + fileName); - final JFileChooser fileChooser = new JFileChooser(defaultSaveFile); - fileChooser.setSelectedFile(defaultSaveFile); - - // Show save dialog; this method does not return until the dialog is closed - int result = fileChooser.showSaveDialog(this); - final File selFile = fileChooser.getSelectedFile(); - - if (selFile != null && result == JFileChooser.APPROVE_OPTION) { - final StringBuilder buf = new StringBuilder(); - final Iterator transcripts = transcript.iterator(); - buf.append(""); - if (headerData != null) { - buf.append(headerData); - } - - buf.append(""); - while (transcripts.hasNext()) { - final Message message = transcripts.next(); - String from = message.getFrom(); - if (from == null) { - from = pref.getNickname(); - } - - if (Message.Type.groupchat == message.getType()) { - if (ModelUtil.hasLength( XmppStringUtils.parseResource(from))) { - from = XmppStringUtils.parseResource(from); - } - } - - final String body = message.getBody(); - - final JivePropertiesExtension extension = ((JivePropertiesExtension) message.getExtension( JivePropertiesExtension.NAMESPACE )); - Date insertionDate = null; - if ( extension != null ) { - insertionDate = (Date) extension.getProperty( "insertionDate" ); - } - - formatter = new SimpleDateFormat("hh:mm:ss"); - - String value = ""; - if (insertionDate != null) { - value = "(" + formatter.format(insertionDate) + ") "; - } - buf.append(""); - - } - buf.append("
        ").append(value).append("").append(from).append(": ").append(body).append("
        "); - final BufferedWriter writer = new BufferedWriter(new FileWriter(selFile)); - writer.write(buf.toString()); - writer.close(); - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), "Chat transcript has been saved.", - "Chat Transcript Saved", JOptionPane.INFORMATION_MESSAGE); - } - } - catch (Exception ex) { - Log.error("Unable to save chat transcript.", ex); - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), "Could not save transcript.", "Error", JOptionPane.ERROR_MESSAGE); - } - - } - - public void cleanup() { - super.releaseResources(); - - clear(); - - removeMouseListener(this); - removeMouseMotionListener(this); - - removeContextMenuListener(this); - getActionMap().remove("copy"); - } - - - public void setFont(Font font) { - this.defaultFont = font; - } - - public Font getFont() { - return defaultFont; - } - - - /** - * Adds Print and Clear actions. - * - * @param object the TransferWindow - * @param popup the popup menu to add to. - */ - public void poppingUp(final Object object, JPopupMenu popup) { - Action printAction = new AbstractAction() { - private static final long serialVersionUID = -244227593637660347L; - - public void actionPerformed(ActionEvent actionEvent) { - SparkManager.printChatTranscript((TranscriptWindow)object); - } - }; - - - Action clearAction = new AbstractAction() { - private static final long serialVersionUID = -5664307353522844588L; - - public void actionPerformed(ActionEvent actionEvent) { - - String user = null; - try { - ChatManager manager = SparkManager.getChatManager(); - ChatRoom room = manager.getChatContainer().getActiveChatRoom(); - user = room.getRoomname(); - - } catch (ChatRoomNotFoundException e) { - e.printStackTrace(); - } - - int ok = JOptionPane.showConfirmDialog((TranscriptWindow)object, - Res.getString("delete.permanently"), Res.getString("delete.log.permanently"), - JOptionPane.YES_NO_OPTION, - JOptionPane.QUESTION_MESSAGE); - if (ok == JOptionPane.YES_OPTION) { - if(user != null){ - // This actions must be move into Transcript Plugin! - File transcriptDir = new File(SparkManager.getUserDirectory(), "transcripts"); - File transcriptFile = new File(transcriptDir ,user + ".xml"); - transcriptFile.delete(); - transcriptFile = new File(transcriptDir,user + "_current.xml"); - transcriptFile.delete(); - clear(); - } - } - } - }; - - - printAction.putValue(Action.NAME, Res.getString("action.print")); - printAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.PRINTER_IMAGE_16x16)); - - clearAction.putValue(Action.NAME, Res.getString("action.clear")); - clearAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.ERASER_IMAGE)); - popup.addSeparator(); - popup.add(printAction); - - if (!Default.getBoolean("HIDE_HISTORY_SETTINGS")) { - popup.add(clearAction); - } - - //History window - Action viewLogAction = new AbstractAction() { - - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent e) { - - ChatManager manager = SparkManager.getChatManager(); - ChatRoom room; - try { - room = manager.getChatContainer().getActiveChatRoom(); - HistoryWindow hw = new HistoryWindow(SparkManager.getUserDirectory(), room.getRoomname()); - hw.showWindow(); - - } catch (Exception e1) { - e1.printStackTrace(); - } - } - - }; - viewLogAction.putValue(Action.NAME, Res.getString("action.viewlog")); - popup.add(viewLogAction); - } - - public void poppingDown(JPopupMenu popup) { - - } - - public boolean handleDefaultAction(MouseEvent e) { - return false; - } - - protected SimpleDateFormat getNotificationDateFormatter() { - return notificationDateFormatter; - } - - protected Date getLastPost() { - return lastPost; - } - - protected void setLastPost(Date lastPost) { - this.lastPost = lastPost; - } - - protected void setLastUpdated(Date lastUpdated) { - this.lastUpdated = lastUpdated; - } - - -} diff --git a/src/java/org/jivesoftware/spark/ui/TranscriptWindowInterceptor.java b/src/java/org/jivesoftware/spark/ui/TranscriptWindowInterceptor.java deleted file mode 100644 index 91753bb88..000000000 --- a/src/java/org/jivesoftware/spark/ui/TranscriptWindowInterceptor.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import org.jivesoftware.smack.packet.Message; - -/** - * Allows users to intercept messages before they are inserted into the TranscriptWindow. - * - * @see TranscriptWindow - * @see org.jivesoftware.spark.ChatManager - */ -public interface TranscriptWindowInterceptor { - - /** - * Is called before a message by this user is inserted into the TranscriptWindow. - * - * @param window the TranscriptWindow. - * @param userid the userid. - * @param message the message to be inserted. - * @return true if it should be handled by a custom interceptor. - */ - boolean isMessageIntercepted(TranscriptWindow window, String userid, Message message); - -} diff --git a/src/java/org/jivesoftware/spark/ui/VCardViewer.java b/src/java/org/jivesoftware/spark/ui/VCardViewer.java deleted file mode 100644 index 53a0fcdd5..000000000 --- a/src/java/org/jivesoftware/spark/ui/VCardViewer.java +++ /dev/null @@ -1,269 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui; - -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Desktop; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Image; -import java.awt.Insets; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; - -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smackx.vcardtemp.packet.VCard; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.UserManager; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; - -/** - * UI to display VCard Information in Wizards, Dialogs, Chat Rooms and any other container. - * - * @author Derek DeMoro - */ -public class VCardViewer extends JPanel { - - private static final long serialVersionUID = -5642099937626355102L; - private Cursor DEFAULT_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR); - private Cursor LINK_CURSOR = new Cursor(Cursor.HAND_CURSOR); - - private final String jid; - private final JLabel avatarImage; - - private String emailAddress = ""; - - /** - * Generate a VCard Panel using the specified jid. - * - * @param jid the jid to use when retrieving the vcard information. - */ - public VCardViewer(final String jid) { - setLayout(new GridBagLayout()); - setOpaque(false); - - this.jid = jid; - avatarImage = new JLabel(); - add(avatarImage, new GridBagConstraints(0, 0, 1, 3, 0.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 0, 5, 0), 0, 0)); - - - Image aImage = SparkRes.getImageIcon(SparkRes.BLANK_24x24).getImage(); - aImage = aImage.getScaledInstance(-1, 64, Image.SCALE_SMOOTH); - ImageIcon ico = new ImageIcon(aImage); - - avatarImage.setIcon(ico); - - final SwingWorker vcardLoader = new SwingWorker() { - VCard vcard = null; - - public Object construct() { - vcard = SparkManager.getVCardManager().getVCard(jid); - return vcard; - } - - public void finished() { - if (vcard == null) { - // Do nothing. - return; - } - - ImageIcon icon = null; - - byte[] bytes = vcard.getAvatar(); - if (bytes != null && bytes.length > 0) { - try { - icon = new ImageIcon(bytes); - Image aImage = icon.getImage(); - aImage = aImage.getScaledInstance(-1, 48, Image.SCALE_SMOOTH); - icon = new ImageIcon(aImage); - } - catch (Exception e) { - Log.error(e); - } - } - else { - icon = SparkRes.getImageIcon(SparkRes.DEFAULT_AVATAR_32x32_IMAGE); - } - - if (icon != null && icon.getIconWidth() > 0) { - avatarImage.setIcon(icon); - avatarImage.setBorder(BorderFactory.createBevelBorder(0, Color.white, Color.lightGray)); - } - - vcard.setJabberId(jid); - buildUI(vcard); - } - }; - - vcardLoader.start(); - } - - private void buildUI(final VCard vcard) { - - String firstName = vcard.getFirstName(); - if (firstName == null) { - firstName = ""; - } - - String lastName = vcard.getLastName(); - if (lastName == null) { - lastName = ""; - } - - - final JLabel usernameLabel = new JLabel(); - usernameLabel.setHorizontalTextPosition(JLabel.LEFT); - usernameLabel.setFont(new Font(Font.DIALOG, Font.BOLD, 15)); - - usernameLabel.setForeground(Color.GRAY); - if (ModelUtil.hasLength(firstName) && ModelUtil.hasLength(lastName)) { - usernameLabel.setText(firstName + " " + lastName); - } - else { - String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid); - usernameLabel.setText(UserManager.unescapeJID(nickname)); - } - - - final Icon icon = SparkManager.getChatManager().getIconForContactHandler(vcard.getJabberId()); - if (icon != null) { - usernameLabel.setIcon(icon); - } - - - add(usernameLabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 0), 0, 0)); - - String title = vcard.getField("TITLE"); - if (ModelUtil.hasLength(title)) { - final JLabel titleLabel = new JLabel(title); - titleLabel.setFont(new Font(Font.DIALOG, Font.PLAIN, 11)); - add(titleLabel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 0, 0), 0, 0)); - } - - - if (ModelUtil.hasLength(vcard.getEmailHome())) { - emailAddress = vcard.getEmailHome(); - } - - final Color linkColor = new Color(49, 89, 151); - final String unselectedText = "" + emailAddress + ""; - final String hoverText = "" + emailAddress + ""; - final JLabel emailTime = new JLabel(unselectedText); - emailTime.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - startEmailClient(emailAddress); - } - - public void mouseEntered(MouseEvent e) { - emailTime.setText(hoverText); - setCursor(LINK_CURSOR); - - } - - public void mouseExited(MouseEvent e) { - emailTime.setText(unselectedText); - setCursor(DEFAULT_CURSOR); - } - }); - - - add(emailTime, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 10, 0), 0, 0)); - - // Add JID Label - final String jid = UserManager.unescapeJID(vcard.getJabberId()); - final JLabel jidLabel = new JLabel("JID: " + jid + ""); - jidLabel.setToolTipText("Click to copy jid to clipboard."); - jidLabel.addMouseListener(new MouseAdapter() { - public void mouseEntered(MouseEvent mouseEvent) { - jidLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); - } - - public void mouseExited(MouseEvent mouseEvent) { - jidLabel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - - } - - public void mouseClicked(MouseEvent mouseEvent) { - SparkManager.setClipboard(jid); - } - }); - - add(jidLabel, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 2, 0), 0, 0)); - - // Add Home Phone - String homeNumber = vcard.getPhoneHome("VOICE"); - if (!ModelUtil.hasLength(homeNumber)) { - homeNumber = Res.getString("label.na"); - } - final JLabel homePhoneLabel = new JLabel(Res.getString("label.home").replace("&", "") + ": " + homeNumber); - add(homePhoneLabel, new GridBagConstraints(1, 4, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 2, 0), 0, 0)); - - // Add Work Phone - String workNumber = vcard.getPhoneWork("VOICE"); - if (!ModelUtil.hasLength(workNumber)) { - workNumber = Res.getString("label.na"); - } - final JLabel workPhoneLabel = new JLabel(Res.getString("label.work").replace("&", "") + ": " + workNumber); - add(workPhoneLabel, new GridBagConstraints(1, 5, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 2, 0), 0, 0)); - - // Add Cell Phone - String cellNumber = vcard.getPhoneWork("CELL"); - if (!ModelUtil.hasLength(cellNumber)) { - cellNumber = Res.getString("label.na"); - } - - final JLabel cellPhoneLabel = new JLabel(Res.getString("label.cell").replace("&", "") + ": " + cellNumber); - add(cellPhoneLabel, new GridBagConstraints(1, 6, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 2, 0), 0, 0)); - - // Add Company - String company = vcard.getOrganization(); - final JLabel orgLabel = new JLabel(Res.getString("label.company").replace("&", "") + ": " + company); - add(orgLabel, new GridBagConstraints(1, 7, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 2, 0), 0, 0)); - - } - - - private void startEmailClient(String emailAddress) { - try { - Desktop.getDesktop().mail(new URI("mailto:" + emailAddress)); - } catch (IOException e) { - Log.error("Can't open Mailer", e); - } catch (URISyntaxException e) { - Log.error("URI Wrong", e); - } - } - - -} diff --git a/src/java/org/jivesoftware/spark/ui/conferences/AnswerFormDialog.java b/src/java/org/jivesoftware/spark/ui/conferences/AnswerFormDialog.java deleted file mode 100644 index e92058a16..000000000 --- a/src/java/org/jivesoftware/spark/ui/conferences/AnswerFormDialog.java +++ /dev/null @@ -1,170 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.conferences; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.FlowLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.util.HashMap; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextArea; -import javax.swing.JTextField; -import org.jivesoftware.resource.Res; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.xdata.Form; -import org.jivesoftware.smackx.xdata.FormField; -import org.jivesoftware.smackx.muc.MultiUserChat; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ResourceUtils; - -/** - * Creates an Answer Form Dialog - * @author wolf.posdorfer - * - */ -public class AnswerFormDialog { - - private static final long serialVersionUID = 3637412110943006392L; - private JDialog dialog = null; - private JPanel centerpanel; - - HashMap _map = new HashMap<>(); - - /** - * Creates an Answer Form Dialog from the specified Form - * @param parent - * @param chat - * @param form - */ - public AnswerFormDialog(JFrame parent, final MultiUserChat chat, - final Form form) { - - centerpanel = new JPanel(); - JPanel bottompanel = new JPanel(); - centerpanel.setLayout(new GridBagLayout()); - - dialog = new JDialog(parent, true); - dialog.setTitle(Res.getString("button.register").replace("&", "")); - - int row = 0; - for ( final FormField formfield : form.getFields() ) { - JLabel label = new JLabel(formfield.getLabel()); - FormField.Type type = formfield.getType(); - - JComponent comp = null; - if (type.equals(FormField.Type.text_single)) { - comp = new JTextField(); - } else if (type.equals(FormField.Type.text_multi)) { - comp = new JTextArea(); - comp.setBorder(new JTextField().getBorder()); - } - - if (comp != null) { - addComponent(label, comp, row, formfield.getVariable()); - row++; - } - } - - JButton updatebutton = new JButton(); - ResourceUtils.resButton(updatebutton, Res.getString("apply")); - updatebutton.addActionListener( e -> { - dialog.dispose(); - sendAnswerForm(form.createAnswerForm(), chat); - } ); - - bottompanel.setLayout(new FlowLayout(FlowLayout.RIGHT)); - bottompanel.add(updatebutton); - - dialog.getContentPane().setLayout(new BorderLayout()); - dialog.getContentPane().add(centerpanel, BorderLayout.CENTER); - dialog.getContentPane().add( bottompanel, BorderLayout.SOUTH); - dialog.pack(); - dialog.setSize(600, 400); - GraphicUtils.centerWindowOnScreen(dialog); - dialog.setVisible(true); - - } - - private void addComponent(JLabel label, JComponent comp, int row, String variable) { - - centerpanel.add(label, new GridBagConstraints(0, row, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); - centerpanel.add(comp, new GridBagConstraints(1, row, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); - - _map.put(variable, comp); - - } - - /** - * Sends the Answer Form - * @param answer must be an answer-form - * @param chat - */ - private void sendAnswerForm(Form answer, MultiUserChat chat) { - - ChatRoom room = SparkManager.getChatManager().getChatRoom(chat.getRoom()); - - for (String key : _map.keySet()) { - String value = getValueFromComponent(key); - answer.setAnswer(key, value); - } - try { - chat.sendRegistrationForm(answer); - - - String reg = Res.getString("message.groupchat.registered.member", chat.getRoom()); - room.getTranscriptWindow().insertNotificationMessage(reg,ChatManager.NOTIFICATION_COLOR); - } catch (XMPPException | SmackException e) { - room.getTranscriptWindow().insertNotificationMessage(e.getMessage(),ChatManager.ERROR_COLOR); - } - - } - - /** - * returns the Component specific value - * - * @param label - * @return - */ - private String getValueFromComponent(String label) { - Component comp = _map.get(label); - - if (comp instanceof JTextField) { - return ((JTextField) comp).getText(); - } else if (comp instanceof JTextArea) { - return ((JTextArea) comp).getText(); - } else { - return null; - } - - } - -} diff --git a/src/java/org/jivesoftware/spark/ui/conferences/BookmarksUI.java b/src/java/org/jivesoftware/spark/ui/conferences/BookmarksUI.java deleted file mode 100644 index 4f7236ae1..000000000 --- a/src/java/org/jivesoftware/spark/ui/conferences/BookmarksUI.java +++ /dev/null @@ -1,707 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.conferences; - -import java.awt.Color; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.TimerTask; -import javax.swing.UIManager; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JTextField; - -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreePath; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; -import org.jivesoftware.smackx.bookmarks.BookmarkManager; -import org.jivesoftware.smackx.bookmarks.BookmarkedConference; -import org.jivesoftware.smackx.disco.packet.DiscoverInfo; -import org.jivesoftware.smackx.disco.packet.DiscoverItems; -import org.jivesoftware.smackx.muc.MultiUserChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.JiveTreeCellRenderer; -import org.jivesoftware.spark.component.JiveTreeNode; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.component.Tree; -import org.jivesoftware.spark.plugin.ContextMenuListener; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; - -/** - * BookmarkedConferences is used to display the UI for all bookmarked conference rooms. - */ -public class BookmarksUI extends JPanel { - private static final long serialVersionUID = -315974309284551232L; - - private Tree tree; - - private JiveTreeNode rootNode; - - private Collection mucServices; - - private Set autoJoinRooms = new HashSet<>(); - - private List listeners = new ArrayList<>(); - - /** - * Bookmarks listeners - */ - private List bookmarkListeners = new ArrayList<>(); - - private BookmarkManager manager; - - /** - * - */ - public BookmarksUI() { - - } - - /** - * Initialize Conference UI. - */ - public void loadUI() { - setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY)); - setLayout(new GridBagLayout()); - - add(getServicePanel(), new GridBagConstraints(0, 0, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - rootNode = new JiveTreeNode("Conference Services"); - tree = new Tree(rootNode) { - private static final long serialVersionUID = -8445572224948613446L; - - @Override - protected void setExpandedState(TreePath path, boolean state) { - // Ignore all collapse requests; collapse events will not be fired - if (state) { - super.setExpandedState(path, state); - } - } - }; - - tree.addMouseListener(new MouseAdapter() { - @Override - public void mouseEntered(MouseEvent mouseEvent) { - tree.setCursor(GraphicUtils.HAND_CURSOR); - } - - @Override - public void mouseExited(MouseEvent mouseEvent) { - tree.setCursor(GraphicUtils.DEFAULT_CURSOR); - } - }); - - - JScrollPane scrollPane = new JScrollPane(tree); - add(scrollPane, new GridBagConstraints(0, 2, 2, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); - - // Add all registered services. - addRegisteredServices(); - - - tree.setCellRenderer(new JiveTreeCellRenderer()); - tree.putClientProperty("JTree.lineStyle", "None"); - tree.setRootVisible(false); - - tree.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent mouseEvent) { - if (mouseEvent.getClickCount() == 2) { - TreePath path = tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY()); - if (path == null) { - return; - } - JiveTreeNode node = (JiveTreeNode)path.getLastPathComponent(); - if (node != null && node.getAllowsChildren()) { - browseRooms((String)node.getUserObject()); - } - else if (node != null) { - String roomJID = node.getAssociatedObject().toString(); - - ConferenceUtils.joinConferenceOnSeperateThread(node.getUserObject().toString(), roomJID, null); - } - } - } - - @Override - public void mouseReleased(MouseEvent mouseEvent) { - checkPopup(mouseEvent); - } - - @Override - public void mousePressed(MouseEvent mouseEvent) { - checkPopup(mouseEvent); - } - } - ); - setBackground(Color.white); - - try { - manager = BookmarkManager.getBookmarkManager(SparkManager.getConnection()); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - - final TimerTask bookmarkTask = new TimerTask() { - @Override - public void run() { - Collection bc = null; - try - { - while(bc == null) - { - bc = manager.getBookmarkedConferences(); - } - setBookmarks(bc); - } - catch (XMPPException | SmackException error) - { - Log.error(error); - } - } - }; - - TaskEngine.getInstance().schedule(bookmarkTask, 5000); - } - - private void checkPopup(MouseEvent mouseEvent) { - // Handle no path for x y coordinates - if (tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY()) == null) { - return; - } - - final JiveTreeNode node = (JiveTreeNode)tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY()).getLastPathComponent(); - - if (mouseEvent.isPopupTrigger() && node != null) { - JPopupMenu popupMenu = new JPopupMenu(); - - // Define service actions - Action browseAction = new AbstractAction() { - private static final long serialVersionUID = -8866708581713789939L; - - @Override - public void actionPerformed(ActionEvent actionEvent) { - browseRooms(node.toString()); - } - }; - browseAction.putValue(Action.NAME, Res.getString("menuitem.browse.service")); - browseAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_DATA_FIND_IMAGE)); - - Action removeServiceAction = new AbstractAction() { - private static final long serialVersionUID = -5276754429117462223L; - - @Override - public void actionPerformed(ActionEvent actionEvent) { - DefaultTreeModel treeModel = (DefaultTreeModel)tree.getModel(); - treeModel.removeNodeFromParent(node); - } - }; - removeServiceAction.putValue(Action.NAME, Res.getString("menuitem.remove.service")); - removeServiceAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_DELETE)); - - JMenuItem browseServiceMenu = new JMenuItem(browseAction); - JMenuItem removeServiceMenu = new JMenuItem(removeServiceAction); - - // Define room actions - Action joinRoomAction = new AbstractAction() { - private static final long serialVersionUID = -356016505214728244L; - - @Override - public void actionPerformed(ActionEvent actionEvent) { - String roomName = node.getUserObject().toString(); - String roomJID = node.getAssociatedObject().toString(); - ConferenceUtils.joinConferenceOnSeperateThread(roomName, roomJID, null); - } - }; - - joinRoomAction.putValue(Action.NAME, Res.getString("menuitem.join.room")); - joinRoomAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_USER_ENTER)); - - Action removeRoomAction = new AbstractAction() { - private static final long serialVersionUID = -7560090091884746914L; - - @Override - public void actionPerformed(ActionEvent actionEvent) { - DefaultTreeModel treeModel = (DefaultTreeModel)tree.getModel(); - treeModel.removeNodeFromParent(node); - String roomJID = node.getAssociatedObject().toString(); - autoJoinRooms.remove(roomJID); - removeBookmark(roomJID); - } - }; - removeRoomAction.putValue(Action.NAME, Res.getString("menuitem.remove.bookmark")); - removeRoomAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.DELETE_BOOKMARK_ICON)); - - - JMenuItem joinRoomMenu = new JMenuItem(joinRoomAction); - JMenuItem removeRoomMenu = new JMenuItem(removeRoomAction); - - - if (node.getAllowsChildren()) { - popupMenu.add(browseServiceMenu); - popupMenu.add(removeServiceMenu); - } - else { - popupMenu.add(joinRoomMenu); - popupMenu.add(removeRoomMenu); - popupMenu.addSeparator(); - - Action autoJoin = new AbstractAction() { - private static final long serialVersionUID = 7857469398581933449L; - - @Override - public void actionPerformed(ActionEvent e) { - String roomJID = node.getAssociatedObject().toString(); - if (autoJoinRooms.contains(roomJID)) { - autoJoinRooms.remove(roomJID); - } - else { - autoJoinRooms.add(roomJID); - } - - String name = node.getUserObject().toString(); - addBookmark(name, roomJID, autoJoinRooms.contains(roomJID)); - } - }; - - autoJoin.putValue(Action.NAME, Res.getString("menuitem.join.on.startup")); - - JCheckBoxMenuItem item = new JCheckBoxMenuItem(autoJoin); - String roomJID = node.getAssociatedObject().toString(); - item.setSelected(autoJoinRooms.contains(roomJID)); - popupMenu.add(item); - - // Define service actions - Action roomInfoAction = new AbstractAction() { - private static final long serialVersionUID = -8336773839944003744L; - - @Override - public void actionPerformed(ActionEvent actionEvent) { - String roomJID = node.getAssociatedObject().toString(); - RoomBrowser roomBrowser = new RoomBrowser(); - roomBrowser.displayRoomInformation(roomJID); - } - }; - - roomInfoAction.putValue(Action.NAME, Res.getString("menuitem.view.room.info")); - roomInfoAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_DATA_FIND_IMAGE)); - popupMenu.add(roomInfoAction); - } - - // Fire menu listeners - fireContextMenuListeners(popupMenu, node); - - // Display popup menu. - popupMenu.show(tree, mouseEvent.getX(), mouseEvent.getY()); - } - } - - public void browseRooms(String serviceName) { - ConferenceRoomBrowser rooms = new ConferenceRoomBrowser(this, serviceName); - rooms.invoke(); - } - - private void addRegisteredServices() { - SwingWorker worker = new SwingWorker() { - - @Override - public Object construct() { - try { - if (SparkManager.getConnection().isConnected()) { - mucServices = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getServiceNames(); - } - } - catch (XMPPException | SmackException e) { - Log.error("Unable to load MUC Service Names.", e); - } - return mucServices; - } - - @Override - public void finished() { - if (mucServices == null) { - return; - } - - for (Object mucService : mucServices) { - String service = (String) mucService; - if (!hasService(service)) { - addServiceToList(service); - } - } - } - }; - - worker.start(); - } - - /** - * Adds a new service (ex. conferences@jabber.org) to the services list. - * - * @param service the new service. - * @return the new service node created. - */ - public JiveTreeNode addServiceToList(String service) { - final JiveTreeNode serviceNode = new JiveTreeNode(service, true, SparkRes.getImageIcon(SparkRes.SERVER_ICON)); - rootNode.add(serviceNode); - final DefaultTreeModel model = (DefaultTreeModel)tree.getModel(); - model.nodeStructureChanged(rootNode); - // expand the tree for displaying - for (int i = 0; i <= tree.getRowCount(); i++) { - tree.expandPath(tree.getPathForRow(i)); - } - return serviceNode; - } - - /** - * Adds a new bookmark to a particular service node. - * - * @param serviceNode the service node. - * @param roomName the name of the room to bookmark. - * @param roomJID the jid of the room. - * @return the new bookmark created. - */ - public JiveTreeNode addBookmark(JiveTreeNode serviceNode, String roomName, String roomJID) { - JiveTreeNode roomNode = new JiveTreeNode(roomName, false, SparkRes.getImageIcon(SparkRes.BOOKMARK_ICON)); - roomNode.setAssociatedObject(roomJID); - serviceNode.add(roomNode); - final DefaultTreeModel model = (DefaultTreeModel)tree.getModel(); - model.nodeStructureChanged(serviceNode); - return roomNode; - } - - public void addBookmark(String roomName, String roomJID, boolean autoJoin) { - try { - if (autoJoin) - { - autoJoinRooms.add(roomJID); - } - manager.addBookmarkedConference(roomName, roomJID, autoJoin, null, null); - fireBookmarksAdded(roomJID); //fire bookmark event - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - } - - public void removeBookmark(String roomJID) { - try { - if (autoJoinRooms.contains(roomJID)) - { - autoJoinRooms.remove(roomJID); - } - manager.removeBookmarkedConference(roomJID); - fireBookmarksRemoved(roomJID); // fire bookmark remove event - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - } - - - private JPanel getServicePanel() { - final JPanel servicePanel = new JPanel(); - servicePanel.setOpaque(false); - servicePanel.setLayout(new GridBagLayout()); - - final JLabel serviceLabel = new JLabel(); - final RolloverButton addButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.SMALL_ADD_IMAGE)); - addButton.setToolTipText(Res.getString("message.add.conference.service")); - - final JTextField serviceField = new JTextField(); - servicePanel.add(serviceLabel, new GridBagConstraints(0, 0, 2, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 2, 5), 0, 0)); - servicePanel.add(serviceField, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 2, 5), 0, 0)); - servicePanel.add(addButton, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 2, 5), 0, 0)); - - // Add resource utils - ResourceUtils.resLabel(serviceLabel, serviceField, Res.getString("label.add.conference.service")); - - final Action conferenceAction = new AbstractAction() { - private static final long serialVersionUID = 7973928300442518496L; - - @Override - public void actionPerformed(ActionEvent e) { - final String conferenceService = serviceField.getText(); - if (hasService(conferenceService)) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(null, Res.getString("message.service.already.exists"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - serviceField.setText(""); - } - else { - final List serviceList = new ArrayList<>(); - serviceField.setText(Res.getString("message.searching.please.wait")); - serviceField.setEnabled(false); - addButton.setEnabled(false); - SwingWorker worker = new SwingWorker() { - DiscoverInfo discoInfo; - - @Override - public Object construct() { - ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(SparkManager.getConnection()); - - try { - discoInfo = discoManager.discoverInfo(conferenceService); - for (DiscoverInfo.Identity identity : discoInfo.getIdentities() ) { - if ("conference".equals(identity.getCategory())) { - serviceList.add(conferenceService); - break; - } - else if ("server".equals(identity.getCategory())) { - try { - Collection services = getConferenceServices(conferenceService); - for (String service : services) { - serviceList.add(service); - } - } - catch (Exception e1) { - Log.error("Unable to load conference services in server.", e1); - } - - } - } - } - catch (XMPPException | SmackException e1) { - Log.error("Error in disco discovery.", e1); - } - return true; - } - - @Override - public void finished() { - if (discoInfo != null) { - for (String aServiceList : serviceList) { - if (!hasService(aServiceList)) { - addServiceToList(aServiceList); - } - } - serviceField.setText(""); - serviceField.setEnabled(true); - addButton.setEnabled(true); - } - else { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), Res.getString("message.conference.service.error"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - serviceField.setText(""); - serviceField.setEnabled(true); - addButton.setEnabled(true); - } - } - }; - worker.start(); - } - } - }; - - addButton.addActionListener(conferenceAction); - - - serviceField.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyChar() == KeyEvent.VK_ENTER) { - conferenceAction.actionPerformed(null); - } - } - }); - - return servicePanel; - } - - private Collection getConferenceServices(String server) throws Exception { - List answer = new ArrayList<>(); - ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(SparkManager.getConnection()); - DiscoverItems items = discoManager.discoverItems(server); - for (DiscoverItems.Item item : items.getItems()) { - if (item.getEntityID().startsWith("conference") || item.getEntityID().startsWith("private")) { - answer.add(item.getEntityID()); - } - else { - try { - DiscoverInfo info = discoManager.discoverInfo(item.getEntityID()); - if (info.containsFeature("http://jabber.org/protocol/muc")) { - answer.add(item.getEntityID()); - } - } - catch (XMPPException | SmackException e) { - Log.error("Problem when loading conference service.", e); - } - } - } - return answer; - } - - private boolean hasService(String service) { - TreePath path = tree.findByName(tree, new String[]{rootNode.getUserObject().toString(), service}); - return path != null; - } - - /** - * Returns the Tree used to display bookmarks. - * - * @return Tree used to display bookmarks. - */ - public Tree getTree() { - return tree; - } - - /** - * Sets the current bookmarks used with this account. - * - * @param bookmarks the current bookmarks used with this account. - */ - public void setBookmarks(Collection bookmarks) { - - for (BookmarkedConference bookmark : bookmarks) { - String serviceName = XmppStringUtils.parseDomain(bookmark.getJid()); - String roomJID = bookmark.getJid(); - String roomName = XmppStringUtils.parseLocalpart(bookmark.getJid()); - - if (bookmark.isAutoJoin()) { - ConferenceUtils.joinConferenceOnSeperateThread(roomName, bookmark.getJid(), bookmark.getPassword()); - ConferenceUtils.addUnclosableChatRoom(roomJID); - autoJoinRooms.add(bookmark.getJid()); - } - - // Get Service Node - TreePath path = tree.findByName(tree, new String[]{rootNode.getUserObject().toString(), serviceName}); - JiveTreeNode serviceNode; - if (path == null) { - serviceNode = addServiceToList(serviceName); - path = tree.findByName(tree, new String[]{rootNode.getUserObject().toString(), serviceName}); - } - else { - serviceNode = (JiveTreeNode)path.getLastPathComponent(); - } - - addBookmark(serviceNode, roomName, roomJID); - - tree.expandPath(path); - } - } - - /** - * Returns all MUC services available. - * - * @return a collection of MUC services. - */ - public Collection getMucServices() { - return mucServices; - } - - /** - * Adds a new ContextMenuListener. - * - * @param listener the listener. - */ - public void addContextMenuListener(ContextMenuListener listener) { - listeners.add(listener); - } - - /** - * Removes a ContextMenuListener. - * - * @param listener the listener. - */ - public void removeContextMenuListener(ContextMenuListener listener) { - listeners.remove(listener); - } - - private void fireContextMenuListeners(JPopupMenu popup, JiveTreeNode node) { - for (ContextMenuListener listener : new ArrayList<>( listeners )) { - listener.poppingUp(node, popup); - } - } - - /** - * Adds a new BookmarksListener. - * - * @param bookmarkListener the bookmarkListener. - */ - public void addBookmarksListener(BookmarksListener bookmarkListener) { - bookmarkListeners.add(bookmarkListener); - } - - /** - * Removes a BookmarksListener. - * - * @param bookmarkListener the bookmarkListener. - */ - public void removeBookmarksListener(BookmarksListener bookmarkListener) { - bookmarkListeners.remove(bookmarkListener); - } - - private void fireBookmarksAdded(String roomJID) { - for (BookmarksListener bookmarkListener : new ArrayList<>( bookmarkListeners )) { - bookmarkListener.bookmarkAdded(roomJID); - } - } - - private void fireBookmarksRemoved(String roomJID) { - for (BookmarksListener bookmarkListener : new ArrayList<>( bookmarkListeners )) { - bookmarkListener.bookmarkRemoved(roomJID); - } - } - - /** - * Returns a list of bookmarks. - * @return a Collection of bookmarks. - */ - public Collection getBookmarks() { - try { - return manager.getBookmarkedConferences(); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - return Collections.emptyList(); - } - -} diff --git a/src/java/org/jivesoftware/spark/ui/conferences/ConferenceRoomBrowser.java b/src/java/org/jivesoftware/spark/ui/conferences/ConferenceRoomBrowser.java deleted file mode 100644 index 041fa5db3..000000000 --- a/src/java/org/jivesoftware/spark/ui/conferences/ConferenceRoomBrowser.java +++ /dev/null @@ -1,1111 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.conferences; - -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.TimerTask; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.ImageIcon; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.JTextField; -import javax.swing.ListSelectionModel; -import javax.swing.RowFilter; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableModel; -import javax.swing.table.TableRowSorter; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreePath; -import javax.swing.UIManager; - - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.muc.MultiUserChatManager; -import org.jivesoftware.smackx.xdata.Form; -import org.jivesoftware.smackx.bookmarks.BookmarkedConference; -import org.jivesoftware.smackx.muc.HostedRoom; -import org.jivesoftware.smackx.muc.MultiUserChat; -import org.jivesoftware.smackx.muc.RoomInfo; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.JiveTreeNode; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.component.Table; -import org.jivesoftware.spark.component.TitlePanel; -import org.jivesoftware.spark.component.Tree; -import org.jivesoftware.spark.ui.ChatRoomNotFoundException; -import org.jivesoftware.spark.ui.rooms.GroupChatRoom; -import org.jivesoftware.spark.util.ImageCombiner; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.UIComponentRegistry; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -/** - * A UI that handles all Group Rooms contained in an XMPP Messenger server. This - * handles creation and joining of rooms for group chat discussions as well as - * the listing of the creation times, number of occupants in a room, and the - * room name itself. - */ -public class ConferenceRoomBrowser extends JPanel implements ActionListener, - ComponentListener { - private static final long serialVersionUID = -4483998189117467048L; - private final RoomList roomsTable; - private final RolloverButton createButton = new RolloverButton("", - SparkRes.getImageIcon(SparkRes.SMALL_USER1_NEW)); - private final RolloverButton joinRoomButton = new RolloverButton("", - SparkRes.getImageIcon(SparkRes.DOOR_IMAGE)); - private final RolloverButton refreshButton = new RolloverButton("", - SparkRes.getImageIcon(SparkRes.REFRESH_IMAGE)); - private final RolloverButton addRoomButton = new RolloverButton("", - SparkRes.getImageIcon(SparkRes.ADD_BOOKMARK_ICON)); - - private final RolloverButton showHiddenButtons = new RolloverButton( - SparkRes.getImageIcon(SparkRes.PANE_UP_ARROW_IMAGE)); - - private JMenuItem joinRoomItem; - private JMenuItem addRoomItem; - private JMenuItem createItem; - private JMenuItem refreshItem; - - private ChatManager chatManager; - - private JDialog dlg; - - private BookmarksUI conferences; - private String serviceName; - - private int allButtonWidth; - private int threeButtonWidth; - private int twoButtonWidth; - private int oneButtonWidth; - - private boolean partialDiscovery = false; - - private JPopupMenu popup; - - final TableRowSorter sorter; - - /** - * Creates a new instance of ConferenceRooms. - * - * @param conferences - * the conference ui. - * @param serviceName - * the name of the conference service. - * - */ - public ConferenceRoomBrowser(BookmarksUI conferences, - final String serviceName) { - - this.setLayout(new BorderLayout()); - - this.conferences = conferences; - this.serviceName = serviceName; - - popup = new JPopupMenu(); - - joinRoomItem = new JMenuItem(Res.getString("menuitem.join.room")); - addRoomItem = new JMenuItem(Res.getString("menuitem.bookmark.room")); - createItem = new JMenuItem(Res.getString("menuitem.create.room")); - refreshItem = new JMenuItem(Res.getString("menuitem.refresh")); - - joinRoomItem.setIcon(SparkRes.getImageIcon(SparkRes.DOOR_IMAGE)); - addRoomItem.setIcon(SparkRes.getImageIcon(SparkRes.ADD_BOOKMARK_ICON)); - createItem.setIcon(SparkRes.getImageIcon(SparkRes.SMALL_USER1_NEW)); - refreshItem.setIcon(SparkRes.getImageIcon(SparkRes.REFRESH_IMAGE)); - - popup.add(joinRoomItem); - popup.add(addRoomItem); - popup.add(createItem); - popup.add(refreshItem); - - // Add Toolbar - final JPanel Hauptpanel = new JPanel(new BorderLayout()); - JPanel toolbar = new JPanel(new FlowLayout(FlowLayout.LEFT)); - JPanel pane_hiddenButtons = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - toolbar.add(joinRoomButton); - toolbar.add(addRoomButton); - toolbar.add(createButton); - toolbar.add(refreshButton); - pane_hiddenButtons.add(showHiddenButtons); - - Hauptpanel.add(toolbar, BorderLayout.WEST); - Hauptpanel.add(pane_hiddenButtons, BorderLayout.EAST); - this.add(Hauptpanel, BorderLayout.NORTH); - - JLabel labelFilter = new JLabel( Res.getString( "label.search" ) ); - JTextField txtFilter = new JTextField( 20 ); - txtFilter.setMinimumSize(new Dimension(50,20)); - - //add fields for filter - final JPanel Filterpanel = new JPanel(new BorderLayout()); - JPanel toolbarFilter = new JPanel(new FlowLayout(FlowLayout.LEFT)); - toolbarFilter.add( labelFilter ); - toolbarFilter.add( txtFilter ); - - Filterpanel.add(toolbarFilter); - this.add(Filterpanel,BorderLayout.SOUTH); - - - createButton.addActionListener(this); - createItem.addActionListener(this); - joinRoomButton.addActionListener(this); - refreshButton.addActionListener(this); - - ResourceUtils.resButton(createButton, - Res.getString("button.create.room")); - ResourceUtils.resButton(joinRoomButton, - Res.getString("button.join.room")); - ResourceUtils.resButton(refreshButton, Res.getString("button.refresh")); - ResourceUtils.resButton(addRoomButton, - Res.getString("button.bookmark.room")); - - refreshButton.setToolTipText(Res.getString("message.update.room.list")); - joinRoomButton.setToolTipText(Res - .getString("message.join.conference.room")); - createButton.setToolTipText(Res - .getString("message.create.or.join.room")); - - // Add Group Chat Table - roomsTable = new RoomList(); - - //build model for roomsTable, ignoring the 1st column - sorter = new TableRowSorter<>( roomsTable.getModel() ); - roomsTable.setRowSorter(sorter); - - final JScrollPane pane = new JScrollPane(roomsTable); - pane.setBackground(Color.white); - pane.setForeground(Color.white); - this.setBackground(Color.white); - this.setForeground(Color.white); - pane.getViewport().setBackground(Color.white); - this.add(pane, BorderLayout.CENTER); - - chatManager = SparkManager.getChatManager(); - - - txtFilter.addKeyListener( new KeyAdapter() { - @Override - public void keyReleased(KeyEvent e) { - JTextField textField = (JTextField)e.getSource(); - String text = textField.getText(); - List> filters = new ArrayList<>(); - filters.add(RowFilter.regexFilter(text, 1)); - filters.add(RowFilter.regexFilter(text, 2)); - filters.add(RowFilter.regexFilter(text, 3)); - RowFilter af = RowFilter.orFilter(filters); - sorter.setRowFilter(af); - } - }); - joinRoomButton.addActionListener( actionEvent -> joinSelectedRoom() ); - addRoomButton.addActionListener( actionEvent -> bookmarkRoom(serviceName) ); - - refreshButton.addActionListener( actionEvent -> refreshRoomList(serviceName) ); - - joinRoomItem.addActionListener( actionEvent -> joinSelectedRoom() ); - - addRoomItem.addActionListener( actionEvent -> bookmarkRoom(serviceName) ); - - refreshItem.addActionListener( actionEvent -> refreshRoomList(serviceName) ); - - showHiddenButtons.addActionListener( actionEvent -> popup.show(showHiddenButtons, 0, showHiddenButtons.getHeight()) ); - - joinRoomButton.setEnabled(false); - addRoomButton.setEnabled(false); - joinRoomItem.setEnabled(false); - addRoomItem.setEnabled(false); - - addTableListener(); - } - - private void startLoadingImg(){ - SwingWorker startLoading = new SwingWorker() { - - @Override - public Object construct() { - return null; - } - - @Override - public void finished() { - refreshButton.setIcon(SparkRes.getImageIcon(SparkRes.BUSY_IMAGE)); - refreshButton.validate(); - refreshButton.repaint(); - refreshItem.setIcon(SparkRes.getImageIcon(SparkRes.BUSY_IMAGE)); - refreshItem.validate(); - refreshItem.repaint(); - } - }; - startLoading.start(); - } - - private void stopLoadingImg(){ - SwingWorker stopLoading = new SwingWorker() { - - @Override - public Object construct() { - return null; - } - public void finished() { - refreshButton.setIcon(SparkRes.getImageIcon(SparkRes.REFRESH_IMAGE)); - refreshButton.validate(); - refreshButton.repaint(); - refreshItem.setIcon(SparkRes.getImageIcon(SparkRes.REFRESH_IMAGE)); - refreshItem.validate(); - refreshItem.repaint(); - } - }; - stopLoading.start(); - } - - private void clearTable(){ - SwingWorker clearTable = new SwingWorker() { - - @Override - public Object construct() { - return null; - } - @Override - public void finished() { - roomsTable.clearTable(); - } - }; - clearTable.start(); - } - - private void refreshRoomList(final String serviceName) { - startLoadingImg(); - clearTable(); - - TimerTask refreshTask = new TimerTask() { - Collection rooms; - - @Override - public void run() { - try { - rooms = getRoomList(serviceName); - try { - for (HostedRoom aResult : rooms) { - RoomObject room = getRoomsAndInfo(aResult); - addRoomToTable(room.getRoomJID(), room.getRoomName(), - room.getNumberOfOccupants()); - } - stopLoadingImg(); - } catch (Exception e) { - Log.error("Unable to retrieve room list and info.", e); - } - } catch ( Exception e1 ) { - System.err.println(e1); - } - } - }; - TaskEngine.getInstance().submit(refreshTask); - } - - private RoomObject getRoomsAndInfo(final HostedRoom room) { - boolean stillSearchForOccupants = true; - RoomObject result = null; - try { - try { - String roomName = room.getName(); - String roomJID = room.getJid(); - int numberOfOccupants = -1; - if (stillSearchForOccupants) { - RoomInfo roomInfo = null; - try { - roomInfo = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getRoomInfo( roomJID ); - } catch (Exception e) { - // Nothing to do - } - - if (roomInfo != null) { - numberOfOccupants = roomInfo.getOccupantsCount(); - if (numberOfOccupants == -1) { - } - } else { - } - } - - result = new RoomObject(); - result.setRoomJID(roomJID); - result.setRoomName(roomName); - result.setNumberOfOccupants(numberOfOccupants); - } catch (Exception e) { - Log.error("Error setting up GroupChatTable", e); - } - } catch (Exception e) { - System.err.println(e); - } - return result; - } - - private void bookmarkRoom(String serviceName) { - int selectedRow = roomsTable.getSelectedRow(); - - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - - if (-1 == selectedRow) { - JOptionPane.showMessageDialog(dlg, Res.getString("message.select.add.room.to.add"), Res.getString("title.group.chat"), JOptionPane.INFORMATION_MESSAGE); - return; - } - - final String roomJID = roomsTable.getValueAt(selectedRow, 2) + "@" + serviceName; - final String roomName = roomsTable.getValueAt(selectedRow, 1).toString(); - - // Check to see what type of room this is. - boolean persistent = false; - try { - final RoomInfo roomInfo = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getRoomInfo( roomJID ); - persistent = roomInfo.isPersistent(); - } catch (Exception e) { - // Do not return - Log.error("This room does not exist. Probably this room was temporary and was closed"); - } - if (!persistent) { - JOptionPane.showMessageDialog(dlg, Res.getString("message.bookmark.temporary.room.error"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - return; - } - - Tree serviceTree = conferences.getTree(); - JiveTreeNode rootNode = (JiveTreeNode) serviceTree.getModel().getRoot(); - - TreePath rootPath = serviceTree.findByName(serviceTree, new String[] { rootNode.toString(), serviceName }); - - boolean isBookmarked = isBookmarked(roomJID); - - if (!isBookmarked) { - JiveTreeNode node = (JiveTreeNode) serviceTree.getLastSelectedPathComponent(); - if (node == null) { - TreePath path = serviceTree.findByName(serviceTree, new String[] { rootNode.toString(), ConferenceServices.getDefaultServiceName() }); - node = (JiveTreeNode) path.getLastPathComponent(); - } - JiveTreeNode roomNode = new JiveTreeNode(roomName, false, SparkRes.getImageIcon(SparkRes.BOOKMARK_ICON)); - roomNode.setAssociatedObject(roomJID); - node.add(roomNode); - final DefaultTreeModel model = (DefaultTreeModel) serviceTree.getModel(); - model.nodeStructureChanged(node); - serviceTree.expandPath(rootPath); - roomsTable.getTableModel().setValueAt(new JLabel(SparkRes.getImageIcon(SparkRes.BOOKMARK_ICON)), selectedRow, 0); - addBookmarkUI(false); - - conferences.addBookmark(roomName, roomJID, false); - } else { - // Remove bookmark - TreePath path = serviceTree.findByName(serviceTree, new String[] { rootNode.toString(), serviceName, roomName }); - JiveTreeNode node = (JiveTreeNode) path.getLastPathComponent(); - final DefaultTreeModel model = (DefaultTreeModel) serviceTree.getModel(); - model.removeNodeFromParent(node); - roomsTable.getTableModel().setValueAt(new JLabel(SparkRes.getImageIcon(SparkRes.BLANK_IMAGE)), selectedRow, 0); - addBookmarkUI(true); - - String jid = (String) node.getAssociatedObject(); - conferences.removeBookmark(jid); - } - } - - private void joinSelectedRoom() { - int selectedRow = roomsTable.getSelectedRow(); - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - if (-1 == selectedRow) { - JOptionPane.showMessageDialog(dlg, - Res.getString("message.select.room.to.join"), - Res.getString("title.group.chat"), - JOptionPane.INFORMATION_MESSAGE); - return; - } - enterRoom(); - } - - private void addTableListener() { - roomsTable.getSelectionModel().addListSelectionListener( - e -> { - if (e.getValueIsAdjusting()) - return; - - int selectedRow = roomsTable.getSelectedRow(); - if (selectedRow != -1) { - joinRoomButton.setEnabled(true); - joinRoomItem.setEnabled(true); - String roomJID = roomsTable.getValueAt(selectedRow, - 2) + "@" + serviceName; - addRoomButton.setEnabled(true); - addRoomItem.setEnabled(true); - if (isBookmarked(roomJID)) { - addBookmarkUI(false); - } else { - addBookmarkUI(true); - } - } else { - joinRoomButton.setEnabled(false); - addRoomButton.setEnabled(false); - joinRoomItem.setEnabled(false); - addRoomItem.setEnabled(false); - addBookmarkUI(true); - } - } ); - } - - /** - * Displays the ConferenceRoomBrowser. - */ - public void invoke() { - startLoadingImg(); - TimerTask invokeThread = new TimerTask() { - Collection rooms; - - @Override - public void run() { - try { - rooms = getRoomList(serviceName); - - if (rooms == null) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(conferences, - Res.getString("message.conference.info.error"), - Res.getString("title.error"), - JOptionPane.ERROR_MESSAGE); - if (dlg != null) { - dlg.dispose(); - } - }else{ - try { - for (HostedRoom room : rooms) { - - String roomName = room.getName(); - String roomJID = room.getJid(); - - int numberOfOccupants = -1; - - // Need to handle the case where the room info does not - // contain the number of occupants. If that is the case, - // we should not continue to request this info from the - // service. - if (!partialDiscovery) { - RoomInfo roomInfo = null; - try { - roomInfo = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getRoomInfo( roomJID ); - } catch (Exception e) { - // Nothing to do - } - - if (roomInfo != null) { - numberOfOccupants = roomInfo - .getOccupantsCount(); - } - if (roomInfo == null || numberOfOccupants == -1) { - partialDiscovery = true; - } - } - addRoomToTable(roomJID, roomName, numberOfOccupants); - } - } catch (Exception e) { - Log.error("Error setting up GroupChatTable", e); - } - } - } catch (Exception e) { - Log.error("Unable to retrieve list of rooms.", e); - } - stopLoadingImg(); - } - }; - - final JOptionPane pane; - - TitlePanel titlePanel; - - // Create the title panel for this dialog - titlePanel = new TitlePanel( - Res.getString("title.create.or.bookmark.room"), - Res.getString("message.add.favorite.room"), - SparkRes.getImageIcon(SparkRes.BLANK_IMAGE), true); - - // Construct main panel w/ layout. - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(titlePanel, BorderLayout.NORTH); - - // The user should only be able to close this dialog. - Object[] options = { Res.getString("close") }; - pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, - JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); - - mainPanel.add(pane, BorderLayout.CENTER); - - final JOptionPane p = new JOptionPane(); - - dlg = p.createDialog(SparkManager.getMainWindow(), - Res.getString("title.browse.room.service", serviceName)); - dlg.setModal(false); - dlg.pack(); - dlg.addComponentListener(this); - - /* - * looking up which bundle is used to set the size of the Window (not - * using Localpreferences getLanguage() because sometimes language is - * not saved in the properties file and so the method only returns an - * empty String) - */ - if (Res.getBundle().getLocale().toString().equals("de")) - dlg.setSize(700, 400); - else - dlg.setSize(500, 400); - - dlg.setResizable(true); - dlg.setContentPane(mainPanel); - dlg.setLocationRelativeTo(SparkManager.getMainWindow()); - - PropertyChangeListener changeListener = new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent e) { - String value = (String) pane.getValue(); - if (Res.getString("close").equals(value)) { - pane.removePropertyChangeListener(this); - dlg.dispose(); - } else if (Res.getString("close").equals(value)) { - pane.setValue(JOptionPane.UNINITIALIZED_VALUE); - } - } - }; - - pane.addPropertyChangeListener(changeListener); - - dlg.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { - if (e.getKeyChar() == KeyEvent.VK_ESCAPE) { - dlg.dispose(); - } - } - }); - - // will need that, when the window is smaller then the buttons width... - setButtonsWidth(); - - showHiddenButtons.setVisible(false); - - dlg.setVisible(true); - dlg.toFront(); - dlg.requestFocus(); - TaskEngine.getInstance().submit(invokeThread); - } - - private final class RoomList extends Table { - private static final long serialVersionUID = -731280190627042419L; - - public RoomList() { - super(new String[] { " ", Res.getString("title.name"), - Res.getString("title.address"), - Res.getString("title.occupants") }); - getColumnModel().setColumnMargin(0); - getColumnModel().getColumn(0).setMaxWidth(30); - getColumnModel().getColumn(3).setMaxWidth(80); - - setSelectionBackground(Table.SELECTION_COLOR); - setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - setRowSelectionAllowed(true); - // setSortable(true); - - addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - enterRoom(); - } - } - - public void mouseReleased(MouseEvent e) { - checkPopup(e); - } - - public void mousePressed(MouseEvent e) { - checkPopup(e); - } - }); - - } - - // Handle image rendering correctly - public TableCellRenderer getCellRenderer(int row, int column) { - Object o = getValueAt(row, column); - if (o != null) { - if (o instanceof JLabel) { - return new JLabelRenderer(false); - } - } - - if (column == 3) { - return new CenterRenderer(); - } - - return super.getCellRenderer(row, column); - } - - private void checkPopup(MouseEvent e) { - if (e.isPopupTrigger()) { - final JPopupMenu popupMenu = new JPopupMenu(); - - Action roomInfoAction = new AbstractAction() { - private static final long serialVersionUID = 5142016247851363420L; - - public void actionPerformed(ActionEvent actionEvent) { - int selectedRow = roomsTable.getSelectedRow(); - if (selectedRow != -1) { - String roomJID = roomsTable.getValueAt(selectedRow, 2) + "@" + serviceName; - RoomBrowser roomBrowser = new RoomBrowser(); - roomBrowser.displayRoomInformation(roomJID); - } - } - }; - - roomInfoAction.putValue(Action.NAME, Res.getString("menuitem.view.room.info")); - roomInfoAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_DATA_FIND_IMAGE)); - - final int selectedRow = roomsTable.getSelectedRow(); - final String roomName = roomsTable.getValueAt(selectedRow, 1).toString(); - popupMenu.add(roomInfoAction); - final JCheckBoxMenuItem autoJoin = new JCheckBoxMenuItem(Res.getString("menuitem.join.on.startup")); - autoJoin.addActionListener( e1 -> { - String roomJID = roomsTable.getValueAt(selectedRow, 2) + "@" + serviceName; - conferences.removeBookmark(roomJID); - conferences.addBookmark(roomName, roomJID, autoJoin.isSelected()); - } ); - - - if (selectedRow != -1) { - - for (BookmarkedConference bookmark :conferences.getBookmarks()) - { - if (roomName.equals(bookmark.getName())) - { - autoJoin.setSelected(bookmark.isAutoJoin()); - popupMenu.add(autoJoin); - } - - } - - - } - - popupMenu.show(roomsTable, e.getX(), e.getY()); - } - } - - } - - public void actionPerformed(ActionEvent e) { - if (e.getSource() == createButton || e.getSource() == createItem) { - createRoom(); - } - } - - private void enterRoom() { - int selectedRow = roomsTable.getSelectedRow(); - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - if (-1 == selectedRow) { - JOptionPane.showMessageDialog(dlg, - Res.getString("message.select.room.to.enter"), - Res.getString("title.group.chat"), - JOptionPane.INFORMATION_MESSAGE); - return; - } - final String roomJID = roomsTable.getValueAt(selectedRow, 2) + "@" - + serviceName; - final String roomDescription = (String) roomsTable.getValueAt( - selectedRow, 1); - - try { - chatManager.getChatContainer().getChatRoom(roomJID); - } catch (ChatRoomNotFoundException e1) { - ConferenceUtils.joinConferenceOnSeperateThread(roomDescription, - roomJID, null); - } - } - - /** - * Returns a Collection of all rooms in the specified Conference Service. - * - * @param serviceName - * the name of the conference service. - * @return a Collection of all rooms in the Conference service. - * @throws Exception - * if a problem occurs while getting the room list - */ - private static Collection getRoomList(String serviceName) - throws Exception { - return MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getHostedRooms( serviceName ); - } - - /** - * Create a new room based on room table selection. - */ - private void createRoom() { - RoomCreationDialog mucRoomDialog = new RoomCreationDialog(); - final MultiUserChat groupChat = mucRoomDialog.createGroupChat( - SparkManager.getMainWindow(), serviceName); - LocalPreferences pref = SettingsManager.getLocalPreferences(); - - if (null != groupChat) { - - // Join Room - try { - GroupChatRoom room = UIComponentRegistry.createGroupChatRoom(groupChat); - - groupChat.create(pref.getNickname()); - chatManager.getChatContainer().addChatRoom(room); - chatManager.getChatContainer().activateChatRoom(room); - - // Send Form - Form form = groupChat.getConfigurationForm().createAnswerForm(); - if (mucRoomDialog.isPasswordProtected()) { - String password = mucRoomDialog.getPassword(); - room.setPassword(password); - form.setAnswer("muc#roomconfig_passwordprotectedroom", true); - form.setAnswer("muc#roomconfig_roomsecret", password); - } - form.setAnswer("muc#roomconfig_roomname", - mucRoomDialog.getRoomName()); - form.setAnswer("muc#roomconfig_roomdesc", - mucRoomDialog.getRoomTopic()); - - if (mucRoomDialog.isPermanent()) { - form.setAnswer("muc#roomconfig_persistentroom", true); - } - - List owners = new ArrayList<>(); - owners.add(SparkManager.getSessionManager().getBareAddress()); - form.setAnswer("muc#roomconfig_roomowners", owners); - - // new DataFormDialog(groupChat, form); - groupChat.sendConfigurationForm(form); - addRoomToTable(groupChat.getRoom(), XmppStringUtils.parseLocalpart(groupChat.getRoom()), 1); - } catch (XMPPException | SmackException e1) { - Log.error("Error creating new room.", e1); - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane - .showMessageDialog(this, - Res.getString("message.room.creation.error"), - Res.getString("title.error"), - JOptionPane.ERROR_MESSAGE); - } - } - } - - /** - * Adds a room to the room table. - * - * @param jid - * the jid of the conference room. - * @param roomName - * the name of the conference room. - * @param numberOfOccupants - * the number of occupants in the conference room. If -1 is - * specified, the the occupant count will show as n/a. - */ - private void addRoomToTable(final String jid, final String roomName, - final int numberOfOccupants) { - SwingWorker addRoomThread = new SwingWorker() { - - @Override - public Object construct() { - JLabel iconLabel = new JLabel(); - iconLabel.setAlignmentX(JLabel.RIGHT_ALIGNMENT); - boolean isbookmark = false; - boolean ispassword = false; - - ImageIcon bookmarkicon = SparkRes.getImageIcon(SparkRes.BOOKMARK_ICON); - ImageIcon passwordicon = SparkRes.getImageIcon(SparkRes.LOCK_16x16); - - if (isBookmarked(jid)) { - isbookmark = true; - iconLabel.setIcon(SparkRes.getImageIcon(SparkRes.BOOKMARK_ICON)); - } - if (isPasswordProtected(jid)) { - ispassword = true; - } - - if (isbookmark && ispassword) { - Image img = ImageCombiner.combine(bookmarkicon, passwordicon); - iconLabel.setIcon(new ImageIcon(img)); - } else if (isbookmark) { - iconLabel.setIcon(bookmarkicon); - } else if (ispassword) { - Image img = ImageCombiner.returnTransparentImage( - passwordicon.getIconWidth(), passwordicon.getIconHeight()); - - Image combined = ImageCombiner.combine(new ImageIcon(img), - passwordicon); - - iconLabel.setIcon(new ImageIcon(combined)); - } - - String occupants = Integer.toString(numberOfOccupants); - if (numberOfOccupants == -1) { - occupants = "n/a"; - } - - final Object[] insertRoom = new Object[] { iconLabel, roomName, - XmppStringUtils.parseLocalpart(jid), occupants }; - return insertRoom; - } - - @Override - public void finished() { - Object[] insertRoom = (Object[])get(); - roomsTable.getTableModel().addRow(insertRoom); - } - }; - addRoomThread.start(); - } - - /** - * Returns true if the room specified is bookmarked. - * - * @param roomJID - * the jid of the room to check. - * @return true if the room is bookmarked. - */ - private boolean isBookmarked(String roomJID) { - for (Object o : conferences.getBookmarks()) { - BookmarkedConference bk = (BookmarkedConference) o; - String jid = bk.getJid(); - if (jid != null && roomJID.equals(jid)) { - return true; - } - } - - return false; - - } - - /** - * Returns true if the room is password protected or Members only - * - * @param roomjid - * @return - */ - private boolean isPasswordProtected(String roomjid) { - boolean result = false; - try { - - RoomInfo rif = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getRoomInfo( roomjid ); - - result = rif.isMembersOnly() || rif.isPasswordProtected(); - - } catch (XMPPException | SmackException | NumberFormatException e) { - - } - - return result; - } - - /** - * Toggles the bookmark room button depending on it's state. - * - * @param addBookmark - * true if the button should display itself as bookmarkable :) - */ - private void addBookmarkUI(boolean addBookmark) { - if (!addBookmark) { - addRoomButton.setText(Res.getString("button.remove.bookmark")); - addRoomButton.setIcon(SparkRes - .getImageIcon(SparkRes.DELETE_BOOKMARK_ICON)); - } else { - ResourceUtils.resButton(addRoomButton, - Res.getString("button.bookmark.room")); - addRoomButton.setIcon(SparkRes - .getImageIcon(SparkRes.ADD_BOOKMARK_ICON)); - } - } - - /* - * * Center the text - */ - static class CenterRenderer extends DefaultTableCellRenderer { - private static final long serialVersionUID = 105809683882744641L; - - public CenterRenderer() { - setHorizontalAlignment(CENTER); - } - - public Component getTableCellRendererComponent(JTable table, - Object value, boolean isSelected, boolean hasFocus, int row, - int column) { - super.getTableCellRendererComponent(table, value, isSelected, - hasFocus, row, column); - return this; - } - } - - private class RoomObject { - private String roomName; - private String roomJID; - - int numberOfOccupants; - - public String getRoomName() { - return roomName; - } - - public void setRoomName(String roomName) { - this.roomName = roomName; - } - - public String getRoomJID() { - return roomJID; - } - - public void setRoomJID(String roomJID) { - this.roomJID = roomJID; - } - - public int getNumberOfOccupants() { - return numberOfOccupants; - } - - public void setNumberOfOccupants(int numberOfOccupants) { - this.numberOfOccupants = numberOfOccupants; - } - } - - public void componentHidden(ComponentEvent e) { - - } - - public void componentMoved(ComponentEvent e) { - - } - - public void componentResized(ComponentEvent e) { - if (this.getWidth() <= (oneButtonWidth + 19)) { - joinRoomButton.setVisible(false); - addRoomButton.setVisible(false); - createButton.setVisible(false); - refreshButton.setVisible(false); - - joinRoomItem.setVisible(true); - addRoomItem.setVisible(true); - createItem.setVisible(true); - refreshItem.setVisible(true); - - showHiddenButtons.setVisible(true); - } - - else if (this.getWidth() <= (twoButtonWidth + 19)) { - joinRoomButton.setVisible(true); - addRoomButton.setVisible(false); - createButton.setVisible(false); - refreshButton.setVisible(false); - - joinRoomItem.setVisible(false); - addRoomItem.setVisible(true); - createItem.setVisible(true); - refreshItem.setVisible(true); - - showHiddenButtons.setVisible(true); - } - - else if (this.getWidth() <= (threeButtonWidth + 19)) { - joinRoomButton.setVisible(true); - addRoomButton.setVisible(true); - createButton.setVisible(false); - refreshButton.setVisible(false); - - joinRoomItem.setVisible(false); - addRoomItem.setVisible(false); - createItem.setVisible(true); - refreshItem.setVisible(true); - - showHiddenButtons.setVisible(true); - } - - else if (this.getWidth() <= (allButtonWidth + 19)) { - joinRoomButton.setVisible(true); - addRoomButton.setVisible(true); - createButton.setVisible(true); - refreshButton.setVisible(false); - - joinRoomItem.setVisible(false); - addRoomItem.setVisible(false); - createItem.setVisible(false); - refreshItem.setVisible(true); - - showHiddenButtons.setVisible(true); - } - - else if (this.getWidth() > (allButtonWidth + 19)) { - joinRoomButton.setVisible(true); - addRoomButton.setVisible(true); - createButton.setVisible(true); - refreshButton.setVisible(true); - - joinRoomItem.setVisible(false); - addRoomItem.setVisible(false); - createItem.setVisible(false); - refreshItem.setVisible(false); - - showHiddenButtons.setVisible(false); - } - } - - public void componentShown(ComponentEvent e) { - - } - - // will need that, when the window is smaller than the buttons width... - private void setButtonsWidth() { - allButtonWidth = createButton.getWidth() + refreshButton.getWidth() - + addRoomButton.getWidth() + joinRoomButton.getWidth(); - threeButtonWidth = createButton.getWidth() + addRoomButton.getWidth() - + joinRoomButton.getWidth() + showHiddenButtons.getWidth(); - twoButtonWidth = addRoomButton.getWidth() + joinRoomButton.getWidth() - + showHiddenButtons.getWidth(); - oneButtonWidth = joinRoomButton.getWidth() - + showHiddenButtons.getWidth(); - } - -} diff --git a/src/java/org/jivesoftware/spark/ui/conferences/ConferenceServices.java b/src/java/org/jivesoftware/spark/ui/conferences/ConferenceServices.java deleted file mode 100644 index c924a0466..000000000 --- a/src/java/org/jivesoftware/spark/ui/conferences/ConferenceServices.java +++ /dev/null @@ -1,531 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.conferences; - -import java.awt.Frame; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.TimerTask; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPopupMenu; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; -import org.jivesoftware.smackx.bookmarks.BookmarkManager; -import org.jivesoftware.smackx.bookmarks.BookmarkedConference; -import org.jivesoftware.smackx.muc.InvitationListener; -import org.jivesoftware.smackx.muc.MultiUserChat; -import org.jivesoftware.smackx.muc.MultiUserChatManager; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.Workspace; -import org.jivesoftware.spark.plugin.ContextMenuListener; -import org.jivesoftware.spark.ui.ChatFrame; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomButton; -import org.jivesoftware.spark.ui.ChatRoomClosingListener; -import org.jivesoftware.spark.ui.ChatRoomListener; -import org.jivesoftware.spark.ui.ChatRoomNotFoundException; -import org.jivesoftware.spark.ui.ContactGroup; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.ui.PresenceListener; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.ui.rooms.GroupChatRoom; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.UIComponentRegistry; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -/** - * Conference plugin is reponsible for the initial loading of MultiUser Chat support. To disable plugin, - * you can remove from the plugins.xml file located in the classpath of Communicator. - */ -public class ConferenceServices implements InvitationListener { - private static BookmarksUI bookmarksUI = new BookmarksUI(); //This variable shouldn't be null. - - private static LocalPreferences _localPreferences = SettingsManager.getLocalPreferences(); - public ConferenceServices() { - ServiceDiscoveryManager manager = ServiceDiscoveryManager.getInstanceFor(SparkManager.getConnection()); - boolean mucSupported = manager.includesFeature("http://jabber.org/protocol/muc"); - - if (mucSupported) { - // Add an invitation listener. - addInvitationListener(); - - addChatRoomListener(); - - addPopupListeners(); - - // Add Join Conference Button to ActionMenu - - final JMenu actionsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions")); - JMenuItem actionMenuItem = new JMenuItem(Res.getString("message.join.conference.room"), SparkRes.getImageIcon(SparkRes.CONFERENCE_IMAGE_16x16)); - actionsMenu.add(actionMenuItem,1); - actionMenuItem.addActionListener( e -> { - ConferenceRoomBrowser rooms = new ConferenceRoomBrowser(bookmarksUI, getDefaultServiceName()); - rooms.invoke(); - } ); - - // Add Presence Listener to send directed presence to Group Chat Rooms. - PresenceListener presenceListener = presence -> SwingUtilities.invokeLater( () -> { - for (ChatRoom room : SparkManager.getChatManager().getChatContainer().getChatRooms()) { - if (room instanceof GroupChatRoom) { - int priority = presence.getPriority(); - //Sometimes priority is not set in the presence packet received. Make sure priority is in valid range - priority = (priority < -128 || priority > 128) ? 1 : priority; - final Presence p = new Presence(presence.getType(), presence.getStatus(), priority, presence.getMode()); - - GroupChatRoom groupChatRoom = (GroupChatRoom)room; - String jid = groupChatRoom.getMultiUserChat().getRoom(); - - p.setTo(jid); - try - { - SparkManager.getConnection().sendStanza(p); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to send stanza to " + p.getTo(), e ); - } - } - } - } ); - - SparkManager.getSessionManager().addPresenceListener(presenceListener); - } - } - - /** - * Adds an invitation listener to check for any MUC invites. - */ - private void addInvitationListener() { - MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).addInvitationListener( this ); - } - - /** - * Persists bookmarked data, if any. - */ - public void shutdown() { - } - - /** - * Load all bookmarked data. - */ - public void loadConferenceBookmarks() { - final TimerTask bookmarkLoader = new TimerTask(){ - - @Override - public void run() { - Collection bc = null; - - try { - while (bc == null) { - BookmarkManager manager = BookmarkManager.getBookmarkManager(SparkManager.getConnection()); - bc = manager.getBookmarkedConferences(); - } - } catch (XMPPException | SmackException error) { - Log.error(error); - } - bookmarksUI.loadUI(); - addBookmarksUI(); - } - - }; - TaskEngine.getInstance().schedule(bookmarkLoader, 500); - } - - protected void addBookmarksUI() { - final Workspace workspace = SparkManager.getWorkspace(); - final boolean useTab = _localPreferences.isShowConferenceTab(); - - if (useTab) { - workspace.getWorkspacePane().addTab(Res.getString("tab.conferences"), - SparkRes.getImageIcon(SparkRes.CONFERENCE_IMAGE_16x16), bookmarksUI); - } - } - - private void addChatRoomListener() { - ChatManager chatManager = SparkManager.getChatManager(); - chatManager.addChatRoomListener(new ChatRoomListener() { - public void chatRoomOpened(final ChatRoom room) { - if (room instanceof ChatRoomImpl) { - final ChatRoomDecorator decorator = new ChatRoomDecorator(room); - decorator.decorate(); - } - } - - public void chatRoomLeft(ChatRoom room) { - - } - - public void chatRoomClosed(ChatRoom room) { - - } - - public void chatRoomActivated(ChatRoom room) { - - } - - public void userHasJoined(ChatRoom room, String userid) { - - } - - public void userHasLeft(ChatRoom room, String userid) { - - } - }); - } - - - public boolean canShutDown() { - return true; - } - - public static String getDefaultServiceName() { - String serviceName = null; - Collection services = bookmarksUI.getMucServices(); - if (services != null) { - for (Object service : services) { - serviceName = (String) service; - break; - } - } - return serviceName; - } - - private void addPopupListeners() { - final ContactList contactList = SparkManager.getWorkspace().getContactList(); - - // Add ContactList items. - final Action inviteAllAction = new AbstractAction() { - private static final long serialVersionUID = -7486282521151183678L; - - public void actionPerformed(ActionEvent actionEvent) { - Collection contacts = contactList.getActiveGroup().getContactItems(); - startConference(contacts); - - } - }; - - inviteAllAction.putValue(Action.NAME, Res.getString("menuitem.invite.group.to.conference")); - inviteAllAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.CONFERENCE_IMAGE_16x16)); - - - final Action conferenceAction = new AbstractAction() { - private static final long serialVersionUID = 4724119680969496581L; - - public void actionPerformed(ActionEvent actionEvent) { - Collection contacts = contactList.getSelectedUsers(); - startConference(contacts); - } - }; - - conferenceAction.putValue(Action.NAME, Res.getString("menuitem.start.a.conference")); - conferenceAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_WORKGROUP_QUEUE_IMAGE)); - - - contactList.addContextMenuListener(new ContextMenuListener() { - public void poppingUp(Object component, JPopupMenu popup) { - Collection col = contactList.getSelectedUsers(); - if (component instanceof ContactGroup) { - popup.add(inviteAllAction); - } - else if (component instanceof Collection && col.size() > 0) { - popup.add(conferenceAction); - } - } - - public void poppingDown(JPopupMenu popup) { - - } - - public boolean handleDefaultAction(MouseEvent e) { - return false; - } - }); - - // Add to Actions Menu - final JMenu actionsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions")); - actionsMenu.add(conferenceAction); - } - - private void startConference(Collection items) { - final ContactList contactList = SparkManager.getWorkspace().getContactList(); - List jids = new ArrayList<>(); - for (ContactItem item : items) { - ContactGroup contactGroup = contactList.getContactGroup(item.getGroupName()); - contactGroup.clearSelection(); - - if (item.isAvailable()) { - jids.add(item.getJID()); - } - } - - String userName = XmppStringUtils.parseLocalpart(SparkManager.getSessionManager().getJID()); - final String roomName = userName + "_" + StringUtils.randomString(3); - - String serviceName = getDefaultServiceName(); - if (ModelUtil.hasLength(serviceName)) { - ConferenceUtils.inviteUsersToRoom(serviceName, roomName, jids, true); - } - } - - protected BookmarkedConference getDefaultBookmark() { - BookmarkedConference bookmarkedConference = null; - try { - Collection bookmarkedConfs = ConferenceUtils.retrieveBookmarkedConferences(); - String implicitBookmarkedJID = SettingsManager.getLocalPreferences().getDefaultBookmarkedConf(); - if (bookmarkedConfs != null && !bookmarkedConfs.isEmpty()) { - - // check if the "default" bookmarked conference is still in the bookmarks list: - if (implicitBookmarkedJID != null && implicitBookmarkedJID.trim().length() > 0) { - for (BookmarkedConference bc : bookmarkedConfs) { - if (implicitBookmarkedJID.equalsIgnoreCase(bc.getJid())) { - bookmarkedConference = bc; - break; - } - } - } - // if no match was found, or no "default" bookmark could be retrieved-use the - // first bookmark: - if (bookmarkedConference == null) { - bookmarkedConference = bookmarkedConfs.iterator().next(); - } - } - return bookmarkedConference; - } catch (XMPPException | SmackException ex) { - Log.warning("No default bookmark"); - // no bookmark can be retrieved; - } - return null; - - } - - /** - * Returns the UI for the addition and removal of Conference bookmarks. - * - * @return the BookedMarkedConferences UI. - */ - public static BookmarksUI getBookmarkedConferences() { - return bookmarksUI; - } - - private class ChatRoomDecorator implements ActionListener, ChatRoomClosingListener { - private ChatRoom chatRoom; - private ChatRoomButton inviteButton; - - public ChatRoomDecorator(ChatRoom room) { - this.chatRoom = room; - chatRoom.addClosingListener(this); - } - - public void decorate() { - - // Add Conference Invite Button. - inviteButton = UIComponentRegistry.getButtonFactory().createInviteConferenceButton(); - inviteButton.setToolTipText(Res.getString("title.invite.to.conference")); - - chatRoom.addChatRoomButton(inviteButton); - - inviteButton.addActionListener(this); - } - - - public void closing() { - inviteButton.removeActionListener(this); - chatRoom.removeClosingListener(this); - } - - public void actionPerformed(ActionEvent e) { - String userName = XmppStringUtils.parseLocalpart(SparkManager.getSessionManager().getJID()); - final String roomName = userName + "_" + StringUtils.randomString(3); - - - final List jids = new ArrayList<>(); - jids.add(((ChatRoomImpl)chatRoom).getParticipantJID()); - - final String serviceName = getDefaultServiceName(); - if (serviceName != null) { - SwingWorker worker = new SwingWorker() { - public Object construct() { - try { - Thread.sleep(25); - } - catch (InterruptedException e1) { - Log.error(e1); - } - return "ok"; - } - - public void finished() { - try { - BookmarkedConference selectedBookmarkedConf = _localPreferences.isUseAdHocRoom() ? null : getDefaultBookmark(); - if (selectedBookmarkedConf == null) { - ConferenceUtils.createPrivateConference(serviceName, - Res.getString("message.please.join.in.conference"), roomName, jids); - } else { - ConferenceUtils.joinConferenceOnSeperateThread(selectedBookmarkedConf.getName(), - selectedBookmarkedConf.getJid(), selectedBookmarkedConf.getPassword(), - Res.getString("message.please.join.in.conference"), jids); - } - } - catch (SmackException ex) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(chatRoom, "An error occurred.", Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - } - } - }; - worker.start(); - } - } - } - - @Override - public void invitationReceived(final XMPPConnection conn, final MultiUserChat room, final String inviter, final String reason, - final String password, final Message message) { - SwingUtilities.invokeLater( () -> { - Collection listeners = new ArrayList<>( SparkManager - .getChatManager().getInvitationListeners() ); - for (RoomInvitationListener listener : listeners) { - boolean handle = listener.handleInvitation(conn, room, inviter, reason, password, message); - if (handle) { - return; - } - } - - // Make sure the user is not already in the - // room. - try { - SparkManager.getChatManager().getChatContainer().getChatRoom(room.getRoom()); - return; - } catch (ChatRoomNotFoundException e) { - // Ignore :) - } - - final GroupChatInvitationUI invitationUI = new GroupChatInvitationUI(room.getRoom(), inviter, password, reason); - String message1 = Res.getString("message.invite.to.groupchat", inviter); - String title = Res.getString("title.group.chat"); - String bareJID = XmppStringUtils.parseBareJid(inviter); - - if (_localPreferences.isAutoAcceptMucInvite()) { - ConferenceUtils.enterRoomOnSameThread(XmppStringUtils.parseLocalpart(room.getRoom()), room.getRoom(), password); - MultiUserChatManager manager = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ); - GroupChatRoom chat = UIComponentRegistry.createGroupChatRoom(manager.getMultiUserChat( room.getRoom() )); - - showToaster( message1, title, chat); - return; - // Nothing to do here, we want to join the - // room, and stuff - } - try { - ChatRoom chatRoom = SparkManager.getChatManager().getChatContainer().getChatRoom(bareJID); - - // If the ChatRoom exists, add an invitationUI. - chatRoom.getTranscriptWindow().addComponent(invitationUI); - - // Notify user of incoming invitation. - chatRoom.increaseUnreadMessageCount(); - - chatRoom.scrollToBottom(); - - SparkManager.getChatManager().getChatContainer() - .fireNotifyOnMessage(chatRoom, true, message1, title); - } catch (ChatRoomNotFoundException e) { - // If it doesn't exists. Create a new Group - // Chat Room - // Create the Group Chat Room - final MultiUserChatManager manager = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ); - final GroupChatRoom groupChatRoom = UIComponentRegistry.createGroupChatRoom(manager.getMultiUserChat( room.getRoom() )); - - showToaster( message1, title, groupChatRoom); - - groupChatRoom.getSplitPane().setDividerSize(5); - groupChatRoom.getVerticalSlipPane().setDividerLocation(0.6); - groupChatRoom.getSplitPane().setDividerLocation(0.6); - String roomName = XmppStringUtils.parseLocalpart(room.getRoom()); - groupChatRoom.setTabTitle(roomName); - groupChatRoom.getToolBar().setVisible(true); - SparkManager.getChatManager().getChatContainer().addChatRoom(groupChatRoom); - groupChatRoom.getTranscriptWindow().addComponent(invitationUI); - // Notify user of incoming invitation. - groupChatRoom.increaseUnreadMessageCount(); - groupChatRoom.scrollToBottom(); - SparkManager.getChatManager().getChatContainer().fireNotifyOnMessage(groupChatRoom, true, message1, - title); - - } - // If no listeners handled the invitation, - // default to generic invite. - // new ConversationInvitation(conn, room, - // inviter, reason, password, message); - } ); - - } - - private void showToaster(String message, String title, GroupChatRoom groupChatRoom) { - if (_localPreferences.getShowToasterPopup()) { - SparkToaster toaster = new SparkToaster(); - - toaster.setCustomAction(new AbstractAction() { - private static final long serialVersionUID = -4546475740161533555L; - - @Override - public void actionPerformed(ActionEvent e) { - ChatFrame chatFrame = SparkManager.getChatManager().getChatContainer().getChatFrame(); - chatFrame.setState(Frame.NORMAL); - chatFrame.setVisible(true); - - } - }); - toaster.setDisplayTime(5000); - toaster.setBorder(BorderFactory.createBevelBorder(0)); - toaster.setToasterHeight(150); - toaster.setToasterWidth(200); - toaster.setTitle(title); - toaster.showToaster(groupChatRoom.getTabIcon(), message); - } - } - -} diff --git a/src/java/org/jivesoftware/spark/ui/conferences/ConferenceUtils.java b/src/java/org/jivesoftware/spark/ui/conferences/ConferenceUtils.java deleted file mode 100644 index ac1b17236..000000000 --- a/src/java/org/jivesoftware/spark/ui/conferences/ConferenceUtils.java +++ /dev/null @@ -1,714 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.conferences; - -import java.awt.Component; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.List; - -import javax.swing.JOptionPane; -import javax.swing.UIManager; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.packet.XMPPError; -import org.jivesoftware.smackx.muc.MultiUserChatManager; -import org.jivesoftware.smackx.xdata.Form; -import org.jivesoftware.smackx.xdata.FormField; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; -import org.jivesoftware.smackx.bookmarks.BookmarkManager; -import org.jivesoftware.smackx.bookmarks.BookmarkedConference; -import org.jivesoftware.smackx.muc.HostedRoom; -import org.jivesoftware.smackx.muc.MultiUserChat; -import org.jivesoftware.smackx.muc.RoomInfo; -import org.jivesoftware.smackx.xdata.packet.DataForm; -import org.jivesoftware.smackx.disco.packet.DiscoverInfo; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.PresenceManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.PasswordDialog; -import org.jivesoftware.spark.ui.ChatRoomNotFoundException; -import org.jivesoftware.spark.ui.rooms.GroupChatRoom; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.UIComponentRegistry; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.privacy.PrivacyManager; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -/** - * ConferenceUtils allow for basic joining and inviting of users. - */ -public class ConferenceUtils { - - private ConferenceUtils() { - } - - /** - * Return a list of available Conference rooms from the server - * based on the service name. - * - * @param serviceName the service name (ex. conference@jivesoftware.com) - * @return a collection of rooms. - * @throws Exception if an error occured during fetch. - */ - public static Collection getRoomList(String serviceName) throws Exception { - return MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getHostedRooms( serviceName ); - } - - /** - * Return the number of occupants in a room. - * - * @param roomJID the full JID of the conference room. (ex. dev@conference.jivesoftware.com) - * @return the number of occupants in the room if available. - * @throws XMPPException thrown if an error occured during retrieval of the information. - */ - public static int getNumberOfOccupants(String roomJID) throws SmackException, XMPPException { - final RoomInfo roomInfo = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getRoomInfo( roomJID ); - return roomInfo.getOccupantsCount(); - } - - /** - * Retrieve the date (in yyyyMMdd) format of the time the room was created. - * - * @param roomJID the jid of the room. - * @return the formatted date. - * @throws Exception throws an exception if we are unable to retrieve the date. - */ - public static String getCreationDate(String roomJID) throws Exception { - ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(SparkManager.getConnection()); - - final DateFormat dateFormatter = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss"); - DiscoverInfo infoResult = discoManager.discoverInfo(roomJID); - DataForm dataForm = infoResult.getExtension("x", "jabber:x:data"); - if (dataForm == null) { - return "Not available"; - } - String creationDate = ""; - for ( final FormField field : dataForm.getFields() ) { - String label = field.getLabel(); - - - if (label != null && "Creation date".equalsIgnoreCase(label)) { - for ( String value : field.getValues() ) { - creationDate = value; - Date date = dateFormatter.parse(creationDate); - creationDate = DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.MEDIUM).format(date); - } - } - } - return creationDate; - } - - public static void joinConferenceOnSeperateThread(final String roomName, String roomJID, String password) { - joinConferenceOnSeperateThread(roomName, roomJID, password, null, null); - } - - /** - * Joins a conference room using another thread. This allows for a smoother opening of rooms. - * - * @param roomName the name of the room. - * @param roomJID the jid of the room. - * @param password the rooms password if required. - */ - public static void joinConferenceOnSeperateThread(final String roomName, String roomJID, String password, final String message, final Collection jids) { - ChatManager chatManager = SparkManager.getChatManager(); - LocalPreferences pref = SettingsManager.getLocalPreferences(); - - final MultiUserChat groupChat = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getMultiUserChat( roomJID ); - final String nickname = pref.getNickname().trim(); - - // Check if room already exists. If so, join room again. - try { - GroupChatRoom chatRoom = (GroupChatRoom)chatManager.getChatContainer().getChatRoom(roomJID); - MultiUserChat muc = chatRoom.getMultiUserChat(); - chatRoom.setPassword(password); - if (!muc.isJoined()) { - joinRoom(muc, nickname, password); - } - - chatManager.getChatContainer().activateChatRoom(chatRoom); - invite(groupChat, chatRoom, jids, message); - return; - } - catch (ChatRoomNotFoundException e) { - // Nothing to do - } - - - final GroupChatRoom room = UIComponentRegistry.createGroupChatRoom(groupChat); - room.setTabTitle(roomName); - room.setPassword(password); - - if (isPasswordRequired(roomJID) && password == null) { - final PasswordDialog passwordDialog = new PasswordDialog(); - password = passwordDialog.getPassword(Res.getString("title.password.required"), Res.getString("message.groupchat.require.password"), SparkRes.getImageIcon(SparkRes.LOCK_16x16), SparkManager.getFocusedComponent()); - room.setPassword(password); - if (!ModelUtil.hasLength(password)) { - return; - } - } - - - final List errors = new ArrayList<>(); - final String userPassword = password; - - final SwingWorker startChat = new SwingWorker() { - public Object construct() { - if (!groupChat.isJoined()) { - int groupChatCounter = 0; - while (true) { - groupChatCounter++; - String joinName = nickname; - if (groupChatCounter > 1) { - joinName = joinName + groupChatCounter; - } - if (groupChatCounter < 10) { - try { - if (!confirmToRevealVisibility()) - return null; - - if (ModelUtil.hasLength(userPassword)) { - groupChat.join(joinName, userPassword); - } - else { - groupChat.join(joinName); - } - break; - } - catch (XMPPException | SmackException ex) { - XMPPError error = null; - if ( ex instanceof XMPPException.XMPPErrorException) { - error = (( XMPPException.XMPPErrorException ) ex).getXMPPError(); - } - - final String errorText = ConferenceUtils.getReason( error ); - - errors.add( errorText ); - if ( error.getCondition() != XMPPError.Condition.conflict ) - { - break; - } - } - } - else { - break; - } - } - } - invite(groupChat, room, jids, message); - return "ok"; - } - - public void finished() { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - if (errors.size() > 0) { - String error = errors.get(0); - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), error, "Unable to join the room at this time.", JOptionPane.ERROR_MESSAGE); - } - else if (groupChat.isJoined()) { - changePresenceToAvailableIfInvisible(); - ChatManager chatManager = SparkManager.getChatManager(); - chatManager.getChatContainer().addChatRoom(room); - chatManager.getChatContainer().activateChatRoom(room); - } - else { - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), "Unable to join the room.", "Error", JOptionPane.ERROR_MESSAGE); - } - } - }; - - startChat.start(); - } - - private static void invite(MultiUserChat groupChat, GroupChatRoom room, Collection jids, String message) - { - if (jids != null && message != null) { - for (String jid : jids) { - try - { - groupChat.invite(jid, message); - room.getTranscriptWindow().insertNotificationMessage( - Res.getString("message.waiting.for.user.to.join", jid), ChatManager.NOTIFICATION_COLOR); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to invite " + jid + " to " + room, e ); - } - } - } - } - - /** - * Presents the user with a dialog pre-filled with the room name and the jid. - * - * @param roomName the name of the room. - * @param roomJID the rooms jid. - */ - public static void joinConferenceRoom(final String roomName, String roomJID) { - JoinConferenceRoomDialog joinDialog = new JoinConferenceRoomDialog(); - joinDialog.joinRoom(roomJID, roomName); - changePresenceToAvailableIfInvisible(); - } - - - /** - * Joins a chat room without using the UI. - * - * @param groupChat the MultiUserChat - * @param nickname the nickname of the user. - * @param password the password to join the room with. - * @return a List of errors, if any. - */ - public static List joinRoom(MultiUserChat groupChat, String nickname, String password) { - final List errors = new ArrayList<>(); - if (!groupChat.isJoined()) { - int groupChatCounter = 0; - while (true) { - groupChatCounter++; - String joinName = nickname; - if (groupChatCounter > 1) { - joinName = joinName + groupChatCounter; - } - if (groupChatCounter < 10) { - try { - if (ModelUtil.hasLength(password)) { - groupChat.join(joinName, password); - } - else { - groupChat.join(joinName); - } - changePresenceToAvailableIfInvisible(); - break; - } - catch (XMPPException | SmackException ex) { - XMPPError error = null; - if ( ex instanceof XMPPException.XMPPErrorException) { - error = (( XMPPException.XMPPErrorException ) ex).getXMPPError(); - } - - final String errorText = ConferenceUtils.getReason( error ); - - errors.add( errorText ); - if ( error.getCondition() != XMPPError.Condition.conflict ) - { - break; - } - } - } - else { - break; - } - } - } - - return errors; - } - - /** - * Invites users to an existing room. - * - * @param chat The room to invite people into. - * @param jids a collection of the users to invite. - */ - public static void inviteUsersToRoom(MultiUserChat chat, Collection jids, boolean randomName ) { - inviteUsersToRoom( XmppStringUtils.parseDomain( chat.getRoom() ), XmppStringUtils.parseLocalpart( chat.getRoom() ), jids, randomName ); - } - - /** - * Invites users to an existing room. - * - * @param serviceName the service name to use. - * @param roomName the name of the room. - * @param jids a collection of the users to invite. - */ - public static void inviteUsersToRoom(String serviceName, String roomName, Collection jids, boolean randomName) { - final LocalPreferences pref = SettingsManager.getLocalPreferences(); - boolean useTextField = pref.isUseAdHocRoom(); - Collection rooms = null; - if (!useTextField) { - try { - rooms = retrieveBookmarkedConferences(); - } catch (Exception ex) { - Log.error(ex); - } - useTextField = !randomName || (rooms == null || rooms.size() == 0); - } - InvitationDialog inviteDialog = new InvitationDialog(useTextField); - inviteDialog.inviteUsersToRoom(serviceName, rooms, roomName, jids); - } - - public static Collection retrieveBookmarkedConferences() throws XMPPException, SmackException - { - BookmarkManager manager = BookmarkManager.getBookmarkManager(SparkManager.getConnection()); - return manager.getBookmarkedConferences(); - } - - /** - * Returns true if the room requires a password. - * - * @param roomJID the JID of the room. - * @return true if the room requires a password. - */ - public static boolean isPasswordRequired(String roomJID) { - // Check to see if the room is password protected - ServiceDiscoveryManager discover = ServiceDiscoveryManager.getInstanceFor(SparkManager.getConnection()); - - - try { - DiscoverInfo info = discover.discoverInfo(roomJID); - return info.containsFeature("muc_passwordprotected"); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - return false; - } - - /** - * Creates a private conference. - * - * @param serviceName the service name to use for the private conference. - * @param message the message sent to each individual invitee. - * @param roomName the name of the room to create. - * @param jids a collection of the user JIDs to invite. - * @throws XMPPException thrown if an error occurs during room creation. - */ - public static void createPrivateConference(String serviceName, String message, String roomName, Collection jids) throws SmackException - { - final String roomJID = XmppStringUtils.escapeLocalpart(roomName) + "@" + serviceName; - final MultiUserChat multiUserChat = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getMultiUserChat( roomJID ); - final LocalPreferences pref = SettingsManager.getLocalPreferences(); - - - final GroupChatRoom room = UIComponentRegistry.createGroupChatRoom(multiUserChat); - try { - // Attempt to create room. - multiUserChat.create(pref.getNickname()); - } - catch (XMPPException | SmackException e) { - throw new SmackException(e); - } - - try { - // Since this is a private room, make the room not public and set user as owner of the room. - Form submitForm = multiUserChat.getConfigurationForm().createAnswerForm(); - submitForm.setAnswer("muc#roomconfig_publicroom", false); - submitForm.setAnswer("muc#roomconfig_roomname", roomName); - - final List owners = new ArrayList<>(); - owners.add(SparkManager.getSessionManager().getBareAddress()); - submitForm.setAnswer("muc#roomconfig_roomowners", owners); - - multiUserChat.sendConfigurationForm(submitForm); - } - catch (XMPPException | SmackException e1) { - Log.error("Unable to send conference room chat configuration form.", e1); - } - - - ChatManager chatManager = SparkManager.getChatManager(); - - // Check if room already is open - try { - chatManager.getChatContainer().getChatRoom(room.getRoomname()); - } - catch (ChatRoomNotFoundException e) { - chatManager.getChatContainer().addChatRoom(room); - chatManager.getChatContainer().activateChatRoom(room); - } - - for (String jid : jids) { - multiUserChat.invite(jid, message); - room.getTranscriptWindow().insertNotificationMessage(Res.getString("message.waiting.for.user.to.join",jid), ChatManager.NOTIFICATION_COLOR); - } - } - - /** - * Returns an explanation for the exception. - * - * @param error The XMPP error - * @return the reason for the exception. - * @see XEP-0045 Error Conditions - */ - public static String getReason(XMPPError error) { - if (error == null) { - return "No response from server."; - } - - switch ( error.getCondition() ) - { - case conflict: - return "Your desired nickname is in use or reserved by someone else."; - case forbidden: - return "You have been banned from this room."; - case item_not_found: - return "The room you are trying to enter does not exist."; - case not_acceptable: - return "You must use your reserved room nick."; - case not_allowed: - return "You do not have permission to create a room."; - case not_authorized: - return "The password did not match the room's password."; - case registration_required: - return "You are not a member of this room.\nThis room requires you to be a member to join."; - default: - return "An error has occurred: " + error.getConditionText(); - } - - } - - /** - * Enters a GroupChatRoom on the event thread. - * - * @param roomName the name of the room. - * @param roomJID the rooms jid. - * @param password the rooms password (if any). - * @return the GroupChatRoom created. - */ - public static GroupChatRoom enterRoomOnSameThread(final String roomName, String roomJID, String password) { - ChatManager chatManager = SparkManager.getChatManager(); - - - final LocalPreferences pref = SettingsManager.getLocalPreferences(); - - final String nickname = pref.getNickname().trim(); - - - try { - GroupChatRoom chatRoom = (GroupChatRoom)chatManager.getChatContainer().getChatRoom(roomJID); - MultiUserChat muc = chatRoom.getMultiUserChat(); - if (!muc.isJoined()) { - joinRoom(muc, nickname, password); - } - chatManager.getChatContainer().activateChatRoom(chatRoom); - return chatRoom; - } - catch (ChatRoomNotFoundException e) { - // Nothing to do - } - - final MultiUserChat groupChat = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getMultiUserChat( roomJID ); - - - final GroupChatRoom room = UIComponentRegistry.createGroupChatRoom(groupChat); - room.setTabTitle(roomName); - - - if (isPasswordRequired(roomJID) && password == null) { - password = JOptionPane.showInputDialog(null, "Enter Room Password", "Need Password", JOptionPane.QUESTION_MESSAGE); - if (!ModelUtil.hasLength(password)) { - return null; - } - } - - - final List errors = new ArrayList<>(); - final String userPassword = password; - - - if (!groupChat.isJoined()) { - int groupChatCounter = 0; - while (true) { - groupChatCounter++; - String joinName = nickname; - if (groupChatCounter > 1) { - joinName = joinName + groupChatCounter; - } - if (groupChatCounter < 10) { - try { - if (!confirmToRevealVisibility()) - return null; - - if (ModelUtil.hasLength(userPassword)) { - groupChat.join(joinName, userPassword); - } - else { - groupChat.join(joinName); - } - break; - } - catch (XMPPException | SmackException ex) { - XMPPError error = null; - if ( ex instanceof XMPPException.XMPPErrorException) { - error = (( XMPPException.XMPPErrorException ) ex).getXMPPError(); - } - - final String errorText = ConferenceUtils.getReason( error ); - - errors.add( errorText ); - if ( error.getCondition() != XMPPError.Condition.conflict ) - { - break; - } - } - } - else { - break; - } - } - - } - - - if (errors.size() > 0) { - String error = errors.get(0); - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), error, "Unable to join the room at this time.", JOptionPane.ERROR_MESSAGE); - return null; - } - else if (groupChat.isJoined()) { - changePresenceToAvailableIfInvisible(); - chatManager.getChatContainer().addChatRoom(room); - chatManager.getChatContainer().activateChatRoom(room); - } - else { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), "Unable to join the room.", "Error", JOptionPane.ERROR_MESSAGE); - return null; - } - return room; - } - - public static void enterRoom(final MultiUserChat groupChat, String tabTitle, final String nickname, final String password) { - final GroupChatRoom room = UIComponentRegistry.createGroupChatRoom(groupChat); - room.setTabTitle(tabTitle); - - final List errors = new ArrayList<>(); - - if (!groupChat.isJoined()) { - int groupChatCounter = 0; - while (true) { - groupChatCounter++; - String joinName = nickname; - if (groupChatCounter > 1) { - joinName = joinName + groupChatCounter; - } - if (groupChatCounter < 10) { - try { - if (!confirmToRevealVisibility()) - return; - - if (ModelUtil.hasLength(password)) { - groupChat.join(joinName, password); - } - else { - groupChat.join(joinName); - } - break; - } - catch (XMPPException | SmackException ex) { - XMPPError error = null; - if ( ex instanceof XMPPException.XMPPErrorException) { - error = (( XMPPException.XMPPErrorException ) ex).getXMPPError(); - } - - final String errorText = ConferenceUtils.getReason( error ); - - errors.add( errorText ); - if ( error.getCondition() != XMPPError.Condition.conflict ) - { - break; - } - } - } - else { - break; - } - } - } - - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - - if (errors.size() > 0) { - String error = errors.get(0); - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), error, "Could Not Join Room", JOptionPane.ERROR_MESSAGE); - } - else if (groupChat.isJoined()) { - changePresenceToAvailableIfInvisible(); - ChatManager chatManager = SparkManager.getChatManager(); - chatManager.getChatContainer().addChatRoom(room); - chatManager.getChatContainer().activateChatRoom(room); - } - else { - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), "Unable to join room.", "Error", JOptionPane.ERROR_MESSAGE); - } - - } - - final static List unclosableChatRooms = new ArrayList<>(); - public synchronized static void addUnclosableChatRoom(String jid) { - unclosableChatRooms.add(jid); - } - - public static boolean isChatRoomClosable(Component c) { - if(c instanceof GroupChatRoom ) { - GroupChatRoom groupChatRoom = (GroupChatRoom) c; - String roomName = groupChatRoom.getChatRoom().getRoomname(); - - if(unclosableChatRooms.contains(roomName)){ - return false; - } - } - return true; - - } - - public static boolean confirmToRevealVisibility() { - Presence currentPresence = SparkManager.getWorkspace().getStatusBar().getPresence(); - - if (!PresenceManager.isInvisible(currentPresence)) - return true; - - int reply = JOptionPane.showConfirmDialog(null, - Res.getString("dialog.confirm.to.reveal.visibility.msg"), - Res.getString("dialog.confirm.to.reveal.visibility.title"), - JOptionPane.YES_NO_OPTION); - return reply == JOptionPane.YES_OPTION; - } - - /** - * If the current present is 'invisible' then this method change it to - * 'Online'. Decided 'invisibility' is a kind of private thing. So if user - * would like to go to the conference then the user reveal him/herself. i.e. - * if current presence is invisible then we should go to visible. Otherwise - * all 'invisible' users will be shown as 'Offline' on the conference - * participant list which is confusing. This method mostly is used in - * ConferenceUtils. Usually it is called after user is joined to a room. - */ - public static void changePresenceToAvailableIfInvisible() { - Presence currentPresence = SparkManager.getWorkspace().getStatusBar().getPresence(); - if (PresenceManager.isInvisible(currentPresence)) { - PrivacyManager.getInstance().goToVisible(); - SparkManager.getSessionManager().changePresence(PresenceManager.getAvailablePresence()); - } - } - -} - diff --git a/src/java/org/jivesoftware/spark/ui/conferences/DataFormDialog.java b/src/java/org/jivesoftware/spark/ui/conferences/DataFormDialog.java deleted file mode 100644 index c33a4de6b..000000000 --- a/src/java/org/jivesoftware/spark/ui/conferences/DataFormDialog.java +++ /dev/null @@ -1,282 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.conferences; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.StringTokenizer; - -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JPasswordField; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.JTextField; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.muc.MultiUserChatManager; -import org.jivesoftware.smackx.xdata.Form; -import org.jivesoftware.smackx.xdata.FormField; -import org.jivesoftware.smackx.xdata.FormField.Option; -import org.jivesoftware.smackx.bookmarks.BookmarkManager; -import org.jivesoftware.smackx.muc.MultiUserChat; -import org.jivesoftware.smackx.muc.RoomInfo; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.CheckBoxList; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.log.Log; - -public class DataFormDialog extends JPanel { - private static final long serialVersionUID = -1536217028590811636L; - private final Map valueMap = new HashMap<>(); - private int row = 0; - JDialog dialog = null; - - - public DataFormDialog(JFrame parent, final MultiUserChat chat, final Form submitForm) { - dialog = new JDialog(parent, true); - dialog.setTitle(Res.getString("title.configure.chat.room")); - - this.setLayout(new GridBagLayout()); - Form form = null; - // Create the room - try { - form = chat.getConfigurationForm(); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - - // Create a new form to submit based on the original form - try { - // Add default answers to the form to submit - for ( final FormField field : form.getFields() ) { - submitForm.addField(field); - String variable = field.getVariable(); - String label = field.getLabel(); - FormField.Type type = field.getType(); - - List valueList = field.getValues(); - - if (type.equals(FormField.Type.bool)) { - String o = valueList.get(0); - boolean isSelected = o.equals("1"); - JCheckBox box = new JCheckBox(label); - box.setSelected(isSelected); - addField(label, box, variable); - } - else if (type.equals(FormField.Type.text_single) || - type.equals(FormField.Type.jid_single)) { - String value = valueList.get(0); - addField(label, new JTextField(value), variable); - } - else if (type.equals(FormField.Type.text_multi) || - type.equals(FormField.Type.jid_multi)) { - StringBuilder buf = new StringBuilder(); - final Iterator iter = valueList.iterator(); - while (iter.hasNext()) { - buf.append( iter.next() ); - - if (iter.hasNext()) { - buf.append(","); - } - } - addField(label, new JTextArea(buf.toString()), variable); - } - else if (type.equals(FormField.Type.text_private)) { - addField(label, new JPasswordField(), variable); - } - else if (type.equals(FormField.Type.list_single)) { - JComboBox box = new JComboBox(); - for ( final FormField.Option option : field.getOptions() ) { - String value = option.getValue(); - box.addItem(value); - } - if (valueList.size() > 0) { - String defaultValue = valueList.get(0); - box.setSelectedItem(defaultValue); - } - - addField(label, box, variable); - } - else if (type.equals(FormField.Type.list_multi)) { - CheckBoxList checkBoxList = new CheckBoxList(); - final List values = field.getValues(); - for ( final Option option : field.getOptions() ) { - String optionLabel = option.getLabel(); - String optionValue = option.getValue(); - checkBoxList.addCheckBox(new JCheckBox(optionLabel, values.contains(optionValue)), optionValue); - } - addField(label, checkBoxList, variable); - } - } - } - catch (NullPointerException e) { - Log.error(e); - } - - - JButton button = new JButton(); - ResourceUtils.resButton(button, Res.getString("button.update")); - button.addActionListener( e -> { - dialog.dispose(); - // Now submit all information - updateRoomConfiguration(submitForm, chat); - } ); - - final JScrollPane pane = new JScrollPane(this); - pane.getVerticalScrollBar().setBlockIncrement(200); - pane.getVerticalScrollBar().setUnitIncrement(20); - - dialog.getContentPane().setLayout(new BorderLayout()); - - dialog.getContentPane().add(pane, BorderLayout.CENTER); - - JPanel bottomPanel = new JPanel(); - bottomPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)); - bottomPanel.add(button); - - JButton cancelButton = new JButton(); - ResourceUtils.resButton(cancelButton, Res.getString("button.cancel")); - cancelButton.addActionListener( actionEvent -> dialog.dispose() ); - - bottomPanel.add(cancelButton); - - dialog.getContentPane().add(bottomPanel, BorderLayout.SOUTH); - - dialog.pack(); - dialog.setSize(600, 400); - GraphicUtils.centerWindowOnScreen(dialog); - dialog.setVisible(true); - - - } - - private void updateRoomConfiguration(Form submitForm, MultiUserChat chat) { - for (Object o1 : valueMap.keySet()) { - String answer = (String) o1; - Object o = valueMap.get(answer); - if (o instanceof JCheckBox) { - boolean isSelected = ((JCheckBox) o).isSelected(); - submitForm.setAnswer(answer, isSelected); - } else if (o instanceof JTextArea) { - List list = new ArrayList<>(); - String value = ((JTextArea) o).getText(); - StringTokenizer tokenizer = new StringTokenizer(value, ", ", false); - while (tokenizer.hasMoreTokens()) { - list.add(tokenizer.nextToken()); - } - if (list.size() > 0) { - submitForm.setAnswer(answer, list); - } - } else if (o instanceof JTextField) { - String value = ((JTextField) o).getText(); - if (ModelUtil.hasLength(value)) { - submitForm.setAnswer(answer, value); - } - } else if (o instanceof JComboBox) { - String value = (String) ((JComboBox) o).getSelectedItem(); - List list = new ArrayList<>(); - list.add(value); - if (list.size() > 0) { - submitForm.setAnswer(answer, list); - } - } else if (o instanceof CheckBoxList) { - List list = ((CheckBoxList) o).getSelectedValues(); - if (list.size() > 0) { - submitForm.setAnswer(answer, list); - } - } - } - - - try { - chat.sendConfigurationForm(submitForm); - RoomInfo info = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getRoomInfo( chat.getRoom() ); - //remove bookmark if any for non persistent room - if (!info.isPersistent()) { - BookmarkManager.getBookmarkManager(SparkManager.getConnection()).removeBookmarkedConference(info.getRoom()); - } - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - } - - private void addField(String label, JComponent comp, String variable) { - - if (!(comp instanceof JCheckBox)) { - JLabel formLabel = new JLabel(label); - formLabel.setFont(new Font("dialog", Font.BOLD, 10)); - this.add(formLabel, new GridBagConstraints(0, row, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - } - if (comp instanceof JTextArea) { - JScrollPane pane = new JScrollPane(comp); - pane.setBorder(BorderFactory.createTitledBorder(Res.getString("group.comma.delimited"))); - this.add(pane, new GridBagConstraints(1, row, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 75, 50)); - } - else if (comp instanceof JCheckBox) { - this.add(comp, new GridBagConstraints(0, row, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - } - else if (comp instanceof CheckBoxList) { - this.add(comp, new GridBagConstraints(1, row, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 75, 50)); - } - else { - this.add(comp, new GridBagConstraints(1, row, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 75, 0)); - - } - valueMap.put(variable, comp); - row++; - } - - - public String getValue(String label) { - Component comp = valueMap.get(label); - if (comp instanceof JCheckBox) { - return "" + ((JCheckBox)comp).isSelected(); - } - - if (comp instanceof JTextField) { - return ((JTextField)comp).getText(); - } - return null; - } -} diff --git a/src/java/org/jivesoftware/spark/ui/conferences/GroupChatInvitationUI.java b/src/java/org/jivesoftware/spark/ui/conferences/GroupChatInvitationUI.java deleted file mode 100644 index e4b856424..000000000 --- a/src/java/org/jivesoftware/spark/ui/conferences/GroupChatInvitationUI.java +++ /dev/null @@ -1,202 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.conferences; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smackx.muc.MultiUserChatManager; -import org.jivesoftware.spark.ChatNotFoundException; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.rooms.GroupChatRoom; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.SwingTimerTask; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; - -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextPane; -import javax.swing.text.BadLocationException; -import javax.swing.text.Document; -import javax.swing.text.SimpleAttributeSet; -import javax.swing.text.StyleConstants; - -import java.awt.Color; -import java.awt.Container; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.TimerTask; - -/** - * Conference Invitation UI. - * - * @author Derek DeMoro - */ -public class GroupChatInvitationUI extends JPanel implements ActionListener { - - private static final long serialVersionUID = 6066796370413837508L; - - private RolloverButton acceptButton; - - private String room; - private String inviter; - private String password; - - public GroupChatInvitationUI(String room, String inviter, String password, String reason) { - setLayout(new GridBagLayout()); - - setBackground(new Color(230, 239, 249)); - - this.room = room; - this.inviter = inviter; - this.password = password; - - // Build invitation time label. - final Date now = new Date(); - String invitationDateFormat = ( (SimpleDateFormat) SimpleDateFormat.getTimeInstance( SimpleDateFormat.MEDIUM ) ).toPattern(); - final SimpleDateFormat dateFormatter = new SimpleDateFormat( invitationDateFormat ); - final String invitationTime = dateFormatter.format(now); - - // Get users nickname, if there is one. - String nickname = SparkManager.getUserManager().getUserNicknameFromJID(inviter); - - - JLabel iconLabel = new JLabel(SparkRes.getImageIcon(SparkRes.CONFERENCE_IMAGE_48x48)); - - JTextPane titleLabel = new JTextPane(); - titleLabel.setOpaque(false); - titleLabel.setEditable(false); - titleLabel.setBackground(new Color(230, 239, 249)); - - acceptButton = new RolloverButton(Res.getString("button.accept").replace("&",""), SparkRes.getImageIcon(SparkRes.ACCEPT_INVITE_IMAGE)); - acceptButton.setForeground(new Color(63, 158, 61)); - - RolloverButton rejectButton = new RolloverButton(Res.getString("button.reject"), SparkRes.getImageIcon(SparkRes.REJECT_INVITE_IMAGE)); - rejectButton.setForeground(new Color(185, 33, 33)); - - add(iconLabel, new GridBagConstraints(0, 0, 1, 2, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - - add(titleLabel, new GridBagConstraints(1, 0, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0)); - - add(acceptButton, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 2, 2, 2), 0, 0)); - add(rejectButton, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 2, 2, 2), 0, 0)); - - final SimpleAttributeSet styles = new SimpleAttributeSet(); - StyleConstants.setForeground(styles, new Color(13, 104, 196)); - - Document document = titleLabel.getDocument(); - try { - document.insertString(0, "[" + invitationTime + "] ", styles); - StyleConstants.setBold(styles, true); - document.insertString(document.getLength(), Res.getString("message.invite.to.groupchat",nickname) , styles); - - if (ModelUtil.hasLength(reason)) { - StyleConstants.setBold(styles, false); - document.insertString(document.getLength(), "\nMessage: " + reason, styles); - } - } - catch (BadLocationException e) { - Log.error(e); - } - - acceptButton.addActionListener(this); - rejectButton.addActionListener(this); - } - - public void actionPerformed(ActionEvent event) { - if (event.getSource() == acceptButton) { - acceptInvitation(); - } - else { - rejectInvitation(); - } - } - - /** - * Action taking when a user clicks on the accept button. - */ - private void acceptInvitation() { - setVisible(false); - String name = XmppStringUtils.parseLocalpart(room); - ConferenceUtils.enterRoomOnSameThread(name, room, password); - - final TimerTask removeUITask = new SwingTimerTask() { - public void doRun() { - removeUI(); - } - }; - - TaskEngine.getInstance().schedule(removeUITask, 2000); - } - - - /** - * Action taking when a user clicks on the reject button. - */ - private void rejectInvitation() - { - removeUI(); - - try { - ChatRoom chatRoom = SparkManager.getChatManager().getGroupChat(room); - if (chatRoom instanceof GroupChatRoom) { - GroupChatRoom gcr = (GroupChatRoom)chatRoom; - if (!gcr.getMultiUserChat().isJoined()) { - chatRoom.closeChatRoom(); - } - } - } - catch (ChatNotFoundException e) { - // Ignore - } - - try - { - MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).decline( room, inviter, "No thank you"); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to decline inviation from " + inviter + " to join room " + room, e ); - } - } - - /** - * Removes this interface from it's parent. - */ - private void removeUI() { - final Container par = getParent(); - if (par != null) { - par.remove(this); - par.invalidate(); - par.validate(); - par.repaint(); - } - - } -} diff --git a/src/java/org/jivesoftware/spark/ui/conferences/GroupChatParticipantList.java b/src/java/org/jivesoftware/spark/ui/conferences/GroupChatParticipantList.java deleted file mode 100644 index a5f0eb470..000000000 --- a/src/java/org/jivesoftware/spark/ui/conferences/GroupChatParticipantList.java +++ /dev/null @@ -1,1357 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.conferences; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.Point; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.DefaultListModel; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.ListCellRenderer; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; - -import org.jdesktop.swingx.JXList; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.PresenceListener; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.ExtensionElement; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.packet.XMPPError; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; -import org.jivesoftware.smackx.muc.*; -import org.jivesoftware.smackx.disco.packet.DiscoverInfo; -import org.jivesoftware.smackx.muc.packet.MUCItem; -import org.jivesoftware.smackx.muc.packet.MUCUser; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.PresenceManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.UserManager; -import org.jivesoftware.spark.component.ImageTitlePanel; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomNotFoundException; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.ui.rooms.GroupChatRoom; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -/** - * The RoomInfo class is used to display all room information, such - * as agents and room information. - */ -public class GroupChatParticipantList extends JPanel { - - private static final long serialVersionUID = 3809155443119207342L; - private GroupChatRoom groupChatRoom; - private final ImageTitlePanel agentInfoPanel; - private ChatManager chatManager; - private MultiUserChat chat; - private LocalPreferences _localPreferences = SettingsManager.getLocalPreferences(); - - private final Map userMap = new HashMap<>(); - - private UserManager userManager = SparkManager.getUserManager(); - - private DefaultListModel model = new DefaultListModel(); - - private JXList participantsList; - - private PresenceListener listener = null; - - private Map invitees = new HashMap<>(); - - private boolean allowNicknameChange = true; - - private DiscoverInfo roomInformation; - - private List users = new ArrayList<>(); - - private HashMap usersandRoles = new HashMap<>(); - - /** - * Creates a new RoomInfo instance using the specified ChatRoom. The - * RoomInfo component is responsible for monitoring all activity in the - * ChatRoom. - */ - public GroupChatParticipantList() { - setLayout(new GridBagLayout()); - chatManager = SparkManager.getChatManager(); - - agentInfoPanel = new ImageTitlePanel(Res - .getString("message.participants.in.room")); - participantsList = new JXList(model); - participantsList.setCellRenderer(new ParticipantRenderer()); - - // Set the room to track - this.setOpaque(false); - this.setBackground(Color.white); - - // Respond to Double-Click in Agent List to start a chat - participantsList.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent evt) { - if (evt.getClickCount() == 2) { - String selectedUser = getSelectedUser(); - startChat(groupChatRoom, userMap.get(selectedUser)); - } - } - - public void mouseReleased(final MouseEvent evt) { - if (evt.isPopupTrigger()) { - checkPopup(evt); - } - } - - public void mousePressed(final MouseEvent evt) { - if (evt.isPopupTrigger()) { - checkPopup(evt); - } - } - }); - - JScrollPane scroller = new JScrollPane(participantsList); - - // Speed up scrolling. It was way too slow. - scroller.getVerticalScrollBar().setBlockIncrement(200); - scroller.getVerticalScrollBar().setUnitIncrement(20); - scroller.setBackground(Color.white); - scroller.getViewport().setBackground(Color.white); - - add(scroller, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets( - 0, 0, 0, 0), 0, 0)); - } - - public void setChatRoom(final ChatRoom chatRoom) { - this.groupChatRoom = (GroupChatRoom) chatRoom; - - chat = groupChatRoom.getMultiUserChat(); - - chat.addInvitationRejectionListener( ( jid1, message ) -> { - String nickname = userManager.getUserNicknameFromJID( jid1 ); - - userHasLeft(nickname); - - chatRoom.getTranscriptWindow().insertNotificationMessage( - nickname + " has rejected the invitation.", - ChatManager.NOTIFICATION_COLOR); - } ); - - listener = p -> SwingUtilities.invokeLater( () -> { -if (p.getError() != null) { -if (p.getError() -.getCondition() -.equals(XMPPError.Condition.conflict -.toString())) { -return; -} -} -final String userid = p.getFrom(); - -String displayName = XmppStringUtils.parseResource(userid); -userMap.put(displayName, userid); - -if (p.getType() == Presence.Type.available) { -addParticipant(userid, p); -agentInfoPanel.setVisible(true); -} else { -removeUser(displayName); -} - -// When joining a room, check if the current user is an owner/admin. If so, the UI should allow the current -// user to change settings of this MUC. -final MUCUser mucUserEx = p.getExtension( MUCUser.ELEMENT, MUCUser.NAMESPACE ); -if (mucUserEx != null && mucUserEx.getStatus().contains( MUCUser.Status.create( 110 ) ) ) // 110 = Inform user that presence refers to itself -{ -final MUCItem item = mucUserEx.getItem(); -if ( item != null ) -{ -if ( item.getAffiliation() == MUCAffiliation.admin || item.getAffiliation() == MUCAffiliation.owner ) -{ -groupChatRoom.notifySettingsAccessRight(); -} -} -} -} ); - - chat.addParticipantListener(listener); - - ServiceDiscoveryManager disco = ServiceDiscoveryManager - .getInstanceFor(SparkManager.getConnection()); - try { - roomInformation = disco.discoverInfo(chat.getRoom()); - } catch (XMPPException | SmackException e) { - Log.debug("Unable to retrieve room information for " - + chat.getRoom()); - } - } - - public void chatRoomOpened(ChatRoom room) { - if (room != groupChatRoom) { - return; - } - - chat.addUserStatusListener(new UserStatusListener() { - public void kicked(String actor, String reason) { - - } - - public void voiceGranted() { - - } - - public void voiceRevoked() { - - } - - public void banned(String actor, String reason) { - - } - - public void membershipGranted() { - - } - - public void membershipRevoked() { - - } - - public void moderatorGranted() { - - } - - public void moderatorRevoked() { - - } - - public void ownershipGranted() { - } - - public void ownershipRevoked() { - - } - - public void adminGranted() { - - } - - public void adminRevoked() { - - } - }); - } - - public void addInvitee(String jid, String message) { - // So the problem with this is that I have no idea what the users actual - // jid is in most cases. - final UserManager userManager = SparkManager.getUserManager(); - - String displayName = userManager.getUserNicknameFromJID(jid); - - groupChatRoom.getTranscriptWindow().insertNotificationMessage( - displayName + " has been invited to join this room.", - ChatManager.NOTIFICATION_COLOR); - - if (roomInformation != null - && !roomInformation.containsFeature("muc_nonanonymous")) { - return; - } - - final ImageIcon inviteIcon = SparkRes - .getImageIcon(SparkRes.USER1_BACK_16x16); - - addUser(inviteIcon, displayName); - - invitees.put(displayName, message); - } - - protected ImageIcon getImageIcon(String participantJID) { - String displayName = XmppStringUtils.parseResource(participantJID); - ImageIcon icon = SparkRes.getImageIcon(SparkRes.GREEN_BALL); - icon.setDescription(displayName); - return icon; - } - - protected void addParticipant(final String participantJID, Presence presence) { - // Remove reference to invitees - - for (String displayName : invitees.keySet()) { - String jid = SparkManager.getUserManager().getJIDFromDisplayName( - displayName); - - Occupant occ = chat.getOccupant(participantJID); - if (occ != null) { - String actualJID = occ.getJid(); - if (actualJID.equals(jid)) { - removeUser(displayName); - } - } - } - - String nickname = XmppStringUtils.parseResource(participantJID); - - String affiliation = parseRoleFromPacket(presence)[0]; - String userRole = parseRoleFromPacket(presence)[1]; - - usersandRoles.put(participantJID, affiliation+","+userRole); - - Icon icon; - if (_localPreferences.isShowingRoleIcons()) { - icon = getIconForRole(userRole, affiliation); - } else { - icon = PresenceManager.getIconFromPresence(presence); - if (icon == null) { - icon = SparkRes.getImageIcon(SparkRes.GREEN_BALL); - } - } - - if (!exists(nickname)) { - addUser(icon, nickname); - } else { - int index = getIndex(nickname); - if (index != -1) { - final JLabel userLabel = new JLabel(nickname, icon, - JLabel.HORIZONTAL); - model.setElementAt(userLabel, index); - } - } - } - - /** - * Parses the Affiliation and Role from the Presence packet - * @param p - * @return String[] ,[0]=affiliation , [1]=role - */ - protected String[] parseRoleFromPacket(Presence p) { - String affi = ""; - String role = ""; - - for (ExtensionElement pack : p.getExtensions()) { - String[] args = pack.toXML().toString().split(" "); - - for (String ss : args) { - int first = ss.indexOf("\""); - int last = ss.lastIndexOf("\""); - if (ss.contains("affiliation")) { - if (first >=0 && first < last) { - affi = ss.substring(first + 1, last); - } - } - if (ss.contains("role")) { - if (first >=0 && first < last) { - role = ss.substring(first + 1, last); - } - } - } - } - - if (affi.equals("")) - affi = "none"; - if (role.equals("")) - role = "participant"; - - return new String[] { affi, role }; - - } - - /** - * Returns corresponding Icons for each MUC-Role - * icons are:
        - * Owner = Gold Star
        - * Admin = Silver Star
        - * Moderator = Bronze Star
        - * Member = Yellow
        - * Participant = Green
        - * Visitor = Blue
        - * N/A = Grey
        - * @param role - * @return {@link Icon} - */ - private Icon getIconForRole(String role, String affiliation) { - Icon icon; - - if (role.equalsIgnoreCase("participant")) { - icon = SparkRes.getImageIcon(SparkRes.STAR_GREEN_IMAGE); - - } else if (role.equalsIgnoreCase("moderator")) { - icon = SparkRes.getImageIcon(SparkRes.STAR_MODERATOR); - - } else if (role.equalsIgnoreCase("visitor")) { - icon = SparkRes.getImageIcon(SparkRes.STAR_BLUE_IMAGE); - - } else { - icon = SparkRes.getImageIcon(SparkRes.STAR_GREY_IMAGE); - } - - if (affiliation.equalsIgnoreCase("owner")) { - icon = SparkRes.getImageIcon(SparkRes.STAR_OWNER); - } - if (affiliation.equalsIgnoreCase("admin")) { - icon = SparkRes.getImageIcon(SparkRes.STAR_ADMIN); - } - if (affiliation.equalsIgnoreCase("member")) { - if (role.equals("moderator")) { - icon = SparkRes.getImageIcon(SparkRes.STAR_MODERATOR); - } else { - icon = SparkRes.getImageIcon(SparkRes.STAR_YELLOW_IMAGE); - } - } - return icon; - } - - public void userHasLeft(String userid) { - int index = getIndex(userid); - - if (index != -1) { - removeUser(userid); - userMap.remove(userid); - } - } - - protected boolean exists(String nickname) { - for (int i = 0; i < model.getSize(); i++) { - final JLabel userLabel = (JLabel) model.getElementAt(i); - if (userLabel.getText().equals(nickname)) { - return true; - } - } - return false; - } - - protected String getSelectedUser() { - JLabel label = (JLabel) participantsList.getSelectedValue(); - if (label != null) { - return label.getText(); - } - - return null; - } - - protected void startChat(ChatRoom groupChat, String groupJID) { - String userNickname = XmppStringUtils.parseResource(groupJID); - String roomTitle = userNickname + " - " - + XmppStringUtils.parseLocalpart(groupChat.getRoomname()); - - String nicknameOfUser = XmppStringUtils.parseResource(groupJID); - String nickname = groupChat.getNickname(); - - if (nicknameOfUser.equals(nickname)) { - return; - } - - ChatRoom chatRoom; - try { - chatRoom = chatManager.getChatContainer().getChatRoom(groupJID); - } catch (ChatRoomNotFoundException e) { - Log.debug("Could not find chat room - " + groupJID); - - // Create new room - chatRoom = new ChatRoomImpl(groupJID, nicknameOfUser, roomTitle); - chatManager.getChatContainer().addChatRoom(chatRoom); - } - - chatManager.getChatContainer().activateChatRoom(chatRoom); - } - - public void tabSelected() { - // To change body of implemented methods use File | Settings | File - // Templates. - } - - public String getTabTitle() { - return Res.getString("title.room.information"); - } - - public Icon getTabIcon() { - return SparkRes.getImageIcon(SparkRes.SMALL_BUSINESS_MAN_VIEW); - } - - public String getTabToolTip() { - return Res.getString("title.room.information"); - } - - public JComponent getGUI() { - return this; - } - - protected void kickUser(String nickname) { - try { - chat.kickParticipant(nickname, Res - .getString("message.you.have.been.kicked")); - } catch (XMPPException | SmackException e) { - groupChatRoom.insertText(Res.getString("message.kicked.error", - nickname)); - } - } - - protected void banUser(String displayName) { - try { - Occupant occupant = chat.getOccupant(userMap.get(displayName)); - if (occupant != null) { - String bareJID = XmppStringUtils - .parseBareJid(occupant.getJid()); - chat.banUser(bareJID, Res - .getString("message.you.have.been.banned")); - } - } catch (XMPPException | SmackException e) { - groupChatRoom.getTranscriptWindow(). - insertNotificationMessage("No can do "+e.getMessage(), ChatManager.ERROR_COLOR); - } - } - - protected void unbanUser(String jid) { - try { - chat.grantMembership(jid); - } catch (XMPPException | SmackException e) { - groupChatRoom.getTranscriptWindow(). - insertNotificationMessage("No can do "+e.getMessage(), ChatManager.ERROR_COLOR); - } - } - - protected void grantVoice(String nickname) { - try { - chat.grantVoice(nickname); - } catch (XMPPException | SmackException e) { - groupChatRoom.getTranscriptWindow(). - insertNotificationMessage("No can do "+e.getMessage(), ChatManager.ERROR_COLOR); - } - } - - protected void revokeVoice(String nickname) { - try { - chat.revokeVoice(nickname); - } catch (XMPPException | SmackException e) { - groupChatRoom.getTranscriptWindow(). - insertNotificationMessage("No can do "+e.getMessage(), ChatManager.ERROR_COLOR); - } - } - - protected void grantModerator(String nickname) { - try { - chat.grantModerator(nickname); - } catch (XMPPException | SmackException e) { - groupChatRoom.getTranscriptWindow().insertNotificationMessage( - "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); - } - } - - protected void revokeModerator(String nickname) { - try { - chat.revokeModerator(nickname); - } catch (XMPPException | SmackException e) { - groupChatRoom.getTranscriptWindow().insertNotificationMessage( - "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); - } - } - - protected void grantMember(String nickname) { - try { - Occupant o = userManager.getOccupant(groupChatRoom,nickname); - nickname = XmppStringUtils.parseBareJid(o.getJid()); - chat.grantMembership(nickname); - - } catch (XMPPException | SmackException e) { - groupChatRoom.getTranscriptWindow().insertNotificationMessage( - "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); - } - } - protected void revokeMember(String nickname) { - try { - Occupant o = userManager.getOccupant(groupChatRoom,nickname); - nickname = XmppStringUtils.parseBareJid(o.getJid()); - chat.revokeMembership(nickname); - } catch (XMPPException | SmackException e) { - groupChatRoom.getTranscriptWindow().insertNotificationMessage( - "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); - } - } - - protected void grantAdmin(String nickname) { - try { - Occupant o = userManager.getOccupant(groupChatRoom,nickname); - nickname = XmppStringUtils.parseBareJid(o.getJid()); - chat.grantAdmin(nickname); - } catch (XMPPException | SmackException e) { - groupChatRoom.getTranscriptWindow().insertNotificationMessage( - "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); - } - } - protected void revokeAdmin(String nickname) { - try { - Occupant o = userManager.getOccupant(groupChatRoom,nickname); - nickname = XmppStringUtils.parseBareJid(o.getJid()); - chat.revokeAdmin(nickname); - } catch (XMPPException | SmackException e) { - groupChatRoom.getTranscriptWindow().insertNotificationMessage( - "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); - } - } - - protected void grantOwner(String nickname) { - try { - Occupant o = userManager.getOccupant(groupChatRoom,nickname); - nickname = XmppStringUtils.parseBareJid(o.getJid()); - chat.grantOwnership(nickname); - } catch (XMPPException | SmackException e) { - groupChatRoom.getTranscriptWindow().insertNotificationMessage( - "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); - } - } - protected void revokeOwner(String nickname) { - try { - Occupant o = userManager.getOccupant(groupChatRoom,nickname); - nickname = XmppStringUtils.parseBareJid(o.getJid()); - chat.revokeOwnership(nickname); - } catch (XMPPException | SmackException e) { - groupChatRoom.getTranscriptWindow().insertNotificationMessage( - "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); - } - } - - - /** - * Let's make sure that the panel doesn't strech past the scrollpane view - * pane. - * - * @return the preferred dimension - */ - public Dimension getPreferredSize() { - final Dimension size = super.getPreferredSize(); - size.width = 150; - return size; - } - - protected void checkPopup(MouseEvent evt) { - Point p = evt.getPoint(); - final int index = participantsList.locationToIndex(p); - - final JPopupMenu popup = new JPopupMenu(); - - if (index != -1) { - participantsList.setSelectedIndex(index); - final JLabel userLabel = (JLabel) model.getElementAt(index); - final String selectedUser = userLabel.getText(); - final String groupJID = userMap.get(selectedUser); - String groupJIDNickname = XmppStringUtils.parseResource(groupJID); - - final String nickname = groupChatRoom.getNickname(); - final Occupant occupant = userManager.getOccupant(groupChatRoom, - selectedUser); - final boolean iamAdmin = SparkManager.getUserManager().isAdmin( - groupChatRoom, chat.getNickname()); - final boolean iamOwner = SparkManager.getUserManager().isOwner(groupChatRoom, chat.getNickname()); - - final boolean iamAdminOrOwner = iamAdmin || iamOwner; - - final boolean iamModerator = SparkManager.getUserManager() - .isModerator(groupChatRoom, chat.getNickname()); - - final boolean userIsMember = SparkManager.getUserManager().isMember(occupant); - - final boolean userIsAdmin = userManager.isAdmin(groupChatRoom, occupant.getNick()); - final boolean userIsOwner = userManager.isOwner(occupant); - final boolean userIsModerator = userManager.isModerator(occupant); - boolean selectedMyself = nickname.equals(groupJIDNickname); - - // Handle invites - if (groupJIDNickname == null) { - Action inviteAgainAction = new AbstractAction() { - private static final long serialVersionUID = -1875073139356098243L; - - public void actionPerformed(ActionEvent actionEvent) { - String message = invitees.get(selectedUser); - String jid = userManager.getJIDFromDisplayName(selectedUser); - try - { - chat.invite(jid, message); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to send stanza to " + jid, e ); - } - } - }; - - inviteAgainAction.putValue(Action.NAME, - Res.getString("menuitem.inivite.again")); - popup.add(inviteAgainAction); - - Action removeInvite = new AbstractAction() { - private static final long serialVersionUID = -3647279452501661970L; - - public void actionPerformed(ActionEvent actionEvent) { - int index = getIndex(selectedUser); - - if (index != -1) { - model.removeElementAt(index); - } - } - }; - - removeInvite.putValue(Action.NAME, - Res.getString("menuitem.remove")); - popup.add(removeInvite); - - popup.show(participantsList, evt.getX(), evt.getY()); - return; - } - - if (selectedMyself) { - Action changeNicknameAction = new AbstractAction() { - private static final long serialVersionUID = -7891803180672794112L; - - public void actionPerformed(ActionEvent actionEvent) { - String newNickname = JOptionPane.showInputDialog( - groupChatRoom, - Res.getString("label.new.nickname") + ":", - Res.getString("title.change.nickname"), - JOptionPane.QUESTION_MESSAGE); - if (ModelUtil.hasLength(newNickname)) { - while (true) { - newNickname = newNickname.trim(); - String nick = chat.getNickname(); - if (newNickname.equals(nick)) { - // return; - } - try { - chat.changeNickname(newNickname); - break; - } catch (XMPPException | SmackException e1) { - if ( e1 instanceof XMPPException.XMPPErrorException && (( XMPPException.XMPPErrorException ) e1).getXMPPError().getCondition() == XMPPError.Condition.not_acceptable ) - { - // handle deny changing nick. - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane - .showMessageDialog( - groupChatRoom, - Res.getString("message.nickname.not.acceptable"), - Res.getString("title.change.nickname"), - JOptionPane.ERROR_MESSAGE); - break; - } - newNickname = JOptionPane - .showInputDialog( - groupChatRoom, - Res.getString("message.nickname.in.use") - + ":", - Res.getString("title.change.nickname"), - JOptionPane.QUESTION_MESSAGE); - if (!ModelUtil.hasLength(newNickname)) { - break; - } - } - } - } - } - }; - - changeNicknameAction.putValue(Action.NAME, - Res.getString("menuitem.change.nickname")); - changeNicknameAction.putValue(Action.SMALL_ICON, - SparkRes.getImageIcon(SparkRes.DESKTOP_IMAGE)); - - if (allowNicknameChange) { - popup.add(changeNicknameAction); - } - } - - Action chatAction = new AbstractAction() { - private static final long serialVersionUID = -2739549054781928195L; - - public void actionPerformed(ActionEvent actionEvent) { - String selectedUser = getSelectedUser(); - startChat(groupChatRoom, userMap.get(selectedUser)); - } - }; - - chatAction.putValue(Action.NAME, - Res.getString("menuitem.start.a.chat")); - chatAction.putValue(Action.SMALL_ICON, - SparkRes.getImageIcon(SparkRes.SMALL_MESSAGE_IMAGE)); - if (!selectedMyself) { - popup.add(chatAction); - } - - Action blockAction = new AbstractAction() { - private static final long serialVersionUID = 8771362206105723776L; - - public void actionPerformed(ActionEvent e) { - String user = getSelectedUser(); - ImageIcon icon; - if (groupChatRoom.isBlocked(groupJID)) { - groupChatRoom.removeBlockedUser(groupJID); - icon = getImageIcon(groupJID); - } else { - groupChatRoom.addBlockedUser(groupJID); - icon = SparkRes.getImageIcon(SparkRes.BRICKWALL_IMAGE); - } - - JLabel label = new JLabel(user, icon, JLabel.HORIZONTAL); - model.setElementAt(label, index); - } - }; - - blockAction.putValue(Action.NAME, - Res.getString("menuitem.block.user")); - blockAction.putValue(Action.SMALL_ICON, - SparkRes.getImageIcon(SparkRes.BRICKWALL_IMAGE)); - if (!selectedMyself) { - if (groupChatRoom.isBlocked(groupJID)) { - blockAction.putValue(Action.NAME, - Res.getString("menuitem.unblock.user")); - } - popup.add(blockAction); - } - - Action kickAction = new AbstractAction() { - private static final long serialVersionUID = 5769982955040961189L; - - public void actionPerformed(ActionEvent actionEvent) { - kickUser(selectedUser); - } - }; - - kickAction.putValue(Action.NAME, - Res.getString("menuitem.kick.user")); - kickAction.putValue(Action.SMALL_ICON, - SparkRes.getImageIcon(SparkRes.SMALL_DELETE)); - if (iamModerator && !userIsAdmin && !selectedMyself) { - popup.add(kickAction); - } - - // Handle Voice Operations - Action voiceAction = new AbstractAction() { - private static final long serialVersionUID = 7628207942009369329L; - - public void actionPerformed(ActionEvent actionEvent) { - if (userManager.hasVoice(groupChatRoom, selectedUser)) { - revokeVoice(selectedUser); - } else { - grantVoice(selectedUser); - } - Collections.sort(users, labelComp); - - } - }; - - voiceAction.putValue(Action.NAME, Res.getString("menuitem.voice")); - voiceAction.putValue(Action.SMALL_ICON, - SparkRes.getImageIcon(SparkRes.MEGAPHONE_16x16)); - if (iamModerator && !userIsModerator && !selectedMyself) { - if (userManager.hasVoice(groupChatRoom, selectedUser)) { - voiceAction.putValue(Action.NAME, - Res.getString("menuitem.revoke.voice")); - } else { - voiceAction.putValue(Action.NAME, - Res.getString("menuitem.grant.voice")); - } - popup.add(voiceAction); - } - - Action banAction = new AbstractAction() { - private static final long serialVersionUID = 4290194898356641253L; - - public void actionPerformed(ActionEvent actionEvent) { - banUser(selectedUser); - } - }; - banAction.putValue(Action.NAME, Res.getString("menuitem.ban.user")); - banAction.putValue(Action.SMALL_ICON, - SparkRes.getImageIcon(SparkRes.RED_FLAG_16x16)); - if (iamAdminOrOwner && !userIsModerator && !selectedMyself) { - popup.add(banAction); - } - - - JMenu affiliationMenu = new JMenu(Res.getString("menuitem.affiliation")); - affiliationMenu.setIcon(SparkRes.getImageIcon(SparkRes.MODERATOR_IMAGE)); - - Action memberAction = new AbstractAction() { - private static final long serialVersionUID = -2528887841227305432L; - - @Override - public void actionPerformed(ActionEvent e) { - if (!userIsMember) { - grantMember(selectedUser); - } else { - revokeMember(selectedUser); - } - Collections.sort(users, labelComp); - } - }; - memberAction.putValue(Action.SMALL_ICON, - SparkRes.getImageIcon(SparkRes.STAR_YELLOW_IMAGE)); - if(iamAdminOrOwner && !userIsMember) - { - memberAction.putValue(Action.NAME,Res.getString("menuitem.grant.member")); - affiliationMenu.add(memberAction); - } - else if(iamAdminOrOwner && userIsMember && !selectedMyself) - { - memberAction.putValue(Action.NAME,Res.getString("menuitem.revoke.member")); - affiliationMenu.add(memberAction); - } - - - Action moderatorAction = new AbstractAction() { - private static final long serialVersionUID = 8162535640460764896L; - - public void actionPerformed(ActionEvent actionEvent) { - if (!userIsModerator) { - grantModerator(selectedUser); - } else { - revokeModerator(selectedUser); - } - Collections.sort(users, labelComp); - - } - }; - - moderatorAction.putValue(Action.SMALL_ICON, - SparkRes.getImageIcon(SparkRes.STAR_MODERATOR)); - - if (iamAdminOrOwner && !userIsModerator && !userIsAdmin && !userIsOwner) { - moderatorAction.putValue(Action.NAME, - Res.getString("menuitem.grant.moderator")); - affiliationMenu.add(moderatorAction); - } else if (iamAdminOrOwner && userIsModerator && !selectedMyself) { - moderatorAction.putValue(Action.NAME, - Res.getString("menuitem.revoke.moderator")); - affiliationMenu.add(moderatorAction); - } - - Action adminAction = new AbstractAction() { - private static final long serialVersionUID = 3672121864443182872L; - - @Override - public void actionPerformed(ActionEvent e) { - if (!userIsAdmin) { - grantAdmin(selectedUser); - } else { - revokeAdmin(selectedUser); - } - Collections.sort(users, labelComp); - - } - }; - adminAction.putValue(Action.SMALL_ICON, - SparkRes.getImageIcon(SparkRes.STAR_ADMIN)); - if(iamAdminOrOwner && !userIsAdmin && !userIsOwner) - { - adminAction.putValue(Action.NAME, - Res.getString("menuitem.grant.admin")); - affiliationMenu.add(adminAction); - } - else if(iamAdminOrOwner && !selectedMyself ) - { - adminAction.putValue(Action.NAME, - Res.getString("menuitem.revoke.admin")); - affiliationMenu.add(adminAction); - } - - - Action ownerAction = new AbstractAction() { - private static final long serialVersionUID = 3672121864443182872L; - - @Override - public void actionPerformed(ActionEvent e) { - if (!userIsOwner) { - grantOwner(selectedUser); - } else { - revokeOwner(selectedUser); - } - Collections.sort(users, labelComp); - - } - }; - ownerAction.putValue(Action.SMALL_ICON, - SparkRes.getImageIcon(SparkRes.STAR_OWNER)); - - if( iamOwner && !userIsOwner) - { - ownerAction.putValue(Action.NAME, - Res.getString("menuitem.grant.owner")); - affiliationMenu.add(ownerAction); - } - else if(iamOwner && !selectedMyself ) - { - ownerAction.putValue(Action.NAME, - Res.getString("menuitem.revoke.owner")); - affiliationMenu.add(ownerAction); - } - - if(affiliationMenu.getItemCount()>0) - popup.add(affiliationMenu); - - - // Handle Unbanning of users. - Action unbanAction = new AbstractAction() { - private static final long serialVersionUID = 3672121864443182872L; - - public void actionPerformed(ActionEvent actionEvent) { - String jid = ((JMenuItem) actionEvent.getSource()) - .getText(); - unbanUser(jid); - } - }; - - if (iamAdmin || iamOwner) { - JMenu unbanMenu = new JMenu(Res.getString("menuitem.unban")); - Iterator bannedUsers = null; - try { - bannedUsers = chat.getOutcasts().iterator(); - } catch (XMPPException | SmackException e) { - Log.error("Error loading all banned users", e); - } - - while (bannedUsers != null && bannedUsers.hasNext()) { - Affiliate bannedUser = bannedUsers.next(); - ImageIcon icon = SparkRes.getImageIcon(SparkRes.RED_BALL); - JMenuItem bannedItem = new JMenuItem(bannedUser.getJid(), - icon); - unbanMenu.add(bannedItem); - bannedItem.addActionListener(unbanAction); - } - - if (unbanMenu.getMenuComponentCount() > 0) { - popup.add(unbanMenu); - } - } - } - - Action inviteAction = new AbstractAction() { - private static final long serialVersionUID = 2240864466141501086L; - - public void actionPerformed(ActionEvent actionEvent) { - ConferenceUtils.inviteUsersToRoom( groupChatRoom.getMultiUserChat(), null, false); - } - }; - - inviteAction.putValue(Action.NAME, - Res.getString("menuitem.invite.users")); - inviteAction.putValue(Action.SMALL_ICON, - SparkRes.getImageIcon(SparkRes.CONFERENCE_IMAGE_16x16)); - - if (index != -1) { - popup.addSeparator(); - } - popup.add(inviteAction); - - popup.show(participantsList, evt.getX(), evt.getY()); - } - - public void setNicknameChangeAllowed(boolean allowed) { - allowNicknameChange = allowed; - } - - public int getIndex(String name) { - for (int i = 0; i < model.getSize(); i++) { - JLabel label = (JLabel) model.getElementAt(i); - if (label.getText().equals(name)) { - return i; - } - } - return -1; - } - - /** - * Removes a user from the participant list based on their displayed name. - * - * @param displayName - * the users displayed name to remove. - */ - public synchronized void removeUser(String displayName) { - try { - for (int i = 0; i < users.size(); i++) { - JLabel label = users.get(i); - if (label.getText().equals(displayName)) { - users.remove(label); - model.removeElement(label); - } - } - - for (int i = 0; i < model.size(); i++) { - JLabel label = (JLabel) model.getElementAt(i); - if (label.getText().equals(displayName)) { - users.remove(label); - model.removeElement(label); - } - } - } catch (Exception e) { - Log.error(e); - } - } - - /** - * Adds a new user to the participant list. - * - * @param userIcon - * the icon to use initially. - * @param nickname - * the users nickname. - */ - public synchronized void addUser(Icon userIcon, String nickname) { - try { - final JLabel user = new JLabel(nickname, userIcon, - JLabel.HORIZONTAL); - users.add(user); - - // Sort users alpha. - Collections.sort(users, labelComp); - - // Add to the correct position in the model. - final int index = users.indexOf(user); - model.insertElementAt(user, index); - } catch (Exception e) { - Log.error(e); - } - } - - /** - * Sorts ContactItems. - */ - final Comparator labelComp = new Comparator() { - - public int compare(JLabel item1, JLabel item2) { - if (_localPreferences.isShowingRoleIcons()) { - return compareWithRole(item1, item2); - } else { - return compareWithoutRole(item1.getText(), item2.getText()); - } - - } - - private int compareWithoutRole(String s1, String s2) { - return (s1.toLowerCase().compareTo(s2.toLowerCase())); - } - - /** - * Comparaes 2 items by their Role and Affiliation
        - * affiliation > role
        - * owner > admin > moderator > member > participant > visitor - * @param item1 - * @param item2 - * @return -1, 0 or 1 - */ - private int compareWithRole(JLabel item1, JLabel item2) { - - int user1 = 100; - int user2 = 100; - try { - // append Room-JID to UserLabel - String jid1 = chat.getRoom() + "/" + item1.getText(); - String jid2 = chat.getRoom() + "/" + item2.getText(); - - user1 = getCompareValue(jid1); - user2 = getCompareValue(jid2); - - } catch (Exception e) { - // Sometimes theres no Occupant with that jid, dunno why - } - - int result = 0; - if (user1 == user2) { - result = compareWithoutRole(item1.getText(), item2.getText()); - - } else { - // a=owner,b=admin, m=moderator, n=member , p=participant, v=visitor - // a < b < m < n < p < v - if (user1 < user2) - result = -1; - if (user1 > user2) - result = 1; - } - return result; - } - }; - - /** - * check if we have an affiliation to this room
        - * and map it to an integer
        - * 0=owner,1=admin.....5=visitor
        - */ - private int getCompareValue(String jid) { - int result; - - String affi = usersandRoles.get(jid).split(",")[0]; - String role = usersandRoles.get(jid).split(",")[1]; - - if (affi == null) - affi = "z"; - if (role == null) - role = "z"; - - switch (affi.charAt(0)) { - case 'o': - result = 0; - break; // owner - case 'a': - result = 1; - break; // admin - // Moderator is in between with 2 - case 'm': - result = 3; - break; // member - default: - result = 100; - } - - if (affi.equalsIgnoreCase("none")) { - - switch (role.charAt(0)) { - case 'm': - result = 2; - break; // moderator - // Member is in between with 3 - case 'p': - result = 4; - break; // participant - case 'v': - result = 5; - break; // visitor - default: - result = 100; - } - } - if (affi.equalsIgnoreCase("member") && role.charAt(0) == 'm') { - result = 2; - } - return result; - } - - /** - * The JLabelIconRenderer is the an implementation of - * ListCellRenderer to add icons w/ associated text in JComboBox and JList. - * - * @author Derek DeMoro - */ - public class ParticipantRenderer extends JLabel implements ListCellRenderer { - private static final long serialVersionUID = -7509947975798079141L; - - /** - * Construct Default JLabelIconRenderer. - */ - public ParticipantRenderer() { - setOpaque(true); - } - - public Component getListCellRendererComponent(JList list, Object value, - int index, boolean isSelected, boolean cellHasFocus) { - if (isSelected) { - setBackground(list.getSelectionBackground()); - setForeground(list.getSelectionForeground()); - } else { - setBackground(list.getBackground()); - setForeground(list.getForeground()); - } - - JLabel label = (JLabel) value; - setText(label.getText()); - setIcon(label.getIcon()); - return this; - } - } - - protected GroupChatRoom getGroupChatRoom() { - return groupChatRoom; - } - - protected ImageTitlePanel getAgentInfoPanel() { - return agentInfoPanel; - } - - protected MultiUserChat getChat() { - return chat; - } - - protected Map getUserMap() { - return userMap; - } - - protected DefaultListModel getModel() { - return model; - } - - protected JXList getParticipantsList() { - - return participantsList; - - } - - protected PresenceListener getListener() { - return listener; - } - - protected Map getInvitees() { - return invitees; - } - - protected boolean isAllowNicknameChange() { - return allowNicknameChange; - } - - protected DiscoverInfo getRoomInformation() { - return roomInformation; - } - - protected List getUsers() { - return users; - } - - protected HashMap getUsersandRoles() { - return usersandRoles; - } - - protected Comparator getLabelComp() { - return labelComp; - } -} - diff --git a/src/java/org/jivesoftware/spark/ui/conferences/GroupChatRoomListener.java b/src/java/org/jivesoftware/spark/ui/conferences/GroupChatRoomListener.java deleted file mode 100644 index 5a10dc22f..000000000 --- a/src/java/org/jivesoftware/spark/ui/conferences/GroupChatRoomListener.java +++ /dev/null @@ -1,134 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2013 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.conferences; - -import org.jivesoftware.smackx.muc.MultiUserChat; -import org.jivesoftware.smackx.muc.UserStatusListener; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomListener; -import org.jivesoftware.spark.ui.rooms.GroupChatRoom; -/** - * This listener is notified for every group chat room. The affected chat room - * is sent as parameter in every method. Keeping such listener tied to a group chat room instance - * is wrong because all listeners will be notified when someone joins a particular chat room for example - */ -public class GroupChatRoomListener implements ChatRoomListener { - @Override - public void chatRoomOpened(ChatRoom room) { - if (!(room instanceof GroupChatRoom)) { - return; - } - GroupChatRoom groupChatRoom = (GroupChatRoom)room; - MultiUserChat chat = groupChatRoom.getMultiUserChat(); - chat.addUserStatusListener(new UserStatusListener() { - public void kicked(String actor, String reason) { - - } - - public void voiceGranted() { - - } - - public void voiceRevoked() { - - } - - public void banned(String actor, String reason) { - - } - - public void membershipGranted() { - - } - - public void membershipRevoked() { - - } - - public void moderatorGranted() { - - } - - public void moderatorRevoked() { - - } - - public void ownershipGranted() { - } - - public void ownershipRevoked() { - - } - - public void adminGranted() { - - } - - public void adminRevoked() { - - } - }); - } - - @Override - public void chatRoomLeft(ChatRoom room) { - if (!(room instanceof GroupChatRoom)) { - return; - } - GroupChatRoom groupChatRoom = (GroupChatRoom)room; - groupChatRoom.getConferenceRoomInfo().getAgentInfoPanel().setVisible(false); - } - - @Override - public void chatRoomClosed(ChatRoom room) { - if (!(room instanceof GroupChatRoom)) { - return; - } - GroupChatRoom groupChatRoom = (GroupChatRoom)room; - MultiUserChat chat = groupChatRoom.getMultiUserChat(); - chat.removeParticipantListener(groupChatRoom.getConferenceRoomInfo().getListener()); - } - - @Override - public void chatRoomActivated(ChatRoom room) { - - } - - @Override - public void userHasJoined(ChatRoom room, String userid) { - - } - - @Override - public void userHasLeft(ChatRoom room, String userid) { - if (!(room instanceof GroupChatRoom)) { - return; - } - GroupChatRoom groupChatRoom = (GroupChatRoom)room; - - int index = groupChatRoom.getConferenceRoomInfo().getIndex(userid); - - if (index != -1) { - groupChatRoom.getConferenceRoomInfo().removeUser(userid); - groupChatRoom.getConferenceRoomInfo().getUserMap().remove(userid); - } - } - -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/spark/ui/conferences/InvitationDialog.java b/src/java/org/jivesoftware/spark/ui/conferences/InvitationDialog.java deleted file mode 100644 index 03aa5093c..000000000 --- a/src/java/org/jivesoftware/spark/ui/conferences/InvitationDialog.java +++ /dev/null @@ -1,423 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.conferences; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smackx.bookmarks.BookmarkedConference; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.ChatNotFoundException; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.TitlePanel; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.RosterPickList; -import org.jivesoftware.spark.ui.rooms.GroupChatRoom; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.DefaultListModel; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JTextField; -import javax.swing.UIManager; - -import java.awt.BorderLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.beans.PropertyChangeListener; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -final class InvitationDialog extends JPanel { - private static final long serialVersionUID = -8588678602429200581L; - private JTextField textRoomsField; - private JComboBox comboRoomsField; - - private JTextField messageField = new JTextField(); - - - private DefaultListModel invitedUsers = new DefaultListModel(); - private JList invitedUserList = new JList(invitedUsers); - - private JDialog dlg; - - public InvitationDialog(boolean adhoc) { - JComponent roomsField = new JTextField(); - if (adhoc) { - roomsField = new JTextField(); - textRoomsField = (JTextField) roomsField; - } else { - roomsField = new JComboBox(); - comboRoomsField = (JComboBox) roomsField; - comboRoomsField.setEditable(true); - comboRoomsField.addActionListener( e -> { - // get selected bookmark and persist it: - BookmarkedConference bookmarkedConf = null; - Object bookmarkedConfItem = comboRoomsField.getSelectedItem(); - if (bookmarkedConfItem instanceof ConferenceItem) { - bookmarkedConf = ((ConferenceItem) bookmarkedConfItem).getBookmarkedConf(); - SettingsManager.getLocalPreferences().setDefaultBookmarkedConf(bookmarkedConf.getJid()); - SettingsManager.saveSettings(); - } - } ); - } - GridBagLayout gridBagLayout1 = new GridBagLayout(); - setLayout( gridBagLayout1 ); - - JLabel roomsLabel = new JLabel(); - add( roomsLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add( roomsField, new GridBagConstraints(1, 0, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - - JLabel messageLabel = new JLabel(); - add( messageLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(messageField, new GridBagConstraints(1, 1, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - JLabel jidLabel = new JLabel(); - final JTextField jidField = new JTextField(); - JButton addJIDButton = new JButton(); - JButton browseButton = new JButton(); - ResourceUtils.resButton(addJIDButton, Res.getString("button.add")); - ResourceUtils.resButton(browseButton, Res.getString("button.roster")); - ResourceUtils.resLabel(jidLabel, jidField, Res.getString("label.add.jid")); - - add(jidLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - add(jidField, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - add(addJIDButton, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(browseButton, new GridBagConstraints(3, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - addJIDButton.addActionListener( actionEvent -> { - String jid = jidField.getText(); - String server = XmppStringUtils.parseBareJid(jid); - if (server == null || !server.contains( "@" ) ) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(dlg, Res.getString("message.enter.valid.jid"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - jidField.setText(""); - jidField.requestFocus(); - } - else { - if (!invitedUsers.contains(jid)) { - invitedUsers.addElement(jid); - } - jidField.setText(""); - } - } ); - - browseButton.addActionListener( actionEvent -> { - RosterPickList browser = new RosterPickList(); - Collection col = browser.showRoster(dlg); - - for (String aCol : col) { - String jid = aCol; - if (!invitedUsers.contains(jid)) { - invitedUsers.addElement(jid); - } - - } - } ); - - - JLabel inviteLabel = new JLabel(); - add( inviteLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - add(new JScrollPane(invitedUserList), new GridBagConstraints(1, 3, 3, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - - // Add Resource Utils - ResourceUtils.resLabel( messageLabel, messageField, Res.getString("label.message") + ":"); - ResourceUtils.resLabel( roomsLabel, roomsField, Res.getString("label.room") + ":"); - inviteLabel.setText(Res.getString("label.invited.users")); - - messageField.setText(Res.getString("message.please.join.in.conference")); - - // Add Listener to list - invitedUserList.addMouseListener(new MouseAdapter() { - public void mouseReleased(MouseEvent mouseEvent) { - if (mouseEvent.isPopupTrigger()) { - showPopup(mouseEvent); - } - } - - public void mousePressed(MouseEvent mouseEvent) { - if (mouseEvent.isPopupTrigger()) { - showPopup(mouseEvent); - } - } - }); - } - - private void showPopup(MouseEvent e) { - final JPopupMenu popup = new JPopupMenu(); - final int index = invitedUserList.locationToIndex(e.getPoint()); - - Action removeAction = new AbstractAction() { - private static final long serialVersionUID = 7837533277115442942L; - - public void actionPerformed(ActionEvent e) { - invitedUsers.remove(index); - } - }; - - removeAction.putValue(Action.NAME, Res.getString("menuitem.remove")); - removeAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_DELETE)); - - popup.add(removeAction); - - popup.show(invitedUserList, e.getX(), e.getY()); - - } - - private void fillRoomsUI(Collection rooms, String adHocRoomName) { - if (textRoomsField != null) { - textRoomsField.setText(adHocRoomName); - } - if (comboRoomsField != null) { - // comboRoomsField.setSelectedIndex(-1); - ConferenceItem bookmarkedConf = null; - final String bookmarkedConfJid = SettingsManager.getLocalPreferences().getDefaultBookmarkedConf(); - - for (BookmarkedConference room : rooms) { - final ConferenceItem ci = new ConferenceItem(room); - if (bookmarkedConfJid != null && bookmarkedConfJid.equalsIgnoreCase(ci.getBookmarkedConf().getJid())) { - bookmarkedConf = ci; - } - comboRoomsField.addItem(ci); - } - if (bookmarkedConf != null) { - comboRoomsField.setSelectedItem(bookmarkedConf); - } - } - } - - private String getSelectedRoomName() { - String roomTitle = null; - - if (textRoomsField != null) { - roomTitle = textRoomsField.getText(); - } - if (comboRoomsField != null) { - roomTitle = comboRoomsField.getSelectedItem().toString(); - } - - return roomTitle; - } - - private BookmarkedConference getSelectedBookmarkedConference() { - BookmarkedConference bookmarkedConf = null; - if (comboRoomsField != null) { - Object bookmarkedConfItem = comboRoomsField.getSelectedItem(); - if (bookmarkedConfItem instanceof ConferenceItem) { - bookmarkedConf = ((ConferenceItem) bookmarkedConfItem).getBookmarkedConf(); - } - } - return bookmarkedConf; - } - - public void inviteUsersToRoom(final String serviceName, Collection rooms, String adHocRoomName, Collection jids) { - fillRoomsUI(rooms, adHocRoomName); - - - JFrame parent = SparkManager.getChatManager().getChatContainer().getChatFrame(); - if (parent == null || !parent.isVisible()) { - parent = SparkManager.getMainWindow(); - } - - // Add jids to user list - if (jids != null) { - for (Object jid : jids) { - invitedUsers.addElement(jid); - } - } - - final JOptionPane pane; - - - TitlePanel titlePanel; - - // Create the title panel for this dialog - titlePanel = new TitlePanel(Res.getString("title.invite.to.conference"), Res.getString("message.invite.users.to.conference"), SparkRes.getImageIcon(SparkRes.BLANK_IMAGE), true); - - // Construct main panel w/ layout. - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(titlePanel, BorderLayout.NORTH); - - // The user should only be able to close this dialog. - Object[] options = {Res.getString("invite"), Res.getString("cancel")}; - pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); - - mainPanel.add(pane, BorderLayout.CENTER); - - final JOptionPane p = new JOptionPane(); - - dlg = p.createDialog(parent, Res.getString("title.conference.rooms")); - dlg.setModal(false); - - dlg.pack(); - dlg.setSize(500, 450); - dlg.setResizable(true); - dlg.setContentPane(mainPanel); - dlg.setLocationRelativeTo(parent); - - - PropertyChangeListener changeListener = e -> { - String value = (String)pane.getValue(); - if (Res.getString("cancel").equals(value)) { - pane.setValue(JOptionPane.UNINITIALIZED_VALUE); - dlg.dispose(); - } - else if (Res.getString("invite").equals(value)) { - final String roomTitle = getSelectedRoomName(); - final BookmarkedConference selectedBookmarkedConf = getSelectedBookmarkedConference(); - int size = invitedUserList.getModel().getSize(); - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - - if (size == 0) { - JOptionPane.showMessageDialog(dlg, Res.getString("message.specify.users.to.join.conference"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - pane.setValue(JOptionPane.UNINITIALIZED_VALUE); - return; - } - - if (!ModelUtil.hasLength(roomTitle)) { - JOptionPane.showMessageDialog(dlg, Res.getString("message.no.room.to.join.error"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - pane.setValue(JOptionPane.UNINITIALIZED_VALUE); - return; - } - String roomName = ""; - - // Add all rooms the user is in to list. - ChatManager chatManager = SparkManager.getChatManager(); - for (ChatRoom chatRoom : chatManager.getChatContainer().getChatRooms()) { - if (chatRoom instanceof GroupChatRoom) { - GroupChatRoom groupRoom = (GroupChatRoom) chatRoom; - if (groupRoom.getRoomname().equals(roomTitle)) { - roomName = groupRoom.getMultiUserChat().getRoom(); - break; - } - } - } - String message = messageField.getText(); - final String messageText = message != null ? message : Res.getString("message.please.join.in.conference"); - - if (invitedUsers.getSize() > 0) { - invitedUserList.setSelectionInterval(0, invitedUsers.getSize() - 1); - } - - - GroupChatRoom chatRoom; - try { - chatRoom = SparkManager.getChatManager().getGroupChat(roomName); - } - catch (ChatNotFoundException e1) { - dlg.setVisible(false); - final List jidList = new ArrayList<>(); - Object[] jids1 = invitedUserList.getSelectedValues(); - final int no = jids1 != null ? jids1.length : 0; - for (int i = 0; i < no; i++) { - try { - jidList.add((String) jids1[i]); - } - catch (NullPointerException ee) { - Log.error(ee); - } - } - - SwingWorker worker = new SwingWorker() { - public Object construct() { - try { - Thread.sleep(15); - } - catch (InterruptedException e2) { - Log.error(e2); - } - return "ok"; - } - - public void finished() { - try { - if (selectedBookmarkedConf == null) { - ConferenceUtils.createPrivateConference(serviceName, messageText, roomTitle, - jidList); - } else { - ConferenceUtils.joinConferenceOnSeperateThread( - selectedBookmarkedConf.getName(), selectedBookmarkedConf.getJid(), - selectedBookmarkedConf.getPassword(), messageText, jidList); - } - } - catch (SmackException ex) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(pane, "An error occurred.", Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - } - } - }; - - worker.start(); - pane.setValue(JOptionPane.UNINITIALIZED_VALUE); - return; - } - - pane.setValue(JOptionPane.UNINITIALIZED_VALUE); - dlg.dispose(); - - Object[] values = invitedUserList.getSelectedValues(); - final int no = values != null ? values.length : 0; - for (int i = 0; i < no; i++) { - String jid = (String)values[i]; - try - { - chatRoom.getMultiUserChat().invite(jid, message != null ? message : Res.getString("message.please.join.in.conference")); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to send stanza to " + jid, e1 ); - } - String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid); - chatRoom.getTranscriptWindow().insertNotificationMessage("Invited " + nickname, ChatManager.NOTIFICATION_COLOR); - } - - } - }; - - pane.addPropertyChangeListener(changeListener); - - dlg.setVisible(true); - dlg.toFront(); - dlg.requestFocus(); - } -} diff --git a/src/java/org/jivesoftware/spark/ui/conferences/JoinConferenceRoomDialog.java b/src/java/org/jivesoftware/spark/ui/conferences/JoinConferenceRoomDialog.java deleted file mode 100644 index 040fbd2cc..000000000 --- a/src/java/org/jivesoftware/spark/ui/conferences/JoinConferenceRoomDialog.java +++ /dev/null @@ -1,148 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.conferences; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.resource.Res; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.TitlePanel; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -import java.awt.BorderLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.beans.PropertyChangeListener; - -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPasswordField; -import javax.swing.JTextField; - -final class JoinConferenceRoomDialog extends JPanel { - private static final long serialVersionUID = -6400555509113588047L; - private JLabel passwordLabel = new JLabel(); - private JPasswordField passwordField = new JPasswordField(); - private JTextField nicknameField = new JTextField(); - private JLabel roomNameDescription = new JLabel(); - - public JoinConferenceRoomDialog() { - GridBagLayout gridBagLayout1 = new GridBagLayout(); - setLayout( gridBagLayout1 ); - add(nicknameField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - add(passwordField, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - add(passwordLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - JLabel nicknameLabel = new JLabel(); - add( nicknameLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - JLabel roomNameLabel = new JLabel(); - add( roomNameLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(roomNameDescription, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - add(new JLabel(), new GridBagConstraints(0, 3, 2, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.VERTICAL, new Insets(5, 5, 5, 5), 0, 0)); - - // Add Resource Utils - ResourceUtils.resLabel( nicknameLabel, nicknameField, Res.getString("label.nickname") + ":"); - ResourceUtils.resLabel(passwordLabel, passwordField, Res.getString("label.password") + ":"); - - roomNameLabel.setText(Res.getString("room.name") +":"); - } - - public void joinRoom(final String roomJID, final String roomName) { - final LocalPreferences pref = SettingsManager.getLocalPreferences(); - - // Set default nickname - nicknameField.setText(pref.getNickname()); - - // Enable password field if a password is required - passwordField.setVisible(false); - passwordLabel.setVisible(false); - - - roomNameDescription.setText(roomName); - - final JOptionPane pane; - - - TitlePanel titlePanel; - - // Create the title panel for this dialog - titlePanel = new TitlePanel(Res.getString("title.join.conference.room"), Res.getString("message.specify.information.for.conference"), SparkRes.getImageIcon(SparkRes.BLANK_IMAGE), true); - - // Construct main panel w/ layout. - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(titlePanel, BorderLayout.NORTH); - - // The user should only be able to close this dialog. - Object[] options = {Res.getString("join"), Res.getString("cancel")}; - pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); - - mainPanel.add(pane, BorderLayout.CENTER); - - final JOptionPane p = new JOptionPane(); - - final JDialog dlg = p.createDialog(SparkManager.getMainWindow(), Res.getString("title.conference.rooms")); - dlg.setModal(false); - - dlg.pack(); - dlg.setSize(350, 250); - dlg.setResizable(true); - dlg.setContentPane(mainPanel); - dlg.setLocationRelativeTo(SparkManager.getMainWindow()); - - PropertyChangeListener changeListener = e -> { - String value = (String)pane.getValue(); - if (Res.getString("cancel").equals(value)) { - pane.setValue(JOptionPane.UNINITIALIZED_VALUE); - dlg.dispose(); - } - else if (Res.getString("join").equals(value)) { - pane.setValue(JOptionPane.UNINITIALIZED_VALUE); - dlg.dispose(); - ConferenceUtils.joinConferenceOnSeperateThread(roomName, roomJID, null); - } - }; - - pane.addPropertyChangeListener(changeListener); - - dlg.setVisible(true); - dlg.toFront(); - dlg.requestFocus(); - - SwingWorker worker = new SwingWorker() { - boolean requiresPassword; - - public Object construct() { - requiresPassword = ConferenceUtils.isPasswordRequired(roomJID); - return requiresPassword; - } - - public void finished() { - passwordField.setVisible(requiresPassword); - passwordLabel.setVisible(requiresPassword); - } - }; - worker.start(); - } -} diff --git a/src/java/org/jivesoftware/spark/ui/conferences/RoomBrowser.java b/src/java/org/jivesoftware/spark/ui/conferences/RoomBrowser.java deleted file mode 100644 index 570ed48e0..000000000 --- a/src/java/org/jivesoftware/spark/ui/conferences/RoomBrowser.java +++ /dev/null @@ -1,193 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.conferences; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; -import org.jivesoftware.smackx.muc.MultiUserChatManager; -import org.jivesoftware.smackx.muc.RoomInfo; -import org.jivesoftware.smackx.disco.packet.DiscoverItems; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.JiveTreeCellRenderer; -import org.jivesoftware.spark.component.JiveTreeNode; -import org.jivesoftware.spark.component.TitlePanel; -import org.jivesoftware.spark.component.Tree; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; - -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.beans.PropertyChangeListener; - -public class RoomBrowser extends JPanel { - private static final long serialVersionUID = 8820670697089268423L; - - private JLabel descriptionValue = new JLabel(); - private JLabel subjectValue = new JLabel(); - private JLabel occupantsValue = new JLabel(); - private JLabel roomNameValue = new JLabel(); - - private JiveTreeNode rootNode; - private Tree tree; - - public RoomBrowser() { - JLabel descriptionLabel = new JLabel(); - descriptionLabel.setText(Res.getString("description") + ":"); - JLabel subjectLabel = new JLabel(); - subjectLabel.setText(Res.getString("subject") + ":"); - JLabel occupantsLabel = new JLabel(); - occupantsLabel.setText(Res.getString("occupants") + ":"); - JLabel roomNameLabel = new JLabel(); - roomNameLabel.setText(Res.getString("room.name") + ":"); - - // Add labels to UI - setLayout(new GridBagLayout()); - add( descriptionLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(descriptionValue, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - add( subjectLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(subjectValue, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - add( occupantsLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(occupantsValue, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - add( roomNameLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(roomNameValue, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - - rootNode = new JiveTreeNode(Res.getString("tree.users.in.room"), true); - tree = new Tree(rootNode); - - add(tree, new GridBagConstraints(0, 4, 2, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - setBackground(Color.white); - tree.setCellRenderer(new JiveTreeCellRenderer()); - - - } - - public void displayRoomInformation(final String roomJID) { - SwingWorker worker = new SwingWorker() { - RoomInfo roomInfo = null; - DiscoverItems items = null; - - public Object construct() { - try { - roomInfo = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getRoomInfo( roomJID ); - - - ServiceDiscoveryManager manager = ServiceDiscoveryManager.getInstanceFor(SparkManager.getConnection()); - items = manager.discoverItems(roomJID); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - return "ok"; - } - - public void finished() { - setupRoomInformationUI(roomJID, roomInfo, items); - } - }; - - worker.start(); - } - - private void setupRoomInformationUI(String roomJID, final RoomInfo roomInfo, final DiscoverItems items) { - descriptionValue.setText(Res.getString("message.no.description.available")); - subjectValue.setText(Res.getString("message.no.subject.available")); - occupantsValue.setText("n/a"); - roomNameValue.setText("n/a"); - try { - descriptionValue.setText(roomInfo.getDescription()); - subjectValue.setText(roomInfo.getSubject()); - - if (roomInfo.getOccupantsCount() == -1) { - occupantsValue.setText("n/a"); - } - else { - occupantsValue.setText(Integer.toString(roomInfo.getOccupantsCount())); - } - roomNameValue.setText(roomInfo.getRoom()); - - for (DiscoverItems.Item item : items.getItems() ) { - String jid = item.getEntityID(); - rootNode.add(new JiveTreeNode(jid, false, SparkRes.getImageIcon(SparkRes.SMALL_USER1_INFORMATION))); - } - tree.expandRow(0); - } - catch (Exception e) { - Log.error(e); - } - - final JOptionPane pane; - - // Create the title panel for this dialog - TitlePanel titlePanel = new TitlePanel(Res.getString("title.view.room.information"), Res.getString("message.room.information.for", roomJID), SparkRes.getImageIcon(SparkRes.BLANK_IMAGE), true); - - // Construct main panel w/ layout. - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(titlePanel, BorderLayout.NORTH); - - // The user should only be able to close this dialog. - Object[] options = {Res.getString("close")}; - pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); - - mainPanel.add(pane, BorderLayout.CENTER); - - final JOptionPane p = new JOptionPane(); - - final JDialog dlg = p.createDialog(SparkManager.getMainWindow(), Res.getString("title.view.room.information")); - dlg.setModal(false); - - dlg.pack(); - dlg.setSize(450, 400); - dlg.setResizable(true); - dlg.setContentPane(mainPanel); - dlg.setLocationRelativeTo(SparkManager.getMainWindow()); - - PropertyChangeListener changeListener = e -> { - String value = (String)pane.getValue(); - if (Res.getString("close").equals(value)) { - pane.setValue(JOptionPane.UNINITIALIZED_VALUE); - dlg.dispose(); - } - }; - - pane.addPropertyChangeListener(changeListener); - - dlg.setVisible(true); - dlg.toFront(); - dlg.requestFocus(); - } - - -} diff --git a/src/java/org/jivesoftware/spark/ui/conferences/RoomCreationDialog.java b/src/java/org/jivesoftware/spark/ui/conferences/RoomCreationDialog.java deleted file mode 100644 index 1da5be113..000000000 --- a/src/java/org/jivesoftware/spark/ui/conferences/RoomCreationDialog.java +++ /dev/null @@ -1,267 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.conferences; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.resource.Res; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.muc.MultiUserChat; -import org.jivesoftware.smackx.muc.MultiUserChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.TitlePanel; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.log.Log; - -import javax.swing.JCheckBox; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPasswordField; -import javax.swing.JTextField; -import javax.swing.UIManager; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - -public class RoomCreationDialog extends JPanel { - private static final long serialVersionUID = -8391698290385575601L; - private JLabel nameLabel = new JLabel(); - private JLabel topicLabel = new JLabel(); - private JLabel passwordLabel = new JLabel(); - private JLabel confirmPasswordLabel = new JLabel(); - private JCheckBox permanentCheckBox = new JCheckBox(); - private JCheckBox privateCheckbox = new JCheckBox(); - private JTextField nameField = new JTextField(); - private JTextField topicField = new JTextField(); - private JPasswordField passwordField = new JPasswordField(); - private JPasswordField confirmPasswordField = new JPasswordField(); - private GridBagLayout gridBagLayout1 = new GridBagLayout(); - private MultiUserChat groupChat = null; - - public RoomCreationDialog() { - try { - jbInit(); - } - catch (Exception e) { - Log.error(e); - } - } - - private void jbInit() throws Exception { - this.setLayout(gridBagLayout1); - this.add(confirmPasswordField, new GridBagConstraints(1, 4, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - this.add(passwordField, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - this.add(topicField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - this.add(nameField, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - this.add(privateCheckbox, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - this.add(permanentCheckBox, new GridBagConstraints(0, 5, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - this.add(confirmPasswordLabel, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - this.add(passwordLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - this.add(topicLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 5, 0)); - this.add(nameLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - ResourceUtils.resLabel(nameLabel, nameField, Res.getString("label.room.name")); - ResourceUtils.resLabel(topicLabel, topicField, Res.getString("label.room.topic") + ":"); - ResourceUtils.resLabel(passwordLabel, passwordField, Res.getString("label.password") + ":"); - ResourceUtils.resLabel(confirmPasswordLabel, confirmPasswordField, Res.getString("label.confirm.password") + ":"); - ResourceUtils.resButton(permanentCheckBox, Res.getString("checkbox.permanent")); - ResourceUtils.resButton(privateCheckbox, Res.getString("checkbox.private.room")); - } - - public MultiUserChat createGroupChat(Component parent, final String serviceName) { - final JOptionPane pane; - final JDialog dlg; - - TitlePanel titlePanel; - - // Create the title panel for this dialog - titlePanel = new TitlePanel(Res.getString("title.create.or.join"), Res.getString("message.create.or.join.room"), SparkRes.getImageIcon(SparkRes.BLANK_24x24), true); - - // Construct main panel w/ layout. - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(titlePanel, BorderLayout.NORTH); - - // The user should only be able to close this dialog. - Object[] options = {Res.getString("create"), Res.getString("close")}; - pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); - - mainPanel.add(pane, BorderLayout.CENTER); - - JOptionPane p = new JOptionPane(); - dlg = p.createDialog(parent, Res.getString("title.conference.rooms")); - dlg.pack(); - dlg.setSize(400, 350); - dlg.setContentPane(mainPanel); - dlg.setLocationRelativeTo(parent); - - - PropertyChangeListener changeListener = new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent e) { - Object o = pane.getValue(); - if (o instanceof Integer) { - dlg.setVisible(false); - return; - } - - String value = (String)pane.getValue(); - if (Res.getString("close").equals(value)) { - dlg.setVisible(false); - } - else if (Res.getString("create").equals(value)) { - boolean isValid = validatePanel(); - if (isValid) { - String room = nameField.getText().replaceAll(" ", "_") + "@" + serviceName; - try { - MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getRoomInfo( room ); - //JOptionPane.showMessageDialog(dlg, "Room already exists. Please specify a unique room name.", "Room Exists", JOptionPane.ERROR_MESSAGE); - //pane.setValue(JOptionPane.UNINITIALIZED_VALUE); - pane.removePropertyChangeListener(this); - dlg.setVisible(false); - ConferenceUtils.joinConferenceRoom(room, room); - return; - } - catch (XMPPException | SmackException e1) { - // Nothing to do - } - - groupChat = createGroupChat(nameField.getText(), serviceName); - if (groupChat == null) { - showError("Could not join chat " + nameField.getText()); - pane.setValue(JOptionPane.UNINITIALIZED_VALUE); - - } - else { - pane.removePropertyChangeListener(this); - dlg.setVisible(false); - } - } - else { - pane.setValue(JOptionPane.UNINITIALIZED_VALUE); - } - } - } - }; - - pane.addPropertyChangeListener(changeListener); - nameField.requestFocusInWindow(); - - dlg.setVisible(true); - dlg.toFront(); - dlg.requestFocus(); - - return groupChat; - } - - private boolean validatePanel() { - String roomName = nameField.getText(); - String password = new String(passwordField.getPassword()); - String confirmPassword = new String(confirmPasswordField.getPassword()); - boolean isPrivate = privateCheckbox.isSelected(); - - // Check for valid information - if (!ModelUtil.hasLength(roomName)) { - showError(Res.getString("message.specify.name.error")); - nameField.requestFocus(); - return false; - } - - if (isPrivate) { - if (!ModelUtil.hasLength(password)) { - showError(Res.getString("message.password.private.room.error")); - passwordField.requestFocus(); - return false; - } - - if (!ModelUtil.hasLength(confirmPassword)) { - showError(Res.getString("message.confirmation.password.error")); - confirmPasswordField.requestFocus(); - return false; - } - - if (!ModelUtil.areEqual(password, confirmPassword)) { - showError(Res.getString("message.passwords.no.match")); - passwordField.requestFocus(); - return false; - } - } - - return true; - } - - private MultiUserChat createGroupChat(String roomName, String serviceName) { - String room = roomName.replaceAll(" ", "_") + "@" + serviceName; - - // Create a group chat with valid information - return MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getMultiUserChat( room.toLowerCase() ); - } - - - private void showError(String errorMessage) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(this, errorMessage, Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - } - - public boolean isPrivate() { - return privateCheckbox.isSelected(); - } - - public boolean isPermanent() { - return permanentCheckBox.isSelected(); - } - - public boolean isPasswordProtected() { - String password = new String(passwordField.getPassword()); - if (password.length() > 0) { - return true; - } - - return false; - } - - public String getPassword() { - return new String(confirmPasswordField.getPassword()); - } - - /** - * Returns the Room name of the RoomCreationDialog - * - * @return The Room name - */ - public String getRoomName() { - return nameField.getText(); - } - /** - * Returns the Topic of the RoomCreationDialog - * @return The Rooms Topic - */ - public String getRoomTopic() { - return topicField.getText(); - } - -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/spark/ui/history/HistoryMessage.java b/src/java/org/jivesoftware/spark/ui/history/HistoryMessage.java deleted file mode 100644 index 66acbdd9c..000000000 --- a/src/java/org/jivesoftware/spark/ui/history/HistoryMessage.java +++ /dev/null @@ -1,191 +0,0 @@ -package org.jivesoftware.spark.ui.history; - -import java.text.MessageFormat; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; - -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -/** - * @author Vyacheslav Durin (nixspirit@gmail.com) - * - * Apr 17, 2013 - * @version 0.1 - */ -public class HistoryMessage { - - private static final String EMPTY = ""; - private static final SimpleDateFormat dateFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss.S z"); - private static final SimpleDateFormat fromDateFormat = new SimpleDateFormat( - "hh:mm:ss a"); - private static final MessageFormat contentFormat = new MessageFormat( - "({0}) {1}: {2}
        "); - private Element messageElement; - private String to; - private String from; - private String body; - private Date date; - - public HistoryMessage(Element messageEl) { - this.messageElement = messageEl; - - String to = getElementValue(this.messageElement, "to"); - String from = getElementValue(this.messageElement, "from"); - String body = getElementValue(this.messageElement, "body"); - String date = getElementValue(this.messageElement, "date"); - - setTo(to); - setFrom(from); - setBody(body); - setDate(date); - } - - public HistoryMessage() { - } - - public HistoryMessage(HistoryMessage orig) { - if (orig == null) - throw new IllegalArgumentException( - "Original message cannot be null"); - setTo(orig.getTo()); - setFrom(orig.getFrom()); - setBody(orig.getBody()); - setDate(orig.getDate()); - } - - /** - * @param to - * the to to set - */ - public void setTo(String to) { - this.to = to; - } - - /** - * @param from - * the from to set - */ - public void setFrom(String from) { - this.from = from; - } - - /** - * @param body - * the body to set - */ - public void setBody(String body) { - this.body = body; - } - - /** - * @param date - * the date to set - */ - public void setDate(Date date) { - this.date = date; - } - - /** - * @param date - * the date to set - */ - public void setDate(String date) { - this.date = parseHistoryDate(date); - } - - /** - * @return the messageElement - */ - public Element getXML() { - return messageElement; - } - - /** - * @return the to - */ - public String getTo() { - return to; - } - - /** - * @return the from - */ - public String getFrom() { - return from; - } - - /** - * @return the body - */ - public String getBody() { - return body; - } - - /** - * @return the date - */ - public Date getDate() { - return date; - } - - public Date getNormalizedDate() { - Calendar cal = normalizeDate(getDate()); - return cal.getTime(); - } - - public Date getNormalizedMonth() { - Calendar cal = normalizeDate(getDate()); - cal.set(Calendar.DATE, 1); - return cal.getTime(); - } - - public String getContent() { - return contentFormat.format(new String[] { fromDateFormat.format(date), - from, body }); - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - return "HistoryMessage to=" + to + ", from=" + from + ", body=" + body - + ", date=" + date + "]"; - } - - private static Date parseHistoryDate(String dateToParse) { - try { - return dateFormat.parse(dateToParse); - } catch (Exception e) { - e.printStackTrace(); - } - return Calendar.getInstance().getTime(); - } - - private static Calendar normalizeDate(Date d) { - Calendar cal = Calendar.getInstance(); - cal.setTime(d); - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - return cal; - } - - private static String getElementValue(Element element, String tag) { - if (element == null || tag == null || EMPTY.equals(tag)) - return EMPTY; - - NodeList to = element.getElementsByTagName(tag); - if (to.getLength() < 1) - return EMPTY; - Element el = (Element) to.item(0); - if (el == null) - return EMPTY; - return el.getFirstChild().getNodeValue(); - } - -} diff --git a/src/java/org/jivesoftware/spark/ui/rooms/ChatRoomImpl.java b/src/java/org/jivesoftware/spark/ui/rooms/ChatRoomImpl.java deleted file mode 100644 index 954025a1d..000000000 --- a/src/java/org/jivesoftware/spark/ui/rooms/ChatRoomImpl.java +++ /dev/null @@ -1,857 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.rooms; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.GridBagConstraints; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; -import java.text.DateFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.TimerTask; - -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.SwingUtilities; -import javax.swing.event.DocumentEvent; - -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.chat.Chat; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.packet.*; -import org.jivesoftware.smack.roster.Roster; -import org.jivesoftware.smack.roster.RosterEntry; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.filter.AndFilter; -import org.jivesoftware.smack.filter.FromMatchesFilter; -import org.jivesoftware.smack.filter.OrFilter; -import org.jivesoftware.smack.filter.StanzaFilter; -import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smackx.chatstates.ChatState; -import org.jivesoftware.smackx.chatstates.ChatStateManager; -import org.jivesoftware.smackx.xevent.MessageEventManager; -import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; -import org.jivesoftware.smackx.xevent.packet.MessageEvent; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.PresenceManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomButton; -import org.jivesoftware.spark.ui.ChatStatePanel; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.ui.MessageEventListener; -import org.jivesoftware.spark.ui.RosterDialog; -import org.jivesoftware.spark.ui.VCardPanel; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.transcripts.ChatTranscript; -import org.jivesoftware.sparkimpl.plugin.transcripts.ChatTranscripts; -import org.jivesoftware.sparkimpl.plugin.transcripts.HistoryMessage; -import org.jivesoftware.sparkimpl.profile.VCardManager; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -/** - * This is the Person to Person implementation of ChatRoom - * This room only allows for 1 to 1 conversations. - */ -public class ChatRoomImpl extends ChatRoom { - private static final long serialVersionUID = 6163762803773980872L; - private List messageEventListeners = new ArrayList<>(); - private String roomname; - private Icon tabIcon; - private String roomTitle; - private String tabTitle; - private String participantJID; - private String participantNickname; - - private final Color TRANSPARENT_COLOR = new Color(0,0,0,0); - - private Presence presence; - - private boolean offlineSent; - - private Roster roster; - - private long startNotificationSendingTime; - private boolean sendComposingNotification = true; - private boolean sendPausingNotification = false; - private boolean sendInactiveNotification = false; - private boolean sendGoneNotification = false; - private ChatState lastNotificationSent = null; - - private TimerTask typingTimerTask; - private boolean sendChatStateNotification = false; - private String threadID; - - private long lastActivity; - - private boolean active; - - // Information button - private ChatRoomButton infoButton; - - private ChatRoomButton addToRosterButton; - private VCardPanel vcardPanel; - - private long pauseTimePeriod = 2000; - private long inactiveTimePeriod = 120000; - private long goneTimePeriod = 600000; - - private JComponent chatStatePanel; - - public ChatRoomImpl(final String participantJID, String participantNickname, String title) { - this(participantJID, participantNickname, title, true); - } - - /** - * Constructs a 1-to-1 ChatRoom. - * - * @param participantJID the participants jid to chat with. - * @param participantNickname the nickname of the participant. - * @param title the title of the room. - */ - public ChatRoomImpl(final String participantJID, String participantNickname, String title, boolean initUi) { - this.active = true; - //activateNotificationTime = System.currentTimeMillis(); - this.participantJID = participantJID; - this.participantNickname = participantNickname; - - // Loads the current history for this user. - loadHistory(); - - // Register StanzaListeners - StanzaFilter fromFilter = new FromMatchesFilter(participantJID, false); - StanzaFilter orFilter = new OrFilter(new StanzaTypeFilter(Presence.class), new StanzaTypeFilter(Message.class)); - StanzaFilter andFilter = new AndFilter(orFilter, fromFilter); - - SparkManager.getConnection().addAsyncStanzaListener(this, andFilter); - - // The roomname will be the participantJID - this.roomname = participantJID; - - // Use the agents username as the Tab Title - this.tabTitle = title; - - // The name of the room will be the node of the user jid + conversation. - this.roomTitle = participantNickname; - - // Add RoomInfo - this.getSplitPane().setRightComponent(null); - getSplitPane().setDividerSize(0); - - - presence = PresenceManager.getPresence(participantJID); - - roster = Roster.getInstanceFor( SparkManager.getConnection() ); - - RosterEntry entry = roster.getEntry(participantJID); - - tabIcon = PresenceManager.getIconFromPresence(presence); - - if (initUi) { - // Create toolbar buttons. - infoButton = new ChatRoomButton("", SparkRes.getImageIcon(SparkRes.PROFILE_IMAGE_24x24)); - infoButton.setToolTipText(Res.getString("message.view.information.about.this.user")); - // Create basic toolbar. - addChatRoomButton(infoButton); - // Show VCard. - infoButton.addActionListener(this); - } - - // If the user is not in the roster, then allow user to add them. - addToRosterButton = new ChatRoomButton("", SparkRes.getImageIcon(SparkRes.ADD_IMAGE_24x24)); - if (entry == null && !XmppStringUtils.parseResource(participantJID).equals(participantNickname)) { - addToRosterButton.setToolTipText(Res.getString("message.add.this.user.to.your.roster")); - if(!Default.getBoolean(Default.ADD_CONTACT_DISABLED)) { - addChatRoomButton(addToRosterButton); - } - addToRosterButton.addActionListener(this); - } - - // If this is a private chat from a group chat room, do not show toolbar. - if (XmppStringUtils.parseResource(participantJID).equals(participantNickname)) { - getToolBar().setVisible(false); - } - - createChatStateTimerTask(); - - lastActivity = System.currentTimeMillis(); - getChatInputEditor().addFocusListener(new ChatStateFocusListener()); - } - - protected void createChatStateTimerTask() { - typingTimerTask = new TimerTask() { - public void run() { - if (!sendChatStateNotification) { - return; - } - long now = System.currentTimeMillis(); - long time = now - startNotificationSendingTime; - if (inBetween(time, pauseTimePeriod, inactiveTimePeriod)) { - if (sendPausingNotification) { - // send cancel - //SparkManager.getMessageEventManager().sendCancelledNotification(getParticipantJID(), threadID); - sendChatState(ChatState.paused); - sendPausingNotification = false; - sendComposingNotification = true; - } - } else if (inBetween(time, inactiveTimePeriod, goneTimePeriod)) { - if(sendInactiveNotification) { - sendChatState(ChatState.inactive); - sendInactiveNotification = false; - } - } else if (time > goneTimePeriod) { - if (sendGoneNotification) { - sendChatState(ChatState.gone); - sendGoneNotification = false; - } - } - } - }; - TaskEngine.getInstance().scheduleAtFixedRate(typingTimerTask, pauseTimePeriod, pauseTimePeriod); - } - - private boolean inBetween(long time, long lowLimit, long highLimit) { - return lowLimit < time && time < highLimit; - } - - public void activateChatStateNotificationSystem() { - startNotificationSendingTime = System.currentTimeMillis(); - sendInactiveNotification = true; - sendGoneNotification = true; - sendPausingNotification = false; - sendComposingNotification = true; - if (lastNotificationSent == null || !lastNotificationSent.equals(ChatState.active)) { - sendChatState(ChatState.active); - } - } - - public void inactivateChatStateNotificationSystem() { - startNotificationSendingTime = System.currentTimeMillis(); - sendInactiveNotification = false; - sendGoneNotification = true; - sendPausingNotification = false; - sendComposingNotification = false; - if (lastNotificationSent != null && !lastNotificationSent.equals(ChatState.inactive) && !lastNotificationSent.equals(ChatState.gone)) { - sendChatState(ChatState.inactive); - } - } - - private void sendChatState(ChatState state) { - XMPPConnection connection = SparkManager.getConnection(); - boolean connected = connection.isConnected(); - if (connected) { - Chat chat = org.jivesoftware.smack.chat.ChatManager.getInstanceFor( connection ).createChat(getParticipantJID(), null); - try { - ChatStateManager.getInstance(connection).setCurrentState(state, chat); - lastNotificationSent = state; - } catch (SmackException e) { - Log.error("Cannot send " + state + " chat notification"); - } - } - } - - public void closeChatRoom() { - // If already closed, don't bother. - if (!active) { - return; - } - - super.closeChatRoom(); - - removeListeners(); - - sendChatState(ChatState.gone); - sendGoneNotification = false; - - SparkManager.getChatManager().removeChat(this); - - SparkManager.getConnection().removeAsyncStanzaListener(this); - if (typingTimerTask != null) { - TaskEngine.getInstance().cancelScheduledTask(typingTimerTask); - typingTimerTask = null; - } - active = false; - vcardPanel = null; - - this.removeAll(); - } - - protected void removeListeners() { - // Remove info listener - infoButton.removeActionListener(this); - addToRosterButton.removeActionListener(this); - } - - public void sendMessage() { - String text = getChatInputEditor().getText(); - sendMessage(text); - } - - public void sendMessage(String text) { - final Message message = new Message(); - - if (threadID == null) { - threadID = StringUtils.randomString(6); - } - message.setThread(threadID); - - // Set the body of the message using typedMessage and remove control - // characters - text = text.replaceAll("[\\u0001-\\u0008\\u000B-\\u001F]", ""); - message.setBody(text); - - // IF there is no body, just return and do nothing - if (!ModelUtil.hasLength(text)) { - return; - } - - // Fire Message Filters - SparkManager.getChatManager().filterOutgoingMessage(this, message); - - // Fire Global Filters - SparkManager.getChatManager().fireGlobalMessageSentListeners(this, message); - - sendMessage(message); - } - - /** - * Sends a message to the appropriate jid. The message is automatically added to the transcript. - * - * @param message the message to send. - */ - public void sendMessage(Message message) { - lastActivity = System.currentTimeMillis(); - //Before sending message, let's add our full jid for full verification - //Set message attributes before insertMessage is called - this is useful when transcript window is extended - //more information will be available to be displayed for the chat area Document - message.setType(Message.Type.chat); - message.setTo(participantJID); - message.setFrom(SparkManager.getSessionManager().getJID()); - try { - getTranscriptWindow().insertMessage(getNickname(), message, ChatManager.TO_COLOR, TRANSPARENT_COLOR); - getChatInputEditor().selectAll(); - - getTranscriptWindow().validate(); - getTranscriptWindow().repaint(); - getChatInputEditor().clear(); - } - catch (Exception ex) { - Log.error("Error sending message", ex); - } - - // Notify users that message has been sent - fireMessageSent(message); - - addToTranscript(message, false); - - getChatInputEditor().setCaretPosition(0); - getChatInputEditor().requestFocusInWindow(); - scrollToBottom(); - - // No need to request displayed or delivered as we aren't doing anything with this - // information. - MessageEventManager.addNotificationsRequests(message, true, false, false, true); - - // Send the message that contains the notifications request - try { - fireOutgoingMessageSending(message); - SparkManager.getConnection().sendStanza(message); - } - catch (Exception ex) { - Log.error("Error sending message", ex); - } - sendChatStateNotification = true; - activateChatStateNotificationSystem(); - } - - public String getRoomname() { - return roomname; - } - - - public Icon getTabIcon() { - return tabIcon; - } - - public void setTabIcon(Icon icon) { - this.tabIcon = icon; - } - - public String getTabTitle() { - return tabTitle; - } - - public void setTabTitle(String tabTitle) { - this.tabTitle = tabTitle; - } - - public void setRoomTitle(String roomTitle) { - this.roomTitle = roomTitle; - } - - public String getRoomTitle() { - return roomTitle; - } - - public Message.Type getChatType() { - return Message.Type.chat; - } - - public void leaveChatRoom() { - // There really is no such thing in Agent to Agent - } - - public boolean isActive() { - return true; - } - - /** - * Returns the Bare-Participant JID - * - * user@server.com
        - * for retrieving the full Jid use ChatRoomImpl.getJID() - * - * @return - */ - public String getParticipantJID() { - return participantJID; - } - - /** - * Returns the users full jid (ex. macbeth@jivesoftware.com/spark). - * - * @return the users Full JID. - */ - public String getJID() { - presence = PresenceManager.getPresence(getParticipantJID()); - return presence.getFrom(); - } - - /** - * Process incoming packets. - * - * @param stanza - the packet to process - */ - public void processPacket(final Stanza stanza) { - final Runnable runnable = () -> { - if (stanza instanceof Presence) { - - Presence.Type oldType = presence.getType(); - - presence = (Presence)stanza; - - final Presence presence1 = (Presence)stanza; - - ContactList list = SparkManager.getWorkspace().getContactList(); - ContactItem contactItem = list.getContactItemByJID(getParticipantJID()); - - String time = DateFormat.getTimeInstance(DateFormat.SHORT).format(new Date()); - - if ( presence1.getType() == Presence.Type.unavailable && contactItem != null) { - getTranscriptWindow().insertNotificationMessage("*** " + Res.getString("message.went.offline", participantNickname, time), ChatManager.NOTIFICATION_COLOR); - } - else if (oldType == Presence.Type.unavailable && presence1.getType() == Presence.Type.available) { - getTranscriptWindow().insertNotificationMessage("*** " + Res.getString("message.came.online", participantNickname, time), ChatManager.NOTIFICATION_COLOR); - } - } - else if (stanza instanceof Message) { - lastActivity = System.currentTimeMillis(); - - - // Do something with the incoming packet here. - final Message message = (Message)stanza; - fireReceivingIncomingMessage(message); - if (message.getError() != null) { - if (message.getError().getCondition() == XMPPError.Condition.item_not_found) { - // Check to see if the user is online to recieve this message. - RosterEntry entry = roster.getEntry(participantJID); - if (!presence.isAvailable() && !offlineSent && entry != null) { - getTranscriptWindow().insertNotificationMessage(Res.getString("message.offline.error"), ChatManager.ERROR_COLOR); - offlineSent = true; - } - } - return; - } - - // Check to see if the user is online to recieve this message. - RosterEntry entry = roster.getEntry(participantJID); - if (!presence.isAvailable() && !offlineSent && entry != null) { - getTranscriptWindow().insertNotificationMessage(Res.getString("message.offline"), ChatManager.ERROR_COLOR); - offlineSent = true; - } - - if (threadID == null) { - threadID = message.getThread(); - if (threadID == null) { - threadID = StringUtils.randomString(6); - } - } - - final JivePropertiesExtension extension = ((JivePropertiesExtension) message.getExtension( JivePropertiesExtension.NAMESPACE )); - final boolean broadcast = extension != null && extension.getProperty( "broadcast" ) != null; - - // If this is a group chat message, discard - if (message.getType() == Message.Type.groupchat || broadcast || message.getType() == Message.Type.normal || - message.getType() == Message.Type.headline) { - return; - } - - // Do not accept Administrative messages. - final String host = SparkManager.getSessionManager().getServerAddress(); - if (host.equals(message.getFrom())) { - return; - } - - // If the message is not from the current agent. Append to chat. - if (message.getBody() != null) { - participantJID = message.getFrom(); - insertMessage(message); - - showTyping(false); - } - } - }; - SwingUtilities.invokeLater(runnable); - } - - /** - * Returns the nickname of the user chatting with. - * - * @return the nickname of the chatting user. - */ - public String getParticipantNickname() { - return participantNickname; - } - - - /** - * The current SendField has been updated somehow. - * - * @param e - the DocumentEvent to respond to. - */ - public void insertUpdate(DocumentEvent e) { - checkForText(e); - - if (!sendChatStateNotification) { - return; - } - startNotificationSendingTime = System.currentTimeMillis(); - - // If the user pauses for more than two seconds, send out a new notice. - if (sendComposingNotification) { - try { - //SparkManager.getMessageEventManager().sendComposingNotification(getParticipantJID(), threadID); - sendChatState(ChatState.composing); - - sendPausingNotification = true; - sendInactiveNotification = true; - sendGoneNotification = true; - sendComposingNotification = false; - } - catch (Exception exception) { - Log.error("Error updating", exception); - } - } - } - - public void insertMessage(Message message) { - // Debug info - super.insertMessage(message); - MessageEvent messageEvent = message.getExtension("x", "jabber:x:event"); - if (messageEvent != null) { - checkEvents(message.getFrom(), message.getStanzaId(), messageEvent); - } - - getTranscriptWindow().insertMessage(participantNickname, message, ChatManager.FROM_COLOR, TRANSPARENT_COLOR); - - // Set the participant jid to their full JID. - participantJID = message.getFrom(); - } - - private void checkEvents(String from, String packetID, MessageEvent messageEvent) { - if (messageEvent.isDelivered() || messageEvent.isDisplayed()) { - // Create the message to send - Message msg = new Message(from); - // Create a MessageEvent Package and add it to the message - MessageEvent event = new MessageEvent(); - if (messageEvent.isDelivered()) { - event.setDelivered(true); - } - if (messageEvent.isDisplayed()) { - event.setDisplayed(true); - } - event.setStanzaId(packetID); - msg.addExtension(event); - // Send the packet - try - { - SparkManager.getConnection().sendStanza(msg); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to send message to " + msg.getTo(), e ); - } - } - } - - public void addMessageEventListener(MessageEventListener listener) { - messageEventListeners.add(listener); - } - - public void removeMessageEventListener(MessageEventListener listener) { - messageEventListeners.remove(listener); - } - - public Collection getMessageEventListeners() { - return messageEventListeners; - } - - public void fireOutgoingMessageSending(Message message) { - for (MessageEventListener messageEventListener : new ArrayList<>( messageEventListeners )) { - messageEventListener.sendingMessage(message); - } - } - - public void fireReceivingIncomingMessage(Message message) { - for (MessageEventListener messageEventListener : new ArrayList<>( messageEventListeners )) { - messageEventListener.receivingMessage(message); - } - } - - - /** - * Show the typing notification. - * - * @param typing true if the typing notification should show, otherwise hide it. - */ - public void showTyping(boolean typing) { - if (typing) { - String isTypingText = Res.getString("message.is.typing.a.message", participantNickname); - getNotificationLabel().setText(isTypingText); - getNotificationLabel().setIcon(SparkRes.getImageIcon(SparkRes.SMALL_MESSAGE_EDIT_IMAGE)); - } - else { - // Remove is typing text. - getNotificationLabel().setText(""); - getNotificationLabel().setIcon(SparkRes.getImageIcon(SparkRes.BLANK_IMAGE)); - } - - } - - /** - * The last time this chat room sent or received a message. - * - * @return the last time this chat room sent or receieved a message. - */ - public long getLastActivity() { - return lastActivity; - } - - /** - * Returns the current presence of the client this room was created for. - * - * @return the presence - */ - public Presence getPresence() { - return presence; - } - - public void setSendChatStateNotification(boolean isSendChatStateNotification) { - this.sendChatStateNotification = isSendChatStateNotification; - } - - - @Override - public void connected( XMPPConnection xmppConnection ) - { - - } - - @Override - public void authenticated( XMPPConnection xmppConnection, boolean b ) - { - - } - - public void connectionClosed() { - handleDisconnect(); - - String message = Res.getString("message.disconnected.error"); - getTranscriptWindow().insertNotificationMessage(message, ChatManager.ERROR_COLOR); - } - - public void connectionClosedOnError(Exception ex) { - handleDisconnect(); - - String message = Res.getString("message.disconnected.error"); - - if (ex instanceof XMPPException.StreamErrorException && ((XMPPException.StreamErrorException) ex).getStreamError().getCondition() == StreamError.Condition.conflict ) - { - message = Res.getString("message.disconnected.conflict.error"); - } - - getTranscriptWindow().insertNotificationMessage(message, ChatManager.ERROR_COLOR); - } - - public void reconnectionSuccessful() { - Presence usersPresence = PresenceManager.getPresence(getParticipantJID()); - if (usersPresence.isAvailable()) { - presence = usersPresence; - } - - SparkManager.getChatManager().getChatContainer().fireChatRoomStateUpdated(this); - getChatInputEditor().setEnabled(true); - getSendButton().setEnabled(true); - } - - private void handleDisconnect() { - presence = new Presence(Presence.Type.unavailable); - getChatInputEditor().setEnabled(false); - getSendButton().setEnabled(false); - SparkManager.getChatManager().getChatContainer().fireChatRoomStateUpdated(this); - } - - - protected void loadHistory() { - // Add VCard Panel - vcardPanel = new VCardPanel(participantJID); - getToolBar().add(vcardPanel, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 2, 0, 2), 0, 0)); - - if (!Default.getBoolean("HISTORY_DISABLED")) { - final LocalPreferences localPreferences = SettingsManager.getLocalPreferences(); - if (!localPreferences.isChatHistoryEnabled()) { - return; - } - - if (!localPreferences.isPrevChatHistoryEnabled()) { - return; - } - - final ChatTranscript chatTranscript = ChatTranscripts.getCurrentChatTranscript(getParticipantJID()); - final String personalNickname = SparkManager.getUserManager().getNickname(); - - for (HistoryMessage message : chatTranscript.getMessages()) { - String nickname = SparkManager.getUserManager().getUserNicknameFromJID(message.getFrom()); - String messageBody = message.getBody(); - if (nickname.equals(message.getFrom())) { - String otherJID = XmppStringUtils.parseBareJid(message.getFrom()); - String myJID = SparkManager.getSessionManager().getBareAddress(); - - if (otherJID.equals(myJID)) { - nickname = personalNickname; - } - else { - try - { - nickname = message.getFrom().substring(message.getFrom().indexOf("/")+1); - } - catch(Exception e) - { - nickname = XmppStringUtils.parseLocalpart(nickname); - } - } - } - - if (ModelUtil.hasLength(messageBody) && messageBody.startsWith("/me ")) { - messageBody = messageBody.replaceFirst("/me", nickname); - } - - final Date messageDate = message.getDate(); - getTranscriptWindow().insertHistoryMessage(nickname, messageBody, messageDate); - } - if ( 0 < chatTranscript.getMessages().size() ) { // Check if we have history mesages - getTranscriptWindow().insertHorizontalLine(); - } - chatTranscript.release(); - } - } - - private boolean isOnline() { - Presence presence = roster.getPresence(getParticipantJID()); - return presence.isAvailable(); - } - - - // I would normally use the command pattern, but - // have no real use when dealing with just a couple options. - public void actionPerformed(ActionEvent e) { - - if (e.getSource() == infoButton) { - VCardManager vcard = SparkManager.getVCardManager(); - vcard.viewProfile(participantJID, SparkManager.getChatManager().getChatContainer()); - } - else if (e.getSource() == addToRosterButton) { - RosterDialog rosterDialog = new RosterDialog(); - rosterDialog.setDefaultJID(XmppStringUtils.parseBareJid(participantJID)); - rosterDialog.setDefaultNickname(getParticipantNickname()); - rosterDialog.showRosterDialog(SparkManager.getChatManager().getChatContainer().getChatFrame()); - } else { - super.actionPerformed(e); - } - } - - protected TimerTask getTypingTimerTask() { - return typingTimerTask; - } - - public void notifyChatStateChange(ChatState state) { - if (chatStatePanel != null) { - getEditorWrapperBar().remove(chatStatePanel); - } - - chatStatePanel = new ChatStatePanel(state, getParticipantNickname()); - getEditorWrapperBar().add(chatStatePanel, BorderLayout.SOUTH); - getEditorWrapperBar().revalidate(); - getEditorWrapperBar().repaint(); - } - - private class ChatStateFocusListener extends FocusAdapter { - - @Override - public void focusGained(FocusEvent e) { - if(e.getComponent().equals(getChatInputEditor())) { - if (sendChatStateNotification) { - activateChatStateNotificationSystem(); - } - } - } - @Override - public void focusLost(FocusEvent e) { - if(e.getComponent().equals(getChatInputEditor())) { - inactivateChatStateNotificationSystem(); - } - } - } -} diff --git a/src/java/org/jivesoftware/spark/ui/rooms/GroupChatRoom.java b/src/java/org/jivesoftware/spark/ui/rooms/GroupChatRoom.java deleted file mode 100644 index 1714c3cd0..000000000 --- a/src/java/org/jivesoftware/spark/ui/rooms/GroupChatRoom.java +++ /dev/null @@ -1,1143 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - *

        - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - *

        - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

        - * http://www.apache.org/licenses/LICENSE-2.0 - *

        - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.rooms; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.filter.*; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.packet.Stanza; -import org.jivesoftware.smack.packet.XMPPError; -import org.jivesoftware.smackx.delay.packet.DelayInformation; -import org.jivesoftware.smackx.muc.DefaultParticipantStatusListener; -import org.jivesoftware.smackx.muc.DefaultUserStatusListener; -import org.jivesoftware.smackx.muc.MultiUserChat; -import org.jivesoftware.smackx.muc.packet.Destroy; -import org.jivesoftware.smackx.muc.packet.MUCUser; -import org.jivesoftware.smackx.xdata.Form; -import org.jivesoftware.smackx.xevent.MessageEventManager; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.plugin.ContextMenuListener; -import org.jivesoftware.spark.ui.*; -import org.jivesoftware.spark.ui.conferences.AnswerFormDialog; -import org.jivesoftware.spark.ui.conferences.ConferenceUtils; -import org.jivesoftware.spark.ui.conferences.DataFormDialog; -import org.jivesoftware.spark.ui.conferences.GroupChatParticipantList; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.UIComponentRegistry; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; -import java.util.*; -import java.util.List; -import java.util.regex.Pattern; - -/** - * GroupChatRoom is the conference chat room UI used to have Multi-User Chats. - */ -public class GroupChatRoom extends ChatRoom -{ - private final LocalPreferences pref = SettingsManager.getLocalPreferences(); - private final MultiUserChat chat; - private final Icon tabIcon = SparkRes.getImageIcon( SparkRes.CONFERENCE_IMAGE_16x16 ); - private final SubjectPanel subjectPanel; - private final List currentUserList = new ArrayList<>(); - private final List blockedUsers = new ArrayList<>(); - private final GroupChatParticipantList roomInfo; - private final RolloverButton settings; - private String password = null; - private String tabTitle; - private boolean isActive = true; - private long lastActivity; - private Message lastMessage; - - /** - * Creates a GroupChatRoom from a MultiUserChat. - * - * @param chat the MultiUserChat to create a GroupChatRoom from. - */ - public GroupChatRoom( final MultiUserChat chat ) - { - this.chat = chat; - - // Create the filter and register with the current connection making sure to filter by room - final StanzaFilter fromFilter = FromMatchesFilter.createBare( chat.getRoom() ); - final StanzaFilter orFilter = new OrFilter( new StanzaTypeFilter( Presence.class ), new StanzaTypeFilter( Message.class ) ); - final StanzaFilter andFilter = new AndFilter( orFilter, fromFilter ); - - // Add packet Listener. - SparkManager.getConnection().addAsyncStanzaListener( this, andFilter ); - - // We are just using a generic Group Chat. - tabTitle = XmppStringUtils.parseLocalpart( XmppStringUtils.unescapeLocalpart( chat.getRoom() ) ); - - // Room Information - roomInfo = UIComponentRegistry.createGroupChatParticipantList(); - getSplitPane().setRightComponent( roomInfo.getGUI() ); - - roomInfo.setChatRoom( this ); - getSplitPane().setResizeWeight( 1 ); - - setupListeners(); - - subjectPanel = new SubjectPanel( this ); - - // Do not show top toolbar - getToolBar().add( - subjectPanel, - new GridBagConstraints( 0, 1, 1, 1, 1.0, 0.0, - GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets( 0, 2, 0, 2 ), - 0, 0 ) ); - - // Add ContextMenuListener - getTranscriptWindow().addContextMenuListener( new ContextMenuListener() - { - @Override - public void poppingUp( Object component, JPopupMenu popup ) - { - popup.addSeparator(); - Action inviteAction = new AbstractAction() - { - @Override - public void actionPerformed( ActionEvent actionEvent ) - { - ConferenceUtils.inviteUsersToRoom( chat, null, false ); - } - }; - - inviteAction.putValue( Action.NAME, Res.getString( "menuitem.invite.users" ) ); - inviteAction.putValue( Action.SMALL_ICON, SparkRes.getImageIcon( SparkRes.SMALL_MESSAGE_IMAGE ) ); - - popup.add( inviteAction ); - - Action configureAction = new AbstractAction() - { - @Override - public void actionPerformed( ActionEvent actionEvent ) - { - try - { - ChatFrame chatFrame = SparkManager.getChatManager().getChatContainer().getChatFrame(); - Form form = chat.getConfigurationForm().createAnswerForm(); - new DataFormDialog( chatFrame, chat, form ); - } - catch ( XMPPException | SmackException e ) - { - Log.error( "Error configuring room.", e ); - } - } - }; - - configureAction.putValue( Action.NAME, Res.getString( "title.configure.room" ) ); - configureAction.putValue( Action.SMALL_ICON, SparkRes.getImageIcon( SparkRes.SETTINGS_IMAGE_16x16 ) ); - if ( SparkManager.getUserManager().isOwner( (GroupChatRoom) getChatRoom(), chat.getNickname() ) ) - { - popup.add( configureAction ); - } - - Action subjectChangeAction = new AbstractAction() - { - @Override - public void actionPerformed( ActionEvent actionEvent ) - { - String newSubject = JOptionPane.showInputDialog( - getChatRoom(), - Res.getString( "message.enter.new.subject" ) + ":", - Res.getString( "title.change.subject" ), - JOptionPane.QUESTION_MESSAGE ); - if ( ModelUtil.hasLength( newSubject ) ) - { - try - { - chat.changeSubject( newSubject ); - } - catch ( XMPPException | SmackException e ) - { - Log.error( e ); - } - } - } - }; - - subjectChangeAction.putValue( Action.NAME, Res.getString( "menuitem.change.subject" ) ); - subjectChangeAction.putValue( Action.SMALL_ICON, SparkRes.getImageIcon( SparkRes.SMALL_MESSAGE_EDIT_IMAGE ) ); - popup.add( subjectChangeAction ); - - // Define actions to modify/view room information - Action destroyRoomAction = new AbstractAction() - { - @Override - public void actionPerformed( ActionEvent e ) - { - int ok = JOptionPane.showConfirmDialog( - getChatRoom(), - Res.getString( "message.confirm.destruction.of.room" ), - Res.getString( "title.confirmation" ), - JOptionPane.YES_NO_OPTION, - JOptionPane.QUESTION_MESSAGE ); - if ( ok == JOptionPane.NO_OPTION ) - { - return; - } - - String reason = JOptionPane.showInputDialog( - getChatRoom(), - Res.getString( "message.room.destruction.reason" ), - Res.getString( "title.enter.reason" ), - JOptionPane.QUESTION_MESSAGE ); - if ( ModelUtil.hasLength( reason ) ) - { - try - { - chat.destroy( reason, null ); - getChatRoom().leaveChatRoom(); - } - catch ( XMPPException | SmackException e1 ) - { - Log.warning( "Unable to destroy room", e1 ); - } - } - } - }; - - destroyRoomAction.putValue( Action.NAME, Res.getString( "menuitem.destroy.room" ) ); - destroyRoomAction.putValue( Action.SMALL_ICON, SparkRes.getImageIcon( SparkRes.SMALL_DELETE ) ); - if ( SparkManager.getUserManager().isOwner( (GroupChatRoom) getChatRoom(), getNickname() ) ) - { - popup.add( destroyRoomAction ); - } - - } - - @Override - public void poppingDown( JPopupMenu popup ) - { - } - - @Override - public boolean handleDefaultAction( MouseEvent e ) - { - return false; - } - } ); - - // set last activity to be right now - lastActivity = System.currentTimeMillis(); - - final GroupChatRoomTransferHandler transferHandler = new GroupChatRoomTransferHandler( this ); - getTranscriptWindow().setTransferHandler( transferHandler ); - - // Adds the Settings and Subject Button to the right Toolbar - settings = UIComponentRegistry.getButtonFactory().createSettingsButton(); - settings.setVisible( false ); - final RolloverButton thema = UIComponentRegistry.getButtonFactory().createTemaButton(); - final RolloverButton register = UIComponentRegistry.getButtonFactory().createRegisterButton(); - - addControllerButton( settings ); - addControllerButton( thema ); - addControllerButton( register ); - - settings.addActionListener( new AbstractAction() - { - @Override - public void actionPerformed( ActionEvent event ) - { - try - { - final ChatFrame chatFrame = SparkManager.getChatManager().getChatContainer().getChatFrame(); - final Form form = chat.getConfigurationForm().createAnswerForm(); - new DataFormDialog( chatFrame, chat, form ); - } - catch ( XMPPException | SmackException xmpe ) - { - getTranscriptWindow().insertNotificationMessage( xmpe.getMessage(), ChatManager.ERROR_COLOR ); - scrollToBottom(); - } - } - } ); - - thema.addActionListener( new AbstractAction() - { - @Override - public void actionPerformed( ActionEvent e ) - { - final String newSubject = JOptionPane.showInputDialog( getChatRoom(), - Res.getString( "message.enter.new.subject" ) + ":", - Res.getString( "title.change.subject" ), - JOptionPane.QUESTION_MESSAGE ); - if ( ModelUtil.hasLength( newSubject ) ) - { - try - { - chat.changeSubject( newSubject ); - } - catch ( XMPPException | SmackException xmpee ) - { - getTranscriptWindow().insertNotificationMessage( xmpee.getMessage(), ChatManager.ERROR_COLOR ); - scrollToBottom(); - } - } - } - } ); - - register.addActionListener( event -> { - try - { - final Form form = chat.getRegistrationForm(); - final ChatFrame chatFrame = SparkManager.getChatManager().getChatContainer().getChatFrame(); - - new AnswerFormDialog( chatFrame, chat, form ); - } - catch ( XMPPException | SmackException xmpe ) - { - getTranscriptWindow().insertNotificationMessage( xmpe.getMessage(), ChatManager.ERROR_COLOR ); - scrollToBottom(); - } - } ); - } - - public Message getLastMessage() - { - return lastMessage; - } - - /** - * Have the user leave this chat room and then close it. - */ - @Override - public void closeChatRoom() - { - // Specify the end time. - super.closeChatRoom(); - - // Remove Listener - SparkManager.getConnection().removeAsyncStanzaListener( this ); - - final ChatContainer container = SparkManager.getChatManager().getChatContainer(); - container.leaveChatRoom( this ); - container.closeTab( this ); - } - - /** - * Determines the background color to use for messages. - * - * @param nickname Nickname associated with message. - * @param body Body of message to scan for reasons to highlight. - * @return Color of message background. - */ - private Color getMessageBackground( String nickname, String body ) - { - final String myNickName = chat.getNickname(); - final String myUserName = SparkManager.getSessionManager().getUsername(); - final Pattern usernameMatch = Pattern.compile( myUserName, Pattern.CASE_INSENSITIVE ); - final Pattern nicknameMatch = Pattern.compile( myNickName, Pattern.CASE_INSENSITIVE ); - - // Should we even highlight this packet? - if ( pref.isMucHighNameEnabled() && myNickName.equalsIgnoreCase( nickname ) ) - { - return new Color( 244, 248, 255 ); - } - else if ( pref.isMucHighTextEnabled() && ( usernameMatch.matcher( body ).find() || nicknameMatch.matcher( body ).find() ) ) - { - return new Color( 255, 255, 153 ); - } - else - { - return new Color( 0, 0, 0, 0 ); - } - } - - /** - * Sends a message. - * - * @param message - the message to send. - */ - @Override - public void sendMessage( Message message ) - { - try - { - message.setTo( chat.getRoom() ); - message.setType( Message.Type.groupchat ); - MessageEventManager.addNotificationsRequests( message, true, true, true, true ); - addPacketID( message.getStanzaId() ); - - SparkManager.getChatManager().filterOutgoingMessage( this, message ); - SparkManager.getChatManager().fireGlobalMessageSentListeners( this, message ); - - chat.sendMessage( message ); - } - catch ( SmackException ex ) - { - Log.error( "Unable to send message in conference chat.", ex ); - } - - // Notify users that message has been sent. - fireMessageSent( message ); - - addToTranscript( message, false ); - - getChatInputEditor().clear(); - getTranscriptWindow().validate(); - getTranscriptWindow().repaint(); - - getChatInputEditor().setCaretPosition( 0 ); - getChatInputEditor().requestFocusInWindow(); - scrollToBottom(); - - lastActivity = System.currentTimeMillis(); - } - - /** - * Return name of the room specified when the room was created. - * - * @return the roomname. - */ - @Override - public String getRoomname() - { - return XmppStringUtils.parseLocalpart( chat.getRoom() ); - } - - /** - * Retrieve the nickname of the user in this groupchat. - * - * @return the nickname of the agent in this groupchat - */ - @Override - public String getNickname() - { - return chat.getNickname(); - } - - /** - * Return the Icon that should be used in the tab of this GroupChat Pane. - * - * @return the Icon to use in tab. - */ - @Override - public Icon getTabIcon() - { - return tabIcon; - } - - /** - * Return the title that should be used in the tab. - * - * @return the title to be used on the tab. - */ - @Override - public String getTabTitle() - { - return tabTitle; - } - - /** - * Sets the title to use on the tab describing the Conference room. - * - * @param tabTitle the title to use on the tab. - */ - public void setTabTitle( String tabTitle ) - { - this.tabTitle = tabTitle; - } - - /** - * Return the title of this room. - * - * @return the title of this room. - */ - @Override - public String getRoomTitle() - { - return getTabTitle(); - } - - /** - * Return the type of chat we are in. - * - * @return the type of chat we are in. - */ - @Override - public Message.Type getChatType() - { - return Message.Type.groupchat; - } - - /** - * Implementation of leaveChatRoom. - */ - @Override - public void leaveChatRoom() - { - if ( !isActive ) - { - return; - } - - SparkManager.getConnection().removeAsyncStanzaListener( this ); - - getChatInputEditor().showAsDisabled(); - - // Do not allow other to try and invite or transfer chat - disableToolbar(); - - getToolBar().setVisible( false ); - - // Update Room Notice To Inform Agent that he has left the chat. - getTranscriptWindow().insertNotificationMessage( Res.getString( "message.user.left.room", getNickname() ), ChatManager.NOTIFICATION_COLOR ); - - try - { - chat.leave(); - } - catch ( Exception e ) - { - Log.error( "Closing Group Chat Room error.", e ); - } - - // Set window as greyed out. - getTranscriptWindow().showWindowDisabled(); - - // Update Notification Label - getNotificationLabel().setText( Res.getString( "message.chat.session.ended", SparkManager.DATE_SECOND_FORMATTER.format( new java.util.Date() ) ) ); - getNotificationLabel().setIcon( null ); - getNotificationLabel().setEnabled( false ); - - getSplitPane().setRightComponent( null ); - getSplitPane().setDividerSize( 0 ); - - isActive = false; - } - - /** - * Returns whether or not this ChatRoom is active. To be active means to - * have the agent still engaged in a conversation with a customer. - * - * @return true if the ChatRoom is active. - */ - @Override - public boolean isActive() - { - return isActive; - } - - /** - * Implementation of processPacket to handle muc related packets. - * - * @param stanza the packet. - */ - @Override - public void processPacket( final Stanza stanza ) - { - super.processPacket( stanza ); - if ( stanza instanceof Presence ) - { - SwingUtilities.invokeLater( () -> handlePresencePacket( stanza ) ); - } - - if ( stanza instanceof Message ) - { - SwingUtilities.invokeLater( () -> { - handleMessagePacket( stanza ); - - // Set last activity - lastActivity = System.currentTimeMillis(); - } ); - } - } - - /** - * Handle all MUC related packets. - * - * @param stanza the packet. - */ - private void handleMessagePacket( Stanza stanza ) - { - // Do something with the incoming packet here. - final Message message = (Message) stanza; - lastMessage = message; - if ( message.getType() == Message.Type.groupchat ) - { - final DelayInformation inf = message.getExtension( "delay", "urn:xmpp:delay" ); - final Date sentDate = inf != null ? inf.getStamp() : new Date(); - - // Do not accept Administrative messages. - final String host = SparkManager.getSessionManager().getServerAddress(); - if ( host.equals( message.getFrom() ) ) - { - return; - } - - if ( ModelUtil.hasLength( message.getBody() ) ) - { - // Update transcript - super.insertMessage( message ); - - final String from = XmppStringUtils.parseResource( message.getFrom() ); - - if ( inf != null ) - { - getTranscriptWindow().insertHistoryMessage( from, message.getBody(), sentDate ); - } - else - { - if ( isBlocked( message.getFrom() ) ) - { - return; - } - - final boolean isFromRoom = !message.getFrom().contains( "/" ); - - if ( !SparkManager.getUserManager().hasVoice( this, from ) && !isFromRoom ) - { - return; - } - - getTranscriptWindow().insertMessage( from, message, getColor( from ), getMessageBackground( from, message.getBody() ) ); - } - } - } - else if ( message.getType() == Message.Type.chat ) - { - try - { - SparkManager.getChatManager().getChatContainer().getChatRoom( message.getFrom() ); - } - catch ( ChatRoomNotFoundException e ) - { - final String userNickname = XmppStringUtils.parseResource( message.getFrom() ); - final String roomTitle = userNickname + " - " + XmppStringUtils.parseLocalpart( getRoomname() ); - - // Check to see if this is a message notification. - if ( message.getBody() != null ) - { - // Create new room - ChatRoom chatRoom = new ChatRoomImpl( message.getFrom(), userNickname, roomTitle ); - SparkManager.getChatManager().getChatContainer().addChatRoom( chatRoom ); - - SparkManager.getChatManager().getChatContainer().activateChatRoom( chatRoom ); - chatRoom.insertMessage( message ); - } - } - - } - else if ( message.getError() != null ) - { - String errorMessage = ""; - - if ( message.getError().getCondition() == XMPPError.Condition.forbidden && message.getSubject() != null ) - { - errorMessage = Res.getString( "message.subject.change.error" ); - } - - else if ( message.getError().getCondition() == XMPPError.Condition.forbidden ) - { - errorMessage = Res.getString( "message.forbidden.error" ); - } - - if ( ModelUtil.hasLength( errorMessage ) ) - { - getTranscriptWindow().insertNotificationMessage( errorMessage, ChatManager.ERROR_COLOR ); - } - } - - //Scroll To bottom every time a message is received - scrollToBottom(); - } - - /** - * Handle all presence packets being sent to this Group Chat Room. - * - * @param stanza the presence packet. - */ - private void handlePresencePacket( Stanza stanza ) - { - final Presence presence = (Presence) stanza; - if ( presence.getError() != null ) - { - return; - } - - final String from = presence.getFrom(); - final String nickname = XmppStringUtils.parseResource( from ); - - final MUCUser mucUser = stanza.getExtension( "x", "http://jabber.org/protocol/muc#user" ); - final Set status = new HashSet<>(); - if ( mucUser != null ) - { - status.addAll( mucUser.getStatus() ); - final Destroy destroy = mucUser.getDestroy(); - if ( destroy != null ) - { - UIManager.put( "OptionPane.okButtonText", Res.getString( "ok" ) ); - JOptionPane.showMessageDialog( this, - Res.getString( "message.room.destroyed", destroy.getReason() ), - Res.getString( "title.room.destroyed" ), - JOptionPane.INFORMATION_MESSAGE ); - leaveChatRoom(); - return; - } - } - - if ( presence.getType() == Presence.Type.unavailable && !status.contains( MUCUser.Status.NEW_NICKNAME_303 ) ) - { - if ( currentUserList.contains( from ) ) - { - if ( pref.isShowJoinLeaveMessagesEnabled() ) - { - getTranscriptWindow().insertNotificationMessage( Res.getString( "message.user.left.room", nickname ), ChatManager.NOTIFICATION_COLOR ); - scrollToBottom(); - } - currentUserList.remove( from ); - } - } - else - { - if ( !currentUserList.contains( from ) ) - { - currentUserList.add( from ); - getChatInputEditor().setEnabled( true ); - if ( pref.isShowJoinLeaveMessagesEnabled() ) - { - getTranscriptWindow().insertNotificationMessage( - Res.getString( "message.user.joined.room", nickname ), - ChatManager.NOTIFICATION_COLOR ); - scrollToBottom(); - } - } - } - } - - /** - * Set up the participant listeners and status change listeners. - */ - private void setupListeners() - { - chat.addParticipantStatusListener( new DefaultParticipantStatusListener() - { - @Override - public void kicked( String participant, String actor, String reason ) - { - insertText( Res.getString( "message.user.kicked.from.room", XmppStringUtils.parseResource( participant ), actor, reason ) ); - } - - @Override - public void voiceGranted( String participant ) - { - insertText( Res.getString( "message.user.given.voice", XmppStringUtils.parseResource( participant ) ) ); - } - - @Override - public void voiceRevoked( String participant ) - { - insertText( Res.getString( "message.user.voice.revoked", XmppStringUtils.parseResource( participant ) ) ); - } - - @Override - public void banned( String participant, String actor, String reason ) - { - insertText( Res.getString( "message.user.banned", XmppStringUtils.parseResource( participant ), reason ) ); - } - - @Override - public void membershipGranted( String participant ) - { - insertText( Res.getString( "message.user.granted.membership", XmppStringUtils.parseResource( participant ) ) ); - } - - @Override - public void membershipRevoked( String participant ) - { - insertText( Res.getString( "message.user.revoked.membership", XmppStringUtils.parseResource( participant ) ) ); - } - - @Override - public void moderatorGranted( String participant ) - { - insertText( Res.getString( "message.user.granted.moderator", XmppStringUtils.parseResource( participant ) ) ); - } - - @Override - public void moderatorRevoked( String participant ) - { - insertText( Res.getString( "message.user.revoked.moderator", XmppStringUtils.parseResource( participant ) ) ); - } - - @Override - public void ownershipGranted( String participant ) - { - insertText( Res.getString( "message.user.granted.owner", XmppStringUtils.parseResource( participant ) ) ); - } - - @Override - public void ownershipRevoked( String participant ) - { - insertText( Res.getString( "message.user.revoked.owner", XmppStringUtils.parseResource( participant ) ) ); - } - - @Override - public void adminGranted( String participant ) - { - insertText( Res.getString( "message.user.granted.admin", XmppStringUtils.parseResource( participant ) ) ); - } - - @Override - public void adminRevoked( String participant ) - { - insertText( Res.getString( "message.user.revoked.admin", XmppStringUtils.parseResource( participant ) ) ); - } - - @Override - public void nicknameChanged( String participant, String nickname ) - { - insertText( Res.getString( "message.user.nickname.changed", XmppStringUtils.parseResource( participant ), nickname ) ); - } - } ); - - chat.addUserStatusListener( new DefaultUserStatusListener() - { - @Override - public void kicked( String s, String reason ) - { - if ( ModelUtil.hasLength( reason ) ) - { - insertText( reason ); - } - else - { - insertText( Res.getString( "message.your.kicked", s ) ); - } - - getChatInputEditor().setEnabled( false ); - getSplitPane().setRightComponent( null ); - leaveChatRoom(); - } - - @Override - public void voiceGranted() - { - insertText( Res.getString( "message.your.voice.granted" ) ); - getChatInputEditor().setEnabled( true ); - } - - @Override - public void voiceRevoked() - { - insertText( Res.getString( "message.your.voice.revoked" ) ); - getChatInputEditor().setEnabled( false ); - } - - @Override - public void banned( String s, String reason ) - { - insertText( Res.getString( "message.your.banned" ) ); - } - - @Override - public void membershipGranted() - { - insertText( Res.getString( "message.your.membership.granted" ) ); - } - - @Override - public void membershipRevoked() - { - insertText( Res.getString( "message.your.membership.revoked" ) ); - } - - @Override - public void moderatorGranted() - { - insertText( Res.getString( "message.your.moderator.granted" ) ); - } - - @Override - public void moderatorRevoked() - { - insertText( Res.getString( "message.your.moderator.revoked" ) ); - } - - @Override - public void ownershipGranted() - { - insertText( Res.getString( "message.your.ownership.granted" ) ); - } - - @Override - public void ownershipRevoked() - { - insertText( Res.getString( "message.your.ownership.revoked" ) ); - } - - @Override - public void adminGranted() - { - insertText( Res.getString( "message.your.admin.granted" ) ); - } - - @Override - public void adminRevoked() - { - insertText( Res.getString( "message.your.revoked.granted" ) ); - } - } ); - - chat.addSubjectUpdatedListener( ( subject, by ) -> { - subjectPanel.setSubject( subject ); - subjectPanel.setToolTipText( subject ); - final String nickname = XmppStringUtils.parseResource( by ); - final String insertMessage = Res.getString( "message.subject.has.been.changed.to", subject, nickname ); - getTranscriptWindow().insertNotificationMessage( insertMessage, ChatManager.NOTIFICATION_COLOR ); - } ); - } - - /** - * Inserts a notification message within the TranscriptWindow. - * - * @param text the text to insert. - */ - public void insertText( String text ) - { - getTranscriptWindow().insertNotificationMessage( text, ChatManager.NOTIFICATION_COLOR ); - } - - /** - * Returns the user format (e.g. darkcave@macbeth.shakespeare.lit/thirdwitch) of each user in the room. - * - * @return the user format (e.g. darkcave@macbeth.shakespeare.lit/thirdwitch) of each user in the room. - */ - public Collection getParticipants() - { - return currentUserList; - } - - /** - * Sends the message that is currently in the send field. - */ - @Override - public void sendMessage() - { - sendMessage( getChatInputEditor().getText() ); - } - - @Override - public void sendMessage( String text ) - { - // IF there is no body, just return and do nothing - if ( !ModelUtil.hasLength( text ) ) - { - return; - } - - // Set the body of the message using typedMessage and remove control characters - final Message message = new Message(); - message.setBody( text.replaceAll( "[\\u0001-\\u0008\\u000B-\\u001F]", "" ) ); - - sendMessage( message ); - } - - /** - * Returns a MultiUserChat object associated with this room. - * - * @return the MultiUserChat object associated with this room. - */ - public MultiUserChat getMultiUserChat() - { - return chat; - } - - /** - * Adds a user to the blocked user list. Blocked users is NOT a MUC related item, but rather used by the client to - * not display messages from certain people. - * - * @param usersJID the room jid of the user (ex.spark@conference.jivesoftware.com/Dan) - */ - public void addBlockedUser( String usersJID ) - { - blockedUsers.add( usersJID ); - } - - /** - * Removes a user from the blocked user list. - * - * @param usersJID the jid of the user (ex. spark@conference.jivesoftware.com/Dan) - */ - public void removeBlockedUser( String usersJID ) - { - blockedUsers.remove( usersJID ); - } - - /** - * Returns true if the user is in the blocked user list. - * - * @param usersJID the jid of the user (ex. spark@conference.jivesoftware.com/Dan) - * @return true if the user is blocked, otherwise false. - */ - public boolean isBlocked( String usersJID ) - { - return blockedUsers.contains( usersJID ); - } - - /** - * Invite a user to this conference room. - * - * @param jid the jid of the user to invite. - * @param message the message to send with the invitation. - */ - public void inviteUser( String jid, String message ) - { - message = message != null && !message.isEmpty() ? message : Res.getString( "message.please.join.in.conference" ); - - try - { - getMultiUserChat().invite( jid, message ); - roomInfo.addInvitee( jid, message ); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to invite " + jid + " to room " + roomInfo.getName(), e ); - } - } - - /** - * Returns the GroupChatParticipantList which displays all users within a conference room. - * - * @return the GroupChatParticipantList. - */ - public GroupChatParticipantList getConferenceRoomInfo() - { - return roomInfo; - } - - @Override - public long getLastActivity() - { - return lastActivity; - } - - @Override - public void connected( XMPPConnection xmppConnection ) - { - } - - @Override - public void authenticated( XMPPConnection xmppConnection, boolean b ) - { - } - - @Override - public void connectionClosed() - { - handleDisconnect(); - } - - @Override - public void connectionClosedOnError( Exception ex ) - { - handleDisconnect(); - - getTranscriptWindow().showWindowDisabled(); - getSplitPane().setRightComponent( null ); - getTranscriptWindow().insertNotificationMessage( Res.getString( "message.disconnected.group.chat.error" ), ChatManager.ERROR_COLOR ); - } - - /** - * Sets the Password for this GroupChat if available, to rejoin the chat after a reconnection without prompting the user - */ - public void setPassword( String password ) - { - this.password = password; - } - - /** - * Part of ConnectionListener. Gets triggered when successfully reconnected. - */ - @Override - public void reconnectionSuccessful() - { - final String roomJID = chat.getRoom(); - final String roomName = tabTitle; - isActive = false; - EventQueue.invokeLater( () -> { - ConferenceUtils.joinConferenceOnSeperateThread( roomName, roomJID, password ); - closeChatRoom(); - } ); - } - - /** - * Is called whenever Spark was unexpectedly disconnected. - */ - private void handleDisconnect() - { - getChatInputEditor().setEnabled( false ); - getSendButton().setEnabled( false ); - SparkManager.getChatManager().getChatContainer().fireChatRoomStateUpdated( this ); - } - - /** - * Returns the Color to use. Use Color.blue for yourself - */ - public Color getColor( String nickname ) - { - if ( nickname.equals( this.getNickname() ) ) - { - return ChatManager.TO_COLOR; - } - else - { - if ( pref.isMucRandomColors() ) - { - int index = 0; - for ( int i = 0; i < nickname.length(); i++ ) - { - index += nickname.charAt( i ) * i; - } - - return ChatManager.COLORS[ index % ChatManager.COLORS.length ]; - } - else - { - return ChatManager.FROM_COLOR; - } - } - } - - public void notifySettingsAccessRight() - { - if ( SparkManager.getUserManager().isOwner( (GroupChatRoom) getChatRoom(), chat.getNickname() ) ) - { - settings.setVisible( true ); - } - } -} diff --git a/src/java/org/jivesoftware/spark/ui/rooms/SubjectPanel.java b/src/java/org/jivesoftware/spark/ui/rooms/SubjectPanel.java deleted file mode 100644 index 823f28ddb..000000000 --- a/src/java/org/jivesoftware/spark/ui/rooms/SubjectPanel.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.jivesoftware.spark.ui.rooms; - -import javax.swing.*; -import java.awt.*; - -/** - * A UI implementation for display subjects within the conference room. - */ -public class SubjectPanel extends JPanel -{ - private JLabel roomJIDLabel; - private JLabel subjectLabel; - - public SubjectPanel( GroupChatRoom groupChatRoom ) - { - setLayout( new GridBagLayout() ); - - roomJIDLabel = new JLabel( "<" + groupChatRoom.getMultiUserChat().getRoom() + ">" ); - subjectLabel = new JLabel( groupChatRoom.getMultiUserChat().getSubject() ); - - add( roomJIDLabel, - new GridBagConstraints( 1, 0, 1, 1, 1.0, 0.0, - GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets( 2, 2, 0, - 2 ), 0, 0 ) ); - add( subjectLabel, - new GridBagConstraints( 1, 1, 1, 1, 1.0, 0.0, - GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets( 0, 2, 0, - 2 ), 0, 0 ) ); - - setOpaque( false ); - } - - public void setSubject( String subject ) - { - subjectLabel.setText( subject ); - } - - public void setRoomLabel( String label ) - { - roomJIDLabel.setText( label ); - } -} diff --git a/src/java/org/jivesoftware/spark/ui/status/StatusBar.java b/src/java/org/jivesoftware/spark/ui/status/StatusBar.java deleted file mode 100644 index 91347315a..000000000 --- a/src/java/org/jivesoftware/spark/ui/status/StatusBar.java +++ /dev/null @@ -1,704 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.status; - -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Image; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.geom.AffineTransform; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.TimerTask; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.SwingUtilities; -import javax.swing.border.Border; - -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.packet.ExtensionElement; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smackx.vcardtemp.packet.VCard; -import org.jivesoftware.spark.PresenceManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.ui.CommandPanel; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ImageCombiner; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.StringUtils; -import org.jivesoftware.spark.util.SwingTimerTask; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.UIComponentRegistry; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.privacy.PrivacyManager; -import org.jivesoftware.sparkimpl.plugin.privacy.list.SparkPrivacyList; -import org.jivesoftware.sparkimpl.profile.VCardEditor; -import org.jivesoftware.sparkimpl.profile.VCardListener; -import org.jivesoftware.sparkimpl.profile.VCardManager; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -//TODO: I need to remove the presence logic from this class. -public class StatusBar extends JPanel implements VCardListener { - private static final long serialVersionUID = -4322806442034868526L; - - private List statusList = new ArrayList<>(); - - private JLabel imageLabel = new JLabel(); - private JLabel descriptiveLabel = new JLabel(); - private JLabel nicknameLabel = new JLabel(); - private StatusPanel statusPanel = new StatusPanel(); - - private CommandPanel commandPanel ; - private Image backgroundImage; - private Runnable changePresenceRunnable; - - private Presence currentPresence; - - public StatusBar() { - this(true); - } - - public StatusBar(boolean doLayout) { - commandPanel = UIComponentRegistry.createCommandPanel(); - if (doLayout) { - setLayout(new GridBagLayout()); - - backgroundImage = Default.getImageIcon(Default.TOP_BOTTOM_BACKGROUND_IMAGE).getImage(); - - - - ImageIcon brandedImage = Default.getImageIcon(Default.BRANDED_IMAGE); - if (brandedImage != null && brandedImage.getIconWidth() > 1) { - final JLabel brandedLabel = new JLabel(brandedImage); - add(brandedLabel, new GridBagConstraints(3, 0, 1, 3, 1.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - } - - - add(imageLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(2, 8, 2, 2), 0, 0)); - - add(nicknameLabel, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(2, 12, 0, 0), 0, 0)); - add(statusPanel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 7, 0, 0), 0, 0)); - add(commandPanel, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTHWEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 0), 0, 0)); - nicknameLabel.setToolTipText(SparkManager.getConnection().getUser()); - nicknameLabel.setFont(new Font(Font.DIALOG, Font.BOLD, 12)); - setStatus(Res.getString("status.online")); - } - - buildStatusItemList(); - - // SPARK-1521, if we log in as invisible, default status should be "Invisible" - currentPresence = getPresenceOnStart(); - - updatePresence(); - - //setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230), 1)); - - SparkManager.getSessionManager().addPresenceListener( presence -> { - presence.setStatus(StringUtils.modifyWildcards(presence.getStatus())); - changeAvailability(presence); - - // SPARK-1524: - // after reconnected if we had the 'invisible' presence - // we should re-send it - if (PresenceManager.isInvisible(currentPresence)) { - TimerTask task = new SwingTimerTask() { - public void doRun() { - PrivacyManager.getInstance().goToInvisible(); - } - }; - TaskEngine.getInstance().schedule(task, 500); - } - } ); - - // Show profile on double click of image label - imageLabel.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent mouseEvent) { - if (mouseEvent.getClickCount() == 1) { - VCardManager vcardManager = SparkManager.getVCardManager(); - VCardEditor editor = new VCardEditor(); - editor.editProfile(vcardManager.getVCard(), SparkManager.getWorkspace()); - } - } - - public void mouseEntered(MouseEvent e) { - imageLabel.setCursor(GraphicUtils.HAND_CURSOR); - } - - public void mouseExited(MouseEvent e) { - imageLabel.setCursor(GraphicUtils.DEFAULT_CURSOR); - } - }); - - final TimerTask task = new SwingTimerTask() { - public void doRun() { - SparkManager.getVCardManager().addVCardListener(SparkManager.getWorkspace().getStatusBar()); - } - }; - - TaskEngine.getInstance().schedule(task, 3000); - changePresenceRunnable = () -> updatePresence(); - - - } - - public void setAvatar(Icon icon) { - Image image = ImageCombiner.iconToImage(icon); - if (icon.getIconHeight() > 64 || icon.getIconWidth() > 64) { - imageLabel.setIcon(new ImageIcon(image.getScaledInstance(-1, 64, Image.SCALE_SMOOTH))); - } else { - imageLabel.setIcon(icon); - } - imageLabel.setBorder(null); - revalidate(); - } - - public CommandPanel getCommandPanel() - { - return commandPanel; - } - - public void setNickname(String nickname) { - nicknameLabel.setText(nickname); - } - - /** - * Sets the current status text in the Status Manager. - * - * @param status the status to set. - */ - public void setStatus(String status) { - statusPanel.setStatus(status); - } - - protected void updatePresence() { - setStatus(currentPresence.getStatus()); - final Icon icon = PresenceManager.getIconFromPresence(currentPresence); - if (icon != null) { - statusPanel.setIcon(icon); - } - } - - public void showPopup(MouseEvent e) { - final JPopupMenu popup = new JPopupMenu(); - - List custom = CustomMessages.load(); - if (custom == null) { - custom = new ArrayList<>(); - } - - // Sort Custom Messages - Collections.sort( custom, ( a, b ) -> ( a.getStatus().compareToIgnoreCase( b.getStatus() ) ) ); - - // Build menu from StatusList - for (final StatusItem statusItem : statusList) { - final Action statusAction = new AbstractAction() { - private static final long serialVersionUID = -192865863435381702L; - - public void actionPerformed(ActionEvent actionEvent) { - final String text = statusItem.getText(); - final StatusItem si = getStatusItem(text); - if (si == null) { - // Custom status - Log.error("Unable to find status item for status - " + text); - return; - } - - SwingWorker worker = new SwingWorker() { - public Object construct() { - return changePresence(si.getPresence()); - } - - public void finished() { - setStatus((String) getValue()); - } - }; - worker.start(); - } - }; - - statusAction.putValue(Action.NAME, statusItem.getText()); - statusAction.putValue(Action.SMALL_ICON, statusItem.getIcon()); - - // Has Children - boolean hasChildren = false; - for (Object aCustom : custom) { - final CustomStatusItem cItem = (CustomStatusItem) aCustom; - String type = cItem.getType(); - if (type.equals(statusItem.getText())) { - hasChildren = true; - } - } - - if (!hasChildren) { - // Add as Menu Item - popup.add(statusAction); - } - else { - - final JMenu mainStatusItem = new JMenu(statusAction); - - - popup.add(mainStatusItem); - - // Add Custom Messages - for (Object aCustom : custom) { - final CustomStatusItem customItem = (CustomStatusItem) aCustom; - String type = customItem.getType(); - final String customStatus = customItem.getStatus(); - if (type.equals(statusItem.getText())) { - // Add Child Menu - Action action = new AbstractAction() { - private static final long serialVersionUID = -1264239704492879742L; - - public void actionPerformed(ActionEvent actionEvent) { - final String text = mainStatusItem.getText(); - final StatusItem si = getStatusItem(text); - if (si == null) { - // Custom status - Log.error("Unable to find status item for status - " + text); - return; - } - - SwingWorker worker = new SwingWorker() { - public Object construct() { - Presence presence = PresenceManager.copy(si.getPresence()); - presence.setStatus(customStatus); - presence.setPriority(customItem.getPriority()); - return changePresence(presence); - } - - public void finished() { - setStatus((String) getValue()); - } - }; - worker.start(); - } - }; - action.putValue(Action.NAME, customItem.getStatus()); - action.putValue(Action.SMALL_ICON, statusItem.getIcon()); - mainStatusItem.add(action); - } - } - - // If menu has children, allow it to still be clickable. - mainStatusItem.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent mouseEvent) { - statusAction.actionPerformed(null); - popup.setVisible(false); - } - }); - } - } - - - //SPARK-1521. Add privacy menu if Privacy Manager is active and have any visible lists - final PrivacyManager pmanager = PrivacyManager.getInstance(); - if (pmanager.isPrivacyActive() && pmanager.getPrivacyLists().size() > 0) { - - JMenu privMenu = new JMenu(Res.getString("privacy.status.menu.entry")); - privMenu.setIcon(SparkRes.getImageIcon("PRIVACY_ICON_SMALL")); - - for (SparkPrivacyList plist : pmanager.getPrivacyLists()) { - JMenuItem it = new JMenuItem(plist.getListName()); - privMenu.add(it); - if (plist.isActive()) { - it.setIcon(SparkRes.getImageIcon("PRIVACY_LIGHTNING")); - } else { - it.setIcon(null); - } - final SparkPrivacyList finalList = plist; - it.addActionListener( e1 -> PrivacyManager.getInstance().setListAsActive(finalList.getListName()) ); - } - - if (pmanager.hasActiveList()) { - JMenuItem remMenu = new JMenuItem(Res.getString("privacy.menuitem.deactivate.current.list", pmanager.getActiveList().getListName()), - SparkRes.getImageIcon("PRIVACY_DEACTIVATE_LIST")); - remMenu.addActionListener( e1 -> pmanager.declineActiveList() ); - privMenu.addSeparator(); - privMenu.add(remMenu); - } - - popup.add(privMenu); - } - - // Add change message - final JMenuItem changeStatusMenu = new JMenuItem(Res.getString("menuitem.set.status.message"), SparkRes.getImageIcon(SparkRes.BLANK_IMAGE)); - popup.addSeparator(); - - - popup.add(changeStatusMenu); - changeStatusMenu.addActionListener( e1 -> CustomMessages.addCustomMessage() ); - - - Action editMessagesAction = new AbstractAction() { - private static final long serialVersionUID = 7148051050075679995L; - - public void actionPerformed(ActionEvent actionEvent) { - CustomMessages.editCustomMessages(); - } - }; - - editMessagesAction.putValue(Action.NAME, Res.getString("menuitem.edit.status.message")); - popup.add(editMessagesAction); - - final JPanel panel = getStatusPanel(); - popup.show(panel, 0, panel.getHeight()); - } - - protected JPanel getStatusPanel() { - return statusPanel; - } - - public void changeAvailability(final Presence presence) { - // SPARK-1524: if we were reconnected because of the error - // then we get presence with the mode == null. - if (presence.getMode() == null) - return; - - if ((presence.getMode() == currentPresence.getMode()) && (presence.getType() == currentPresence.getType()) && (presence.getStatus().equals(currentPresence.getStatus()))) { - ExtensionElement pe = presence.getExtension("x", "vcard-temp:x:update"); - if (pe != null) { - // Update VCard - loadVCard(); - } - return; - } - currentPresence = presence; - - SwingUtilities.invokeLater(changePresenceRunnable); - } - - /** - * Populates the current Dnd List. - */ - private void buildStatusItemList() { - for (Presence presence : PresenceManager.getPresences()) { - Icon icon = PresenceManager.getIconFromPresence(presence); - StatusItem item = new StatusItem(presence, icon); - statusList.add(item); - } - - final Icon availableIcon = PresenceManager.getIconFromPresence(new Presence(Presence.Type.available)); - - // Set default presence icon (Avaialble) - statusPanel.setIcon(availableIcon); - } - - - public Collection getStatusList() { - return statusList; - } - - public Collection getCustomStatusList() - { - List custom = CustomMessages.load(); - if (custom == null) - custom = new ArrayList<>(); - - // Sort Custom Messages - Collections.sort( custom, ( a, b ) -> ( a.getStatus().compareToIgnoreCase( b.getStatus() ) ) ); - - return custom; - } - - public Presence getPresence() { - return currentPresence; - } - - public StatusItem getStatusItem(String label) { - for (StatusItem aStatusList : statusList) { - if (aStatusList.getText().equals(label)) { - return aStatusList; - } - } - return null; - } - - public void paintComponent(Graphics g) { - super.paintComponent(g); - if (backgroundImage != null) { - double scaleX = getWidth() / (double)backgroundImage.getWidth(null); - double scaleY = getHeight() / (double)backgroundImage.getHeight(null); - AffineTransform xform = AffineTransform.getScaleInstance(scaleX, scaleY); - ((Graphics2D)g).drawImage(backgroundImage, xform, this); - } - } - - - public void loadVCard() { - final Runnable loadVCard = () -> { - VCard vcard = SparkManager.getVCardManager().getVCard(); - updateVCardInformation(vcard); - }; - - TaskEngine.getInstance().submit(loadVCard); - } - - protected void updateVCardInformation(final VCard vCard) { - SwingUtilities.invokeLater( () -> { - if (vCard.getError() == null) { - String firstName = vCard.getFirstName(); - String lastName = vCard.getLastName(); - String nickname = vCard.getNickName(); - if (ModelUtil.hasLength(firstName) && ModelUtil.hasLength(lastName)) { - setNickname(firstName + " " + lastName); - } - else if (ModelUtil.hasLength(firstName)) { - setNickname(firstName); - } - else if (ModelUtil.hasLength(nickname)) { - setNickname(nickname); - } - else { - nickname = SparkManager.getSessionManager().getUsername(); - setNickname(nickname); - } - } - else { - String nickname = SparkManager.getSessionManager().getUsername(); - setNickname(nickname); - return; - } - - - byte[] avatarBytes = null; - try { - avatarBytes = vCard.getAvatar(); - } - catch (Exception e) { - Log.error("Cannot retrieve avatar bytes.", e); - } - - - if (avatarBytes != null && avatarBytes.length > 0) { - try { - ImageIcon avatarIcon = new ImageIcon(avatarBytes); - avatarIcon = VCardManager.scale(avatarIcon); - setAvatar(avatarIcon); - imageLabel.invalidate(); - imageLabel.validate(); - imageLabel.repaint(); - } - catch (Exception e) { - // no issue - } - } - else { - imageLabel.setIcon(null); - imageLabel.setBorder(null); - imageLabel.invalidate(); - imageLabel.validate(); - imageLabel.repaint(); - } - } ); - - } - - public static Presence copyPresence(Presence presence) { - return new Presence(presence.getType(), presence.getStatus(), presence.getPriority(), presence.getMode()); - } - - /** - * Return the nickname Component used to display the users profile name. - * - * @return the label. - */ - public JLabel getNicknameLabel() { - return nicknameLabel; - } - - private class StatusPanel extends JPanel { - private static final long serialVersionUID = -5086334443225239032L; - private JLabel iconLabel; - private JLabel statusLabel; - - public StatusPanel() { - super(); - - setOpaque(false); - - iconLabel = new JLabel(); - statusLabel = new JLabel(); - - setLayout(new GridBagLayout()); - - // Remove padding from icon label - iconLabel.setIconTextGap(0); - - add(iconLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); - add(statusLabel, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 2, 0, 0), 0, 0)); - - statusLabel.setFont(new Font(Font.DIALOG, Font.PLAIN, 11)); - statusLabel.setIcon(SparkRes.getImageIcon(SparkRes.DOWN_ARROW_IMAGE)); - statusLabel.setHorizontalTextPosition(JLabel.LEFT); - - setOpaque(false); - - final Border border = BorderFactory.createEmptyBorder(2, 2, 2, 2); - setBorder(border); - - - statusLabel.addMouseListener(new MouseAdapter() { - public void mouseReleased(MouseEvent e) { - showPopup(e); - } - - public void mouseEntered(MouseEvent e) { - setCursor(GraphicUtils.HAND_CURSOR); - - setBorder(BorderFactory.createBevelBorder(0)); - } - - public void mouseExited(MouseEvent e) { - setCursor(GraphicUtils.DEFAULT_CURSOR); - setBorder(border); - } - - public void mousePressed(MouseEvent e) { - setBorder(BorderFactory.createBevelBorder(1)); - } - }); - - } - - public void setStatus(String status) { - int length = status.length(); - String visualStatus = status; - if (length > 30) { - visualStatus = status.substring(0, 27) + "..."; - } - - statusLabel.setText(visualStatus); - statusLabel.setToolTipText(status); - } - - public void setIcon(Icon icon) { - iconLabel.setIcon(icon); - } - } - - public void setBackgroundImage(Image image) { - this.backgroundImage = image; - } - - public void setDescriptiveText(String text) { - descriptiveLabel.setText(text); - } - - public Dimension getPreferredSize() { - Dimension dim = super.getPreferredSize(); - dim.width = 0; - return dim; - } - - - public void vcardChanged(VCard vcard) { - updateVCardInformation(vcard); - } - - protected Runnable getChangePresenceRunnable() { - return changePresenceRunnable; - } - - protected Presence getCurrentPresence() { - return currentPresence; - } - - private String changePresence(Presence presence) { - // SPARK-1521. Other clients can see "Invisible" status while we are disappearing. - // So we send "Offline" instead of "Invisible" for them. - boolean isNewPresenceInvisible = PresenceManager - .isInvisible(presence); - if (isNewPresenceInvisible && !PrivacyManager.getInstance().isPrivacyActive()) { - JOptionPane.showMessageDialog(null, Res.getString("dialog.invisible.privacy.lists.not.supported")); - } - - Presence copyPresence = copyPresence(presence); - if (isNewPresenceInvisible) { - copyPresence.setStatus(Res.getString("status.offline")); - } - if (PresenceManager.areEqual(getCurrentPresence(), copyPresence)) { - return presence.getStatus(); - } - - // ask user to confirm that all group chat rooms will be closed if - // he/she goes to invisible. - if (isNewPresenceInvisible - && SparkManager.getChatManager().getChatContainer() - .hasGroupChatRooms()) { - int reply = JOptionPane - .showConfirmDialog( - null, - Res.getString("dialog.confirm.close.all.conferences.if.invisible.msg"), - Res.getString("dialog.confirm.to.reveal.visibility.title"), - JOptionPane.YES_NO_OPTION); - if (reply == JOptionPane.NO_OPTION) { - return getCurrentPresence().getStatus(); - } - } - - // If we go visible then we should send "Available" first. - if (!isNewPresenceInvisible - && PresenceManager.isInvisible(getCurrentPresence())) - PrivacyManager.getInstance().goToVisible(); - - // Then set the current status. - SparkManager.getSessionManager().changePresence(copyPresence); - - // If we go invisible we should activate the "globally invisible list" - // and send "Available" after "Unavailable" presence. - if (isNewPresenceInvisible) { - SparkManager.getChatManager().getChatContainer() - .closeAllGroupChatRooms(); - PrivacyManager.getInstance().goToInvisible(); - } - - return presence.getStatus(); - } - - protected Presence getPresenceOnStart() { - return SettingsManager.getLocalPreferences().isLoginAsInvisible() - ? PresenceManager.getUnavailablePresence() - : PresenceManager.getAvailablePresence(); - } - -} diff --git a/src/java/org/jivesoftware/spark/ui/themes/ColorSettingManager.java b/src/java/org/jivesoftware/spark/ui/themes/ColorSettingManager.java deleted file mode 100644 index a7ec433f3..000000000 --- a/src/java/org/jivesoftware/spark/ui/themes/ColorSettingManager.java +++ /dev/null @@ -1,230 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.themes; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Properties; - -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Default; -import org.jivesoftware.spark.util.log.Log; - -public class ColorSettingManager { - - private static HashMap _propertyHashMap = new HashMap<>(); - - public ColorSettingManager() { - - } - - /** - * Returns the ColorSettingagent - * - * @return ColorSettingagent - */ - public static ColorSettings getColorSettings() { - File settings = getSettingsFile(); - ColorSettings _colorsettings = loadSettings( settings ); - return _colorsettings; - } - - public static boolean exists() { - return getSettingsFile().exists(); - } - - /** - * Returns the file or creates it - * - * @return - */ - public static File getSettingsFile() { - File path = new File(Spark.getSparkUserHome()); - if (!path.exists()) { - path.mkdirs(); - } - File f = new File(path, "color.settings"); - if (!f.exists()) - try { - f.createNewFile(); - } catch (IOException e) { - Log.error("Error saving settings.", e); - } - return f; - } - - /** - * Save all settings - */ - public static void saveColorSettings() { - final Properties props = new Properties(); - - for (String key : _propertyHashMap.keySet()) { - String value = _propertyHashMap.get(key); - props.setProperty(key, value); - } - try { - props.store(new FileOutputStream(getSettingsFile()), - "Storing Spark Color Settings"); - } catch (Exception e) { - Log.error("Error saving settings.", e); - } - } - - /** - * load the Settingfile - * - * @param file - * @return - */ - private static ColorSettings loadSettings(File file) { - // load from file - loadSettingsToMap(file); - - if (_propertyHashMap.size() == 0) { - - Properties p = new Properties(); - try { - p.load(new FileInputStream(getSettingsFile())); - initialLoad(p); - loadSettingsToMap(file); - - } catch (FileNotFoundException e) { - Log.error("Error saving settings.", e); - } catch (IOException e) { - Log.error("Error saving settings.", e); - } - - } else if (_propertyHashMap.size() != getDefaultColors().size()) { - compareSettings(_propertyHashMap, getDefaultColors()); - } - - ColorSettings settings = new ColorSettings(_propertyHashMap); - - return settings; - - } - - /** - * Compares two Hashmaps, if defaultmap has keys that are not within mymap - * - * @param mymap - * HashMap < String,String > - * @param defaultmap - * HashMap < String,String > - */ - private static void compareSettings(HashMap mymap, - HashMap defaultmap) { - boolean changesmade = false; - for (String key : defaultmap.keySet()) { - if (mymap.get(key) == null) // key doesnt exist in mymap - { - mymap.put(key, defaultmap.get(key)); - changesmade = true; - } - } - - if (changesmade) { - saveColorSettings(); - } - - } - - /** - * loads all Properties into a HashMap from the File specified - * - * @param file - */ - private static void loadSettingsToMap(File file) { - - Properties props = new Properties(); - try { - - props.load(new FileInputStream(file)); - - Enumeration enume = props.keys(); - while (enume.hasMoreElements()) { - String object = (String) enume.nextElement(); - _propertyHashMap.put(object, props.getProperty(object)); - } - - } catch (FileNotFoundException e) { - Log.error("Error saving settings.", e); - } catch (IOException e) { - Log.error("Error saving settings.", e); - } - - } - - public static HashMap getDefaultColors() { - HashMap hashmap = new HashMap<>(); - - Enumeration enu = Default.getAllKeys(); - while (enu.hasMoreElements()) { - String s = enu.nextElement(); - - if (Default.getString(s).replace(" ", "") - .matches("[0-9]*,[0-9]*,[0-9]*,[0-9]*")) { - - hashmap.put(s, Default.getString(s)); - } - - } - - return hashmap; - } - - /** - * Used to set the Default values - * - * @param props - */ - private static void initialLoad(Properties props) { - - HashMap map = getDefaultColors(); - for (String key : map.keySet()) { - props.setProperty(key, map.get(key)); - - } - - try { - props.store(new FileOutputStream(getSettingsFile()), - "Storing Spark Color Settings"); - } catch (FileNotFoundException e) { - Log.error("Error saving settings.", e); - } catch (IOException e) { - Log.error("Error saving settings.", e); - } - - } - - /** - * Restores the Default Settings - */ - public static void restoreDefault() { - _propertyHashMap = getDefaultColors(); - saveColorSettings(); - } -} diff --git a/src/java/org/jivesoftware/spark/ui/themes/ColorSettings.java b/src/java/org/jivesoftware/spark/ui/themes/ColorSettings.java deleted file mode 100644 index 12e5db4e8..000000000 --- a/src/java/org/jivesoftware/spark/ui/themes/ColorSettings.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.themes; - -import java.awt.Color; -import java.util.HashMap; -import java.util.Set; - -public class ColorSettings { - - private HashMap _hashmap; - - public ColorSettings(HashMap settingmap) { - _hashmap = settingmap; - } - - public void setColorForProperty(String propertyname, Color color) - { - int r = color.getRed(); - int g = color.getGreen(); - int b = color.getBlue(); - int a = color.getAlpha(); - String c = r + "," + g + "," + b + "," + a; - _hashmap.put(propertyname, c ); - - } - - public Color getColorFromProperty(String propertyname) { - - String s = _hashmap.get(propertyname).replaceAll(" ",""); - s = s.replaceAll("[a-zA-Z]",""); - - String[] items = s.split(","); - - Color c = new Color(Integer.parseInt(items[0]), - Integer.parseInt(items[1]), Integer.parseInt(items[2]), - Integer.parseInt(items[3])); - - return c; - - } - - /** - * Returns all the PropertyNames - * @return - */ - public Set getKeys() - { - - return _hashmap.keySet(); - - } -} - - diff --git a/src/java/org/jivesoftware/spark/ui/themes/ThemePanel.java b/src/java/org/jivesoftware/spark/ui/themes/ThemePanel.java deleted file mode 100644 index 1e3a2994e..000000000 --- a/src/java/org/jivesoftware/spark/ui/themes/ThemePanel.java +++ /dev/null @@ -1,738 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.themes; - -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.Frame; -import java.awt.Window; -import java.io.File; -import java.lang.reflect.Method; -import java.util.Properties; -import java.util.Vector; - -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JDialog; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextField; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.UIManager.LookAndFeelInfo; - -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.ui.TranscriptWindow; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.WindowsFileSystemView; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.emoticons.Emoticon; -import org.jivesoftware.sparkimpl.plugin.emoticons.EmoticonManager; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - - -/** - * ThemePanel is used for the setting of TranscriptWindows and Emoticon packs. - */ -public class ThemePanel extends JPanel { - private static final long serialVersionUID = 2943854311454590459L; - - private JComboBox messageStyleBox; - - private JComboBox emoticonBox; - - private JButton addEmoticonButton; - - private JTextField contactListFontField; - private JLabel contactListFontLabel; - - private JTextField chatRoomFontField; - private JLabel chatRoomFontLabel; - - private JCheckBox emoticonCheckBox; - private JFileChooser fc; - - private JCheckBox showAvatarsBox; - private JCheckBox showVCards; - private JLabel avatarSizeLabel; - private JComboBox avatarSizeField; - - private JCheckBox disableGrayingIdleContacts; - - private JLabel _lookandfeelLabel; - private JComboBox _lookandfeel; - private JButton _lookandfeelpreview; - private Vector _lookandfeelname = new Vector<>(); - private JCheckBox _useTabsForTransports; - private JCheckBox _useTabsForConference; - - private JComboBox _showReconnectBox; - - private LocalPreferences pref = SettingsManager.getLocalPreferences(); - - private JScrollPane emoticonscrollpane; - - private JPanel emoticonspanel; - - /** - * Construct UI - */ - public ThemePanel() { - - ThemePanel _themepanel = this; - _themepanel.setLayout(new GridBagLayout()); - - LookAndFeelInfo[] ui = UIManager.getInstalledLookAndFeels(); - - - Vector lafname = new Vector<>(); - - for(int i=0;i { - // Disable button for java.LaF's and for Synthetica - - if (_lookandfeel.getSelectedIndex() < UIManager.getInstalledLookAndFeels().length) { - _lookandfeelpreview.setEnabled(false); - _lookandfeelpreview - .setToolTipText(Res.getString("lookandfeel.tooltip.restart.yes")); - _lookandfeelpreview.revalidate(); - } else { - _lookandfeelpreview.setEnabled(true); - _lookandfeelpreview.setToolTipText(Res.getString("lookandfeel.tooltip.restart.no")); - _lookandfeelpreview.revalidate(); - } - - } ); - - - _lookandfeelpreview.addActionListener( e -> { - - SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - - return 42; - } - - private void setNewLaF() { - try { - UIManager.setLookAndFeel(_lookandfeelname.get(_lookandfeel.getSelectedIndex())); - setJTattooBar(_lookandfeelname.get(_lookandfeel.getSelectedIndex())); - } catch (Exception e) { - //WTF, i dont care - } - } - - private void updateAllComponentsLaF(final Window window) { - for (Window childWindow : window.getOwnedWindows()) { - updateAllComponentsLaF(childWindow); - } - SwingUtilities.updateComponentTreeUI(window); - } - - @Override - public void finished() { - // if the current laf is substance, and the new laf is not, we need to refresh all components, - // but since substance is very stubborn, we must restart. - UIManager.put("OptionPane.yesButtonText", Res.getString("yes")); - UIManager.put("OptionPane.noButtonText", Res.getString("no")); - if (UIManager.getLookAndFeel().getName().toLowerCase().contains("substance") - && !_lookandfeelname.get(_lookandfeel.getSelectedIndex()).toLowerCase().contains("substance")) { // substance is a PITA! - if (JOptionPane.showConfirmDialog(SparkManager.getPreferenceManager().getPreferenceDialog(), Res.getString("message.restart.required"), - Res.getString("title.alert"), JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { - setNewLaF(); - SettingsManager.getLocalPreferences().setLookAndFeel(getLookAndFeel()); - SparkManager.getMainWindow().logout(false); - } - } else { // otherwise we're ok to just refresh all components - setNewLaF(); - for (Frame frame : Frame.getFrames()) { - updateAllComponentsLaF(frame); - } - JFrame.setDefaultLookAndFeelDecorated(true); - JDialog.setDefaultLookAndFeelDecorated(true); - SettingsManager.getLocalPreferences().setLookAndFeel(getLookAndFeel()); - } - } - }; - worker.start(); - } ); - - - _useTabsForTransports = new JCheckBox(""); - _useTabsForConference = new JCheckBox(""); - - - JLabel messageStyleLabel = new JLabel(); - messageStyleBox = new JComboBox(); - - - emoticonspanel = new EmoticonPanel(10); - emoticonscrollpane = new JScrollPane(emoticonspanel); - emoticonscrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); - emoticonscrollpane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); - - - emoticonBox = new JComboBox(); - - emoticonCheckBox = new JCheckBox(); - - JButton addThemeButton = new JButton(); - addEmoticonButton = new JButton(); - - TranscriptWindow emoticonpreviewtranscript = new TranscriptWindow(); - emoticonpreviewtranscript.setForceEmoticons(true); - - showAvatarsBox = new JCheckBox(); - avatarSizeLabel = new JLabel(); - String[] sizeChoices = {"16x16", "24x24", "32x32"}; - avatarSizeField = new JComboBox(sizeChoices); - - contactListFontField = new JTextField(); - contactListFontLabel = new JLabel(); - - chatRoomFontField = new JTextField(); - chatRoomFontLabel = new JLabel(); - - - - String[] r = { Res.getString("checkbox.reconnect.panel.big"), - Res.getString("checkbox.reconnect.panel.small"), - Res.getString("checkbox.reconnect.panel.icon") }; - _showReconnectBox = new JComboBox(r); - - _showReconnectBox.setSelectedIndex(pref.getReconnectPanelType()); - - _showReconnectBox.addActionListener( e -> { - if(_showReconnectBox.getSelectedIndex()!=-1) - setShowReconnectPanel(_showReconnectBox.getSelectedIndex()); - } ); - - - - showVCards = new JCheckBox(); - - disableGrayingIdleContacts = new JCheckBox(Res.getString("checkbox.graying.out")); - - // Set ResourceUtils - ResourceUtils.resLabel(messageStyleLabel, messageStyleBox, Res.getString("label.message.style") + ":"); -// ResourceUtils.resLabel(emoticonsLabel, emoticonBox, Res.getString("label.emoticons") + ":"); - ResourceUtils.resButton(emoticonCheckBox, Res.getString("checkbox.enable.emoticons")); - - ResourceUtils.resButton(addThemeButton, Res.getString("button.add")); - ResourceUtils.resButton(addEmoticonButton, Res.getString("button.add")); - - ResourceUtils.resLabel(contactListFontLabel, contactListFontField, Res.getString("label.contactlist.fontsize")); - ResourceUtils.resLabel(chatRoomFontLabel, chatRoomFontField, Res.getString("label.chatroom.fontsize")); - ResourceUtils.resButton(showAvatarsBox, Res.getString("checkbox.show.avatars.in.contactlist")); - ResourceUtils.resLabel(avatarSizeLabel, avatarSizeField, Res.getString("label.contactlist.avatarsize")); - ResourceUtils.resButton(showVCards, Res.getString("title.appearance.showVCards")); - _useTabsForTransports.setText(Res.getString("checkbox.transport.tab.setting")); - _useTabsForConference.setText(Res.getString("checkbox.conference.tab.setting")); - - // Build UI - buildUI(); - } - - /** - * Builds the UI. - */ - private void buildUI() { - // Add Viewer -// add(new JScrollPane(transcript), new GridBagConstraints(0, 0, 3, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - add(emoticonscrollpane, new GridBagConstraints(0, 1, 3, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - - add(emoticonBox, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - add(addEmoticonButton, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(emoticonCheckBox, new GridBagConstraints(0, 3, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - add(_lookandfeelLabel, new GridBagConstraints(0, 4, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); - add(_lookandfeel, new GridBagConstraints(1, 4, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); - add(_lookandfeelpreview, new GridBagConstraints(2, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - - add(chatRoomFontLabel, new GridBagConstraints(0, 5, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(chatRoomFontField, new GridBagConstraints(1, 5, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); - add(contactListFontLabel, new GridBagConstraints(0, 6, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(contactListFontField, new GridBagConstraints(1, 6, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); - add(showAvatarsBox, new GridBagConstraints(0, 7, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(avatarSizeLabel, new GridBagConstraints(0, 8, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(avatarSizeField, new GridBagConstraints(1, 8, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); - add(showVCards, new GridBagConstraints(0, 9, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); - add(disableGrayingIdleContacts, new GridBagConstraints(0, 10, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); - add(_useTabsForTransports, new GridBagConstraints(0, 11, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); - add(_useTabsForConference, new GridBagConstraints(0, 12, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); - - - JLabel reconnectionlabel = new JLabel(Res.getString("checkbox.reconnet.info")); - add(reconnectionlabel, new GridBagConstraints(0, 13, 1, 1,0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); - add(_showReconnectBox, new GridBagConstraints(1, 13, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); - - - // Activate live one. - - - - _useTabsForTransports.setSelected(pref.getShowTransportTab()); - _useTabsForTransports.addActionListener( e -> SettingsManager.getLocalPreferences().setShowTransportTab(_useTabsForTransports.isSelected()) ); - _useTabsForConference.setSelected(pref.isShowConferenceTab()); - _useTabsForConference.addActionListener( e -> SettingsManager.getLocalPreferences().setShowConferenceTab( - _useTabsForConference.isSelected()) ); - - _useTabsForConference.setSelected(pref.isShowConferenceTab()); - _useTabsForConference.addActionListener( e -> SettingsManager.getLocalPreferences().setShowConferenceTab(_useTabsForConference.isSelected()) ); - - final EmoticonManager emoticonManager = EmoticonManager.getInstance(); - if (emoticonManager.getEmoticonPacks() != null) - { - for (String pack : emoticonManager.getEmoticonPacks()) { - emoticonBox.addItem(pack); - } - } - - final String activePack = pref.getEmoticonPack(); - emoticonBox.setSelectedItem(activePack); - - emoticonBox.addActionListener( e -> { - emoticonManager.addEmoticonPack((String)emoticonBox.getSelectedItem()); - emoticonManager.setActivePack((String)emoticonBox.getSelectedItem()); - showSelectedEmoticon(); - } ); - - addEmoticonButton.addActionListener( e -> addEmoticonPack() ); - - showSelectedEmoticon(); - - emoticonCheckBox.setSelected(pref.areEmoticonsEnabled()); - - _lookandfeel.setSelectedIndex(_lookandfeelname.indexOf(pref.getLookAndFeel())); - - showVCards.setSelected(pref.areVCardsVisible()); - - showAvatarsBox.setSelected(pref.areAvatarsVisible()); - - disableGrayingIdleContacts.setSelected(pref.isGrayingOutEnabled()); - - - if (pref.getContactListIconSize() == 16) { - avatarSizeField.setSelectedIndex(0); - } - else if (pref.getContactListIconSize() == 24) { - avatarSizeField.setSelectedIndex(1); - } - else if (pref.getContactListIconSize() == 32) { - avatarSizeField.setSelectedIndex(2); - } - else { - avatarSizeField.setSelectedIndex(1); - } - - try { - int chatRoomFontSize = pref.getChatRoomFontSize(); - int contactListFontSize = pref.getContactListFontSize(); - - chatRoomFontField.setText(Integer.toString(chatRoomFontSize)); - contactListFontField.setText(Integer.toString(contactListFontSize)); - } - catch (Exception e) { - Log.error(e); - } - } - - /** - * Displays the active emoticon pack. - */ - protected void showSelectedEmoticon() { - EmoticonManager emoticonManager = EmoticonManager.getInstance(); - - int i = emoticonManager.getActiveEmoticonSet().size(); - if (i==0) - { - emoticonspanel = new EmoticonPanel(1); - JLabel label = new JLabel(SparkRes.getImageIcon(SparkRes.SMALL_DELETE)); - emoticonspanel.add(label); - } - else if (i < 25) { - emoticonspanel = new EmoticonPanel(i); - } else { - emoticonspanel = new EmoticonPanel(10); - } - for(Emoticon emoticon : emoticonManager.getActiveEmoticonSet()) - { - ImageIcon ico = new ImageIcon(emoticonManager.getEmoticonURL(emoticon)); - JLabel label = new JLabel(ico); - emoticonspanel.add(label); - } - - int rows= Math.min(((EmoticonPanel)emoticonspanel).getNumRows()*45, 300); - emoticonscrollpane.setPreferredSize(new Dimension(300,rows)); - emoticonscrollpane.setViewportView(emoticonspanel); - this.revalidate(); - } - - /** - * Returns the name of the theme selected. - * - * @return the name of the selected theme. - */ - public String getSelectedTheme() { - return (String)messageStyleBox.getSelectedItem(); - } - - /** - * Returns the name of the selected emoticon pack. - * - * @return the name of the emoticon pack. - */ - public String getSelectedEmoticonPack() { - return (String)emoticonBox.getSelectedItem(); - } - - public void setEmoticonsEnabled(boolean enabled) { - emoticonCheckBox.setSelected(enabled); - } - - public boolean areEmoticonsEnabled() { - return emoticonCheckBox.isSelected(); - } - - public boolean isGrayingOutEnabled() { - return disableGrayingIdleContacts.isSelected(); - } - - - /** - * Adds a new Emoticon pack to Spark. - */ - private void addEmoticonPack() { - if (fc == null) { - fc = new JFileChooser(); - if (Spark.isWindows()) { - fc.setFileSystemView(new WindowsFileSystemView()); - } - } - fc.setDialogTitle("Add Emoticon Pack"); - - fc.addChoosableFileFilter(new ZipFilter()); - - int returnVal = fc.showOpenDialog(this); - - if (returnVal == JFileChooser.APPROVE_OPTION) { - File pack = fc.getSelectedFile(); - try { - EmoticonManager emoticonManager = EmoticonManager.getInstance(); - String name = emoticonManager.installPack(pack); - - if (name == null) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(this, "Not a valid emoticon pack.", "Error", JOptionPane.ERROR_MESSAGE); - return; - } - - // If the name does not exists, add it to the message box. - for (int i = 0; i < emoticonBox.getItemCount(); i++) { - String n = (String)emoticonBox.getItemAt(i); - if (name.equals(n)) { - return; - } - } - - emoticonBox.addItem(name); - - // Set Selected - emoticonBox.setSelectedItem(name); - } - catch (Exception e) { - Log.error(e); - } - } - } - - /** - * The ZipFilter class is used by the emoticon file picker to filter out all - * other files besides *.zip files. - */ - private class ZipFilter extends javax.swing.filechooser.FileFilter { - public boolean accept(File file) { - String filename = file.getName(); - if (file.isDirectory()) { - return true; - } - return filename.endsWith(".zip"); - } - - public String getDescription() { - return "*.zip"; - } - } - - public String getChatRoomFontSize(){ - return chatRoomFontField.getText(); - } - - public String getContactListFontSize(){ - return contactListFontField.getText(); - } - - public int getContactListIconSize(){ - if (avatarSizeField.getSelectedIndex() == 0) { - return 16; - } - else if (avatarSizeField.getSelectedIndex() == 1) { - return 24; - } - else if (avatarSizeField.getSelectedIndex() == 2) { - return 32; - } - else { - return 24; - } - } - - public boolean areAvatarsVisible(){ - return showAvatarsBox.isSelected(); - } - - public boolean areVCardsVisible(){ - return showVCards.isSelected(); - } - - /** - * Returns the LookAndFeel with package origin
        - * for example: - * com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel - * - * @return {@link String} - */ - public String getLookAndFeel() { - return _lookandfeelname.get(_lookandfeel.getSelectedIndex()); - } - - /** - * Return 0,1,2 - * - * @return - */ - public int getReconnectPanelType() { - return _showReconnectBox.getSelectedIndex(); - } - - /** - * set 0,1,2 - * - * @param reconnect - */ - public void setShowReconnectPanel(int reconnect) { - _showReconnectBox.setSelectedIndex(reconnect); - } - - /** - * Tries to set the Menubar String for JTatto LaFs, doesnt work on Substance - * @param s, the class of the LookandFeel - */ - private void setJTattooBar(String classname) { - - if (classname.contains("jtattoo")) { - try { - Properties props = new Properties(); - - String menubar = Default.getString(Default.MENUBAR_TEXT) == null ? "" - : Default.getString(Default.MENUBAR_TEXT); - - props.put("logoString", menubar); - - Class c = ClassLoader.getSystemClassLoader().loadClass(classname); - Method m = c.getMethod("setCurrentTheme", Properties.class); - - m.invoke(c.newInstance(), props); - } catch (Exception e) { - Log.error("Error Setting JTattoo ", e); - } - } - } - - protected JLabel getLookandfeelLabel() { - return _lookandfeelLabel; - } - - protected JComboBox getLookandfeel() { - return _lookandfeel; - } - - protected JButton getLookandfeelpreview() { - return _lookandfeelpreview; - } - - protected JCheckBox getUseTabsForConference() { - return _useTabsForConference; - } - - protected JCheckBox getShowAvatarsBox() { - return showAvatarsBox; - } - - protected JLabel getAvatarSizeLabel() { - return avatarSizeLabel; - } - - protected JComboBox getAvatarSizeField() { - return avatarSizeField; - } - - - - - -} - -// Maybe Sometime well get a Synthetica License -//"de.javasoft.plaf.synthetica.SyntheticaStandardLookAndFeel", //commec -//"de.javasoft.plaf.synthetica.SyntheticaBlackEyeLookAndFeel", //commerc -//"de.javasoft.plaf.synthetica.SyntheticaBlackMoonLookAndFeel", //free -//"de.javasoft.plaf.synthetica.SyntheticaBlackStarLookAndFeel", //free -//"de.javasoft.plaf.synthetica.SyntheticaBlueIceLookAndFeel", //free -//"de.javasoft.plaf.synthetica.SyntheticaBlueMoonLookAndFeel", //free -//"de.javasoft.plaf.synthetica.SyntheticaBlueSteelLookAndFeel", //free -//"de.javasoft.plaf.synthetica.SyntheticaClassyLookAndFeel", //commerc -//"de.javasoft.plaf.synthetica.SyntheticaGreenDreamLookAndFeel", //free -//"de.javasoft.plaf.synthetica.SyntheticaOrangeMetallicLookAndFeel", //commerc -//"de.javasoft.plaf.synthetica.SyntheticaSilverMoonLookAndFeel", //free -//"de.javasoft.plaf.synthetica.SyntheticaSimple2DLookAndFeel", //commerc -//"de.javasoft.plaf.synthetica.SyntheticaSkyMetallicLookAndFeel", //commerc -//"de.javasoft.plaf.synthetica.SyntheticaWhiteVisionLookAndFeel", //commerc diff --git a/src/java/org/jivesoftware/spark/ui/themes/ThemePreference.java b/src/java/org/jivesoftware/spark/ui/themes/ThemePreference.java deleted file mode 100644 index 7fe1f36e0..000000000 --- a/src/java/org/jivesoftware/spark/ui/themes/ThemePreference.java +++ /dev/null @@ -1,143 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.ui.themes; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.resource.Res; -import org.jivesoftware.spark.preference.Preference; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -import javax.swing.Icon; -import javax.swing.JComponent; - -/** - * - */ -public class ThemePreference implements Preference { - - private MainThemePanel panel; - - public static String NAMESPACE = "themes"; - - public ThemePreference() { - - } - - - public String getTitle() { - return Res.getString("title.appearance.preferences"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.PALETTE_24x24_IMAGE); - } - - public String getTooltip() { - return Res.getString("tooltip.appearance"); - } - - public String getListName() { - return Res.getString("title.appearance"); - } - - public String getNamespace() { - return NAMESPACE; - } - - public JComponent getGUI() { - panel = new MainThemePanel(); - return panel; - } - - /** - * Returns the LookAndFeel with package origin
        - * for example: - * com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel - * - * @return {@link String} - */ - public String getLookAndFeel() - { - return panel.getThemePanel().getLookAndFeel(); - } - - public void loadFromFile() { - - } - - public void load() { - - } - - public boolean isDataValid() { - return true; - } - - public String getErrorMessage() { - return null; - } - - public Object getData() { - return null; - } - - public void commit() { - final String pack = panel.getThemePanel().getSelectedEmoticonPack(); - boolean emotEnabled = panel.getThemePanel().areEmoticonsEnabled(); - boolean grayingOutEnabled = panel.getThemePanel().isGrayingOutEnabled(); - LocalPreferences pref = SettingsManager.getLocalPreferences(); - if(pack != null){ - pref.setEmoticonPack(pack); - } - pref.setEmoticonsEnabled(emotEnabled); - pref.setLookAndFeel(panel.getThemePanel().getLookAndFeel()); - pref.setAvatarVisible(panel.getThemePanel().areAvatarsVisible()); - pref.setContactListIconSize(panel.getThemePanel().getContactListIconSize()); - pref.setVCardsVisible(panel.getThemePanel().areVCardsVisible()); - pref.setGrayingOutEnabled(grayingOutEnabled); - pref.setReconnectPanelType(panel.getThemePanel().getReconnectPanelType()); - - try { - String chatRoomFontSize = panel.getThemePanel().getChatRoomFontSize(); - String contactListFontSize = panel.getThemePanel().getContactListFontSize(); - - pref.setChatRoomFontSize(Integer.parseInt(chatRoomFontSize)); - pref.setContactListFontSize(Integer.parseInt(contactListFontSize)); - } - catch (NumberFormatException e) { - Log.error(e); - } - - - ColorSettingManager.saveColorSettings(); - SettingsManager.saveSettings(); - } - - - public void shutdown() { - - } - - -} - - diff --git a/src/java/org/jivesoftware/spark/uri/UriManager.java b/src/java/org/jivesoftware/spark/uri/UriManager.java deleted file mode 100644 index c276b3fba..000000000 --- a/src/java/org/jivesoftware/spark/uri/UriManager.java +++ /dev/null @@ -1,243 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.uri; - -import java.net.URI; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.roster.Roster; -import org.jivesoftware.smack.roster.RosterEntry; -import org.jivesoftware.smack.roster.RosterGroup; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.UserManager; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.conferences.ConferenceUtils; - -/** - * Class to handle URI-Mappings defined by
        - * - * XEP-0147: XMPP URI Scheme - * Query Components - * - * @author wolf.posdorfer - * - */ -public class UriManager { - - public enum uritypes { - message("message"), - join("join"), - unsubscribe("unsubscribe"), - subscribe("subscribe"), - roster("roster"), - remove("remove"); - - private String _xml; - - private uritypes(String s) { - _xml = s; - } - public String getXML() { - return _xml; - } - } - - /** - * handles the ?message URI - * - * @param uri - * the decoded uri - */ - public void handleMessage(URI uri) { - - String query = uri.getQuery(); - int bodyIndex = query.indexOf("body="); - - String jid = retrieveJID(uri); - String body = null; - - // Find body - if (bodyIndex != -1) { - body = query.substring(bodyIndex + 5); - } - - body = org.jivesoftware.spark.util.StringUtils.unescapeFromXML(body); - - UserManager userManager = SparkManager.getUserManager(); - String nickname = userManager.getUserNicknameFromJID(jid); - if (nickname == null) { - nickname = jid; - } - - ChatManager chatManager = SparkManager.getChatManager(); - ChatRoom chatRoom = chatManager.createChatRoom(jid, nickname, nickname); - if (body != null) { - Message message = new Message(); - message.setBody(body); - chatRoom.sendMessage(message); - } - - chatManager.getChatContainer().activateChatRoom(chatRoom); - } - - /** - * Handles the ?join URI - * - * @param uri - * the decoded uri - * @throws Exception - * thrown if the conference cannot be joined. - */ - public void handleConference(URI uri) throws Exception { - String jid = retrieveJID(uri); - ConferenceUtils.joinConferenceOnSeperateThread(jid, jid, null); - } - - /** - * Handles the ?subscribe URI - * - * @param uri - * the decoded uri - * @throws Exception - */ - public void handleSubscribe(URI uri) throws Exception { - // xmpp:romeo@montague.net?subscribe - // Send contact add request - String jid = retrieveJID(uri); - - Presence response = new Presence(Presence.Type.subscribe); - response.setTo(jid); - SparkManager.getConnection().sendStanza(response); - } - - /** - * Handles the ?unsubscribe URI - * - * @param uri - * the decoded uri - */ - public void handleUnsubscribe(URI uri) throws SmackException.NotConnectedException - { - String jid = retrieveJID(uri); - - Presence response = new Presence(Presence.Type.unsubscribe); - response.setTo(jid); - SparkManager.getConnection().sendStanza(response); - } - - /*** - * Handles the ?roster URI
        - * with name= and group= - * - * @param uri - * the decoded uri - * @throws Exception - */ - public void handleRoster(URI uri) throws Exception { - // xmpp:romeo@montague.net?roster - // xmpp:romeo@montague.net?roster;name=Romeo%20Montague - // xmpp:romeo@montague.net?roster;group=Friends - // xmpp:romeo@montague.net?roster;name=Romeo%20Montague;group=Friends - String jid = retrieveJID(uri); - - String name = ""; - String query = uri.getQuery(); - if (query.contains("name=")) { - StringBuilder buf = new StringBuilder(); - int x = query.indexOf("name=") + 5; - while (x < query.length() && query.charAt(x) != ';') { - buf.append(query.charAt(x)); - x++; - } - } - String group = ""; - if (query.contains("group=")) { - StringBuilder buf = new StringBuilder(); - int x = query.indexOf("group=") + 6; - while (x < query.length() && query.charAt(x) != ';') { - buf.append(query.charAt(x)); - x++; - } - } - - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - RosterEntry userEntry = roster.getEntry(jid); - - roster.createEntry(jid, name, new String[] { group }); - - RosterGroup rosterGroup = roster.getGroup(group); - if (rosterGroup == null) { - rosterGroup = roster.createGroup(group); - } - - if (userEntry == null) { - roster.createEntry(jid, name, new String[] { group }); - userEntry = roster.getEntry(jid); - } else { - userEntry.setName(name); - rosterGroup.addEntry(userEntry); - } - - userEntry = roster.getEntry(jid); - - } - - /** - * Handles the ?remove URI - * - * @param uri - * the decoded uri - * @throws Exception - */ - public void handleRemove(URI uri) throws Exception { - // xmpp:romeo@montague.net?remove - - String jid = retrieveJID(uri); - Roster roster = Roster.getInstanceFor( SparkManager.getConnection() ); - RosterEntry entry = roster.getEntry(jid); - roster.removeEntry(entry); - } - - /** - * Gets JID from URI. Returns the full jid including resource - * - * @param uri - * the URI - * @return romeo@montague.net - */ - public String retrieveJID(URI uri) { - StringBuilder sb = new StringBuilder(32); - String user = uri.getUserInfo(); - if (user != null) { - sb.append(user); - sb.append('@'); - } - sb.append(uri.getHost()); - // Resource contains the leading / - String resource = uri.getPath(); - if (resource != null && resource.length() > 0 && !resource.equals("/")) { - sb.append(resource); - } - return sb.toString(); - } -} diff --git a/src/java/org/jivesoftware/spark/util/Base64.java b/src/java/org/jivesoftware/spark/util/Base64.java deleted file mode 100644 index 7fc09412d..000000000 --- a/src/java/org/jivesoftware/spark/util/Base64.java +++ /dev/null @@ -1,1216 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.util; - -import org.jivesoftware.spark.util.log.Log; - -/** - * Used to encrypt and decrypt bytes -- string using Base64 encoding and decoding. - */ -public class Base64 { - -/* ******** P U B L I C F I E L D S ******** */ - - - /** - * No options specified. Value is zero. - */ - public final static int NO_OPTIONS = 0; - - /** - * Specify encoding. - */ - public final static int ENCODE = 1; - - - /** - * Specify decoding. - */ - public final static int DECODE = 0; - - - /** - * Specify that data should be gzip-compressed. - */ - public final static int GZIP = 2; - - - /** - * Don't break lines when encoding (violates strict Base64 specification) - */ - public final static int DONT_BREAK_LINES = 8; - -/* ******** P R I V A T E F I E L D S ******** */ - - - /** - * Maximum line length (76) of Base64 output. - */ - private final static int MAX_LINE_LENGTH = 76; - - - /** - * The equals sign (=) as a byte. - */ - private final static byte EQUALS_SIGN = (byte)'='; - - - /** - * The new line character (\n) as a byte. - */ - private final static byte NEW_LINE = (byte)'\n'; - - - /** - * Preferred encoding. - */ - private final static String PREFERRED_ENCODING = "UTF-8"; - - - /** - * The 64 valid Base64 values. - */ - private final static byte[] ALPHABET; - private final static byte[] _NATIVE_ALPHABET = /* May be something funny like EBCDIC */ - { - (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', - (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', - (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', - (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', - (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', - (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', - (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', - (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', - (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', - (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/' - }; - - /** Determine which ALPHABET to use. */ - static { - byte[] __bytes; - try { - __bytes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(PREFERRED_ENCODING); - } // end try - catch (java.io.UnsupportedEncodingException use) { - __bytes = _NATIVE_ALPHABET; // Fall back to native encoding - } // end catch - ALPHABET = __bytes; - } // end static - - - /** - * Translates a Base64 value to either its 6-bit reconstruction value - * or a negative number indicating some other meaning. - */ - private final static byte[] DECODABET = - { - -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 - -5, -5, // Whitespace: Tab and Linefeed - -9, -9, // Decimal 11 - 12 - -5, // Whitespace: Carriage Return - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 - -9, -9, -9, -9, -9, // Decimal 27 - 31 - -5, // Whitespace: Space - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42 - 62, // Plus sign at decimal 43 - -9, -9, -9, // Decimal 44 - 46 - 63, // Slash at decimal 47 - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine - -9, -9, -9, // Decimal 58 - 60 - -1, // Equals sign at decimal 61 - -9, -9, -9, // Decimal 62 - 64 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N' - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z' - -9, -9, -9, -9, -9, -9, // Decimal 91 - 96 - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm' - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z' - -9, -9, -9, -9 // Decimal 123 - 126 - /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ - }; - - private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding - private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding - - - /** - * Defeats instantiation. - */ - private Base64() { - } - -/* ******** E N C O D I N G M E T H O D S ******** */ - - /** - * Encodes up to the first three bytes of array threeBytes - * and returns a four-byte array in Base64 notation. - * The actual number of significant bytes in your array is - * given by numSigBytes. - * The array threeBytes needs only be as big as - * numSigBytes. - * Code can reuse a byte array by passing a four-byte array as b4. - * - * @param b4 A reusable byte array to reduce array instantiation - * @param threeBytes the array to convert - * @param numSigBytes the number of significant bytes in your array - * @return four byte array in Base64 notation. - * @since 1.5.1 - */ - private static byte[] encode3to4(byte[] b4, byte[] threeBytes, int numSigBytes) { - encode3to4(threeBytes, 0, numSigBytes, b4, 0); - return b4; - } // end encode3to4 - - - /** - * Encodes up to three bytes of the array source - * and writes the resulting four Base64 bytes to destination. - * The source and destination arrays can be manipulated - * anywhere along their length by specifying - * srcOffset and destOffset. - * This method does not check to make sure your arrays - * are large enough to accomodate srcOffset + 3 for - * the source array or destOffset + 4 for - * the destination array. - * The actual number of significant bytes in your array is - * given by numSigBytes. - * - * @param source the array to convert - * @param srcOffset the index where conversion begins - * @param numSigBytes the number of significant bytes in your array - * @param destination the array to hold the conversion - * @param destOffset the index where output will be put - * @return the destination array - * @since 1.3 - */ - private static byte[] encode3to4(byte[] source, int srcOffset, int numSigBytes, - byte[] destination, int destOffset) { - // 1 2 3 - // 01234567890123456789012345678901 Bit position - // --------000000001111111122222222 Array position from threeBytes - // --------| || || || | Six bit groups to index ALPHABET - // >>18 >>12 >> 6 >> 0 Right shift necessary - // 0x3f 0x3f 0x3f Additional AND - - // Create buffer with zero-padding if there are only one or two - // significant bytes passed in the array. - // We have to shift left 24 in order to flush out the 1's that appear - // when Java treats a value as negative that is cast from a byte to an int. - int inBuff = (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0) - | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0) - | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0); - - switch (numSigBytes) { - case 3: - destination[destOffset] = ALPHABET[(inBuff >>> 18)]; - destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; - destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f]; - destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f]; - return destination; - - case 2: - destination[destOffset] = ALPHABET[(inBuff >>> 18)]; - destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; - destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f]; - destination[destOffset + 3] = EQUALS_SIGN; - return destination; - - case 1: - destination[destOffset] = ALPHABET[(inBuff >>> 18)]; - destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; - destination[destOffset + 2] = EQUALS_SIGN; - destination[destOffset + 3] = EQUALS_SIGN; - return destination; - - default: - return destination; - } // end switch - } // end encode3to4 - - - /** - * Serializes an object and returns the Base64-encoded - * version of that serialized object. If the object - * cannot be serialized or there is another error, - * the method will return null. - * The object is not GZip-compressed before being encoded. - * - * @param serializableObject The object to encode - * @return The Base64-encoded object - * @since 1.4 - */ - public static String encodeObject(java.io.Serializable serializableObject) { - return encodeObject(serializableObject, NO_OPTIONS); - } // end encodeObject - - - /** - * Serializes an object and returns the Base64-encoded - * version of that serialized object. If the object - * cannot be serialized or there is another error, - * the method will return null. - *

        - * Valid options:

        -     *   GZIP: gzip-compresses object before encoding it.
        -     *   DONT_BREAK_LINES: don't break lines at 76 characters
        -     *     Note: Technically, this makes your encoding non-compliant.
        -     * 
        - *

        - * Example: encodeObject( myObj, Base64.GZIP ) or - *

        - * Example: encodeObject( myObj, Base64.GZIP | Base64.DONT_BREAK_LINES ) - * - * @param serializableObject The object to encode - * @param options Options to encoding. - * @return The Base64-encoded object - * @see Base64#GZIP - * @see Base64#DONT_BREAK_LINES - * @since 2.0 - */ - public static String encodeObject(java.io.Serializable serializableObject, int options) { - // Streams - java.io.ByteArrayOutputStream baos = null; - java.io.OutputStream b64os = null; - java.io.ObjectOutputStream oos = null; - java.util.zip.GZIPOutputStream gzos = null; - - // Isolate options - int gzip = (options & GZIP); - int dontBreakLines = (options & DONT_BREAK_LINES); - - try { - // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream - baos = new java.io.ByteArrayOutputStream(); - b64os = new Base64.OutputStream(baos, ENCODE | dontBreakLines); - - // GZip? - if (gzip == GZIP) { - gzos = new java.util.zip.GZIPOutputStream(b64os); - oos = new java.io.ObjectOutputStream(gzos); - } // end if: gzip - else - oos = new java.io.ObjectOutputStream(b64os); - - oos.writeObject(serializableObject); - } // end try - catch (java.io.IOException e) { - Log.error(e); - return null; - } // end catch - finally { - try { - oos.close(); - } - catch (Exception e) { - // Nothing to do - } - try { - gzos.close(); - } - catch (Exception e) { - // Nothing to do - } - try { - b64os.close(); - } - catch (Exception e) { - // Nothing to do - } - try { - baos.close(); - } - catch (Exception e) { - // Nothing to do - } - } // end finally - - // Return value according to relevant encoding. - try { - return new String(baos.toByteArray(), PREFERRED_ENCODING); - } // end try - catch (java.io.UnsupportedEncodingException uue) { - return new String(baos.toByteArray()); - } // end catch - - } // end encode - - - /** - * Encodes a byte array into Base64 notation. - * Does not GZip-compress data. - * - * @param source The data to convert - * @since 1.4 - * @return Encoded string. - */ - public static String encodeBytes(byte[] source) { - return encodeBytes(source, 0, source.length, NO_OPTIONS); - } // end encodeBytes - - - /** - * Encodes a byte array into Base64 notation. - *

        - * Valid options:

        -     *   GZIP: gzip-compresses object before encoding it.
        -     *   DONT_BREAK_LINES: don't break lines at 76 characters
        -     *     Note: Technically, this makes your encoding non-compliant.
        -     * 
        - *

        - * Example: encodeBytes( myData, Base64.GZIP ) or - *

        - * Example: encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES ) - * - * @param source The data to convert - * @param options Specified options - * @see Base64#GZIP - * @see Base64#DONT_BREAK_LINES - * @since 2.0 - * @return Encoded string. - */ - public static String encodeBytes(byte[] source, int options) { - return encodeBytes(source, 0, source.length, options); - } // end encodeBytes - - - /** - * Encodes a byte array into Base64 notation. - * Does not GZip-compress data. - * - * @param source The data to convert - * @param off Offset in array where conversion should begin - * @param len Length of data to convert - * @since 1.4 - * @return Encoded string. - */ - public static String encodeBytes(byte[] source, int off, int len) { - return encodeBytes(source, off, len, NO_OPTIONS); - } // end encodeBytes - - - /** - * Encodes a byte array into Base64 notation. - *

        - * Valid options:

        -     *   GZIP: gzip-compresses object before encoding it.
        -     *   DONT_BREAK_LINES: don't break lines at 76 characters
        -     *     Note: Technically, this makes your encoding non-compliant.
        -     * 
        - *

        - * Example: encodeBytes( myData, Base64.GZIP ) or - *

        - * Example: encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES ) - * - * @param source The data to convert - * @param off Offset in array where conversion should begin - * @param len Length of data to convert - * @param options Specified options - * @see Base64#GZIP - * @see Base64#DONT_BREAK_LINES - * @since 2.0 - * @return String that was encoded. - */ - public static String encodeBytes(byte[] source, int off, int len, int options) { - // Isolate options - int dontBreakLines = (options & DONT_BREAK_LINES); - int gzip = (options & GZIP); - - // Compress? - if (gzip == GZIP) { - java.io.ByteArrayOutputStream baos = null; - java.util.zip.GZIPOutputStream gzos = null; - Base64.OutputStream b64os = null; - - - try { - // GZip -> Base64 -> ByteArray - baos = new java.io.ByteArrayOutputStream(); - b64os = new Base64.OutputStream(baos, ENCODE | dontBreakLines); - gzos = new java.util.zip.GZIPOutputStream(b64os); - - gzos.write(source, off, len); - gzos.close(); - } // end try - catch (java.io.IOException e) { - Log.error(e); - return null; - } // end catch - finally { - try { - gzos.close(); - } - catch (Exception e) { - // Nothing to do - } - try { - b64os.close(); - } - catch (Exception e) { - // Nothing to do - } - try { - baos.close(); - } - catch (Exception e) { - // Nothing to do - } - } // end finally - - // Return value according to relevant encoding. - try { - return new String(baos.toByteArray(), PREFERRED_ENCODING); - } // end try - catch (java.io.UnsupportedEncodingException uue) { - return new String(baos.toByteArray()); - } // end catch - } // end if: compress - - // Else, don't compress. Better not to use streams at all then. - else { - // Convert option to boolean in way that code likes it. - boolean breakLines = dontBreakLines == 0; - - int len43 = len * 4 / 3; - byte[] outBuff = new byte[(len43) // Main 4:3 - + ((len % 3) > 0 ? 4 : 0) // Account for padding - + (breakLines ? (len43 / MAX_LINE_LENGTH) : 0)]; // New lines - int d = 0; - int e = 0; - int len2 = len - 2; - int lineLength = 0; - for (; d < len2; d += 3, e += 4) { - encode3to4(source, d + off, 3, outBuff, e); - - lineLength += 4; - if (breakLines && lineLength == MAX_LINE_LENGTH) { - outBuff[e + 4] = NEW_LINE; - e++; - lineLength = 0; - } // end if: end of line - } // en dfor: each piece of array - - if (d < len) { - encode3to4(source, d + off, len - d, outBuff, e); - e += 4; - } // end if: some padding needed - - // Return value according to relevant encoding. - try { - return new String(outBuff, 0, e, PREFERRED_ENCODING); - } // end try - catch (java.io.UnsupportedEncodingException uue) { - return new String(outBuff, 0, e); - } // end catch - - } // end else: don't compress - - } // end encodeBytes - -/* ******** D E C O D I N G M E T H O D S ******** */ - - - /** - * Decodes four bytes from array source - * and writes the resulting bytes (up to three of them) - * to destination. - * The source and destination arrays can be manipulated - * anywhere along their length by specifying - * srcOffset and destOffset. - * This method does not check to make sure your arrays - * are large enough to accomodate srcOffset + 4 for - * the source array or destOffset + 3 for - * the destination array. - * This method returns the actual number of bytes that - * were converted from the Base64 encoding. - * - * @param source the array to convert - * @param srcOffset the index where conversion begins - * @param destination the array to hold the conversion - * @param destOffset the index where output will be put - * @return the number of decoded bytes converted - * @since 1.3 - */ - private static int decode4to3(byte[] source, int srcOffset, byte[] destination, int destOffset) { - // Example: Dk== - if (source[srcOffset + 2] == EQUALS_SIGN) { - // Two ways to do the same thing. Don't know which way I like best. - //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) - // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 ); - int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) - | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12); - - destination[destOffset] = (byte)(outBuff >>> 16); - return 1; - } - - // Example: DkL= - else if (source[srcOffset + 3] == EQUALS_SIGN) { - // Two ways to do the same thing. Don't know which way I like best. - //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) - // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) - // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ); - int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) - | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12) - | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6); - - destination[destOffset] = (byte)(outBuff >>> 16); - destination[destOffset + 1] = (byte)(outBuff >>> 8); - return 2; - } - - // Example: DkLE - else { - try { - // Two ways to do the same thing. Don't know which way I like best. - //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) - // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) - // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ) - // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 ); - int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) - | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12) - | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6) - | ((DECODABET[source[srcOffset + 3]] & 0xFF)); - - - destination[destOffset] = (byte)(outBuff >> 16); - destination[destOffset + 1] = (byte)(outBuff >> 8); - destination[destOffset + 2] = (byte)(outBuff); - - return 3; - } - catch (Exception e) { - Log.error("" + source[srcOffset] + ": " + (DECODABET[source[srcOffset]])); - Log.error("" + source[srcOffset + 1] + ": " + (DECODABET[source[srcOffset + 1]])); - Log.error("" + source[srcOffset + 2] + ": " + (DECODABET[source[srcOffset + 2]])); - Log.error("" + source[srcOffset + 3] + ": " + (DECODABET[source[srcOffset + 3]])); - return -1; - } //e nd catch - } - } // end decodeToBytes - - - /** - * Very low-level access to decoding ASCII characters in - * the form of a byte array. Does not support automatically - * gunzipping or any other "fancy" features. - * - * @param source The Base64 encoded data - * @param off The offset of where to begin decoding - * @param len The length of characters to decode - * @return decoded data - * @since 1.3 - */ - public static byte[] decode(byte[] source, int off, int len) { - int len34 = len * 3 / 4; - byte[] outBuff = new byte[len34]; // Upper limit on size of output - int outBuffPosn = 0; - - byte[] b4 = new byte[4]; - int b4Posn = 0; - int i; - byte sbiCrop; - byte sbiDecode; - for (i = off; i < off + len; i++) { - sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits - sbiDecode = DECODABET[sbiCrop]; - - if (sbiDecode >= WHITE_SPACE_ENC) // White space, Equals sign or better - { - if (sbiDecode >= EQUALS_SIGN_ENC) { - b4[b4Posn++] = sbiCrop; - if (b4Posn > 3) { - outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn); - b4Posn = 0; - - // If that was the equals sign, break out of 'for' loop - if (sbiCrop == EQUALS_SIGN) - break; - } // end if: quartet built - - } // end if: equals sign or better - - } // end if: white space, equals sign or better - else { - System.err.println("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)"); - return null; - } // end else: - } // each input character - - byte[] out = new byte[outBuffPosn]; - System.arraycopy(outBuff, 0, out, 0, outBuffPosn); - return out; - } // end decode - - - /** - * Decodes data from Base64 notation, automatically - * detecting gzip-compressed data and decompressing it. - * - * @param s the string to decode - * @return the decoded data - * @since 1.4 - */ - public static byte[] decode(String s) { - byte[] bytes; - try { - bytes = s.getBytes(PREFERRED_ENCODING); - } // end try - catch (java.io.UnsupportedEncodingException uee) { - bytes = s.getBytes(); - } // end catch - // - - // Decode - bytes = decode(bytes, 0, bytes.length); - - // Check to see if it's gzip-compressed - // GZIP Magic Two-Byte Number: 0x8b1f (35615) - if (bytes.length >= 2) { - - int head = ((int)bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00); - if ( - bytes != null && // In case decoding returned null - bytes.length >= 4 && // Don't want to get ArrayIndexOutOfBounds exception - java.util.zip.GZIPInputStream.GZIP_MAGIC == head) { - java.io.ByteArrayInputStream bais = null; - java.util.zip.GZIPInputStream gzis = null; - java.io.ByteArrayOutputStream baos = null; - byte[] buffer = new byte[2048]; - int length; - - try { - baos = new java.io.ByteArrayOutputStream(); - bais = new java.io.ByteArrayInputStream(bytes); - gzis = new java.util.zip.GZIPInputStream(bais); - - while ((length = gzis.read(buffer)) >= 0) { - baos.write(buffer, 0, length); - } // end while: reading input - - // No error? Get new bytes. - bytes = baos.toByteArray(); - - } // end try - catch (java.io.IOException e) { - // Just return originally-decoded bytes - } // end catch - finally { - try { - baos.close(); - } - catch (Exception e) { - // Nothing to do - } - try { - gzis.close(); - } - catch (Exception e) { - // Nothing to do - } - try { - bais.close(); - } - catch (Exception e) { - // Nothing to do - } - } // end finally - - } // end if: gzipped - } // end if: bytes.length >= 2 - - return bytes; - } // end decode - - - /** - * Attempts to decode Base64 data and deserialize a Java - * Object within. Returns null if there was an error. - * - * @param encodedObject The Base64 data to decode - * @return The decoded and deserialized object - * @since 1.5 - */ - public static Object decodeToObject(String encodedObject) { - // Decode and gunzip if necessary - byte[] objBytes = decode(encodedObject); - - java.io.ByteArrayInputStream bais = null; - java.io.ObjectInputStream ois = null; - Object obj = null; - - try { - bais = new java.io.ByteArrayInputStream(objBytes); - ois = new java.io.ObjectInputStream(bais); - - obj = ois.readObject(); - } // end try - catch (java.io.IOException e) { - Log.error(e); - obj = null; - } // end catch - catch (java.lang.ClassNotFoundException e) { - Log.error(e); - obj = null; - } // end catch - finally { - try { - if (bais != null) - bais.close(); - } - catch (Exception e) { - // Nothing to do - } - try { - if (ois != null) - ois.close(); - } - catch (Exception e) { - // Nothing to do - } - } // end finally - - return obj; - } // end decodeObject - - /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */ - - - /** - * A InputStream will read data from another - * {@link java.io.InputStream}, given in the constructor, - * and encode/decode to/from Base64 notation on the fly. - * - * @see Base64 - * @see java.io.FilterInputStream - * @since 1.3 - */ - public static class InputStream extends java.io.FilterInputStream { - private boolean encode; // Encoding or decoding - private int position; // Current position in the buffer - private byte[] buffer; // Small buffer holding converted data - private int bufferLength; // Length of buffer (3 or 4) - private int numSigBytes; // Number of meaningful bytes in the buffer - private int lineLength; - private boolean breakLines; // Break lines at less than 80 characters - - - /** - * Constructs a InputStream in DECODE mode. - * - * @param in the {@link java.io.InputStream} from which to read data. - * @since 1.3 - */ - public InputStream(java.io.InputStream in) { - this(in, DECODE); - } // end constructor - - - /** - * Constructs a InputStream in - * either ENCODE or DECODE mode. - *

        - * Valid options:

        -         *   ENCODE or DECODE: Encode or Decode as data is read.
        -         *   DONT_BREAK_LINES: don't break lines at 76 characters
        -         *     (only meaningful when encoding)
        -         *     Note: Technically, this makes your encoding non-compliant.
        -         * 
        - *

        - * Example: new Base64.InputStream( in, Base64.DECODE ) - * - * @param in the {@link java.io.InputStream} from which to read data. - * @param options Specified options - * @see Base64#ENCODE - * @see Base64#DECODE - * @see Base64#DONT_BREAK_LINES - * @since 2.0 - */ - public InputStream(java.io.InputStream in, int options) { - super(in); - this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES; - this.encode = (options & ENCODE) == ENCODE; - this.bufferLength = encode ? 4 : 3; - this.buffer = new byte[bufferLength]; - this.position = -1; - this.lineLength = 0; - } // end constructor - - /** - * Reads enough of the input stream to convert - * to/from Base64 and returns the next byte. - * - * @return next byte - * @since 1.3 - */ - public int read() throws java.io.IOException { - // Do we need to get data? - if (position < 0) { - if (encode) { - byte[] b3 = new byte[3]; - int numBinaryBytes = 0; - for (int i = 0; i < 3; i++) { - try { - int b = in.read(); - - // If end of stream, b is -1. - if (b >= 0) { - b3[i] = (byte)b; - numBinaryBytes++; - } // end if: not end of stream - - } // end try: read - catch (java.io.IOException e) { - // Only a problem if we got no data at all. - if (i == 0) - throw e; - - } // end catch - } // end for: each needed input byte - - if (numBinaryBytes > 0) { - encode3to4(b3, 0, numBinaryBytes, buffer, 0); - position = 0; - numSigBytes = 4; - } // end if: got data - else { - return -1; - } // end else - } // end if: encoding - - // Else decoding - else { - byte[] b4 = new byte[4]; - int i; - for (i = 0; i < 4; i++) { - // Read four "meaningful" bytes: - int b; - do { - b = in.read(); - } - while (b >= 0 && DECODABET[b & 0x7f] <= WHITE_SPACE_ENC); - - if (b < 0) - break; // Reads a -1 if end of stream - - b4[i] = (byte)b; - } // end for: each needed input byte - - if (i == 4) { - numSigBytes = decode4to3(b4, 0, buffer, 0); - position = 0; - } // end if: got four characters - else if (i == 0) { - return -1; - } // end else if: also padded correctly - else { - // Must have broken out from above. - throw new java.io.IOException("Improperly padded Base64 input."); - } // end - - } // end else: decode - } // end else: get data - - // Got data? - if (position >= 0) { - // End of relevant data? - if (/*!encode &&*/ position >= numSigBytes) - return -1; - - if (encode && breakLines && lineLength >= MAX_LINE_LENGTH) { - lineLength = 0; - return '\n'; - } // end if - else { - lineLength++; // This isn't important when decoding - // but throwing an extra "if" seems - // just as wasteful. - - int b = buffer[position++]; - - if (position >= bufferLength) - position = -1; - - return b & 0xFF; // This is how you "cast" a byte that's - // intended to be unsigned. - } // end else - } // end if: position >= 0 - - // Else error - else { - // When JDK1.4 is more accepted, use an assertion here. - throw new java.io.IOException("Error in Base64 code reading stream."); - } // end else - } // end read - - - /** - * Calls {@link #read} repeatedly until the end of stream - * is reached or len bytes are read. - * Returns number of bytes read into array or -1 if - * end of stream is encountered. - * - * @param dest array to hold values - * @param off offset for array - * @param len max number of bytes to read into array - * @return bytes read into array or -1 if end of stream is encountered. - * @since 1.3 - */ - public int read(byte[] dest, int off, int len) throws java.io.IOException { - int i; - int b; - for (i = 0; i < len; i++) { - b = read(); - - //if( b < 0 && i == 0 ) - // return -1; - - if (b >= 0) - dest[off + i] = (byte)b; - else if (i == 0) - return -1; - else - break; // Out of 'for' loop - } // end for: each byte read - return i; - } // end read - - } // end inner class InputStream - - /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */ - - - /** - * A outputStream will write data to another - * {@link java.io.OutputStream}, given in the constructor, - * and encode/decode to/from Base64 notation on the fly. - * - * @see Base64 - * @see java.io.FilterOutputStream - * @since 1.3 - */ - public static class OutputStream extends java.io.FilterOutputStream { - private boolean encode; - private int position; - private byte[] buffer; - private int bufferLength; - private int lineLength; - private boolean breakLines; - private byte[] b4; // Scratch used in a few places - private boolean suspendEncoding; - - /** - * Constructs a OutputStream in ENCODE mode. - * - * @param out the {@link java.io.OutputStream} to which data will be written. - * @since 1.3 - */ - public OutputStream(java.io.OutputStream out) { - this(out, ENCODE); - } // end constructor - - - /** - * Constructs a OutputStream in - * either ENCODE or DECODE mode. - *

        - * Valid options:

        -         *   ENCODE or DECODE: Encode or Decode as data is read.
        -         *   DONT_BREAK_LINES: don't break lines at 76 characters
        -         *     (only meaningful when encoding)
        -         *     Note: Technically, this makes your encoding non-compliant.
        -         * 
        - *

        - * Example: new Base64.OutputStream( out, Base64.ENCODE ) - * - * @param out the {@link java.io.OutputStream} to which data will be written. - * @param options Specified options. - * @see Base64#ENCODE - * @see Base64#DECODE - * @see Base64#DONT_BREAK_LINES - * @since 1.3 - */ - public OutputStream(java.io.OutputStream out, int options) { - super(out); - this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES; - this.encode = (options & ENCODE) == ENCODE; - this.bufferLength = encode ? 3 : 4; - this.buffer = new byte[bufferLength]; - this.position = 0; - this.lineLength = 0; - this.suspendEncoding = false; - this.b4 = new byte[4]; - } // end constructor - - - /** - * Writes the byte to the output stream after - * converting to/from Base64 notation. - * When encoding, bytes are buffered three - * at a time before the output stream actually - * gets a write() call. - * When decoding, bytes are buffered four - * at a time. - * - * @param theByte the byte to write - * @since 1.3 - */ - public void write(int theByte) throws java.io.IOException { - // Encoding suspended? - if (suspendEncoding) { - super.out.write(theByte); - return; - } // end if: supsended - - // Encode? - if (encode) { - buffer[position++] = (byte)theByte; - if (position >= bufferLength) // Enough to encode. - { - out.write(encode3to4(b4, buffer, bufferLength)); - - lineLength += 4; - if (breakLines && lineLength >= MAX_LINE_LENGTH) { - out.write(NEW_LINE); - lineLength = 0; - } // end if: end of line - - position = 0; - } // end if: enough to output - } // end if: encoding - - // Else, Decoding - else { - // Meaningful Base64 character? - if (DECODABET[theByte & 0x7f] > WHITE_SPACE_ENC) { - buffer[position++] = (byte)theByte; - if (position >= bufferLength) // Enough to output. - { - int len = Base64.decode4to3(buffer, 0, b4, 0); - out.write(b4, 0, len); - //out.write( Base64.decode4to3( buffer ) ); - position = 0; - } // end if: enough to output - } // end if: meaningful base64 character - else if (DECODABET[theByte & 0x7f] != WHITE_SPACE_ENC) { - throw new java.io.IOException("Invalid character in Base64 data."); - } // end else: not white space either - } // end else: decoding - } // end write - - - /** - * Calls {@link #write} repeatedly until len - * bytes are written. - * - * @param theBytes array from which to read bytes - * @param off offset for array - * @param len max number of bytes to read into array - * @since 1.3 - */ - public void write(byte[] theBytes, int off, int len) throws java.io.IOException { - // Encoding suspended? - if (suspendEncoding) { - super.out.write(theBytes, off, len); - return; - } // end if: supsended - - for (int i = 0; i < len; i++) { - write(theBytes[off + i]); - } // end for: each byte written - - } // end write - - - /** - * Method added by PHIL. [Thanks, PHIL. -Rob] - * This pads the buffer without closing the stream. - * - * @throws java.io.IOException if there's an error during flush. - */ - public void flushBase64() throws java.io.IOException { - if (position > 0) { - if (encode) { - out.write(encode3to4(b4, buffer, position)); - position = 0; - } // end if: encoding - else { - throw new java.io.IOException("Base64 input not properly padded."); - } // end else: decoding - } // end if: buffer partially full - - } // end flush - - - /** - * Flushes and closes (I think, in the superclass) the stream. - * - * @since 1.3 - */ - public void close() throws java.io.IOException { - // 1. Ensure that pending characters are written - flushBase64(); - - // 2. Actually close the stream - // Base class both flushes and closes. - super.close(); - - buffer = null; - out = null; - } // end close - - - /** - * Suspends encoding of the stream. - * May be helpful if you need to embed a piece of - * base640-encoded data in a stream. - * - * @since 1.5.1 - * @throws java.io.IOException ie an error occurs during suspension. - */ - public void suspendEncoding() throws java.io.IOException { - flushBase64(); - this.suspendEncoding = true; - } // end suspendEncoding - - - /** - * Resumes encoding of the stream. - * May be helpful if you need to embed a piece of - * base640-encoded data in a stream. - * - * @since 1.5.1 - */ - public void resumeEncoding() { - this.suspendEncoding = false; - } // end resumeEncoding - - - } // end inner class OutputStream - - -} // end class Base64 diff --git a/src/java/org/jivesoftware/spark/util/BrowserLauncher.java b/src/java/org/jivesoftware/spark/util/BrowserLauncher.java deleted file mode 100644 index aa0a6ee15..000000000 --- a/src/java/org/jivesoftware/spark/util/BrowserLauncher.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.util; - -import java.awt.Desktop; -import java.io.File; -import java.net.URI; - -public class BrowserLauncher { - - public static void openURL(String url) throws Exception { - if (url.startsWith("http") || url.startsWith("ftp") || url.startsWith("file") || url.startsWith("www")) { - - if (url.startsWith("file") && url.contains(" ")) { - url = url.replace(" ", "%20"); - } - if (url.startsWith("www")) { - url = "http://" + url; - } - Desktop.getDesktop().browse(new URI(url)); - } else { - File f = new File(url); - if (f.exists() && Desktop.isDesktopSupported()){ - try { - Desktop.getDesktop().open(f); - } catch (Exception ex){ - if (!url.toLowerCase().startsWith("//")) url = "//" + url; - Desktop.getDesktop().browse(new URI("http:" + url)); - } - } - } - } -} diff --git a/src/java/org/jivesoftware/spark/util/DummySSLSocketFactory.java b/src/java/org/jivesoftware/spark/util/DummySSLSocketFactory.java deleted file mode 100644 index 240a67eea..000000000 --- a/src/java/org/jivesoftware/spark/util/DummySSLSocketFactory.java +++ /dev/null @@ -1,133 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.util; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; - -import javax.net.SocketFactory; -import javax.net.ssl.SSLSocketFactory; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.Socket; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateExpiredException; -import java.security.cert.CertificateNotYetValidException; -import java.security.cert.X509Certificate; -import java.security.cert.CertificateException; - -/** - * An SSL socket factory that will let any certifacte past, even if it's expired or - * not singed by a root CA. - */ -public class DummySSLSocketFactory extends SSLSocketFactory { - - private SSLSocketFactory factory; - - public DummySSLSocketFactory() { - - try { - SSLContext sslcontent = SSLContext.getInstance("TLS"); - sslcontent.init(null, // KeyManager not required - new TrustManager[]{new DummyTrustManager()}, - new java.security.SecureRandom()); - factory = sslcontent.getSocketFactory(); - } - catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - catch (KeyManagementException e) { - e.printStackTrace(); - } - } - - public static SocketFactory getDefault() { - return new DummySSLSocketFactory(); - } - - public Socket createSocket(Socket socket, String s, int i, boolean flag) - throws IOException { - return factory.createSocket(socket, s, i, flag); - } - - public Socket createSocket(InetAddress inaddr, int i, InetAddress inaddr2, int j) - throws IOException { - return factory.createSocket(inaddr, i, inaddr2, j); - } - - public Socket createSocket(InetAddress inaddr, int i) throws IOException { - return factory.createSocket(inaddr, i); - } - - public Socket createSocket(String s, int i, InetAddress inaddr, int j) throws IOException { - return factory.createSocket(s, i, inaddr, j); - } - - public Socket createSocket(String s, int i) throws IOException { - return factory.createSocket(s, i); - } - - public String[] getDefaultCipherSuites() { - return factory.getSupportedCipherSuites(); - } - - public String[] getSupportedCipherSuites() { - return factory.getSupportedCipherSuites(); - } -} - -/** - * Trust manager which accepts certificates without any validation - * except date validation. - */ -class DummyTrustManager implements X509TrustManager { - - public boolean isClientTrusted(X509Certificate[] cert) { - return true; - } - - public boolean isServerTrusted(X509Certificate[] cert) { - try { - cert[0].checkValidity(); - return true; - } - catch (CertificateExpiredException e) { - return false; - } - catch (CertificateNotYetValidException e) { - return false; - } - } - - public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { - // Do nothing for now. - } - - public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { - // Do nothing for now. - } - - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } -} diff --git a/src/java/org/jivesoftware/spark/util/Encryptor.java b/src/java/org/jivesoftware/spark/util/Encryptor.java deleted file mode 100644 index 3d8ab2f34..000000000 --- a/src/java/org/jivesoftware/spark/util/Encryptor.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.util; - -import org.jivesoftware.spark.util.log.Log; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; - -import java.io.UnsupportedEncodingException; - -/** - * Encrypts and Decrypts text based on DESede keys. - * - * @author Derek DeMoro - */ -public class Encryptor { - - private static Cipher ecipher; - private static Cipher dcipher; - - static { - try { - SecretKey key = decodeKey(); - ecipher = Cipher.getInstance("DESede"); - dcipher = Cipher.getInstance("DESede"); - ecipher.init(Cipher.ENCRYPT_MODE, key); - dcipher.init(Cipher.DECRYPT_MODE, key); - } - catch (Exception e) { - Log.error(e); - } - } - - public static String encrypt(String string) throws Exception { - byte[] utf8 = string.getBytes("UTF8"); - - // Encrypt - byte[] enc = ecipher.doFinal(utf8); - return Base64.encodeBytes(enc); - } - - public static String decrypt(String string) { - byte[] dec = Base64.decode( string ); - - try { - // Decrypt - byte[] utf8 = dcipher.doFinal(dec); - - // Decode using utf-8 - return new String(utf8, "UTF8"); - } - catch (IllegalBlockSizeException e) { - Log.error(e); - } - catch (BadPaddingException e) { - Log.error(e); - } - catch (UnsupportedEncodingException e) { - Log.error(e); - } - return null; - } - - private static SecretKey decodeKey() throws Exception { - String secretKey = "ugfpV1dMC5jyJtqwVAfTpHkxqJ0+E0ae"; - byte[] bytes = Base64.decode( secretKey ); - return new SecretKeySpec(bytes, "DESede"); - } - - public static void main(String[] args) throws Exception { - String encoded = encrypt("How are you today"); - System.out.println(decrypt(encoded)); - } -} diff --git a/src/java/org/jivesoftware/spark/util/ImageCombiner.java b/src/java/org/jivesoftware/spark/util/ImageCombiner.java deleted file mode 100644 index fe0e86bec..000000000 --- a/src/java/org/jivesoftware/spark/util/ImageCombiner.java +++ /dev/null @@ -1,120 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.util; - -import java.awt.Graphics2D; -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; -import java.awt.Image; -import java.awt.image.BufferedImage; -import java.awt.image.ImageObserver; - -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JComponent; - -/** - * ImageCombiner - * - * @author wolf.posdorfer - */ -public class ImageCombiner { - - - /** - * Combines two images into one - * - * @param image1 - * left image - * @param image2 - * right image - * @return combined Image - */ - public static Image combine(Image image1, Image image2) - { - return combine(new ImageIcon(image1), new ImageIcon(image2)); - } - - /** - * Combines two images into one - * - * @param image1 - * left image - * @param image2 - * right image - * @return combined Image - */ - public static Image combine(ImageIcon image1, ImageIcon image2) { - - ImageObserver comp = new JComponent() { - private static final long serialVersionUID = 1L; - }; - - int w = image1.getIconWidth() + image2.getIconWidth(); - int h = Math.max(image1.getIconHeight(), image2.getIconHeight()); - - BufferedImage image = new BufferedImage(w, h, - BufferedImage.TYPE_INT_ARGB); - - Graphics2D g2 = image.createGraphics(); - - g2.drawImage(image1.getImage(), 0, 0, comp); - g2.drawImage(image2.getImage(), image1.getIconWidth(), 0, comp); - g2.dispose(); - - return image; - } - - public static Image returnTransparentImage(int w, int h) { - - BufferedImage image = new BufferedImage(w, h, - BufferedImage.TYPE_INT_ARGB); - - return image; - - } - - - /** - * Creates an Image from the specified Icon - * - * @param icon - * that should be converted to an image - * @return the new image - */ - public static Image iconToImage(Icon icon) { - if (icon instanceof ImageIcon) { - return ((ImageIcon) icon).getImage(); - } else { - int w = icon.getIconWidth(); - int h = icon.getIconHeight(); - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsDevice gd = ge.getDefaultScreenDevice(); - GraphicsConfiguration gc = gd.getDefaultConfiguration(); - BufferedImage image = gc.createCompatibleImage(w, h); - Graphics2D g = image.createGraphics(); - icon.paintIcon(null, g, 0, 0); - g.dispose(); - return image; - } - } - -} diff --git a/src/java/org/jivesoftware/spark/util/ModelUtil.java b/src/java/org/jivesoftware/spark/util/ModelUtil.java deleted file mode 100644 index 47978e5a9..000000000 --- a/src/java/org/jivesoftware/spark/util/ModelUtil.java +++ /dev/null @@ -1,380 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.util; - - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; - -/** - * Utility methods frequently used by data classes and design-time - * classes. - */ -public final class ModelUtil { - - private ModelUtil() { - // Prevent instantiation. - } - - /** - * This is a utility method that compares two objects when one or - * both of the objects might be null The result of - * this method is determined as follows: - *

          - *
        1. If o1 and o2 are the same object - * according to the == operator, return - * true. - *
        2. Otherwise, if either o1 or o2 is - * null, return false. - *
        3. Otherwise, return o1.equals(o2). - *
        - *

        - * This method produces the exact logically inverted result as the - * {@link #areDifferent(Object, Object)} method.

        - *

        - * For array types, one of the equals methods in - * {@link java.util.Arrays} should be used instead of this method. - * Note that arrays with more than one dimension will require some - * custom code in order to implement equals properly. - * - * @param o1 first object to compare - * @param o2 second object to compare - * @return true if they are equal - */ - public static boolean areEqual(Object o1, Object o2) { - if (o1 == o2) { - return true; - } - else if (o1 == null || o2 == null) { - return false; - } - else { - return o1.equals(o2); - } - } - - /** - * This is a utility method that compares two Booleans when one or - * both of the objects might be null The result of - * this method is determined as follows: - *

          - *
        1. If b1 and b2 are both TRUE or - * neither b1 nor b2 is TRUE, - * return true. - *
        2. Otherwise, return false. - *
        - *

        - * This method produces the exact logically inverted result as the - * areDifferent(Boolean, Boolean) method.

        - * - * @param b1 First Boolean to compare - * @param b2 Second Boolean to compare - * @return True if the booleans are equal - */ - public static boolean areBooleansEqual(Boolean b1, Boolean b2) { - // !jwetherb treat NULL the same as Boolean.FALSE - return (b1 == Boolean.TRUE && b2 == Boolean.TRUE) || - (b1 != Boolean.TRUE && b2 != Boolean.TRUE); - } - - /** - * This is a utility method that compares two objects when one or - * both of the objects might be null. The result - * returned by this method is determined as follows: - *

          - *
        1. If o1 and o2 are the same object - * according to the == operator, return - * false. - *
        2. Otherwise, if either o1 or o2 is - * null, return true. - *
        3. Otherwise, return !o1.equals(o2). - *
        - *

        - * This method produces the exact logically inverted result as the - * {@link #areEqual(Object, Object)} method.

        - *

        - * For array types, one of the equals methods in - * {@link java.util.Arrays} should be used instead of this method. - * Note that arrays with more than one dimension will require some - * custom code in order to implement equals properly. - * - * @param o1 First object to compare - * @param o2 Second object to compare - * @return True if objects are different - */ - public static boolean areDifferent(Object o1, Object o2) { - return !areEqual(o1, o2); - } - - - /** - * This is a utility method that compares two Booleans when one or - * both of the objects might be null The result of - * this method is determined as follows: - *

          - *
        1. If b1 and b2 are both TRUE or - * neither b1 nor b2 is TRUE, - * return false. - *
        2. Otherwise, return true. - *
        - *

        - * This method produces the exact logically inverted result as the - * {@link #areBooleansEqual(Boolean, Boolean)} method.

        - * - * @param b1 First boolean to compare - * @param b2 Second boolean to compare - * @return True if booleans are different - */ - public static boolean areBooleansDifferent(Boolean b1, Boolean b2) { - return !areBooleansEqual(b1, b2); - } - - - /** - * Returns true if the specified array is not null - * and contains a non-null element. Returns false - * if the array is null or if all the array elements are null. - * - * @param array Array to scan. - * @return True if there's a null element. - */ - public static boolean hasNonNullElement(Object[] array) { - if (array != null) { - final int n = array.length; - for (int i = 0; i < n; i++) { - if (array[i] != null) { - return true; - } - } - } - return false; - } - - /** - * Returns a single string that is the concatenation of all the - * strings in the specified string array. A single space is - * put between each string array element. Null array elements - * are skipped. If the array itself is null, the empty string - * is returned. This method is guaranteed to return a non-null - * value, if no expections are thrown. - * - * @param strs Array of strings to concatenate. - * @return Concatenated string. - */ - public static String concat(String[] strs) { - return concat(strs, " "); //NOTRANS - } - - /** - * Returns a single string that is the concatenation of all the - * strings in the specified string array. The strings are separated - * by the specified delimiter. Null array elements are skipped. If - * the array itself is null, the empty string is returned. This - * method is guaranteed to return a non-null value, if no expections - * are thrown. - * - * @param strs Array of strings to concatenate. - * @param delim Delimeter to separate strings. - * @return Concatenated string. - */ - public static String concat(String[] strs, String delim) { - if (strs != null) { - final StringBuilder buf = new StringBuilder(); - final int n = strs.length; - for (int i = 0; i < n; i++) { - final String str = strs[i]; - if (str != null) { - buf.append(str).append(delim); - } - } - final int length = buf.length(); - if (length > 0) { - // Trim trailing space. - buf.setLength(length - 1); - } - return buf.toString(); - } - else { - return ""; // NOTRANS - } - } - - /** - * Returns true if the specified {@link String} is not - * null and has a length greater than zero. This is - * a very frequently occurring check. - * - * @param s String to check - * @return True if string is null or empty - */ - public static boolean hasLength(String s) { - return (s != null && !s.trim().isEmpty()); - } - - - /** - * Returns null if the specified string is empty or - * null. Otherwise the string itself is returned. - * - * @param s String to check - * @return Returns null string if string is empty, otherwise string itself. - */ - public static String nullifyIfEmpty(String s) { - return ModelUtil.hasLength(s) ? s : null; - } - - /** - * Returns null if the specified object is null - * or if its toString() representation is empty. - * Otherwise, the toString() representation of the - * object itself is returned. - * - * @param o Object to check - * @return Returns null string if string(object) is empty, otherwise string itself. - */ - public static String nullifyingToString(Object o) { - return o != null ? nullifyIfEmpty(o.toString()) : null; - } - - /** - * Determines if a string has been changed. - * - * @param oldString is the initial value of the String - * @param newString is the new value of the String - * @return true If both oldString and newString are null or if they are - * both not null and equal to each other. Otherwise returns false. - */ - public static boolean hasStringChanged(String oldString, String newString) { - if (oldString == null && newString == null) { - return false; - } - else if (oldString == null || newString == null) { - return true; - } - else { - return !oldString.equals(newString); - } - } - - /** - * Returns a formatted String from time. - * - * @param diff the amount of elapsed time. - * @return the formatte String. - */ - public static String getTimeFromLong(long diff) { - final String HOURS = "h"; - final String MINUTES = "min"; - - final long MS_IN_A_DAY = 1000 * 60 * 60 * 24; - final long MS_IN_AN_HOUR = 1000 * 60 * 60; - final long MS_IN_A_MINUTE = 1000 * 60; - long numDays = diff / MS_IN_A_DAY; - diff = diff % MS_IN_A_DAY; - long numHours = diff / MS_IN_AN_HOUR; - diff = diff % MS_IN_AN_HOUR; - long numMinutes = diff / MS_IN_A_MINUTE; - - StringBuilder buf = new StringBuilder(); - - if(numDays > 0){ - buf.append(numDays).append(" d, "); - } - - if (numHours > 0) { - buf.append(numHours).append(" ").append(HOURS).append(", "); - } - - if (numMinutes > 0) { - buf.append(numMinutes).append(" ").append(MINUTES); - } - - //buf.append(numSeconds + " " + SECONDS); - - String result = buf.toString(); - - if (numMinutes < 1) { - result = "< 1 min"; - } - - return result; - } - - - /** - * Build a List of all elements in an Iterator. - * - * @param i Iterator to return as a list. - * @return List converted from iterator. - */ - public static List iteratorAsList(Iterator i) { - ArrayList list = new ArrayList<>( 10 ); - while (i.hasNext()) { - list.add(i.next()); - } - return list; - } - - /** - * Creates an Iterator that is the reverse of a ListIterator. - * - * @param i Iterator of a list. - * @return Reversed iterator. - */ - public static Iterator reverseListIterator(ListIterator i) { - return new ReverseListIterator<>( i ); - } -} - -/** - * An Iterator that is the reverse of a ListIterator. - */ -class ReverseListIterator implements Iterator { - private ListIterator _i; - - public ReverseListIterator(ListIterator i) { - _i = i; - while (_i.hasNext()) _i.next(); - } - - public boolean hasNext() { - return _i.hasPrevious(); - } - - public T next() { - return _i.previous(); - } - - public void remove() { - _i.remove(); - } -} - - - - - - - - - - diff --git a/src/java/org/jivesoftware/spark/util/URLFileSystem.java b/src/java/org/jivesoftware/spark/util/URLFileSystem.java deleted file mode 100644 index 52ed197d5..000000000 --- a/src/java/org/jivesoftware/spark/util/URLFileSystem.java +++ /dev/null @@ -1,679 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.util; - -import org.jivesoftware.spark.util.log.Log; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Method; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.nio.channels.FileChannel; - -/** - * URLFileSystem class handles some of the most common - * functionallity when working with URLs. - * - * @version 1.0, 03/12/14 - */ - -public class URLFileSystem { - public static void main(String args[]) { - } - - public static String getContents(URL url) { - try { - return getContents(url.openStream()); - } - catch (IOException e) { - return null; - } - } - - public static String getContents(InputStream is) { - byte[] buffer = new byte[2048]; - int length; - StringBuilder sb = new StringBuilder(); - try { - while ((length = is.read(buffer)) != -1) { - sb.append(new String(buffer, 0, length)); - } - return sb.toString(); - } - catch (IOException e) { - return null; - } - } - - public static String getContents(File file) { - try { - return getContents(file.toURI().toURL()); - } - catch (MalformedURLException e) { - return ""; - } - } - - /** - * Copies the contents at src to dst. - * - * @param src URL to copy to local file. - * @param dst File to pull information from to copy to. - * @throws IOException if there is an error during copy. - */ - public static void copy(URL src, File dst) throws IOException { - InputStream in = null; - OutputStream out = null; - try { - in = src.openStream(); - out = new FileOutputStream(dst); - dst.mkdirs(); - copy(in, out); - } - finally { - try { - if (in != null) in.close(); - } - catch (IOException e) { - // Nothing to do - } - try { - if (out != null) out.close(); - } - catch (IOException e) { - // Nothing to do - } - } - } - - /** - * Common code for copy routines. By convention, the streams are - * closed in the same method in which they were opened. Thus, - * this method does not close the streams when the copying is done. - * - * @param in Source stream - * @param out Destination stream - * @throws IOException if there is an error during copy. - */ - public static void copy(InputStream in, OutputStream out) throws IOException { - final byte[] buffer = new byte[4096]; - while (true) { - final int bytesRead = in.read(buffer); - if (bytesRead < 0) { - break; - } - out.write(buffer, 0, bytesRead); - } - - out.flush(); - } - - /** - * If a dot ('.') occurs in the path portion of the {@link URL}, then - * all of the text starting at the last dot is returned, including - * the dot. If the last dot is also the last character in the path, - * then the dot by itself is returned. If there is no dot in the - * path, then the empty string is returned. - * - * @param url the URL. - * @return suffix of url path - */ - public static String getSuffix(URL url) { - final String path = url.getPath(); - int lastDot = path.lastIndexOf('.'); - - return (lastDot >= 0) ? path.substring(lastDot) : ""; - } - - /** - * If a dot ('.') occurs in the path portion of the {@link File}, then - * all of the text starting at the last dot is returned, including - * the dot. If the last dot is also the last character in the path, - * then the dot by itself is returned. If there is no dot in the - * path, then the empty string is returned. - * - * @param file the File. - * @return suffix of filename - */ - public static String getSuffix(File file) { - final String path = file.getAbsolutePath(); - int lastDot = path.lastIndexOf('.'); - - return (lastDot >= 0) ? path.substring(lastDot) : ""; - } - - //-------------------------------------------------------------------------- - // URLFileSystemHelper public API... - //-------------------------------------------------------------------------- - - /** - * Returns a canonical form of the {@link URL}, if one is available. - *

        - *

        - * The default implementation just returns the specified {@link URL} - * as-is. - * - * @param url URL to convert. - * @return Convert url. - */ - public URL canonicalize(URL url) { - return url; - } - - /** - * Tests whether the application can read the resource at the - * specified {@link URL}. - * - * @return true if and only if the specified - * {@link URL} points to a resource that exists and can be - * read by the application; false otherwise. - * - * @param url URL to check if we can read from it. - */ - public boolean canRead(URL url) { - try { - final URLConnection urlConnection = url.openConnection(); - return urlConnection.getDoInput(); - } - catch (Exception e) { - return false; - } - } - - - /** - * Tests whether the application can modify the resource at the - * specified {@link URL}. - * - * @return true if and only if the specified - * {@link URL} points to a file that exists and the - * application is allowed to write to the file; false - * otherwise. - * - * @param url URL to check if we can write to. - */ - public boolean canWrite(URL url) { - try { - final URLConnection urlConnection = url.openConnection(); - return urlConnection.getDoOutput(); - } - catch (Exception e) { - return false; - } - } - - /** - * Tests whether the application can create the resource at the specified - * {@link URL}. - * - * @return true if the resource at the specified {@link URL} - * exists or can be created; false otherwise. - * - * @param url URL to check if we can create things at. - */ - public boolean canCreate(URL url) { - return true; - } - - /** - * Tests whether the specified {@link URL} is valid. If the resource - * pointed by the {@link URL} exists the method returns true. - * If the resource does not exist, the method tests that all components - * of the path can be created. - * - * @return true if the {@link URL} is valid. - * - * @param url URL to check for validity. - */ - public boolean isValid(URL url) { - if (exists(url)) { - return true; - } - - return canCreate(url); - } - - /** - * Returns true if the specified {@link URL} points to a - * resource that currently exists; returns false - * otherwise.

        - *

        - * The default implementation simply returns false - * without doing anything. - * - * @param url URL to test for existance - * @return True if url exists - */ - public static boolean exists(URL url) { - return url2File(url).exists(); - } - - public static boolean mkdirs(URL url) { - final File file = url2File(url); - if (!file.exists()) { - return file.mkdirs(); - } - return true; - } - - - /** - * Returns the name of the file contained by the {@link URL}, not - * including any protocol, hostname authentication, directory path, - * anchor, or query. This simply returns the simple filename. For - * example, if you pass in an {@link URL} whose string representation - * is: - *

        - *

        - * protocol://host:1010/dir1/dir2/file.ext#anchor?query - *
        - *

        - * the returned value is "file.ext" (without the - * quotes).

        - *

        - * The returned file name should only be used for display purposes - * and not for opening streams or otherwise trying to locate the - * resource indicated by the {@link URL}. - * - * @param url URL of resource to get filename of - * @return File name determined - */ - public static String getFileName(URL url) { - if (url == null) { - return ""; - } - - final String path = url.getPath(); - if (path.equals("/")) { - return "/"; - } - final int lastSep = path.lastIndexOf('/'); - if (lastSep == path.length() - 1) { - final int lastSep2 = path.lastIndexOf('/', lastSep - 1); - return path.substring(lastSep2 + 1, lastSep); - } - else { - return path.substring(lastSep + 1); - } - } - - - /** - * Returns the number of bytes contained in the resource that the - * specified {@link URL} points to. If the length cannot be - * determined, -1 is returned.

        - *

        - * The default implementation attempts to get the content length from - * the {@link URLConnection} associated with the {@link URL}. If that - * fails for some reason (e.g. the resource does not exist, there was - * some other an I/O exception, etc.), -1 is returned. - * - * @see URLConnection - * @param url URL to get length of resource of - * @return Content length - */ - public long getLength(URL url) { - try { - final URLConnection urlConnection = url.openConnection(); - return urlConnection.getContentLength(); - } - catch (Exception e) { - return -1; - } - } - - - /** - * Returns the name of the file contained by the {@link URL}, not - * including any protocol, hostname authentication, directory path, - * anchor, or query. This simply returns the simple filename. For - * example, if you pass in an {@link URL} whose string representation - * is: - *

        - *

        - * protocol://host:1010/dir1/dir2/file.ext1.ext2#anchor?query - *
        - *

        - * the returned value is "file" (without the quotes).

        - *

        - * The returned file name should only be used for display purposes - * and not for opening streams or otherwise trying to locate the - * resource indicated by the {@link URL}.

        - *

        - * The default implementation first calls {@link #getFileName(URL)} to - * get the file name part. Then all characters starting with the - * first occurrence of '.' are removed. The remaining string is then - * returned. - * - * @param url URL of resource - * @return Name for URL - */ - public static String getName(URL url) { - final String fileName = getFileName(url); - final int firstDot = fileName.lastIndexOf('.'); - return firstDot > 0 ? fileName.substring(0, firstDot) : fileName; - } - - - /** - * Returns the path part of the {@link URL}. - *

        - * The default implementation delegates to {@link URL#getPath()}. - * - * @param url URL of resource - * @return Path of URL - */ - public String getPath(URL url) { - return url.getPath(); - } - - - /** - * Returns the path part of the {@link URL} without the last file - * extension. To clarify, the following examples demonstrate the - * different cases that come up: - *

        - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
        Path part of input {@link URL}
        Output {@link String} - *
        /dir/file.ext/dir/file
        /dir/file.ext1.ext2/dir/file.ext1
        /dir1.ext1/dir2.ext2/file.ext1.ext2/dir1.ext1/dir2.ext2/file.ext1
        /file.ext/file
        /dir.ext/file/dir.ext/file
        /dir/file/dir/file
        /file/file
        /.ext/
        - *

        - * The default implementation gets the path from {@link - * #getPath(URL)} and then trims off all of the characters beginning - * with the last "." in the path, if and only if the last "." comes - * after the last "/" in the path. If the last "." comes before - * the last "/" or if there is no "." at all, then the entire path - * is returned. - * - * @param url URL of resource - * @return Path without extension - */ - public String getPathNoExt(URL url) { - final String path = getPath(url); - final int lastSlash = path.lastIndexOf("/"); - final int lastDot = path.lastIndexOf("."); - if (lastDot <= lastSlash) { - // When the lastDot < lastSlash, it means that one of the - // directories has an extension, but the filename itself has - // no extension. In this case, returning the whole path is - // the correct behavior. - // - // The only time that lastDot and lastSlash can be equal occurs - // when both of them are -1. In that case, returning the whole - // path is the correct behavior. - return path; - } - // At this point, we know that lastDot must be non-negative, so - // we can return the whole path string up to the last dot. - return path.substring(0, lastDot); - } - - - /** - * Returns the platform-dependent String representation of the - * {@link URL}; the returned string should be considered acceptable - * for users to read. In general, the returned string should omit - * as many parts of the {@link URL} as possible. For the "file" - * protocol, therefore, the platform pathname should just be the - * pathname alone (no protocol) using the appropriate file separator - * character for the current platform. For other protocols, it may - * be necessary to reformat the {@link URL} string into a more - * human-readable form. That decision is left to each - * URLFileSystemHelper implementor. - *

        - * The default implementation returns url.toString(). - * If the {@link URL} is null, the empty string is - * returned. - * - * @return The path portion of the specified {@link URL} in - * platform-dependent notation. This value should only be used for - * display purposes and not for opening streams or otherwise trying - * to locate the document. - * - * @param url URL of resource - */ - public String getPlatformPathName(URL url) { - return url != null ? url.toString() : ""; - } - - public static URL newFileURL(File file) { - String filePath = file.getPath(); - if (filePath == null) { - return null; - } - final String path = sanitizePath(filePath); - return newURL("file", path); - } - - public static URL newFileURL(String filePath) { - if (filePath == null) { - return null; - } - final String path = sanitizePath(filePath); - return newURL("file", path); - } - - /** - * This "sanitizes" the specified string path by converting all - * {@link File#separatorChar} characters to forward slash ('/'). - * Also, a leading forward slash is prepended if the path does - * not begin with one. - * - * @param path Path to sanitize - * @return Sanitized path - */ - private static String sanitizePath(String path) { - if (File.separatorChar != '/') { - path = path.replace(File.separatorChar, '/'); - } - if (!path.startsWith("/")) { - path = "/" + path; - } - return path; - } - - public static URL newURL(String protocol, String path) { - return newURL(protocol, null, null, -1, path, null, null); - } - - //-------------------------------------------------------------------------- - // direct access factory methods... - //-------------------------------------------------------------------------- - - /** - * Creates a new {@link URL} whose parts have the exact values that - * are specified. In general, you should avoid calling this - * method directly.

        - *

        - * This method is the ultimate place where all of the other - * URLFactory methods end up when creating an - * {@link URL}. - *

        - * Non-sanitizing. - * - * @param protocol Protocol portion of uri - * @param userinfo Username/Password portion of uri - * @param host Host portion of uri - * @param port Port portion of uri - * @param path Path portion of uri - * @param query Query portion of uri - * @param ref Ref portion of uri - * @return URL constructed from args - */ - public static URL newURL(String protocol, String userinfo, - String host, int port, - String path, String query, String ref) { - try { - final URL seed = new URL(protocol, "", -1, ""); - final String authority = port < 0 ? host : host + ":" + port; - final Object[] args = new Object[] - { - protocol, host, port, - authority, userinfo, - path, query, ref, - }; - - // IMPORTANT -- this *MUST* be the only place in URLFactory where - // the URL.set(...) method is used. --jdijamco - urlSet.invoke(seed, args); - return seed; - } - catch (Exception e) { - Log.error(e); - return null; - } - } - - /** - * This {@link Method} is used to work-around a bug in Sun's - * java.net.URL implementation. The {@link Method} - * allows us to set the parts of an {@link URL} directly. - */ - private static final Method urlSet; - - static { - final Class str = String.class; - try { - urlSet = URL.class.getDeclaredMethod("set", str, str, int.class, str, str, str, str, str); - - // IMPORTANT: This call to setAccessible effectively overrides - // the "protected" visibility constraint on the URL.set(...) - // method. This is an intentional breaking of encapsulation to - // work-around severe bugs in Sun's java.net.URL implementation - // having to do with: - // * poor handling of special characters like #, ?, and ; - // * poor handling of whitespace - // * no go way to disambiguate UNC paths on Win32 - // - // The use of setAccessible is an implementation detail of the - // URLFactory, and if Sun some day fixes their java.net.URL - // implementation to address the problems above, we may be able - // to change the internal mechanism to use the regular URL - // constructors. For the time being, after having weighed the - // various other alternatives and even tried some of them (and - // encountered other problems), our decision is to force our way - // through to the URL.set(...) method, taking care to invoke - // it method exactly once per URL object with the exactly the - // right arguments. - // - // --jdijamco March 14, 2001 - urlSet.setAccessible(true); - } - catch (NoSuchMethodException e) { - //!jdijamco -- Have some fallback option so that doesn't - //!jdijamco -- just totally barf and prevent the IDE from starting? - throw new IllegalStateException(); - } - } - - public static File url2File(URL url) { - final String path = url.getPath(); - return new File(path); - } - - public static URL getParent(URL url) { - final File file = url2File(url); - final File parentFile = file.getParentFile(); - if (parentFile != null && !file.equals(parentFile)) { - try { - return parentFile.toURI().toURL(); - } - catch (Exception ex) { - return null; - } - } - return null; - } - - /** - * Allows for the copying of entire directories/sub-dirs and their files. - * - * @param src the root directory to copy. - * @param dst the destination directory. - * @throws IOException thrown if there is an issue copying over the files. - */ - public static void copyDir(File src, File dst) throws IOException { - // Create the destination directory - dst.mkdirs(); - - // Loop through the files and directories in the source directory and copy them - File[] files = src.listFiles(); - for (File file : files) { - if (file.isFile()) { - copyFile(file, new File(dst, file.getName())); - } else if (file.isDirectory()) { - copyDir(file, new File(dst, file.getName())); - } - } - } - - private static void copyFile(File src, File dst) throws IOException { - FileChannel in = new FileInputStream(src).getChannel(); - FileChannel out = new FileOutputStream(dst).getChannel(); - - // Fast and efficient way to copy a file - in.transferTo(0, in.size(), out); - - in.close(); - out.close(); - } - - -} diff --git a/src/java/org/jivesoftware/spark/util/WinRegistry.java b/src/java/org/jivesoftware/spark/util/WinRegistry.java deleted file mode 100644 index 4d057340b..000000000 --- a/src/java/org/jivesoftware/spark/util/WinRegistry.java +++ /dev/null @@ -1,387 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.util; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.prefs.Preferences; - - -/*** - * Read and Write to the Windows Registry - */ -public class WinRegistry { - - public static final int HKEY_CURRENT_USER = 0x80000001; - public static final int HKEY_LOCAL_MACHINE = 0x80000002; - public static final int REG_SUCCESS = 0; - public static final int REG_NOTFOUND = 2; - public static final int REG_ACCESSDENIED = 5; - - private static final int KEY_ALL_ACCESS = 0xf003f; - private static final int KEY_READ = 0x20019; - private static Preferences userRoot = Preferences.userRoot(); - private static Preferences systemRoot = Preferences.systemRoot(); - private static Class userClass = userRoot.getClass(); - private static Method regOpenKey = null; - private static Method regCloseKey = null; - private static Method regQueryValueEx = null; - private static Method regEnumValue = null; - private static Method regQueryInfoKey = null; - private static Method regEnumKeyEx = null; - private static Method regCreateKeyEx = null; - private static Method regSetValueEx = null; - private static Method regDeleteKey = null; - private static Method regDeleteValue = null; - - static { - try { - regOpenKey = userClass.getDeclaredMethod("WindowsRegOpenKey", - new Class[] { int.class, byte[].class, int.class }); - regOpenKey.setAccessible(true); - regCloseKey = userClass.getDeclaredMethod("WindowsRegCloseKey", - new Class[] { int.class }); - regCloseKey.setAccessible(true); - regQueryValueEx = userClass.getDeclaredMethod( - "WindowsRegQueryValueEx", new Class[] { int.class, - byte[].class }); - regQueryValueEx.setAccessible(true); - regEnumValue = userClass.getDeclaredMethod("WindowsRegEnumValue", - new Class[] { int.class, int.class, int.class }); - regEnumValue.setAccessible(true); - regQueryInfoKey = userClass.getDeclaredMethod( - "WindowsRegQueryInfoKey1", new Class[] { int.class }); - regQueryInfoKey.setAccessible(true); - regEnumKeyEx = userClass.getDeclaredMethod("WindowsRegEnumKeyEx", - new Class[] { int.class, int.class, int.class }); - regEnumKeyEx.setAccessible(true); - regCreateKeyEx = userClass.getDeclaredMethod( - "WindowsRegCreateKeyEx", new Class[] { int.class, - byte[].class }); - regCreateKeyEx.setAccessible(true); - regSetValueEx = userClass.getDeclaredMethod("WindowsRegSetValueEx", - new Class[] { int.class, byte[].class, byte[].class }); - regSetValueEx.setAccessible(true); - regDeleteValue = userClass.getDeclaredMethod( - "WindowsRegDeleteValue", new Class[] { int.class, - byte[].class }); - regDeleteValue.setAccessible(true); - regDeleteKey = userClass.getDeclaredMethod("WindowsRegDeleteKey", - new Class[] { int.class, byte[].class }); - regDeleteKey.setAccessible(true); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private WinRegistry() { - } - - /** - * Read a value from key and value name - * - * @param hkey - * HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE - * @param key - * @param valueName - * @return the value - * @throws IllegalArgumentException - * @throws IllegalAccessException - * @throws InvocationTargetException - */ - public static String readString(int hkey, String key, String valueName) - throws IllegalArgumentException, IllegalAccessException, - InvocationTargetException { - if (hkey == HKEY_LOCAL_MACHINE) { - return readString(systemRoot, hkey, key, valueName); - } else if (hkey == HKEY_CURRENT_USER) { - return readString(userRoot, hkey, key, valueName); - } else { - throw new IllegalArgumentException("hkey=" + hkey); - } - } - - /** - * Read value(s) and value name(s) form given key - * - * @param hkey - * HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE - * @param key - * @return the value name(s) plus the value(s) - * @throws IllegalArgumentException - * @throws IllegalAccessException - * @throws InvocationTargetException - */ - public static Map readStringValues(int hkey, String key) - throws IllegalArgumentException, IllegalAccessException, - InvocationTargetException { - if (hkey == HKEY_LOCAL_MACHINE) { - return readStringValues(systemRoot, hkey, key); - } else if (hkey == HKEY_CURRENT_USER) { - return readStringValues(userRoot, hkey, key); - } else { - throw new IllegalArgumentException("hkey=" + hkey); - } - } - - /** - * Read the value name(s) from a given key - * - * @param hkey - * HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE - * @param key - * @return the value name(s) - * @throws IllegalArgumentException - * @throws IllegalAccessException - * @throws InvocationTargetException - */ - public static List readStringSubKeys(int hkey, String key) - throws IllegalArgumentException, IllegalAccessException, - InvocationTargetException { - if (hkey == HKEY_LOCAL_MACHINE) { - return readStringSubKeys(systemRoot, hkey, key); - } else if (hkey == HKEY_CURRENT_USER) { - return readStringSubKeys(userRoot, hkey, key); - } else { - throw new IllegalArgumentException("hkey=" + hkey); - } - } - - /** - * Create a key - * - * @param hkey - * HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE - * @param key - * @throws IllegalArgumentException - * @throws IllegalAccessException - * @throws InvocationTargetException - */ - public static void createKey(int hkey, String key) - throws IllegalArgumentException, IllegalAccessException, - InvocationTargetException { - int[] ret; - if (hkey == HKEY_LOCAL_MACHINE) { - ret = createKey(systemRoot, hkey, key); - regCloseKey - .invoke(systemRoot, new Object[] { Integer.valueOf(ret[0]) }); - } else if (hkey == HKEY_CURRENT_USER) { - ret = createKey(userRoot, hkey, key); - regCloseKey.invoke(userRoot, new Object[] { Integer.valueOf(ret[0]) }); - } else { - throw new IllegalArgumentException("hkey=" + hkey); - } - if (ret[1] != REG_SUCCESS) { - throw new IllegalArgumentException("rc=" + ret[1] + " key=" + key); - } - } - - /** - * Write a value in a given key/value name - * - * @param hkey - * @param key - * @param valueName - * @param value - * @throws IllegalArgumentException - * @throws IllegalAccessException - * @throws InvocationTargetException - */ - public static void writeStringValue(int hkey, String key, String valueName, - String value) throws IllegalArgumentException, - IllegalAccessException, InvocationTargetException { - if (hkey == HKEY_LOCAL_MACHINE) { - writeStringValue(systemRoot, hkey, key, valueName, value); - } else if (hkey == HKEY_CURRENT_USER) { - writeStringValue(userRoot, hkey, key, valueName, value); - } else { - throw new IllegalArgumentException("hkey=" + hkey); - } - } - - /** - * Delete a given key - * - * @param hkey - * @param key - * @throws IllegalArgumentException - * @throws IllegalAccessException - * @throws InvocationTargetException - */ - public static void deleteKey(int hkey, String key) - throws IllegalArgumentException, IllegalAccessException, - InvocationTargetException { - int rc = -1; - if (hkey == HKEY_LOCAL_MACHINE) { - rc = deleteKey(systemRoot, hkey, key); - } else if (hkey == HKEY_CURRENT_USER) { - rc = deleteKey(userRoot, hkey, key); - } - if (rc != REG_SUCCESS) { - throw new IllegalArgumentException("rc=" + rc + " key=" + key); - } - } - - /** - * delete a value from a given key/value name - * - * @param hkey - * @param key - * @param value - * @throws IllegalArgumentException - * @throws IllegalAccessException - * @throws InvocationTargetException - */ - public static void deleteValue(int hkey, String key, String value) - throws IllegalArgumentException, IllegalAccessException, - InvocationTargetException { - int rc = -1; - if (hkey == HKEY_LOCAL_MACHINE) { - rc = deleteValue(systemRoot, hkey, key, value); - } else if (hkey == HKEY_CURRENT_USER) { - rc = deleteValue(userRoot, hkey, key, value); - } - if (rc != REG_SUCCESS) { - throw new IllegalArgumentException("rc=" + rc + " key=" + key - + " value=" + value); - } - } - - // ===================== - - private static int deleteValue(Preferences root, int hkey, String key, - String value) throws IllegalArgumentException, - IllegalAccessException, InvocationTargetException { - int[] handles = (int[]) regOpenKey.invoke(root, new Object[] { - Integer.valueOf(hkey), toCstr(key), Integer.valueOf(KEY_ALL_ACCESS) }); - if (handles[1] != REG_SUCCESS) { - return handles[1]; // can be REG_NOTFOUND, REG_ACCESSDENIED - } - int rc = ((Integer) regDeleteValue.invoke(root, new Object[] { - Integer.valueOf(handles[0]), toCstr(value) })).intValue(); - regCloseKey.invoke(root, new Object[] { Integer.valueOf(handles[0]) }); - return rc; - } - - private static int deleteKey(Preferences root, int hkey, String key) - throws IllegalArgumentException, IllegalAccessException, - InvocationTargetException { - int rc = ((Integer) regDeleteKey.invoke(root, new Object[] { - Integer.valueOf(hkey), toCstr(key) })).intValue(); - return rc; // can REG_NOTFOUND, REG_ACCESSDENIED, REG_SUCCESS - } - - private static String readString(Preferences root, int hkey, String key, - String value) throws IllegalArgumentException, - IllegalAccessException, InvocationTargetException { - int[] handles = (int[]) regOpenKey.invoke(root, new Object[] { - Integer.valueOf(hkey), toCstr(key), Integer.valueOf(KEY_READ) }); - if (handles[1] != REG_SUCCESS) { - return null; - } - byte[] valb = (byte[]) regQueryValueEx.invoke(root, new Object[] { - Integer.valueOf(handles[0]), toCstr(value) }); - regCloseKey.invoke(root, new Object[] { Integer.valueOf(handles[0]) }); - return (valb != null ? new String(valb).trim() : null); - } - - private static Map readStringValues(Preferences root, - int hkey, String key) throws IllegalArgumentException, - IllegalAccessException, InvocationTargetException { - HashMap results = new HashMap<>(); - int[] handles = (int[]) regOpenKey.invoke(root, new Object[] { - Integer.valueOf(hkey), toCstr(key), Integer.valueOf(KEY_READ) }); - if (handles[1] != REG_SUCCESS) { - return null; - } - int[] info = (int[]) regQueryInfoKey.invoke(root, - new Object[] { Integer.valueOf(handles[0]) }); - - int count = info[2]; // count - int maxlen = info[3]; // value length max - for (int index = 0; index < count; index++) { - byte[] name = (byte[]) regEnumValue.invoke(root, new Object[] { - Integer.valueOf(handles[0]), Integer.valueOf(index), - Integer.valueOf(maxlen + 1) }); - String value = readString(hkey, key, String.valueOf(name)); - results.put(String.valueOf(name).trim(), value); - } - regCloseKey.invoke(root, new Object[] { Integer.valueOf(handles[0]) }); - return results; - } - - private static List readStringSubKeys(Preferences root, int hkey, - String key) throws IllegalArgumentException, - IllegalAccessException, InvocationTargetException { - List results = new ArrayList<>(); - int[] handles = (int[]) regOpenKey.invoke(root, new Object[] { - Integer.valueOf(hkey), toCstr(key), Integer.valueOf(KEY_READ) }); - if (handles[1] != REG_SUCCESS) { - return null; - } - int[] info = (int[]) regQueryInfoKey.invoke(root, - new Object[] { Integer.valueOf(handles[0]) }); - - int count = info[2]; // count - int maxlen = info[3]; // value length max - for (int index = 0; index < count; index++) { - byte[] name = (byte[]) regEnumKeyEx.invoke(root, new Object[] { - Integer.valueOf(handles[0]), Integer.valueOf(index), - Integer.valueOf(maxlen + 1) }); - results.add(String.valueOf(name).trim()); - } - regCloseKey.invoke(root, new Object[] { Integer.valueOf(handles[0]) }); - return results; - } - - private static int[] createKey(Preferences root, int hkey, String key) - throws IllegalArgumentException, IllegalAccessException, - InvocationTargetException { - return (int[]) regCreateKeyEx.invoke(root, new Object[] { - Integer.valueOf(hkey), toCstr(key) }); - } - - private static void writeStringValue(Preferences root, int hkey, - String key, String valueName, String value) - throws IllegalArgumentException, IllegalAccessException, - InvocationTargetException { - int[] handles = (int[]) regOpenKey.invoke(root, new Object[] { - Integer.valueOf(hkey), toCstr(key), Integer.valueOf(KEY_ALL_ACCESS) }); - - regSetValueEx.invoke(root, new Object[] { Integer.valueOf(handles[0]), - toCstr(valueName), toCstr(value) }); - regCloseKey.invoke(root, new Object[] { Integer.valueOf(handles[0]) }); - } - - // utility - private static byte[] toCstr(String str) { - byte[] result = new byte[str.length() + 1]; - - for (int i = 0; i < str.length(); i++) { - result[i] = (byte) str.charAt(i); - } - result[str.length()] = 0; - return result; - } -} diff --git a/src/java/org/jivesoftware/spark/util/log/Log.java b/src/java/org/jivesoftware/spark/util/log/Log.java deleted file mode 100644 index 6a62099ca..000000000 --- a/src/java/org/jivesoftware/spark/util/log/Log.java +++ /dev/null @@ -1,157 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.util.log; - -import org.jivesoftware.Spark; - -import java.io.File; -import java.io.IOException; -import java.util.logging.FileHandler; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.logging.SimpleFormatter; - -/** - * Creates and writes out messages to a a log file. This should be used for all - * error handling within the Agent application. - */ -public class Log { - private java.util.logging.Logger ERROR_LOGGER; - private Logger WARNING_LOGGER; - - private volatile static Log singleton = null; - - private static Log getInstance() { - if (singleton == null) { - synchronized (Log.class) { - if (singleton == null) { - singleton = new Log(); - } - } - } - return singleton; - } - - private Log() { - if (!Spark.getLogDirectory().exists()) { - Spark.getLogDirectory().mkdirs(); - } - ERROR_LOGGER = java.util.logging.Logger.getAnonymousLogger(); - WARNING_LOGGER = java.util.logging.Logger.getAnonymousLogger(); - - File ERROR_LOG_FILE = new File(Spark.getLogDirectory(), "errors.log"); - File WARNING_LOG_FILE = new File(Spark.getLogDirectory(), "warn.log"); - - try { - // Create an appending file handler - boolean append = true; - FileHandler errorHandler = new FileHandler( - ERROR_LOG_FILE.getCanonicalPath(), append); - errorHandler.setFormatter(new SimpleFormatter()); - - FileHandler warnHandler = new FileHandler( - WARNING_LOG_FILE.getCanonicalPath(), append); - warnHandler.setFormatter(new SimpleFormatter()); - - // Add to the desired logger - ERROR_LOGGER.addHandler(errorHandler); - WARNING_LOGGER.addHandler(warnHandler); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Adds a handler to the error logger - * - * @param h the handler to add - */ - public synchronized static void addErrorHandler(Handler h) { - getInstance().ERROR_LOGGER.addHandler(h); - } - - /** - * Adds a handler to the error logger - * - * @param h the handler to add - */ - public synchronized static void addWarningHandler(Handler h) { - getInstance().WARNING_LOGGER.addHandler(h); - } - - /** - * Logs all error messages to default error logger. - * - * @param message - * a message to append to log file. - * @param ex the exception being thrown. - */ - public static void error(String message, Throwable ex) { - getInstance().ERROR_LOGGER.log(Level.SEVERE, message, ex); - } - - /** - * Logs all error messages to default error logger. - * - * @param ex the exception being thrown. - */ - public static void error(Throwable ex) { - getInstance().ERROR_LOGGER.log(Level.SEVERE, "", ex); - } - - /** - * Log a warning message to the default logger. - * - * @param message the message to log. - * @param ex the exception. - */ - public static void warning(String message, Throwable ex) { - getInstance().WARNING_LOGGER.log(Level.WARNING, message, ex); - } - - public static void warning(String message) { - getInstance().WARNING_LOGGER.log(Level.WARNING, message); - } - - /** - * Logs all error messages to default error logger. - * - * @param message a message to append to log file. - */ - public static void error(String message) { - getInstance().ERROR_LOGGER.log(Level.SEVERE, message); - } - - /** - * Logs all messages to standard errout for debugging purposes. To use, pass - * in the VM Parameters debug.mode=true. - *

        - * ex. (-Ddebug.mode=true) - * - * @param message the message to print out. - */ - public static void debug(String message) { - if (System.getProperty("debug.mode") != null) { - getInstance().ERROR_LOGGER.info(message); - } - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/alerts/BroadcastDialog.java b/src/java/org/jivesoftware/sparkimpl/plugin/alerts/BroadcastDialog.java deleted file mode 100644 index 1ae56fdb7..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/alerts/BroadcastDialog.java +++ /dev/null @@ -1,359 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.alerts; - -import java.awt.BorderLayout; -import java.awt.FlowLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.swing.BorderFactory; -import javax.swing.ButtonGroup; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JDialog; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JScrollPane; -import javax.swing.UIManager; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.CheckNode; -import org.jivesoftware.spark.component.CheckTree; -import org.jivesoftware.spark.component.TitlePanel; -import org.jivesoftware.spark.ui.ChatInputEditor; -import org.jivesoftware.spark.ui.ContactGroup; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.log.Log; - -/** - * Allows for better selective broadcasting. - * - * @author Derek DeMoro - */ -public class BroadcastDialog extends JPanel { - - private static final long serialVersionUID = -8998994627855985137L; - private ChatInputEditor messageBox; - private JCheckBox OfflineUsers = new JCheckBox(Res.getString("checkbox.broadcast.hide.offline.user")); - private JRadioButton normalMessageButton; - - private ArrayList> NodesGroups = new ArrayList<>(); - private List nodes = new ArrayList<>(); - private List groupNodes = new ArrayList<>(); - private CheckNode rosterNode; - private CheckTree checkTree; - private Integer OfflineGroup; - - public BroadcastDialog() { - setLayout(new GridBagLayout()); - rosterNode = new CheckNode(Res.getString("title.roster")); - checkTree = new CheckTree(rosterNode); - final ContactList contactList = SparkManager.getWorkspace().getContactList(); - - // creates the List for the Online Users - String groupName = Res.getString("status.online"); - CheckNode groupNode = new CheckNode(groupName); - groupNodes.add(groupNode); - rosterNode.add(groupNode); - List onlineJIDs = new ArrayList<>(); - //ContactGroup groupp; - for(ContactGroup group : contactList.getContactGroups()) - for (ContactItem item : group.getContactItems()) - { - if(item.isAvailable() && !onlineJIDs.contains(item.getJID())) - { - CheckNode itemNode = new CheckNode(item.getDisplayName(), false, item.getIcon()); - itemNode.setAssociatedObject(item.getJID()); - groupNode.add(itemNode); - nodes.add(itemNode); - onlineJIDs.add(item.getJID()); - } - } - - // Build out from Roster - - for (ContactGroup group : contactList.getContactGroups()) { - groupName = group.getGroupName(); - if (!group.hasAvailableContacts()) { - continue; - } - groupNode = new CheckNode(groupName); - groupNodes.add(groupNode); - rosterNode.add(groupNode); - - // Now add contact items from contact group. - for (ContactItem item : group.getContactItems()) { - CheckNode itemNode = new CheckNode(item.getDisplayName(), false, item.getIcon()); - itemNode.setAssociatedObject(item.getJID()); - groupNode.add(itemNode); - nodes.add(itemNode); - } - - final List offlineContacts = new ArrayList<>( group.getOfflineContacts() ); - Collections.sort(offlineContacts, ContactList.ContactItemComparator); - - for (ContactItem item : offlineContacts) { - CheckNode itemNode = new CheckNode(item.getDisplayName(), false, item.getIcon()); - itemNode.setAssociatedObject(item.getJID()); - groupNode.add(itemNode); - nodes.add(itemNode); - } - } - - messageBox = new ChatInputEditor(); - normalMessageButton = new JRadioButton(Res.getString("message.normal")); - JRadioButton alertMessageButton = new JRadioButton(Res.getString("message.alert.notify")); - - ButtonGroup group = new ButtonGroup(); - group.add(normalMessageButton); - group.add(alertMessageButton); - - final JScrollPane pane = new JScrollPane(messageBox); - pane.setBorder(BorderFactory.createTitledBorder(Res.getString("label.message").replace("&", ""))); - - final JScrollPane treePane = new JScrollPane(checkTree); - treePane.setBorder(BorderFactory.createTitledBorder(Res.getString("message.send.to.these.people"))); - treePane.getVerticalScrollBar().setBlockIncrement(200); - treePane.getVerticalScrollBar().setUnitIncrement(20); - // Add to UI - add(pane, new GridBagConstraints(0, 0, 1, 1, 0.5, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - add(normalMessageButton, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(alertMessageButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 5, 2, 5), 0, 0)); - add(treePane, new GridBagConstraints(1, 0, 1, 3, 0.5, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, 5, 2, 5), 0, 0)); - add(OfflineUsers, new GridBagConstraints(1, 3, 1, 0, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, 5, 2, 5), 0, 0)); - - OfflineUsers.addActionListener( e -> hideOfflineUsers() ); - - normalMessageButton.setSelected(true); - checkTree.expandTree(); - - // get list of selected users - java.util.Collection selectedUsers = contactList.getSelectedUsers(); - // if selected users is 1 or less, - // don't per-select in dialog window (see SPARK-1088) - if (selectedUsers.size() > 1) { - // Iterate through selected users. - for (ContactItem item : selectedUsers) { - for (CheckNode node : nodes) { - if (node.getAssociatedObject().toString().equals(item.getJID())) { - node.setSelected(true); - } - } - } - } - } - - public void invokeDialog(ContactGroup group) { - for (CheckNode node : groupNodes) { - if (node.getUserObject().toString().equals(group.getGroupName())) { - node.setSelected(true); - } - } - - invokeDialog(); - } - - /** - * Displays the broadcast dialog. - */ - public void invokeDialog() { - final JDialog dlg; - - TitlePanel titlePanel; - - // Create the title panel for this dialog - titlePanel = new TitlePanel(Res.getString("title.broadcast.message"), Res.getString("message.enter.broadcast.message"), null, true); - - // Construct main panel w/ layout. - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(titlePanel, BorderLayout.NORTH); - - // The user should only be able to close this dialog. - JButton okButton = new JButton(Res.getString("ok")); - JButton closeButton = new JButton(Res.getString("close")); - - mainPanel.add(this,BorderLayout.CENTER); - - JPanel buttonpanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); - buttonpanel.add(okButton); - buttonpanel.add(closeButton); - - mainPanel.add(buttonpanel,BorderLayout.SOUTH); - - dlg = new JDialog(SparkManager.getMainWindow(), Res.getString("broadcast")); - dlg.setContentPane(mainPanel); - dlg.pack(); - dlg.setSize(800, 600); - dlg.setResizable(false); - dlg.setLocationRelativeTo(SparkManager.getMainWindow()); - - // Add listener - okButton.addActionListener( e -> { -try -{ -if (sendBroadcasts(dlg)) { -dlg.setVisible(false); -} -} -catch ( SmackException.NotConnectedException e1 ) -{ -Log.warning( "Unable to broadcast.", e1 ); -} - -} ); - - closeButton.addActionListener( e -> dlg.setVisible(false) ); - - dlg.setVisible(true); - dlg.toFront(); - dlg.requestFocus(); - - messageBox.requestFocus(); - - } - - private void hideOfflineUsers() { - - int i; - if (OfflineUsers.isSelected()) { - final ContactList contactList = SparkManager.getWorkspace() - .getContactList(); - i = 0; - for (CheckNode node : nodes) { - if (contactList.getContactItemByDisplayName(node.toString()) - .getPresence().getType() == Presence.Type.unavailable) { - if (node.getParent() != null) { - TreeNode parent = node.getParent(); - TreeNode[] path = ((DefaultTreeModel) checkTree - .getTree().getModel()).getPathToRoot(parent); - ((DefaultTreeModel) checkTree.getTree().getModel()) - .removeNodeFromParent(node); - checkTree.getTree() - .setSelectionPath(new TreePath(path)); - NodesGroups.add( new ArrayList<>()); - NodesGroups.get(i).add(parent); - NodesGroups.get(i).add(node); - i++; - } - } - } - for (int x = 0; x < groupNodes.size(); x++) { - if (groupNodes.get(x).toString() - .equals(Res.getString("group.offline"))) { - OfflineGroup = x; - TreeNode parent = groupNodes.get(x).getParent(); - TreeNode[] path = ((DefaultTreeModel) checkTree.getTree() - .getModel()).getPathToRoot(parent); - ((DefaultTreeModel) checkTree.getTree().getModel()) - .removeNodeFromParent(groupNodes.get(x)); - checkTree.getTree().setSelectionPath(new TreePath(path)); - } - } - } else { - i = 0; - DefaultMutableTreeNode child = groupNodes.get(OfflineGroup); - ((DefaultTreeModel) checkTree.getTree().getModel()).insertNodeInto( - child, rosterNode, rosterNode.getChildCount()); - TreeNode[] path = ((DefaultTreeModel) checkTree.getTree() - .getModel()).getPathToRoot(rosterNode); - checkTree.getTree().expandPath(new TreePath(path)); - checkTree.expandTree(); - for (CheckNode node : nodes) { - if (node.getParent() == null) { - child = (CheckNode) NodesGroups.get(i).get(1); - ((DefaultTreeModel) checkTree.getTree().getModel()) - .insertNodeInto(child, ((CheckNode) NodesGroups - .get(i).get(0)), ((CheckNode) NodesGroups - .get(i).get(0)).getChildCount()); - path = ((DefaultTreeModel) checkTree.getTree().getModel()) - .getPathToRoot(node); - checkTree.getTree().expandPath(new TreePath(path)); - checkTree.expandTree(); - i++; - } - } - } - } - - /** - * Sends a broadcast message to all users selected. - * @param dlg - */ - private boolean sendBroadcasts(JDialog dlg) throws SmackException.NotConnectedException - { - final Set jids = new HashSet<>(); - - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - - for (CheckNode node : nodes) { - if (node.isSelected()) { - String jid = (String)node.getAssociatedObject(); - jids.add(jid); - } - } - - if(jids.size() == 0) - { - JOptionPane.showMessageDialog(dlg, Res.getString("message.broadcast.no.user.selected"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - return false; - } - - String text = messageBox.getText(); - if (!ModelUtil.hasLength(text)) { - JOptionPane.showMessageDialog(dlg, Res.getString("message.broadcast.no.text"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - return false; - } - - for (String jid : jids) { - final Message message = new Message(); - message.setTo(jid); - message.setBody(text); - - if (normalMessageButton.isSelected()) { - message.setType(Message.Type.normal); - } - else { - message.setType(Message.Type.headline); - } - SparkManager.getConnection().sendStanza(message); - } - - return true; - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/alerts/BroadcastPlugin.java b/src/java/org/jivesoftware/sparkimpl/plugin/alerts/BroadcastPlugin.java deleted file mode 100644 index 060565e3f..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/alerts/BroadcastPlugin.java +++ /dev/null @@ -1,512 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.alerts; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; -import java.io.File; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; - -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.StanzaListener; -import org.jivesoftware.smack.filter.StanzaFilter; -import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Message.Type; -import org.jivesoftware.smack.packet.Stanza; -import org.jivesoftware.smackx.delay.packet.DelayInformation; -import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.UserManager; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.component.tabbedPane.SparkTab; -import org.jivesoftware.spark.plugin.ContextMenuListener; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.ChatContainer; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomNotFoundException; -import org.jivesoftware.spark.ui.ContactGroup; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.ui.MessageListener; -import org.jivesoftware.spark.ui.SparkTabHandler; -import org.jivesoftware.spark.ui.TranscriptWindow; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.ui.status.StatusBar; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; -import org.jivesoftware.sparkimpl.preference.sounds.SoundPreference; -import org.jivesoftware.sparkimpl.preference.sounds.SoundPreferences; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -/** - * Handles broadcasts from server and allows for roster wide broadcasts. - */ -public class BroadcastPlugin extends SparkTabHandler implements Plugin, StanzaListener { - - private Set broadcastRooms = new HashSet<>(); - - public void initialize() { - boolean enabled = Enterprise.containsFeature(Enterprise.BROADCAST_FEATURE); - if (!enabled) { - return; - } - - // Add as ContainerDecoratr - SparkManager.getChatManager().addSparkTabHandler(this); - - StanzaFilter serverFilter = new StanzaTypeFilter(Message.class); - SparkManager.getConnection().addAsyncStanzaListener(this, serverFilter); - - // Register with action menu - final JMenu actionsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions")); - JMenuItem broadcastMenu = new JMenuItem(Res.getString("title.broadcast.message"), SparkRes.getImageIcon(SparkRes.MEGAPHONE_16x16)); - ResourceUtils.resButton(broadcastMenu, Res.getString("title.broadcast.message")); - actionsMenu.add(broadcastMenu); - broadcastMenu.addActionListener( e -> broadcastToRoster() ); - - // Register with action menu - JMenuItem startConversationtMenu = new JMenuItem("", SparkRes.getImageIcon(SparkRes.SMALL_MESSAGE_IMAGE)); - ResourceUtils.resButton(startConversationtMenu, Res.getString("menuitem.start.a.chat")); - actionsMenu.add(startConversationtMenu,0); - startConversationtMenu.addActionListener( e -> { - ContactList contactList = SparkManager.getWorkspace().getContactList(); - Collection selectedUsers = contactList.getSelectedUsers(); - String selectedUser = ""; - Iterator selectedUsersIterator = selectedUsers.iterator(); - if (selectedUsersIterator.hasNext()) { - ContactItem contactItem = selectedUsersIterator.next(); - selectedUser = contactItem.getJID(); - } - - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - UIManager.put("OptionPane.cancelButtonText", Res.getString("cancel")); - - String jid = (String)JOptionPane.showInputDialog(SparkManager.getMainWindow(), Res.getString("label.enter.address"), Res.getString("title.start.chat"), JOptionPane.QUESTION_MESSAGE, null, null, selectedUser); - if (ModelUtil.hasLength(jid) && ModelUtil.hasLength( XmppStringUtils.parseDomain(jid))) { - if (ModelUtil.hasLength(jid) && jid.indexOf('@') == -1) { - // Append server address - jid = jid + "@" + SparkManager.getConnection().getServiceName(); - } - - String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid); - - jid = UserManager.escapeJID(jid); - ChatRoom chatRoom = SparkManager.getChatManager().createChatRoom(jid, nickname, nickname); - SparkManager.getChatManager().getChatContainer().activateChatRoom(chatRoom); - } - } ); - - - - // Add send to selected users. - final ContactList contactList = SparkManager.getWorkspace().getContactList(); - contactList.addContextMenuListener(new ContextMenuListener() { - public void poppingUp(Object component, JPopupMenu popup) { - if (component instanceof ContactGroup) { - final ContactGroup group = (ContactGroup)component; - Action broadcastMessageAction = new AbstractAction() { - private static final long serialVersionUID = -6411248110270296726L; - - public void actionPerformed(ActionEvent e) { - broadcastToGroup(group); - } - }; - - broadcastMessageAction.putValue(Action.NAME, Res.getString("menuitem.broadcast.to.group")); - broadcastMessageAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.MEGAPHONE_16x16)); - popup.add(broadcastMessageAction); - } - } - - public void poppingDown(JPopupMenu popup) { - - } - - public boolean handleDefaultAction(MouseEvent e) { - return false; - } - }); - - // Add Broadcast to roster - StatusBar statusBar = SparkManager.getWorkspace().getStatusBar(); - - - RolloverButton broadcastToRosterButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.MEGAPHONE_16x16)); - broadcastToRosterButton.setToolTipText(Res.getString("message.send.a.broadcast")); - - statusBar.invalidate(); - statusBar.validate(); - statusBar.repaint(); - - broadcastToRosterButton.addActionListener( e -> broadcastToRoster() ); - } - - public void shutdown() { - - } - - public boolean canShutDown() { - return false; - } - - public void processPacket(final Stanza stanza) { - SwingUtilities.invokeLater( () -> { - try { - final Message message = (Message)stanza; - - // Do not handle errors or offline messages - final DelayInformation offlineInformation = message.getExtension("delay", "urn:xmpp:delay"); - if (offlineInformation != null || message.getError() != null) { - return; - } - - final JivePropertiesExtension extension = ((JivePropertiesExtension) message.getExtension( JivePropertiesExtension.NAMESPACE )); - final boolean broadcast = extension != null && extension.getProperty( "broadcast" ) != null; - - if ((broadcast || message.getType() == Type.normal - || message.getType() == Type.headline) && message.getBody() != null) { - showAlert((Message)stanza); - } - else { - String host = SparkManager.getSessionManager().getServerAddress(); - String from = stanza.getFrom() != null ? stanza.getFrom() : ""; - if (host.equalsIgnoreCase(from) || !ModelUtil.hasLength(from)) { - showAlert((Message)stanza); - } - } - } - catch (Exception e) { - Log.error(e); - } - } ); - - } - - /** - * Show Server Alert. - * - * @param message the message to show. - * @param type - */ - private void showAlert(Message message) { - Type type = message.getType(); - // Do not show alert if the message is an error. - if (message.getError() != null) { - return; - } - - final String body = message.getBody(); - String subject = message.getSubject(); - - StringBuilder buf = new StringBuilder(); - if (subject != null) { - buf.append(Res.getString("subject")).append(": ").append(subject); - buf.append("\n\n"); - } - - buf.append(body); - - String from = message.getFrom() != null ? message.getFrom() : ""; - - final TranscriptWindow window = new TranscriptWindow(); - window.insertPrefixAndMessage(null, buf.toString(), ChatManager.TO_COLOR); - - JPanel p = new JPanel(); - p.setLayout(new BorderLayout()); - p.add(window, BorderLayout.CENTER); - p.setBorder(BorderFactory.createLineBorder(Color.lightGray)); - - // Count the number of linebreaks
        and \n - - String s = message.getBody(); - s = s.replace("
        ", "\n"); - s = s.replace("
        ", "\n"); - int linebreaks = org.jivesoftware.spark.util.StringUtils. - countNumberOfOccurences(s,'\n'); - - // Currently Serverbroadcasts dont contain Subjects, so this might be a MOTD message - boolean mightbeMOTD = message.getSubject()!=null; - - if (!from.contains("@")) { - // if theres no "@" it means the message came from the server - if (Default.getBoolean(Default.BROADCAST_IN_CHATWINDOW) - || linebreaks > 20 || message.getBody().length() > 1000 || mightbeMOTD) { - // if we have more than 20 linebreaks or the message is longer - // than 1000characters we should broadcast - // in a normal chatwindow - broadcastInChat(message); - } else { - broadcastWithPanel(message); - } - - } - else if (message.getFrom() != null) { - userToUserBroadcast(message, type, from); - } - } - - /** - * Handles Broadcasts made from a user to another user - * - * @param message - * the message - * @param type - * the message type - * @param from - * the sender - */ - private void userToUserBroadcast(Message message, Type type, String from) { - String jid = XmppStringUtils.parseBareJid(from); - String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid); - ChatManager chatManager = SparkManager.getChatManager(); - ChatContainer container = chatManager.getChatContainer(); - - ChatRoomImpl chatRoom; - try { - chatRoom = (ChatRoomImpl)container.getChatRoom(jid); - } - catch (ChatRoomNotFoundException e) { - chatRoom = new ChatRoomImpl(jid, nickname, nickname); - SparkManager.getChatManager().getChatContainer().addChatRoom(chatRoom); - } - - Message m = new Message(); - m.setBody(message.getBody()); - m.setTo(message.getTo()); - - String name = XmppStringUtils.parseLocalpart(message.getFrom()); - - String broadcasttype = type == Message.Type.normal ? Res.getString("broadcast") : Res.getString("message.alert.notify"); - //m.setFrom(name +" "+broadcasttype); - m.setFrom(nickname+" - "+broadcasttype); - - chatRoom.getTranscriptWindow().insertMessage(m.getFrom(), message, ChatManager.FROM_COLOR, new Color(0,0,0,0)); - chatRoom.addToTranscript(m,true); - chatRoom.increaseUnreadMessageCount(); - broadcastRooms.add(chatRoom); - - - LocalPreferences pref = SettingsManager.getLocalPreferences(); - if (pref.getShowToasterPopup()) { - SparkToaster toaster = new SparkToaster(); - toaster.setDisplayTime(30000); - toaster.setBorder(BorderFactory.createBevelBorder(0)); - toaster.setTitle(nickname+ " - "+broadcasttype); - toaster.showToaster(message.getBody()); - } - - SparkManager.getChatManager().fireGlobalMessageReceievedListeners(chatRoom, message); - - DelayInformation inf = message.getExtension("delay", "urn:xmpp:delay"); - if (inf == null) { - SoundPreference soundPreference = (SoundPreference)SparkManager.getPreferenceManager().getPreference(new SoundPreference().getNamespace()); - SoundPreferences preferences = soundPreference.getPreferences(); - if (preferences.isPlayIncomingSound()) { - File incomingFile = new File(preferences.getIncomingSound()); - SparkManager.getSoundManager().playClip(incomingFile); - } - } - - chatRoom.addMessageListener(new MessageListener() { - boolean waiting = true; - - public void messageReceived(ChatRoom room, Message message) { - removeAsBroadcast(room); - } - - public void messageSent(ChatRoom room, Message message) { - removeAsBroadcast(room); - } - - private void removeAsBroadcast(ChatRoom room) { - if (waiting) { - broadcastRooms.remove(room); - - // Notify decorators - SparkManager.getChatManager().notifySparkTabHandlers(room); - waiting = false; - } - } - }); - } - - /** - * Broadcasts a message to all in the roster. - */ - private void broadcastToRoster() { - final BroadcastDialog broadcastDialog = new BroadcastDialog(); - broadcastDialog.invokeDialog(); - } - - /** - * Broadcasts a message to all selected users. - * - * @param group the Contact Group to send the messages to. - */ - private void broadcastToGroup(ContactGroup group) { - final BroadcastDialog broadcastDialog = new BroadcastDialog(); - broadcastDialog.invokeDialog(group); - } - - public void uninstall() { - // Do nothing. - } - - - public boolean isTabHandled(SparkTab tab, Component component, boolean isSelectedTab, boolean chatFrameFocused) { - if (component instanceof ChatRoom) { - ChatRoom chatroom = (ChatRoom)component; - if (broadcastRooms.contains(chatroom)) { - final ChatRoomImpl room = (ChatRoomImpl)component; - tab.setIcon(SparkRes.getImageIcon(SparkRes.INFORMATION_IMAGE)); - String nickname = room.getTabTitle(); - nickname = Res.getString("message.broadcast.from", nickname); - tab.setTabTitle(nickname); - - - if ((!chatFrameFocused || !isSelectedTab) && room.getUnreadMessageCount() > 0) { - // Make tab red. - tab.setTitleColor(Color.red); - tab.setTabBold(true); - } - else { - tab.setTitleColor(Color.black); - tab.setTabFont(tab.getDefaultFont()); - room.clearUnreadMessageCount(); - } - - - return true; - } - } - - return false; - } - - /** - * Displays the Serverbroadcast like all other messages - * in its on chatcontainer with transcript history - * @param message - * @param from - */ - private void broadcastInChat(Message message) - { - String from = message.getFrom() != null ? message.getFrom() : ""; - ChatManager chatManager = SparkManager.getChatManager(); - ChatContainer container = chatManager.getChatContainer(); - - ChatRoomImpl chatRoom; - try { - chatRoom = (ChatRoomImpl)container.getChatRoom(from); - } - catch (ChatRoomNotFoundException e) { - String windowtitle = message.getSubject()!=null ? message.getSubject() : Res.getString("administrator"); - chatRoom = new ChatRoomImpl("serveralert@" + from, Res.getString("broadcast"), windowtitle); - chatRoom.getBottomPanel().setVisible(false); - chatRoom.hideToolbar(); - SparkManager.getChatManager().getChatContainer().addChatRoom(chatRoom); - } - - - chatRoom.getTranscriptWindow().insertNotificationMessage(message.getBody(), ChatManager.NOTIFICATION_COLOR); - broadcastRooms.add(chatRoom); - } - - /** - * Displays a Serverbroadcast within a JFrame
        - * Messages can contain html-tags - * @param message - */ - private void broadcastWithPanel(Message message) { - - String title = Res.getString("message.broadcast.from", - Res.getString("administrator")); - final JFrame alert = new JFrame(title); - - alert.setLayout(new GridBagLayout()); - alert.setIconImage(SparkRes.getImageIcon(SparkRes.MAIN_IMAGE) - .getImage()); - String msg = "" + message.getBody().replace("\n", "
        ")+ ""; - - JLabel icon = new JLabel(SparkRes.getImageIcon(SparkRes.ALERT)); - JLabel alertlabel = new JLabel(msg); - - JButton close = new JButton(Res.getString("close")); - - close.addActionListener(new AbstractAction() { - private static final long serialVersionUID = -3822361866008590946L; - - @Override - public void actionPerformed(ActionEvent e) { - alert.setVisible(false); - alert.dispose(); - } - }); - - alert.add(icon,new GridBagConstraints(0,0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0, 0)); - alert.add(alertlabel, new GridBagConstraints(1,0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5,5,5,5), 0, 0)); - alert.add(close, new GridBagConstraints(1,1, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0, 0)); - - alert.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - alert.setVisible(true); - - alert.setMinimumSize(new Dimension(340, 200)); - alert.pack(); - Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); - int x = (dim.width - alert.getSize().width) / 2; - int y = (dim.height - alert.getSize().height) / 2; - alert.setLocation(x, y); - alert.toFront(); - alert.requestFocus(); - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/alerts/BuzzPacket.java b/src/java/org/jivesoftware/sparkimpl/plugin/alerts/BuzzPacket.java deleted file mode 100644 index 871e604c6..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/alerts/BuzzPacket.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.alerts; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.packet.ExtensionElement; -import org.jivesoftware.smack.provider.ExtensionElementProvider; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; - -/** - * XEP-0224 Compliance
        - * see http://xmpp.org/extensions/xep-0224.html - */ -public class BuzzPacket implements ExtensionElement -{ - public static final String ELEMENT_NAME = "attention"; - - public static final String NAMESPACE = "urn:xmpp:attention:0"; - - public String getElementName() { - return ELEMENT_NAME; - } - - public String getNamespace() { - return NAMESPACE; - } - - // TODO 2.7.0 remove buzz only attention gets to stay - public String toXML() { - return "<" + getElementName() + " xmlns=\"" + getNamespace() - + "\"/>"; - } - - public static class Provider extends ExtensionElementProvider { - - public Provider() { - } - - @Override - public BuzzPacket parse( XmlPullParser parser, int i ) throws XmlPullParserException, IOException, SmackException - { - return new BuzzPacket(); - } - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/alerts/BuzzPlugin.java b/src/java/org/jivesoftware/sparkimpl/plugin/alerts/BuzzPlugin.java deleted file mode 100644 index df17f5d68..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/alerts/BuzzPlugin.java +++ /dev/null @@ -1,162 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.alerts; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.provider.ProviderManager; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.ChatFrame; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomListener; -import org.jivesoftware.spark.ui.ChatRoomNotFoundException; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.util.SwingTimerTask; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -import java.util.TimerTask; - -import javax.swing.SwingUtilities; - -/** - * - */ -public class BuzzPlugin implements Plugin { - - private static final String ELEMENTNAME = "attention"; - private static final String NAMESPACE = "urn:xmpp:attention:0"; - - private static final String ELEMENTNAME_OLD = "buzz"; - private static final String NAMESPACE_OLD = "http://www.jivesoftware.com/spark"; - - public void initialize() { - ProviderManager.addExtensionProvider(ELEMENTNAME, - NAMESPACE, new BuzzPacket.Provider()); - - ProviderManager.addExtensionProvider(ELEMENTNAME_OLD, - NAMESPACE_OLD, new BuzzPacket.Provider() ); - - SparkManager.getConnection().addAsyncStanzaListener( stanza -> { - if (stanza instanceof Message) { - final Message message = (Message) stanza; - - boolean buzz = message.getExtension(ELEMENTNAME_OLD, - NAMESPACE_OLD) != null - || message.getExtension(ELEMENTNAME, NAMESPACE) != null; - if (buzz) { - SwingUtilities.invokeLater( () -> shakeWindow(message) ); - } - } - }, new StanzaTypeFilter(Message.class)); - - SparkManager.getChatManager().addChatRoomListener( - new ChatRoomListener() { - public void chatRoomOpened(final ChatRoom room) { - TimerTask task = new SwingTimerTask() { - public void doRun() { - addBuzzFeatureToChatRoom(room); - } - }; - - TaskEngine.getInstance().schedule(task, 100); - } - - public void chatRoomLeft(ChatRoom room) { - } - - public void chatRoomClosed(ChatRoom room) { - } - - public void chatRoomActivated(ChatRoom room) { - } - - public void userHasJoined(ChatRoom room, String userid) { - } - - public void userHasLeft(ChatRoom room, String userid) { - } - }); - } - - private void addBuzzFeatureToChatRoom(final ChatRoom room) { - if (room instanceof ChatRoomImpl) { - // Add Button to toolbar - if (!SettingsManager.getLocalPreferences().isBuzzEnabled()) { - return; - } - - new BuzzRoomDecorator(room); - } - - } - - private void shakeWindow(Message message) { - - String bareJID = XmppStringUtils.parseBareJid(message.getFrom()); - ContactItem contact = SparkManager.getWorkspace().getContactList() - .getContactItemByJID(bareJID); - String nickname = XmppStringUtils.parseLocalpart(bareJID); - if (contact != null) { - nickname = contact.getDisplayName(); - } - - ChatRoom room; - try { - room = SparkManager.getChatManager().getChatContainer() - .getChatRoom(bareJID); - } catch (ChatRoomNotFoundException e) { - // Create the room if it does not exist. - room = SparkManager.getChatManager().createChatRoom(bareJID, - nickname, nickname); - } - - ChatFrame chatFrame = SparkManager.getChatManager().getChatContainer() - .getChatFrame(); - if (chatFrame != null) { - if (SettingsManager.getLocalPreferences().isBuzzEnabled()) { - chatFrame.buzz(); - SparkManager.getChatManager().getChatContainer() - .activateChatRoom(room); - } - } - - // Insert offline message - room.getTranscriptWindow().insertNotificationMessage( - Res.getString("message.buzz.message", nickname), - ChatManager.NOTIFICATION_COLOR); - room.scrollToBottom(); - } - - public void shutdown() { - } - - public boolean canShutDown() { - return true; - } - - public void uninstall() { - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/alerts/BuzzRoomDecorator.java b/src/java/org/jivesoftware/sparkimpl/plugin/alerts/BuzzRoomDecorator.java deleted file mode 100644 index 7ee0f06b5..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/alerts/BuzzRoomDecorator.java +++ /dev/null @@ -1,101 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.alerts; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.TimerTask; - -import javax.swing.JButton; -import javax.swing.JLabel; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.util.SwingTimerTask; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.UIComponentRegistry; -import org.jivesoftware.spark.util.log.Log; - -/** - * Adds a simple buzz operation button the each newly created ChatRoom. - * - * @author Derek DeMoro - */ -public class BuzzRoomDecorator implements ActionListener { - - private ChatRoom chatRoom; - private JButton buzzButton; - - - public BuzzRoomDecorator(ChatRoom chatRoom) { - this.chatRoom = chatRoom; - - buzzButton = UIComponentRegistry.getButtonFactory().createBuzzButton(); - buzzButton.setToolTipText(Res - .getString("message.buzz.alert.notification")); - buzzButton.addActionListener(this); - - final JLabel dividerLabel = UIComponentRegistry.getButtonFactory().createDivider(); - if (dividerLabel != null) { - chatRoom.addEditorComponent(dividerLabel); - } - chatRoom.addEditorComponent(buzzButton); - } - - public void addBuzzButton(BuzzRoomDecorator buzzer) - { - final JLabel dividerLabel = new JLabel(SparkRes.getImageIcon("DIVIDER_IMAGE")); - chatRoom.addEditorComponent(dividerLabel); - chatRoom.addEditorComponent(buzzer.buzzButton); - } - - public void actionPerformed(ActionEvent e) { - final String jid = ((ChatRoomImpl)chatRoom).getParticipantJID(); - Message message = new Message(); - message.setTo(jid); - message.addExtension(new BuzzPacket()); - try - { - SparkManager.getConnection().sendStanza(message); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to send stanza to " + jid, e1 ); - } - - chatRoom.getTranscriptWindow().insertNotificationMessage(Res.getString("message.buzz.sent"), ChatManager.NOTIFICATION_COLOR); - buzzButton.setEnabled(false); - - // Enable the button after 30 seconds to prevent abuse. - final TimerTask enableTask = new SwingTimerTask() { - public void doRun() { - buzzButton.setEnabled(true); - } - }; - - TaskEngine.getInstance().schedule(enableTask, 30000); - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/alerts/SparkToaster.java b/src/java/org/jivesoftware/sparkimpl/plugin/alerts/SparkToaster.java deleted file mode 100644 index 416655017..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/alerts/SparkToaster.java +++ /dev/null @@ -1,728 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.alerts; - -/** - * SparkToaster is an improvement of Java Toaster which is a java utility class for your swing applications - * that show an animate box coming from the bottom of your screen - * with a notification message and/or an associated image - * (like msn online/offline notifications). - * - * Toaster panel in windows system follow the taskbar; So if - * the taskbar is into the bottom the panel coming from the bottom - * and if the taskbar is on the top then the panel coming from the top. - * - * This is a simple example of utilization: - * - * import com.nitido.utils.toaster.*; - * import javax.swing.*; - * - */ - - -import java.awt.Color; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.EventQueue; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GraphicsEnvironment; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Image; -import java.awt.Insets; -import java.awt.Rectangle; -import java.awt.Window; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.geom.AffineTransform; - -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.border.Border; - -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.spark.PresenceManager; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.util.ImageCombiner; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.log.Log; - -/** - * Class to show tosters in multiplatform - * - * @author daniele piras - */ -public class SparkToaster { - - /** - * The default Hand cursor. - */ - public static final Cursor HAND_CURSOR = new Cursor(Cursor.HAND_CURSOR); - - /** - * The default Text Cursor. - */ - public static final Cursor DEFAULT_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR); - - // Width of the toster - private int toasterWidth = 200; - - // Height of the toster - private int toasterHeight = 150; - - // Step for the toaster - private int step = 20; - - // Step time - private int stepTime = 20; - - // Show time - private int displayTime = 3000; - - // Current number of toaster... - private int currentNumberOfToaster = 0; - - // Last opened toaster - private int maxToaster = 0; - - // Font used to display message - private Font font; - - // Color for border - private Color borderColor; - - // Color for toaster - private Color toasterColor; - - // Set message color - private Color messageColor; - - // Set the margin - int margin; - - // Flag that indicate if use alwaysOnTop or not. - // method always on top start only SINCE JDK 5 ! - boolean useAlwaysOnTop = true; - - private String title; - - private Border border; - - - private Action customAction; - - private Window window; - - private JPanel mainPanel = new JPanel(); - - private TitleLabel titleLabel; - - private boolean hideable = true; - - /** - * Constructor to initialized toaster component... - */ - public SparkToaster() { - // Set default font... - font = new Font("Dialog", Font.PLAIN, 11); - - // Border color - borderColor = new Color(245, 153, 15); - toasterColor = Color.WHITE; - messageColor = Color.BLACK; - useAlwaysOnTop = true; - } - - /** - * Class that rappresent a single toaster - * - * @author daniele piras - */ - class SingleToaster extends javax.swing.JWindow { - private static final long serialVersionUID = 1L; - - // Label to store Icon - - // Text area for the message - private JTextArea message = new JTextArea(); - - /** - * Simple costructor that initialized components... - */ - public SingleToaster() { - initComponents(); - } - - /** - * Function to initialized components - */ - private void initComponents() { - message.setFont(getToasterMessageFont()); - - - mainPanel.setBackground(Color.white); - message.setOpaque(false); - mainPanel.setLayout(new GridBagLayout()); - message.setMargin(new Insets(2, 2, 2, 2)); - message.setLineWrap(true); - message.setWrapStyleWord(true); - - message.setForeground(getMessageColor()); - titleLabel = new TitleLabel(getTitle(), true); - titleLabel.setForeground(new Color(87, 166, 211)); - titleLabel.setFont(new Font("Dialog", Font.BOLD, 13)); - - mainPanel.add(titleLabel, new GridBagConstraints(0, 0, 3, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); - - titleLabel.getCloseButton().addActionListener( e -> { - setVisible(false); - dispose(); - } ); - - if (border != null) { - mainPanel.setBorder(border); - } - - message.setForeground(Color.BLACK); - - message.setOpaque(false); - - getContentPane().add(mainPanel); - - - mainPanel.addMouseListener(new PaneMouseListener()); - message.addMouseListener(new PaneMouseListener()); - - pack(); - setSize(toasterWidth, toasterHeight); - mainPanel.setBorder(BorderFactory.createLineBorder(Color.lightGray)); - } - - - /** - * Start toaster animation... - */ - public void animate() { - (new Animation(this)).start(); - } - - private class PaneMouseListener extends MouseAdapter { - - public void mouseClicked(MouseEvent e) { - if (customAction != null) { - customAction.actionPerformed(null); - } - - if (hideable) { - setVisible(false); - dispose(); - } - } - - public void mouseEntered(MouseEvent e) { - message.setCursor(HAND_CURSOR); - setCursor(HAND_CURSOR); - } - - public void mouseExited(MouseEvent e) { - message.setCursor(DEFAULT_CURSOR); - setCursor(DEFAULT_CURSOR); - } - } - } - - - /** - * Class that manage the animation - */ - class Animation extends Thread { - SingleToaster toaster; - - public Animation(SingleToaster toaster) { - this.toaster = toaster; - } - - - /** - * Animate vertically the toaster. The toaster could be moved from bottom - * to upper or to upper to bottom - * - * @param posx X position for toaster. - * @param fromY Y from position - * @param toY Y to position - * @throws InterruptedException if animation is interrupted - */ - protected void animateVertically(int posx, int fromY, int toY) throws InterruptedException { - - toaster.setLocation(posx, fromY); - if (toY < fromY) { - for (int i = fromY; i > toY; i -= step) { - toaster.setLocation(posx, i); - Thread.sleep(stepTime); - } - } - else { - for (int i = fromY; i < toY; i += step) { - toaster.setLocation(posx, i); - Thread.sleep(stepTime); - } - } - toaster.setLocation(posx, toY); - toaster.invalidate(); - toaster.validate(); - toaster.repaint(); - } - - public void run() { - try { - boolean animateFromBottom = true; - GraphicsEnvironment ge = GraphicsEnvironment - .getLocalGraphicsEnvironment(); - Rectangle screenRect = ge.getMaximumWindowBounds(); - - int screenHeight = screenRect.height; - - int startYPosition; - int stopYPosition; - - if (screenRect.y > 0) { - animateFromBottom = false; // Animate from top! - } - - int maxToasterInSceen = screenHeight / toasterHeight; - - - int posx = screenRect.width - toasterWidth - 1; - - toaster.setLocation(posx, screenHeight); - try { - EventQueue.invokeAndWait( () -> toaster.setVisible(true) ); - } - catch(Exception e) - { - Log.error(e); - } - if (useAlwaysOnTop) { - toaster.setAlwaysOnTop(true); - } - - if (animateFromBottom) { - startYPosition = screenHeight; - stopYPosition = startYPosition - toasterHeight - 1; - if (currentNumberOfToaster > 0) { - stopYPosition = stopYPosition - (maxToaster % maxToasterInSceen * toasterHeight); - } - else { - maxToaster = 0; - } - } - else { - startYPosition = screenRect.y - toasterHeight; - stopYPosition = screenRect.y; - - if (currentNumberOfToaster > 0) { - stopYPosition = stopYPosition + (maxToaster % maxToasterInSceen * toasterHeight); - } - else { - maxToaster = 0; - } - } - - currentNumberOfToaster++; - maxToaster++; - - - animateVertically(posx, startYPosition, stopYPosition); - Thread.sleep(displayTime); - animateVertically(posx, stopYPosition, startYPosition); - - currentNumberOfToaster--; - toaster.setVisible(false); - toaster.dispose(); - } - catch (Exception e) { - Log.error(e); - } - } - } - - - /** - * Show a toaster with the specified message and the associated icon. - * - * @param icon Icon to show in toaster popup. - * @param msg Message to show in toaster popup. - */ - public void showToaster(Icon icon, String msg) { - SingleToaster singleToaster = new SingleToaster(); - final JScrollPane pane = new JScrollPane(singleToaster.message); - pane.setOpaque(false); - pane.setBorder(BorderFactory.createEmptyBorder()); - pane.getViewport().setBackground(Color.white); - mainPanel.add(pane, new GridBagConstraints(1, 2, 3, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, 5, 2, 5), 0, 0)); - - - if (icon != null) { - titleLabel.setIcon(icon); - } - if (ModelUtil.hasLength(msg) && msg.startsWith("/me ")) { - msg = msg.replaceFirst("/me", getTitle()); - singleToaster.message.setForeground(Color.MAGENTA); - } - singleToaster.message.setText(msg); - singleToaster.message.setCaretPosition(0); - singleToaster.animate(); - window = singleToaster; - } - - /** - * Show a toaster with the specified message and the associated icon. - * - * @param title Title to use in toaster popup - * @param comp Component to add to toaster popup - */ - public void showToaster(final String title, final Component comp) { - SingleToaster singleToaster = new SingleToaster(); - mainPanel.add(comp, new GridBagConstraints(1, 2, 3, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, 0, 0, 0), 0, 0)); - - titleLabel.setTitle(title); - singleToaster.animate(); - window = singleToaster; - } - - public void showToaster(Icon icon) { - SingleToaster singleToaster = new SingleToaster(); - if (icon != null) { - titleLabel.setIcon(icon); - } - singleToaster.animate(); - window = singleToaster; - } - - public void showToaster() { - SingleToaster singleToaster = new SingleToaster(); - singleToaster.animate(); - window = singleToaster; - } - - /** - * Show a toaster with the specified message. - * - * @param msg Message to display. - */ - public void showToaster(String msg) { - showToaster(null, msg); - } - - /** - * @return Returns the font - */ - public Font getToasterMessageFont() { - return font; - } - - /** - * Set the font for the message - * - * @param f Font to set on toaster messages. - */ - public void setToasterMessageFont(Font f) { - font = f; - } - - - /** - * @return Returns the borderColor. - */ - public Color getBorderColor() { - return borderColor; - } - - - /** - * @param borderColor The borderColor to set. - */ - public void setBorderColor(Color borderColor) { - this.borderColor = borderColor; - } - - - /** - * @return Returns the displayTime. - */ - public int getDisplayTime() { - return displayTime; - } - - - /** - * @param displayTime The displayTime to set. - */ - public void setDisplayTime(int displayTime) { - this.displayTime = displayTime; - } - - - /** - * @return Returns the margin. - */ - public int getMargin() { - return margin; - } - - - /** - * @param margin The margin to set. - */ - public void setMargin(int margin) { - this.margin = margin; - } - - - /** - * @return Returns the messageColor. - */ - public Color getMessageColor() { - return messageColor; - } - - - /** - * @param messageColor The messageColor to set. - */ - public void setMessageColor(Color messageColor) { - this.messageColor = messageColor; - } - - - /** - * @return Returns the step. - */ - public int getStep() { - return step; - } - - - /** - * @param step The step to set. - */ - public void setStep(int step) { - this.step = step; - } - - - /** - * @return Returns the stepTime. - */ - public int getStepTime() { - return stepTime; - } - - - /** - * @param stepTime The stepTime to set. - */ - public void setStepTime(int stepTime) { - this.stepTime = stepTime; - } - - - /** - * @return Returns the toasterColor. - */ - public Color getToasterColor() { - return toasterColor; - } - - - /** - * @param toasterColor The toasterColor to set. - */ - public void setToasterColor(Color toasterColor) { - this.toasterColor = toasterColor; - } - - - /** - * @return Returns the toasterHeight. - */ - public int getToasterHeight() { - return toasterHeight; - } - - - /** - * @param toasterHeight The toasterHeight to set. - */ - public void setToasterHeight(int toasterHeight) { - this.toasterHeight = toasterHeight; - } - - - /** - * @return Returns the toasterWidth. - */ - public int getToasterWidth() { - return toasterWidth; - } - - - /** - * @param toasterWidth The toasterWidth to set. - */ - public void setToasterWidth(int toasterWidth) { - this.toasterWidth = toasterWidth; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public Border getBorder() { - return border; - } - - public void setBorder(Border border) { - this.border = border; - } - - public void setCustomAction(Action action) { - this.customAction = action; - } - - public void setComponent(Component comp) { - mainPanel.add(comp, new GridBagConstraints(1, 2, 3, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, 5, 2, 5), 0, 0)); - } - - public void close() { - if (window != null) { - window.dispose(); - } - } - - public Window getWindow() { - return window; - } - - public void hideTitle() { - titleLabel.setVisible(false); - } - - - class TitleLabel extends JPanel { - private static final long serialVersionUID = -5163519932953987400L; - private JLabel label; - private RolloverButton closeButton; - - public TitleLabel(String text, final boolean showCloseIcon) { - setLayout(new GridBagLayout()); - label = new JLabel(text); - label.setFont(new Font("Dialog", Font.BOLD, 11)); - label.setHorizontalTextPosition(JLabel.RIGHT); - label.setHorizontalAlignment(JLabel.LEFT); - - add(label, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - closeButton = new RolloverButton(SparkRes.getImageIcon(SparkRes.CLOSE_IMAGE)); - - if (showCloseIcon) { - add(closeButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - } - - setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.lightGray)); - } - - public void setIcon(Icon icon) { - if (icon.getIconHeight() > 64 || icon.getIconWidth() > 64) { - Image image = ImageCombiner.iconToImage(icon); - label.setIcon(new ImageIcon(image.getScaledInstance(-1, 64, Image.SCALE_SMOOTH))); - } else - { - label.setIcon(icon); - } - } - - public RolloverButton getCloseButton() { - return closeButton; - } - - public void setTitle(String title) { - label.setText(title); - } - - public JLabel getLabel() - { - return label; - } - - public void paintComponent(Graphics g) { - final Image backgroundImage = Default.getImageIcon(Default.TOP_BOTTOM_BACKGROUND_IMAGE).getImage(); - double scaleX = getWidth() / (double)backgroundImage.getWidth(null); - double scaleY = getHeight() / (double)backgroundImage.getHeight(null); - AffineTransform xform = AffineTransform.getScaleInstance(scaleX, scaleY); - ((Graphics2D)g).drawImage(backgroundImage, xform, this); - } - } - - public void setHidable(boolean hideable) { - this.hideable = hideable; - } - - /** - * Simple Example... - * - * @param args Command line args. - */ - public static void main(String[] args) { - SparkToaster toaster = new SparkToaster(); - toaster.setDisplayTime(30000); - toaster.setBorder(BorderFactory.createBevelBorder(0)); - toaster.setTitle(Res.getString("title.notification")); - - JButton button = new JButton("DDD"); - toaster.hideTitle(); - toaster.showToaster("HELLO", button); - - } - - public void setTitleAlert(Font font, Presence presence) { - final Icon presenceIcon = PresenceManager.getIconFromPresence(presence); - titleLabel.setIcon(presenceIcon); - titleLabel.getLabel().setFont(font); - } - -} - diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/chat/ChatArgumentsPlugin.java b/src/java/org/jivesoftware/sparkimpl/plugin/chat/ChatArgumentsPlugin.java deleted file mode 100644 index efbcad302..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/chat/ChatArgumentsPlugin.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.chat; - -import org.jivesoftware.Spark; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.conferences.ConferenceUtils; -import org.jxmpp.util.XmppStringUtils; - -public class ChatArgumentsPlugin implements Plugin { - - public void initialize() { - String start_chat_jid = Spark.getArgumentValue("start_chat_jid"); - String start_chat_muc = Spark.getArgumentValue("start_chat_muc"); - - if (start_chat_jid != null) { - String nickname = XmppStringUtils.parseLocalpart(start_chat_jid); - SparkManager.getChatManager().createChatRoom(start_chat_jid, nickname, start_chat_jid); - } - - if (start_chat_muc != null) { - ConferenceUtils.joinConferenceOnSeperateThread(start_chat_muc, start_chat_muc, null); - } - - } - - public void shutdown() { - - } - - public boolean canShutDown() { - return false; - } - - public void uninstall() { - // Do nothing. - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/chat/PresenceChangePlugin.java b/src/java/org/jivesoftware/sparkimpl/plugin/chat/PresenceChangePlugin.java deleted file mode 100644 index 4b74f4706..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/chat/PresenceChangePlugin.java +++ /dev/null @@ -1,226 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.chat; - -import java.awt.EventQueue; -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashSet; -import java.util.Set; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.JPopupMenu; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.ContextMenuListener; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -/** - * Allows users to place activity listeners on individual users. This class notifies users when other users - * come from away or offline to available. - * - * @author Derek DeMoro - */ -public class PresenceChangePlugin implements Plugin { - - private final Set sparkContacts = new HashSet<>(); - private LocalPreferences localPref = SettingsManager.getLocalPreferences(); - - public void initialize() { - // Listen for right-clicks on ContactItem - final ContactList contactList = SparkManager.getWorkspace().getContactList(); - - final Action listenAction = new AbstractAction() { - private static final long serialVersionUID = 7705539667621148816L; - - public void actionPerformed(ActionEvent e) { - - for (ContactItem item : contactList.getSelectedUsers()) { - String bareAddress = XmppStringUtils.parseBareJid(item - .getJID()); - sparkContacts.add(bareAddress); - } - } - }; - - listenAction.putValue(Action.NAME, Res.getString("menuitem.alert.when.online")); - listenAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_ALARM_CLOCK)); - - final Action removeAction = new AbstractAction() { - private static final long serialVersionUID = -8726129089417116105L; - - public void actionPerformed(ActionEvent e) { - - for (ContactItem item : contactList.getSelectedUsers()) { - String bareAddress = XmppStringUtils.parseBareJid(item - .getJID()); - sparkContacts.remove(bareAddress); - } - - } - }; - - removeAction.putValue(Action.NAME, Res.getString("menuitem.remove.alert.when.online")); - removeAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_DELETE)); - - - contactList.addContextMenuListener(new ContextMenuListener() { - public void poppingUp(Object object, JPopupMenu popup) { - if (object instanceof ContactItem) { - ContactItem item = (ContactItem)object; - String bareAddress = XmppStringUtils.parseBareJid(item.getJID()); - if (!item.getPresence().isAvailable() || item.getPresence().isAway()) { - if (sparkContacts.contains(bareAddress)) { - popup.add(removeAction); - } - else { - popup.add(listenAction); - } - } - } - } - - public void poppingDown(JPopupMenu popup) { - - } - - public boolean handleDefaultAction(MouseEvent e) { - return false; - } - }); - - // Check presence changes - SparkManager.getConnection().addAsyncStanzaListener( stanza -> { - try { - EventQueue.invokeAndWait( () -> { -Presence presence = (Presence) stanza; -if (!presence.isAvailable() || presence.isAway()) { -return; -} -String from = presence.getFrom(); - -ArrayList removelater = new ArrayList<>(); - -for (final String jid : sparkContacts) { -if (jid.equals(XmppStringUtils -.parseBareJid(from))) { -removelater.add(jid); -// sparkContacts.remove(jid); - -String nickname = SparkManager -.getUserManager() -.getUserNicknameFromJID(jid); -String time = SparkManager.DATE_SECOND_FORMATTER -.format(new Date()); -String infoText = Res -.getString( -"message.user.now.available.to.chat", -nickname, time); - -if (localPref.getShowToasterPopup()) { -SparkToaster toaster = new SparkToaster(); -toaster.setDisplayTime(5000); -toaster.setBorder(BorderFactory -.createBevelBorder(0)); - -toaster.setToasterHeight(150); -toaster.setToasterWidth(200); - -toaster.setTitle(nickname); -toaster.showToaster(null, infoText); - -toaster.setCustomAction(new AbstractAction() { -private static final long serialVersionUID = 4827542713848133369L; - -@Override -public void actionPerformed( -ActionEvent e) { -SparkManager.getChatManager() -.getChatRoom(jid); -} -}); -} - -ChatRoom room = SparkManager.getChatManager().getChatRoom(jid); - -if (localPref.getWindowTakesFocus()) -{ -SparkManager.getChatManager().activateChat(jid, nickname); -} - -room.getTranscriptWindow().insertNotificationMessage(infoText, ChatManager.NOTIFICATION_COLOR); - -} -} -for(String s : removelater){ -sparkContacts.remove(s); -} -} ); - } catch (Exception ex) { - ex.printStackTrace(); - } -}, new StanzaTypeFilter(Presence.class)); - } - - public void shutdown() { - - } - - public boolean canShutDown() { - return true; - } - - public void uninstall() { - // Do nothing. - } - - public void addWatch(String user){ - String bareAddress = XmppStringUtils.parseBareJid(user); - sparkContacts.add(bareAddress); - } - - public void removeWatch(String user){ - String bareAddress = XmppStringUtils.parseBareJid(user); - sparkContacts.remove(bareAddress); - } - - public boolean getWatched(String user) - { - String bareAddress = XmppStringUtils.parseBareJid(user); - return sparkContacts.contains(bareAddress) -; } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonManager.java b/src/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonManager.java deleted file mode 100644 index 5cc935330..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/emoticons/EmoticonManager.java +++ /dev/null @@ -1,597 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.emoticons; - -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.Node; -import org.dom4j.io.SAXReader; -import org.jivesoftware.Spark; -import org.jivesoftware.spark.util.URLFileSystem; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.xml.sax.SAXException; - -import javax.swing.ImageIcon; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.zip.ZipFile; - -/** - * Responsible for the handling of all Emoticon packs. Using the - * EmoticonManager, you can specify any defined Emoticon Pack, retrieve any - * emoticon based on its text equivalant, and retrieve its associated image url. - * - * @author Derek DeMoro - */ -public class EmoticonManager { - - private static EmoticonManager singleton; - private static final Object LOCK = new Object(); - - private Map> emoticonMap = new HashMap<>(); - private Map imageMap = new HashMap<>(); - - /** - * The root emoticon directory. - */ - public static File EMOTICON_DIRECTORY; - - /** - * Returns the singleton instance of EmoticonManager, creating - * it if necessary. - *

        - * - * @return the singleton instance of EmoticonManager - */ - public static EmoticonManager getInstance() { - // Synchronize on LOCK to ensure that we don't end up creating - // two singletons. - synchronized (LOCK) { - if (null == singleton) { - EmoticonManager controller = new EmoticonManager(); - singleton = controller; - return controller; - } - } - return singleton; - } - - /** - * Initialize the EmoticonManager - */ - private EmoticonManager() { - EMOTICON_DIRECTORY = new File(Spark.getBinDirectory().getParent(), - "xtra/emoticons").getAbsoluteFile(); - - File[] files; - files = EMOTICON_DIRECTORY.listFiles(); - - // If files in this directory, copy this files into the Spark User Home - // Directory - if (files != null) { - // Copy over to allow for non-admins to extract. - copyFiles(); - - final LocalPreferences pref = SettingsManager.getLocalPreferences(); - String emoticonPack = pref.getEmoticonPack(); - - try { - addEmoticonPack(emoticonPack); - } catch (Exception e) { - Log.error(e); - } - } - } - - /** - * Copy the files directly over to an accepted permissions directory. - */ - private void copyFiles() { - // Current Plugin directory - File newEmoticonDir = new File(Spark.getLogDirectory().getParentFile(), - "xtra/emoticons").getAbsoluteFile(); - newEmoticonDir.mkdirs(); - - File[] files = EMOTICON_DIRECTORY.listFiles(); - for (File file : files) { - if (file.isFile()) { - try { - // Copy over - File newFile = new File(newEmoticonDir, file.getName()); - - // Check timestamps - long installerFile = file.lastModified(); - long copiedFile = newFile.lastModified(); - if (installerFile > copiedFile) { - // Check if File is Zip-File - int endIndex = file.getName().indexOf(".zip"); - - if (endIndex > 0) { - String unzipURL = file.getName().substring(0, - endIndex); - File unzipFile = new File(newEmoticonDir, unzipURL); - - if (!unzipFile.exists() || !checkIfSameFile(file,newFile)) { - // Copy over and expand :) - URLFileSystem.copy(file.toURI().toURL(), - newFile); - expandNewPack(newFile, newEmoticonDir); - } - } - } - } catch (IOException e) { - Log.error(e); - } - } - } - EMOTICON_DIRECTORY = newEmoticonDir; - } - - private boolean checkIfSameFile(File oldZip, File newZip){ - boolean result = true; - - ZipFile oldZipFile = null; - ZipFile newZipFile = null; - try { - oldZipFile = new JarFile(oldZip); - newZipFile = new JarFile(newZip); - if (oldZipFile.size() == newZipFile.size()){ - for (Enumeration e = newZipFile.entries(); e.hasMoreElements();) { - JarEntry entry = (JarEntry) e.nextElement(); - if (oldZipFile.getEntry(entry.getName()) == null || - entry.hashCode() != oldZipFile.getEntry(entry.getName()).hashCode()){ - result = false; - break; - } - } - }else{ - result = false; - } - } catch (IOException e) { - Log.error(e); - } - closeFile( newZipFile ); - closeFile( oldZipFile ); - return result; - } - - private void closeFile( ZipFile zipFile ) { - try { - if (zipFile != null){ - zipFile.close(); - } - } catch (IOException e) { - Log.error(e); - } - } - - /** - * Returns the active emoticon set within Spark. - * - * @return the active set of emoticons. - */ - public Collection getActiveEmoticonSet() { - final LocalPreferences pref = SettingsManager.getLocalPreferences(); - String emoticonPack; - emoticonPack = pref.getEmoticonPack(); - // If EmoticonPack is set - //When no emoticon set is available, return an empty list - if (emoticonPack != null) { - Collection emoticonSet = emoticonMap.get(emoticonPack); - Collection empty = Collections.emptyList(); - return emoticonSet == null ? empty : emoticonSet; - } - return Collections.emptyList(); - } - - /** - * Returns the name of the active emoticon set. - * - * @return the name of the active emoticon set. - */ - public String getActiveEmoticonSetName() { - final LocalPreferences pref = SettingsManager.getLocalPreferences(); - return pref.getEmoticonPack(); - } - - /** - * Sets the active emoticon set. - * - * @param pack - * the archive containing the emotiocon pack. - */ - public void setActivePack(String pack) { - final LocalPreferences pref = SettingsManager.getLocalPreferences(); - pref.setEmoticonPack(pack); - SettingsManager.saveSettings(); - imageMap.clear(); - } - - /** - * Installs a new Adium style emoticon pack into Spark. - * - * @param pack - * the emotiocn pack (contains Emotiocons.plist) - * @return the name of the newly installed emoticon set. - */ - public String installPack(File pack) { - if (!containsEmoticonPList(pack)) { - return null; - } - - String name = null; - - // Copy to the emoticon area - try { - URLFileSystem.copy(pack.toURI().toURL(), new File( - EMOTICON_DIRECTORY, pack.getName())); - - File rootDirectory = unzipPack(pack, EMOTICON_DIRECTORY); - name = URLFileSystem.getName(rootDirectory.toURI().toURL()); - addEmoticonPack(name); - } catch (IOException e) { - Log.error(e); - } - - return name; - } - - /** - * Loads an emoticon set. - * - * @param packName - * the name of the pack. - */ - public void addEmoticonPack(String packName) { - File emoticonSet = new File(EMOTICON_DIRECTORY, packName - + ".adiumemoticonset"); - if (!emoticonSet.exists()) { - emoticonSet = new File(EMOTICON_DIRECTORY, packName - + ".AdiumEmoticonset"); - } - - if (!emoticonSet.exists()) { - emoticonSet = new File(EMOTICON_DIRECTORY, - "Default.adiumemoticonset"); - packName = "Default"; - setActivePack("Default"); - } - - List emoticons = new ArrayList<>(); - - final File plist = new File(emoticonSet, "Emoticons.plist"); - - // Create SaxReader and set to non-validating parser. - // This will allow for non-http problems to not break spark :) - final SAXReader saxParser = new SAXReader(); - saxParser.setValidation(false); - try { - saxParser.setFeature("http://xml.org/sax/features/validation", - false); - saxParser.setFeature("http://xml.org/sax/features/namespaces", - false); - saxParser.setFeature( - "http://apache.org/xml/features/validation/schema", false); - saxParser - .setFeature( - "http://apache.org/xml/features/validation/schema-full-checking", - false); - saxParser.setFeature( - "http://apache.org/xml/features/validation/dynamic", false); - saxParser - .setFeature( - "http://apache.org/xml/features/allow-java-encodings", - true); - saxParser - .setFeature( - "http://apache.org/xml/features/continue-after-fatal-error", - true); - saxParser - .setFeature( - "http://apache.org/xml/features/nonvalidating/load-dtd-grammar", - false); - saxParser - .setFeature( - "http://apache.org/xml/features/nonvalidating/load-external-dtd", - false); - } catch (SAXException e) { - e.printStackTrace(); - } - - Document emoticonFile; - try { - emoticonFile = saxParser.read(plist); - } catch (DocumentException e) { - Log.error(e); - return; - } - - Node root = emoticonFile.selectSingleNode("/plist/dict/dict"); - - List keyList = root.selectNodes("key"); - List dictonaryList = root.selectNodes("dict"); - - Iterator keys = keyList.iterator(); - Iterator dicts = dictonaryList.iterator(); - - while (keys.hasNext()) { - Element keyEntry = (Element) keys.next(); - String key = keyEntry.getText(); - - Element dict = (Element) dicts.next(); - String name = dict.selectSingleNode("string").getText(); - - // Load equivilants - final List equivs = new ArrayList<>(); - final List equivilants = dict.selectNodes("array/string"); - for (Object equivilant1 : equivilants) { - Element equivilant = (Element) equivilant1; - String equivilantString = equivilant.getText(); - equivs.add(equivilantString); - } - - final Emoticon emoticon = new Emoticon(key, name, equivs, - emoticonSet); - emoticons.add(emoticon); - } - - emoticonMap.put(packName, emoticons); - } - - /** - * Retrieve the URL to an emoticon. - * - * @param emoticon - * the emoticon. - * @return the URL of the image. - */ - public URL getEmoticonURL(Emoticon emoticon) { - final String imageName = emoticon.getImageName(); - - File file = new File(emoticon.getEmoticonDirectory(), imageName); - try { - return file.toURI().toURL(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - return null; - } - - /** - * Retrieves the associated key emoticon. - * - * @param packName - * the name of the Archive Pack File. - * @param key - * the key. - * @return the emoticon. - */ - public Emoticon getEmoticon(String packName, String key) { - final Collection emoticons = emoticonMap.get(packName); - if (emoticons == null) { - return null; - } - for (Emoticon emoticon : emoticons) { - for (String string : emoticon.getEquivalants()) { - if (key.equals(string)) { - return emoticon; - } - } - } - - return null; - } - - /** - * Returns the Emoticon associated with the given key. Note: - * This gets the emoticon from the active emoticon pack. - * - * @param key - * the key. - * @return the Emoticon found. If no emoticon is found, null is returned. - */ - public Emoticon getEmoticon(String key) { - final Collection emoticons = emoticonMap - .get(getActiveEmoticonSetName()); - - for (Emoticon emoticon : emoticons) { - for (String string : emoticon.getEquivalants()) { - if (key.toLowerCase().equals(string.toLowerCase())) { - return emoticon; - } - } - } - - return null; - } - - /** - * Returns the Icon that is mapped to a given key. - * - * @param key - * the key to search for. - * @return the Icon representing the key. - */ - public ImageIcon getEmoticonImage(String key) { - final Emoticon emoticon = getEmoticon(key); - if (emoticon != null) { - ImageIcon icon = imageMap.get(key); - if (icon == null) { - URL url = getEmoticonURL(emoticon); - icon = new ImageIcon(url); - imageMap.put(key, icon); - } - - return imageMap.get(key); - } - - return null; - } - - /** - * Returns a list of all available emoticon packs. - * - * @return Collection of Emoticon Pack names. - */ - public Collection getEmoticonPacks() { - final List emoticonList = new ArrayList<>(); - - File[] dirs = EMOTICON_DIRECTORY.listFiles(); - - // If no emoticons are available - if (dirs == null) { - - return null; - } - - for (File file : dirs) { - if (file.isDirectory() - && file.getName().toLowerCase() - .endsWith("adiumemoticonset")) { - try { - String name = URLFileSystem.getName(file.toURI().toURL()); - name = name.replaceAll("adiumemoticonset", ""); - name = name.replaceAll("AdiumEmoticonset", ""); - emoticonList.add(name); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - } - } - return emoticonList; - } - - /** - * Expands any zipped Emoticon Packs. - * - * @param file - * File to unpack. - * @param dist - * Dist file. - */ - private void expandNewPack(File file, File dist) { - URL url = null; - try { - url = file.toURI().toURL(); - } catch (MalformedURLException e) { - Log.error(e); - } - String name = URLFileSystem.getName(url); - File directory = new File(dist, name); - - // Unzip contents into directory - unzipPack(file, directory.getParentFile()); - } - - /** - * Checks zip file for the Emoticons.plist file. This is Sparks way of - * detecting a valid file. - * - * @param zip - * the zip file to check. - * @return true if the EmoticonPlist exists in the archive. - */ - private boolean containsEmoticonPList(File zip) { - ZipFile zipFile = null; - boolean result = false; - try { - zipFile = new JarFile(zip); - for (Enumeration e = zipFile.entries(); e.hasMoreElements();) { - JarEntry entry = (JarEntry) e.nextElement(); - if (entry.getName().contains("Emoticons.plist")) { - result = true; - break; - } - } - } catch (IOException e) { - Log.error(e); - } - closeFile(zipFile); - return result; - } - - /** - * Unzips a theme from a ZIP file into a directory. - * - * @param zip - * the ZIP file - * @param dir - * the directory to extract the plugin to. - * @return the root directory. - */ - private File unzipPack(File zip, File dir) { - File rootDirectory = null; - try { - ZipFile zipFile = new JarFile(zip); - - dir.mkdir(); - for (Enumeration e = zipFile.entries(); e.hasMoreElements();) { - JarEntry entry = (JarEntry) e.nextElement(); - File entryFile = new File(dir, entry.getName()); - // Ignore any manifest.mf entries. - if (entry.getName().toLowerCase().endsWith("manifest.mf")) { - continue; - } - - if (entry.isDirectory() && rootDirectory == null) { - rootDirectory = entryFile; - } - - if (!entry.isDirectory()) { - entryFile.getParentFile().mkdirs(); - FileOutputStream out = new FileOutputStream(entryFile); - InputStream zin = zipFile.getInputStream(entry); - byte[] b = new byte[512]; - int len; - while ((len = zin.read(b)) != -1) { - out.write(b, 0, len); - } - out.flush(); - out.close(); - zin.close(); - } - } - zipFile.close(); - } catch (Exception e) { - Log.error("Error unzipping emoticon pack", e); - } - - return rootDirectory; - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/ReceiveFileTransfer.java b/src/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/ReceiveFileTransfer.java deleted file mode 100644 index b5a3e3945..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/ReceiveFileTransfer.java +++ /dev/null @@ -1,786 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.filetransfer.transfer.ui; - -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Desktop; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.Timer; -import java.util.TimerTask; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JProgressBar; - -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smackx.filetransfer.FileTransfer; -import org.jivesoftware.smackx.filetransfer.FileTransferRequest; -import org.jivesoftware.smackx.filetransfer.IncomingFileTransfer; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.FileDragLabel; -import org.jivesoftware.spark.filetransfer.preferences.FileTransferPreference; -import org.jivesoftware.spark.preference.Preference; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.util.ByteFormat; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.URLFileSystem; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.filetransfer.transfer.Downloads; -import org.jxmpp.util.XmppStringUtils; - -public class ReceiveFileTransfer extends JPanel { - - private static final long serialVersionUID = -2974192409566650923L; - private FileDragLabel imageLabel = new FileDragLabel(); - private JLabel titleLabel = new JLabel(); - private JLabel fileLabel = new JLabel(); - - private TransferButton acceptButton = new TransferButton(Res.getString("accept"), SparkRes.getImageIcon(SparkRes.ACCEPT_INVITE_IMAGE)); - private TransferButton declineButton = new TransferButton(Res.getString("reject"), SparkRes.getImageIcon(SparkRes.REJECT_INVITE_IMAGE)); - private TransferButton pathButton = new TransferButton(Res.getString("message.file.transfer.direrror.setdir"), SparkRes.getImageIcon(SparkRes.SETTINGS_IMAGE_16x16)); - private JProgressBar progressBar = new JProgressBar(); - private IncomingFileTransfer transfer; - private TransferButton cancelButton = new TransferButton(); - private JLabel progressLabel = new JLabel(); - private long bytesRead; - private long _starttime; - private long _endtime; - - public ReceiveFileTransfer() { - setLayout(new GridBagLayout()); - - setBackground(new Color(250, 249, 242)); - add(imageLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - add(titleLabel, new GridBagConstraints(1, 0, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - titleLabel.setFont(new Font("Dialog", Font.BOLD, 11)); - titleLabel.setForeground(new Color(211, 174, 102)); - add(fileLabel, new GridBagConstraints(1, 1, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0)); - - add(acceptButton, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); - add(pathButton, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); - pathButton.setVisible( false ); - add(declineButton, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); - - // Decorate Cancel Button - decorateCancelButton(); - - - pathButton.setForeground(new Color(73, 113, 196)); - acceptButton.setForeground(new Color(73, 113, 196)); - declineButton.setForeground(new Color(73, 113, 196)); - pathButton.setFont(new Font("Dialog", Font.BOLD, 11)); - declineButton.setFont(new Font("Dialog", Font.BOLD, 11)); - acceptButton.setFont(new Font("Dialog", Font.BOLD, 11)); - - acceptButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196))); - declineButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196))); - - - setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.white)); - - pathButton.addMouseListener(new MouseAdapter() { - public void mouseEntered(MouseEvent e) { - pathButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); - - } - - public void mouseExited(MouseEvent e) { - pathButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - }); - - acceptButton.addMouseListener(new MouseAdapter() { - public void mouseEntered(MouseEvent e) { - acceptButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); - - } - - public void mouseExited(MouseEvent e) { - acceptButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - }); - - declineButton.addMouseListener(new MouseAdapter() { - public void mouseEntered(MouseEvent e) { - declineButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); - } - - public void mouseExited(MouseEvent e) { - declineButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - }); - } - - public void acceptFileTransfer(final FileTransferRequest request) { - String fileName = request.getFileName(); - long fileSize = request.getFileSize(); - String requestor = request.getRequestor(); - String bareJID = XmppStringUtils.parseBareJid(requestor); - - ByteFormat format = new ByteFormat(); - String text = format.format(fileSize); - - fileLabel.setText(fileName + " (" + text + ")"); - - ContactList contactList = SparkManager.getWorkspace().getContactList(); - ContactItem contactItem = contactList.getContactItemByJID(bareJID); - - titleLabel.setText(Res.getString("message.user.is.sending.you.a.file", contactItem.getDisplayName())); - - File tempFile = new File(Spark.getSparkUserHome(), "/tmp"); - try { - tempFile.mkdirs(); - - File file = new File(tempFile, fileName); - file.delete(); - BufferedWriter out = new BufferedWriter(new FileWriter(file)); - out.write("a"); - out.close(); - - imageLabel.setIcon(GraphicUtils.getIcon(file)); - - // Delete temp file when program exits. - file.delete(); - } - catch (IOException e) { - imageLabel.setIcon(SparkRes.getImageIcon(SparkRes.DOCUMENT_INFO_32x32)); - Log.error(e); - } - - acceptButton.addMouseListener(new MouseAdapter() { - - public void mousePressed(MouseEvent e) { - try{ - Downloads.checkDownloadDirectory(); - acceptRequest(request); - }catch (Exception ex){ - // this means there is a problem with the download directory - try - { - request.reject(); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to reject the request.", ex); - } - - setBackground(new Color(239, 245, 250)); - acceptButton.setVisible(false); - declineButton.setVisible(false); - if (Downloads.getDownloadDirectory() == null){ - fileLabel.setText(""); - }else{ - ResourceUtils.resLabel( fileLabel, null, Res.getString("label.transfer.download.directory") + - " " + Downloads.getDownloadDirectory().getAbsolutePath() ); - } - - // option to set a new path for the file-download - pathButton.setVisible( true ); - pathButton.addMouseListener( new MouseAdapter() { - public void mousePressed(MouseEvent e) { - Preference p = SparkManager.getPreferenceManager().getPreference( - new FileTransferPreference().getNamespace() ); - // retrieve the filetransfer preferences and show the preference menu - // to the user - SparkManager.getPreferenceManager().showPreferences(p); - } - }); - - titleLabel.setText(ex.getMessage()); - titleLabel.setForeground(new Color(65, 139, 179)); - - invalidate(); - validate(); - repaint(); - } - } - }); - - declineButton.addMouseListener(new MouseAdapter() { - public void mousePressed(MouseEvent e) { - rejectRequest(request); - } - }); - - } - - private void rejectRequest(FileTransferRequest request) { - try - { - request.reject(); - } - catch ( SmackException.NotConnectedException ex ) - { - Log.warning( "Unable to reject the request.", ex); - } - setBackground(new Color(239, 245, 250)); - acceptButton.setVisible(false); - declineButton.setVisible(false); - fileLabel.setText(""); - titleLabel.setText(Res.getString("message.file.transfer.canceled")); - titleLabel.setForeground(new Color(65, 139, 179)); - - invalidate(); - validate(); - repaint(); - } - - private void acceptRequest(final FileTransferRequest request) { - String requestor = request.getRequestor(); - String bareJID = XmppStringUtils.parseBareJid(requestor); - - ContactList contactList = SparkManager.getWorkspace().getContactList(); - final ContactItem contactItem = contactList - .getContactItemByJID(bareJID); - - setBackground(new Color(239, 245, 250)); - acceptButton.setVisible(false); - declineButton.setVisible(false); - titleLabel.setText(Res.getString("message.negotiate.file.transfer")); - titleLabel.setForeground(new Color(65, 139, 179)); - - add(progressBar, new GridBagConstraints(1, 2, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 150, 0)); - add(progressLabel, new GridBagConstraints(1, 3, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 150, 0)); - add(cancelButton, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0)); - cancelButton.setVisible(true); - transfer = request.accept(); - final File downloadedFile = new File(Downloads.getDownloadDirectory(), request.getFileName()); - - try { - _starttime = System.currentTimeMillis(); - transfer.recieveFile(downloadedFile); - } - catch (SmackException | IOException e) { - Log.error(e); - } - - progressBar.setMaximum(100); // setting it to percent - progressBar.setStringPainted(true); - - - final Timer timer = new Timer(); - TimerTask updateProgessBar = new TimerTask() { - @Override - public void run() { - if (transfer.getAmountWritten() >= request.getFileSize() - || transfer.getStatus() == FileTransfer.Status.error - || transfer.getStatus() == FileTransfer.Status.refused - || transfer.getStatus() == FileTransfer.Status.cancelled - || transfer.getStatus() == FileTransfer.Status.complete) - { - this.cancel(); - timer.cancel(); - _endtime = System.currentTimeMillis(); - updateonFinished(request, downloadedFile); - }else - { - // 100 % = Filesize - // x % = Currentsize - long p = (transfer.getAmountWritten() * 100 / transfer.getFileSize() ); - progressBar.setValue(Math.round(p)); - } - - } - }; - - final Timer timer2 = new Timer(); - TimerTask updatePrograssBarText = new TimerTask() { - long timenow; - long timeearlier; - long bytesnow; - long bytesearlier; - @Override - public void run() { - if (transfer.getAmountWritten() >= request.getFileSize() - || transfer.getStatus() == FileTransfer.Status.error - || transfer.getStatus() == FileTransfer.Status.refused - || transfer.getStatus() == FileTransfer.Status.cancelled - || transfer.getStatus() == FileTransfer.Status.complete) - { - this.cancel(); - timer2.cancel(); - } - else{ - - timenow = System.currentTimeMillis(); - bytesnow = transfer.getAmountWritten(); - bytesRead = transfer.getAmountWritten(); - if (bytesRead == -1) { - bytesRead = 0; - } - ByteFormat format = new ByteFormat(); - String text = format.format(bytesRead); - - - - - FileTransfer.Status status = transfer.getStatus(); - if (status == FileTransfer.Status.in_progress) - { - titleLabel.setText(Res.getString("message.receiving.file", contactItem.getDisplayName())); - String speed =TransferUtils.calculateSpeed(bytesnow-bytesearlier, timenow-timeearlier); - String est = TransferUtils.calculateEstimate(bytesnow, transfer.getFileSize(), _starttime, System.currentTimeMillis()); - progressLabel.setText(Res.getString("message.transfer.progressbar.text.received", text, speed, est)); - } - else if (status == FileTransfer.Status.negotiating_stream) { - titleLabel.setText(Res.getString("message.negotiate.stream")); - } - bytesearlier = bytesnow; - timeearlier = timenow; - } - } - }; - - - - timer.scheduleAtFixedRate(updateProgessBar, 10, 10); - timer2.scheduleAtFixedRate(updatePrograssBarText, 10, 500); - - } - - private void updateonFinished(final FileTransferRequest request, - final File downloadedFile) { - if (transfer.getAmountWritten() >= request.getFileSize()) { - transferDone(request, transfer); - - imageLabel.setFile(downloadedFile); - imageLabel.setToolTipText(Res.getString("message.click.to.open")); - titleLabel.setToolTipText(Res.getString("message.click.to.open")); - String fin = TransferUtils.convertSecondstoHHMMSS(Math.round(_endtime-_starttime)/1000); - progressLabel.setText(Res.getString("label.time", fin)); - - imageLabel.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - launchFile(downloadedFile); - } - } - }); - - imageLabel.addMouseListener(new MouseAdapter() { - public void mouseEntered(MouseEvent e) { - imageLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); - - } - - public void mouseExited(MouseEvent e) { - imageLabel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - }); - - - titleLabel.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - launchFile(downloadedFile); - } - } - }); - - titleLabel.addMouseListener(new MouseAdapter() { - public void mouseEntered(MouseEvent e) { - titleLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); - } - - public void mouseExited(MouseEvent e) { - titleLabel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - }); - - invalidate(); - validate(); - repaint(); - } - - String transferMessage = ""; - if (transfer.getStatus() == FileTransfer.Status.error) { - if (transfer.getException() != null) { - Log.error("There was an error during file transfer.", transfer.getException()); - } - transferMessage = Res.getString("message.error.during.file.transfer"); - } - else if (transfer.getStatus() == FileTransfer.Status.refused) { - transferMessage = Res.getString("message.transfer.refused"); - } - else if (transfer.getStatus() == FileTransfer.Status.cancelled || - transfer.getAmountWritten() < request.getFileSize()) { - transferMessage = Res.getString("message.transfer.cancelled"); - } - else if(transfer.getAmountWritten() >= request.getFileSize()) - { - transferMessage = Res.getString("message.transfer.complete", transfer.getFileName()); - } - - setFinishedText(transferMessage); - showAlert(true); - } - - - - private void setFinishedText(String text) { - acceptButton.setVisible(false); - declineButton.setVisible(false); - fileLabel.setText(""); - titleLabel.setText(text); - titleLabel.setForeground(new Color(65, 139, 179)); - progressBar.setVisible(false); - cancelButton.setVisible(false); - invalidate(); - validate(); - repaint(); - } - - private void transferDone(final FileTransferRequest request, FileTransfer transfer) { - cancelButton.setVisible(false); - - showAlert(true); - - String bareJID = XmppStringUtils.parseBareJid(request.getRequestor()); - - ContactList contactList = SparkManager.getWorkspace().getContactList(); - ContactItem contactItem = contactList.getContactItemByJID(bareJID); - - titleLabel.setText(Res.getString("message.received.file", contactItem.getDisplayName())); - fileLabel.setText(request.getFileName()); - - remove(acceptButton); - remove(declineButton); - remove(progressBar); - remove(pathButton); - - - final TransferButton openFileButton = new TransferButton(); - final TransferButton openFolderButton = new TransferButton(); - add(openFileButton, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); - add(openFolderButton, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); - - - final File downloadedFile = new File(Downloads.getDownloadDirectory(), request.getFileName()); - openFileButton.addMouseListener(new MouseAdapter() { - public void mouseEntered(MouseEvent e) { - openFileButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); - - } - - public void mouseExited(MouseEvent e) { - openFileButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - - public void mousePressed(MouseEvent e) { - launchFile(Downloads.getDownloadDirectory()+File.separator+request.getFileName()); - } - }); - - openFolderButton.addMouseListener(new MouseAdapter() { - public void mouseEntered(MouseEvent e) { - openFolderButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); - - } - - public void mouseExited(MouseEvent e) { - openFolderButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - - public void mousePressed(MouseEvent event) { - launchFile(Downloads.getDownloadDirectory()); - } - }); - - - add(fileLabel, new GridBagConstraints(1, 1, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0)); - - ResourceUtils.resButton(openFileButton, Res.getString("open")); - ResourceUtils.resButton(openFolderButton, Res.getString("open.folder")); - - openFileButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196))); - openFileButton.setForeground(new Color(73, 113, 196)); - openFileButton.setFont(new Font("Dialog", Font.BOLD, 11)); - - openFolderButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196))); - openFolderButton.setForeground(new Color(73, 113, 196)); - openFolderButton.setFont(new Font("Dialog", Font.BOLD, 11)); - - - imageLabel.setIcon(GraphicUtils.getIcon(downloadedFile)); - imageLabel.addMouseListener(new MouseAdapter() { - public void mousePressed(MouseEvent e) { - showPopup(e, downloadedFile); - } - - public void mouseReleased(MouseEvent e) { - showPopup(e, downloadedFile); - } - }); - - - if (isImage(downloadedFile.getName())) { - try { - URL imageURL = downloadedFile.toURI().toURL(); - ImageIcon image = new ImageIcon(imageURL); - image = GraphicUtils.scaleImageIcon(image, 64, 64); - imageLabel.setIcon(image); - } - catch (MalformedURLException e) { - Log.error("Could not locate image.", e); - imageLabel.setIcon(SparkRes.getImageIcon(SparkRes.DOCUMENT_INFO_32x32)); - } - } - - invalidate(); - validate(); - repaint(); - } - - - - private class TransferButton extends JButton { - - private static final long serialVersionUID = -9198495278243559064L; - - - public TransferButton() { - decorate(); - } - - /** - * Create a new RolloverButton. - * - * @param text the button text. - * @param icon the button icon. - */ - public TransferButton(String text, Icon icon) { - super(text, icon); - decorate(); - } - - - /** - * Decorates the button with the approriate UI configurations. - */ - private void decorate() { - setBorderPainted(false); - setOpaque(true); - - setContentAreaFilled(false); - setMargin(new Insets(1, 1, 1, 1)); - } - - } - - private boolean isImage(String fileName) { - fileName = fileName.toLowerCase(); - - String[] imageTypes = {"jpeg", "gif", "jpg", "png"}; - for (String imageType : imageTypes) { - if (fileName.endsWith(imageType)) { - return true; - } - } - - return false; - } - - private void showAlert(boolean alert) { - if (alert) { - titleLabel.setForeground(new Color(211, 174, 102)); - setBackground(new Color(250, 249, 242)); - } - else { - setBackground(new Color(239, 245, 250)); - titleLabel.setForeground(new Color(65, 139, 179)); - } - } - - public void cancelTransfer() { - if (transfer != null) { - transfer.cancel(); - } - } - - /** - * Handle the UI for the Cancel Button - */ - private void decorateCancelButton() { - cancelButton.setVisible(false); - ResourceUtils.resButton(cancelButton, Res.getString("cancel")); - cancelButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196))); - cancelButton.setForeground(new Color(73, 113, 196)); - cancelButton.setFont(new Font("Dialog", Font.BOLD, 11)); - cancelButton.setIcon(SparkRes.getImageIcon(SparkRes.SMALL_DELETE)); - - cancelButton.addActionListener( e -> { - cancelTransfer(); - acceptButton.setVisible(false); - declineButton.setVisible(false); - cancelButton.setVisible(false); - - } ); - - cancelButton.addMouseListener(new MouseAdapter() { - public void mouseEntered(MouseEvent e) { - cancelButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); - - } - - public void mouseExited(MouseEvent e) { - cancelButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - }); - - } - - private void showPopup(MouseEvent e, final File downloadedFile) { - if (e.isPopupTrigger()) { - final JPopupMenu popup = new JPopupMenu(); - - final ReceiveFileTransfer ui = this; - Action saveAsAction = new AbstractAction() { - private static final long serialVersionUID = -3010501340128285438L; - - public void actionPerformed(ActionEvent e) { - final JFileChooser chooser = Downloads.getFileChooser(); - File selectedFile = chooser.getSelectedFile(); - if (selectedFile != null) { - selectedFile = new File(selectedFile.getParent(), downloadedFile.getName()); - } - else { - selectedFile = downloadedFile; - } - chooser.setSelectedFile(selectedFile); - - int ok = chooser.showSaveDialog(ui); - if (ok == JFileChooser.APPROVE_OPTION) { - File file = chooser.getSelectedFile(); - try { - if (file.exists()) { - int confirm = JOptionPane.showConfirmDialog(ui, Res.getString("message.file.exists.question"), Res.getString("title.file.exists"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); - if (confirm == JOptionPane.NO_OPTION) { - return; - } - } - URLFileSystem.copy(downloadedFile.toURI().toURL(), file); - } - catch (IOException e1) { - Log.error(e1); - } - } - } - }; - - saveAsAction.putValue(Action.NAME, Res.getString("menuitem.save.as")); - popup.add(saveAsAction); - popup.show(this, e.getX(), e.getY()); - } - } - - /** - * Return correct URI for filePath. dont mind of local or remote path - * - * @param filePath - * @return - */ - private static URI getFileURI(String filePath) { - URI uri = null; - filePath = filePath.trim(); - if (filePath.indexOf("http") == 0 || filePath.indexOf("\\") == 0) { - if (filePath.indexOf("\\") == 0) - filePath = "file:" + filePath; - try { - filePath = filePath.replaceAll(" ", "%20"); - URL url = new URL(filePath); - uri = url.toURI(); - } catch (MalformedURLException ex) { - ex.printStackTrace(); - } catch (URISyntaxException ex) { - ex.printStackTrace(); - } - } else { - File file = new File(filePath); - uri = file.toURI(); - } - return uri; - } - - /** - * Launches a file browser or opens a file with java Desktop.open() if is - * supported - * - * @param file - */ - private void launchFile(File file) { - if (!Desktop.isDesktopSupported()) - return; - Desktop dt = Desktop.getDesktop(); - try { - dt.open(file); - } catch (IOException ex) { - launchFile(file.getPath()); - } - } - - /** - * Launches a file browser or opens a file with java Desktop.open() if is - * supported - * - * @param filePath - */ - private void launchFile(String filePath) { - if (filePath == null || filePath.trim().length() == 0) - return; - if (!Desktop.isDesktopSupported()) - return; - Desktop dt = Desktop.getDesktop(); - try { - dt.browse(getFileURI(filePath)); - } catch (Exception ex) { - ex.printStackTrace(); - } - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/SendFileTransfer.java b/src/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/SendFileTransfer.java deleted file mode 100644 index b1d404672..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/filetransfer/transfer/ui/SendFileTransfer.java +++ /dev/null @@ -1,389 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.filetransfer.transfer.ui; - -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Desktop; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; - -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JProgressBar; -import javax.swing.SwingUtilities; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smackx.filetransfer.FileTransfer; -import org.jivesoftware.smackx.filetransfer.FileTransfer.Status; -import org.jivesoftware.smackx.filetransfer.FileTransferManager; -import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.FileDragLabel; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.util.ByteFormat; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; - -public class SendFileTransfer extends JPanel { - - private static final long serialVersionUID = -4403839897649365671L; - private FileDragLabel imageLabel = new FileDragLabel(); - private JLabel titleLabel = new JLabel(); - private JLabel fileLabel = new JLabel(); - - private TransferButton cancelButton = new TransferButton(); - private JProgressBar progressBar = new JProgressBar(); - private File fileToSend; - private OutgoingFileTransfer transfer; - - - private TransferButton retryButton = new TransferButton(); - - private FileTransferManager transferManager; - private String fullJID; - private String nickname; - private JLabel progressLabel = new JLabel(); - private long _starttime; - - public SendFileTransfer() { - setLayout(new GridBagLayout()); - - setBackground(new Color(250, 249, 242)); - add(imageLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - add(titleLabel, new GridBagConstraints(1, 0, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - titleLabel.setFont(new Font("Dialog", Font.BOLD, 11)); - titleLabel.setForeground(new Color(211, 174, 102)); - add(fileLabel, new GridBagConstraints(1, 1, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0)); - - cancelButton.setText(Res.getString("cancel")); - retryButton.setText(Res.getString("retry")); - cancelButton.setIcon(SparkRes.getImageIcon(SparkRes.SMALL_DELETE)); - retryButton.setIcon(SparkRes.getImageIcon(SparkRes.REFRESH_IMAGE)); - - add(cancelButton, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); - add(retryButton, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); - retryButton.setVisible(false); - - retryButton.addActionListener( e -> { - try { - File file = new File(transfer.getFilePath()); - transfer = transferManager.createOutgoingFileTransfer(fullJID); - transfer.sendFile(file, "Sending"); - } - catch (SmackException e1) { - Log.error(e1); - } - sendFile(transfer, transferManager, fullJID, nickname); - } ); - - cancelButton.setForeground(new Color(73, 113, 196)); - cancelButton.setFont(new Font("Dialog", Font.BOLD, 11)); - cancelButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196))); - - - retryButton.setForeground(new Color(73, 113, 196)); - retryButton.setFont(new Font("Dialog", Font.BOLD, 11)); - retryButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196))); - - - setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.white)); - } - - public void sendFile(final OutgoingFileTransfer transfer, FileTransferManager transferManager, final String jid, final String nickname) { - this.transferManager = transferManager; - - cancelButton.setVisible(true); - retryButton.setVisible(false); - this.fullJID = jid; - this.nickname = nickname; - - this.transfer = transfer; - String fileName = transfer.getFileName(); - long fileSize = transfer.getFileSize(); - ByteFormat format = new ByteFormat(); - String text = format.format(fileSize); - - fileToSend = new File(transfer.getFilePath()); - imageLabel.setFile(fileToSend); - - fileLabel.setText(fileName + " (" + text + ")"); - - ContactList contactList = SparkManager.getWorkspace().getContactList(); - ContactItem contactItem = contactList.getContactItemByJID(jid); - - titleLabel.setText(Res.getString("message.transfer.waiting.on.user", contactItem.getDisplayName())); - - if (isImage(fileName)) { - try { - URL imageURL = new File(transfer.getFilePath()).toURI().toURL(); - ImageIcon image = new ImageIcon(imageURL); - image = GraphicUtils.scaleImageIcon(image, 64, 64); - imageLabel.setIcon(image); - } - catch (MalformedURLException e) { - Log.error("Could not locate image.", e); - imageLabel.setIcon(SparkRes.getImageIcon(SparkRes.DOCUMENT_INFO_32x32)); - } - } - else { - File file = new File(transfer.getFilePath()); - Icon icon = GraphicUtils.getIcon(file); - imageLabel.setIcon(icon); - } - cancelButton.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent mouseEvent) { - transfer.cancel(); - } - }); - - cancelButton.addMouseListener(new MouseAdapter() { - public void mouseEntered(MouseEvent e) { - cancelButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); - - } - - public void mouseExited(MouseEvent e) { - cancelButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - }); - - - progressBar.setMaximum(100); - progressBar.setVisible(false); - progressBar.setStringPainted(true); - add(progressBar, new GridBagConstraints(1, 2, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 150, 0)); - add(progressLabel, new GridBagConstraints(1, 3, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 150, 0)); - - - SwingWorker worker = new SwingWorker() { - - - public Object construct() { - while (true) { - try { - if(transfer.getBytesSent() >0 && _starttime==0){ - _starttime = System.currentTimeMillis(); - } - - long starttime = System.currentTimeMillis(); - long startbyte = transfer.getBytesSent(); - Thread.sleep(500); - FileTransfer.Status status = transfer.getStatus(); - if (status == Status.error || - status == Status.complete || status == Status.cancelled || - status == Status.refused) { - break; - } - long endtime = System.currentTimeMillis(); - long endbyte = transfer.getBytesSent(); - - long timediff = endtime-starttime; - long bytediff = endbyte-startbyte; - - updateBar(transfer, nickname, TransferUtils.calculateSpeed(bytediff, timediff) ); - } - catch (InterruptedException e) { - Log.error("Unable to sleep thread.", e); - } - - } - return ""; - } - - public void finished() { - updateBar(transfer, nickname, "??MB/s"); - } - }; - - worker.start(); - - makeClickable(imageLabel); - makeClickable(titleLabel); - } - - private void makeClickable(final JLabel label) { - label.setToolTipText(Res.getString("message.click.to.open")); - - label.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - openFile(fileToSend); - } - - public void mouseEntered(MouseEvent e) { - label.setCursor(new Cursor(Cursor.HAND_CURSOR)); - - } - - public void mouseExited(MouseEvent e) { - label.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - }); - } - - private void openFile(File downloadedFile) { - try { - Desktop.getDesktop().open(downloadedFile); - } catch (IOException e) { - Log.error(e); - } - } - - private void updateBar(final OutgoingFileTransfer transfer, String nickname, String kBperSecond) { - FileTransfer.Status status = transfer.getStatus(); - if (status == Status.negotiating_stream) { - titleLabel.setText(Res.getString("message.negotiation.file.transfer", nickname)); - } - else if (status == Status.error) { - if (transfer.getException() != null) { - Log.error("Error occured during file transfer.", transfer.getException()); - } - progressBar.setVisible(false); - progressLabel.setVisible(false); - titleLabel.setText(Res.getString("message.unable.to.send.file", nickname)); - cancelButton.setVisible(false); - retryButton.setVisible(true); - showAlert(true); - } - else if (status == Status.in_progress) { - titleLabel.setText(Res.getString("message.sending.file.to", nickname)); - showAlert(false); - if (!progressBar.isVisible()) { - progressBar.setVisible(true); - progressLabel.setVisible(true); - } - - try { - SwingUtilities.invokeAndWait( () -> { - // 100 % = Filesize - // x % = Currentsize - long p = (transfer.getBytesSent() * 100 / transfer.getFileSize() ); - progressBar.setValue(Math.round(p)); - } ); - } - catch (Exception e) { - Log.error(e); - } - - ByteFormat format = new ByteFormat(); - String bytesSent = format.format(transfer.getBytesSent()); - String est = TransferUtils.calculateEstimate(transfer.getBytesSent(), transfer.getFileSize(), _starttime, System.currentTimeMillis()); - - progressLabel.setText(Res.getString("message.transfer.progressbar.text.sent", bytesSent, kBperSecond, est)); - } - else if (status == Status.complete) { - progressBar.setVisible(false); - - String fin = TransferUtils.convertSecondstoHHMMSS(Math.round(System.currentTimeMillis()-_starttime)/1000); - progressLabel.setText(Res.getString("label.time", fin)); - titleLabel.setText(Res.getString("message.you.have.sent", nickname)); - cancelButton.setVisible(false); - showAlert(true); - } - else if (status == Status.cancelled) { - progressBar.setVisible(false); - progressLabel.setVisible(false); - titleLabel.setText(Res.getString("message.file.transfer.canceled")); - cancelButton.setVisible(false); - retryButton.setVisible(true); - showAlert(true); - } - else if (status == Status.refused) { - progressBar.setVisible(false); - progressLabel.setVisible(false); - titleLabel.setText(Res.getString("message.file.transfer.rejected", nickname)); - cancelButton.setVisible(false); - retryButton.setVisible(true); - showAlert(true); - } - - } - - private class TransferButton extends JButton { - - private static final long serialVersionUID = 8807434179541503654L; - - public TransferButton() { - decorate(); - } - - /** - * Decorates the button with the approriate UI configurations. - */ - private void decorate() { - setBorderPainted(false); - setOpaque(true); - - setContentAreaFilled(false); - setMargin(new Insets(1, 1, 1, 1)); - } - - } - - - private boolean isImage(String fileName) { - fileName = fileName.toLowerCase(); - - String[] imageTypes = {"jpeg", "gif", "jpg", "png"}; - for (String imageType : imageTypes) { - if (fileName.endsWith(imageType)) { - return true; - } - } - - return false; - } - - private void showAlert(boolean alert) { - if (alert) { - titleLabel.setForeground(new Color(211, 174, 102)); - setBackground(new Color(250, 249, 242)); - } - else { - setBackground(new Color(239, 245, 250)); - titleLabel.setForeground(new Color(65, 139, 179)); - } - } - - public void cancelTransfer() { - if (transfer != null) { - transfer.cancel(); - } - } - - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/Gateway.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/Gateway.java deleted file mode 100644 index 7ff819fdb..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/Gateway.java +++ /dev/null @@ -1,152 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways; - -import org.jivesoftware.smack.*; -import org.jivesoftware.smack.filter.StanzaIdFilter; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.provider.IQProvider; -import org.jivesoftware.spark.SparkManager; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; - -/** - * - */ -public class Gateway extends IQ { - - private String jid; - private String username; - - protected Gateway() - { - super( ELEMENT_NAME, NAMESPACE ); - } - - - public String getJid() { - return jid; - } - - public void setJid(String jid) { - this.jid = jid; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - /** - * Element name of the packet extension. - */ - public static final String ELEMENT_NAME = "query"; - - /** - * Namespace of the packet extension. - */ - public static final String NAMESPACE = "jabber:iq:gateway"; - - @Override - protected IQChildElementXmlStringBuilder getIQChildElementBuilder( IQChildElementXmlStringBuilder buf ) - { - buf.rightAngleBracket(); - buf.append(""); - buf.append("").append(username).append(""); - buf.append(""); - return buf; - } - - /** - * An IQProvider for Gateway packet. - * - * @author Derek DeMoro - */ - public static class Provider extends IQProvider { - - public Provider() { - super(); - } - - public Gateway parse(XmlPullParser parser, int i) throws IOException, XmlPullParserException - { - Gateway version = new Gateway(); - - boolean done = false; - while (!done) { - int eventType = parser.next(); - if (eventType == XmlPullParser.START_TAG) { - if (parser.getName().equals("jid")) { - version.setJid(parser.nextText()); - } - else if (parser.getName().equals("username")) { - version.setUsername(parser.nextText()); - } - } - - else if (eventType == XmlPullParser.END_TAG) { - if (parser.getName().equals(ELEMENT_NAME)) { - done = true; - } - } - } - - return version; - } - } - - /** - * Returns the fully qualified JID of a user. - * - * @param serviceName the service the user belongs to. - * @param username the name of the user. - * @return the JID. - */ - public static String getJID(String serviceName, String username) throws SmackException.NotConnectedException - { - Gateway registration = new Gateway(); - registration.setType(IQ.Type.set); - registration.setTo(serviceName); - registration.setUsername(username); - - XMPPConnection con = SparkManager.getConnection(); - PacketCollector collector = con.createPacketCollector(new StanzaIdFilter(registration.getStanzaId())); - try - { - con.sendStanza( registration ); - - Gateway response = collector.nextResult( SmackConfiguration.getDefaultPacketReplyTimeout() ); - return response.getJid(); - } - finally - { - collector.cancel(); - } - } - - -} - - diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayItem.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayItem.java deleted file mode 100644 index 927f0e069..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayItem.java +++ /dev/null @@ -1,17 +0,0 @@ -/** - * - */ -package org.jivesoftware.sparkimpl.plugin.gateways; - -/** - * @author holger.bergunde - * - */ -public interface GatewayItem { - - public void signedIn(boolean signedIn); - - public boolean isLoggedIn(); - - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayPlugin.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayPlugin.java deleted file mode 100644 index ee0034180..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayPlugin.java +++ /dev/null @@ -1,337 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.filter.OrFilter; -import org.jivesoftware.smack.filter.StanzaFilter; -import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.provider.ProviderManager; -import org.jivesoftware.smackx.disco.packet.DiscoverItems; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.PresenceManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.MessageDialog; -import org.jivesoftware.spark.component.VerticalFlowLayout; - -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.*; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.gateways.transports.*; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - - -import javax.swing.*; - - -import java.awt.Color; -import java.util.HashMap; -import java.util.Map; - -/** - * Handles Gateways/Transports in Spark. - * - * @author Derek DeMoro - */ -public class GatewayPlugin implements Plugin, ContactItemHandler { - - /** - * Defined Static Variable for Gateways. * - */ - public static final String GATEWAY = "gateway"; - private boolean useTab; - - private Map uiMap = new HashMap<>();; - private JPanel transferTab = new JPanel(); - - public void initialize() { - ProviderManager.addIQProvider(Gateway.ELEMENT_NAME, Gateway.NAMESPACE, new Gateway.Provider()); - LocalPreferences localPref = SettingsManager.getLocalPreferences(); - useTab = localPref.getShowTransportTab(); - transferTab.setBackground((Color)UIManager.get("ContactItem.background")); - SwingWorker thread = new SwingWorker() { - public Object construct() { - try { - // Let's try and avoid any timing issues with the gateway presence. - Thread.sleep(5000); - populateTransports(); - } - catch (Exception e) { - Log.error(e); - return false; - } - - return true; - } - - public void finished() { - - transferTab.setLayout(new VerticalFlowLayout(0,0,0,true,false)); - Boolean transportExists = (Boolean)get(); - if (!transportExists) { - return; - } - - - - if (TransportUtils.getTransports().size() > 0 && useTab) { - SparkManager.getWorkspace().getWorkspacePane().addTab(Res.getString("title.transports"), SparkRes.getImageIcon(SparkRes.TRANSPORT_ICON), transferTab); - } - - for (final Transport transport : TransportUtils.getTransports()) { - addTransport(transport); - } - - // Register presences. - registerPresenceListener(); - } - }; - - thread.start(); - } - - public void shutdown() { - } - - public boolean canShutDown() { - return false; - } - - public void uninstall() { - } - - private void populateTransports() throws Exception { - DiscoverItems discoItems = SparkManager.getSessionManager().getDiscoveredItems(); - - for (DiscoverItems.Item item : discoItems.getItems() ) { - - String entityName = item.getEntityID(); - if (entityName != null) { - if (entityName.startsWith("aim.")) { - AIMTransport aim = new AIMTransport(item.getEntityID()); - TransportUtils.addTransport(item.getEntityID(), aim); - } - else if (entityName.startsWith("msn.")) { - MSNTransport msn = new MSNTransport(item.getEntityID()); - TransportUtils.addTransport(item.getEntityID(), msn); - } - else if (entityName.startsWith("yahoo.")) { - YahooTransport yahoo = new YahooTransport(item.getEntityID()); - TransportUtils.addTransport(item.getEntityID(), yahoo); - } - else if (entityName.startsWith("icq.")) { - ICQTransport icq = new ICQTransport(item.getEntityID()); - TransportUtils.addTransport(item.getEntityID(), icq); - } - else if (entityName.startsWith("gtalk.")) { - GTalkTransport gtalk = new GTalkTransport(item.getEntityID()); - TransportUtils.addTransport(item.getEntityID(), gtalk); - } - else if (entityName.startsWith("xmpp.")) { - XMPPTransport xmppTransport = new XMPPTransport(item.getEntityID()); - TransportUtils.addTransport(item.getEntityID(), xmppTransport); - } - else if (entityName.startsWith("irc.")) { - IRCTransport ircTransport = new IRCTransport(item.getEntityID()); - TransportUtils.addTransport(item.getEntityID(), ircTransport); - } - else if (entityName.startsWith("sip.") || entityName.startsWith("simple.")) { - SimpleTransport simpleTransport = new SimpleTransport(item.getEntityID()); - TransportUtils.addTransport(item.getEntityID(), simpleTransport); - } - else if (entityName.startsWith("gadugadu.")) { - GaduGaduTransport gadugaduTransport = new GaduGaduTransport(item.getEntityID()); - TransportUtils.addTransport(item.getEntityID(), gadugaduTransport); - } - else if (entityName.startsWith("qq.")) { - QQTransport qqTransport = new QQTransport(item.getEntityID()); - TransportUtils.addTransport(item.getEntityID(), qqTransport); - } - else if (entityName.startsWith("sametime.")) { - SametimeTransport sametimeTransport = new SametimeTransport(item.getEntityID()); - TransportUtils.addTransport(item.getEntityID(), sametimeTransport); - } - else if (entityName.startsWith("facebook.")) { - FacebookTransport facebookTransport = new FacebookTransport(item.getEntityID()); - TransportUtils.addTransport(item.getEntityID(), facebookTransport); - } - else if (entityName.startsWith("myspace.") || entityName.startsWith("myspaceim.")) { - MySpaceTransport myspaceTransport = new MySpaceTransport(item.getEntityID()); - TransportUtils.addTransport(item.getEntityID(), myspaceTransport); - } - } - } - - } - - private void addTransport(final Transport transport) { - GatewayItem item; - if (useTab) - { - item = new GatewayTabItem(transport); - transferTab.add((GatewayTabItem)item); - } - else - { - item = new GatewayButton(transport); - } - uiMap.put(transport, item); - // transferTab.add(button); - // transferTab.add(new GatewayTabItem(transport)); - } - - private void registerPresenceListener() { - StanzaFilter orFilter = new OrFilter(new StanzaTypeFilter(Presence.class), new StanzaTypeFilter(Message.class)); - - SparkManager.getConnection().addAsyncStanzaListener( stanza -> { - if (stanza instanceof Presence) { - Presence presence = (Presence)stanza; - Transport transport = TransportUtils.getTransport(stanza.getFrom()); - if (transport != null) { - boolean registered = true; - if (presence.getType() == Presence.Type.unavailable) { - registered = false; - } - - - GatewayItem button = uiMap.get(transport); - - button.signedIn(registered); - - SwingWorker worker = new SwingWorker() { - - @Override - public Object construct() { - transferTab.revalidate(); - transferTab.repaint(); - return 41; - } - }; - worker.start(); - } - } - else if (stanza instanceof Message) { - Message message = (Message)stanza; - String from = message.getFrom(); - boolean hasError = message.getType() == Message.Type.error; - String body = message.getBody(); - - if (from != null && hasError) { - Transport transport = TransportUtils.getTransport(from); - if (transport != null) { - String title = "Alert from " + transport.getName(); - // Show error - MessageDialog.showAlert(body, title, "Information", SparkRes.getImageIcon(SparkRes.INFORMATION_IMAGE)); - } - } - } - }, orFilter); - - - ChatManager chatManager = SparkManager.getChatManager(); - chatManager.addContactItemHandler(this); - - // Iterate through Contacts and check for - final ContactList contactList = SparkManager.getWorkspace().getContactList(); - for (ContactGroup contactGroup : contactList.getContactGroups()) { - for (ContactItem contactItem : contactGroup.getContactItems()) { - Presence presence = contactItem.getPresence(); - if (presence.isAvailable()) { - String domain = XmppStringUtils.parseDomain(presence.getFrom()); - Transport transport = TransportUtils.getTransport(domain); - if (transport != null) { - handlePresence(contactItem, presence); - contactGroup.fireContactGroupUpdated(); - } - } - } - } - - SparkManager.getSessionManager().addPresenceListener( presence -> { - for (Transport transport : TransportUtils.getTransports()) { - GatewayItem button = uiMap.get(transport); - if (button.isLoggedIn()) { - if (!presence.isAvailable()) { - return; - } - // Create new presence - Presence p = new Presence(presence.getType(), presence.getStatus(), presence.getPriority(), presence.getMode()); - p.setTo(transport.getServiceName()); - try - { - SparkManager.getConnection().sendStanza(p); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to forward presence change to transport.", e ); - } - } - } - } ); - } - - - public boolean handlePresence(ContactItem item, Presence presence) { - if (presence.isAvailable()) { - String domain = XmppStringUtils.parseDomain(presence.getFrom()); - Transport transport = TransportUtils.getTransport(domain); - if (transport != null) { - if (presence.getType() == Presence.Type.available) { - item.setSpecialIcon(transport.getIcon()); - } - else { - item.setSpecialIcon(transport.getInactiveIcon()); - } - return false; - } - } - - return false; - } - - public boolean handleDoubleClick(ContactItem item) { - return false; - } - - public Icon getIcon(String jid) { - String domain = XmppStringUtils.parseDomain(jid); - Transport transport = TransportUtils.getTransport(domain); - if (transport != null) { - if (PresenceManager.isOnline(jid)) { - return transport.getIcon(); - } - else { - return transport.getInactiveIcon(); - } - } - return null; - } - - public Icon getTabIcon(Presence presence) { - return null; - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayPrivateData.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayPrivateData.java deleted file mode 100644 index 6a884f084..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/GatewayPrivateData.java +++ /dev/null @@ -1,132 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways; - -import org.jivesoftware.smackx.iqprivate.packet.PrivateData; -import org.jivesoftware.smackx.iqprivate.provider.PrivateDataProvider; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - * Handle Gateway preferences through private data to persist through seperate locations of the client. - * - * @author Derek DeMoro - */ -public class GatewayPrivateData implements PrivateData { - - private final Map loginSettingsMap = new HashMap<>(); - - public static final String ELEMENT = "gateway-settings"; - public static final String NAMESPACE = "http://www.jivesoftware.org/spark"; - - public void addService(String serviceName, boolean autoLogin) { - loginSettingsMap.put(serviceName, Boolean.toString(autoLogin)); - } - - public boolean autoLogin(String serviceName) { - String str = loginSettingsMap.get(serviceName); - if(str == null){ - return true; - } - - return Boolean.parseBoolean(str); - } - - public String getElementName() { - return ELEMENT; - } - - public String getNamespace() { - return NAMESPACE; - } - - - public String toXML() { - StringBuilder buf = new StringBuilder(); - buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append("\">"); - buf.append(""); - for (String serviceName : loginSettingsMap.keySet()) { - buf.append(""); - String autoLogin = loginSettingsMap.get(serviceName); - buf.append("").append(serviceName).append(""); - buf.append("").append(autoLogin).append(""); - buf.append(""); - } - buf.append(""); - - - buf.append(""); - return buf.toString(); - } - - public static class ConferencePrivateDataProvider implements PrivateDataProvider { - - public ConferencePrivateDataProvider() { - } - - public PrivateData parsePrivateData(XmlPullParser parser) throws IOException, XmlPullParserException - { - GatewayPrivateData data = new GatewayPrivateData(); - - boolean done = false; - - boolean isInstalled = false; - while (!done) { - int eventType = parser.next(); - if (eventType == XmlPullParser.START_TAG && parser.getName().equals("gateways")) { - isInstalled = true; - } - - if (eventType == XmlPullParser.START_TAG && parser.getName().equals("gateway")) { - boolean gatewayDone = false; - String serviceName = null; - String autoLogin = null; - while (!gatewayDone) { - int eType = parser.next(); - if (eType == XmlPullParser.START_TAG && parser.getName().equals("serviceName")) { - serviceName = parser.nextText(); - } - else if (eType == XmlPullParser.START_TAG && parser.getName().equals("autoLogin")) { - autoLogin = parser.nextText(); - } - else if (eType == XmlPullParser.END_TAG && parser.getName().equals("gateway")) { - data.addService(serviceName, Boolean.parseBoolean(autoLogin)); - gatewayDone = true; - } - } - } - - else if (eventType == XmlPullParser.END_TAG && parser.getName().equals("gateways")) { - done = true; - } - else if (!isInstalled) { - done = true; - } - } - return data; - } - } - - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/AIMTransport.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/AIMTransport.java deleted file mode 100644 index 0ef1730d2..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/AIMTransport.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways.transports; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.resource.Res; - -import javax.swing.Icon; - -/** - * - */ -public class AIMTransport implements Transport { - - private String serviceName; - - public AIMTransport(String serviceName){ - this.serviceName = serviceName; - } - - public String getTitle(){ - return Res.getString("title.aim.registration"); - } - - public String getInstructions() { - return Res.getString("message.enter.aim"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.AIM_TRANSPORT_ACTIVE_IMAGE); - } - - public Icon getInactiveIcon() { - return SparkRes.getImageIcon(SparkRes.AIM_TRANSPORT_INACTIVE_IMAGE); - } - - public String getServiceName() { - return serviceName; - } - - public String getName(){ - return "AIM"; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public Boolean requiresUsername() { - return true; - } - - public Boolean requiresPassword() { - return true; - } - - public Boolean requiresNickname() { - return false; - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/FacebookTransport.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/FacebookTransport.java deleted file mode 100644 index 2ca2164f0..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/FacebookTransport.java +++ /dev/null @@ -1,74 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways.transports; - -import javax.swing.Icon; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; - -public class FacebookTransport implements Transport { - - private String serviceName; - - public FacebookTransport(String serviceName){ - this.serviceName = serviceName; - } - - public String getTitle(){ - return Res.getString("title.facebook.registration"); - } - - public String getInstructions() { - return Res.getString("message.enter.facebook"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.FACEBOOK_TRANSPORT_ACTIVE_IMAGE); - } - - public Icon getInactiveIcon() { - return SparkRes.getImageIcon(SparkRes.FACEBOOK_TRANSPORT_INACTIVE_IMAGE); - } - - public String getServiceName() { - return serviceName; - } - - public String getName(){ - return "Facebook"; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public Boolean requiresUsername() { - return true; - } - - public Boolean requiresPassword() { - return true; - } - - public Boolean requiresNickname() { - return false; - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/GTalkTransport.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/GTalkTransport.java deleted file mode 100644 index 6d58b6dea..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/GTalkTransport.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways.transports; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; - -import javax.swing.Icon; - -/** - * - */ -public class GTalkTransport implements Transport { - - private String serviceName; - - public GTalkTransport(String serviceName) { - this.serviceName = serviceName; - } - - public String getTitle() { - return Res.getString("title.gtalk.registration"); - } - - public String getInstructions() { - return Res.getString("message.enter.gtalk"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.GTALK_TRANSPORT_ACTIVE_IMAGE); - } - - public Icon getInactiveIcon() { - return SparkRes.getImageIcon(SparkRes.GTALK_TRANSPORT_INACTIVE_IMAGE); - } - - public String getServiceName() { - return serviceName; - } - - public String getName() { - return "GTalk"; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public Boolean requiresUsername() { - return true; - } - - public Boolean requiresPassword() { - return true; - } - - public Boolean requiresNickname() { - return false; - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/GaduGaduTransport.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/GaduGaduTransport.java deleted file mode 100644 index 548b682d4..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/GaduGaduTransport.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways.transports; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.resource.Res; - -import javax.swing.Icon; - -/** - * - */ -public class GaduGaduTransport implements Transport { - - private String serviceName; - - public GaduGaduTransport(String serviceName){ - this.serviceName = serviceName; - } - - public String getTitle(){ - return Res.getString("title.gadugadu.registration"); - } - - public String getInstructions() { - return Res.getString("message.enter.gadugadu"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.GADUGADU_TRANSPORT_ACTIVE_IMAGE); - } - - public Icon getInactiveIcon() { - return SparkRes.getImageIcon(SparkRes.GADUGADU_TRANSPORT_INACTIVE_IMAGE); - } - - public String getServiceName() { - return serviceName; - } - - public String getName(){ - return "GaduGadu"; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public Boolean requiresUsername() { - return true; - } - - public Boolean requiresPassword() { - return true; - } - - public Boolean requiresNickname() { - return false; - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/ICQTransport.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/ICQTransport.java deleted file mode 100644 index 600cf3d2d..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/ICQTransport.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways.transports; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; - -import javax.swing.Icon; - -/** - * - */ -public class ICQTransport implements Transport { - - private String serviceName; - - public ICQTransport(String serviceName){ - this.serviceName = serviceName; - } - - public String getTitle(){ - return Res.getString("title.icq.registration"); - } - - public String getInstructions() { - return Res.getString("message.enter.icq"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.ICQ_TRANSPORT_ACTIVE_IMAGE); - } - - public Icon getInactiveIcon() { - return SparkRes.getImageIcon(SparkRes.ICQ_TRANSPORT_INACTIVE_IMAGE); - } - - public String getName(){ - return "ICQ"; - } - - public String getServiceName() { - return serviceName; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public Boolean requiresUsername() { - return true; - } - - public Boolean requiresPassword() { - return true; - } - - public Boolean requiresNickname() { - return false; - } - -} - diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/IRCTransport.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/IRCTransport.java deleted file mode 100644 index 1d2c8af40..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/IRCTransport.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways.transports; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.resource.Res; - -import javax.swing.Icon; - -/** - * - */ -public class IRCTransport implements Transport { - - private String serviceName; - - public IRCTransport(String serviceName){ - this.serviceName = serviceName; - } - - public String getTitle(){ - return Res.getString("title.irc.registration"); - } - - public String getInstructions() { - return Res.getString("message.enter.irc"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.IRC_TRANSPORT_ACTIVE_IMAGE); - } - - public Icon getInactiveIcon() { - return SparkRes.getImageIcon(SparkRes.IRC_TRANSPORT_INACTIVE_IMAGE); - } - - public String getServiceName() { - return serviceName; - } - - public String getName(){ - return "IRC"; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public Boolean requiresUsername() { - return true; - } - - public Boolean requiresPassword() { - return false; - } - - public Boolean requiresNickname() { - return true; - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/MSNTransport.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/MSNTransport.java deleted file mode 100644 index 31acc0122..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/MSNTransport.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways.transports; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.resource.Res; - -import javax.swing.Icon; - -/** - * - */ -public class MSNTransport implements Transport { - - private String serviceName; - - public MSNTransport(String serviceName) { - this.serviceName = serviceName; - } - - public String getTitle() { - return Res.getString("title.msn.registration"); - } - - public String getInstructions() { - return Res.getString("message.enter.msn"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.MSN_TRANSPORT_ACTIVE_IMAGE); - } - - public Icon getInactiveIcon() { - return SparkRes.getImageIcon(SparkRes.MSN_TRANSPORT_INACTIVE_IMAGE); - } - - public String getServiceName() { - return serviceName; - } - - public String getName(){ - return "MSN"; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public Boolean requiresUsername() { - return true; - } - - public Boolean requiresPassword() { - return true; - } - - public Boolean requiresNickname() { - return false; - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/MySpaceTransport.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/MySpaceTransport.java deleted file mode 100644 index 5c2d903cb..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/MySpaceTransport.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways.transports; - -import javax.swing.Icon; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; - -public class MySpaceTransport implements Transport { - private String serviceName; - - public MySpaceTransport(String serviceName){ - this.serviceName = serviceName; - } - - public String getTitle(){ - return Res.getString("title.myspace.registration"); - } - - public String getInstructions() { - return Res.getString("message.enter.myspace"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.MYSPACE_TRANSPORT_ACTIVE_IMAGE); - } - - public Icon getInactiveIcon() { - return SparkRes.getImageIcon(SparkRes.MYSPACE_TRANSPORT_INACTIVE_IMAGE); - } - - public String getServiceName() { - return serviceName; - } - - public String getName(){ - return "MySpace"; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public Boolean requiresUsername() { - return true; - } - - public Boolean requiresPassword() { - return true; - } - - public Boolean requiresNickname() { - return false; - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/QQTransport.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/QQTransport.java deleted file mode 100644 index 7722edd35..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/QQTransport.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways.transports; - - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.resource.Res; - -import javax.swing.Icon; - -/** - * - */ -public class QQTransport implements Transport { - private String serviceName; - - public QQTransport(String serviceName) { - this.serviceName = serviceName; - - } - - public String getTitle() { - return Res.getString("title.qq.registration"); - } - - public String getInstructions() { - return Res.getString("message.enter.qq"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.QQ_TRANSPORT_ACTIVE_IMAGE); - } - - public Icon getInactiveIcon() { - return SparkRes.getImageIcon(SparkRes.QQ_TRANSPORT_INACTIVE_IMAGE); - } - - public String getServiceName() { - return serviceName; - } - - public String getName() { - return "QQ"; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public Boolean requiresUsername() { - return true; - } - - public Boolean requiresPassword() { - return true; - } - - public Boolean requiresNickname() { - return false; - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/SametimeTransport.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/SametimeTransport.java deleted file mode 100644 index d2eff861d..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/SametimeTransport.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways.transports; - -import javax.swing.Icon; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; - -public class SametimeTransport implements Transport { - private String serviceName; - - public SametimeTransport(String serviceName){ - this.serviceName = serviceName; - } - - public String getTitle(){ - return Res.getString("title.sametime.registration"); - } - - public String getInstructions() { - return Res.getString("message.enter.sametime"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.SAMETIME_TRANSPORT_ACTIVE_IMAGE); - } - - public Icon getInactiveIcon() { - return SparkRes.getImageIcon(SparkRes.SAMETIME_TRANSPORT_INACTIVE_IMAGE); - } - - public String getServiceName() { - return serviceName; - } - - public String getName(){ - return "Sametime"; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public Boolean requiresUsername() { - return true; - } - - public Boolean requiresPassword() { - return true; - } - - public Boolean requiresNickname() { - return false; - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/SimpleTransport.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/SimpleTransport.java deleted file mode 100644 index 8cdf5c9a4..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/SimpleTransport.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways.transports; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.resource.Res; - -import javax.swing.Icon; - -/** - * - */ -public class SimpleTransport implements Transport { - - private String serviceName; - - public SimpleTransport(String serviceName){ - this.serviceName = serviceName; - } - - public String getTitle(){ - return Res.getString("title.simple.registration"); - } - - public String getInstructions() { - return Res.getString("message.enter.simple"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.SIMPLE_TRANSPORT_ACTIVE_IMAGE); - } - - public Icon getInactiveIcon() { - return SparkRes.getImageIcon(SparkRes.SIMPLE_TRANSPORT_INACTIVE_IMAGE); - } - - public String getServiceName() { - return serviceName; - } - - public String getName(){ - return "SIMPLE"; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public Boolean requiresUsername() { - return true; - } - - public Boolean requiresPassword() { - return true; - } - - public Boolean requiresNickname() { - return false; - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/TransportUtils.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/TransportUtils.java deleted file mode 100644 index d6f0547e0..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/TransportUtils.java +++ /dev/null @@ -1,214 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways.transports; - -import org.jivesoftware.smack.*; -import org.jivesoftware.smack.filter.IQReplyFilter; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.packet.ExtensionElement; -import org.jivesoftware.smackx.iqregister.packet.Registration; -import org.jivesoftware.smackx.iqprivate.PrivateDataManager; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; -import org.jivesoftware.smackx.disco.packet.DiscoverInfo; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.gateways.GatewayPrivateData; -import org.jxmpp.util.XmppStringUtils; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -/** - * Handles some basic handling of - */ -public class TransportUtils { - - private static Map transports = new HashMap<>(); - private static GatewayPrivateData gatewayPreferences; - - private TransportUtils() { - } - - static { - PrivateDataManager.addPrivateDataProvider(GatewayPrivateData.ELEMENT, GatewayPrivateData.NAMESPACE, new GatewayPrivateData.ConferencePrivateDataProvider()); - - final Runnable loadGateways = () -> { - PrivateDataManager pdm = SparkManager.getSessionManager().getPersonalDataManager(); - gatewayPreferences = null; - //Re: SPARK-1483 comment the loop as it causes Out Of Memory (infinite loop) if preferences not found - //If really necessary to try more times, a Thread Pool may be used: java ScheduledThreadPoolExecutor for example - //while (gatewayPreferences == null){ - try { - gatewayPreferences = (GatewayPrivateData)pdm.getPrivateData(GatewayPrivateData.ELEMENT, GatewayPrivateData.NAMESPACE); - } - catch (XMPPException | SmackException e) { - Log.error("Unable to load private data for Gateways", e); - } - //} - }; - - TaskEngine.getInstance().submit(loadGateways); - } - - public static boolean autoJoinService(String serviceName) { - if (gatewayPreferences != null) { - return gatewayPreferences.autoLogin(serviceName); - }else{ - return false; - } - } - - public static void setAutoJoin(String serviceName, boolean autoJoin) { - if (gatewayPreferences != null) { - gatewayPreferences.addService(serviceName, autoJoin); - PrivateDataManager pdm = SparkManager.getSessionManager().getPersonalDataManager(); - try { - pdm.setPrivateData(gatewayPreferences); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - } else { - Log.warning("Cannot set privacy data as gatewayPreferences is NULL"); - } - } - - public static Transport getTransport(String serviceName) { - // Return transport. - if (transports.containsKey(serviceName)) { - return transports.get(serviceName); - } - - return null; - } - - /** - * Returns true if the jid is from a gateway. - * @param jid the jid. - * @return true if the jid is from a gateway. - */ - public static boolean isFromGateway(String jid) { - String serviceName = XmppStringUtils.parseDomain(jid); - return transports.containsKey(serviceName); - } - - public static void addTransport(String serviceName, Transport transport) { - transports.put(serviceName, transport); - } - - public static Collection getTransports() { - return transports.values(); - } - - /** - * Checks if the user is registered with a gateway. - * - * @param con the XMPPConnection. - * @param transport the transport. - * @return true if the user is registered with the transport. - */ - public static boolean isRegistered(XMPPConnection con, Transport transport) { - if (!con.isConnected()) { - return false; - } - - ServiceDiscoveryManager discoveryManager = ServiceDiscoveryManager.getInstanceFor(con); - try { - DiscoverInfo info = discoveryManager.discoverInfo(transport.getServiceName()); - return info.containsFeature("jabber:iq:registered"); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - return false; - } - - /** - * Registers a user with a gateway. - * - * @param con the XMPPConnection. - * @param gatewayDomain the domain of the gateway (service name) - * @param username the username. - * @param password the password. - * @param nickname the nickname. - * @throws XMPPException thrown if there was an issue registering with the gateway. - */ - public static void registerUser(XMPPConnection con, String gatewayDomain, String username, String password, String nickname, StanzaListener callback) throws SmackException.NotConnectedException - { - Map attributes = new HashMap<>(); - if (username != null) { - attributes.put("username", username); - } - if (password != null) { - attributes.put("password", password); - } - if (nickname != null) { - attributes.put("nick", nickname); - } - Registration registration = new Registration( attributes ); - registration.setType(IQ.Type.set); - registration.setTo(gatewayDomain); - registration.addExtension(new GatewayRegisterExtension()); - - con.sendStanzaWithResponseCallback( registration, new IQReplyFilter( registration, con ), callback); - } - - /** - * @param con the XMPPConnection. - * @param gatewayDomain the domain of the gateway (service name) - * @throws XMPPException thrown if there was an issue unregistering with the gateway. - */ - public static void unregister(XMPPConnection con, String gatewayDomain) throws SmackException.NotConnectedException - { - Map map = new HashMap<>(); - map.put("remove", ""); - Registration registration = new Registration( map ); - registration.setType(IQ.Type.set); - registration.setTo(gatewayDomain); - - con.sendStanzaWithResponseCallback( registration, new IQReplyFilter( registration, con ), stanza -> { - IQ response = (IQ) stanza; - if (response.getType() == IQ.Type.error ) { - Log.warning( "Unable to unregister from gateway: " + stanza ); - } - } ); - } - - - static class GatewayRegisterExtension implements ExtensionElement { - - public String getElementName() { - return "x"; - } - - public String getNamespace() { - return "jabber:iq:gateway:register"; - } - - public String toXML() { - String builder = "<" + getElementName() + " xmlns=\"" + getNamespace() + - "\"/>"; - return builder; - } - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/XMPPTransport.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/XMPPTransport.java deleted file mode 100644 index 1e932b98d..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/XMPPTransport.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways.transports; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; - -import javax.swing.Icon; - -/** - * - */ -public class XMPPTransport implements Transport { - - private String serviceName; - - public XMPPTransport(String serviceName) { - this.serviceName = serviceName; - } - - public String getTitle() { - return Res.getString("title.xmpp.registration"); - } - - public String getInstructions() { - return Res.getString("message.enter.xmpp"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.XMPP_TRANSPORT_ACTIVE_IMAGE); - } - - public Icon getInactiveIcon() { - return SparkRes.getImageIcon(SparkRes.XMPP_TRANSPORT_INACTIVE_IMAGE); - } - - public String getServiceName() { - return serviceName; - } - - public String getName() { - return "XMPP"; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public Boolean requiresUsername() { - return true; - } - - public Boolean requiresPassword() { - return true; - } - - public Boolean requiresNickname() { - return false; - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/YahooTransport.java b/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/YahooTransport.java deleted file mode 100644 index ac44f5f74..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/gateways/transports/YahooTransport.java +++ /dev/null @@ -1,74 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.gateways.transports; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.resource.Res; - -import javax.swing.Icon; - -/** - * - */ -public class YahooTransport implements Transport { - - private String serviceName; - - public YahooTransport(String serviceName) { - this.serviceName = serviceName; - } - - public String getTitle() { - return Res.getString("title.yahoo.registration"); - } - - public String getInstructions() { - return Res.getString("message.enter.yahoo"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.YAHOO_TRANSPORT_ACTIVE_IMAGE); - } - - public Icon getInactiveIcon() { - return SparkRes.getImageIcon(SparkRes.YAHOO_TRANSPORT_INACTIVE_IMAGE); - } - - public String getServiceName() { - return serviceName; - } - - public String getName(){ - return "Yahoo"; - } - - public Boolean requiresUsername() { - return true; - } - - public Boolean requiresPassword() { - return true; - } - - public Boolean requiresNickname() { - return false; - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/history/ConversationHistoryPlugin.java b/src/java/org/jivesoftware/sparkimpl/plugin/history/ConversationHistoryPlugin.java deleted file mode 100644 index 290dfab16..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/history/ConversationHistoryPlugin.java +++ /dev/null @@ -1,357 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.history; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.ui.MessageFilter; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; -import org.xmlpull.mxp1.MXParser; -import org.xmlpull.v1.XmlPullParser; - -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.swing.AbstractAction; -import javax.swing.BorderFactory; -import javax.swing.DefaultListModel; -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.KeyStroke; -import javax.swing.ListCellRenderer; -import javax.swing.SwingUtilities; - -/** - * Allows users to see the last 10 people they have talked with. - * - * @author Derek DeMoro - */ -public class ConversationHistoryPlugin implements Plugin { - - private List historyList = new ArrayList<>(); - private File transcriptDir; - private File conFile; - - private final DefaultListModel model = new DefaultListModel(); - private JList contacts; - private Window window; - - private Map jidMap = new HashMap<>(); - - public void initialize() { - transcriptDir = new File(SparkManager.getUserDirectory(), "transcripts"); - conFile = new File(transcriptDir, "conversations.xml"); - - contacts = new JList(model); - contacts.setCellRenderer(new InternalRenderer()); - - window = new Window(SparkManager.getMainWindow()); - - - final JPanel mainPanel = new JPanel(new BorderLayout()); - final JLabel titleLabel = new JLabel(Res.getString("label.recent.conversation")); - titleLabel.setFont(new Font("Dialog", Font.BOLD, 11)); - titleLabel.setHorizontalAlignment(JLabel.CENTER); - mainPanel.add(titleLabel, BorderLayout.NORTH); - mainPanel.add(contacts, BorderLayout.CENTER); - mainPanel.setBorder(BorderFactory.createLineBorder(Color.gray)); - - window.add(mainPanel); - - // Add Listeners - contacts.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if (SwingUtilities.isRightMouseButton(e)) { - - contacts.setSelectedIndex(contacts.locationToIndex(e - .getPoint())); - String user = jidMap.get( contacts - .getSelectedValue() ); - ContactItem contact = SparkManager.getContactList() - .getContactItemByJID(user); - SparkManager.getContactList().setSelectedUser(contact.getJID()); - SparkManager.getContactList().showPopup(contacts, e, - contact); - } - - if (e.getClickCount() == 2) { - final JLabel label = (JLabel) contacts.getSelectedValue(); - String user = jidMap.get(label); - if (user != null) { - final String contactUsername = SparkManager - .getUserManager().getUserNicknameFromJID(user); - SparkManager.getChatManager().activateChat(user, - contactUsername); - window.dispose(); - } - } - } - }); - - contacts.addKeyListener(new KeyAdapter() { - public void keyReleased(KeyEvent e) { - if (e.getKeyChar() == KeyEvent.VK_ENTER) { - final JLabel label = (JLabel) contacts.getSelectedValue(); - String user = jidMap.get(label); - if (user != null) { - final String contactUsername = SparkManager.getUserManager().getUserNicknameFromJID(user); - SparkManager.getChatManager().activateChat(user, contactUsername); - window.dispose(); - } - } - else if (e.getKeyChar() == KeyEvent.VK_ESCAPE) { - window.dispose(); - } - } - }); - - contacts.addFocusListener(new FocusListener() { - public void focusGained(FocusEvent e) { - - } - - public void focusLost(FocusEvent e) { - window.dispose(); - } - }); - - // Load Previous History - loadPreviousHistory(); - - // Add Keymapping to ContactList - SparkManager.getMainWindow().getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_E, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "historyPeople"); - SparkManager.getMainWindow().getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_E, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "historyPeople"); - - SparkManager.getMainWindow().getRootPane().getActionMap().put("historyPeople", new AbstractAction("historyPeople") { - private static final long serialVersionUID = 2465628887318732082L; - - public void actionPerformed(ActionEvent e) { - // Show History Popup - showHistoryPopup(); - } - }); - - // Persist order of conversations. - SparkManager.getChatManager().addMessageFilter(new MessageFilter() { - public void filterOutgoing(ChatRoom room, Message message) { - addUserToHistory(room); - } - - public void filterIncoming(ChatRoom room, Message message) { - addUserToHistory(room); - } - }); - } - - /** - * Adds the last user to the history tags. - * - * @param room the ChatRoom where the conversation took place. - */ - private void addUserToHistory(ChatRoom room) { - if (room instanceof ChatRoomImpl) { - ChatRoomImpl roomImpl = (ChatRoomImpl) room; - String jid = roomImpl.getParticipantJID(); - jid = XmppStringUtils.parseBareJid(jid); - historyList.remove(jid); - historyList.add(0, jid); - } - } - - /** - * Displays the Previous Conversation Window. - */ - private void showHistoryPopup() { - // Get Transcript Directory - if (!transcriptDir.exists()) { - return; - } - - jidMap.clear(); - model.clear(); - - - final ContactList contactList = SparkManager.getWorkspace().getContactList(); - - int limit = historyList.size() > 10 ? 10 : historyList.size(); - - for (final String user : historyList.subList(0, limit)) { - - ContactItem contactItem = contactList.getContactItemByJID(user); - Icon icon; - if (contactItem != null) { - icon = contactItem.getIcon(); - if (icon == null) { - icon = SparkRes.getImageIcon(SparkRes.CLEAR_BALL_ICON); - } - - JLabel label = new JLabel(); - label.setText(contactItem.getDisplayName()); - label.setIcon(icon); - - model.addElement(label); - jidMap.put(label, user); - } - } - - - window.setSize(200, 200); - GraphicUtils.centerWindowOnComponent(window, SparkManager.getMainWindow()); - - - if (model.size() > 0) { - contacts.setSelectedIndex(0); - } - - window.setVisible(true); - - - } - - /** - * Loads the previous history. - */ - private void loadPreviousHistory() { - if (!conFile.exists()) { - return; - } - - // Otherwise load it. - try { - final MXParser parser = new MXParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(conFile), "UTF-8")); - parser.setInput(in); - boolean done = false; - while (!done) { - int eventType = parser.next(); - if (eventType == XmlPullParser.START_TAG && "user".equals(parser.getName())) { - String jid = XmppStringUtils.parseBareJid(parser.nextText()); - historyList.add(jid); - } - else if (eventType == XmlPullParser.END_TAG && "conversations".equals(parser.getName())) { - done = true; - } - } - } - catch (Exception e) { - Log.error(e); - } - } - - public void shutdown() { - final StringBuilder builder = new StringBuilder(); - builder.append(""); - for (String user : historyList) { - builder.append("").append(user).append(""); - } - builder.append(""); - - // Write out to file system. - - if (!transcriptDir.exists()) { - transcriptDir.mkdirs(); - } - - // Write out new File - try { - File conFile = new File(transcriptDir, "conversations.xml"); - BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(conFile), "UTF-8")); - out.write(builder.toString()); - out.close(); - } - catch (IOException e) { - Log.error(e); - } - } - - public boolean canShutDown() { - return true; - } - - public void uninstall() { - } - - /** - * Internal handling of a Jlabel Renderer. - */ - public class InternalRenderer extends JLabel implements ListCellRenderer { - private static final long serialVersionUID = 1812281106979897477L; - - /** - * Construct Default Renderer. - */ - public InternalRenderer() { - setOpaque(true); - } - - public Component getListCellRendererComponent(JList list, - Object value, - int index, - boolean isSelected, - boolean cellHasFocus) { - if (isSelected) { - setBackground(list.getSelectionBackground()); - setForeground(list.getSelectionForeground()); - } - else { - setBackground(list.getBackground()); - setForeground(list.getForeground()); - } - - JLabel label = (JLabel) value; - setText(label.getText()); - setIcon(label.getIcon()); - return this; - } - } - - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/idle/COPYING b/src/java/org/jivesoftware/sparkimpl/plugin/idle/COPYING deleted file mode 100644 index 65c5ca88a..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/idle/COPYING +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser 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 -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/idle/UserIdlePlugin.java b/src/java/org/jivesoftware/sparkimpl/plugin/idle/UserIdlePlugin.java deleted file mode 100644 index ceb3dbb01..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/idle/UserIdlePlugin.java +++ /dev/null @@ -1,287 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * This plugin 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 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ -package org.jivesoftware.sparkimpl.plugin.idle; - -import com.sun.jna.platform.win32.Kernel32; -import com.sun.jna.platform.win32.User32; -import com.sun.jna.platform.win32.WinDef.HMODULE; -import com.sun.jna.platform.win32.WinUser; -import com.sun.jna.platform.win32.WinUser.HHOOK; -import com.sun.jna.platform.win32.WinUser.LowLevelKeyboardProc; -import com.sun.jna.platform.win32.WinUser.MSG; -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Res; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.util.StringUtils; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.phone.PhonePlugin; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -import java.awt.*; -import java.awt.event.KeyEvent; -import java.util.Timer; -import java.util.TimerTask; - -public class UserIdlePlugin extends TimerTask implements Plugin { - - private final int CHECKTIME = 2; - private double x = 0; - private double y = 0; - private boolean hasChanged = false; - private int counter = 0; - public static LocalPreferences pref = SettingsManager.getLocalPreferences(); - public static Presence latestPresence; - private KeyHook keyHook; - private static boolean DesktopLockStatus; - private static String statustext; - - public static boolean getDesktopLockStatus() { - - return DesktopLockStatus; - } - - @Override - public boolean canShutDown() { - return false; - } - - @Override - public void initialize() { - Timer timer = new Timer(); - // Check all 5 secounds - timer.schedule(this, (1000 * 10), (1000 * CHECKTIME)); - - if (Spark.isWindows()) { - keyHook = new KeyHook(); - keyHook.initKeyHook(); - } else { - addGlobalListener(); - } - } - - @Override - public void shutdown() { - } - - @Override - public void uninstall() { - if (Spark.isWindows()) { - keyHook.quitKeyHook(); - } - } - - private void setIdle() { - - latestPresence = SparkManager.getWorkspace().getStatusBar().getPresence(); - - if (latestPresence.getStatus().equals(Res.getString("status.online")) || latestPresence.getStatus().equals(Res.getString("status.free.to.chat"))) { - statustext = pref.getIdleMessage(); - } else { - statustext = latestPresence.getStatus(); - } - - if (latestPresence.isAway()) { - Log.debug("UserIdlePlugin: Presence is already set to away"); - } else { - Presence statusPresence = new Presence(Presence.Type.available, StringUtils.modifyWildcards(statustext), 1, Presence.Mode.away); - SparkManager.getSessionManager().changePresence(statusPresence); - Log.debug("UserIdlePlugin: Setting idle presence"); - } - } - - - - private void setOnline() { - DesktopLockStatus = false; - - if (PhonePlugin.onPhonePresence !=null) { - SparkManager.getSessionManager().changePresence(PhonePlugin.onPhonePresence); - Log.debug("UserIdlePlugin: Returning from idle/lock - On the Phone"); - - } else if ((latestPresence.getStatus().contains("On the phone")) && (PhonePlugin.offPhonePresence !=null) - && ((PhonePlugin.offPhonePresence.getMode().equals(Presence.Mode.dnd)) - || (PhonePlugin.offPhonePresence.getMode().equals(Presence.Mode.xa)))) { - SparkManager.getSessionManager().changePresence(PhonePlugin.offPhonePresence); - Log.debug("UserIdlePlugin: Matched DND/XA - Setting presence from PhonePlugin"); - - } else if (((latestPresence.getStatus().contains("On the phone")) && (PhonePlugin.offPhonePresence !=null) - && (PhonePlugin.offPhonePresence.getStatus().contentEquals(statustext)))) { - Presence presence = new Presence(Presence.Type.available, PhonePlugin.offPhonePresence.getStatus(), 1, Presence.Mode.available); - SparkManager.getSessionManager().changePresence(presence); - Log.debug("UserIdlePlugin: Setting presence from PhonePlugin ...."); - - } else if ((latestPresence.getStatus().contains("On the phone")) && (PhonePlugin.offPhonePresence !=null)) { - SparkManager.getSessionManager().changePresence(PhonePlugin.offPhonePresence); - Log.debug("UserIdlePlugin: Setting presence from PhonePlugin"); - - } else { SparkManager.getSessionManager().changePresence(latestPresence); - Log.debug("UserIdlePlugin: Setting presence using latestPresence"); } - - } - - @Override - public void run() { - if (pref.isIdleOn()) { - PointerInfo info = MouseInfo.getPointerInfo(); - // DecimalFormat format = new DecimalFormat("0.00"); - // System.out.println(format.format(info.getLocation().getY()).toString() - // + "-" + 7.24288464E8 + "-" + (info.getLocation().getY() == - // 7.24288464E8)); - // System.out.println(format.format(info.getLocation().getX()).toString() - // + "-" + 7.24288464E8 + "-" + (info.getLocation().getX() == - // 7.24288464E8)); - int automaticIdleTime = (pref.getIdleTime() * 60) / CHECKTIME; - - // Windows Desktop Lock - if (Spark.isWindows()) { - - if (info != null) { - if (info.getLocation().getX() > 50000000 - || info.getLocation().getY() > 50000000) { - if (!hasChanged) { - Log.debug("Desktop Locked .. "); - hasChanged = true; - setIdle(); - DesktopLockStatus = true; - y = info.getLocation().getY(); - x = info.getLocation().getX(); - } - } - } else { - if (!hasChanged) { - Log.debug("Desktop Locked .. "); - hasChanged = true; - setIdle(); - DesktopLockStatus = true; - y = -1; - x = -1; - } - } - } - - // Default Idle - if (info != null) { - if (x == info.getLocation().getX() - && y == info.getLocation().getY()) { - if (counter > automaticIdleTime) { - if (!hasChanged) { - setIdle(); - } - hasChanged = true; - } - counter++; - } else { - if (hasChanged) { - setOnline(); - hasChanged = false; - } - counter = 0; - } - - y = info.getLocation().getY(); - x = info.getLocation().getX(); - } - } - } - - private void addGlobalListener() { - EventQueue e = Toolkit.getDefaultToolkit().getSystemEventQueue(); - e.push(new EventQueue() { - - @Override - protected void dispatchEvent(AWTEvent event) { - if (event instanceof KeyEvent) { - counter = 0; - if (hasChanged) { - setOnline(); - hasChanged = false; - } - } - super.dispatchEvent(event); - } - }); - } - - private void userActive() { - counter = 0; - if (hasChanged) { - setOnline(); - hasChanged = false; - } - } - - /** Sample implementation of a low-level keyboard hook on W32. */ - class KeyHook { - private HHOOK hhk; - private LowLevelKeyboardProc keyboardHook; - private Thread thread; - - public void initKeyHook() { - System.setProperty( "jna.predictable_field_order","true"); - - thread = new Thread( () -> { - final User32 lib = User32.INSTANCE; - HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null); - keyboardHook = ( nCode, wParam, info ) -> { -if (nCode >= 0) { -switch (wParam.intValue()) { -// case WinUser.WM_KEYUP: -case WinUser.WM_KEYDOWN: -// case WinUser.WM_SYSKEYUP: -case WinUser.WM_SYSKEYDOWN: -// do active -userActive(); -} -} -return lib.CallNextHookEx(hhk, nCode, wParam, -info.getPointer()); -}; - hhk = lib.SetWindowsHookEx(WinUser.WH_KEYBOARD_LL, - keyboardHook, hMod, 0); - - // This bit never returns from GetMessage - int result; - MSG msg = new MSG(); - while ((result = lib.GetMessage(msg, null, 0, 0)) != 0) { - if (result == -1) { - System.err.println("error in get message"); - break; - } else { - System.err.println("got message"); - lib.TranslateMessage(msg); - lib.DispatchMessage(msg); - } - } - lib.UnhookWindowsHookEx(hhk); - } ); - thread.start(); - } - - @SuppressWarnings("deprecation") - public void quitKeyHook() { - final User32 lib = User32.INSTANCE; - lib.UnhookWindowsHookEx(hhk); - thread.stop(); - } - - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/jabber/JabberBrowser.java b/src/java/org/jivesoftware/sparkimpl/plugin/jabber/JabberBrowser.java deleted file mode 100644 index 5ea8f14ab..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/jabber/JabberBrowser.java +++ /dev/null @@ -1,231 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.jabber; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; -import org.jivesoftware.smackx.disco.packet.DiscoverItems; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.log.Log; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.EventQueue; -import java.awt.FlowLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.AbstractAction; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.KeyStroke; - -public class JabberBrowser implements Plugin { - private JLabel addressLabel; - private JComboBox addressField; - private XMPPConnection con; - private JPanel browsePanel; - - public void display() { - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new GridBagLayout()); - - // Setup resource - ResourceUtils.resLabel(addressLabel, addressField, Res.getString("label.jabber.address") + ":"); - - RolloverButton backButton = new RolloverButton(); - backButton.setIcon(SparkRes.getImageIcon(SparkRes.LEFT_ARROW_IMAGE)); - backButton.addActionListener( e -> { - int selectedItem = addressField.getSelectedIndex(); - if (selectedItem > 0) { - Object historyItem = addressField.getItemAt(selectedItem - 1); - browse((String)historyItem); - } - } ); - - mainPanel.add(backButton, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - mainPanel.add(addressLabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - mainPanel.add(addressField, new GridBagConstraints(2, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - - JButton browseButton = new JButton(""); - ResourceUtils.resButton(browseButton, Res.getString("button.browse")); - browseButton.addActionListener( e -> { - String serviceName = (String)addressField.getSelectedItem(); - if (!ModelUtil.hasLength(serviceName)) { - return; - } - browse(serviceName); - } ); - mainPanel.add(addressField, new GridBagConstraints(2, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - mainPanel.add(browseButton, new GridBagConstraints(3, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - browsePanel = new JPanel(); - browsePanel.setLayout(new FlowLayout(FlowLayout.LEFT)); - browsePanel.setBackground(Color.white); - - JScrollPane pane = new JScrollPane(browsePanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - browsePanel.setPreferredSize(new Dimension(0, 0)); - mainPanel.add(pane, new GridBagConstraints(0, 1, 4, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - - JFrame frame = new JFrame(); - frame.setIconImage(SparkRes.getImageIcon(SparkRes.FIND_IMAGE).getImage()); - - JDialog dialog = new JDialog(frame, Res.getString("title.jabber.browser")); - dialog.getContentPane().setLayout(new BorderLayout()); - dialog.getContentPane().add(mainPanel, BorderLayout.CENTER); - dialog.pack(); - dialog.setSize(600, 400); - dialog.setLocationRelativeTo(SparkManager.getMainWindow()); - dialog.setVisible(true); - } - - private void browse(String serviceName) { - browsePanel.removeAll(); - - ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(con); - DiscoverItems result; - try { - result = discoManager.discoverItems(serviceName); - } - catch (XMPPException | SmackException e) { - Log.error(e); - return; - } - - addAddress(serviceName); - - - for (DiscoverItems.Item item : result.getItems() ) { - Entity entity = new Entity(item); - browsePanel.add(entity); - } - - browsePanel.invalidate(); - browsePanel.validate(); - browsePanel.repaint(); - } - - private void browseItem(DiscoverItems.Item discoveredItem) { - addAddress(discoveredItem.getEntityID()); - browsePanel.removeAll(); - ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(con); - DiscoverItems result; - try { - result = discoManager.discoverItems(discoveredItem.getEntityID()); - } - catch (XMPPException | SmackException e) { - browsePanel.invalidate(); - browsePanel.validate(); - browsePanel.repaint(); - return; - } - - List list = new ArrayList<>(); - for (DiscoverItems.Item item : result.getItems() ) { - Entity entity = new Entity(item); - browsePanel.add(entity); - list.add(entity); - } - - GraphicUtils.makeSameSize((JComponent[])list.toArray(new JComponent[list.size()])); - - browsePanel.invalidate(); - browsePanel.validate(); - browsePanel.repaint(); - } - - public class Entity extends RolloverButton { - private static final long serialVersionUID = 2084728014635239794L; - private DiscoverItems.Item item; - - public Entity(final DiscoverItems.Item item) { - this.item = item; - setVerticalTextPosition(JLabel.BOTTOM); - setHorizontalTextPosition(JLabel.CENTER); - setText(item.getName()); - setIcon(SparkRes.getImageIcon(SparkRes.USER1_MESSAGE_24x24)); - - addActionListener( e -> browseItem(item) ); - - } - - public DiscoverItems.Item getItem() { - return item; - } - } - - private void addAddress(String address) { - addressField.addItem(address); - addressField.setSelectedItem(address); - } - - public void initialize() { - this.con = SparkManager.getConnection(); - EventQueue.invokeLater( () -> { - addressLabel = new JLabel(); - addressField = new JComboBox(); - addressField.setEditable(true); - addressField.addItem(con.getHost()); - } ); - SparkManager.getWorkspace().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("F8"), "showBrowser"); - SparkManager.getWorkspace().getActionMap().put("showBrowser", new AbstractAction("showBrowser") { - private static final long serialVersionUID = 341826581565007606L; - - public void actionPerformed(ActionEvent evt) { - display(); - } - }); - } - - public void shutdown() { - - } - - public boolean canShutDown() { - return false; - } - - public void uninstall() { - // Do nothing. - } - - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/jabber/JabberVersion.java b/src/java/org/jivesoftware/sparkimpl/plugin/jabber/JabberVersion.java deleted file mode 100644 index f7e42b719..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/jabber/JabberVersion.java +++ /dev/null @@ -1,175 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.jabber; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.filter.StanzaFilter; -import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smackx.time.packet.Time; -import org.jivesoftware.smackx.iqversion.packet.Version; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.ContextMenuListener; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.JiveInfo; -import org.jivesoftware.resource.Res; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.JComponent; -import javax.swing.JPopupMenu; -import javax.swing.KeyStroke; - -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; -import java.util.Collection; -import java.util.Date; - - -public class JabberVersion implements Plugin { - - public void initialize() { - // Create IQ Filter - StanzaFilter packetFilter = new StanzaTypeFilter(IQ.class); - SparkManager.getConnection().addAsyncStanzaListener( stanza -> { - IQ iq = (IQ)stanza; - - try - { - // Handle Version Request - if (iq instanceof Version && iq.getType() == IQ.Type.get) { - // Send Version - Version version = new Version( JiveInfo.getName(), JiveInfo.getVersion(), JiveInfo.getOS() ); - - // Send back as a reply - version.setStanzaId(iq.getStanzaId()); - version.setType(IQ.Type.result); - version.setTo(iq.getFrom()); - version.setFrom(iq.getTo()); - SparkManager.getConnection().sendStanza(version); - } - // Send time - else if (iq instanceof Time && iq.getType() == IQ.Type.get) { - Time time = new Time(); - time.setStanzaId(iq.getStanzaId()); - time.setFrom(iq.getTo()); - time.setTo(iq.getFrom()); - time.setTime(new Date()); - time.setType(IQ.Type.result); - - // Send Time - SparkManager.getConnection().sendStanza(time); - } - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to answer request: " + stanza, e); - } - }, packetFilter); - - final ContactList contactList = SparkManager.getWorkspace().getContactList(); - contactList.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control F11"), "viewClient"); - contactList.addContextMenuListener(new ContextMenuListener() { - public void poppingUp(final Object component, JPopupMenu popup) { - if (!(component instanceof ContactItem)) { - return; - } - - ContactItem contactItem = (ContactItem)component; - if(contactItem.getPresence() == null){ - return; - } - - Action versionRequest = new AbstractAction() { - private static final long serialVersionUID = -5619737417315441711L; - - public void actionPerformed(ActionEvent e) { - viewClient(); - } - }; - - versionRequest.putValue(Action.NAME, Res.getString("menuitem.view.client.version")); - popup.add(versionRequest); - } - - public void poppingDown(JPopupMenu popup) { - - } - - public boolean handleDefaultAction(MouseEvent e) { - return false; - } - }); - - - contactList.getActionMap().put("viewClient", new AbstractAction("viewClient") { - private static final long serialVersionUID = 8282301357403753561L; - - public void actionPerformed(ActionEvent evt) { - viewClient(); - } - }); - - - } - - private void viewClient() { - final ContactList contactList = SparkManager.getWorkspace().getContactList(); - Collection selectedUsers = contactList.getSelectedUsers(); - if (selectedUsers.size() == 1) { - ContactItem item = (ContactItem)selectedUsers.toArray()[0]; - Presence presence = item.getPresence(); - final String jid = presence.getFrom(); - SwingWorker worker = new SwingWorker() { - public Object construct() { - try { - Thread.sleep(10); - } - catch (InterruptedException e1) { - // Nothing to do - } - return jid; - } - - public void finished() { - VersionViewer.viewVersion(jid); - } - }; - worker.start(); - } - } - - public void shutdown() { - - } - - public boolean canShutDown() { - return false; - } - - public void uninstall() { - // Do nothing. - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/jabber/VersionViewer.java b/src/java/org/jivesoftware/sparkimpl/plugin/jabber/VersionViewer.java deleted file mode 100644 index 811b59779..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/jabber/VersionViewer.java +++ /dev/null @@ -1,122 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.jabber; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.filter.IQReplyFilter; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smackx.time.packet.Time; -import org.jivesoftware.smackx.iqversion.packet.Version; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.UserManager; -import org.jivesoftware.spark.component.MessageDialog; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.log.Log; - -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; - -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.text.SimpleDateFormat; - -public class VersionViewer { - - private VersionViewer() { - - } - - public static void viewVersion(String jid) { - final JPanel panel = new JPanel(); - panel.setLayout(new GridBagLayout()); - - JLabel timeLabel = new JLabel(); - JLabel softwareLabel = new JLabel(); - JLabel versionLabel = new JLabel(); - JLabel osLabel = new JLabel(); - - final JTextField timeField = new JTextField(); - final JTextField softwareField = new JTextField(); - final JTextField versionField = new JTextField(); - final JTextField osField = new JTextField(); - - // Add resources - ResourceUtils.resLabel(timeLabel, timeField, Res.getString("label.local.time") + ":"); - ResourceUtils.resLabel(softwareLabel, softwareField, Res.getString("label.software") + ":"); - ResourceUtils.resLabel(versionLabel, versionField, Res.getString("label.version") + ":"); - ResourceUtils.resLabel(osLabel, osField, Res.getString("label.os") + ":"); - - // Add Time Label - panel.add(timeLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - panel.add(timeField, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - panel.add(softwareLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - panel.add(softwareField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - - panel.add(versionLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - panel.add(versionField, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - - panel.add(osLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - panel.add(osField, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - final XMPPConnection connection = SparkManager.getConnection(); - try - { - // Load Version - final Version versionRequest = new Version(); - versionRequest.setType(IQ.Type.get); - versionRequest.setTo(jid); - - connection.sendStanzaWithResponseCallback( versionRequest, new IQReplyFilter( versionRequest, connection ), stanza -> { - final Version versionResult = (Version) stanza; - softwareField.setText(versionResult.getName()); - versionField.setText(versionResult.getVersion()); - osField.setText(versionResult.getOs()); - } ); - - // Time - final Time time = new Time(); - time.setType(IQ.Type.get); - time.setTo(jid); - - connection.sendStanzaWithResponseCallback( time, new IQReplyFilter( time, connection ), stanza -> {; - timeField.setText( new SimpleDateFormat( ).format( ((Time)stanza).getTime())); - } ); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to query for version.", e ); - } - - osField.setEditable(false); - versionField.setEditable(false); - softwareField.setEditable(false); - timeField.setEditable(false); - MessageDialog.showComponent(Res.getString("title.version.and.time"), Res.getString("message.client.information", UserManager.unescapeJID(jid)), SparkRes.getImageIcon(SparkRes.PROFILE_IMAGE_24x24), panel, SparkManager.getMainWindow(), 400, 300, false); - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/language/LanguagePlugin.java b/src/java/org/jivesoftware/sparkimpl/plugin/language/LanguagePlugin.java deleted file mode 100644 index 75e93d7b4..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/language/LanguagePlugin.java +++ /dev/null @@ -1,144 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.language; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -import java.awt.event.ActionEvent; -import java.io.File; -import java.net.URL; -import java.net.URLDecoder; -import java.util.Enumeration; -import java.util.Locale; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.nio.charset.Charset; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.JMenu; -import javax.swing.JOptionPane; -import javax.swing.UIManager; - -/** - * Allows for changing of default languages within Spark. - * - * @author Derek DeMoro - */ -public class LanguagePlugin implements Plugin { - - private Locale[] locales; - private JMenu languageMenu; - - public void initialize() { - // Register with action menu - final JMenu actionsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions")); - - languageMenu = new JMenu(Res.getString("menuitem.languages")); - languageMenu.setIcon(SparkRes.getImageIcon("LANGUAGE_ICON")); - - locales = Locale.getAvailableLocales(); - - // Load files - URL sparkJar = getClass().getClassLoader().getResource("spark.jar"); - if (sparkJar == null) { - sparkJar = getClass().getProtectionDomain().getCodeSource().getLocation(); - if (sparkJar == null) return; - } - - try { - String url = URLDecoder.decode(sparkJar.getPath(), Charset.defaultCharset().toString()); - ZipFile zipFile = new JarFile(new File(url)); - for (Enumeration e = zipFile.entries(); e.hasMoreElements();) { - JarEntry entry = (JarEntry)e.nextElement(); - String propertiesName = entry.getName(); - // Ignore any manifest.mf entries. - if (propertiesName.endsWith(".properties")) { - int lastIndex = propertiesName.lastIndexOf("i18n_"); - int period = propertiesName.lastIndexOf("."); - if (lastIndex == -1 && propertiesName.contains("spark_i18n")) { - addLanguage("en"); - } - else { - String language = propertiesName.substring(lastIndex + 5, period); - addLanguage(language); - } - } - } - zipFile.close(); - } - catch (Throwable e) { - Log.error("Error unzipping plugin", e); - } - - actionsMenu.add(languageMenu); - } - - private void addLanguage(String language) { - for (final Locale locale : locales) { - if (locale.toString().equals(language)) { - Action action = new AbstractAction() { - private static final long serialVersionUID = -7093236616888591766L; - - public void actionPerformed(ActionEvent e) { - final LocalPreferences preferences = SettingsManager.getLocalPreferences(); - preferences.setLanguage(locale.toString()); - SettingsManager.saveSettings(); - - UIManager.put("OptionPane.yesButtonText", Res.getString("yes")); - UIManager.put("OptionPane.noButtonText", Res.getString("no")); - - int ok = JOptionPane.showConfirmDialog(SparkManager.getMainWindow(), Res.getString("message.restart.required"), Res. getString("title.confirmation"), JOptionPane.YES_NO_OPTION); - if (ok == JOptionPane.YES_OPTION) { - SparkManager.getMainWindow().closeConnectionAndInvoke("Language Change"); - } - } - }; - String label = locale.getDisplayLanguage(locale); - if (locale.getDisplayCountry(locale) != null && - locale.getDisplayCountry(locale).trim().length() > 0) { - label = label + "-" + locale.getDisplayCountry(locale).trim(); - } - action.putValue(Action.NAME, label); - languageMenu.add(action); - break; - } - } - } - - public void shutdown() { - } - - public boolean canShutDown() { - return false; - } - - - public void uninstall() { - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutPlugin.java b/src/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutPlugin.java deleted file mode 100644 index f913edfef..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutPlugin.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.layout; - -import org.jivesoftware.MainWindow; -import org.jivesoftware.MainWindowListener; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.Plugin; - -public class LayoutPlugin implements Plugin { - - public void initialize() { - final MainWindow mainWindow = SparkManager.getMainWindow(); - - SparkManager.getMainWindow().addMainWindowListener(new MainWindowListener() { - public void shutdown() { - int x = mainWindow.getX(); - int y = mainWindow.getY(); - int width = mainWindow.getWidth(); - int height = mainWindow.getHeight(); - - LayoutSettings settings = LayoutSettingsManager.getLayoutSettings(); - - settings.setMainWindowHeight(height); - settings.setMainWindowWidth(width); - settings.setMainWindowX(x); - settings.setMainWindowY(y); - if (mainWindow.isDocked()){ - settings.setSplitPaneDividerLocation(mainWindow.getSplitPane().getDividerLocation()); - } - else{ - settings.setSplitPaneDividerLocation(-1); - } - LayoutSettingsManager.saveLayoutSettings(); - } - - public void mainWindowActivated() { - - } - - public void mainWindowDeactivated() { - - } - }); - } - - public void shutdown() { - - } - - public boolean canShutDown() { - return true; - } - - public void uninstall() { - // Do nothing. - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutSettings.java b/src/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutSettings.java deleted file mode 100644 index a958aea07..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutSettings.java +++ /dev/null @@ -1,161 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.layout; - -import java.awt.Toolkit; - - -public class LayoutSettings { - - private int mainWindowX; - private int mainWindowY; - private int mainWindowWidth; - private int mainWindowHeight; - - private int chatFrameX; - private int chatFrameY; - private int chatFrameWidth; - private int chatFrameHeight; - - private int preferencesFrameX; - private int preferencesFrameY; - private int preferencesFrameWidth; - private int preferencesFrameHeight; - private int dividerLocation = -1; - - public int getMainWindowX() { - return mainWindowX; - } - - public void setMainWindowX(int mainWindowX) { - this.mainWindowX = mainWindowX; - } - - public int getMainWindowY() { - return mainWindowY; - } - - public void setMainWindowY(int mainWindowY) { - this.mainWindowY = mainWindowY; - } - - public int getMainWindowWidth() { - if (mainWindowWidth < 100) { - mainWindowWidth = 100; - } else if (mainWindowWidth > Toolkit.getDefaultToolkit() - .getScreenSize().width) { - mainWindowWidth = Toolkit.getDefaultToolkit().getScreenSize().width - 50; - } - return mainWindowWidth; - } - - public void setMainWindowWidth(int mainWindowWidth) { - this.mainWindowWidth = mainWindowWidth; - } - - public int getMainWindowHeight() { - if (mainWindowHeight < 200) { - mainWindowHeight = 500; - } else if (mainWindowHeight > Toolkit.getDefaultToolkit() - .getScreenSize().height) { - mainWindowHeight = Toolkit.getDefaultToolkit().getScreenSize().height - 50; - } - return mainWindowHeight; - } - - public void setMainWindowHeight(int mainWindowHeight) { - this.mainWindowHeight = mainWindowHeight; - } - - public int getChatFrameX() { - return chatFrameX; - } - - public void setChatFrameX(int chatFrameX) { - this.chatFrameX = chatFrameX; - } - - public int getChatFrameY() { - return chatFrameY; - } - - public void setChatFrameY(int chatFrameY) { - this.chatFrameY = chatFrameY; - } - - public int getChatFrameWidth() { - return chatFrameWidth < 300 ? 300 : chatFrameWidth; - } - - public void setChatFrameWidth(int chatFrameWidth) { - this.chatFrameWidth = chatFrameWidth; - } - - public int getChatFrameHeight() { - return chatFrameHeight < 300 ? 300 : chatFrameHeight; - } - - public void setChatFrameHeight(int chatFrameHeight) { - this.chatFrameHeight = chatFrameHeight; - } - - public void setSplitPaneDividerLocation(int dividerLocation) { - this.dividerLocation = dividerLocation; - - } - - public int getPreferencesFrameX() { - return preferencesFrameX; - } - - public void setPreferencesFrameX(int preferencesFrameX) { - this.preferencesFrameX = preferencesFrameX; - } - - public int getPreferencesFrameY() { - return preferencesFrameY; - } - - public void setPreferencesFrameY(int preferencesFrameY) { - this.preferencesFrameY = preferencesFrameY; - } - - public int getPreferencesFrameWidth() { - return preferencesFrameWidth < 600 ? 600 : preferencesFrameWidth; - } - - public void setPreferencesFrameWidth(int preferencesFrameWidth) { - this.preferencesFrameWidth = preferencesFrameWidth; - } - - public int getPreferencesFrameHeight() { - return preferencesFrameHeight < 600 ? 600 : preferencesFrameHeight; - } - - public void setPreferencesFrameHeight(int preferencesFrameHeight) { - this.preferencesFrameHeight = preferencesFrameHeight; - } - - public int getSplitPaneDividerLocation() { - return dividerLocation; - } - - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutSettingsManager.java b/src/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutSettingsManager.java deleted file mode 100644 index 16e5c939f..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/layout/LayoutSettingsManager.java +++ /dev/null @@ -1,280 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.layout; - -import java.awt.Dimension; -import java.awt.Rectangle; -import java.awt.Toolkit; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.util.Properties; - -import org.jivesoftware.Spark; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.log.Log; - -/** - * Responsbile for the loading and persisting of LocalSettings. - */ -public class LayoutSettingsManager { - private static LayoutSettings layoutSettings; - - private LayoutSettingsManager() { - } - - /** - * Returns the LayoutSettings for this agent. - * - * @return the LayoutSettings for this agent. - */ - public static LayoutSettings getLayoutSettings() { - if (!exists() && layoutSettings == null) { - layoutSettings = new LayoutSettings(); - } - - if (layoutSettings == null) { - // Do Initial Load from FileSystem. - File settingsFile = getSettingsFile(); - layoutSettings = load(settingsFile); - } - return layoutSettings; - } - - /** - * Persists the settings to the local file system. - */ - public static void saveLayoutSettings() { - final Properties props = new Properties(); - - String mainWindowX = Integer.toString(layoutSettings.getMainWindowX()); - String mainWindowY = Integer.toString(layoutSettings.getMainWindowY()); - String mainWindowHeight = Integer.toString(layoutSettings.getMainWindowHeight()); - String mainWindowWidth = Integer.toString(layoutSettings.getMainWindowWidth()); - String chatFrameX = Integer.toString(layoutSettings.getChatFrameX()); - String chatFrameY = Integer.toString(layoutSettings.getChatFrameY()); - String chatFrameWidth = Integer.toString(layoutSettings.getChatFrameWidth()); - String chatFrameHeight = Integer.toString(layoutSettings.getChatFrameHeight()); - String splitDividerLocation = Integer.toString(layoutSettings.getSplitPaneDividerLocation()); - String preferencesFrameX = Integer.toString(layoutSettings.getPreferencesFrameX()); - String preferencesFrameY = Integer.toString(layoutSettings.getPreferencesFrameY()); - String preferencesFrameWidth = Integer.toString(layoutSettings.getPreferencesFrameWidth()); - String preferencesFrameHeight = Integer.toString(layoutSettings.getPreferencesFrameHeight()); - - props.setProperty("mainWindowX", mainWindowX); - props.setProperty("mainWindowY", mainWindowY); - props.setProperty("mainWindowHeight", mainWindowHeight); - props.setProperty("mainWindowWidth", mainWindowWidth); - - props.setProperty("chatFrameX", chatFrameX); - props.setProperty("chatFrameY", chatFrameY); - props.setProperty("chatFrameWidth", chatFrameWidth); - props.setProperty("chatFrameHeight", chatFrameHeight); - - props.setProperty("preferencesFrameX", preferencesFrameX); - props.setProperty("preferencesFrameY", preferencesFrameY); - props.setProperty("preferencesFrameWidth", preferencesFrameWidth); - props.setProperty("preferencesFrameHeight", preferencesFrameHeight); - - props.setProperty("splitDividerLocation", splitDividerLocation); - - try { - props.store(new FileOutputStream(getSettingsFile()), "Storing Spark Layout Settings"); - } - catch (Exception e) { - Log.error("Error saving settings.", e); - } - } - - /** - * Return true if the settings file exists. - * - * @return true if the settings file exists.('settings.xml') - */ - public static boolean exists() { - return getSettingsFile().exists(); - } - - /** - * Returns the settings file. - * - * @return the settings file. - */ - public static File getSettingsFile() { - File file = new File(Spark.getSparkUserHome()); - if (!file.exists()) { - file.mkdirs(); - } - return new File(file, "layout.settings"); - } - - private static LayoutSettings load(File file) { - final Properties props = new Properties(); - try { - props.load(new FileInputStream(file)); - - - LayoutSettings settings; - String mainWindowX = props.getProperty("mainWindowX"); - String mainWindowY = props.getProperty("mainWindowY"); - String mainWindowHeight = props.getProperty("mainWindowHeight"); - String mainWindowWidth = props.getProperty("mainWindowWidth"); - String chatFrameX = props.getProperty("chatFrameX"); - String chatFrameY = props.getProperty("chatFrameY"); - String chatFrameWidth = props.getProperty("chatFrameWidth"); - String chatFrameHeight = props.getProperty("chatFrameHeight"); - String splitDividerLocation = props.getProperty("splitDividerLocation"); - String preferencesFrameX = props.getProperty("preferencesFrameX"); - String preferencesFrameY = props.getProperty("preferencesFrameY"); - String preferencesFrameWidth = props.getProperty("preferencesFrameWidth"); - String preferencesFrameHeight = props.getProperty("preferencesFrameHeight"); - - settings = new LayoutSettings(); - - final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - int height = (int)screenSize.getHeight(); - int width = (int)screenSize.getWidth(); - - int mainWindowXInt = Integer.parseInt(mainWindowX); - int mainWindowYInt = Integer.parseInt(mainWindowY); - int mainWindowHeightInt = Integer.parseInt(mainWindowHeight); - int mainWindowWidthInt = Integer.parseInt(mainWindowWidth); - - if (!isValidWindowPosition(mainWindowXInt, mainWindowYInt, - mainWindowWidthInt, mainWindowHeightInt)) { - mainWindowXInt = (width - mainWindowWidthInt) / 2; - mainWindowYInt = (height - mainWindowHeightInt) / 2; - } - - int chatFrameXInt = Integer.parseInt(chatFrameX); - int chatFrameYInt = Integer.parseInt(chatFrameY); - int chatFrameWidthInt = Integer.parseInt(chatFrameWidth); - int chatFrameHeightInt = Integer.parseInt(chatFrameHeight); - - if (!isValidWindowPosition(chatFrameXInt, chatFrameYInt, - chatFrameWidthInt, chatFrameHeightInt)) { - chatFrameXInt = (width - chatFrameWidthInt) / 2; - chatFrameYInt = (height - chatFrameHeightInt) / 2; - } - - int preferencesFrameXInt = preferencesFrameX == null ? -1 : Integer.parseInt(preferencesFrameX); - int preferencesFrameYInt = preferencesFrameY == null ? -1 : Integer.parseInt(preferencesFrameY); - int preferencesFrameWidthInt = preferencesFrameWidth == null ? -1 : Integer.parseInt(preferencesFrameWidth); - int preferencesFrameHeightInt = preferencesFrameHeight == null ? -1 : Integer.parseInt(preferencesFrameHeight); - - if (!isValidWindowPosition(preferencesFrameXInt, preferencesFrameYInt, - preferencesFrameWidthInt, preferencesFrameHeightInt)) { - preferencesFrameXInt = (width - preferencesFrameWidthInt) / 2; - preferencesFrameYInt = (height - preferencesFrameHeightInt) / 2; - } - - int splitDividerLocationInt = splitDividerLocation == null ? -1 : Integer.parseInt(splitDividerLocation); - - if (chatFrameHeightInt < 100) { - chatFrameHeightInt = 100; - } - if (chatFrameWidthInt < 100) { - chatFrameWidthInt = 100; - } - if (preferencesFrameWidthInt < 600) { - preferencesFrameWidthInt = 600; - } - if (preferencesFrameHeightInt < 600) { - preferencesFrameHeightInt = 600; - } - - settings.setMainWindowX(mainWindowXInt); - settings.setMainWindowY(mainWindowYInt); - settings.setMainWindowHeight(mainWindowHeightInt); - settings.setMainWindowWidth(mainWindowWidthInt); - - settings.setChatFrameX(chatFrameXInt); - settings.setChatFrameY(chatFrameYInt); - settings.setChatFrameWidth(chatFrameWidthInt); - settings.setChatFrameHeight(chatFrameHeightInt); - settings.setSplitPaneDividerLocation(splitDividerLocationInt); - - settings.setPreferencesFrameX(preferencesFrameXInt); - settings.setPreferencesFrameY(preferencesFrameYInt); - settings.setPreferencesFrameWidth(preferencesFrameWidthInt); - settings.setPreferencesFrameHeight(preferencesFrameHeightInt); - - return settings; - } - catch (Exception e) { - Log.error(e); - return new LayoutSettings(); - } - } - - protected static boolean isValidWindowPosition(int x, int y, int width, int height) { - Rectangle windowTitleBounds = new Rectangle(x,y,width,20); - double windowTitleArea = windowTitleBounds.getWidth() * windowTitleBounds.getHeight(); - - Rectangle[] screenBounds = GraphicUtils.getScreenBounds(); - for (int i = 0; i < screenBounds.length; i++) { - Rectangle screen = screenBounds[i].getBounds(); - Rectangle intersection = screen.intersection(windowTitleBounds); - double visibleArea = intersection.getWidth() * intersection.getHeight(); - - // if 25% of it is visible in the device, then it is good - if ((visibleArea/windowTitleArea) > 0.25) - return true; - - } - - return false; - } - - /** - * converts a Rectangle to a String - * @param r - * @return - */ - public static String rectangleToString(Rectangle r) { - return r.x + "," + r.y + "," + r.width + "," + r.height; - } - - /** - * converts a String to a Rectangle - * @param s - * @return - */ - public static Rectangle stringToRectangle(String s) { - - if(s == null) - { - return new Rectangle(0,0,0,0); - } - - if (!s.matches("[0-9]*,[0-9]*,[0-9]*,[0-9]*")) { - return new Rectangle(0,0,0,0); - } else { - String[] arr = s.split(","); - - - return new Rectangle(Integer.parseInt(arr[0]), - Integer.parseInt(arr[1]), Integer.parseInt(arr[2]), - Integer.parseInt(arr[3])); - } - - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/manager/Enterprise.java b/src/java/org/jivesoftware/sparkimpl/plugin/manager/Enterprise.java deleted file mode 100644 index 08bf1051c..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/manager/Enterprise.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.manager; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; -import org.jivesoftware.smackx.disco.packet.DiscoverInfo; -import org.jivesoftware.smackx.disco.packet.DiscoverItems; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.util.log.Log; - -/** - * EnterpriseSparkManager is responsible for the detecting of features on the server. This allows for fine-grain control of - * feature sets to enable/disable within Spark. - * - * @author Derek DeMoro - */ -public class Enterprise { - - public static final String BROADCAST_FEATURE = "broadcast"; - public static final String MUC_FEATURE = "muc"; - public static final String VCARD_FEATURE = "vcard"; - public static final String FILE_TRANSFER_FEATURE = "file-transfer"; - - private static DiscoverInfo featureInfo; - - private boolean sparkManagerInstalled; - - public Enterprise() { - // Retrieve feature list. - populateFeatureSet(); - } - - /** - * Returns true if the Enterprise Spark Manager module is installed on the server we are currently connected to. - * - * @return true if Enterprise Spark Manager exists. - */ - public boolean isSparkManagerInstalled() { - return sparkManagerInstalled; - } - - /** - * Returns true if the feature is available. - * - * @param feature the name of the feature to detect. - * @return true if the feature is available on the server, otherwise false. - */ - public static boolean containsFeature(String feature) { - if (featureInfo == null) { - return true; - } - - return featureInfo.containsFeature(feature); - } - - private void populateFeatureSet() { - final ServiceDiscoveryManager disco = ServiceDiscoveryManager.getInstanceFor(SparkManager.getConnection()); - final DiscoverItems items = SparkManager.getSessionManager().getDiscoveredItems(); - for (DiscoverItems.Item item : items.getItems() ) { - String entity = item.getEntityID(); - if (entity != null) { - if (entity.startsWith("manager.")) { - sparkManagerInstalled = true; - - // Populate with feature sets. - try { - featureInfo = disco.discoverInfo(item.getEntityID()); - } - catch (XMPPException | SmackException e) { - Log.error("Error while retrieving feature list for SparkManager.", e); - } - - } - } - } - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/manager/Features.java b/src/java/org/jivesoftware/sparkimpl/plugin/manager/Features.java deleted file mode 100644 index b24f3aa61..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/manager/Features.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.manager; - -import org.jivesoftware.smack.packet.ExtensionElement; -import org.jivesoftware.smack.provider.ExtensionElementProvider; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - - -public class Features implements ExtensionElement { - - private List availableFeatures = new ArrayList<>(); - - - public List getAvailableFeatures() { - return availableFeatures; - } - - public void addFeature(String feature) { - availableFeatures.add(feature); - } - - /** - * Element name of the packet extension. - */ - public static final String ELEMENT_NAME = "event"; - - /** - * Namespace of the packet extension. - */ - public static final String NAMESPACE = "http://jabber.org/protocol/disco#info"; - - - public String getElementName() { - return ELEMENT_NAME; - } - - public String getNamespace() { - return NAMESPACE; - } - - public String toXML() { - return ( ""; - } - - public static class Provider extends ExtensionElementProvider - { - public Provider() { - } - - public Features parse( XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException { - Features features = new Features(); - boolean done = false; - while (!done) { - int eventType = parser.next(); - if (eventType == XmlPullParser.START_TAG && "event".equals(parser.getName())) { - parser.nextText(); - } - if (eventType == XmlPullParser.START_TAG && "feature".equals(parser.getName())) { - String feature = parser.getAttributeValue("", "var"); - features.addFeature(feature); - } - else if (eventType == XmlPullParser.END_TAG) { - if ("event".equals(parser.getName())) { - done = true; - } - } - } - - return features; - } - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/phone/IncomingCall.java b/src/java/org/jivesoftware/sparkimpl/plugin/phone/IncomingCall.java deleted file mode 100644 index c3bb9b559..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/phone/IncomingCall.java +++ /dev/null @@ -1,94 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.phone; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.resource.Res; - -import javax.swing.JLabel; -import javax.swing.JPanel; - -import java.awt.Color; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; - -public class IncomingCall extends JPanel { - private static final long serialVersionUID = -5840942759253687771L; - private JLabel callerNameLabel; - private JLabel callerNumberLabel; - - - public IncomingCall() { - setLayout(new GridBagLayout()); - setBackground(Color.white); - - callerNameLabel = new JLabel(); - callerNameLabel.setFont(new Font("Dialog", Font.BOLD, 13)); - callerNameLabel.setHorizontalAlignment(JLabel.CENTER); - - callerNumberLabel = new JLabel(); - callerNumberLabel.setFont(new Font("Dialog", Font.PLAIN, 12)); - callerNumberLabel.setHorizontalAlignment(JLabel.CENTER); - - - final JLabel phoneImage = new JLabel(SparkRes.getImageIcon(SparkRes.TELEPHONE_24x24)); - phoneImage.setHorizontalAlignment(JLabel.CENTER); - phoneImage.setVerticalTextPosition(JLabel.BOTTOM); - phoneImage.setHorizontalTextPosition(JLabel.CENTER); - phoneImage.setText(Res.getString("title.incoming.call")); - phoneImage.setFont(new Font("Dialog", Font.BOLD, 16)); - - - add(phoneImage, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 10, 0, 10), 0, 0)); - add(callerNameLabel, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 0, 0, 0), 0, 0)); - add(callerNumberLabel, new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 0, 10, 0), 0, 0)); - - } - - public void setCallerName(String user) { - callerNameLabel.setText(user); - } - - public void setCallerNumber(String number) { - final StringBuilder buf = new StringBuilder(); - if (number == null) { - return; - } - - if (number.trim().length() == 10) { - buf.append("("); - String areaCode = number.substring(0, 3); - buf.append(areaCode); - buf.append(") "); - - String nextThree = number.substring(3, 6); - buf.append(" "); - buf.append(nextThree); - buf.append("-"); - - String lastThree = number.substring(6, 10); - buf.append(lastThree); - } - - callerNumberLabel.setText(buf.toString()); - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/phone/JMFInit.java b/src/java/org/jivesoftware/sparkimpl/plugin/phone/JMFInit.java deleted file mode 100644 index 2e4c5148b..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/phone/JMFInit.java +++ /dev/null @@ -1,285 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.phone; - -import com.sun.media.ExclusiveUse; -import com.sun.media.util.Registry; -import org.jivesoftware.spark.util.log.Log; - -import javax.media.Format; -import javax.media.PlugInManager; -import javax.media.Renderer; -import javax.media.format.AudioFormat; - -import java.awt.Frame; -import java.util.Vector; - -public class JMFInit extends Frame implements Runnable { - private static final long serialVersionUID = 6591937615313371376L; - - public JMFInit(String[] args, boolean visible) { - super("Initializing JMF..."); - - Registry.set("secure.allowCaptureFromApplets", true); - Registry.set("secure.allowSaveFileFromApplets", true); - - - updateTemp(args); - - try { - Registry.commit(); - } - catch (Exception e) { - - message("Failed to commit to JMFRegistry!"); - } - - Thread detectThread = new Thread(this); - detectThread.run(); - - /* - * int slept = 0; while (!done && slept < 60 * 1000 * 2) { try { - * Thread.currentThread().sleep(500); } catch (InterruptedException ie) { } - * slept += 500; } - * - * if (!done) { console.error("Detection is taking too long! - * Aborting!"); message("Detection is taking too long! Aborting!"); } - * - * try { Thread.currentThread().sleep(2000); } catch - * (InterruptedException ie) { } - */ - } - - public void run() { - detectDirectAudio(); - detectS8DirectAudio(); - detectCaptureDevices(); - } - - private void updateTemp(String[] args) { - if (args != null && args.length > 0) { - String tempDir = args[0]; - - message("Setting cache directory to " + tempDir); - try { - Registry.set("secure.cacheDir", tempDir); - Registry.commit(); - - message("Updated registry"); - } - catch (Exception e) { - message("Couldn't update registry!"); - } - } - } - - private void detectCaptureDevices() { - // check if JavaSound capture is available - message("Looking for Audio capturer"); - Class dsauto; - try { - dsauto = Class.forName("DirectSoundAuto"); - dsauto.newInstance(); - message("Finished detecting DirectSound capturer"); - } - catch (ThreadDeath td) { - throw td; - } - catch (Throwable t) { - // Nothing to do - } - - Class jsauto; - try { - jsauto = Class.forName("JavaSoundAuto"); - jsauto.newInstance(); - message("Finished detecting javasound capturer"); - } - catch (ThreadDeath td) { - throw td; - } - catch (Throwable t) { - message("JavaSound capturer detection failed!"); - } - - /* - // Check if VFWAuto or SunVideoAuto is available - message("Looking for video capture devices"); - Class auto = null; - Class autoPlus = null; - try { - auto = Class.forName("VFWAuto"); - } - catch (Exception e) { - } - if (auto == null) { - try { - auto = Class.forName("SunVideoAuto"); - } - catch (Exception ee) { - - } - try { - autoPlus = Class.forName("SunVideoPlusAuto"); - } - catch (Exception ee) { - - } - } - if (auto == null) { - try { - auto = Class.forName("V4LAuto"); - } - catch (Exception ee) { - - } - } - try { - Object instance = auto.newInstance(); - if (autoPlus != null) { - Object instancePlus = autoPlus.newInstance(); - } - - message("Finished detecting video capture devices"); - } - catch (ThreadDeath td) { - throw td; - } - catch (Throwable t) { - - message("Capture device detection failed!"); - } - */ - } - - private void detectDirectAudio() { - Class cls; - int plType = PlugInManager.RENDERER; - String dar = "com.sun.media.renderer.audio.DirectAudioRenderer"; - try { - // Check if this is the Windows Performance Pack - hack - Class.forName("VFWAuto"); - // Check if DS capture is supported, otherwise fail DS renderer - // since NT doesn't have capture - Class.forName("com.sun.media.protocol.dsound.DSound"); - // Find the renderer class and instantiate it. - cls = Class.forName(dar); - - Renderer rend = (Renderer)cls.newInstance(); - try { - // Set the format and open the device - AudioFormat af = new AudioFormat(AudioFormat.LINEAR, 44100, 16, - 2); - rend.setInputFormat(af); - rend.open(); - Format[] inputFormats = rend.getSupportedInputFormats(); - // Register the device - PlugInManager.addPlugIn(dar, inputFormats, new Format[0], - plType); - // Move it to the top of the list - Vector rendList = PlugInManager.getPlugInList(null, null, plType); - int listSize = rendList.size(); - if (rendList.elementAt(listSize - 1).equals(dar)) { - rendList.removeElementAt(listSize - 1); - rendList.insertElementAt(dar, 0); - PlugInManager.setPlugInList(rendList, plType); - PlugInManager.commit(); - // Log.debug("registered"); - } - rend.close(); - } - catch (Throwable t) { - // Log.debug("Error " + t); - } - } - catch (Throwable tt) { - // Nothing to do - } - } - - private void detectS8DirectAudio() { - Class cls; - int plType = PlugInManager.RENDERER; - String dar = "com.sun.media.renderer.audio.DirectAudioRenderer"; - try { - // Check if this is the solaris Performance Pack - hack - Class.forName("SunVideoAuto"); - - // Find the renderer class and instantiate it. - cls = Class.forName(dar); - - Renderer rend = (Renderer)cls.newInstance(); - - if (rend instanceof ExclusiveUse - && !((ExclusiveUse)rend).isExclusive()) { - // sol8+, DAR supports mixing - Vector rendList = PlugInManager.getPlugInList(null, null, - plType); - int listSize = rendList.size(); - boolean found = false; - String rname; - - for (int i = 0; i < listSize; i++) { - rname = rendList.elementAt(i); - if (rname.equals(dar)) { // DAR is in the registry - found = true; - rendList.removeElementAt(i); - break; - } - } - - if (found) { - rendList.insertElementAt(dar, 0); - PlugInManager.setPlugInList(rendList, plType); - PlugInManager.commit(); - } - } - } - catch (Throwable tt) { - // Nothing to do - } - } - - private void message(String message) { - Log.debug(message); - } - -// private void createGUI() { -// TextArea textBox = new TextArea(5, 50); -// add("Center", textBox); -// textBox.setEditable(false); -// addNotify(); -// pack(); -// -// int scrWidth = (int)Toolkit.getDefaultToolkit().getScreenSize() -// .getWidth(); -// int scrHeight = (int)Toolkit.getDefaultToolkit().getScreenSize() -// .getHeight(); -// -// setLocation((scrWidth - getWidth()) / 2, (scrHeight - getHeight()) / 2); -// -// setVisible(visible); -// -// } - - public static void start(boolean visible) { - new JMFInit(null, visible); - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/phone/PhonePlugin.java b/src/java/org/jivesoftware/sparkimpl/plugin/phone/PhonePlugin.java deleted file mode 100644 index 66423cadb..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/phone/PhonePlugin.java +++ /dev/null @@ -1,346 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.phone; - -import org.jivesoftware.phone.client.*; -import org.jivesoftware.phone.client.action.PhoneActionIQProvider; -import org.jivesoftware.phone.client.event.PhoneEventPacketExtensionProvider; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.provider.ProviderManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.phone.PhoneManager; -import org.jivesoftware.spark.plugin.ContextMenuListener; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.*; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.util.*; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; -import org.jivesoftware.sparkimpl.plugin.idle.UserIdlePlugin; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -import javax.swing.*; -import java.awt.event.*; -import java.util.TimerTask; - -public class PhonePlugin implements Plugin { - public static PhoneClient phoneClient; - private DialPanel dialPanel; - // private Alert incomingDialog; - private JFrame dialDialog; - - public static Presence offPhonePresence; - public static Presence onPhonePresence; - public void initialize() { - ProviderManager.addExtensionProvider("phone-event", "http://jivesoftware.com/xmlns/phone", new PhoneEventPacketExtensionProvider()); - ProviderManager.addIQProvider("phone-action", "http://jivesoftware.com/xmlns/phone", new PhoneActionIQProvider()); - - final XMPPConnection con = SparkManager.getConnection(); - - - SwingWorker worker = new SwingWorker() { - public Object construct() { - try { - phoneClient = new PhoneClient(con); - - // Add BaseListener - phoneClient.addEventListener(new PhoneListener()); - } - catch (Exception e) { - // Ignore because the user does not have support. - //Log.debug(e); - } - return phoneClient; - } - - public void finished() { - if (phoneClient != null) { - setupPhoneSystem(); - } - } - }; - - worker.start(); - } - - private void setupPhoneSystem() { - // Add Dial Menu - final JMenu viewMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions")); - JMenuItem dialNumberMenu = new JMenuItem(SparkRes.getImageIcon(SparkRes.ON_PHONE_IMAGE)); - ResourceUtils.resButton(dialNumberMenu, Res.getString("button.dial.number")); - - // Add Listener - dialNumberMenu.addActionListener( e -> { - dialPanel = new DialPanel(); - dialPanel.getDialButton().addActionListener( e1 -> { - String number = dialPanel.getNumberToDial(); - if (ModelUtil.hasLength(number)) { - dialPanel.setText(Res.getString("message.calling", number)); - dialPanel.changeToRinging(); - callExtension(number); - - } - - } ); - - dialDialog = PhoneDialog.invoke(dialPanel, Res.getString("title.dial.phone"), Res.getString("message.number.to.call"), null); - dialPanel.getDialField().requestFocusInWindow(); - - dialPanel.getDialField().addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { - if (e.getKeyChar() == KeyEvent.VK_ENTER) { - try { - String number = dialPanel.getNumberToDial(); - if (ModelUtil.hasLength(number)) { - dialPanel.setText(Res.getString("message.calling", number)); - dialPanel.changeToRinging(); - callExtension(number); - - } - e.consume(); - } - catch (Exception ex) { - Log.error(ex); - } - } - } - }); - } ); - viewMenu.add(dialNumberMenu); - - // Add ChatRoomListener to call users based on JID - SparkManager.getChatManager().addChatRoomListener(new ChatRoomListenerAdapter() { - public void chatRoomOpened(final ChatRoom room) { - if (room instanceof ChatRoomImpl) { - final ChatRoomButton callButton = new ChatRoomButton("", SparkRes.getImageIcon(SparkRes.TELEPHONE_24x24)); - callButton.setToolTipText(Res.getString("tooltip.place.a.call")); - final ChatRoomImpl chatRoom = (ChatRoomImpl)room; - boolean phoneEnabled = false; - try { - phoneEnabled = phoneClient.isPhoneEnabled( XmppStringUtils.parseBareJid(chatRoom.getParticipantJID())); - } - catch (Exception e) { - Log.error(e); - } - - if (phoneEnabled) { - room.addChatRoomButton(callButton); - callButton.addActionListener( e -> callJID(chatRoom.getParticipantJID()) ); - } - } - } - }); - - ContactList contactList = SparkManager.getWorkspace().getContactList(); - contactList.addContextMenuListener(new ContextMenuListener() { - public void poppingUp(Object object, final JPopupMenu popup) { - if (object instanceof ContactItem) { - final ContactItem item = (ContactItem)object; - - boolean phoneEnabled = false; - - - try { - phoneEnabled = phoneClient.isPhoneEnabled(item.getJID()); - } - catch (Exception e) { - Log.error("There was an error retrieving phone information.", e); - } - - if (phoneEnabled) { - Action callAction = new AbstractAction() { - private static final long serialVersionUID = 7221741748743018431L; - - public void actionPerformed(ActionEvent e) { - callJID(item.getJID()); - } - }; - - callAction.putValue(Action.NAME, "Call"); - callAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.ON_PHONE_IMAGE)); - popup.add(callAction); - } - } - } - - public void poppingDown(JPopupMenu popup) { - - } - - public boolean handleDefaultAction(MouseEvent e) { - return false; - } - }); - } - - private class PhoneListener extends BasePhoneEventListener { - - public void handleOnPhone(OnPhoneEvent event) { - if (dialDialog != null) { - dialDialog.setVisible(false); - } - - // Get current presence if necessary. - offPhonePresence = SparkManager.getWorkspace().getStatusBar().getPresence(); - - - // Send "on the phone" presence - onPhonePresence = new Presence(Presence.Type.available, "On the phone", 1, Presence.Mode.away); - SparkManager.getSessionManager().changePresence(onPhonePresence); - } - - - public void handleHangUp(HangUpEvent event) { - onPhonePresence = null; - if (dialDialog != null) { - dialDialog.setVisible(false); - } - - if (offPhonePresence != null) { - - if (((offPhonePresence.getMode().equals(Presence.Mode.away)) && (!UserIdlePlugin.getDesktopLockStatus()) - && (UserIdlePlugin.latestPresence != null)) && (!UserIdlePlugin.latestPresence.getStatus().contentEquals("On the Phone"))) { - SparkManager.getSessionManager().changePresence(UserIdlePlugin.latestPresence); - Log.debug("PhonePlugin: Setting presence from UserIdlePlugin"); - - } else if ((UserIdlePlugin.getDesktopLockStatus()) && ((offPhonePresence.getStatus().equals("Online")) - || (offPhonePresence.getStatus().equals("Free to chat")))) { - Presence presence = new Presence(Presence.Type.available, UserIdlePlugin.pref.getIdleMessage(), 1, Presence.Mode.away); - SparkManager.getSessionManager().changePresence(presence); - Log.debug("PhonePlugin: Desktop is Locked - Setting presence from pref.idle message"); - - } else if (UserIdlePlugin.getDesktopLockStatus() && (!offPhonePresence.isAway())) { - Presence presence = new Presence(Presence.Type.available, offPhonePresence.getStatus(), 1, Presence.Mode.away); - SparkManager.getSessionManager().changePresence(presence); - Log.debug("PhonePlugin: Desktop is Locked - Setting presence from user defined presence"); - - } else { - // Set user to previous presence state when all phone calls are hung up. - SparkManager.getSessionManager().changePresence(offPhonePresence); - Log.debug("PhonePlugin: Setting Presence from PhonePlugin."); - } - - - } else { - // If no previous state available, set status to Available - Presence availablePresence = new Presence(Presence.Type.available, "Online", 1, Presence.Mode.available); - - SparkManager.getSessionManager().changePresence(availablePresence); - Log.debug("no previous state available from Phone Plugin..setting to Online"); - - } - } - - public void handleRing(final RingEvent event) { - final TimerTask task = new SwingTimerTask() { - public void doRun() { - String callerID = event.getCallerID(); - if (ModelUtil.hasLength(callerID)) { - String number = PhoneManager.getNumbersFromPhone(callerID); - if (PhoneManager.getInstance().containsCurrentCall(number)) { - return; - } - } - displayRingUI(event); - } - }; - - TaskEngine.getInstance().schedule(task, 1000); - } - } - - private void displayRingUI(RingEvent event) { - IncomingCall incomingCall = new IncomingCall(); - boolean idExists = false; - if (ModelUtil.hasLength(event.getCallerIDName())) { - incomingCall.setCallerName(event.getCallerIDName()); - idExists = true; - } - - if (ModelUtil.hasLength(event.getCallerID())) { - incomingCall.setCallerNumber(event.getCallerID()); - idExists = true; - } - - if (!idExists) { - incomingCall.setCallerName(Res.getString("message.no.caller.id")); - } - - if (!SettingsManager.getLocalPreferences().getDisableAsteriskToasterPopup()) { - SparkToaster toasterManager = new SparkToaster(); - toasterManager.setTitle("Incoming Phone Call"); - toasterManager.setDisplayTime(15000); - toasterManager.showToaster(SparkRes.getImageIcon(SparkRes.ON_PHONE_IMAGE)); - toasterManager.setComponent(incomingCall); - - } - } - - - public void callExtension(final String number) { - final Runnable caller = () -> { - try { - phoneClient.dialByExtension(number); - } - catch (PhoneActionException e) { - Log.error(e); - } - }; - - TaskEngine.getInstance().submit(caller); - } - - public void callJID(final String jid) { - final Runnable caller = () -> { - try { - phoneClient.dialByJID(jid); - } - catch (PhoneActionException e) { - Log.error(e); - } - }; - - TaskEngine.getInstance().submit(caller); - } - - - public static PhoneClient getPhoneClient() { - return phoneClient; - } - - public void shutdown() { - - } - - public boolean canShutDown() { - return true; - } - - public void uninstall() { - // Do nothing. - } - - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyPlugin.java b/src/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyPlugin.java deleted file mode 100644 index 92a44898d..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/PrivacyPlugin.java +++ /dev/null @@ -1,166 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.privacy; - -import java.awt.event.MouseEvent; -import java.util.TimerTask; - - -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smackx.privacy.packet.PrivacyItem; -import org.jivesoftware.smackx.privacy.packet.PrivacyItem.Type; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.ContextMenuListener; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.privacy.list.SparkPrivacyList; - -/** - * This is Privacy plugin for Spark. - * - * This plugin built using specification: XEP-0016: Privacy Lists - * {@see http://xmpp.org/extensions/xep-0016.html} - * - * @author Zolotarev Konstantin, Bergunde Holger - */ -public class PrivacyPlugin implements Plugin { - - @Override - public void initialize() { - TimerTask pManagerInstance = new TimerTask() { - @Override - public void run() { - PrivacyManager.getInstance(); // Initiating PrivacyLists - - TimerTask thread = new TimerTask() { - @Override - public void run() { - addMenuItemToContactItems(); - } - }; - TaskEngine.getInstance().schedule(thread, 500); - } - }; - TaskEngine.getInstance().schedule(pManagerInstance, 1000); - - - } - - @Override - public void shutdown() { - // @todo remove Privacy List - } - - @Override - public boolean canShutDown() { - return false; - } - - @Override - public void uninstall() { - - } - - protected void addPrivacyListsToPresenceChange() { - - } - - // /** - // * Adding block menu item to contact popupmenu - // */ - protected void addMenuItemToContactItems() { - if (PrivacyManager.getInstance().isPrivacyActive()) { - SparkManager.getContactList().addContextMenuListener(new ContextMenuListener() { - @Override - public void poppingUp(Object object, JPopupMenu popup) { - - if (object instanceof ContactItem) { - final PrivacyManager pManager = PrivacyManager.getInstance(); - - if (pManager.hasActiveList()) { - final SparkPrivacyList activeList = pManager.getActiveList(); - - final ContactItem item = (ContactItem) object; - JMenuItem blockMenu; - - if (activeList.isBlockedItem(item.getJID())) { - blockMenu = new JMenuItem(Res.getString("menuitem.unblock.contact"), SparkRes.getImageIcon(SparkRes.UNBLOCK_CONTACT_16x16)); - blockMenu.addActionListener( ae -> { - if (item != null) { - try - { - activeList.removeItem( item.getJID()); - activeList.save(); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to remove item from block list: " + item, e ); - } - } - } ); - } else { - blockMenu = new JMenuItem(Res.getString("menuitem.block.contact"), SparkRes.getImageIcon(SparkRes.BLOCK_CONTACT_16x16)); - blockMenu.addActionListener( ae -> { - if (item != null) { - PrivacyItem pItem = new PrivacyItem(Type.jid, item.getJID(), false, activeList.getNewItemOrder()); - pItem.setFilterMessage(true); - pItem.setFilterPresenceOut(true); - - try - { - activeList.addItem(pItem); - activeList.save(); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to add item to block list: " + item, e ); - } - } - } ); - } - - popup.add(blockMenu); - } - } - } - - @Override - public void poppingDown(JPopupMenu popup) { - // ignore - } - - @Override - public boolean handleDefaultAction(MouseEvent e) { - return false; - } - }); - } - - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/list/PrivacyPresenceHandler.java b/src/java/org/jivesoftware/sparkimpl/plugin/privacy/list/PrivacyPresenceHandler.java deleted file mode 100644 index 5bba1038d..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/privacy/list/PrivacyPresenceHandler.java +++ /dev/null @@ -1,174 +0,0 @@ -package org.jivesoftware.sparkimpl.plugin.privacy.list; - - - -import java.util.Collection; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smackx.privacy.packet.PrivacyItem; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.ui.ContactGroup; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.sparkimpl.plugin.privacy.PrivacyManager; - - -/** - * - * @author Bergunde Holger - */ - -public class PrivacyPresenceHandler implements SparkPrivacyItemListener { - - - - /** - * Send Unavailable (offline status) to jid . - * - * @param jid - * JID to send offline status - */ - public void sendUnavailableTo(String jid) throws SmackException.NotConnectedException - { - Presence pack = new Presence(Presence.Type.unavailable); - pack.setTo(jid); - SparkManager.getConnection().sendStanza(pack); - } - - /** - * Send my presence for user - * - * @param jid - * JID to send presence - */ - public void sendRealPresenceTo(String jid) throws SmackException.NotConnectedException - { - Presence presence = SparkManager.getWorkspace().getStatusBar().getPresence(); - Presence pack = new Presence(presence.getType(), presence.getStatus(), 1, presence.getMode()); - pack.setTo(jid); - SparkManager.getConnection().sendStanza(pack); - } - - public void setIconsForList(SparkPrivacyList list) throws SmackException.NotConnectedException - { - for (PrivacyItem pItem : list.getPrivacyItems()) { - if (pItem.getType().equals(PrivacyItem.Type.jid)) { - setBlockedIconToContact(pItem.getValue()); - if (pItem.isFilterPresenceOut()) { - sendUnavailableTo(pItem.getValue()); - } - } - - if (pItem.getType().equals(PrivacyItem.Type.group)) { - ContactGroup group = SparkManager.getWorkspace().getContactList().getContactGroup(pItem.getValue()); - for (ContactItem citem : group.getContactItems()) { - setBlockedIconToContact(citem.getJID()); - if (pItem.isFilterPresenceOut()) { - sendUnavailableTo(citem.getJID()); - } - } - - } - - } - SparkManager.getContactList().updateUI(); - } - - private void setBlockedIconToContact(String jid) { - Collection items = SparkManager.getWorkspace().getContactList().getContactItemsByJID(jid); - for (ContactItem contactItem : items) { - if (contactItem != null) { - contactItem.setSpecialIcon(SparkRes.getImageIcon("PRIVACY_ICON_SMALL")); - } - } - } - - public void removeIconsForList(SparkPrivacyList list) throws SmackException.NotConnectedException - { - for (PrivacyItem pItem : list.getPrivacyItems()) { - if (pItem.getType().equals(PrivacyItem.Type.jid)) { - removeBlockedIconFromContact(pItem.getValue()); - if (pItem.isFilterPresenceOut()) { - sendRealPresenceTo(pItem.getValue()); - } - } - - if (pItem.getType().equals(PrivacyItem.Type.group)) { - ContactGroup group = SparkManager.getWorkspace().getContactList().getContactGroup(pItem.getValue()); - for (ContactItem citem : group.getContactItems()) { - removeBlockedIconFromContact(citem.getJID()); - if (pItem.isFilterPresenceOut()) { - sendRealPresenceTo(citem.getJID()); - } - } - } - - } - SparkManager.getContactList().updateUI(); - } - - private void removeBlockedIconFromContact(String jid) { - Collection items = SparkManager.getWorkspace().getContactList().getContactItemsByJID(jid); - for (ContactItem item : items) { - if (item != null) { - item.setSpecialIcon(null); - } - } - - } - - @Override - public void itemAdded(PrivacyItem item, String listname) throws SmackException.NotConnectedException - { - PrivacyManager pmanager = PrivacyManager.getInstance(); - if (pmanager.getPrivacyList(listname).isActive()) { - if (item.getType().equals(PrivacyItem.Type.jid)) { - setBlockedIconToContact(item.getValue()); - if (item.isFilterPresenceOut()) { - sendUnavailableTo(item.getValue()); - } - } - - if (item.getType().equals(PrivacyItem.Type.group)) { - ContactGroup group = SparkManager.getWorkspace().getContactList().getContactGroup(item.getValue()); - for (ContactItem citem : group.getContactItems()) { - setBlockedIconToContact(citem.getJID()); - if (item.isFilterPresenceOut()) { - sendUnavailableTo(citem.getJID()); - } - } - - } - SparkManager.getContactList().updateUI(); - } - } - - @Override - public void itemRemoved(PrivacyItem item, String listname) throws SmackException.NotConnectedException - { - PrivacyManager pmanager = PrivacyManager.getInstance(); - if (pmanager.getPrivacyList(listname).isActive()) { - if (item.getType().equals(PrivacyItem.Type.jid)) { - removeBlockedIconFromContact(item.getValue()); - if (item.isFilterPresenceOut()) { - sendRealPresenceTo(item.getValue()); - } - } - - if (item.getType().equals(PrivacyItem.Type.group)) { - ContactGroup group = SparkManager.getWorkspace().getContactList().getContactGroup(item.getValue()); - for (ContactItem citem : group.getContactItems()) { - removeBlockedIconFromContact(citem.getJID()); - if (item.isFilterPresenceOut()) { - sendRealPresenceTo(citem.getJID()); - } - } - - } - SparkManager.getContactList().updateUI(); - } - - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/PrivateNotes.java b/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/PrivateNotes.java deleted file mode 100644 index 5990fd685..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/PrivateNotes.java +++ /dev/null @@ -1,170 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.scratchpad; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.iqprivate.PrivateDataManager; -import org.jivesoftware.smackx.iqprivate.packet.PrivateData; -import org.jivesoftware.smackx.iqprivate.provider.PrivateDataProvider; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.util.log.Log; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; - -/** - * @author Derek DeMoro - */ -public class PrivateNotes implements PrivateData { - - private String notes; - - /** - * Required Empty Constructor to use Bookmarks. - */ - public PrivateNotes() { - } - - - public String getNotes() { - return notes; - } - - public void setNotes(String notes) { - if(notes!=null) - { - this.notes=notes.replaceAll("&","&"); - } else { - this.notes=notes; - } - } - - public void setMyNotes(String notes) { - this.notes=notes; - - } - - /** - * Returns the root element name. - * - * @return the element name. - */ - public String getElementName() { - return "scratchpad"; - } - - /** - * Returns the root element XML namespace. - * - * @return the namespace. - */ - public String getNamespace() { - return "scratchpad:notes"; - } - - /** - * Returns the XML reppresentation of the PrivateData. - * - * @return the private data as XML. - */ - public String toXML() { - StringBuilder buf = new StringBuilder(); - buf.append(""); - - if (getNotes() != null) { - buf.append("").append(getNotes()).append(""); - } - - buf.append(""); - return buf.toString(); - } - - /** - * The IQ Provider for BookmarkStorage. - * - * @author Derek DeMoro - */ - public static class Provider implements PrivateDataProvider { - - PrivateNotes notes = new PrivateNotes(); - - /** - * Empty Constructor for PrivateDataProvider. - */ - public Provider() { - super(); - } - - public PrivateData parsePrivateData(XmlPullParser parser) throws XmlPullParserException, IOException { - boolean done = false; - while (!done) { - int eventType = parser.next(); - if (eventType == XmlPullParser.START_TAG && "text".equals(parser.getName())) { - notes.setNotes(parser.nextText()); - } - else if (eventType == XmlPullParser.END_TAG) { - if ("scratchpad".equals(parser.getName())) { - done = true; - } - } - } - - - return notes; - } - } - - public static void savePrivateNotes(PrivateNotes notes) { - PrivateDataManager manager = PrivateDataManager.getInstanceFor(SparkManager.getConnection()); - - PrivateDataManager.addPrivateDataProvider("scratchpad", "scratchpad:notes", new PrivateNotes.Provider()); - try { - manager.setPrivateData(notes); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - } - - public static PrivateNotes getPrivateNotes() { - PrivateDataManager manager = PrivateDataManager.getInstanceFor(SparkManager.getConnection()); - - PrivateDataManager.addPrivateDataProvider("scratchpad", "scratchpad:notes", new PrivateNotes.Provider()); - - PrivateNotes notes = null; - - try { - notes = (PrivateNotes)manager.getPrivateData("scratchpad", "scratchpad:notes"); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - - if(notes.getNotes() != null ) - { - String note=notes.getNotes().replaceAll("&","&"); - notes.setMyNotes(note); - } - - return notes; - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/ScratchPadPlugin.java b/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/ScratchPadPlugin.java deleted file mode 100644 index edc804446..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/ScratchPadPlugin.java +++ /dev/null @@ -1,575 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.scratchpad; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Font; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.TimerTask; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.ButtonGroup; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextField; -import javax.swing.JTextPane; -import javax.swing.JToggleButton; -import javax.swing.KeyStroke; - -import org.jdesktop.swingx.calendar.DateUtils; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.component.VerticalFlowLayout; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.TaskEngine; - -/** - * - */ -public class ScratchPadPlugin implements Plugin { - - public static boolean SHOW_ALL_TASKS = true; - - private static final String dateShortFormat = ((SimpleDateFormat)SimpleDateFormat.getDateInstance(SimpleDateFormat.SHORT)).toPattern(); - private SimpleDateFormat formatter = new SimpleDateFormat(dateShortFormat); - private static List taskList = new ArrayList<>(); - private static JPanel panel_events; - private static JPanel mainPanel; - private static JFrame frame; - - public void initialize() { - - TimerTask startTask = new TimerTask() { - @Override - public void run() { - panel_events = new JPanel(); - mainPanel = new JPanel(); - } - }; - - TaskEngine.getInstance().schedule(startTask, 500); - - ContactList contactList = SparkManager.getWorkspace().getContactList(); - contactList.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control F6"), "viewNotes"); - - contactList.getActionMap().put("viewNotes", new AbstractAction("viewNotes") { - private static final long serialVersionUID = -3258500919859584696L; - - public void actionPerformed(ActionEvent evt) { - // Retrieve notes and dispaly in editor. - retrieveNotes(); - } - }); - - contactList.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control F5"), "viewTasks"); - - contactList.getActionMap().put("viewTasks", new AbstractAction("viewTasks") { - private static final long serialVersionUID = 8589614513097901484L; - - public void actionPerformed(ActionEvent evt) { - // Retrieve notes and dispaly in editor. - showTaskList(); - } - }); - - //TODO REMOVE - @SuppressWarnings("unused") - int index = -1; - JPanel commandPanel = SparkManager.getWorkspace().getCommandPanel(); - for (int i = 0; i < commandPanel.getComponentCount(); i++) { - if (commandPanel.getComponent(i) instanceof JLabel) { - break; - } - } - - - JMenuItem taskMenu = new JMenuItem(Res.getString("button.view.tasklist"), - SparkRes.getImageIcon(SparkRes.DESKTOP_IMAGE)); - - JMenuItem notesMenu = new JMenuItem(Res.getString("button.view.notes"), - SparkRes.getImageIcon(SparkRes.DOCUMENT_16x16)); - - taskMenu.addActionListener( e -> showTaskList() ); - - notesMenu.addActionListener( e -> retrieveNotes() ); - - // Add To toolbar - final JMenu actionsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions")); - actionsMenu.addSeparator(); - actionsMenu.add(taskMenu); - actionsMenu.add(notesMenu); - - - // Start notifications. - new TaskNotification(); - - } - - private void showTaskList() { - frame = new JFrame(Res.getString("title.tasks")); - frame.setIconImage(SparkManager.getMainWindow().getIconImage()); - panel_events.removeAll(); - mainPanel.removeAll(); - - //final List taskList = new ArrayList(); - //final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); - mainPanel.setBackground(Color.white); - - final JPanel topPanel = new JPanel(new GridBagLayout()); - final JTextField taskField = new JTextField(); - final JTextField dueDateField = new JTextField(); - - final JButton addButton = new JButton(Res.getString("add")); - final JLabel addTaskLabel = new JLabel(Res.getString("label.add.task")); - topPanel.setOpaque(false); - - topPanel.add(addTaskLabel, new GridBagConstraints(0, 0, 1, 1, .9, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - topPanel.add(taskField, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 0, 2), 0, 0)); - - topPanel.add(dueDateField, new GridBagConstraints(1, 1, 1, 1, 0.1, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 0, 2), 50, 0)); - topPanel.add(addButton, new GridBagConstraints(3, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 0, 2), 0, 0)); - - topPanel.add(new JLabel(Res.getString("label.timeformat", formatter.toPattern())), new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - mainPanel.add(topPanel); - - // Add Selection - final JPanel middlePanel = new JPanel(new GridBagLayout()); - final JLabel showLabel = new JLabel(Res.getString("label.show")); - final JToggleButton allButton = new JToggleButton(Res.getString("button.tasks.all")); - final JToggleButton activeButton = new JToggleButton(Res.getString("button.tasks.active")); - final ButtonGroup buttonGroup = new ButtonGroup(); - buttonGroup.add(allButton); - buttonGroup.add(activeButton); - middlePanel.setOpaque(false); - - middlePanel.add(showLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - middlePanel.add(allButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - middlePanel.add(activeButton, new GridBagConstraints(2, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - - mainPanel.add(middlePanel); - mainPanel.setBackground(Color.white); - - final JPanel titlePanel = new JPanel(new BorderLayout()) { - private static final long serialVersionUID = -8812868562658925280L; - - public void paintComponent(Graphics g) { - Color startColor = Color.white; - Color endColor = new Color(198, 211, 247); - - Graphics2D g2 = (Graphics2D)g; - - int w = getWidth(); - int h = getHeight(); - - GradientPaint gradient = new GradientPaint(0, 0, startColor, w, h, endColor, true); - g2.setPaint(gradient); - g2.fillRect(0, 0, w, h); - } - - }; - final JLabel taskLabel = new JLabel(Res.getString("label.due") + " "); - taskLabel.setFont(taskLabel.getFont().deriveFont(Font.BOLD)); - titlePanel.add(taskLabel, BorderLayout.EAST); - mainPanel.add(titlePanel); - - Action showAllAction = new AbstractAction() { - private static final long serialVersionUID = -7031122285194582204L; - - public void actionPerformed(ActionEvent e) { - for (TaskUI ui : taskList) { - ui.setVisible(true); - } - - SHOW_ALL_TASKS = true; - } - }; - - Action showActiveAction = new AbstractAction() { - private static final long serialVersionUID = -7551153291479117311L; - - public void actionPerformed(ActionEvent e) { - for (TaskUI ui : taskList) { - if (ui.isSelected()) { - ui.setVisible(false); - } - } - - SHOW_ALL_TASKS = false; - } - }; - - final Action addAction = new AbstractAction() { - private static final long serialVersionUID = -5937301529216080813L; - - public void actionPerformed(ActionEvent e) { - String taskTitle = taskField.getText(); - if (!ModelUtil.hasLength(taskTitle)) { - return; - } - Task task = new Task(); - task.setTitle(taskTitle); - - // Set creation time. - final Date creationDate = new Date(); - task.setCreatedDate(creationDate.getTime()); - - // Set due date. - String dueDate = dueDateField.getText(); - if (ModelUtil.hasLength(dueDate)) { - - try { - Date date = formatter.parse(dueDate); - task.setDueDate(date.getTime()); - } - catch (ParseException e1) { - // Nothing to do - } - - } - - taskField.setText(""); - - final TaskUI taskUI = new TaskUI(task); - //mainPanel.add(taskUI); - panel_events.add(taskUI); - taskList.add(taskUI); - - panel_events.invalidate(); - panel_events.validate(); - panel_events.repaint(); - mainPanel.invalidate(); - mainPanel.validate(); - mainPanel.repaint(); - frame.invalidate(); - frame.validate(); - frame.repaint(); - } - }; - - mainPanel.add(panel_events); - panel_events.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); - panel_events.setBackground(Color.white); - - allButton.addActionListener(showAllAction); - activeButton.addActionListener(showActiveAction); - - GraphicUtils.makeSameSize(allButton, activeButton); - - addButton.addActionListener(addAction); - - Tasks tasks = Tasks.getTaskList(SparkManager.getConnection()); - updateTaskUI(tasks); - - if (SHOW_ALL_TASKS) { - allButton.setSelected(true); - } - else { - activeButton.setSelected(true); - showActiveAction.actionPerformed(null); - } - - long tomorrow = DateUtils.addDays(new Date().getTime(), 1); - SimpleDateFormat formatter = new SimpleDateFormat(dateShortFormat); - dueDateField.setText(formatter.format(new Date(tomorrow))); - - - final JScrollPane pane = new JScrollPane(mainPanel); - - frame.getContentPane().setLayout(new BorderLayout()); - frame.getContentPane().add(pane, BorderLayout.CENTER); - frame.pack(); - frame.setSize(400, 400); - - final Action saveAction = new AbstractAction() { - private static final long serialVersionUID = -4287799161421970177L; - - public void actionPerformed(ActionEvent actionEvent) { - // Save it. - Tasks tasks = new Tasks(); - for (TaskUI ui : taskList) { - Task task = ui.getTask(); - tasks.addTask(task); - } - - Tasks.saveTasks(tasks, SparkManager.getConnection()); - } - }; - - addButton.addKeyListener(new KeyAdapter() { - public void keyReleased(KeyEvent e) { - if (e.getKeyChar() == KeyEvent.VK_ESCAPE) { - frame.dispose(); - - saveAction.actionPerformed(null); - } - } - }); - - - frame.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent windowEvent) { - saveAction.actionPerformed(null); - } - }); - - taskField.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { - if (e.getKeyChar() == KeyEvent.VK_ENTER) { - addAction.actionPerformed(null); - } - } - }); - - - GraphicUtils.centerWindowOnComponent(frame, SparkManager.getMainWindow()); - frame.setVisible(true); - } - - /** - * Updates the GUI of Tasks - * - * @param tasks Tasks - */ - public static void updateTaskUI(Tasks tasks) { - panel_events.removeAll(); - taskList.clear(); - - for (Object o : tasks.getTasks()) { - Task task = (Task) o; - final TaskUI taskUI = new TaskUI(task); - - if ( !SHOW_ALL_TASKS ) { - if ( taskUI.isSelected() ) { - taskUI.setVisible(false); - }else { - taskUI.setVisible(true); - } - } - - panel_events.add(taskUI); - taskList.add(taskUI); - } - - panel_events.invalidate(); - panel_events.validate(); - panel_events.repaint(); - mainPanel.invalidate(); - mainPanel.validate(); - mainPanel.repaint(); - frame.invalidate(); - frame.validate(); - frame.repaint(); - } - - /** - * Retrieve private notes from server. - */ - private void retrieveNotes() { - // Retrieve private notes from server. - final SwingWorker notesWorker = new SwingWorker() { - public Object construct() { - return PrivateNotes.getPrivateNotes(); - } - - public void finished() { - final PrivateNotes privateNotes = (PrivateNotes)get(); - showPrivateNotes(privateNotes); - } - }; - - notesWorker.start(); - } - - private void showPrivateNotes(final PrivateNotes privateNotes) { - String text = privateNotes.getNotes(); - - final JLabel titleLabel = new JLabel("Notepad"); - titleLabel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.LIGHT_GRAY)); - titleLabel.setFont(new Font("Dialog", Font.BOLD, 13)); - titleLabel.setHorizontalAlignment(JLabel.CENTER); - - - final JTextPane pane = new JTextPane(); - pane.setFont(new Font("Dialog", Font.PLAIN, 12)); - - pane.setOpaque(false); - - final JScrollPane scrollPane = new JScrollPane(pane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - scrollPane.setOpaque(false); - scrollPane.getViewport().setOpaque(false); - - pane.setText(text); - final RolloverButton button = new RolloverButton(Res.getString("save"), null); - final RolloverButton cancelButton = new RolloverButton(Res.getString("cancel"), null); - ResourceUtils.resButton(button, Res.getString("button.save")); - ResourceUtils.resButton(cancelButton, Res.getString("button.cancel")); - - final JFrame frame = new JFrame(Res.getString("title.notes")); - - - final JPanel mainPanel = new JPanel(); - - pane.addKeyListener(new KeyAdapter() { - public void keyReleased(KeyEvent e) { - if (e.getKeyChar() == KeyEvent.VK_ESCAPE) { - frame.dispose(); - - // Save it. - String text = pane.getText(); - privateNotes.setNotes(text); - PrivateNotes.savePrivateNotes(privateNotes); - } - } - }); - - mainPanel.setBackground(Color.white); - mainPanel.setLayout(new GridBagLayout()); - frame.setIconImage(SparkManager.getMainWindow().getIconImage()); - frame.getContentPane().add(mainPanel); - - // mainPanel.add(titleLabel, new GridBagConstraints(0, 0, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); - - mainPanel.add(scrollPane, new GridBagConstraints(0, 1, 3, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); - mainPanel.add(button, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); - mainPanel.add(cancelButton, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); - - frame.pack(); - frame.setSize(400, 400); - - - GraphicUtils.centerWindowOnComponent(frame, SparkManager.getMainWindow()); - frame.setVisible(true); - pane.setCaretPosition(0); - - button.addActionListener( actionEvent -> { - frame.dispose(); - - // Save it. - String text1 = pane.getText(); - privateNotes.setNotes( text1 ); - PrivateNotes.savePrivateNotes(privateNotes); - } ); - - cancelButton.addActionListener( actionEvent -> frame.dispose() ); - } - - public void shutdown() { - } - - public boolean canShutDown() { - return true; - } - - public void uninstall() { - } - - public static List getTaskList() { - return taskList; - } - -// private class DragWindowAdapter extends MouseAdapter -// implements MouseMotionListener { -// private JFrame m_msgWnd; -// private int m_mousePrevX, -// m_mousePrevY; -// private int m_frameX, -// m_frameY; -// -// public DragWindowAdapter(JFrame mw) { -// m_msgWnd = mw; -// } -// -// public void mousePressed(MouseEvent e) { -// super.mousePressed(e); -// m_mousePrevX = e.getX(); -// m_mousePrevY = e.getY(); -// m_frameX = 0; -// m_frameY = 0; -// } -// -// public void mouseDragged(MouseEvent e) { -// int X = e.getX(); -// int Y = e.getY(); -// int MsgX = m_msgWnd.getX(); -// int MsgY = m_msgWnd.getY(); -// -// int moveX = X - m_mousePrevX; // Negative if move left -// int moveY = Y - m_mousePrevY; // Negative if move down -// if (moveX == 0 && moveY == 0) return; -// m_mousePrevX = X - moveX; -// m_mousePrevY = Y - moveY; -// -// //System.out.println("mouseDragged x,y = (" + X + "," + Y + -// // ") diff (" + moveX + "," + moveY + -// // ") MsgX/MsgY = " + MsgX + "," + MsgY); -// -// // mouseDragged caused by setLocation() on frame. -// if (m_frameX == MsgX && m_frameY == MsgY) { -// m_frameX = 0; -// m_frameY = 0; -// return; -// } -// -// // '-' would cause wrong direction for movement. -// int newFrameX = MsgX + moveX; -// // '-' would cause wrong -// int newFrameY = MsgY + moveY; -// -// m_frameX = newFrameX; -// m_frameY = newFrameY; -// m_msgWnd.setLocation(newFrameX, newFrameY); -// } -// -// public void mouseMoved(MouseEvent e) { -// } -// } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/TaskNotification.java b/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/TaskNotification.java deleted file mode 100644 index b263b7cf2..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/TaskNotification.java +++ /dev/null @@ -1,139 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.scratchpad; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.VerticalFlowLayout; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; - -import javax.swing.BorderFactory; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Font; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Iterator; -import java.util.TimerTask; - -/** - * - */ -public class TaskNotification { - private SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yy"); - - - public TaskNotification() { - TimerTask task = new TimerTask() { - public void run() { - notifyUser(); - } - }; - - long twoHours = (60 * 1000) * 120; - TaskEngine.getInstance().scheduleAtFixedRate(task, (10 * 1000), twoHours); - } - - private void notifyUser() { - - TimerTask newTask = new TimerTask() { - - @Override - public void run() { - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); - mainPanel.setBackground(Color.white); - - long now = System.currentTimeMillis(); - Tasks tasks = Tasks.getTaskList(SparkManager.getConnection()); - Iterator taskIter = tasks.getTasks().iterator(); - - - final JPanel titlePanel = new JPanel(new BorderLayout()) { - private static final long serialVersionUID = -8871487137643685431L; - - public void paintComponent(Graphics g) { - Color startColor = Color.white; - Color endColor = new Color(198, 211, 247); - - Graphics2D g2 = (Graphics2D)g; - - int w = getWidth(); - int h = getHeight(); - - GradientPaint gradient = new GradientPaint(0, 0, startColor, w, h, endColor, true); - g2.setPaint(gradient); - g2.fillRect(0, 0, w, h); - } - - }; - final JLabel taskLabel = new JLabel("Due "); - taskLabel.setFont(taskLabel.getFont().deriveFont(Font.BOLD)); - titlePanel.add(taskLabel, BorderLayout.EAST); - mainPanel.add(titlePanel); - - boolean hasItems = false; - while (taskIter.hasNext()) { - Task task = taskIter.next(); - if (task.isCompleted()) { - continue; - } - - long dueDate = task.getDueDate(); - if (dueDate != -1) { - if (now > dueDate) { - final JPanel item = new JPanel(new BorderLayout()); - item.setOpaque(false); - JLabel label = new JLabel(task.getTitle()); - item.add(label, BorderLayout.CENTER); - - JLabel dueItem = new JLabel(formatter.format(new Date(task.getDueDate()))); - item.add(dueItem, BorderLayout.EAST); - mainPanel.add(item); - hasItems = true; - } - } - } - - if (hasItems) { - SparkToaster toaster = new SparkToaster(); - toaster.setDisplayTime(30000); - toaster.setToasterHeight(175); - toaster.setToasterWidth(300); - - toaster.setBorder(BorderFactory.createBevelBorder(0)); - JScrollPane pane = new JScrollPane(mainPanel); - pane.getViewport().setBackground(Color.white); - toaster.showToaster(Res.getString("title.task.notification"), pane); - } - } - }; - TaskEngine.getInstance().schedule(newTask, 500); - - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/TaskUI.java b/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/TaskUI.java deleted file mode 100644 index f8f2e4ff6..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/TaskUI.java +++ /dev/null @@ -1,166 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.scratchpad; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.font.TextAttribute; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Map; - -import javax.swing.JCheckBox; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import org.jdesktop.swingx.calendar.DateUtils; -import org.jivesoftware.resource.SparkRes; - -/** - * - */ -public class TaskUI extends JPanel implements ActionListener { - - private static final long serialVersionUID = -8443764502684168188L; - private Task task; - private JCheckBox box; - - public TaskUI(final Task task) { - setLayout(new BorderLayout()); - setOpaque(false); - - this.task = task; - - box = new JCheckBox(); - box.setOpaque(false); - JLabel dueLabel = new JLabel(); - dueLabel.setOpaque(false); - - JPanel p_east = new JPanel(new BorderLayout()); - p_east.setBackground(Color.white); - - JLabel btn_del = new JLabel(SparkRes.getImageIcon(SparkRes.TASK_DELETE_IMAGE)); - - p_east.add(btn_del, BorderLayout.EAST); - p_east.add(new JLabel(" "), BorderLayout.CENTER); - p_east.add(dueLabel, BorderLayout.WEST); - - add(box, BorderLayout.WEST); - - //add(dueLabel, BorderLayout.EAST); - add(p_east, BorderLayout.EAST); - - long dueDate = task.getDueDate(); - if (dueDate != -1) { - Date d = new Date(dueDate); - String dateShortFormat = ( (SimpleDateFormat) SimpleDateFormat.getDateInstance( SimpleDateFormat.SHORT ) ).toPattern(); - SimpleDateFormat formatter = new SimpleDateFormat( dateShortFormat ); - String theDate = formatter.format(d); - dueLabel.setText(theDate); - } - - int diff = DateUtils.getDaysDiff(dueDate, new Date().getTime()); - - if (diff > 0){ - dueLabel.setForeground(Color.red); - } - - box.setText(task.getTitle()); - - updateTitleFont(); - - box.addActionListener(this); - - btn_del.addMouseListener(new MouseListener() { - public void mouseClicked(MouseEvent arg0) { - Tasks.deleteTask(task); - } - - public void mouseEntered(MouseEvent e) { - - } - public void mouseExited(MouseEvent e) { - - } - public void mousePressed(MouseEvent e) { - - } - public void mouseReleased(MouseEvent e) { - - } - }); - } - - public boolean isSelected() { - return box.isSelected(); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public void updateTitleFont() { - if (task.isCompleted()) { - Font font = box.getFont(); - - - Map attribs = font.getAttributes(); - - attribs.put(TextAttribute.STRIKETHROUGH, true); - - box.setFont(new Font(attribs)); - box.setSelected(true); - } - else { - Font font = box.getFont(); - - Map Attribs = font.getAttributes(); - - Attribs.put(TextAttribute.STRIKETHROUGH, false); - - box.setFont(new Font(Attribs)); - box.setSelected(false); - } - } - - public void actionPerformed(ActionEvent e) { - if (isSelected()) { - task.setCompleted(true); - } - else { - task.setCompleted(false); - } - - updateTitleFont(); - - if (ScratchPadPlugin.SHOW_ALL_TASKS) { - setVisible(true); - } - else if (task.isCompleted()) { - setVisible(false); - } - } - - public Task getTask() { - return task; - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/Tasks.java b/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/Tasks.java deleted file mode 100644 index 49d66eac3..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/scratchpad/Tasks.java +++ /dev/null @@ -1,245 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.scratchpad; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.iqprivate.PrivateDataManager; -import org.jivesoftware.smackx.iqprivate.packet.PrivateData; -import org.jivesoftware.smackx.iqprivate.provider.PrivateDataProvider; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.log.Log; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -/** - * @author Derek DeMoro - */ -public class Tasks implements PrivateData { - - private List tasks = new ArrayList<>(); - - /** - * Required Empty Constructor to use Tasks. - */ - public Tasks() { - } - - - public List getTasks() { - return tasks; - } - - public void setTasks(List tasks) { - this.tasks = tasks; - } - - public void addTask(Task task) { - tasks.add(task); - } - - /** - * Returns the root element name. - * - * @return the element name. - */ - public String getElementName() { - return "scratchpad"; - } - - /** - * Returns the root element XML namespace. - * - * @return the namespace. - */ - public String getNamespace() { - return "scratchpad:tasks"; - } - - /** - * Returns the XML reppresentation of the PrivateData. - * - * @return the private data as XML. - */ - public String toXML() { - StringBuilder buf = new StringBuilder(); - buf.append(""); - buf.append(""); - - for (Task task : getTasks()) { - buf.append(""); - buf.append("").append(task.getTitle()).append(""); - buf.append("").append(task.getDueDate()).append(""); - buf.append("").append(task.getCreatedDate()).append(""); - if (task.isCompleted()) { - buf.append("true"); - } - buf.append(""); - } - - buf.append(""); - - buf.append(""); - return buf.toString(); - } - - /** - * The IQ Provider for Tasks - * - * @author Derek DeMoro - */ - public static class Provider implements PrivateDataProvider { - - Tasks tasks = new Tasks(); - - /** - * Empty Constructor for PrivateDataProvider. - */ - public Provider() { - super(); - } - - public PrivateData parsePrivateData(XmlPullParser parser) throws XmlPullParserException, IOException { - boolean done = false; - while (!done) { - int eventType = parser.next(); - if (eventType == XmlPullParser.START_TAG && "tasks".equals(parser.getName())) { - String showAll = parser.getAttributeValue("", "showAll"); - ScratchPadPlugin.SHOW_ALL_TASKS = Boolean.parseBoolean(showAll); - } - - if (eventType == XmlPullParser.START_TAG && "task".equals(parser.getName())) { - tasks.addTask(getTask(parser)); - } - else if (eventType == XmlPullParser.END_TAG) { - if ("scratchpad".equals(parser.getName())) { - done = true; - } - } - } - - - return tasks; - } - } - - public static Task getTask(XmlPullParser parser) throws XmlPullParserException, IOException { - final Task task = new Task(); - - boolean done = false; - while (!done) { - int eventType = parser.next(); - if (eventType == XmlPullParser.START_TAG && "title".equals(parser.getName())) { - task.setTitle(parser.nextText()); - } - - if (eventType == XmlPullParser.START_TAG && "dueDate".equals(parser.getName())) { - String dueDate = parser.nextText(); - task.setDueDate(Long.parseLong(dueDate)); - } - - if (eventType == XmlPullParser.START_TAG && "creationDate".equals(parser.getName())) { - String creationDate = parser.nextText(); - task.setCreatedDate(Long.parseLong(creationDate)); - } - - if (eventType == XmlPullParser.START_TAG && "completed".equals(parser.getName())) { - String completed = parser.nextText(); - if (ModelUtil.hasLength(completed)) { - task.setCompleted(Boolean.parseBoolean(completed)); - } - } - - else if (eventType == XmlPullParser.END_TAG) { - if ("task".equals(parser.getName())) { - done = true; - } - } - } - - - return task; - } - - - public static void saveTasks(Tasks tasks, XMPPConnection con) { - PrivateDataManager manager = PrivateDataManager.getInstanceFor( con ); - - PrivateDataManager.addPrivateDataProvider("scratchpad", "scratchpad:tasks", new Tasks.Provider()); - try { - manager.setPrivateData(tasks); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - } - - public static Tasks getTaskList(XMPPConnection con) { - PrivateDataManager manager = PrivateDataManager.getInstanceFor( con ); - - PrivateDataManager.addPrivateDataProvider("scratchpad", "scratchpad:tasks", new Tasks.Provider()); - - - Tasks tasks = null; - - try { - tasks = (Tasks)manager.getPrivateData("scratchpad", "scratchpad:tasks"); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - - return tasks; - } - - /** - * Delete task - * - * @param task : task to delete - */ - public static void deleteTask(Task task) { - - List taskList = ScratchPadPlugin.getTaskList(); - - // find and delete task in list - for ( int i = 0; i < taskList.size(); i++ ) { - Task t = taskList.get(i).getTask(); - if ( t == task ) { - taskList.remove(i); - break; - } - } - - // save Tasks - Tasks tasks = new Tasks(); - for (TaskUI ui : taskList) { - Task nTask = ui.getTask(); - tasks.addTask(nTask); - } - - // update GUI - ScratchPadPlugin.updateTaskUI(tasks); - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/systray/SysTrayPlugin.java b/src/java/org/jivesoftware/sparkimpl/plugin/systray/SysTrayPlugin.java deleted file mode 100644 index c75d6b2ed..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/systray/SysTrayPlugin.java +++ /dev/null @@ -1,517 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.systray; - -import java.awt.MouseInfo; -import java.awt.SystemTray; -import java.awt.TrayIcon; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.ImageIcon; -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; - -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.chat.Chat; -import org.jivesoftware.smack.ConnectionListener; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smackx.chatstates.ChatState; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.NativeHandler; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.status.CustomStatusItem; -import org.jivesoftware.spark.ui.status.StatusBar; -import org.jivesoftware.spark.ui.status.StatusItem; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jivesoftware.smack.chat.ChatManagerListener; -import org.jivesoftware.smackx.chatstates.ChatStateListener; - -public class SysTrayPlugin implements Plugin, NativeHandler, ChatManagerListener, ChatStateListener { - private JPopupMenu popupMenu = new JPopupMenu(); - - private JMenu statusMenu; - - private LocalPreferences pref = SettingsManager.getLocalPreferences(); - private ImageIcon availableIcon; - private ImageIcon dndIcon; - private ImageIcon awayIcon; - private ImageIcon offlineIcon; - private ImageIcon connectingIcon; - private ImageIcon newMessageIcon; - private ImageIcon typingIcon; - private TrayIcon trayIcon; - private boolean newMessage = false; - ChatMessageHandlerImpl chatMessageHandler = new ChatMessageHandlerImpl(); - - @Override - public boolean canShutDown() { - return true; - } - - @Override - public void initialize() { - - if (SystemTray.isSupported()) { - - JMenuItem openMenu = new JMenuItem( Res.getString( "menuitem.open" ) ); - JMenuItem minimizeMenu = new JMenuItem( Res.getString( "menuitem.hide" ) ); - JMenuItem exitMenu = new JMenuItem( Res.getString( "menuitem.exit" ) ); - statusMenu = new JMenu(Res.getString("menuitem.status")); - JMenuItem logoutMenu = new JMenuItem( - Res.getString( "menuitem.logout.no.status" ) ); - - SystemTray tray = SystemTray.getSystemTray(); - SparkManager.getNativeManager().addNativeHandler(this); - ChatManager.getInstance().addChatMessageHandler(chatMessageHandler); - //XEP-0085 suport (replaces the obsolete XEP-0022) - org.jivesoftware.smack.chat.ChatManager.getInstanceFor( SparkManager.getConnection() ).addChatListener(this); - - if (Spark.isLinux()) { - newMessageIcon = SparkRes - .getImageIcon(SparkRes.MESSAGE_NEW_TRAY_LINUX); - typingIcon = SparkRes.getImageIcon(SparkRes.TYPING_TRAY_LINUX); - } else { - newMessageIcon = SparkRes - .getImageIcon(SparkRes.MESSAGE_NEW_TRAY); - typingIcon = SparkRes.getImageIcon(SparkRes.TYPING_TRAY); - } - - availableIcon = Default.getImageIcon(Default.TRAY_IMAGE); - if (Spark.isLinux()) { - if (availableIcon == null) { - availableIcon = SparkRes - .getImageIcon(SparkRes.TRAY_IMAGE_LINUX); - Log.error(availableIcon.toString()); - } - awayIcon = SparkRes.getImageIcon(SparkRes.TRAY_AWAY_LINUX); - dndIcon = SparkRes.getImageIcon(SparkRes.TRAY_DND_LINUX); - offlineIcon = SparkRes - .getImageIcon(SparkRes.TRAY_OFFLINE_LINUX); - connectingIcon = SparkRes - .getImageIcon(SparkRes.TRAY_CONNECTING_LINUX); - } else { - if (availableIcon == null) { - availableIcon = SparkRes.getImageIcon(SparkRes.TRAY_IMAGE); - } - awayIcon = SparkRes.getImageIcon(SparkRes.TRAY_AWAY); - dndIcon = SparkRes.getImageIcon(SparkRes.TRAY_DND); - offlineIcon = SparkRes.getImageIcon(SparkRes.TRAY_OFFLINE); - connectingIcon = SparkRes - .getImageIcon(SparkRes.TRAY_CONNECTING); - } - - popupMenu.add( openMenu ); - openMenu.addActionListener( new AbstractAction() { - - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent event) { - SparkManager.getMainWindow().setVisible(true); - SparkManager.getMainWindow().toFront(); - } - - }); - popupMenu.add( minimizeMenu ); - minimizeMenu.addActionListener( new AbstractAction() { - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent event) { - SparkManager.getMainWindow().setVisible(false); - } - }); - popupMenu.addSeparator(); - addStatusMessages(); - popupMenu.add(statusMenu); - statusMenu.addActionListener(new AbstractAction() { - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent event) { - - } - }); - - if (Spark.isWindows()) { - if (!Default.getBoolean("DISABLE_EXIT")) - popupMenu.add( logoutMenu ); - - logoutMenu.addActionListener( new AbstractAction() { - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent e) { - SparkManager.getMainWindow().logout(false); - } - }); - } - // Exit Menu - exitMenu.addActionListener( new AbstractAction() { - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent e) { - SparkManager.getMainWindow().shutdown(); - } - }); - if (!Default.getBoolean("DISABLE_EXIT")) - popupMenu.add( exitMenu ); - - /** - * If connection closed set offline tray image - */ - SparkManager.getConnection().addConnectionListener( - new ConnectionListener() { - - @Override - public void connected( XMPPConnection xmppConnection ) { - trayIcon.setImage( availableIcon.getImage() ); - } - - @Override - public void authenticated( XMPPConnection xmppConnection, boolean b ) { - trayIcon.setImage( availableIcon.getImage() ); - } - - @Override - public void connectionClosed() { - trayIcon.setImage(offlineIcon.getImage()); - } - - @Override - public void connectionClosedOnError(Exception arg0) { - trayIcon.setImage(offlineIcon.getImage()); - } - - @Override - public void reconnectingIn(int arg0) { - trayIcon.setImage(connectingIcon.getImage()); - } - - @Override - public void reconnectionSuccessful() { - trayIcon.setImage(availableIcon.getImage()); - } - - @Override - public void reconnectionFailed(Exception arg0) { - trayIcon.setImage(offlineIcon.getImage()); - } - }); - - SparkManager.getSessionManager().addPresenceListener( - presence -> { - if (presence.getMode() == Presence.Mode.available) { - trayIcon.setImage(availableIcon.getImage()); - } else if (presence.getMode() == Presence.Mode.away - || presence.getMode() == Presence.Mode.xa) { - trayIcon.setImage(awayIcon.getImage()); - } else if (presence.getMode() == Presence.Mode.dnd) { - trayIcon.setImage(dndIcon.getImage()); - } else { - trayIcon.setImage(availableIcon.getImage()); - } - } ); - - try { - - - - trayIcon = new TrayIcon(availableIcon.getImage(), - Default.getString(Default.APPLICATION_NAME), null); - trayIcon.setImageAutoSize(true); - - trayIcon.addMouseListener(new MouseListener() { - - @Override - public void mouseClicked(MouseEvent event) { - // if we are using double click on tray icon - if ( (!pref.isUsingSingleTrayClick() - && event.getButton() == MouseEvent.BUTTON1 - && event.getClickCount() % 2 == 0) - || - // if we using single click on tray icon - (pref.isUsingSingleTrayClick() - && event.getButton() == MouseEvent.BUTTON1 - && event.getClickCount() == 1)) { - - // bring the mainwindow to front - if ((SparkManager.getMainWindow().isVisible()) - && (SparkManager.getMainWindow().getState() == java.awt.Frame.NORMAL)) { - SparkManager.getMainWindow().setVisible(false); - } else { - SparkManager.getMainWindow().setVisible(true); - SparkManager.getMainWindow().setState(java.awt.Frame.NORMAL); - SparkManager.getMainWindow().toFront(); - } - - } else if (event.getButton() == MouseEvent.BUTTON1) { - SparkManager.getMainWindow().toFront(); - // SparkManager.getMainWindow().requestFocus(); - } else if (event.getButton() == MouseEvent.BUTTON3) { - - if (popupMenu.isVisible()) { - popupMenu.setVisible(false); - } else { - - double x = MouseInfo.getPointerInfo() - .getLocation().getX(); - double y = MouseInfo.getPointerInfo() - .getLocation().getY(); - - if (Spark.isMac()) { - popupMenu.setLocation((int) x, (int) y); - } else { - popupMenu.setLocation(event.getX(), - event.getY()); - } - - popupMenu.setInvoker(popupMenu); - popupMenu.setVisible(true); - } - } - } - - @Override - public void mouseEntered(MouseEvent event) { - - } - - @Override - public void mouseExited(MouseEvent event) { - - } - - @Override - public void mousePressed(MouseEvent event) { - - // on Mac i would want the window to show when i left-click the Icon - if (Spark.isMac() && event.getButton()!=MouseEvent.BUTTON3) { - SparkManager.getMainWindow().setVisible(false); - SparkManager.getMainWindow().setVisible(true); - SparkManager.getMainWindow().requestFocusInWindow(); - SparkManager.getMainWindow().bringFrameIntoFocus(); - SparkManager.getMainWindow().toFront(); - SparkManager.getMainWindow().requestFocus(); - } - } - - @Override - public void mouseReleased(MouseEvent event) { - - } - - }); - - tray.add(trayIcon); - } catch (Exception e) { - // Not Supported - } - } else { - Log.error("Tray don't supports on this platform."); - } - } - - public void addStatusMessages() { - StatusBar statusBar = SparkManager.getWorkspace().getStatusBar(); - for (Object o : statusBar.getStatusList()) { - final StatusItem statusItem = (StatusItem) o; - - final AbstractAction action = new AbstractAction() { - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent e) { - - StatusBar statusBar = SparkManager.getWorkspace() - .getStatusBar(); - - SparkManager.getSessionManager().changePresence( - statusItem.getPresence()); - statusBar.setStatus(statusItem.getText()); - } - }; - action.putValue(Action.NAME, statusItem.getText()); - action.putValue(Action.SMALL_ICON, statusItem.getIcon()); - - boolean hasChildren = false; - for (Object aCustom : SparkManager.getWorkspace().getStatusBar() - .getCustomStatusList()) { - final CustomStatusItem cItem = (CustomStatusItem) aCustom; - String type = cItem.getType(); - if (type.equals(statusItem.getText())) { - hasChildren = true; - } - } - - if (!hasChildren) { - JMenuItem status = new JMenuItem(action); - statusMenu.add(status); - } else { - final JMenu status = new JMenu(action); - statusMenu.add(status); - - status.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent mouseEvent) { - action.actionPerformed(null); - popupMenu.setVisible(false); - } - }); - - for (Object aCustom : SparkManager.getWorkspace() - .getStatusBar().getCustomStatusList()) { - final CustomStatusItem customItem = (CustomStatusItem) aCustom; - String type = customItem.getType(); - if (type.equals(statusItem.getText())) { - AbstractAction customAction = new AbstractAction() { - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent e) { - StatusBar statusBar = SparkManager - .getWorkspace().getStatusBar(); - - Presence oldPresence = statusItem.getPresence(); - Presence presence = StatusBar - .copyPresence(oldPresence); - presence.setStatus(customItem.getStatus()); - presence.setPriority(customItem.getPriority()); - SparkManager.getSessionManager() - .changePresence(presence); - - statusBar.setStatus(statusItem.getName() - + " - " + customItem.getStatus()); - } - }; - customAction.putValue(Action.NAME, - customItem.getStatus()); - customAction.putValue(Action.SMALL_ICON, - statusItem.getIcon()); - JMenuItem menuItem = new JMenuItem(customAction); - status.add(menuItem); - } - } - - } - } - } - - @Override - public void shutdown() { - if (SystemTray.isSupported()) { - SystemTray tray = SystemTray.getSystemTray(); - tray.remove(trayIcon); - } - ChatManager.getInstance().removeChatMessageHandler(chatMessageHandler); - } - - @Override - public void uninstall() { - ChatManager.getInstance().removeChatMessageHandler(chatMessageHandler); - } - - // Info on new Messages - @Override - public void flashWindow(Window window) { - if (pref.isSystemTrayNotificationEnabled()) { - trayIcon.setImage(newMessageIcon.getImage()); - if (window instanceof JFrame) { - ((JFrame) window).setTitle(getCounteredTitle( - ((JFrame) window).getTitle(), chatMessageHandler.getUnreadMessages())); - } - newMessage = true; - } - } - - private String getCounteredTitle(String title, int counter) { - String stringCounter = String.format("[%s] ", counter); - String MESSAGE_COUNTER_REG_EXP = "\\[\\d+\\] "; - return counter > 0 ? stringCounter + title.replaceFirst( MESSAGE_COUNTER_REG_EXP, "") : title.replaceFirst( MESSAGE_COUNTER_REG_EXP, ""); - } - - @Override - public void flashWindowStopWhenFocused(Window window) { - trayIcon.setImage(availableIcon.getImage()); - newMessage = false; - chatMessageHandler.clearUnreadMessages(); - } - - @Override - public boolean handleNotification() { - return true; - } - - @Override - public void stopFlashing(Window window) { - trayIcon.setImage(availableIcon.getImage()); - newMessage = false; - chatMessageHandler.clearUnreadMessages(); - } - - // For Typing - @Override - public void processMessage(Chat arg0, Message arg1) { - // Do nothing - stateChanged is in charge - - } - - @Override - public void stateChanged(Chat chat, ChatState state) { - if (ChatState.composing.equals(state)) { - changeSysTrayIcon(); - } else { - if (!newMessage) - trayIcon.setImage(availableIcon.getImage()); - else { - trayIcon.setImage(newMessageIcon.getImage()); - } - } - } - - @Override - public void chatCreated(Chat chat, boolean isLocal) { - chat.addMessageListener(this); - } - - private void changeSysTrayIcon() { - if (pref.isTypingNotificationShown()) { - trayIcon.setImage(typingIcon.getImage()); - } - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscript.java b/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscript.java deleted file mode 100644 index 644ac3457..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscript.java +++ /dev/null @@ -1,128 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.transcripts; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * A single chat transcript mapped to one JID. - * - * @author Derek DeMoro - */ -public class ChatTranscript { - - private List messages = new ArrayList<>(); - - /** - * Add a HistoryMessage to users chat transcript. - * - * @param entry the HistoryMessage to add. - */ - public void addHistoryMessage(HistoryMessage entry) { - messages.add(entry); - } - - /** - * Returns all messages. - * - * @return all messages. - */ - public List getMessages() { - return messages; - } - - /** - * Returns a specified number of messages. - * - * @param number the number of messages to return. - * @return the specified number of messages, or all messages if number is greater than the current amount. - */ - public Collection getNumberOfEntries(int number) { - int listSize = messages.size(); - - if (messages.size() <= number) { - return messages; - } - else { - int start = listSize - number; - return messages.subList(start, listSize); - } - } - - /** - * Returns messages that included search keywords. - * - * @param text search keywords.If the search keywords is null, return all message. - * @return the messages that included search keywords. - */ - public List getMessage(String text) { - if(text == null || "".equals(text)) { - return messages; - } else { - List searchResult = new ArrayList<>(); - for(HistoryMessage message : messages) { - // ignore keywords' case - if( message.getBody().toLowerCase().contains( text.toLowerCase() ) ) { - searchResult.add(message); - } - } - return searchResult; - } - } - - /** - * Clears the Message History if its not needed anymore - */ - public void release() { - messages.clear(); - } - - /** - * Set the new List for the chat transcript - * @param newList The list with the history messages - */ - public void setList(List newList){ - this.messages = newList; - } - - /** - * Return the size of the message list - * @return The size of the message list - */ - public int size(){ - return this.messages.size(); - } - - /** - * Return the HistoryMessage by the given index - * @param i the index of the history message - * @return the history message, null if out of bounds - */ - public HistoryMessage getMessage(int i){ - HistoryMessage result = null; - if ((i > -1) && i < messages.size()){ - result = messages.get(i); - } - return result; - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscriptPlugin.java b/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscriptPlugin.java deleted file mode 100644 index f83414b7d..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscriptPlugin.java +++ /dev/null @@ -1,369 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.transcripts; - -import java.awt.BorderLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; -import java.io.File; -import java.text.SimpleDateFormat; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.List; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; - -import org.jivesoftware.MainWindowListener; -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.ConnectionListener; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.ContextMenuListener; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomButton; -import org.jivesoftware.spark.ui.ChatRoomClosingListener; -import org.jivesoftware.spark.ui.ChatRoomListener; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.util.UIComponentRegistry; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -/** - * The ChatTranscriptPlugin is responsible for transcript handling within Spark. - * - * @author Derek DeMoro - */ -public class ChatTranscriptPlugin implements ChatRoomListener { - - private final SimpleDateFormat notificationDateFormatter; - private final SimpleDateFormat messageDateFormatter; - private HashMap lastMessage = new HashMap<>(); - private JDialog Frame; - private HistoryTranscript transcript = null; - /** - * Register the listeners for transcript persistence. - */ - public ChatTranscriptPlugin() { - SparkManager.getChatManager().addChatRoomListener(this); - - String dateFormat = ( (SimpleDateFormat) SimpleDateFormat.getDateInstance( SimpleDateFormat.FULL ) ).toPattern(); - notificationDateFormatter = new SimpleDateFormat( dateFormat ); - String timeFormat = "HH:mm:ss"; - messageDateFormatter = new SimpleDateFormat( timeFormat ); - - final ContactList contactList = SparkManager.getWorkspace().getContactList(); - - final Action viewHistoryAction = new AbstractAction() { - private static final long serialVersionUID = -6498776252446416099L; - - public void actionPerformed(ActionEvent actionEvent) { - ContactItem item = contactList.getSelectedUsers().iterator().next(); - final String jid = item.getJID(); - transcript = new HistoryTranscript(notificationDateFormatter, messageDateFormatter); - transcript.showHistory(jid); - //showHistory(jid); - } - }; - - viewHistoryAction.putValue(Action.NAME, Res.getString("menuitem.view.contact.history")); - viewHistoryAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.HISTORY_16x16)); - - final Action showStatusMessageAction = new AbstractAction() { - private static final long serialVersionUID = -5000370836304286019L; - - public void actionPerformed(ActionEvent actionEvent) { - ContactItem item = contactList.getSelectedUsers().iterator().next(); - showStatusMessage(item); - } - }; - - showStatusMessageAction.putValue(Action.NAME, Res.getString("menuitem.show.contact.statusmessage")); - - contactList.addContextMenuListener(new ContextMenuListener() { - public void poppingUp(Object object, JPopupMenu popup) { - if (object instanceof ContactItem) { - if (!Default.getBoolean("HISTORY_DISABLED")) { - popup.add(viewHistoryAction); - } - popup.add(showStatusMessageAction); - } - } - - public void poppingDown(JPopupMenu popup) { - - } - - public boolean handleDefaultAction(MouseEvent e) { - return false; - } - }); - - SparkManager.getMainWindow().addMainWindowListener(new MainWindowListener() { - public void shutdown() { - persistConversations(); - } - - public void mainWindowActivated() { - - } - - public void mainWindowDeactivated() { - - } - }); - - - SparkManager.getConnection().addConnectionListener(new ConnectionListener() { - @Override - public void connected( XMPPConnection xmppConnection ) { - } - - @Override - public void authenticated( XMPPConnection xmppConnection, boolean b ) { - } - - @Override - public void connectionClosed() { - } - - @Override - public void connectionClosedOnError(Exception e) { - persistConversations(); - } - - @Override - public void reconnectingIn(int i) { - } - - @Override - public void reconnectionSuccessful() { - } - - @Override - public void reconnectionFailed(Exception exception) { - } - }); - } - - public void persistConversations() { - for (ChatRoom room : SparkManager.getChatManager().getChatContainer().getChatRooms()) { - if (room instanceof ChatRoomImpl) { - ChatRoomImpl roomImpl = (ChatRoomImpl)room; - if (roomImpl.isActive()) { - persistChatRoom(roomImpl); - } - } - } - } - - public boolean canShutDown() { - return true; - } - - public void chatRoomOpened(final ChatRoom room) { - LocalPreferences pref = SettingsManager.getLocalPreferences(); - if (!pref.isChatHistoryEnabled()) { - return; - } - - final String jid = room.getRoomname(); - - File transcriptFile = ChatTranscripts.getTranscriptFile(jid); - if (!transcriptFile.exists()) { - return; - } - - if (room instanceof ChatRoomImpl) { - new ChatRoomDecorator(room); - } - } - - public void chatRoomLeft(ChatRoom room) { - - } - - public void chatRoomClosed(final ChatRoom room) { - // Persist only agent to agent chat rooms. - if (room.getChatType() == Message.Type.chat) { - persistChatRoom(room); - } - } - - public void persistChatRoom(final ChatRoom room) { - LocalPreferences pref = SettingsManager.getLocalPreferences(); - if (!pref.isChatHistoryEnabled()) { - return; - } - - final String jid = room.getRoomname(); - - final List transcripts = room.getTranscripts(); - ChatTranscript transcript = new ChatTranscript(); - int count = 0; - int i = 0; - if (lastMessage.get(jid) != null) - { - count = transcripts.indexOf(lastMessage.get(jid)) + 1; - } - for (Message message : transcripts) { - if (i < count) - { - i++; - continue; - } - lastMessage.put(jid,message); - HistoryMessage history = new HistoryMessage(); - history.setTo(message.getTo()); - history.setFrom(message.getFrom()); - history.setBody(message.getBody()); - final JivePropertiesExtension extension = ((JivePropertiesExtension) message.getExtension( JivePropertiesExtension.NAMESPACE )); - Date date = null; - if ( extension != null ) { - date = (Date) extension.getProperty( "date" ); - } - history.setDate( date == null ? new Date() : date ); - transcript.addHistoryMessage(history); - } - - ChatTranscripts.appendToTranscript(jid, transcript); - - } - - public void chatRoomActivated(ChatRoom room) { - - } - - public void userHasJoined(ChatRoom room, String userid) { - - } - - public void userHasLeft(ChatRoom room, String userid) { - - } - - public void uninstall() { - // Do nothing. - } - - private void showStatusMessage(ContactItem item) - { - Frame = new JDialog(); - Frame.setTitle(item.getDisplayName() + " - Status"); - JPanel pane = new JPanel(); - JTextArea textArea = new JTextArea(5, 30); - JButton btn_close = new JButton(Res.getString("button.close")); - - btn_close.addActionListener( e -> Frame.setVisible(false) ); - - textArea.setLineWrap(true); - textArea.setWrapStyleWord(true); - - pane.add(new JScrollPane(textArea)); - Frame.setLayout(new BorderLayout()); - Frame.add(pane, BorderLayout.CENTER); - Frame.add(btn_close, BorderLayout.SOUTH); - - textArea.setEditable(false); - textArea.setText(item.getStatus()); - - Frame.setLocationRelativeTo(SparkManager.getMainWindow()); - Frame.setBounds(Frame.getX() - 175, Frame.getY() - 75, 350, 150); - Frame.setSize(350, 150); - Frame.setResizable(false); - Frame.setVisible(true); - } - - - /** - * Sort HistoryMessages by date. - */ - final Comparator dateComparator = ( messageOne, messageTwo ) -> { - - long time1 = messageOne.getDate().getTime(); - long time2 = messageTwo.getDate().getTime(); - - if (time1 < time2) { - return 1; - } - else if (time1 > time2) { - return -1; - } - return 0; - - }; - - private class ChatRoomDecorator implements ActionListener, ChatRoomClosingListener { - - private ChatRoom chatRoom; - private ChatRoomButton chatHistoryButton; - private final LocalPreferences localPreferences; - - public ChatRoomDecorator(ChatRoom chatRoom) { - this.chatRoom = chatRoom; - chatRoom.addClosingListener(this); - - // Add History Button - localPreferences = SettingsManager.getLocalPreferences(); - if (!localPreferences.isChatHistoryEnabled()) { - return; - } - chatHistoryButton = UIComponentRegistry.getButtonFactory().createChatTranscriptButton(); - if (!Default.getBoolean("HISTORY_DISABLED")) { - chatRoom.addChatRoomButton(chatHistoryButton); - } - chatHistoryButton.setToolTipText(Res.getString("tooltip.view.history")); - chatHistoryButton.addActionListener(this); - } - - - public void closing() { - if (localPreferences.isChatHistoryEnabled()) { - chatHistoryButton.removeActionListener(this); - } - chatRoom.removeClosingListener(this); - chatRoom = null; - chatHistoryButton = null; - } - - public void actionPerformed(ActionEvent e) { - ChatRoomImpl roomImpl = (ChatRoomImpl)chatRoom; - transcript = new HistoryTranscript(notificationDateFormatter, messageDateFormatter); - transcript.showHistory(roomImpl.getParticipantJID()); - } - } - - -} - diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscripts.java b/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscripts.java deleted file mode 100644 index 6943ba138..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscripts.java +++ /dev/null @@ -1,280 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.transcripts; - -import org.jivesoftware.resource.Default; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.UserManager; -import org.jivesoftware.spark.util.StringUtils; -import org.jivesoftware.spark.util.log.Log; -import org.xmlpull.mxp1.MXParser; -import org.xmlpull.v1.XmlPullParser; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.RandomAccessFile; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Collection; -import java.util.Date; - - -/** - * A Utility class that manages the Chat Transcripts within Spark. - * - * @author Derek DeMoro - */ -public final class ChatTranscripts { - - /** - * Default Date Formatter * - */ - private static DateFormat FORMATTER; - - static { - FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S z"); - } - - private ChatTranscripts() { - - } - - /** - * Appends the given ChatTranscript to the transcript file associated with a JID. - * - * @param jid the jid of the user. - * @param transcript the ChatTranscript. - */ - public static void appendToTranscript(String jid, ChatTranscript transcript) { - final File transcriptFile = getTranscriptFile(jid); - - if (!Default.getBoolean("HISTORY_DISABLED")) { - // Write Full Transcript, appending the messages. - writeToFile(transcriptFile, transcript.getMessages(), true); - - // Write to current history File - final File currentHistoryFile = getCurrentHistoryFile(jid); - ChatTranscript tempTranscript = getCurrentChatTranscript(jid); - for (HistoryMessage message : transcript.getMessages()) { - tempTranscript.addHistoryMessage(message); - } - writeToFile(currentHistoryFile, tempTranscript.getNumberOfEntries(20), false); - } - } - - private static void writeToFile(File transcriptFile, Collection messages, boolean append) { - final StringBuilder builder = new StringBuilder(); - - final String one = " "; - final String two = " "; - final String three = " "; - - // Handle new transcript file. - if (!transcriptFile.exists() || !append) { - builder.append("\n"); - builder.append(one+"\n"); - } - - for (HistoryMessage m : messages) { - builder.append(two+"\n"); - builder.append(three+"").append(m.getTo()).append("\n"); - builder.append(three+"").append(m.getFrom()).append("\n"); - builder.append(three+"").append(StringUtils.escapeForXML(m.getBody())).append("\n"); - - String dateString = FORMATTER.format(m.getDate()); - builder.append(three+"").append(dateString).append("\n"); - builder.append(two+"\n"); - } - - if (!transcriptFile.exists() || !append) { - builder.append(one+"\n"); - builder.append(""); - } - - - if (!transcriptFile.exists() || !append) { - // Write out new File - try { - transcriptFile.getParentFile().mkdirs(); - BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(transcriptFile), "UTF-8")); - out.write(builder.toString()); - out.close(); - } - catch (IOException e) { - Log.error(e); - } - return; - } - - // Append to File - try { - final RandomAccessFile raf = new RandomAccessFile(transcriptFile, "rw"); - - // We want to append near the end of the document as the last - // child in the transcript. - final String endTag = " \n"; - - String line = raf.readLine(); - if(line.contains("")) - { - // replace the old one with the new one - line = line.replace("",endTag); - raf.write(line.getBytes("UTF-8")); - } - - builder.append(endTag); - - raf.seek(transcriptFile.length() - endTag.length()); - - // Append to the end - raf.write(builder.toString().getBytes("UTF-8")); - raf.close(); - } - catch (IOException e) { - Log.error(e); - } - } - - /** - * Retrieve the current chat history. - * - * @param jid the jid of the user whos history you wish to retrieve. - * @return the ChatTranscript (last 20 messages max). - */ - public static ChatTranscript getCurrentChatTranscript(String jid) { - return getTranscript(getCurrentHistoryFile(jid)); - } - - /** - * Retrieve the full chat history. - * - * @param jid the jid of the the user whos history you wish to retrieve. - * @return the ChatTranscript. - */ - public static ChatTranscript getChatTranscript(String jid) { - return getTranscript(getTranscriptFile(jid)); - } - - /** - * Reads in the transcript file using the Xml Pull Parser. - * - * @param transcriptFile the transcript file to read. - * @return the ChatTranscript. - */ - public static ChatTranscript getTranscript(File transcriptFile) { - final ChatTranscript transcript = new ChatTranscript(); - if (!transcriptFile.exists()) { - return transcript; - } - - try { - final MXParser parser = new MXParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(transcriptFile), "UTF-8")); - parser.setInput(in); - boolean done = false; - while (!done) { - int eventType = parser.next(); - if (eventType == XmlPullParser.START_TAG && "message".equals(parser.getName())) { - transcript.addHistoryMessage(getHistoryMessage(parser)); - } - else if (eventType == XmlPullParser.END_TAG && "transcript".equals(parser.getName())) { - done = true; - } - } - } - catch (Exception e) { - e.printStackTrace(); - } - - - return transcript; - } - - /** - * Returns the settings file. - * - * @param jid the - * @return the settings file. - */ - public static File getTranscriptFile(String jid) { - // Unescape Node - jid = UserManager.unescapeJID(jid); - - return new File(SparkManager.getUserDirectory(), "transcripts/" + jid + ".xml"); - } - - /** - * Returns the current transcript (20 messages) for a particular jid. - * - * @param jid the jid of the user. - * @return the current transcript file. - */ - public static File getCurrentHistoryFile(String jid) { - // Unescape Node - jid = UserManager.unescapeJID(jid); - - return new File(SparkManager.getUserDirectory(), "transcripts/" + jid + "_current.xml"); - } - - private static HistoryMessage getHistoryMessage(XmlPullParser parser) throws Exception { - HistoryMessage message = new HistoryMessage(); - - // Check for nickname - boolean done = false; - while (!done) { - int eventType = parser.next(); - if (eventType == XmlPullParser.START_TAG && "to".equals(parser.getName())) { - message.setTo(parser.nextText()); - } - else if (eventType == XmlPullParser.START_TAG && "from".equals(parser.getName())) { - message.setFrom(parser.nextText()); - } - else if (eventType == XmlPullParser.START_TAG && "body".equals(parser.getName())) { - message.setBody(StringUtils.unescapeFromXML(parser.nextText())); - } - else if (eventType == XmlPullParser.START_TAG && "date".equals(parser.getName())) { - Date d; - try { - d = FORMATTER.parse(parser.nextText()); - } - catch (ParseException e) { - d = new Date(); - } - message.setDate(d); - } - else if (eventType == XmlPullParser.END_TAG && "message".equals(parser.getName())) { - done = true; - } - } - - - return message; - } - - -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/HistoryMessage.java b/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/HistoryMessage.java deleted file mode 100644 index 9951f993c..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/HistoryMessage.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.transcripts; - -import java.util.Date; - -public class HistoryMessage { - - private String to; - private String from; - private String body; - private Date date; - - public String getTo() { - return to; - } - - public void setTo(String to) { - this.to = to; - } - - public String getFrom() { - return from; - } - - public void setFrom(String from) { - this.from = from; - } - - public Date getDate() { - return date; - } - - public void setDate(Date date) { - this.date = date; - } - - public String getBody() { - return body; - } - - public void setBody(String body) { - this.body = body; - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/HistoryTranscript.java b/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/HistoryTranscript.java deleted file mode 100644 index c8c17a81c..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/HistoryTranscript.java +++ /dev/null @@ -1,621 +0,0 @@ -package org.jivesoftware.sparkimpl.plugin.transcripts; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.concurrent.Semaphore; -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JEditorPane; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextField; -import javax.swing.UIManager; -import javax.swing.text.html.HTMLEditorKit; - - -import org.jdesktop.swingx.calendar.DateUtils; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.BackgroundPanel; -import org.jivesoftware.spark.ui.VCardPanel; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -/** - * This class represents the history transcript - * @author tim.jentz - * - */ -public class HistoryTranscript extends SwingWorker { - - private Semaphore token = new Semaphore(1); - private int pageIndex = 0; - private int maxPages = 0; - private final String period_oneMonth = "message.search.period.month.one"; - private final String period_oneYear = "message.search.period.year.one"; - private final String period_noPeriod = "message.search.period.none"; - private String searchPeriod = ""; - private List periods = new ArrayList<>(); - private final timerTranscript transcriptTask = new timerTranscript(); - private JLabel pageCounter = new JLabel("0 / 0"); - private JButton pageLeft = new JButton("<"); - private JButton pageRight = new JButton(">"); - private String jid = null; - private SimpleDateFormat notificationDateFormatter = null; - private SimpleDateFormat messageDateFormatter = null; - private final AtomicBoolean isInitialized = new AtomicBoolean(false); - - private LocalPreferences pref = SettingsManager.getLocalPreferences(); - private final JComboBox periodChooser= new JComboBox() ; - private final JPanel filterPanel = new JPanel(); - private final JPanel mainPanel = new BackgroundPanel(); - private final JPanel searchPanel = new BackgroundPanel(); - private final JPanel navigatorPanel = new JPanel(); - private final JPanel overTheTopPanel = new BackgroundPanel(); - private final JPanel controlPanel = new BackgroundPanel(); - private VCardPanel vacardPanel = null; - private final JTextField searchField = new JTextField(25); - private final JEditorPane window = new JEditorPane(); - private final JScrollPane pane = new JScrollPane(window); - private final JFrame frame = new JFrame(Res.getString("title.history.for", jid)); - private final StringBuilder builder = new StringBuilder(); - private List searchFilteredList = new ArrayList<>(); - private List dateFilteredUnfilteredList = new ArrayList<>(); - private AtomicBoolean isHistoryLoaded = new AtomicBoolean(false); - - - /** - * Open the Transcript with the given formatter. - * @param notificationDateFormatter the formatter for the notifications - * @param messageDateFormatter the formatter for dates - */ - public HistoryTranscript(SimpleDateFormat notificationDateFormatter, SimpleDateFormat messageDateFormatter) { - this.notificationDateFormatter = notificationDateFormatter; - this.messageDateFormatter = messageDateFormatter; - } - - /** - * Show the History for the given Contact. - * @param jid the JID of the current transcript - */ - public void showHistory(String jid) { - vacardPanel = new VCardPanel(jid); - frame.setTitle(Res.getString("title.history.for", jid)); - this.jid = jid; - this.start(); - } - - /** - * Check if the period was changed an apply the filter - * to the message history - * @param change the choosen value for the period - */ - private synchronized void handlePeriodChange(String change){ - try { - token.acquire(); - if ( !Objects.equals( change, searchPeriod ) && isInitialized.get()){ - searchPeriod = change; - pref.setSearchPeriod(searchPeriod); - isHistoryLoaded.set(false); - TaskEngine.getInstance().schedule(transcriptTask, 10); - } - token.release(); - } catch (InterruptedException e) { - Log.error(e); - e.printStackTrace(); - } - } - - /** - * Navigate one page left through the history. - * Do nothing if at index 0. - */ - private synchronized void pageLeft() { - try { - AtomicBoolean changed = new AtomicBoolean(); - changed.set(false); - token.acquire(); - if (pageIndex > 1){ - pageIndex--; - changed.set(true); - } - token.release(); - if (changed.get()) display(); - }catch(InterruptedException e){ - Log.error(e); - e.printStackTrace(); - } - } - - /** - * Navigate one page right through the history. - * Do nothing if at maximum index. - */ - private synchronized void pageRight() { - try { - AtomicBoolean changed = new AtomicBoolean(); - changed.set(false); - token.acquire(); - if (pageIndex < maxPages){ - pageIndex++; - changed.set(true); - } - token.release(); - if (changed.get()) display(); - } catch (InterruptedException e) { - Log.error(e); - e.printStackTrace(); - } - } - - /** - * Builds html string with the stored messages - * @param notificationDateFormatter SimpleDateFormat for formating notifications - * @param messageDateFormatter notificationDateFormatter SimpleDateFormat for formating messages - * @return String containing the messages as html - */ - public final String buildString(List messages){ - StringBuilder builder = new StringBuilder(); - final String personalNickname = SparkManager.getUserManager().getNickname(); - Date lastPost = null; - String broadcastnick = null; - boolean initialized = false; - - for (HistoryMessage message : messages) { - String color = "blue"; - - String from = message.getFrom(); - String nickname = SparkManager.getUserManager() - .getUserNicknameFromJID(message.getFrom()); - String body = org.jivesoftware.spark.util.StringUtils - .escapeHTMLTags(message.getBody()); - if (nickname.equals(message.getFrom())) { - String otherJID = XmppStringUtils.parseBareJid(message - .getFrom()); - String myJID = SparkManager.getSessionManager() - .getBareAddress(); - - if (otherJID.equals(myJID)) { - nickname = personalNickname; - } else { - nickname = XmppStringUtils.parseLocalpart(nickname); - broadcastnick = message.getFrom(); - } - } - - if (!XmppStringUtils.parseBareJid(from).equals( - SparkManager.getSessionManager().getBareAddress())) { - color = "red"; - } - - long lastPostTime = lastPost != null ? lastPost.getTime() : 0; - - int diff; - if (DateUtils.getDaysDiff(lastPostTime, message.getDate() - .getTime()) != 0) { - diff = DateUtils.getDaysDiff(lastPostTime, message - .getDate().getTime()); - } else { - diff = DateUtils.getDayOfWeek(lastPostTime) - - DateUtils.getDayOfWeek(message.getDate() - .getTime()); - } - - if (diff != 0) { - if (initialized) { - builder.append("
        "); - } - builder.append( - "") - .append(notificationDateFormatter.format(message - .getDate())) - .append(""); - initialized = true; - } - - String value = "(" + messageDateFormatter.format(message.getDate()) + ") "; - - builder.append(""); - builder.append(""); - builder.append(value); - if (broadcastnick == null){ - builder.append(nickname + ": "); - } else { - builder.append(broadcastnick + ": "); - } - builder.append(""); - builder.append(""); - builder.append(body); - builder.append(""); - builder.append("
        "); - - lastPost = message.getDate(); - broadcastnick = null; - } - builder.append(""); - - return builder.toString(); - } - - /** - * If a new page is loaded or the search is - * changed, displays the current page again. - */ - private synchronized void display() { - try { - token.acquire(); - - if ((searchFilteredList.size() > 0) && (pageIndex <= searchFilteredList.size())) { - builder.append(buildString(searchFilteredList.get(pageIndex-1).getMessages())); - - }else{ - // Handle no history - builder.replace(0, builder.length(), ""); - builder.append("") - .append(Res.getString("message.no.history.found")) - .append(""); - } - window.setText(builder.toString()); - builder.replace(0, builder.length(), ""); - if (window.getText().length() > 0) window.setCaretPosition(0); - pageCounter.setText(pageIndex + " / " + maxPages); - token.release(); - } catch (InterruptedException e) { - Log.error(e); - e.printStackTrace(); - } - } - - /** - * This class will run every time a search has startet on the messages, saved in the transcript - * or the time period has been changed - * @author tim.jentz - * - */ - private class timerTranscript extends TimerTask { - - /** - * This function check if the date of the new message is in the same period as the date - * of the old message. - * - * At the moment, there are three different time periods: - * - one week - * - three weeks - * - one month - * @param newDate the date gained from new message - * @param oldDate the date gained from new message - * @return true if both dates in the same period, false if not - */ - private boolean dateInPeriod(Date newDate, Date oldDate){ - boolean result = false; - Calendar cal = Calendar.getInstance(); - cal.setTime(newDate); - long yearNew = Math.round((double)cal.get(Calendar.YEAR)); - long monthNew = Math.round((double)cal.get(Calendar.MONTH)); - - cal.setTime(oldDate); - long yearOld = Math.round((double)cal.get(Calendar.YEAR)); - long monthOld = Math.round((double)cal.get(Calendar.MONTH)); - - if (searchPeriod.equals(period_oneMonth)) { - // for one month, we only check if the month and the year is equal - if ((monthOld == monthNew) && (yearOld == yearNew)) result = true; - }else if (searchPeriod.equals(period_oneYear)) { - // for one year, we only check if the year is the same - if ((yearOld == yearNew)) result = true; - }else if (searchPeriod.equals(period_noPeriod)) { - // for unfiltered list, we return true all the time - result = true; - } - return result; - } - - /** - * Sort the messages by the choosen period of time - * @param transcript the transcript to sort - * @return List of transcript sorted by period. each transcript contains the messages of the giving period - */ - private List getDateSortedTranscript(ChatTranscript transcript){ - List tmpList = new ArrayList<>(); - - if (transcript.size() > 0){ - ChatTranscript sortedTranscript = new ChatTranscript(); - HistoryMessage msg; - - // retrieve the first message - - Date oldDate; - Integer iteratorValue; - Integer startValue; - Integer endValue; - - boolean sortDateAsc = pref.getChatHistoryAscending(); - - if ( sortDateAsc ){ - oldDate = transcript.getMessage(0).getDate(); - iteratorValue = 1; - startValue = 0; - endValue = transcript.size(); - }else{ - oldDate = transcript.getMessage(transcript.size()-1).getDate(); - iteratorValue = -1; - startValue = transcript.size()-1; - endValue = -1; - } - - Calendar cal = Calendar.getInstance(); - cal.setTime(oldDate); - Date newDate; - - ChatTranscript history = new ChatTranscript(); - boolean handled = true; - - for(int i = startValue; i != endValue; i += iteratorValue){ - msg = transcript.getMessage(i); - // get the date of the current message - newDate = msg.getDate(); - - if (! dateInPeriod(newDate, oldDate)){ - history = new ChatTranscript(); - history.setList(sortedTranscript.getMessages()); - - // add the messages to the list - if (history.getMessages().size() > 0) tmpList.add(history); - - // we have handled this entry - - oldDate = msg.getDate(); - sortedTranscript = new ChatTranscript(); - } - sortedTranscript.addHistoryMessage(msg); - // the latest entries not yet saved to the list - handled = false; - } - - // if the latest entries where not yet handled, do it now - if (!handled) { - history = new ChatTranscript(); - history.setList(sortedTranscript.getMessages()); - if (history.getMessages().size() > 0) tmpList.add(history); - } - } - - return tmpList; - } - - @Override - public void run() { - if (! isHistoryLoaded.get()){ - // if we have to load the history - dateFilteredUnfilteredList = getDateSortedTranscript((ChatTranscript) get()); - - try { - token.acquire(); - // confirm that the history is loaded - isHistoryLoaded.set(true); - token.release(); - } catch (InterruptedException e) { - Log.error(e); - e.printStackTrace(); - } - } - - - String searchString = searchField.getText(); - // if we searching for a string or not - if (Res.getString("message.search.for.history").equals( - searchField.getText()) - || searchField.getText().equals("")) - searchString = null; - - List tmpList = new ArrayList<>(); - ChatTranscript tmpTranscript; - - for (int i = 0; i < dateFilteredUnfilteredList.size(); i++){ - tmpTranscript = new ChatTranscript(); - tmpTranscript.setList(dateFilteredUnfilteredList.get(i).getMessage(searchString)); - if (tmpTranscript.size() > 0) tmpList.add(tmpTranscript); - } - - try { - token.acquire(); - searchFilteredList = tmpList; - pageIndex = (searchFilteredList.size() > 0) ? 1 : 0; - maxPages = searchFilteredList.size(); - token.release(); - } catch (InterruptedException e) { - Log.error(e); - e.printStackTrace(); - } - display(); - } - } - - /** - * Check if the given String represents a valid period - * @param p the period, that have to be checked - * @return true if valid, false if invalid - */ - private int getPeriodIndex(String p){ - int result = 0; - for (int i = 0; i < periods.size(); i++){ - if (p.equals(periods.get(i))) { - result = i; - break; - } - } - return result; - } - - /** - * Set the layout settings - */ - public void finished() { - pageLeft.addActionListener( arg0 -> pageLeft() ); - pageRight.addActionListener( arg0 -> pageRight() ); - periodChooser.addActionListener( e -> handlePeriodChange (periods.get(periodChooser.getSelectedIndex())) ); - - // add search text input - searchPanel.setLayout(new GridBagLayout()); - navigatorPanel.setLayout(new GridBagLayout()); - controlPanel.setLayout(new BorderLayout()); - filterPanel.setLayout(new GridBagLayout()); - mainPanel.setLayout(new BorderLayout()); - - // the list of periods -// periods.add(period_oneWeek); -// periods.add(period_threeWeeks); - periods.add(period_oneMonth); - periods.add(period_oneYear); - periods.add(period_noPeriod); - - // get the default preferences for the search period - int index = getPeriodIndex(pref.getSearchPeriod(periods.get(0))); - - for (String period : periods){ - periodChooser.addItem(Res.getString(period)); - - } - - periodChooser.setToolTipText(Res.getString("message.search.page.timeperiod")); - pageCounter.setToolTipText(Res.getString("message.search.page.counter")); - pageRight.setToolTipText(Res.getString("message.search.page.right")); - pageLeft.setToolTipText(Res.getString("message.search.page.left")); - searchField.setText(Res.getString("message.search.for.history")); - searchField.setToolTipText(Res.getString("message.search.for.history")); - searchField.setForeground((Color) UIManager - .get("TextField.lightforeground")); - - searchPanel.add(vacardPanel, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, - GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, - new Insets(1, 5, 1, 1), 0, 0)); - - filterPanel.add(periodChooser,new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(1, 5, 1, 1), 0, 0)); - - filterPanel.add(searchField, new GridBagConstraints(2, 0, - GridBagConstraints.REMAINDER, 1, 1.0, 1.0, - GridBagConstraints.EAST, GridBagConstraints.NONE, - new Insets(1, 1, 6, 1), 0, 0)); - - navigatorPanel.add(pageLeft, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(1, 5, 1, 1), 0, 0)); - navigatorPanel.add(pageCounter, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0, - GridBagConstraints.CENTER, GridBagConstraints.NONE, - new Insets(1, 5, 1, 1), 0, 0)); - navigatorPanel.add(pageRight, new GridBagConstraints(2, 0, - GridBagConstraints.REMAINDER, 1, 1.0, 1.0, - GridBagConstraints.EAST, GridBagConstraints.NONE, - new Insets(1, 1, 6, 1), 0, 0)); - - controlPanel.add(filterPanel, BorderLayout.NORTH); - controlPanel.add(navigatorPanel, BorderLayout.SOUTH); - - overTheTopPanel.setLayout(new BorderLayout()); - overTheTopPanel.add(searchPanel,BorderLayout.NORTH); - overTheTopPanel.add(controlPanel,BorderLayout.SOUTH); - - mainPanel.add(overTheTopPanel, BorderLayout.NORTH); - - window.setEditorKit(new HTMLEditorKit()); - window.setBackground(Color.white); - pane.getVerticalScrollBar().setBlockIncrement(200); - pane.getVerticalScrollBar().setUnitIncrement(20); - - mainPanel.add(pane, BorderLayout.CENTER); - - frame.setIconImage(SparkRes.getImageIcon(SparkRes.HISTORY_16x16) - .getImage()); - frame.getContentPane().setLayout(new BorderLayout()); - frame.getContentPane().add(mainPanel, BorderLayout.CENTER); - frame.pack(); - frame.setSize(600, 400); - window.setCaretPosition(0); - window.requestFocus(); - GraphicUtils.centerWindowOnScreen(frame); - frame.setVisible(true); - window.setEditable(false); - - builder.append(""); - - searchField.addKeyListener(new KeyListener() { - @Override - public void keyTyped(KeyEvent e) { - } - - @Override - public void keyReleased(KeyEvent e) { - if (e.getKeyChar() == KeyEvent.VK_ENTER) { - TaskEngine.getInstance().schedule(transcriptTask, 10); - searchField.requestFocus(); - } - } - - @Override - public void keyPressed(KeyEvent e) { - - } - }); - searchField.addFocusListener(new FocusListener() { - public void focusGained(FocusEvent e) { - searchField.setText(""); - searchField.setForeground((Color) UIManager - .get("TextField.foreground")); - } - - public void focusLost(FocusEvent e) { - searchField.setForeground((Color) UIManager - .get("TextField.lightforeground")); - searchField.setText(Res.getString("message.search.for.history")); - } - }); - - // after initializing the period, we can load the history - isInitialized.set(true); - periodChooser.setSelectedIndex(index); - - frame.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - window.setText(""); - } - - @Override - public void windowClosed(WindowEvent e) { - frame.removeWindowListener(this); - frame.dispose(); - transcriptTask.cancel(); - searchPanel.remove(vacardPanel); - } - }); - } - - @Override - public Object construct() { - String bareJID = XmppStringUtils.parseBareJid(jid); - return ChatTranscripts.getChatTranscript(bareJID); - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/viewer/PluginViewer.java b/src/java/org/jivesoftware/sparkimpl/plugin/viewer/PluginViewer.java deleted file mode 100644 index 11e983577..000000000 --- a/src/java/org/jivesoftware/sparkimpl/plugin/viewer/PluginViewer.java +++ /dev/null @@ -1,687 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.plugin.viewer; - -import java.awt.Color; -import java.awt.Component; -import java.awt.EventQueue; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JProgressBar; -import javax.swing.JScrollPane; -import javax.swing.JTabbedPane; -import javax.swing.UIManager; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.commons.httpclient.protocol.Protocol; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.Node; -import org.dom4j.io.SAXReader; -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.PluginManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.MessageDialog; -import org.jivesoftware.spark.component.VerticalFlowLayout; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.plugin.PublicPlugin; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.URLFileSystem; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.JiveInfo; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jivesoftware.sparkimpl.updater.EasySSLProtocolSocketFactory; - -/** - * Class to handle the viewing of installed and downloadable Plugins - */ -public class PluginViewer extends JPanel implements Plugin { - - private static final long serialVersionUID = -4249017716988031394L; - - private JTabbedPane tabbedPane; - - private boolean loaded = false; - - private String retrieveListURL = Default.getString("PLUGIN_REPOSITORY"); - - private JProgressBar progressBar; - - private JPanel installedPanel; - private JPanel availablePanel; - private JPanel deactivatedPanel; - private LocalPreferences _prefs; - private List _deactivatedPlugins; - - public PluginViewer() { - _prefs = SettingsManager.getLocalPreferences(); - _deactivatedPlugins = _prefs.getDeactivatedPlugins(); - - EventQueue.invokeLater( () -> { - - tabbedPane = new JTabbedPane(); - installedPanel = new JPanel(); - availablePanel = new JPanel(); - deactivatedPanel = new JPanel(); - setLayout(new GridBagLayout()); - - installedPanel.setLayout(new VerticalFlowLayout( - VerticalFlowLayout.TOP, 0, 0, true, false)); - installedPanel.setBackground(Color.white); - - availablePanel.setLayout(new VerticalFlowLayout( - VerticalFlowLayout.TOP, 0, 0, true, false)); - availablePanel.setBackground(Color.white); - - - // Add TabbedPane - add(tabbedPane, new GridBagConstraints(0, 1, 2, 1, 1.0, 1.0, - GridBagConstraints.WEST, GridBagConstraints.BOTH, - new Insets(5, 5, 5, 5), 0, 0)); - - // Add Tabs - tabbedPane.addTab(Res.getString("tab.installed.plugins"), - new JScrollPane(installedPanel)); - if (!Default.getBoolean(Default.INSTALL_PLUGINS_DISABLED)) { - tabbedPane.addTab(Res.getString("tab.available.plugins"), - new JScrollPane(availablePanel)); - } - - loadInstalledPlugins(); - loadDeactivatedPlugins(); - - tabbedPane.addChangeListener( changeEvent -> { - if (tabbedPane.getSelectedComponent().equals( - availablePanel.getParent().getParent())) { - loadAvailablePlugins(); - loaded = true; - } - } ); - } ); - } - - private void loadInstalledPlugins() { - PluginManager pluginManager = PluginManager.getInstance(); - List plugins = pluginManager.getPublicPlugins(); - for (Object plugin1 : plugins) { - PublicPlugin plugin = (PublicPlugin) plugin1; - final SparkPlugUI ui = new SparkPlugUI(plugin); - ui.useLocalIcon(); - installedPanel.add(ui); - addSparkPlugUIListener(ui); - } - } - - /** - * Initializes the Deactivated Plugins Tab - */ - private void loadDeactivatedPlugins() { - deactivatedPanel.setLayout(new VerticalFlowLayout( - VerticalFlowLayout.TOP, 0, 0, true, false)); - if (!Default.getBoolean(Default.DEINSTALL_PLUGINS_DISABLED)) { - tabbedPane.addTab(Res.getString("tab.deactivated.plugins"), new JScrollPane(deactivatedPanel)); - } - for (final String s : _deactivatedPlugins) { - PublicPlugin plg = new PublicPlugin(); - plg.setName(s); - final SparkPlugUI ui = new SparkPlugUI(plg); - ui.useLocalIcon(); - deactivatedPanel.add(ui); - addDeactivatedListener(ui); - - } - - } - - - public void initialize() { - // Add Plugins Menu - JMenuBar menuBar = SparkManager.getMainWindow().getJMenuBar(); - - // Get last menu which is help - JMenu sparkMenu = menuBar.getMenu(0); - - JMenuItem viewPluginsMenu = new JMenuItem(); - - Action viewAction = new AbstractAction() { - private static final long serialVersionUID = 6518407602062984752L; - - public void actionPerformed(ActionEvent e) { - invokeViewer(); - } - }; - - viewAction.putValue(Action.NAME, Res.getString("menuitem.plugins")); - viewAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.PLUGIN_IMAGE)); - viewPluginsMenu.setAction(viewAction); - - sparkMenu.insert(viewPluginsMenu, 2); - } - - private boolean uninstall(final PublicPlugin plugin) { - UIManager.put("OptionPane.yesButtonText", Res.getString("yes")); - UIManager.put("OptionPane.noButtonText", Res.getString("no")); - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - - int ok = JOptionPane.showConfirmDialog(installedPanel, Res.getString("message.prompt.plugin.uninstall", plugin.getName()), Res.getString("title.confirmation"), JOptionPane.YES_NO_OPTION); - if (ok == JOptionPane.YES_OPTION) { - - // DOENST DELETE ANYMORE, Plugin will be added to a 'do-not-load-list' - // Delete main jar. - // File pluginDir = plugin.getPluginDir(); - // File pluginJAR = new File(plugin.getPluginDir().getParentFile(), - // pluginDir.getName() + ".jar"); - // File mainpluginJar = new - // File(Spark.getBinDirectory().getParent()+"/plugins/"+pluginJAR.getName()); - // pluginJAR.delete(); - // mainpluginJar.delete(); - - List deact = _prefs.getDeactivatedPlugins(); - deact.add(plugin.getName()); - _prefs.setDeactivatedPlugins(deact); - _deactivatedPlugins = deact; - - final SparkPlugUI ui = new SparkPlugUI(plugin); - deactivatedPanel.add(ui); - addDeactivatedListener(ui); - - JOptionPane.showMessageDialog(this, Res.getString("message.restart.spark.changes"), Res.getString("title.reminder"), JOptionPane.INFORMATION_MESSAGE); - PluginManager.getInstance().removePublicPlugin(plugin); - return true; - } - - return false; - } - - private void invokeViewer() { - PluginViewer viewer = new PluginViewer(); - MessageDialog.showComponent(Res.getString("title.plugins"), "", null, viewer, SparkManager.getMainWindow(), 600, 600, false); - } - - public void shutdown() { - - } - - public boolean canShutDown() { - return false; - } - - private void loadAvailablePlugins() { - availablePanel.removeAll(); - availablePanel.invalidate(); - availablePanel.validate(); - availablePanel.repaint(); - - JLabel label = new JLabel(Res.getString("message.loading.please.wait")); - availablePanel.add(label); - - - SwingWorker worker = new SwingWorker() { - Collection pluginList = null; - - public Object construct() { - // Prepare HTTP post - final GetMethod post = new GetMethod(retrieveListURL); - - // Get HTTP client - Protocol.registerProtocol("https", new Protocol("https", new EasySSLProtocolSocketFactory(), 443)); - final HttpClient httpclient = new HttpClient(); - - if(Default.getBoolean("PLUGIN_REPOSITORY_USE_PROXY")) - { - String proxyHost = System.getProperty("http.proxyHost"); - String proxyPort = System.getProperty("http.proxyPort"); - if (ModelUtil.hasLength(proxyHost) && ModelUtil.hasLength(proxyPort)) { - try { - httpclient.getHostConfiguration().setProxy(proxyHost, Integer.parseInt(proxyPort)); - } - catch (NumberFormatException e) { - Log.error(e); - } - } - } - - // Execute request - - try { - int result = httpclient.executeMethod(post); - if (result != 200) { - return null; - } - - pluginList = getPluginList(post.getResponseBodyAsStream()); - } - catch (Exception ex) { - // Nothing to do - } - return "ok"; - } - - public void finished() { - final PluginManager pluginManager = PluginManager.getInstance(); - if (pluginList == null) { - availablePanel.removeAll(); - availablePanel.invalidate(); - availablePanel.validate(); - availablePanel.repaint(); - - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(availablePanel, Res.getString("message.plugins.not.available"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - return; - } - Iterator plugs = pluginList.iterator(); - availablePanel.removeAll(); - - while (plugs.hasNext()) { - PublicPlugin plugin = plugs.next(); - if (!pluginManager.isInstalled(plugin)) { - SparkPlugUI ui = new SparkPlugUI(plugin); - availablePanel.add(ui); - addSparkPlugUIListener(ui); - } - } - - availablePanel.invalidate(); - availablePanel.validate(); - availablePanel.repaint(); - } - }; - - worker.start(); - } - - private void downloadPlugin(final PublicPlugin plugin) { - // Prepare HTTP post - final GetMethod post = new GetMethod(plugin.getDownloadURL()); - - // Get HTTP client - Protocol.registerProtocol("https", new Protocol("https", new EasySSLProtocolSocketFactory(), 443)); - final HttpClient httpclient = new HttpClient(); - String proxyHost = System.getProperty("http.proxyHost"); - String proxyPort = System.getProperty("http.proxyPort"); - - if (Default.getBoolean("PLUGIN_REPOSITORY_USE_PROXY")) { - if (ModelUtil.hasLength(proxyHost) - && ModelUtil.hasLength(proxyPort)) { - try { - httpclient.getHostConfiguration().setProxy(proxyHost, - Integer.parseInt(proxyPort)); - } catch (NumberFormatException e) { - Log.error(e); - } - } - } - // Execute request - - - try { - int result = httpclient.executeMethod(post); - if (result != 200) { - return; - } - - long length = post.getResponseContentLength(); - int contentLength = (int)length; - - progressBar = new JProgressBar(0, contentLength); - - final JFrame frame = new JFrame(Res.getString("message.downloading", plugin.getName())); - - frame.setIconImage(SparkRes.getImageIcon(SparkRes.SMALL_MESSAGE_IMAGE).getImage()); - - final Thread thread = new Thread( () -> { - try { - Thread.sleep(2000); - InputStream stream = post.getResponseBodyAsStream(); - - URL url = new URL(plugin.getDownloadURL()); - String name1 = URLFileSystem.getFileName(url); - String directoryName = URLFileSystem.getName(url); - - File pluginDownload = new File(PluginManager.PLUGINS_DIRECTORY, name1 ); - - FileOutputStream out = new FileOutputStream(pluginDownload); - copy(stream, out); - out.close(); - - frame.dispose(); - - // Remove SparkPlugUI - // Clear all selections - Component[] comps = availablePanel.getComponents(); - for (Component comp : comps) { - if (comp instanceof SparkPlugUI) { - SparkPlugUI sparkPlug = (SparkPlugUI) comp; - if (sparkPlug.getPlugin().getDownloadURL().equals(plugin.getDownloadURL())) { - availablePanel.remove(sparkPlug); - - _deactivatedPlugins.remove(sparkPlug.getPlugin().getName()); - _prefs.setDeactivatedPlugins(_deactivatedPlugins); - - PluginManager.getInstance().addPlugin(sparkPlug.getPlugin()); - - sparkPlug.showOperationButton(); - installedPanel.add(sparkPlug); - sparkPlug.getPlugin().setPluginDir(new File(PluginManager.PLUGINS_DIRECTORY, directoryName)); - installedPanel.invalidate(); - installedPanel.repaint(); - availablePanel.invalidate(); - availablePanel.invalidate(); - availablePanel.validate(); - availablePanel.repaint(); - } - } - } - } - catch (Exception ex) { - // Nothing to do - } - finally { - // Release current connection to the connection pool once you are done - post.releaseConnection(); - } - } ); - - - frame.getContentPane().setLayout(new GridBagLayout()); - frame.getContentPane().add(new JLabel(Res.getString("message.downloading.spark.plug")), new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - frame.getContentPane().add(progressBar, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - frame.pack(); - frame.setSize(400, 100); - GraphicUtils.centerWindowOnComponent(frame, this); - - - frame.setVisible(true); - thread.start(); - - } - catch (IOException e) { - Log.error(e); - } - } - - - public Collection getPluginList(InputStream response) { - final List pluginList = new ArrayList<>(); - SAXReader saxReader = new SAXReader(); - Document pluginXML = null; - - try { - pluginXML = saxReader.read(response); - } - catch (DocumentException e) { - Log.error(e); - } - - List plugins = pluginXML.selectNodes("/plugins/plugin"); - - for (Node plugin1 : plugins) { - PublicPlugin publicPlugin = new PublicPlugin(); - - String clazz; - String name = null; - try { - Element plugin = (Element) plugin1; - - try { - String version = plugin.selectSingleNode("minSparkVersion").getText(); - if (!isGreaterOrEqual(JiveInfo.getVersion(), version)) { - Log.error("Unable to load plugin " + name + " due to min version incompatibility."); - continue; - } - } - catch (Exception e) { - Log.error("Unable to load plugin " + name + " due to no minSparkVersion."); - continue; - } - - name = plugin.selectSingleNode("name").getText(); - clazz = plugin.selectSingleNode("class").getText(); - publicPlugin.setPluginClass(clazz); - publicPlugin.setName(name); - - try { - String version = plugin.selectSingleNode("version").getText(); - publicPlugin.setVersion(version); - - String author = plugin.selectSingleNode("author").getText(); - publicPlugin.setAuthor(author); - - - Node emailNode = plugin.selectSingleNode("email"); - if (emailNode != null) { - publicPlugin.setEmail(emailNode.getText()); - } - - Node descriptionNode = plugin.selectSingleNode("description"); - if (descriptionNode != null) { - publicPlugin.setDescription(descriptionNode.getText()); - } - - Node homePageNode = plugin.selectSingleNode("homePage"); - if (homePageNode != null) { - publicPlugin.setHomePage(homePageNode.getText()); - } - - Node downloadNode = plugin.selectSingleNode("downloadURL"); - if (downloadNode != null) { - String downloadURL = downloadNode.getText(); - publicPlugin.setDownloadURL(downloadURL); - } - - Node changeLogNode = plugin.selectSingleNode("changeLog"); - if (changeLogNode != null) { - publicPlugin.setChangeLogURL(changeLogNode.getText()); - } - - Node readMeNode = plugin.selectSingleNode("readme"); - if (readMeNode != null) { - publicPlugin.setReadMeURL(readMeNode.getText()); - } - - Node smallIcon = plugin.selectSingleNode("smallIcon"); - if (smallIcon != null) { - publicPlugin.setSmallIconAvailable(true); - } - - Node largeIcon = plugin.selectSingleNode("largeIcon"); - if (largeIcon != null) { - publicPlugin.setLargeIconAvailable(true); - } - - } - catch (Exception e) { - Log.error("Error retrieving PluginInformation from xml.",e); - } - pluginList.add(publicPlugin); - } - catch (Exception ex) { - ex.printStackTrace(); - } - - - } - return pluginList; - } - - /** - * Common code for copy routines. By convention, the streams are - * closed in the same method in which they were opened. Thus, - * this method does not close the streams when the copying is done. - * - * @param in Stream to copy from. - * @param out Stream to copy to. - */ - private void copy(final InputStream in, final OutputStream out) { - int read = 0; - while (true) { - try { - try { - Thread.sleep(10); - } - catch (InterruptedException e) { - Log.error(e); - } - final byte[] buffer = new byte[4096]; - - int bytesRead = in.read(buffer); - if (bytesRead < 0) { - break; - } - out.write(buffer, 0, bytesRead); - read += bytesRead; - final int readprogr = read; - EventQueue.invokeLater( () -> progressBar.setValue(readprogr) ); - } - catch (IOException e) { - Log.error(e); - } - } - } - - - private void addSparkPlugUIListener(final SparkPlugUI ui) { - ui.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent mouseEvent) { - // Clear all selections - Component[] comps = installedPanel.getComponents(); - for (Component comp : comps) { - if (comp instanceof SparkPlugUI) { - SparkPlugUI sparkPlug = (SparkPlugUI) comp; - sparkPlug.setSelected(false); - } - } - - // Clear all selections - comps = availablePanel.getComponents(); - for (Component comp : comps) { - if (comp instanceof SparkPlugUI) { - SparkPlugUI sparkPlug = (SparkPlugUI) comp; - sparkPlug.setSelected(false); - } - } - - ui.setSelected(true); - - final PluginManager pluginManager = PluginManager.getInstance(); - ui.getInstallButton().addMouseListener(new MouseAdapter() { - - @Override - public void mouseClicked(MouseEvent e) { - - boolean isInstalled = pluginManager.isInstalled(ui.getPlugin()); - if (isInstalled) { - boolean uninstalled = uninstall(ui.getPlugin()); - if (uninstalled) { - installedPanel.remove(ui); - installedPanel.invalidate(); - installedPanel.repaint(); - installedPanel.revalidate(); - } - } - else { - downloadPlugin(ui.getPlugin()); - } - } - }); - } - }); - } - /** - * Adds the MouseClick Listener to the PluginPreview
        - * Adds the MouseClick Listener to the InstallButton - * @param ui - */ - private void addDeactivatedListener(final SparkPlugUI ui) { - - ui.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - - for(Component c : deactivatedPanel.getComponents()) - { - if (c instanceof SparkPlugUI) - { - ((SparkPlugUI)c).setSelected(false); - } - } - ui.setSelected(true); - } - }); - - ui.getInstallButton().addActionListener( e -> { - deactivatedPanel.remove(ui); - _deactivatedPlugins.remove(ui.getPlugin().getName()); - _prefs.setDeactivatedPlugins(_deactivatedPlugins); - deactivatedPanel.repaint(); - deactivatedPanel.revalidate(); - } ); - } - - public void uninstall() { - // Do nothing. - } - - /** - * Returns true if the first version number is greater than the second. - * - * @param firstVersion the first version number. - * @param secondVersion the second version number. - * @return returns true if the first version is greater than the second. - */ - public boolean isGreaterOrEqual(String firstVersion, String secondVersion) { - return firstVersion.compareTo(secondVersion) >= 0; - } - - public boolean isLoaded() { - return loaded; - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/preference/PreferenceDialog.java b/src/java/org/jivesoftware/sparkimpl/preference/PreferenceDialog.java deleted file mode 100644 index 084541c5c..000000000 --- a/src/java/org/jivesoftware/sparkimpl/preference/PreferenceDialog.java +++ /dev/null @@ -1,144 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkimpl.preference; - -import java.awt.BorderLayout; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JOptionPane; -import javax.swing.JPanel; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettings; -import org.jivesoftware.sparkimpl.plugin.layout.LayoutSettingsManager; - -public class PreferenceDialog implements PropertyChangeListener { - private JDialog preferenceDialog; - private JOptionPane pane = null; - private PreferencesPanel prefPanel; - - public void invoke(JFrame parentFrame, PreferencesPanel contentPane) { - - this.prefPanel = contentPane; - - // Construct main panel w/ layout. - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - - // Construct Dialog - preferenceDialog = new JDialog(parentFrame, - Res.getString("title.preferences"), - false); - - JButton btn_apply = new JButton(Res.getString("apply")); - JButton btn_save = new JButton(Res.getString("save")); - JButton btn_close = new JButton(Res.getString("close")); - - btn_close.addActionListener( e -> { - saveLayout(); - preferenceDialog.setVisible(false); - preferenceDialog.dispose(); - } ); - btn_save.addActionListener( e -> { - boolean okToClose = prefPanel.closing(); -if (okToClose) { -saveLayout(); -preferenceDialog.setVisible(false); -preferenceDialog.dispose(); -} -else { -pane.setValue(JOptionPane.UNINITIALIZED_VALUE); -} - } ); - btn_apply.addActionListener( e -> { - boolean okToClose = prefPanel.closing(); -if (!okToClose) { -pane.setValue(JOptionPane.UNINITIALIZED_VALUE); -} - } ); - - Object[] options = {btn_apply, btn_save, btn_close}; - pane = new JOptionPane(contentPane, JOptionPane.PLAIN_MESSAGE, - JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); - mainPanel.add(pane, BorderLayout.CENTER); - preferenceDialog.setContentPane(mainPanel); - preferenceDialog.pack(); - - LayoutSettings settings = LayoutSettingsManager.getLayoutSettings(); - if ((settings.getPreferencesFrameX() == 0 && settings.getPreferencesFrameY() == 0) - || settings.getPreferencesFrameHeight() < 100 - || settings.getPreferencesFrameWidth() < 100) { - // Use default settings. - preferenceDialog.setSize(750, 550); - preferenceDialog.setLocationRelativeTo(SparkManager.getMainWindow()); - } - else { - preferenceDialog.setBounds(settings.getPreferencesFrameX(), settings.getPreferencesFrameY(), settings.getPreferencesFrameWidth(), settings.getPreferencesFrameHeight()); - } - - pane.addPropertyChangeListener(this); - - preferenceDialog.setVisible(true); - preferenceDialog.toFront(); - - preferenceDialog.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - saveLayout(); - } - }); - } - - public void propertyChange(PropertyChangeEvent e) { - if (pane.getValue() instanceof Integer) { - saveLayout(); - pane.removePropertyChangeListener(this); - preferenceDialog.dispose(); - } - } - - public JDialog getDialog() { - return preferenceDialog; - } - - /** - * Saves the layout on closing of the main window. - */ - private void saveLayout() { - try { - LayoutSettings settings = LayoutSettingsManager.getLayoutSettings(); - settings.setPreferencesFrameHeight(preferenceDialog.getHeight()); - settings.setPreferencesFrameWidth(preferenceDialog.getWidth()); - settings.setPreferencesFrameX(preferenceDialog.getX()); - settings.setPreferencesFrameY(preferenceDialog.getY()); - LayoutSettingsManager.saveLayoutSettings(); - } - catch (Exception e) { - // Don't let this cause a real problem shutting down. - } - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/preference/PreferenceUI.java b/src/java/org/jivesoftware/sparkimpl/preference/PreferenceUI.java deleted file mode 100644 index 696ffbd4b..000000000 --- a/src/java/org/jivesoftware/sparkimpl/preference/PreferenceUI.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkimpl.preference; - -import org.jivesoftware.spark.preference.Preference; -import org.jivesoftware.spark.util.GraphicUtils; - -import javax.swing.JButton; -import javax.swing.JLabel; - -import java.awt.event.MouseEvent; - -public class PreferenceUI extends JLabel { - private static final long serialVersionUID = 1094181037849878301L; - private Preference preference; - - public PreferenceUI(Preference preference) { - this.preference = preference; - this.setIcon(preference.getIcon()); - this.setText(preference.getListName()); - - // Set tooltip - this.setToolTipText(GraphicUtils.createToolTip(preference.getTooltip())); - } - - - public void mouseEntered(MouseEvent e) { - if (this.isEnabled()) { - this.invalidate(); - this.repaint(); - } - } - - - public void decorate() { - this.setOpaque(true); - - this.setVerticalTextPosition(JButton.BOTTOM); - this.setHorizontalTextPosition(JButton.CENTER); - } - - public Preference getPreference() { - return preference; - } - -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/sparkimpl/preference/PreferencesPanel.java b/src/java/org/jivesoftware/sparkimpl/preference/PreferencesPanel.java deleted file mode 100644 index a537f00d6..000000000 --- a/src/java/org/jivesoftware/sparkimpl/preference/PreferencesPanel.java +++ /dev/null @@ -1,177 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkimpl.preference; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.util.Iterator; -import java.util.Objects; - -import javax.swing.DefaultListModel; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.UIManager; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.spark.component.TitlePanel; -import org.jivesoftware.spark.component.renderer.JLabelIconRenderer; -import org.jivesoftware.spark.preference.Preference; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -public class PreferencesPanel extends JPanel implements ListSelectionListener { - - private static final long serialVersionUID = 1520420979038154046L; - /** - * flowpanel is the right panel, where the plugin specific UI is displayed - */ - private final JPanel flowPanel = new JPanel(new BorderLayout()); - private DefaultListModel listModel = new DefaultListModel(); - private JList list = new JList(listModel); - private Preference currentPreference; - - /** - *

        Constructor - PreferencesPanel

        - * This is an option to select the transmitted preference by code - * If the given preference is null or not contained in the preference-list, - * the first index of the list will be selected. - * - * @param preferences the preference list - * @param displayPref the preference you want to select - */ - public PreferencesPanel (Iterator preferences, Preference displayPref){ - this(preferences); - if ( displayPref != null || listModel.getSize() == 1){ - // iterate through all preference-ui items - for (int i = 0; i < listModel.size(); i++){ - PreferenceUI p = (PreferenceUI)listModel.get( i ); - // check if the namespace is the namespace we search for - if ( Objects.equals( p.getPreference().getNamespace(), displayPref.getNamespace() ) ){ - // if we've got our target, we can select this item and stop the search - list.setSelectedIndex( i ); - break; - } - } - // if we got a valid target, we trigger the selection changed method - if (list.getSelectedIndex() > -1) selectionChanged(); - } - } - - public PreferencesPanel(Iterator preferences) { - this.setLayout(new GridBagLayout()); - - JLabel titleLabel = new JLabel(); - titleLabel.setText(Res.getString("title.preferences")); - titleLabel.setFont(new Font("Dialog", Font.BOLD, 15)); - /* - scrollPane is the left panel displaying the preference icons - */ - JScrollPane scrollPane = new JScrollPane( list ); - scrollPane.setPreferredSize(new Dimension(125, 0)); - scrollPane.setMinimumSize(new Dimension(125,100)); - list.setFixedCellHeight(50); - - add( scrollPane, new GridBagConstraints(0, 0, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.VERTICAL, new Insets(5, 5, 5, 5), 50, 0)); - add(flowPanel, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - - - list.setCellRenderer(new JLabelIconRenderer()); - list.addListSelectionListener(this); - // Populate with current preferences - while (preferences.hasNext()) { - Preference preference = preferences.next(); - listModel.addElement(new PreferenceUI(preference)); - } - - list.setSelectedIndex(0); - } - - private synchronized void selectionChanged(){ - PreferenceUI o = (PreferenceUI)list.getSelectedValue(); - Preference pref = o.getPreference(); - pref.load(); - - JComponent comp = pref.getGUI(); - flowPanel.removeAll(); - - // Create the title panel for this dialog - TitlePanel titlePanel = new TitlePanel(pref.getTitle(), - pref.getTooltip(), - pref.getIcon(), - false); - - - flowPanel.add(comp, BorderLayout.CENTER); - flowPanel.add(titlePanel, BorderLayout.NORTH); - flowPanel.invalidate(); - flowPanel.validate(); - flowPanel.repaint(); - currentPreference = pref; - } - - public void valueChanged(ListSelectionEvent e) { - - if (!e.getValueIsAdjusting()) { - - if (currentPreference != null) { - if (currentPreference.isDataValid()) { - currentPreference.commit(); - } - else { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(this, currentPreference.getErrorMessage(), - Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - list.removeListSelectionListener(this); - list.setSelectedIndex(e.getLastIndex()); - list.addListSelectionListener(this); - } - - } - selectionChanged(); - } - } - - public boolean closing() { - if (currentPreference != null) { - if (currentPreference.isDataValid()) { - currentPreference.commit(); - SettingsManager.fireListeners(); - return true; - } - else { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(this, currentPreference.getErrorMessage(), - Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - return false; - } - } - return true; - } -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/sparkimpl/preference/chat/ChatPreferencePanel.java b/src/java/org/jivesoftware/sparkimpl/preference/chat/ChatPreferencePanel.java deleted file mode 100644 index 8d38716c2..000000000 --- a/src/java/org/jivesoftware/sparkimpl/preference/chat/ChatPreferencePanel.java +++ /dev/null @@ -1,316 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.preference.chat; - -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; - -import javax.swing.BorderFactory; -import javax.swing.ButtonGroup; -import javax.swing.JCheckBox; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPasswordField; -import javax.swing.JRadioButton; -import javax.swing.JTextField; -import javax.swing.UIManager; - -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.VerticalFlowLayout; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -/** - * The Preference UI used to handle changing of Chat Preferences. - */ -public class ChatPreferencePanel extends JPanel implements ActionListener { - - private static final long serialVersionUID = 8910938026549098719L; - private JCheckBox showTimeBox = new JCheckBox(); - private ButtonGroup timeFormat = new ButtonGroup(); - private JRadioButton format12 = new JRadioButton("12:00 PM", false); - private JRadioButton format24 = new JRadioButton("24:00", true); - private JRadioButton format12s = new JRadioButton("12:00:00 PM", false); - private JRadioButton format24s = new JRadioButton("24:00:00", false); - private JCheckBox groupChatNotificationBox = new JCheckBox(); - private JPanel generalPanel = new JPanel(); - private JPanel chatWindowPanel = new JPanel(); - - // Password changing - private JPasswordField passwordField = new JPasswordField(); - private JPasswordField confirmationPasswordField = new JPasswordField(); - private JLabel passwordLabel = new JLabel(); - private JLabel confirmationPasswordLabel = new JLabel(); - private JCheckBox hideChatHistory = new JCheckBox(); - private JCheckBox sortChatHistoryAscending = new JCheckBox(); - private JCheckBox hidePrevChatHistory = new JCheckBox(); - private JCheckBox tabsOnTopBox = new JCheckBox(); - private JTextField chatTimeoutField = new JTextField(); - private JCheckBox buzzBox = new JCheckBox(); - - /** - * Constructor invokes UI setup. - */ - public ChatPreferencePanel() { - // Build the UI - createUI(); - } - - private void createUI() { - setLayout(new VerticalFlowLayout()); - timeFormat.add(format24); - timeFormat.add(format24s); - timeFormat.add(format12); - timeFormat.add(format12s); - final LocalPreferences pref = SettingsManager.getLocalPreferences(); - if(pref.getTimeFormat().equals("HH:mm")) - { - format24.setSelected(true); - } - else if(pref.getTimeFormat().equals("HH:mm:ss")) - { - format24s.setSelected(true); - } - else if(pref.getTimeFormat().equals("h:mm a")) - { - format12.setSelected(true); - } - else - { - format12s.setSelected(true); - } - - // Setup Mnemonics - ResourceUtils.resButton(showTimeBox, Res.getString("checkbox.show.time.in.chat.window")); - ResourceUtils.resLabel(passwordLabel, passwordField, Res.getString("label.change.password.to") + ":"); - ResourceUtils.resLabel(confirmationPasswordLabel, confirmationPasswordField, Res.getString("label.confirm.password") + ":"); - ResourceUtils.resButton(groupChatNotificationBox, Res.getString("checkbox.show.notifications.in.conference")); - ResourceUtils.resButton(hideChatHistory, Res.getString("checkbox.disable.chat.history")); - ResourceUtils.resButton(hidePrevChatHistory, Res.getString("checkbox.disable.prev.chat.history")); - ResourceUtils.resButton(sortChatHistoryAscending, Res.getString("checkbox.sort.asc.history")); - ResourceUtils.resButton(tabsOnTopBox, Res.getString("checkbox.tabs.on.top")); - ResourceUtils.resButton(buzzBox, Res.getString("checkbox.allow.buzz")); - - generalPanel.setBorder(BorderFactory.createTitledBorder(Res.getString("group.general.information"))); - chatWindowPanel.setBorder(BorderFactory.createTitledBorder(Res.getString("group.chat.window.information"))); - - if (!Default.getBoolean(Default.CHANGE_PASSWORD_DISABLED)) { - add(generalPanel); - } - add(chatWindowPanel); - - generalPanel.setLayout(new GridBagLayout()); - chatWindowPanel.setLayout(new GridBagLayout()); - - // Chat Window Panel settings - chatWindowPanel.add(showTimeBox, new GridBagConstraints(0, 0, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - chatWindowPanel.add(format24, new GridBagConstraints(1, 0, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - chatWindowPanel.add(format24s, new GridBagConstraints(1, 1, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - chatWindowPanel.add(format12, new GridBagConstraints(2, 0, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - chatWindowPanel.add(format12s, new GridBagConstraints(2, 1, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - chatWindowPanel.add(groupChatNotificationBox, new GridBagConstraints(0, 2, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - if (!Default.getBoolean("HISTORY_DISABLED") && !Default.getBoolean("HIDE_HISTORY_SETTINGS")) { - chatWindowPanel.add(hideChatHistory, new GridBagConstraints(0, 3, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - chatWindowPanel.add(hidePrevChatHistory, new GridBagConstraints(0, 4, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - } - chatWindowPanel.add(sortChatHistoryAscending, new GridBagConstraints(0, 5, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - chatWindowPanel.add(tabsOnTopBox, new GridBagConstraints(0, 6, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - chatWindowPanel.add(buzzBox, new GridBagConstraints(0, 7, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - JLabel chatTimeoutLabel = new JLabel(); - ResourceUtils.resLabel(chatTimeoutLabel, chatTimeoutField, Res.getString("label.minutes.before.stale.chat") + ":"); - chatWindowPanel.add(chatTimeoutLabel, new GridBagConstraints(0, 8, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - chatWindowPanel.add(chatTimeoutField, new GridBagConstraints(1, 8, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 50, 0)); - - - generalPanel.add(passwordLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - generalPanel.add(passwordField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 100, 0)); - generalPanel.add(confirmationPasswordLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - generalPanel.add(confirmationPasswordField, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 100, 0)); - - showTimeBox.addActionListener( e -> { - if(showTimeBox.isSelected()) - { - format12.setEnabled(true); - format24.setEnabled(true); - format12s.setEnabled(true); - format24s.setEnabled(true); - } - else - { - format12.setEnabled(false); - format24.setEnabled(false); - format12s.setEnabled(false); - format24s.setEnabled(false); - } - } ); - - hideChatHistory.addActionListener(this); - - } - - /** - * Set to true to have the ChatWindow show the timestamp of each message. - * - * @param showTime true to show timestamp of each message. - */ - public void setShowTime(boolean showTime) { - showTimeBox.setSelected(showTime); - } - - /** - * Returns true if the ChatWindow should show a timestamp of each message. - * - * @return true if the ChatWindow should show a timestamp of each message. - */ - public boolean getShowTime() { - return showTimeBox.isSelected(); - } - - public String getFormatTime() { - if(format24.isSelected()) - { - return "HH:mm"; - } - else if(format24s.isSelected()) - { - return "HH:mm:ss"; - } - else if(format12.isSelected()) - { - return "h:mm a"; - } - else - { - return "h:mm:ss a"; - } - } - - /** - * Returns the new password to use. - * - * @return the new password to use. - */ - public String getPassword() { - return new String(passwordField.getPassword()); - } - - /** - * Returns the confirmation password used to compare to the first password. - * - * @return the confirmation password used to compare to the first password. - */ - public String getConfirmationPassword() { - return new String(confirmationPasswordField.getPassword()); - } - - public void setSortChatHistoryAscending(boolean on) { - sortChatHistoryAscending.setSelected(on); - } - - public boolean isSortChatHistoryAscending() { - return sortChatHistoryAscending.isSelected(); - } - - public void setGroupChatNotificationsOn(boolean on) { - groupChatNotificationBox.setSelected(on); - } - - public boolean isGroupChatNotificationsOn() { - return groupChatNotificationBox.isSelected(); - } - - public void setChatHistoryHidden(boolean hide) { - hideChatHistory.setSelected(hide); - } - - public boolean isChatHistoryHidden() { - return hideChatHistory.isSelected(); - } - - public void setPrevChatHistoryHidden(boolean hide) { - hidePrevChatHistory.setSelected(hide); - } - - public boolean isPrevChatHistoryHidden() { - return hidePrevChatHistory.isSelected(); - } - - public void setChatTimeoutTime(int time) { - chatTimeoutField.setText(Integer.toString(time)); - } - - public void setTabsOnTop(boolean top){ - tabsOnTopBox.setSelected(top); - } - - public boolean isTabsOnTop(){ - return tabsOnTopBox.isSelected(); - } - - public void setBuzzEnabled(boolean allowBuzz){ - buzzBox.setSelected(allowBuzz); - } - - public boolean isBuzzEnabled(){ - return buzzBox.isSelected(); - } - - public int getChatTimeoutTime() { - try { - return Integer.parseInt(chatTimeoutField.getText()); - } - catch (NumberFormatException e) { - return 15; - } - } - - public void actionPerformed(ActionEvent actionEvent) { - if (hideChatHistory.isSelected()) { - UIManager.put("OptionPane.yesButtonText", Res.getString("yes")); - UIManager.put("OptionPane.noButtonText", Res.getString("no")); - UIManager.put("OptionPane.cancelButtonText", Res.getString("cancel")); - int ok = JOptionPane.showConfirmDialog(this, Res.getString("message.delete.all.history"), Res.getString("title.confirmation"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); - if (ok == JOptionPane.YES_OPTION) { - File transcriptDir = new File(SparkManager.getUserDirectory(), "transcripts"); - File[] files = transcriptDir.listFiles(); - - hidePrevChatHistory.setEnabled(false); - hidePrevChatHistory.setSelected(false); - - for (File transcriptFile : files) { - transcriptFile.delete(); - } - } - } else { - hidePrevChatHistory.setEnabled(true); - } - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/preference/media/MediaPreference.java b/src/java/org/jivesoftware/sparkimpl/preference/media/MediaPreference.java deleted file mode 100644 index b3d6730e8..000000000 --- a/src/java/org/jivesoftware/sparkimpl/preference/media/MediaPreference.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.preference.media; - -import javax.swing.Icon; -import javax.swing.JComponent; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.preference.Preference; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -public class MediaPreference implements Preference { - - private MediaPreferencePanel panel = new MediaPreferencePanel(); - public static final String NAMESPACE = "http://www.jivesoftware.org/spark/media"; - - @Override - public Object getData() { - return null; - } - - @Override - public String getErrorMessage() { - return null; - } - - @Override - public JComponent getGUI() { - return panel; - } - - @Override - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.HEADSET_IMAGE); - } - - @Override - public String getListName() { - return Res.getString("title.general.media"); - } - - @Override - public String getNamespace() { - return NAMESPACE; - } - - @Override - public String getTitle() { - return Res.getString("title.general.media"); - } - - @Override - public String getTooltip() { - return Res.getString("title.general.media"); - } - - @Override - public boolean isDataValid() { - return true; - } - - @Override - public void load() { - LocalPreferences localPreferences = SettingsManager.getLocalPreferences(); - panel.setAudioSystem(localPreferences.getAudioSystem()); - panel.setVideoDevice(localPreferences.getVideoDevice()); - panel.setAudioDevice(localPreferences.getAudioDevice()); - panel.setStunServer(localPreferences.getStunFallbackHost()); - panel.setStunPort(localPreferences.getStunFallbackPort()); - panel.setPlaybackDevice(localPreferences.getPlaybackDevice()); - } - - @Override - public void commit() { - LocalPreferences pref = SettingsManager.getLocalPreferences(); - pref.setAudioSystem(panel.getAudioSystem()); - pref.setAudioDevice(panel.getAudioDevice()); - pref.setVideoDevice(panel.getVideoDevice()); - pref.setStunFallbackHost(panel.getStunServer()); - pref.setStunFallbackPort(panel.getStunPort()); - pref.setPlaybackDevice(panel.getPlaybackDevice()); - SettingsManager.saveSettings(); - } - - @Override - public void shutdown() { - commit(); - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/preference/media/MediaPreferencePanel.java b/src/java/org/jivesoftware/sparkimpl/preference/media/MediaPreferencePanel.java deleted file mode 100644 index a5a08ec1a..000000000 --- a/src/java/org/jivesoftware/sparkimpl/preference/media/MediaPreferencePanel.java +++ /dev/null @@ -1,316 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.preference.media; - -import org.jitsi.impl.neomedia.MediaServiceImpl; -import org.jitsi.impl.neomedia.codec.video.AVFrameFormat; -import org.jitsi.impl.neomedia.device.AudioSystem; -import org.jitsi.impl.neomedia.device.AudioSystem.DataFlow; -import org.jitsi.impl.neomedia.device.CaptureDeviceInfo2; -import org.jitsi.service.configuration.ConfigurationService; -import org.jitsi.service.libjitsi.LibJitsi; -import org.jitsi.service.neomedia.MediaService; -import org.jitsi.service.neomedia.MediaType; -import org.jitsi.service.neomedia.MediaUseCase; -import org.jitsi.service.neomedia.device.MediaDevice; -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Res; -import org.jivesoftware.spark.component.VerticalFlowLayout; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.log.Log; - -import javax.media.CaptureDeviceInfo; -import javax.media.CaptureDeviceManager; -import javax.media.Format; -import javax.media.format.AudioFormat; -import javax.swing.*; -import java.awt.*; -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.util.Vector; - -public class MediaPreferencePanel extends JPanel { - private static final long serialVersionUID = 8297469864676223072L; - private Vector vectorAudioDevices; - private Vector vectorVideoDevices; - private Vector vectorAudioSystem = new Vector<>(); - private Vector vectorPlaybackDevices = new Vector<>(); - - private JComboBox audioDevice = new JComboBox(); - private JComboBox audioSystem = new JComboBox(); - private JComboBox playbackDevice = new JComboBox(); - private JComboBox videoDevice = new JComboBox(); - private JTextField _stunServerInput = new JTextField(); - private JTextField _stunPortInput = new JTextField(); - - public MediaPreferencePanel() { - setLayout(new VerticalFlowLayout()); - - JPanel panel = new JPanel(); - panel.setBorder(BorderFactory.createTitledBorder(Res.getString("title.general.media"))); - add(panel); - - panel.setLayout(new GridBagLayout()); - - JLabel lAudioSystem = new JLabel(); // Res.getString("label.audio.device")); - panel.add( lAudioSystem, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); - panel.add(audioSystem, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); - - - JLabel lPlaybackAudio = new JLabel(); // Res.getString("label.audio.device")); - panel.add( lPlaybackAudio, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); - panel.add(playbackDevice, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); - - - JLabel lAudio = new JLabel(); // Res.getString("label.audio.device")); - panel.add( lAudio, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); - panel.add(audioDevice, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); - - - JLabel lVideo = new JLabel(); // Res.getString("label.video.device")); - panel.add( lVideo, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); - panel.add(videoDevice, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); - - JButton redetect = new JButton(); // Res.getString("button.re.detect") ); - redetect.addActionListener( event -> scanDevices() ); - - panel.add(redetect,new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); - - // Setup Mnemonics - ResourceUtils.resButton(redetect, Res.getString("button.re.detect")); - ResourceUtils.resLabel(lVideo, videoDevice, Res.getString("label.video.device") + ":"); - ResourceUtils.resLabel(lPlaybackAudio, playbackDevice, Res.getString("label.audio.device") + ":"); - ResourceUtils.resLabel(lAudio, audioDevice, Res.getString("label.audio.device") + ":"); - - scanDevices(); - - createSTUNPanel(); - } - - private String convertSysString(String src) - { - String res = src; - try { - res = new String(src.getBytes("ISO-8859-1"),Charset.defaultCharset()); - } catch (UnsupportedEncodingException e) { - Log.error("convertSysString" , e); - } - return res; - } - - - - @SuppressWarnings("unchecked") - public void scanDevices() - { - // Remove all Items - audioDevice.removeAllItems(); - videoDevice.removeAllItems(); - playbackDevice.removeAllItems(); - audioSystem.removeAllItems(); - - vectorPlaybackDevices.removeAllElements(); - vectorAudioSystem.removeAllElements(); - // FMJ - System.setProperty(ConfigurationService.PNAME_SC_HOME_DIR_LOCATION, Spark.getUserHome()); - System.setProperty(ConfigurationService.PNAME_SC_HOME_DIR_NAME, "."); - System.setProperty(ConfigurationService.PNAME_SC_CACHE_DIR_LOCATION, Spark.getUserHome()); - System.setProperty(ConfigurationService.PNAME_SC_LOG_DIR_LOCATION, Spark.getUserHome()); - - LibJitsi.start(); - - MediaType[] mediaTypes = MediaType.values(); - MediaService mediaService = LibJitsi.getMediaService(); - for (MediaType mediaType : mediaTypes) - { - System.err.println("================================"); - System.err.println("MediaType: " + mediaType); - System.out.println(mediaService); - - MediaDevice device = mediaService.getDefaultDevice(mediaType, MediaUseCase.CALL); - if (device != null) - { - System.out.println(device.getDirection()); - } - System.err.println("Device: " + device); - System.err.println("================================"); - } - - - vectorAudioDevices = CaptureDeviceManager.getDeviceList(new AudioFormat(AudioFormat.LINEAR)); - for ( CaptureDeviceInfo infoCaptureDevice : vectorAudioDevices) - { - String protocol = infoCaptureDevice.getLocator().getProtocol(); - audioDevice.addItem("[" + protocol + "]" + convertSysString(infoCaptureDevice.getName())); - } - - vectorVideoDevices = CaptureDeviceManager.getDeviceList(new AVFrameFormat()); - for ( CaptureDeviceInfo infoCaptureDevice : vectorVideoDevices ) - { - videoDevice.addItem(convertSysString(infoCaptureDevice.getName())); - } - vectorVideoDevices.add(null); - videoDevice.addItem(""); - - AudioSystem mediaAudioSystem = ((MediaServiceImpl)LibJitsi.getMediaService()).getDeviceConfiguration().getAudioSystem(); - for (AudioSystem system : AudioSystem.getAudioSystems()) - { - System.out.println(system); - vectorAudioSystem.add(system); - audioSystem.addItem(system); - } - - for (CaptureDeviceInfo2 device : mediaAudioSystem.getDevices(DataFlow.PLAYBACK)) { - playbackDevice.addItem(convertSysString(device.getName())); - vectorPlaybackDevices.add(device); - } - } - - private void createSTUNPanel() - { - JPanel stunPanel = new JPanel(new GridBagLayout()); - stunPanel.setBorder(BorderFactory.createTitledBorder(Res.getString("stun.border.label"))); - add(stunPanel); - - JLabel stunServer = new JLabel(Res.getString("stun.server.addr")); - JLabel stunPort = new JLabel(Res.getString("stun.server.port")); - - - _stunServerInput.setPreferredSize(new Dimension(120, 20)); - _stunPortInput.setPreferredSize(new Dimension(120, 20)); - - stunPanel.add(stunServer, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); - stunPanel.add(_stunServerInput, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); - stunPanel.add(stunPort, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); - stunPanel.add(_stunPortInput, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); - } - - public String getAudioDevice() { - if (audioDevice.getSelectedIndex() >= 0) { - return vectorAudioDevices.get(audioDevice.getSelectedIndex()).getLocator().toExternalForm(); - } - return ""; - } - - public void setAudioDevice(String device) { - AudioSystem audioSystem = ((MediaServiceImpl)LibJitsi.getMediaService()).getDeviceConfiguration().getAudioSystem(); - for ( CaptureDeviceInfo2 infoCaptureDevice : vectorAudioDevices) { - System.out.println(device); - if (infoCaptureDevice.getLocator().toExternalForm().equals(device)) { - audioDevice.setSelectedIndex(vectorAudioDevices.indexOf(infoCaptureDevice)); - audioSystem.setDevice(DataFlow.CAPTURE, infoCaptureDevice, true); - } - } - } - - public String getPlaybackDevice() { - if (playbackDevice.getSelectedIndex() >= 0) { - return vectorPlaybackDevices.get(playbackDevice.getSelectedIndex()).getLocator().toExternalForm(); - } - return ""; - } - - public void setPlaybackDevice(String device) { - AudioSystem audioSystem = ((MediaServiceImpl)LibJitsi.getMediaService()).getDeviceConfiguration().getAudioSystem(); - for ( CaptureDeviceInfo2 infoCaptureDevice : vectorPlaybackDevices) { - if (infoCaptureDevice.getLocator().toExternalForm().equals(device)) { - playbackDevice.setSelectedItem(infoCaptureDevice.getName()); - audioSystem.setDevice(DataFlow.PLAYBACK, infoCaptureDevice, true); - audioSystem.setDevice(DataFlow.NOTIFY , infoCaptureDevice, true); - } - } - } - - public String getAudioSystem() { - if (audioSystem.getSelectedIndex() >= 0) - { - return vectorAudioSystem.get(audioSystem.getSelectedIndex()).getLocatorProtocol(); - } - return null; - } - - public void setAudioSystem(String selectedAudioSystem) { - for (AudioSystem system : vectorAudioSystem) - { - if (system.getLocatorProtocol().equals(selectedAudioSystem)) - { - System.out.println("setAudioSystem:" + system); - audioSystem.setSelectedIndex(vectorAudioSystem.indexOf(system)); - ((MediaServiceImpl)LibJitsi.getMediaService()).getDeviceConfiguration().setAudioSystem(system, true); - } - } - System.out.println("AudioSystem:" + ((MediaServiceImpl)LibJitsi.getMediaService()).getDeviceConfiguration().getAudioSystem()); - } - - - public void setVideoDevice(String device) { - for ( CaptureDeviceInfo infoCaptureDevice : vectorVideoDevices) { - if (infoCaptureDevice != null && - infoCaptureDevice.getLocator().toExternalForm().equals(device)) { - videoDevice.setSelectedItem(infoCaptureDevice.getName()); - } - } - } - - public String getVideoDevice() { - if (videoDevice.getSelectedIndex() >= 0) { - if (vectorVideoDevices.get(videoDevice.getSelectedIndex()) == null) { - return ""; - } - return vectorVideoDevices.get(videoDevice.getSelectedIndex()).getLocator().toExternalForm(); - } - return ""; - } - - - public String getStunServer() { - return _stunServerInput.getText(); - } - - public void setStunServer(String server) { - this._stunServerInput.setText(server); - } - - public int getStunPort() { - return Integer.valueOf(_stunPortInput.getText()); - } - - public void setStunPort(int port) { - - this._stunPortInput.setText(String.valueOf(port)); - } - - - - /** - * Logs the audio devices - */ - public void logAudioDevices() { - @SuppressWarnings("unchecked") - final Vector vectorDevices = CaptureDeviceManager.getDeviceList(null); - - for (CaptureDeviceInfo infoCaptureDevice : vectorDevices) { - System.err.println(convertSysString(infoCaptureDevice.getName())); - for (Format format : infoCaptureDevice.getFormats()) { - System.err.println(" " + format); - } - } - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationAlertUI.java b/src/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationAlertUI.java deleted file mode 100644 index b82e376c5..000000000 --- a/src/java/org/jivesoftware/sparkimpl/preference/notifications/NotificationAlertUI.java +++ /dev/null @@ -1,261 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 1999-2010 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.preference.notifications; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smackx.vcardtemp.packet.VCard; -import org.jivesoftware.spark.PresenceManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; - -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import java.awt.Color; -import java.awt.Font; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.RenderingHints; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.image.BufferedImage; - -public class NotificationAlertUI extends JPanel { - private static final long serialVersionUID = 3359608942567718697L; - private JLabel avatarLabel = new JLabel(); - private JLabel titleLabel = new JLabel(); - private JLabel emailAddressLabel = new JLabel(); - private JLabel professionLabel = new JLabel(); - - private VCard vcard; - private String jid; - - private boolean available; - - final JLabel topLabel = new JLabel(); - - private static final int AVATAR_HEIGHT = 64; - private static final int AVATAR_WIDTH = 64; - - public NotificationAlertUI(String jid, boolean available, Presence presence) { - setLayout(new GridBagLayout()); - - this.available = available; - this.jid = XmppStringUtils.parseBareJid(jid); - - vcard = SparkManager.getVCardManager().getVCardFromMemory(XmppStringUtils.parseBareJid(jid)); - - final Icon presenceIcon = PresenceManager.getIconFromPresence(presence); - - topLabel.setIcon(presenceIcon); - topLabel.setHorizontalTextPosition(JLabel.RIGHT); - topLabel.setFont(new Font("Dialog", Font.BOLD, 15)); - topLabel.setForeground(Color.DARK_GRAY); - - // Add Calller Block - buildInnerBlock(); - } - - - /** - * Builds the part of the incoming call UI with the Callers information. - */ - private void buildInnerBlock() { - final JPanel panel = new JPanel(new GridBagLayout()); - panel.setBackground(Color.white); - panel.setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230), 1)); - - titleLabel.setHorizontalTextPosition(JLabel.RIGHT); - - // Add Avatar - panel.add(avatarLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 15, 5, 0), 0, 0)); - - // Add Avatar information - panel.add(titleLabel, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(10, 5, 0, 0), 0, 0)); - panel.add(professionLabel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 0, 0), 0, 0)); - panel.add(emailAddressLabel, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 0, 0), 0, 0)); - - // Set default settings - titleLabel.setForeground(new Color(64, 103, 162)); - titleLabel.setFont(new Font("Dialog", Font.BOLD, 16)); - - - if (vcard != null) { - handleVCardInformation(vcard); - } - else { - updateWithGenericInfo(); - } - - // Add to panel - add(panel, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - } - - - private void updateWithGenericInfo() { - String title = SparkManager.getUserManager().getUserNicknameFromJID(jid); - - titleLabel.setText(title); - - avatarLabel.setIcon(SparkRes.getImageIcon(SparkRes.DEFAULT_AVATAR_64x64_IMAGE)); - avatarLabel.invalidate(); - avatarLabel.validate(); - avatarLabel.repaint(); - - - invalidate(); - validate(); - repaint(); - } - - private void handleVCardInformation(VCard vcard) { - if (vcard.getError() != null) { - updateWithGenericInfo(); - return; - } - - // Nickname label should show presence and nickname. - String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid); - - String firstName = vcard.getFirstName(); - String lastName = vcard.getLastName(); - if (ModelUtil.hasLength(firstName) && ModelUtil.hasLength(lastName)) { - titleLabel.setText(firstName + " " + lastName); - } - else if (ModelUtil.hasLength(firstName)) { - titleLabel.setText(firstName); - } - else { - titleLabel.setText(nickname); - } - - final StringBuilder builder = new StringBuilder(); - - String username = titleLabel.getText(); - builder.append(username); - builder.append(" is "); - - builder.append(available ? "Online" : "Offline"); - topLabel.setText(builder.toString()); - - String jobTitle = vcard.getField("TITLE"); - if (jobTitle != null) { - professionLabel.setText(jobTitle); - } - - String emailAddress = vcard.getEmailHome(); - if (ModelUtil.hasLength(emailAddress)) { - emailAddressLabel.setText(emailAddress); - - final Color linkColor = new Color(49, 89, 151); - final String unselectedText = "" + emailAddress + ""; - final String hoverText = "" + emailAddress + ""; - emailAddressLabel.addMouseListener(new MouseAdapter() { - public void mouseEntered(MouseEvent e) { - emailAddressLabel.setText(hoverText); - } - - public void mouseExited(MouseEvent e) { - emailAddressLabel.setText(unselectedText); - } - }); - } - - byte[] avatarBytes = null; - try { - avatarBytes = vcard.getAvatar(); - } - catch (Exception e) { - Log.error("Cannot retrieve avatar bytes.", e); - } - - if (avatarBytes != null) { - try { - ImageIcon avatarIcon = new ImageIcon(avatarBytes); - - int w = avatarIcon.getIconWidth(); - int h = avatarIcon.getIconHeight(); - Double ratio = (double)w / (double)h; - if ( w > 120 || h > 120) - { - if ( w > h) - { - w = 120; - h = (int)(w/ratio); - }else - { - h = 120; - w = (int)(h*ratio); - } - } - - BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); - Graphics2D g2 = resizedImg.createGraphics(); - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - g2.drawImage(avatarIcon.getImage(), 0, 0, w, h, null); - g2.dispose(); - - avatarIcon = new ImageIcon(resizedImg); - - avatarLabel.setIcon(GraphicUtils.scale(avatarIcon, AVATAR_HEIGHT, AVATAR_WIDTH)); - - } - catch (Exception e) { - // no issue - } - } - else { - avatarLabel.setIcon(SparkRes.getImageIcon(SparkRes.DEFAULT_AVATAR_64x64_IMAGE)); - } - - avatarLabel.invalidate(); - avatarLabel.validate(); - avatarLabel.repaint(); - - invalidate(); - validate(); - repaint(); - } - - public void paintComponent(Graphics g) { - BufferedImage cache = new BufferedImage(2, getHeight(), BufferedImage.TYPE_INT_RGB); - Graphics2D g2d = cache.createGraphics(); - - GradientPaint paint = new GradientPaint(0, 0, new Color(233, 240, 247), 0, getHeight(), Color.white, true); - - g2d.setPaint(paint); - g2d.fillRect(0, 0, getWidth(), getHeight()); - g2d.dispose(); - - g.drawImage(cache, 0, 0, getWidth(), getHeight(), null); - } -} - diff --git a/src/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPlugin.java b/src/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPlugin.java deleted file mode 100644 index cad5c27b9..000000000 --- a/src/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPlugin.java +++ /dev/null @@ -1,135 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkimpl.preference.sounds; - -import java.io.File; - -import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smackx.delay.packet.DelayInformation; -import org.jivesoftware.smackx.muc.MultiUserChatManager; -import org.jivesoftware.spark.PresenceManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomListener; -import org.jivesoftware.spark.ui.MessageListener; -import org.jivesoftware.spark.util.TaskEngine; - -public class SoundPlugin implements Plugin, MessageListener, ChatRoomListener { - SoundPreference soundPreference; - - public void initialize() { - soundPreference = new SoundPreference(); - SparkManager.getPreferenceManager().addPreference(soundPreference); - - SparkManager.getChatManager().addChatRoomListener(this); - - SparkManager.getConnection().addAsyncStanzaListener( stanza -> { - Presence presence = (Presence)stanza; - if (!presence.isAvailable()) { - SoundPreferences preferences = soundPreference.getPreferences(); - if (preferences != null && preferences.isPlayOfflineSound()) { - if (!PresenceManager.isOnline(presence.getFrom())) { - String offline = preferences.getOfflineSound(); - File offlineFile = new File(offline); - SparkManager.getSoundManager().playClip(offlineFile); - } - } - } - }, new StanzaTypeFilter(Presence.class)); - - // Load sound preferences. - final Runnable soundLoader = () -> soundPreference.loadFromFile(); - - TaskEngine.getInstance().submit(soundLoader); - - MultiUserChatManager.getInstanceFor(SparkManager.getConnection()).addInvitationListener( ( xmppConnection, muc, string1, string2, string3, message ) -> { - SoundPreferences preferences = soundPreference.getPreferences(); - if (preferences != null && preferences.playIncomingInvitationSound()) { - String incomingSoundFile = preferences.getIncomingInvitationSoundFile(); - File offlineFile = new File(incomingSoundFile); - SparkManager.getSoundManager().playClip(offlineFile); - } - } ); - - } - - public void messageReceived(ChatRoom room, Message message) { - - // Do not play sounds on history updates. - DelayInformation inf = message.getExtension("delay", "urn:xmpp:delay"); - if (inf != null) { - return; - } - - SoundPreferences preferences = soundPreference.getPreferences(); - if (preferences.isPlayIncomingSound()) { - File incomingFile = new File(preferences.getIncomingSound()); - SparkManager.getSoundManager().playClip(incomingFile); - } - } - - public void messageSent(ChatRoom room, Message message) { - SoundPreferences preferences = soundPreference.getPreferences(); - if (preferences.isPlayOutgoingSound()) { - File outgoingFile = new File(preferences.getOutgoingSound()); - SparkManager.getSoundManager().playClip(outgoingFile); - } - } - - public void shutdown() { - - } - - public boolean canShutDown() { - return false; - } - - public void chatRoomOpened(ChatRoom room) { - room.addMessageListener(this); - } - - public void chatRoomLeft(ChatRoom room) { - - } - - public void chatRoomClosed(ChatRoom room) { - room.removeMessageListener(this); - } - - public void chatRoomActivated(ChatRoom room) { - - } - - public void userHasJoined(ChatRoom room, String userid) { - - } - - public void userHasLeft(ChatRoom room, String userid) { - - } - - public void uninstall() { - // Do nothing. - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPreference.java b/src/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPreference.java deleted file mode 100644 index 9fce4bd41..000000000 --- a/src/java/org/jivesoftware/sparkimpl/preference/sounds/SoundPreference.java +++ /dev/null @@ -1,374 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkimpl.preference.sounds; - -import java.awt.EventQueue; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; - -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComponent; -import javax.swing.JFileChooser; -import javax.swing.JPanel; -import javax.swing.JTextField; - -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.preference.Preference; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.WindowsFileSystemView; -import org.jivesoftware.spark.util.log.Log; - -import com.thoughtworks.xstream.XStream; - -/** - * Preferences to handle Sounds played within Spark. - * - * @author Derek DeMoro - */ -public class SoundPreference implements Preference { - - private XStream xstream; - private SoundPreferences preferences; - private SoundPanel soundPanel; - - public static String NAMESPACE = "Sounds"; - - public SoundPreference() { - - } - - - public String getTitle() { - return Res.getString("title.sound.preferences"); - } - - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.SOUND_PREFERENCES_IMAGE); - } - - public String getTooltip() { - return Res.getString("title.sounds"); - } - - public String getListName() { - return Res.getString("title.sounds"); - } - - public String getNamespace() { - return NAMESPACE; - } - - public JComponent getGUI() { - if (soundPanel == null) { - try { - EventQueue.invokeAndWait( () -> soundPanel = new SoundPanel() ); - } catch (Exception e) { - e.printStackTrace(); - } - - } - return soundPanel; - } - - public void loadFromFile() { - if (preferences != null) { - return; - } - - if (!getSoundSettingsFile().exists()) { - preferences = new SoundPreferences(); - } - else { - - // Do Initial Load from FileSystem. - File settingsFile = getSoundSettingsFile(); - try { - FileReader reader = new FileReader(settingsFile); - preferences = (SoundPreferences)getXStream().fromXML(reader); - } - catch (Exception e) { - Log.error("Error loading Sound Preferences.", e); - preferences = new SoundPreferences(); - } - } - } - - public void load() { - if (soundPanel == null) { - soundPanel = new SoundPanel(); - } - - SwingWorker worker = new SwingWorker() { - public Object construct() { - loadFromFile(); - return preferences; - } - - public void finished() { - // Set default settings - soundPanel.setIncomingMessageSound(preferences.getIncomingSound()); - soundPanel.playIncomingSound(preferences.isPlayIncomingSound()); - - soundPanel.setOutgoingMessageSound(preferences.getOutgoingSound()); - soundPanel.playOutgoingSound(preferences.isPlayOutgoingSound()); - - soundPanel.setOfflineSound(preferences.getOfflineSound()); - soundPanel.playOfflineSound(preferences.isPlayOfflineSound()); - - soundPanel.setInvitationSound(preferences.getIncomingInvitationSoundFile()); - soundPanel.setPlayInvitationSound(preferences.playIncomingInvitationSound()); - } - }; - worker.start(); - } - - public void commit() { - preferences.setIncomingSound(soundPanel.getIncomingSound()); - preferences.setOutgoingSound(soundPanel.getOutgoingSound()); - - preferences.setOfflineSound(soundPanel.getOfflineSound()); - preferences.setPlayOfflineSound(soundPanel.playOfflineSound()); - - preferences.setPlayIncomingSound(soundPanel.playIncomingSound()); - preferences.setPlayOutgoingSound(soundPanel.playOutgoingSound()); - - preferences.setIncomingInvitationSoundFile(soundPanel.getInvitationSound()); - preferences.setPlayIncomingInvitationSound(soundPanel.playInvitationSound()); - - saveSoundsFile(); - } - - public boolean isDataValid() { - return true; - } - - public String getErrorMessage() { - return null; - } - - public Object getData() { - return null; - } - - - private class SoundPanel extends JPanel { - private static final long serialVersionUID = 4332294589601051699L; - private final JCheckBox incomingMessageBox = new JCheckBox(); - private final JTextField incomingMessageSound = new JTextField(); - private final JButton incomingBrowseButton = new JButton(".."); - - private final JCheckBox outgoingMessageBox = new JCheckBox(); - private final JTextField outgoingMessageSound = new JTextField(); - private final JButton outgoingBrowseButton = new JButton(".."); - - private final JCheckBox userOfflineCheckbox = new JCheckBox(); - private final JTextField userOfflineField = new JTextField(); - private final JButton offlineBrowseButton = new JButton(".."); - - private final JCheckBox incomingInvitationBox = new JCheckBox(); - private final JTextField incomingInvitationField = new JTextField(); - private final JButton incomingInvitationBrowseButton = new JButton(".."); - private JFileChooser fc; - - - public SoundPanel() { - setLayout(new GridBagLayout()); - - setBorder(BorderFactory.createTitledBorder(Res.getString("title.sound.preferences"))); - // Add ResourceUtils - ResourceUtils.resButton(incomingMessageBox, Res.getString("checkbox.play.sound.on.new.message")); - ResourceUtils.resButton(outgoingMessageBox, Res.getString("checkbox.play.sound.on.outgoing.message")); - ResourceUtils.resButton(userOfflineCheckbox, Res.getString("checkbox.play.sound.when.offline")); - ResourceUtils.resButton(incomingInvitationBox, Res.getString("checkbox.play.sound.on.invitation")); - - // Handle incoming sounds - add(incomingMessageBox, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(incomingMessageSound, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - add(incomingBrowseButton, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - // Handle sending sounds - add(outgoingMessageBox, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(outgoingMessageSound, new GridBagConstraints(0, 3, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - add(outgoingBrowseButton, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - // Handle User Online Sound - add(userOfflineCheckbox, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(userOfflineField, new GridBagConstraints(0, 5, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - add(offlineBrowseButton, new GridBagConstraints(1, 5, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - // Handle Invitation Sound - add(incomingInvitationBox, new GridBagConstraints(0, 6, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(incomingInvitationField, new GridBagConstraints(0, 7, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - add(incomingInvitationBrowseButton, new GridBagConstraints(1, 7, 1, 1, 0.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - incomingBrowseButton.addActionListener( e -> pickFile(Res.getString("title.choose.incoming.sound"), incomingMessageSound) ); - - - outgoingBrowseButton.addActionListener( e -> pickFile(Res.getString("title.choose.outgoing.sound"), outgoingMessageSound) ); - - offlineBrowseButton.addActionListener( e -> pickFile(Res.getString("title.choose.offline.sound"), userOfflineField) ); - - incomingInvitationBrowseButton.addActionListener( e -> pickFile(Res.getString("title.choose.incoming.sound"), incomingInvitationField) ); - - - } - - public void setIncomingMessageSound(String path) { - incomingMessageSound.setText(path); - } - - public void setOutgoingMessageSound(String path) { - outgoingMessageSound.setText(path); - } - - public void setOfflineSound(String path) { - userOfflineField.setText(path); - } - - public void playIncomingSound(boolean play) { - incomingMessageBox.setSelected(play); - } - - public void playOutgoingSound(boolean play) { - outgoingMessageBox.setSelected(play); - } - - public void playOfflineSound(boolean play) { - userOfflineCheckbox.setSelected(play); - } - - - public String getIncomingSound() { - return incomingMessageSound.getText(); - } - - public boolean playIncomingSound() { - return incomingMessageBox.isSelected(); - } - - public boolean playOutgoingSound() { - return outgoingMessageBox.isSelected(); - } - - public String getOutgoingSound() { - return outgoingMessageSound.getText(); - } - - public boolean playOfflineSound() { - return userOfflineCheckbox.isSelected(); - } - - public String getOfflineSound() { - return userOfflineField.getText(); - } - - public void setInvitationSound(String invitationSound) { - incomingInvitationField.setText(invitationSound); - } - - public String getInvitationSound() { - return incomingInvitationField.getText(); - } - - public void setPlayInvitationSound(boolean play) { - incomingInvitationBox.setSelected(play); - } - - public boolean playInvitationSound() { - return incomingInvitationBox.isSelected(); - } - - - private void pickFile(String title, JTextField field) { - if (fc == null) { - fc = new JFileChooser(); - if (Spark.isWindows()) { - fc.setFileSystemView(new WindowsFileSystemView()); - } - } - fc.setDialogTitle(title); - int returnVal = fc.showOpenDialog(this); - - if (returnVal == JFileChooser.APPROVE_OPTION) { - File file = fc.getSelectedFile(); - try { - field.setText(file.getCanonicalPath()); - } - catch (IOException e) { - Log.error(e); - } - } - else { - - } - } - - } - - private File getSoundSettingsFile() { - File file = new File(Spark.getSparkUserHome()); - if (!file.exists()) { - file.mkdirs(); - } - return new File(file, "sound-settings.xml"); - } - - private void saveSoundsFile() { - try { - FileWriter writer = new FileWriter(getSoundSettingsFile()); - getXStream().toXML(preferences, writer); - } - catch (Exception e) { - Log.error("Error saving sound settings.", e); - } - } - - public SoundPreferences getPreferences() { - if (preferences == null) { - load(); - } - return preferences; - } - - public void shutdown() { - - } - - private XStream getXStream() { - if (xstream == null) { - xstream = new XStream(); - xstream.alias("sounds", SoundPreferences.class); - } - return xstream; - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/profile/AvatarPanel.java b/src/java/org/jivesoftware/sparkimpl/profile/AvatarPanel.java deleted file mode 100644 index fad90a20f..000000000 --- a/src/java/org/jivesoftware/sparkimpl/profile/AvatarPanel.java +++ /dev/null @@ -1,301 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.profile; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.URLFileSystem; -import org.jivesoftware.spark.util.log.Log; - -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.UIManager; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Dialog; -import java.awt.FileDialog; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Image; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; - -/** - * UI to view/edit avatar. - */ -public class AvatarPanel extends JPanel implements ActionListener { - private static final long serialVersionUID = -5526978906063691519L; - private JLabel avatar; - private byte[] bytes; - private File avatarFile; - final JButton browseButton = new JButton(); - final JButton clearButton = new JButton(); - private FileDialog fileChooser; - - private Dialog dlg; - - /** - * Default Constructor - */ - public AvatarPanel() { - setLayout(new GridBagLayout()); - - - final JLabel photo = new JLabel(Res.getString("label.avatar")); - - avatar = new JLabel(); - - add(photo, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(avatar, new GridBagConstraints(1, 0, 1, 2, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(browseButton, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(clearButton, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - browseButton.addActionListener(this); - - // Add ResourceUtils - ResourceUtils.resButton(browseButton, Res.getString("button.browse")); - ResourceUtils.resButton(clearButton, Res.getString("button.clear")); - - clearButton.addActionListener( actionEvent -> { - avatar.setIcon(null); - bytes = null; - avatarFile = null; - avatar.setBorder(null); - } ); - - avatar.setText(Res.getString("message.no.avatar.found")); - - GraphicUtils.makeSameSize(browseButton, clearButton); - } - - /** - * Sets if the Avatar can be edited. - * - * @param editable true if edtiable. - */ - public void setEditable(boolean editable) { - browseButton.setVisible(editable); - clearButton.setVisible(editable); - } - - /** - * Sets the displayable icon with the users avatar. - * - * @param icon the icon. - */ - public void setAvatar(ImageIcon icon) { - avatar.setBorder(BorderFactory.createBevelBorder(0, Color.white, Color.lightGray)); - if (icon.getIconHeight() > 128 || icon.getIconWidth() > 128) { - avatar.setIcon(new ImageIcon(icon.getImage().getScaledInstance(-1, 128, Image.SCALE_SMOOTH))); - } - else { - avatar.setIcon(icon); - } - avatar.setText(""); - } - - /** - * Sets the avatar bytes. - * - * @param bytes the bytes. - */ - public void setAvatarBytes(byte[] bytes) { - this.bytes = bytes; - } - - /** - * Returns the avatars bytes. - * - * @return the bytes. - */ - public byte[] getAvatarBytes() { - return bytes; - } - - /** - * Returns the Icon representation of the Avatar. - * - * @return Icon of avatar. - */ - public Icon getAvatar() { - return avatar.getIcon(); - } - - /** - * Returns the image file to use as the avatar. - * - * @return File of avatar. - */ - public File getAvatarFile() { - return avatarFile; - } - - public void actionPerformed(ActionEvent e) { - // init file chooser (if not already done) - initFileChooser(); - - fileChooser.setVisible(true); - - if (fileChooser.getDirectory() != null && fileChooser.getFile() != null) { - File file = new File(fileChooser.getDirectory(), fileChooser.getFile()); - String suffix = URLFileSystem.getSuffix(file); - if (suffix.toLowerCase().equals(".jpeg") || - suffix.toLowerCase().equals(".gif") || - suffix.toLowerCase().equals(".jpg") || - suffix.toLowerCase().equals(".png")) { - changeAvatar(file, this); - } - else { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(this, "Please choose a valid image file.", Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - } - - - } - } - - private void changeAvatar(final File selectedFile, final Component parent) { - SwingWorker worker = new SwingWorker() { - public Object construct() { - try { - ImageIcon imageOnDisk = new ImageIcon(selectedFile.getCanonicalPath()); - Image avatarImage = imageOnDisk.getImage(); - if (avatarImage.getHeight(null) > 128 || avatarImage.getWidth(null) > 128) { - avatarImage = avatarImage.getScaledInstance(-1, 128, Image.SCALE_SMOOTH); - } - return avatarImage; - } - catch (IOException ex) { - Log.error(ex); - } - return null; - } - - public void finished() { - Image avatarImage = (Image)get(); - - /* - // Check size. - long length = GraphicUtils.getBytesFromImage(avatarImage).length * 8; - - long k = 8192; - - long actualSize = (length / k) + 1; - - if (actualSize > 16) { - // Do not allow - JOptionPane.showMessageDialog(parent, Res.getString("message.image.too.large")); - return; - } - */ - setAvatar(new ImageIcon(avatarImage)); - avatarFile = selectedFile; - } - }; - - worker.start(); - } - - public class ImageFilter implements FilenameFilter { - public final String jpeg = "jpeg"; - public final String jpg = "jpg"; - public final String gif = "gif"; - public final String png = "png"; - - //Accept all directories and all gif, jpg, tiff, or png files. - public boolean accept(File f, String string) { - if (f.isDirectory()) { - return true; - } - - String extension = getExtension(f); - if (extension != null) { - if (extension.equals(gif) || extension.equals(jpeg) ||extension.equals(jpg) || extension.equals(png)) { - return true; - } - else { - return false; - } - } - - return false; - } - - /* - * Get the extension of a file. - */ - public String getExtension(File f) { - String ext = null; - String s = f.getName(); - int i = s.lastIndexOf('.'); - - if (i > 0 && i < s.length() - 1) { - ext = s.substring(i + 1).toLowerCase(); - } - return ext; - } - - //The description of this filter - public String getDescription() { - return "*.JPEG, *.GIF, *.PNG"; - } - } - - public void allowEditing(boolean allowEditing) { - Component[] comps = getComponents(); - if (comps != null) { - final int no = comps.length; - for (int i = 0; i < no; i++) { - Component comp = comps[i]; - if (comp instanceof JTextField) { - ((JTextField)comp).setEditable(allowEditing); - } - } - } - } - - public void initFileChooser() { - if (fileChooser == null) { - fileChooser = new FileDialog(dlg, "Choose Avatar", FileDialog.LOAD); - fileChooser.setFilenameFilter(new ImageFilter()); - } - } - - public void setParentDialog(Dialog dialog) { - this.dlg = dialog; - } - - -} - - diff --git a/src/java/org/jivesoftware/sparkimpl/profile/VCardEditor.java b/src/java/org/jivesoftware/sparkimpl/profile/VCardEditor.java deleted file mode 100644 index 6fb085172..000000000 --- a/src/java/org/jivesoftware/sparkimpl/profile/VCardEditor.java +++ /dev/null @@ -1,499 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkimpl.profile; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Image; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.File; - -import javax.swing.BorderFactory; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTabbedPane; -import javax.swing.UIManager; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smackx.vcardtemp.packet.VCard; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.TitlePanel; -import org.jivesoftware.spark.ui.VCardViewer; -import org.jivesoftware.spark.ui.status.StatusBar; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.log.Log; - -/** - * Handles the UI for viewing and editing of VCard information. - */ -public class VCardEditor { - - private BusinessPanel businessPanel; - private PersonalPanel personalPanel; - private HomePanel homePanel; - private AvatarPanel avatarPanel; - private JLabel avatarLabel; - //TODO REMOVE - @SuppressWarnings("unused") - private VCard _vcard; - - /** - * Displays the VCard for an individual. - * - * @param vCard - * the users vcard. - * @param parent - * the parent component, used for location. - */ - public void editProfile(final VCard vCard, JComponent parent) { - final JTabbedPane tabbedPane = new JTabbedPane(); - - // Initialize Panels - personalPanel = new PersonalPanel(); - personalPanel.showJID(false); - - tabbedPane.addTab(Res.getString("tab.personal"), personalPanel); - - businessPanel = new BusinessPanel(); - tabbedPane.addTab(Res.getString("tab.business"), businessPanel); - - homePanel = new HomePanel(); - tabbedPane.addTab(Res.getString("tab.home"), homePanel); - - avatarPanel = new AvatarPanel(); - tabbedPane.addTab(Res.getString("tab.avatar"), avatarPanel); - - // Build the UI - buildUI(vCard); - - final JOptionPane pane; - final JDialog dlg; - - TitlePanel titlePanel; - - ImageIcon icon = VCardManager.getAvatarIcon(vCard); - if (icon == null) { - icon = SparkRes.getImageIcon(SparkRes.BLANK_24x24); - } - - // Create the title panel for this dialog - titlePanel = new TitlePanel(Res.getString("title.edit.profile"), - Res.getString("message.save.profile"), icon, true); - - // Construct main panel w/ layout. - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(titlePanel, BorderLayout.NORTH); - - // The user should only be able to close this dialog. - Object[] options = { Res.getString("save"), Res.getString("cancel") }; - pane = new JOptionPane(tabbedPane, JOptionPane.PLAIN_MESSAGE, - JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); - - mainPanel.add(pane, BorderLayout.CENTER); - - JOptionPane p = new JOptionPane(); - dlg = p.createDialog(parent, Res.getString("title.profile.information")); - dlg.setModal(false); - - dlg.pack(); - dlg.setSize(600, 400); - dlg.setResizable(true); - dlg.setContentPane(mainPanel); - dlg.setLocationRelativeTo(parent); - - PropertyChangeListener changeListener = new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent e) { - String value = (String) pane.getValue(); - if (Res.getString("cancel").equals(value)) { - pane.removePropertyChangeListener(this); - dlg.dispose(); - } else if (Res.getString("save").equals(value)) { - pane.removePropertyChangeListener(this); - dlg.dispose(); - saveVCard(); - } - } - }; - - pane.addPropertyChangeListener(changeListener); - avatarPanel.setParentDialog(dlg); - dlg.setVisible(true); - dlg.toFront(); - dlg.requestFocus(); - - personalPanel.focus(); - } - - /** - * Displays the VCard for an individual. - * - * @param vCard - * the users vcard. - * @param parent - * the parent component, used for location. - */ - public void viewFullProfile(final VCard vCard, JComponent parent) { - final JTabbedPane tabbedPane = new JTabbedPane(); - - // Initialize Panels - personalPanel = new PersonalPanel(); - personalPanel.allowEditing(false); - personalPanel.showJID(false); - - tabbedPane.addTab(Res.getString("tab.personal"), personalPanel); - - businessPanel = new BusinessPanel(); - businessPanel.allowEditing(false); - tabbedPane.addTab(Res.getString("tab.business"), businessPanel); - - homePanel = new HomePanel(); - homePanel.allowEditing(false); - tabbedPane.addTab(Res.getString("tab.home"), homePanel); - - avatarPanel = new AvatarPanel(); - avatarPanel.allowEditing(false); - tabbedPane.addTab(Res.getString("tab.avatar"), avatarPanel); - - // Build the UI - buildUI(vCard); - - final JOptionPane pane; - final JDialog dlg; - - TitlePanel titlePanel; - - ImageIcon icon = VCardManager.getAvatarIcon(vCard); - if (icon == null) { - icon = SparkRes.getImageIcon(SparkRes.BLANK_24x24); - } - - // Create the title panel for this dialog - titlePanel = new TitlePanel(Res.getString("title.profile.information"), - "", icon, true); - - // Construct main panel w/ layout. - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(titlePanel, BorderLayout.NORTH); - - // The user should only be able to close this dialog. - Object[] options = { Res.getString("close"), Res.getString("refresh") }; - pane = new JOptionPane(tabbedPane, JOptionPane.PLAIN_MESSAGE, - JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); - - mainPanel.add(pane, BorderLayout.CENTER); - - JOptionPane p = new JOptionPane(); - dlg = p.createDialog(parent, Res.getString("title.profile.information")); - dlg.setModal(false); - - dlg.pack(); - dlg.setSize(600, 400); - dlg.setResizable(true); - dlg.setContentPane(mainPanel); - dlg.setLocationRelativeTo(parent); - PropertyChangeListener changeListener = new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent e) { - Object o = pane.getValue(); - if (o instanceof Integer) { - pane.removePropertyChangeListener(this); - dlg.dispose(); - return; - } - - String value = (String) pane.getValue(); - if (Res.getString("close").equals(value)) { - pane.removePropertyChangeListener(this); - dlg.dispose(); - } - - if (Res.getString("refresh").equals(value)) { - VCardManager manager = SparkManager.getVCardManager(); - VCard card = manager.reloadVCard(vCard.getJabberId()); - fillUI(card); - } - - } - }; - - pane.addPropertyChangeListener(changeListener); - - dlg.setVisible(true); - dlg.toFront(); - dlg.requestFocus(); - - personalPanel.focus(); - } - - /** - * Displays a users profile. - * - * @param jid - * the jid of the user. - * @param vcard - * the users vcard. - * @param parent - * the parent component, used for location handling. - */ - public void displayProfile(final String jid, VCard vcard, JComponent parent) { - VCardViewer viewer = new VCardViewer(jid); - - final JFrame dlg = new JFrame(Res.getString("title.view.profile.for", - jid)); - - avatarLabel = new JLabel(); - avatarLabel.setHorizontalAlignment(JButton.RIGHT); - avatarLabel.setBorder(BorderFactory.createBevelBorder(0, Color.white, - Color.lightGray)); - - // The user should only be able to close this dialog. - Object[] options = { Res.getString("button.view.profile"), - Res.getString("close") }; - final JOptionPane pane = new JOptionPane(viewer, - JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, - options, options[0]); - - // mainPanel.add(pane, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, - // GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, - // 5, 5), 0, 0)); - - dlg.setIconImage(SparkRes.getImageIcon(SparkRes.PROFILE_IMAGE_16x16) - .getImage()); - - dlg.pack(); - dlg.setSize(350, 250); - dlg.setResizable(true); - dlg.setContentPane(pane); - dlg.setLocationRelativeTo(parent); - - PropertyChangeListener changeListener = new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent e) { - if (pane.getValue() instanceof Integer) { - pane.removePropertyChangeListener(this); - dlg.dispose(); - return; - } - String value = (String) pane.getValue(); - if (Res.getString("close").equals(value)) { - pane.removePropertyChangeListener(this); - dlg.dispose(); - } else if (Res.getString("button.view.profile").equals(value)) { - pane.setValue(JOptionPane.UNINITIALIZED_VALUE); - SparkManager.getVCardManager().viewFullProfile(jid, pane); - } - } - }; - - pane.addPropertyChangeListener(changeListener); - - dlg.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent keyEvent) { - if (keyEvent.getKeyChar() == KeyEvent.VK_ESCAPE) { - dlg.dispose(); - } - } - }); - - dlg.setVisible(true); - dlg.toFront(); - dlg.requestFocus(); - } - - /** - * Builds the UI based on a VCard. - * - * @param vcard - * the vcard used to build the UI. - */ - private void buildUI(VCard vcard) { - - fillUI(vcard); - - // Set avatar - byte[] bytes = vcard.getAvatar(); - if (bytes != null && bytes.length > 0) { - ImageIcon icon = new ImageIcon(bytes); - avatarPanel.setAvatar(icon); - avatarPanel.setAvatarBytes(bytes); - if (avatarLabel != null) { - icon = GraphicUtils.scaleImageIcon(icon, 48, 48); - - avatarLabel.setIcon(icon); - } - } - } - - private void fillUI(VCard vcard){ - personalPanel.setFirstName(vcard.getFirstName()); - personalPanel.setMiddleName(vcard.getMiddleName()); - personalPanel.setLastName(vcard.getLastName()); - personalPanel.setEmailAddress(vcard.getEmailHome()); - personalPanel.setNickname(vcard.getNickName()); - personalPanel.setJID(vcard.getJabberId()); - - businessPanel.setCompany(vcard.getOrganization()); - businessPanel.setDepartment(vcard.getOrganizationUnit()); - businessPanel.setStreetAddress(vcard.getAddressFieldWork("STREET")); - businessPanel.setCity(vcard.getAddressFieldWork("LOCALITY")); - businessPanel.setState(vcard.getAddressFieldWork("REGION")); - businessPanel.setZipCode(vcard.getAddressFieldWork("PCODE")); - businessPanel.setCountry(vcard.getAddressFieldWork("CTRY")); - businessPanel.setJobTitle(vcard.getField("TITLE")); - businessPanel.setPhone(vcard.getPhoneWork("VOICE")); - businessPanel.setFax(vcard.getPhoneWork("FAX")); - businessPanel.setPager(vcard.getPhoneWork("PAGER")); - businessPanel.setMobile(vcard.getPhoneWork("CELL")); - businessPanel.setWebPage(vcard.getField("URL")); - - // Load Home Info - homePanel.setStreetAddress(vcard.getAddressFieldHome("STREET")); - homePanel.setCity(vcard.getAddressFieldHome("LOCALITY")); - homePanel.setState(vcard.getAddressFieldHome("REGION")); - homePanel.setZipCode(vcard.getAddressFieldHome("PCODE")); - homePanel.setCountry(vcard.getAddressFieldHome("CTRY")); - homePanel.setPhone(vcard.getPhoneHome("VOICE")); - homePanel.setFax(vcard.getPhoneHome("FAX")); - homePanel.setPager(vcard.getPhoneHome("PAGER")); - homePanel.setMobile(vcard.getPhoneHome("CELL")); - } - - - /** - * Saves the VCard. - */ - private void saveVCard() { - final VCard vcard = new VCard(); - - // Save personal info - vcard.setFirstName(personalPanel.getFirstName()); - vcard.setLastName(personalPanel.getLastName()); - vcard.setMiddleName(personalPanel.getMiddleName()); - vcard.setEmailHome(personalPanel.getEmailAddress()); - vcard.setNickName(personalPanel.getNickname()); - - // Save business info - vcard.setOrganization(businessPanel.getCompany()); - vcard.setAddressFieldWork("STREET", businessPanel.getStreetAddress()); - vcard.setAddressFieldWork("LOCALITY", businessPanel.getCity()); - vcard.setAddressFieldWork("REGION", businessPanel.getState()); - vcard.setAddressFieldWork("PCODE", businessPanel.getZipCode()); - vcard.setAddressFieldWork("CTRY", businessPanel.getCountry()); - vcard.setField("TITLE", businessPanel.getJobTitle()); - vcard.setOrganizationUnit(businessPanel.getDepartment()); - vcard.setPhoneWork("VOICE", businessPanel.getPhone()); - vcard.setPhoneWork("FAX", businessPanel.getFax()); - vcard.setPhoneWork("PAGER", businessPanel.getPager()); - vcard.setPhoneWork("CELL", businessPanel.getMobile()); - vcard.setField("URL", businessPanel.getWebPage()); - - // Save Home Info - vcard.setAddressFieldHome("STREET", homePanel.getStreetAddress()); - vcard.setAddressFieldHome("LOCALITY", homePanel.getCity()); - vcard.setAddressFieldHome("REGION", homePanel.getState()); - vcard.setAddressFieldHome("PCODE", homePanel.getZipCode()); - vcard.setAddressFieldHome("CTRY", homePanel.getCountry()); - vcard.setPhoneHome("VOICE", homePanel.getPhone()); - vcard.setPhoneHome("FAX", homePanel.getFax()); - vcard.setPhoneHome("PAGER", homePanel.getPager()); - vcard.setPhoneHome("CELL", homePanel.getMobile()); - - // Save Avatar - final File avatarFile = avatarPanel.getAvatarFile(); - byte[] avatarBytes = avatarPanel.getAvatarBytes(); - - if (avatarFile != null) { - avatarBytes = GraphicUtils.getBytesFromImage(avatarFile); - ImageIcon icon = new ImageIcon(avatarBytes); - Image image = icon.getImage(); - if (icon.getIconHeight() > 128 || icon.getIconWidth() > 128) { - image = image.getScaledInstance(-1, 128, Image.SCALE_SMOOTH); - } - - } - - // If avatar bytes, persist as vcard. - if (avatarBytes != null) { - vcard.setAvatar(avatarBytes); - } - - try { - final VCardManager vcardManager = SparkManager.getVCardManager(); - vcardManager.setPersonalVCard(vcard); - - vcard.save(SparkManager.getConnection()); - - // Notify users. - if (avatarFile != null || avatarBytes != null) { - Presence presence = SparkManager.getWorkspace().getStatusBar() - .getPresence(); - Presence newPresence = new Presence(presence.getType(), - presence.getStatus(), presence.getPriority(), - presence.getMode()); - - // Change my own presence - SparkManager.getSessionManager().changePresence(newPresence); - - // Chnage avatar in status bar. - StatusBar statusBar = SparkManager.getWorkspace() - .getStatusBar(); - statusBar.setAvatar(new ImageIcon(vcard.getAvatar())); - } else { - String firstName = vcard.getFirstName(); - String lastName = vcard.getLastName(); - StatusBar statusBar = SparkManager.getWorkspace() - .getStatusBar(); - if (ModelUtil.hasLength(firstName) - && ModelUtil.hasLength(lastName)) { - statusBar.setNickname(firstName + " " + lastName); - } else if (ModelUtil.hasLength(firstName)) { - statusBar.setNickname(firstName); - } - - statusBar.setAvatar(null); - } - - // Notify listenres - SparkManager.getVCardManager().notifyVCardListeners(); - } catch (XMPPException | SmackException e) { - Log.error(e); - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), - Res.getString("message.vcard.not.supported"), - Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - } - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/profile/VCardManager.java b/src/java/org/jivesoftware/sparkimpl/profile/VCardManager.java deleted file mode 100644 index 8f4ab623f..000000000 --- a/src/java/org/jivesoftware/sparkimpl/profile/VCardManager.java +++ /dev/null @@ -1,850 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.profile; - -import java.awt.Image; -import java.awt.image.BufferedImage; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.LinkedBlockingQueue; - -import javax.imageio.ImageIO; -import javax.swing.ImageIcon; -import javax.swing.JComponent; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.UIManager; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.StanzaListener; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.filter.StanzaFilter; -import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.packet.ExtensionElement; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.packet.XMPPError; -import org.jivesoftware.smack.provider.ProviderManager; -import org.jivesoftware.smackx.vcardtemp.packet.VCard; -import org.jivesoftware.smackx.vcardtemp.provider.VCardProvider; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.util.Base64; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.manager.Enterprise; -import org.jivesoftware.sparkimpl.profile.ext.JabberAvatarExtension; -import org.jivesoftware.sparkimpl.profile.ext.VCardUpdateExtension; -import org.jxmpp.util.XmppStringUtils; -import org.xmlpull.mxp1.MXParser; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -/** - * VCardManager handles all VCard loading/caching within Spark. - * - * @author Derek DeMoro - */ -public class VCardManager { - - private VCard personalVCard; - - private Map vcards = Collections.synchronizedMap( new HashMap<>()); - - private Set delayedContacts = Collections.synchronizedSet( new HashSet<>()); - - private boolean vcardLoaded; - - private File imageFile; - - private final VCardEditor editor; - - private File vcardStorageDirectory; - - final MXParser parser; - - private LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); - - private File contactsDir; - - private List listeners = new ArrayList<>(); - - private List writingQueue = Collections.synchronizedList( new ArrayList<>()); - - /** - * Initialize VCardManager. - */ - public VCardManager() { - - // Register providers - ProviderManager.addExtensionProvider( JabberAvatarExtension.ELEMENT_NAME, JabberAvatarExtension.NAMESPACE, new JabberAvatarExtension.Provider() ); - ProviderManager.addExtensionProvider( VCardUpdateExtension.ELEMENT_NAME, VCardUpdateExtension.NAMESPACE, new VCardUpdateExtension.Provider() ); - - // Initialize parser - parser = new MXParser(); - - try { - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - } - catch (XmlPullParserException e) { - Log.error(e); - } - - imageFile = new File(SparkManager.getUserDirectory(), "personal.png"); - - // Initialize vCard. - personalVCard = new VCard(); - - // Set VCard Storage - vcardStorageDirectory = new File(SparkManager.getUserDirectory(), "vcards"); - vcardStorageDirectory.mkdirs(); - - // Set the current user directory. - contactsDir = new File(SparkManager.getUserDirectory(), "contacts"); - contactsDir.mkdirs(); - - initializeUI(); - - // Intercept all presence packets being sent and append vcard information. - StanzaFilter presenceFilter = new StanzaTypeFilter(Presence.class); - SparkManager.getConnection().addPacketInterceptor( stanza -> { - Presence newPresence = (Presence)stanza; - VCardUpdateExtension update = new VCardUpdateExtension(); - JabberAvatarExtension jax = new JabberAvatarExtension(); - - ExtensionElement updateExt = newPresence.getExtension(update.getElementName(), update.getNamespace()); - ExtensionElement jabberExt = newPresence.getExtension(jax.getElementName(), jax.getNamespace()); - - if (updateExt != null) { - newPresence.removeExtension(updateExt); - } - - if (jabberExt != null) { - newPresence.removeExtension(jabberExt); - } - - if (personalVCard != null) { - byte[] bytes = personalVCard.getAvatar(); - if (bytes != null && bytes.length > 0) { - update.setPhotoHash(personalVCard.getAvatarHash()); - jax.setPhotoHash(personalVCard.getAvatarHash()); - - newPresence.addExtension(update); - newPresence.addExtension(jax); - } - } - }, presenceFilter); - - editor = new VCardEditor(); - - // Start Listener - startQueueListener(); - } - - /** - * Listens for new VCards to lookup in a queue. - */ - private void startQueueListener() { - final Runnable queueListener = () -> { - while (true) { - try { - String jid = queue.take(); - reloadVCard(jid); - } - catch (InterruptedException e) { - e.printStackTrace(); - break; - } - } - }; - - TaskEngine.getInstance().submit(queueListener); - - StanzaFilter filter = new StanzaTypeFilter(VCard.class); - StanzaListener myListener = stanza -> { - if (stanza instanceof VCard) - { - VCard VCardpacket = (VCard)stanza; - String jid = VCardpacket.getFrom(); - if (VCardpacket.getType().equals(IQ.Type.result) && jid != null && delayedContacts.contains(jid)) - { - delayedContacts.remove(jid); - addVCard(jid, VCardpacket); - persistVCard(jid, VCardpacket); - } - - } - }; - - SparkManager.getConnection().addAsyncStanzaListener(myListener, filter); - - } - - /** - * Adds a jid to lookup vCard. - * - * @param jid the jid to lookup. - */ - public void addToQueue(String jid) { - if (!queue.contains(jid)) { - queue.add(jid); - } - - } - - /** - * Adds VCard capabilities to menus and other components in Spark. - */ - private void initializeUI() { - boolean enabled = Enterprise.containsFeature(Enterprise.VCARD_FEATURE); - if (!enabled) { - return; - } - - // Add Actions Menu - final JMenu contactsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.contacts")); - final JMenu communicatorMenu = SparkManager.getMainWindow().getJMenuBar().getMenu(0); - - JMenuItem editProfileMenu = new JMenuItem(SparkRes.getImageIcon(SparkRes.SMALL_BUSINESS_MAN_VIEW)); - ResourceUtils.resButton(editProfileMenu, Res.getString("menuitem.edit.my.profile")); - - int size = contactsMenu.getMenuComponentCount(); - - communicatorMenu.insert(editProfileMenu, 1); - editProfileMenu.addActionListener( e -> { - SwingWorker vcardLoaderWorker = new SwingWorker() { - public Object construct() { - try { - personalVCard.load(SparkManager.getConnection()); - } - catch (XMPPException | SmackException e) { - Log.error("Error loading vcard information.", e); - } - return true; - } - - public void finished() { - editor.editProfile(personalVCard, SparkManager.getWorkspace()); - } - }; - vcardLoaderWorker.start(); - } ); - - JMenuItem viewProfileMenu = new JMenuItem("", SparkRes.getImageIcon(SparkRes.FIND_TEXT_IMAGE)); - ResourceUtils.resButton(viewProfileMenu, Res.getString("menuitem.lookup.profile")); - contactsMenu.insert(viewProfileMenu, size > 0 ? size - 1 : 0); - viewProfileMenu.addActionListener( e -> { - String jidToView = JOptionPane.showInputDialog(SparkManager.getMainWindow(), Res.getString("message.enter.jabber.id") + ":", Res.getString("title.lookup.profile"), JOptionPane.QUESTION_MESSAGE); - if (ModelUtil.hasLength(jidToView) && jidToView.contains( "@" ) && ModelUtil.hasLength( XmppStringUtils.parseDomain(jidToView))) { - viewProfile(jidToView, SparkManager.getWorkspace()); - } - else if (ModelUtil.hasLength(jidToView)) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), Res.getString("message.invalid.jabber.id"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE); - } - } ); - } - - - /** - * Displays VCardViewer for a particular JID. - * - * @param jid the jid of the user to display. - * @param parent the parent component to use for displaying dialog. - */ - public void viewProfile(final String jid, final JComponent parent) { - final SwingWorker vcardThread = new SwingWorker() { - VCard vcard = new VCard(); - - public Object construct() { - vcard = getVCard(jid); - return vcard; - } - - public void finished() { - if (vcard == null) { - // Show vcard not found - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(parent, Res.getString("message.unable.to.load.profile", jid), Res.getString("title.profile.not.found"), JOptionPane.ERROR_MESSAGE); - } - else { - editor.displayProfile(jid, vcard, parent); - } - } - }; - - vcardThread.start(); - - } - - /** - * Displays the full profile for a particular JID. - * - * @param jid the jid of the user to display. - * @param parent the parent component to use for displaying dialog. - */ - public void viewFullProfile(final String jid, final JComponent parent) { - final SwingWorker vcardThread = new SwingWorker() { - VCard vcard = new VCard(); - - public Object construct() { - vcard = getVCard(jid); - return vcard; - } - - public void finished() { - if (vcard.getError() != null || vcard == null) { - // Show vcard not found - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(parent, Res.getString("message.unable.to.load.profile", jid), Res.getString("title.profile.not.found"), JOptionPane.ERROR_MESSAGE); - } - else { - editor.viewFullProfile(vcard, parent); - } - } - }; - - vcardThread.start(); - - } - - /** - * Returns the VCard for this Spark user. This information will be cached after loading. - * - * @return this users VCard. - */ - public VCard getVCard() { - if (!vcardLoaded) { - reloadPersonalVCard(); - vcardLoaded = true; - } - return personalVCard; - } - - /** - * Loads the vcard for this Spark user - * @return this users VCard. - */ - public void reloadPersonalVCard() { - try { - personalVCard.load(SparkManager.getConnection()); - // If VCard is loaded, then save the avatar to the personal folder. - byte[] bytes = personalVCard.getAvatar(); - if (bytes != null && bytes.length > 0) { - ImageIcon icon = new ImageIcon(bytes); - icon = VCardManager.scale(icon); - if (icon != null && icon.getIconWidth() != -1) { - BufferedImage image = GraphicUtils.convert(icon.getImage()); - ImageIO.write(image, "PNG", imageFile); - } - } - } - catch (Exception e) { - personalVCard.setError(new XMPPError(XMPPError.Condition.conflict)); - Log.error(e); - } - } - - /** - * Returns the Avatar in the form of an ImageIcon. - * - * @param vcard the vCard containing the avatar. - * @return the ImageIcon or null if no avatar was present. - */ - public static ImageIcon getAvatarIcon(VCard vcard) { - // Set avatar - byte[] bytes = vcard.getAvatar(); - if (bytes != null && bytes.length > 0) { - ImageIcon icon = new ImageIcon(bytes); - return GraphicUtils.scaleImageIcon(icon, 40, 40); - } - return null; - } - - /** - * Returns the VCard. Will first look in VCard cache. You will receive a - * dummy vcard, if there is no vCard for specified jid in cache. Same as - * getVCard(jid, true) - * - * @param jid - * the users jid. - * @return the VCard. - */ - public VCard getVCard(String jid) { - return getVCard(jid, true); - } - - /** - * Loads the vCard from memory. If no vCard is found in memory, will add it - * to a loading queue for future loading. Users of this method should only - * use it if the correct vCard is not important the first time around. You - * will get a dummy vCard if there is currently no vCard in memory. - * - * @param jid - * the users jid. - * @return the users VCard or an empty VCard. - */ - public VCard getVCardFromMemory(String jid) { - // Check in memory first. - if (vcards.containsKey(jid)) { - return vcards.get(jid); - } - - // if not in memory - VCard vcard = loadFromFileSystem(jid); - if (vcard == null) { - addToQueue(jid); - - // Create temp vcard. - vcard = new VCard(); - vcard.setJabberId(jid); - } else { - //System.out.println(jid+" HDD ---------->"); - } - - - return vcard; - } - - /** - * Returns the VCard. You should always use useChachedVCards. VCardManager - * will keep the VCards up to date. If you wan't to force a network reload - * of the VCard you can set useChachedVCards to false. That means that you - * have to wait for the vcard response. The method will block until the - * result is available or a timeout occurs (like reloadVCard(String jid)). - * If there is no response from server this method a dummy vcard with an - * error. Use getVCard(String jid) to get a dummy VCard if there is - * currently no VCard. If you get a vCard with an error you may wait some - * seconds. Sometimes vCards could not be loaded within smack timeout but we - * are still listening for vCards that are too late. Be patient for some - * seconds and try again, maybe we will get it. - * - * @param jid - * the users jid. - * @param useCachedVCards - * true to check in cache and hdd, otherwise false will do a new - * network vcard operation. - * @return the VCard. - */ - public VCard getVCard(String jid, boolean useCachedVCards) { - jid = XmppStringUtils.parseBareJid(jid); - if (useCachedVCards) - { - return getVCardFromMemory(jid); - - } else { - return reloadVCard(jid); - } - } - - - /** - * Forces a reload of a VCard. To load a VCard you should use - * getVCard(String jid) instead. This method will perform a network lookup - * which could take some time. If you're having problems with request - * timeout you should also use getVCard(String jid). Use addToQueue(String - * jid) if you want VCardManager to update the VCard by the given jid. The - * method will block until the result is available or a timeout occurs. - * - * @param jid - * the jid of the user. - * - * @return the new network vCard or a vCard with an error - */ - public VCard reloadVCard(String jid) { - jid = XmppStringUtils.parseBareJid(jid); - VCard vcard = new VCard(); - try { - vcard.setJabberId(jid); - vcard.load(SparkManager.getConnection(), jid); - if (vcard.getNickName() != null && vcard.getNickName().length() > 0) - { - // update nickname. - ContactItem item = SparkManager.getWorkspace().getContactList().getContactItemByJID(jid); - item.setNickname(vcard.getNickName()); - // TODO: this doesn't work if someone removes his nickname. If we remove it in that case, it will cause problems with people using another way to manage their nicknames. - } - addVCard(jid, vcard); - persistVCard(jid, vcard); - } - catch (XMPPException | SmackException e) { - ////System.out.println(jid+" Fehler in reloadVCard ----> null"); - vcard.setError(new XMPPError(XMPPError.Condition.resource_constraint)); - vcard.setJabberId(jid); - delayedContacts.add(jid); - return vcard; - //We dont want cards with error - // vcard.setError(new XMPPError(XMPPError.Condition.request_timeout)); - //addVCard(jid, vcard); - } - - // Persist XML - - - return vcard; - } - - - /** - * Adds a new vCard to the cache. - * - * @param jid the jid of the user. - * @param vcard the users vcard to cache. - */ - public void addVCard(String jid, VCard vcard) { - if (vcard == null) - return; - vcard.setJabberId(jid); - if (vcards.containsKey(jid) && vcards.get(jid).getError() == null && vcard.getError()!= null) - { - return; - - } - vcards.put(jid, vcard); - } - - /** - * Scales an image to the preferred avatar size. - * - * @param icon the icon to scale. - * @return the scaled version of the image. - */ - public static ImageIcon scale(ImageIcon icon) { - Image avatarImage = icon.getImage(); - if (icon.getIconHeight() > 64 || icon.getIconWidth() > 64) { - avatarImage = avatarImage.getScaledInstance(-1, 64, Image.SCALE_SMOOTH); - } - - return new ImageIcon(avatarImage); - } - - /** - * Returns the URL of the avatar image associated with the users JID. - * - * @param jid the jid of the user. - * @return the URL of the image. If not image is found, a default avatar is returned. - */ - public URL getAvatar(String jid) { - // Handle own avatar file. - if (jid != null && XmppStringUtils.parseBareJid(SparkManager.getSessionManager().getJID()).equals(XmppStringUtils.parseBareJid(jid))) { - if (imageFile.exists()) { - try { - return imageFile.toURI().toURL(); - } - catch (MalformedURLException e) { - Log.error(e); - } - } - else { - return SparkRes.getURL(SparkRes.DUMMY_CONTACT_IMAGE); - } - } - - // Handle other users JID - ContactItem item = SparkManager.getWorkspace().getContactList().getContactItemByJID(jid); - URL avatarURL = null; - if (item != null) { - try { - avatarURL = item.getAvatarURL(); - } - catch (MalformedURLException e) { - Log.error(e); - } - } - - if (avatarURL == null) { - return SparkRes.getURL(SparkRes.DUMMY_CONTACT_IMAGE); - } - - return avatarURL; - } - - /** - * Searches all vCards for a specified phone number. - * - * @param phoneNumber the phoneNumber. - * @return the vCard which contains the phone number. - */ - public VCard searchPhoneNumber(String phoneNumber) { - for (VCard vcard : vcards.values()) { - String homePhone = getNumbersFromPhone(vcard.getPhoneHome("VOICE")); - String workPhone = getNumbersFromPhone(vcard.getPhoneWork("VOICE")); - String cellPhone = getNumbersFromPhone(vcard.getPhoneWork("CELL")); - - String query = getNumbersFromPhone(phoneNumber); - if ((homePhone != null && homePhone.endsWith(query)) || - (workPhone != null && workPhone.endsWith(query)) || - (cellPhone != null && cellPhone.endsWith(query))) { - return vcard; - } - } - - return null; - } - - /** - * Parses out the numbers only from a phone number. - * - * @param number the full phone number. - * @return the phone number only (5551212) - */ - public static String getNumbersFromPhone(String number) { - if (number == null) { - return null; - } - - number = number.replace("-", ""); - number = number.replace("(", ""); - number = number.replace(")", ""); - number = number.replace(" ", ""); - - return number; - } - - /** - * Sets the personal vcard of the user. - * - * @param vcard the users vCard. - */ - public void setPersonalVCard(VCard vcard) { - this.personalVCard = vcard; - } - - public URL getAvatarURL(String jid) { - VCard vcard = getVCard(jid); - if (vcard != null) { - String hash = vcard.getAvatarHash(); - if (!ModelUtil.hasLength(hash)) { - return null; - } - - final File avatarFile = new File(contactsDir, hash); - try { - return avatarFile.toURI().toURL(); - } - catch (MalformedURLException e) { - Log.error(e); - } - } - return null; - } - - /** - * Get URL for avatar from vcard. If there is no vcard available we will try - * to get it from the server and return null. - * - * @param jid - * the users jid - * @return the vcard if there is already one, otherwise null and we try to - * load vcard in background - * - */ - public URL getAvatarURLIfAvailable(String jid) { - if (getVCard(jid) != null) { - return getAvatarURL(jid); - } else { - addToQueue(jid); - return null; - } - } - - - /** - * Persist vCard information out for caching. - * - * @param jid the users jid. - * @param vcard the users vcard. - */ - private void persistVCard(String jid, VCard vcard) { - if (jid == null || jid.trim().isEmpty() || vcard == null) { - return; - } - - - String fileName = Base64.encodeBytes(jid.getBytes()); - // remove tab - fileName = fileName.replaceAll("\t", ""); - // remove new line (Unix) - fileName = fileName.replaceAll("\n", ""); - // remove new line (Windows) - fileName = fileName.replaceAll("\r", ""); - - byte[] bytes = vcard.getAvatar(); - if (bytes != null && bytes.length > 0) { - vcard.setAvatar(bytes); - try { - String hash = vcard.getAvatarHash(); - final File avatarFile = new File(contactsDir, hash); - ImageIcon icon = new ImageIcon(bytes); - icon = VCardManager.scale(icon); - if (icon != null && icon.getIconWidth() != -1) { - BufferedImage image = GraphicUtils.convert(icon.getImage()); - if (image == null) { - Log.warning("Unable to write out avatar for " + jid); - } - else { - - if (writingQueue.contains(jid)) { - writeAvatarSync(image, avatarFile); - } else { - writingQueue.add(jid); - ImageIO.write(image, "PNG", avatarFile); - writingQueue.remove(jid); - } - - - } - } - } - catch (Exception e) { - Log.error("Unable to update avatar in Contact Item.", e); - } - } - - // Set timestamp - vcard.setField("timestamp", Long.toString(System.currentTimeMillis())); - - final String xml = vcard.toString(); - - File vcardFile = new File(vcardStorageDirectory, fileName); - - // write xml to file - try { - BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(vcardFile), "UTF-8")); - out.write(xml); - out.close(); - } - catch (IOException e) { - Log.error(e); - } - } - - private synchronized void writeAvatarSync(BufferedImage image, File avatarFile) throws IOException { - ImageIO.write(image, "PNG", avatarFile); - } - - /** - * Attempts to load - * - * @param jid the jid of the user. - * @return the VCard if found, otherwise null. - */ - private VCard loadFromFileSystem(String jid) { - if (jid == null || jid.trim().isEmpty()) { - return null; - } - - // Unescape JID - String fileName = Base64.encodeBytes(jid.getBytes()); - - // remove tab - fileName = fileName.replaceAll("\t", ""); - // remove new line (Unix) - fileName = fileName.replaceAll("\n", ""); - // remove new line (Windows) - fileName = fileName.replaceAll("\r", ""); - - final File vcardFile = new File(vcardStorageDirectory, fileName); - if (!vcardFile.exists()) { - return null; - } - - try { - // Otherwise load from file system. - BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(vcardFile), "UTF-8")); - VCardProvider provider = new VCardProvider(); - parser.setInput(in); - parser.next(); // progress past the first start tag. - VCard vcard = provider.parse(parser); - - // Check to see if the file is older 10 minutes. If so, reload. - String timestamp = vcard.getField("timestamp"); - if (timestamp != null) { - long time = Long.parseLong(timestamp); - long now = System.currentTimeMillis(); - - - long hour = (1000 * 60) * 60; - if (now - time > hour) { - addToQueue(jid); - } - } - - addVCard(jid, vcard); - return vcard; - } - catch (Exception e) { - Log.warning("Unable to load vCard for " + jid, e); - } - - return null; - } - - - /** - * Add VCardListener. Listens to the personalVCard. - * - * @param listener the listener to add. - */ - public void addVCardListener(VCardListener listener) { - listeners.add(listener); - } - - /** - * Remove VCardListener. - * - * @param listener the listener to remove. - */ - public void removeVCardListener(VCardListener listener) { - listeners.remove(listener); - } - - /** - * Notify all VCardListener implementations. - */ - protected void notifyVCardListeners() { - for (VCardListener listener : listeners) { - listener.vcardChanged(personalVCard); - } - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/profile/ext/JabberAvatarExtension.java b/src/java/org/jivesoftware/sparkimpl/profile/ext/JabberAvatarExtension.java deleted file mode 100644 index 9663874b5..000000000 --- a/src/java/org/jivesoftware/sparkimpl/profile/ext/JabberAvatarExtension.java +++ /dev/null @@ -1,94 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkimpl.profile.ext; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.packet.ExtensionElement; -import org.jivesoftware.smack.provider.ExtensionElementProvider; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; - -public class JabberAvatarExtension implements ExtensionElement { - - public static final String ELEMENT_NAME = "x"; - - public static final String NAMESPACE = "jabber:x:avatar"; - - private String photoHash; - - public void setPhotoHash(String hash) { - photoHash = hash; - } - - public String getElementName() { - return ELEMENT_NAME; - } - - public String getNamespace() { - return NAMESPACE; - } - - public String toXML() { - String buf = "<" + getElementName() + " xmlns=\"" + getNamespace() + "\">" + - "" + - photoHash + - "" + - ""; - return buf; - } - - public static class Provider extends ExtensionElementProvider - { - public Provider() { - } - - @Override - public JabberAvatarExtension parse( XmlPullParser parser, int i ) throws XmlPullParserException, IOException, SmackException - { - final JabberAvatarExtension result = new JabberAvatarExtension(); - - while ( true ) - { - parser.next(); - String elementName = parser.getName(); - switch ( parser.getEventType() ) - { - case XmlPullParser.START_TAG: - if ( "photo".equals( elementName ) ) - { - result.setPhotoHash( parser.nextText() ); - } - break; - - case XmlPullParser.END_TAG: - if ( ELEMENT_NAME.equals( elementName ) ) - { - return result; - } - break; - } - } - } - } - -} \ No newline at end of file diff --git a/src/java/org/jivesoftware/sparkimpl/profile/ext/VCardUpdateExtension.java b/src/java/org/jivesoftware/sparkimpl/profile/ext/VCardUpdateExtension.java deleted file mode 100644 index fa779bfa2..000000000 --- a/src/java/org/jivesoftware/sparkimpl/profile/ext/VCardUpdateExtension.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkimpl.profile.ext; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.packet.ExtensionElement; -import org.jivesoftware.smack.provider.ExtensionElementProvider; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; - -public class VCardUpdateExtension implements ExtensionElement { - - public static final String ELEMENT_NAME = "x"; - - public static final String NAMESPACE = "vcard-temp:x:update"; - - private String photoHash; - - public void setPhotoHash(String hash) { - photoHash = hash; - } - - public String getPhotoHash() { - return photoHash; - } - - public String getElementName() { - return ELEMENT_NAME; - } - - public String getNamespace() { - return NAMESPACE; - } - - public String toXML() { - String buf = "<" + getElementName() + " xmlns=\"" + getNamespace() + "\">" + - "" + - photoHash + - "" + - ""; - return buf; - } - - public static class Provider extends ExtensionElementProvider - { - public Provider() { - } - - @Override - public VCardUpdateExtension parse( XmlPullParser parser, int i ) throws XmlPullParserException, IOException, SmackException - { - final VCardUpdateExtension result = new VCardUpdateExtension(); - - while ( true ) - { - parser.next(); - String elementName = parser.getName(); - switch ( parser.getEventType() ) - { - case XmlPullParser.START_TAG: - if ( "photo".equals( elementName ) ) - { - result.setPhotoHash( parser.nextText() ); - } - break; - - case XmlPullParser.END_TAG: - if ( ELEMENT_NAME.equals( elementName ) ) - { - return result; - } - break; - } - } - } - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/settings/JiveInfo.java b/src/java/org/jivesoftware/sparkimpl/settings/JiveInfo.java deleted file mode 100644 index 63a339bf8..000000000 --- a/src/java/org/jivesoftware/sparkimpl/settings/JiveInfo.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkimpl.settings; - -import org.jivesoftware.resource.Default; - -public class JiveInfo { - - private JiveInfo() { - - } - - public static String getName() { - return Default.getString(Default.APPLICATION_NAME); - } - - public static String getVersion() { - return Default.getString(Default.APPLICATION_VERSION); - } - - /* - * This should be used for an actual - * build number, rather than duplicating - * getVersion(); i propose to use the - * SVN revision number of the build - */ - public static String getBuildNumber() { - return "12555"; - } - - public static String getOS() { - return System.getProperty("os.name"); - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/settings/local/LocalPreferencePanel.java b/src/java/org/jivesoftware/sparkimpl/settings/local/LocalPreferencePanel.java deleted file mode 100644 index 026226105..000000000 --- a/src/java/org/jivesoftware/sparkimpl/settings/local/LocalPreferencePanel.java +++ /dev/null @@ -1,303 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkimpl.settings.local; - -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; - -import javax.swing.BorderFactory; -import javax.swing.JCheckBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; - -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.spark.component.VerticalFlowLayout; -import org.jivesoftware.spark.util.ResourceUtils; - -/** - * UI for editing Local Preferences. - */ -public class LocalPreferencePanel extends JPanel { - private static final long serialVersionUID = -1675058807882383560L; - - private JTextField _portField = new JTextField(); - private JTextField _timeOutField = new JTextField(); - private JTextField _idleField = new JTextField(); - private JTextField _idleStatusText; - - private JCheckBox _autoLoginBox = new JCheckBox(); - private JCheckBox _savePasswordBox = new JCheckBox(); - private JCheckBox _idleBox = new JCheckBox(); - private JCheckBox _launchOnStartupBox = new JCheckBox(); - private JCheckBox _startMinimizedBox = new JCheckBox(); - private JCheckBox _useSingleTrayClick = new JCheckBox(); - - - /** - * Construct Local Preference UI. - */ - public LocalPreferencePanel() { - setLayout(new VerticalFlowLayout()); - - - // Load local localPref - LocalPreferences preferences = SettingsManager.getLocalPreferences(); - _portField.setText(Integer.toString(preferences.getXmppPort())); - _timeOutField.setText(Integer.toString(preferences.getTimeOut())); - _autoLoginBox.setSelected(preferences.isAutoLogin()); - _savePasswordBox.setSelected(preferences.isSavePassword()); - _startMinimizedBox.setSelected(preferences.isStartedHidden()); - _useSingleTrayClick.setSelected(preferences.isUsingSingleTrayClick()); - - _idleStatusText = new JTextField(preferences.getIdleMessage()); - - _savePasswordBox.addActionListener( e -> { - _autoLoginBox.setEnabled(_savePasswordBox.isSelected()); - if (!_savePasswordBox.isSelected()) { - _autoLoginBox.setSelected(false); - } - } ); - - _autoLoginBox.addActionListener( e -> { - if (_autoLoginBox.isSelected()) { - _savePasswordBox.setSelected(true); - } - } ); - - _idleBox.addActionListener( e -> _idleField.setEnabled(_idleBox.isSelected()) ); - - - _idleBox.setSelected(preferences.isIdleOn()); - _idleField.setText(Integer.toString(preferences.getIdleTime())); - - final JPanel inputPanel = new JPanel(); - inputPanel.setLayout(new GridBagLayout()); - inputPanel.setBorder(BorderFactory.createTitledBorder(Res - .getString("group.login.information"))); - - JLabel _portLabel = new JLabel(); - ResourceUtils.resLabel( _portLabel, _portField,Res.getString("label.xmpp.port") + ":"); - JLabel _timeOutLabel = new JLabel(); - ResourceUtils.resLabel( _timeOutLabel, _timeOutField, - Res.getString("label.response.timeout") + ":"); - - JLabel _idleStatusLabel = new JLabel(); - ResourceUtils.resLabel( _idleStatusLabel, _idleStatusText, - Res.getString("label.time.till.idlemessage") + ":"); - - ResourceUtils.resButton(_autoLoginBox, - Res.getString("checkbox.auto.login")); - ResourceUtils.resButton(_savePasswordBox, - Res.getString("checkbox.save.password")); - JLabel _idleLabel = new JLabel(); - ResourceUtils.resLabel( _idleLabel, _idleField, - Res.getString("label.time.till.idle") + ":"); - ResourceUtils.resButton(_idleBox, - Res.getString("checkbox.idle.enabled")); - - ResourceUtils.resButton(_launchOnStartupBox, - Res.getString("checkbox.launch.on.startup")); - ResourceUtils.resButton(_startMinimizedBox, - Res.getString("checkbox.start.in.tray")); - ResourceUtils.resButton(_useSingleTrayClick, - Res.getString("checkbox.click.single.tray")); - - inputPanel.add( _portLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - inputPanel.add(_portField, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,new Insets(5, 5, 5, 5), 0, 0)); - inputPanel.add( _timeOutLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,new Insets(5, 5, 5, 5), 50, 0)); - inputPanel.add(_timeOutField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); - inputPanel.add( _idleLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,new Insets(5, 5, 5, 5), 50, 0)); - inputPanel.add(_idleField, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,new Insets(5, 5, 5, 5), 50, 0)); - inputPanel.add( _idleStatusLabel,new GridBagConstraints(0, 3, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); - inputPanel.add(_idleStatusText, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); - inputPanel.add(_idleBox, new GridBagConstraints(0, 4, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,new Insets(5, 5, 5, 5), 50, 0)); - - if(!Default.getBoolean(Default.HIDE_SAVE_PASSWORD_AND_AUTOLOGIN)) { - inputPanel.add(_savePasswordBox, new GridBagConstraints(0, 5, 2, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); - inputPanel.add(_autoLoginBox, new GridBagConstraints(0, 6, 2, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); - } - - if (Spark.isWindows()) { - inputPanel.add(_launchOnStartupBox, new GridBagConstraints(0, 7, 2, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50,0)); - _launchOnStartupBox.addActionListener( e -> setStartOnStartup(_launchOnStartupBox.isSelected()) ); - - _launchOnStartupBox.setSelected(preferences.getStartOnStartup()); - } - - inputPanel.add(_startMinimizedBox, new GridBagConstraints(0, 8, 2, 1,0.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); - inputPanel.add(_useSingleTrayClick, new GridBagConstraints(0, 9, 2, 1,0.0, 0.0, GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 50, 0)); - inputPanel.add(new JLabel(), new GridBagConstraints(0, 10, 2, 1, 1.0,1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,new Insets(5, 5, 5, 5), 50, 0)); - - - add(inputPanel); - } - - /** - * Sets the XMPP port to comminucate on. - * - * @param port - * the XMPP port to communicate on. - */ - public void setPort(String port) { - _portField.setText(port); - } - - /** - * Return the XMPP Port to communicate on. - * - * @return the XMPP Port to communicate on. - */ - public String getPort() { - return _portField.getText(); - } - - /** - * Sets the XMPP Timeout(in seconds). - * - * @param timeOut - * the XMPP Timeout(in seconds). - */ - public void setTimeOut(String timeOut) { - _timeOutField.setText(timeOut); - } - - /** - * Return the XMPP Timeout variable. - * - * @return the XMPP Timeout variable. - */ - public String getTimeout() { - return _timeOutField.getText(); - } - - /** - * Sets Auto Login on and off. - * - * @param auto - * true if Auto Login is on. - */ - public void setAutoLogin(boolean auto) { - _autoLoginBox.setSelected(auto); - } - - /** - * Return true if Auto Login is on. - * - * @return true if Auto Login is on. - */ - public boolean getAutoLogin() { - return _autoLoginBox.isSelected(); - } - - /** - * Set true if the password should be encoded and saved. - * - * @param save - * true if the password should be encoded and saved. - */ - public void setSavePassword(boolean save) { - _savePasswordBox.setSelected(save); - } - - /** - * Return true if the password should be saved. - * - * @return true if the password should be saved. - */ - public boolean isSavePassword() { - return _savePasswordBox.isSelected(); - } - - /** - * Returns true if IDLE is on. - * - * @return true if IDLE is on. - */ - public boolean isIdleOn() { - return _idleBox.isSelected(); - } - - /** - * Sets the IDLE on or off. - * - * @param on - * true if IDLE should be on. - */ - public void setIdleOn(boolean on) { - _idleBox.setSelected(on); - } - - /** - * Sets the Idle Time in minutes. - * - * @param time - * the Idle time in minutes. - */ - public void setIdleTime(int time) { - String idleTime = Integer.toString(time); - _idleField.setText(idleTime); - } - - /** - * Return the time to IDLE. - * - * @return the time to IDLE. - */ - public String getIdleTime() { - return _idleField.getText(); - } - - public void startInSystemTray(boolean startInTray) { - _startMinimizedBox.setSelected(startInTray); - } - - public boolean startInSystemTray() { - return _startMinimizedBox.isSelected(); - } - - public void useSingleClickInTray(boolean clickInTray) { - _useSingleTrayClick.setSelected(clickInTray); - } - - public boolean useSingleClickInTray() { - return _useSingleTrayClick.isSelected(); - } - - public boolean startOnStartup() { - return _launchOnStartupBox.isSelected(); - } - - public void setStartOnStartup(boolean startup) { - _launchOnStartupBox.setSelected(startup); - } - - public String getIdleMessage(){ - return _idleStatusText.getText(); - } - public void setIdleMessage(String text){ - _idleStatusText.setText(text); - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/settings/local/LocalPreferences.java b/src/java/org/jivesoftware/sparkimpl/settings/local/LocalPreferences.java deleted file mode 100644 index 946b59e82..000000000 --- a/src/java/org/jivesoftware/sparkimpl/settings/local/LocalPreferences.java +++ /dev/null @@ -1,1255 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkimpl.settings.local; - -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.spark.PluginRes; -import org.jivesoftware.spark.SparkManager; -import java.io.File; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Properties; -import java.util.StringTokenizer; - -import javax.swing.UIManager; - -import org.jivesoftware.spark.util.Encryptor; -import org.jivesoftware.spark.util.log.Log; - -/** - * Represents the LocalPreference Model for this system. - */ -public class LocalPreferences { - - private Properties props; - - public LocalPreferences(Properties props) { - this.props = props; - } - - public LocalPreferences() { - this.props = new Properties(); - } - - public Properties getProperties() { - return props; - } - - /** - * Returns the XMPP Port to communicate on. - * - * @return the XMPP Port to communicate on. Default is 5222. - */ - public int getXmppPort() { - return Integer.parseInt(props.getProperty("xmppPort", "5222")); - } - - /** - * Sets the XMPP Port to communicate on. - * - * @param xmppPort - * the XMPP Port to communicate on. Default is 5222. - */ - public void setXmppPort(int xmppPort) { - props.setProperty("xmppPort", Integer.toString(xmppPort)); - } - - /** - * Return the smack timeout for requests. Default is 5 seconds. - * - * @return the smack timeout for requests. - */ - public int getTimeOut() { - return Integer.parseInt(props.getProperty("timeout", "10")); - } - - /** - * Sets the smack timeout for requests. The default is 5 seconds, but you - * may wish to increase this number for low bandwidth users. - * - * @param timeOut - * the smack timeout. - */ - public void setTimeOut(int timeOut) { - props.setProperty("timeout", Integer.toString(timeOut)); - } - - /** - * Returns the encoded password. - * - * @return the encoded password. - */ -// public String getPassword() { -// return props.getProperty("password"); -// } - - /** - * Sets the encoded password. - * - * @param password - * the encoded password. - */ -// public void setPassword(String password) { -// props.setProperty("password", password); -// } - - /** - * returns the password for an encrypted jid - * @param barejid - * @return - */ - public String getPasswordForUser(String barejid) - { - try { - String pw = "password"+Encryptor.encrypt(barejid); - return Encryptor.decrypt(props.getProperty(pw)); - } catch(Exception e){ - return null; - } - } - - /** - * Sets the password for barejid
        - * both will be encrypted - * @param barejid - * @param password - * @throws Exception - */ - public void setPasswordForUser(String barejid, String password) throws Exception - { - String user = "password"+Encryptor.encrypt(barejid); - String pw = Encryptor.encrypt(password); - props.setProperty(user, pw); - } - - /** - * Return true if the IDLE feature is on. The IDLE feature allows to monitor - * computer activity and set presence accordingly. - * - * @return true if IDLE is on. - */ - public boolean isIdleOn() { - return Boolean.parseBoolean(props.getProperty("idleOn", "true")); - } - - /** - * Set the IDLE feature on or off. The IDLE feature allows to monitor - * computer activity and set presence accordingly. - * - * @param idleOn - * true to turn idle on. - */ - public void setIdleOn(boolean idleOn) { - props.setProperty("idleOn", Boolean.toString(idleOn)); - } - - /** - * Returns true if it is wanted that a new ad hoc room to be created every time Actions/Start conference room is chosen, - * or, from a chat window - invite to group chat room icon is pressed. - * Returns false if it is wanted that the bookmarked room (if any) to be opened every time Actions/Start conference room is chosen, - * or, from a chat window - invite to group chat room icon is pressed. - * @param adHocRoom - * @return - */ - public boolean isUseAdHocRoom() { - String adhoc = PluginRes.getPreferenceRes("useAdHocRoom"); - return getBoolean("useAdHocRoom", adhoc != null ? new Boolean(adhoc) : true); - } - - /** - * Set useAdHocRoom on or off. When disabled, if there is at least one bookmark room, that - * room will be used in Actions/Start conference room Invitation Dialog (instead of creating an ad-hoc room) - * If there is more than one bookmark room, you can select the bookmarked room that you want to be used - * Also, when invite to join group chat room will be sent from the chat window, the bookmark room will automatically - * be opened. - * @param adHocRoom - * @return - */ - public void setUseAdHocRoom(boolean adHocRoom) { - setBoolean("useAdHocRoom", adHocRoom); - } - /** - * Returns the Idle Message to Display when going automatically away - * @return - */ - public String getIdleMessage(){ - return props.getProperty("idleOnMessage",Res.getString("status.away")); - } - - /** - * Sets the idle Message when going automatically away - * @param message - */ - public void setIdleMessage(String message){ - props.setProperty("idleOnMessage",message); - } - - /** - * Returns the number of minutes to set to unavailable if the computer has - * no activity. - * - * @return the number of minutes before checking for IDLE computer. - */ - public int getIdleTime() { - return Integer.parseInt(props.getProperty("idleTime", "3")); - } - - /** - * Set the number of minutes to set to unavailable if the computer has no - * activity. - * - * @param secondIdleTime - * the number of minutes. - */ - public void setIdleTime(int secondIdleTime) { - props.setProperty("idleTime", Integer.toString(secondIdleTime)); - } - - /** - * Return true if Auto Login is on. - * - * @return true if Auto Login is on. - */ - public boolean isAutoLogin() { - return Boolean.parseBoolean(props.getProperty("autoLoginEnabled", - "false")); - } - - /** - * Turn on or off Auto Login. Auto Login allows a user to login to the - * system without inputting their signing information. - * - * @param autoLogin - * true if Auto Login should be on. - */ - public void setAutoLogin(boolean autoLogin) { - props.setProperty("autoLoginEnabled", Boolean.toString(autoLogin)); - } - - /** - * Return true if Login As Invisible is on. - * - * @return true if Auto Login is on. - */ - public boolean isLoginAsInvisible() { - return Boolean.parseBoolean(props.getProperty("loginAsInvisibleEnabled", - "false")); - } - - /** - * Turn on or off Login As Invisible option. - * - * @param autoLogin - * true if Auto Login should be on. - */ - public void setLoginAsInvisible(boolean loginAsInvisible) { - props.setProperty("loginAsInvisibleEnabled", Boolean.toString(loginAsInvisible)); - } - - /** - * Return true if the password should be encoded and persisted. - * - * @return true if the password is encoded and persisted. - */ - public boolean isSavePassword() { - return Boolean - .parseBoolean(props.getProperty("passwordSaved", "false")); - } - - /** - * Set to true to encode and save password. You would use this if you wish - * to not always input ones password. - * - * @param savePassword - * true if the password should be saved. - */ - public void setSavePassword(boolean savePassword) { - props.setProperty("passwordSaved", Boolean.toString(savePassword)); - } - - /** - * Returns the last used Username - * - * @return the username of the agent. - */ - public String getLastUsername() { - return props.getProperty("username"); - } - - /** - * Sets the Agents username. - * - * @param username - * the agents username. - */ - public void setLastUsername(String username) { - props.setProperty("username", username); - } - - /** - * Returns the last Server accessed. - * - * @return the last Server accessed. - */ - public String getServer() { - return props.getProperty("server"); - } - - /** - * Sets the last Server accessed. - * - * @param server - * the last Server accessed. - */ - public void setServer(String server) { - props.setProperty("server", server); - } - - /** - * Return true if this is a fresh install. - * - * @return true if a fresh install. - */ - public boolean isNewInstall() { - return Boolean.parseBoolean(props.getProperty("newInstall", "false")); - } - - /** - * Set if this is a fresh install. - * - * @param newInstall - * true if this is a fresh install. - */ - public void setNewInstall(boolean newInstall) { - props.setProperty("newInstall", Boolean.toString(newInstall)); - } - - /** - * Returns true to use SSL. - * - * @return true if we should connect via SSL. - */ - public boolean isSSL() { - return Boolean.parseBoolean(props.getProperty("sslEnabled", "false")); - } - - /** - * Sets if the agent should use SSL for connecting. - * - * @param ssl - * true if we should be using SSL. - */ - public void setSSL(boolean ssl) { - props.setProperty("sslEnabled", Boolean.toString(ssl)); - } - - /** - * Returns the Download Directory, doesnt return null - * @return {@link String} - */ - public String getDownloadDir() { - - File downloadedDir = null; - if (Spark.isLinux() || Spark.isMac()) { - downloadedDir = new File(System.getProperty("user.home") + "/Downloads/"); - Log.error(downloadedDir.getAbsolutePath()); - } else if (Spark.isWindows()) { - - String regpath = WinRegistryReader.getMyDocumentsFromWinRegistry(); - if (regpath != null) { - downloadedDir = new File(regpath + "\\Downloads"); - if (!downloadedDir.exists()) { - downloadedDir.mkdir(); - } - } - else - { - // if for some Reason there is no "My Documents" Folder we should select the Desktop - downloadedDir = new File(System.getProperty("user.home") + "\\Desktop\\"); - } - } - - return props.getProperty("downloadDirectory", downloadedDir.getAbsolutePath()); - } - - public void setDownloadDir(String downloadDir) { - props.setProperty("downloadDirectory", downloadDir); - } - - public String getFileExplorer() { - return props.getProperty("fileExplorer"); - } - - public void setFileExplorer(String fileExplorer) { - props.setProperty("fileExplorer", fileExplorer); - } - - public boolean isProxyEnabled() { - return getBoolean("proxyEnabled", false); - } - - public void setProxyEnabled(boolean proxyEnabled) { - setBoolean("proxyEnabled", proxyEnabled); - } - - public String getHost() { - return props.getProperty("host"); - } - - public void setHost(String host) { - props.setProperty("host", host); - } - - public String getPort() { - return props.getProperty("port"); - } - - public void setPort(String port) { - props.setProperty("port", port); - } - - public String getProxyUsername() { - return props.getProperty("proxyUsername"); - } - - public void setProxyUsername(String proxyUsername) { - props.setProperty("proxyUsername", proxyUsername); - } - - public String getProxyPassword() { - return props.getProperty("proxyPassword"); - } - - public void setProxyPassword(String proxyPassword) { - props.setProperty("proxyPassword", proxyPassword); - } - - public String getProtocol() { - return props.getProperty("protocol"); - } - - public void setProtocol(String protocol) { - props.setProperty("protocol", protocol); - } - - public String getDefaultNickname() { - return props.getProperty("defaultNickname"); - } - - public void setDefaultNickname(String defaultNickname) { - props.setProperty("defaultNickname", defaultNickname); - } - - public int getCheckForUpdates() { - return Integer.parseInt(props.getProperty("checkForUpdates", "7")); - } - - public Date getLastCheckForUpdates() { - String date = props.getProperty("lastUpdateCheck"); - if (date == null) { - return null; - } - - // Convert to long - long time = Long.parseLong(date); - return new Date(time); - } - - public void setLastCheckForUpdates(Date lastCheckForUpdates) { - String time = Long.toString(lastCheckForUpdates.getTime()); - props.setProperty("lastUpdateCheck", time); - } - - public String getXmppHost() { - return props.getProperty("xmppHost"); - } - - public void setXmppHost(String xmppHost) { - props.setProperty("xmppHost", xmppHost); - } - - public boolean isHostAndPortConfigured() { - return getBoolean("hostAndPort", false); - } - - public void setHostAndPortConfigured(boolean configured) { - setBoolean("hostAndPort", configured); - } - - public String getResource() { - return props.getProperty("resource", Default.getString(Default.SHORT_NAME)); - } - - public void setResource(String resource) { - props.setProperty("resource", resource); - } - - public boolean isStartedHidden() { - return getBoolean("startHidden", false); - } - - public void setStartedHidden(boolean startedHidden) { - setBoolean("startHidden", startedHidden); - } - - public boolean isUsingSingleTrayClick() { - return getBoolean("useSingleTrayClick", true); - } - - public void setUsingSingleTrayClick(boolean useSingle) { - setBoolean("useSingleTrayClick", useSingle); - } - - public boolean isTimeDisplayedInChat() { - return getBoolean("timeDisplayed", true); - } - - public void setTimeDisplayedInChat(boolean timeDisplayedInChat) { - setBoolean("timeDisplayed", timeDisplayedInChat); - } - - public void setTimeFormat(String format) { - props.setProperty("timeFormat", format); - } - - public String getTimeFormat() { - return props.getProperty("timeFormat", "HH:mm"); - } - - public boolean isSpellCheckerEnabled() { - return getBoolean("spellCheckerEnabled", true); - } - - public void setSpellCheckerEnabled(boolean enabled) { - setBoolean("spellCheckerEnabled", enabled); - } - - public boolean isChatRoomNotificationsOn() { - return getBoolean("chatNotificationOn", true); - } - - public void setChatRoomNotifications(boolean on) { - setBoolean("chatNotificationOn", on); - } - - public boolean isChatHistoryEnabled() { - return getBoolean("showHistory", true); - } - - public void setChatHistoryEnabled(boolean hidePrevChatHistory) { - setBoolean("showHistory", hidePrevChatHistory); - } - - public boolean isPrevChatHistoryEnabled() { - return getBoolean("showPrevHistory", true); - } - - public void setPrevChatHistoryEnabled(boolean hidePrevChatHistory) { - setBoolean("showPrevHistory", hidePrevChatHistory); - } - - public boolean isEmptyGroupsShown() { - return getBoolean("showEmptyGroups", false); - } - - public void setEmptyGroupsShown(boolean shown) { - setBoolean("showEmptyGroups", shown); - } - - public boolean isOfflineUsersShown() { - return getBoolean("showOfflineUsers", false); - } - - public void setOfflineUsersShown(boolean shown) { - setBoolean("showOfflineUsers", shown); - } - - public boolean isTypingNotificationShown() { - String showTypingNotification = PluginRes.getPreferenceRes("showTypingNotification"); - return getBoolean("showTypingNotification", showTypingNotification != null ? new Boolean(showTypingNotification) : false); - } - - public void setSystemTrayNotificationEnabled(boolean shown) { - setBoolean("SystemTrayNotificationEnabled", shown); - } - - public boolean isSystemTrayNotificationEnabled() { - String SystemTrayNotificationEnabled = PluginRes.getPreferenceRes("SystemTrayNotificationEnabled"); - return getBoolean("SystemTrayNotificationEnabled", SystemTrayNotificationEnabled != null ? new Boolean(SystemTrayNotificationEnabled) : false); - } - - public void setTypingNotificationOn(boolean shown) { - setBoolean("showTypingNotification", shown); - } - - public int getFileTransferTimeout() { - return Integer.parseInt(props.getProperty("fileTransferTimeout", "30")); - } - - public void setFileTransferTimeout(int minutes) { - props.setProperty("fileTransferTimeout", Integer.toString(minutes)); - } - - public void setChatLengthDefaultTimeout(int minutes) { - props - .setProperty("defaultChatLengthTimeout", Integer - .toString(minutes)); - } - - public int getChatLengthDefaultTimeout() { - return Integer.parseInt(props.getProperty("defaultChatLengthTimeout", - "15")); - } - - public void setNickname(String nickname) { - props.setProperty("nickname", nickname); - } - - public String getNickname() { - return props.getProperty("nickname", SparkManager.getUserManager() - .getNickname()); - } - - public void setShowToasterPopup(boolean show) { - setBoolean("toasterPopup", show); - } - - public boolean getShowToasterPopup() { - String toasterPopup = PluginRes.getPreferenceRes("toasterPopup"); - return getBoolean("toasterPopup", toasterPopup != null ? new Boolean(toasterPopup) : false); - } - - public void setDisableAsteriskToasterPopup(boolean disable) { - setBoolean("disableAsteriskToasterPopup", disable); - } - - public boolean getDisableAsteriskToasterPopup() { - return getBoolean("disableAsteriskToasterPopup", false); - } - - public void setWindowTakesFocus(boolean focus) { - setBoolean("windowTakesFocus", focus); - } - - public boolean getWindowTakesFocus() { - return getBoolean("windowTakesFocus", false); - } - - public void setStartOnStartup(boolean startup) { - setBoolean("startOnStartup", startup); - } - - public boolean getStartOnStartup() { - return getBoolean("startOnStartup", false); - } - - /** - * Sets the Reconnection display type

        - * 0 = ReconnectPanel

        - * 1 = Reconnect as Group

        - * 2 = Reconnect as Icon

        - * @param reconnect - */ - public void setReconnectPanelType(int reconnect) { - setInt("ReconnectPanelType", reconnect); - } - - /** - * Sets the Reconnection display type

        - * 0 = ReconnectPanel

        - * 1 = Reconnect as Group

        - * 2 = Reconnect as Icon

        - * @return - */ - public int getReconnectPanelType() { - return getInt("ReconnectPanelType", 1); - } - - public void setCompressionEnabled(boolean on) { - setBoolean("compressionOn", on); - } - - public boolean isCompressionEnabled() { - return getBoolean("compressionOn", false); - } - - public void setTheme(String theme) { - props.setProperty("theme", theme); - } - - public String getTheme() { - return props.getProperty("theme", "Default"); - } - - public void setEmoticonPack(String pack) { - props.setProperty("emoticonPack", pack); - } - - public String getEmoticonPack() { - return props.getProperty("emoticonPack", "Default"); - } - - public void setNotificationsDisplayTime(Integer DisplayTime) { - setInt("DisplayTime", DisplayTime); - } - - public int getNotificationsDisplayTime() { - return getInt("DisplayTime", 3); - } - - public void setOfflineNotifications(boolean notify) { - setBoolean("notifyOnOffline", notify); - } - - public boolean isOfflineNotificationsOn() { - String notifyOnOffline = PluginRes.getPreferenceRes("notifyOnOffline"); - return getBoolean("notifyOnOffline", notifyOnOffline != null ? new Boolean(notifyOnOffline) : false); - } - - public void setOnlineNotifications(boolean notify) { - setBoolean("notifyOnOnline", notify); - } - - public boolean isOnlineNotificationsOn() { - String notifyOnOnline = PluginRes.getPreferenceRes("notifyOnOnline"); - return getBoolean("notifyOnOnline", notifyOnOnline != null ? new Boolean(notifyOnOnline) : false); - } - - public void setDockingEnabled(boolean dockingEnabled) { - setBoolean("dockingEnabled", dockingEnabled); - } - - public boolean isDockingEnabled() { - return getBoolean("dockingEnabled", false); - } - - public void setAutoCloseChatRoomsEnabled(boolean autoCloseChatRoomsEnabled) { - setBoolean("autoCloseChatRoomsEnabled", autoCloseChatRoomsEnabled); - } - - public boolean isAutoCloseChatRoomsEnabled() { - return getBoolean("autoCloseChatRoomsEnabled", true); - } - - public void setTabsOnTop(boolean onTop) { - setBoolean("tabsOnTop", onTop); - } - - public boolean isTabTopPosition() { - return getBoolean("tabsOnTop", true); - } - - public void setBuzzEnabled(boolean enabled) { - setBoolean("buzzEnabled", enabled); - } - - public boolean isBuzzEnabled() { - return getBoolean("buzzEnabled", true); - } - - public void setOfflineGroupVisible(boolean visible) { - setBoolean("offlineGroupVisible", visible); - } - - public boolean isOfflineGroupVisible() { - return getBoolean("offlineGroupVisible", true); - } - - public void setEmoticonsEnabled(boolean enabled) { - setBoolean("emoticonsEnabled", enabled); - } - - public boolean areEmoticonsEnabled() { - return getBoolean("emoticonsEnabled", true); - } - - public void setGrayingOutEnabled(boolean enabled) { - setBoolean("GrayingOut", enabled); - } - - public boolean isGrayingOutEnabled() { - return getBoolean("GrayingOut", true); - } - - public void setLookAndFeel(String laf) - { - setString("LookAndFeel",laf); - } - - public String getLookAndFeel() { - String defaultstring; - try { - defaultstring = Spark.isMac() ? Default.getString(Default.DEFAULT_LOOK_AND_FEEL_MAC) - : Default.getString(Default.DEFAULT_LOOK_AND_FEEL); - } catch (Exception e) { - defaultstring = UIManager.getSystemLookAndFeelClassName(); - } - if (defaultstring.length() < 1) { - defaultstring = UIManager.getSystemLookAndFeelClassName(); - } - return getString("LookAndFeel", defaultstring); - } - - public void setCheckForBeta(boolean checkForBeta) { - setBoolean("checkForBeta", checkForBeta); - } - - public boolean isBetaCheckingEnabled() { - return getBoolean("checkForBeta", false); - } - - public boolean isMucHighNameEnabled() { - return getBoolean("isMucHighNameOn", false); - } - - public boolean isMucHighTextEnabled() { - return getBoolean("isMucHighTextOn", false); - } - - public boolean isMucRandomColors(){ - return getBoolean("isMucRandomColors", true); - } - - public void setMucRandomColors(boolean value){ - setBoolean("isMucRandomColors", value); - } - - public boolean isMucHighToastEnabled() { - return getBoolean("isMucHighToastOn", false); - } - - public boolean isShowingRoleIcons() { - return getBoolean("isShowingRoleIcons",false); - } - - public boolean isShowJoinLeaveMessagesEnabled() { - return getBoolean("isShowJoinLeaveMessagesOn", true); - } - - public void setShowJoinLeaveMessagesEnabled(boolean enabled) { - setBoolean("isShowJoinLeaveMessagesOn", enabled); - } - - public void setMucHighNameEnabled(boolean setMucNHigh) { - setBoolean("isMucHighNameOn", setMucNHigh); - } - - public void setMucHighTextEnabled(boolean setMucTHigh) { - setBoolean("isMucHighTextOn", setMucTHigh); - } - - public void setMuchHighToastEnabled(boolean setMucPHigh) { - setBoolean("isMucHighToastOn", setMucPHigh); - } - - public void setShowRoleIconInsteadStatusIcon(boolean roleicons){ - setBoolean("isShowingRoleIcons",roleicons); - } - - public void setSSOEnabled(boolean enabled) { - setBoolean("ssoEnabled", enabled); - } - - public boolean isSSOEnabled() { - return getBoolean("ssoEnabled", false); - } - - public void setSSOAdv(boolean enabled) { - setBoolean("ssoAdv", enabled); - } - - public boolean getSSOAdv() { - return getBoolean("ssoAdv", false); - } - - public void setSSOMethod(String method) { - props.setProperty("ssoMethod", method); - } - - public String getSSOMethod() { - return props.getProperty("ssoMethod"); - } - - public void setSSORealm(String realm) { - props.setProperty("ssoRealm", realm); - } - - public String getSSORealm() { - return props.getProperty("ssoRealm"); - } - - public void setSSOKDC(String kdc) { - props.setProperty("ssoKDC", kdc); - } - - public String getSSOKDC() { - return props.getProperty("ssoKDC"); - } - - public void setPKIEnabled(boolean enabled) { - setBoolean("pkiEnabled", enabled); - } - - public boolean isPKIEnabled() { - return getBoolean("pkiEnabled", false); - } - - public void setPKIStore(String type) { - props.setProperty("pkiStore", type); - } - - public String getPKIStore() { - return props.getProperty("pkiStore"); - } - - public void setJKSPath(String file) { - props.setProperty("jksPath", file); - } - - public String getJKSPath() { - return props.getProperty("jksPath"); - } - - public void setPKCS11Library(String file) { - props.setProperty("pkcs11Library", file); - } - - public String getPKCS11Library() { - return props.getProperty("pkcs11Library"); - } - - public void setTrustStorePath(String file) { - props.setProperty("trustStorePath", file); - } - - public String getTrustStorePath() { - return props.getProperty("trustStorePath"); - } - - public void setTrustStorePassword(String password) { - props.setProperty("trustStorePassword", password); - } - - public String getTrustStorePassword() { - return props.getProperty("trustStorePassword"); - } - - public boolean getDebug() { - return getBoolean("debug", false); - } - - public void setDebug(boolean debug) { - setBoolean("debug", debug); - } - - public void setDebuggerEnabled(boolean enabled) { - setBoolean("debuggerEnabled", enabled); - } - - public boolean isDebuggerEnabled() { - return getBoolean("debuggerEnabled", false); - } - - public void setContactListFontSize(int fontSize) { - setInt("contactListFontSize", fontSize); - } - - public int getContactListFontSize() { - return getInt("contactListFontSize", 11); - } - - public void setContactListIconSize(int iconSize) { - setInt("contactListIconSize", iconSize); - } - - public int getContactListIconSize() { - return getInt("contactListIconSize", 24); - } - - public void setChatRoomFontSize(int fontSize) { - setInt("chatRoomFontSize", fontSize); - } - - public int getChatRoomFontSize() { - return getInt("chatRoomFontSize", 12); - } - - public void setLanguage(String language) { - props.setProperty("language", language); - } - - public String getLanguage() { - return props.getProperty("language", ""); - } - - public void setAvatarVisible(boolean visible) { - setBoolean("showAvatar", visible); - } - - public boolean areAvatarsVisible() { - return getBoolean("showAvatar", false); - } - - public void setVCardsVisible(boolean visible) { - setBoolean("showVCards", visible); - } - - public boolean areVCardsVisible() { - return getBoolean("showVCards", true); - } - - public void setAudioSystem(String device) { - props.setProperty("audioSystem", device); - } - - public String getAudioSystem() { - return props.getProperty("audioSystem","wasapi"); - } - - - public void setAudioDevice(String device) { - props.setProperty("audioDevice", device); - } - - public String getAudioDevice() { - return props.getProperty("audioDevice","javasound://"); - } - - public void setPlaybackDevice(String device) { - props.setProperty("playbackDevice", device); - } - - public String getPlaybackDevice() { - return props.getProperty("playbackDevice","javasound://"); - } - - public void setVideoDevice(String device) { - props.setProperty("videoDevice", device); - } - - public String getVideoDevice() { - return props.getProperty("videoDevice",null); - } - - public boolean isMainWindowAlwaysOnTop() { - return getBoolean("MainWindowAlwaysOnTop", false); - } - - public void setMainWindowAlwaysOnTop(boolean onTop) { - setBoolean("MainWindowAlwaysOnTop", onTop); - } - - public boolean isChatWindowAlwaysOnTop() { - return getBoolean("ChatWindowAlwaysOnTop", false); - } - - public void setChatWindowAlwaysOnTop(boolean onTop) { - setBoolean("ChatWindowAlwaysOnTop", onTop); - } - - public String getSelectedCodecs() { - return getString("SelectedCodecs", null); - } - - public String getStunFallbackHost() - { - return getString("stunFallbackHost", ""); - } - - public int getStunFallbackPort() - { - return getInt("stunFallbackPort", 3478); - } - - public void setStunFallbackHost(String host) { - setString("stunFallbackHost", host); - } - - public void setStunFallbackPort(int port) { - setInt("stunFallbackPort", port); - } - - public boolean getShowTransportTab() - { - return getBoolean("useTabForTransport", false); - } - - public void setShowTransportTab(boolean value) - { - setBoolean("useTabForTransport", value); - } - - public boolean isShowConferenceTab() - { - return getBoolean("useTabForConference", true); - } - - public void setShowConferenceTab(boolean value) - { - setBoolean("useTabForConference", value); - } - - public String getAvailableCodecs() { - return getString("AvailableCodecs", null); - } - - public void setSelectedCodecs(String value) { - setString("SelectedCodecs", value); - } - - public void setAvailableCodecs(String value) { - setString("AvailableCodecs", value); - } - - private boolean getBoolean(String property, boolean defaultValue) { - return Boolean.parseBoolean(props.getProperty(property, Boolean - .toString(defaultValue))); - } - - private void setBoolean(String property, boolean value) { - props.setProperty(property, Boolean.toString(value)); - } - - private int getInt(String property, int defaultValue) { - return Integer.parseInt(props.getProperty(property, Integer - .toString(defaultValue))); - } - - private void setInt(String property, int value) { - props.setProperty(property, Integer.toString(value)); - } - - private String getString(String property, String defaultValue) { - return props.getProperty(property, defaultValue); - } - - private void setString(String property, String value) { - props.setProperty(property, value); - } - - public boolean isAutoAcceptMucInvite() { - return getBoolean("autoAcceptMucInvite", false); - } - - public void setAutoAcceptMucInvite(boolean autoAcceptMuc) { - setBoolean("autoAcceptMucInvite", autoAcceptMuc); - - } - - public String getDefaultBookmarkedConf() { - return props.getProperty("defaultBookmarkedConf"); - } - - public void setDefaultBookmarkedConf(String bookmarkedConferenceJid) { - setString("defaultBookmarkedConf",bookmarkedConferenceJid); - } - - /** - * This will save if themessage-history should be display the messages
        - * by {@link Date} ascending (true) or descending (false) - * - * @param dateIsAsc indicates if the date should be displayed ascending or not - */ - public void setChatHistoryAscending(boolean dateIsAsc){ - setBoolean("HISTORY_SORT_DATEASC", dateIsAsc); - } - - /** - * This will return a {@link Boolean} to indicate if the message-history should display
        - * the messages by {@link Date} ascending (true) or descending (false) - * - * @return an {@link Boolean} that indicates if the message-history should
        - * be displayed ascending or descending - */ - public boolean getChatHistoryAscending(){ - return getBoolean("HISTORY_SORT_DATEASC", true); - } - - /** - * Get the default value for the search period in the - * history transcript plugin - * @param defaultValue the default value for the period - * @return the last value that was set - */ - public String getSearchPeriod(String defaultValue){ - return getString("HISTORY_SEARCH_PERIOD", "defaultValue"); - } - - /** - * Get the defaultVaue for the search period in the - * history transcript period - * @param value the last value that was set - */ - public void setSearchPeriod(String value){ - setString("HISTORY_SEARCH_PERIOD", value); - } - - public List getDeactivatedPlugins() - { - String plugs = getString("deactivatedPlugins", ""); - ArrayList liste = new ArrayList<>(); - - StringTokenizer tokenz = new StringTokenizer(plugs, ","); - - while(tokenz.hasMoreTokens()) - { - String x = tokenz.nextToken(); - liste.add(x); - } - return liste; - } - - public void setDeactivatedPlugins(List list) { - - // [hallo, hallo, hallo, hallo, hallo] - // = - // hallo,hallo,hallo,hallo,hallo - if (list.size() > 0) { - String liste = list.toString().substring(1, - list.toString().length() - 1); - liste = liste.replace(", ", ","); - setString("deactivatedPlugins", liste); - } else { - setString("deactivatedPlugins", ""); - } - - } - - public boolean isUseHostnameAsResource() { - return getBoolean("useHostnameAsResource", false); - } - - public void setUseHostnameAsResource(boolean useHostnameAsResource) { - setBoolean("useHostnameAsResource", useHostnameAsResource); - } - - public boolean isUseVersionAsResource() { - return getBoolean("useVersionAsResource", false); - } - - public void setUseVersionAsResource(boolean useVersionAsResource) { - setBoolean("useVersionAsResource", useVersionAsResource); - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/settings/local/SettingsManager.java b/src/java/org/jivesoftware/sparkimpl/settings/local/SettingsManager.java deleted file mode 100644 index c2431b6cd..000000000 --- a/src/java/org/jivesoftware/sparkimpl/settings/local/SettingsManager.java +++ /dev/null @@ -1,199 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkimpl.settings.local; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -import org.jivesoftware.Spark; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.util.WinRegistry; -import org.jivesoftware.spark.util.log.Log; - - -/** - * Responsbile for the loading and persisting of LocalSettings. - */ -public class SettingsManager { - private static LocalPreferences localPreferences; - - private static List listeners = new ArrayList<>(); - - private static boolean fileExists = false; - - private SettingsManager() { - } - - /** - * Returns the LocalPreferences for this user. - * - * @return the LocalPreferences for this user. - */ - public static LocalPreferences getLocalPreferences() { - if(localPreferences != null){ - return localPreferences; - } - - if (!fileExists) { - fileExists = exists(); - } - - if (!fileExists && localPreferences == null) { - localPreferences = new LocalPreferences(); - saveSettings(); - } - - if (localPreferences == null) { - // Do Initial Load from FileSystem. - getSettingsFile(); - localPreferences = load(); - } - - return localPreferences; - } - - /** - * Persists the settings to the local file system. - */ - public static void saveSettings() { - final Properties props = localPreferences.getProperties(); - - try { - props.store(new FileOutputStream(getSettingsFile()), "Spark Settings"); - } - catch (Exception e) { - Log.error("Error saving settings.", e); - } - - if (localPreferences.getStartOnStartup()) - { - try { - if (Spark.isWindows()) - { - String PROGDIR = Spark.getBinDirectory().getParent(); - File file = new File(PROGDIR + "\\" + SparkRes.getString(SparkRes.EXECUTABLE_NAME)); - if (file.exists()) - { - WinRegistry.createKey( - WinRegistry.HKEY_CURRENT_USER, - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"); - WinRegistry.writeStringValue( - WinRegistry.HKEY_CURRENT_USER, - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", - SparkRes.getString(SparkRes.APP_NAME), - file.getAbsolutePath()); - } - } - } - catch (Exception e) { - e.printStackTrace(); - } - } - else - { - - if (Spark.isWindows()) - { - try { - String run = WinRegistry.readString( - WinRegistry.HKEY_CURRENT_USER, - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", - SparkRes.getString(SparkRes.APP_NAME)); - if (run != null) - { - WinRegistry.deleteValue( - WinRegistry.HKEY_CURRENT_USER, - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", - SparkRes.getString(SparkRes.APP_NAME)); - } - } - catch (Exception e) { - Log.error("Can not delete registry entry",e); - } - } - } - } - - /** - * Return true if the settings file exists. - * - * @return true if the settings file exists.('spark.properties') - */ - public static boolean exists() { - return getSettingsFile().exists(); - } - - /** - * Returns the settings file. - * - * @return the settings file. - */ - public static File getSettingsFile() { - File file = new File(Spark.getSparkUserHome()); - if (!file.exists()) { - file.mkdirs(); - } - return new File(file, "spark.properties"); - } - - - private static LocalPreferences load() { - final Properties props = new Properties(); - try { - props.load(new FileInputStream(getSettingsFile())); - } - catch (IOException e) { - Log.error(e); - return new LocalPreferences(); - } - - // Override with global settings file - File globalSettingsFile = new File("spark.properties"); - if (globalSettingsFile.exists()) { - try { - props.load(new FileInputStream(globalSettingsFile)); - } catch (IOException e) { - Log.error(e); - } - } - - return new LocalPreferences(props); - } - - public static void addPreferenceListener(PreferenceListener listener) { - listeners.add(listener); - } - - public static void removePreferenceListener(PreferenceListener listener) { - listeners.remove(listener); - } - - public static void fireListeners() { - for (PreferenceListener listener : listeners) { - listener.preferencesChanged(localPreferences); - } - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/settings/local/WinRegistryReader.java b/src/java/org/jivesoftware/sparkimpl/settings/local/WinRegistryReader.java deleted file mode 100755 index e02fd2639..000000000 --- a/src/java/org/jivesoftware/sparkimpl/settings/local/WinRegistryReader.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.settings.local; - -import java.io.IOException; -import java.io.InputStream; -import java.io.StringWriter; - -/** - * Class that helps getting the My Documents Folder on Windows via the registry - * - * @author wolf.posdorfer - * - */ -public class WinRegistryReader { - - private static final String REGQUERY_UTIL = "reg query "; - private static final String REGSTR_TOKEN = "REG_SZ"; - - private static final String PERSONAL_FOLDER_CMD = REGQUERY_UTIL - + "\"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\" - + "Explorer\\Shell Folders\" /v Personal"; - - /** - * returns the Path to the "My Documents" folder or null - * - * @return {@link String} - */ - public static String getMyDocumentsFromWinRegistry() { - try { - Process process = Runtime.getRuntime().exec(PERSONAL_FOLDER_CMD); - StreamReader streamreader = new StreamReader(process.getInputStream()); - - streamreader.start(); - process.waitFor(); - streamreader.join(); - - String result = streamreader.getResult(); - int p = result.indexOf(REGSTR_TOKEN); - - if (p == -1) - return null; - - return result.substring(p + REGSTR_TOKEN.length()).trim(); - } catch (Exception e) { - return null; - } - } - - static class StreamReader extends Thread { - private InputStream is; - private StringWriter sw; - - StreamReader(InputStream is) { - this.is = is; - sw = new StringWriter(); - } - - @Override - public void run() { - try { - int c; - while ((c = is.read()) != -1) - sw.write(c); - } catch (IOException e) { - System.err.println(e); - } - } - - String getResult() { - return sw.toString(); - } - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/updater/CheckUpdates.java b/src/java/org/jivesoftware/sparkimpl/updater/CheckUpdates.java deleted file mode 100644 index 804d17ef6..000000000 --- a/src/java/org/jivesoftware/sparkimpl/updater/CheckUpdates.java +++ /dev/null @@ -1,691 +0,0 @@ -/** - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkimpl.updater; - -import com.thoughtworks.xstream.XStream; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.protocol.Protocol; -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.*; -import org.jivesoftware.smack.filter.IQReplyFilter; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.provider.ProviderManager; -import org.jivesoftware.smackx.disco.packet.DiscoverItems; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.ConfirmDialog; -import org.jivesoftware.spark.component.ConfirmDialog.ConfirmListener; -import org.jivesoftware.spark.component.TitlePanel; -import org.jivesoftware.spark.util.BrowserLauncher; -import org.jivesoftware.spark.util.ByteFormat; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.JiveInfo; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; - -import javax.swing.JEditorPane; -import javax.swing.JFrame; -import javax.swing.JOptionPane; -import javax.swing.JProgressBar; -import javax.swing.JScrollPane; -import javax.swing.text.html.HTMLEditorKit; -import javax.swing.UIManager; - -import java.awt.Color; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Calendar; -import java.util.Date; -import java.util.TimerTask; - -public class CheckUpdates { - private String mainUpdateURL; - private JProgressBar bar; - private TitlePanel titlePanel; - private boolean downloadComplete = false; - private boolean cancel = false; - public static boolean UPDATING = false; - private boolean sparkPluginInstalled; - private XStream xstream = new XStream(); - private String sizeText; - - - public CheckUpdates() { - // Set the Jabber IQ Provider for Jabber:iq:spark - ProviderManager.addIQProvider("query", "jabber:iq:spark", new SparkVersion.Provider()); - - // For simplicity, use an alias for the root xml tag - xstream.alias("Version", SparkVersion.class); - - // Specify the main update url for JiveSoftware - this.mainUpdateURL = "http://www.igniterealtime.org/updater/updater"; - - sparkPluginInstalled = isSparkPluginInstalled(SparkManager.getConnection()); - } - - public SparkVersion newBuildAvailable() { - if (!sparkPluginInstalled && !Spark.disableUpdatesOnCustom()) { - // Handle Jivesoftware.org update - return isNewBuildAvailableFromJivesoftware(); - } - else if (sparkPluginInstalled) { - try { - SparkVersion serverVersion = getLatestVersion(SparkManager.getConnection()); - if (isGreater(serverVersion.getVersion(), JiveInfo.getVersion())) { - return serverVersion; - } - } - catch (SmackException | XMPPException.XMPPErrorException e) { - Log.warning( "Unable the check fo new build.", e ); - } - - } - - return null; - } - - - /** - * Returns true if there is a new build available for download. - * - * @return true if there is a new build available for download. - */ - public SparkVersion isNewBuildAvailableFromJivesoftware() { - PostMethod post = new PostMethod(mainUpdateURL); - if (Spark.isWindows()) { - post.addParameter("os", "windows"); - } - else if (Spark.isMac()) { - post.addParameter("os", "mac"); - } - else { - post.addParameter("os", "linux"); - } - -// Properties isBetaCheckingEnabled is now used to indicate if updates are allowed -// // Check to see if the beta should be included. -// LocalPreferences pref = SettingsManager.getLocalPreferences(); -// boolean isBetaCheckingEnabled = pref.isBetaCheckingEnabled(); -// if (isBetaCheckingEnabled) { -// post.addParameter("beta", "true"); -// } - - - Protocol.registerProtocol("https", new Protocol("https", new EasySSLProtocolSocketFactory(), 443)); - HttpClient httpclient = new HttpClient(); - String proxyHost = System.getProperty("http.proxyHost"); - String proxyPort = System.getProperty("http.proxyPort"); - if (ModelUtil.hasLength(proxyHost) && ModelUtil.hasLength(proxyPort)) { - try { - httpclient.getHostConfiguration().setProxy(proxyHost, Integer.parseInt(proxyPort)); - } - catch (NumberFormatException e) { - Log.error(e); - } - } - try { - int result = httpclient.executeMethod(post); - if (result != 200) { - return null; - } - - - String xml = post.getResponseBodyAsString(); - - // Server Version - SparkVersion serverVersion = (SparkVersion)xstream.fromXML(xml); - if (isGreater(serverVersion.getVersion(), JiveInfo.getVersion())) { - return serverVersion; - } - } - catch (IOException e) { - Log.error(e); - } - return null; - } - - - public void downloadUpdate(final File downloadedFile, final SparkVersion version) { - final java.util.Timer timer = new java.util.Timer(); - - // Prepare HTTP post - final GetMethod post = new GetMethod(version.getDownloadURL()); - - // Get HTTP client - Protocol.registerProtocol("https", new Protocol("https", new EasySSLProtocolSocketFactory(), 443)); - final HttpClient httpclient = new HttpClient(); - String proxyHost = System.getProperty("http.proxyHost"); - String proxyPort = System.getProperty("http.proxyPort"); - if (ModelUtil.hasLength(proxyHost) && ModelUtil.hasLength(proxyPort)) { - try { - httpclient.getHostConfiguration().setProxy(proxyHost, Integer.parseInt(proxyPort)); - } - catch (NumberFormatException e) { - Log.error(e); - } - } - - // Execute request - - try { - int result = httpclient.executeMethod(post); - if (result != 200) { - return; - } - - long length = post.getResponseContentLength(); - int contentLength = (int)length; - - bar = new JProgressBar(0, contentLength); - } - catch (IOException e) { - Log.error(e); - } - - final JFrame frame = new JFrame(Res.getString("title.downloading.im.client")); - - frame.setIconImage(SparkRes.getImageIcon(SparkRes.SMALL_MESSAGE_IMAGE).getImage()); - - titlePanel = new TitlePanel(Res.getString("title.upgrading.client"), Res.getString("message.version", version.getVersion()), SparkRes.getImageIcon(SparkRes.SEND_FILE_24x24), true); - - final Thread thread = new Thread( () -> { - try { - InputStream stream = post.getResponseBodyAsStream(); - long size = post.getResponseContentLength(); - ByteFormat formater = new ByteFormat(); - sizeText = formater.format(size); - titlePanel.setDescription(Res.getString("message.version", version.getVersion()) + " \n" + Res.getString("message.file.size", sizeText)); - - - downloadedFile.getParentFile().mkdirs(); - - FileOutputStream out = new FileOutputStream(downloadedFile); - copy(stream, out); - out.close(); - - if (!cancel) { - downloadComplete = true; - promptForInstallation(downloadedFile, Res.getString("title.download.complete"), Res.getString("message.restart.spark")); - } - else { - out.close(); - downloadedFile.delete(); - } - - - UPDATING = false; - frame.dispose(); - } - catch (Exception ex) { - // Nothing to do - } - finally { - timer.cancel(); - // Release current connection to the connection pool once you are done - post.releaseConnection(); - } - } ); - - - frame.getContentPane().setLayout(new GridBagLayout()); - frame.getContentPane().add(titlePanel, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - frame.getContentPane().add(bar, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - JEditorPane pane = new JEditorPane(); - boolean displayContentPane = version.getChangeLogURL() != null || version.getDisplayMessage() != null; - - try { - pane.setEditable(false); - if (version.getChangeLogURL() != null) { - pane.setEditorKit(new HTMLEditorKit()); - pane.setPage(version.getChangeLogURL()); - } - else if (version.getDisplayMessage() != null) { - pane.setText(version.getDisplayMessage()); - } - - if (displayContentPane) { - frame.getContentPane().add(new JScrollPane(pane), new GridBagConstraints(0, 2, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - } - } - catch (IOException e) { - Log.error(e); - } - - frame.getContentPane().setBackground(Color.WHITE); - frame.pack(); - if (displayContentPane) { - frame.setSize(600, 400); - } - else { - frame.setSize(400, 100); - } - frame.setLocationRelativeTo(SparkManager.getMainWindow()); - GraphicUtils.centerWindowOnScreen(frame); - frame.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent windowEvent) { - thread.interrupt(); - cancel = true; - - UPDATING = false; - - if (!downloadComplete) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), Res.getString("message.updating.cancelled"), Res.getString("title.cancelled"), JOptionPane.ERROR_MESSAGE); - } - - } - }); - frame.setVisible(true); - thread.start(); - - - timer.scheduleAtFixedRate(new TimerTask() { - int seconds = 1; - - public void run() { - ByteFormat formatter = new ByteFormat(); - long value = bar.getValue(); - long average = value / seconds; - String text = formatter.format(average) + "/Sec"; - - String total = formatter.format(value); - titlePanel.setDescription(Res.getString("message.version", version.getVersion()) + " \n" + Res.getString("message.file.size", sizeText) + "\n" + Res.getString("message.transfer.rate") + ": " + text + "\n" + Res.getString("message.total.downloaded") + ": " + total); - seconds++; - } - }, 1000, 1000); - } - - /** - * Common code for copy routines. By convention, the streams are - * closed in the same method in which they were opened. Thus, - * this method does not close the streams when the copying is done. - * - * @param in Source stream - * @param out Destination stream - */ - private void copy(final InputStream in, final OutputStream out) { - int read = 0; - - try { - final byte[] buffer = new byte[4096]; - while (!cancel) { - int bytesRead = in.read(buffer); - if (bytesRead < 0) { - break; - } - out.write(buffer, 0, bytesRead); - read += bytesRead; - bar.setValue(read); - } - } - catch (IOException e) { - Log.error(e); - } - } - - /** - * Checks Spark Manager and/or Jive Software for the latest version of Spark. - * - * @param explicit true if the user explicitly asks for the latest version. - * @throws Exception if there is an error during check - */ - public void checkForUpdate(boolean explicit) throws Exception { - if (UPDATING) { - return; - } - - UPDATING = true; - - if (isLocalBuildAvailable()) { - return; - } - - LocalPreferences localPreferences = SettingsManager.getLocalPreferences(); - - //defaults to 7, 0=disabled - int CheckForUpdates = localPreferences.getCheckForUpdates(); - if (CheckForUpdates == 0) { - return; - } - - Date lastChecked = localPreferences.getLastCheckForUpdates(); - if (lastChecked == null) { - lastChecked = new Date(); - // This is the first invocation of Communicator - localPreferences.setLastCheckForUpdates(lastChecked); - SettingsManager.saveSettings(); - } - - // Check to see if it has been a CheckForUpdates (default 7) days - Calendar calendar = Calendar.getInstance(); - calendar.setTime(lastChecked); - calendar.add(Calendar.DATE, CheckForUpdates); - - final Date lastCheckedPlusAPeriod = calendar.getTime(); - - boolean periodOrLonger = new Date().getTime() >= lastCheckedPlusAPeriod.getTime(); - - - if (periodOrLonger || explicit || sparkPluginInstalled) { - - if (!explicit && !localPreferences.isBetaCheckingEnabled()) - { - return; - } - // Check version on server. - lastChecked = new Date(); - localPreferences.setLastCheckForUpdates(lastChecked); - SettingsManager.saveSettings(); - - final SparkVersion serverVersion = newBuildAvailable(); - if (serverVersion == null) { - UPDATING = false; - - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - - if (explicit) { - UIManager.put("OptionPane.okButtonText", Res.getString("ok")); - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), Res.getString("message.no.updates"), Res.getString("title.no.updates"), JOptionPane.INFORMATION_MESSAGE); - } - return; - } - - // Otherwise updates are available - String downloadURL = serverVersion.getDownloadURL(); - String filename = downloadURL.substring(downloadURL.lastIndexOf("/") + 1); - - if (filename.indexOf('=') != -1) { - filename = filename.substring(filename.indexOf('=') + 1); - } - - // Set Download Directory - final File downloadDir = new File(Spark.getSparkUserHome(), "updates"); - downloadDir.mkdirs(); - - // Set file to download. - final File fileToDownload = new File(downloadDir, filename); - if (fileToDownload.exists()) { - fileToDownload.delete(); - } - - ConfirmDialog confirm = new ConfirmDialog(); - confirm.showConfirmDialog(SparkManager.getMainWindow(), Res.getString("title.new.version.available"), - Res.getString("message.new.spark.available", filename), Res.getString("yes"), Res.getString("no"), - null); - confirm.setDialogSize(400, 300); - confirm.setConfirmListener(new ConfirmListener() { - public void yesOption() { - SwingWorker worker = new SwingWorker() { - public Object construct() { - try { - Thread.sleep(50); - } - catch (InterruptedException e) { - Log.error(e); - } - return "ok"; - } - - public void finished() { - if (Spark.isWindows()) { - downloadUpdate(fileToDownload, serverVersion); - } - else { - // Launch browser to download page. - try { - if (sparkPluginInstalled) { - BrowserLauncher.openURL(serverVersion.getDownloadURL()); - } - else { - BrowserLauncher.openURL("http://www.igniterealtime.org/downloads/index.jsp#spark"); - } - } - - catch (Exception e) { - Log.error(e); - } - UPDATING = false; - } - } - - }; - worker.start(); - } - - public void noOption() { - UPDATING = false; - } - }); - } - else { - UPDATING = false; - } - - } - - - /** - * Returns true if the first version number is greater than the second. - * - * @param firstVersion the first version number. - * @param secondVersion the second version number. - * @return returns true if the first version is greater than the second. - */ - public static boolean isGreater(String firstVersion, String secondVersion) { - int indexOne = firstVersion.indexOf("_"); - if (indexOne != -1) { - firstVersion = firstVersion.substring(indexOne + 1); - } - - int indexTwo = secondVersion.indexOf("_"); - if (indexTwo != -1) { - secondVersion = secondVersion.substring(indexTwo + 1); - } - - firstVersion = firstVersion.replaceAll(".online", ""); - secondVersion = secondVersion.replace(".online", ""); - - boolean versionOneBetaOrAlpha = firstVersion.toLowerCase().contains("beta") || firstVersion.toLowerCase().contains("alpha"); - boolean versionTwoBetaOrAlpha = secondVersion.toLowerCase().contains("beta") || secondVersion.toLowerCase().contains("alpha"); - - // Handle case where they are both betas / alphas - if ((versionOneBetaOrAlpha && versionTwoBetaOrAlpha) || (!versionOneBetaOrAlpha && !versionTwoBetaOrAlpha)) { - return firstVersion.compareTo(secondVersion) >= 1; - } - - // Handle the case where version 1 is a beta or alpha - if (versionOneBetaOrAlpha) { - String versionOne = getVersion(firstVersion); - return versionOne.compareTo(secondVersion) >= 1; - } - else if (versionTwoBetaOrAlpha) { - String versionTwo = getVersion(secondVersion); - int result = firstVersion.compareTo(versionTwo); - return result >= 0; - } - - - return firstVersion.compareTo(secondVersion) >= 1; - } - - public static String getVersion(String version) { - int lastIndexOf = version.lastIndexOf("."); - if (lastIndexOf != -1) { - return version.substring(0, lastIndexOf); - } - - return version; - - } - - /** - * Returns the latest version of Spark available via Spark Manager or Jive Software. - * - * @param connection the XMPPConnection to use. - * @return the information for about the latest Spark Client. - * @throws XMPPException If unable to retrieve latest version. - */ - public static SparkVersion getLatestVersion(XMPPConnection connection) throws SmackException, XMPPException.XMPPErrorException - { - SparkVersion request = new SparkVersion(); - request.setType(IQ.Type.get); - request.setTo("updater." + connection.getServiceName()); - - PacketCollector collector = connection.createPacketCollector(new IQReplyFilter( request, connection )); - connection.sendStanza(request); - - - SparkVersion response = collector.nextResult(SmackConfiguration.getDefaultPacketReplyTimeout()); - - // Cancel the collector. - collector.cancel(); - if (response == null) { - throw SmackException.NoResponseException.newWith( connection, collector ); - } - XMPPException.XMPPErrorException.ifHasErrorThenThrow( response ); - - return response; - } - - /** - * Does a service discvery on the server to see if a Spark Manager - * is enabled. - * - * @param con the XMPPConnection to use. - * @return true if Spark Manager is available. - */ - public static boolean isSparkPluginInstalled(XMPPConnection con) { - if (!con.isConnected()) { - return false; - } - - - try { - DiscoverItems items = SparkManager.getSessionManager().getDiscoveredItems(); - for (DiscoverItems.Item item : items.getItems() ) { - if ("Spark Updater".equals(item.getName())) { - return true; - } - } - } - catch (Exception e) { - Log.error(e); - } - - return false; - - } - - /** - * Prompts the user to install the latest Spark. - * - * @param downloadedFile the location of the latest downloaded client. - * @param title the title - * @param message the message - */ - private void promptForInstallation(final File downloadedFile, String title, String message) { - ConfirmDialog confirm = new ConfirmDialog(); - confirm.showConfirmDialog(SparkManager.getMainWindow(), title, - message, Res.getString("yes"), Res.getString("no"), - null); - confirm.setConfirmListener(new ConfirmListener() { - public void yesOption() { - try { - if (Spark.isWindows()) { - Runtime.getRuntime().exec(downloadedFile.getAbsolutePath()); - } - else if (Spark.isMac()) { - Runtime.getRuntime().exec("open " + downloadedFile.getCanonicalPath()); - } - } - catch (IOException e) { - Log.error(e); - } - SparkManager.getMainWindow().shutdown(); - } - - public void noOption() { - - } - }); - } - - /** - * Checks to see if a new version of Spark has already been downloaded by not installed. - * - * @return true if a newer version exists. - */ - private boolean isLocalBuildAvailable() { - // Check the bin directory for previous downloads. If there is a - // newer version of Spark, ask if they wish to install. - if (Spark.isWindows()) { - File binDirectory = Spark.getBinDirectory(); - File[] files = binDirectory.listFiles(); - if (files != null) { - int no = files.length; - for (int i = 0; i < no; i++) { - File file = files[i]; - String fileName = file.getName(); - if (fileName.endsWith(".exe")) { - int index = fileName.indexOf("_"); - - // Add version number - String versionNumber = fileName.substring(index + 1); - int indexOfPeriod = versionNumber.indexOf("."); - - versionNumber = versionNumber.substring(0, indexOfPeriod); - versionNumber = versionNumber.replaceAll("_online", ""); - versionNumber = versionNumber.replaceAll("_", "."); - - boolean isGreater = versionNumber.compareTo(JiveInfo.getVersion()) >= 1; - if (isGreater) { - // Prompt - promptForInstallation(file, Res.getString("title.new.client.available"), Res.getString("message.restart.spark.to.install")); - return true; - } - else { - file.delete(); - } - - } - } - } - } - - return false; - } - - -} diff --git a/src/java/org/jivesoftware/sparkimpl/updater/EasySSLProtocolSocketFactory.java b/src/java/org/jivesoftware/sparkimpl/updater/EasySSLProtocolSocketFactory.java deleted file mode 100644 index 905f23618..000000000 --- a/src/java/org/jivesoftware/sparkimpl/updater/EasySSLProtocolSocketFactory.java +++ /dev/null @@ -1,243 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkimpl.updater; -/* - * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/contrib/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java,v 1.7 2004/06/11 19:26:27 olegk Exp $ - * $Revision$ - * $Date$ - * - * ==================================================================== - * - * Copyright 2002-2004 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - - -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import org.apache.commons.httpclient.ConnectTimeoutException; -import org.apache.commons.httpclient.HttpClientError; -import org.apache.commons.httpclient.params.HttpConnectionParams; -import org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory; -import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; -import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.Socket; -import java.net.UnknownHostException; - -/** - *

        - * EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s - * that accept self-signed certificates. - *

        - *

        - * This socket factory SHOULD NOT be used for productive systems - * due to security reasons, unless it is a concious decision and - * you are perfectly aware of security implications of accepting - * self-signed certificates - *

        - *

        - *

        - * Example of using custom protocol socket factory for a specific host: - *

        - *     Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
        - * 

        - * HttpClient client = new HttpClient(); - * client.getHostConfiguration().setHost("localhost", 443, easyhttps); - * // use relative url only - * GetMethod httpget = new GetMethod("/"); - * client.executeMethod(httpget); - *

        - *

        - *

        - * Example of using custom protocol socket factory per default instead of the standard one: - *

        - *     Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
        - *     Protocol.registerProtocol("https", easyhttps);
        - * 

        - * HttpClient client = new HttpClient(); - * GetMethod httpget = new GetMethod("https://localhost/"); - * client.executeMethod(httpget); - *

        - *

        - * - * @author Oleg Kalnichevski - *

        - *

        - * DISCLAIMER: HttpClient developers DO NOT actively support this component. - * The component is provided as a reference material, which may be inappropriate - * for use without additional customization. - *

        - */ - -public class EasySSLProtocolSocketFactory implements ProtocolSocketFactory { - - /** - * Log object for this class. - */ - private static final Log LOG = LogFactory.getLog(EasySSLProtocolSocketFactory.class); - - private SSLContext sslcontext = null; - - /** - * Constructor for EasySSLProtocolSocketFactory. - */ - public EasySSLProtocolSocketFactory() { - super(); - } - - private static SSLContext createEasySSLContext() { - try { - SSLContext context = SSLContext.getInstance("SSL"); - context.init( - null, - new TrustManager[]{new EasyX509TrustManager(null)}, - null); - return context; - } - catch (Exception e) { - LOG.error(e.getMessage(), e); - throw new HttpClientError(e.toString()); - } - } - - private SSLContext getSSLContext() { - if (this.sslcontext == null) { - this.sslcontext = createEasySSLContext(); - } - return this.sslcontext; - } - - /** - * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int) - */ - public Socket createSocket( - String host, - int port, - InetAddress clientHost, - int clientPort) - throws IOException { - - return getSSLContext().getSocketFactory().createSocket( - host, - port, - clientHost, - clientPort - ); - } - - /** - * Attempts to get a new socket connection to the given host within the given time limit. - *

        - * To circumvent the limitations of older JREs that do not support connect timeout a - * controller thread is executed. The controller thread attempts to create a new socket - * within the given limit of time. If socket constructor does not return until the - * timeout expires, the controller terminates and throws an {@link ConnectTimeoutException} - *

        - * - * @param host the host name/IP - * @param port the port on the host - * @param params {@link HttpConnectionParams Http connection parameters} - * @return Socket a new socket - * @throws IOException if an I/O error occurs while creating the socket - * @throws UnknownHostException if the IP address of the host cannot be - * determined - */ - public Socket createSocket( - final String host, - final int port, - final InetAddress localAddress, - final int localPort, - final HttpConnectionParams params - ) throws IOException { - if (params == null) { - throw new IllegalArgumentException("Parameters may not be null"); - } - int timeout = params.getConnectionTimeout(); - if (timeout == 0) { - return createSocket(host, port, localAddress, localPort); - } - else { - // To be eventually deprecated when migrated to Java 1.4 or above - return ControllerThreadSocketFactory.createSocket( - this, host, port, localAddress, localPort, timeout); - } - } - - /** - * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int) - */ - public Socket createSocket(String host, int port) - throws IOException { - return getSSLContext().getSocketFactory().createSocket( - host, - port - ); - } - - /** - * @see SecureProtocolSocketFactory#createSocket(java.net.Socket, String, int, boolean) - */ - public Socket createSocket( - Socket socket, - String host, - int port, - boolean autoClose) - throws IOException { - return getSSLContext().getSocketFactory().createSocket( - socket, - host, - port, - autoClose - ); - } - - public boolean equals(Object obj) { - return ((obj != null) && obj.getClass().equals(EasySSLProtocolSocketFactory.class)); - } - - public int hashCode() { - return EasySSLProtocolSocketFactory.class.hashCode(); - } - -} diff --git a/src/java/org/jivesoftware/sparkimpl/updater/EasyX509TrustManager.java b/src/java/org/jivesoftware/sparkimpl/updater/EasyX509TrustManager.java deleted file mode 100644 index 8ba1a7559..000000000 --- a/src/java/org/jivesoftware/sparkimpl/updater/EasyX509TrustManager.java +++ /dev/null @@ -1,126 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkimpl.updater; - -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; - -/** - *

        - * EasyX509TrustManager unlike default {@link X509TrustManager} accepts - * self-signed certificates. - *

        - *

        - * This trust manager SHOULD NOT be used for productive systems - * due to security reasons, unless it is a concious decision and - * you are perfectly aware of security implications of accepting - * self-signed certificates - *

        - * - * @author Adrian Sutton - * @author Oleg Kalnichevski - *

        - *

        - * DISCLAIMER: HttpClient developers DO NOT actively support this component. - * The component is provided as a reference material, which may be inappropriate - * for use without additional customization. - *

        - */ - -public class EasyX509TrustManager implements X509TrustManager { - private X509TrustManager standardTrustManager = null; - - /** - * Log object for this class. - */ - private static final Log LOG = LogFactory.getLog(EasyX509TrustManager.class); - - public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException { - super(); - TrustManagerFactory factory = TrustManagerFactory.getInstance("SunX509"); - factory.init(keystore); - TrustManager[] trustmanagers = factory.getTrustManagers(); - if (trustmanagers.length == 0) { - throw new NoSuchAlgorithmException("SunX509 trust manager not supported"); - } - this.standardTrustManager = (X509TrustManager)trustmanagers[0]; - } - - public boolean isClientTrusted(X509Certificate[] certificates) { - try { - this.standardTrustManager.checkClientTrusted(certificates, null); - return true; - } - catch (CertificateException e) { - return false; - } - } - - public boolean isServerTrusted(X509Certificate[] certificates) { - if ((certificates != null) && LOG.isDebugEnabled()) { - LOG.debug("Server certificate chain:"); - for (int i = 0; i < certificates.length; i++) { - LOG.debug("X509Certificate[" + i + "]=" + certificates[i]); - } - } - if ((certificates != null) && (certificates.length == 1)) { - X509Certificate certificate = certificates[0]; - try { - certificate.checkValidity(); - } - catch (CertificateException e) { - LOG.error(e.toString()); - return false; - } - return true; - } - else { - try { - this.standardTrustManager.checkServerTrusted(certificates, null); - return true; - } - catch (CertificateException e) { - return false; - } - } - } - - public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { - } - - public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { - } - - /** - * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers() - */ - public X509Certificate[] getAcceptedIssuers() { - return this.standardTrustManager.getAcceptedIssuers(); - } -} diff --git a/src/java/org/jivesoftware/sparkimpl/updater/SparkVersion.java b/src/java/org/jivesoftware/sparkimpl/updater/SparkVersion.java deleted file mode 100644 index d4a45678e..000000000 --- a/src/java/org/jivesoftware/sparkimpl/updater/SparkVersion.java +++ /dev/null @@ -1,160 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkimpl.updater; - -import org.jivesoftware.Spark; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.provider.IQProvider; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.util.Date; - -public class SparkVersion extends IQ { - - private String version; - private long updateTime; - private String downloadURL; - private String displayMessage; - private String changeLogURL; - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public Date getUpdateTime() { - return new Date(updateTime); - } - - public void setUpdateTime(long updateTime) { - this.updateTime = updateTime; - } - - public String getDownloadURL() { - return downloadURL; - } - - public void setDownloadURL(String downloadURL) { - this.downloadURL = downloadURL; - } - - public String getDisplayMessage() { - return displayMessage; - } - - public void setDisplayMessage(String displayMessage) { - this.displayMessage = displayMessage; - } - - public String getChangeLogURL() { - return changeLogURL; - } - - public void setChangeLogURL(String changeLogURL) { - this.changeLogURL = changeLogURL; - } - - - /** - * Element name of the packet extension. - */ - public static final String ELEMENT_NAME = "query"; - - /** - * Namespace of the packet extension. - */ - public static final String NAMESPACE = "jabber:iq:spark"; - - public SparkVersion() { - super( ELEMENT_NAME, NAMESPACE); - } - - @Override - protected IQChildElementXmlStringBuilder getIQChildElementBuilder( IQChildElementXmlStringBuilder buf) - { - buf.rightAngleBracket(); - buf.append(""); - - // Add os specific information - - if (Spark.isWindows()) { - buf.append("windows"); - } - else if (Spark.isMac()) { - buf.append("mac"); - } - else { - buf.append("linux"); - } - - buf.append(""); - return buf; - } - - /** - * An IQProvider for SparkVersion packets. - * - * @author Derek DeMoro - */ - public static class Provider extends IQProvider { - - public Provider() { - super(); - } - - public SparkVersion parse(XmlPullParser parser, int i) throws XmlPullParserException, IOException{ - SparkVersion version = new SparkVersion(); - - boolean done = false; - while (!done) { - int eventType = parser.next(); - if (eventType == XmlPullParser.START_TAG) { - if (parser.getName().equals("version")) { - version.setVersion(parser.nextText()); - } - else if (parser.getName().equals("updatedTime")) { - Long time = Long.valueOf(parser.nextText()); - version.setUpdateTime(time); - } - else if (parser.getName().equals("downloadURL")) { - version.setDownloadURL(parser.nextText()); - } - else if (parser.getName().equals("displayMessage")) { - version.setDisplayMessage(parser.nextText()); - } - } - - else if (eventType == XmlPullParser.END_TAG) { - if (parser.getName().equals(ELEMENT_NAME)) { - done = true; - } - } - } - - return version; - } - } -} diff --git a/src/jtattoo/JTattoo.license b/src/jtattoo/JTattoo.license deleted file mode 100644 index 157e69f9f..000000000 --- a/src/jtattoo/JTattoo.license +++ /dev/null @@ -1,21 +0,0 @@ -Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. - -JTattoo is multiple licensed. If your are an open source developer you can use -it under the terms and conditions of the GNU General Public License version 2.0 -or later as published by the Free Software Foundation. - -see: gpl-2.0.txt - -If you pay for a license you will become a registered user who could use the -software under the terms and conditions of the GNU Lesser General Public License -version 2.0 or later with classpath exception as published by the Free Software -Foundation. - -see: lgpl-2.0.txt -see: classpath-exception.txt - -Registered users could also use JTattoo under the terms and conditions of the -Apache License, Version 2.0 as published by the Apache Software Foundation. - -see: APACHE-LICENSE-2.0.txt - \ No newline at end of file diff --git a/src/jtattoo/build/MANIFEST.MF b/src/jtattoo/build/MANIFEST.MF deleted file mode 100644 index 3084d577a..000000000 --- a/src/jtattoo/build/MANIFEST.MF +++ /dev/null @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -Created-By: NetBeans IDE -Specified-By: JTattoo.jarContent -Main-Class: com.jtattoo.plaf.About - diff --git a/src/jtattoo/build/build.xml b/src/jtattoo/build/build.xml deleted file mode 100644 index a86c99d02..000000000 --- a/src/jtattoo/build/build.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/jtattoo/src/com/jtattoo/plaf/About.java b/src/jtattoo/src/com/jtattoo/plaf/About.java deleted file mode 100644 index 5e1dfc5a0..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/About.java +++ /dev/null @@ -1,92 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; - -/** - * - * @author Michael Hagen - */ - -// TODO: -// - Auf dem Mac scheint es ein Problem mit dem zeichnen des Aluminium Hintergrunds zu geben -// - setMaximizedBounds unter Linux bei multiscreen Umgebungen funktioniert nicht. Aus diesem Grund -// wird in Linux die Toolbar beim maximieren verdeckt (siehe BaseTitlePane maximize) -public class About extends JDialog { - - public static String JTATTOO_VERSION = "Version: 1.6.9"; - - private static final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - private static final Dimension dlgSize = new Dimension(440, 240); - private static int dlgPosX = (screenSize.width / 2) - (dlgSize.width / 2); - private static int dlgPosY = (screenSize.height / 2) - (dlgSize.height / 2); - - public About() { - super((JFrame) null, "About JTattoo"); - JPanel contentPanel = new JPanel(null); - JLabel titleLabel = new JLabel("JTattoo " + JTATTOO_VERSION); - titleLabel.setFont(new Font("Arial", Font.BOLD, 24)); - titleLabel.setBounds(0, 20, dlgSize.width - 8, 36); - titleLabel.setHorizontalAlignment(JLabel.CENTER); - contentPanel.add(titleLabel); - - JLabel copyrightLabel = new JLabel("(c) 2002 and later by MH Software-Entwicklung"); - copyrightLabel.setBounds(0, 80, dlgSize.width - 8, 20); - copyrightLabel.setHorizontalAlignment(JLabel.CENTER); - contentPanel.add(copyrightLabel); - - JButton okButton = new JButton("OK"); - okButton.setBounds((dlgSize.width - 80) / 2, 170, 80, 24); - contentPanel.add(okButton); - - setContentPane(contentPanel); - - addWindowListener(new WindowAdapter() { - - public void windowClosing(WindowEvent ev) { - System.exit(0); - } - }); - - okButton.addActionListener( ev -> System.exit(0) ); - } - - /** Starten der Anwendung - * @param args the command line arguments - */ - public static void main(String args[]) { - try { - UIManager.setLookAndFeel("com.jtattoo.plaf.mcwin.McWinLookAndFeel"); - About dlg = new About(); - dlg.setSize(dlgSize); - dlg.setLocation(dlgPosX, dlgPosY); - dlg.setVisible(true); - } catch (Exception ex) { - ex.printStackTrace(); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/AbstractBorderFactory.java b/src/jtattoo/src/com/jtattoo/plaf/AbstractBorderFactory.java deleted file mode 100644 index e7c82974d..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/AbstractBorderFactory.java +++ /dev/null @@ -1,71 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import javax.swing.border.Border; - -/** - * @author Michael Hagen - */ -public interface AbstractBorderFactory { - - public Border getFocusFrameBorder(); - - public Border getButtonBorder(); - - public Border getToggleButtonBorder(); - - public Border getTextBorder(); - - public Border getSpinnerBorder(); - - public Border getTextFieldBorder(); - - public Border getComboBoxBorder(); - - public Border getTableHeaderBorder(); - - public Border getTableScrollPaneBorder(); - - public Border getScrollPaneBorder(); - - public Border getTabbedPaneBorder(); - - public Border getMenuBarBorder(); - - public Border getMenuItemBorder(); - - public Border getPopupMenuBorder(); - - public Border getInternalFrameBorder(); - - public Border getPaletteBorder(); - - public Border getToolBarBorder(); - - public Border getDesktopIconBorder(); - - public Border getProgressBarBorder(); -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/AbstractIconFactory.java b/src/jtattoo/src/com/jtattoo/plaf/AbstractIconFactory.java deleted file mode 100644 index c170169e0..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/AbstractIconFactory.java +++ /dev/null @@ -1,116 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public interface AbstractIconFactory { - - public Icon getOptionPaneErrorIcon(); - - public Icon getOptionPaneWarningIcon(); - - public Icon getOptionPaneInformationIcon(); - - public Icon getOptionPaneQuestionIcon(); - - public Icon getFileChooserDetailViewIcon(); - - public Icon getFileChooserHomeFolderIcon(); - - public Icon getFileChooserListViewIcon(); - - public Icon getFileChooserNewFolderIcon(); - - public Icon getFileChooserUpFolderIcon(); - - public Icon getMenuIcon(); - - public Icon getIconIcon(); - - public Icon getMaxIcon(); - - public Icon getMinIcon(); - - public Icon getCloseIcon(); - - public Icon getPaletteCloseIcon(); - - public Icon getRadioButtonIcon(); - - public Icon getCheckBoxIcon(); - - public Icon getComboBoxIcon(); - - public Icon getTreeComputerIcon(); - - public Icon getTreeFloppyDriveIcon(); - - public Icon getTreeHardDriveIcon(); - - public Icon getTreeFolderIcon(); - - public Icon getTreeLeafIcon(); - - public Icon getTreeCollapsedIcon(); - - public Icon getTreeExpandedIcon(); - - public Icon getMenuArrowIcon(); - - public Icon getMenuCheckBoxIcon(); - - public Icon getMenuRadioButtonIcon(); - - public Icon getUpArrowIcon(); - - public Icon getDownArrowIcon(); - - public Icon getLeftArrowIcon(); - - public Icon getRightArrowIcon(); - - public Icon getSplitterUpArrowIcon(); - - public Icon getSplitterDownArrowIcon(); - - public Icon getSplitterLeftArrowIcon(); - - public Icon getSplitterRightArrowIcon(); - - public Icon getSplitterHorBumpIcon(); - - public Icon getSplitterVerBumpIcon(); - - public Icon getThumbHorIcon(); - - public Icon getThumbVerIcon(); - - public Icon getThumbHorIconRollover(); - - public Icon getThumbVerIconRollover(); -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/AbstractLookAndFeel.java b/src/jtattoo/src/com/jtattoo/plaf/AbstractLookAndFeel.java deleted file mode 100644 index 4c523a94d..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/AbstractLookAndFeel.java +++ /dev/null @@ -1,686 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.Color; -import java.util.ArrayList; -import javax.swing.*; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.InsetsUIResource; -import javax.swing.plaf.metal.MetalLookAndFeel; -import javax.swing.plaf.metal.MetalTheme; - -/** - * @author Michael Hagen - */ -abstract public class AbstractLookAndFeel extends MetalLookAndFeel { - - // Workaround to avoid a bug in the java 1.3 VM - static { - try { - if (JTattooUtilities.getJavaVersion() < 1.4) { - UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); - } - } catch (Exception ex) { - } - } - - private static AbstractTheme myTheme = null; - - abstract public AbstractBorderFactory getBorderFactory(); - - abstract public AbstractIconFactory getIconFactory(); - - protected void initSystemColorDefaults(UIDefaults table) { - Object[] systemColors = { - "desktop", getDesktopColor(), // Color of the desktop background - - "activeCaption", getWindowTitleBackgroundColor(), // Color for captions (title bars) when they are active. - "activeCaptionLight", getWindowTitleColorLight(), - "activeCaptionDark", getWindowTitleColorDark(), - "activeCaptionText", getWindowTitleForegroundColor(), // Text color for text in captions (title bars). - "activeCaptionBorder", getWindowBorderColor(), // Border color for caption (title bar) window borders. - - "inactiveCaption", getWindowInactiveTitleBackgroundColor(), // Color for captions (title bars) when not active. - "inactiveCaptionLight", getWindowInactiveTitleColorLight(), // - "inactiveCaptionDark", getWindowInactiveTitleColorDark(), // - "inactiveCaptionText", getWindowInactiveTitleForegroundColor(), // Text color for text in inactive captions (title bars). - "inactiveCaptionBorder", getWindowInactiveBorderColor(), // Border color for inactive caption (title bar) window borders. - - "window", getInputBackgroundColor(), // Default color for the interior of windows, list, tree etc - "windowBorder", getBackgroundColor(), // ??? - "windowText", getControlForegroundColor(), // ??? - - "menu", getMenuBackgroundColor(), // Background color for menus - "menuText", getMenuForegroundColor(), // Text color for menus - "MenuBar.rolloverEnabled", Boolean.TRUE, - - "text", getBackgroundColor(), // Text background color - "textText", getControlForegroundColor(), // Text foreground color - "textHighlight", getSelectionBackgroundColor(), // Text background color when selected - "textHighlightText", getSelectionForegroundColor(), // Text color when selected - "textInactiveText", getDisabledForegroundColor(), // Text color when disabled - - "control", getControlBackgroundColor(), // Default color for controls (buttons, sliders, etc) - "controlText", getControlForegroundColor(), // Default color for text in controls - "controlHighlight", getControlHighlightColor(), // Specular highlight (opposite of the shadow) - "controlLtHighlight", getControlHighlightColor(), // Highlight color for controls - "controlShadow", getControlShadowColor(), // Shadow color for controls - "controlDkShadow", getControlDarkShadowColor(), // Dark shadow color for controls - - "scrollbar", getControlBackgroundColor(), // Scrollbar background (usually the "track") - "info", getTooltipBackgroundColor(), // ToolTip Background - "infoText", getTooltipForegroundColor() // ToolTip Text - }; - - for (int i = 0; i < systemColors.length; i += 2) { - table.put( systemColors[i], systemColors[i + 1]); - } - } - - protected void initComponentDefaults(UIDefaults table) { - super.initComponentDefaults(table); - - BaseBorders.initDefaults(); - BaseIcons.initDefaults(); - - Object textFieldBorder = getBorderFactory().getTextFieldBorder(); - Object comboBoxBorder = getBorderFactory().getComboBoxBorder(); - Object scrollPaneBorder = getBorderFactory().getScrollPaneBorder(); - Object tableScrollPaneBorder = getBorderFactory().getTableScrollPaneBorder(); - Object tabbedPaneBorder = getBorderFactory().getTabbedPaneBorder(); - Object buttonBorder = getBorderFactory().getButtonBorder(); - Object toggleButtonBorder = getBorderFactory().getToggleButtonBorder(); - Object titledBorderBorder = new UIDefaults.ProxyLazyValue("javax.swing.plaf.BorderUIResource$LineBorderUIResource", new Object[]{getFrameColor()}); - Object menuBarBorder = getBorderFactory().getMenuBarBorder(); - Object popupMenuBorder = getBorderFactory().getPopupMenuBorder(); - Object menuItemBorder = getBorderFactory().getMenuItemBorder(); - Object toolBarBorder = getBorderFactory().getToolBarBorder(); - Object progressBarBorder = getBorderFactory().getProgressBarBorder(); - Object toolTipBorder = new UIDefaults.ProxyLazyValue("javax.swing.plaf.BorderUIResource$LineBorderUIResource", new Object[]{getFrameColor()}); - Object focusCellHighlightBorder = new UIDefaults.ProxyLazyValue("javax.swing.plaf.BorderUIResource$LineBorderUIResource", new Object[]{getFocusCellColor()}); - Object optionPaneBorder = BorderFactory.createEmptyBorder(0, 0, 0, 0); - Object optionPaneMessageAreaBorder = BorderFactory.createEmptyBorder(8, 8, 8, 8); - Object optionPaneButtonAreaBorder = BorderFactory.createEmptyBorder(0, 8, 8, 8); - Object windowBorder = getBorderFactory().getInternalFrameBorder(); - - Color c = getBackgroundColor(); - ColorUIResource progressBarBackground = new ColorUIResource(ColorHelper.brighter(c, 20)); - - // DEFAULTS TABLE - Object[] defaults = { - "controlTextFont", getControlTextFont(), - "systemTextFont ", getSystemTextFont(), - "userTextFont", getUserTextFont(), - "menuTextFont", getMenuTextFont(), - "windowTitleFont", getWindowTitleFont(), - "subTextFont", getSubTextFont(), - - "Label.font", getUserTextFont(), - "Label.background", getBackgroundColor(), - "Label.foreground", getForegroundColor(), - "Label.disabledText", getDisabledForegroundColor(), - "Label.disabledShadow", getWhite(), - // Text (Note: many are inherited) - "TextField.border", textFieldBorder, - "TextField.foreground", getInputForegroundColor(), - "TextField.background", getInputBackgroundColor(), - "TextField.disabledForeground", getDisabledForegroundColor(), - "TextField.disabledBackground", getDisabledBackgroundColor(), - "TextField.inactiveForeground", getDisabledForegroundColor(), - "TextField.inactiveBackground", getDisabledBackgroundColor(), - "TextArea.foreground", getInputForegroundColor(), - "TextArea.background", getInputBackgroundColor(), - "TextArea.disabledForeground", getDisabledForegroundColor(), - "TextArea.disabledBackground", getDisabledBackgroundColor(), - "TextArea.inactiveForeground", getDisabledForegroundColor(), - "TextArea.inactiveBackground", getDisabledBackgroundColor(), - "EditorPane.foreground", getInputForegroundColor(), - "EditorPane.background", getInputBackgroundColor(), - "EditorPane.disabledForeground", getDisabledForegroundColor(), - "EditorPane.disabledBackground", getDisabledBackgroundColor(), - "EditorPane.inactiveForeground", getDisabledForegroundColor(), - "EditorPane.inactiveBackground", getDisabledBackgroundColor(), - "FormattedTextField.border", textFieldBorder, - "FormattedTextField.foreground", getInputForegroundColor(), - "FormattedTextField.background", getInputBackgroundColor(), - "FormattedTextField.disabledForeground", getDisabledForegroundColor(), - "FormattedTextField.disabledBackground", getDisabledBackgroundColor(), - "FormattedTextField.inactiveForeground", getDisabledForegroundColor(), - "FormattedTextField.inactiveBackground", getDisabledBackgroundColor(), - "PasswordField.border", textFieldBorder, - "PasswordField.foreground", getInputForegroundColor(), - "PasswordField.background", getInputBackgroundColor(), - "PasswordField.disabledForeground", getDisabledForegroundColor(), - "PasswordField.disabledBackground", getDisabledBackgroundColor(), - "PasswordField.inactiveForeground", getDisabledForegroundColor(), - "PasswordField.inactiveBackground", getDisabledBackgroundColor(), - // Buttons - "Button.background", getButtonBackgroundColor(), - "Button.foreground", getButtonForegroundColor(), - "Button.disabledText", getDisabledForegroundColor(), - "Button.disabledShadow", getWhite(), - "Button.select", getSelectionBackgroundColor(), - "Button.border", buttonBorder, - "Button.frame", getFrameColor(), - "Button.focus", getFocusColor(), - "Button.rolloverColor", getTheme().getRolloverColor(), - "CheckBox.font", getUserTextFont(), - "CheckBox.background", getBackgroundColor(), - "CheckBox.foreground", getForegroundColor(), - "CheckBox.disabledText", getDisabledForegroundColor(), - "CheckBox.disabledShadow", getWhite(), - "Checkbox.select", getSelectionBackgroundColor(), - "CheckBox.focus", getFocusColor(), - "CheckBox.icon", getIconFactory().getCheckBoxIcon(), - "RadioButton.font", getUserTextFont(), - "RadioButton.background", getBackgroundColor(), - "RadioButton.foreground", getForegroundColor(), - "RadioButton.disabledText", getDisabledForegroundColor(), - "RadioButton.disabledShadow", getWhite(), - "RadioButton.select", getSelectionBackgroundColor(), - "RadioButton.icon", getIconFactory().getRadioButtonIcon(), - "RadioButton.focus", getFocusColor(), - "ToggleButton.background", getButtonBackgroundColor(), - "ToggleButton.foreground", getButtonForegroundColor(), - "ToggleButton.select", getSelectionBackgroundColor(), - "ToggleButton.text", getButtonForegroundColor(), - "ToggleButton.disabledText", getDisabledForegroundColor(), - "ToggleButton.disabledShadow", getWhite(), - "ToggleButton.disabledSelectedText", getDisabledForegroundColor(), - "ToggleButton.disabledBackground", getButtonBackgroundColor(), - "ToggleButton.disabledSelectedBackground", getSelectionBackgroundColor(), - "ToggleButton.focus", getFocusColor(), - "ToggleButton.border", toggleButtonBorder, - // ToolTip - "ToolTip.border", toolTipBorder, - "ToolTip.foreground", getTooltipForegroundColor(), - "ToolTip.background", getTooltipBackgroundColor(), - // Slider - "Slider.border", null, - "Slider.foreground", getFrameColor(), - "Slider.background", getBackgroundColor(), - "Slider.focus", getFocusColor(), - "Slider.focusInsets", new InsetsUIResource(0, 0, 0, 0), - "Slider.trackWidth", new Integer(7), - "Slider.majorTickLength", new Integer(6), - // Progress Bar - "ProgressBar.border", progressBarBorder, - "ProgressBar.background", progressBarBackground, - "ProgressBar.selectionForeground", getSelectionForegroundColor(), - "ProgressBar.selectionBackground", getForegroundColor(), - // Combo Box - "ComboBox.border", comboBoxBorder, - "ComboBox.background", getInputBackgroundColor(), - "ComboBox.foreground", getInputForegroundColor(), - "ComboBox.selectionBackground", getSelectionBackgroundColor(), - "ComboBox.selectionForeground", getSelectionForegroundColor(), - "ComboBox.selectionBorderColor", getFocusColor(), - "ComboBox.disabledBackground", getDisabledBackgroundColor(), - "ComboBox.disabledForeground", getDisabledForegroundColor(), - "ComboBox.listBackground", getInputBackgroundColor(), - "ComboBox.listForeground", getInputForegroundColor(), - "ComboBox.font", getUserTextFont(), - // Panel - "Panel.foreground", getForegroundColor(), - "Panel.background", getBackgroundColor(), - "Panel.darkBackground", getTheme().getBackgroundColorDark(), - "Panel.lightBackground", getTheme().getBackgroundColorLight(), - "Panel.alterBackground", getTheme().getAlterBackgroundColor(), - "Panel.font", getUserTextFont(), - // RootPane - "RootPane.frameBorder", windowBorder, - "RootPane.plainDialogBorder", windowBorder, - "RootPane.informationDialogBorder", windowBorder, - "RootPane.errorDialogBorder", windowBorder, - "RootPane.colorChooserDialogBorder", windowBorder, - "RootPane.fileChooserDialogBorder", windowBorder, - "RootPane.questionDialogBorder", windowBorder, - "RootPane.warningDialogBorder", windowBorder, - // InternalFrame - "InternalFrame.border", getBorderFactory().getInternalFrameBorder(), - "InternalFrame.font", getWindowTitleFont(), - "InternalFrame.paletteBorder", getBorderFactory().getPaletteBorder(), - "InternalFrame.paletteTitleHeight", new Integer(11), - "InternalFrame.paletteCloseIcon", getIconFactory().getPaletteCloseIcon(), - "InternalFrame.icon", getIconFactory().getMenuIcon(), - "InternalFrame.iconifyIcon", getIconFactory().getIconIcon(), - "InternalFrame.maximizeIcon", getIconFactory().getMaxIcon(), - "InternalFrame.minimizeIcon", getIconFactory().getMinIcon(), - "InternalFrame.closeIcon", getIconFactory().getCloseIcon(), - - // Titled Border - "TitledBorder.titleColor", getForegroundColor(), - "TitledBorder.border", titledBorderBorder, - // List - "List.focusCellHighlightBorder", focusCellHighlightBorder, - "List.font", getUserTextFont(), - "List.foreground", getInputForegroundColor(), - "List.background", getInputBackgroundColor(), - "List.selectionForeground", getSelectionForegroundColor(), - "List.selectionBackground", getSelectionBackgroundColor(), - "List.disabledForeground", getDisabledForegroundColor(), - "List.disabledBackground", getDisabledBackgroundColor(), - // ScrollBar - "ScrollBar.background", getControlBackgroundColor(), - "ScrollBar.highlight", getControlHighlightColor(), - "ScrollBar.shadow", getControlShadowColor(), - "ScrollBar.darkShadow", getControlDarkShadowColor(), - "ScrollBar.thumb", getControlBackgroundColor(), - "ScrollBar.thumbShadow", getControlShadowColor(), - "ScrollBar.thumbHighlight", getControlHighlightColor(), - "ScrollBar.width", new Integer(17), - "ScrollBar.allowsAbsolutePositioning", Boolean.TRUE, - // ScrollPane - "ScrollPane.border", scrollPaneBorder, - "ScrollPane.foreground", getForegroundColor(), - "ScrollPane.background", getBackgroundColor(), - // Viewport - "Viewport.foreground", getForegroundColor(), - "Viewport.background", getBackgroundColor(), - "Viewport.font", getUserTextFont(), - - // Tabbed Pane - "TabbedPane.boder", tabbedPaneBorder, - "TabbedPane.background", getBackgroundColor(), - "TabbedPane.tabAreaBackground", getTabAreaBackgroundColor(), - "TabbedPane.unselectedBackground", getControlColorDark(), - "TabbedPane.foreground", getControlForegroundColor(), - "TabbedPane.selected", getBackgroundColor(), - "TabbedPane.selectedForeground", getTabSelectionForegroundColor(), - "TabbedPane.tabAreaInsets", new InsetsUIResource(5, 5, 5, 5), - "TabbedPane.contentBorderInsets", new InsetsUIResource(0, 0, 0, 0), - "TabbedPane.tabInsets", new InsetsUIResource(1, 6, 1, 6), - "TabbedPane.focus", getFocusColor(), - // TabbedPane ScrollButton - "TabbedPane.selected", getButtonBackgroundColor(), - "TabbedPane.shadow", new ColorUIResource(180, 180, 180), - "TabbedPane.darkShadow", new ColorUIResource(120, 120, 120), - "TabbedPane.highlight", new ColorUIResource(Color.white), - // Tab Colors in Netbeans - "tab_unsel_fill", getControlBackgroundColor(), - "tab_sel_fill", getControlBackgroundColor(), - // Table - "Table.focusCellHighlightBorder", focusCellHighlightBorder, - "Table.scrollPaneBorder", tableScrollPaneBorder, - "Table.foreground", getInputForegroundColor(), - "Table.background", getInputBackgroundColor(), - "Table.gridColor", getGridColor(), - "TableHeader.foreground", getControlForegroundColor(), - "TableHeader.background", getBackgroundColor(), - "TableHeader.cellBorder", getBorderFactory().getTableHeaderBorder(), - // MenuBar - "MenuBar.border", menuBarBorder, - "MenuBar.foreground", getMenuForegroundColor(), - "MenuBar.background", getMenuBackgroundColor(), - // Menu - "Menu.border", menuItemBorder, - "Menu.borderPainted", Boolean.TRUE, - "Menu.foreground", getMenuForegroundColor(), - "Menu.background", getMenuBackgroundColor(), - "Menu.selectionForeground", getMenuSelectionForegroundColor(), - "Menu.selectionBackground", getMenuSelectionBackgroundColor(), - "Menu.disabledForeground", getDisabledForegroundColor(), - "Menu.acceleratorForeground", getMenuForegroundColor(), - "Menu.acceleratorSelectionForeground", getMenuSelectionForegroundColor(), - "Menu.arrowIcon", getIconFactory().getMenuArrowIcon(), - // Popup Menu - "PopupMenu.background", getMenuBackgroundColor(), - "PopupMenu.border", popupMenuBorder, - // Menu Item - "MenuItem.border", menuItemBorder, - "MenuItem.borderPainted", Boolean.TRUE, - "MenuItem.foreground", getMenuForegroundColor(), - "MenuItem.background", getMenuBackgroundColor(), - "MenuItem.selectionForeground", getMenuSelectionForegroundColor(), - "MenuItem.selectionBackground", getMenuSelectionBackgroundColor(), - "MenuItem.disabledForeground", getDisabledForegroundColor(), - "MenuItem.disabledShadow", getWhite(), - "MenuItem.acceleratorForeground", getMenuForegroundColor(), - "MenuItem.acceleratorSelectionForeground", getMenuSelectionForegroundColor(), - "CheckBoxMenuItem.border", menuItemBorder, - "CheckBoxMenuItem.borderPainted", Boolean.TRUE, - "CheckBoxMenuItem.foreground", getMenuForegroundColor(), - "CheckBoxMenuItem.background", getMenuBackgroundColor(), - "CheckBoxMenuItem.selectionForeground", getMenuSelectionForegroundColor(), - "CheckBoxMenuItem.selectionBackground", getMenuSelectionBackgroundColor(), - "CheckBoxMenuItem.disabledForeground", getDisabledForegroundColor(), - "CheckBoxMenuItem.disabledShadow", getWhite(), - "CheckBoxMenuItem.acceleratorForeground", getMenuForegroundColor(), - "CheckBoxMenuItem.acceleratorSelectionForeground", getMenuSelectionForegroundColor(), - "CheckBoxMenuItem.checkIcon", getIconFactory().getMenuCheckBoxIcon(), - "RadioButtonMenuItem.border", menuItemBorder, - "RadioButtonMenuItem.borderPainted", Boolean.TRUE, - "RadioButtonMenuItem.foreground", getMenuForegroundColor(), - "RadioButtonMenuItem.background", getMenuBackgroundColor(), - "RadioButtonMenuItem.selectionForeground", getMenuSelectionForegroundColor(), - "RadioButtonMenuItem.selectionBackground", getMenuSelectionBackgroundColor(), - "RadioButtonMenuItem.disabledForeground", getDisabledForegroundColor(), - "RadioButtonMenuItem.disabledShadow", getWhite(), - "RadioButtonMenuItem.acceleratorForeground", getMenuForegroundColor(), - "RadioButtonMenuItem.acceleratorSelectionForeground", getMenuSelectionForegroundColor(), - "RadioButtonMenuItem.checkIcon", getIconFactory().getMenuRadioButtonIcon(), - // OptionPane. - "OptionPane.errorIcon", getIconFactory().getOptionPaneErrorIcon(), - "OptionPane.informationIcon", getIconFactory().getOptionPaneInformationIcon(), - "OptionPane.warningIcon", getIconFactory().getOptionPaneWarningIcon(), - "OptionPane.questionIcon", getIconFactory().getOptionPaneQuestionIcon(), - "OptionPane.border", optionPaneBorder, - "OptionPane.messageAreaBorder", optionPaneMessageAreaBorder, - "OptionPane.buttonAreaBorder", optionPaneButtonAreaBorder, - // File View - "FileView.directoryIcon", getIconFactory().getTreeFolderIcon(), - "FileView.fileIcon", getIconFactory().getTreeLeafIcon(), - "FileView.computerIcon", getIconFactory().getTreeComputerIcon(), - "FileView.hardDriveIcon", getIconFactory().getTreeHardDriveIcon(), - "FileView.floppyDriveIcon", getIconFactory().getTreeFloppyDriveIcon(), - // File Chooser - "FileChooser.detailsViewIcon", getIconFactory().getFileChooserDetailViewIcon(), - "FileChooser.homeFolderIcon", getIconFactory().getFileChooserHomeFolderIcon(), - "FileChooser.listViewIcon", getIconFactory().getFileChooserListViewIcon(), - "FileChooser.newFolderIcon", getIconFactory().getFileChooserNewFolderIcon(), - "FileChooser.upFolderIcon", getIconFactory().getFileChooserUpFolderIcon(), - // Separator - "Separator.background", getBackgroundColor(), - "Separator.foreground", getControlForegroundColor(), - // SplitPane - "SplitPane.centerOneTouchButtons", Boolean.TRUE, - "SplitPane.dividerSize", new Integer(7), - "SplitPane.border", BorderFactory.createEmptyBorder(), - // Tree - "Tree.background", getInputBackgroundColor(), - "Tree.foreground", getInputForegroundColor(), - "Tree.textForeground", getInputForegroundColor(), - "Tree.textBackground", getInputBackgroundColor(), - - "Tree.openIcon", getIconFactory().getTreeFolderIcon(), - "Tree.closedIcon", getIconFactory().getTreeFolderIcon(), - "Tree.leafIcon", getIconFactory().getTreeLeafIcon(), - "Tree.expandedIcon", getIconFactory().getTreeExpandedIcon(), - "Tree.collapsedIcon", getIconFactory().getTreeCollapsedIcon(), - "Tree.selectionBorderColor", getFocusCellColor(), - "Tree.line", getFrameColor(), // horiz lines - "Tree.hash", getFrameColor(), // legs - - // ToolBar - "JToolBar.isRollover", Boolean.TRUE, - "ToolBar.border", toolBarBorder, - "ToolBar.background", getToolbarBackgroundColor(), - "ToolBar.foreground", getToolbarForegroundColor(), - "ToolBar.dockingBackground", getToolbarBackgroundColor(), - "ToolBar.dockingForeground", getToolbarDockingColor(), - "ToolBar.floatingBackground", getToolbarBackgroundColor(), - "ToolBar.floatingForeground", getToolbarForegroundColor(),}; - table.putDefaults(defaults); - - if (JTattooUtilities.getJavaVersion() >= 1.5) { - table.put("Spinner.font", getControlTextFont()); - table.put("Spinner.background", getButtonBackgroundColor()); - table.put("Spinner.foreground", getButtonForegroundColor()); - table.put("Spinner.border", getBorderFactory().getSpinnerBorder()); - table.put("Spinner.arrowButtonInsets", null); - table.put("Spinner.arrowButtonBorder", BorderFactory.createEmptyBorder()); - table.put("Spinner.editorBorderPainted", Boolean.FALSE); - } - } - - public static void setTheme(AbstractTheme theme) { - if (theme == null) { - return; - } - - MetalLookAndFeel.setCurrentTheme(theme); - myTheme = theme; - if (isWindowDecorationOn()) { - DecorationHelper.decorateWindows(Boolean.TRUE); - } else { - DecorationHelper.decorateWindows(Boolean.FALSE); - } - } - - /** - * Set a theme by name. Allowed themes may come from the list returned by getThemes - */ - public static void setTheme(String name) { - // Overwrite this in derived classes - } - - public static AbstractTheme getTheme() { - return myTheme; - } - - public static MetalTheme getCurrentTheme() { - return myTheme; - } - - public static java.util.List getThemes() { - ArrayList themes = new ArrayList(); - themes.add(getTheme().getName()); - return themes; - } - - public static boolean isWindowDecorationOn() { - return getTheme().isWindowDecorationOn(); - } - - public static ColorUIResource getForegroundColor() { - return getTheme().getForegroundColor(); - } - - public static ColorUIResource getDisabledForegroundColor() { - return getTheme().getDisabledForegroundColor(); - } - - public static ColorUIResource getBackgroundColor() { - return getTheme().getBackgroundColor(); - } - - public static ColorUIResource getAlterBackgroundColor() { - return getTheme().getAlterBackgroundColor(); - } - - public static ColorUIResource getDisabledBackgroundColor() { - return getTheme().getDisabledBackgroundColor(); - } - - public static ColorUIResource getInputForegroundColor() { - return getTheme().getInputForegroundColor(); - } - - public static ColorUIResource getInputBackgroundColor() { - return getTheme().getInputBackgroundColor(); - } - - public static ColorUIResource getFocusColor() { - return getTheme().getFocusColor(); - } - - public static ColorUIResource getFocusCellColor() { - return getTheme().getFocusCellColor(); - } - - public static ColorUIResource getFrameColor() { - return getTheme().getFrameColor(); - } - - public static ColorUIResource getGridColor() { - return getTheme().getGridColor(); - } - - public static ColorUIResource getSelectionForegroundColor() { - return getTheme().getSelectionForegroundColor(); - } - - public static ColorUIResource getSelectionBackgroundColor() { - return getTheme().getSelectionBackgroundColor(); - } - - public static ColorUIResource getButtonForegroundColor() { - return getTheme().getButtonForegroundColor(); - } - - public static ColorUIResource getButtonBackgroundColor() { - return getTheme().getButtonBackgroundColor(); - } - - public static ColorUIResource getButtonColorLight() { - return getTheme().getButtonColorLight(); - } - - public static ColorUIResource getButtonColorDark() { - return getTheme().getButtonColorDark(); - } - - public static ColorUIResource getControlForegroundColor() { - return getTheme().getControlForegroundColor(); - } - - public static ColorUIResource getControlBackgroundColor() { - return getTheme().getControlBackgroundColor(); - } - - public ColorUIResource getControlHighlightColor() { - return getTheme().getControlHighlightColor(); - } - - public ColorUIResource getControlShadowColor() { - return getTheme().getControlShadowColor(); - } - - public ColorUIResource getControlDarkShadowColor() { - return getTheme().getControlDarkShadowColor(); - } - - public static ColorUIResource getControlColorLight() { - return getTheme().getControlColorLight(); - } - - public static ColorUIResource getControlColorDark() { - return getTheme().getControlColorDark(); - } - - public static ColorUIResource getWindowTitleForegroundColor() { - return getTheme().getWindowTitleForegroundColor(); - } - - public static ColorUIResource getWindowTitleBackgroundColor() { - return getTheme().getWindowTitleBackgroundColor(); - } - - public static ColorUIResource getWindowTitleColorLight() { - return getTheme().getWindowTitleColorLight(); - } - - public static ColorUIResource getWindowTitleColorDark() { - return getTheme().getWindowTitleColorDark(); - } - - public static ColorUIResource getWindowBorderColor() { - return getTheme().getWindowBorderColor(); - } - - public static ColorUIResource getWindowInactiveTitleForegroundColor() { - return getTheme().getWindowInactiveTitleForegroundColor(); - } - - public static ColorUIResource getWindowInactiveTitleBackgroundColor() { - return getTheme().getWindowInactiveTitleBackgroundColor(); - } - - public static ColorUIResource getWindowInactiveTitleColorLight() { - return getTheme().getWindowInactiveTitleColorLight(); - } - - public static ColorUIResource getWindowInactiveTitleColorDark() { - return getTheme().getWindowInactiveTitleColorDark(); - } - - public static ColorUIResource getWindowInactiveBorderColor() { - return getTheme().getWindowInactiveBorderColor(); - } - - public static ColorUIResource getMenuForegroundColor() { - return getTheme().getMenuForegroundColor(); - } - - public static ColorUIResource getMenuBackgroundColor() { - return getTheme().getMenuBackgroundColor(); - } - - public static ColorUIResource getMenuSelectionForegroundColor() { - return getTheme().getMenuSelectionForegroundColor(); - } - - public static ColorUIResource getMenuSelectionBackgroundColor() { - return getTheme().getMenuSelectionBackgroundColor(); - } - - public static ColorUIResource getMenuColorLight() { - return getTheme().getMenuColorLight(); - } - - public static ColorUIResource getMenuColorDark() { - return getTheme().getMenuColorDark(); - } - - public static ColorUIResource getToolbarForegroundColor() { - return getTheme().getToolbarForegroundColor(); - } - - public static ColorUIResource getToolbarBackgroundColor() { - return getTheme().getToolbarBackgroundColor(); - } - - public static ColorUIResource getToolbarColorLight() { - return getTheme().getToolbarColorLight(); - } - - public static ColorUIResource getToolbarColorDark() { - return getTheme().getToolbarColorDark(); - } - - public static ColorUIResource getToolbarDockingColor() { - return getTheme().getFocusColor(); - } - - public static ColorUIResource getTabAreaBackgroundColor() { - return getTheme().getTabAreaBackgroundColor(); - } - - public static ColorUIResource getTabSelectionForegroundColor() { - return getTheme().getTabSelectionForegroundColor(); - } - - public static ColorUIResource getDesktopColor() { - return getTheme().getDesktopColor(); - } - - public static ColorUIResource getTooltipForegroundColor() { - return getTheme().getTooltipForegroundColor(); - } - - public static ColorUIResource getTooltipBackgroundColor() { - return getTheme().getTooltipBackgroundColor(); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/AbstractTheme.java b/src/jtattoo/src/com/jtattoo/plaf/AbstractTheme.java deleted file mode 100644 index a7a3f5596..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/AbstractTheme.java +++ /dev/null @@ -1,1412 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.io.FileInputStream; -import java.util.Properties; -import javax.swing.Icon; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.FontUIResource; -import javax.swing.plaf.metal.MetalTheme; - -public abstract class AbstractTheme extends MetalTheme { - - public static final int TEXT_ANTIALIAS_DEFAULT = 0; - public static final int TEXT_ANTIALIAS_GRAY = 1; - public static final int TEXT_ANTIALIAS_HRGB = 2; - public static final int TEXT_ANTIALIAS_HBGR = 3; - public static final int TEXT_ANTIALIAS_VRGB = 4; - public static final int TEXT_ANTIALIAS_VBGR = 5; - public static final String DIALOG = "Dialog"; - - public static final ColorUIResource red = new ColorUIResource(255, 0, 0); - public static final ColorUIResource green = new ColorUIResource(0, 255, 255); - public static final ColorUIResource cyan = new ColorUIResource(0, 255, 255); - public static final ColorUIResource white = new ColorUIResource(255, 255, 255); - public static final ColorUIResource superLightGray = new ColorUIResource(248, 248, 248); - public static final ColorUIResource extraLightGray = new ColorUIResource(232, 232, 232); - public static final ColorUIResource lightGray = new ColorUIResource(196, 196, 196); - public static final ColorUIResource gray = new ColorUIResource(164, 164, 164); - public static final ColorUIResource darkGray = new ColorUIResource(148, 148, 148); - public static final ColorUIResource extraDarkGray = new ColorUIResource(96, 96, 96); - public static final ColorUIResource black = new ColorUIResource(0, 0, 0); - public static final ColorUIResource orange = new ColorUIResource(255, 200, 0); - public static final ColorUIResource lightOrange = new ColorUIResource(255, 220, 96); - public static final ColorUIResource yellow = new ColorUIResource(255, 255, 196); - public static final ColorUIResource blue = new ColorUIResource(0, 128, 255); - public static final ColorUIResource darkBlue = new ColorUIResource(0, 64, 128); - - protected static String internalName = "Default"; - protected static boolean windowDecoration = false; - protected static boolean macStyleWindowDecoration = false; - protected static boolean linuxStyleScrollBar = false; - protected static boolean dynamicLayout = false; - protected static boolean textShadow = false; - protected static boolean textAntiAliasing = false; - protected static int textAntiAliasingMode = TEXT_ANTIALIAS_HRGB; - protected static boolean backgroundPattern = true; - protected static boolean brightMode = false; - protected static boolean showFocusFrame = false; - protected static boolean drawSquareButtons = false; - protected static boolean toolbarDecorated = true; - - protected static boolean menuOpaque = true; - protected static float menuAlpha = 0.9f; - protected static String logoString = "JTattoo"; - protected static FontUIResource controlFont = null; - protected static FontUIResource systemFont = null; - protected static FontUIResource userFont = null; - protected static FontUIResource smallFont = null; - protected static FontUIResource menuFont = null; - protected static FontUIResource windowTitleFont = null; - protected static ColorUIResource foregroundColor = null; - protected static ColorUIResource backgroundColor = null; - protected static ColorUIResource backgroundColorLight = null; - protected static ColorUIResource backgroundColorDark = null; - protected static ColorUIResource alterBackgroundColor = null; - protected static ColorUIResource disabledForegroundColor = null; - protected static ColorUIResource disabledBackgroundColor = null; - protected static ColorUIResource inputBackgroundColor = null; - protected static ColorUIResource inputForegroundColor = null; - protected static ColorUIResource selectionForegroundColor = null; - protected static ColorUIResource selectionBackgroundColorLight = null; - protected static ColorUIResource selectionBackgroundColorDark = null; - protected static ColorUIResource selectionBackgroundColor = null; - protected static ColorUIResource rolloverForegroundColor = null; - protected static ColorUIResource rolloverColor = null; - protected static ColorUIResource rolloverColorLight = null; - protected static ColorUIResource rolloverColorDark = null; - protected static ColorUIResource pressedForegroundColor = null; - protected static ColorUIResource focusColor = null; - protected static ColorUIResource focusCellColor = null; - protected static ColorUIResource focusFrameColor = null; - protected static ColorUIResource focusBackgroundColor = null; - protected static ColorUIResource focusForegroundColor = null; - protected static ColorUIResource frameColor = null; - protected static ColorUIResource gridColor = null; - protected static ColorUIResource shadowColor = null; - protected static ColorUIResource buttonForegroundColor = null; - protected static ColorUIResource buttonBackgroundColor = null; - protected static ColorUIResource buttonColorLight = null; - protected static ColorUIResource buttonColorDark = null; - protected static ColorUIResource controlForegroundColor = null; - protected static ColorUIResource controlBackgroundColor = null; - protected static ColorUIResource controlHighlightColor = null; - protected static ColorUIResource controlShadowColor = null; - protected static ColorUIResource controlDarkShadowColor = null; - protected static ColorUIResource controlColorLight = null; - protected static ColorUIResource controlColorDark = null; - protected static ColorUIResource windowTitleForegroundColor = null; - protected static ColorUIResource windowTitleBackgroundColor = null; - protected static ColorUIResource windowTitleColorLight = null; - protected static ColorUIResource windowTitleColorDark = null; - protected static ColorUIResource windowBorderColor = null; - protected static ColorUIResource windowIconColor = null; - protected static ColorUIResource windowIconShadowColor = null; - protected static ColorUIResource windowIconRolloverColor = null; - - protected static ColorUIResource windowInactiveTitleForegroundColor = null; - protected static ColorUIResource windowInactiveTitleBackgroundColor = null; - protected static ColorUIResource windowInactiveTitleColorLight = null; - protected static ColorUIResource windowInactiveTitleColorDark = null; - protected static ColorUIResource windowInactiveBorderColor = null; - protected static ColorUIResource menuForegroundColor = null; - protected static ColorUIResource menuBackgroundColor = null; - protected static ColorUIResource menuSelectionForegroundColor = null; - protected static ColorUIResource menuSelectionBackgroundColor = null; - protected static ColorUIResource menuSelectionBackgroundColorLight = null; - protected static ColorUIResource menuSelectionBackgroundColorDark = null; - protected static ColorUIResource menuColorLight = null; - protected static ColorUIResource menuColorDark = null; - protected static ColorUIResource toolbarForegroundColor = null; - protected static ColorUIResource toolbarBackgroundColor = null; - protected static ColorUIResource toolbarColorLight = null; - protected static ColorUIResource toolbarColorDark = null; - protected static ColorUIResource tabAreaBackgroundColor = null; - protected static ColorUIResource tabSelectionForegroundColor = null; - protected static ColorUIResource desktopColor = null; - protected static ColorUIResource tooltipForegroundColor = null; - protected static ColorUIResource tooltipBackgroundColor = null; - protected static int tooltipBorderSize = 6; - protected static int tooltipShadowSize = 6; - protected static boolean tooltipCastShadow = false; - - protected static Color DEFAULT_COLORS[] = null; - protected static Color HIDEFAULT_COLORS[] = null; - protected static Color ACTIVE_COLORS[] = null; - protected static Color INACTIVE_COLORS[] = null; - protected static Color ROLLOVER_COLORS[] = null; - protected static Color SELECTED_COLORS[] = null; - protected static Color SELECTION_COLORS[] = null; - protected static Color FOCUS_COLORS[] = null; - protected static Color MENU_SELECTION_COLORS[] = null; - protected static Color PRESSED_COLORS[] = null; - protected static Color DISABLED_COLORS[] = null; - protected static Color WINDOW_TITLE_COLORS[] = null; - protected static Color WINDOW_INACTIVE_TITLE_COLORS[] = null; - protected static Color TOOLBAR_COLORS[] = null; - protected static Color MENUBAR_COLORS[] = null; - protected static Color BUTTON_COLORS[] = null; - protected static Color CHECKBOX_COLORS[] = null; - protected static Color TAB_COLORS[] = null; - protected static Color COL_HEADER_COLORS[] = null; - protected static Color TRACK_COLORS[] = null; - protected static Color THUMB_COLORS[] = null; - protected static Color SLIDER_COLORS[] = null; - protected static Color PROGRESSBAR_COLORS[] = null; - - protected static String textureSet = "Default"; - protected static boolean darkTexture = true; - protected static Icon windowTexture = null; - protected static Icon backgroundTexture = null; - protected static Icon alterBackgroundTexture = null; - protected static Icon selectedTexture = null; - protected static Icon rolloverTexture = null; - protected static Icon pressedTexture = null; - protected static Icon disabledTexture = null; - protected static Icon menubarTexture = null; - - public AbstractTheme() { - super(); - } - - public String getName() { - return getInternalName(); - } - - public static String getInternalName() { - return internalName; - } - - public static void setInternalName(String name) { - internalName = name; - } - - public String getPropertyFileName() { - return "JTattooTheme.properties"; - } - - public void setUpColor() { - windowDecoration = true; - macStyleWindowDecoration = JTattooUtilities.isMac(); - linuxStyleScrollBar = !JTattooUtilities.isWindows(); - dynamicLayout = true; - textShadow = false; - textAntiAliasing = false; - textAntiAliasingMode = TEXT_ANTIALIAS_HRGB; - backgroundPattern = true; - brightMode = false; - showFocusFrame = false; - drawSquareButtons = false; - toolbarDecorated = true; - menuOpaque = true; - menuAlpha = 0.9f; - logoString = "JTattoo"; - - controlFont = null; - systemFont = null; - userFont = null; - smallFont = null; - menuFont = null; - windowTitleFont = null; - - foregroundColor = black; - backgroundColor = extraLightGray; - backgroundColorLight = white; - backgroundColorDark = extraLightGray; - alterBackgroundColor = lightGray; - disabledForegroundColor = gray; - disabledBackgroundColor = superLightGray; - inputBackgroundColor = white; - inputForegroundColor = black; - selectionForegroundColor = black; - selectionBackgroundColor = lightGray; - selectionBackgroundColorLight = extraLightGray; - selectionBackgroundColorDark = lightGray; - focusColor = orange; - focusCellColor = orange; - focusFrameColor = new ColorUIResource(230, 191, 116); - focusBackgroundColor = new ColorUIResource(255, 250, 212); - focusForegroundColor = black; - frameColor = darkGray; - gridColor = gray; - shadowColor = new ColorUIResource(0, 24, 0); - - rolloverForegroundColor = black; - rolloverColor = extraLightGray; - rolloverColorLight = white; - rolloverColorDark = extraLightGray; - - pressedForegroundColor = black; - - buttonForegroundColor = black; - buttonBackgroundColor = lightGray; - buttonColorLight = white; - buttonColorDark = lightGray; - - controlForegroundColor = black; - controlBackgroundColor = lightGray; - controlHighlightColor = white; - controlShadowColor = lightGray; - controlDarkShadowColor = darkGray; - controlColorLight = white; - controlColorDark = lightGray; - - windowTitleForegroundColor = black; - windowTitleBackgroundColor = blue; - windowTitleColorLight = extraLightGray; - windowTitleColorDark = lightGray; - windowBorderColor = lightGray; - windowIconColor = black; - windowIconShadowColor = white; - windowIconRolloverColor = red; - - windowInactiveTitleForegroundColor = black; - windowInactiveTitleBackgroundColor = extraLightGray; - windowInactiveTitleColorLight = white; - windowInactiveTitleColorDark = extraLightGray; - windowInactiveBorderColor = extraLightGray; - - menuForegroundColor = black; - menuBackgroundColor = extraLightGray; - menuSelectionForegroundColor = black; - menuSelectionBackgroundColor = lightGray; - menuSelectionBackgroundColorLight = extraLightGray; - menuSelectionBackgroundColorDark = lightGray; - menuColorLight = extraLightGray; - menuColorDark = lightGray; - - toolbarForegroundColor = black; - toolbarBackgroundColor = lightGray; - toolbarColorLight = white; - toolbarColorDark = lightGray; - - tabAreaBackgroundColor = backgroundColor; - tabSelectionForegroundColor = selectionForegroundColor; - desktopColor = darkBlue; - tooltipForegroundColor = black; - tooltipBackgroundColor = yellow; - tooltipBorderSize = 6; - tooltipShadowSize = 6; - tooltipCastShadow = false; - - textureSet = "Default"; - darkTexture = true; - } - - public void setUpColorArrs() { - DEFAULT_COLORS = ColorHelper.createColorArr(controlColorLight, controlColorDark, 20); - HIDEFAULT_COLORS = ColorHelper.createColorArr(ColorHelper.brighter(controlColorLight, 40), ColorHelper.brighter(controlColorDark, 40), 20); - ACTIVE_COLORS = DEFAULT_COLORS; - INACTIVE_COLORS = HIDEFAULT_COLORS; - ROLLOVER_COLORS = ColorHelper.createColorArr(rolloverColorLight, rolloverColorDark, 20); - SELECTED_COLORS = DEFAULT_COLORS; - SELECTION_COLORS = ColorHelper.createColorArr(selectionBackgroundColorLight, selectionBackgroundColorDark, 20); - FOCUS_COLORS = ColorHelper.createColorArr(ColorHelper.brighter(focusBackgroundColor, 20), ColorHelper.darker(focusBackgroundColor, 10), 20); - MENU_SELECTION_COLORS = ColorHelper.createColorArr(menuSelectionBackgroundColorLight, menuSelectionBackgroundColorDark, 20); - PRESSED_COLORS = DEFAULT_COLORS; - DISABLED_COLORS = HIDEFAULT_COLORS; - WINDOW_TITLE_COLORS = ColorHelper.createColorArr(windowTitleColorLight, windowTitleColorDark, 20); - WINDOW_INACTIVE_TITLE_COLORS = ColorHelper.createColorArr(windowInactiveTitleColorLight, windowInactiveTitleColorDark, 20); - TOOLBAR_COLORS = ColorHelper.createColorArr(toolbarColorLight, toolbarColorDark, 20); - MENUBAR_COLORS = ColorHelper.createColorArr(menuColorLight, menuColorDark, 20); - BUTTON_COLORS = ColorHelper.createColorArr(buttonColorLight, buttonColorDark, 20); - CHECKBOX_COLORS = DEFAULT_COLORS; - TAB_COLORS = DEFAULT_COLORS; - COL_HEADER_COLORS = DEFAULT_COLORS; - TRACK_COLORS = ColorHelper.createColorArr(new Color(220, 220, 220), Color.white, 20); - THUMB_COLORS = DEFAULT_COLORS; - SLIDER_COLORS = DEFAULT_COLORS; - PROGRESSBAR_COLORS = DEFAULT_COLORS; - } - - public void setProperties(Properties props) { - if (props != null) { - if (props.getProperty("windowDecoration") != null) { - windowDecoration = props.getProperty("windowDecoration").trim().equalsIgnoreCase("on"); - } - if (props.getProperty("macStyleWindowDecoration") != null) { - macStyleWindowDecoration = props.getProperty("macStyleWindowDecoration").trim().equalsIgnoreCase("on"); - } - if (props.getProperty("linuxStyleScrollBar") != null) { - linuxStyleScrollBar = props.getProperty("linuxStyleScrollBar").trim().equalsIgnoreCase("on"); - } - if (props.getProperty("dynamicLayout") != null) { - dynamicLayout = props.getProperty("dynamicLayout").trim().equalsIgnoreCase("on"); - } - if (props.getProperty("textShadow") != null) { - textShadow = props.getProperty("textShadow").trim().equalsIgnoreCase("on"); - } - if (props.getProperty("textAntiAliasing") != null) { - textAntiAliasing = props.getProperty("textAntiAliasing").trim().equalsIgnoreCase("on"); - } - if (props.getProperty("textAntiAliasingMode") != null) { - String mode = props.getProperty("textAntiAliasingMode"); - if (mode.equalsIgnoreCase("default")) { - textAntiAliasingMode = TEXT_ANTIALIAS_DEFAULT; - } - if (mode.equalsIgnoreCase("gray")) { - textAntiAliasingMode = TEXT_ANTIALIAS_GRAY; - } - if (mode.equalsIgnoreCase("hrgb")) { - textAntiAliasingMode = TEXT_ANTIALIAS_HRGB; - } - if (mode.equalsIgnoreCase("hbgr")) { - textAntiAliasingMode = TEXT_ANTIALIAS_HBGR; - } - if (mode.equalsIgnoreCase("vrgb")) { - textAntiAliasingMode = TEXT_ANTIALIAS_VRGB; - } - if (mode.equalsIgnoreCase("vbgr")) { - textAntiAliasingMode = TEXT_ANTIALIAS_VBGR; - } - } - if (props.getProperty("backgroundPattern") != null) { - backgroundPattern = props.getProperty("backgroundPattern").trim().equalsIgnoreCase("on"); - } - if (props.getProperty("brightMode") != null) { - brightMode = props.getProperty("brightMode").trim().equalsIgnoreCase("on"); - } - if (props.getProperty("showFocusFrame") != null) { - showFocusFrame = props.getProperty("showFocusFrame").trim().equalsIgnoreCase("on"); - } - if (props.getProperty("drawSquareButtons") != null) { - drawSquareButtons = props.getProperty("drawSquareButtons").trim().equalsIgnoreCase("on"); - } - if (props.getProperty("toolbarDecorated") != null) { - toolbarDecorated = props.getProperty("toolbarDecorated").trim().equalsIgnoreCase("on"); - } - if (props.getProperty("menuOpaque") != null) { - menuOpaque = props.getProperty("menuOpaque").trim().equalsIgnoreCase("on"); - } - if (props.getProperty("logoString") != null) { - logoString = props.getProperty("logoString").trim(); - } - if (props.getProperty("controlTextFont") != null) { - controlFont = createFont(props.getProperty("controlTextFont")); - } - if (props.getProperty("systemTextFont") != null) { - systemFont = createFont(props.getProperty("systemTextFont")); - } - if (props.getProperty("userTextFont") != null) { - userFont = createFont(props.getProperty("userTextFont")); - } - if (props.getProperty("menuTextFont") != null) { - menuFont = createFont(props.getProperty("menuTextFont")); - } - if (props.getProperty("windowTitleFont") != null) { - windowTitleFont = createFont(props.getProperty("windowTitleFont")); - } - if (props.getProperty("subTextFont") != null) { - smallFont = createFont(props.getProperty("subTextFont")); - } - - if (props.getProperty("foregroundColor") != null) { - foregroundColor = createColor(props.getProperty("foregroundColor"), foregroundColor); - } - if (props.getProperty("backgroundColor") != null) { - backgroundColor = createColor(props.getProperty("backgroundColor"), backgroundColor); - } - if (props.getProperty("backgroundColorLight") != null) { - backgroundColorLight = createColor(props.getProperty("backgroundColorLight"), backgroundColorLight); - } - if (props.getProperty("backgroundColorDark") != null) { - backgroundColorDark = createColor(props.getProperty("backgroundColorDark"), backgroundColorDark); - } - if (props.getProperty("alterBackgroundColor") != null) { - alterBackgroundColor = createColor(props.getProperty("alterBackgroundColor"), alterBackgroundColor); - } - if (props.getProperty("disabledForegroundColor") != null) { - disabledForegroundColor = createColor(props.getProperty("disabledForegroundColor"), disabledForegroundColor); - } - if (props.getProperty("disabledBackgroundColor") != null) { - disabledBackgroundColor = createColor(props.getProperty("disabledBackgroundColor"), disabledBackgroundColor); - } - if (props.getProperty("inputForegroundColor") != null) { - inputForegroundColor = createColor(props.getProperty("inputForegroundColor"), inputForegroundColor); - } - if (props.getProperty("inputBackgroundColor") != null) { - inputBackgroundColor = createColor(props.getProperty("inputBackgroundColor"), inputBackgroundColor); - } - if (props.getProperty("selectionForegroundColor") != null) { - selectionForegroundColor = createColor(props.getProperty("selectionForegroundColor"), selectionForegroundColor); - } - if (props.getProperty("selectionBackgroundColor") != null) { - selectionBackgroundColor = createColor(props.getProperty("selectionBackgroundColor"), selectionBackgroundColor); - } - if (props.getProperty("selectionBackgroundColorLight") != null) { - selectionBackgroundColorLight = createColor(props.getProperty("selectionBackgroundColorLight"), selectionBackgroundColorLight); - } - if (props.getProperty("selectionBackgroundColorDark") != null) { - selectionBackgroundColorDark = createColor(props.getProperty("selectionBackgroundColorDark"), selectionBackgroundColorDark); - } - if (props.getProperty("frameColor") != null) { - frameColor = createColor(props.getProperty("frameColor"), frameColor); - } - if (props.getProperty("gridColor") != null) { - gridColor = createColor(props.getProperty("gridColor"), gridColor); - } - if (props.getProperty("shadowColor") != null) { - shadowColor = createColor(props.getProperty("shadowColor"), shadowColor); - } - if (props.getProperty("focusColor") != null) { - focusColor = createColor(props.getProperty("focusColor"), focusColor); - } - if (props.getProperty("focusCellColor") != null) { - focusCellColor = createColor(props.getProperty("focusCellColor"), focusCellColor); - } - if (props.getProperty("focusFrameColor") != null) { - focusFrameColor = createColor(props.getProperty("focusFrameColor"), focusFrameColor); - } - if (props.getProperty("focusBackgroundColor") != null) { - focusBackgroundColor = createColor(props.getProperty("focusBackgroundColor"), focusBackgroundColor); - } - if (props.getProperty("focusForegroundColor") != null) { - focusForegroundColor = createColor(props.getProperty("focusForegroundColor"), focusForegroundColor); - } - - if (props.getProperty("rolloverForegroundColor") != null) { - rolloverForegroundColor = createColor(props.getProperty("rolloverForegroundColor"), rolloverForegroundColor); - } - if (props.getProperty("rolloverColor") != null) { - rolloverColor = createColor(props.getProperty("rolloverColor"), rolloverColor); - } - if (props.getProperty("rolloverColorLight") != null) { - rolloverColorLight = createColor(props.getProperty("rolloverColorLight"), rolloverColorLight); - } - if (props.getProperty("rolloverColorDark") != null) { - rolloverColorDark = createColor(props.getProperty("rolloverColorDark"), rolloverColorDark); - } - if (props.getProperty("pressedForegroundColor") != null) { - pressedForegroundColor = createColor(props.getProperty("pressedForegroundColor"), pressedForegroundColor); - } - - if (props.getProperty("buttonForegroundColor") != null) { - buttonForegroundColor = createColor(props.getProperty("buttonForegroundColor"), buttonForegroundColor); - } - if (props.getProperty("buttonBackgroundColor") != null) { - buttonBackgroundColor = createColor(props.getProperty("buttonBackgroundColor"), buttonBackgroundColor); - } - if (props.getProperty("buttonColorLight") != null) { - buttonColorLight = createColor(props.getProperty("buttonColorLight"), buttonColorLight); - } - if (props.getProperty("buttonColorDark") != null) { - buttonColorDark = createColor(props.getProperty("buttonColorDark"), buttonColorDark); - } - - if (props.getProperty("controlForegroundColor") != null) { - controlForegroundColor = createColor(props.getProperty("controlForegroundColor"), controlForegroundColor); - } - if (props.getProperty("controlBackgroundColor") != null) { - controlBackgroundColor = createColor(props.getProperty("controlBackgroundColor"), controlBackgroundColor); - } - if (props.getProperty("controlColorLight") != null) { - controlColorLight = createColor(props.getProperty("controlColorLight"), controlColorLight); - } - if (props.getProperty("controlColorDark") != null) { - controlColorDark = createColor(props.getProperty("controlColorDark"), controlColorDark); - } - if (props.getProperty("controlHighlightColor") != null) { - controlHighlightColor = createColor(props.getProperty("controlHighlightColor"), controlHighlightColor); - } - if (props.getProperty("controlShadowColor") != null) { - controlShadowColor = createColor(props.getProperty("controlShadowColor"), controlShadowColor); - } - if (props.getProperty("controlDarkShadowColor") != null) { - controlDarkShadowColor = createColor(props.getProperty("controlDarkShadowColor"), controlDarkShadowColor); - } - - if (props.getProperty("windowTitleForegroundColor") != null) { - windowTitleForegroundColor = createColor(props.getProperty("windowTitleForegroundColor"), windowTitleForegroundColor); - } - if (props.getProperty("windowTitleBackgroundColor") != null) { - windowTitleBackgroundColor = createColor(props.getProperty("windowTitleBackgroundColor"), windowTitleBackgroundColor); - } - if (props.getProperty("windowTitleColorLight") != null) { - windowTitleColorLight = createColor(props.getProperty("windowTitleColorLight"), windowTitleColorLight); - } - if (props.getProperty("windowTitleColorDark") != null) { - windowTitleColorDark = createColor(props.getProperty("windowTitleColorDark"), windowTitleColorDark); - } - if (props.getProperty("windowBorderColor") != null) { - windowBorderColor = createColor(props.getProperty("windowBorderColor"), windowBorderColor); - } - if (props.getProperty("windowIconColor") != null) { - windowIconColor = createColor(props.getProperty("windowIconColor"), windowIconColor); - } - if (props.getProperty("windowIconShadowColor") != null) { - windowIconShadowColor = createColor(props.getProperty("windowIconShadowColor"), windowIconShadowColor); - } - if (props.getProperty("windowIconRolloverColor") != null) { - windowIconRolloverColor = createColor(props.getProperty("windowIconRolloverColor"), windowIconRolloverColor); - } - - if (props.getProperty("windowInactiveTitleForegroundColor") != null) { - windowInactiveTitleForegroundColor = createColor(props.getProperty("windowInactiveTitleForegroundColor"), windowInactiveTitleForegroundColor); - } - if (props.getProperty("windowTitleBackgroundColor") != null) { - windowInactiveTitleBackgroundColor = createColor(props.getProperty("windowInactiveTitleBackgroundColor"), windowInactiveTitleBackgroundColor); - } - if (props.getProperty("windowInactiveTitleColorLight") != null) { - windowInactiveTitleColorLight = createColor(props.getProperty("windowInactiveTitleColorLight"), windowInactiveTitleColorLight); - } - if (props.getProperty("windowInactiveTitleColorDark") != null) { - windowInactiveTitleColorDark = createColor(props.getProperty("windowInactiveTitleColorDark"), windowInactiveTitleColorDark); - } - if (props.getProperty("windowInactiveBorderColor") != null) { - windowInactiveBorderColor = createColor(props.getProperty("windowInactiveBorderColor"), windowInactiveBorderColor); - } - - if (props.getProperty("menuForegroundColor") != null) { - menuForegroundColor = createColor(props.getProperty("menuForegroundColor"), menuForegroundColor); - } - if (props.getProperty("menuBackgroundColor") != null) { - menuBackgroundColor = createColor(props.getProperty("menuBackgroundColor"), menuBackgroundColor); - } - if (props.getProperty("menuSelectionForegroundColor") != null) { - menuSelectionForegroundColor = createColor(props.getProperty("menuSelectionForegroundColor"), menuSelectionForegroundColor); - } - if (props.getProperty("menuSelectionBackgroundColor") != null) { - menuSelectionBackgroundColor = createColor(props.getProperty("menuSelectionBackgroundColor"), menuSelectionBackgroundColor); - } - if (props.getProperty("menuSelectionBackgroundColorLight") != null) { - menuSelectionBackgroundColorLight = createColor(props.getProperty("menuSelectionBackgroundColorLight"), menuSelectionBackgroundColorLight); - } - if (props.getProperty("menuSelectionBackgroundColorDark") != null) { - menuSelectionBackgroundColorDark = createColor(props.getProperty("menuSelectionBackgroundColorDark"), menuSelectionBackgroundColorDark); - } - if (props.getProperty("menuColorLight") != null) { - menuColorLight = createColor(props.getProperty("menuColorLight"), menuColorLight); - } - if (props.getProperty("menuColorDark") != null) { - menuColorDark = createColor(props.getProperty("menuColorDark"), menuColorDark); - } - - if (props.getProperty("toolbarForegroundColor") != null) { - toolbarForegroundColor = createColor(props.getProperty("toolbarForegroundColor"), toolbarForegroundColor); - } - if (props.getProperty("toolbarBackgroundColor") != null) { - toolbarBackgroundColor = createColor(props.getProperty("toolbarBackgroundColor"), toolbarBackgroundColor); - } - if (props.getProperty("toolbarColorLight") != null) { - toolbarColorLight = createColor(props.getProperty("toolbarColorLight"), toolbarColorLight); - } - if (props.getProperty("toolbarColorDark") != null) { - toolbarColorDark = createColor(props.getProperty("toolbarColorDark"), toolbarColorDark); - } - - if (props.getProperty("tabAreaBackgroundColor") != null) { - tabAreaBackgroundColor = createColor(props.getProperty("tabAreaBackgroundColor"), tabAreaBackgroundColor); - } else { - tabAreaBackgroundColor = backgroundColor; - } - if (props.getProperty("tabSelectionForegroundColor") != null) { - tabSelectionForegroundColor = createColor(props.getProperty("tabSelectionForegroundColor"), tabSelectionForegroundColor); - } - - if (props.getProperty("desktopColor") != null) { - desktopColor = createColor(props.getProperty("desktopColor"), desktopColor); - } - if (props.getProperty("tooltipForegroundColor") != null) { - tooltipForegroundColor = createColor(props.getProperty("tooltipForegroundColor"), tooltipForegroundColor); - } - if (props.getProperty("tooltipBackgroundColor") != null) { - tooltipBackgroundColor = createColor(props.getProperty("tooltipBackgroundColor"), tooltipBackgroundColor); - } - if (props.getProperty("tooltipBorderSize") != null) { - tooltipBorderSize = createInt(props.getProperty("tooltipBorderSize"), tooltipBorderSize); - } - if (props.getProperty("tooltipShadowSize") != null) { - tooltipShadowSize = createInt(props.getProperty("tooltipShadowSize"), tooltipShadowSize); - } - if (props.getProperty("tooltipCastShadow") != null) { - tooltipCastShadow = props.getProperty("tooltipCastShadow").trim().equalsIgnoreCase("on"); - } - - if (props.getProperty("textureSet") != null) { - textureSet = props.getProperty("textureSet"); - } - if (props.getProperty("darkTexture") != null) { - darkTexture = props.getProperty("darkTexture").trim().equalsIgnoreCase("on"); - } - if (props.get("windowTexture") != null) { - Object texture = props.get("windowTexture"); - if (texture instanceof Icon) { - windowTexture = (Icon)texture; - } - } - if (props.get("backgroundTexture") != null) { - Object texture = props.get("backgroundTexture"); - if (texture instanceof Icon) { - backgroundTexture = (Icon)texture; - } - } - if (props.get("alterBackgroundTexture") != null) { - Object texture = props.get("alterBackgroundTexture"); - if (texture instanceof Icon) { - alterBackgroundTexture = (Icon)texture; - } - } - if (props.get("selectedTexture") != null) { - Object texture = props.get("selectedTexture"); - if (texture instanceof Icon) { - selectedTexture = (Icon)texture; - } - } - if (props.get("rolloverTexture") != null) { - Object texture = props.get("rolloverTexture"); - if (texture instanceof Icon) { - rolloverTexture = (Icon)texture; - } - } - if (props.get("pressedTexture") != null) { - Object texture = props.get("pressedTexture"); - if (texture instanceof Icon) { - pressedTexture = (Icon)texture; - } - } - if (props.get("disabledTexture") != null) { - Object texture = props.get("disabledTexture"); - if (texture instanceof Icon) { - disabledTexture = (Icon)texture; - } - } - if (props.get("menubarTexture") != null) { - Object texture = props.get("menubarTexture"); - if (texture instanceof Icon) { - menubarTexture = (Icon)texture; - } - } - } - } - - public void loadProperties() { - FileInputStream in = null; - try { - String fileName = System.getProperty("user.home") + "/.jtattoo/" + getPropertyFileName(); - Properties props = new Properties(); - in = new FileInputStream(fileName); - props.load(in); - setProperties(props); - } catch (Exception ex) { - } finally { - try { - if (in != null) { - in.close(); - } - } catch (Exception ex) { - } - } - } - - protected static FontUIResource createFont(String fontProp) { - if ((fontProp != null) && (fontProp.trim().length() > 5)) { - return new FontUIResource(Font.decode(fontProp)); - } - return null; - } - - protected static ColorUIResource createColor(String colorProp, ColorUIResource color) { - if ((colorProp != null) && (colorProp.trim().length() >= 5)) { - colorProp = colorProp.trim(); - int r = color.getRed(); - int g = color.getGreen(); - int b = color.getBlue(); - try { - int p1 = 0; - int p2 = colorProp.indexOf(' '); - if (p2 > 0) { - r = Integer.parseInt(colorProp.substring(p1, p2)); - } - p1 = p2 + 1; - p2 = colorProp.indexOf(' ', p1); - if (p2 > 0) { - g = Integer.parseInt(colorProp.substring(p1, p2)); - } - b = Integer.parseInt(colorProp.substring(p2 + 1)); - return new ColorUIResource(r, g, b); - } catch (Exception ex) { - System.out.println("Exception while parsing color: " + colorProp); - } - } - return color; - } - - protected static int createInt(String intProp, int defaultValue) { - int val = defaultValue; - try { - val = Integer.parseInt(intProp); - } catch (Exception ex) { - System.out.println("Exception while parsing color: " + intProp); - } - return val; - } - - public FontUIResource getControlTextFont() { - if (controlFont == null) { - if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) { - controlFont = new FontUIResource(DIALOG, Font.BOLD, 14); - } else { - controlFont = new FontUIResource(DIALOG, Font.PLAIN, 12); - } - } - return controlFont; - } - - public FontUIResource getSystemTextFont() { - if (systemFont == null) { - if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) { - systemFont = new FontUIResource(DIALOG, Font.BOLD, 14); - } else { - systemFont = new FontUIResource(DIALOG, Font.PLAIN, 12); - } - } - return systemFont; - } - - public FontUIResource getUserTextFont() { - if (userFont == null) { - if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) { - userFont = new FontUIResource(DIALOG, Font.BOLD, 14); - } else { - userFont = new FontUIResource(DIALOG, Font.PLAIN, 12); - } - } - return userFont; - } - - public FontUIResource getMenuTextFont() { - if (menuFont == null) { - if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) { - menuFont = new FontUIResource(DIALOG, Font.BOLD, 14); - } else { - menuFont = new FontUIResource(DIALOG, Font.PLAIN, 12); - } - } - return menuFont; - } - - public FontUIResource getWindowTitleFont() { - if (windowTitleFont == null) { - if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) { - windowTitleFont = new FontUIResource(DIALOG, Font.BOLD, 14); - } else { - windowTitleFont = new FontUIResource(DIALOG, Font.BOLD, 12); - } - } - return windowTitleFont; - } - - public FontUIResource getSubTextFont() { - if (smallFont == null) { - if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) { - smallFont = new FontUIResource(DIALOG, Font.BOLD, 12); - } else { - smallFont = new FontUIResource(DIALOG, Font.PLAIN, 10); - } - } - return smallFont; - } - - //----------------------------------------------------------------------------------- - protected ColorUIResource getPrimary1() { - return foregroundColor; - } - - protected ColorUIResource getPrimary2() { - return desktopColor; - } - - protected ColorUIResource getPrimary3() { - return selectionBackgroundColor; - } - - protected ColorUIResource getSecondary1() { - return frameColor; - } - - protected ColorUIResource getSecondary2() { - return controlBackgroundColor; - } - - protected ColorUIResource getSecondary3() { - return backgroundColor; - } - - public ColorUIResource getControl() { - return controlBackgroundColor; - } - - public ColorUIResource getControlShadow() { - return controlShadowColor; - } - - public ColorUIResource getControlDarkShadow() { - return controlDarkShadowColor; - } - - public ColorUIResource getControlInfo() { - return controlForegroundColor; - } - - public ColorUIResource getControlHighlight() { - return controlHighlightColor; - } - - public ColorUIResource getControlDisabled() { - return controlShadowColor; - } - - public ColorUIResource getPrimaryControl() { - return extraLightGray; - } - - public ColorUIResource getPrimaryControlShadow() { - return lightGray; - } - - public ColorUIResource getPrimaryControlDarkShadow() { - return gray; - } - - public ColorUIResource getPrimaryControlInfo() { - return darkGray; - } - - public ColorUIResource getPrimaryControlHighlight() { - return white; - } - - public ColorUIResource getControlTextColor() { - return controlForegroundColor; - } - - public ColorUIResource getSystemTextColor() { - return foregroundColor; - } - - public String getLogoString() { - if (logoString != null) { - if (logoString.trim().length() == 0) { - return null; - } - } - return logoString; - } - - public boolean isWindowDecorationOn() { - return windowDecoration; - } - - public boolean isMacStyleWindowDecorationOn() { - return macStyleWindowDecoration; - } - - public boolean isLinuxStyleScrollBarOn() { - return linuxStyleScrollBar; - } - - public boolean isDynamicLayout() { - return dynamicLayout; - } - - public boolean isTextShadowOn() { - return textShadow; - } - - public boolean isTextAntiAliasingOn() { - if (JTattooUtilities.getJavaVersion() < 1.4) { - return false; - } - return textAntiAliasing; - } - - public int getTextAntiAliasingMode() { - return textAntiAliasingMode; - } - - public Object getTextAntiAliasingHint() { - if (isTextAntiAliasingOn()) { - if (JTattooUtilities.getJavaVersion() >= 1.6) { - switch (textAntiAliasingMode) { - case TEXT_ANTIALIAS_DEFAULT: - return RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT; - case TEXT_ANTIALIAS_HRGB: - return RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB; - case TEXT_ANTIALIAS_HBGR: - return RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR; - case TEXT_ANTIALIAS_VRGB: - return RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB; - case TEXT_ANTIALIAS_VBGR: - return RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR; - default: - return RenderingHints.VALUE_TEXT_ANTIALIAS_ON; - } - } - return RenderingHints.VALUE_TEXT_ANTIALIAS_ON; - } - return RenderingHints.VALUE_TEXT_ANTIALIAS_OFF; - } - - public boolean isBackgroundPatternOn() { - return backgroundPattern; - } - - public boolean isBrightMode() { - return brightMode; - } - - public boolean doShowFocusFrame() { - return showFocusFrame; - } - - public boolean doDrawSquareButtons() { - return drawSquareButtons; - } - - public boolean isToolbarDecorated() { - return toolbarDecorated; - } - - public boolean isMenuOpaque() { - return menuOpaque; - } - - public float getMenuAlpha() { - return menuAlpha; - } - - public ColorUIResource getForegroundColor() { - return foregroundColor; - } - - public ColorUIResource getDisabledForegroundColor() { - return disabledForegroundColor; - } - - public ColorUIResource getBackgroundColor() { - return backgroundColor; - } - - public ColorUIResource getDisabledBackgroundColor() { - return disabledBackgroundColor; - } - - public ColorUIResource getBackgroundColorLight() { - return backgroundColorLight; - } - - public ColorUIResource getBackgroundColorDark() { - return backgroundColorDark; - } - - public ColorUIResource getAlterBackgroundColor() { - return alterBackgroundColor; - } - - public ColorUIResource getInputForegroundColor() { - return inputForegroundColor; - } - - public ColorUIResource getInputBackgroundColor() { - return inputBackgroundColor; - } - - public ColorUIResource getSelectionForegroundColor() { - return selectionForegroundColor; - } - - public ColorUIResource getSelectionBackgroundColorLight() { - return selectionBackgroundColorLight; - } - - public ColorUIResource getSelectionBackgroundColorDark() { - return selectionBackgroundColorDark; - } - - public ColorUIResource getSelectionBackgroundColor() { - return selectionBackgroundColor; - } - - public ColorUIResource getFrameColor() { - return frameColor; - } - - public ColorUIResource getGridColor() { - return gridColor; - } - - public ColorUIResource getShadowColor() { - return shadowColor; - } - - public ColorUIResource getFocusColor() { - return focusColor; - } - - public ColorUIResource getFocusCellColor() { - return focusCellColor; - } - - public ColorUIResource getFocusFrameColor() { - return focusFrameColor; - } - - public ColorUIResource getFocusBackgroundColor() { - return focusBackgroundColor; - } - - public ColorUIResource getFocusForegroundColor() { - return focusForegroundColor; - } - - public ColorUIResource getRolloverForegroundColor() { - return rolloverForegroundColor; - } - - public ColorUIResource getRolloverColor() { - return rolloverColor; - } - - public ColorUIResource getRolloverColorLight() { - return rolloverColorLight; - } - - public ColorUIResource getRolloverColorDark() { - return rolloverColorDark; - } - - public ColorUIResource getPressedForegroundColor() { - return pressedForegroundColor; - } - - public ColorUIResource getButtonForegroundColor() { - return buttonForegroundColor; - } - - public ColorUIResource getButtonBackgroundColor() { - return buttonBackgroundColor; - } - - public ColorUIResource getButtonColorLight() { - return buttonColorLight; - } - - public ColorUIResource getButtonColorDark() { - return buttonColorDark; - } - - public ColorUIResource getControlForegroundColor() { - return controlForegroundColor; - } - - public ColorUIResource getControlBackgroundColor() { - return controlBackgroundColor; - } - - public ColorUIResource getControlHighlightColor() { - return controlHighlightColor; - } - - public ColorUIResource getControlShadowColor() { - return controlShadowColor; - } - - public ColorUIResource getControlDarkShadowColor() { - return controlDarkShadowColor; - } - - public ColorUIResource getControlColorLight() { - return controlColorLight; - } - - public ColorUIResource getControlColorDark() { - return controlColorDark; - } - - public ColorUIResource getWindowTitleForegroundColor() { - return windowTitleForegroundColor; - } - - public ColorUIResource getWindowTitleBackgroundColor() { - return windowTitleBackgroundColor; - } - - public ColorUIResource getWindowTitleColorLight() { - return windowTitleColorLight; - } - - public ColorUIResource getWindowTitleColorDark() { - return windowTitleColorDark; - } - - public ColorUIResource getWindowBorderColor() { - return windowBorderColor; - } - - public ColorUIResource getWindowIconColor() { - return windowIconColor; - } - - public ColorUIResource getWindowIconShadowColor() { - return windowIconShadowColor; - } - - public ColorUIResource getWindowIconRolloverColor() { - return windowIconRolloverColor; - } - - public ColorUIResource getWindowInactiveTitleForegroundColor() { - return windowInactiveTitleForegroundColor; - } - - public ColorUIResource getWindowInactiveTitleBackgroundColor() { - return windowInactiveTitleBackgroundColor; - } - - public ColorUIResource getWindowInactiveTitleColorLight() { - return windowInactiveTitleColorLight; - } - - public ColorUIResource getWindowInactiveTitleColorDark() { - return windowInactiveTitleColorDark; - } - - public ColorUIResource getWindowInactiveBorderColor() { - return windowInactiveBorderColor; - } - - public ColorUIResource getMenuForegroundColor() { - return menuForegroundColor; - } - - public ColorUIResource getMenuBackgroundColor() { - return menuBackgroundColor; - } - - public ColorUIResource getMenuSelectionForegroundColor() { - return menuSelectionForegroundColor; - } - - public ColorUIResource getMenuSelectionBackgroundColor() { - return menuSelectionBackgroundColor; - } - - public ColorUIResource getMenuSelectionBackgroundColorLight() { - return menuSelectionBackgroundColorLight; - } - - public ColorUIResource getMenuSelectionBackgroundColorDark() { - return menuSelectionBackgroundColorDark; - } - - public ColorUIResource getMenuColorLight() { - return menuColorLight; - } - - public ColorUIResource getMenuColorDark() { - return menuColorDark; - } - - public ColorUIResource getToolbarForegroundColor() { - return toolbarForegroundColor; - } - - public ColorUIResource getToolbarBackgroundColor() { - return toolbarBackgroundColor; - } - - public ColorUIResource getToolbarColorLight() { - return toolbarColorLight; - } - - public ColorUIResource getToolbarColorDark() { - return toolbarColorDark; - } - - public ColorUIResource getTabAreaBackgroundColor() { - return tabAreaBackgroundColor; - } - - public ColorUIResource getTabSelectionForegroundColor() { - return tabSelectionForegroundColor; - } - - public ColorUIResource getDesktopColor() { - return desktopColor; - } - - public ColorUIResource getTooltipForegroundColor() { - return tooltipForegroundColor; - } - - public ColorUIResource getTooltipBackgroundColor() { - return tooltipBackgroundColor; - } - - public int getTooltipBorderSize() { - return Math.max(0, Math.min(8, tooltipBorderSize)); - } - - public int getTooltipShadowSize() { - return Math.max(0, Math.min(8, tooltipShadowSize)); - } - - public boolean isTooltipCastShadow() { - return tooltipCastShadow; - } - - public Color[] getDefaultColors() { - return DEFAULT_COLORS; - } - - public Color[] getHiDefaultColors() { - return HIDEFAULT_COLORS; - } - - public Color[] getActiveColors() { - return ACTIVE_COLORS; - } - - public Color[] getInActiveColors() { - return INACTIVE_COLORS; - } - - public Color[] getRolloverColors() { - return ROLLOVER_COLORS; - } - - public Color[] getSelectedColors() { - return SELECTED_COLORS; - } - - public Color[] getSelectionColors() { - return SELECTION_COLORS; - } - - public Color[] getFocusColors() { - return FOCUS_COLORS; - } - - public Color[] getMenuSelectionColors() { - return MENU_SELECTION_COLORS; - } - - public Color[] getPressedColors() { - return PRESSED_COLORS; - } - - public Color[] getDisabledColors() { - return DISABLED_COLORS; - } - - public Color[] getWindowTitleColors() { - return WINDOW_TITLE_COLORS; - } - - public Color[] getWindowInactiveTitleColors() { - return WINDOW_INACTIVE_TITLE_COLORS; - } - - public Color[] getToolBarColors() { - return TOOLBAR_COLORS; - } - - public Color[] getMenuBarColors() { - return MENUBAR_COLORS; - } - - public Color[] getButtonColors() { - return BUTTON_COLORS; - } - - public Color[] getCheckBoxColors() { - return CHECKBOX_COLORS; - } - - public Color[] getTabColors() { - return TAB_COLORS; - } - - public Color[] getColHeaderColors() { - return COL_HEADER_COLORS; - } - - public Color[] getTrackColors() { - return TRACK_COLORS; - } - - public Color[] getThumbColors() { - return THUMB_COLORS; - } - - public Color[] getSliderColors() { - return SLIDER_COLORS; - } - - public Color[] getProgressBarColors() { - return PROGRESSBAR_COLORS; - } - - public String getTextureSet() { - return textureSet; - } - - public boolean isDarkTexture() { - return darkTexture; - } - - public Icon getWindowTexture() { - return windowTexture; - } - - public Icon getBackgroundTexture() { - return backgroundTexture; - } - - public Icon getAlterBackgroundTexture() { - return alterBackgroundTexture; - } - - public Icon getSelectedTexture() { - return selectedTexture; - } - - public Icon getRolloverTexture() { - return rolloverTexture; - } - - public Icon getPressedTexture() { - return pressedTexture; - } - - public Icon getDisabledTexture() { - return disabledTexture; - } - - public Icon getMenubarTexture() { - return menubarTexture; - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/AbstractToolBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/AbstractToolBarUI.java deleted file mode 100644 index 4790f2d71..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/AbstractToolBarUI.java +++ /dev/null @@ -1,254 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.ContainerEvent; -import java.awt.event.ContainerListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.Hashtable; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicToolBarUI; - -public abstract class AbstractToolBarUI extends BasicToolBarUI { - - private final static String IS_ROLLOVER = "JToolBar.isRollover"; - private final static Insets BUTTON_MARGIN = new Insets(1, 1, 1, 1); - private final static Border INNER_BORDER = BorderFactory.createEmptyBorder(2, 2, 2, 2); - private boolean rolloverEnabled = true; - private MyPropertyChangeListener propertyChangeListener = null; - private MyContainerListener containerListener = null; - private Hashtable orgBorders = new Hashtable(); - private Hashtable orgMargins = new Hashtable(); - - public abstract Border getRolloverBorder(); - - public abstract Border getNonRolloverBorder(); - - public abstract boolean isButtonOpaque(); - - public void installUI(JComponent c) { - super.installUI(c); - Boolean isRollover = (Boolean) UIManager.get(IS_ROLLOVER); - if (isRollover != null) { - rolloverEnabled = isRollover.booleanValue(); - } - SwingUtilities.invokeLater( () -> changeBorders() ); - } - - public void uninstallUI(JComponent c) { - restoreBorders(); - super.uninstallUI(c); - } - - protected void installListeners() { - super.installListeners(); - propertyChangeListener = new MyPropertyChangeListener(); - if (propertyChangeListener != null) { - toolBar.addPropertyChangeListener(propertyChangeListener); - } - containerListener = new MyContainerListener(); - if (containerListener != null) { - toolBar.addContainerListener(containerListener); - } - } - - protected void uninstallListeners() { - if (propertyChangeListener != null) { - toolBar.removePropertyChangeListener(propertyChangeListener); - } - propertyChangeListener = null; - if (containerListener != null) { - toolBar.removeContainerListener(containerListener); - } - containerListener = null; - super.uninstallListeners(); - } - - protected boolean isRolloverEnabled() { - return rolloverEnabled; - } - - protected void setBorderToNormal(Component c) { - } - - protected void setBorderToRollover(Component c) { - } - - protected void setBorderToNonRollover(Component c) { - } - - protected void changeBorders() { - Component[] components = toolBar.getComponents(); - for (int i = 0; i < components.length; ++i) { - Component comp = components[i]; - if (comp instanceof AbstractButton) { - changeButtonBorder((AbstractButton) comp); - } - } - } - - protected void restoreBorders() { - Component[] components = toolBar.getComponents(); - for (int i = 0; i < components.length; ++i) { - Component comp = components[i]; - if (comp instanceof AbstractButton) { - restoreButtonBorder((AbstractButton) comp); - } - } - } - - protected void changeButtonBorder(AbstractButton b) { - Object cp = b.getClientProperty("paintToolBarBorder"); - if ((cp != null) && (cp instanceof Boolean)) { - Boolean changeBorder = (Boolean)cp; - if (!changeBorder.booleanValue()) { - return; - } - } - if (!orgBorders.contains(b)) { - if (b.getBorder() != null) { - orgBorders.put(b, b.getBorder()); - } else { - orgBorders.put(b, new NullBorder()); - } - } - - if (!orgMargins.contains(b)) { - orgMargins.put(b, b.getMargin()); - } - - if (b.getBorder() != null) { - if (isRolloverEnabled()) { - b.setBorderPainted(true); - b.setBorder(BorderFactory.createCompoundBorder(getRolloverBorder(), INNER_BORDER)); - b.setMargin(BUTTON_MARGIN); - b.setRolloverEnabled(true); - b.setOpaque(isButtonOpaque()); - b.setContentAreaFilled(isButtonOpaque()); - } else { - b.setBorder(BorderFactory.createCompoundBorder(getNonRolloverBorder(), INNER_BORDER)); - b.setMargin(BUTTON_MARGIN); - b.setRolloverEnabled(false); - b.setOpaque(isButtonOpaque()); - b.setContentAreaFilled(isButtonOpaque()); - } - } - } - - protected void restoreButtonBorder(AbstractButton b) { - Object cp = b.getClientProperty("paintToolBarBorder"); - if ((cp != null) && (cp instanceof Boolean)) { - Boolean changeBorder = (Boolean)cp; - if (!changeBorder.booleanValue()) { - return; - } - } - Border border = (Border) orgBorders.get(b); - if (border != null) { - if (border instanceof NullBorder) { - b.setBorder(null); - } else { - b.setBorder(border); - } - } - b.setMargin((Insets) orgMargins.get(b)); - } - - protected void updateToolbarBorder() { - toolBar.revalidate(); - toolBar.repaint(); - } - - protected boolean isToolBarUnderMenubar() { - if (toolBar != null && toolBar.getOrientation() == JToolBar.HORIZONTAL) { - JRootPane rp = SwingUtilities.getRootPane(toolBar); - JMenuBar mb = rp.getJMenuBar(); - if (mb != null) { - Point mbPoint = new Point(0, 0); - mbPoint = SwingUtilities.convertPoint(mb, mbPoint, rp); - Point tbPoint = new Point(0, 0); - tbPoint = SwingUtilities.convertPoint(toolBar, tbPoint, rp); - tbPoint.y -= mb.getHeight() - 1; - Rectangle rect = new Rectangle(mbPoint, mb.getSize()); - return rect.contains(tbPoint); - } - } - return false; - } - - protected boolean isToolbarDecorated() { - return AbstractLookAndFeel.getTheme().isToolbarDecorated(); - } - - protected class MyPropertyChangeListener implements PropertyChangeListener { - - public void propertyChange(PropertyChangeEvent e) { - if (e.getPropertyName().equals(IS_ROLLOVER)) { - if (e.getNewValue() != null) { - rolloverEnabled = ((Boolean) e.getNewValue()).booleanValue(); - changeBorders(); - } - } else if ("componentOrientation".equals(e.getPropertyName())) { - updateToolbarBorder(); - } - } - } - - protected class MyContainerListener implements ContainerListener { - - public void componentAdded(ContainerEvent e) { - Component c = e.getChild(); - if (c instanceof AbstractButton) { - changeButtonBorder((AbstractButton) c); - } - } - - public void componentRemoved(ContainerEvent e) { - Component c = e.getChild(); - if (c instanceof AbstractButton) { - restoreButtonBorder((AbstractButton) c); - } - } - } - - private static class NullBorder implements Border, UIResource { - - private static final Insets insets = new Insets(0, 0, 0, 0); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - } - - public Insets getBorderInsets(Component c) { - return insets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class NullBorder -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseBorders.java b/src/jtattoo/src/com/jtattoo/plaf/BaseBorders.java deleted file mode 100644 index d4cfc459d..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseBorders.java +++ /dev/null @@ -1,912 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.geom.AffineTransform; -import javax.swing.*; -import javax.swing.border.*; -import javax.swing.plaf.BorderUIResource; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class BaseBorders { - - protected static Border buttonBorder = null; - protected static Border focusFrameBorder = null; - protected static Border textFieldBorder = null; - protected static Border spinnerBorder = null; - protected static Border comboBoxBorder = null; - protected static Border progressBarBorder = null; - protected static Border tableHeaderBorder = null; - protected static Border popupMenuBorder = null; - protected static Border menuItemBorder = null; - protected static Border toolBarBorder = null; - protected static Border toolButtonBorder = null; - protected static Border rolloverToolButtonBorder = null; - protected static Border internalFrameBorder = null; - protected static Border paletteBorder = null; - protected static Border scrollPaneBorder = null; - protected static Border tableScrollPaneBorder = null; - protected static Border tabbedPaneBorder = null; - protected static Border desktopIconBorder = null; - - public static void initDefaults() { - buttonBorder = null; - textFieldBorder = null; - spinnerBorder = null; - comboBoxBorder = null; - progressBarBorder = null; - tableHeaderBorder = null; - popupMenuBorder = null; - menuItemBorder = null; - toolBarBorder = null; - toolButtonBorder = null; - rolloverToolButtonBorder = null; - paletteBorder = null; - internalFrameBorder = null; - scrollPaneBorder = null; - tableScrollPaneBorder = null; - tabbedPaneBorder = null; - desktopIconBorder = null; - } - - //------------------------------------------------------------------------------------ - // Lazy access methods - //------------------------------------------------------------------------------------ - public static Border getFocusFrameBorder() { - if (focusFrameBorder == null) { - focusFrameBorder = new FocusFrameBorder(); - } - return focusFrameBorder; - } - - //------------------------------------------------------------------------------------ - // Lazy access methods - //------------------------------------------------------------------------------------ - public static Border getTextBorder() { - if (textFieldBorder == null) { - textFieldBorder = new TextFieldBorder(); - } - return textFieldBorder; - } - - public static Border getSpinnerBorder() { - if (spinnerBorder == null) { - spinnerBorder = new SpinnerBorder(); - } - return spinnerBorder; - } - - public static Border getTextFieldBorder() { - return getTextBorder(); - } - - public static Border getComboBoxBorder() { - if (comboBoxBorder == null) { - comboBoxBorder = new ComboBoxBorder(); - } - return comboBoxBorder; - } - - public static Border getProgressBarBorder() { - if (progressBarBorder == null) { - progressBarBorder = BorderFactory.createLineBorder(ColorHelper.darker(AbstractLookAndFeel.getBackgroundColor(), 30)); - } - return progressBarBorder; - } - - public static Border getTableHeaderBorder() { - if (tableHeaderBorder == null) { - tableHeaderBorder = new TableHeaderBorder(); - } - return tableHeaderBorder; - } - - public static Border getPopupMenuBorder() { - if (popupMenuBorder == null) { - if (AbstractLookAndFeel.getTheme().isMenuOpaque()) { - popupMenuBorder = new BasePopupMenuBorder(); - } else { - popupMenuBorder = new BasePopupMenuShadowBorder(); - } - } - return popupMenuBorder; - } - - public static Border getMenuItemBorder() { - if (menuItemBorder == null) { - menuItemBorder = new MenuItemBorder(); - } - return menuItemBorder; - } - - public static Border getToolBarBorder() { - if (toolBarBorder == null) { - toolBarBorder = new ToolBarBorder(); - } - return toolBarBorder; - } - - public static Border getToolButtonBorder() { - if (toolButtonBorder == null) { - toolButtonBorder = new ToolButtonBorder(); - } - return toolButtonBorder; - } - - public static Border getMenuBarBorder() { - return BorderFactory.createEmptyBorder(1, 1, 1, 1); - } - - public static Border getPaletteBorder() { - if (paletteBorder == null) { - paletteBorder = new PaletteBorder(); - } - return paletteBorder; - } - - public static Border getScrollPaneBorder() { - if (scrollPaneBorder == null) { - scrollPaneBorder = new ScrollPaneBorder(false); - } - return scrollPaneBorder; - } - - public static Border getTableScrollPaneBorder() { - if (tableScrollPaneBorder == null) { - tableScrollPaneBorder = new ScrollPaneBorder(true); - } - return tableScrollPaneBorder; - } - - public static Border getTabbedPaneBorder() { - if (tabbedPaneBorder == null) { - tabbedPaneBorder = BorderFactory.createEmptyBorder(1, 1, 1, 1); - } - return tabbedPaneBorder; - } - - public static Border getDesktopIconBorder() { - if (desktopIconBorder == null) { - desktopIconBorder = new BorderUIResource.CompoundBorderUIResource( - new LineBorder(AbstractLookAndFeel.getWindowBorderColor(), 1), - new MatteBorder(2, 2, 1, 2, AbstractLookAndFeel.getWindowBorderColor())); - } - return desktopIconBorder; - } - - //------------------------------------------------------------------------------------ - // Implementation of border classes - //------------------------------------------------------------------------------------ - public static class FocusFrameBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(2, 2, 2, 2); - - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - Color hiColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFocusFrameColor(), 60); - Color loColor = AbstractLookAndFeel.getTheme().getFocusFrameColor(); - g.setColor(loColor); - g.drawRect(x, y, width - 1, height - 1); - g.setColor(hiColor); - g.drawRect(x + 1, y + 1, width - 3, height - 3); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - } // class FocusFrameBorder - - public static class TextFieldBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(2, 2, 2, 2); - - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - g.setColor(AbstractLookAndFeel.getTheme().getFrameColor()); - g.drawRect(x, y, width - 1, height - 1); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - } // class TextFieldBorder - - public static class SpinnerBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - g.setColor(AbstractLookAndFeel.getTheme().getFrameColor()); - g.drawRect(x, y, width - 1, height - 1); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - } // class SpinnerBorder - - public static class ComboBoxBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - g.setColor(AbstractLookAndFeel.getTheme().getFrameColor()); - g.drawRect(x, y, width - 1, height - 1); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - } // class ComboBoxBorder - - public static class TableHeaderBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(2, 2, 2, 0); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Graphics2D g2D = (Graphics2D)g; - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f); - g2D.setComposite(alpha); - Color cHi = AbstractLookAndFeel.getTheme().getControlHighlightColor(); - Color cLo = AbstractLookAndFeel.getTheme().getControlShadowColor(); - JTattooUtilities.draw3DBorder(g, cHi, cLo, x, y, w, h); - g2D.setComposite(savedComposite); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - } // class TableHeaderBorder - - public static class ScrollPaneBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(2, 2, 2, 2); - private static final Insets tableInsets = new Insets(1, 1, 1, 1); - - private boolean tableBorder = false; - - public ScrollPaneBorder(boolean tableBorder) { - this.tableBorder = tableBorder; - } - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - g.setColor(AbstractLookAndFeel.getTheme().getFrameColor()); - g.drawRect(x, y, w - 1, h - 1); - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getTheme().getBackgroundColor(), 50)); - g.drawRect(x + 1, y + 1, w - 3, h - 3); - } - - public Insets getBorderInsets(Component c) { - if (tableBorder) { - return new Insets(tableInsets.top, tableInsets.left, tableInsets.bottom, tableInsets.right); - } else { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - Insets ins = getBorderInsets(c); - borderInsets.left = ins.left; - borderInsets.top = ins.top; - borderInsets.right = ins.right; - borderInsets.bottom = ins.bottom; - return borderInsets; - } - - } // class ScrollPaneBorder - - public static class BasePopupMenuBorder extends AbstractBorder implements UIResource { - - protected static Font logoFont; - protected static Insets leftLogoInsets; - protected static Insets rightLogoInsets; - protected static Insets insets; - protected static int shadowSize; - - public BasePopupMenuBorder() { - logoFont = new Font("Dialog", Font.BOLD, 12); - leftLogoInsets = new Insets(2, 18, 1, 1); - rightLogoInsets = new Insets(2, 2, 1, 18); - insets = new Insets(2, 1, 1, 1); - shadowSize = 0; - } - - public boolean isMenuBarPopup(Component c) { - boolean menuBarPopup = false; - if (c instanceof JPopupMenu) { - JPopupMenu pm = (JPopupMenu) c; - if (pm.getInvoker() != null) { - menuBarPopup = (pm.getInvoker().getParent() instanceof JMenuBar); - } - } - return menuBarPopup; - } - - public boolean hasLogo(Component c) { - return ((AbstractLookAndFeel.getTheme().getLogoString() != null) && (AbstractLookAndFeel.getTheme().getLogoString().length() > 0)); - } - - public Color getLogoColorHi() { - return Color.white; - } - - public Color getLogoColorLo() { - return ColorHelper.darker(AbstractLookAndFeel.getTheme().getMenuSelectionBackgroundColor(), 20); - } - - public void paintLogo(Component c, Graphics g, int x, int y, int w, int h) { - if (hasLogo(c)) { - Graphics2D g2D = (Graphics2D)g; - - Font savedFont = g2D.getFont(); - g.setFont(logoFont); - - FontMetrics fm = g2D.getFontMetrics(); - String logo = JTattooUtilities.getClippedText(AbstractLookAndFeel.getTheme().getLogoString(), fm, h - 16); - - AffineTransform savedTransform = g2D.getTransform(); - - Color fc = getLogoColorHi(); - Color bc = getLogoColorLo(); - - if (JTattooUtilities.isLeftToRight(c)) { - g2D.translate(fm.getAscent() + 1, h - shadowSize - 4); - g2D.rotate(Math.toRadians(-90)); - g2D.setColor(bc); - JTattooUtilities.drawString((JComponent)c, g, logo, 0, 1); - g2D.setColor(fc); - JTattooUtilities.drawString((JComponent)c, g, logo, 1, 0); - } else { - g2D.translate(w - shadowSize - 4, h - shadowSize - 4); - g2D.rotate(Math.toRadians(-90)); - g2D.setColor(bc); - JTattooUtilities.drawString((JComponent)c, g, logo, 0, 1); - g2D.setColor(fc); - JTattooUtilities.drawString((JComponent)c, g, logo, 1, 0); - } - - g2D.setTransform(savedTransform); - g2D.setFont(savedFont); - } - } - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Color logoColor = AbstractLookAndFeel.getMenuSelectionBackgroundColor(); - Color borderColorLo = AbstractLookAndFeel.getFrameColor(); - Color borderColorHi = ColorHelper.brighter(AbstractLookAndFeel.getMenuSelectionBackgroundColor(), 40); - g.setColor(logoColor); - if (JTattooUtilities.isLeftToRight(c)) { - int dx = getBorderInsets(c).left; - g.fillRect(x, y, dx - 1, h - 1); - paintLogo(c, g, x, y, w, h); - // - highlight - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getMenuBackgroundColor(), 40)); - g.drawLine(x + dx, y + 1, x + w - 2, y + 1); - g.setColor(borderColorHi); - g.drawLine(x + 1, y, x + 1, y + h - 2); - // - outer frame - g.setColor(borderColorLo); - if (isMenuBarPopup(c)) { - // top - g.drawLine(x + dx - 1, y, x + w, y); - // left - g.drawLine(x, y, x, y + h - 1); - // bottom - g.drawLine(x, y + h - 1, x + w, y + h - 1); - // right - g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); - } else { - g.drawRect(x, y, w - 1, h - 1); - } - // - logo separator - g.drawLine(x + dx - 1, y + 1, x + dx - 1, y + h - 1); - } else { - int dx = getBorderInsets(c).right; - g.fillRect(x + w - dx, y, dx, h - 1); - paintLogo(c, g, x, y, w, h); - // - highlight - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getMenuBackgroundColor(), 40)); - g.drawLine(x + 1, y + 1, x + w - dx - 1, y + 1); - g.drawLine(x + 1, y + 1, x + 1, y + h - 2); - // - outer frame - g.setColor(borderColorLo); - if (isMenuBarPopup(c)) { - // top - g.drawLine(x, y, x + w - dx, y); - // left - g.drawLine(x, y, x, y + h - 1); - // bottom - g.drawLine(x, y + h - 1, x + w, y + h - 1); - // right - g.drawLine(x + w - 1, y, x + w - 1, y + h - 1); - } else { - g.drawRect(x, y, w - 1, h - 1); - } - // - logo separator - g.drawLine(x + w - dx, y + 1, x + w - dx, y + h - 1); - } - } - - public Insets getBorderInsets(Component c) { - if (hasLogo(c)) { - if (JTattooUtilities.isLeftToRight(c)) { - return new Insets(leftLogoInsets.top, leftLogoInsets.left, leftLogoInsets.bottom + shadowSize, leftLogoInsets.right + shadowSize); - } else { - return new Insets(rightLogoInsets.top, rightLogoInsets.left, rightLogoInsets.bottom + shadowSize, rightLogoInsets.right + shadowSize); - } - } else { - return new Insets(insets.top, insets.left, insets.bottom + shadowSize, insets.right + shadowSize); - } - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - Insets ins = getBorderInsets(c); - borderInsets.left = ins.left; - borderInsets.top = ins.top; - borderInsets.right = ins.right; - borderInsets.bottom = ins.bottom; - return borderInsets; - } - - } // class PopupMenuBorder - - public static class BasePopupMenuShadowBorder extends BasePopupMenuBorder { - - public BasePopupMenuShadowBorder() { - shadowSize = 4; - } - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, AbstractLookAndFeel.getTheme().getMenuAlpha()); - g2D.setComposite(alpha); - Color logoColor = AbstractLookAndFeel.getTheme().getMenuSelectionBackgroundColor(); - Color borderColorLo = AbstractLookAndFeel.getFrameColor(); - Color borderColorHi = ColorHelper.brighter(AbstractLookAndFeel.getMenuSelectionBackgroundColor(), 40); - g.setColor(logoColor); - if (JTattooUtilities.isLeftToRight(c)) { - int dx = getBorderInsets(c).left; - g.fillRect(x, y, dx - 1, h - 1 - shadowSize); - paintLogo(c, g, x, y, w, h); - // - highlight - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getMenuBackgroundColor(), 40)); - g.drawLine(x + dx, y + 1, x + w - shadowSize - 2, y + 1); - g.setColor(borderColorHi); - g.drawLine(x + 1, y, x + 1, y + h - shadowSize - 2); - // - outer frame - g.setColor(borderColorLo); - if (isMenuBarPopup(c)) { - // top - g.drawLine(x + dx - 1, y, x + w - shadowSize - 1, y); - // left - g.drawLine(x, y, x, y + h - shadowSize - 1); - // bottom - g.drawLine(x, y + h - shadowSize - 1, x + w - shadowSize - 1, y + h - shadowSize - 1); - // right - g.drawLine(x + w - shadowSize - 1, y + 1, x + w - shadowSize - 1, y + h - shadowSize - 1); - } else { - g.drawRect(x, y, w - shadowSize - 1, h - shadowSize - 1); - } - // - logo separator - g.drawLine(x + dx - 1, y + 1, x + dx - 1, y + h - shadowSize - 1); - } else { - int dx = getBorderInsets(c).right - shadowSize; - g.fillRect(x + w - dx - shadowSize, y, dx - 1, h - 1 - shadowSize); - paintLogo(c, g, x, y, w, h); - // - highlight - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getMenuBackgroundColor(), 40)); - g.drawLine(x + 1, y + 1, x + w - dx - shadowSize - 1, y + 1); - g.drawLine(x + 1, y + 1, x + 1, y + h - shadowSize - 2); - // - outer frame - g.setColor(borderColorLo); - if (isMenuBarPopup(c)) { - // top - g.drawLine(x, y, x + w - dx - shadowSize, y); - // left - g.drawLine(x, y, x, y + h - shadowSize - 1); - // bottom - g.drawLine(x, y + h - shadowSize - 1, x + w - shadowSize - 1, y + h - shadowSize - 1); - // right - g.drawLine(x + w - shadowSize - 1, y, x + w - shadowSize - 1, y + h - shadowSize - 1); - } else { - g.drawRect(x, y, w - shadowSize - 1, h - shadowSize - 1); - } - // - logo separator - g.drawLine(x + w - dx - shadowSize, y + 1, x + w - dx - shadowSize, y + h - shadowSize - 1); - } - - // paint the shadow - g2D.setColor(AbstractLookAndFeel.getTheme().getShadowColor()); - float alphaValue = 0.4f; - for (int i = 0; i < shadowSize; i++) { - alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alphaValue); - g2D.setComposite(alpha); - g.drawLine(x + w - shadowSize + i, y + shadowSize, x + w - shadowSize + i, y + h - shadowSize - 1 + i); - g.drawLine(x + shadowSize, y + h - shadowSize + i, x + w - shadowSize + i, y + h - shadowSize + i); - alphaValue -= (alphaValue / 2); - } - - g2D.setComposite(savedComposite); - } - - } // class PopupMenuShadowBorder - - public static class MenuItemBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(2, 2, 2, 2); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - JMenuItem b = (JMenuItem) c; - ButtonModel model = b.getModel(); - Color borderColorLo = AbstractLookAndFeel.getFrameColor(); - Color borderColorHi = ColorHelper.brighter(AbstractLookAndFeel.getMenuSelectionBackgroundColor(), 40); - if (c.getParent() instanceof JMenuBar) { - if (model.isArmed() || model.isSelected()) { - g.setColor(borderColorLo); - g.drawLine(x, y, x + w - 1, y); - g.drawLine(x, y, x, y + h - 1); - g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); - g.setColor(borderColorHi); - g.drawLine(x + 1, y + 1, x + w - 2, y + 1); - g.drawLine(x + 1, y + 1, x + 1, y + h - 1); - } - } else { - if (model.isArmed() || (c instanceof JMenu && model.isSelected())) { - g.setColor(borderColorLo); - g.drawLine(x, y, x + w - 1, y); - g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); - g.setColor(borderColorHi); - g.drawLine(x, y + 1, x + w - 2, y + 1); - } - } - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - } // class MenuItemBorder - - public static class ToolBarBorder extends AbstractBorder implements UIResource, SwingConstants { - - private static final Color shadow = new Color(160, 160, 160); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - if (((JToolBar) c).isFloatable()) { - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); - g2D.setComposite(alpha); - if (((JToolBar) c).getOrientation() == HORIZONTAL) { - if (!JTattooUtilities.isLeftToRight(c)) { - x += w - 15; - } - g.setColor(Color.white); - g.drawLine(x + 3, y + 4, x + 3, h - 5); - g.drawLine(x + 6, y + 3, x + 6, h - 4); - g.drawLine(x + 9, y + 4, x + 9, h - 5); - g.setColor(shadow); - g.drawLine(x + 4, y + 4, x + 4, h - 5); - g.drawLine(x + 7, y + 3, x + 7, h - 4); - g.drawLine(x + 10, y + 4, x + 10, h - 5); - } else { - // vertical - g.setColor(Color.white); - g.drawLine(x + 3, y + 3, w - 4, y + 3); - g.drawLine(x + 3, y + 6, w - 4, y + 6); - g.drawLine(x + 3, y + 9, w - 4, y + 9); - g.setColor(shadow); - g.drawLine(x + 3, y + 4, w - 4, y + 4); - g.drawLine(x + 3, y + 7, w - 4, y + 7); - g.drawLine(x + 3, y + 10, w - 4, y + 10); - } - g2D.setComposite(savedComposite); - } - } - - public Insets getBorderInsets(Component c) { - Insets insets = new Insets(2, 2, 2, 2); - if (((JToolBar) c).isFloatable()) { - if (((JToolBar) c).getOrientation() == HORIZONTAL) { - if (JTattooUtilities.isLeftToRight(c)) { - insets.left = 15; - } else { - insets.right = 15; - } - } else { - insets.top = 15; - } - } - Insets margin = ((JToolBar) c).getMargin(); - if (margin != null) { - insets.left += margin.left; - insets.top += margin.top; - insets.right += margin.right; - insets.bottom += margin.bottom; - } - return insets; - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - Insets insets = getBorderInsets(c); - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - } // class ToolBarBorder - - public static class ToolButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(2, 2, 2, 2); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - Color frameColor = AbstractLookAndFeel.getToolbarBackgroundColor(); - Color frameHiColor = ColorHelper.brighter(frameColor, 10); - Color frameLoColor = ColorHelper.darker(frameColor, 30); - JTattooUtilities.draw3DBorder(g, frameHiColor, frameLoColor, x, y, w, h); - if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - JTattooUtilities.draw3DBorder(g, frameLoColor, frameHiColor, x, y, w, h); - } else { - JTattooUtilities.draw3DBorder(g, frameLoColor, frameHiColor, x, y, w, h); - JTattooUtilities.draw3DBorder(g, frameHiColor, frameLoColor, x + 1, y + 1, w - 2, h - 2); - } - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class ToolButtonBorder - - public static class PaletteBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - if (JTattooUtilities.isFrameActive((JComponent) c)) { - g.setColor(AbstractLookAndFeel.getWindowBorderColor()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveBorderColor()); - } - g.drawRect(x, y, w - 1, h - 1); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - } // class PaletteBorder - - public static class BaseInternalFrameBorder extends AbstractBorder implements UIResource { - - protected final int dw = 5; - protected final int trackWidth = 22; - protected final Insets insets = new Insets(dw, dw, dw, dw); - protected final Insets paletteInsets = new Insets(3, 3, 3, 3); - - public BaseInternalFrameBorder() { - } - - public boolean isResizable(Component c) { - boolean resizable = true; - if (c instanceof JDialog) { - JDialog dialog = (JDialog) c; - resizable = dialog.isResizable(); - } else if (c instanceof JInternalFrame) { - JInternalFrame frame = (JInternalFrame) c; - resizable = frame.isResizable(); - } else if (c instanceof JRootPane) { - JRootPane jp = (JRootPane) c; - if (jp.getParent() instanceof JFrame) { - JFrame frame = (JFrame) c.getParent(); - resizable = frame.isResizable(); - } else if (jp.getParent() instanceof JDialog) { - JDialog dialog = (JDialog) c.getParent(); - resizable = dialog.isResizable(); - } - } - return resizable; - } - - public boolean isActive(Component c) { - boolean active = true; - if (c instanceof JDialog) { - JDialog dlg = (JDialog) c; - if (dlg.getParent() instanceof JComponent) { - return JTattooUtilities.isActive((JComponent) (dlg.getParent())); - } - } else if (c instanceof JInternalFrame) { - JInternalFrame frame = (JInternalFrame) c; - active = frame.isSelected(); - if (active) { - return JTattooUtilities.isActive(frame); - } - } else if (c instanceof JRootPane) { - JRootPane jp = (JRootPane) c; - if (jp.getTopLevelAncestor() instanceof Window) { - Window window = (Window) jp.getTopLevelAncestor(); - return JTattooUtilities.isWindowActive(window); - } - } - return active; - } - - public int getTitleHeight(Component c) { - int th = 21; - int fh = getBorderInsets(c).top + getBorderInsets(c).bottom; - if (c instanceof JDialog) { - JDialog dialog = (JDialog) c; - th = dialog.getSize().height - dialog.getContentPane().getSize().height - fh - 1; - if (dialog.getJMenuBar() != null) { - th -= dialog.getJMenuBar().getSize().height; - } - } else if (c instanceof JInternalFrame) { - JInternalFrame frame = (JInternalFrame) c; - th = frame.getSize().height - frame.getRootPane().getSize().height - fh - 1; - if (frame.getJMenuBar() != null) { - th -= frame.getJMenuBar().getSize().height; - } - } else if (c instanceof JRootPane) { - JRootPane jp = (JRootPane) c; - if (jp.getParent() instanceof JFrame) { - JFrame frame = (JFrame) c.getParent(); - th = frame.getSize().height - frame.getContentPane().getSize().height - fh - 1; - if (frame.getJMenuBar() != null) { - th -= frame.getJMenuBar().getSize().height; - } - } else if (jp.getParent() instanceof JDialog) { - JDialog dialog = (JDialog) c.getParent(); - th = dialog.getSize().height - dialog.getContentPane().getSize().height - fh - 1; - if (dialog.getJMenuBar() != null) { - th -= dialog.getJMenuBar().getSize().height; - } - } - } - return th; - } - - public Insets getBorderInsets(Component c) { - if (isResizable(c)) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } else { - return new Insets(paletteInsets.top, paletteInsets.left, paletteInsets.bottom, paletteInsets.right); - } - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - Insets ins = getBorderInsets(c); - borderInsets.left = ins.left; - borderInsets.top = ins.top; - borderInsets.right = ins.right; - borderInsets.bottom = ins.bottom; - return borderInsets; - } - - } // class BaseInternalFrameBorder - - public static class Down3DBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Color frameColor = AbstractLookAndFeel.getTheme().getBackgroundColor(); - JTattooUtilities.draw3DBorder(g, ColorHelper.darker(frameColor, 20), ColorHelper.brighter(frameColor, 80), x, y, w, h); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - } // class Down3DBorder - -} // class BaseBorders diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseButtonListener.java b/src/jtattoo/src/com/jtattoo/plaf/BaseButtonListener.java deleted file mode 100644 index ea4c72060..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseButtonListener.java +++ /dev/null @@ -1,62 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.event.FocusEvent; -import java.awt.event.MouseEvent; -import javax.swing.AbstractButton; -import javax.swing.plaf.basic.BasicButtonListener; - -public class BaseButtonListener extends BasicButtonListener { - - public BaseButtonListener(AbstractButton b) { - super(b); - } - - public void focusGained(FocusEvent e) { - AbstractButton b = (AbstractButton) e.getSource(); - b.repaint(); - } - - public void focusLost(FocusEvent e) { - AbstractButton b = (AbstractButton) e.getSource(); - b.repaint(); - } - - public void mouseEntered(MouseEvent e) { - super.mouseEntered(e); - AbstractButton button = (AbstractButton) e.getSource(); - button.getModel().setRollover(true); - } - - public void mouseExited(MouseEvent e) { - super.mouseExited(e); - AbstractButton button = (AbstractButton) e.getSource(); - button.getModel().setRollover(false); - } - - public void mouseReleased(MouseEvent e) { - super.mouseReleased(e); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseButtonUI.java deleted file mode 100644 index 9bbd30bcb..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseButtonUI.java +++ /dev/null @@ -1,229 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is dual licensed. You can use it under the terms and conditions of the -* GNU General Public License version 2.0 or later as published by the Free Software -* Foundation. -* -* see: gpl-2.0.txt -* -* Registered users (this who payed for a license) could use the software under the -* terms and conditions of the GNU Lesser General Public License version 2.0 or later -* with classpath exception as published by the Free Software Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.KeyEvent; -import javax.swing.*; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.*; -import javax.swing.text.View; - -/** - * @author Michael Hagen - */ -public class BaseButtonUI extends BasicButtonUI { - - protected static Rectangle viewRect = new Rectangle(); - protected static Rectangle textRect = new Rectangle(); - protected static Rectangle iconRect = new Rectangle(); - protected static Color[] defaultColors = null; - - public static ComponentUI createUI(JComponent c) { - return new BaseButtonUI(); - } - - protected void installKeyboardActions(AbstractButton b) { - super.installKeyboardActions(b); - InputMap im = (InputMap) UIManager.get("Button.focusInputMap"); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "pressed"); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), "released"); - Color cArr[] = AbstractLookAndFeel.getTheme().getButtonColors(); - defaultColors = new Color[cArr.length]; - for (int i = 0; i < cArr.length; i++) { - defaultColors[i] = ColorHelper.brighter(cArr[i], 20); - } - } - - public void installDefaults(AbstractButton b) { - super.installDefaults(b); - b.setOpaque(false); - b.setRolloverEnabled(true); - } - - public void uninstallDefaults(AbstractButton b) { - super.uninstallDefaults(b); - b.setOpaque(true); - b.setRolloverEnabled(false); - } - - protected BasicButtonListener createButtonListener(AbstractButton b) { - return new BaseButtonListener(b); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - if (!b.isContentAreaFilled() || (b.getParent() instanceof JMenuBar)) { - return; - } - - int width = b.getWidth(); - int height = b.getHeight(); - - ButtonModel model = b.getModel(); - Color colors[] = AbstractLookAndFeel.getTheme().getButtonColors(); - if (b.isEnabled()) { - Color background = b.getBackground(); - if (background instanceof ColorUIResource) { - if (model.isPressed() && model.isArmed()) { - colors = AbstractLookAndFeel.getTheme().getPressedColors(); - } else if (b.isRolloverEnabled() && model.isRollover()) { - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - } else if (AbstractLookAndFeel.getTheme().doShowFocusFrame() && b.hasFocus()) { - colors = AbstractLookAndFeel.getTheme().getFocusColors(); - } else if (JTattooUtilities.isFrameActive(b) - && (b.getRootPane() != null) - && (b.equals(b.getRootPane().getDefaultButton()))) { - colors = defaultColors; - } - } else { - if (model.isPressed() && model.isArmed()) { - colors = ColorHelper.createColorArr(ColorHelper.darker(background, 30), ColorHelper.darker(background, 10), 20); - } else { - if (b.isRolloverEnabled() && model.isRollover()) { - colors = ColorHelper.createColorArr(ColorHelper.brighter(background, 50), ColorHelper.brighter(background, 10), 20); - } else { - colors = ColorHelper.createColorArr(ColorHelper.brighter(background, 30), ColorHelper.darker(background, 10), 20); - } - } - } - } else { // disabled - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } - - if (b.isBorderPainted() && (b.getBorder() != null)) { - Insets insets = b.getBorder().getBorderInsets(b); - int x = insets.left > 0 ? 1 : 0; - int y = insets.top > 0 ? 1 : 0; - int w = insets.right > 0 ? width - 1 : width; - int h = insets.bottom > 0 ? height - 1 : height; - JTattooUtilities.fillHorGradient(g, colors, x, y, w - x, h - y); - } else { - JTattooUtilities.fillHorGradient(g, colors, 0, 0, width, height); - } - } - - protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) { - ButtonModel model = b.getModel(); - FontMetrics fm = g.getFontMetrics(); - int mnemIndex; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = b.getDisplayedMnemonicIndex(); - } else { - mnemIndex = JTattooUtilities.findDisplayedMnemonicIndex(b.getText(), model.getMnemonic()); - } - - if (model.isEnabled()) { - Color foreground = b.getForeground(); - int offs = 0; - if (model.isArmed() && model.isPressed()) { - offs = 1; - } - if (foreground instanceof ColorUIResource) { - if (model.isRollover()) { - g.setColor(AbstractLookAndFeel.getTheme().getRolloverForegroundColor()); - } else if (model.isPressed()) { - g.setColor(AbstractLookAndFeel.getTheme().getPressedForegroundColor()); - } else { - g.setColor(b.getForeground()); - } - } else { - g.setColor(b.getForeground()); - } - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x + offs, textRect.y + offs + fm.getAscent()); - } else { - g.setColor(Color.white); - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x + 1, textRect.y + 1 + fm.getAscent()); - g.setColor(AbstractLookAndFeel.getDisabledForegroundColor()); - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); - } - } - - protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - BasicGraphicsUtils.drawDashedRect(g, 4, 3, b.getWidth() - 8, b.getHeight() - 6); - } - - public void paint(Graphics g, JComponent c) { - Graphics2D g2D = (Graphics2D) g; - - AbstractButton b = (AbstractButton) c; - Font f = c.getFont(); - g.setFont(f); - FontMetrics fm = g.getFontMetrics(); - Insets insets = c.getInsets(); - - viewRect.x = insets.left; - viewRect.y = insets.top; - viewRect.width = b.getWidth() - (insets.right + viewRect.x); - viewRect.height = b.getHeight() - (insets.bottom + viewRect.y); - - textRect.x = textRect.y = textRect.width = textRect.height = 0; - iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0; - - int iconTextGap = defaultTextIconGap; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - iconTextGap = b.getIconTextGap(); - } - String text = SwingUtilities.layoutCompoundLabel( - c, fm, b.getText(), b.getIcon(), - b.getVerticalAlignment(), b.getHorizontalAlignment(), - b.getVerticalTextPosition(), b.getHorizontalTextPosition(), - viewRect, iconRect, textRect, - b.getText() == null ? 0 : iconTextGap); - - paintBackground(g, b); - - if (b.getIcon() != null) { - if (!b.isEnabled()) { - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); - g2D.setComposite(alpha); - paintIcon(g, c, iconRect); - g2D.setComposite(savedComposite); - } else { - if (b.getModel().isPressed() && b.getModel().isRollover()) { - iconRect.x++; - iconRect.y++; - } - paintIcon(g, c, iconRect); - } - } - - if (text != null && !text.equals("")) { - View v = (View) c.getClientProperty(BasicHTML.propertyKey); - if (v != null) { - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - } - v.paint(g, textRect); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } else { - paintText(g, b, textRect, text); - } - } - - if (b.isFocusPainted() && b.hasFocus()) { - paintFocus(g, b, viewRect, textRect, iconRect); - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseCheckBoxMenuItemUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseCheckBoxMenuItemUI.java deleted file mode 100644 index 3b643da11..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseCheckBoxMenuItemUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import javax.swing.JComponent; -import javax.swing.UIManager; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class BaseCheckBoxMenuItemUI extends BaseMenuItemUI { - - public static ComponentUI createUI(JComponent c) { - return new BaseCheckBoxMenuItemUI(); - } - - protected void installDefaults() { - super.installDefaults(); - checkIcon = UIManager.getIcon("CheckBoxMenuItem.checkIcon"); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseCheckBoxUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseCheckBoxUI.java deleted file mode 100644 index b21829187..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseCheckBoxUI.java +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class BaseCheckBoxUI extends BaseRadioButtonUI { - - private static BaseCheckBoxUI checkBoxUI = null; - - public static ComponentUI createUI(JComponent b) { - if (checkBoxUI == null) { - checkBoxUI = new BaseCheckBoxUI(); - } - return checkBoxUI; - } - - public void installDefaults(AbstractButton b) { - super.installDefaults(b); - icon = UIManager.getIcon("CheckBox.icon"); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseComboBoxUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseComboBoxUI.java deleted file mode 100644 index 70c65b619..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseComboBoxUI.java +++ /dev/null @@ -1,178 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicComboBoxUI; - -public class BaseComboBoxUI extends BasicComboBoxUI { - - private PropertyChangeListener propertyChangeListener = null; - private FocusListener focusListener = null; - private Border orgBorder = null; - private Color orgBackgroundColor = null; - - public static ComponentUI createUI(JComponent c) { - return new BaseComboBoxUI(); - } - - public void installUI(JComponent c) { - super.installUI(c); - comboBox.setRequestFocusEnabled(true); - if (comboBox.getEditor() != null) { - if (comboBox.getEditor().getEditorComponent() instanceof JTextField) { - ((JTextField) (comboBox.getEditor().getEditorComponent())).setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); - } - } - } - - protected void installListeners() { - super.installListeners(); - propertyChangeListener = new PropertyChangeHandler(); - comboBox.addPropertyChangeListener(propertyChangeListener); - - if (AbstractLookAndFeel.getTheme().doShowFocusFrame()) { - focusListener = new FocusListener() { - - public void focusGained(FocusEvent e) { - if (comboBox != null) { - orgBorder = comboBox.getBorder(); - orgBackgroundColor = comboBox.getBackground(); - LookAndFeel laf = UIManager.getLookAndFeel(); - if (laf instanceof AbstractLookAndFeel) { - if (orgBorder instanceof UIResource) { - Border focusBorder = ((AbstractLookAndFeel)laf).getBorderFactory().getFocusFrameBorder(); - comboBox.setBorder(focusBorder); - } - Color backgroundColor = AbstractLookAndFeel.getTheme().getFocusBackgroundColor(); - comboBox.setBackground(backgroundColor); - } - } - } - - public void focusLost(FocusEvent e) { - if (comboBox != null) { - if (orgBorder instanceof UIResource) { - comboBox.setBorder(orgBorder); - } - comboBox.setBackground(orgBackgroundColor); - } - } - }; - comboBox.addFocusListener(focusListener); - } - } - - protected void uninstallListeners() { - comboBox.removePropertyChangeListener(propertyChangeListener); - comboBox.removeFocusListener(focusListener); - propertyChangeListener = null; - focusListener = null; - super.uninstallListeners(); - } - - public Dimension getPreferredSize(JComponent c) { - Dimension size = super.getPreferredSize(c); - return new Dimension(size.width + 2, size.height + 2); - } - - public JButton createArrowButton() { - JButton button = new ArrowButton(); - if (JTattooUtilities.isLeftToRight(comboBox)) { - Border border = BorderFactory.createMatteBorder(0, 1, 0, 0, AbstractLookAndFeel.getFrameColor()); - button.setBorder(border); - } else { - Border border = BorderFactory.createMatteBorder(0, 0, 0, 1, AbstractLookAndFeel.getFrameColor()); - button.setBorder(border); - } - return button; - } - - protected void setButtonBorder() { - if (JTattooUtilities.isLeftToRight(comboBox)) { - Border border = BorderFactory.createMatteBorder(0, 1, 0, 0, AbstractLookAndFeel.getFrameColor()); - arrowButton.setBorder(border); - } else { - Border border = BorderFactory.createMatteBorder(0, 0, 0, 1, AbstractLookAndFeel.getFrameColor()); - arrowButton.setBorder(border); - } - } - - public class PropertyChangeHandler implements PropertyChangeListener { - - public void propertyChange(PropertyChangeEvent e) { - String name = e.getPropertyName(); - if (name.equals("componentOrientation")) { - setButtonBorder(); - } - } - } -//----------------------------------------------------------------------------- - - public static class ArrowButton extends NoFocusButton { - - public void paint(Graphics g) { - Dimension size = getSize(); - Color colors[]; - if (isEnabled()) { - if (getModel().isArmed() && getModel().isPressed()) { - colors = AbstractLookAndFeel.getTheme().getPressedColors(); - } else if (getModel().isRollover()) { - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - } else { - colors = AbstractLookAndFeel.getTheme().getButtonColors(); - } - } else { - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } - JTattooUtilities.fillHorGradient(g, colors, 0, 0, size.width, size.height); - - boolean inverse = ColorHelper.getGrayValue(colors) < 128; - - Icon icon = inverse ? BaseIcons.getComboBoxInverseIcon() : BaseIcons.getComboBoxIcon();; - int x = (size.width - icon.getIconWidth()) / 2; - int y = (size.height - icon.getIconHeight()) / 2; - - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f)); - if (getModel().isPressed() && getModel().isArmed()) { - icon.paintIcon(this, g, x + 2, y + 1); - } else { - icon.paintIcon(this, g, x + 1, y); - } - g2D.setComposite(savedComposite); - paintBorder(g2D); - - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseDesktopPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseDesktopPaneUI.java deleted file mode 100644 index 21a325532..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseDesktopPaneUI.java +++ /dev/null @@ -1,53 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.Graphics; -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicDesktopPaneUI; - -/** - * @author Michael Hagen - */ -public class BaseDesktopPaneUI extends BasicDesktopPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new BaseDesktopPaneUI(); - } - - public void update(Graphics g, JComponent c) { - if (c.isOpaque()) { - Object backgroundTexture = c.getClientProperty("backgroundTexture"); - if (backgroundTexture instanceof Icon) { - JTattooUtilities.fillComponent(g, c, (Icon)backgroundTexture); - } else { - g.setColor(c.getBackground()); - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } - paint(g, c); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseEditorPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseEditorPaneUI.java deleted file mode 100644 index 06e5b269d..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseEditorPaneUI.java +++ /dev/null @@ -1,128 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.Graphics; -import java.awt.Toolkit; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.KeyEvent; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicEditorPaneUI; -import javax.swing.text.DefaultEditorKit; -import javax.swing.text.JTextComponent; - -/** - * @author Michael Hagen - */ -public class BaseEditorPaneUI extends BasicEditorPaneUI { - - private Border orgBorder = null; - private FocusListener focusListener = null; - - public static ComponentUI createUI(JComponent c) { - return new BaseEditorPaneUI(); - } - - public void installDefaults() { - super.installDefaults(); - updateBackground(); - } - - protected void installKeyboardActions() { - super.installKeyboardActions(); - if (JTattooUtilities.isMac()) { - InputMap im = (InputMap) UIManager.get("TextField.focusInputMap"); - int commandKey = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, commandKey), DefaultEditorKit.copyAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, commandKey), DefaultEditorKit.pasteAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, commandKey), DefaultEditorKit.cutAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.ALT_DOWN_MASK), DefaultEditorKit.nextWordAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.ALT_DOWN_MASK), DefaultEditorKit.previousWordAction); - } - } - - protected void installListeners() { - super.installListeners(); - - if (AbstractLookAndFeel.getTheme().doShowFocusFrame()) { - focusListener = new FocusListener() { - - public void focusGained(FocusEvent e) { - if (getComponent() != null) { - orgBorder = getComponent().getBorder(); - LookAndFeel laf = UIManager.getLookAndFeel(); - if (laf instanceof AbstractLookAndFeel && orgBorder instanceof UIResource) { - Border focusBorder = ((AbstractLookAndFeel)laf).getBorderFactory().getFocusFrameBorder(); - getComponent().setBorder(focusBorder); - } - getComponent().invalidate(); - getComponent().repaint(); - } - } - - public void focusLost(FocusEvent e) { - if (getComponent() != null) { - if (orgBorder instanceof UIResource) { - getComponent().setBorder(orgBorder); - } - getComponent().invalidate(); - getComponent().repaint(); - } - } - }; - getComponent().addFocusListener(focusListener); - } - } - - protected void uninstallListeners() { - getComponent().removeFocusListener(focusListener); - focusListener = null; - super.uninstallListeners(); - } - - protected void paintBackground(Graphics g) { - g.setColor(getComponent().getBackground()); - if (AbstractLookAndFeel.getTheme().doShowFocusFrame()) { - if (getComponent().hasFocus() && getComponent().isEditable()) { - g.setColor(AbstractLookAndFeel.getTheme().getFocusBackgroundColor()); - } - } - g.fillRect(0, 0, getComponent().getWidth(), getComponent().getHeight()); - } - - private void updateBackground() { - JTextComponent c = getComponent(); - if (c.getBackground() instanceof UIResource) { - if (!c.isEnabled() || !c.isEditable()) { - c.setBackground(AbstractLookAndFeel.getDisabledBackgroundColor()); - } else { - c.setBackground(AbstractLookAndFeel.getInputBackgroundColor()); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseFileChooserUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseFileChooserUI.java deleted file mode 100644 index 22be126fc..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseFileChooserUI.java +++ /dev/null @@ -1,103 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.Dimension; -import java.io.File; -import javax.swing.*; -import javax.swing.filechooser.FileView; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.metal.MetalFileChooserUI; - -/** - * @author Michael Hagen - */ -public class BaseFileChooserUI extends MetalFileChooserUI { - - private FileView fileView = null; - - // Preferred and Minimum sizes for the dialog box - private static final int PREF_WIDTH = 580; - private static final int PREF_HEIGHT = 340; - private static Dimension PREF_SIZE = new Dimension(PREF_WIDTH, PREF_HEIGHT); - - public BaseFileChooserUI(JFileChooser fileChooser) { - super(fileChooser); - fileView = new BaseFileView(); - } - - public static ComponentUI createUI(JComponent c) { - return new BaseFileChooserUI((JFileChooser) c); - } - - /** - * Returns the preferred size of the specified - * JFileChooser. - * The preferred size is at least as large, - * in both height and width, - * as the preferred size recommended - * by the file chooser's layout manager. - * - * @param c a JFileChooser - * @return a Dimension specifying the preferred - * width and height of the file chooser - */ - public Dimension getPreferredSize(JComponent c) { - int prefWidth = PREF_SIZE.width; - Dimension d = c.getLayout().preferredLayoutSize(c); - if (d != null) { - return new Dimension(d.width < prefWidth ? prefWidth : d.width, - d.height < PREF_SIZE.height ? PREF_SIZE.height : d.height); - } else { - return new Dimension(prefWidth, PREF_SIZE.height); - } - } - - public FileView getFileView(JFileChooser fc) { - if (JTattooUtilities.getJavaVersion() < 1.4) { - return super.getFileView(fc); - } else { - return fileView; - } - } - -//------------------------------------------------------------------------------ - protected class BaseFileView extends BasicFileView { - - public Icon getIcon(File f) { - Icon icon = getCachedIcon(f); - if (icon != null) { - return icon; - } - if (f != null) { - icon = getFileChooser().getFileSystemView().getSystemIcon(f); - } - if (icon == null) { - icon = super.getIcon(f); - } - cacheIcon(f, icon); - return icon; - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseFormattedTextFieldUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseFormattedTextFieldUI.java deleted file mode 100644 index 25485359d..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseFormattedTextFieldUI.java +++ /dev/null @@ -1,108 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicFormattedTextFieldUI; - -/** - * @author Michael Hagen - */ -public class BaseFormattedTextFieldUI extends BasicFormattedTextFieldUI { - - private Border orgBorder = null; - private FocusListener focusListener = null; - - public static ComponentUI createUI(JComponent c) { - return new BaseFormattedTextFieldUI(); - } - - protected void installListeners() { - super.installListeners(); - - if (AbstractLookAndFeel.getTheme().doShowFocusFrame()) { - focusListener = new FocusListener() { - - public void focusGained(FocusEvent e) { - if (getComponent() != null) { - orgBorder = getComponent().getBorder(); - LookAndFeel laf = UIManager.getLookAndFeel(); - if (laf instanceof AbstractLookAndFeel && orgBorder instanceof UIResource) { - Border focusBorder = ((AbstractLookAndFeel)laf).getBorderFactory().getFocusFrameBorder(); - getComponent().setBorder(focusBorder); - } - getComponent().invalidate(); - getComponent().repaint(); - } - } - - public void focusLost(FocusEvent e) { - if (getComponent() != null) { - if (orgBorder instanceof UIResource) { - getComponent().setBorder(orgBorder); - getComponent().invalidate(); - getComponent().repaint(); - } - } - } - }; - getComponent().addFocusListener(focusListener); - } - } - - protected void uninstallListeners() { - getComponent().removeFocusListener(focusListener); - focusListener = null; - super.uninstallListeners(); - } - - protected void paintBackground(Graphics g) { - g.setColor(getComponent().getBackground()); - if (AbstractLookAndFeel.getTheme().doShowFocusFrame()) { - if (getComponent().hasFocus() && getComponent().isEditable()) { - g.setColor(AbstractLookAndFeel.getTheme().getFocusBackgroundColor()); - } - } - g.fillRect(0, 0, getComponent().getWidth(), getComponent().getHeight()); - } - - protected void paintSafely(Graphics g) { - Graphics2D g2D = (Graphics2D) g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - super.paintSafely(g); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseIcons.java b/src/jtattoo/src/com/jtattoo/plaf/BaseIcons.java deleted file mode 100644 index e27177c02..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseIcons.java +++ /dev/null @@ -1,1285 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.geom.*; -import javax.swing.*; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class BaseIcons { - - public static final LazyImageIcon PEARL_RED_24x24 = new LazyImageIcon("icons/pearl_red_24x24.png"); - public static final LazyImageIcon PEARL_YELLOW_24x24 = new LazyImageIcon("icons/pearl_yellow_24x24.png"); - public static final LazyImageIcon PEARL_GREEN_24x24 = new LazyImageIcon("icons/pearl_green_24x24.png"); - public static final LazyImageIcon PEARL_GREY_24x24 = new LazyImageIcon("icons/pearl_grey_24x24.png"); - public static final LazyImageIcon PEARL_RED_28x28 = new LazyImageIcon("icons/pearl_red_28x28.png"); - public static final LazyImageIcon PEARL_YELLOW_28x28 = new LazyImageIcon("icons/pearl_yellow_28x28.png"); - public static final LazyImageIcon PEARL_GREEN_28x28 = new LazyImageIcon("icons/pearl_green_28x28.png"); - public static final LazyImageIcon PEARL_GREY_28x28 = new LazyImageIcon("icons/pearl_grey_28x28.png"); - public static final LazyImageIcon PEARL_RED_32x32 = new LazyImageIcon("icons/pearl_red_32x32.png"); - public static final LazyImageIcon PEARL_YELLOW_32x32 = new LazyImageIcon("icons/pearl_yellow_32x32.png"); - public static final LazyImageIcon PEARL_GREEN_32x32 = new LazyImageIcon("icons/pearl_green_32x32.png"); - public static final LazyImageIcon PEARL_GREY_32x32 = new LazyImageIcon("icons/pearl_grey_32x32.png"); - public static final LazyImageIcon ICONIZER_10x10 = new LazyImageIcon("icons/iconizer_10x10.png"); - public static final LazyImageIcon ICONIZER_12x12 = new LazyImageIcon("icons/iconizer_12x12.png"); - public static final LazyImageIcon MINIMIZER_10x10 = new LazyImageIcon("icons/minimizer_10x10.png"); - public static final LazyImageIcon MINIMIZER_12x12 = new LazyImageIcon("icons/minimizer_12x12.png"); - public static final LazyImageIcon MAXIMIZER_10x10 = new LazyImageIcon("icons/maximizer_10x10.png"); - public static final LazyImageIcon MAXIMIZER_12x12 = new LazyImageIcon("icons/maximizer_12x12.png"); - public static final LazyImageIcon CLOSER_10x10 = new LazyImageIcon("icons/closer_10x10.png"); - public static final LazyImageIcon CLOSER_12x12 = new LazyImageIcon("icons/closer_12x12.png"); - public static final LazyImageIcon EMPTY_8x8 = new LazyImageIcon("icons/empty_8x8.png"); - - protected static Icon comboBoxIcon = null; - protected static Icon checkBoxIcon = null; - protected static Icon menuCheckBoxIcon = null; - protected static Icon radioButtonIcon = null; - protected static Icon menuRadioButtonIcon = null; - protected static Icon optionPaneErrorIcon = null; - protected static Icon optionPaneWarningIcon = null; - protected static Icon optionPaneInformationIcon = null; - protected static Icon optionPaneQuestionIcon = null; - protected static Icon fileChooserDetailViewIcon = null; - protected static Icon fileChooserHomeFolderIcon = null; - protected static Icon fileChooserListViewIcon = null; - protected static Icon fileChooserNewFolderIcon = null; - protected static Icon fileChooserUpFolderIcon = null; - protected static Icon treeComputerIcon = null; - protected static Icon treeFloppyDriveIcon = null; - protected static Icon treeHardDriveIcon = null; - protected static Icon treeFolderIcon = null; - protected static Icon treeLeafIcon = null; - protected static Icon treeOpenIcon = null; - protected static Icon treeClosedIcon = null; - protected static Icon paletteCloseIcon = null; - protected static Icon menuIcon = null; - - protected static Icon iconIcon = null; - protected static Icon maxIcon = null; - protected static Icon minIcon = null; - protected static Icon closeIcon = null; - - protected static Icon upArrowIcon = null; - protected static Icon upArrowInverseIcon = null; - protected static Icon downArrowIcon = null; - protected static Icon downArrowInverseIcon = null; - protected static Icon leftArrowIcon = null; - protected static Icon leftArrowInverseIcon = null; - protected static Icon rightArrowIcon = null; - protected static Icon rightArrowInverseIcon = null; - protected static Icon menuArrowIcon = null; - protected static Icon splitterUpArrowIcon = null; - protected static Icon splitterDownArrowIcon = null; - protected static Icon splitterLeftArrowIcon = null; - protected static Icon splitterRightArrowIcon = null; - protected static Icon splitterHorBumpIcon = null; - protected static Icon splitterVerBumpIcon = null; - protected static Icon thumbHorIcon = null; - protected static Icon thumbVerIcon = null; - protected static Icon thumbHorIconRollover = null; - protected static Icon thumbVerIconRollover = null; - - public static void initDefaults() { - comboBoxIcon = null; - checkBoxIcon = null; - menuCheckBoxIcon = null; - radioButtonIcon = null; - menuRadioButtonIcon = null; - optionPaneErrorIcon = null; - optionPaneWarningIcon = null; - optionPaneInformationIcon = null; - optionPaneQuestionIcon = null; - fileChooserDetailViewIcon = null; - fileChooserHomeFolderIcon = null; - fileChooserListViewIcon = null; - fileChooserNewFolderIcon = null; - fileChooserUpFolderIcon = null; - treeComputerIcon = null; - treeFloppyDriveIcon = null; - treeHardDriveIcon = null; - treeFolderIcon = null; - treeLeafIcon = null; - treeOpenIcon = null; - treeClosedIcon = null; - paletteCloseIcon = null; - menuIcon = null; - iconIcon = null; - maxIcon = null; - minIcon = null; - closeIcon = null; - upArrowIcon = null; - upArrowInverseIcon = null; - downArrowIcon = null; - downArrowInverseIcon = null; - leftArrowIcon = null; - leftArrowInverseIcon = null; - rightArrowIcon = null; - rightArrowInverseIcon = null; - menuArrowIcon = null; - splitterUpArrowIcon = null; - splitterDownArrowIcon = null; - splitterLeftArrowIcon = null; - splitterRightArrowIcon = null; - splitterHorBumpIcon = null; - splitterVerBumpIcon = null; - thumbHorIcon = null; - thumbVerIcon = null; - thumbHorIconRollover = null; - thumbVerIconRollover = null; - } - - public static Icon getRadioButtonIcon() { - if (radioButtonIcon == null) { - radioButtonIcon = new RadioButtonIcon(); - } - return radioButtonIcon; - } - - public static Icon getCheckBoxIcon() { - if (checkBoxIcon == null) { - checkBoxIcon = new CheckBoxIcon(); - } - return checkBoxIcon; - } - - // OptionPane - public static Icon getOptionPaneErrorIcon() { - if (optionPaneErrorIcon == null) { - optionPaneErrorIcon = new LazyImageIcon("icons/OptionPaneError.png"); - } - return optionPaneErrorIcon; - } - - public static Icon getOptionPaneWarningIcon() { - if (optionPaneWarningIcon == null) { - optionPaneWarningIcon = new LazyImageIcon("icons/OptionPaneWarning.png"); - } - return optionPaneWarningIcon; - } - - public static Icon getOptionPaneInformationIcon() { - if (optionPaneInformationIcon == null) { - optionPaneInformationIcon = new LazyImageIcon("icons/OptionPaneInformation.png"); - } - return optionPaneInformationIcon; - } - - public static Icon getOptionPaneQuestionIcon() { - if (optionPaneQuestionIcon == null) { - optionPaneQuestionIcon = new LazyImageIcon("icons/OptionPaneQuestion.png"); - } - return optionPaneQuestionIcon; - } - - // FileChooser - public static Icon getFileChooserDetailViewIcon() { - if (fileChooserDetailViewIcon == null) { - fileChooserDetailViewIcon = new LazyImageIcon("icons/DetailsView.gif"); - } - return fileChooserDetailViewIcon; - } - - public static Icon getFileChooserHomeFolderIcon() { - if (fileChooserHomeFolderIcon == null) { - fileChooserHomeFolderIcon = new LazyImageIcon("icons/Home.gif"); - } - return fileChooserHomeFolderIcon; - } - - public static Icon getFileChooserListViewIcon() { - if (fileChooserListViewIcon == null) { - fileChooserListViewIcon = new LazyImageIcon("icons/ListView.gif"); - } - return fileChooserListViewIcon; - } - - public static Icon getFileChooserNewFolderIcon() { - if (fileChooserNewFolderIcon == null) { - fileChooserNewFolderIcon = new LazyImageIcon("icons/NewFolder.gif"); - } - return fileChooserNewFolderIcon; - } - - public static Icon getFileChooserUpFolderIcon() { - if (fileChooserUpFolderIcon == null) { - fileChooserUpFolderIcon = new LazyImageIcon("icons/UpFolder.gif"); - } - return fileChooserUpFolderIcon; - } - - // Tree - public static Icon getTreeComputerIcon() { - if (treeComputerIcon == null) { - treeComputerIcon = new LazyImageIcon("icons/Computer.gif"); - } - return treeComputerIcon; - } - - public static Icon getTreeFloppyDriveIcon() { - if (treeFloppyDriveIcon == null) { - treeFloppyDriveIcon = new LazyImageIcon("icons/FloppyDrive.gif"); - } - return treeFloppyDriveIcon; - } - - public static Icon getTreeHardDriveIcon() { - if (treeHardDriveIcon == null) { - treeHardDriveIcon = new LazyImageIcon("icons/HardDrive.gif"); - } - return treeHardDriveIcon; - } - - public static Icon getTreeFolderIcon() { - if (treeFolderIcon == null) { - treeFolderIcon = new LazyImageIcon("icons/TreeClosed.gif"); - } - return treeFolderIcon; - } - - public static Icon getTreeLeafIcon() { - if (treeLeafIcon == null) { - treeLeafIcon = new LazyImageIcon("icons/TreeLeaf.gif"); - } - return treeLeafIcon; - } - - public static Icon getTreeControlIcon(boolean isCollapsed) { - if (isCollapsed) { - if (treeClosedIcon == null) { - treeClosedIcon = new LazyImageIcon("icons/TreeClosedButton.gif"); - } - return treeClosedIcon; - } else { - if (treeOpenIcon == null) { - treeOpenIcon = new LazyImageIcon("icons/TreeOpenButton.gif"); - } - return treeOpenIcon; - } - } - - // TitlePane icons - public static Icon getMenuIcon() { - if (menuIcon == null) { - menuIcon = new LazyImageIcon("icons/JavaCup.gif"); - } - return menuIcon; - } - - public static Icon getIconIcon() { - if (iconIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - iconIcon = new MacIconIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - iconIcon = new IconSymbol(iconColor, null, iconRolloverColor); - } - } - return iconIcon; - } - - public static Icon getMaxIcon() { - if (maxIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - maxIcon = new MacMaxIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - maxIcon = new MaxSymbol(iconColor, null, iconRolloverColor); - } - } - return maxIcon; - } - - public static Icon getMinIcon() { - if (minIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - minIcon = new MacMinIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - minIcon = new MinSymbol(iconColor, null, iconRolloverColor); - } - } - return minIcon; - } - - public static Icon getCloseIcon() { - if (closeIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - closeIcon = new MacCloseIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - closeIcon = new CloseSymbol(iconColor, null, iconRolloverColor); - } - } - return closeIcon; - } - - public static Icon getPaletteCloseIcon() { - if (paletteCloseIcon == null) { - paletteCloseIcon = new CloseSymbol(Color.black, null, Color.red); - } - return paletteCloseIcon; - } - - // MenuIcons - public static Icon getMenuArrowIcon() { - if (menuArrowIcon == null) { - menuArrowIcon = new LazyMenuArrowImageIcon("icons/MenuRightArrow.gif", "icons/MenuLeftArrow.gif"); - } - return menuArrowIcon; - } - - public static Icon getMenuCheckBoxIcon() { - if (menuCheckBoxIcon == null) { - menuCheckBoxIcon = new CheckBoxIcon(); - } - return menuCheckBoxIcon; - } - - public static Icon getMenuRadioButtonIcon() { - if (menuRadioButtonIcon == null) { - menuRadioButtonIcon = new RadioButtonIcon(); - } - return menuRadioButtonIcon; - } - - // ArrowIcons - public static Icon getUpArrowIcon() { - if (upArrowIcon == null) { - upArrowIcon = new LazyImageIcon("icons/UpArrow.gif"); - } - return upArrowIcon; - } - - public static Icon getUpArrowInverseIcon() { - if (upArrowInverseIcon == null) { - upArrowInverseIcon = new LazyImageIcon("icons/UpArrowInverse.gif"); - } - return upArrowInverseIcon; - } - - public static Icon getDownArrowIcon() { - if (downArrowIcon == null) { - downArrowIcon = new LazyImageIcon("icons/DownArrow.gif"); - } - return downArrowIcon; - } - - public static Icon getDownArrowInverseIcon() { - if (downArrowInverseIcon == null) { - downArrowInverseIcon = new LazyImageIcon("icons/DownArrowInverse.gif"); - } - return downArrowInverseIcon; - } - - public static Icon getLeftArrowIcon() { - if (leftArrowIcon == null) { - leftArrowIcon = new LazyImageIcon("icons/LeftArrow.gif"); - } - return leftArrowIcon; - } - - public static Icon getLeftArrowInverseIcon() { - if (leftArrowInverseIcon == null) { - leftArrowInverseIcon = new LazyImageIcon("icons/LeftArrowInverse.gif"); - } - return leftArrowInverseIcon; - } - - public static Icon getRightArrowIcon() { - if (rightArrowIcon == null) { - rightArrowIcon = new LazyImageIcon("icons/RightArrow.gif"); - } - return rightArrowIcon; - } - - public static Icon getRightArrowInverseIcon() { - if (rightArrowInverseIcon == null) { - rightArrowInverseIcon = new LazyImageIcon("icons/RightArrowInverse.gif"); - } - return rightArrowInverseIcon; - } - - public static Icon getSplitterUpArrowIcon() { - if (splitterUpArrowIcon == null) { - splitterUpArrowIcon = new LazyImageIcon("icons/SplitterUpArrow.gif"); - } - return splitterUpArrowIcon; - } - - public static Icon getSplitterDownArrowIcon() { - if (splitterDownArrowIcon == null) { - splitterDownArrowIcon = new LazyImageIcon("icons/SplitterDownArrow.gif"); - } - return splitterDownArrowIcon; - } - - public static Icon getSplitterLeftArrowIcon() { - if (splitterLeftArrowIcon == null) { - splitterLeftArrowIcon = new LazyImageIcon("icons/SplitterLeftArrow.gif"); - } - return splitterLeftArrowIcon; - } - - public static Icon getSplitterRightArrowIcon() { - if (splitterRightArrowIcon == null) { - splitterRightArrowIcon = new LazyImageIcon("icons/SplitterRightArrow.gif"); - } - return splitterRightArrowIcon; - } - - public static Icon getSplitterHorBumpIcon() { - if (splitterHorBumpIcon == null) { - splitterHorBumpIcon = new LazyImageIcon("icons/SplitterHorBumps.gif"); - } - return splitterHorBumpIcon; - } - - public static Icon getSplitterVerBumpIcon() { - if (splitterVerBumpIcon == null) { - splitterVerBumpIcon = new LazyImageIcon("icons/SplitterVerBumps.gif"); - } - return splitterVerBumpIcon; - } - - public static Icon getComboBoxIcon() { - return getDownArrowIcon(); - } - - public static Icon getComboBoxInverseIcon() { - return getDownArrowInverseIcon(); - } - - public static Icon getThumbHorIcon() { - if (thumbHorIcon == null) { - thumbHorIcon = new LazyImageIcon("icons/thumb_hor.gif"); - } - return thumbHorIcon; - } - - public static Icon getThumbVerIcon() { - if (thumbVerIcon == null) { - thumbVerIcon = new LazyImageIcon("icons/thumb_ver.gif"); - } - return thumbVerIcon; - } - - public static Icon getThumbHorIconRollover() { - if (thumbHorIconRollover == null) { - thumbHorIconRollover = new LazyImageIcon("icons/thumb_hor_rollover.gif"); - } - return thumbHorIconRollover; - } - - public static Icon getThumbVerIconRollover() { - if (thumbVerIconRollover == null) { - thumbVerIconRollover = new LazyImageIcon("icons/thumb_ver_rollover.gif"); - } - return thumbVerIconRollover; - } - -//----------------------------------------------------------------------------------------------------------- - private static class CheckBoxIcon implements Icon { - - private static Icon checkIcon = new LazyImageIcon("icons/CheckSymbol.gif"); - private static Icon checkIconDisabled = new LazyImageIcon("icons/CheckSymbolDisabled.gif"); - private static Icon checkPressedIcon = new LazyImageIcon("icons/CheckPressedSymbol.gif"); - private static final int WIDTH = 10; - private static final int HEIGHT = 10; - - public void paintIcon(Component c, Graphics g, int x, int y) { - if (!JTattooUtilities.isLeftToRight(c)) { - x += 3; - } - - AbstractButton b = (AbstractButton) c; - ButtonModel model = b.getModel(); - if (c instanceof JCheckBoxMenuItem) { - g.setColor(Color.white); - g.fillRect(x, y, WIDTH, HEIGHT); - if (b.isEnabled()) { - g.setColor(AbstractLookAndFeel.getFrameColor()); - } else { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 40)); - } - g.drawRect(x, y, WIDTH, HEIGHT); - } else { - if (b.isEnabled()) { - if (b.isRolloverEnabled() && model.isRollover()) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getRolloverColors(), x, y, WIDTH, HEIGHT); - } else { - if (AbstractLookAndFeel.getTheme().doShowFocusFrame() && b.hasFocus()) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getFocusColors(), x, y, WIDTH, HEIGHT); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getCheckBoxColors(), x, y, WIDTH, HEIGHT); - } - if (!model.isPressed()) { - g.setColor(Color.white); - g.drawLine(x + 1, y + 1, x + 1, y + HEIGHT - 2); - g.drawLine(x + WIDTH - 1, y + 1, x + WIDTH - 1, y + HEIGHT - 2); - } - } - if (AbstractLookAndFeel.getTheme().doShowFocusFrame() && b.hasFocus()) { - Color hiColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFocusFrameColor(), 30); - Color loColor = ColorHelper.darker(AbstractLookAndFeel.getTheme().getFocusFrameColor(), 20); - g.setColor(hiColor); - g.drawRect(x - 1, y - 1, WIDTH + 2, HEIGHT + 2); - g.setColor(loColor); - g.drawRect(x, y, WIDTH, HEIGHT); - } else { - g.setColor(AbstractLookAndFeel.getFrameColor()); - g.drawRect(x, y, WIDTH, HEIGHT); - } - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getDisabledColors(), x, y, WIDTH, HEIGHT); - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 40)); - g.drawRect(x, y, WIDTH, HEIGHT); - } - } - int xi = x + ((WIDTH - checkIcon.getIconWidth()) / 2) + 1; - int yi = y + ((HEIGHT - checkIcon.getIconHeight()) / 2) + 1; - if (model.isPressed() && model.isArmed()) { - checkPressedIcon.paintIcon(c, g, xi, yi); - } else if (model.isSelected()) { - if (b.isEnabled()) { - checkIcon.paintIcon(c, g, xi, yi); - } else { - checkIconDisabled.paintIcon(c, g, xi, yi); - } - } - } - - public int getIconWidth() { - return WIDTH + 4; - } - - public int getIconHeight() { - return HEIGHT; - } - } - -//----------------------------------------------------------------------------------------------------------- - private static class RadioButtonIcon implements Icon { - - private static final int WIDTH = 14; - private static final int HEIGHT = 14; - - public void paintIcon(Component c, Graphics g, int x, int y) { - if (!JTattooUtilities.isLeftToRight(c)) { - x += 3; - } - Graphics2D g2D = (Graphics2D) g; - AbstractButton b = (AbstractButton) c; - ButtonModel model = b.getModel(); - Shape savedClip = g.getClip(); - Area clipArea = new Area(new Ellipse2D.Double(x, y, WIDTH + 1, HEIGHT + 1)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - if (c instanceof JRadioButtonMenuItem) { - g.setColor(Color.white); - g.fillRect(x, y, WIDTH, HEIGHT); - } else { - if (b.isEnabled()) { - if (b.isRolloverEnabled() && model.isRollover()) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getRolloverColors(), x, y, WIDTH, HEIGHT); - } else { - if (AbstractLookAndFeel.getTheme().doShowFocusFrame() && b.hasFocus()) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getFocusColors(), x, y, WIDTH, HEIGHT); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getCheckBoxColors(), x, y, WIDTH, HEIGHT); - } - } - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getDisabledColors(), x, y, WIDTH, HEIGHT); - } - } - g2D.setClip(savedClip); - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - if (!model.isRollover()) { - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - g2D.setColor(Color.white); - g2D.drawOval(x + 1, y + 1, WIDTH - 2, HEIGHT - 2); - g2D.setComposite(savedComposite); - } - if (b.isEnabled()) { - if (AbstractLookAndFeel.getTheme().doShowFocusFrame() && b.hasFocus()) { - Color hiColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFocusFrameColor(), 30); - Color loColor = ColorHelper.darker(AbstractLookAndFeel.getTheme().getFocusFrameColor(), 20); - g.setColor(hiColor); - g.drawOval(x - 1, y - 1, WIDTH + 2, HEIGHT + 2); - g.setColor(loColor); - g2D.drawOval(x, y, WIDTH, HEIGHT); - } else { - g.setColor(AbstractLookAndFeel.getFrameColor()); - g2D.drawOval(x, y, WIDTH, HEIGHT); - } - } else { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 40)); - g2D.drawOval(x, y, WIDTH, HEIGHT); - } - - if (model.isSelected()) { - if (b.isEnabled()) { - g.setColor(Color.black); - } else { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 40)); - } - g2D.fillOval(x + 4, y + 4, WIDTH - 7, HEIGHT - 7); - } - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - } - - public int getIconWidth() { - return WIDTH + 4; - } - - public int getIconHeight() { - return HEIGHT; - } - } - -//----------------------------------------------------------------------------------------------------------- - public static class MacCloseIcon implements Icon, UIResource { - - public void paintIcon(Component c, Graphics g, int x, int y) { - AbstractButton btn = (AbstractButton) c; - ButtonModel model = btn.getModel(); - int w = c.getWidth(); - int h = c.getHeight(); - Icon closerIcon; - Icon pearlIcon; - if (w <= 18) { - closerIcon = CLOSER_10x10; - pearlIcon = PEARL_RED_24x24; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_24x24; - } - } else if (w <= 22) { - closerIcon = CLOSER_12x12; - pearlIcon = PEARL_RED_28x28; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_28x28; - } - } else { - closerIcon = CLOSER_12x12; - pearlIcon = PEARL_RED_32x32; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_32x32; - } - } - x = (w - pearlIcon.getIconWidth()) / 2; - y = (h - pearlIcon.getIconHeight()) / 2; - pearlIcon.paintIcon(c, g, x, y); - if (model.isRollover()) { - x += (pearlIcon.getIconWidth() - closerIcon.getIconWidth()) / 2; - y += (pearlIcon.getIconHeight() - closerIcon.getIconHeight()) / 2; - closerIcon.paintIcon(c, g, x, y); - } - } - - public int getIconHeight() { - return 24; - } - - public int getIconWidth() { - return 24; - } - } - - public static class MacIconIcon implements Icon, UIResource { - - public void paintIcon(Component c, Graphics g, int x, int y) { - AbstractButton btn = (AbstractButton) c; - ButtonModel model = btn.getModel(); - int w = c.getWidth(); - int h = c.getHeight(); - Icon iconizerIcon; - Icon pearlIcon; - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - if (w <= 18) { - iconizerIcon = ICONIZER_10x10; - pearlIcon = PEARL_YELLOW_24x24; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_24x24; - } - } else if (w <= 22) { - iconizerIcon = ICONIZER_12x12; - pearlIcon = PEARL_YELLOW_28x28; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_28x28; - } - } else { - iconizerIcon = ICONIZER_12x12; - pearlIcon = PEARL_YELLOW_32x32; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_32x32; - } - } - - } else { - if (w <= 18) { - iconizerIcon = ICONIZER_10x10; - pearlIcon = PEARL_GREEN_24x24; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_24x24; - } - } else if (w <= 22) { - iconizerIcon = ICONIZER_12x12; - pearlIcon = PEARL_GREEN_28x28; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_28x28; - } - } else { - iconizerIcon = ICONIZER_12x12; - pearlIcon = PEARL_GREEN_32x32; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_32x32; - } - } - } - x = (w - pearlIcon.getIconWidth()) / 2; - y = (h - pearlIcon.getIconHeight()) / 2; - pearlIcon.paintIcon(c, g, x, y); - if (model.isRollover()) { - x += (pearlIcon.getIconWidth() - iconizerIcon.getIconWidth()) / 2; - y += (pearlIcon.getIconHeight() - iconizerIcon.getIconHeight()) / 2; - iconizerIcon.paintIcon(c, g, x, y); - } - } - - public int getIconHeight() { - return 24; - } - - public int getIconWidth() { - return 24; - } - } - - public static class MacMaxIcon implements Icon, UIResource { - - public void paintIcon(Component c, Graphics g, int x, int y) { - AbstractButton btn = (AbstractButton) c; - ButtonModel model = btn.getModel(); - int w = c.getWidth(); - int h = c.getHeight(); - Icon maximizerIcon; - Icon pearlIcon; - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - if (w <= 18) { - maximizerIcon = MAXIMIZER_10x10; - pearlIcon = PEARL_GREEN_24x24; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_24x24; - } - } else if (w <= 22) { - maximizerIcon = MAXIMIZER_12x12; - pearlIcon = PEARL_GREEN_28x28; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_28x28; - } - } else { - maximizerIcon = MAXIMIZER_12x12; - pearlIcon = PEARL_GREEN_32x32; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_32x32; - } - } - } else { - if (w <= 18) { - maximizerIcon = MAXIMIZER_10x10; - pearlIcon = PEARL_YELLOW_24x24; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_24x24; - } - } else if (w <= 22) { - maximizerIcon = MAXIMIZER_12x12; - pearlIcon = PEARL_YELLOW_28x28; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_28x28; - } - } else { - maximizerIcon = MAXIMIZER_12x12; - pearlIcon = PEARL_YELLOW_32x32; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_32x32; - } - } - } - x = (w - pearlIcon.getIconWidth()) / 2; - y = (h - pearlIcon.getIconHeight()) / 2; - pearlIcon.paintIcon(c, g, x, y); - if (model.isRollover()) { - x += (pearlIcon.getIconWidth() - maximizerIcon.getIconWidth()) / 2; - y += (pearlIcon.getIconHeight() - maximizerIcon.getIconHeight()) / 2; - maximizerIcon.paintIcon(c, g, x, y); - } - } - - public int getIconHeight() { - return 24; - } - - public int getIconWidth() { - return 24; - } - } - - public static class MacMinIcon implements Icon, UIResource { - - public void paintIcon(Component c, Graphics g, int x, int y) { - AbstractButton btn = (AbstractButton) c; - ButtonModel model = btn.getModel(); - int w = c.getWidth(); - int h = c.getHeight(); - Icon minimizerIcon; - Icon pearlIcon; - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - if (w <= 18) { - minimizerIcon = MINIMIZER_10x10; - pearlIcon = PEARL_GREEN_24x24; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_24x24; - } - } else if (w <= 22) { - minimizerIcon = MINIMIZER_12x12; - pearlIcon = PEARL_GREEN_28x28; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_28x28; - } - } else { - minimizerIcon = MINIMIZER_12x12; - pearlIcon = PEARL_GREEN_32x32; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_32x32; - } - } - } else { - if (w <= 18) { - minimizerIcon = MINIMIZER_10x10; - pearlIcon = PEARL_YELLOW_24x24; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_24x24; - } - } else if (w <= 22) { - minimizerIcon = MINIMIZER_12x12; - pearlIcon = PEARL_YELLOW_28x28; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_28x28; - } - } else { - minimizerIcon = MINIMIZER_12x12; - pearlIcon = PEARL_YELLOW_32x32; - if (!JTattooUtilities.isActive(btn)) { - pearlIcon = PEARL_GREY_32x32; - } - } - } - x = (w - pearlIcon.getIconWidth()) / 2; - y = (h - pearlIcon.getIconHeight()) / 2; - pearlIcon.paintIcon(c, g, x, y); - if (model.isRollover()) { - x += (pearlIcon.getIconWidth() - minimizerIcon.getIconWidth()) / 2; - y += (pearlIcon.getIconHeight() - minimizerIcon.getIconHeight()) / 2; - minimizerIcon.paintIcon(c, g, x, y); - } - } - - public int getIconHeight() { - return 24; - } - - public int getIconWidth() { - return 24; - } - } - -//----------------------------------------------------------------------------------------------------------- - public static class IconSymbol implements Icon { - - private Color foregroundColor = null; - private Color shadowColor = null; - private Color inactiveForegroundColor = null; - private Color inactiveShadowColor = null; - private Color rolloverColor = null; - private Insets insets = new Insets(0, 0, 0, 0); - - public IconSymbol(Color foregroundColor, Color shadowColor, Color rolloverColor) { - this.foregroundColor = foregroundColor; - this.shadowColor = shadowColor; - this.rolloverColor = rolloverColor; - this.inactiveForegroundColor = foregroundColor; - this.inactiveShadowColor = shadowColor; - } - - public IconSymbol(Color foregroundColor, Color shadowColor, Color rolloverColor, Insets insets) { - this.foregroundColor = foregroundColor; - this.shadowColor = shadowColor; - this.rolloverColor = rolloverColor; - this.inactiveForegroundColor = foregroundColor; - this.inactiveShadowColor = shadowColor; - this.insets = insets; - } - - public IconSymbol(Color foregroundColor, Color shadowColor, Color rolloverColor, Color inactiveForegroundColor, Color inactiveShadowColor, Insets insets) { - this.foregroundColor = foregroundColor; - this.shadowColor = shadowColor; - this.rolloverColor = rolloverColor; - this.inactiveForegroundColor = inactiveForegroundColor; - this.inactiveShadowColor = inactiveShadowColor; - this.insets = insets; - } - - public int getIconHeight() { - return 16; - } - - public int getIconWidth() { - return 16; - } - - public void paintIcon(Component c, Graphics g, int x, int y) { - Graphics2D g2D = (Graphics2D) g; - g2D.translate(insets.left, insets.top); - int w = c.getWidth() - insets.left - insets.right; - int h = c.getHeight() - insets.top - insets.bottom; - boolean active = JTattooUtilities.isActive((JComponent) c); - Color color = foregroundColor; - if (!active) { - color = inactiveForegroundColor; - } - if (c instanceof AbstractButton) { - if (((AbstractButton) c).getModel().isRollover() && (rolloverColor != null)) { - color = rolloverColor; - } - } - int lw = (w / 12) + 1; - int dx = (w / 5) + 2; - int dy = dx; - - Stroke savedStroke = g2D.getStroke(); - g2D.setStroke(new BasicStroke(lw, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)); - if (shadowColor != null) { - if (!active) { - g2D.setColor(inactiveShadowColor); - } else { - g2D.setColor(shadowColor); - } - g2D.drawLine(dx + 1, h - dy, w - dx + 1, h - dy); - } - g2D.setColor(color); - g2D.drawLine(dx, h - dy - 1, w - dx, h - dy - 1); - g2D.setStroke(savedStroke); - g2D.translate(-insets.left, -insets.top); - } - } - -//----------------------------------------------------------------------------------------------------------- - public static class MaxSymbol implements Icon { - - private Color foregroundColor = null; - private Color shadowColor = null; - private Color rolloverColor = null; - private Color inactiveForegroundColor = null; - private Color inactiveShadowColor = null; - private Insets insets = new Insets(0, 0, 0, 0); - - public MaxSymbol(Color foregroundColor, Color shadowColor, Color rolloverColor) { - this.foregroundColor = foregroundColor; - this.shadowColor = shadowColor; - this.rolloverColor = rolloverColor; - this.inactiveForegroundColor = foregroundColor; - this.inactiveShadowColor = shadowColor; - } - - public MaxSymbol(Color foregroundColor, Color shadowColor, Color rolloverColor, Insets insets) { - this.foregroundColor = foregroundColor; - this.shadowColor = shadowColor; - this.rolloverColor = rolloverColor; - this.inactiveForegroundColor = foregroundColor; - this.inactiveShadowColor = shadowColor; - this.insets = insets; - } - - public MaxSymbol(Color foregroundColor, Color shadowColor, Color rolloverColor, Color inactiveForegroundColor, Color inactiveShadowColor, Insets insets) { - this.foregroundColor = foregroundColor; - this.shadowColor = shadowColor; - this.rolloverColor = rolloverColor; - this.inactiveForegroundColor = inactiveForegroundColor; - this.inactiveShadowColor = inactiveShadowColor; - this.insets = insets; - } - - public int getIconHeight() { - return 16; - } - - public int getIconWidth() { - return 16; - } - - public void paintIcon(Component c, Graphics g, int x, int y) { - Graphics2D g2D = (Graphics2D) g; - g2D.translate(insets.left, insets.top); - int w = c.getWidth() - insets.left - insets.right; - int h = c.getHeight() - insets.top - insets.bottom; - boolean active = JTattooUtilities.isActive((JComponent) c); - Color color = foregroundColor; - if (!active) { - color = inactiveForegroundColor; - } - if (c instanceof AbstractButton) { - if (((AbstractButton) c).getModel().isRollover() && (rolloverColor != null)) { - color = rolloverColor; - } - } - int lw = (w / 12); - int dx = (w / 5) + 1; - int dy = (h / 5) + 2; - - Stroke savedStroke = g2D.getStroke(); - g2D.setStroke(new BasicStroke(lw, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)); - if (shadowColor != null) { - if (!active) { - g2D.setColor(inactiveShadowColor); - } else { - g2D.setColor(shadowColor); - } - g2D.drawRect(dx + 1, dy + 1, w - (2 * dx), h - (2 * dy)); - g2D.drawLine(dx + 1, dy + lw + 1, w - dx, dy + lw + 1); - } - g2D.setColor(color); - g2D.drawRect(dx, dy, w - (2 * dx), h - (2 * dy)); - g2D.drawLine(dx + 1, dy + lw, w - dx, dy + lw); - - g2D.setStroke(savedStroke); - g2D.translate(-insets.left, -insets.top); - } - } - -//----------------------------------------------------------------------------------------------------------- - public static class MinSymbol implements Icon { - - private Color foregroundColor = null; - private Color shadowColor = null; - private Color rolloverColor = null; - private Color inactiveForegroundColor = null; - private Color inactiveShadowColor = null; - private Insets insets = new Insets(0, 0, 0, 0); - - public MinSymbol(Color foregroundColor, Color shadowColor, Color rolloverColor) { - this.foregroundColor = foregroundColor; - this.shadowColor = shadowColor; - this.rolloverColor = rolloverColor; - this.inactiveForegroundColor = foregroundColor; - this.inactiveShadowColor = shadowColor; - } - - public MinSymbol(Color foregroundColor, Color shadowColor, Color rolloverColor, Insets insets) { - this.foregroundColor = foregroundColor; - this.shadowColor = shadowColor; - this.rolloverColor = rolloverColor; - this.inactiveForegroundColor = foregroundColor; - this.inactiveShadowColor = shadowColor; - this.insets = insets; - } - - public MinSymbol(Color foregroundColor, Color shadowColor, Color rolloverColor, Color inactiveForegroundColor, Color inactiveShadowColor, Insets insets) { - this.foregroundColor = foregroundColor; - this.shadowColor = shadowColor; - this.rolloverColor = rolloverColor; - this.inactiveForegroundColor = inactiveForegroundColor; - this.inactiveShadowColor = inactiveShadowColor; - this.insets = insets; - } - - public int getIconHeight() { - return 16; - } - - public int getIconWidth() { - return 16; - } - - public void paintIcon(Component c, Graphics g, int x, int y) { - Graphics2D g2D = (Graphics2D) g; - g2D.translate(insets.left, insets.top); - int w = c.getWidth() - insets.left - insets.right; - int h = c.getHeight() - insets.top - insets.bottom; - - int lw = (h > 22) ? 2 : 1; - int delta = w / 4; - - w = Math.min(w, h) - 6; - h = w; - - int x1 = 3; - int y1 = 3; - int w1 = w - delta; - int h1 = h - delta; - - int x2 = delta + 2; - int y2 = delta + 2; - int w2 = w - delta; - int h2 = h - delta; - - boolean active = JTattooUtilities.isActive((JComponent) c); - Color ic = foregroundColor; - Color sc = shadowColor; - if (!active) { - ic = inactiveForegroundColor; - if (sc != null) { - sc = inactiveShadowColor; - } - } - if (c instanceof AbstractButton) { - if (((AbstractButton) c).getModel().isRollover() && (rolloverColor != null)) { - ic = rolloverColor; - } - } - - Shape savedClip = g2D.getClip(); - Stroke savedStroke = g2D.getStroke(); - g2D.setStroke(new BasicStroke(lw, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)); - Area clipArea = new Area(savedClip); - clipArea.subtract(new Area(new Rectangle2D.Double(x2, y2, w2, h2))); - g2D.setClip(clipArea); - paintRect(g2D, x1, y1, w1, h1, lw, ic, sc); - g2D.setClip(savedClip); - paintRect(g2D, x2, y2, w2, h2, lw, ic, sc); - - g2D.setStroke(savedStroke); - g2D.translate(-insets.left, -insets.top); - } - - private void paintRect(Graphics2D g2D, int x, int y, int w, int h, int lw, Color iconColor, Color shadowColor) { - if (shadowColor != null) { - g2D.setColor(shadowColor); - g2D.drawRect(x + 1, y + 1, w, h); - g2D.drawLine(x + 1, y + lw + 1, x + w + 1, y + lw + 1); - } - g2D.setColor(iconColor); - g2D.drawRect(x, y, w, h); - g2D.drawLine(x, y + lw, x + w, y + lw); - - } - } - -//----------------------------------------------------------------------------------------------------------- - public static class CloseSymbol implements Icon { - - private Color foregroundColor = null; - private Color shadowColor = null; - private Color rolloverColor = null; - private Color inactiveForegroundColor = null; - private Color inactiveShadowColor = null; - private Insets insets = new Insets(0, 0, 0, 0); - - public CloseSymbol(Color foregroundColor, Color shadowColor, Color rolloverColor) { - this.foregroundColor = foregroundColor; - this.shadowColor = shadowColor; - this.rolloverColor = rolloverColor; - this.inactiveForegroundColor = foregroundColor; - this.inactiveShadowColor = shadowColor; - } - - public CloseSymbol(Color foregroundColor, Color shadowColor, Color rolloverColor, Insets insets) { - this.foregroundColor = foregroundColor; - this.shadowColor = shadowColor; - this.rolloverColor = rolloverColor; - this.insets = insets; - this.inactiveForegroundColor = foregroundColor; - this.inactiveShadowColor = shadowColor; - } - - public CloseSymbol(Color foregroundColor, Color shadowColor, Color rolloverColor, Color inactiveForegroundColor, Color inactiveShadowColor, Insets insets) { - this.foregroundColor = foregroundColor; - this.shadowColor = shadowColor; - this.rolloverColor = rolloverColor; - this.inactiveForegroundColor = inactiveForegroundColor; - this.inactiveShadowColor = inactiveShadowColor; - this.insets = insets; - } - - public int getIconHeight() { - return 16; - } - - public int getIconWidth() { - return 16; - } - - public void paintIcon(Component c, Graphics g, int x, int y) { - Graphics2D g2D = (Graphics2D) g; - g2D.translate(insets.left, insets.top); - int w = c.getWidth() - insets.left - insets.right; - int h = c.getHeight() - insets.top - insets.bottom; - boolean active = JTattooUtilities.isActive((JComponent) c); - Color color = foregroundColor; - if (!active) { - color = inactiveForegroundColor; - } - if (c instanceof AbstractButton) { - if (((AbstractButton) c).getModel().isRollover() && (rolloverColor != null)) { - color = rolloverColor; - } - } - int lw = (w / 12) + 1; - int dx = (w / 5) + 2; - int dy = dx; - - Stroke savedStroke = g2D.getStroke(); - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - g2D.setStroke(new BasicStroke(lw, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); - if (shadowColor != null) { - if (!active) { - g2D.setColor(inactiveShadowColor); - } else { - g2D.setColor(shadowColor); - } - g2D.drawLine(dx + 1, dy + 1, w - dx + 1, h - dy + 1); - g2D.drawLine(w - dx + 1, dy + 1, dx + 1, h - dy + 1); - } - g2D.setColor(color); - g2D.drawLine(dx, dy, w - dx, h - dy); - g2D.drawLine(w - dx, dy, dx, h - dy); - - g2D.setStroke(savedStroke); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - g2D.translate(-insets.left, -insets.top); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseInternalFrameTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/BaseInternalFrameTitlePane.java deleted file mode 100644 index 771fa04f5..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseInternalFrameTitlePane.java +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.image.BufferedImage; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import javax.swing.*; -import javax.swing.plaf.basic.BasicInternalFrameTitlePane; - -/** - * This class is a modified copy of the javax.swing.plaf.metal.MetalInternalFrameTitlePane - * - * Class that manages a JLF title bar

        - * - * @author Steve Wilson - * @author Brian Beck - * @author Michael Hagen - */ -public class BaseInternalFrameTitlePane extends BasicInternalFrameTitlePane implements ActionListener { - - public static final String PAINT_ACTIVE = "paintActive"; - public static final String ICONIFY = "Iconify"; - public static final String MAXIMIZE = "Maximize"; - public static final String CLOSE = "Close"; - protected boolean isPalette = false; - protected Icon paletteCloseIcon; - protected int paletteTitleHeight; - protected int buttonsWidth = 0; - protected JPanel customTitlePanel; - - public BaseInternalFrameTitlePane(JInternalFrame f) { - super(f); - } - - protected void installDefaults() { - super.installDefaults(); - setFont(UIManager.getFont("InternalFrame.font")); - paletteTitleHeight = UIManager.getInt("InternalFrame.paletteTitleHeight"); - paletteCloseIcon = UIManager.getIcon("InternalFrame.paletteCloseIcon"); - iconIcon = UIManager.getIcon("InternalFrame.iconifyIcon"); - minIcon = UIManager.getIcon("InternalFrame.minimizeIcon"); - maxIcon = UIManager.getIcon("InternalFrame.maximizeIcon"); - closeIcon = UIManager.getIcon("InternalFrame.closeIcon"); - if (frame.getClientProperty("customTitlePanel") instanceof JPanel) { - setCustomizedTitlePanel((JPanel)frame.getClientProperty("customTitlePanel")); - } - } - - public void setCustomizedTitlePanel(JPanel panel) { - if (customTitlePanel != null) { - remove(customTitlePanel); - customTitlePanel = null; - } - if (panel != null) { - customTitlePanel = panel; - add(customTitlePanel); - } - frame.putClientProperty("customTitlePanel", customTitlePanel); - revalidate(); - repaint(); - } - - protected void createButtons() { - iconButton = new BaseTitleButton(iconifyAction, ICONIFY, iconIcon, 1.0f); - maxButton = new BaseTitleButton(maximizeAction, MAXIMIZE, maxIcon, 1.0f); - closeButton = new BaseTitleButton(closeAction, CLOSE, closeIcon, 1.0f); - setButtonIcons(); - } - - protected void setButtonIcons() { - super.setButtonIcons(); - iconButton.setToolTipText(null); - maxButton.setToolTipText(null); - closeButton.setToolTipText(null); - } - - protected void enableActions() { - super.enableActions(); - maximizeAction.setEnabled(frame.isMaximizable()); - } - - protected void assembleSystemMenu() { - } - - protected void addSystemMenuItems(JMenu systemMenu) { - } - - protected void addSubComponents() { - add(iconButton); - add(maxButton); - add(closeButton); - } - - protected PropertyChangeListener createPropertyChangeListener() { - return new BasePropertyChangeHandler(); - } - - protected LayoutManager createLayout() { - return new BaseTitlePaneLayout(); - } - - protected int getHorSpacing() { - return 3; - } - - protected int getVerSpacing() { - return 3; - } - - protected boolean centerButtons() { - return true; - } - - public void activateFrame() { - } - - public void deactivateFrame() { - } - - protected boolean isMacStyleWindowDecoration() { - return AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn(); - } - - public boolean isActive() { - return JTattooUtilities.isActive(this); - } - - public boolean isPalette() { - return isPalette; - } - - public void setPalette(boolean b) { - isPalette = b; - if (isPalette) { - closeButton.setIcon(paletteCloseIcon); - if (frame.isMaximizable()) { - remove(maxButton); - } - if (frame.isIconifiable()) { - remove(iconButton); - } - } else { - closeButton.setIcon(closeIcon); - if (frame.isMaximizable()) { - add(maxButton); - } - if (frame.isIconifiable()) { - add(iconButton); - } - } - revalidate(); - repaint(); - } - - public void actionPerformed(ActionEvent e) { - AbstractButton button = (AbstractButton) e.getSource(); - button.getModel().setRollover(false); - } - - public void paintPalette(Graphics g) { - int width = getWidth(); - int height = getHeight(); - if (JTattooUtilities.isFrameActive(this)) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 0, 0, width, height); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 0, 0, width, height); - } - } - - public void paintBackground(Graphics g) { - if (isActive()) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 0, 0, getWidth(), getHeight()); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 0, 0, getWidth(), getHeight()); - } - } - - private Image iconToImage(Icon icon) { - if (icon instanceof ImageIcon) { - return ((ImageIcon) icon).getImage(); - } else if (icon != null) { - int w = icon.getIconWidth(); - int h = icon.getIconHeight(); - BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = image.createGraphics(); - icon.paintIcon(null, g, 0, 0); - g.dispose(); - return image; - } - return null; - } - - protected int paintIcon(Graphics g, int x, int y) { - Image image = iconToImage(frame.getFrameIcon()); - if (image != null) { - Graphics2D g2D = (Graphics2D)g; - Object savedHint = g2D.getRenderingHint(RenderingHints.KEY_INTERPOLATION); - if (JTattooUtilities.getJavaVersion() >= 1.6) { - g2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - } - int h = getHeight(); - int ih = image.getHeight(null); - int iw = image.getWidth(null); - if (ih <= h) { - g2D.drawImage(image, x, (h - ih) / 2, iw, ih, null); - } else { - double fac = (double) iw / (double) ih; - ih = h - 1; - iw = (int) (fac * (double) ih); - g2D.drawImage(image, x, 0, iw, ih, null); - } - if (savedHint != null) { - g2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, savedHint); - } - return iw; - } - return 0; - } - - public void paintText(Graphics g, int x, int y, String title) { - if (isMacStyleWindowDecoration()) { - x += paintIcon(g, x, y) + 5; - } - if (isActive()) { - g.setColor(AbstractLookAndFeel.getWindowTitleForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - } - JTattooUtilities.drawString(frame, g, title, x, y); - } - - public void paintBorder(Graphics g) { - Color borderColor = AbstractLookAndFeel.getWindowInactiveBorderColor(); - if (isActive() || isPalette) { - borderColor = AbstractLookAndFeel.getWindowBorderColor(); - } - JTattooUtilities.draw3DBorder(g, ColorHelper.brighter(borderColor, 20), ColorHelper.darker(borderColor, 10), 0, 0, getWidth(), getHeight()); - } - - public void paintComponent(Graphics g) { - if (isPalette) { - paintPalette(g); - return; - } - - paintBackground(g); - - boolean leftToRight = JTattooUtilities.isLeftToRight(frame); - - int width = getWidth(); - int height = getHeight(); - int xOffset = leftToRight ? 5 : width - 5; - int titleWidth = width - buttonsWidth - 10; - - Icon icon = frame.getFrameIcon(); - if (icon != null) { - if (!isMacStyleWindowDecoration()) { - if (!leftToRight) { - xOffset -= icon.getIconWidth(); - } - int iconY = (height / 2) - (icon.getIconHeight() / 2) - 1; - int iconWidth = paintIcon(g, xOffset, iconY); - xOffset += leftToRight ? iconWidth + 5 : -5; - titleWidth -= iconWidth + 5; - } else { - titleWidth -= icon.getIconWidth() + 5; - } - } - - g.setFont(getFont()); - FontMetrics fm = g.getFontMetrics(); - String frameTitle = JTattooUtilities.getClippedText(frame.getTitle(), fm, titleWidth); - int titleLength = fm.stringWidth(frameTitle); - int yOffset = ((height - fm.getHeight()) / 2) + fm.getAscent(); - if (!leftToRight) { - xOffset -= titleLength; - } - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - xOffset = Math.max(buttonsWidth + 5, (width - titleLength) / 2); - } - paintText(g, xOffset, yOffset, frameTitle); - paintBorder(g); - } - - class BasePropertyChangeHandler extends BasicInternalFrameTitlePane.PropertyChangeHandler { - - public void propertyChange(PropertyChangeEvent evt) { - String prop = evt.getPropertyName(); - if (prop.equals(JInternalFrame.IS_SELECTED_PROPERTY)) { - Boolean b = (Boolean) evt.getNewValue(); - iconButton.putClientProperty(PAINT_ACTIVE, b); - closeButton.putClientProperty(PAINT_ACTIVE, b); - maxButton.putClientProperty(PAINT_ACTIVE, b); - if (b.booleanValue()) { - activateFrame(); - } else { - deactivateFrame(); - } - repaint(); - } - super.propertyChange(evt); - } - } - -//------------------------------------------------------------------------------ -// inner classes -//------------------------------------------------------------------------------ - class BaseTitlePaneLayout extends TitlePaneLayout { - - public void addLayoutComponent(String name, Component c) { - } - - public void removeLayoutComponent(Component c) { - } - - public Dimension preferredLayoutSize(Container c) { - return minimumLayoutSize(c); - } - - public Dimension minimumLayoutSize(Container c) { - int width = 30; - if (frame.isClosable()) { - width += 21; - } - if (frame.isMaximizable()) { - width += 16 + (frame.isClosable() ? 10 : 4); - } - if (frame.isIconifiable()) { - width += 16 + (frame.isMaximizable() ? 2 : (frame.isClosable() ? 10 : 4)); - } - FontMetrics fm = getFontMetrics(getFont()); - String frameTitle = frame.getTitle(); - int title_w = frameTitle != null ? fm.stringWidth(frameTitle) : 0; - int title_length = frameTitle != null ? frameTitle.length() : 0; - - if (title_length > 2) { - int subtitle_w = fm.stringWidth(frame.getTitle().substring(0, 2) + "..."); - width += (title_w < subtitle_w) ? title_w : subtitle_w; - } else { - width += title_w; - } - - int height = paletteTitleHeight; - if (!isPalette) { - Icon icon = isMacStyleWindowDecoration() ? null : frame.getFrameIcon(); - if (icon == null) { - height = Math.max(fm.getHeight() + 6, 16); - } else { - height = Math.max(fm.getHeight() + 6, Math.min(icon.getIconHeight(), 24)); - } - } - return new Dimension(width, height); - } - - public void layoutContainer(Container c) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - layoutMacStyle(c); - } else { - layoutDefault(c); - } - } - - public void layoutDefault(Container c) { - boolean leftToRight = JTattooUtilities.isLeftToRight(frame); - - int spacing = getHorSpacing(); - int w = getWidth(); - int h = getHeight(); - - // assumes all buttons have the same dimensions these dimensions include the borders - int btnHeight = h - getVerSpacing(); - int btnWidth = btnHeight; - - int x = leftToRight ? w - spacing : 0; - int y = Math.max(0, ((h - btnHeight) / 2) - 1); - - if (frame.isClosable()) { - x += leftToRight ? -btnWidth : spacing; - closeButton.setBounds(x, y, btnWidth, btnHeight); - if (!leftToRight) { - x += btnWidth; - } - } - - if (frame.isMaximizable() && !isPalette) { - x += leftToRight ? -spacing - btnWidth : spacing; - maxButton.setBounds(x, y, btnWidth, btnHeight); - if (!leftToRight) { - x += btnWidth; - } - } - - if (frame.isIconifiable() && !isPalette) { - x += leftToRight ? -spacing - btnWidth : spacing; - iconButton.setBounds(x, y, btnWidth, btnHeight); - if (!leftToRight) { - x += btnWidth; - } - } - - buttonsWidth = leftToRight ? w - x : x; - - if (customTitlePanel != null) { - int maxWidth = w - buttonsWidth - spacing - 20; - Icon icon = frame.getFrameIcon(); - if (icon != null) { - maxWidth -= icon.getIconWidth(); - maxWidth -= spacing; - } - int cpw = Math.min(maxWidth, customTitlePanel.getPreferredSize().width); - int cph = h; - int cpx = leftToRight ? w - buttonsWidth - cpw : buttonsWidth; - int cpy = 0; - customTitlePanel.setBounds(cpx, cpy, cpw, cph); - buttonsWidth += customTitlePanel.getPreferredSize().width; - } - } - - private void layoutMacStyle(Container c) { - int spacing = getHorSpacing(); - int h = getHeight(); - - // assumes all buttons have the same dimensions these dimensions include the borders - int btnHeight = h - getVerSpacing() - 1; - int btnWidth = btnHeight; - - int x = 2; - int y = centerButtons() ? Math.max(0, ((h - btnHeight) / 2) - 1) : 0; - - if (frame.isClosable()) { - closeButton.setBounds(x, y, btnWidth, btnHeight); - x += spacing + btnWidth; - } - if (frame.isIconifiable() && !isPalette) { - iconButton.setBounds(x, y, btnWidth, btnHeight); - x += spacing + btnWidth; - } - if (frame.isMaximizable() && !isPalette) { - maxButton.setBounds(x, y, btnWidth, btnHeight); - x += spacing + btnWidth; - } - - buttonsWidth = x; - - if (customTitlePanel != null) { - int cpx = buttonsWidth + 5; - int cpy = 0; - int cpw = customTitlePanel.getPreferredSize().width; - int cph = h; - customTitlePanel.setBounds(cpx, cpy, cpw, cph); - buttonsWidth += cpw + 5; - } - } - } // end class BaseTitlePaneLayout -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseInternalFrameUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseInternalFrameUI.java deleted file mode 100644 index fe0f376d4..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseInternalFrameUI.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. - * - * JTattoo is multiple licensed. If your are an open source developer you can use - * it under the terms and conditions of the GNU General Public License version 2.0 - * or later as published by the Free Software Foundation. - * - * see: gpl-2.0.txt - * - * If you pay for a license you will become a registered user who could use the - * software under the terms and conditions of the GNU Lesser General Public License - * version 2.0 or later with classpath exception as published by the Free Software - * Foundation. - * - * see: lgpl-2.0.txt - * see: classpath-exception.txt - * - * Registered users could also use JTattoo under the terms and conditions of the - * Apache License, Version 2.0 as published by the Apache Software Foundation. - * - * see: APACHE-LICENSE-2.0.txt - */ -package com.jtattoo.plaf; - -import java.awt.Container; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicInternalFrameUI; - -public class BaseInternalFrameUI extends BasicInternalFrameUI { - - private static final PropertyChangeListener MY_PROPERTY_CHANGE_LISTENER = new MyPropertyChangeHandler(); - - private static final Border HANDY_EMPTY_BORDER = new EmptyBorder(0, 0, 0, 0); - - private static String IS_PALETTE = "JInternalFrame.isPalette"; - private static String FRAME_BORDER = "InternalFrame.border"; - private static String FRAME_PALETTE_BORDER = "InternalFrame.paletteBorder"; - - public BaseInternalFrameUI(JInternalFrame b) { - super(b); - } - - public static ComponentUI createUI(JComponent c) { - return new BaseInternalFrameUI((JInternalFrame) c); - } - - public void installUI(JComponent c) { - super.installUI(c); - Object paletteProp = c.getClientProperty(IS_PALETTE); - if (paletteProp != null) { - setPalette(((Boolean) paletteProp).booleanValue()); - } - stripContentBorder(); - } - - public void uninstallUI(JComponent c) { - Container cp = frame.getContentPane(); - if (cp instanceof JComponent) { - JComponent contentPane = (JComponent) cp; - if (contentPane.getBorder() == HANDY_EMPTY_BORDER) { - contentPane.setBorder(null); - } - } - super.uninstallUI(c); - } - - protected void installListeners() { - super.installListeners(); - frame.addPropertyChangeListener(MY_PROPERTY_CHANGE_LISTENER); - } - - protected void uninstallListeners() { - frame.removePropertyChangeListener(MY_PROPERTY_CHANGE_LISTENER); - super.uninstallListeners(); - } - - protected void uninstallComponents() { - titlePane = null; - super.uninstallComponents(); - } - - public void stripContentBorder() { - Container cp = frame.getContentPane(); - if (cp instanceof JComponent) { - JComponent contentPane = (JComponent) cp; - Border contentBorder = contentPane.getBorder(); - if (contentBorder == null || contentBorder instanceof UIResource) { - contentPane.setBorder(HANDY_EMPTY_BORDER); - } - } - } - - protected JComponent createNorthPane(JInternalFrame w) { - return new BaseInternalFrameTitlePane(w); - } - - public BaseInternalFrameTitlePane getTitlePane() { - return (BaseInternalFrameTitlePane) titlePane; - } - - public void setPalette(boolean isPalette) { - if (isPalette) { - frame.setBorder(UIManager.getBorder(FRAME_PALETTE_BORDER)); - } else { - frame.setBorder(UIManager.getBorder(FRAME_BORDER)); - } - getTitlePane().setPalette(isPalette); - } - -//----------------------------------------------------------------------------- -// inner classes -//----------------------------------------------------------------------------- - private static class MyPropertyChangeHandler implements PropertyChangeListener { - - public void propertyChange(PropertyChangeEvent e) { - JInternalFrame jif = (JInternalFrame) e.getSource(); - if (!(jif.getUI() instanceof BaseInternalFrameUI)) { - return; - } - - BaseInternalFrameUI ui = (BaseInternalFrameUI) jif.getUI(); - String name = e.getPropertyName(); - String FRAME_TYPE = "JInternalFrame.frameType"; - if (name.equals( FRAME_TYPE )) { - if (e.getNewValue() instanceof String) { - String PALETTE_FRAME = "palette"; - if ( PALETTE_FRAME.equals(e.getNewValue())) { - LookAndFeel.installBorder(ui.frame, FRAME_PALETTE_BORDER); - ui.setPalette(true); - } else { - LookAndFeel.installBorder(ui.frame, FRAME_BORDER); - ui.setPalette(false); - } - } - } else if (name.equals(IS_PALETTE)) { - if (e.getNewValue() != null) { - ui.setPalette(((Boolean) e.getNewValue()).booleanValue()); - } else { - ui.setPalette(false); - } - } else if (name.equals(JInternalFrame.CONTENT_PANE_PROPERTY)) { - ui.stripContentBorder(); - } - } - } // end class MyPropertyChangeHandler -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseLabelUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseLabelUI.java deleted file mode 100644 index b44ced83c..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseLabelUI.java +++ /dev/null @@ -1,71 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicLabelUI; - -/** - * @author Michael Hagen - */ -public class BaseLabelUI extends BasicLabelUI { - - private static BaseLabelUI baseLabelUI = null; - - public static ComponentUI createUI(JComponent c) { - if (baseLabelUI == null) { - baseLabelUI = new BaseLabelUI(); - } - return baseLabelUI; - } - - protected void paintEnabledText(JLabel l, Graphics g, String s, int textX, int textY) { - int mnemIndex; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = l.getDisplayedMnemonicIndex(); - } else { - mnemIndex = JTattooUtilities.findDisplayedMnemonicIndex(l.getText(), l.getDisplayedMnemonic()); - } - g.setColor(l.getForeground()); - JTattooUtilities.drawStringUnderlineCharAt(l, g, s, mnemIndex, textX, textY); - } - - protected void paintDisabledText(JLabel l, Graphics g, String s, int textX, int textY) { - int mnemIndex; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = l.getDisplayedMnemonicIndex(); - } else { - mnemIndex = JTattooUtilities.findDisplayedMnemonicIndex(l.getText(), l.getDisplayedMnemonic()); - } - g.setColor(Color.white); - JTattooUtilities.drawStringUnderlineCharAt(l, g, s, mnemIndex, textX + 1, textY + 1); - g.setColor(AbstractLookAndFeel.getDisabledForegroundColor()); - JTattooUtilities.drawStringUnderlineCharAt(l, g, s, mnemIndex, textX, textY); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseMenuBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseMenuBarUI.java deleted file mode 100644 index cde711d06..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseMenuBarUI.java +++ /dev/null @@ -1,45 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicMenuBarUI; - -/** - * @author Michael Hagen - */ -public class BaseMenuBarUI extends BasicMenuBarUI { - - public static ComponentUI createUI(JComponent c) { - return new BaseMenuBarUI(); - } - - public void paint(Graphics g, JComponent c) { - int w = c.getWidth(); - int h = c.getHeight(); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getMenuBarColors(), 0, 0, w, h); - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseMenuItemUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseMenuItemUI.java deleted file mode 100644 index 2b827f851..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseMenuItemUI.java +++ /dev/null @@ -1,105 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicMenuItemUI; - -/** - * @author Michael Hagen - */ -public class BaseMenuItemUI extends BasicMenuItemUI { - - public static ComponentUI createUI(JComponent c) { - return new BaseMenuItemUI(); - } - - public void installUI(JComponent c) { - super.installUI(c); - c.setOpaque(false); - } - - public void uninstallUI(JComponent c) { - c.setOpaque(true); - super.uninstallUI(c); - } - - public void update(Graphics g, JComponent c) { - paintBackground(g, c, 0, 0, c.getWidth(), c.getHeight()); - paint(g, c); - } - - protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) { - if (menuItem.isOpaque()) { - int w = menuItem.getWidth(); - int h = menuItem.getHeight(); - paintBackground(g, menuItem, 0, 0, w, h); - } - } - - protected void paintBackground(Graphics g, JComponent c, int x, int y, int w, int h) { - JMenuItem b = (JMenuItem) c; - ButtonModel model = b.getModel(); - if (model.isArmed() || (c instanceof JMenu && model.isSelected())) { - g.setColor(AbstractLookAndFeel.getMenuSelectionBackgroundColor()); - g.fillRect(x, y, w, h); - } else if (!AbstractLookAndFeel.getTheme().isMenuOpaque()) { - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, AbstractLookAndFeel.getTheme().getMenuAlpha()); - g2D.setComposite(alpha); - g.setColor(AbstractLookAndFeel.getMenuBackgroundColor()); - g.fillRect(x, y, w, h); - g2D.setComposite(savedComposite); - } else { - g.setColor(AbstractLookAndFeel.getMenuBackgroundColor()); - g.fillRect(x, y, w, h); - } - if (menuItem.isSelected() && menuItem.isArmed()) { - g.setColor(AbstractLookAndFeel.getMenuSelectionForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getMenuForegroundColor()); - } - } - - protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { - Graphics2D g2D = (Graphics2D) g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - if (menuItem.isSelected() && menuItem.isArmed()) { - g.setColor(AbstractLookAndFeel.getMenuSelectionForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getMenuForegroundColor()); - } - super.paintText(g, menuItem, textRect, text); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseMenuUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseMenuUI.java deleted file mode 100644 index 9d114bf0a..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseMenuUI.java +++ /dev/null @@ -1,173 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.MouseEvent; -import javax.swing.*; -import javax.swing.event.MouseInputListener; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicMenuUI; - -/** - * @author Michael Hagen - */ -public class BaseMenuUI extends BasicMenuUI { - - protected boolean paintRolloverBorder = true; - - public static ComponentUI createUI(JComponent c) { - return new BaseMenuUI(); - } - - public void installUI(JComponent c) { - super.installUI(c); - c.setOpaque(false); - } - - public void uninstallUI(JComponent c) { - c.setOpaque(true); - super.uninstallUI(c); - } - - public void update(Graphics g, JComponent c) { - paintBackground(g, c, 0, 0, c.getWidth(), c.getHeight()); - paint(g, c); - } - - protected void installDefaults() { - super.installDefaults(); - Boolean isRolloverEnabled = (Boolean)UIManager.get("MenuBar.rolloverEnabled"); - if (isRolloverEnabled.booleanValue()) { - menuItem.setRolloverEnabled(true); - } - } - - protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) { - if (menuItem.isOpaque()) { - int w = menuItem.getWidth(); - int h = menuItem.getHeight(); - paintBackground(g, menuItem, 0, 0, w, h); - } - } - - protected void paintBackground(Graphics g, JComponent c, int x, int y, int w, int h) { - JMenuItem mi = (JMenuItem) c; - ButtonModel model = mi.getModel(); - if (c.getParent() instanceof JMenuBar) { - if (model.isRollover() || model.isArmed() || (c instanceof JMenu && model.isSelected())) { - Color backColor = AbstractLookAndFeel.getMenuSelectionBackgroundColor(); - if (model.isRollover()) { - backColor = ColorHelper.brighter(backColor, 10); - } - g.setColor(backColor); - g.fillRect(x, y, w, h); - if (paintRolloverBorder && model.isRollover() && !model.isSelected()) { - backColor = ColorHelper.darker(backColor, 20); - g.setColor(backColor); - g.drawRect(x, y, w - 1, h - 1); - } - } - } else { - if (model.isArmed() || (c instanceof JMenu && model.isSelected())) { - g.setColor(AbstractLookAndFeel.getMenuSelectionBackgroundColor()); - g.fillRect(x, y, w, h); - } else if (!AbstractLookAndFeel.getTheme().isMenuOpaque()) { - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, AbstractLookAndFeel.getTheme().getMenuAlpha()); - g2D.setComposite(alpha); - g.setColor(AbstractLookAndFeel.getMenuBackgroundColor()); - g.fillRect(x, y, w, h); - g2D.setComposite(savedComposite); - } else { - g.setColor(AbstractLookAndFeel.getMenuBackgroundColor()); - g.fillRect(x, y, w, h); - } - } - if (menuItem.isSelected() && menuItem.isArmed()) { - g.setColor(AbstractLookAndFeel.getMenuSelectionForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getMenuForegroundColor()); - } - } - - protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { - ButtonModel model = menuItem.getModel(); - Graphics2D g2D = (Graphics2D) g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - g.setColor(AbstractLookAndFeel.getMenuForegroundColor()); - if (menuItem.getParent() instanceof JMenuBar) { - if (model.isRollover() || model.isArmed() || (menuItem instanceof JMenu && model.isSelected())) { - g.setColor(AbstractLookAndFeel.getMenuSelectionForegroundColor()); - } - } else if(menuItem.isSelected() && menuItem.isArmed()) { - g.setColor(AbstractLookAndFeel.getMenuSelectionForegroundColor()); - } - super.paintText(g, menuItem, textRect, text); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } - - protected MouseInputListener createMouseInputListener(JComponent c) { - if (JTattooUtilities.getJavaVersion() >= 1.5) { - return new MyMouseInputHandler(); - } else { - return super.createMouseInputListener(c); - } - } - -//------------------------------------------------------------------------------ -// inner classes -//------------------------------------------------------------------------------ - - protected class MyMouseInputHandler extends BasicMenuUI.MouseInputHandler { - - public void mouseEntered(MouseEvent evt) { - super.mouseEntered(evt); - - JMenu menu = (JMenu) evt.getSource(); - if (menu.isTopLevelMenu() && menu.isRolloverEnabled()) { - menu.getModel().setRollover(true); - menuItem.repaint(); - } - } - - public void mouseExited(MouseEvent evt) { - super.mouseExited(evt); - - JMenu menu = (JMenu) evt.getSource(); - ButtonModel model = menu.getModel(); - if (menu.isRolloverEnabled()) { - model.setRollover(false); - menuItem.repaint(); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BasePanelUI.java b/src/jtattoo/src/com/jtattoo/plaf/BasePanelUI.java deleted file mode 100644 index 4422ce0a1..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BasePanelUI.java +++ /dev/null @@ -1,90 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.lang.reflect.Field; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicPanelUI; - -/** - * @author Michael Hagen - */ -public class BasePanelUI extends BasicPanelUI { - - private static BasePanelUI panelUI = null; - - public static ComponentUI createUI(JComponent c) { - if (panelUI == null) { - panelUI = new BasePanelUI(); - } - return panelUI; - } - - protected void installDefaults(JPanel p) { - super.installDefaults(p); - p.setFont(AbstractLookAndFeel.getTheme().getControlTextFont()); - - // We don't want medium weight popups for tool tips, so we try to force heavy weight popups. - try { - Field field; - if (JTattooUtilities.getJavaVersion() < 1.7) { - Class clazz = Class.forName("javax.swing.PopupFactory"); - field = clazz.getDeclaredField("forceHeavyWeightPopupKey"); - } else { //1.7.0, 1.8.0 - Class clazz = Class.forName("javax.swing.ClientPropertyKey"); - field = clazz.getDeclaredField("PopupFactory_FORCE_HEAVYWEIGHT_POPUP"); - } - field.setAccessible(true); - p.putClientProperty(field.get(null), Boolean.TRUE); - } catch(Exception ex) { - } - } - - public void update(Graphics g, JComponent c) { - if (c.isOpaque()) { - Object backgroundTexture = c.getClientProperty("backgroundTexture"); - if (backgroundTexture instanceof Icon) { - JTattooUtilities.fillComponent(g, c, (Icon)backgroundTexture); - } else { - g.setColor(c.getBackground()); - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } - } - - public void paint(Graphics g, JComponent c) { - Graphics2D g2D = (Graphics2D) g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - super.paint(g, c); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BasePasswordFieldUI.java b/src/jtattoo/src/com/jtattoo/plaf/BasePasswordFieldUI.java deleted file mode 100644 index 47f762ac4..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BasePasswordFieldUI.java +++ /dev/null @@ -1,123 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.KeyEvent; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicPasswordFieldUI; -import javax.swing.text.DefaultEditorKit; - -/** - * @author Michael Hagen - */ -public class BasePasswordFieldUI extends BasicPasswordFieldUI { - - private Border orgBorder = null; - private FocusListener focusListener = null; - - public static ComponentUI createUI(JComponent c) { - return new BasePasswordFieldUI(); - } - - protected void installKeyboardActions() { - super.installKeyboardActions(); - if (JTattooUtilities.isMac()) { - InputMap im = (InputMap) UIManager.get("TextField.focusInputMap"); - int commandKey = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, commandKey), DefaultEditorKit.copyAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, commandKey), DefaultEditorKit.pasteAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, commandKey), DefaultEditorKit.cutAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.ALT_DOWN_MASK), DefaultEditorKit.nextWordAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.ALT_DOWN_MASK), DefaultEditorKit.previousWordAction); - } - } - - protected void installListeners() { - super.installListeners(); - - if (AbstractLookAndFeel.getTheme().doShowFocusFrame()) { - focusListener = new FocusListener() { - - public void focusGained(FocusEvent e) { - if (getComponent() != null) { - orgBorder = getComponent().getBorder(); - LookAndFeel laf = UIManager.getLookAndFeel(); - if (laf instanceof AbstractLookAndFeel && orgBorder instanceof UIResource) { - Border focusBorder = ((AbstractLookAndFeel)laf).getBorderFactory().getFocusFrameBorder(); - getComponent().setBorder(focusBorder); - } - getComponent().invalidate(); - getComponent().repaint(); - } - } - - public void focusLost(FocusEvent e) { - if (getComponent() != null) { - if (orgBorder instanceof UIResource) { - getComponent().setBorder(orgBorder); - } - getComponent().invalidate(); - getComponent().repaint(); - } - } - }; - getComponent().addFocusListener(focusListener); - } - } - - protected void uninstallListeners() { - getComponent().removeFocusListener(focusListener); - focusListener = null; - super.uninstallListeners(); - } - - protected void paintBackground(Graphics g) { - g.setColor(getComponent().getBackground()); - if (AbstractLookAndFeel.getTheme().doShowFocusFrame()) { - if (getComponent().hasFocus() && getComponent().isEditable()) { - g.setColor(AbstractLookAndFeel.getTheme().getFocusBackgroundColor()); - } - } - g.fillRect(0, 0, getComponent().getWidth(), getComponent().getHeight()); - } - - protected void paintSafely(Graphics g) { - Graphics2D g2D = (Graphics2D) g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - super.paintSafely(g); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BasePopupMenuUI.java b/src/jtattoo/src/com/jtattoo/plaf/BasePopupMenuUI.java deleted file mode 100644 index 820fbe714..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BasePopupMenuUI.java +++ /dev/null @@ -1,144 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.image.BufferedImage; -import javax.swing.*; -import javax.swing.event.PopupMenuEvent; -import javax.swing.event.PopupMenuListener; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicPopupMenuUI; - -/** - * @author Michael Hagen - */ -public class BasePopupMenuUI extends BasicPopupMenuUI { - - protected static Robot robot = null; - protected BufferedImage screenImage = null; - protected MyPopupMenuListener myPopupListener = null; - - public static ComponentUI createUI(JComponent c) { - return new BasePopupMenuUI(); - } - - public void installUI(JComponent c) { - super.installUI(c); - c.setOpaque(false); - } - - public void uninstallUI(JComponent c) { - super.uninstallUI(c); - c.setOpaque(true); - } - - public void installListeners() { - super.installListeners(); - if (!isMenuOpaque()) { - myPopupListener = new MyPopupMenuListener(this); - popupMenu.addPopupMenuListener(myPopupListener); - } - } - - public void uninstallListeners() { - if (!isMenuOpaque()) { - popupMenu.removePopupMenuListener(myPopupListener); - } - super.uninstallListeners(); - } - - private boolean isMenuOpaque() { - return (AbstractLookAndFeel.getTheme().isMenuOpaque() || (getRobot() == null)); - } - - private Robot getRobot() { - if (robot == null) { - try { - robot = new Robot(); - } catch (Exception ex) { - } - } - return robot; - } - - public Popup getPopup(JPopupMenu popupMenu, int x, int y) { - if (!isMenuOpaque()) { - try { - Dimension size = popupMenu.getPreferredSize(); - Rectangle screenRect = new Rectangle(x, y, size.width, size.height); - screenImage = getRobot().createScreenCapture(screenRect); - } catch (Exception ex) { - screenImage = null; - } - } - return super.getPopup(popupMenu, x, y); - } - - private void resetScreenImage() { - screenImage = null; - } - - public void update(Graphics g, JComponent c) { - if (screenImage != null) { - g.drawImage(screenImage, 0, 0, null); - } else { - g.setColor(Color.white); - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } - -//---------------------------------------------------------------------------------------- -// inner classes -//---------------------------------------------------------------------------------------- - public static class MyPopupMenuListener implements PopupMenuListener { - - private BasePopupMenuUI popupMenuUI = null; - - public MyPopupMenuListener(BasePopupMenuUI aPopupMenuUI) { - popupMenuUI = aPopupMenuUI; - } - - public void popupMenuCanceled(PopupMenuEvent e) { - } - - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { - if (popupMenuUI.screenImage != null) { - JPopupMenu popup = (JPopupMenu) e.getSource(); - JRootPane root = popup.getRootPane(); - if (popup.isShowing() && root.isShowing()) { - Point ptPopup = popup.getLocationOnScreen(); - Point ptRoot = root.getLocationOnScreen(); - Graphics g = popup.getRootPane().getGraphics(); - g.drawImage(popupMenuUI.screenImage, ptPopup.x - ptRoot.x, ptPopup.y - ptRoot.y, null); - popupMenuUI.resetScreenImage(); - } - } - } - - public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - } - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseProgressBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseProgressBarUI.java deleted file mode 100644 index 5205f07ad..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseProgressBarUI.java +++ /dev/null @@ -1,219 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicProgressBarUI; - -/** - * @author Michael Hagen - */ -public class BaseProgressBarUI extends BasicProgressBarUI { - - protected PropertyChangeListener propertyChangeListener; - - public static ComponentUI createUI(JComponent c) { - return new BaseProgressBarUI(); - } - - public void installUI(JComponent c) { - super.installUI(c); - c.setBorder(UIManager.getBorder("ProgressBar.border")); - propertyChangeListener = new PropertyChangeHandler(); - c.addPropertyChangeListener(propertyChangeListener); - } - - public void uninstallUI(JComponent c) { - c.removePropertyChangeListener(propertyChangeListener); - super.uninstallUI(c); - } - - /** - * The "selectionForeground" is the color of the text when it is painted - * over a filled area of the progress bar. - */ - protected Color getSelectionForeground() { - Object selectionForeground = progressBar.getClientProperty("selectionForeground"); - if (selectionForeground instanceof Color) { - return (Color)selectionForeground; - } - return super.getSelectionForeground(); - } - - /** - * The "selectionBackground" is the color of the text when it is painted - * over an unfilled area of the progress bar. - */ - protected Color getSelectionBackground() { - Object selectionBackground = progressBar.getClientProperty("selectionBackground"); - if (selectionBackground instanceof Color) { - return (Color)selectionBackground; - } - return super.getSelectionBackground(); - } - - protected void paintIndeterminate(Graphics g, JComponent c) { - if (!(g instanceof Graphics2D)) { - return; - } - Graphics2D g2D = (Graphics2D) g; - - Insets b = progressBar.getInsets(); // area for border - int barRectWidth = progressBar.getWidth() - (b.right + b.left); - int barRectHeight = progressBar.getHeight() - (b.top + b.bottom); - - Color colors[]; - if (progressBar.getForeground() instanceof UIResource) { - if (!JTattooUtilities.isActive(c)) { - colors = AbstractLookAndFeel.getTheme().getInActiveColors(); - } else if (c.isEnabled()) { - colors = AbstractLookAndFeel.getTheme().getProgressBarColors(); - } else { - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } - } else { - Color hiColor = ColorHelper.brighter(progressBar.getForeground(), 40); - Color loColor = ColorHelper.darker(progressBar.getForeground(), 20); - colors = ColorHelper.createColorArr(hiColor, loColor, 20); - } - - Color cHi = ColorHelper.darker(colors[colors.length - 1], 5); - Color cLo = ColorHelper.darker(colors[colors.length - 1], 10); - - // Paint the bouncing box. - Rectangle box = getBox(null); - if (box != null) { - g2D.setColor(progressBar.getForeground()); - JTattooUtilities.draw3DBorder(g, cHi, cLo, box.x + 1, box.y + 1, box.width - 2, box.height - 2); - if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) { - JTattooUtilities.fillHorGradient(g, colors, box.x + 2, box.y + 2, box.width - 4, box.height - 4); - } else { - JTattooUtilities.fillVerGradient(g, colors, box.x + 2, box.y + 2, box.width - 4, box.height - 4); - } - } - - // Deal with possible text painting - if (progressBar.isStringPainted()) { - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) { - paintString(g2D, b.left, b.top, barRectWidth, barRectHeight, box.width, b); - } else { - paintString(g2D, b.left, b.top, barRectWidth, barRectHeight, box.height, b); - } - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } - } - - protected void paintDeterminate(Graphics g, JComponent c) { - if (!(g instanceof Graphics2D)) { - return; - } - - Graphics2D g2D = (Graphics2D) g; - Insets b = progressBar.getInsets(); // area for border - int w = progressBar.getWidth() - (b.right + b.left); - int h = progressBar.getHeight() - (b.top + b.bottom); - - // amount of progress to draw - int amountFull = getAmountFull(b, w, h); - Color colors[]; - if (progressBar.getForeground() instanceof UIResource) { - if (!JTattooUtilities.isActive(c)) { - colors = AbstractLookAndFeel.getTheme().getInActiveColors(); - } else if (c.isEnabled()) { - colors = AbstractLookAndFeel.getTheme().getProgressBarColors(); - } else { - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } - } else { - Color hiColor = ColorHelper.brighter(progressBar.getForeground(), 40); - Color loColor = ColorHelper.darker(progressBar.getForeground(), 20); - colors = ColorHelper.createColorArr(hiColor, loColor, 20); - } - Color cHi = ColorHelper.darker(colors[colors.length - 1], 5); - Color cLo = ColorHelper.darker(colors[colors.length - 1], 10); - if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) { - if (JTattooUtilities.isLeftToRight(progressBar)) { - JTattooUtilities.draw3DBorder(g, cHi, cLo, 2, 2, amountFull - 2, h - 2); - JTattooUtilities.fillHorGradient(g, colors, 3, 3, amountFull - 4, h - 4); - } else { - JTattooUtilities.draw3DBorder(g, cHi, cLo, w - amountFull + 2, 2, w - 2, h - 2); - JTattooUtilities.fillHorGradient(g, colors, w - amountFull + 3, 3, w - 4, h - 4); - } - } else { // VERTICAL - JTattooUtilities.draw3DBorder(g, cHi, cLo, 2, h - amountFull + 2, w - 2, amountFull - 2); - JTattooUtilities.fillVerGradient(g, colors, 3, h - amountFull + 3, w - 4, amountFull - 4); - } - - // Deal with possible text painting - if (progressBar.isStringPainted()) { - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - paintString(g, b.left, b.top, w, h, amountFull, b); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } - } - - public void paint(Graphics g, JComponent c) { - if (JTattooUtilities.getJavaVersion() >= 1.4) { - if (progressBar.isIndeterminate()) { - paintIndeterminate(g, c); - } else { - paintDeterminate(g, c); - } - } else { - paintDeterminate(g, c); - } - } - -//----------------------------------------------------------------------------------------------- - protected class PropertyChangeHandler implements PropertyChangeListener { - - public void propertyChange(PropertyChangeEvent e) { - if ("selectionForeground".equals(e.getPropertyName()) && (e.getNewValue() instanceof Color)) { - progressBar.invalidate(); - progressBar.repaint(); - } else if ("selectionBackground".equals(e.getPropertyName()) && (e.getNewValue() instanceof Color)) { - progressBar.invalidate(); - progressBar.repaint(); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseRadioButtonMenuItemUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseRadioButtonMenuItemUI.java deleted file mode 100644 index 40f901d3c..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseRadioButtonMenuItemUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import javax.swing.JComponent; -import javax.swing.UIManager; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class BaseRadioButtonMenuItemUI extends BaseMenuItemUI { - - public static ComponentUI createUI(JComponent b) { - return new BaseRadioButtonMenuItemUI(); - } - - protected void installDefaults() { - super.installDefaults(); - checkIcon = UIManager.getIcon("RadioButtonMenuItem.checkIcon"); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseRadioButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseRadioButtonUI.java deleted file mode 100644 index 21150c148..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseRadioButtonUI.java +++ /dev/null @@ -1,198 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.*; -import javax.swing.text.View; - -/** - * @author Michael Hagen - */ -public class BaseRadioButtonUI extends BasicRadioButtonUI { - - private static BaseRadioButtonUI radioButtonUI = null; - /* These Dimensions/Rectangles are allocated once for all - * RadioButtonUI.paint() calls. Re-using rectangles - * rather than allocating them in each paint call substantially - * reduced the time it took paint to run. Obviously, this - * method can't be re-entered. - */ - protected static Dimension size = new Dimension(); - protected static Rectangle viewRect = new Rectangle(); - protected static Rectangle iconRect = new Rectangle(); - protected static Rectangle textRect = new Rectangle(); - - public static ComponentUI createUI(JComponent c) { - if (radioButtonUI == null) { - radioButtonUI = new BaseRadioButtonUI(); - } - return radioButtonUI; - } - - public void installDefaults(AbstractButton b) { - super.installDefaults(b); - b.setRolloverEnabled(true); - icon = UIManager.getIcon("RadioButton.icon"); - } - - public void paint(Graphics g, JComponent c) { - AbstractButton b = (AbstractButton) c; - Font f = c.getFont(); - g.setFont(f); - FontMetrics fm = g.getFontMetrics(); - - Insets i = c.getInsets(); - size = b.getSize(size); - viewRect.x = i.left; - viewRect.y = i.top; - viewRect.width = size.width - (i.right + viewRect.x); - viewRect.height = size.height - (i.bottom + viewRect.y); - iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0; - textRect.x = textRect.y = textRect.width = textRect.height = 0; - Icon altIcon = b.getIcon(); - int iconTextGap = getDefaultTextIconGap(b); - if (JTattooUtilities.getJavaVersion() >= 1.4) { - iconTextGap = b.getIconTextGap(); - } - String text = SwingUtilities.layoutCompoundLabel( - c, - fm, - b.getText(), - altIcon != null ? altIcon : getDefaultIcon(), - b.getVerticalAlignment(), - b.getHorizontalAlignment(), - b.getVerticalTextPosition(), - b.getHorizontalTextPosition(), - viewRect, - iconRect, - textRect, - iconTextGap); - - // fill background - if (c.isOpaque()) { - paintBackground(g, c); - } - - paintIcon(g, c, iconRect); - - if (text != null) { - paintText(g, c, text, textRect); - } - - if (b.hasFocus() && b.isFocusPainted() && (textRect.width > 0) && (textRect.height > 0)) { - paintFocus(g, textRect, size); - } - } - - protected void paintBackground(Graphics g, JComponent c) { - g.setColor(c.getBackground()); - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - - protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect) { - AbstractButton b = (AbstractButton) c; - ButtonModel model = b.getModel(); - Icon ico; - if (!model.isEnabled()) { - if (b.isSelected()) { - ico = b.getDisabledSelectedIcon(); - } else { - ico = b.getDisabledIcon(); - } - } else { - if (model.isPressed()) { - ico = b.getPressedIcon(); - } else { - if (model.isRollover()) { - if (b.isSelected()) { - ico = b.getRolloverSelectedIcon(); - } else { - ico = b.getRolloverIcon(); - } - } else { - if (b.isSelected()) { - ico = b.getSelectedIcon(); - } else { - ico = b.getIcon(); - } - } - } - } - - if (ico != null) { - ico.paintIcon(c, g, iconRect.x, iconRect.y - 1); - } else { - if (b.getIcon() != null) { - b.getIcon().paintIcon(c, g, iconRect.x, iconRect.y - 1); - } else { - getDefaultIcon().paintIcon(c, g, iconRect.x, iconRect.y - 1); - } - } - } - - protected void paintText(Graphics g, JComponent c, String text, Rectangle textRect) { - View v = (View) c.getClientProperty(BasicHTML.propertyKey); - if (v != null) { - Graphics2D g2D = (Graphics2D) g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - v.paint(g, textRect); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } else { - AbstractButton b = (AbstractButton) c; - ButtonModel model = b.getModel(); - Font f = c.getFont(); - g.setFont(f); - FontMetrics fm = g.getFontMetrics(); - int mnemIndex; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = b.getDisplayedMnemonicIndex(); - } else { - mnemIndex = JTattooUtilities.findDisplayedMnemonicIndex(b.getText(), model.getMnemonic()); - } - if (model.isEnabled()) { - g.setColor(b.getForeground()); - JTattooUtilities.drawStringUnderlineCharAt(c, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); - } else { - g.setColor(Color.white); - JTattooUtilities.drawStringUnderlineCharAt(c, g, text, mnemIndex, textRect.x + 1, textRect.y + 1 + fm.getAscent()); - g.setColor(AbstractLookAndFeel.getDisabledForegroundColor()); - JTattooUtilities.drawStringUnderlineCharAt(c, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); - } - } - } - - protected void paintFocus(Graphics g, Rectangle t, Dimension d) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - BasicGraphicsUtils.drawDashedRect(g, t.x, t.y - 1, t.width + 1, t.height + 1); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseRootPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseRootPaneUI.java deleted file mode 100644 index 51ff36121..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseRootPaneUI.java +++ /dev/null @@ -1,934 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.InputEvent; -import java.awt.event.MouseEvent; -import java.awt.image.BufferedImage; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import javax.swing.*; -import javax.swing.event.MouseInputListener; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicRootPaneUI; - -/** - * This source is a modified copy of javax.swing.plaf.metal.MetalRootPaneUI - * Provides the base look and feel implementation of RootPaneUI. - *

        - * BaseRootPaneUI provides support for the - * windowDecorationStyle property of JRootPane. - * BaseRootPaneUI does this by way of installing a custom - * LayoutManager, a private Component to render - * the appropriate widgets, and a private Border. The - * LayoutManager is always installed, regardless of the value of - * the windowDecorationStyle property, but the - * Border and Component are only installed/added if - * the windowDecorationStyle is other than - * JRootPane.NONE. - *

        - * Warning: - * Serialized objects of this class will not be compatible with - * future Swing releases. The current serialization support is - * appropriate for short term storage or RMI between applications running - * the same version of Swing. As of 1.4, support for long term storage - * of all JavaBeansTM - * has been added to the java.beans package. - * Please see {@link java.beans.XMLEncoder}. - * - * @version 1.20 04/27/04 - * @author Terry Kellerman - * @author Michael Hagen - * @since 1.4 - */ -public class BaseRootPaneUI extends BasicRootPaneUI { - // Konstanten aus javax.swing.JRootPane damit Attribute aus Java 1.4 sich mit Java 1.3 uebersetzen lassen - - public static final int NONE = 0; - public static final int FRAME = 1; - public static final int PLAIN_DIALOG = 2; - public static final int INFORMATION_DIALOG = 3; - public static final int ERROR_DIALOG = 4; - public static final int COLOR_CHOOSER_DIALOG = 5; - public static final int FILE_CHOOSER_DIALOG = 6; - public static final int QUESTION_DIALOG = 7; - public static final int WARNING_DIALOG = 8; - // Konstanten aus java.awt.Frame damit Attribute aus Java 1.4 sich mit Java 1.3 uebersetzen lassen - public static final int MAXIMIZED_HORIZ = 2; - public static final int MAXIMIZED_VERT = 4; - public static final int MAXIMIZED_BOTH = MAXIMIZED_VERT | MAXIMIZED_HORIZ; - private static final String[] borderKeys = new String[]{ - null, - "RootPane.frameBorder", - "RootPane.plainDialogBorder", - "RootPane.informationDialogBorder", - "RootPane.errorDialogBorder", - "RootPane.colorChooserDialogBorder", - "RootPane.fileChooserDialogBorder", - "RootPane.questionDialogBorder", - "RootPane.warningDialogBorder" - }; - /** - * The minimum/maximum size of a Window - */ - private static final Dimension MINIMUM_SIZE = new Dimension(120, 80); - private static final Dimension MAXIMUM_SIZE = Toolkit.getDefaultToolkit().getScreenSize(); - /** - * The amount of space (in pixels) that the cursor is changed on. - */ - private static final int CORNER_DRAG_WIDTH = 16; - /** - * Region from edges that dragging is active from. - */ - private static final int BORDER_DRAG_THICKNESS = 5; - /** - * Window the JRootPane is in. - */ - private Window window; - /** - * JComponent providing window decorations. This will be - * null if not providing window decorations. - */ - private BaseTitlePane titlePane; - /** - * MouseInputListener that is added to the parent - * Window the JRootPane is contained in. - */ - private MouseInputListener mouseInputListener; - /** - * The LayoutManager that is set on the - * JRootPane. - */ - private LayoutManager layoutManager; - /** - * LayoutManager of the JRootPane before we - * replaced it. - */ - private LayoutManager savedOldLayout; - /** - * JRootPane providing the look and feel for. - */ - private JRootPane root; - - private Cursor savedCursor = null; - - /** - * Cursor used to track the cursor set by the user. - * This is initially Cursor.DEFAULT_CURSOR. - */ - /** - * Creates a UI for a JRootPane. - * - * @param c the JRootPane the RootPaneUI will be created for - * @return the RootPaneUI implementation for the passed in JRootPane - */ - public static ComponentUI createUI(JComponent c) { - return new BaseRootPaneUI(); - } - - public void installUI(JComponent c) { - super.installUI(c); - root = (JRootPane) c; - if (DecorationHelper.getWindowDecorationStyle(root) != NONE) { - installClientDecorations(root); - } - } - - public void uninstallUI(JComponent c) { - super.uninstallUI(c); - uninstallClientDecorations(root); - - layoutManager = null; - mouseInputListener = null; - root = null; - } - - public void installBorder(JRootPane root) { - int style = DecorationHelper.getWindowDecorationStyle(root); - if (style == NONE) { - LookAndFeel.uninstallBorder(root); - } else { - LookAndFeel.installBorder(root, borderKeys[style]); - } - } - - /** - * Removes any border that may have been installed. - */ - public void uninstallBorder(JRootPane root) { - LookAndFeel.uninstallBorder(root); - } - - /** - * Installs the necessary Listeners on the parent Window, - * if there is one. - *

        - * This takes the parent so that cleanup can be done from - * removeNotify, at which point the parent hasn't been - * reset yet. - * - * @param parent The parent of the JRootPane - */ - public void installWindowListeners(JRootPane root, Component parent) { - if (parent instanceof Window) { - window = (Window) parent; - } else { - window = SwingUtilities.getWindowAncestor(parent); - } - if (window != null) { - if (mouseInputListener == null) { - mouseInputListener = createWindowMouseInputListener(root); - } - window.addMouseListener(mouseInputListener); - window.addMouseMotionListener(mouseInputListener); - // fixes a problem with netbeans, decorated windows and java 1.5 - // the MetalLookAndFeel seems to have the same problem - if ((JTattooUtilities.getJavaVersion() >= 1.5) && (JTattooUtilities.getJavaVersion() <= 1.6)) { - SwingUtilities.invokeLater( () -> { - if (window != null) { - if (window instanceof JFrame) { - JFrame frame = (JFrame) window; - frame.update(frame.getGraphics()); - } - } - } ); - } - } - } - - /** - * Uninstalls the necessary Listeners on the Window the - * Listeners were last installed on. - */ - public void uninstallWindowListeners(JRootPane root) { - if (window != null) { - window.removeMouseListener(mouseInputListener); - window.removeMouseMotionListener(mouseInputListener); - } - } - - /** - * Installs the appropriate LayoutManager on the JRootPane - * to render the window decorations. - */ - public void installLayout(JRootPane root) { - if (layoutManager == null) { - layoutManager = createLayoutManager(); - } - savedOldLayout = root.getLayout(); - root.setLayout(layoutManager); - } - - public void uninstallLayout(JRootPane root) { - if (savedOldLayout != null) { - root.setLayout(savedOldLayout); - savedOldLayout = null; - } - } - - public void installClientDecorations(JRootPane root) { - installBorder(root); - setTitlePane(root, createTitlePane(root)); - installWindowListeners(root, root.getParent()); - installLayout(root); - if (window != null) { - savedCursor = window.getCursor(); - root.revalidate(); - root.repaint(); - } - } - - public void uninstallClientDecorations(JRootPane root) { - uninstallBorder(root); - uninstallWindowListeners(root); - setTitlePane(root, null); - uninstallLayout(root); - int style = DecorationHelper.getWindowDecorationStyle(root); - if (style == NONE) { - root.repaint(); - root.revalidate(); - } - // Reset the cursor, as we may have changed it to a resize cursor - if (window != null) { - window.setCursor(savedCursor); - } - window = null; - } - - /** - * Returns the JComponent to render the window decoration - * style. - */ - public BaseTitlePane createTitlePane(JRootPane root) { - return new BaseTitlePane(root, this); - } - - /** - * Returns a MouseListener that will be added to the - * Window containing the JRootPane. - */ - public MouseInputListener createWindowMouseInputListener(JRootPane root) { - return new MouseInputHandler(); - } - - /** - * Returns a LayoutManager that will be set on the - * JRootPane. - */ - public LayoutManager createLayoutManager() { - return new BaseRootLayout(); - } - - /** - * Sets the window title pane -- the JComponent used to provide a plaf a - * way to override the native operating system's window title pane with - * one whose look and feel are controlled by the plaf. The plaf creates - * and sets this value; the default is null, implying a native operating - * system window title pane. - * - * @param root the JRootPane where to set the title pane - * @param titlePane the BaseTitlePane to use for the window title pane. - */ - public void setTitlePane(JRootPane root, BaseTitlePane titlePane) { - JLayeredPane layeredPane = root.getLayeredPane(); - BaseTitlePane oldTitlePane = getTitlePane(); - - if (oldTitlePane != null) { - oldTitlePane.setVisible(false); - layeredPane.remove(oldTitlePane); - } - if (titlePane != null) { - layeredPane.add(titlePane, JLayeredPane.FRAME_CONTENT_LAYER); - titlePane.setVisible(true); - } - this.titlePane = titlePane; - } - - /** - * Returns the JComponent rendering the title pane. If this - * returns null, it implies there is no need to render window decorations. - * - * @return the current window title pane, or null - * @see #setTitlePane - */ - public BaseTitlePane getTitlePane() { - return titlePane; - } - - public JRootPane getRootPane() { - return root; - } - - public void propertyChange(PropertyChangeEvent e) { - super.propertyChange(e); - - String propertyName = e.getPropertyName(); - JRootPane root = (JRootPane) e.getSource(); - if ("windowDecorationStyle".equals(propertyName)) { - int style = DecorationHelper.getWindowDecorationStyle(root); - - // This is potentially more than needs to be done, - // but it rarely happens and makes the install/uninstall process - // simpler. BaseTitlePane also assumes it will be recreated if - // the decoration style changes. - uninstallClientDecorations(root); - if (style != NONE) { - installClientDecorations(root); - } - if (!JTattooUtilities.isMac() && (window instanceof Frame)) { - Frame frame = (Frame)window; - if (frame != null) { - GraphicsConfiguration gc = frame.getGraphicsConfiguration(); - Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(gc); - Rectangle screenBounds = gc.getBounds(); - int x = Math.max(0, screenInsets.left); - int y = Math.max(0, screenInsets.top); - int w = screenBounds.width - (screenInsets.left + screenInsets.right); - int h = screenBounds.height - (screenInsets.top + screenInsets.bottom); - // Keep taskbar visible - frame.setMaximizedBounds(new Rectangle(x, y, w, h)); - } - } - } else if ("ancestor".equals(propertyName)) { - uninstallWindowListeners(root); - if (DecorationHelper.getWindowDecorationStyle(root) != NONE) { - installWindowListeners(root, root.getParent()); - } - } - } - - private boolean isDynamicLayout() { - return AbstractLookAndFeel.getTheme().isDynamicLayout(); - } - -//------------------------------------------------------------------------------ - private static class BaseRootLayout implements LayoutManager2 { - - /** - * Returns the amount of space the layout would like to have. - * - * @param the Container for which this layout manager is being used - * @return a Dimension object containing the layout's preferred size - */ - public Dimension preferredLayoutSize(Container parent) { - Dimension cpd, mbd, tpd; - int cpWidth = 0; - int cpHeight = 0; - int mbWidth = 0; - int mbHeight = 0; - int tpWidth = 0; - Insets i = parent.getInsets(); - JRootPane root = (JRootPane) parent; - - if (root.getContentPane() != null) { - cpd = root.getContentPane().getPreferredSize(); - } else { - cpd = root.getSize(); - } - if (cpd != null) { - cpWidth = cpd.width; - cpHeight = cpd.height; - } - - if (root.getJMenuBar() != null) { - mbd = root.getJMenuBar().getPreferredSize(); - if (mbd != null) { - mbWidth = mbd.width; - mbHeight = mbd.height; - } - } - - if (DecorationHelper.getWindowDecorationStyle(root) != NONE && (root.getUI() instanceof BaseRootPaneUI)) { - BaseTitlePane titlePane = ((BaseRootPaneUI) root.getUI()).getTitlePane(); - if (titlePane != null) { - tpd = titlePane.getPreferredSize(); - if (tpd != null) { - tpWidth = tpd.width; - } - } - } - - return new Dimension(Math.max(Math.max(cpWidth, mbWidth), tpWidth) + i.left + i.right, cpHeight + mbHeight + tpWidth + i.top + i.bottom); - } - - /** - * Returns the minimum amount of space the layout needs. - * - * @param the Container for which this layout manager is being used - * @return a Dimension object containing the layout's minimum size - */ - public Dimension minimumLayoutSize(Container parent) { - return MINIMUM_SIZE; - } - - /** - * Returns the maximum amount of space the layout can use. - * - * @param the Container for which this layout manager is being used - * @return a Dimension object containing the layout's maximum size - */ - public Dimension maximumLayoutSize(Container target) { - return MAXIMUM_SIZE; - } - - /** - * Instructs the layout manager to perform the layout for the specified - * container. - * - * @param the Container for which this layout manager is being used - */ - public void layoutContainer(Container parent) { - JRootPane root = (JRootPane) parent; - Rectangle b = root.getBounds(); - Insets i = root.getInsets(); - int nextY = 0; - int w = b.width - i.right - i.left; - int h = b.height - i.top - i.bottom; - - if (root.getLayeredPane() != null) { - root.getLayeredPane().setBounds(i.left, i.top, w, h); - } - if (root.getGlassPane() != null) { - if (DecorationHelper.getWindowDecorationStyle(root) != NONE && (root.getUI() instanceof BaseRootPaneUI)) { - BaseTitlePane titlePane = ((BaseRootPaneUI) root.getUI()).getTitlePane(); - int titleHeight = 0; - if (titlePane != null) { - titleHeight = titlePane.getSize().height; - } - root.getGlassPane().setBounds(i.left, i.top + titleHeight, w, h - titleHeight); - } - else { - root.getGlassPane().setBounds(i.left, i.top, w, h); - } - } - // Note: This is laying out the children in the layeredPane, - // technically, these are not our children. - if (DecorationHelper.getWindowDecorationStyle(root) != NONE && (root.getUI() instanceof BaseRootPaneUI)) { - BaseTitlePane titlePane = ((BaseRootPaneUI) root.getUI()).getTitlePane(); - if (titlePane != null) { - Dimension tpd = titlePane.getPreferredSize(); - if (tpd != null) { - int tpHeight = tpd.height; - titlePane.setBounds(0, 0, w, tpHeight); - nextY += tpHeight; - } - } - } - if (root.getJMenuBar() != null) { - Dimension mbd = root.getJMenuBar().getPreferredSize(); - root.getJMenuBar().setBounds(0, nextY, w, mbd.height); - nextY += mbd.height; - } - if (root.getContentPane() != null) { - root.getContentPane().setBounds(0, nextY, w, h < nextY ? 0 : h - nextY); - } - } - - public void addLayoutComponent(String name, Component comp) { - } - - public void removeLayoutComponent(Component comp) { - } - - public void addLayoutComponent(Component comp, Object constraints) { - } - - public float getLayoutAlignmentX(Container target) { - return 0.0f; - } - - public float getLayoutAlignmentY(Container target) { - return 0.0f; - } - - public void invalidateLayout(Container target) { - } - } - /** - * Maps from positions to cursor type. Refer to calculateCorner and - * calculatePosition for details of this. - */ - private static final int[] cursorMapping = new int[]{ - Cursor.NW_RESIZE_CURSOR, Cursor.NW_RESIZE_CURSOR, Cursor.N_RESIZE_CURSOR, - Cursor.NE_RESIZE_CURSOR, Cursor.NE_RESIZE_CURSOR, - Cursor.NW_RESIZE_CURSOR, 0, 0, 0, Cursor.NE_RESIZE_CURSOR, - Cursor.W_RESIZE_CURSOR, 0, 0, 0, Cursor.E_RESIZE_CURSOR, - Cursor.SW_RESIZE_CURSOR, 0, 0, 0, Cursor.SE_RESIZE_CURSOR, - Cursor.SW_RESIZE_CURSOR, Cursor.SW_RESIZE_CURSOR, Cursor.S_RESIZE_CURSOR, - Cursor.SE_RESIZE_CURSOR, Cursor.SE_RESIZE_CURSOR - }; - -//------------------------------------------------------------------------------ - /** - * MouseInputHandler is responsible for handling resize/moving of - * the Window. It sets the cursor directly on the Window when then - * mouse moves over a hot spot. - */ - private class MouseInputHandler implements MouseInputListener { - - /** - * Set to true if the drag operation is moving the window. - */ - private boolean isMovingWindow; - /** - * Set to true if the drag operation is resizing the window. - */ - private boolean isResizingWindow; - /** - * Used to determine the corner the resize is occuring from. - */ - private int dragCursor; - /** - * X location the mouse went down on for a drag operation. - */ - private int dragOffsetX; - /** - * Y location the mouse went down on for a drag operation. - */ - private int dragOffsetY; - /** - * Width of the window when the drag started. - */ - private int dragWidth; - /** - * Height of the window when the drag started. - */ - private int dragHeight; - private Container savedContentPane = null; - private ResizingPanel resizingPanel = null; - - public void mousePressed(MouseEvent ev) { - if (ev.getSource() instanceof Window) { - JRootPane root = getRootPane(); - if (DecorationHelper.getWindowDecorationStyle(root) == NONE) { - return; - } - - Point dragWindowOffset = ev.getPoint(); - Window w = (Window) ev.getSource(); - if (w != null) { - w.toFront(); - } - - Point convertedDragWindowOffset = SwingUtilities.convertPoint(w, dragWindowOffset, getTitlePane()); - - Frame f = null; - Dialog d = null; - - if (w instanceof Frame) { - f = (Frame) w; - } else if (w instanceof Dialog) { - d = (Dialog) w; - } - - int frameState = (f != null) ? DecorationHelper.getExtendedState(f) : 0; - - if (getTitlePane() != null && getTitlePane().contains(convertedDragWindowOffset)) { - if ((f != null && ((frameState & BaseRootPaneUI.MAXIMIZED_BOTH) == 0) || (d != null)) - && dragWindowOffset.y >= BORDER_DRAG_THICKNESS - && dragWindowOffset.x >= BORDER_DRAG_THICKNESS - && dragWindowOffset.x < w.getWidth() - BORDER_DRAG_THICKNESS) { - isMovingWindow = true; - dragOffsetX = dragWindowOffset.x; - dragOffsetY = dragWindowOffset.y; - if (window instanceof JFrame) { - JFrame frame = (JFrame) window; - PropertyChangeListener[] pcl = frame.getPropertyChangeListeners(); - for (int i = 0; i < pcl.length; i++) { - pcl[i].propertyChange(new PropertyChangeEvent(window, "windowMoving", Boolean.FALSE, Boolean.FALSE)); - } - } - if (window instanceof JDialog) { - JDialog dialog = (JDialog) window; - PropertyChangeListener[] pcl = dialog.getPropertyChangeListeners(); - for (int i = 0; i < pcl.length; i++) { - pcl[i].propertyChange(new PropertyChangeEvent(window, "windowMoving", Boolean.FALSE, Boolean.FALSE)); - } - } - } - } else if (f != null - && f.isResizable() - && ((frameState & BaseRootPaneUI.MAXIMIZED_BOTH) == 0) - || (d != null && d.isResizable())) { - isResizingWindow = true; - if (!isDynamicLayout()) { - savedContentPane = getRootPane().getContentPane(); - GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); - BufferedImage bi = gc.createCompatibleImage(savedContentPane.getWidth(), savedContentPane.getHeight()); - savedContentPane.paint(bi.getGraphics()); - resizingPanel = new ResizingPanel(bi); - getRootPane().setContentPane(resizingPanel); - } - dragOffsetX = dragWindowOffset.x; - dragOffsetY = dragWindowOffset.y; - dragWidth = w.getWidth(); - dragHeight = w.getHeight(); - dragCursor = getCursor(calculateCorner(w, dragWindowOffset.x, dragWindowOffset.y)); - if (window instanceof JFrame) { - JFrame frame = (JFrame) window; - PropertyChangeListener[] pcl = frame.getPropertyChangeListeners(); - for (int i = 0; i < pcl.length; i++) { - pcl[i].propertyChange(new PropertyChangeEvent(window, "windowResizing", Boolean.FALSE, Boolean.FALSE)); - } - } - if (window instanceof JDialog) { - JDialog dialog = (JDialog) window; - PropertyChangeListener[] pcl = dialog.getPropertyChangeListeners(); - for (int i = 0; i < pcl.length; i++) { - pcl[i].propertyChange(new PropertyChangeEvent(window, "windowResizing", Boolean.FALSE, Boolean.FALSE)); - } - } - } - } - } - - public void mouseReleased(MouseEvent ev) { - if (ev.getSource() instanceof Window) { - Window w = (Window) ev.getSource(); - if (w != null) { - if (!isDynamicLayout() && isResizingWindow) { - getRootPane().setContentPane(savedContentPane); - getRootPane().updateUI(); - resizingPanel = null; - } else if (dragCursor != 0 && !window.isValid()) { - // Some Window systems validate as you resize, others won't, - // thus the check for validity before repainting. - w.validate(); - getRootPane().repaint(); - } - - if (window instanceof JFrame) { - JFrame frame = (JFrame) window; - PropertyChangeListener[] pcl = frame.getPropertyChangeListeners(); - for (int i = 0; i < pcl.length; i++) { - if (isMovingWindow) { - pcl[i].propertyChange(new PropertyChangeEvent(window, "windowMoved", Boolean.FALSE, Boolean.FALSE)); - } else { - pcl[i].propertyChange(new PropertyChangeEvent(window, "windowResized", Boolean.FALSE, Boolean.FALSE)); - } - } - } - if (window instanceof JDialog) { - JDialog dialog = (JDialog) window; - PropertyChangeListener[] pcl = dialog.getPropertyChangeListeners(); - for (int i = 0; i < pcl.length; i++) { - if (isMovingWindow) { - pcl[i].propertyChange(new PropertyChangeEvent(window, "windowMoved", Boolean.FALSE, Boolean.FALSE)); - } else { - pcl[i].propertyChange(new PropertyChangeEvent(window, "windowResized", Boolean.FALSE, Boolean.FALSE)); - } - } - } - } - isMovingWindow = false; - isResizingWindow = false; - dragCursor = 0; - } - } - - public void mouseMoved(MouseEvent ev) { - if (ev.getSource() instanceof Window) { - JRootPane root = getRootPane(); - if (DecorationHelper.getWindowDecorationStyle(root) == NONE) { - return; - } - - Window w = (Window) ev.getSource(); - Frame f = null; - Dialog d = null; - - if (w instanceof Frame) { - f = (Frame) w; - } else if (w instanceof Dialog) { - d = (Dialog) w; - } - - // Update the cursor - int cursor = getCursor(calculateCorner(w, ev.getX(), ev.getY())); - if (cursor != 0 && ((f != null && (f.isResizable() && (DecorationHelper.getExtendedState(f) & BaseRootPaneUI.MAXIMIZED_BOTH) == 0)) || (d != null && d.isResizable()))) { - w.setCursor(Cursor.getPredefinedCursor(cursor)); - } else { - w.setCursor(savedCursor); - } - } - } - - private void adjust(Rectangle bounds, Dimension min, int deltaX, int deltaY, int deltaWidth, int deltaHeight) { - bounds.x += deltaX; - bounds.y += deltaY; - bounds.width += deltaWidth; - bounds.height += deltaHeight; - if (min != null) { - if (bounds.width < min.width) { - int correction = min.width - bounds.width; - if (deltaX != 0) { - bounds.x -= correction; - } - bounds.width = min.width; - } - if (bounds.height < min.height) { - int correction = min.height - bounds.height; - if (deltaY != 0) { - bounds.y -= correction; - } - bounds.height = min.height; - } - } - } - - private int getMinScreenY() { - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsDevice devices[] = ge.getScreenDevices(); - GraphicsDevice gd = devices[0]; - GraphicsConfiguration gc = gd.getDefaultConfiguration(); - int minScreenY = gc.getBounds().y + Toolkit.getDefaultToolkit().getScreenInsets(gc).top; - if (devices.length > 1) { - for (int i = 1; i < devices.length; i++) { - gd = devices[i]; - gc = gd.getDefaultConfiguration(); - minScreenY = Math.min(minScreenY, gc.getBounds().y + Toolkit.getDefaultToolkit().getScreenInsets(gc).top); - } - } - return minScreenY; - } - - public void mouseDragged(MouseEvent ev) { - if (ev.getSource() instanceof Window) { - Window w = (Window) ev.getSource(); - int minScreenY = getMinScreenY(); - if (isMovingWindow) { - Point location = ev.getLocationOnScreen(); - location.x = location.x - dragOffsetX; - location.y = Math.max(minScreenY, location.y - dragOffsetY); - w.setLocation(location); - } else if (dragCursor != 0) { - Point pt = ev.getPoint(); - Rectangle bounds = w.getBounds(); - Rectangle startBounds = new Rectangle(bounds); - Dimension min = MINIMUM_SIZE; - switch (dragCursor) { - case Cursor.E_RESIZE_CURSOR: - adjust(bounds, min, 0, 0, pt.x + (dragWidth - dragOffsetX) - bounds.width, 0); - break; - case Cursor.S_RESIZE_CURSOR: - adjust(bounds, min, 0, 0, 0, pt.y + (dragHeight - dragOffsetY) - bounds.height); - break; - case Cursor.N_RESIZE_CURSOR: - adjust(bounds, min, 0, pt.y - dragOffsetY, 0, -(pt.y - dragOffsetY)); - break; - case Cursor.W_RESIZE_CURSOR: - adjust(bounds, min, pt.x - dragOffsetX, 0, -(pt.x - dragOffsetX), 0); - break; - case Cursor.NE_RESIZE_CURSOR: - adjust(bounds, min, 0, pt.y - dragOffsetY, pt.x + (dragWidth - dragOffsetX) - bounds.width, -(pt.y - dragOffsetY)); - break; - case Cursor.SE_RESIZE_CURSOR: - adjust(bounds, min, 0, 0, pt.x + (dragWidth - dragOffsetX) - bounds.width, pt.y + (dragHeight - dragOffsetY) - bounds.height); - break; - case Cursor.NW_RESIZE_CURSOR: - adjust(bounds, min, pt.x - dragOffsetX, pt.y - dragOffsetY, -(pt.x - dragOffsetX), -(pt.y - dragOffsetY)); - break; - case Cursor.SW_RESIZE_CURSOR: - adjust(bounds, min, pt.x - dragOffsetX, 0, -(pt.x - dragOffsetX), pt.y + (dragHeight - dragOffsetY) - bounds.height); - break; - default: - break; - } - if (!bounds.equals(startBounds)) { - if (bounds.y < minScreenY) { - int delta = minScreenY - bounds.y; - bounds.y = minScreenY; - bounds.height -= delta; - } - w.setBounds(bounds); - w.validate(); - //getRootPane().repaint(); - } - } - } - } - - public void mouseEntered(MouseEvent ev) { - mouseMoved(ev); - } - - public void mouseExited(MouseEvent ev) { - if (ev.getSource() instanceof Window) { - Window w = (Window) ev.getSource(); - w.setCursor(savedCursor); - } - } - - public void mouseClicked(MouseEvent ev) { - if (ev.getSource() instanceof Window) { - Window window = (Window) ev.getSource(); - if (!(window instanceof Frame)) { - return; - } - Frame frame = (Frame) window; - Point convertedPoint = SwingUtilities.convertPoint(window, ev.getPoint(), getTitlePane()); - int state = DecorationHelper.getExtendedState(frame); - if (getTitlePane() != null && getTitlePane().contains(convertedPoint)) { - if ((ev.getClickCount() % 2) == 0 && ((ev.getModifiers() & InputEvent.BUTTON1_MASK) != 0)) { - if (frame.isResizable()) { - if ((state & BaseRootPaneUI.MAXIMIZED_BOTH) != 0) { - titlePane.restore(); - } else { - titlePane.maximize(); - } - } - } - } - } - } - - /** - * Returns the corner that contains the point x, - * y, or -1 if the position doesn't match a corner. - */ - private int calculateCorner(Component c, int x, int y) { - int xPosition = calculatePosition(x, c.getWidth()); - int yPosition = calculatePosition(y, c.getHeight()); - - if (xPosition == -1 || yPosition == -1) { - return -1; - } - return yPosition * 5 + xPosition; - } - - /** - * Returns the Cursor to render for the specified corner. This returns - * 0 if the corner doesn't map to a valid Cursor - */ - private int getCursor(int corner) { - if (corner == -1) { - return 0; - } - return cursorMapping[corner]; - } - - /** - * Returns an integer indicating the position of spot - * in width. The return value will be: - * 0 if < BORDER_DRAG_THICKNESS - * 1 if < CORNER_DRAG_WIDTH - * 2 if >= CORNER_DRAG_WIDTH && < width - BORDER_DRAG_THICKNESS - * 3 if >= width - CORNER_DRAG_WIDTH - * 4 if >= width - BORDER_DRAG_THICKNESS - * 5 otherwise - */ - private int calculatePosition(int spot, int width) { - if (spot < BORDER_DRAG_THICKNESS) { - return 0; - } - if (spot < CORNER_DRAG_WIDTH) { - return 1; - } - if (spot >= (width - BORDER_DRAG_THICKNESS)) { - return 4; - } - if (spot >= (width - CORNER_DRAG_WIDTH)) { - return 3; - } - return 2; - } - } - -//------------------------------------------------------------------------------ - private static class ResizingPanel extends JPanel { - - private BufferedImage bi = null; - - public ResizingPanel(BufferedImage bi) { - super(); - this.bi = bi; - } - - public void paint(Graphics g) { - super.paint(g); - g.drawImage(bi, 0, 0, null); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseScrollBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseScrollBarUI.java deleted file mode 100644 index bd5c34688..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseScrollBarUI.java +++ /dev/null @@ -1,349 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.MouseEvent; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicScrollBarUI; - -/** - * @author Michael Hagen - */ -public class BaseScrollBarUI extends BasicScrollBarUI { - - protected int scrollBarWidth = 17; - protected int incrGap = 0; - protected int decrGap = 0; - protected boolean isRollover = false; - - public static ComponentUI createUI(JComponent c) { - return new BaseScrollBarUI(); - } - - protected void installDefaults() { - super.installDefaults(); - - scrollBarWidth = UIManager.getInt("ScrollBar.width"); - incrGap = UIManager.getInt("ScrollBar.incrementButtonGap"); - decrGap = UIManager.getInt("ScrollBar.decrementButtonGap"); - - // TODO this can be removed when incrGap/decrGap become protected - // handle scaling for sizeVarients for special case components. The - // key "JComponent.sizeVariant" scales for large/small/mini - // components are based on Apples LAF - String scaleKey = (String)scrollbar.getClientProperty("JComponent.sizeVariant"); - if (scaleKey != null){ - if ("large".equals(scaleKey)){ - scrollBarWidth *= 1.15; - incrGap *= 1.15; - decrGap *= 1.15; - } else if ("small".equals(scaleKey)){ - scrollBarWidth *= 0.857; - incrGap *= 0.857; - decrGap *= 0.857; - } else if ("mini".equals(scaleKey)){ - scrollBarWidth *= 0.714; - incrGap *= 0.714; - decrGap *= 0.714; - } - } - } - - protected JButton createDecreaseButton(int orientation) { - return new BaseScrollButton(orientation, scrollBarWidth); - } - - protected JButton createIncreaseButton(int orientation) { - return new BaseScrollButton(orientation, scrollBarWidth); - } - - public TrackListener createTrackListener() { - return new MyTrackListener(); - } - - public Dimension getPreferredSize(JComponent c) { - if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { - return new Dimension(scrollBarWidth, scrollBarWidth * 3 + 16); - } else { - return new Dimension(scrollBarWidth * 3 + 16, scrollBarWidth); - } - } - - protected Dimension getMinimumThumbSize() { - return new Dimension(scrollBarWidth, scrollBarWidth); - } - - protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) { - int w = c.getWidth(); - int h = c.getHeight(); - if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { - JTattooUtilities.fillVerGradient(g, AbstractLookAndFeel.getTheme().getTrackColors(), 0, 0, w, h); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getTrackColors(), 0, 0, w, h); - } - } - - protected Color[] getThumbColors() { - if (isRollover || isDragging) { - return AbstractLookAndFeel.getTheme().getRolloverColors(); - } else if (!JTattooUtilities.isActive(scrollbar)) { - return AbstractLookAndFeel.getTheme().getInActiveColors(); - } else { - return AbstractLookAndFeel.getTheme().getThumbColors(); - } - } - - protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { - if (!c.isEnabled()) { - return; - } - - g.translate(thumbBounds.x, thumbBounds.y); - - Color colors[] = getThumbColors(); - - Color frameColorHi = ColorHelper.brighter(colors[1], 20); - Color frameColorLo = ColorHelper.darker(colors[colors.length - 1], 10); - - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { - JTattooUtilities.fillVerGradient(g, colors, 1, 1, thumbBounds.width - 1, thumbBounds.height - 1); - JTattooUtilities.draw3DBorder(g, frameColorLo, ColorHelper.darker(frameColorLo, 15), 0, 0, thumbBounds.width, thumbBounds.height); - - g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f)); - g.setColor(frameColorHi); - g.drawLine(1, 1, thumbBounds.width - 2, 1); - g.drawLine(1, 1, 1, thumbBounds.height - 2); - - int dx = 5; - int dy = thumbBounds.height / 2 - 3; - int dw = thumbBounds.width - 11; - - Color c1 = Color.white; - Color c2 = Color.darkGray; - - for (int i = 0; i < 4; i++) { - g.setColor(c1); - g.drawLine(dx, dy, dx + dw, dy); - dy++; - g.setColor(c2); - g.drawLine(dx, dy, dx + dw, dy); - dy++; - } - g2D.setComposite(savedComposite); - } else { // HORIZONTAL - JTattooUtilities.fillHorGradient(g, colors, 1, 1, thumbBounds.width - 1, thumbBounds.height - 1); - JTattooUtilities.draw3DBorder(g, frameColorLo, ColorHelper.darker(frameColorLo, 10), 0, 0, thumbBounds.width, thumbBounds.height); - - g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f)); - g.setColor(frameColorHi); - g.drawLine(1, 1, thumbBounds.width - 2, 1); - g.drawLine(1, 1, 1, thumbBounds.height - 2); - - int dx = thumbBounds.width / 2 - 3; - int dy = 5; - int dh = thumbBounds.height - 11; - - Color c1 = Color.white; - Color c2 = Color.darkGray; - - for (int i = 0; i < 4; i++) { - g.setColor(c1); - g.drawLine(dx, dy, dx, dy + dh); - dx++; - g.setColor(c2); - g.drawLine(dx, dy, dx, dy + dh); - dx++; - } - } - g2D.setComposite(savedComposite); - - g.translate(-thumbBounds.x, -thumbBounds.y); - } - - protected void layoutVScrollbar(JScrollBar sb) { - if (AbstractLookAndFeel.getTheme().isLinuxStyleScrollBarOn()) { - Dimension sbSize = sb.getSize(); - Insets sbInsets = sb.getInsets(); - int sizeH = sbSize.height - sbInsets.top - sbInsets.bottom; - - /* - * Width and left edge of the buttons and thumb. - */ - int itemX = sbInsets.left; - int itemW = sbSize.width - (sbInsets.left + sbInsets.right); - int itemH = Math.min(itemW, sizeH / 2); - - /* Nominal locations of the buttons, assuming their preferred - * size will fit. - */ - int decrButtonY = sbSize.height - sbInsets.bottom - itemH - itemH + 1; - int incrButtonY = sbSize.height - sbInsets.bottom - itemH; - - /* Compute the height and origin of the thumb. The case - * where the thumb is at the bottom edge is handled specially - * to avoid numerical problems in computing thumbY. Enforce - * the thumbs min/max dimensions. If the thumb doesn't - * fit in the track (trackH) we'll hide it later. - */ - float trackH = sbSize.height - sbInsets.top - sbInsets.bottom - itemW - itemW + 1; - float min = sb.getMinimum(); - float max = sb.getMaximum(); - float extent = sb.getVisibleAmount(); - float range = max - min; - float value = sb.getValue(); - - int maxThumbH = getMaximumThumbSize().height; - int minThumbH = getMinimumThumbSize().height; - int thumbH = (range <= 0) ? maxThumbH : (int) (trackH * (extent / range)); - thumbH = Math.max(thumbH, minThumbH); - thumbH = Math.min(thumbH, maxThumbH); - - int thumbY = decrButtonY - thumbH; - if (value < (max - extent)) { - float thumbRange = trackH - thumbH; - thumbY = (int) (0.5f + (thumbRange * ((value - min) / (range - extent)))); - } - - /* If the thumb isn't going to fit, zero it's bounds. Otherwise - * make sure it fits between the buttons. Note that setting the - * thumbs bounds will cause a repaint. - */ - if (thumbH > trackH) { - setThumbBounds(0, 0, 0, 0); - } else { - setThumbBounds(itemX, thumbY, itemW, thumbH); - } - decrButton.setBounds(itemX, decrButtonY, itemW, itemH); - incrButton.setBounds(itemX, incrButtonY, itemW, itemH); - - /* Update the trackRect field. - */ - trackRect.setBounds(itemX, 0, itemW, (int)trackH); - - } else { - super.layoutVScrollbar(sb); - } - } - - protected void layoutHScrollbar(JScrollBar sb) { - if (AbstractLookAndFeel.getTheme().isLinuxStyleScrollBarOn()) { - Dimension sbSize = sb.getSize(); - Insets sbInsets = sb.getInsets(); - int sizeW = sbSize.width - sbInsets.left - sbInsets.right; - - /* - * Height and top edge of the buttons and thumb. - */ - int itemY = sbInsets.top; - int itemH = sbSize.height - (sbInsets.top + sbInsets.bottom);//Math.min(itemW, sizeH / 2); - int itemW = Math.min(itemH, sizeW / 2);//sbSize.width - (sbInsets.left + sbInsets.right); - - /* Nominal locations of the buttons, assuming their preferred - * size will fit. - */ - int decrButtonX = sbSize.width - sbInsets.right - itemW - itemW + 1; - int incrButtonX = sbSize.width - sbInsets.right - itemW; - - /* Compute the width and origin of the thumb. The case - * where the thumb is at the right edge is handled specially - * to avoid numerical problems in computing thumbX. Enforce - * the thumbs min/max dimensions. If the thumb doesn't - * fit in the track (trackW) we'll hide it later. - */ - float trackW = sbSize.width - sbInsets.left - sbInsets.right - itemH - itemH + 1; - float min = sb.getMinimum(); - float max = sb.getMaximum(); - float extent = sb.getVisibleAmount(); - float range = max - min; - float value = sb.getValue(); - - int maxThumbW = getMaximumThumbSize().width; - int minThumbW = getMinimumThumbSize().width; - int thumbW = (range <= 0) ? maxThumbW : (int) (trackW * (extent / range)); - thumbW = Math.max(thumbW, minThumbW); - thumbW = Math.min(thumbW, maxThumbW); - - int thumbX = decrButtonX - thumbW; - if (value < (max - extent)) { - float thumbRange = trackW - thumbW; - thumbX = (int) (0.5f + (thumbRange * ((value - min) / (range - extent)))); - } - - /* If the thumb isn't going to fit, zero it's bounds. Otherwise - * make sure it fits between the buttons. Note that setting the - * thumbs bounds will cause a repaint. - */ - if (thumbW > trackW) { - setThumbBounds(0, 0, 0, 0); - } else { - setThumbBounds(thumbX, itemY, thumbW, itemH); - } - decrButton.setBounds(decrButtonX, itemY, itemW, itemH); - incrButton.setBounds(incrButtonX, itemY, itemW, itemH); - - /* Update the trackRect field. - */ - trackRect.setBounds(0, itemY, (int)trackW, itemH); - - } else { - super.layoutHScrollbar(sb); - } - } - -//----------------------------------------------------------------------------- -// inner classes -//----------------------------------------------------------------------------- - protected class MyTrackListener extends TrackListener { - - public void mouseEntered(MouseEvent e) { - super.mouseEntered(e); - isRollover = true; - Rectangle r = getTrackBounds(); - scrollbar.repaint(r.x, r.y, r.width, r.height); - } - - public void mouseExited(MouseEvent e) { - super.mouseExited(e); - isRollover = false; - Rectangle r = getTrackBounds(); - scrollbar.repaint(r.x, r.y, r.width, r.height); - } - - public void mousePressed(MouseEvent e) { - super.mousePressed(e); - Rectangle r = getTrackBounds(); - scrollbar.repaint(r.x, r.y, r.width, r.height); - } - - public void mouseReleased(MouseEvent e) { - super.mouseReleased(e); - Rectangle r = getTrackBounds(); - scrollbar.repaint(r.x, r.y, r.width, r.height); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseScrollButton.java b/src/jtattoo/src/com/jtattoo/plaf/BaseScrollButton.java deleted file mode 100644 index 57d8300a8..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseScrollButton.java +++ /dev/null @@ -1,127 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import javax.swing.Icon; -import javax.swing.plaf.basic.BasicArrowButton; - -/** - * @author Michael Hagen - */ -public class BaseScrollButton extends BasicArrowButton { - - protected int buttonWidth = 24; - - public BaseScrollButton(int direction, int width) { - super(direction); - buttonWidth = width; - } - - public void paint(Graphics g) { - boolean isPressed = getModel().isPressed(); - boolean isRollover = getModel().isRollover(); - - int width = getWidth(); - int height = getHeight(); - - Color colors[]; - if (isPressed) { - colors = AbstractLookAndFeel.getTheme().getPressedColors(); - } else if (isRollover) { - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - } else { - colors = AbstractLookAndFeel.getTheme().getButtonColors(); - } - - boolean inverse = ColorHelper.getGrayValue(colors) < 128; - - Color frameColorHi = ColorHelper.brighter(colors[0], 20); - Color frameColorLo = ColorHelper.darker(colors[colors.length - 1], 20); - - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - if ((getDirection() == NORTH) || (getDirection() == SOUTH)) { - JTattooUtilities.fillVerGradient(g2D, colors, 0, 0, width, height); - } else { - JTattooUtilities.fillHorGradient(g2D, colors, 0, 0, width, height); - } - g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f)); - if (getDirection() == NORTH) { - Icon upArrow = inverse ? BaseIcons.getUpArrowInverseIcon() : BaseIcons.getUpArrowIcon(); - int x = (width / 2) - (upArrow.getIconWidth() / 2); - int y = (height / 2) - (upArrow.getIconHeight() / 2) - 1; - upArrow.paintIcon(this, g2D, x, y); - } else if (getDirection() == SOUTH) { - Icon downArrow = inverse ? BaseIcons.getDownArrowInverseIcon() : BaseIcons.getDownArrowIcon(); - int x = (width / 2) - (downArrow.getIconWidth() / 2); - int y = (height / 2) - (downArrow.getIconHeight() / 2); - downArrow.paintIcon(this, g2D, x, y); - } else if (getDirection() == WEST) { - Icon leftArrow = inverse ? BaseIcons.getLeftArrowInverseIcon() : BaseIcons.getLeftArrowIcon(); - int x = (width / 2) - (leftArrow.getIconWidth() / 2) - 1; - int y = (height / 2) - (leftArrow.getIconHeight() / 2); - leftArrow.paintIcon(this, g2D, x, y); - } else { - Icon rightArrow = inverse ? BaseIcons.getRightArrowInverseIcon() : BaseIcons.getRightArrowIcon(); - int x = (width / 2) - (rightArrow.getIconWidth() / 2); - int y = (height / 2) - (rightArrow.getIconHeight() / 2); - rightArrow.paintIcon(this, g2D, x, y); - } - JTattooUtilities.draw3DBorder(g2D, frameColorLo, ColorHelper.darker(frameColorLo, 10), 0, 0, width, height); - g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f)); - g2D.setColor(frameColorHi); - g2D.drawLine(1, 1, width - 2, 1); - g2D.drawLine(1, 1, 1, height - 2); - - g2D.setComposite(savedComposite); - } - - public Dimension getPreferredSize() { - if (getDirection() == NORTH) { - return new Dimension(buttonWidth, buttonWidth + 1); - } else if (getDirection() == SOUTH) { - return new Dimension(buttonWidth, buttonWidth + 1); - } else if (getDirection() == EAST) { - return new Dimension(buttonWidth + 1, buttonWidth); - } else if (getDirection() == WEST) { - return new Dimension(buttonWidth + 1, buttonWidth); - } else { - return new Dimension(0, 0); - } - } - - public Dimension getMinimumSize() { - return getPreferredSize(); - } - - public Dimension getMaximumSize() { - return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); - } - - public int getButtonWidth() { - return buttonWidth; - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseScrollPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseScrollPaneUI.java deleted file mode 100644 index b925d30b6..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseScrollPaneUI.java +++ /dev/null @@ -1,39 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicScrollPaneUI; - -/** - * @author Michael Hagen - */ -public class BaseScrollPaneUI extends BasicScrollPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new BaseScrollPaneUI(); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseSeparatorUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseSeparatorUI.java deleted file mode 100644 index 8a84237ff..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseSeparatorUI.java +++ /dev/null @@ -1,73 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.Dimension; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.JSeparator; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSeparatorUI; - -/** - * @author Michael Hagen - */ -public class BaseSeparatorUI extends BasicSeparatorUI { - - private static final Dimension size = new Dimension(2, 3); - - public static ComponentUI createUI(JComponent c) { - return new BaseSeparatorUI(); - } - - public void paint(Graphics g, JComponent c) { - boolean horizontal = true; - if (c instanceof JSeparator) { - horizontal = (((JSeparator) c).getOrientation() == JSeparator.HORIZONTAL); - } - if (horizontal) { - int w = c.getWidth(); - g.setColor(AbstractLookAndFeel.getBackgroundColor()); - g.drawLine(0, 0, w, 0); - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getBackgroundColor(), 30)); - g.drawLine(0, 1, w, 1); - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getBackgroundColor(), 50)); - g.drawLine(0, 2, w, 2); - } else { - int h = c.getHeight(); - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getBackgroundColor(), 30)); - g.drawLine(0, 0, 0, h); - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getBackgroundColor(), 50)); - g.drawLine(1, 0, 1, h); - } - } - - public Dimension getPreferredSize(JComponent c) { - return size; - } -} - - - - diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseSliderUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseSliderUI.java deleted file mode 100644 index f295a173f..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseSliderUI.java +++ /dev/null @@ -1,354 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.MouseEvent; -import javax.swing.*; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSliderUI; - -/** - * @author Michael Hagen - */ -public class BaseSliderUI extends BasicSliderUI { - - protected boolean isRollover = false; - - public BaseSliderUI(JSlider slider) { - super(slider); - } - - public static ComponentUI createUI(JComponent c) { - return new BaseSliderUI((JSlider) c); - } - - public TrackListener createTrackListener(JSlider slider) { - return new MyTrackListener(); - } - - public Icon getThumbHorIcon() { - if (UIManager.getLookAndFeel() instanceof AbstractLookAndFeel) { - return ((AbstractLookAndFeel) UIManager.getLookAndFeel()).getIconFactory().getThumbHorIcon(); - } - return null; - } - - public Icon getThumbHorIconRollover() { - if (UIManager.getLookAndFeel() instanceof AbstractLookAndFeel) { - return ((AbstractLookAndFeel) UIManager.getLookAndFeel()).getIconFactory().getThumbHorIconRollover(); - } - return null; - } - - public Icon getThumbVerIcon() { - if (UIManager.getLookAndFeel() instanceof AbstractLookAndFeel) { - return ((AbstractLookAndFeel) UIManager.getLookAndFeel()).getIconFactory().getThumbVerIcon(); - } - return null; - } - - public Icon getThumbVerIconRollover() { - if (UIManager.getLookAndFeel() instanceof AbstractLookAndFeel) { - return ((AbstractLookAndFeel) UIManager.getLookAndFeel()).getIconFactory().getThumbVerIconRollover(); - } - return null; - } - - protected int getTrackWidth() { - if (slider.getOrientation() == JSlider.HORIZONTAL) { - return (thumbRect.height - 9); - } else { - return (thumbRect.width - 9); - } - } - - protected Dimension getThumbSize() { - Dimension size = super.getThumbSize(); - if ((getThumbHorIcon() != null) && (getThumbVerIcon() != null)) { - if (slider.getOrientation() == JSlider.HORIZONTAL) { - size.width = getThumbHorIcon().getIconWidth(); - size.height = getThumbHorIcon().getIconHeight(); - } else { - size.width = getThumbVerIcon().getIconWidth(); - size.height = getThumbVerIcon().getIconHeight(); - } - } - return size; - } - - public void paint(Graphics g, JComponent c) { - paintBackground(g, c); - recalculateIfInsetsChanged(); - recalculateIfOrientationChanged(); - Rectangle clip = g.getClipBounds(); - if (slider.getPaintTrack() && clip.intersects(trackRect)) { - paintTrack(g); - } - if (slider.getPaintTicks() && clip.intersects(tickRect)) { - paintTicks(g); - } - if (slider.getPaintLabels() && clip.intersects(labelRect)) { - paintLabels(g); - } - if (slider.hasFocus() && clip.intersects(focusRect)) { - paintFocus(g); - } - if (clip.intersects(thumbRect)) { - paintThumb(g); - } - } - - public void paintBackground(Graphics g, JComponent c) { - if (c.isOpaque()) { - if (c.getBackground() instanceof ColorUIResource) { - g.setColor(AbstractLookAndFeel.getBackgroundColor()); - } else { - g.setColor(c.getBackground()); - } - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } - - public void paintTrack(Graphics g) { - boolean leftToRight = JTattooUtilities.isLeftToRight(slider); - - g.translate(trackRect.x, trackRect.y); - int overhang = 4; - int trackLeft = 0; - int trackTop = 0; - int trackRight; - int trackBottom; - - if (slider.getOrientation() == JSlider.HORIZONTAL) { - trackBottom = (trackRect.height - 1) - overhang; - trackTop = trackBottom - (getTrackWidth() - 1); - trackRight = trackRect.width - 1; - } else { - if (leftToRight) { - trackLeft = (trackRect.width - overhang) - getTrackWidth(); - trackRight = (trackRect.width - overhang) - 1; - } else { - trackLeft = overhang; - trackRight = overhang + getTrackWidth() - 1; - } - trackBottom = trackRect.height - 1; - } - - g.setColor(AbstractLookAndFeel.getFrameColor()); - g.drawRect(trackLeft, trackTop, (trackRight - trackLeft) - 1, (trackBottom - trackTop) - 1); - - int middleOfThumb; - int fillTop; - int fillLeft; - int fillBottom; - int fillRight; - - if (slider.getOrientation() == JSlider.HORIZONTAL) { - middleOfThumb = thumbRect.x + (thumbRect.width / 2); - middleOfThumb -= trackRect.x; - fillTop = trackTop + 1; - fillBottom = trackBottom - 2; - - if (!drawInverted()) { - fillLeft = trackLeft + 1; - fillRight = middleOfThumb; - } else { - fillLeft = middleOfThumb; - fillRight = trackRight - 2; - } - Color colors[]; - if (!JTattooUtilities.isActive(slider)) { - colors = AbstractLookAndFeel.getTheme().getInActiveColors(); - } else { - if (slider.isEnabled()) { - colors = AbstractLookAndFeel.getTheme().getSliderColors(); - } else { - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } - } - JTattooUtilities.fillHorGradient(g, colors, fillLeft + 2, fillTop + 2, fillRight - fillLeft - 2, fillBottom - fillTop - 2); - Color cHi = ColorHelper.darker(colors[colors.length - 1], 5); - Color cLo = ColorHelper.darker(colors[colors.length - 1], 10); - JTattooUtilities.draw3DBorder(g, cHi, cLo, fillLeft + 1, fillTop + 1, fillRight - fillLeft - 1, fillBottom - fillTop - 1); - } else { - middleOfThumb = thumbRect.y + (thumbRect.height / 2); - middleOfThumb -= trackRect.y; - fillLeft = trackLeft + 1; - fillRight = trackRight - 2; - - if (!drawInverted()) { - fillTop = middleOfThumb; - fillBottom = trackBottom - 2; - } else { - fillTop = trackTop + 1; - fillBottom = middleOfThumb; - } - Color colors[]; - if (!JTattooUtilities.isActive(slider)) { - colors = AbstractLookAndFeel.getTheme().getInActiveColors(); - } else { - if (slider.isEnabled()) { - colors = AbstractLookAndFeel.getTheme().getSliderColors(); - } else { - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } - } - JTattooUtilities.fillVerGradient(g, colors, fillLeft + 2, fillTop + 2, fillRight - fillLeft - 2, fillBottom - fillTop - 2); - Color cHi = ColorHelper.darker(colors[colors.length - 1], 5); - Color cLo = ColorHelper.darker(colors[colors.length - 1], 10); - JTattooUtilities.draw3DBorder(g, cHi, cLo, fillLeft + 1, fillTop + 1, fillRight - fillLeft - 1, fillBottom - fillTop - 1); - } - g.translate(-trackRect.x, -trackRect.y); - } - - public void paintTicks(Graphics g) { - boolean leftToRight = JTattooUtilities.isLeftToRight(slider); - Rectangle tickBounds = tickRect; - g.setColor(slider.getForeground()); - if (slider.getOrientation() == JSlider.HORIZONTAL) { - g.translate(0, tickBounds.y); - - int value = slider.getMinimum(); - int xPos; - - if (slider.getMinorTickSpacing() > 0) { - while (value <= slider.getMaximum()) { - xPos = xPositionForValue(value); - paintMinorTickForHorizSlider(g, tickBounds, xPos); - value += slider.getMinorTickSpacing(); - } - } - - if (slider.getMajorTickSpacing() > 0) { - value = slider.getMinimum(); - while (value <= slider.getMaximum()) { - xPos = xPositionForValue(value); - paintMajorTickForHorizSlider(g, tickBounds, xPos); - value += slider.getMajorTickSpacing(); - } - } - - g.translate(0, -tickBounds.y); - } else { - g.translate(tickBounds.x, 0); - - int value = slider.getMinimum(); - int yPos; - - if (slider.getMinorTickSpacing() > 0) { - int offset = 0; - if (!leftToRight) { - offset = tickBounds.width - tickBounds.width / 2; - g.translate(offset, 0); - } - - while (value <= slider.getMaximum()) { - yPos = yPositionForValue(value); - paintMinorTickForVertSlider(g, tickBounds, yPos); - value += slider.getMinorTickSpacing(); - } - if (!leftToRight) { - g.translate(-offset, 0); - } - } - - if (slider.getMajorTickSpacing() > 0) { - value = slider.getMinimum(); - if (!leftToRight) { - g.translate(2, 0); - } - - while (value <= slider.getMaximum()) { - yPos = yPositionForValue(value); - paintMajorTickForVertSlider(g, tickBounds, yPos); - value += slider.getMajorTickSpacing(); - } - - if (!leftToRight) { - g.translate(-2, 0); - } - } - g.translate(-tickBounds.x, 0); - } - } - - public void paintThumb(Graphics g) { - Icon icon; - if (slider.getOrientation() == JSlider.HORIZONTAL) { - if (isRollover && slider.isEnabled()) { - icon = getThumbHorIconRollover(); - } else { - icon = getThumbHorIcon(); - } - } else { - if (isRollover && slider.isEnabled()) { - icon = getThumbVerIconRollover(); - } else { - icon = getThumbVerIcon(); - } - } - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - if (!slider.isEnabled()) { - g.setColor(AbstractLookAndFeel.getBackgroundColor()); - g.fillRect(thumbRect.x + 1, thumbRect.y + 1, thumbRect.width - 2, thumbRect.height - 2); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - } - icon.paintIcon(null, g, thumbRect.x, thumbRect.y); - g2D.setComposite(savedComposite); - } - - protected class MyTrackListener extends TrackListener { - - public void mouseEntered(MouseEvent e) { - super.mouseEntered(e); - if (slider.isEnabled()) { - isRollover = thumbRect.contains(e.getPoint()); - slider.repaint(); - } - } - - public void mouseMoved(MouseEvent e) { - super.mouseMoved(e); - if (slider.isEnabled()) { - boolean rollover = thumbRect.contains(e.getPoint()); - if (rollover != isRollover) { - isRollover = rollover; - slider.repaint(); - } - } - } - - public void mouseExited(MouseEvent e) { - super.mouseExited(e); - if (slider.isEnabled()) { - isRollover = false; - slider.repaint(); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseSpinnerUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseSpinnerUI.java deleted file mode 100644 index e628aeaf0..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseSpinnerUI.java +++ /dev/null @@ -1,265 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSpinnerUI; - -/** - * - * @author Michael Hagen - */ -public class BaseSpinnerUI extends BasicSpinnerUI { - /** - * Used by the default LayoutManager class - SpinnerLayout for - * missing (null) editor/nextButton/previousButton children. - */ - private static final Dimension zeroSize = new Dimension(0, 0); - - private MyLayoutManager myLayoutManager = null; - - /** - * Returns a new instance of BaseSpinnerUI. SpinnerListUI - * delegates are allocated one per JSpinner. - * - * @param c the JSpinner (not used) - * @see ComponentUI#createUI - * @return a new BasicSpinnerUI object - */ - public static ComponentUI createUI(JComponent c) { - return new BaseSpinnerUI(); - } - - /** - * Create a LayoutManager that manages the editor, - * nextButton, and previousButton - * children of the JSpinner. These three children must be - * added with a constraint that identifies their role: - * "Editor", "Next", and "Previous". The default layout manager - * can handle the absence of any of these children. - * - * @return a LayoutManager for the editor, next button, and previous button. - * @see #createNextButton - * @see #createPreviousButton - * @see #createEditor - */ - protected LayoutManager createLayout() { - if (myLayoutManager == null) { - myLayoutManager = new MyLayoutManager(); - } - return myLayoutManager; - } - - protected Component createNextButton() { - JButton button = new SpinButton(SwingConstants.NORTH); - if (JTattooUtilities.isLeftToRight(spinner)) { - Border border = BorderFactory.createMatteBorder(0, 1, 1, 0, AbstractLookAndFeel.getFrameColor()); - button.setBorder(border); - } else { - Border border = BorderFactory.createMatteBorder(0, 0, 1, 1, AbstractLookAndFeel.getFrameColor()); - button.setBorder(border); - } - installNextButtonListeners(button); - return button; - } - - protected Component createPreviousButton() { - JButton button = new SpinButton(SwingConstants.SOUTH); - if (JTattooUtilities.isLeftToRight(spinner)) { - Border border = BorderFactory.createMatteBorder(0, 1, 0, 0, AbstractLookAndFeel.getFrameColor()); - button.setBorder(border); - } else { - Border border = BorderFactory.createMatteBorder(0, 0, 0, 1, AbstractLookAndFeel.getFrameColor()); - button.setBorder(border); - } - installPreviousButtonListeners(button); - return button; - } - - -//----------------------------------------------------------------------------------------- -// inner classes -//----------------------------------------------------------------------------------------- - public static class SpinButton extends NoFocusButton { - - private static Dimension minSize = new Dimension(14, 12); - private int direction = SwingConstants.NORTH; - - public SpinButton(int aDirection) { - super(); - setInheritsPopupMenu(true); - direction = aDirection; - } - - public Dimension getPreferredSize() { - Dimension size = super.getPreferredSize(); - size.width = Math.max(size.width, minSize.width); - size.height = Math.max(size.height, minSize.height); - return size; - } - - public void paint(Graphics g) { - Color colors[]; - ButtonModel model = getModel(); - if (isEnabled()) { - if (model.isPressed() && model.isArmed()) { - colors = AbstractLookAndFeel.getTheme().getPressedColors(); - } else { - if (model.isRollover()) - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - else if (JTattooUtilities.isFrameActive(this)) - colors = AbstractLookAndFeel.getTheme().getButtonColors(); - else - colors = AbstractLookAndFeel.getTheme().getInActiveColors(); - } - } else { - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } - JTattooUtilities.fillHorGradient(g, colors, 0, 0, getWidth(), getHeight()); - paintBorder(g); - g.setColor(getForeground()); - int w = 4; - int h = 3; - int x = (getWidth() - w) / 2; - int y = (getHeight() - h) / 2; - if (direction == SwingConstants.NORTH) { - for (int i = 0; i < h; i++) { - g.drawLine(x + (h - i) - 1, y + i, x + w - (h - i) + 1, y + i); - } - } else { - for (int i = 0; i < h; i++) { - g.drawLine(x + i, y + i, x + w - i, y + i); - } - } - } - - } - -//---------------------------------------------------------------------------------------------- -// inner classes -//---------------------------------------------------------------------------------------------- - private static class MyLayoutManager implements LayoutManager { - - private Component nextButton = null; - private Component previousButton = null; - private Component editor = null; - - public void addLayoutComponent(String name, Component c) { - if ("Next".equals(name)) { - nextButton = c; - } else if ("Previous".equals(name)) { - previousButton = c; - } else if ("Editor".equals(name)) { - editor = c; - } - } - - public void removeLayoutComponent(Component c) { - if (c == nextButton) { - nextButton = null; - } else if (c == previousButton) { - previousButton = null; - } else if (c == editor) { - editor = null; - } - } - - private Dimension preferredSize(Component c) { - return (c == null) ? zeroSize : c.getPreferredSize(); - } - - public Dimension preferredLayoutSize(Container parent) { - Dimension nextD = preferredSize(nextButton); - Dimension previousD = preferredSize(previousButton); - Dimension editorD = preferredSize(editor); - - // Force the editors height to be a multiple of 2 - editorD.height = ((editorD.height + 1) / 2) * 2; - - Dimension size = new Dimension(editorD.width, editorD.height); - size.width += Math.max(nextD.width, previousD.width); - Insets insets = parent.getInsets(); - size.width += insets.left + insets.right; - size.height += insets.top + insets.bottom + 4; - return size; - } - - public Dimension minimumLayoutSize(Container parent) { - return preferredLayoutSize(parent); - } - - private void setBounds(Component c, int x, int y, int width, int height) { - if (c != null) { - c.setBounds(x, y, width, height); - } - } - - public void layoutContainer(Container parent) { - int width = parent.getWidth(); - int height = parent.getHeight(); - - Insets insets = parent.getInsets(); - Dimension nextD = preferredSize(nextButton); - Dimension previousD = preferredSize(previousButton); - int buttonsWidth = Math.max(nextD.width, previousD.width); - int editorHeight = height - (insets.top + insets.bottom); - - // The arrowButtonInsets value is used instead of the JSpinner's - // insets if not null. Defining this to be (0, 0, 0, 0) causes the - // buttons to be aligned with the outer edge of the spinner's - // border, and leaving it as "null" places the buttons completely - // inside the spinner's border. - Insets buttonInsets = UIManager.getInsets("Spinner.arrowButtonInsets"); - if (buttonInsets == null) { - buttonInsets = insets; - } - - // Deal with the spinner's componentOrientation property. - int editorX, editorWidth, buttonsX; - if (parent.getComponentOrientation().isLeftToRight()) { - editorX = insets.left; - editorWidth = width - insets.left - buttonsWidth - buttonInsets.right; - buttonsX = width - buttonsWidth - buttonInsets.right; - } else { - buttonsX = buttonInsets.left; - editorX = buttonsX + buttonsWidth; - editorWidth = width - buttonInsets.left - buttonsWidth - insets.right; - } - - int nextY = buttonInsets.top; - int nextHeight = (height / 2) + (height % 2) - nextY; - int previousY = buttonInsets.top + nextHeight; - int previousHeight = height - previousY - buttonInsets.bottom; - - setBounds(editor, editorX, insets.top, editorWidth, editorHeight); - setBounds(nextButton, buttonsX, nextY, buttonsWidth, nextHeight); - setBounds(previousButton, buttonsX, previousY, buttonsWidth, previousHeight); - } - - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseSplitPaneDivider.java b/src/jtattoo/src/com/jtattoo/plaf/BaseSplitPaneDivider.java deleted file mode 100644 index 330da32c0..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseSplitPaneDivider.java +++ /dev/null @@ -1,328 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.basic.BasicSplitPaneDivider; -import javax.swing.plaf.basic.BasicSplitPaneUI; - -/** - * @author Michael Hagen - */ -public class BaseSplitPaneDivider extends BasicSplitPaneDivider { - - protected boolean centerOneTouchButtons = true; - protected boolean flatMode = false; - - public BaseSplitPaneDivider(BasicSplitPaneUI ui) { - super(ui); - if (JTattooUtilities.getJavaVersion() >= 1.4) { - if (UIManager.get("SplitPane.centerOneTouchButtons") != null) { - centerOneTouchButtons = UIManager.getBoolean("SplitPane.centerOneTouchButtons"); - } - } - setLayout(new MyDividerLayout()); - Object flatModeProperty = ui.getSplitPane().getClientProperty("flatMode"); - if (flatModeProperty instanceof Boolean) { - flatMode = ((Boolean)flatModeProperty).booleanValue(); - } - } - - public boolean isFlatMode() { - return flatMode; - } - - public void setFlatMode(boolean flatMode) { - this.flatMode = flatMode; - } - - public Border getBorder() { - return null; - } - - public Color getRolloverColor() { - return ColorHelper.darker(AbstractLookAndFeel.getTheme().getRolloverColor(), 16); - } - - public void paint(Graphics g) { - if (!isFlatMode()) { - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - int width = getSize().width; - int height = getSize().height; - int dx = 0; - int dy = 0; - if ((width % 2) == 1) { - dx = 1; - } - if ((height % 2) == 1) { - dy = 1; - } - Color color = AbstractLookAndFeel.getBackgroundColor(); - Color cHi = ColorHelper.brighter(color, 25); - Color cLo = ColorHelper.darker(color, 5); - Color colors[] = ColorHelper.createColorArr(cHi, cLo, 10); - - if (UIManager.getLookAndFeel() instanceof AbstractLookAndFeel) { - AbstractLookAndFeel laf = (AbstractLookAndFeel) UIManager.getLookAndFeel(); - if (orientation == JSplitPane.HORIZONTAL_SPLIT) { - JTattooUtilities.fillVerGradient(g, colors, 0, 0, width, height); - Icon horBumps = laf.getIconFactory().getSplitterHorBumpIcon(); - if ((horBumps != null) && (width > horBumps.getIconWidth())) { - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f); - g2D.setComposite(alpha); - - if (splitPane.isOneTouchExpandable() && centerOneTouchButtons) { - int centerY = height / 2; - int x = (width - horBumps.getIconWidth()) / 2 + dx; - int y = centerY - horBumps.getIconHeight() - 40; - horBumps.paintIcon(this, g, x, y); - y = centerY + 40; - horBumps.paintIcon(this, g, x, y); - } else { - int x = (width - horBumps.getIconWidth()) / 2 + dx; - int y = (height - horBumps.getIconHeight()) / 2; - horBumps.paintIcon(this, g, x, y); - } - } - } else { - JTattooUtilities.fillHorGradient(g, colors, 0, 0, width, height); - Icon verBumps = laf.getIconFactory().getSplitterVerBumpIcon(); - if ((verBumps != null) && (height > verBumps.getIconHeight())) { - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f); - g2D.setComposite(alpha); - if (splitPane.isOneTouchExpandable() && centerOneTouchButtons) { - int centerX = width / 2; - int x = centerX - verBumps.getIconWidth() - 40; - int y = (height - verBumps.getIconHeight()) / 2 + dy; - verBumps.paintIcon(this, g, x, y); - x = centerX + 40; - verBumps.paintIcon(this, g, x, y); - } else { - int x = (width - verBumps.getIconWidth()) / 2; - int y = (height - verBumps.getIconHeight()) / 2 + dy; - verBumps.paintIcon(this, g, x, y); - } - } - } - } - g2D.setComposite(savedComposite); - } - paintComponents(g); - } - - protected JButton createLeftOneTouchButton() { - JButton b = new JButton() { - - public void paint(Graphics g) { - Color color = getBackground(); - int w = getSize().width; - int h = getSize().height; - if (getModel().isPressed() && getModel().isArmed()) { - g.setColor(ColorHelper.darker(color, 40)); - g.fillRect(0, 0, w, h); - } else if (getModel().isRollover()) { - g.setColor(getRolloverColor()); - g.fillRect(0, 0, w, h); - } - Icon icon; - if (UIManager.getLookAndFeel() instanceof AbstractLookAndFeel) { - AbstractLookAndFeel lf = (AbstractLookAndFeel) UIManager.getLookAndFeel(); - if (orientation == JSplitPane.HORIZONTAL_SPLIT) { - icon = lf.getIconFactory().getSplitterLeftArrowIcon(); - } else { - icon = lf.getIconFactory().getSplitterUpArrowIcon(); - } - int x = (w - icon.getIconWidth()) / 2; - int y = (h - icon.getIconHeight()) / 2; - icon.paintIcon(this, g, x, y); - } - if (getModel().isArmed()) { - if (getModel().isPressed()) { - JTattooUtilities.draw3DBorder(g, ColorHelper.darker(color, 30), ColorHelper.brighter(color, 80), 0, 0, w, h); - } else { - JTattooUtilities.draw3DBorder(g, ColorHelper.brighter(color, 80), ColorHelper.darker(color, 30), 0, 0, w, h); - } - } - } - - public boolean isFocusTraversable() { - return false; - } - }; - b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - b.setFocusPainted(false); - b.setBorderPainted(false); - b.setContentAreaFilled(false); - b.setRolloverEnabled(true); - return b; - } - - protected JButton createRightOneTouchButton() { - JButton b = new JButton() { - - public void paint(Graphics g) { - Color color = getBackground(); - int w = getSize().width; - int h = getSize().height; - if (getModel().isPressed() && getModel().isArmed()) { - g.setColor(ColorHelper.darker(color, 40)); - g.fillRect(0, 0, w, h); - } else if (getModel().isRollover()) { - g.setColor(getRolloverColor()); - g.fillRect(0, 0, w, h); - } - Icon icon; - if (UIManager.getLookAndFeel() instanceof AbstractLookAndFeel) { - AbstractLookAndFeel laf = (AbstractLookAndFeel) UIManager.getLookAndFeel(); - if (orientation == JSplitPane.HORIZONTAL_SPLIT) { - icon = laf.getIconFactory().getSplitterRightArrowIcon(); - } else { - icon = laf.getIconFactory().getSplitterDownArrowIcon(); - } - int x = (w - icon.getIconWidth()) / 2; - int y = (h - icon.getIconHeight()) / 2; - icon.paintIcon(this, g, x, y); - } - if (getModel().isArmed()) { - if (getModel().isPressed()) { - JTattooUtilities.draw3DBorder(g, ColorHelper.darker(color, 30), ColorHelper.brighter(color, 80), 0, 0, w, h); - } else { - JTattooUtilities.draw3DBorder(g, ColorHelper.brighter(color, 80), ColorHelper.darker(color, 30), 0, 0, w, h); - } - } - } - - public boolean isFocusTraversable() { - return false; - } - }; - b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - b.setFocusPainted(false); - b.setBorderPainted(false); - b.setContentAreaFilled(false); - b.setRolloverEnabled(true); - return b; - } - - /** - * Used to layout a BasicSplitPaneDivider. - * Layout for the divider - * involves appropriately moving the left/right buttons around. - *

        - */ - protected class MyDividerLayout implements LayoutManager { - - public void layoutContainer(Container c) { - if (leftButton != null && rightButton != null && c == BaseSplitPaneDivider.this) { - if (splitPane.isOneTouchExpandable()) { - Insets insets = getInsets(); - int blockSize = 11; - int xOffs = 0; - int yOffs = 0; - if (centerOneTouchButtons) { - blockSize = 13; - xOffs = ((getWidth() - (2 * blockSize)) / 2) - blockSize; - yOffs = ((getHeight() - (2 * blockSize)) / 2) - blockSize; - } - - if (orientation == JSplitPane.VERTICAL_SPLIT) { - int extraX = (insets != null) ? insets.left : 0; - if (insets != null) { - blockSize -= (insets.top + insets.bottom); - blockSize = Math.max(blockSize, 0); - } - int y = (c.getSize().height - blockSize) / 2; - leftButton.setBounds(xOffs + extraX, y, blockSize * 2, blockSize); - rightButton.setBounds(xOffs + extraX + blockSize * 2 + 1, y, blockSize * 2, blockSize); - } else { - int extraY = (insets != null) ? insets.top : 0; - if (insets != null) { - blockSize -= (insets.left + insets.right); - blockSize = Math.max(blockSize, 0); - } - int x = (c.getSize().width - blockSize) / 2; - leftButton.setBounds(x, yOffs + extraY, blockSize, blockSize * 2); - rightButton.setBounds(x, yOffs + extraY + blockSize * 2 + 1, blockSize, blockSize * 2); - } - } else { - leftButton.setBounds(-5, -5, 1, 1); - rightButton.setBounds(-5, -5, 1, 1); - } - } - } - - public Dimension minimumLayoutSize(Container c) { - // NOTE: This isn't really used, refer to - // BasicSplitPaneDivider.getPreferredSize for the reason. - // I leave it in hopes of having this used at some point. - if (c != BaseSplitPaneDivider.this || splitPane == null) { - return new Dimension(0, 0); - } - Dimension buttonMinSize = null; - - if (splitPane.isOneTouchExpandable() && leftButton != null) { - buttonMinSize = leftButton.getMinimumSize(); - } - - Insets insets = getInsets(); - int width = getDividerSize(); - int height = width; - - if (orientation == JSplitPane.VERTICAL_SPLIT) { - if (buttonMinSize != null) { - int size = buttonMinSize.height; - if (insets != null) { - size += insets.top + insets.bottom; - } - height = Math.max(height, size); - } - width = 1; - } else { - if (buttonMinSize != null) { - int size = buttonMinSize.width; - if (insets != null) { - size += insets.left + insets.right; - } - width = Math.max(width, size); - } - height = 1; - } - return new Dimension(width, height); - } - - public Dimension preferredLayoutSize(Container c) { - return minimumLayoutSize(c); - } - - public void removeLayoutComponent(Component c) { - } - - public void addLayoutComponent(String string, Component c) { - } - - } // end class MyDividerLayout -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseSplitPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseSplitPaneUI.java deleted file mode 100644 index 69ffc0702..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseSplitPaneUI.java +++ /dev/null @@ -1,62 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.beans.PropertyChangeListener; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSplitPaneDivider; -import javax.swing.plaf.basic.BasicSplitPaneUI; - -/** - * @author Michael Hagen - */ -public class BaseSplitPaneUI extends BasicSplitPaneUI { - - protected PropertyChangeListener myPropertyChangeListener = null; - - public static ComponentUI createUI(JComponent c) { - return new BaseSplitPaneUI(); - } - - protected void installListeners() { - super.installListeners(); - myPropertyChangeListener = evt -> { - if ("flatMode".equals(evt.getPropertyName()) && evt.getNewValue() instanceof Boolean) { - ((BaseSplitPaneDivider)getDivider()).setFlatMode(((Boolean)evt.getNewValue()).booleanValue()); - } - }; - getSplitPane().addPropertyChangeListener(myPropertyChangeListener); - } - - protected void uninstallListeners() { - super.uninstallListeners(); - getSplitPane().removePropertyChangeListener(myPropertyChangeListener); - } - - - public BasicSplitPaneDivider createDefaultDivider() { - return new BaseSplitPaneDivider(this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseTabbedPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseTabbedPaneUI.java deleted file mode 100644 index 9b682f5bc..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseTabbedPaneUI.java +++ /dev/null @@ -1,3968 +0,0 @@ -/* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.*; -import java.awt.geom.*; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.ArrayList; -import java.util.HashMap; -import javax.swing.*; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.plaf.*; -import javax.swing.plaf.basic.BasicGraphicsUtils; -import javax.swing.plaf.basic.BasicHTML; -import javax.swing.text.View; - -/** - * This class is a modified copy of the javax.swing.plaf.basic.BasicTabbedPaneUI - * - * A Basic L&F implementation of TabbedPaneUI. - * - * @version 1.87 06/08/99 - * @author Amy Fowler - * @author Philip Milne - * @author Steve Wilson - * @author Tom Santos - * @author Dave Moore - * @author Michael Hagen - */ -public class BaseTabbedPaneUI extends TabbedPaneUI implements SwingConstants { - - protected static final Insets NULL_BORDER_INSETS = new Insets(0, 0, 0, 0); - protected static final int GAP = 5; - - // Instance variables initialized at installation - protected JTabbedPane tabPane; - protected Color tabAreaBackground; - protected Color selectedColor; - protected int textIconGap; - protected int tabRunOverlay; - protected Insets tabInsets; - protected Insets selectedTabPadInsets; - protected Insets tabAreaInsets; - protected Insets contentBorderInsets; -// Transient variables (recalculated each time TabbedPane is layed out) - protected int tabRuns[] = new int[10]; - protected int runCount = 0; - protected int selectedRun = -1; - protected Rectangle rects[] = new Rectangle[0]; - protected int maxTabHeight; - protected int maxTabWidth; -// Listeners - protected ChangeListener tabChangeListener; - protected ComponentListener tabComponentListener; - protected PropertyChangeListener propertyChangeListener; - protected MouseListener mouseListener; - protected MouseMotionListener mouseMotionListener; - protected FocusListener focusListener; - // PENDING(api): See comment for ContainerHandler - private ContainerListener containerListener; -// Private instance data - private Insets currentPadInsets = new Insets(0, 0, 0, 0); - private Insets currentTabAreaInsets = new Insets(0, 0, 0, 0); - private Component visibleComponent; - // PENDING(api): See comment for ContainerHandler - private ArrayList htmlViews; - private HashMap mnemonicToIndexMap; - /** - * InputMap used for mnemonics. Only non-null if the JTabbedPane has - * mnemonics associated with it. Lazily created in initMnemonics. - */ - private InputMap mnemonicInputMap; - // For use when tabLayoutPolicy = SCROLL_TAB_LAYOUT - private ScrollableTabSupport tabScroller; - private TabContainer tabContainer; - /** - * A rectangle used for general layout calculations in order - * to avoid constructing many new Rectangles on the fly. - */ - protected transient Rectangle calcRect = new Rectangle(0, 0, 0, 0); - /** - * Number of tabs. When the count differs, the mnemonics are updated. - */ - // PENDING: This wouldn't be necessary if JTabbedPane had a better - // way of notifying listeners when the count changed. - private int tabCount; - protected int oldRolloverIndex = -1; - protected int rolloverIndex = -1; - protected boolean roundedTabs = true; - protected boolean simpleButtonBorder = false; - - public static ComponentUI createUI(JComponent c) { - return new BaseTabbedPaneUI(); - } - - // UI Installation/De-installation - public void installUI(JComponent c) { - this.tabPane = (JTabbedPane) c; - c.setLayout(createLayoutManager()); - installComponents(); - installDefaults(); - installListeners(); - installKeyboardActions(); - } - - public void uninstallUI(JComponent c) { - uninstallKeyboardActions(); - uninstallListeners(); - uninstallDefaults(); - uninstallComponents(); - c.setLayout(null); - - this.tabPane = null; - } - - /** - * Invoked by installUI to create - * a layout manager object to manage - * the JTabbedPane. - * - * @return a layout manager object - * - * @see TabbedPaneLayout - * @see javax.swing.JTabbedPane#getTabLayoutPolicy - */ - protected LayoutManager createLayoutManager() { - if (JTattooUtilities.getJavaVersion() >= 1.4) { - if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) { - return new TabbedPaneScrollLayout(); - } - } - /* WRAP_TAB_LAYOUT */ - return new TabbedPaneLayout(); - } - - /* In an attempt to preserve backward compatibility for programs - * which have extended BaseTabbedPaneUI to do their own layout, the - * UI uses the installed layoutManager (and not tabLayoutPolicy) to - * determine if scrollTabLayout is enabled. - */ - protected boolean scrollableTabLayoutEnabled() { - return (tabPane.getLayout() instanceof TabbedPaneScrollLayout); - } - - /** - * Creates and installs any required subcomponents for the JTabbedPane. - * Invoked by installUI. - * - * @since 1.4 - */ - protected void installComponents() { - if (scrollableTabLayoutEnabled()) { - if (tabScroller == null) { - tabScroller = new ScrollableTabSupport(tabPane.getTabPlacement()); - tabPane.add(tabScroller.viewport); - tabPane.add(tabScroller.scrollForwardButton); - tabPane.add(tabScroller.scrollBackwardButton); - tabPane.add(tabScroller.popupMenuButton); - tabScroller.tabPanel.setBackground(tabAreaBackground); - } - } - installTabContainer(); - } - - private Component getTabComponentAt(int index) { - if (JTattooUtilities.getJavaVersion() >= 1.6) { - return tabPane.getTabComponentAt(index); - } - return null; - } - - private void installTabContainer() { - if (JTattooUtilities.getJavaVersion() >= 1.6) { - for (int i = 0; i < tabPane.getTabCount(); i++) { - Component tabComponent = getTabComponentAt(i); - if (tabComponent != null) { - if (tabContainer == null) { - tabContainer = new TabContainer(); - } - tabContainer.add(tabComponent); - addMyPropertyChangeListeners(tabComponent); - } - } - if (tabContainer == null) { - return; - } - if (scrollableTabLayoutEnabled()) { - tabScroller.tabPanel.add(tabContainer); - } else { - tabPane.add(tabContainer); - } - } - } - - /** - * Removes any installed subcomponents from the JTabbedPane. - * Invoked by uninstallUI. - * - * @since 1.4 - */ - protected void uninstallComponents() { - uninstallTabContainer(); - if (scrollableTabLayoutEnabled()) { - tabPane.remove(tabScroller.viewport); - tabPane.remove(tabScroller.scrollForwardButton); - tabPane.remove(tabScroller.scrollBackwardButton); - tabPane.remove(tabScroller.popupMenuButton); - tabScroller = null; - } - } - - private void addMyPropertyChangeListeners(Component component) { - component.addPropertyChangeListener(new MyTabComponentListener()); - if (component instanceof Container) { - Container container = (Container) component; - for (int i = 0; i < container.getComponentCount(); i++) { - Component c = container.getComponent(i); - addMyPropertyChangeListeners(c); - } - } - } - - private void removeMyPropertyChangeListeners(Component component) { - PropertyChangeListener[] listeners = component.getPropertyChangeListeners(); - for (int i = 0; i < listeners.length; i++) { - if (listeners[i] instanceof MyTabComponentListener) { - component.removePropertyChangeListener(listeners[i]); - } - } - if (component instanceof Container) { - Container container = (Container) component; - for (int i = 0; i < container.getComponentCount(); i++) { - Component c = container.getComponent(i); - removeMyPropertyChangeListeners(c); - } - } - } - - private void uninstallTabContainer() { - if (JTattooUtilities.getJavaVersion() >= 1.6) { - if (tabContainer == null) { - return; - } - // Remove all the tabComponents, making sure not to notify the tabbedpane. - tabContainer.notifyTabbedPane = false; - for (int i = 0; i < tabContainer.getComponentCount(); i++) { - Component c = tabContainer.getComponent(i); - removeMyPropertyChangeListeners(c); - } - tabContainer.removeAll(); - if (scrollableTabLayoutEnabled()) { - tabScroller.tabPanel.remove(tabContainer); - } else { - tabPane.remove(tabContainer); - } - tabContainer = null; - } - } - - protected void installDefaults() { - LookAndFeel.installColorsAndFont(tabPane, "TabbedPane.background", "TabbedPane.foreground", "TabbedPane.font"); - tabAreaBackground = UIManager.getColor("TabbedPane.tabAreaBackground"); - selectedColor = UIManager.getColor("TabbedPane.selected"); - textIconGap = UIManager.getInt("TabbedPane.textIconGap"); - tabInsets = UIManager.getInsets("TabbedPane.tabInsets"); - selectedTabPadInsets = UIManager.getInsets("TabbedPane.selectedTabPadInsets"); - tabAreaInsets = UIManager.getInsets("TabbedPane.tabAreaInsets"); - contentBorderInsets = UIManager.getInsets("TabbedPane.contentBorderInsets"); - tabRunOverlay = UIManager.getInt("TabbedPane.tabRunOverlay"); - tabPane.setBorder(UIManager.getBorder("TabbedPane.boder")); - } - - protected void uninstallDefaults() { - tabInsets = null; - selectedTabPadInsets = null; - tabAreaInsets = null; - contentBorderInsets = null; - } - - protected void installListeners() { - if ((propertyChangeListener = createPropertyChangeListener()) != null) { - tabPane.addPropertyChangeListener(propertyChangeListener); - } - if ((tabChangeListener = createChangeListener()) != null) { - tabPane.addChangeListener(tabChangeListener); - } - if ((tabComponentListener = createComponentListener()) != null) { - tabPane.addComponentListener(tabComponentListener); - } - if ((mouseListener = createMouseListener()) != null) { - if (scrollableTabLayoutEnabled()) { - tabScroller.tabPanel.addMouseListener(mouseListener); - - } else { // WRAP_TAB_LAYOUT - tabPane.addMouseListener(mouseListener); - } - } - if ((mouseMotionListener = createMouseMotionListener()) != null) { - if (scrollableTabLayoutEnabled()) { - tabScroller.tabPanel.addMouseMotionListener(mouseMotionListener); - - } else { // WRAP_TAB_LAYOUT - tabPane.addMouseMotionListener(mouseMotionListener); - } - } - if ((focusListener = createFocusListener()) != null) { - tabPane.addFocusListener(focusListener); - } - // PENDING(api) : See comment for ContainerHandler - containerListener = new ContainerHandler(); - tabPane.addContainerListener(containerListener); - if (tabPane.getTabCount() > 0) { - htmlViews = createHTMLViewList(); - } - } - - protected void uninstallListeners() { - if (mouseListener != null) { - if (scrollableTabLayoutEnabled()) { - // SCROLL_TAB_LAYOUT - tabScroller.tabPanel.removeMouseListener(mouseListener); - } else { - // WRAP_TAB_LAYOUT - tabPane.removeMouseListener(mouseListener); - } - mouseListener = null; - } - if (mouseMotionListener != null) { - if (scrollableTabLayoutEnabled()) { - // SCROLL_TAB_LAYOUT - tabScroller.tabPanel.removeMouseMotionListener(mouseMotionListener); - } else { - // WRAP_TAB_LAYOUT - tabPane.removeMouseMotionListener(mouseMotionListener); - } - mouseMotionListener = null; - } - if (focusListener != null) { - tabPane.removeFocusListener(focusListener); - focusListener = null; - } - - // PENDING(api): See comment for ContainerHandler - if (containerListener != null) { - tabPane.removeContainerListener(containerListener); - containerListener = null; - if (htmlViews != null) { - htmlViews.clear(); - htmlViews = null; - } - } - if (tabChangeListener != null) { - tabPane.removeChangeListener(tabChangeListener); - tabChangeListener = null; - } - if (tabComponentListener != null) { - tabPane.removeComponentListener(tabComponentListener); - tabChangeListener = null; - } - if (propertyChangeListener != null) { - tabPane.removePropertyChangeListener(propertyChangeListener); - propertyChangeListener = null; - } - } - - protected MouseListener createMouseListener() { - return new MouseHandler(); - } - - protected MouseMotionListener createMouseMotionListener() { - return new MouseMotionHandler(); - } - - protected FocusListener createFocusListener() { - return new FocusHandler(); - } - - protected ChangeListener createChangeListener() { - return new TabSelectionHandler(); - } - - protected ComponentListener createComponentListener() { - return new TabComponentHandler(); - } - - protected PropertyChangeListener createPropertyChangeListener() { - return new PropertyChangeHandler(); - } - - protected void installKeyboardActions() { - InputMap km = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); - SwingUtilities.replaceUIInputMap(tabPane, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, km); - km = getInputMap(JComponent.WHEN_FOCUSED); - SwingUtilities.replaceUIInputMap(tabPane, JComponent.WHEN_FOCUSED, km); - ActionMap am = getActionMap(); - SwingUtilities.replaceUIActionMap(tabPane, am); - if (scrollableTabLayoutEnabled()) { - tabScroller.scrollForwardButton.setAction(am.get("scrollTabsForwardAction")); - tabScroller.scrollBackwardButton.setAction(am.get("scrollTabsBackwardAction")); - tabScroller.popupMenuButton.setAction(am.get("scrollTabsPopupMenuAction")); - } - } - - InputMap getInputMap(int condition) { - if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) { - return (InputMap) UIManager.get("TabbedPane.ancestorInputMap"); - } else if (condition == JComponent.WHEN_FOCUSED) { - return (InputMap) UIManager.get("TabbedPane.focusInputMap"); - } - return null; - } - - ActionMap getActionMap() { - ActionMap map = (ActionMap) UIManager.get("TabbedPane.actionMap"); - - if (map == null) { - map = createActionMap(); - if (map != null) { - UIManager.getLookAndFeelDefaults().put("TabbedPane.actionMap", map); - } - } - return map; - } - - ActionMap createActionMap() { - ActionMap map = new ActionMapUIResource(); - map.put("navigateNext", new NextAction()); - map.put("navigatePrevious", new PreviousAction()); - map.put("navigateRight", new RightAction()); - map.put("navigateLeft", new LeftAction()); - map.put("navigateUp", new UpAction()); - map.put("navigateDown", new DownAction()); - map.put("navigatePageUp", new PageUpAction()); - map.put("navigatePageDown", new PageDownAction()); - map.put("requestFocus", new RequestFocusAction()); - map.put("requestFocusForVisibleComponent", new RequestFocusForVisibleAction()); - map.put("setSelectedIndex", new SetSelectedIndexAction()); - map.put("scrollTabsForwardAction", new ScrollTabsForwardAction()); - map.put("scrollTabsBackwardAction", new ScrollTabsBackwardAction()); - map.put("scrollTabsPopupMenuAction", new ScrollTabsPopupMenuAction()); - return map; - } - - protected void uninstallKeyboardActions() { - SwingUtilities.replaceUIActionMap(tabPane, null); - SwingUtilities.replaceUIInputMap(tabPane, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null); - SwingUtilities.replaceUIInputMap(tabPane, JComponent.WHEN_FOCUSED, null); - } - - /** - * Reloads the mnemonics. This should be invoked when a memonic changes, - * when the title of a mnemonic changes, or when tabs are added/removed. - */ - private void updateMnemonics() { - if (JTattooUtilities.getJavaVersion() >= 1.4) { - resetMnemonics(); - for (int counter = tabPane.getTabCount() - 1; counter >= 0; counter--) { - int mnemonic = tabPane.getMnemonicAt(counter); - if (mnemonic > 0) { - addMnemonic(counter, mnemonic); - } - } - } - } - - /** - * Resets the mnemonics bindings to an empty state. - */ - private void resetMnemonics() { - if (mnemonicToIndexMap != null) { - mnemonicToIndexMap.clear(); - mnemonicInputMap.clear(); - } - } - - /** - * Adds the specified mnemonic at the specified index. - */ - private void addMnemonic(int index, int mnemonic) { - if (mnemonicToIndexMap == null) { - initMnemonics(); - } - mnemonicInputMap.put(KeyStroke.getKeyStroke(mnemonic, Event.ALT_MASK), "setSelectedIndex"); - mnemonicToIndexMap.put(new Integer(mnemonic), new Integer(index)); - } - - /** - * Installs the state needed for mnemonics. - */ - private void initMnemonics() { - mnemonicToIndexMap = new HashMap(); - mnemonicInputMap = new InputMapUIResource(); - mnemonicInputMap.setParent(SwingUtilities.getUIInputMap(tabPane, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)); - SwingUtilities.replaceUIInputMap(tabPane, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, mnemonicInputMap); - } - - protected boolean isContentOpaque() { - if (!tabPane.isOpaque()) { - if (UIManager.get("TabbedPane.contentOpaque") != null) { - return UIManager.getBoolean("TabbedPane.contentOpaque"); - } - } - return true; - } - - protected boolean isTabOpaque() { - if (!tabPane.isOpaque()) { - if (UIManager.get("TabbedPane.tabsOpaque") != null) { - return UIManager.getBoolean("TabbedPane.tabsOpaque"); - } - } - return true; - } - - protected boolean hasInnerBorder() { - return false; - } - - // colors - protected Color[] getTabColors(int tabIndex, boolean isSelected, boolean isRollover) { - Color colorArr[] = AbstractLookAndFeel.getTheme().getTabColors(); - if ((tabIndex >= 0) && (tabIndex < tabPane.getTabCount())) { - boolean isEnabled = tabPane.isEnabledAt(tabIndex); - Color backColor = tabPane.getBackgroundAt(tabIndex); - if ((backColor instanceof UIResource)) { - if (isSelected) { - colorArr = AbstractLookAndFeel.getTheme().getSelectedColors(); - } else if (isRollover && isEnabled) { - colorArr = AbstractLookAndFeel.getTheme().getRolloverColors(); - } else { - if (JTattooUtilities.isFrameActive(tabPane)) { - colorArr = AbstractLookAndFeel.getTheme().getTabColors(); - } else { - colorArr = AbstractLookAndFeel.getTheme().getInActiveColors(); - } - } - } else { - if (isSelected) { - colorArr = ColorHelper.createColorArr(ColorHelper.brighter(backColor, 60), backColor, 20); - } else if (isRollover && isEnabled) { - colorArr = ColorHelper.createColorArr(ColorHelper.brighter(backColor, 80), ColorHelper.brighter(backColor, 20), 20); - } else { - colorArr = ColorHelper.createColorArr(ColorHelper.brighter(backColor, 40), ColorHelper.darker(backColor, 10), 20); - } - } - } - return colorArr; - } - - protected Color getLoBorderColor(int tabIndex) { - return AbstractLookAndFeel.getControlDarkShadow(); - } - - protected Color getHiBorderColor(int tabIndex) { - Color backColor = tabPane.getBackgroundAt(tabIndex); - if (tabIndex == tabPane.getSelectedIndex()) { - if (backColor instanceof UIResource) { - return AbstractLookAndFeel.getControlHighlight(); - } else { - return ColorHelper.brighter(backColor, 40); - } - } - if (tabIndex >= 0 && tabIndex <= tabCount) { - if (!isTabOpaque() || backColor instanceof UIResource) { - return AbstractLookAndFeel.getControlHighlight(); - } else { - return ColorHelper.brighter(backColor, 40); - } - } - return AbstractLookAndFeel.getControlHighlight(); - } - - protected Color[] getContentBorderColors(int tabPlacement) { - int sepHeight = tabAreaInsets.bottom; - Color selColors[] = AbstractLookAndFeel.getTheme().getSelectedColors(); - Color loColor = selColors[selColors.length - 1]; - Color darkLoColor = ColorHelper.darker(loColor, 20); - return ColorHelper.createColorArr(loColor, darkLoColor, sepHeight); - } - - protected Color getContentBorderColor() { - return AbstractLookAndFeel.getFrameColor(); - } - - protected Color getGapColor(int tabIndex) { - if (isTabOpaque() || tabIndex == tabPane.getSelectedIndex()) { - if ((tabIndex >= 0) && (tabIndex < tabCount)) { - Color tabColors[] = getTabColors(tabIndex, tabIndex == tabPane.getSelectedIndex(), false); - if (tabColors != null && tabColors.length > 0) { - return tabColors[tabColors.length - 1]; - } else { - return tabPane.getBackgroundAt(tabIndex); - } - } - } - if (!tabPane.isOpaque()) { - Container parent = tabPane.getParent(); - while (parent != null) { - if (parent.isOpaque()) { - return parent.getBackground(); - } - parent = parent.getParent(); - } - } - return tabAreaBackground; - } - - // Geometry - public Dimension getPreferredSize(JComponent c) { - // Default to LayoutManager's preferredLayoutSize - return null; - } - - public Dimension getMinimumSize(JComponent c) { - // Default to LayoutManager's minimumLayoutSize - return null; - } - - public Dimension getMaximumSize(JComponent c) { - // Default to LayoutManager's maximumLayoutSize - return null; - } - - // UI Rendering - public void paint(Graphics g, JComponent c) { - int tc = tabPane.getTabCount(); - if (tabCount != tc) { - tabCount = tc; - updateMnemonics(); - } - - int selectedIndex = tabPane.getSelectedIndex(); - int tabPlacement = tabPane.getTabPlacement(); - - ensureCurrentLayout(); - - // Paint content border - paintContentBorder(g, tabPlacement, selectedIndex, 0, 0, c.getWidth(), c.getHeight()); - - // Paint tab area - // If scrollable tabs are enabled, the tab area will be - // painted by the scrollable tab panel instead. - // - if (!scrollableTabLayoutEnabled()) { - // WRAP_TAB_LAYOUT - paintTabArea(g, tabPlacement, selectedIndex); - } - } - - /** - * Paints the tabs in the tab area. - * Invoked by paint(). - * The graphics parameter must be a valid Graphics - * object. Tab placement may be either: - * JTabbedPane.TOP, JTabbedPane.BOTTOM, - * JTabbedPane.LEFT, or JTabbedPane.RIGHT. - * The selected index must be a valid tabbed pane tab index (0 to - * tab count - 1, inclusive) or -1 if no tab is currently selected. - * The handling of invalid parameters is unspecified. - * - * @param g the graphics object to use for rendering - * @param tabPlacement the placement for the tabs within the JTabbedPane - * @param selectedIndex the tab index of the selected component - * - * @since 1.4 - */ - protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex) { - int tc = tabPane.getTabCount(); - Rectangle iconRect = new Rectangle(), textRect = new Rectangle(); - Shape savedClip = g.getClip(); - Rectangle clipRect = g.getClipBounds(); - // Dirty trick to fix clipping problem - if (scrollableTabLayoutEnabled() && tabScroller.scrollBackwardButton.isVisible()) { - if ((tabPlacement == TOP) || (tabPlacement == BOTTOM)) { - g.setClip(clipRect.x, clipRect.y, clipRect.width + 1, clipRect.height); - } else { - g.setClip(clipRect.x, clipRect.y, clipRect.width, clipRect.height + 1); - } - } - // Paint tabRuns of tabs from back to front - for (int i = runCount - 1; i >= 0; i--) { - int start = tabRuns[i]; - int next = tabRuns[(i == runCount - 1) ? 0 : i + 1]; - int end = (next != 0 ? next - 1 : tc - 1); - for (int j = start; j <= end; j++) { - if (rects[j].intersects(clipRect)) { - paintTab(g, tabPlacement, rects, j, iconRect, textRect); - } - } - } - - // Paint selected tab if its in the front run - // since it may overlap other tabs - if ((selectedIndex >= 0) && (selectedIndex < rects.length) && getRunForTab(tc, selectedIndex) == 0) { - if (rects[selectedIndex].intersects(clipRect)) { - paintTab(g, tabPlacement, rects, selectedIndex, iconRect, textRect); - } - } - g.setClip(savedClip); - } - - protected Font getTabFont(boolean isSelected) { - return tabPane.getFont(); - } - - protected void paintTab(Graphics g, int tabPlacement, Rectangle[] rects, int tabIndex, Rectangle iconRect, Rectangle textRect) { - Rectangle tabRect = rects[tabIndex]; - int selectedIndex = tabPane.getSelectedIndex(); - boolean isSelected = selectedIndex == tabIndex; - Graphics2D g2D = null; - Polygon cropShape = null; - Shape savedClip = null; - int cropx = 0; - int cropy = 0; - - if (scrollableTabLayoutEnabled()) { - if (g instanceof Graphics2D) { - g2D = (Graphics2D) g; - - // Render visual for cropped tab edge... - Rectangle viewRect = tabScroller.viewport.getViewRect(); - int cropline; - switch (tabPlacement) { - case LEFT: - case RIGHT: - cropline = viewRect.y + viewRect.height; - if ((tabRect.y < cropline) && (tabRect.y + tabRect.height > cropline)) { - cropShape = createCroppedTabClip(tabPlacement, tabRect, cropline); - cropx = tabRect.x; - cropy = cropline - 1; - } - break; - case TOP: - case BOTTOM: - default: - cropline = viewRect.x + viewRect.width; - if ((tabRect.x < cropline) && (tabRect.x + tabRect.width > cropline)) { - cropShape = createCroppedTabClip(tabPlacement, tabRect, cropline); - cropx = cropline - 1; - cropy = tabRect.y; - } - } - if (cropShape != null) { - savedClip = g2D.getClip(); - g2D.clip(cropShape); - } - } - } - - paintTabBackground(g, tabPlacement, tabIndex, tabRect.x, tabRect.y, tabRect.width, tabRect.height, isSelected); - paintTabBorder(g, tabPlacement, tabIndex, tabRect.x, tabRect.y, tabRect.width, tabRect.height, isSelected); - - try { - boolean doPaintContent = getTabComponentAt(tabIndex) == null; - if (doPaintContent) { - String title = tabPane.getTitleAt(tabIndex); - Font font = getTabFont(isSelected); - FontMetrics metrics = g.getFontMetrics(font); - Icon icon = getIconForTab(tabIndex); - - layoutLabel(tabPlacement, metrics, tabIndex, title, icon, tabRect, iconRect, textRect, isSelected); - paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected); - paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected); - } - paintFocusIndicator(g, tabPlacement, rects, tabIndex, iconRect, textRect, isSelected); - } catch (Exception ex) { - } - - if (cropShape != null) { - paintCroppedTabEdge(g, tabPlacement, tabIndex, cropx, cropy); - if (g2D != null && savedClip != null) { - g2D.setClip(savedClip); - } - } - } - /* This method will create and return a polygon shape for the given tab rectangle - * which has been cropped at the specified cropline with a torn edge visual. - * e.g. A "File" tab which has cropped been cropped just after the "i": - * ------------- - * | ..... | - * | . | - * | ... . | - * | . . | - * | . . | - * | . . | - * -------------- - * - * The x, y arrays below define the pattern used to create a "torn" edge - * segment which is repeated to fill the edge of the tab. - * For tabs placed on TOP and BOTTOM, this righthand torn edge is created by - * line segments which are defined by coordinates obtained by - * subtracting xCropLen[i] from (tab.x + tab.width) and adding yCroplen[i] - * to (tab.y). - * For tabs placed on LEFT or RIGHT, the bottom torn edge is created by - * subtracting xCropLen[i] from (tab.y + tab.height) and adding yCropLen[i] - * to (tab.x). - */ - private int xCropLen[] = {1, 1, 0, 0, 1, 1, 2, 2}; - private int yCropLen[] = {0, 3, 3, 6, 6, 9, 9, 12}; - private static final int CROP_SEGMENT = 12; - - private Polygon createCroppedTabClip(int tabPlacement, Rectangle tabRect, int cropline) { - int rlen; - int start; - int end; - int ostart; - - switch (tabPlacement) { - case LEFT: - case RIGHT: - rlen = tabRect.width; - start = tabRect.x; - end = tabRect.x + tabRect.width; - ostart = tabRect.y; - break; - case TOP: - case BOTTOM: - default: - rlen = tabRect.height; - start = tabRect.y; - end = tabRect.y + tabRect.height; - ostart = tabRect.x; - } - int rcnt = rlen / CROP_SEGMENT; - if (rlen % CROP_SEGMENT > 0) { - rcnt++; - } - int npts = 2 + (rcnt * 8); - int xp[] = new int[npts]; - int yp[] = new int[npts]; - int pcnt = 0; - - xp[pcnt] = ostart; - yp[pcnt++] = end; - xp[pcnt] = ostart; - yp[pcnt++] = start; - for (int i = 0; i < rcnt; i++) { - for (int j = 0; j < xCropLen.length; j++) { - xp[pcnt] = cropline - xCropLen[j]; - yp[pcnt] = start + (i * CROP_SEGMENT) + yCropLen[j]; - if (yp[pcnt] >= end) { - yp[pcnt] = end; - pcnt++; - break; - } - pcnt++; - } - } - if (tabPlacement == JTabbedPane.TOP || tabPlacement == JTabbedPane.BOTTOM) { - return new Polygon(xp, yp, pcnt); - } else { - // LEFT or RIGHT - return new Polygon(yp, xp, pcnt); - } - } - - /* If tabLayoutPolicy == SCROLL_TAB_LAYOUT, this method will paint an edge - * indicating the tab is cropped in the viewport display - */ - private void paintCroppedTabEdge(Graphics g, int tabPlacement, int tabIndex, int x, int y) { - g.setColor(Color.gray); - switch (tabPlacement) { - case LEFT: - case RIGHT: - int xx = x; - while (xx <= x + rects[tabIndex].width) { - for (int i = 0; i < xCropLen.length; i += 2) { - g.drawLine(xx + yCropLen[i], y - xCropLen[i], xx + yCropLen[i + 1] - 1, y - xCropLen[i + 1]); - } - xx += CROP_SEGMENT; - } - break; - case TOP: - case BOTTOM: - default: - int yy = y; - while (yy <= y + rects[tabIndex].height) { - for (int i = 0; i < xCropLen.length; i += 2) { - g.drawLine(x - xCropLen[i], yy + yCropLen[i], x - xCropLen[i + 1], yy + yCropLen[i + 1] - 1); - } - yy += CROP_SEGMENT; - } - } - } - - protected void layoutLabel(int tabPlacement, FontMetrics metrics, - int tabIndex, String title, Icon icon, Rectangle tabRect, - Rectangle iconRect, Rectangle textRect, boolean isSelected) { - textRect.x = textRect.y = iconRect.x = iconRect.y = 0; - View v = getTextViewForTab(tabIndex); - if (v != null) { - tabPane.putClientProperty("html", v); - } - - SwingUtilities.layoutCompoundLabel( tabPane, - metrics, title, icon, - SwingUtilities.CENTER, - SwingUtilities.CENTER, - SwingUtilities.CENTER, - SwingUtilities.TRAILING, - tabRect, - iconRect, - textRect, - textIconGap); - - tabPane.putClientProperty("html", null); - - int xNudge = getTabLabelShiftX(tabPlacement, tabIndex, isSelected); - int yNudge = getTabLabelShiftY(tabPlacement, tabIndex, isSelected); - iconRect.x += xNudge; - iconRect.y += yNudge; - textRect.x += xNudge; - textRect.y += yNudge; - } - - protected int getTabLabelShiftX(int tabPlacement, int tabIndex, boolean isSelected) { - return 0; - } - - protected int getTabLabelShiftY(int tabPlacement, int tabIndex, boolean isSelected) { - if (!isSelected) { - if (tabPlacement == TOP) { - return 1; - } else if (tabPlacement == BOTTOM) { - return -1; - } - } - return 0; - } - - protected void paintIcon(Graphics g, int tabPlacement, int tabIndex, Icon icon, Rectangle iconRect, boolean isSelected) { - if (icon != null) { - icon.paintIcon(tabPane, g, iconRect.x, iconRect.y); - } - } - - protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected) { - g.setFont(font); - View v = getTextViewForTab(tabIndex); - if (v != null) { - // html - Graphics2D g2D = (Graphics2D) g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - v.paint(g, textRect); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } else { - // plain text - int mnemIndex = -1; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); - } - - if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) { - if (isSelected) { - Color backColor = tabPane.getBackgroundAt(tabIndex); - if (backColor instanceof UIResource) { - g.setColor(AbstractLookAndFeel.getTabSelectionForegroundColor()); - } else { - g.setColor(tabPane.getForegroundAt(tabIndex)); - } - } else { - g.setColor(tabPane.getForegroundAt(tabIndex)); - } - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); - - } else { // tab disabled - g.setColor(tabPane.getBackgroundAt(tabIndex).brighter()); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); - g.setColor(tabPane.getBackgroundAt(tabIndex).darker()); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x - 1, textRect.y + metrics.getAscent() - 1); - } - } - } - - protected void paintFocusIndicator(Graphics g, int tabPlacement, Rectangle[] rects, int tabIndex, Rectangle iconRect, Rectangle textRect, boolean isSelected) { - if (tabPane.isRequestFocusEnabled() && tabPane.hasFocus() && isSelected && tabIndex >= 0 && textRect.width > 8) { - g.setColor(AbstractLookAndFeel.getTheme().getFocusColor()); - BasicGraphicsUtils.drawDashedRect(g, textRect.x - 4, textRect.y + 1, textRect.width + 8, textRect.height); - } - } - - /** - * this function draws the border around each tab - * note that this function does now draw the background of the tab. - * that is done elsewhere - */ - protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) { - int x2 = x + (w); - int y2 = y + (h); - switch (tabPlacement) { - case LEFT: - paintLeftTabBorder(tabIndex, g, x, y, x2, y2, isSelected); - break; - case RIGHT: - paintRightTabBorder(tabIndex, g, x, y, x2, y2, isSelected); - break; - case BOTTOM: - if (roundedTabs) { - paintRoundedBottomTabBorder(tabIndex, g, x, y, x2, y2 - 1, isSelected); - } else { - paintBottomTabBorder(tabIndex, g, x, y, x2, y2 - 1, isSelected); - } - break; - case TOP: - default: - if (roundedTabs) { - paintRoundedTopTabBorder(tabIndex, g, x, y, x2, y2, isSelected); - } else { - paintTopTabBorder(tabIndex, g, x, y, x2, y2, isSelected); - } - } - } - - protected void paintRoundedTopTabBorder(int tabIndex, Graphics g, int x1, int y1, int x2, int y2, boolean isSelected) { - Graphics2D g2D = (Graphics2D) g; - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - Color borderColor = getLoBorderColor(tabIndex); - g.setColor(borderColor); - int d = 2 * GAP; - if (isSelected) { - g.drawLine(x1 + GAP, y1, x2 - GAP, y1); - g.drawArc(x1, y1, d, d, 90, 90); - g.drawArc(x2 - d, y1, d, d, 0, 90); - g.drawLine(x1, y1 + GAP + 1, x1, y2); - g.drawLine(x2, y1 + GAP + 1, x2, y2); - } else { - g.drawLine(x1 + GAP, y1, x2 - GAP, y1); - g.drawArc(x1, y1, d, d, 90, 90); - g.drawArc(x2 - d, y1, d, d, 0, 90); - g.drawLine(x1, y1 + GAP + 1, x1, y2 - 1); - g.drawLine(x2, y1 + GAP + 1, x2, y2 - 1); - } - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - } - - protected void paintTopTabBorder(int tabIndex, Graphics g, int x1, int y1, int x2, int y2, boolean isSelected) { - int tc = tabPane.getTabCount(); - int currentRun = getRunForTab(tc, tabIndex); - int lastIndex = lastTabInRun(tc, currentRun); - int firstIndex = tabRuns[currentRun]; - boolean leftToRight = JTattooUtilities.isLeftToRight(tabPane); - - Color loColor = getLoBorderColor(tabIndex); - Color hiColor = getHiBorderColor(tabIndex); - - g.setColor(loColor); - g.drawLine(x1 + GAP, y1, x2, y1); - g.drawLine(x1 + GAP, y1, x1, y1 + GAP); - g.drawLine(x1, y1 + GAP + 1, x1, y2); - g.drawLine(x2, y1, x2, y2); - g.setColor(hiColor); - g.drawLine(x1 + GAP + 1, y1 + 1, x2 - 1, y1 + 1); - g.drawLine(x1 + GAP + 1, y1 + 1, x1 + 1, y1 + GAP + 1); - g.drawLine(x1 + 1, y1 + GAP + 1, x1 + 1, y2 - 1); - - // paint gap - int gapTabIndex = getTabAtLocation(x1 + 2, y1 - 2); - Color gapColor = getGapColor(gapTabIndex); - g.setColor(gapColor); - for (int i = 0; i < GAP; i++) { - g.drawLine(x1, y1 + i, x1 + GAP - i - 1, y1 + i); - } - - if (leftToRight) { - if ((tabIndex != firstIndex) || (currentRun != (runCount - 1))) { - g.setColor(loColor); - g.drawLine(x1, y1, x1, y1 + GAP); - } - if (!isSelected && (tabIndex == firstIndex) && (currentRun != (runCount - 1))) { - g.setColor(hiColor); - g.drawLine(x1 + 1, y1, x1 + 1, y1 + GAP - 2); - } - } else { - if ((tabIndex != lastIndex) || (currentRun != (runCount - 1))) { - g.setColor(loColor); - g.drawLine(x1, y1, x1, y1 + GAP); - } - } - } - - protected void paintLeftTabBorder(int tabIndex, Graphics g, int x1, int y1, int x2, int y2, boolean isSelected) { - Graphics2D g2D = (Graphics2D)g; - - int tc = tabPane.getTabCount(); - int currentRun = getRunForTab(tc, tabIndex); - int lastIndex = lastTabInRun(tc, currentRun); - int firstIndex = tabRuns[currentRun]; - - Color loColor = getLoBorderColor(tabIndex); - Color hiColor = getHiBorderColor(tabIndex); - - g.setColor(hiColor); - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - g.drawLine(x1 + GAP + 1, y1 + 1, x2 - 1, y1 + 1); - g.drawLine(x1 + GAP, y1 + 1, x1 + 1, y1 + GAP); - g.drawLine(x1 + 1, y1 + GAP + 1, x1 + 1, y2 - 1); - g2D.setComposite(savedComposite); - - g.setColor(loColor); - g.drawLine(x1 + GAP, y1, x2 - 1, y1); - g.drawLine(x1 + GAP, y1, x1, y1 + GAP); - g.drawLine(x1, y1 + GAP, x1, y2); - g.drawLine(x1 + GAP, y2, x2 - 1, y2); - if (tabIndex == lastIndex) { - g.drawLine(x1, y2, x1 + GAP, y2); - } - // paint gap - int gapTabIndex = getTabAtLocation(x1 + 2, y1 - 2); - Color gapColor = getGapColor(gapTabIndex); - g.setColor(gapColor); - for (int i = 0; i < GAP; i++) { - g.drawLine(x1, y1 + i, x1 + GAP - i - 1, y1 + i); - } - - if ((tabIndex != firstIndex) || (currentRun != (runCount - 1))) { - loColor = getLoBorderColor(gapTabIndex); - g.setColor(loColor); - g.drawLine(x1, y1, x1, y1 + GAP - 1); - if (tabIndex != firstIndex) { - g2D.setComposite(alpha); - hiColor = getHiBorderColor(gapTabIndex); - g.setColor(hiColor); - g.drawLine(x1 + 1, y1, x1 + 1, y1 + GAP - 2); - g2D.setComposite(savedComposite); - } - } - } - - protected void paintRoundedBottomTabBorder(int tabIndex, Graphics g, int x1, int y1, int x2, int y2, boolean isSelected) { - Graphics2D g2D = (Graphics2D) g; - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - Color loColor = getLoBorderColor(tabIndex); - int d = 2 * GAP; - g.setColor(loColor); - g.drawLine(x1 + GAP, y2, x2 - GAP, y2); - g.drawArc(x1, y2 - d, d, d, 180, 90); - g.drawArc(x2 - d, y2 - d, d, d, -90, 90); - g.drawLine(x1, y1, x1, y2 - GAP - 1); - g.drawLine(x2, y1, x2, y2 - GAP - 1); - - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - } - - protected void paintBottomTabBorder(int tabIndex, Graphics g, int x1, int y1, int x2, int y2, boolean isSelected) { - int tc = tabPane.getTabCount(); - int currentRun = getRunForTab(tc, tabIndex); - int lastIndex = lastTabInRun(tc, currentRun); - int firstIndex = tabRuns[currentRun]; - boolean leftToRight = JTattooUtilities.isLeftToRight(tabPane); - - Color loColor = getLoBorderColor(tabIndex); - Color hiColor = getHiBorderColor(tabIndex); - - g.setColor(loColor); - g.drawLine(x1, y1, x1, y2 - GAP); - g.drawLine(x1, y2 - GAP, x1 + GAP, y2); - g.drawLine(x1 + GAP, y2, x2, y2); - g.drawLine(x2, y2, x2, y1); - g.setColor(hiColor); - g.drawLine(x1 + 1, y1, x1 + 1, y2 - GAP - 1); - g.drawLine(x1 + 1, y2 - GAP, x1 + GAP, y2 - 1); - - // paint gap - int gapTabIndex = getTabAtLocation(x1 + 2, y2 + 2); - Color gapColor = getGapColor(gapTabIndex); - - g.setColor(gapColor); - for (int i = 0; i < GAP; i++) { - g.drawLine(x1, y2 - i, x1 + GAP - i - 1, y2 - i); - } - if (leftToRight) { - if ((tabIndex != firstIndex) || (currentRun != (runCount - 1))) { - g.setColor(loColor); - g.drawLine(x1, y2 - GAP, x1, y2); - } - } else { - if ((tabIndex != lastIndex) || (currentRun != (runCount - 1))) { - g.setColor(loColor); - g.drawLine(x1, y2 - GAP, x1, y2); - } - } - } - - protected void paintRightTabBorder(int tabIndex, Graphics g, int x1, int y1, int x2, int y2, boolean isSelected) { - Graphics2D g2D = (Graphics2D)g; - - int tc = tabPane.getTabCount(); - int currentRun = getRunForTab(tc, tabIndex); - int lastIndex = lastTabInRun(tc, currentRun); - int firstIndex = tabRuns[currentRun]; - - Color loColor = getLoBorderColor(tabIndex); - Color hiColor = getHiBorderColor(tabIndex); - - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - g.setColor(hiColor); - g.drawLine(x1, y1 + 1, x2 - GAP - 1, y1 + 1); - g.drawLine(x2 - GAP, y1 + 1, x2 - 1, y1 + GAP); - g2D.setComposite(savedComposite); - - g.setColor(loColor); - g.drawLine(x1, y1, x2 - GAP, y1); - g.drawLine(x2 - GAP, y1, x2, y1 + GAP); - g.drawLine(x2, y1 + GAP, x2, y2); - if (tabIndex == lastIndex) { - g.drawLine(x2, y2, x1, y2); - } - - // paint gap - int gapTabIndex = getTabAtLocation(x1 + 2, y1 - 2); - Color gapColor = getGapColor(gapTabIndex); - g.setColor(gapColor); - for (int i = 0; i < GAP; i++) { - g.drawLine(x2 - GAP + i + 1, y1 + i, x2, y1 + i); - } - - if ((tabIndex != firstIndex) || (currentRun != (runCount - 1))) { - loColor = getLoBorderColor(gapTabIndex); - g.setColor(loColor); - g.drawLine(x2, y1, x2, y1 + GAP - 1); - } - } - - protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) { - if (isTabOpaque() || isSelected) { - Graphics2D g2D = (Graphics2D) g; - Shape savedClip = g.getClip(); - Area orgClipArea = new Area(savedClip); - Color colorArr[] = getTabColors(tabIndex, isSelected, tabIndex == rolloverIndex); - int d = 2 * GAP; - switch (tabPlacement) { - case TOP: - default: - if (isSelected) { - Area clipArea = new Area(new RoundRectangle2D.Double(x, y, w , h + 4, d, d)); - Area rectArea = new Area(new Rectangle2D.Double(x, y, w, h + 2)); - clipArea.intersect(rectArea); - clipArea.intersect(orgClipArea); - g2D.setClip(clipArea); - JTattooUtilities.fillHorGradient(g, colorArr, x, y, w, h + 4); - g2D.setClip(savedClip); - } else { - Area clipArea = new Area(new RoundRectangle2D.Double(x, y, w, h + 4, d, d)); - Area rectArea = new Area(new Rectangle2D.Double(x, y, w, h)); - clipArea.intersect(rectArea); - clipArea.intersect(orgClipArea); - g2D.setClip(clipArea); - JTattooUtilities.fillHorGradient(g, colorArr, x, y, w, h + 4); - g2D.setClip(savedClip); - } - break; - case LEFT: - if (isSelected) { - JTattooUtilities.fillHorGradient(g, colorArr, x + 1, y + 1, w + 1, h - 1); - } else { - JTattooUtilities.fillHorGradient(g, colorArr, x + 1, y + 1, w - 1, h - 1); - } - break; - case BOTTOM: - if (isSelected) { - Area clipArea = new Area(new RoundRectangle2D.Double(x, y - 4, w, h + 4, d, d)); - Area rectArea = new Area(new Rectangle2D.Double(x, y - 2, w, h + 1)); - clipArea.intersect(rectArea); - clipArea.intersect(orgClipArea); - g2D.setClip(clipArea); - JTattooUtilities.fillHorGradient(g, colorArr, x, y - 4, w, h + 4); - g2D.setClip(savedClip); - } else { - Area clipArea = new Area(new RoundRectangle2D.Double(x, y - 4, w, h + 4, d, d)); - Area rectArea = new Area(new Rectangle2D.Double(x, y, w, h)); - clipArea.intersect(rectArea); - clipArea.intersect(orgClipArea); - g2D.setClip(clipArea); - JTattooUtilities.fillHorGradient(g, colorArr, x, y - 4, w, h + 4); - g2D.setClip(savedClip); - } - break; - case RIGHT: - if (isSelected) { - JTattooUtilities.fillHorGradient(g, colorArr, x - 2, y + 1, w + 2, h - 1); - } else { - JTattooUtilities.fillHorGradient(g, colorArr, x, y + 1, w + 1, h - 1); - } - break; - } - } - } - - protected void paintContentBorder(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) { - int tabAreaHeight = calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight); - int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth); - - // paint the background - if (tabPane.isOpaque()) { - int xt = tabPlacement == RIGHT ? w - tabAreaWidth : 0; - int yt = tabPlacement == BOTTOM ? h - tabAreaHeight : 0; - int wt = tabPlacement == TOP || tabPlacement == BOTTOM ? w : tabAreaWidth; - int ht = tabPlacement == LEFT || tabPlacement == RIGHT ? h : tabAreaHeight; - g.setColor(tabAreaBackground); - g.fillRect(xt, yt, wt, ht); - } - if (isContentOpaque()) { - int xt = tabPlacement == LEFT ? tabAreaWidth : 0; - int yt = tabPlacement == TOP ? tabAreaHeight : 0; - int wt = tabPlacement == LEFT || tabPlacement == RIGHT ? w - tabAreaWidth : w; - int ht = tabPlacement == TOP || tabPlacement == BOTTOM ? h - tabAreaHeight : h; - g.setColor(tabPane.getBackground()); - g.fillRect(xt, yt, wt, ht); - } - - Insets bi = new Insets(0, 0, 0, 0); - if (tabPane.getBorder() != null) { - bi = tabPane.getBorder().getBorderInsets(tabPane); - } - if (hasInnerBorder()) { - Color loColor = AbstractLookAndFeel.getControlDarkShadow(); - Color hiColor = AbstractLookAndFeel.getControlHighlight(); - g.setColor(loColor); - switch (tabPlacement) { - case TOP: { - int x1 = x + bi.left - 1; - int y1 = y + tabAreaHeight + bi.top - 2; - int x2 = x1 + w - bi.left - bi.right + 1; - int y2 = h - bi.bottom; - int ws = w - bi.left - bi.right + 1; - int hs = h - tabAreaHeight - bi.top - bi.bottom + 2; - - if (tabPane.getBorder() == null) { - g.drawLine(x1, y1, x2, y1); - g.setColor(hiColor); - g.drawLine(x1, y1 + 1, x2, y1 + 1); - } else { - g.drawRect(x1, y1, ws, hs); - g.setColor(hiColor); - g.drawLine(x1 + 1, y1 + 1, x2 - 1, y1 + 1); - } - break; - } - case LEFT: { - int x1 = x + tabAreaWidth + bi.left - 2; - int y1 = y + bi.top - 1; - //int x2 = w - bi.right; - int y2 = y1 + h - bi.top - bi.bottom + 1; - int ws = w - tabAreaWidth - bi.left - bi.right + 2; - int hs = h - bi.top - bi.bottom + 1; - - if (tabPane.getBorder() == null) { - g.drawLine(x1, y1, x1, y2); - g.setColor(hiColor); - g.drawLine(x1 + 1, y1, x1 + 1, y2); - } else { - g.drawRect(x1, y1, ws, hs); - g.setColor(hiColor); - g.drawLine(x1 + 1, y1 + 1, x1 + 1, y2 - 1); - } - break; - } - case BOTTOM: { - int x1 = x + bi.left - 1; - int y1 = y + bi.top - 1; - int x2 = x1 + w - bi.left - bi.right + 1; - int y2 = h - tabAreaHeight - bi.bottom; - int ws = w - bi.left - bi.right + 1; - int hs = h - tabAreaHeight - bi.top - bi.bottom + 2; - - if (tabPane.getBorder() == null) { - g.drawLine(x1, y2, x2, y2); - } else { - g.drawRect(x1, y1, ws, hs); - } - break; - } - case RIGHT: { - int x1 = x + bi.left - 1; - int y1 = y + bi.top - 1; - int x2 = w - tabAreaWidth - bi.right + 1; - int y2 = y1 + h - bi.top - bi.bottom + 1; - int ws = w - tabAreaWidth - bi.left - bi.right + 2; - int hs = h - bi.top - bi.bottom + 1; - - if (tabPane.getBorder() == null) { - g.drawLine(x2, y1, x2, y2); - } else { - g.drawRect(x1, y1, ws, hs); - } - break; - } - } - } else { - int sepHeight = tabAreaInsets.bottom; - if (sepHeight > 0) { - switch (tabPlacement) { - case TOP: { - Color colors[] = getContentBorderColors(tabPlacement); - int ys = y + tabAreaHeight - sepHeight + bi.top; - for (int i = 0; i < colors.length; i++) { - g.setColor(colors[i]); - g.drawLine(x, ys + i, x + w, ys + i); - } - break; - } - case LEFT: { - Color colors[] = getContentBorderColors(tabPlacement); - int xs = x + tabAreaWidth - sepHeight + bi.left; - for (int i = 0; i < colors.length; i++) { - g.setColor(colors[i]); - g.drawLine(xs + i, y, xs + i, y + h); - } - break; - } - case BOTTOM: { - Color colors[] = getContentBorderColors(tabPlacement); - int ys = y + h - tabAreaHeight - bi.bottom; - for (int i = 0; i < colors.length; i++) { - g.setColor(colors[i]); - g.drawLine(x, ys + i, x + w, ys + i); - } - break; - } - case RIGHT: { - Color colors[] = getContentBorderColors(tabPlacement); - int xs = x + w - tabAreaWidth - bi.right; - for (int i = 0; i < colors.length; i++) { - g.setColor(colors[i]); - g.drawLine(xs + i, y, xs + i, y + h); - } - break; - } - } - } - } - } - - protected void paintScrollContentBorder(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) { - Insets bi = new Insets(0, 0, 0, 0); - if (tabPane.getBorder() != null) { - bi = tabPane.getBorder().getBorderInsets(tabPane); - } - if (tabPane.getTabPlacement() == TOP) { - paintContentBorder(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex(), x, y - bi.top, w, h); - } else if (tabPane.getTabPlacement() == BOTTOM) { - paintContentBorder(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex(), x, y + bi.bottom, w, h); - } else if (tabPane.getTabPlacement() == LEFT) { - paintContentBorder(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex(), x - bi.left, y, w, h); - } else if (tabPane.getTabPlacement() == RIGHT) { - paintContentBorder(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex(), x + bi.right, y, w, h); - } - } - - // TabbedPaneUI methods - private void ensureCurrentLayout() { - // TabPane maybe still invalid. See bug 4237677. - ((TabbedPaneLayout) tabPane.getLayout()).calculateLayoutInfo(); - } - - /** - * Returns the bounds of the specified tab index. The bounds are - * with respect to the JTabbedPane's coordinate space. - */ - public Rectangle getTabBounds(JTabbedPane pane, int i) { - ensureCurrentLayout(); - Rectangle tabRect = new Rectangle(); - return getTabBounds(i, tabRect); - } - - public int getTabRunCount(JTabbedPane pane) { - ensureCurrentLayout(); - return runCount; - } - - /** - * Returns the tab index which intersects the specified point - * in the JTabbedPane's coordinate space. - */ - public int tabForCoordinate(JTabbedPane pane, int x, int y) { - ensureCurrentLayout(); - Point p = new Point(x, y); - - if (scrollableTabLayoutEnabled()) { - translatePointToTabPanel(x, y, p); - } - int tc = tabPane.getTabCount(); - for (int i = 0; i < tc; i++) { - if (rects[i].contains(p.x, p.y)) { - return i; - } - } - return -1; - } - - /** - * Returns the bounds of the specified tab in the coordinate space - * of the JTabbedPane component. This is required because the tab rects - * are by default defined in the coordinate space of the component where - * they are rendered, which could be the JTabbedPane - * (for WRAP_TAB_LAYOUT) or a ScrollableTabPanel (SCROLL_TAB_LAYOUT). - * This method should be used whenever the tab rectangle must be relative - * to the JTabbedPane itself and the result should be placed in a - * designated Rectangle object (rather than instantiating and returning - * a new Rectangle each time). The tab index parameter must be a valid - * tabbed pane tab index (0 to tab count - 1, inclusive). The destination - * rectangle parameter must be a valid Rectangle instance. - * The handling of invalid parameters is unspecified. - * - * @param tabIndex the index of the tab - * @param dest the rectangle where the result should be placed - * @return the resulting rectangle - * - * @since 1.4 - */ - protected Rectangle getTabBounds(int tabIndex, Rectangle dest) { - dest.width = rects[tabIndex].width; - dest.height = rects[tabIndex].height; - - if (scrollableTabLayoutEnabled()) { // SCROLL_TAB_LAYOUT - // Need to translate coordinates based on viewport location & - // view position - Point vpp = tabScroller.viewport.getLocation(); - Point viewp = tabScroller.viewport.getViewPosition(); - dest.x = rects[tabIndex].x + vpp.x - viewp.x; - dest.y = rects[tabIndex].y + vpp.y - viewp.y; - - } else { // WRAP_TAB_LAYOUT - dest.x = rects[tabIndex].x; - dest.y = rects[tabIndex].y; - } - return dest; - } - - /** - * Returns the tab index which intersects the specified point - * in the coordinate space of the component where the - * tabs are actually rendered, which could be the JTabbedPane - * (for WRAP_TAB_LAYOUT) or a ScrollableTabPanel (SCROLL_TAB_LAYOUT). - */ - protected int getTabAtLocation(int x, int y) { - ensureCurrentLayout(); - int tc = tabPane.getTabCount(); - for (int i = 0; i < tc; i++) { - if (rects[i].contains(x, y)) { - return i; - } - } - return -1; - } - - /** - * Returns the index of the tab closest to the passed in location, note - * that the returned tab may not contain the location x,y. - */ - protected int getClosestTab(int x, int y) { - int min = 0; - int tc = Math.min(rects.length, tabPane.getTabCount()); - int max = tc; - int tabPlacement = tabPane.getTabPlacement(); - boolean useX = (tabPlacement == TOP || tabPlacement == BOTTOM); - int want = (useX) ? x : y; - - while (min != max) { - int current = (max + min) / 2; - int minLoc; - int maxLoc; - - if (useX) { - minLoc = rects[current].x; - maxLoc = minLoc + rects[current].width; - } else { - minLoc = rects[current].y; - maxLoc = minLoc + rects[current].height; - } - if (want < minLoc) { - max = current; - if (min == max) { - return Math.max(0, current - 1); - } - } else if (want >= maxLoc) { - min = current; - if (max - min <= 1) { - return Math.max(current + 1, tc - 1); - } - } else { - return current; - } - } - return min; - } - - /** - * Returns a point which is translated from the specified point in the - * JTabbedPane's coordinate space to the coordinate space of the - * ScrollableTabPanel. This is used for SCROLL_TAB_LAYOUT ONLY. - */ - private Point translatePointToTabPanel(int srcx, int srcy, Point dest) { - Point vpp = tabScroller.viewport.getLocation(); - Point viewp = tabScroller.viewport.getViewPosition(); - dest.x = srcx - vpp.x + viewp.x; - dest.y = srcy - vpp.y + viewp.y; - return dest; - } - - // BaseTabbedPaneUI methods - protected Component getVisibleComponent() { - return visibleComponent; - } - - protected void setVisibleComponent(Component component) { - if (visibleComponent != null && visibleComponent != component && visibleComponent.getParent() == tabPane) { - visibleComponent.setVisible(false); - } - if (component != null && !component.isVisible()) { - component.setVisible(true); - } - visibleComponent = component; - } - - protected void assureRectsCreated(int tabCount) { - int rectArrayLen = rects.length; - if (tabCount != rectArrayLen) { - Rectangle[] tempRectArray = new Rectangle[tabCount]; - System.arraycopy(rects, 0, tempRectArray, 0, Math.min(rectArrayLen, tabCount)); - rects = tempRectArray; - for (int rectIndex = rectArrayLen; rectIndex < tabCount; rectIndex++) { - rects[rectIndex] = new Rectangle(); - } - } - } - - protected void expandTabRunsArray() { - int rectLen = tabRuns.length; - int[] newArray = new int[rectLen + 10]; - System.arraycopy(tabRuns, 0, newArray, 0, runCount); - tabRuns = newArray; - } - - protected int getRunForTab(int tabCount, int tabIndex) { - for (int i = 0; i < runCount; i++) { - int first = tabRuns[i]; - int last = lastTabInRun(tabCount, i); - if (tabIndex >= first && tabIndex <= last) { - return i; - } - } - return 0; - } - - protected int lastTabInRun(int tabCount, int run) { - if (runCount == 1) { - return tabCount - 1; - } - int nextRun = (run == runCount - 1 ? 0 : run + 1); - if (tabRuns[nextRun] == 0) { - return tabCount - 1; - } - return tabRuns[nextRun] - 1; - } - - protected int getTabRunOverlay(int tabPlacement) { - return tabRunOverlay; - } - - protected int getTabRunIndent(int tabPlacement, int run) { - return 0; - } - - protected boolean shouldPadTabRun(int tabPlacement, int run) { - return runCount > 1; - } - - protected boolean shouldRotateTabRuns(int tabPlacement) { - return true; - } - - protected Icon getIconForTab(int tabIndex) { - if (tabIndex >= 0 && tabIndex < tabCount) { - return (!tabPane.isEnabled() || !tabPane.isEnabledAt(tabIndex)) ? tabPane.getDisabledIconAt(tabIndex) : tabPane.getIconAt(tabIndex); - } - return null; - } - - /** - * Returns the text View object required to render stylized text (HTML) for - * the specified tab or null if no specialized text rendering is needed - * for this tab. This is provided to support html rendering inside tabs. - * - * @param tabIndex the index of the tab - * @return the text view to render the tab's text or null if no - * specialized rendering is required - * - * @since 1.4 - */ - protected View getTextViewForTab(int tabIndex) { - if (htmlViews != null && htmlViews.size() > tabIndex) { - return (View) htmlViews.get(tabIndex); - } - return null; - } - - protected int calculateTabHeight(int tabPlacement, int tabIndex, int fontHeight) { - int height = 0; - Component tabComponent = getTabComponentAt(tabIndex); - if (tabComponent != null) { - height = tabComponent.getPreferredSize().height; - } else { - View v = getTextViewForTab(tabIndex); - if (v != null) { - // html - height += (int) v.getPreferredSpan(View.Y_AXIS); - } else { - // plain text - height += fontHeight; - } - Icon icon = getIconForTab(tabIndex); - if (icon != null) { - height = Math.max(height, icon.getIconHeight()); - } - } - Insets ti = getTabInsets(tabPlacement, tabIndex); - height += ti.top + ti.bottom + 2; - return height; - } - - protected int calculateMaxTabHeight(int tabPlacement) { - FontMetrics metrics = getFontMetrics(); - int tc = tabPane.getTabCount(); - int result = 0; - int fontHeight = metrics.getHeight(); - for (int i = 0; i < tc; i++) { - result = Math.max(calculateTabHeight(tabPlacement, i, fontHeight), result); - } - return result; - } - - protected int calculateTabWidth(int tabPlacement, int tabIndex, FontMetrics metrics) { - Insets insets = getTabInsets(tabPlacement, tabIndex); - int width = insets.left + insets.right + 3; - Component tabComponent = getTabComponentAt(tabIndex); - if (tabComponent != null) { - width += tabComponent.getPreferredSize().width; - } else { - Icon icon = getIconForTab(tabIndex); - if (icon != null) { - width += icon.getIconWidth() + textIconGap; - } - View v = getTextViewForTab(tabIndex); - if (v != null) { - // html - width += (int) v.getPreferredSpan(View.X_AXIS); - } else { - // plain text - String title = tabPane.getTitleAt(tabIndex); - width += SwingUtilities.computeStringWidth(metrics, title); - } - } - - return width; - } - - protected int calculateMaxTabWidth(int tabPlacement) { - FontMetrics metrics = getFontMetrics(); - int tc = tabPane.getTabCount(); - int result = 0; - for (int i = 0; i < tc; i++) { - result = Math.max(calculateTabWidth(tabPlacement, i, metrics), result); - } - return result; - } - - protected int calculateTabAreaHeight(int tabPlacement, int horizRunCount, int maxTabHeight) { - if (tabPlacement == JTabbedPane.TOP || tabPlacement == JTabbedPane.BOTTOM) { - Insets insets = getTabAreaInsets(tabPlacement); - int overlay = getTabRunOverlay(tabPlacement); - return (horizRunCount > 0 ? horizRunCount * (maxTabHeight - overlay) + overlay + insets.top + insets.bottom : 0); - } else { - return tabPane.getHeight(); - } - } - - protected int calculateTabAreaWidth(int tabPlacement, int vertRunCount, int maxTabWidth) { - if (tabPlacement == JTabbedPane.LEFT || tabPlacement == JTabbedPane.RIGHT) { - Insets insets = getTabAreaInsets(tabPlacement); - int overlay = getTabRunOverlay(tabPlacement); - return (vertRunCount > 0 ? vertRunCount * (maxTabWidth - overlay) + overlay + insets.left + insets.right : 0); - } else { - return tabPane.getWidth(); - } - } - - protected Insets getTabInsets(int tabPlacement, int tabIndex) { - return tabInsets; - } - - protected Insets getSelectedTabPadInsets(int tabPlacement) { - rotateInsets(selectedTabPadInsets, currentPadInsets, tabPlacement); - return currentPadInsets; - } - - protected Insets getTabAreaInsets(int tabPlacement) { - rotateInsets(tabAreaInsets, currentTabAreaInsets, tabPlacement); - return currentTabAreaInsets; - } - - protected Insets getContentBorderInsets(int tabPlacement) { - if (tabPane.getBorder() == null) { - return NULL_BORDER_INSETS; - } - return contentBorderInsets; - } - - protected FontMetrics getFontMetrics() { - Font font = tabPane.getFont().deriveFont(Font.BOLD); - return Toolkit.getDefaultToolkit().getFontMetrics(font); - } - - // Tab Navigation methods - protected void navigateSelectedTab(int direction) { - int tabPlacement = tabPane.getTabPlacement(); - int current = tabPane.getSelectedIndex(); - int tc = tabPane.getTabCount(); - boolean leftToRight = JTattooUtilities.isLeftToRight(tabPane); - - // If we have no tabs then don't navigate. - if (tc <= 0) { - return; - } - - int offset; - switch (tabPlacement) { - case NEXT: - selectNextTab(current); - break; - case PREVIOUS: - selectPreviousTab(current); - break; - case LEFT: - case RIGHT: - switch (direction) { - case NORTH: - selectPreviousTabInRun(current); - break; - case SOUTH: - selectNextTabInRun(current); - break; - case WEST: - offset = getTabRunOffset(tabPlacement, tc, current, false); - selectAdjacentRunTab(tabPlacement, current, offset); - break; - case EAST: - offset = getTabRunOffset(tabPlacement, tc, current, true); - selectAdjacentRunTab(tabPlacement, current, offset); - break; - default: - } - break; - case BOTTOM: - case TOP: - default: - switch (direction) { - case NORTH: - offset = getTabRunOffset(tabPlacement, tc, current, false); - selectAdjacentRunTab(tabPlacement, current, offset); - break; - case SOUTH: - offset = getTabRunOffset(tabPlacement, tc, current, true); - selectAdjacentRunTab(tabPlacement, current, offset); - break; - case EAST: - if (leftToRight) { - selectNextTabInRun(current); - } else { - selectPreviousTabInRun(current); - } - break; - case WEST: - if (leftToRight) { - selectPreviousTabInRun(current); - } else { - selectNextTabInRun(current); - } - break; - default: - } - } - } - - protected void selectNextTabInRun(int current) { - int tc = tabPane.getTabCount(); - int tabIndex = getNextTabIndexInRun(tc, current); - while (tabIndex != current && !tabPane.isEnabledAt(tabIndex)) { - tabIndex = getNextTabIndexInRun(tc, tabIndex); - } - tabPane.setSelectedIndex(tabIndex); - } - - protected void selectPreviousTabInRun(int current) { - int tc = tabPane.getTabCount(); - int tabIndex = getPreviousTabIndexInRun(tc, current); - while (tabIndex != current && !tabPane.isEnabledAt(tabIndex)) { - tabIndex = getPreviousTabIndexInRun(tc, tabIndex); - } - tabPane.setSelectedIndex(tabIndex); - } - - protected void selectNextTab(int current) { - int tabIndex = getNextTabIndex(current); - while (tabIndex != current && !tabPane.isEnabledAt(tabIndex)) { - tabIndex = getNextTabIndex(tabIndex); - } - tabPane.setSelectedIndex(tabIndex); - } - - protected void selectPreviousTab(int current) { - int tabIndex = getPreviousTabIndex(current); - while (tabIndex != current && !tabPane.isEnabledAt(tabIndex)) { - tabIndex = getPreviousTabIndex(tabIndex); - } - tabPane.setSelectedIndex(tabIndex); - } - - protected void selectAdjacentRunTab(int tabPlacement, int tabIndex, int offset) { - if (runCount < 2) { - return; - } - int newIndex; - Rectangle r = rects[tabIndex]; - switch (tabPlacement) { - case LEFT: - case RIGHT: - newIndex = getTabAtLocation(r.x + r.width / 2 + offset, - r.y + r.height / 2); - break; - case BOTTOM: - case TOP: - default: - newIndex = getTabAtLocation(r.x + r.width / 2, - r.y + r.height / 2 + offset); - } - if (newIndex != -1) { - while (!tabPane.isEnabledAt(newIndex) && newIndex != tabIndex) { - newIndex = getNextTabIndex(newIndex); - } - tabPane.setSelectedIndex(newIndex); - } - } - - protected int getTabRunOffset(int tabPlacement, int tabCount, int tabIndex, boolean forward) { - int run = getRunForTab(tabCount, tabIndex); - int offset; - switch (tabPlacement) { - case LEFT: { - if (run == 0) { - offset = (forward ? -(calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth) - maxTabWidth) : -maxTabWidth); - - } else if (run == runCount - 1) { - offset = (forward ? maxTabWidth : calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth) - maxTabWidth); - } else { - offset = (forward ? maxTabWidth : -maxTabWidth); - } - break; - } - case RIGHT: { - if (run == 0) { - offset = (forward ? maxTabWidth : calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth) - maxTabWidth); - } else if (run == runCount - 1) { - offset = (forward ? -(calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth) - maxTabWidth) : -maxTabWidth); - } else { - offset = (forward ? maxTabWidth : -maxTabWidth); - } - break; - } - case BOTTOM: { - if (run == 0) { - offset = (forward ? maxTabHeight : calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight) - maxTabHeight); - } else if (run == runCount - 1) { - offset = (forward ? -(calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight) - maxTabHeight) : -maxTabHeight); - } else { - offset = (forward ? maxTabHeight : -maxTabHeight); - } - break; - } - case TOP: - default: { - if (run == 0) { - offset = (forward ? -(calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight) - maxTabHeight) : -maxTabHeight); - } else if (run == runCount - 1) { - offset = (forward ? maxTabHeight : calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight) - maxTabHeight); - } else { - offset = (forward ? maxTabHeight : -maxTabHeight); - } - } - } - return offset; - } - - protected int getPreviousTabIndex(int base) { - int tabIndex = (base - 1 >= 0 ? base - 1 : tabPane.getTabCount() - 1); - return (tabIndex >= 0 ? tabIndex : 0); - } - - protected int getNextTabIndex(int base) { - return (base + 1) % tabPane.getTabCount(); - } - - protected int getNextTabIndexInRun(int tabCount, int base) { - if (runCount < 2) { - return getNextTabIndex(base); - } - int currentRun = getRunForTab(tabCount, base); - int next = getNextTabIndex(base); - if (next == tabRuns[getNextTabRun(currentRun)]) { - return tabRuns[currentRun]; - } - return next; - } - - protected int getPreviousTabIndexInRun(int tabCount, int base) { - if (runCount < 2) { - return getPreviousTabIndex(base); - } - int currentRun = getRunForTab(tabCount, base); - if (base == tabRuns[currentRun]) { - int previous = tabRuns[getNextTabRun(currentRun)] - 1; - return (previous != -1 ? previous : tabCount - 1); - } - return getPreviousTabIndex(base); - } - - protected int getPreviousTabRun(int baseRun) { - int runIndex = (baseRun - 1 >= 0 ? baseRun - 1 : runCount - 1); - return (runIndex >= 0 ? runIndex : 0); - } - - protected int getNextTabRun(int baseRun) { - return (baseRun + 1) % runCount; - } - - protected static void rotateInsets(Insets topInsets, Insets targetInsets, int targetPlacement) { - switch (targetPlacement) { - case LEFT: - targetInsets.top = topInsets.left; - targetInsets.left = topInsets.top; - targetInsets.bottom = topInsets.right; - targetInsets.right = topInsets.bottom; - break; - case BOTTOM: - targetInsets.top = topInsets.bottom; - targetInsets.left = topInsets.left; - targetInsets.bottom = topInsets.top; - targetInsets.right = topInsets.right; - break; - case RIGHT: - targetInsets.top = topInsets.left; - targetInsets.left = topInsets.bottom; - targetInsets.bottom = topInsets.right; - targetInsets.right = topInsets.top; - break; - case TOP: - default: - targetInsets.top = topInsets.top; - targetInsets.left = topInsets.left; - targetInsets.bottom = topInsets.bottom; - targetInsets.right = topInsets.right; - } - } - - protected boolean requestFocusForVisibleComponent() { - Component vc = getVisibleComponent(); - if (vc.isFocusTraversable()) { - vc.requestFocus(); - return true; - } else if (vc instanceof JComponent) { - if (((JComponent) vc).requestDefaultFocus()) { - return true; - } - } - return false; - } - - private static class RightAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - JTabbedPane pane = (JTabbedPane) e.getSource(); - BaseTabbedPaneUI ui = (BaseTabbedPaneUI) pane.getUI(); - ui.navigateSelectedTab(EAST); - } - }; - - private static class LeftAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - JTabbedPane pane = (JTabbedPane) e.getSource(); - BaseTabbedPaneUI ui = (BaseTabbedPaneUI) pane.getUI(); - ui.navigateSelectedTab(WEST); - } - }; - - private static class UpAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - JTabbedPane pane = (JTabbedPane) e.getSource(); - BaseTabbedPaneUI ui = (BaseTabbedPaneUI) pane.getUI(); - ui.navigateSelectedTab(NORTH); - } - }; - - private static class DownAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - JTabbedPane pane = (JTabbedPane) e.getSource(); - BaseTabbedPaneUI ui = (BaseTabbedPaneUI) pane.getUI(); - ui.navigateSelectedTab(SOUTH); - } - }; - - private static class NextAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - JTabbedPane pane = (JTabbedPane) e.getSource(); - BaseTabbedPaneUI ui = (BaseTabbedPaneUI) pane.getUI(); - ui.navigateSelectedTab(NEXT); - } - }; - - private static class PreviousAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - JTabbedPane pane = (JTabbedPane) e.getSource(); - BaseTabbedPaneUI ui = (BaseTabbedPaneUI) pane.getUI(); - ui.navigateSelectedTab(PREVIOUS); - } - }; - - private static class PageUpAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - JTabbedPane pane = (JTabbedPane) e.getSource(); - BaseTabbedPaneUI ui = (BaseTabbedPaneUI) pane.getUI(); - int tabPlacement = pane.getTabPlacement(); - if (tabPlacement == TOP || tabPlacement == BOTTOM) { - ui.navigateSelectedTab(WEST); - } else { - ui.navigateSelectedTab(NORTH); - } - } - }; - - private static class PageDownAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - JTabbedPane pane = (JTabbedPane) e.getSource(); - BaseTabbedPaneUI ui = (BaseTabbedPaneUI) pane.getUI(); - int tabPlacement = pane.getTabPlacement(); - if (tabPlacement == TOP || tabPlacement == BOTTOM) { - ui.navigateSelectedTab(EAST); - } else { - ui.navigateSelectedTab(SOUTH); - } - } - }; - - private static class RequestFocusAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - JTabbedPane pane = (JTabbedPane) e.getSource(); - pane.requestFocus(); - } - }; - - private static class RequestFocusForVisibleAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - JTabbedPane pane = (JTabbedPane) e.getSource(); - BaseTabbedPaneUI ui = (BaseTabbedPaneUI) pane.getUI(); - ui.requestFocusForVisibleComponent(); - } - }; - - /** - * Selects a tab in the JTabbedPane based on the String of the - * action command. The tab selected is based on the first tab that - * has a mnemonic matching the first character of the action command. - */ - private static class SetSelectedIndexAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - JTabbedPane pane = (JTabbedPane) e.getSource(); - - if (pane != null && (pane.getUI() instanceof BaseTabbedPaneUI)) { - BaseTabbedPaneUI ui = (BaseTabbedPaneUI) pane.getUI(); - String command = e.getActionCommand(); - - if (command != null && command.length() > 0) { - int mnemonic = (int) e.getActionCommand().charAt(0); - if (mnemonic >= 'a' && mnemonic <= 'z') { - mnemonic -= ('a' - 'A'); - } - Integer index = (Integer) ui.mnemonicToIndexMap.get(new Integer(mnemonic)); - if (index != null && pane.isEnabledAt(index.intValue())) { - pane.setSelectedIndex(index.intValue()); - } - } - } - } - }; - - private static class ScrollTabsForwardAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - JTabbedPane pane; - Object src = e.getSource(); - if (src instanceof JTabbedPane) { - pane = (JTabbedPane) src; - } else if (src instanceof ScrollableTabButton) { - pane = (JTabbedPane) ((ScrollableTabButton) src).getParent(); - } else { - return; // shouldn't happen - } - BaseTabbedPaneUI ui = (BaseTabbedPaneUI) pane.getUI(); - - if (ui.scrollableTabLayoutEnabled()) { - ui.tabScroller.scrollForward(pane.getTabPlacement()); - } - } - } - - private static class ScrollTabsBackwardAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - JTabbedPane pane; - Object src = e.getSource(); - if (src instanceof JTabbedPane) { - pane = (JTabbedPane) src; - } else if (src instanceof ScrollableTabButton) { - pane = (JTabbedPane) ((ScrollableTabButton) src).getParent(); - } else { - return; // shouldn't happen - } - BaseTabbedPaneUI ui = (BaseTabbedPaneUI) pane.getUI(); - - if (ui.scrollableTabLayoutEnabled()) { - ui.tabScroller.scrollBackward(pane.getTabPlacement()); - } - } - } - - private static class ScrollTabsPopupMenuItemAction extends AbstractAction { - - private JTabbedPane tabbedPane = null; - private int selectIndex = 0; - - public ScrollTabsPopupMenuItemAction(JTabbedPane pane, int index) { - tabbedPane = pane; - selectIndex = index; - } - - public void actionPerformed(ActionEvent e) { - tabbedPane.setSelectedIndex(selectIndex); - } - } - - private static class ScrollTabsPopupMenuAction extends AbstractAction { - - private JTabbedPane tabbedPane = null; - - public void actionPerformed(ActionEvent e) { - Object src = e.getSource(); - if (src instanceof JTabbedPane) { - tabbedPane = (JTabbedPane) src; - } else if (src instanceof ScrollablePopupMenuTabButton) { - tabbedPane = (JTabbedPane) ((ScrollablePopupMenuTabButton) src).getParent(); - } else { - return; // shouldn't happen - } - BaseTabbedPaneUI ui = (BaseTabbedPaneUI) tabbedPane.getUI(); - if (ui.scrollableTabLayoutEnabled()) { - JPopupMenu popup = new JPopupMenu(); - for (int i = 0; i < tabbedPane.getTabCount(); i++) { - JMenuItem item = new JMenuItem(tabbedPane.getTitleAt(i)); - item.addActionListener(new ScrollTabsPopupMenuItemAction(tabbedPane, i)); - item.setEnabled(tabbedPane.isEnabledAt(i)); - popup.add(item); - } - popup.show(ui.tabScroller.popupMenuButton, 0, 0); - Point pt = ui.tabScroller.popupMenuButton.getLocationOnScreen(); - int x = -popup.getWidth() + ui.tabScroller.popupMenuButton.getWidth(); - int y = ui.tabScroller.popupMenuButton.getHeight() - 1; - popup.setLocation(pt.x + x, pt.y + y); - } - } - } - - /** - * This inner class is marked "public" due to a compiler bug. - * This class should be treated as a "protected" inner class. - * Instantiate it only within subclasses of BaseTabbedPaneUI. - */ - public class TabbedPaneLayout implements LayoutManager { - - public void addLayoutComponent(String name, Component comp) { - } - - public void removeLayoutComponent(Component comp) { - } - - public Dimension preferredLayoutSize(Container parent) { - return calculateSize(false); - } - - public Dimension minimumLayoutSize(Container parent) { - return calculateSize(true); - } - - protected Dimension calculateSize(boolean minimum) { - int tabPlacement = tabPane.getTabPlacement(); - Insets insets = tabPane.getInsets(); - Insets contentInsets = getContentBorderInsets(tabPlacement); - Insets tabAreaInsets = getTabAreaInsets(tabPlacement); - - Dimension zeroSize = new Dimension(0, 0); - int height = contentInsets.top + contentInsets.bottom; - int width = contentInsets.left + contentInsets.right; - int cWidth = 0; - int cHeight = 0; - - // Determine minimum size required to display largest - // child in each dimension - // - for (int i = 0; i < tabPane.getTabCount(); i++) { - Component component = tabPane.getComponentAt(i); - if (component != null) { - Dimension size = minimum ? component.getMinimumSize() : component.getPreferredSize(); - if (size != null) { - cHeight = Math.max(size.height, cHeight); - cWidth = Math.max(size.width, cWidth); - } - } - } - // Add content border insets to minimum size - width += cWidth; - height += cHeight; - int tabExtent; - - // Calculate how much space the tabs will need, based on the - // minimum size required to display largest child + content border - // - switch (tabPlacement) { - case LEFT: - case RIGHT: - height = Math.max(height, calculateMaxTabHeight(tabPlacement) - + tabAreaInsets.top + tabAreaInsets.bottom); - tabExtent = preferredTabAreaWidth(tabPlacement, height); - width += tabExtent; - break; - case TOP: - case BOTTOM: - default: - width = Math.max(width, calculateMaxTabWidth(tabPlacement) - + tabAreaInsets.left + tabAreaInsets.right); - tabExtent = preferredTabAreaHeight(tabPlacement, width); - height += tabExtent; - } - return new Dimension(width + insets.left + insets.right, height + insets.bottom + insets.top); - } - - protected int preferredTabAreaHeight(int tabPlacement, int width) { - FontMetrics metrics = getFontMetrics(); - int tc = tabPane.getTabCount(); - int total = 0; - if (tc > 0) { - int rows = 1; - int x = 0; - int maxTabHeight = calculateMaxTabHeight(tabPlacement); - - for (int i = 0; i < tc; i++) { - int tabWidth = calculateTabWidth(tabPlacement, i, metrics); - - if (x != 0 && x + tabWidth > width) { - rows++; - x = 0; - } - x += tabWidth; - } - total = calculateTabAreaHeight(tabPlacement, rows, maxTabHeight); - } - return total; - } - - protected int preferredTabAreaWidth(int tabPlacement, int height) { - FontMetrics metrics = getFontMetrics(); - int tc = tabPane.getTabCount(); - int total = 0; - if (tc > 0) { - int columns = 1; - int y = 0; - int fontHeight = metrics.getHeight(); - - maxTabWidth = calculateMaxTabWidth(tabPlacement); - - for (int i = 0; i < tc; i++) { - int tabHeight = calculateTabHeight(tabPlacement, i, fontHeight); - - if (y != 0 && y + tabHeight > height) { - columns++; - y = 0; - } - y += tabHeight; - } - total = calculateTabAreaWidth(tabPlacement, columns, maxTabWidth); - } - return total; - } - - public void layoutContainer(Container parent) { - /* Some of the code in this method deals with changing the - * visibility of components to hide and show the contents for the - * selected tab. This is older code that has since been duplicated - * in JTabbedPane.fireStateChanged(), so as to allow visibility - * changes to happen sooner (see the note there). This code remains - * for backward compatibility as there are some cases, such as - * subclasses that don't fireStateChanged() where it may be used. - * Any changes here need to be kept in synch with - * JTabbedPane.fireStateChanged(). - */ - - int tabPlacement = tabPane.getTabPlacement(); - Insets insets = tabPane.getInsets(); - int selectedIndex = tabPane.getSelectedIndex(); - Component visibleComponent = getVisibleComponent(); - - calculateLayoutInfo(); - - Component selectedComponent = null; - if (selectedIndex < 0) { - if (visibleComponent != null) { - // The last tab was removed, so remove the component - setVisibleComponent(null); - } - } else { - try { - selectedComponent = tabPane.getComponentAt(selectedIndex); - } catch (Exception ex) { - } - } - int cx, cy, cw, ch; - int totalTabWidth = 0; - int totalTabHeight = 0; - Insets contentInsets = getContentBorderInsets(tabPlacement); - - boolean shouldChangeFocus = false; - - // In order to allow programs to use a single component - // as the display for multiple tabs, we will not change - // the visible compnent if the currently selected tab - // has a null component. This is a bit dicey, as we don't - // explicitly state we support this in the spec, but since - // programs are now depending on this, we're making it work. - // - if (selectedComponent != null) { - if (selectedComponent != visibleComponent && visibleComponent != null) { - if (SwingUtilities.findFocusOwner(visibleComponent) != null) { - shouldChangeFocus = true; - } - } - setVisibleComponent(selectedComponent); - } - - Rectangle bounds = tabPane.getBounds(); - int numChildren = tabPane.getComponentCount(); - - if (numChildren > 0) { - - switch (tabPlacement) { - case LEFT: - totalTabWidth = calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth); - cx = insets.left + totalTabWidth + contentInsets.left; - cy = insets.top + contentInsets.top; - break; - case RIGHT: - totalTabWidth = calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth); - cx = insets.left + contentInsets.left; - cy = insets.top + contentInsets.top; - break; - case BOTTOM: - totalTabHeight = calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight); - cx = insets.left + contentInsets.left; - cy = insets.top + contentInsets.top; - break; - case TOP: - default: - totalTabHeight = calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight); - cx = insets.left + contentInsets.left; - cy = insets.top + totalTabHeight + contentInsets.top; - } - - cw = bounds.width - totalTabWidth - - insets.left - insets.right - - contentInsets.left - contentInsets.right; - ch = bounds.height - totalTabHeight - - insets.top - insets.bottom - - contentInsets.top - contentInsets.bottom; - - for (int i = 0; i < numChildren; i++) { - Component child = tabPane.getComponent(i); - if (child == tabContainer) { - - int tabContainerWidth = totalTabWidth == 0 ? cw : totalTabWidth; - int tabContainerHeight = totalTabHeight == 0 ? ch : totalTabHeight; - - int tabContainerX = 0; - int tabContainerY = 0; - if (tabPlacement == BOTTOM) { - tabContainerY = bounds.height - tabContainerHeight; - } else if (tabPlacement == RIGHT) { - tabContainerX = bounds.width - tabContainerWidth; - } - child.setBounds(tabContainerX, tabContainerY, tabContainerWidth, tabContainerHeight); - } else { - child.setBounds(cx, cy, cw, ch); - } - } - } - layoutTabComponents(); - if (shouldChangeFocus) { - if (!requestFocusForVisibleComponent()) { - tabPane.requestFocus(); - } - } - } - - public void calculateLayoutInfo() { - int tc = tabPane.getTabCount(); - assureRectsCreated(tc); - calculateTabRects(tabPane.getTabPlacement(), tc); - } - - private void layoutTabComponents() { - if (JTattooUtilities.getJavaVersion() >= 1.6) { - if (tabContainer == null) { - return; - } - Rectangle rect = new Rectangle(); - Point delta = new Point(-tabContainer.getX(), -tabContainer.getY()); - if (scrollableTabLayoutEnabled()) { - translatePointToTabPanel(0, 0, delta); - } - for (int i = 0; i < tabPane.getTabCount(); i++) { - Component tabComponent = getTabComponentAt(i); - if (tabComponent == null) { - continue; - } - getTabBounds(i, rect); - Dimension preferredSize = tabComponent.getPreferredSize(); - Insets insets = getTabInsets(tabPane.getTabPlacement(), i); - int outerX = rect.x + insets.left + delta.x; - int outerY = rect.y + insets.top + delta.y; - int outerWidth = rect.width - insets.left - insets.right; - int outerHeight = rect.height - insets.top - insets.bottom; - //centralize component - int x = outerX + (outerWidth - preferredSize.width) / 2; - int y = outerY + (outerHeight - preferredSize.height) / 2; - int tabPlacement = tabPane.getTabPlacement(); - boolean isSeleceted = i == tabPane.getSelectedIndex(); - tabComponent.setBounds(x + getTabLabelShiftX(tabPlacement, i, isSeleceted), y + getTabLabelShiftY(tabPlacement, i, isSeleceted), preferredSize.width, preferredSize.height); - } - } - } - - protected void calculateTabRects(int tabPlacement, int tabCount) { - FontMetrics metrics = getFontMetrics(); - Dimension size = tabPane.getSize(); - Insets insets = tabPane.getInsets(); - Insets tabAreaInsets = getTabAreaInsets(tabPlacement); - int fontHeight = metrics.getHeight(); - int selectedIndex = tabPane.getSelectedIndex(); - int tabRunOverlay; - int i, j; - int x, y; - int returnAt; - boolean verticalTabRuns = (tabPlacement == LEFT || tabPlacement == RIGHT); - boolean leftToRight = JTattooUtilities.isLeftToRight(tabPane); - - // - // Calculate bounds within which a tab run must fit - // - switch (tabPlacement) { - case LEFT: - maxTabWidth = calculateMaxTabWidth(tabPlacement); - x = insets.left + tabAreaInsets.left; - y = insets.top + tabAreaInsets.top; - returnAt = size.height - (insets.bottom + tabAreaInsets.bottom); - break; - case RIGHT: - maxTabWidth = calculateMaxTabWidth(tabPlacement); - x = size.width - insets.right - tabAreaInsets.right - maxTabWidth; - y = insets.top + tabAreaInsets.top; - returnAt = size.height - (insets.bottom + tabAreaInsets.bottom); - break; - case BOTTOM: - maxTabHeight = calculateMaxTabHeight(tabPlacement); - x = insets.left + tabAreaInsets.left; - y = size.height - insets.bottom - tabAreaInsets.bottom - maxTabHeight; - returnAt = size.width - (insets.right + tabAreaInsets.right); - break; - case TOP: - default: - maxTabHeight = calculateMaxTabHeight(tabPlacement); - x = insets.left + tabAreaInsets.left; - y = insets.top + tabAreaInsets.top; - returnAt = size.width - (insets.right + tabAreaInsets.right); - break; - } - - tabRunOverlay = getTabRunOverlay(tabPlacement); - - runCount = 0; - selectedRun = -1; - - if (tabCount == 0) { - return; - } - - // Run through tabs and partition them into runs - Rectangle rect; - for (i = 0; i < tabCount; i++) { - rect = rects[i]; - - if (!verticalTabRuns) { - // Tabs on TOP or BOTTOM.... - if (i > 0) { - rect.x = rects[i - 1].x + rects[i - 1].width; - } else { - tabRuns[0] = 0; - runCount = 1; - maxTabWidth = 0; - rect.x = x; - } - rect.width = calculateTabWidth(tabPlacement, i, metrics); - maxTabWidth = Math.max(maxTabWidth, rect.width); - - // Never move a TAB down a run if it is in the first column. - // Even if there isn't enough room, moving it to a fresh - // line won't help. - if (rect.x != 2 + insets.left && rect.x + rect.width > returnAt) { - if (runCount > tabRuns.length - 1) { - expandTabRunsArray(); - } - tabRuns[runCount] = i; - runCount++; - rect.x = x; - } - // Initialize y position in case there's just one run - rect.y = y; - rect.height = maxTabHeight/* - 2*/; - - } else { - // Tabs on LEFT or RIGHT... - if (i > 0) { - rect.y = rects[i - 1].y + rects[i - 1].height; - } else { - tabRuns[0] = 0; - runCount = 1; - maxTabHeight = 0; - rect.y = y; - } - rect.height = calculateTabHeight(tabPlacement, i, fontHeight); - maxTabHeight = Math.max(maxTabHeight, rect.height); - - // Never move a TAB over a run if it is in the first run. - // Even if there isn't enough room, moving it to a fresh - // column won't help. - if (rect.y != 2 + insets.top && rect.y + rect.height > returnAt) { - if (runCount > tabRuns.length - 1) { - expandTabRunsArray(); - } - tabRuns[runCount] = i; - runCount++; - rect.y = y; - } - // Initialize x position in case there's just one column - rect.x = x; - rect.width = maxTabWidth/* - 2*/; - - } - if (i == selectedIndex) { - selectedRun = runCount - 1; - } - } - - if (runCount > 1) { - // Re-distribute tabs in case last run has leftover space - normalizeTabRuns(tabPlacement, tabCount, verticalTabRuns ? y : x, returnAt); - - selectedRun = getRunForTab(tabCount, selectedIndex); - - // Rotate run array so that selected run is first - if (shouldRotateTabRuns(tabPlacement)) { - rotateTabRuns(tabPlacement, selectedRun); - } - } - - // Step through runs from back to front to calculate - // tab y locations and to pad runs appropriately - for (i = runCount - 1; i >= 0; i--) { - int start = tabRuns[i]; - int next = tabRuns[i == (runCount - 1) ? 0 : i + 1]; - int end = (next != 0 ? next - 1 : tabCount - 1); - if (!verticalTabRuns) { - for (j = start; j <= end; j++) { - rect = rects[j]; - rect.y = y; - rect.x += getTabRunIndent(tabPlacement, i); - } - if (shouldPadTabRun(tabPlacement, i)) { - padTabRun(tabPlacement, start, end, returnAt); - } - if (tabPlacement == BOTTOM) { - y -= (maxTabHeight - tabRunOverlay); - } else { - y += (maxTabHeight - tabRunOverlay); - } - } else { - for (j = start; j <= end; j++) { - rect = rects[j]; - rect.x = x; - rect.y += getTabRunIndent(tabPlacement, i); - } - if (shouldPadTabRun(tabPlacement, i)) { - padTabRun(tabPlacement, start, end, returnAt); - } - if (tabPlacement == RIGHT) { - x -= (maxTabWidth - tabRunOverlay); - } else { - x += (maxTabWidth - tabRunOverlay); - } - } - } - - // Pad the selected tab so that it appears raised in front - padSelectedTab(tabPlacement, selectedIndex); - - // if right to left and tab placement on the top or - // the bottom, flip x positions and adjust by widths - if (!leftToRight && !verticalTabRuns) { - int rightMargin = size.width - (insets.right + tabAreaInsets.right); - for (i = 0; i < tabCount; i++) { - rects[i].x = rightMargin - rects[i].x - rects[i].width; - } - } - } - - /* - * Rotates the run-index array so that the selected run is run[0] - */ - protected void rotateTabRuns(int tabPlacement, int selectedRun) { - for (int i = 0; i < selectedRun; i++) { - int save = tabRuns[0]; - for (int j = 1; j < runCount; j++) { - tabRuns[j - 1] = tabRuns[j]; - } - tabRuns[runCount - 1] = save; - } - } - - protected void normalizeTabRuns(int tabPlacement, int tabCount, int start, int max) { - // Only normalize the runs for top & bottom; normalizing - // doesn't look right for Metal's vertical tabs - // because the last run isn't padded and it looks odd to have - // fat tabs in the first vertical runs, but slimmer ones in the - // last (this effect isn't noticeable for horizontal tabs). - if (tabPlacement == TOP || tabPlacement == BOTTOM) { - int run = runCount - 1; - boolean keepAdjusting = true; - double weight = 1.25; - - // At this point the tab runs are packed to fit as many - // tabs as possible, which can leave the last run with a lot - // of extra space (resulting in very fat tabs on the last run). - // So we'll attempt to distribute this extra space more evenly - // across the runs in order to make the runs look more consistent. - // - // Starting with the last run, determine whether the last tab in - // the previous run would fit (generously) in this run; if so, - // move tab to current run and shift tabs accordingly. Cycle - // through remaining runs using the same algorithm. - // - while (keepAdjusting) { - int last = lastTabInRun(tabCount, run); - int prevLast = lastTabInRun(tabCount, run - 1); - int end; - int prevLastLen; - - end = rects[last].x + rects[last].width; - prevLastLen = (int) (maxTabWidth * weight); - - // Check if the run has enough extra space to fit the last tab - // from the previous row... - if (max - end > prevLastLen) { - - // Insert tab from previous row and shift rest over - tabRuns[run] = prevLast; - rects[prevLast].x = start; - for (int i = prevLast + 1; i <= last; i++) { - rects[i].x = rects[i - 1].x + rects[i - 1].width; - } - - } else if (run == runCount - 1) { - // no more room left in last run, so we're done! - keepAdjusting = false; - } - if (run - 1 > 0) { - // check previous run next... - run -= 1; - } else { - // check last run again...but require a higher ratio - // of extraspace-to-tabsize because we don't want to - // end up with too many tabs on the last run! - run = runCount - 1; - weight += .25; - } - } - } - } - - protected void padTabRun(int tabPlacement, int start, int end, int max) { - Rectangle lastRect = rects[end]; - if (tabPlacement == TOP || tabPlacement == BOTTOM) { - int runWidth = (lastRect.x + lastRect.width) - rects[start].x; - int deltaWidth = max - (lastRect.x + lastRect.width); - float factor = (float) deltaWidth / (float) runWidth; - - for (int j = start; j <= end; j++) { - Rectangle pastRect = rects[j]; - if (j > start) { - pastRect.x = rects[j - 1].x + rects[j - 1].width; - } - pastRect.width += Math.round((float) pastRect.width * factor); - } - lastRect.width = max - lastRect.x; - } else { - int runHeight = (lastRect.y + lastRect.height) - rects[start].y; - int deltaHeight = max - (lastRect.y + lastRect.height); - float factor = (float) deltaHeight / (float) runHeight; - - for (int j = start; j <= end; j++) { - Rectangle pastRect = rects[j]; - if (j > start) { - pastRect.y = rects[j - 1].y + rects[j - 1].height; - } - pastRect.height += Math.round((float) pastRect.height * factor); - } - lastRect.height = max - lastRect.y; - } - } - - protected void padSelectedTab(int tabPlacement, int selectedIndex) { -// if ((selectedIndex >= 0) && (selectedIndex < rects.length)) { -// Rectangle selRect = rects[selectedIndex]; -// Insets padInsets = getSelectedTabPadInsets(tabPlacement); -// selRect.x -= padInsets.left; -// selRect.width += (padInsets.left + padInsets.right); -// selRect.y -= padInsets.top; -// selRect.height += (padInsets.top + padInsets.bottom); -// } - } - } - - private class TabbedPaneScrollLayout extends TabbedPaneLayout { - - protected int preferredTabAreaHeight(int tabPlacement, int width) { - return calculateMaxTabHeight(tabPlacement); - } - - protected int preferredTabAreaWidth(int tabPlacement, int height) { - return calculateMaxTabWidth(tabPlacement); - } - - public void layoutContainer(Container parent) { - int tabPlacement = tabPane.getTabPlacement(); - int tc = tabPane.getTabCount(); - Insets insets = tabPane.getInsets(); - int selectedIndex = tabPane.getSelectedIndex(); - Component visibleComponent = getVisibleComponent(); - - calculateLayoutInfo(); - - Component selectedComponent = null; - if (selectedIndex < 0) { - if (visibleComponent != null) { - // The last tab was removed, so remove the component - setVisibleComponent(null); - } - } else { - try { - selectedComponent = tabPane.getComponentAt(selectedIndex); - } catch (Exception ex) { -// outStream.print("----------------------------------------------------\n"); -// ex.printStackTrace(outStream); - } - } - boolean shouldChangeFocus = false; - - // In order to allow programs to use a single component - // as the display for multiple tabs, we will not change - // the visible compnent if the currently selected tab - // has a null component. This is a bit dicey, as we don't - // explicitly state we support this in the spec, but since - // programs are now depending on this, we're making it work. - // - if (selectedComponent != null) { - if (selectedComponent != visibleComponent && visibleComponent != null) { - if (SwingUtilities.findFocusOwner(visibleComponent) != null) { - shouldChangeFocus = true; - } - } - setVisibleComponent(selectedComponent); - } - int tx, ty, tw, th; // tab area bounds - int cx, cy, cw, ch; // content area bounds - Insets contentInsets = getContentBorderInsets(tabPlacement); - Rectangle bounds = tabPane.getBounds(); - int numChildren = tabPane.getComponentCount(); - - int space = 60; - if ((numChildren > 0) && (tc > 0)) { - switch (tabPlacement) { - case LEFT: - // calculate tab area bounds - tw = calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth); - th = bounds.height - insets.top - insets.bottom; - tx = insets.left; - ty = insets.top; - - // calculate content area bounds - cx = tx + tw + contentInsets.left; - cy = ty + contentInsets.top; - cw = bounds.width - insets.left - insets.right - tw - contentInsets.left - contentInsets.right; - ch = bounds.height - insets.top - insets.bottom - contentInsets.top - contentInsets.bottom; - break; - case RIGHT: - // calculate tab area bounds - tw = calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth); - th = bounds.height - insets.top - insets.bottom; - tx = bounds.width - insets.right - tw; - ty = insets.top; - - // calculate content area bounds - cx = insets.left + contentInsets.left; - cy = insets.top + contentInsets.top; - cw = bounds.width - insets.left - insets.right - tw - contentInsets.left - contentInsets.right; - ch = bounds.height - insets.top - insets.bottom - contentInsets.top - contentInsets.bottom; - break; - case BOTTOM: - // calculate tab area bounds - tw = bounds.width - insets.left - insets.right; - th = calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight); - tx = insets.left; - ty = bounds.height - insets.bottom - th; - - // calculate content area bounds - cx = insets.left + contentInsets.left; - cy = insets.top + contentInsets.top; - cw = bounds.width - insets.left - insets.right - contentInsets.left - contentInsets.right; - ch = bounds.height - insets.top - insets.bottom - th - contentInsets.top - contentInsets.bottom; - break; - case TOP: - default: - // calculate tab area bounds - tw = bounds.width - insets.left - insets.right; - th = calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight); - tx = insets.left; - ty = insets.top; - - // calculate content area bounds - cx = tx + contentInsets.left; - cy = ty + th + contentInsets.top; - cw = bounds.width - insets.left - insets.right - contentInsets.left - contentInsets.right; - ch = bounds.height - insets.top - insets.bottom - th - contentInsets.top - contentInsets.bottom; - } - for (int i = 0; i < numChildren; i++) { - Component child = tabPane.getComponent(i); - if (child instanceof ScrollableTabViewport) { - JViewport viewport = (JViewport) child; - Rectangle viewRect = viewport.getViewRect(); - int vw = tw; - int vh = th; - switch (tabPlacement) { - case LEFT: - case RIGHT: - int totalTabHeight = rects[tc - 1].y + rects[tc - 1].height; - if (totalTabHeight > th) { - // Allow space for scrollbuttons - vh = Math.max(th - space, space); - if (totalTabHeight - viewRect.y <= vh) { - // Scrolled to the end, so ensure the viewport size is - // such that the scroll offset aligns with a tab - vh = totalTabHeight - viewRect.y; - } - } - break; - case BOTTOM: - case TOP: - default: - int totalTabWidth = rects[tc - 1].x + rects[tc - 1].width; - if (totalTabWidth > tw) { - // Allow space for scrollbuttons - vw = Math.max(tw - space, space); - if (totalTabWidth - viewRect.x <= vw) { - // Scrolled to the end, so ensure the viewport size is - // such that the scroll offset aligns with a tab - vw = totalTabWidth - viewRect.x; - } - } - } - - child.setBounds(tx, ty, vw, vh); - - } else if (child instanceof ScrollableTabButton) { - ScrollableTabButton scrollbutton = (ScrollableTabButton) child; - Dimension bsize = scrollbutton.getPreferredSize(); - int bx = 0; - int by = 0; - int bw = bsize.width; - int bh = bsize.height; - boolean visible = false; - - switch (tabPlacement) { - case LEFT: - case RIGHT: - int totalTabHeight = rects[tc - 1].y + rects[tc - 1].height; - if (totalTabHeight > th) { - int dir = scrollbutton.scrollsForward() ? SOUTH : NORTH; - scrollbutton.setDirection(dir); - visible = true; - bx = tabPlacement == LEFT ? tw - insets.left - tabAreaInsets.bottom - bsize.width : bounds.width - insets.left - bsize.width; - by = dir == SOUTH ? bounds.height - insets.bottom - 2 * bsize.height - 2 : bounds.height - insets.bottom - 3 * bsize.height - 2; - } - break; - - case BOTTOM: - case TOP: - default: - int totalTabWidth = rects[tc - 1].x + rects[tc - 1].width; - if (totalTabWidth > tw) { - int dir = scrollbutton.scrollsForward() ? EAST : WEST; - scrollbutton.setDirection(dir); - visible = true; - bx = dir == EAST ? bounds.width - insets.left - 2 * bsize.width - 2 : bounds.width - insets.left - 3 * bsize.width - 2; - by = ty + (th - bsize.height - tabAreaInsets.bottom) / 2; - if (tabPlacement == BOTTOM) { - by += tabAreaInsets.bottom; - } else { - by++; - } - } - } - - child.setVisible(visible); - if (visible) { - child.setBounds(bx, by, bw, bh); - } - - } else if (child instanceof ScrollablePopupMenuTabButton) { - ScrollablePopupMenuTabButton button = (ScrollablePopupMenuTabButton) child; - Dimension bsize = button.getPreferredSize(); - int bx = 0; - int by = 0; - int bw = bsize.width; - int bh = bsize.height; - boolean visible = false; - - switch (tabPlacement) { - case LEFT: - case RIGHT: - int totalTabHeight = rects[tc - 1].y + rects[tc - 1].height; - if (totalTabHeight > th) { - visible = true; - bx = tabPlacement == LEFT ? tw - insets.left - tabAreaInsets.bottom - bsize.width : bounds.width - insets.left - bsize.width; - by = bounds.height - insets.bottom - bsize.height; - } - break; - - case BOTTOM: - case TOP: - default: - int totalTabWidth = rects[tc - 1].x + rects[tc - 1].width; - if (totalTabWidth > tw) { - visible = true; - bx = bounds.width - insets.left - bsize.width; - by = ty + (th - bsize.height - tabAreaInsets.bottom) / 2; - if (tabPlacement == BOTTOM) { - by += tabAreaInsets.bottom; - } else { - by++; - } - } - } - - child.setVisible(visible); - if (visible) { - child.setBounds(bx, by, bw, bh); - } - } else { - // All content children... - child.setBounds(cx, cy, cw, ch); - } - } - super.layoutTabComponents(); - if (shouldChangeFocus) { - if (!requestFocusForVisibleComponent()) { - tabPane.requestFocus(); - } - } - } - } - - protected void calculateTabRects(int tabPlacement, int tabCount) { - FontMetrics metrics = getFontMetrics(); - Dimension size = tabPane.getSize(); - Insets insets = tabPane.getInsets(); - Insets tabAreaInsets = getTabAreaInsets(tabPlacement); - int fontHeight = metrics.getHeight(); - boolean verticalTabRuns = (tabPlacement == LEFT || tabPlacement == RIGHT); - boolean leftToRight = JTattooUtilities.isLeftToRight(tabPane); - int x = tabAreaInsets.left; - int y = tabAreaInsets.top; - int totalWidth = 0; - int totalHeight = 0; - - // - // Calculate bounds within which a tab run must fit - // - switch (tabPlacement) { - case LEFT: - case RIGHT: - maxTabWidth = calculateMaxTabWidth(tabPlacement); - break; - case BOTTOM: - case TOP: - default: - maxTabHeight = calculateMaxTabHeight(tabPlacement); - } - - runCount = 0; - selectedRun = -1; - - if (tabCount == 0) { - return; - } - - selectedRun = 0; - runCount = 1; - - // Run through tabs and lay them out in a single run - Rectangle rect; - for (int i = 0; i < tabCount; i++) { - rect = rects[i]; - - if (!verticalTabRuns) { - // Tabs on TOP or BOTTOM.... - if (i > 0) { - rect.x = rects[i - 1].x + rects[i - 1].width; - } else { - tabRuns[0] = 0; - maxTabWidth = 0; - totalHeight += maxTabHeight; - rect.x = x; - } - rect.width = calculateTabWidth(tabPlacement, i, metrics); - totalWidth = rect.x + rect.width; - maxTabWidth = Math.max(maxTabWidth, rect.width); - - rect.y = y; - rect.height = maxTabHeight/* - 2*/; - - } else { - // Tabs on LEFT or RIGHT... - if (i > 0) { - rect.y = rects[i - 1].y + rects[i - 1].height; - } else { - tabRuns[0] = 0; - maxTabHeight = 0; - totalWidth = maxTabWidth; - rect.y = y; - } - rect.height = calculateTabHeight(tabPlacement, i, fontHeight); - totalHeight = rect.y + rect.height; - maxTabHeight = Math.max(maxTabHeight, rect.height); - - rect.x = x; - rect.width = maxTabWidth/* - 2*/; - - } - } - - // if right to left and tab placement on the top or - // the bottom, flip x positions and adjust by widths - if (!leftToRight && !verticalTabRuns) { - int rightMargin = size.width - (insets.right + tabAreaInsets.right); - for (int i = 0; i < tabCount; i++) { - rects[i].x = rightMargin - rects[i].x - rects[i].width; - } - } - //tabPanel.setSize(totalWidth, totalHeight); - tabScroller.tabPanel.setPreferredSize(new Dimension(totalWidth, totalHeight)); - } - } - - private class ScrollableTabSupport implements ChangeListener { - - public ScrollableTabViewport viewport; - public ScrollableTabPanel tabPanel; - public ScrollableTabButton scrollForwardButton; - public ScrollableTabButton scrollBackwardButton; - public ScrollablePopupMenuTabButton popupMenuButton; - public int leadingTabIndex; - private Point tabViewPosition = new Point(0, 0); - - ScrollableTabSupport(int tabPlacement) { - viewport = new ScrollableTabViewport(); - tabPanel = new ScrollableTabPanel(); - - viewport.setView(tabPanel); - viewport.addChangeListener(this); - - if (tabPlacement == TOP || tabPlacement == BOTTOM) { - scrollForwardButton = new ScrollableTabButton(EAST); - scrollBackwardButton = new ScrollableTabButton(WEST); - - } else { // tabPlacement = LEFT || RIGHT - scrollForwardButton = new ScrollableTabButton(SOUTH); - scrollBackwardButton = new ScrollableTabButton(NORTH); - } - popupMenuButton = new ScrollablePopupMenuTabButton(); - } - - public void scrollForward(int tabPlacement) { - Dimension viewSize = viewport.getViewSize(); - Rectangle viewRect = viewport.getViewRect(); - - if (tabPlacement == TOP || tabPlacement == BOTTOM) { - if (viewRect.width >= viewSize.width - viewRect.x) { - return; // no room left to scroll - } - } else { - // tabPlacement == LEFT || tabPlacement == RIGHT - if (viewRect.height >= viewSize.height - viewRect.y) { - return; - } - } - setLeadingTabIndex(tabPlacement, leadingTabIndex + 1); - tabPane.doLayout(); - } - - public void scrollBackward(int tabPlacement) { - if (leadingTabIndex == 0) { - return; // no room left to scroll - } - setLeadingTabIndex(tabPlacement, leadingTabIndex - 1); - tabPane.doLayout(); - } - - public void scrollTabToVisible(int tabPlacement, int index) { - if (index <= leadingTabIndex) { - setLeadingTabIndex(tabPlacement, index); - } else { - Rectangle viewRect = viewport.getViewRect(); - switch (tabPlacement) { - case TOP: - case BOTTOM: { - int i = index; - int x = viewRect.width - rects[index].width; - while ((i > 0) && (x - rects[i - 1].width >= 0)) { - i--; - x -= rects[i].width; - } - if (leadingTabIndex < i) { - setLeadingTabIndex(tabPlacement, i); - } - break; - - } - case LEFT: - case RIGHT: { - int i = index; - int y = viewRect.height - rects[index].height; - while ((i > 0) && (y - rects[i - 1].height > 0)) { - i--; - y -= rects[i].height; - } - if (leadingTabIndex < i) { - setLeadingTabIndex(tabPlacement, i); - } - break; - } - } - } - } - - public void setLeadingTabIndex(int tabPlacement, int index) { - leadingTabIndex = index; - Dimension viewSize = viewport.getViewSize(); - Rectangle viewRect = viewport.getViewRect(); - - switch (tabPlacement) { - case TOP: - case BOTTOM: - tabViewPosition.x = leadingTabIndex == 0 ? 0 : rects[leadingTabIndex].x; - - if ((viewSize.width - tabViewPosition.x) < viewRect.width) { - // We've scrolled to the end, so adjust the viewport size - // to ensure the view position remains aligned on a tab boundary - Dimension extentSize = new Dimension(viewSize.width - tabViewPosition.x, viewRect.height); - viewport.setExtentSize(extentSize); - } - break; - case LEFT: - case RIGHT: - tabViewPosition.y = leadingTabIndex == 0 ? 0 : rects[leadingTabIndex].y; - - if ((viewSize.height - tabViewPosition.y) < viewRect.height) { - // We've scrolled to the end, so adjust the viewport size - // to ensure the view position remains aligned on a tab boundary - Dimension extentSize = new Dimension(viewRect.width, viewSize.height - tabViewPosition.y); - viewport.setExtentSize(extentSize); - } - } - viewport.setViewPosition(tabViewPosition); - } - - public void stateChanged(ChangeEvent e) { - JViewport vp = (JViewport) e.getSource(); - int tabPlacement = tabPane.getTabPlacement(); - int tc = tabPane.getTabCount(); - Rectangle vpRect = vp.getBounds(); - Dimension viewSize = vp.getViewSize(); - Rectangle viewRect = vp.getViewRect(); - - leadingTabIndex = getClosestTab(viewRect.x, viewRect.y); - if (leadingTabIndex >= rects.length) { - return; - } - - // If the tab isn't right aligned, adjust it. - if (leadingTabIndex + 1 < tc) { - switch (tabPlacement) { - case TOP: - case BOTTOM: - if (rects[leadingTabIndex].x < viewRect.x) { - leadingTabIndex++; - } - break; - case LEFT: - case RIGHT: - if (rects[leadingTabIndex].y < viewRect.y) { - leadingTabIndex++; - } - break; - } - } - Insets contentInsets = getContentBorderInsets(tabPlacement); - switch (tabPlacement) { - case LEFT: - tabPane.repaint(vpRect.x + vpRect.width, vpRect.y, contentInsets.left, vpRect.height); - scrollBackwardButton.setEnabled(viewRect.y > 0); - scrollForwardButton.setEnabled(leadingTabIndex < tc - 1 && viewSize.height - viewRect.y > viewRect.height); - break; - case RIGHT: - tabPane.repaint(vpRect.x - contentInsets.right, vpRect.y, contentInsets.right, vpRect.height); - scrollBackwardButton.setEnabled(viewRect.y > 0); - scrollForwardButton.setEnabled(leadingTabIndex < tc - 1 && viewSize.height - viewRect.y > viewRect.height); - break; - case BOTTOM: - tabPane.repaint(vpRect.x, vpRect.y - contentInsets.bottom, vpRect.width, contentInsets.bottom); - scrollBackwardButton.setEnabled(viewRect.x > 0); - scrollForwardButton.setEnabled(leadingTabIndex < tc - 1 && viewSize.width - viewRect.x > viewRect.width); - break; - case TOP: - default: - tabPane.repaint(vpRect.x, vpRect.y + vpRect.height, vpRect.width, contentInsets.top); - scrollBackwardButton.setEnabled(viewRect.x > 0); - scrollForwardButton.setEnabled(leadingTabIndex < tc - 1 && viewSize.width - viewRect.x > viewRect.width); - } - } - - } - - private class ScrollableTabViewport extends JViewport implements UIResource { - - public ScrollableTabViewport() { - setScrollMode(SIMPLE_SCROLL_MODE); - setOpaque(false); - } - - } - - private class ScrollableTabPanel extends JPanel implements UIResource { - - public ScrollableTabPanel() { - setLayout(null); - setOpaque(false); - } - - public void paintComponent(Graphics g) { - super.paintComponent(g); - paintScrollContentBorder(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex(), 0, 0, getWidth(), getHeight()); - paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex()); - } - - public void doLayout() { - if (getComponentCount() > 0) { - Component child = getComponent(0); - child.setBounds(0, 0, getWidth(), getHeight()); - } - } - } - - public class ArrowButton extends JButton implements SwingConstants { - - protected int direction; - - public ArrowButton(int direction) { - super(); - this.direction = direction; - setRequestFocusEnabled(false); - if (simpleButtonBorder) { - Color cLo = getLoBorderColor(0); - Color cHi = AbstractLookAndFeel.getTheme().getControlHighlight(); - setBorder(BorderFactory.createEtchedBorder(cHi, cLo)); - } - } - - public int getDirection() { - return direction; - } - - public void setDirection(int dir) { - direction = dir; - } - - public void paint(Graphics g) { - super.paint(g); - // Draw the arrow - int w = getSize().width; - int h = getSize().height; - int size = Math.min((h - 4) / 3, (w - 4) / 3); - size = Math.max(size, 2); - paintTriangle(g, (w - size) / 2 + 1, (h - size) / 2 + 1, size); - } - - public Dimension getPreferredSize() { - return new Dimension(17, 17); - } - - public Dimension getMinimumSize() { - return new Dimension(5, 5); - } - - public Dimension getMaximumSize() { - return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); - } - - public boolean isFocusTraversable() { - return false; - } - - public void paintTriangle(Graphics g, int x, int y, int size) { - Color oldColor = g.getColor(); - int mid, i, j; - size = Math.max(size, 2); - mid = (size / 2) - 1; - - Color enabledColor = AbstractLookAndFeel.getTheme().getButtonForegroundColor(); - Color disabledColor = AbstractLookAndFeel.getTheme().getDisabledForegroundColor(); - - g.translate(x, y); - if (isEnabled()) { - g.setColor(enabledColor); - } else { - g.setColor(disabledColor); - } - - switch (direction) { - case NORTH: - for (i = 0; i < size; i++) { - g.drawLine(mid - i, i, mid + i, i); - } - break; - case SOUTH: - j = 0; - for (i = size - 1; i >= 0; i--) { - g.drawLine(mid - i, j, mid + i, j); - j++; - } - break; - case WEST: - for (i = 0; i < size; i++) { - g.drawLine(i, mid - i, i, mid + i); - } - break; - case EAST: - j = 0; - for (i = size - 1; i >= 0; i--) { - g.drawLine(j, mid - i, j, mid + i); - j++; - } - break; - } - g.translate(-x, -y); - g.setColor(oldColor); - } - } - - private class ScrollableTabButton extends ArrowButton implements UIResource, SwingConstants { - - public ScrollableTabButton(int direction) { - super(direction); - } - - public boolean scrollsForward() { - return direction == EAST || direction == SOUTH; - } - } - - private class ScrollablePopupMenuTabButton extends ArrowButton implements UIResource, SwingConstants { - - public ScrollablePopupMenuTabButton() { - super(SOUTH); - } - } - -// Controller: event listeners - /** - * This inner class is marked "public" due to a compiler bug. - * This class should be treated as a "protected" inner class. - * Instantiate it only within subclasses of BaseTabbedPaneUI. - */ - public class PropertyChangeHandler implements PropertyChangeListener { - - public void propertyChange(PropertyChangeEvent e) { - JTabbedPane pane = (JTabbedPane) e.getSource(); - String name = e.getPropertyName(); - boolean isScrollLayout = scrollableTabLayoutEnabled(); - if ("mnemonicAt".equals(name)) { - updateMnemonics(); - pane.repaint(); - } else if ("displayedMnemonicIndexAt".equals(name)) { - pane.repaint(); - } else if ("indexForTitle".equals(name)) { - int index = ((Integer) e.getNewValue()).intValue(); - String title = tabPane.getTitleAt(index); - if (BasicHTML.isHTMLString(title)) { - if (htmlViews == null) { // Initialize vector - htmlViews = createHTMLViewList(); - } else { // Vector already exists - View v = BasicHTML.createHTMLView(tabPane, title); - htmlViews.set(index, v); - } - } else { - if (htmlViews != null && htmlViews.get(index) != null) { - htmlViews.set(index, null); - } - } - updateMnemonics(); - } else if ("tabLayoutPolicy".equals(name)) { - BaseTabbedPaneUI.this.uninstallUI(pane); - BaseTabbedPaneUI.this.installUI(pane); - } else if ("background".equals(name) && isScrollLayout) { - Color newVal = (Color) e.getNewValue(); - tabScroller.tabPanel.setBackground(newVal); - tabScroller.viewport.setBackground(newVal); - Color newColor = selectedColor == null ? newVal : selectedColor; - tabScroller.scrollForwardButton.setBackground(newColor); - tabScroller.scrollBackwardButton.setBackground(newColor); - } else if ("indexForTabComponent".equals(name)) { - if (tabContainer != null) { - tabContainer.removeUnusedTabComponents(); - } - try { - Component tabComponent = getTabComponentAt(((Integer) e.getNewValue()).intValue()); - if (tabComponent != null) { - if (tabContainer == null) { - installTabContainer(); - } else { - addMyPropertyChangeListeners(tabComponent); - tabContainer.add(tabComponent); - } - } - } catch (Exception ex) { - } - tabPane.revalidate(); - tabPane.repaint(); - } else if ("componentOrientation".equals(name)) { - pane.revalidate(); - pane.repaint(); - } else if ("tabAreaBackground".equals(name)) { - pane.revalidate(); - pane.repaint(); - } - } - } - - public class MyTabComponentListener implements PropertyChangeListener { - - public void propertyChange(PropertyChangeEvent evt) { - if ("font".equals(evt.getPropertyName()) || "text".equals(evt.getPropertyName())) { - tabPane.revalidate(); - tabPane.repaint(); - } - } - } - - /** - * This inner class is marked "public" due to a compiler bug. - * This class should be treated as a "protected" inner class. - * Instantiate it only within subclasses of BaseTabbedPaneUI. - */ - public class TabSelectionHandler implements ChangeListener { - - public void stateChanged(ChangeEvent e) { - JTabbedPane tabPane = (JTabbedPane) e.getSource(); - if (JTattooUtilities.getJavaVersion() >= 1.4) { - if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) { - int index = tabPane.getSelectedIndex(); - if (index >= 0) { - BaseTabbedPaneUI ui = (BaseTabbedPaneUI) tabPane.getUI(); - ui.tabScroller.scrollTabToVisible(tabPane.getTabPlacement(), index); - } - } - } - tabPane.revalidate(); - tabPane.repaint(); - } - } - - public class TabComponentHandler implements ComponentListener { - - public void componentResized(ComponentEvent ce) { - SwingUtilities.invokeLater( () -> tabPane.doLayout() ); - } - - public void componentMoved(ComponentEvent ce) { - } - - public void componentShown(ComponentEvent ce) { - - } - - public void componentHidden(ComponentEvent ce) { - } - } - - /** - * This inner class is marked "public" due to a compiler bug. - * This class should be treated as a "protected" inner class. - * Instantiate it only within subclasses of BaseTabbedPaneUI. - */ - public class MouseHandler extends MouseAdapter { - - public void mouseClicked(MouseEvent e) { - if (scrollableTabLayoutEnabled()) { - MouseListener[] ml = tabPane.getMouseListeners(); - for (int i = 0; i < ml.length; i++) { - ml[i].mouseClicked(e); - } - } - } - - public void mousePressed(MouseEvent e) { - if (scrollableTabLayoutEnabled()) { - MouseListener[] ml = tabPane.getMouseListeners(); - for (int i = 0; i < ml.length; i++) { - ml[i].mousePressed(e); - } - } - if (!tabPane.isEnabled()) { - return; - } - int tabIndex = getTabAtLocation(e.getX(), e.getY()); - if (tabIndex >= 0 && tabPane.isEnabledAt(tabIndex)) { - if (tabIndex == tabPane.getSelectedIndex()) { - if (tabPane.isRequestFocusEnabled()) { - tabPane.requestFocus(); - tabPane.repaint(getTabBounds(tabPane, tabIndex)); - } - } else { - tabPane.setSelectedIndex(tabIndex); - } - } - } - - public void mouseReleased(MouseEvent e) { - if (scrollableTabLayoutEnabled()) { - MouseListener[] ml = tabPane.getMouseListeners(); - for (int i = 0; i < ml.length; i++) { - ml[i].mouseReleased(e); - } - } - } - - public void mouseEntered(MouseEvent e) { - if (scrollableTabLayoutEnabled()) { - MouseListener[] ml = tabPane.getMouseListeners(); - for (int i = 0; i < ml.length; i++) { - ml[i].mouseEntered(e); - } - } - } - - public void mouseExited(MouseEvent e) { - if (scrollableTabLayoutEnabled()) { - MouseListener[] ml = tabPane.getMouseListeners(); - for (int i = 0; i < ml.length; i++) { - ml[i].mouseExited(e); - } - } - rolloverIndex = -1; - if (rolloverIndex != oldRolloverIndex) { - if ((oldRolloverIndex >= 0) && (oldRolloverIndex < tabPane.getTabCount())) { - tabPane.repaint(getTabBounds(tabPane, oldRolloverIndex)); - } - if ((rolloverIndex >= 0) && (rolloverIndex < tabPane.getTabCount())) { - tabPane.repaint(getTabBounds(tabPane, rolloverIndex)); - } - oldRolloverIndex = rolloverIndex; - } - } - } - - /** - * This inner class is marked "public" due to a compiler bug. - * This class should be treated as a "protected" inner class. - * Instantiate it only within subclasses of BaseTabbedPaneUI. - */ - public class MouseMotionHandler extends MouseMotionAdapter { - - public void mouseDragged(MouseEvent e) { - if (scrollableTabLayoutEnabled()) { - MouseMotionListener[] mml = tabPane.getMouseMotionListeners(); - for (int i = 0; i < mml.length; i++) { - mml[i].mouseDragged(e); - } - } - } - - public void mouseMoved(MouseEvent e) { - if (scrollableTabLayoutEnabled()) { - MouseMotionListener[] mml = tabPane.getMouseMotionListeners(); - for (int i = 0; i < mml.length; i++) { - mml[i].mouseMoved(e); - } - } - rolloverIndex = getTabAtLocation(e.getX(), e.getY()); - if (rolloverIndex != oldRolloverIndex) { - if ((oldRolloverIndex >= 0) && (oldRolloverIndex < tabPane.getTabCount())) { - tabPane.repaint(getTabBounds(tabPane, oldRolloverIndex)); - } - if ((rolloverIndex >= 0) && (rolloverIndex < tabPane.getTabCount())) { - tabPane.repaint(getTabBounds(tabPane, rolloverIndex)); - } - oldRolloverIndex = rolloverIndex; - } - } - } - - /** - * This inner class is marked "public" due to a compiler bug. - * This class should be treated as a "protected" inner class. - * Instantiate it only within subclasses of BaseTabbedPaneUI. - */ - public class FocusHandler extends FocusAdapter { - - public void focusGained(FocusEvent e) { - JTabbedPane tabPane = (JTabbedPane) e.getSource(); - int tabCount = tabPane.getTabCount(); - int selectedIndex = tabPane.getSelectedIndex(); - if (selectedIndex != -1 && tabCount > 0 && tabCount == rects.length) { - tabPane.repaint(getTabBounds(tabPane, selectedIndex)); - } - } - - public void focusLost(FocusEvent e) { - JTabbedPane tabPane = (JTabbedPane) e.getSource(); - int tabCount = tabPane.getTabCount(); - int selectedIndex = tabPane.getSelectedIndex(); - if (selectedIndex != -1 && tabCount > 0 && tabCount == rects.length) { - tabPane.repaint(getTabBounds(tabPane, selectedIndex)); - } - } - } - - /* GES 2/3/99: - The container listener code was added to support HTML - rendering of tab titles. - - Ideally, we would be able to listen for property changes - when a tab is added or its text modified. At the moment - there are no such events because the Beans spec doesn't - allow 'indexed' property changes (i.e. tab 2's text changed - from A to B). - - In order to get around this, we listen for tabs to be added - or removed by listening for the container events. we then - queue up a runnable (so the component has a chance to complete - the add) which checks the tab title of the new component to see - if it requires HTML rendering. - - The Views (one per tab title requiring HTML rendering) are - stored in the htmlViews list, which is only allocated after - the first time we run into an HTML tab. Note that this list - is kept in step with the number of pages, and nulls are added - for those pages whose tab title do not require HTML rendering. - - This makes it easy for the paint and layout code to tell - whether to invoke the HTML engine without having to check - the string during time-sensitive operations. - - When we have added a way to listen for tab additions and - changes to tab text, this code should be removed and - replaced by something which uses that. */ - private class ContainerHandler implements ContainerListener { - - public void componentAdded(ContainerEvent e) { - JTabbedPane tp = (JTabbedPane) e.getContainer(); - TabbedPaneLayout layout = (TabbedPaneLayout) tp.getLayout(); - layout.layoutContainer(tp); - - Component child = e.getChild(); - if (child instanceof UIResource) { - return; - } - int index = tp.indexOfComponent(child); - String title = tp.getTitleAt(index); - boolean isHTML = BasicHTML.isHTMLString(title); - if (isHTML) { - if (htmlViews == null) { - // Initialize vector - htmlViews = createHTMLViewList(); - } else { - // Vector already exists - View v = BasicHTML.createHTMLView(tp, title); - htmlViews.add(index, v); - } - } else { - // Not HTML - if (htmlViews != null) { - // Add placeholder - htmlViews.add(index, null); - } // else nada! - } - } - - public void componentRemoved(ContainerEvent e) { - JTabbedPane tp = (JTabbedPane) e.getContainer(); - Component child = e.getChild(); - if (child instanceof UIResource) { - return; - } - - // NOTE 4/15/2002 (joutwate): - // This fix is implemented using client properties since there is - // currently no IndexPropertyChangeEvent. Once - // IndexPropertyChangeEvents have been added this code should be - // modified to use it. - Integer indexObj = (Integer) tp.getClientProperty("__index_to_remove__"); - if (indexObj != null) { - int index = indexObj.intValue(); - if (htmlViews != null && htmlViews.size() >= index) { - htmlViews.remove(index); - } - } - } - } - - private ArrayList createHTMLViewList() { - ArrayList viewList = new ArrayList(); - int count = tabPane.getTabCount(); - for (int i = 0; i < count; i++) { - String title = tabPane.getTitleAt(i); - if (BasicHTML.isHTMLString(title)) { - viewList.add(BasicHTML.createHTMLView(tabPane, title)); - } else { - viewList.add(null); - } - } - return viewList; - } - - private class TabContainer extends JPanel implements UIResource { - - private boolean notifyTabbedPane = true; - - public TabContainer() { - super(null); - setOpaque(false); - } - - public void remove(Component comp) { - int index = tabPane.indexOfTabComponent(comp); - PropertyChangeListener[] listeners = comp.getPropertyChangeListeners(); - for (int j = 0; j < listeners.length; j++) { - if (listeners[j] instanceof MyTabComponentListener) { - comp.removePropertyChangeListener(listeners[j]); - } - } - super.remove(comp); - if (notifyTabbedPane && index != -1) { - tabPane.setTabComponentAt(index, null); - } - } - - private void removeUnusedTabComponents() { - for (int i = 0; i < getComponentCount(); i++) { - Component c = getComponent(i); - if (!(c instanceof UIResource)) { - int index = tabPane.indexOfTabComponent(c); - if (index == -1) { - PropertyChangeListener[] listeners = c.getPropertyChangeListeners(); - for (int j = 0; j < listeners.length; j++) { - if (listeners[j] instanceof MyTabComponentListener) { - c.removePropertyChangeListener(listeners[j]); - } - } - super.remove(c); - } - } - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseTableHeaderUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseTableHeaderUI.java deleted file mode 100644 index a00a660d9..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseTableHeaderUI.java +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. - * - * JTattoo is multiple licensed. If your are an open source developer you can use - * it under the terms and conditions of the GNU General Public License version 2.0 - * or later as published by the Free Software Foundation. - * - * see: gpl-2.0.txt - * - * If you pay for a license you will become a registered user who could use the - * software under the terms and conditions of the GNU Lesser General Public License - * version 2.0 or later with classpath exception as published by the Free Software - * Foundation. - * - * see: lgpl-2.0.txt - * see: classpath-exception.txt - * - * Registered users could also use JTattoo under the terms and conditions of the - * Apache License, Version 2.0 as published by the Apache Software Foundation. - * - * see: APACHE-LICENSE-2.0.txt - */ -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.*; -import java.util.Enumeration; -import java.util.List; -import javax.swing.*; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicTableHeaderUI; -import javax.swing.table.*; - -/** - * - * @author Michael Hagen - */ -public class BaseTableHeaderUI extends BasicTableHeaderUI { - - private TableCellRenderer originalHeaderRenderer; - protected MouseAdapter myMouseAdapter = null; - protected MouseMotionAdapter myMouseMotionAdapter = null; - protected int rolloverCol = -1; - - public static ComponentUI createUI(JComponent h) { - return new BaseTableHeaderUI(); - } - - public void installUI(JComponent c) { - super.installUI(c); - if ((header != null) && header.getTable() != null) { - originalHeaderRenderer = header.getDefaultRenderer(); - if ((originalHeaderRenderer != null) - && "sun.swing.table.DefaultTableCellHeaderRenderer".equals(originalHeaderRenderer.getClass().getName())) { - header.setDefaultRenderer(new BaseDefaultHeaderRenderer()); - } - } - } - - public void uninstallUI(JComponent c) { - if ((header != null) && (header.getTable() != null)) { - if (header.getDefaultRenderer() instanceof BaseDefaultHeaderRenderer) { - header.setDefaultRenderer(originalHeaderRenderer); - } - } - super.uninstallUI(c); - } - - public void installListeners() { - super.installListeners(); - myMouseAdapter = new MouseAdapter() { - public void mouseReleased(MouseEvent e) { - if ((header == null) || (header.getTable() == null)) { - return; - } - boolean rolloverEnabled = Boolean.TRUE.equals(header.getClientProperty("rolloverEnabled")); - boolean sortingAllowed = false; - if (JTattooUtilities.getJavaVersion() >= 1.6) { - sortingAllowed = header.getTable().getRowSorter() != null; - } - if (rolloverEnabled || sortingAllowed || header.getReorderingAllowed()) { - if (header.getBounds().contains(e.getPoint())) { - int oldRolloverCol = rolloverCol; - rolloverCol = header.getColumnModel().getColumnIndexAtX(e.getX()); - updateRolloverColumn(oldRolloverCol, rolloverCol); - } else { - int oldRolloverCol = rolloverCol; - rolloverCol = -1; - updateRolloverColumn(oldRolloverCol, rolloverCol); - } - } - } - - public void mouseEntered(MouseEvent e) { - if ((header == null) || (header.getTable() == null)) { - return; - } - boolean rolloverEnabled = Boolean.TRUE.equals(header.getClientProperty("rolloverEnabled")); - boolean sortingAllowed = false; - if (JTattooUtilities.getJavaVersion() >= 1.6) { - sortingAllowed = header.getTable().getRowSorter() != null; - } - if (rolloverEnabled || sortingAllowed || header.getReorderingAllowed()) { - int oldRolloverCol = rolloverCol; - rolloverCol = header.getColumnModel().getColumnIndexAtX(e.getX()); - updateRolloverColumn(oldRolloverCol, rolloverCol); - } - } - - public void mouseExited(MouseEvent e) { - if ((header == null) || (header.getTable() == null)) { - return; - } - boolean rolloverEnabled = Boolean.TRUE.equals(header.getClientProperty("rolloverEnabled")); - boolean sortingAllowed = false; - if (JTattooUtilities.getJavaVersion() >= 1.6) { - sortingAllowed = header.getTable().getRowSorter() != null; - } - if (rolloverEnabled || sortingAllowed || header.getReorderingAllowed()) { - int oldRolloverCol = rolloverCol; - rolloverCol = -1; - updateRolloverColumn(oldRolloverCol, rolloverCol); - } - } - }; - myMouseMotionAdapter = new MouseMotionAdapter() { - public void mouseMoved(MouseEvent e) { - if ((header == null) || (header.getTable() == null)) { - return; - } - boolean rolloverEnabled = Boolean.TRUE.equals(header.getClientProperty("rolloverEnabled")); - boolean sortingAllowed = false; - if (JTattooUtilities.getJavaVersion() >= 1.6) { - sortingAllowed = header.getTable().getRowSorter() != null; - } - if (rolloverEnabled || sortingAllowed || header.getReorderingAllowed()) { - if (header.getDraggedColumn() == null) { - int oldRolloverCol = rolloverCol; - rolloverCol = header.getColumnModel().getColumnIndexAtX(e.getX()); - updateRolloverColumn(oldRolloverCol, rolloverCol); - } - } - } - - public void mouseDragged(MouseEvent e) { - if ((header == null) || (header.getTable() == null)) { - return; - } - boolean rolloverEnabled = Boolean.TRUE.equals(header.getClientProperty("rolloverEnabled")); - boolean sortingAllowed = false; - if (JTattooUtilities.getJavaVersion() >= 1.6) { - sortingAllowed = header.getTable().getRowSorter() != null; - } - if (rolloverEnabled || sortingAllowed || header.getReorderingAllowed()) { - if (header.getDraggedColumn() != null && header.getDraggedColumn().getIdentifier() != null) { - rolloverCol = header.getColumnModel().getColumnIndex(header.getDraggedColumn().getIdentifier()); - } else if (header.getResizingColumn() != null) { - rolloverCol = -1; - } - } - } - }; - header.addMouseListener(myMouseAdapter); - header.addMouseMotionListener(myMouseMotionAdapter); - } - - public void uninstallListeners() { - header.removeMouseListener(myMouseAdapter); - header.removeMouseMotionListener(myMouseMotionAdapter); - super.uninstallListeners(); - } - - protected boolean drawAllwaysActive() { - return false; - } - - protected boolean drawRolloverBar() { - return false; - } - - protected Component getHeaderRenderer(int col) { - if ((header == null) || (header.getTable() == null)) { - return null; - } - TableColumn tabCol = header.getColumnModel().getColumn(col); - TableCellRenderer renderer = tabCol.getHeaderRenderer(); - if (renderer == null) { - renderer = header.getDefaultRenderer(); - } - return renderer.getTableCellRendererComponent(header.getTable(), tabCol.getHeaderValue(), false, false, -1, col); - } - - private int getHeaderHeight() { - if ((header == null) || (header.getTable() == null)) { - return 0; - } - int height = 0; - boolean accomodatedDefault = false; - TableColumnModel columnModel = header.getColumnModel(); - for (int column = 0; column < columnModel.getColumnCount(); column++) { - TableColumn aColumn = columnModel.getColumn(column); - boolean isDefault = (aColumn.getHeaderRenderer() == null); - - if (!isDefault || !accomodatedDefault) { - Component comp = getHeaderRenderer(column); - int rendererHeight = comp.getPreferredSize().height; - height = Math.max(height, rendererHeight); - - // Configuring the header renderer to calculate its preferred size - // is expensive. Optimise this by assuming the default renderer - // always has the same height as the first non-zero height that - // it returns for a non-null/non-empty value. - if (isDefault && rendererHeight > 0) { - Object headerValue = aColumn.getHeaderValue(); - if (headerValue != null) { - headerValue = headerValue.toString(); - - if (headerValue != null && !headerValue.equals("")) { - accomodatedDefault = true; - } - } - } - } - } - return height + 2; - } - - /** - * Return the preferred size of the header. The preferred height is the maximum of the preferred heights of all of - * the components provided by the header renderers. The preferred width is the sum of the preferred widths of each - * column (plus inter-cell spacing). - */ - public Dimension getPreferredSize(JComponent c) { - if ((header == null) || (header.getTable() == null)) { - return new Dimension(0, 0); - } - long width = 0; - Enumeration enumeration = header.getColumnModel().getColumns(); - while (enumeration.hasMoreElements()) { - TableColumn aColumn = (TableColumn) enumeration.nextElement(); - width = width + aColumn.getPreferredWidth(); - } - if (width > Integer.MAX_VALUE) { - width = Integer.MAX_VALUE; - } - return new Dimension((int) width, getHeaderHeight()); - } - - protected void updateRolloverColumn(int oldColumn, int newColumn) { - if ((header == null) || (header.getTable() == null)) { - return; - } - header.repaint(header.getHeaderRect(oldColumn)); - header.repaint(header.getHeaderRect(newColumn)); - } - - protected void rolloverColumnUpdated(int oldColumn, int newColumn) { - // Empty to avoid multiple paints - } - - public void paint(Graphics g, JComponent c) { - if ((header == null) || (header.getTable() == null) || header.getColumnModel().getColumnCount() <= 0) { - return; - } - - boolean ltr = header.getComponentOrientation().isLeftToRight(); - Rectangle clip = g.getClipBounds(); - Point left = clip.getLocation(); - Point right = new Point(clip.x + clip.width - 1, clip.y); - TableColumnModel cm = header.getColumnModel(); - int cMin = header.columnAtPoint(ltr ? left : right); - int cMax = header.columnAtPoint(ltr ? right : left); - // This should never happen. - if (cMin == -1) { - cMin = 0; - } - // If the table does not have enough columns to fill the view we'll get -1. - // Replace this with the index of the last column. - if (cMax == -1) { - cMax = cm.getColumnCount() - 1; - } - - TableColumn draggedColumn = header.getDraggedColumn(); - Rectangle cellRect = header.getHeaderRect(ltr ? cMin : cMax); - int columnWidth; - TableColumn aColumn; - if (ltr) { - for (int column = cMin; column <= cMax; column++) { - aColumn = cm.getColumn(column); - columnWidth = aColumn.getWidth(); - cellRect.width = columnWidth; - if (aColumn != draggedColumn) { - paintCell(g, cellRect, column); - } - cellRect.x += columnWidth; - } - } else { - for (int column = cMax; column >= cMin; column--) { - aColumn = cm.getColumn(column); - columnWidth = aColumn.getWidth(); - cellRect.width = columnWidth; - if (aColumn != draggedColumn) { - paintCell(g, cellRect, column); - } - cellRect.x += columnWidth; - } - } - - // Paint the dragged column if we are dragging. - if (draggedColumn != null) { - int draggedColumnIndex = viewIndexForColumn(draggedColumn); - Rectangle draggedCellRect = header.getHeaderRect(draggedColumnIndex); - // Draw a gray well in place of the moving column. - g.setColor(header.getParent().getBackground()); - g.fillRect(draggedCellRect.x, draggedCellRect.y, draggedCellRect.width, draggedCellRect.height); - draggedCellRect.x += header.getDraggedDistance(); - - // Fill the background. - g.setColor(header.getBackground()); - g.fillRect(draggedCellRect.x, draggedCellRect.y, draggedCellRect.width, draggedCellRect.height); - paintCell(g, draggedCellRect, draggedColumnIndex); - } - - // Remove all components in the rendererPane. - rendererPane.removeAll(); - } - - protected void paintBackground(Graphics g, Rectangle cellRect, int col) { - Component component = getHeaderRenderer(col); - int x = cellRect.x; - int y = cellRect.y; - int w = cellRect.width; - int h = cellRect.height; - if (header.getBackground() instanceof ColorUIResource) { - if ((col == rolloverCol) && (component != null) && component.isEnabled()) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getRolloverColors(), x, y, w, h); - } else if (drawAllwaysActive() || JTattooUtilities.isFrameActive(header)) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getColHeaderColors(), x, y, w, h); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getInActiveColors(), x, y, w, h); - } - } else { - g.setColor(header.getBackground()); - g.fillRect(x, y, w, h); - } - } - - protected void paintCell(Graphics g, Rectangle cellRect, int col) { - if ((header == null) || (header.getTable() == null)) { - return; - } - Component component = getHeaderRenderer(col); - if (!(component instanceof BaseDefaultHeaderRenderer)) { - paintBackground(g, cellRect, col); - } - rendererPane.paintComponent(g, component, header, cellRect.x, cellRect.y, cellRect.width, cellRect.height, true); - } - - private int viewIndexForColumn(TableColumn aColumn) { - if ((header == null) || (header.getTable() == null)) { - return -1; - } - TableColumnModel cm = header.getColumnModel(); - for (int column = 0; column < cm.getColumnCount(); column++) { - if (cm.getColumn(column) == aColumn) { - return column; - } - } - return -1; - } - -//---------------------------------------------------------------------------------------------------------------------- -// inner classes -//---------------------------------------------------------------------------------------------------------------------- - private class BaseDefaultHeaderRenderer extends DefaultTableCellRenderer { - - public BaseDefaultHeaderRenderer() { - super(); - } - - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - return new MyRenderComponent(table, value, isSelected, hasFocus, row, column); - } - } - - private class MyRenderComponent extends JLabel { - - private JTable table = null; - private int col = 0; - private int gv = 0; - - public MyRenderComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) { - super(); - this.table = table; - this.col = col; - if (value != null) { - setText(value.toString()); - } else { - setText(""); - } - setOpaque(false); - setFont(UIManager.getFont("TableHeader.font")); - setForeground(UIManager.getColor("TableHeader.foreground")); - setHorizontalAlignment(JLabel.CENTER); - setHorizontalTextPosition(SwingConstants.LEADING); - setBorder(UIManager.getBorder("TableHeader.cellBorder")); - if ((JTattooUtilities.getJavaVersion() >= 1.6) && (UIManager.getLookAndFeel() instanceof AbstractLookAndFeel)) { - RowSorter rowSorter = table == null ? null : table.getRowSorter(); - List keyList = rowSorter == null ? null : rowSorter.getSortKeys(); - if ((keyList != null) && (keyList.size() > 0)) { - RowSorter.SortKey sortKey = (RowSorter.SortKey) keyList.get(0); - if (sortKey.getColumn() == table.convertColumnIndexToModel(col)) { - AbstractIconFactory iconFactory = ((AbstractLookAndFeel) UIManager.getLookAndFeel()).getIconFactory(); - if (sortKey.getSortOrder().equals(SortOrder.ASCENDING)) { - setIcon(iconFactory.getUpArrowIcon()); - } else if (sortKey.getSortOrder().equals(SortOrder.DESCENDING)) { - setIcon(iconFactory.getDownArrowIcon()); - } - } - } - } - gv = ColorHelper.getGrayValue(AbstractLookAndFeel.getTheme().getRolloverColor()); - } - - protected void paintBackground(Graphics g) { - int draggedColumn = -1; - if ((header != null) && (header.getTable() != null) && header.getDraggedColumn() != null) { - draggedColumn = header.getColumnModel().getColumnIndex(header.getDraggedColumn().getIdentifier()); - } - int w = getWidth(); - int h = getHeight(); - if ((table != null) && table.isEnabled() && (col == rolloverCol || col == draggedColumn)) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getRolloverColors(), 0, 0, w, h); - if (drawRolloverBar()) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - g.drawLine(0, 0, w - 1, 0); - g.drawLine(0, 1, w - 1, 1); - g.drawLine(0, 2, w - 1, 2); - } - } else if (drawAllwaysActive() || JTattooUtilities.isFrameActive(header)) { - if (header.getBackground() instanceof ColorUIResource) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getColHeaderColors(), 0, 0, w, h); - } else { - g.setColor(header.getBackground()); - g.fillRect(0, 0, w, h); - } - } else { - if (header.getBackground() instanceof ColorUIResource) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getInActiveColors(), 0, 0, w, h); - } else { - g.setColor(header.getBackground()); - g.fillRect(0, 0, w, h); - } - } - } - - public void paint(Graphics g) { - paintBackground(g); - if (rolloverCol == col) { - if (gv > 128) { - setForeground(Color.black); - } else { - setForeground(Color.white); - } - } - super.paint(g); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseTableUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseTableUI.java deleted file mode 100644 index c5aac860c..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseTableUI.java +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.FontMetrics; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicTableUI; - -/** - * @author Michael Hagen - */ -public class BaseTableUI extends BasicTableUI { - - public static ComponentUI createUI(JComponent c) { - return new BaseTableUI(); - } - - public void installDefaults() { - super.installDefaults(); - // Setup the rowheight. The font may change if UI switches - FontMetrics fm = table.getFontMetrics(table.getFont()); - table.setRowHeight(fm.getHeight() + (fm.getHeight() / 4)); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseTextAreaUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseTextAreaUI.java deleted file mode 100644 index aff18121c..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseTextAreaUI.java +++ /dev/null @@ -1,149 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.KeyEvent; -import java.beans.PropertyChangeEvent; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicTextAreaUI; -import javax.swing.text.DefaultEditorKit; -import javax.swing.text.JTextComponent; - -/** - * @author Michael Hagen - */ -public class BaseTextAreaUI extends BasicTextAreaUI { - - private Border orgBorder = null; - private FocusListener focusListener = null; - - public static ComponentUI createUI(JComponent c) { - return new BaseTextAreaUI(); - } - - public void installDefaults() { - super.installDefaults(); - updateBackground(); - } - - protected void installKeyboardActions() { - super.installKeyboardActions(); - if (JTattooUtilities.isMac()) { - InputMap im = (InputMap) UIManager.get("TextField.focusInputMap"); - int commandKey = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, commandKey), DefaultEditorKit.copyAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, commandKey), DefaultEditorKit.pasteAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, commandKey), DefaultEditorKit.cutAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.ALT_DOWN_MASK), DefaultEditorKit.nextWordAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.ALT_DOWN_MASK), DefaultEditorKit.previousWordAction); - } - } - - protected void installListeners() { - super.installListeners(); - - if (AbstractLookAndFeel.getTheme().doShowFocusFrame()) { - focusListener = new FocusListener() { - - public void focusGained(FocusEvent e) { - if (getComponent() != null) { - orgBorder = getComponent().getBorder(); - LookAndFeel laf = UIManager.getLookAndFeel(); - if (laf instanceof AbstractLookAndFeel && orgBorder instanceof UIResource) { - Border focusBorder = ((AbstractLookAndFeel)laf).getBorderFactory().getFocusFrameBorder(); - getComponent().setBorder(focusBorder); - } - getComponent().invalidate(); - getComponent().repaint(); - } - } - - public void focusLost(FocusEvent e) { - if (getComponent() != null) { - if (orgBorder instanceof UIResource) { - getComponent().setBorder(orgBorder); - } - getComponent().invalidate(); - getComponent().repaint(); - } - } - }; - getComponent().addFocusListener(focusListener); - } - } - - protected void uninstallListeners() { - getComponent().removeFocusListener(focusListener); - focusListener = null; - super.uninstallListeners(); - } - - protected void paintBackground(Graphics g) { - g.setColor(getComponent().getBackground()); - if (AbstractLookAndFeel.getTheme().doShowFocusFrame()) { - if (getComponent().hasFocus() && getComponent().isEditable()) { - g.setColor(AbstractLookAndFeel.getTheme().getFocusBackgroundColor()); - } - } - g.fillRect(0, 0, getComponent().getWidth(), getComponent().getHeight()); - } - - protected void paintSafely(Graphics g) { - Graphics2D g2D = (Graphics2D) g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - super.paintSafely(g); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } - - protected void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals("editable") || - evt.getPropertyName().equals("enabled")) { - updateBackground(); - } - super.propertyChange(evt); - } - - private void updateBackground() { - JTextComponent c = getComponent(); - if (c.getBackground() instanceof UIResource) { - if (!c.isEnabled() || !c.isEditable()) { - c.setBackground(AbstractLookAndFeel.getDisabledBackgroundColor()); - } else { - c.setBackground(AbstractLookAndFeel.getInputBackgroundColor()); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseTextFieldUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseTextFieldUI.java deleted file mode 100644 index 55dd2bc37..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseTextFieldUI.java +++ /dev/null @@ -1,126 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.KeyEvent; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.metal.MetalTextFieldUI; -import javax.swing.text.DefaultEditorKit; - -/** - * @author Michael Hagen - */ -public class BaseTextFieldUI extends MetalTextFieldUI { - - private Border orgBorder = null; - private FocusListener focusListener = null; - - public static ComponentUI createUI(JComponent c) { - return new BaseTextFieldUI(); - } - - protected void installKeyboardActions() { - super.installKeyboardActions(); - if (JTattooUtilities.isMac()) { - InputMap im = (InputMap) UIManager.get("TextField.focusInputMap"); - int commandKey = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, commandKey), DefaultEditorKit.copyAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, commandKey), DefaultEditorKit.pasteAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, commandKey), DefaultEditorKit.cutAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.ALT_DOWN_MASK), DefaultEditorKit.nextWordAction); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.ALT_DOWN_MASK), DefaultEditorKit.previousWordAction); - } - } - - protected void installListeners() { - super.installListeners(); - - if (AbstractLookAndFeel.getTheme().doShowFocusFrame()) { - focusListener = new FocusListener() { - public void focusGained(FocusEvent e) { - if (getComponent() != null) { - orgBorder = getComponent().getBorder(); - LookAndFeel laf = UIManager.getLookAndFeel(); - if (laf instanceof AbstractLookAndFeel && orgBorder instanceof UIResource) { - Border focusBorder = ((AbstractLookAndFeel) laf).getBorderFactory().getFocusFrameBorder(); - getComponent().setBorder(focusBorder); - } - getComponent().invalidate(); - getComponent().repaint(); - } - } - - public void focusLost(FocusEvent e) { - if (getComponent() != null) { - if (orgBorder instanceof UIResource) { - getComponent().setBorder(orgBorder); - } - getComponent().invalidate(); - getComponent().repaint(); - } - } - }; - - getComponent().addFocusListener(focusListener); - } - } - - protected void uninstallListeners() { - getComponent().removeFocusListener(focusListener); - focusListener = null; - super.uninstallListeners(); - } - - protected void paintBackground(Graphics g) { - g.setColor(getComponent().getBackground()); - if (AbstractLookAndFeel.getTheme().doShowFocusFrame()) { - Boolean doShow = (Boolean) getComponent().getClientProperty("doShowFocusFrame"); - if (doShow == null || doShow.booleanValue()) { - if (getComponent().hasFocus() && getComponent().isEditable()) { - g.setColor(AbstractLookAndFeel.getTheme().getFocusBackgroundColor()); - } - } - } - g.fillRect(0, 0, getComponent().getWidth(), getComponent().getHeight()); - } - - protected void paintSafely(Graphics g) { - Graphics2D g2D = (Graphics2D) g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - super.paintSafely(g); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseTitleButton.java b/src/jtattoo/src/com/jtattoo/plaf/BaseTitleButton.java deleted file mode 100644 index cbb9e1716..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseTitleButton.java +++ /dev/null @@ -1,61 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import javax.swing.Action; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class BaseTitleButton extends NoFocusButton { - - private float alpha = 1.0f; - - public BaseTitleButton(Action action, String accessibleName, Icon icon, float alpha) { - setContentAreaFilled(false); - setBorderPainted(false); - setAction(action); - setText(null); - setIcon(icon); - putClientProperty("paintActive", Boolean.TRUE); - getAccessibleContext().setAccessibleName(accessibleName); - this.alpha = Math.max(0.2f, alpha); - } - - public void paint(Graphics g) { - if (JTattooUtilities.isActive(this) || (alpha >= 1.0)) { - super.paint(g); - } else { - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - AlphaComposite alphaComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha); - g2D.setComposite(alphaComposite); - super.paint(g); - g2D.setComposite(savedComposite); - } - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/BaseTitlePane.java deleted file mode 100644 index da5c4fab7..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseTitlePane.java +++ /dev/null @@ -1,888 +0,0 @@ -/* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.*; -import java.awt.image.BufferedImage; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import javax.swing.*; -import javax.swing.plaf.UIResource; - -/** - * This class is a modified copy of the javax.swing.plaf.metal.MetalTitlePaneUI - * - * Class that manages a JLF awt.Window-descendant class's title bar. - *

        - * This class assumes it will be created with a particular window - * decoration style, and that if the style changes, a new one will - * be created. - * - * @version 1.12 01/23/03 - * @author Terry Kellerman - * @author Michael Hagen - * - * @since 1.4 - */ -public class BaseTitlePane extends JComponent { - - public static final String PAINT_ACTIVE = "paintActive"; - public static final String ICONIFY = "Iconify"; - public static final String MAXIMIZE = "Maximize"; - public static final String CLOSE = "Close"; - protected PropertyChangeListener propertyChangeListener; - protected Action closeAction; - protected Action iconifyAction; - protected Action restoreAction; - protected Action maximizeAction; - protected JMenuBar menuBar; - protected JPanel customTitlePanel; - protected JButton iconifyButton; - protected JButton maxButton; - protected JButton closeButton; - protected Icon iconifyIcon; - protected Icon maximizeIcon; - protected Icon minimizeIcon; - protected Icon closeIcon; - protected WindowListener windowListener; - protected Window window; - protected JRootPane rootPane; - protected BaseRootPaneUI rootPaneUI; - protected int buttonsWidth; - protected int state; - // This flag is used to avoid a bug with OSX and java 1.7. The call to setExtendedState - // with both flags ICONIFY and MAXIMIZED_BOTH throws an illegal state exception, so we - // have to switch off the MAXIMIZED_BOTH flag in the iconify() method. If frame is deiconified - // we use the wasMaximized flag to restore the maximized state. - protected boolean wasMaximized; - protected BufferedImage backgroundImage = null; - protected float alphaValue = 0.85f; - protected boolean useMaximizedBounds = true; - - public BaseTitlePane(JRootPane root, BaseRootPaneUI ui) { - rootPane = root; - rootPaneUI = ui; - state = -1; - wasMaximized = false; - iconifyIcon = UIManager.getIcon("InternalFrame.iconifyIcon"); - maximizeIcon = UIManager.getIcon("InternalFrame.maximizeIcon"); - minimizeIcon = UIManager.getIcon("InternalFrame.minimizeIcon"); - closeIcon = UIManager.getIcon("InternalFrame.closeIcon"); - - installSubcomponents(); - installDefaults(); - setLayout(createLayout()); - } - - - protected void uninstall() { - uninstallListeners(); - window = null; - removeAll(); - } - - protected void installListeners() { - if (window != null) { - windowListener = createWindowListener(); - window.addWindowListener(windowListener); - propertyChangeListener = createWindowPropertyChangeListener(); - window.addPropertyChangeListener(propertyChangeListener); - } - } - - protected void uninstallListeners() { - if (window != null) { - window.removeWindowListener(windowListener); - window.removePropertyChangeListener(propertyChangeListener); - } - } - - protected WindowListener createWindowListener() { - return new WindowHandler(); - } - - protected PropertyChangeListener createWindowPropertyChangeListener() { - return new PropertyChangeHandler(); - } - - public JRootPane getRootPane() { - return rootPane; - } - - protected Frame getFrame() { - if (window instanceof Frame) { - return (Frame) window; - } - return null; - } - - protected Window getWindow() { - return window; - } - - protected int getWindowDecorationStyle() { - return DecorationHelper.getWindowDecorationStyle(rootPane); - } - - protected boolean isMacStyleWindowDecoration() { - return AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn(); - } - - protected Image getFrameIconImage() { - // try to find icon for dialog windows - if (getFrame() == null && JTattooUtilities.getJavaVersion() >= 1.6) { - java.util.List icons = getWindow().getIconImages(); - // No icon found ? search in window chain for an icon - if (icons == null || icons.isEmpty()) { - Window owner = getWindow().getOwner(); - while (owner != null) { - icons = owner.getIconImages(); - // found ? return the icon - if (icons != null && !icons.isEmpty()) { - return (Image)(icons.get(0)); - } - owner = owner.getOwner(); - } - } else { - return (Image)(icons.get(0)); - } - // No icon found ? return icon of the first frame - if (icons == null || icons.isEmpty()) { - if (Frame.getFrames() != null && Frame.getFrames().length > 0) { - return Frame.getFrames()[0].getIconImage(); - } - } - return null; - } else { - if (getFrame() != null) { - return getFrame().getIconImage(); - } - } - return null; - } - - public void addNotify() { - super.addNotify(); - uninstallListeners(); - window = SwingUtilities.getWindowAncestor(this); - if (window != null) { - if (window instanceof Frame) { - setState(DecorationHelper.getExtendedState((Frame) window)); - } else { - setState(0); - } - setActive(JTattooUtilities.isWindowActive(window)); - installListeners(); - } - } - - public void removeNotify() { - super.removeNotify(); - uninstallListeners(); - window = null; - } - - protected void installSubcomponents() { - createActions(); - createButtons(); - if (getWindowDecorationStyle() == BaseRootPaneUI.FRAME) { - if (!isMacStyleWindowDecoration()) { - createMenuBar(); - add(menuBar); - } - add(iconifyButton); - add(maxButton); - } - add(closeButton); - } - - protected void installDefaults() { - setFont(UIManager.getFont("InternalFrame.titleFont")); - if (rootPane.getClientProperty("customTitlePanel") instanceof JPanel) { - setCustomizedTitlePanel((JPanel)rootPane.getClientProperty("customTitlePanel")); - } - } - - protected void uninstallDefaults() { - } - - protected void createMenuBar() { - menuBar = new SystemMenuBar(); - if (getWindowDecorationStyle() == BaseRootPaneUI.FRAME) { - JMenu menu = new JMenu(" "); - - JMenuItem mi = menu.add(restoreAction); - int mnemonic = getInt("MetalTitlePane.restoreMnemonic", -1); - if (mnemonic != -1) { - mi.setMnemonic(mnemonic); - } - mi = menu.add(iconifyAction); - mnemonic = getInt("MetalTitlePane.iconifyMnemonic", -1); - if (mnemonic != -1) { - mi.setMnemonic(mnemonic); - } - - if (DecorationHelper.isFrameStateSupported(Toolkit.getDefaultToolkit(), BaseRootPaneUI.MAXIMIZED_BOTH)) { - mi = menu.add(maximizeAction); - mnemonic = getInt("MetalTitlePane.maximizeMnemonic", -1); - if (mnemonic != -1) { - mi.setMnemonic(mnemonic); - } - } - menu.addSeparator(); - mi = menu.add(closeAction); - mnemonic = getInt("MetalTitlePane.closeMnemonic", -1); - if (mnemonic != -1) { - mi.setMnemonic(mnemonic); - } - - menuBar.add(menu); - } - } - - public void setCustomizedTitlePanel(JPanel panel) { - if (customTitlePanel != null) { - remove(customTitlePanel); - customTitlePanel = null; - } - if (panel != null) { - customTitlePanel = panel; - add(customTitlePanel); - } - rootPane.putClientProperty("customTitlePanel", customTitlePanel); - revalidate(); - repaint(); - } - - public void createButtons() { - iconifyButton = new BaseTitleButton(iconifyAction, ICONIFY, iconifyIcon, 1.0f); - maxButton = new BaseTitleButton(restoreAction, MAXIMIZE, maximizeIcon, 1.0f); - closeButton = new BaseTitleButton(closeAction, CLOSE, closeIcon, 1.0f); - } - - public LayoutManager createLayout() { - return new TitlePaneLayout(); - } - - protected void close() { - if (window != null) { - window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); - } - } - - protected void iconify() { - Frame frame = getFrame(); - if (frame != null) { - if (JTattooUtilities.isMac() && JTattooUtilities.getJavaVersion() >= 1.7) { - // Workarround to avoid a bug within OSX and Java 1.7 - DecorationHelper.setExtendedState(frame, state & ~BaseRootPaneUI.MAXIMIZED_BOTH | Frame.ICONIFIED); - } else { - DecorationHelper.setExtendedState(frame, state | Frame.ICONIFIED); - } - } - } - - protected void maximize() { - Frame frame = getFrame(); - if (frame != null) { - PropertyChangeListener[] pcl = frame.getPropertyChangeListeners(); - for (int i = 0; i < pcl.length; i++) { - pcl[i].propertyChange(new PropertyChangeEvent(this, "windowMaximize", Boolean.FALSE, Boolean.FALSE)); - } - DecorationHelper.setExtendedState(frame, state | BaseRootPaneUI.MAXIMIZED_BOTH); - for (int i = 0; i < pcl.length; i++) { - pcl[i].propertyChange(new PropertyChangeEvent(this, "windowMaximized", Boolean.FALSE, Boolean.FALSE)); - } - } - } - - protected void restore() { - Frame frame = getFrame(); - if (frame != null) { - PropertyChangeListener[] pcl = frame.getPropertyChangeListeners(); - for (int i = 0; i < pcl.length; i++) { - pcl[i].propertyChange(new PropertyChangeEvent(this, "windowRestore", Boolean.FALSE, Boolean.FALSE)); - } - if ((state & Frame.ICONIFIED) != 0) { - DecorationHelper.setExtendedState(frame, state & ~Frame.ICONIFIED); - } else { - DecorationHelper.setExtendedState(frame, state & ~BaseRootPaneUI.MAXIMIZED_BOTH); - } - for (int i = 0; i < pcl.length; i++) { - pcl[i].propertyChange(new PropertyChangeEvent(this, "windowRestored", Boolean.FALSE, Boolean.FALSE)); - } - } - } - - protected void createActions() { - closeAction = new CloseAction(); - iconifyAction = new IconifyAction(); - restoreAction = new RestoreAction(); - maximizeAction = new MaximizeAction(); - } - - static int getInt(Object key, int defaultValue) { - Object value = UIManager.get(key); - if (value instanceof Integer) { - return ((Integer) value).intValue(); - } - if (value instanceof String) { - try { - return Integer.parseInt((String) value); - } catch (NumberFormatException nfe) { - } - } - return defaultValue; - } - - protected void setActive(boolean flag) { - if (getWindowDecorationStyle() == BaseRootPaneUI.FRAME) { - Boolean active = flag ? Boolean.TRUE : Boolean.FALSE; - iconifyButton.putClientProperty(PAINT_ACTIVE, active); - closeButton.putClientProperty(PAINT_ACTIVE, active); - maxButton.putClientProperty(PAINT_ACTIVE, active); - } - getRootPane().repaint(); - } - - protected boolean isActive() { - return (window == null) ? true : JTattooUtilities.isWindowActive(window); - } - - protected boolean isLeftToRight() { - return (window == null) ? getRootPane().getComponentOrientation().isLeftToRight() : window.getComponentOrientation().isLeftToRight(); - } - - public void setBackgroundImage(BufferedImage bgImage) { - backgroundImage = bgImage; - } - - public void setAlphaTransparency(float alpha) { - alphaValue = alpha; - } - - protected void setState(int state) { - setState(state, false); - } - - protected void setState(int state, boolean updateRegardless) { - if (window != null && getWindowDecorationStyle() == BaseRootPaneUI.FRAME) { - if (this.state == state && !updateRegardless) { - return; - } - - Frame frame = getFrame(); - if (frame != null) { - - if (((state & BaseRootPaneUI.MAXIMIZED_BOTH) != 0) && (rootPane.getBorder() == null || (rootPane.getBorder() instanceof UIResource)) && frame.isShowing()) { - rootPane.setBorder(null); - } else if ((state & BaseRootPaneUI.MAXIMIZED_BOTH) == 0) { - rootPaneUI.installBorder(rootPane); - } - - if (frame.isResizable()) { - if ((state & BaseRootPaneUI.MAXIMIZED_BOTH) != 0) { - updateMaxButton(restoreAction, minimizeIcon); - maximizeAction.setEnabled(false); - restoreAction.setEnabled(true); - } else { - updateMaxButton(maximizeAction, maximizeIcon); - maximizeAction.setEnabled(true); - restoreAction.setEnabled(false); - } - if (maxButton.getParent() == null || iconifyButton.getParent() == null) { - add(maxButton); - add(iconifyButton); - revalidate(); - repaint(); - } - maxButton.setText(null); - } else { - maximizeAction.setEnabled(false); - restoreAction.setEnabled(false); - if (maxButton.getParent() != null) { - remove(maxButton); - revalidate(); - repaint(); - } - } - } else { - // Not contained in a Frame - maximizeAction.setEnabled(false); - restoreAction.setEnabled(false); - iconifyAction.setEnabled(false); - remove(maxButton); - remove(iconifyButton); - revalidate(); - repaint(); - } - closeAction.setEnabled(true); - this.state = state; - } - } - - protected void updateMaxButton(Action action, Icon icon) { - maxButton.setAction(action); - maxButton.setIcon(icon); - } - - protected int getHorSpacing() { - return 3; - } - - protected int getVerSpacing() { - return 3; - } - - protected boolean centerButtons() { - return true; - } - - protected String getTitle() { - if (window instanceof Frame) { - return ((Frame) window).getTitle(); - } else if (window instanceof Dialog) { - return ((Dialog) window).getTitle(); - } - return null; - } - - public void paintBackground(Graphics g) { - if (isActive()) { - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - if (backgroundImage != null) { - g.drawImage(backgroundImage, 0, 0, null); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alphaValue); - g2D.setComposite(alpha); - } - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 0, 0, getWidth(), getHeight()); - g2D.setComposite(savedComposite); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 0, 0, getWidth(), getHeight()); - } - } - - protected int paintIcon(Graphics g, int x, int y) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn() || (getWindow() instanceof JDialog)) { - Image image = getFrameIconImage(); - if (image != null) { - Graphics2D g2D = (Graphics2D)g; - Object savedHint = g2D.getRenderingHint(RenderingHints.KEY_INTERPOLATION); - if (JTattooUtilities.getJavaVersion() >= 1.6) { - g2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - } - int h = getHeight(); - int ih = image.getHeight(null); - int iw = image.getWidth(null); - if (ih <= h) { - g2D.drawImage(image, x, (h - ih) / 2, iw, ih, null); - } else { - double fac = (double)iw / (double)ih; - ih = h; - iw = (int)(fac * (double)ih); - g2D.drawImage(image, x, 0, iw, ih, null); - } - if (savedHint != null) { - g2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, savedHint); - } - return iw + 4; - } - } - return 0; - } - - public void paintText(Graphics g, int x, int y, String title) { - x += paintIcon(g, x, y); - if (isActive()) { - g.setColor(AbstractLookAndFeel.getWindowTitleForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - } - JTattooUtilities.drawString(rootPane, g, title, x, y); - } - - public void paintComponent(Graphics g) { - if (getFrame() != null) { - setState(DecorationHelper.getExtendedState(getFrame())); - } - - paintBackground(g); - - boolean leftToRight = isLeftToRight(); - int width = getWidth(); - int height = getHeight(); - int titleWidth = width - buttonsWidth - 4; - int xOffset = leftToRight ? 2 : width - 2; - if (menuBar != null) { - int mw = menuBar.getWidth() + 2; - xOffset += leftToRight ? mw : -mw; - titleWidth -= height; - } - - g.setFont(getFont()); - FontMetrics fm = g.getFontMetrics(); - String frameTitle = JTattooUtilities.getClippedText(getTitle(), fm, titleWidth); - int titleLength = fm.stringWidth(frameTitle); - int yOffset = ((height - fm.getHeight()) / 2) + fm.getAscent() - 1; - if (!leftToRight) { - xOffset -= titleLength; - } - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - xOffset = Math.max(buttonsWidth + 5, (width - titleLength) / 2); - } - paintText(g, xOffset, yOffset, frameTitle); - } - - protected class CloseAction extends AbstractAction { - - public CloseAction() { - super(UIManager.getString("MetalTitlePane.closeTitle")); - } - - public void actionPerformed(ActionEvent e) { - close(); - } - } - - protected class IconifyAction extends AbstractAction { - - public IconifyAction() { - super(UIManager.getString("MetalTitlePane.iconifyTitle")); - } - - public void actionPerformed(ActionEvent e) { - iconify(); - } - } - - protected class RestoreAction extends AbstractAction { - - public RestoreAction() { - super(UIManager.getString("MetalTitlePane.restoreTitle")); - } - - public void actionPerformed(ActionEvent e) { - restore(); - } - } - - protected class MaximizeAction extends AbstractAction { - - public MaximizeAction() { - super(UIManager.getString("MetalTitlePane.maximizeTitle")); - } - - public void actionPerformed(ActionEvent e) { - maximize(); - } - } - -//----------------------------------------------------------------------------------------------- - protected class SystemMenuBar extends JMenuBar { - - public SystemMenuBar() { - setOpaque(false); - } - - public void paint(Graphics g) { - Image image = getFrameIconImage(); - if (image != null) { - Graphics2D g2D = (Graphics2D)g; - Object savedHint = g2D.getRenderingHint(RenderingHints.KEY_INTERPOLATION); - g2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - int x = 0; - int y = 0; - int iw = image.getWidth(null); - int ih = image.getHeight(null); - if (ih > getHeight()) { - double scale = (double)(getHeight() - 2) / (double)ih; - iw = (int)(scale * iw); - ih = (int)(scale * ih); - } else { - y = (getHeight() - ih) / 2; - } - g2D.drawImage(image, x, y, iw, ih, null); - if (savedHint != null) { - g2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, savedHint); - } - } else { - Icon icon = UIManager.getIcon("InternalFrame.icon"); - if (icon != null) { - icon.paintIcon(this, g, 2, 2); - } - } - } - - public Dimension getMinimumSize() { - return getPreferredSize(); - } - - protected int computeHeight() { - FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(getFont()); - return fm.getHeight() + 6; - } - - public Dimension getPreferredSize() { - Dimension size = super.getPreferredSize(); - Image image = getFrameIconImage(); - if (image != null) { - int iw = image.getWidth(null); - int ih = image.getHeight(null); - int th = computeHeight(); - if (ih > th) { - double scale = (double)th / (double)ih; - iw = (int)(scale * iw); - ih = (int)(scale * ih); - } - return new Dimension(Math.max(iw, size.width), Math.max(ih, size.height)); - } else { - return size; - } - } - } - -//----------------------------------------------------------------------------------------------- - protected class TitlePaneLayout implements LayoutManager { - - public void addLayoutComponent(String name, Component c) { - } - - public void removeLayoutComponent(Component c) { - } - - public Dimension preferredLayoutSize(Container c) { - int height = computeHeight(); - return new Dimension(height, height); - } - - public Dimension minimumLayoutSize(Container c) { - return preferredLayoutSize(c); - } - - protected int computeHeight() { - FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(getFont()); - return fm.getHeight() + 6; - } - - public void layoutContainer(Container c) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - layoutMacStyle(c); - } else { - layoutDefault(c); - } - } - - public void layoutDefault(Container c) { - boolean leftToRight = isLeftToRight(); - - int spacing = getHorSpacing(); - int w = getWidth(); - int h = getHeight(); - - // assumes all buttons have the same dimensions these dimensions include the borders - int btnHeight = h - getVerSpacing(); - int btnWidth = btnHeight; - - - if (menuBar != null) { - int mw = menuBar.getPreferredSize().width; - int mh = menuBar.getPreferredSize().height; - if (leftToRight) { - menuBar.setBounds(2, (h - mh) / 2, mw, mh); - } else { - menuBar.setBounds(getWidth() - mw, (h - mh) / 2, mw, mh); - } - } - - int x = leftToRight ? w - spacing : 0; - int y = Math.max(0, ((h - btnHeight) / 2) - 1); - - if (closeButton != null) { - x += leftToRight ? -btnWidth : spacing; - closeButton.setBounds(x, y, btnWidth, btnHeight); - if (!leftToRight) { - x += btnWidth; - } - } - - if ((maxButton != null) && (maxButton.getParent() != null)) { - if (DecorationHelper.isFrameStateSupported(Toolkit.getDefaultToolkit(), BaseRootPaneUI.MAXIMIZED_BOTH)) { - x += leftToRight ? -spacing - btnWidth : spacing; - maxButton.setBounds(x, y, btnWidth, btnHeight); - if (!leftToRight) { - x += btnWidth; - } - } - } - - if ((iconifyButton != null) && (iconifyButton.getParent() != null)) { - x += leftToRight ? -spacing - btnWidth : spacing; - iconifyButton.setBounds(x, y, btnWidth, btnHeight); - if (!leftToRight) { - x += btnWidth; - } - } - - buttonsWidth = leftToRight ? w - x : x; - - if (customTitlePanel != null) { - int maxWidth = w - buttonsWidth - spacing - 20; - if (menuBar != null) { - maxWidth -= menuBar.getPreferredSize().width; - maxWidth -= spacing; - } - int cpw = Math.min(maxWidth, customTitlePanel.getPreferredSize().width); - int cph = h; - int cpx = leftToRight ? w - buttonsWidth - cpw : buttonsWidth; - int cpy = 0; - customTitlePanel.setBounds(cpx, cpy, cpw, cph); - buttonsWidth += customTitlePanel.getPreferredSize().width; - } - } - - public void layoutMacStyle(Container c) { - int spacing = getHorSpacing(); - int w = getWidth(); - int h = getHeight(); - - // assumes all buttons have the same dimensions these dimensions include the borders - int btnHeight = h - getVerSpacing() - 1; - int btnWidth = btnHeight; - - int x = 2; - int y = centerButtons() ? Math.max(0, ((h - btnHeight) / 2) - 1) : 0; - - if (closeButton != null) { - closeButton.setBounds(x, y, btnWidth, btnHeight); - x += btnWidth + spacing; - } - if ((iconifyButton != null) && (iconifyButton.getParent() != null)) { - iconifyButton.setBounds(x, y, btnWidth, btnHeight); - x += btnWidth + spacing; - } - if ((maxButton != null) && (maxButton.getParent() != null)) { - if (DecorationHelper.isFrameStateSupported(Toolkit.getDefaultToolkit(), BaseRootPaneUI.MAXIMIZED_BOTH)) { - maxButton.setBounds(x, y, btnWidth, btnHeight); - x += btnWidth + spacing; - } - } - - buttonsWidth = x; - - if (customTitlePanel != null) { - int cpx = buttonsWidth + 5; - int cpy = 0; - int cpw = customTitlePanel.getPreferredSize().width; - int cph = h; - customTitlePanel.setBounds(cpx, cpy, cpw, cph); - buttonsWidth += cpw + 5; - } - } - } - -//----------------------------------------------------------------------------------------------- - protected class PropertyChangeHandler implements PropertyChangeListener { - - public void propertyChange(PropertyChangeEvent pce) { - String name = pce.getPropertyName(); - // Frame.state isn't currently bound. - if ("resizable".equals(name) || "state".equals(name)) { - Frame frame = getFrame(); - if (frame != null) { - setState(DecorationHelper.getExtendedState(frame), true); - } - if ("resizable".equals(name)) { - getRootPane().repaint(); - } - } else if ("title".equals(name)) { - repaint(); - } else if ("componentOrientation".equals(name)) { - revalidate(); - repaint(); - // a call to setMaximizedBounds may cause an invalid frame size on multi screen environments - // see: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6699851 - // try and error to avoid the setMaximizedBounds bug - } else if (!JTattooUtilities.isMac() && useMaximizedBounds && "windowMaximize".equals(name)) { - Frame frame = getFrame(); - if (frame != null) { - GraphicsConfiguration gc = frame.getGraphicsConfiguration(); - Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(gc); - Rectangle screenBounds = gc.getBounds(); - int x = Math.max(0, screenInsets.left); - int y = Math.max(0, screenInsets.top); - int w = screenBounds.width - (screenInsets.left + screenInsets.right); - int h = screenBounds.height - (screenInsets.top + screenInsets.bottom); - // Keep taskbar visible - frame.setMaximizedBounds(new Rectangle(x, y, w, h)); - } - } else if (!JTattooUtilities.isMac() && useMaximizedBounds && "windowMaximized".equals(name)) { - Frame frame = getFrame(); - if (frame != null) { - GraphicsConfiguration gc = frame.getGraphicsConfiguration(); - Rectangle screenBounds = gc.getBounds(); - if (frame.getSize().width > screenBounds.width || frame.getSize().height > screenBounds.height) { - useMaximizedBounds = false; - frame.setMaximizedBounds(null); - restore(); - maximize(); - } - } - } else if (!JTattooUtilities.isMac() && "windowMoved".equals(name)) { - useMaximizedBounds = true; - } - - if (JTattooUtilities.isMac() && JTattooUtilities.getJavaVersion() >= 1.7) { - if ("windowRestored".equals(name)) { - wasMaximized = false; - } else if ("windowMaximized".equals(name)) { - wasMaximized = true; - } - } - } - } - -//----------------------------------------------------------------------------------------------- - protected class WindowHandler extends WindowAdapter { - - public void windowDeiconified(WindowEvent e) { - if (JTattooUtilities.isMac() && JTattooUtilities.getJavaVersion() >= 1.7 && wasMaximized) { - SwingUtilities.invokeLater( () -> maximize() ); - } - } - - public void windowActivated(WindowEvent ev) { - setActive(true); - } - - public void windowDeactivated(WindowEvent ev) { - setActive(false); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseToggleButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseToggleButtonUI.java deleted file mode 100644 index 74353f190..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseToggleButtonUI.java +++ /dev/null @@ -1,214 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.*; -import javax.swing.text.View; - -public class BaseToggleButtonUI extends BasicToggleButtonUI { - - private static Rectangle viewRect = new Rectangle(); - private static Rectangle textRect = new Rectangle(); - private static Rectangle iconRect = new Rectangle(); - protected static Color[] rolloverPressedColors = null; - - public static ComponentUI createUI(JComponent b) { - return new BaseToggleButtonUI(); - } - - public void installDefaults(AbstractButton b) { - super.installDefaults(b); - b.setOpaque(false); - b.setRolloverEnabled(true); - Color cArr[] = AbstractLookAndFeel.getTheme().getPressedColors(); - rolloverPressedColors = new Color[cArr.length]; - for (int i = 0; i < cArr.length; i++) { - rolloverPressedColors[i] = ColorHelper.brighter(cArr[i], 20); - } - } - - public void uninstallDefaults(AbstractButton b) { - super.uninstallDefaults(b); - b.setOpaque(true); - b.setRolloverEnabled(false); - } - - protected BasicButtonListener createButtonListener(AbstractButton b) { - return new BaseButtonListener(b); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - if (!b.isContentAreaFilled() || (b.getParent() instanceof JMenuBar)) { - return; - } - - int width = b.getWidth(); - int height = b.getHeight(); - - ButtonModel model = b.getModel(); - Color colors[]; - if (b.isEnabled()) { - Color background = b.getBackground(); - if (background instanceof ColorUIResource) { - if (model.isPressed() && model.isArmed()) { - colors = AbstractLookAndFeel.getTheme().getPressedColors(); - } else if (b.isRolloverEnabled() && model.isRollover()) { - if (model.isSelected()) { - colors = rolloverPressedColors; - } else { - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - } - } else if (model.isSelected()) { - colors = AbstractLookAndFeel.getTheme().getPressedColors(); - } else { - if (AbstractLookAndFeel.getTheme().doShowFocusFrame() && b.hasFocus()) { - colors = AbstractLookAndFeel.getTheme().getFocusColors(); - } else { - colors = AbstractLookAndFeel.getTheme().getButtonColors(); - } - } - } else { - if (model.isPressed() && model.isArmed()) { - colors = ColorHelper.createColorArr(ColorHelper.darker(background, 30), ColorHelper.darker(background, 10), 20); - } else if (b.isRolloverEnabled() && model.isRollover()) { - if (model.isSelected()) { - colors = ColorHelper.createColorArr(ColorHelper.darker(background, 20), background, 20); - } else { - colors = ColorHelper.createColorArr(ColorHelper.brighter(background, 50), ColorHelper.brighter(background, 10), 20); - } - } else if (model.isSelected()) { - colors = ColorHelper.createColorArr(ColorHelper.darker(background, 40), ColorHelper.darker(background, 20), 20); - } else { - colors = ColorHelper.createColorArr(ColorHelper.brighter(background, 30), ColorHelper.darker(background, 10), 20); - } - } - } else { // disabled - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } - JTattooUtilities.fillHorGradient(g, colors, 1, 1, width - 2, height - 2); - } - - protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) { - ButtonModel model = b.getModel(); - FontMetrics fm = g.getFontMetrics(); - int mnemIndex; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = b.getDisplayedMnemonicIndex(); - } else { - mnemIndex = JTattooUtilities.findDisplayedMnemonicIndex(b.getText(), model.getMnemonic()); - } - - if (model.isEnabled()) { - Color foreground = b.getForeground(); - int offs = 0; - if ((model.isArmed() && model.isPressed()) || model.isSelected()) { - offs = 1; - } - if (foreground instanceof ColorUIResource) { - if (model.isRollover()) { - g.setColor(AbstractLookAndFeel.getTheme().getRolloverForegroundColor()); - } else { - g.setColor(b.getForeground()); - } - } else { - g.setColor(b.getForeground()); - } - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x + offs, textRect.y + offs + fm.getAscent()); - } else { - g.setColor(Color.white); - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x + 1, textRect.y + 1 + fm.getAscent()); - g.setColor(AbstractLookAndFeel.getDisabledForegroundColor()); - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); - } - } - - protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - BasicGraphicsUtils.drawDashedRect(g, 4, 3, b.getWidth() - 8, b.getHeight() - 6); - } - - public void paint(Graphics g, JComponent c) { - Graphics2D g2D = (Graphics2D) g; - - AbstractButton b = (AbstractButton) c; - Font f = c.getFont(); - g.setFont(f); - FontMetrics fm = g.getFontMetrics(); - Insets insets = c.getInsets(); - - viewRect.x = insets.left; - viewRect.y = insets.top; - viewRect.width = b.getWidth() - (insets.right + viewRect.x); - viewRect.height = b.getHeight() - (insets.bottom + viewRect.y); - - textRect.x = textRect.y = textRect.width = textRect.height = 0; - iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0; - - String text = SwingUtilities.layoutCompoundLabel( - c, fm, b.getText(), b.getIcon(), - b.getVerticalAlignment(), b.getHorizontalAlignment(), - b.getVerticalTextPosition(), b.getHorizontalTextPosition(), - viewRect, iconRect, textRect, - b.getText() == null ? 0 : defaultTextIconGap); - - paintBackground(g, b); - - if (b.getIcon() != null) { - if (!b.isEnabled()) { - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); - g2D.setComposite(alpha); - paintIcon(g, c, iconRect); - g2D.setComposite(savedComposite); - } else { - paintIcon(g, c, iconRect); - } - } - - if (text != null && !text.equals("") && textRect != null) { - View v = (View) c.getClientProperty(BasicHTML.propertyKey); - if (v != null) { - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - v.paint(g, textRect); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } else { - paintText(g, b, textRect, text); - } - } - - if (b.isFocusPainted() && b.hasFocus()) { - paintFocus(g, b, viewRect, textRect, iconRect); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseToolTipUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseToolTipUI.java deleted file mode 100644 index d9d66a884..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseToolTipUI.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. - * - * JTattoo is multiple licensed. If your are an open source developer you can use - * it under the terms and conditions of the GNU General Public License version 2.0 - * or later as published by the Free Software Foundation. - * - * see: gpl-2.0.txt - * - * If you pay for a license you will become a registered user who could use the - * software under the terms and conditions of the GNU Lesser General Public License - * version 2.0 or later with classpath exception as published by the Free Software - * Foundation. - * - * see: lgpl-2.0.txt - * see: classpath-exception.txt - * - * Registered users could also use JTattoo under the terms and conditions of the - * Apache License, Version 2.0 as published by the Apache Software Foundation. - * - * see: APACHE-LICENSE-2.0.txt - */ -package com.jtattoo.plaf; - -import java.awt.*; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; -import java.awt.image.BufferedImage; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.metal.MetalToolTipUI; - -/** - * @author Michael Hagen, Daniel Raedel - */ -public class BaseToolTipUI extends MetalToolTipUI { - - private boolean fancyLayout = false; - private ComponentListener popupWindowListener = null; - - public static ComponentUI createUI(JComponent c) { - return new BaseToolTipUI(); - } - - public void installUI(JComponent c) { - super.installUI(c); - int borderSize = AbstractLookAndFeel.getTheme().getTooltipBorderSize(); - int shadowSize = AbstractLookAndFeel.getTheme().getTooltipShadowSize(); - fancyLayout = DecorationHelper.isTranslucentWindowSupported() && ToolTipManager.sharedInstance().isLightWeightPopupEnabled(); - if (fancyLayout) { - c.setBorder(BorderFactory.createEmptyBorder(borderSize, borderSize + shadowSize, borderSize + shadowSize, borderSize + shadowSize)); - c.setOpaque(false); - Container parent = c.getParent(); - if (parent instanceof JPanel) { - ((JPanel) c.getParent()).setOpaque(false); - } - } else { - c.setBorder(BorderFactory.createEmptyBorder(borderSize, borderSize, borderSize, borderSize)); - } - } - - protected void installListeners(JComponent c) { - super.installListeners(c); - - // We must set the popup window to opaque because it is cached and reused within the PopupFactory - popupWindowListener = new ComponentAdapter() { - - public void componentHidden(ComponentEvent e) { - Window window = (Window)e.getComponent(); - DecorationHelper.setTranslucentWindow(window, false); - window.removeComponentListener(popupWindowListener); - } - }; - } - - public void paint(Graphics g, JComponent c) { - Graphics2D g2D = (Graphics2D) g; - Composite savedComposit = g2D.getComposite(); - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - int borderSize = AbstractLookAndFeel.getTheme().getTooltipBorderSize(); - int shadowSize = AbstractLookAndFeel.getTheme().getTooltipShadowSize(); - - int w = c.getWidth(); - int h = c.getHeight(); - Color backColor = AbstractLookAndFeel.getTheme().getTooltipBackgroundColor(); - - if (fancyLayout && shadowSize > 0) { - Container parent = c.getParent(); - while (parent != null) { - if ((parent.getClass().getName().indexOf("HeavyWeightWindow") > 0) && (parent instanceof Window)) { - // Make the popup transparent - Window window = (Window)parent; - // Add a component listener to revert this operation if popup is closed - window.addComponentListener(popupWindowListener); - DecorationHelper.setTranslucentWindow(window, true); - break; - } - parent = parent.getParent(); - } - // draw the shadow - g2D.setColor(AbstractLookAndFeel.getTheme().getShadowColor()); - float[] composites = {0.01f, 0.02f, 0.04f, 0.06f, 0.08f, 0.12f}; - int shadowOffset = AbstractLookAndFeel.getTheme().isTooltipCastShadow() ? shadowSize : 0; - for (int i = 0; i < shadowSize; i++) { - g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, composites[i >= composites.length ? composites.length - 1 : i])); - g2D.fillRoundRect(i + shadowOffset, borderSize + i, w - (2 * i) - shadowOffset, h - borderSize - (2 * i), 12 - i, 12 - i); - - } - g2D.setComposite(savedComposit); - - // Draw background with borders - if (ColorHelper.getGrayValue(backColor) < 128) { - g2D.setColor(ColorHelper.brighter(AbstractLookAndFeel.getTheme().getBackgroundColor(), 20)); - } else { - g2D.setColor(Color.white); - - } - //g2D.fillRoundRect(shadowSize, 0, w - (2 * shadowSize) - 1, h - shadowSize - 1, 6, 6); - g2D.fillRoundRect(shadowSize, 0, w - (2 * shadowSize) - 1, h - shadowSize - 1, shadowSize, shadowSize); - g2D.setColor(ColorHelper.darker(backColor, 40)); - //g2D.drawRoundRect(shadowSize, 0, w - (2 * shadowSize) - 1, h - shadowSize - 1, 6, 6); - g2D.drawRoundRect(shadowSize, 0, w - (2 * shadowSize) - 1, h - shadowSize - 1, shadowSize, shadowSize); - g2D.setColor(ColorHelper.darker(backColor, 10)); - g2D.drawRect(borderSize + shadowSize - 1, borderSize - 1, w - (2 * borderSize) - (2 * shadowSize) + 1, h - (2 * borderSize) - shadowSize + 1); - - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - // Draw the text. This must be done within an offscreen image because of a bug - // in the jdk, wich causes ugly antialiased font rendering when background is - // transparent and popup is heavy weight. - BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); - Graphics2D big = bi.createGraphics(); - big.setClip(0, 0, w, h); - Paint savedPaint = big.getPaint(); - Color cHi; - Color cLo; - if (ColorHelper.getGrayValue(backColor) < 128) { - cHi = ColorHelper.brighter(backColor, 10); - cLo = ColorHelper.darker(backColor, 20); - } else { - cHi = ColorHelper.brighter(backColor, 40); - cLo = ColorHelper.darker(backColor, 5); - } - big.setPaint(new GradientPaint(0, borderSize, cHi, 0, h - (2 * borderSize) - shadowSize, cLo)); - big.fillRect(borderSize + shadowSize, borderSize, w - (2 * borderSize) - (2 * shadowSize), h - (2 * borderSize) - shadowSize); - - big.setPaint(savedPaint); - - if (c instanceof JToolTip) { - JToolTip tip = (JToolTip) c; - if (tip.getComponent() != null && tip.getComponent().isEnabled()) { - c.setForeground(AbstractLookAndFeel.getTheme().getTooltipForegroundColor()); - } else { - c.setForeground(AbstractLookAndFeel.getTheme().getDisabledForegroundColor()); - } - } - super.paint(big, c); - g2D.setClip(borderSize + shadowSize, borderSize, w - (2 * borderSize) - (2 * shadowSize), h - (2 * borderSize) - shadowSize); - g2D.drawImage(bi, 0, 0, null); - - } else { - // Draw background with borders - if (ColorHelper.getGrayValue(backColor) < 128) { - g2D.setColor(ColorHelper.brighter(AbstractLookAndFeel.getTheme().getBackgroundColor(), 20)); - } else { - g2D.setColor(Color.white); - } - g2D.fillRect(0, 0, w, h); - g2D.setColor(ColorHelper.darker(backColor, 40)); - g2D.drawRect(0, 0, w - 1, h - 1); - g2D.setColor(ColorHelper.darker(backColor, 10)); - g2D.drawRect(borderSize - 1, borderSize - 1, w - (2 * borderSize - 1), h - (2 * borderSize - 1)); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - - Paint savedPaint = g2D.getPaint(); - Color cHi; - Color cLo; - if (ColorHelper.getGrayValue(backColor) < 128) { - cHi = ColorHelper.brighter(backColor, 10); - cLo = ColorHelper.darker(backColor, 20); - } else { - cHi = ColorHelper.brighter(backColor, 40); - cLo = ColorHelper.darker(backColor, 5); - } - g2D.setPaint(new GradientPaint(0, borderSize, cHi, 0, h - (2 * borderSize), cLo)); - g2D.fillRect(borderSize, borderSize, w - (2 * borderSize), h - (2 * borderSize)); - g2D.setPaint(savedPaint); - - super.paint(g, c); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/BaseTreeUI.java b/src/jtattoo/src/com/jtattoo/plaf/BaseTreeUI.java deleted file mode 100644 index c1cc5d2c3..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/BaseTreeUI.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicTreeUI; - -/** - * author Michael Hagen - */ -public class BaseTreeUI extends BasicTreeUI { - - public static ComponentUI createUI(JComponent c) { - return new BaseTreeUI(); - } - - protected void paintVerticalLine(Graphics g, JComponent c, int x, int top, int bottom) { - drawDashedVerticalLine(g, x, top, bottom); - } - - protected void paintHorizontalLine(Graphics g, JComponent c, int y, int left, int right) { - drawDashedHorizontalLine(g, y, left, right); - } -} - - diff --git a/src/jtattoo/src/com/jtattoo/plaf/ColorHelper.java b/src/jtattoo/src/com/jtattoo/plaf/ColorHelper.java deleted file mode 100644 index 2be0bb8d1..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/ColorHelper.java +++ /dev/null @@ -1,205 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.Color; - -/** - * A helper class for handling color values. - * - * @author Michael Hagen - */ -public class ColorHelper { - - /** - * Avoid creation of this class. This class only contains static helper methods, so creation of an object - * is not necessary. - */ - private ColorHelper() { - } - - /** - * Creates a color object. - * - * @param r the Red component - * @param g the Green component - * @param b the Blue component - * - * @return a color object - */ - public static Color createColor(int r, int g, int b) { - return new Color(((r & 0xFF) << 16) | ((g & 0xFF) << 8) | ((b & 0xFF))); - } - - /** - * Creates an array of color values. The colors created will be a gradient from color c1 to color c1 with a count - * of steps values. - * - * @param c1 the starting color - * @param c2 the ending color - * @param steps the number of steps between c1 and c2 (the size of the created array) - * - * @return the array of color values - */ - public static Color[] createColorArr(Color c1, Color c2, int steps) { - if (c1 == null || c2 == null) { - return null; - } - - Color colors[] = new Color[steps]; - double r = c1.getRed(); - double g = c1.getGreen(); - double b = c1.getBlue(); - double dr = ((double) c2.getRed() - r) / steps; - double dg = ((double) c2.getGreen() - g) / steps; - double db = ((double) c2.getBlue() - b) / steps; - colors[0] = c1; - for (int i = 1; i < steps - 1; i++) { - r += dr; - g += dg; - b += db; - colors[i] = createColor((int) r, (int) g, (int) b); - } - colors[steps - 1] = c2; - return colors; - } - - /** - * Creates a color that is the brighter version of the color parameter c. - * - * @param c the color - * @param p the factor of the brightness in percent from 0 to 100 - * @return a new color value that is a brighter version of the color parameter c - */ - public static Color brighter(Color c, double p) { - if (c == null) { - return null; - } - - double r = c.getRed(); - double g = c.getGreen(); - double b = c.getBlue(); - - double rd = 255.0 - r; - double gd = 255.0 - g; - double bd = 255.0 - b; - - r += (rd * p) / 100.0; - g += (gd * p) / 100.0; - b += (bd * p) / 100.0; - return createColor((int) r, (int) g, (int) b); - } - - /** - * Creates a color that is the darker version of the color parameter c. - * - * @param c the color - * @param p the factor to shade the color c in percent from 0 to 100 - * - * @return a new color value that is a darker version of the color parameter c - */ - public static Color darker(Color c, double p) { - if (c == null) { - return null; - } - - double r = c.getRed(); - double g = c.getGreen(); - double b = c.getBlue(); - - r -= (r * p) / 100.0; - g -= (g * p) / 100.0; - b -= (b * p) / 100.0; - - return createColor((int) r, (int) g, (int) b); - } - - /** - * Returns a color value which is the media between the colors c1 and c1 - * - * @param c1 the first color - * @param c2 the second color - * - * @return the median color value of the two colors c1 and c1 - */ - public static Color median(Color c1, Color c2) { - if ((c1 == null || c2 == null)) { - return null; - } - - int r = (c1.getRed() + c2.getRed()) / 2; - int g = (c1.getGreen() + c2.getGreen()) / 2; - int b = (c1.getBlue() + c2.getBlue()) / 2; - return createColor(r, g, b); - } - - /** - * Returns a value between 0 and 255 which represents the gray value of the color parameter. - * - * @param c the color you want to calculate the gray value - * - * @return the gray value - */ - public static int getGrayValue(Color c) { - if (c == null) { - return 0; - } - - double r = c.getRed(); - double g = c.getGreen(); - double b = c.getBlue(); - return Math.min(255, (int) (r * 0.28 + g * 0.59 + b * 0.13)); - } - - /** - * Returns a value between 0 and 255 which represents the median gray value of the color array. - * - * @param ca the color array you want to calculate the gray value - * - * @return the gray value - */ - public static int getGrayValue(Color[] ca) { - int sum = 0; - for (int i = 0; i < ca.length; i++) { - sum += getGrayValue(ca[i]); - } - return (sum / ca.length); - } - - /** - * Returns a gray version of the color parameter c, which means all parts (r,g,b) do have the same value. - * - * @param c the color - * - * @return a gray version of the color parameter c. - */ - public static Color toGray(Color c) { - if (c == null) { - return null; - } - - int gray = getGrayValue(c); - return new Color(gray, gray, gray, c.getAlpha()); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/DecorationHelper.java b/src/jtattoo/src/com/jtattoo/plaf/DecorationHelper.java deleted file mode 100644 index 234fc5b7d..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/DecorationHelper.java +++ /dev/null @@ -1,142 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.lang.reflect.Method; -import javax.swing.*; - -/** - * @author Michael Hagen - */ -public class DecorationHelper { - - private DecorationHelper() { - } - - public static void decorateWindows(Boolean decorate) { - if (JTattooUtilities.getJavaVersion() >= 1.4) { - try { - Class classParams[] = {Boolean.TYPE}; - Method m = JFrame.class.getMethod("setDefaultLookAndFeelDecorated", classParams); - Object methodParams[] = {decorate}; - m.invoke(null, methodParams); - m = JDialog.class.getMethod("setDefaultLookAndFeelDecorated", classParams); - m.invoke(null, methodParams); - System.setProperty("sun.awt.noerasebackground", "true"); - System.setProperty("sun.awt.erasebackgroundonresize", "false"); - } catch (Exception ex) { - } - } - } - - public static int getWindowDecorationStyle(JRootPane root) { - if (JTattooUtilities.getJavaVersion() >= 1.4) { - try { - Class paramTypes[] = null; - Object args[] = null; - Method m = root.getClass().getMethod("getWindowDecorationStyle", paramTypes); - Integer i = (Integer) m.invoke(root, args); - return i.intValue(); - } catch (Exception ex) { - } - } - return 0; - } - - public static int getExtendedState(Frame frame) { - if (JTattooUtilities.getJavaVersion() >= 1.4) { - try { - Class paramTypes[] = null; - Object args[] = null; - Method m = frame.getClass().getMethod("getExtendedState", paramTypes); - Integer i = (Integer) m.invoke(frame, args); - return i.intValue(); - } catch (Exception ex) { - } - } - return 0; - } - - public static void setExtendedState(Frame frame, int state) { - if (JTattooUtilities.getJavaVersion() >= 1.4) { - try { - Class classParams[] = {Integer.TYPE}; - Method m = frame.getClass().getMethod("setExtendedState", classParams); - Object methodParams[] = {new Integer(state)}; - m.invoke(frame, methodParams); - } catch (Exception ex) { - } - } - } - - public static boolean isFrameStateSupported(Toolkit tk, int state) { - if (JTattooUtilities.getJavaVersion() >= 1.4) { - try { - Class classParams[] = {Integer.TYPE}; - Method m = tk.getClass().getMethod("isFrameStateSupported", classParams); - Object methodParams[] = {new Integer(state)}; - Boolean b = (Boolean) m.invoke(tk, methodParams); - return b.booleanValue(); - } catch (Exception ex) { - } - } - return false; - } - - public static boolean isTranslucentWindowSupported() { - return (JTattooUtilities.getJavaVersion() >= 1.6010) && (JTattooUtilities.isMac() || JTattooUtilities.isWindows()); - } - - public static void setTranslucentWindow(Window wnd, boolean translucent) { - if (isTranslucentWindowSupported()) { - if (JTattooUtilities.getJavaVersion() >= 1.7) { - if (translucent) { - if (!wnd.getBackground().equals(new Color(0, 0, 0, 0))) { - wnd.setBackground(new Color(0, 0, 0, 0)); - } - } else { - if (!wnd.getBackground().equals(new Color(0, 0, 0, 0xff))) { - wnd.setBackground(new Color(0, 0, 0, 0xff)); - } - } - } else if (JTattooUtilities.getJavaVersion() >= 1.6010) { - try { - Class clazz = Class.forName("com.sun.awt.AWTUtilities"); - Class classParams[] = {Window.class, Boolean.TYPE}; - Method method = clazz.getMethod("setWindowOpaque", classParams); - if (translucent) { - Object methodParams[] = {wnd, Boolean.FALSE}; - method.invoke(wnd, methodParams); - } else { - Object methodParams[] = {wnd, Boolean.TRUE}; - method.invoke(wnd, methodParams); - } - } catch (Exception ex) { - } - } - } - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/JTattooUtilities.java b/src/jtattoo/src/com/jtattoo/plaf/JTattooUtilities.java deleted file mode 100644 index 11e3c8dca..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/JTattooUtilities.java +++ /dev/null @@ -1,499 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import java.lang.reflect.Method; -import javax.swing.*; -import javax.swing.plaf.basic.BasicGraphicsUtils; - -/** - * @author Michael Hagen - */ -public class JTattooUtilities { - - private static final boolean isWindows = System.getProperty( "os.name" ).toLowerCase().contains( "windows" ); - private static final boolean isOS2 = System.getProperty( "os.name" ).toLowerCase().contains( "os/2" ); - private static final boolean isMac = System.getProperty( "os.name" ).toLowerCase().contains( "mac" ); - private static final boolean isLinux = System.getProperty( "os.name" ).toLowerCase().contains( "linux" ); - private static final boolean isSunOS = System.getProperty( "os.name" ).toLowerCase().contains( "sunos" ); - private static final boolean isAIX = System.getProperty( "os.name" ).toLowerCase().contains( "aix" ); - private static final boolean isHPUX = System.getProperty( "os.name" ).toLowerCase().contains( "hpux" ); - private static final boolean isFreeBSD = System.getProperty( "os.name" ).toLowerCase().contains( "freebsd" ); - private static final boolean isHiresScreen = Toolkit.getDefaultToolkit().getScreenSize().width > 1280; - private static Double javaVersion = null; - private static final String ELLIPSIS = "..."; - - public static double getJavaVersion() { - if (javaVersion == null) { - try { - String ver = System.getProperties().getProperty("java.version"); - String version = ""; - boolean firstPoint = true; - for (int i = 0; i < ver.length(); i++) { - if (ver.charAt(i) == '.') { - if (firstPoint) { - version += ver.charAt(i); - } - firstPoint = false; - } else if (Character.isDigit(ver.charAt(i))) { - version += ver.charAt(i); - } - } - javaVersion = new Double(version); - } catch (Exception ex) { - javaVersion = new Double(1.3); - } - } - return javaVersion.doubleValue(); - } - - public static boolean isWindows() { - return isWindows; - } - - public static boolean isOS2() { - return isOS2; - } - - public static boolean isMac() { - return isMac; - } - - public static boolean isLinux() { - return isLinux; - } - - public static boolean isSunOS() { - return isSunOS; - } - - public static boolean isAIX() { - return isAIX; - } - - public static boolean isHPUX() { - return isHPUX; - } - - public static boolean isFreeBSD() { - return isFreeBSD; - } - - public static boolean isHiresScreen() { - return isHiresScreen; - } - - public static boolean isLeftToRight(Component c) { - if (c == null) { - return true; - } - return c.getComponentOrientation().isLeftToRight(); - } - - public static boolean isActive(JComponent c) { - if (c == null) { - return false; - } - - boolean active = true; - if (c instanceof JInternalFrame) { - active = ((JInternalFrame) c).isSelected(); - } - if (active) { - Container parent = c.getParent(); - while (parent != null) { - if (parent instanceof JInternalFrame) { - active = ((JInternalFrame) parent).isSelected(); - break; - } - parent = parent.getParent(); - } - } - if (active) { - active = isFrameActive(c); - } - return active; - } - - public static boolean isFrameActive(JComponent c) { - if (c == null) { - return false; - } - - if (c.getTopLevelAncestor() instanceof Window) { - return isWindowActive((Window) c.getTopLevelAncestor()); - } - - return true; - } - - public static boolean isWindowActive(Window window) { - if (getJavaVersion() >= 1.4) { - try { - Class paramTypes[] = null; - Object args[] = null; - Method m = window.getClass().getMethod("isActive", paramTypes); - Boolean b = (Boolean) m.invoke(window, args); - return b.booleanValue(); - } catch (Exception ex) { - } - } - return true; - } - - public static Container getRootContainer(Component c) { - if (c == null) { - return null; - } - Container parent = c.getParent(); - while ((parent != null) && !(parent instanceof JPopupMenu) && !(parent instanceof JInternalFrame) && !(parent instanceof Window) && (parent.getParent() != null)) { - parent = parent.getParent(); - } - return parent; - } - - public static Dimension getFrameSize(Component c) { - Container parent = getRootContainer(c); - if (parent != null) { - return parent.getSize(); - } - return Toolkit.getDefaultToolkit().getScreenSize(); - } - - public static Point getRelLocation(Component c) { - if (c == null || !c.isShowing()) { - return new Point(0, 0); - } - - Container parent = getRootContainer(c); - if ((parent != null) && parent.isShowing()) { - Point p1 = c.getLocationOnScreen(); - Point p2 = parent.getLocationOnScreen(); - return new Point(p1.x - p2.x, p1.y - p2.y); - } - - return new Point(0, 0); - } - - public static String getClippedText(String text, FontMetrics fm, int maxWidth) { - if ((text == null) || (text.length() == 0)) { - return ""; - } - int width = SwingUtilities.computeStringWidth(fm, text); - if (width > maxWidth) { - int totalWidth = SwingUtilities.computeStringWidth(fm, ELLIPSIS); - for (int i = 0; i < text.length(); i++) { - totalWidth += fm.charWidth(text.charAt(i)); - if (totalWidth > maxWidth) { - return text.substring(0, i) + ELLIPSIS; - } - } - } - return text; - } - - public static int findDisplayedMnemonicIndex(String text, int mnemonic) { - if (text == null || mnemonic == '\0') { - return -1; - } - - char uc = Character.toUpperCase((char)mnemonic); - char lc = Character.toLowerCase((char)mnemonic); - - int uci = text.indexOf(uc); - int lci = text.indexOf(lc); - - if (uci == -1) { - return lci; - } else if(lci == -1) { - return uci; - } else { - return (lci < uci) ? lci : uci; - } - } - - public static void drawString(JComponent c, Graphics g, String text, int x, int y) { - Graphics2D g2D = (Graphics2D) g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - if (getJavaVersion() >= 1.6) { - try { - Class swingUtilities2Class = Class.forName("sun.swing.SwingUtilities2"); - Class classParams[] = {JComponent.class, Graphics.class, String.class, Integer.TYPE, Integer.TYPE}; - Method m = swingUtilities2Class.getMethod("drawString", classParams); - Object methodParams[] = {c, g, text, new Integer(x), new Integer(y)}; - m.invoke(null, methodParams); - } catch (Exception ex) { - g.drawString(text, x, y); - } - } else { - g.drawString(text, x, y); - } - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } - - public static void drawStringUnderlineCharAt(JComponent c, Graphics g, String text, int underlinedIndex, int x, int y) { - Graphics2D g2D = (Graphics2D) g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - if (getJavaVersion() >= 1.6) { - try { - Class swingUtilities2Class = Class.forName("sun.swing.SwingUtilities2"); - Class classParams[] = {JComponent.class, Graphics.class, String.class, Integer.TYPE, Integer.TYPE, Integer.TYPE}; - Method m = swingUtilities2Class.getMethod("drawStringUnderlineCharAt", classParams); - Object methodParams[] = {c, g, text, new Integer(underlinedIndex), new Integer(x), new Integer(y)}; - m.invoke(null, methodParams); - } catch (Exception ex) { - BasicGraphicsUtils.drawString(g, text, underlinedIndex, x, y); - } - } else if (getJavaVersion() >= 1.4) { - BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, underlinedIndex, x, y); - } else { - BasicGraphicsUtils.drawString(g, text, underlinedIndex, x, y); - } - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } - - public static void fillHorGradient(Graphics g, Color[] colors, int x, int y, int w, int h) { - int steps = colors.length; - double dy = (double) h / (double) (steps); - if (dy <= 3.001) { - int y1 = y; - for (int i = 0; i < steps; i++) { - int y2 = y + (int) Math.round((double) i * dy); - g.setColor(colors[i]); - if (i == (steps - 1)) { - g.fillRect(x, y1, w, y + h - y1); - } else { - g.fillRect(x, y1, w, y2 - y1); - } - y1 = y2; - } - } else { - smoothFillHorGradient(g, colors, x, y, w, h); - } - } - - public static void smoothFillHorGradient(Graphics g, Color[] colors, int x, int y, int w, int h) { - Graphics2D g2D = (Graphics2D) g; - Paint savedPaint = g2D.getPaint(); - int steps = colors.length; - double dy = (double) h / (double) (steps - 1); - int y1 = y; - for (int i = 0; i < steps; i++) { - int y2 = y + (int) Math.round((double) i * dy); - if (i == (steps - 1)) { - g2D.setPaint(null); - g2D.setColor(colors[i]); - g2D.fillRect(x, y1, w, y + h - y1); - } else { - g2D.setPaint(new GradientPaint(0, y1, colors[i], 0, y2, colors[i + 1])); - g2D.fillRect(x, y1, w, y2 - y1); - } - y1 = y2; - } - g2D.setPaint(savedPaint); - } - - public static void fillInverseHorGradient(Graphics g, Color[] colors, int x, int y, int w, int h) { - int steps = colors.length; - double dy = (double) h / (double) steps; - if (dy <= 3.001) { - int y1 = y; - for (int i = 0; i < steps; i++) { - int y2 = y + (int) Math.round((double) i * dy); - g.setColor(colors[colors.length - i - 1]); - if (i == (steps - 1)) { - g.fillRect(x, y1, w, y + h - y1); - } else { - g.fillRect(x, y1, w, y2 - y1); - } - y1 = y2; - } - } else { - smoothFillInverseHorGradient(g, colors, x, y, w, h); - } - - } - - public static void smoothFillInverseHorGradient(Graphics g, Color[] colors, int x, int y, int w, int h) { - Graphics2D g2D = (Graphics2D) g; - Paint savedPaint = g2D.getPaint(); - int steps = colors.length; - double dy = (double) h / (double) steps; - int y1 = y; - for (int i = 0; i < steps; i++) { - int y2 = y + (int) Math.round((double) i * dy); - g.setColor(colors[colors.length - i - 1]); - if (i == (steps - 1)) { - g2D.setPaint(null); - g2D.setColor(colors[colors.length - i - 1]); - g.fillRect(x, y1, w, y + h - y1); - } else { - g2D.setPaint(new GradientPaint(0, y1, colors[colors.length - i - 1], 0, y2, colors[colors.length - i - 2])); - g.fillRect(x, y1, w, y2 - y1); - } - y1 = y2; - } - g2D.setPaint(savedPaint); - } - - public static void fillVerGradient(Graphics g, Color[] colors, int x, int y, int w, int h) { - int steps = colors.length; - double dx = (double) w / (double) steps; - int x1 = x; - for (int i = 0; i < steps; i++) { - int x2 = x + (int) Math.round((double) i * dx); - g.setColor(colors[i]); - if (i == (steps - 1)) { - g.fillRect(x1, y, x + w - x1, h); - } else { - g.fillRect(x1, y, x2 - x1, h); - } - x1 = x2; - } - } - - public static void fillInverseVerGradient(Graphics g, Color[] colors, int x, int y, int w, int h) { - int steps = colors.length; - double dx = (double) w / (double) steps; - int x1 = x; - for (int i = 0; i < steps; i++) { - int x2 = x + (int) Math.round((double) i * dx); - g.setColor(colors[colors.length - i - 1]); - if (i == (steps - 1)) { - g.fillRect(x1, y, x + w - x1, h); - } else { - g.fillRect(x1, y, x2 - x1, h); - } - x1 = x2; - } - } - - public static void fillComponent(Graphics g, Component c, Icon texture) { - int x = 0; - int y = 0; - int w = c.getWidth(); - int h = c.getHeight(); - if (texture != null) { - int tw = texture.getIconWidth(); - int th = texture.getIconHeight(); - Point p = JTattooUtilities.getRelLocation(c); - y = -p.y; - while (y < h) { - x = -p.x; - while (x < w) { - texture.paintIcon(c, g, x, y); - x += tw; - } - y += th; - } - } else { - g.setColor(c.getBackground()); - g.fillRect(x, y, w, h); - } - } - - //------------------------------------------------------------------------------------------- - - public static void drawBorder(Graphics g, Color c, int x, int y, int w, int h) { - g.setColor(c); - g.drawRect(x, y, w - 1, h - 1); - } - - public static void draw3DBorder(Graphics g, Color c1, Color c2, int x, int y, int w, int h) { - int x2 = x + w - 1; - int y2 = y + h - 1; - g.setColor(c1); - g.drawLine(x, y, x2 - 1, y); - g.drawLine(x, y + 1, x, y2); - g.setColor(c2); - g.drawLine(x, y2, x2 - 1, y2); - g.drawLine(x2, y, x2, y2); - } - - public static void drawRoundBorder(Graphics g, Color c, int x, int y, int w, int h, int r) { - Graphics2D g2D = (Graphics2D) g; - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2D.setColor(c); - g2D.drawRoundRect(x, y, w - 1, h - 1, r, r); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - } - - public static void drawRound3DBorder(Graphics g, Color c1, Color c2, int x, int y, int w, int h) { - Graphics2D g2D = (Graphics2D) g; - int x2 = x + w; - int y2 = y + h; - int d = h; - int r = h / 2; - Color cm = ColorHelper.median(c1, c2); - Color c1m = ColorHelper.median(c1, cm); - Color c2m = ColorHelper.median(c2, cm); - - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - // oben - g2D.setColor(c1); - g2D.drawLine(x + r, y, x2 - r, y); - // rechts - g2D.drawLine(x, y + r, x, y2 - r); - // unten - g2D.setColor(c2); - g2D.drawLine(x + r, y2, x2 - r, y2); - // links - g2D.drawLine(x2, y + r, x2, y2 - r); - - // links - g2D.setColor(c1); - g2D.drawArc(x, y, d, d, 90, 45); - g2D.setColor(c1m); - g2D.drawArc(x, y, d, d, 135, 45); - g2D.setColor(cm); - g2D.drawArc(x, y, d, d, 180, 45); - g2D.setColor(c2m); - g2D.drawArc(x, y, d, d, 225, 45); - // rechts - g2D.setColor(c1m); - g2D.drawArc(x2 - d, y, d, d, 45, 45); - g2D.setColor(cm); - g2D.drawArc(x2 - d, y, d, d, 0, 45); - g2D.setColor(c2m); - g2D.drawArc(x2 - d, y, d, d, -45, 45); - g2D.setColor(c2); - g2D.drawArc(x2 - d, y, d, d, -90, 45); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/LazyImageIcon.java b/src/jtattoo/src/com/jtattoo/plaf/LazyImageIcon.java deleted file mode 100644 index fd20a7985..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/LazyImageIcon.java +++ /dev/null @@ -1,89 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import javax.swing.Icon; -import javax.swing.ImageIcon; - -/** - * - * @author Michael Hagen - */ -public class LazyImageIcon implements Icon { - - private String name = null; - private ImageIcon icon = null; - - public LazyImageIcon(String name) { - this.name = name; - } - - private Icon getIcon() { - if (icon == null) { - try { - icon = new ImageIcon(LazyImageIcon.class.getResource(name)); - } catch (Throwable t) { - System.out.println("ERROR: loading image " + name + " failed!"); - } - } - return icon; - } - - public Image getImage() { - if (getIcon() != null) { - return icon.getImage(); - } - return null; - } - - public int getIconHeight() { - if (getIcon() != null) { - return icon.getIconHeight(); - } else { - return 16; - } - } - - public int getIconWidth() { - if (getIcon() != null) { - return icon.getIconWidth(); - } else { - return 16; - } - } - - public void paintIcon(Component c, Graphics g, int x, int y) { - if (getIcon() != null) { - icon.paintIcon(c, g, x, y); - } else { - g.setColor(Color.red); - g.fillRect(x, y, 16, 16); - g.setColor(Color.white); - g.drawLine(x, y, x + 15, y + 15); - g.drawLine(x + 15, y, x, y + 15); - } - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/LazyMenuArrowImageIcon.java b/src/jtattoo/src/com/jtattoo/plaf/LazyMenuArrowImageIcon.java deleted file mode 100644 index ec5bd0d42..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/LazyMenuArrowImageIcon.java +++ /dev/null @@ -1,107 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import javax.swing.Icon; -import javax.swing.ImageIcon; - -/** - * - * @author Michael Hagen - */ -public class LazyMenuArrowImageIcon implements Icon { - - private String leftToRightName = null; - private String rightToLefttName = null; - private Icon leftToRightIcon = null; - private Icon rightToLeftIcon = null; - - public LazyMenuArrowImageIcon(String leftToRightName, String rightToLefttName) { - this.leftToRightName = leftToRightName; - this.rightToLefttName = rightToLefttName; - } - - private Icon getLeftToRightIcon() { - if (leftToRightIcon == null) { - try { - leftToRightIcon = new ImageIcon(LazyMenuArrowImageIcon.class.getResource(leftToRightName)); - } catch (Throwable t) { - System.out.println("ERROR: loading image " + leftToRightName + " failed!"); - } - } - return leftToRightIcon; - } - - private Icon getRightToLeftIcon() { - if (rightToLeftIcon == null) { - try { - rightToLeftIcon = new ImageIcon(LazyMenuArrowImageIcon.class.getResource(rightToLefttName)); - } catch (Throwable t) { - System.out.println("ERROR: loading image " + rightToLefttName + " failed!"); - } - } - return rightToLeftIcon; - } - - private Icon getIcon(Component c) { - if (JTattooUtilities.isLeftToRight(c)) { - return getLeftToRightIcon(); - } else { - return getRightToLeftIcon(); - } - } - - public int getIconHeight() { - Icon ico = getIcon(null); - if (ico != null) { - return ico.getIconHeight(); - } else { - return 16; - } - } - - public int getIconWidth() { - Icon ico = getIcon(null); - if (ico != null) { - return ico.getIconWidth(); - } else { - return 16; - } - } - - public void paintIcon(Component c, Graphics g, int x, int y) { - Icon ico = getIcon(c); - if (ico != null) { - ico.paintIcon(c, g, x, y); - } else { - g.setColor(Color.red); - g.fillRect(x, y, 16, 16); - g.setColor(Color.white); - g.drawLine(x, y, x + 15, y + 15); - g.drawLine(x + 15, y, x, y + 15); - } - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/NoFocusButton.java b/src/jtattoo/src/com/jtattoo/plaf/NoFocusButton.java deleted file mode 100644 index e0e9600f8..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/NoFocusButton.java +++ /dev/null @@ -1,58 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import javax.swing.Icon; -import javax.swing.JButton; - -/** - * @author Michael Hagen - */ -public class NoFocusButton extends JButton { - - public NoFocusButton() { - super(); - init(); - } - - public NoFocusButton(Icon ico) { - super(ico); - init(); - } - - private void init() { - setFocusPainted(false); - setRolloverEnabled(true); - if (JTattooUtilities.getJavaVersion() >= 1.4) { - setFocusable(false); - } - } - - public boolean isFocusTraversable() { - return false; - } - - public void requestFocus() { - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/XPScrollBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/XPScrollBarUI.java deleted file mode 100644 index 20d08bd28..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/XPScrollBarUI.java +++ /dev/null @@ -1,154 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import com.jtattoo.plaf.texture.TextureScrollButton; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * - * @author Michael Hagen - */ -public class XPScrollBarUI extends BaseScrollBarUI { - - protected static Color rolloverColors[] = null; - protected static Color dragColors[] = null; - - public static ComponentUI createUI(JComponent c) { - return new XPScrollBarUI(); - } - - protected void installDefaults() { - super.installDefaults(); - Color colors[] = AbstractLookAndFeel.getTheme().getThumbColors(); - rolloverColors = new Color[colors.length]; - dragColors = new Color[colors.length]; - for (int i = 0; i < colors.length; i++) { - rolloverColors[i] = ColorHelper.brighter(colors[i], 16); - dragColors[i] = ColorHelper.darker(colors[i], 8); - } - } - - protected JButton createDecreaseButton(int orientation) { - return new TextureScrollButton(orientation, scrollBarWidth); - } - - protected JButton createIncreaseButton(int orientation) { - return new TextureScrollButton(orientation, scrollBarWidth); - } - - protected Color getFrameColor() { - return Color.white; - } - - protected Color[] getThumbColors() { - if (isDragging) { - return dragColors; - } - if (isRollover) { - return rolloverColors; - } - return AbstractLookAndFeel.getTheme().getThumbColors(); - } - - protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { - if (!c.isEnabled()) { - return; - } - - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - - int x = thumbBounds.x; - int y = thumbBounds.y; - int width = thumbBounds.width; - int height = thumbBounds.height; - - g.translate(x, y); - - Color[] colors = getThumbColors(); - if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { - JTattooUtilities.fillVerGradient(g, colors, 0, 0, width, height); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - int dx = 6; - int dy = height / 2 - 3; - int dw = width - 13; - Color c1 = ColorHelper.brighter(colors[0], 60); - Color c2 = ColorHelper.darker(colors[0], 30); - for (int i = 0; i < 4; i++) { - g.setColor(c1); - g.drawLine(dx, dy, dx + dw, dy); - dy++; - g.setColor(c2); - g.drawLine(dx, dy, dx + dw, dy); - dy++; - } - } else { - JTattooUtilities.fillHorGradient(g, colors, 0, 0, width, height); - int dx = width / 2 - 3; - int dy = 6; - int dh = height - 13; - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f); - g2D.setComposite(alpha); - Color c1 = ColorHelper.brighter(colors[0], 60); - Color c2 = ColorHelper.darker(colors[0], 30); - for (int i = 0; i < 4; i++) { - g.setColor(c1); - g.drawLine(dx, dy, dx, dy + dh); - dx++; - g.setColor(c2); - g.drawLine(dx, dy, dx, dy + dh); - dx++; - } - } - - g2D.setComposite(savedComposite); - g.setColor(getFrameColor()); - g.drawLine(1, 1, width - 2, 1); - g.drawLine(1, 2, 1, height - 3); - g.drawLine(width - 2, 2, width - 2, height - 3); - g.drawLine(2, height - 2, width - 3, height - 2); - - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); - g2D.setComposite(alpha); - Color fc = colors[colors.length - 1]; - g2D.setColor(fc); - g.drawLine(2, 2, width - 3, 2); - g.drawLine(2, 3, 2, height - 3); - - g.setColor(ColorHelper.darker(fc, 40)); - g.drawLine(width - 1, 2, width - 1, height - 3); - g.drawLine(3, height - 1, width - 3, height - 1); - alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f); - g2D.setComposite(alpha); - g.drawLine(1, height - 2, 2, height - 1); - g.drawLine(width - 1, height - 2, width - 2, height - 1); - - g.translate(-x, -y); - g2D.setComposite(savedComposite); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/XPScrollButton.java b/src/jtattoo/src/com/jtattoo/plaf/XPScrollButton.java deleted file mode 100644 index 761d61c40..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/XPScrollButton.java +++ /dev/null @@ -1,128 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf; - -import java.awt.*; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public abstract class XPScrollButton extends BaseScrollButton { - - public XPScrollButton(int direction, int width) { - super(direction, width); - } - - public abstract Icon getUpArrowIcon(); - public abstract Icon getDownArrowIcon(); - public abstract Icon getLeftArrowIcon(); - public abstract Icon getRightArrowIcon(); - - public Color getFrameColor() { - return Color.white; - } - - public void paint(Graphics g) { - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - Paint savedPaint = g2D.getPaint(); - - boolean isPressed = getModel().isPressed(); - boolean isRollover = getModel().isRollover(); - - int width = getWidth(); - int height = getHeight(); - - Color[] tc = AbstractLookAndFeel.getTheme().getThumbColors(); - Color c1 = tc[0]; - Color c2 = tc[tc.length - 1]; - if (isPressed) { - c1 = ColorHelper.darker(c1, 5); - c2 = ColorHelper.darker(c2, 5); - } else if (isRollover) { - c1 = ColorHelper.brighter(c1, 20); - c2 = ColorHelper.brighter(c2, 20); - } - - g2D.setPaint(new GradientPaint(0, 0, c1, width, height, c2)); - g.fillRect(0, 0, width, height); - g2D.setPaint(savedPaint); - - g.setColor(getFrameColor()); - g.drawLine(1, 1, width - 2, 1); - g.drawLine(1, 1, 1, height - 3); - g.drawLine(width - 2, 1, width - 2, height - 3); - g.drawLine(2, height - 2, width - 3, height - 2); - - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); - g2D.setComposite(alpha); - g2D.setColor(c2); - g.drawLine(2, 2, width - 3, 2); - g.drawLine(2, 3, 2, height - 3); - - g.setColor(ColorHelper.darker(c2, 40)); - g.drawLine(width - 1, 2, width - 1, height - 3); - g.drawLine(3, height - 1, width - 3, height - 1); - alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f); - g2D.setComposite(alpha); - g.drawLine(1, height - 2, 2, height - 1); - g.drawLine(width - 1, height - 2, width - 2, height - 1); - - g2D.setComposite(savedComposite); - - // paint the icon - if (getDirection() == NORTH) { - int x = (width / 2) - (getUpArrowIcon().getIconWidth() / 2); - int y = (height / 2) - (getUpArrowIcon().getIconHeight() / 2); - getUpArrowIcon().paintIcon(this, g, x, y); - } else if (getDirection() == SOUTH) { - int x = (width / 2) - (getDownArrowIcon().getIconWidth() / 2); - int y = (height / 2) - (getDownArrowIcon().getIconHeight() / 2) + 1; - getDownArrowIcon().paintIcon(this, g, x, y); - } else if (getDirection() == WEST) { - int x = (width / 2) - (getLeftArrowIcon().getIconWidth() / 2); - int y = (height / 2) - (getLeftArrowIcon().getIconHeight() / 2); - getLeftArrowIcon().paintIcon(this, g, x, y); - } else { - int x = (width / 2) - (getRightArrowIcon().getIconWidth() / 2) + 1; - int y = (height / 2) - (getRightArrowIcon().getIconHeight() / 2); - getRightArrowIcon().paintIcon(this, g, x, y); - } - } - - public Dimension getPreferredSize() { - if (getDirection() == NORTH) { - return new Dimension(buttonWidth, buttonWidth); - } else if (getDirection() == SOUTH) { - return new Dimension(buttonWidth, buttonWidth); - } else if (getDirection() == EAST) { - return new Dimension(buttonWidth, buttonWidth); - } else if (getDirection() == WEST) { - return new Dimension(buttonWidth, buttonWidth); - } else { - return new Dimension(0, 0); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylBorderFactory.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylBorderFactory.java deleted file mode 100644 index 3ded54d30..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylBorderFactory.java +++ /dev/null @@ -1,122 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.AbstractBorderFactory; -import javax.swing.border.Border; - -/** - * @author Michael Hagen - */ -public class AcrylBorderFactory implements AbstractBorderFactory { - - private static AcrylBorderFactory instance = null; - - private AcrylBorderFactory() { - } - - public static synchronized AcrylBorderFactory getInstance() { - if (instance == null) { - instance = new AcrylBorderFactory(); - } - return instance; - } - - public Border getFocusFrameBorder() { - return AcrylBorders.getFocusFrameBorder(); - } - - public Border getButtonBorder() { - return AcrylBorders.getButtonBorder(); - } - - public Border getToggleButtonBorder() { - return AcrylBorders.getToggleButtonBorder(); - } - - public Border getTextBorder() { - return AcrylBorders.getTextBorder(); - } - - public Border getSpinnerBorder() { - return AcrylBorders.getSpinnerBorder(); - } - - public Border getTextFieldBorder() { - return AcrylBorders.getTextFieldBorder(); - } - - public Border getComboBoxBorder() { - return AcrylBorders.getComboBoxBorder(); - } - - public Border getTableHeaderBorder() { - return AcrylBorders.getTableHeaderBorder(); - } - - public Border getTableScrollPaneBorder() { - return AcrylBorders.getTableScrollPaneBorder(); - } - - public Border getScrollPaneBorder() { - return AcrylBorders.getScrollPaneBorder(); - } - - public Border getTabbedPaneBorder() { - return AcrylBorders.getTabbedPaneBorder(); - } - - public Border getMenuBarBorder() { - return AcrylBorders.getMenuBarBorder(); - } - - public Border getMenuItemBorder() { - return AcrylBorders.getMenuItemBorder(); - } - - public Border getPopupMenuBorder() { - return AcrylBorders.getPopupMenuBorder(); - } - - public Border getInternalFrameBorder() { - return AcrylBorders.getInternalFrameBorder(); - } - - public Border getPaletteBorder() { - return AcrylBorders.getPaletteBorder(); - } - - public Border getToolBarBorder() { - return AcrylBorders.getToolBarBorder(); - } - - public Border getProgressBarBorder() { - return AcrylBorders.getProgressBarBorder(); - } - - public Border getDesktopIconBorder() { - return AcrylBorders.getDesktopIconBorder(); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylBorders.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylBorders.java deleted file mode 100644 index 79c77882c..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylBorders.java +++ /dev/null @@ -1,366 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.AbstractButton; -import javax.swing.ButtonModel; -import javax.swing.border.AbstractBorder; -import javax.swing.border.Border; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class AcrylBorders extends BaseBorders { - - //------------------------------------------------------------------------------------ - // Lazy access methods - //------------------------------------------------------------------------------------ - public static Border getTextBorder() { - if (textFieldBorder == null) { - textFieldBorder = new TextFieldBorder(); - } - return textFieldBorder; - } - - public static Border getSpinnerBorder() { - if (spinnerBorder == null) { - spinnerBorder = new SpinnerBorder(); - } - return spinnerBorder; - } - - public static Border getTextFieldBorder() { - return getTextBorder(); - } - - public static Border getComboBoxBorder() { - if (comboBoxBorder == null) { - comboBoxBorder = new ComboBoxBorder(); - } - return comboBoxBorder; - } - - public static Border getScrollPaneBorder() { - if (scrollPaneBorder == null) { - scrollPaneBorder = new ScrollPaneBorder(false); - } - return scrollPaneBorder; - } - - public static Border getTableScrollPaneBorder() { - if (tableScrollPaneBorder == null) { - tableScrollPaneBorder = new ScrollPaneBorder(true); - } - return tableScrollPaneBorder; - } - - public static Border getButtonBorder() { - if (buttonBorder == null) { - buttonBorder = new ButtonBorder(); - } - return buttonBorder; - } - - public static Border getToggleButtonBorder() { - return getButtonBorder(); - } - - public static Border getRolloverToolButtonBorder() { - if (rolloverToolButtonBorder == null) { - rolloverToolButtonBorder = new RolloverToolButtonBorder(); - } - return rolloverToolButtonBorder; - } - - public static Border getInternalFrameBorder() { - if (internalFrameBorder == null) { - internalFrameBorder = new InternalFrameBorder(); - } - return internalFrameBorder; - } - - //------------------------------------------------------------------------------------ - // Implementation of border classes - //------------------------------------------------------------------------------------ - public static class TextFieldBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(2, 2, 2, 2); - - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - Color borderColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFrameColor(), 50); - g.setColor(borderColor); - g.drawRect(x, y, width - 1, height - 1); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - } // class TextFieldBorder - - public static class SpinnerBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - Color borderColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFrameColor(), 50); - g.setColor(borderColor); - g.drawRect(x, y, width - 1, height - 1); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - } // class SpinnerBorder - - public static class ComboBoxBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - Color borderColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFrameColor(), 50); - g.setColor(borderColor); - g.drawRect(x, y, width - 1, height - 1); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - } // class ComboBoxBorder - - public static class ScrollPaneBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(2, 2, 2, 2); - private static final Insets tableInsets = new Insets(1, 1, 1, 1); - - private boolean tableBorder = false; - - public ScrollPaneBorder(boolean tableBorder) { - this.tableBorder = tableBorder; - } - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFrameColor(), 50)); - g.drawRect(x, y, w - 1, h - 1); - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getTheme().getBackgroundColor(), 50)); - g.drawRect(x + 1, y + 1, w - 3, h - 3); - } - - public Insets getBorderInsets(Component c) { - if (tableBorder) { - return new Insets(tableInsets.top, tableInsets.left, tableInsets.bottom, tableInsets.right); - } else { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - Insets ins = getBorderInsets(c); - borderInsets.left = ins.left; - borderInsets.top = ins.top; - borderInsets.right = ins.right; - borderInsets.bottom = ins.bottom; - return borderInsets; - } - - } // class ScrollPaneBorder - - public static class ButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(3, 6, 3, 6); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - Graphics2D g2D = (Graphics2D) g; - Color frameColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFrameColor(), 50); - if (!JTattooUtilities.isFrameActive(button)) { - frameColor = ColorHelper.brighter(frameColor, 30); - } - if (model.isRollover() && !model.isPressed() && !model.isArmed()) { - frameColor = AbstractLookAndFeel.getTheme().getRolloverColorDark(); - } - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - g2D.setColor(Color.white); - g2D.drawRoundRect(x, y, w - 1, h - 1, 6, 6); - - g2D.setColor(frameColor); - g2D.drawRoundRect(x, y, w - 2, h - 2, 6, 6); - - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - } - - public Insets getBorderInsets(Component c) { - return insets; - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class ButtonBorder - - public static class RolloverToolButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(2, 2, 2, 2); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - if (model.isEnabled()) { - if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - Color frameColor = ColorHelper.darker(AbstractLookAndFeel.getToolbarBackgroundColor(), 30); - g.setColor(frameColor); - g.drawRect(x, y, w - 1, h - 1); - Graphics2D g2D = (Graphics2D) g; - Composite savedComposit = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f); - g2D.setComposite(alpha); - g.setColor(Color.black); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(savedComposit); - } else if (model.isRollover()) { - Color frameColor = AbstractLookAndFeel.getToolbarBackgroundColor(); - Color frameHiColor = ColorHelper.darker(frameColor, 5); - Color frameLoColor = ColorHelper.darker(frameColor, 30); - JTattooUtilities.draw3DBorder(g, frameHiColor, frameLoColor, x, y, w, h); - frameHiColor = Color.white; - frameLoColor = ColorHelper.brighter(frameLoColor, 60); - JTattooUtilities.draw3DBorder(g, frameHiColor, frameLoColor, x + 1, y + 1, w - 2, h - 2); - - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - g.setColor(Color.white); - g.fillRect(x + 2, y + 2, w - 4, h - 4); - g2D.setComposite(composite); - } else if (model.isSelected()) { - Color frameColor = AbstractLookAndFeel.getToolbarBackgroundColor(); - Color frameHiColor = Color.white; - Color frameLoColor = ColorHelper.darker(frameColor, 30); - JTattooUtilities.draw3DBorder(g, frameLoColor, frameHiColor, x, y, w, h); - } - } - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class RolloverToolButtonBorder - - public static class InternalFrameBorder extends BaseInternalFrameBorder { - - public InternalFrameBorder() { - insets.top = 3; - } - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - boolean active = isActive(c); - int th = getTitleHeight(c); - Color titleColor = ColorHelper.brighter(AbstractLookAndFeel.getWindowInactiveTitleColorLight(), 10); - Color borderColor = AbstractLookAndFeel.getWindowInactiveTitleColorLight(); - Color frameColor = ColorHelper.darker(AbstractLookAndFeel.getWindowInactiveBorderColor(), 10); - if (active) { - titleColor = AbstractLookAndFeel.getWindowTitleColorLight(); - borderColor = AbstractLookAndFeel.getWindowTitleColorLight(); - frameColor = ColorHelper.darker(AbstractLookAndFeel.getWindowBorderColor(), 10); - } - g.setColor(titleColor); - g.fillRect(x, y + 1, w, insets.top - 1); - g.setColor(borderColor); - g.fillRect(x + 1, y + h - dw, w - 2, dw - 1); - - if (active) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 1, insets.top, dw, th + 1); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), w - dw, insets.top, dw, th + 1); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 1, insets.top, dw - 1, th + 1); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), w - dw, insets.top, dw - 1, th + 1); - } - g.setColor(borderColor); - g.fillRect(1, insets.top + th + 1, dw - 1, h - th - dw); - g.fillRect(w - dw, insets.top + th + 1, dw - 1, h - th - dw); - - g.setColor(frameColor); - g.drawRect(x, y, w - 1, h - 1); - g.drawLine(x + dw - 1, y + insets.top + th, x + dw - 1, y + h - dw); - g.drawLine(x + w - dw, y + insets.top + th, x + w - dw, y + h - dw); - g.drawLine(x + dw - 1, y + h - dw, x + w - dw, y + h - dw); - } - - } // class InternalFrameBorder - -} // class AcrylBorders - diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylButtonUI.java deleted file mode 100644 index d85f4dff3..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylButtonUI.java +++ /dev/null @@ -1,59 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.BaseButtonUI; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.RoundRectangle2D; -import javax.swing.AbstractButton; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class AcrylButtonUI extends BaseButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new AcrylButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - int w = b.getWidth(); - int h = b.getHeight(); - Graphics2D g2D = (Graphics2D) g; - Shape savedClip = g.getClip(); - if ((b.getBorder() != null) && b.isBorderPainted() && (b.getBorder() instanceof UIResource)) { - Area clipArea = new Area(new RoundRectangle2D.Double(0, 0, w -1, h - 1, 6, 6)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - } - super.paintBackground(g, b); - g2D.setClip(savedClip); - } -} - - diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylComboBoxUI.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylComboBoxUI.java deleted file mode 100644 index 0dc563ad9..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylComboBoxUI.java +++ /dev/null @@ -1,64 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AcrylComboBoxUI extends BaseComboBoxUI { - - public static ComponentUI createUI(JComponent c) { - return new AcrylComboBoxUI(); - } - - public JButton createArrowButton() { - ArrowButton button = new BaseComboBoxUI.ArrowButton(); - Color borderColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFrameColor(), 50); - if (JTattooUtilities.isLeftToRight(comboBox)) { - Border border = BorderFactory.createMatteBorder(0, 1, 0, 0, borderColor); - button.setBorder(border); - } else { - Border border = BorderFactory.createMatteBorder(0, 0, 0, 1, borderColor); - button.setBorder(border); - } - return button; - } - - protected void setButtonBorder() { - Color borderColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFrameColor(), 50); - if (JTattooUtilities.isLeftToRight(comboBox)) { - Border border = BorderFactory.createMatteBorder(0, 1, 0, 0, borderColor); - arrowButton.setBorder(border); - } else { - Border border = BorderFactory.createMatteBorder(0, 0, 0, 1, borderColor); - arrowButton.setBorder(border); - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylDefaultTheme.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylDefaultTheme.java deleted file mode 100644 index 850ba8869..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylDefaultTheme.java +++ /dev/null @@ -1,222 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.AbstractTheme; -import com.jtattoo.plaf.ColorHelper; -import java.awt.Color; -import javax.swing.plaf.ColorUIResource; - -public class AcrylDefaultTheme extends AbstractTheme { - - public AcrylDefaultTheme() { - super(); - // Setup theme with defaults - setUpColor(); - // Overwrite defaults with user props - loadProperties(); - // Setup the color arrays - setUpColorArrs(); - } - - public String getPropertyFileName() { - return "AcrylTheme.properties"; - } - - public void setUpColor() { - super.setUpColor(); - // Defaults for AcrylLookAndFeel - menuOpaque = false; - menuAlpha = 0.90f; - - backgroundColor = new ColorUIResource(244, 244, 244); - backgroundColorLight = new ColorUIResource(255, 255, 255); - backgroundColorDark = new ColorUIResource(232, 232, 232); - alterBackgroundColor = new ColorUIResource(232, 232, 232); - - selectionForegroundColor = white; - selectionBackgroundColor = extraDarkGray; - frameColor = new ColorUIResource(32, 32, 32); - focusCellColor = focusColor; - - buttonBackgroundColor = extraLightGray; - buttonColorLight = new ColorUIResource(244, 244, 244); - buttonColorDark = new ColorUIResource(220, 220, 220); - - rolloverColor = new ColorUIResource(152, 191, 231); - rolloverColorLight = new ColorUIResource(188, 252, 255); - rolloverColorDark = new ColorUIResource(61, 134, 209); - - controlForegroundColor = black; - controlBackgroundColor = backgroundColor; - controlColorLight = new ColorUIResource(96, 98, 100); - controlColorDark = new ColorUIResource(64, 65, 66);//new ColorUIResource(48, 49, 50); - - controlShadowColor = gray; - controlDarkShadowColor = darkGray; - - windowTitleForegroundColor = white; - windowTitleBackgroundColor = gray; // controlColorLight; - windowTitleColorLight = controlColorLight; - windowTitleColorDark = controlColorDark; - windowBorderColor = new ColorUIResource(0, 0, 0); - - windowInactiveTitleForegroundColor = new ColorUIResource(ColorHelper.brighter(windowTitleForegroundColor, 10)); - windowInactiveTitleBackgroundColor = new ColorUIResource(244, 244, 244); // new ColorUIResource(ColorHelper.brighter(windowTitleBackgroundColor, 10)); - windowInactiveTitleColorLight = new ColorUIResource(ColorHelper.brighter(windowTitleColorLight, 10)); - windowInactiveTitleColorDark = new ColorUIResource(ColorHelper.brighter(windowTitleColorDark, 10)); - windowInactiveBorderColor = new ColorUIResource(ColorHelper.brighter(windowBorderColor, 10)); - - menuBackgroundColor = backgroundColor; - menuSelectionForegroundColor = white; - menuSelectionBackgroundColor = extraDarkGray; - menuColorLight = white; - menuColorDark = backgroundColor; - - toolbarBackgroundColor = backgroundColor; - toolbarColorLight = menuColorLight; - toolbarColorDark = menuColorDark; - - tabAreaBackgroundColor = backgroundColor; - tabSelectionForegroundColor = selectionForegroundColor; - - desktopColor = backgroundColor; - } - - public void setUpColorArrs() { - super.setUpColorArrs(); - - // Generate the color arrays - Color topHi = ColorHelper.brighter(controlColorLight, 10); - Color topLo = ColorHelper.brighter(controlColorLight, 20);//ColorHelper.brighter(controlColorLight, 30); - Color bottomHi = controlColorDark; - Color bottomLo = controlColorLight; - - Color[] topColors = ColorHelper.createColorArr(topHi, topLo, 10); - Color[] bottomColors = ColorHelper.createColorArr(bottomHi, bottomLo, 10); - DEFAULT_COLORS = new Color[20]; - for (int i = 0; i < 10; i++) { - DEFAULT_COLORS[i] = topColors[i]; - DEFAULT_COLORS[i + 10] = bottomColors[i]; - } - - ACTIVE_COLORS = DEFAULT_COLORS; -// topHi = ColorHelper.brighter(backgroundColor, 15); -// topLo = ColorHelper.darker(backgroundColor, 5); -// INACTIVE_COLORS = ColorHelper.createColorArr(topHi, topLo, 20); - if (controlColorLight.equals(new ColorUIResource(96, 98, 100))) { - ROLLOVER_COLORS = new Color[]{ - new Color(194, 207, 233), - new Color(185, 201, 231), - new Color(176, 195, 228), - new Color(168, 189, 226), - new Color(158, 182, 223), - new Color(148, 176, 220), - new Color(138, 169, 217), - new Color(132, 169, 217), - new Color(124, 169, 218), - new Color(116, 167, 218), - new Color(104, 160, 218), - new Color(86, 150, 214), - new Color(64, 136, 210), - new Color(72, 144, 214), - new Color(79, 150, 219), - new Color(89, 157, 224), - new Color(100, 165, 230), - new Color(110, 172, 235), - new Color(120, 180, 240), - new Color(127, 186, 247), - new Color(134, 193, 254), - new Color(142, 202, 254), - new Color(151, 211, 255), - new Color(158, 218, 255), - new Color(166, 226, 255), - new Color(177, 239, 255), - new Color(188, 252, 255),}; - } else { - topHi = ColorHelper.brighter(rolloverColorLight, 20); - topLo = ColorHelper.brighter(rolloverColorLight, 30); - bottomHi = rolloverColorDark; - bottomLo = rolloverColorLight; - topColors = ColorHelper.createColorArr(topHi, topLo, 10); - bottomColors = ColorHelper.createColorArr(bottomHi, bottomLo, 10); - ROLLOVER_COLORS = new Color[20]; - for (int i = 0; i < 10; i++) { - ROLLOVER_COLORS[i] = topColors[i]; - ROLLOVER_COLORS[i + 10] = bottomColors[i]; - } - } - - SELECTED_COLORS = ColorHelper.createColorArr(new Color(200, 200, 200), new Color(240, 240, 240), 20); - PRESSED_COLORS = SELECTED_COLORS; - DISABLED_COLORS = ColorHelper.createColorArr(Color.white, new Color(230, 230, 230), 20); - - topHi = windowTitleColorLight; - topLo = ColorHelper.brighter(windowTitleColorLight, 20); - bottomHi = windowTitleColorDark; - bottomLo = windowTitleColorLight; - topColors = ColorHelper.createColorArr(topHi, topLo, 10); - bottomColors = ColorHelper.createColorArr(bottomHi, bottomLo, 10); - WINDOW_TITLE_COLORS = new Color[20]; - for (int i = 0; i < 10; i++) { - WINDOW_TITLE_COLORS[i] = topColors[i]; - WINDOW_TITLE_COLORS[i + 10] = bottomColors[i]; - } - - topHi = windowInactiveTitleColorLight; - topLo = ColorHelper.brighter(windowInactiveTitleColorLight, 20); - bottomHi = windowInactiveTitleColorDark; - bottomLo = windowInactiveTitleColorLight; - topColors = ColorHelper.createColorArr(topHi, topLo, 10); - bottomColors = ColorHelper.createColorArr(bottomHi, bottomLo, 10); - WINDOW_INACTIVE_TITLE_COLORS = new Color[20]; - for (int i = 0; i < 10; i++) { - WINDOW_INACTIVE_TITLE_COLORS[i] = ColorHelper.brighter(topColors[i], 10); - WINDOW_INACTIVE_TITLE_COLORS[i + 10] = ColorHelper.brighter(bottomColors[i], 10); - } - - MENUBAR_COLORS = ColorHelper.createColorArr(menuColorLight, menuColorDark, 20); - TOOLBAR_COLORS = ColorHelper.createColorArr(toolbarColorLight, toolbarColorDark, 20); - - topHi = ColorHelper.brighter(buttonColorLight, 20); - topLo = ColorHelper.brighter(buttonColorLight, 80); - bottomHi = buttonColorDark; - bottomLo = buttonColorLight; - topColors = ColorHelper.createColorArr(topHi, topLo, 10); - bottomColors = ColorHelper.createColorArr(bottomHi, bottomLo, 10); - BUTTON_COLORS = new Color[20]; - for (int i = 0; i < 10; i++) { - BUTTON_COLORS[i] = topColors[i]; - BUTTON_COLORS[i + 10] = bottomColors[i]; - } - INACTIVE_COLORS = BUTTON_COLORS; - TAB_COLORS = BUTTON_COLORS; - COL_HEADER_COLORS = BUTTON_COLORS; - - TRACK_COLORS = ColorHelper.createColorArr(backgroundColor, Color.white, 16); - THUMB_COLORS = DEFAULT_COLORS; - SLIDER_COLORS = DEFAULT_COLORS; - PROGRESSBAR_COLORS = DEFAULT_COLORS; - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylIconFactory.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylIconFactory.java deleted file mode 100644 index 503cc4417..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylIconFactory.java +++ /dev/null @@ -1,213 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.AbstractIconFactory; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class AcrylIconFactory implements AbstractIconFactory { - - private static AcrylIconFactory instance = null; - - private AcrylIconFactory() { - } - - public static synchronized AcrylIconFactory getInstance() { - if (instance == null) { - instance = new AcrylIconFactory(); - } - return instance; - } - - public Icon getOptionPaneErrorIcon() { - return AcrylIcons.getOptionPaneErrorIcon(); - } - - public Icon getOptionPaneWarningIcon() { - return AcrylIcons.getOptionPaneWarningIcon(); - } - - public Icon getOptionPaneInformationIcon() { - return AcrylIcons.getOptionPaneInformationIcon(); - } - - public Icon getOptionPaneQuestionIcon() { - return AcrylIcons.getOptionPaneQuestionIcon(); - } - - public Icon getFileChooserDetailViewIcon() { - return AcrylIcons.getFileChooserDetailViewIcon(); - } - - public Icon getFileChooserHomeFolderIcon() { - return AcrylIcons.getFileChooserHomeFolderIcon(); - } - - public Icon getFileChooserListViewIcon() { - return AcrylIcons.getFileChooserListViewIcon(); - } - - public Icon getFileChooserNewFolderIcon() { - return AcrylIcons.getFileChooserNewFolderIcon(); - } - - public Icon getFileChooserUpFolderIcon() { - return AcrylIcons.getFileChooserUpFolderIcon(); - } - - public Icon getMenuIcon() { - return AcrylIcons.getMenuIcon(); - } - - public Icon getIconIcon() { - return AcrylIcons.getIconIcon(); - } - - public Icon getMaxIcon() { - return AcrylIcons.getMaxIcon(); - } - - public Icon getMinIcon() { - return AcrylIcons.getMinIcon(); - } - - public Icon getCloseIcon() { - return AcrylIcons.getCloseIcon(); - } - - public Icon getPaletteCloseIcon() { - return AcrylIcons.getPaletteCloseIcon(); - } - - public Icon getRadioButtonIcon() { - return AcrylIcons.getRadioButtonIcon(); - } - - public Icon getCheckBoxIcon() { - return AcrylIcons.getCheckBoxIcon(); - } - - public Icon getComboBoxIcon() { - return AcrylIcons.getComboBoxIcon(); - } - - public Icon getTreeComputerIcon() { - return AcrylIcons.getTreeComputerIcon(); - } - - public Icon getTreeFloppyDriveIcon() { - return AcrylIcons.getTreeFloppyDriveIcon(); - } - - public Icon getTreeHardDriveIcon() { - return AcrylIcons.getTreeHardDriveIcon(); - } - - public Icon getTreeFolderIcon() { - return AcrylIcons.getTreeFolderIcon(); - } - - public Icon getTreeLeafIcon() { - return AcrylIcons.getTreeLeafIcon(); - } - - public Icon getTreeCollapsedIcon() { - return AcrylIcons.getTreeControlIcon(true); - } - - public Icon getTreeExpandedIcon() { - return AcrylIcons.getTreeControlIcon(false); - } - - public Icon getMenuArrowIcon() { - return AcrylIcons.getMenuArrowIcon(); - } - - public Icon getMenuCheckBoxIcon() { - return AcrylIcons.getMenuCheckBoxIcon(); - } - - public Icon getMenuRadioButtonIcon() { - return AcrylIcons.getMenuRadioButtonIcon(); - } - - public Icon getUpArrowIcon() { - return AcrylIcons.getUpArrowIcon(); - } - - public Icon getDownArrowIcon() { - return AcrylIcons.getDownArrowIcon(); - } - - public Icon getLeftArrowIcon() { - return AcrylIcons.getLeftArrowIcon(); - } - - public Icon getRightArrowIcon() { - return AcrylIcons.getRightArrowIcon(); - } - - public Icon getSplitterDownArrowIcon() { - return AcrylIcons.getSplitterDownArrowIcon(); - } - - public Icon getSplitterHorBumpIcon() { - return AcrylIcons.getSplitterHorBumpIcon(); - } - - public Icon getSplitterLeftArrowIcon() { - return AcrylIcons.getSplitterLeftArrowIcon(); - } - - public Icon getSplitterRightArrowIcon() { - return AcrylIcons.getSplitterRightArrowIcon(); - } - - public Icon getSplitterUpArrowIcon() { - return AcrylIcons.getSplitterUpArrowIcon(); - } - - public Icon getSplitterVerBumpIcon() { - return AcrylIcons.getSplitterVerBumpIcon(); - } - - public Icon getThumbHorIcon() { - return AcrylIcons.getThumbHorIcon(); - } - - public Icon getThumbVerIcon() { - return AcrylIcons.getThumbVerIcon(); - } - - public Icon getThumbHorIconRollover() { - return AcrylIcons.getThumbHorIconRollover(); - } - - public Icon getThumbVerIconRollover() { - return AcrylIcons.getThumbVerIconRollover(); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylIcons.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylIcons.java deleted file mode 100644 index bb0488798..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylIcons.java +++ /dev/null @@ -1,392 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.*; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.Ellipse2D; -import javax.swing.*; -import javax.swing.plaf.ColorUIResource; - -/** - * @author Michael Hagen - */ -public class AcrylIcons extends BaseIcons { - - public static Icon getIconIcon() { - if (iconIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - iconIcon = new MacIconIcon(); - } else { - iconIcon = new TitleButtonIcon(TitleButtonIcon.ICON_ICON_TYP); - } - } - return iconIcon; - } - - public static Icon getMinIcon() { - if (minIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - minIcon = new MacMinIcon(); - } else { - minIcon = new TitleButtonIcon(TitleButtonIcon.MIN_ICON_TYP); - } - } - return minIcon; - } - - public static Icon getMaxIcon() { - if (maxIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - maxIcon = new MacMaxIcon(); - } else { - maxIcon = new TitleButtonIcon(TitleButtonIcon.MAX_ICON_TYP); - } - } - return maxIcon; - } - - public static Icon getCloseIcon() { - if (closeIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - closeIcon = new MacCloseIcon(); - } else { - closeIcon = new TitleButtonIcon(TitleButtonIcon.CLOSE_ICON_TYP); - } - } - return closeIcon; - } - - public static Icon getTreeControlIcon(boolean isCollapsed) { - if (!AbstractLookAndFeel.getControlColorLight().equals(new ColorUIResource(96, 98, 100))) { - return BaseIcons.getTreeControlIcon(isCollapsed); - } - - if (isCollapsed) { - if (treeClosedIcon == null) { - treeClosedIcon = new LazyImageIcon("acryl/icons/TreeClosedButton.gif"); - } - return treeClosedIcon; - } else { - if (treeOpenIcon == null) { - treeOpenIcon = new LazyImageIcon("acryl/icons/TreeOpenButton.gif"); - } - return treeOpenIcon; - } - } - - public static Icon getRadioButtonIcon() { - if (radioButtonIcon == null) { - radioButtonIcon = new RadioButtonIcon(); - } - return radioButtonIcon; - } - - public static Icon getCheckBoxIcon() { - if (checkBoxIcon == null) { - checkBoxIcon = new CheckBoxIcon(); - } - return checkBoxIcon; - } - - public static Icon getThumbHorIcon() { - if (!AbstractLookAndFeel.getControlColorLight().equals(new ColorUIResource(96, 98, 100))) { - return BaseIcons.getThumbHorIcon(); - } - - if (thumbHorIcon == null) { - thumbHorIcon = new LazyImageIcon("acryl/icons/thumb_hor.gif"); - } - return thumbHorIcon; - } - - public static Icon getThumbVerIcon() { - if (!AbstractLookAndFeel.getControlColorLight().equals(new ColorUIResource(96, 98, 100))) { - return BaseIcons.getThumbVerIcon(); - } - - if (thumbVerIcon == null) { - thumbVerIcon = new LazyImageIcon("acryl/icons/thumb_ver.gif"); - } - return thumbVerIcon; - } - - public static Icon getThumbHorIconRollover() { - if (!AbstractLookAndFeel.getControlColorLight().equals(new ColorUIResource(96, 98, 100))) { - return BaseIcons.getThumbHorIconRollover(); - } - - if (thumbHorIconRollover == null) { - thumbHorIconRollover = new LazyImageIcon("acryl/icons/thumb_hor_rollover.gif"); - } - return thumbHorIconRollover; - } - - public static Icon getThumbVerIconRollover() { - if (!AbstractLookAndFeel.getControlColorLight().equals(new ColorUIResource(96, 98, 100))) { - return BaseIcons.getThumbVerIconRollover(); - } - - if (thumbVerIconRollover == null) { - thumbVerIconRollover = new LazyImageIcon("acryl/icons/thumb_ver_rollover.gif"); - } - return thumbVerIconRollover; - } - -//------------------------------------------------------------------------------ - private static class TitleButtonIcon implements Icon { - - private static Color extraLightGray = new Color(240, 240, 240); - private static Color closerColorLight = new Color(241, 172, 154); - private static Color closerColorDark = new Color(224, 56, 2); - public static final int ICON_ICON_TYP = 0; - public static final int MIN_ICON_TYP = 1; - public static final int MAX_ICON_TYP = 2; - public static final int CLOSE_ICON_TYP = 3; - private int iconTyp = ICON_ICON_TYP; - - public TitleButtonIcon(int typ) { - iconTyp = typ; - } - - public int getIconHeight() { - return 20; - } - - public int getIconWidth() { - return 20; - } - - public void paintIcon(Component c, Graphics g, int x, int y) { - int w = c.getWidth(); - int h = c.getHeight(); - - JButton b = (JButton) c; - Graphics2D g2D = (Graphics2D) g; - - boolean isPressed = b.getModel().isPressed(); - boolean isArmed = b.getModel().isArmed(); - boolean isRollover = b.getModel().isRollover(); - - Color cFrame = AbstractLookAndFeel.getTheme().getWindowBorderColor(); - Color cFrameInner = ColorHelper.brighter(cFrame, 60); - Color cHi = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getWindowTitleColorLight(), 40); - Color cLo = ColorHelper.darker(AbstractLookAndFeel.getTheme().getWindowTitleColorDark(), 10); - Color cShadow = Color.black; - if (iconTyp == CLOSE_ICON_TYP) { - cHi = closerColorLight; - cLo = closerColorDark; - } - - if (isPressed && isArmed) { - Color cTemp = ColorHelper.darker(cLo, 10); - cLo = ColorHelper.darker(cHi, 10); - cHi = cTemp; - g2D.setPaint(new GradientPaint(0, 0, cHi, w, h, cLo)); - g.fillRect(2, 2, w - 3, h - 3); - } else if (isRollover) { - cFrameInner = ColorHelper.brighter(cFrameInner, 50); - if (iconTyp == CLOSE_ICON_TYP) { - cHi = closerColorLight; - cLo = closerColorDark; - cShadow = cLo; - g2D.setPaint(new GradientPaint(0, 0, cHi, w, h, cLo)); - g2D.fillRect(2, 2, w - 3, h - 3); - } else { - JTattooUtilities.fillHorGradient(g2D, AbstractLookAndFeel.getTheme().getRolloverColors(), 2, 2, w - 3, h - 3); - } - } - - g2D.setColor(cFrame); - g2D.drawLine(1, 0, w - 2, 0); - g2D.drawLine(1, h - 1, w - 2, h - 1); - g2D.drawLine(0, 1, 0, h - 2); - g2D.drawLine(w - 1, 1, w - 1, h - 2); - - g2D.setColor(cFrameInner); - g2D.drawRect(1, 1, w - 3, h - 3); - - Icon icon = null; - if (iconTyp == ICON_ICON_TYP) { - icon = new BaseIcons.IconSymbol(extraLightGray, cShadow, null, new Insets(0, 5, 0, 5)); - } else if (iconTyp == MIN_ICON_TYP) { - icon = new BaseIcons.MinSymbol(extraLightGray, cShadow, null, new Insets(0, 4, 0, 4)); - } else if (iconTyp == MAX_ICON_TYP) { - icon = new BaseIcons.MaxSymbol(extraLightGray, cShadow, null, new Insets(0, 4, 0, 4)); - } else if (iconTyp == CLOSE_ICON_TYP) { - icon = new BaseIcons.CloseSymbol(Color.white, ColorHelper.darker(cShadow, 50), null, new Insets(0, 5, 0, 5)); - } - if (icon != null) { - icon.paintIcon(c, g, 0, 0); - } - } - } - - //----------------------------------------------------------------------------------------------------------- - private static class CheckBoxIcon implements Icon { - - private static Icon checkIcon = new LazyImageIcon("acryl/icons/CheckSymbol.gif"); - private static Icon checkPressedIcon = new LazyImageIcon("acryl/icons/CheckPressedSymbol.gif"); - private static Icon checkInactiveIcon = new LazyImageIcon("icons/CheckSymbol.gif"); - private static Icon checkDisabledIcon = new LazyImageIcon("icons/CheckSymbolDisabled.gif"); - - private static final int WIDTH = 14; - private static final int HEIGHT = 14; - - public void paintIcon(Component c, Graphics g, int x, int y) { - if (!JTattooUtilities.isLeftToRight(c)) { - x += 3; - } - AbstractButton b = (AbstractButton) c; - ButtonModel model = b.getModel(); - Color frameColor = AbstractLookAndFeel.getFrameColor(); - - if (b.isEnabled()) { - if (b.isRolloverEnabled() && model.isRollover()) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getRolloverColors(), x + 1, y + 1, WIDTH - 2, HEIGHT - 2); - frameColor = ColorHelper.brighter(frameColor, 30); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getDefaultColors(), x + 1, y + 1, WIDTH - 2, HEIGHT - 2); - } - - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getDisabledColors(), x + 1, y + 1, WIDTH - 2, HEIGHT - 2); - frameColor = ColorHelper.brighter(frameColor, 40); - } - - g.setColor(AbstractLookAndFeel.getTheme().getControlShadowColor()); - g.drawRect(x, y, WIDTH - 1, HEIGHT - 1); - g.setColor(frameColor); - g.drawLine(x + 1, y, x + WIDTH - 2, y); - g.drawLine(x + 1, y + HEIGHT - 1, x + WIDTH - 2, y + HEIGHT - 1); - g.drawLine(x, y + 1, x, y + HEIGHT - 2); - g.drawLine(x + WIDTH - 1, y + 1, x + WIDTH - 1, y + HEIGHT - 2); - g.setColor(AbstractLookAndFeel.getTheme().getControlShadowColor()); - g.drawLine(x + WIDTH, y + 2, x + WIDTH, y + HEIGHT - 1); - g.drawLine(x + 2, y + HEIGHT, x + WIDTH - 1, y + HEIGHT); - - int xi = x + ((WIDTH - checkInactiveIcon.getIconWidth()) / 2) - 1; - int yi = y + ((HEIGHT - checkInactiveIcon.getIconHeight()) / 2) - 1; - if (model.isPressed() && model.isArmed()) { - checkPressedIcon.paintIcon(c, g, xi + 1, yi + 1); - } else if (model.isSelected()) { - if (!model.isEnabled()) { - checkDisabledIcon.paintIcon(c, g, xi + 1, yi + 1); - } else { - int gv; - if (model.isRollover()) { - gv = ColorHelper.getGrayValue(AbstractLookAndFeel.getTheme().getRolloverColorDark()); - } else { - gv = ColorHelper.getGrayValue(AbstractLookAndFeel.getTheme().getControlColorDark()); - } - if (gv > 128) { - checkInactiveIcon.paintIcon(c, g, xi + 1, yi + 1); - } else { - checkIcon.paintIcon(c, g, xi, yi); - } - } - } - } - - public int getIconWidth() { - return WIDTH + 4; - } - - public int getIconHeight() { - return HEIGHT; - } - } - - //----------------------------------------------------------------------------------------------------------- - private static class RadioButtonIcon implements Icon { - - private static Icon radioIcon = new LazyImageIcon("acryl/icons/RadioSymbol.gif"); - private static final int WIDTH = 13; - private static final int HEIGHT = 13; - - public void paintIcon(Component c, Graphics g, int x, int y) { - if (!JTattooUtilities.isLeftToRight(c)) { - x += 3; - } - Graphics2D g2D = (Graphics2D) g; - AbstractButton b = (AbstractButton) c; - ButtonModel model = b.getModel(); - Color frameColor = AbstractLookAndFeel.getFrameColor(); - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - Shape savedClip = g.getClip(); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2D.setColor(AbstractLookAndFeel.getTheme().getControlShadowColor()); - g2D.drawOval(x + 1, y + 1, WIDTH - 1, HEIGHT - 1); - Area clipArea = new Area(new Ellipse2D.Double(x, y, WIDTH, HEIGHT)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - if (b.isEnabled()) { - if (b.isRolloverEnabled() && model.isRollover()) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getRolloverColors(), x + 1, y + 1, WIDTH - 2, HEIGHT - 2); - frameColor = ColorHelper.brighter(frameColor, 30); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getDefaultColors(), x + 1, y + 1, WIDTH - 2, HEIGHT - 2); - } - - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getDisabledColors(), x + 1, y + 1, WIDTH - 2, HEIGHT - 2); - frameColor = ColorHelper.brighter(frameColor, 40); - } - g2D.setClip(savedClip); - g2D.setColor(frameColor); - g2D.drawOval(x, y, WIDTH - 1, HEIGHT - 1); - if (model.isSelected()) { - int xi = x + ((WIDTH - radioIcon.getIconWidth()) / 2); - int yi = y + ((HEIGHT - radioIcon.getIconHeight()) / 2); - if (!model.isEnabled()) { - g.setColor(Color.gray); - g.fillOval(x + (WIDTH / 2) - 2, y + (HEIGHT / 2) - 2, 5, 5); - } else { - int gv; - if (model.isRollover()) { - gv = ColorHelper.getGrayValue(AbstractLookAndFeel.getTheme().getRolloverColorDark()); - } else { - gv = ColorHelper.getGrayValue(AbstractLookAndFeel.getTheme().getControlColorDark()); - } - if (gv > 128) { - g.setColor(Color.black); - g.fillOval(x + (WIDTH / 2) - 2, y + (HEIGHT / 2) - 2, 5, 5); - } else { - radioIcon.paintIcon(c, g, xi, yi); - } - } - } - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - } - - public int getIconWidth() { - return WIDTH + 4; - } - - public int getIconHeight() { - return HEIGHT; - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylInternalFrameTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylInternalFrameTitlePane.java deleted file mode 100644 index 0f4086331..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylInternalFrameTitlePane.java +++ /dev/null @@ -1,233 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.Icon; -import javax.swing.JInternalFrame; - -/** - * @author Michael Hagen - */ -public class AcrylInternalFrameTitlePane extends BaseInternalFrameTitlePane { - - public AcrylInternalFrameTitlePane(JInternalFrame f) { - super(f); - } - - protected LayoutManager createLayout() { - return new BaseTitlePaneLayout(); - } - - protected int getHorSpacing() { - return 1; - } - - protected int getVerSpacing() { - return 3; - } - - public void paintBorder(Graphics g) { - if (isActive()) { - g.setColor(AbstractLookAndFeel.getWindowBorderColor()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveBorderColor()); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } - - public void paintText(Graphics g, int x, int y, String title) { - if (isMacStyleWindowDecoration()) { - x += paintIcon(g, x, y) + 5; - } - Color shadowColor = AbstractLookAndFeel.getWindowTitleColorDark(); - if (isActive()) { - shadowColor = ColorHelper.darker(shadowColor, 30); - } - g.setColor(shadowColor); - JTattooUtilities.drawString(frame, g, title, x - 1, y - 2); - JTattooUtilities.drawString(frame, g, title, x - 1, y ); - JTattooUtilities.drawString(frame, g, title, x + 1, y - 2); - JTattooUtilities.drawString(frame, g, title, x + 1, y); - if (isActive()) { - g.setColor(AbstractLookAndFeel.getWindowTitleForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - } - JTattooUtilities.drawString(frame, g, title, x, y - 1); - } - -//-------------------------------------------------------------------------------------------- - class BaseTitlePaneLayout extends TitlePaneLayout { - - public void addLayoutComponent(String name, Component c) { - } - - public void removeLayoutComponent(Component c) { - } - - public Dimension preferredLayoutSize(Container c) { - return minimumLayoutSize(c); - } - - public Dimension minimumLayoutSize(Container c) { - int width = 30; - if (frame.isClosable()) { - width += 21; - } - if (frame.isMaximizable()) { - width += 16 + (frame.isClosable() ? 10 : 4); - } - if (frame.isIconifiable()) { - width += 16 + (frame.isMaximizable() ? 2 : (frame.isClosable() ? 10 : 4)); - } - FontMetrics fm = getFontMetrics(getFont()); - String frameTitle = frame.getTitle(); - int title_w = frameTitle != null ? fm.stringWidth(frameTitle) : 0; - int title_length = frameTitle != null ? frameTitle.length() : 0; - - if (title_length > 2) { - int subtitle_w = fm.stringWidth(frame.getTitle().substring(0, 2) + "..."); - width += (title_w < subtitle_w) ? title_w : subtitle_w; - } else { - width += title_w; - } - - int height = paletteTitleHeight; - if (!isPalette) { - int fontHeight = fm.getHeight() + 5; - Icon icon = isMacStyleWindowDecoration() ? null : frame.getFrameIcon(); - int iconHeight = 0; - if (icon != null) { - iconHeight = Math.min(icon.getIconHeight(), 18); - } - iconHeight += 5; - height = Math.max(fontHeight, iconHeight); - } - return new Dimension(width, height); - } - - public void layoutContainer(Container c) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - layoutMacStyle(c); - } else { - layoutDefault(c); - } - } - - public void layoutDefault(Container c) { - boolean leftToRight = JTattooUtilities.isLeftToRight(frame); - - int spacing = getHorSpacing(); - int w = getWidth(); - int h = getHeight(); - - // assumes all buttons have the same dimensions these dimensions include the borders - int btnHeight = h - getVerSpacing(); - int btnWidth = btnHeight + 10; - - int x = leftToRight ? w - spacing : 0; - int y = Math.max(0, ((h - btnHeight) / 2) - 1); - - if (frame.isClosable()) { - x += leftToRight ? -btnWidth : spacing; - closeButton.setBounds(x, y, btnWidth, btnHeight); - if (!leftToRight) { - x += btnWidth; - } - } - - if (frame.isMaximizable() && !isPalette) { - x += leftToRight ? -spacing - btnWidth : spacing; - maxButton.setBounds(x, y, btnWidth, btnHeight); - if (!leftToRight) { - x += btnWidth; - } - } - - if (frame.isIconifiable() && !isPalette) { - x += leftToRight ? -spacing - btnWidth : spacing; - iconButton.setBounds(x, y, btnWidth, btnHeight); - if (!leftToRight) { - x += btnWidth; - } - } - - buttonsWidth = leftToRight ? w - x : x; - - if (customTitlePanel != null) { - int maxWidth = w - buttonsWidth - spacing - 20; - Icon icon = frame.getFrameIcon(); - if (icon != null) { - maxWidth -= icon.getIconWidth(); - maxWidth -= spacing; - } - int cpw = Math.min(maxWidth, customTitlePanel.getPreferredSize().width); - int cph = h; - int cpx = leftToRight ? w - buttonsWidth - cpw : buttonsWidth; - int cpy = 0; - customTitlePanel.setBounds(cpx, cpy, cpw, cph); - buttonsWidth += customTitlePanel.getPreferredSize().width; - } - } - - private void layoutMacStyle(Container c) { - int spacing = getHorSpacing(); - int h = getHeight(); - - // assumes all buttons have the same dimensions these dimensions include the borders - int btnHeight = h - getVerSpacing(); - int btnWidth = btnHeight; - - int x = 0; - int y = 0; - - if (frame.isClosable()) { - closeButton.setBounds(x, y, btnWidth, btnHeight); - x += btnWidth + spacing; - } - if (frame.isIconifiable() && !isPalette) { - iconButton.setBounds(x, y, btnWidth, btnHeight); - x += btnWidth + spacing; - } - if (frame.isMaximizable() && !isPalette) { - maxButton.setBounds(x, y, btnWidth, btnHeight); - x += btnWidth + spacing; - } - - buttonsWidth = x; - - if (customTitlePanel != null) { - int cpx = buttonsWidth + 5; - int cpy = 0; - int cpw = customTitlePanel.getPreferredSize().width; - int cph = h; - customTitlePanel.setBounds(cpx, cpy, cpw, cph); - buttonsWidth += cpw + 5; - } - } - - } // end class BaseTitlePaneLayout -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylInternalFrameUI.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylInternalFrameUI.java deleted file mode 100644 index 0ebe10685..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylInternalFrameUI.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.BaseInternalFrameUI; -import javax.swing.JComponent; -import javax.swing.JInternalFrame; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AcrylInternalFrameUI extends BaseInternalFrameUI { - - public AcrylInternalFrameUI(JInternalFrame b) { - super(b); - } - - public static ComponentUI createUI(JComponent c) { - return new AcrylInternalFrameUI((JInternalFrame) c); - } - - protected JComponent createNorthPane(JInternalFrame w) { - titlePane = new AcrylInternalFrameTitlePane(w); - return titlePane; - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylLookAndFeel.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylLookAndFeel.java deleted file mode 100644 index e0afef850..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylLookAndFeel.java +++ /dev/null @@ -1,378 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.*; -import java.util.*; -import javax.swing.UIDefaults; - -/** - * @author Michael Hagen - */ -public class AcrylLookAndFeel extends AbstractLookAndFeel { - - private static AcrylDefaultTheme myTheme = null; - - private static final ArrayList themesList = new ArrayList(); - private static final HashMap themesMap = new HashMap(); - private static final Properties defaultProps = new Properties(); - private static final Properties smallFontProps = new Properties(); - private static final Properties largeFontProps = new Properties(); - private static final Properties giantFontProps = new Properties(); - private static final Properties greenProps = new Properties(); - private static final Properties greenSmallFontProps = new Properties(); - private static final Properties greenLargeFontProps = new Properties(); - private static final Properties greenGiantFontProps = new Properties(); - private static final Properties lemmonProps = new Properties(); - private static final Properties lemmonSmallFontProps = new Properties(); - private static final Properties lemmonLargeFontProps = new Properties(); - private static final Properties lemmonGiantFontProps = new Properties(); - private static final Properties redProps = new Properties(); - private static final Properties redSmallFontProps = new Properties(); - private static final Properties redLargeFontProps = new Properties(); - private static final Properties redGiantFontProps = new Properties(); - - static { - smallFontProps.setProperty("controlTextFont", "Dialog 10"); - smallFontProps.setProperty("systemTextFont", "Dialog 10"); - smallFontProps.setProperty("userTextFont", "Dialog 10"); - smallFontProps.setProperty("menuTextFont", "Dialog 10"); - smallFontProps.setProperty("windowTitleFont", "Dialog bold 10"); - smallFontProps.setProperty("subTextFont", "Dialog 8"); - - largeFontProps.setProperty("controlTextFont", "Dialog 14"); - largeFontProps.setProperty("systemTextFont", "Dialog 14"); - largeFontProps.setProperty("userTextFont", "Dialog 14"); - largeFontProps.setProperty("menuTextFont", "Dialog 14"); - largeFontProps.setProperty("windowTitleFont", "Dialog bold 14"); - largeFontProps.setProperty("subTextFont", "Dialog 12"); - - giantFontProps.setProperty("controlTextFont", "Dialog 18"); - giantFontProps.setProperty("systemTextFont", "Dialog 18"); - giantFontProps.setProperty("userTextFont", "Dialog 18"); - giantFontProps.setProperty("menuTextFont", "Dialog 18"); - giantFontProps.setProperty("windowTitleFont", "Dialog 18"); - giantFontProps.setProperty("subTextFont", "Dialog 16"); - - greenProps.setProperty("backgroundColor", "232 229 222"); - greenProps.setProperty("alterBackgroundColor", "220 216 205"); - greenProps.setProperty("frameColor", "28 64 43"); - greenProps.setProperty("selectionBackgroundColor", "54 126 85"); - greenProps.setProperty("menuSelectionBackgroundColor", "54 126 85"); - greenProps.setProperty("controlColorLight", "64 149 100"); - greenProps.setProperty("controlColorDark", "48 112 75"); - greenProps.setProperty("rolloverColor", "255 213 113"); - greenProps.setProperty("rolloverColorLight", "255 213 113"); - greenProps.setProperty("rolloverColorDark", "240 168 0"); - greenProps.setProperty("windowTitleBackgroundColor", "64 149 100"); - greenProps.setProperty("windowTitleColorLight", "64 149 100"); - greenProps.setProperty("windowTitleColorDark", "48 112 75"); - greenProps.setProperty("windowBorderColor", "40 94 63"); - greenProps.setProperty("windowInactiveTitleBackgroundColor", "77 179 120"); - greenProps.setProperty("windowInactiveTitleColorLight", "77 179 120"); - greenProps.setProperty("windowInactiveTitleColorDark", "64 149 100"); - greenProps.setProperty("windowInactiveBorderColor", "64 149 100"); - greenProps.setProperty("menuBackgroundColor", "232 229 222"); - greenProps.setProperty("menuColorLight", "238 236 232"); - greenProps.setProperty("menuColorDark", "232 229 222"); - greenProps.setProperty("toolbarBackgroundColor", "232 229 222"); - greenProps.setProperty("toolbarColorLight", "238 236 232"); - greenProps.setProperty("toolbarColorDark", "232 229 222"); - greenProps.setProperty("desktopColor", "244 242 232"); - - lemmonProps.setProperty("backgroundColor", "240 243 242"); - lemmonProps.setProperty("frameColor", "100 133 14"); - lemmonProps.setProperty("selectionForegroundColor", "0 0 0"); - lemmonProps.setProperty("selectionBackgroundColor", "175 232 28"); - lemmonProps.setProperty("rolloverColor", "231 253 104"); - lemmonProps.setProperty("rolloverColorLight", "243 254 180"); - lemmonProps.setProperty("rolloverColorDark", "231 253 104"); - lemmonProps.setProperty("windowTitleForegroundColor", "243 254 180"); - lemmonProps.setProperty("windowTitleBackgroundColor", "164 217 23"); - lemmonProps.setProperty("windowTitleColorLight", "164 217 23"); - lemmonProps.setProperty("windowTitleColorDark", "140 186 20"); - lemmonProps.setProperty("windowBorderColor", "106 140 15"); - lemmonProps.setProperty("windowInactiveTitleForegroundColor", "243 254 180"); - lemmonProps.setProperty("windowInactiveTitleBackgroundColor", "148 196 21"); - lemmonProps.setProperty("windowInactiveTitleColorLight", "148 196 21"); - lemmonProps.setProperty("windowInactiveTitleColorDark", "126 167 18"); - lemmonProps.setProperty("windowInactiveBorderColor", "92 123 13"); - lemmonProps.setProperty("controlColorLight", "207 245 35"); - lemmonProps.setProperty("controlColorDark", "155 211 18"); - lemmonProps.setProperty("menuBackgroundColor", "240 243 242"); - lemmonProps.setProperty("menuSelectionForegroundColor", "0 0 0"); - lemmonProps.setProperty("menuSelectionBackgroundColor", "175 232 28"); - lemmonProps.setProperty("menuColorLight", "244 247 245"); - lemmonProps.setProperty("menuColorDark", "232 236 235"); - lemmonProps.setProperty("toolbarBackgroundColor", "240 243 242"); - lemmonProps.setProperty("toolbarColorLight", "244 247 245"); - lemmonProps.setProperty("toolbarColorDark", "232 236 235"); - - redProps.setProperty("backgroundColor", "244 244 244"); - redProps.setProperty("frameColor", "64 48 48"); - redProps.setProperty("selectionForegroundColor", "255 255 255"); - redProps.setProperty("selectionBackgroundColor", "220 0 0"); - redProps.setProperty("rolloverColor", "222 222 190"); - redProps.setProperty("rolloverColorLight", "248 248 180"); - redProps.setProperty("rolloverColorDark", "200 200 120"); - redProps.setProperty("windowTitleForegroundColor", "255 255 255"); - redProps.setProperty("windowTitleBackgroundColor", "160 0 0"); - redProps.setProperty("windowTitleColorLight", "230 12 12"); - redProps.setProperty("windowTitleColorDark", "190 0 0"); - redProps.setProperty("windowBorderColor", "160 0 0"); - redProps.setProperty("windowInactiveTitleForegroundColor", "255 255 255"); - redProps.setProperty("windowInactiveTitleBackgroundColor", "180 0 0"); - redProps.setProperty("windowInactiveTitleColorLight", "255 24 24"); - redProps.setProperty("windowInactiveTitleColorDark", "180 0 0"); - redProps.setProperty("windowInactiveBorderColor", "180 0 0"); - redProps.setProperty("controlColorLight", "255 24 24"); - redProps.setProperty("controlColorDark", "190 0 0"); - redProps.setProperty("menuBackgroundColor", "248 248 248"); - redProps.setProperty("menuSelectionForegroundColor", "255 255 255"); - redProps.setProperty("menuSelectionBackgroundColor", "220 0 0"); - redProps.setProperty("menuColorLight", "248 248 248"); - redProps.setProperty("menuColorDark", "236 236 236"); - redProps.setProperty("toolbarBackgroundColor", "248 248 248"); - redProps.setProperty("toolbarColorLight", "248 248 248"); - redProps.setProperty("toolbarColorDark", "236 236 236"); - - String key; - String value; - Iterator iter = smallFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = smallFontProps.getProperty(key); - greenSmallFontProps.setProperty(key, value); - lemmonSmallFontProps.setProperty(key, value); - redSmallFontProps.setProperty(key, value); - } - iter = largeFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = largeFontProps.getProperty(key); - greenLargeFontProps.setProperty(key, value); - lemmonLargeFontProps.setProperty(key, value); - redLargeFontProps.setProperty(key, value); - } - iter = giantFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = giantFontProps.getProperty(key); - greenGiantFontProps.setProperty(key, value); - lemmonGiantFontProps.setProperty(key, value); - redGiantFontProps.setProperty(key, value); - } - - iter = greenProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = greenProps.getProperty(key); - greenSmallFontProps.setProperty(key, value); - greenLargeFontProps.setProperty(key, value); - greenGiantFontProps.setProperty(key, value); - } - iter = lemmonProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = lemmonProps.getProperty(key); - lemmonSmallFontProps.setProperty(key, value); - lemmonLargeFontProps.setProperty(key, value); - lemmonGiantFontProps.setProperty(key, value); - } - iter = redProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = redProps.getProperty(key); - redSmallFontProps.setProperty(key, value); - redLargeFontProps.setProperty(key, value); - redGiantFontProps.setProperty(key, value); - } - - themesList.add("Default"); - themesList.add("Small-Font"); - themesList.add("Large-Font"); - themesList.add("Giant-Font"); - - themesList.add("Green"); - themesList.add("Green-Small-Font"); - themesList.add("Green-Large-Font"); - themesList.add("Green-Giant-Font"); - - themesList.add("Lemmon"); - themesList.add("Lemmon-Small-Font"); - themesList.add("Lemmon-Large-Font"); - themesList.add("Lemmon-Giant-Font"); - - themesList.add("Red"); - themesList.add("Red-Small-Font"); - themesList.add("Red-Large-Font"); - themesList.add("Red-Giant-Font"); - - themesMap.put("Default", defaultProps); - themesMap.put("Small-Font", smallFontProps); - themesMap.put("Large-Font", largeFontProps); - themesMap.put("Giant-Font", giantFontProps); - - themesMap.put("Green", greenProps); - themesMap.put("Green-Small-Font", greenSmallFontProps); - themesMap.put("Green-Large-Font", greenLargeFontProps); - themesMap.put("Green-Giant-Font", greenGiantFontProps); - - themesMap.put("Lemmon", lemmonProps); - themesMap.put("Lemmon-Small-Font", lemmonSmallFontProps); - themesMap.put("Lemmon-Large-Font", lemmonLargeFontProps); - themesMap.put("Lemmon-Giant-Font", lemmonGiantFontProps); - - themesMap.put("Red", redProps); - themesMap.put("Red-Small-Font", redSmallFontProps); - themesMap.put("Red-Large-Font", redLargeFontProps); - themesMap.put("Red-Giant-Font", redGiantFontProps); - } - - public static java.util.List getThemes() { - return themesList; - } - - public static Properties getThemeProperties(String name) { - return ((Properties) themesMap.get(name)); - } - - public static void setTheme(String name) { - setTheme((Properties) themesMap.get(name)); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - - public static void setTheme(String name, String licenseKey, String logoString) { - Properties props = (Properties) themesMap.get(name); - if (props != null) { - props.put("licenseKey", licenseKey); - props.put("logoString", logoString); - setTheme(props); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - } - - public static void setTheme(Properties themesProps) { - if (myTheme == null) { - myTheme = new AcrylDefaultTheme(); - } - if ((myTheme != null) && (themesProps != null)) { - myTheme.setUpColor(); - myTheme.setProperties(themesProps); - myTheme.setUpColorArrs(); - AbstractLookAndFeel.setTheme(myTheme); - } - } - - public static void setCurrentTheme(Properties themesProps) { - setTheme(themesProps); - } - - public String getName() { - return "Acryl"; - } - - public String getID() { - return "Acryl"; - } - - public String getDescription() { - return "The Acryl Look and Feel"; - } - - public boolean isNativeLookAndFeel() { - return false; - } - - public boolean isSupportedLookAndFeel() { - return true; - } - - public AbstractBorderFactory getBorderFactory() { - return AcrylBorderFactory.getInstance(); - } - - public AbstractIconFactory getIconFactory() { - return AcrylIconFactory.getInstance(); - } - - protected void createDefaultTheme() { - if (myTheme == null) { - myTheme = new AcrylDefaultTheme(); - } - setTheme(myTheme); - } - - protected void initClassDefaults(UIDefaults table) { - super.initClassDefaults(table); - Object[] uiDefaults = { - // BaseLookAndFeel classes - "ToggleButtonUI", BaseToggleButtonUI.class.getName(), - "LabelUI", BaseLabelUI.class.getName(), - "SeparatorUI", BaseSeparatorUI.class.getName(), - "TextFieldUI", BaseTextFieldUI.class.getName(), - "TextAreaUI", BaseTextAreaUI.class.getName(), - "EditorPaneUI", BaseEditorPaneUI.class.getName(), - "PasswordFieldUI", BasePasswordFieldUI.class.getName(), - "CheckBoxUI", BaseCheckBoxUI.class.getName(), - "RadioButtonUI", BaseRadioButtonUI.class.getName(), - "SplitPaneUI", BaseSplitPaneUI.class.getName(), - "ToolTipUI", BaseToolTipUI.class.getName(), - "TreeUI", BaseTreeUI.class.getName(), - "TableUI", BaseTableUI.class.getName(), - "SliderUI", BaseSliderUI.class.getName(), - "ProgressBarUI", BaseProgressBarUI.class.getName(), - "ScrollPaneUI", BaseScrollPaneUI.class.getName(), - "PanelUI", BasePanelUI.class.getName(), - "TableHeaderUI", BaseTableHeaderUI.class.getName(), - "FileChooserUI", BaseFileChooserUI.class.getName(), - "MenuBarUI", BaseMenuBarUI.class.getName(), - "MenuUI", BaseMenuUI.class.getName(), - "PopupMenuUI", BasePopupMenuUI.class.getName(), - "MenuItemUI", BaseMenuItemUI.class.getName(), - "CheckBoxMenuItemUI", BaseCheckBoxMenuItemUI.class.getName(), - "RadioButtonMenuItemUI", BaseRadioButtonMenuItemUI.class.getName(), - "PopupMenuSeparatorUI", BaseSeparatorUI.class.getName(), - "DesktopPaneUI", BaseDesktopPaneUI.class.getName(), - - // AcrylLookAndFeel classes - "ButtonUI", AcrylButtonUI.class.getName(), - "ComboBoxUI", AcrylComboBoxUI.class.getName(), - "TabbedPaneUI", AcrylTabbedPaneUI.class.getName(), - "ToolBarUI", AcrylToolBarUI.class.getName(), - "InternalFrameUI", AcrylInternalFrameUI.class.getName(), - "RootPaneUI", AcrylRootPaneUI.class.getName(), - "ScrollBarUI", AcrylScrollBarUI.class.getName(), - }; - table.putDefaults(uiDefaults); - if (JTattooUtilities.getJavaVersion() >= 1.5) { - table.put("FormattedTextFieldUI", BaseFormattedTextFieldUI.class.getName()); - table.put("SpinnerUI", AcrylSpinnerUI.class.getName()); - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylRootPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylRootPaneUI.java deleted file mode 100644 index 8a6a26e38..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylRootPaneUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.BaseRootPaneUI; -import com.jtattoo.plaf.BaseTitlePane; -import javax.swing.JComponent; -import javax.swing.JRootPane; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AcrylRootPaneUI extends BaseRootPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new AcrylRootPaneUI(); - } - - public BaseTitlePane createTitlePane(JRootPane root) { - return new AcrylTitlePane(root, this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylScrollBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylScrollBarUI.java deleted file mode 100644 index c4b37a31a..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylScrollBarUI.java +++ /dev/null @@ -1,120 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * - * @author Michael Hagen - */ -public class AcrylScrollBarUI extends BaseScrollBarUI { - - public static ComponentUI createUI(JComponent c) { - return new AcrylScrollBarUI(); - } - - protected JButton createDecreaseButton(int orientation) { - return new BaseScrollButton(orientation, scrollBarWidth); - } - - protected JButton createIncreaseButton(int orientation) { - return new BaseScrollButton(orientation, scrollBarWidth); - } - - protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { - if (!c.isEnabled()) { - return; - } - - g.translate(thumbBounds.x, thumbBounds.y); - - Color colors[] = getThumbColors(); - Color frameColor = AbstractLookAndFeel.getFrameColor(); - if (!JTattooUtilities.isActive(scrollbar)) { - frameColor = ColorHelper.brighter(frameColor, 80); - } - if (isRollover || isDragging) { - frameColor = AbstractLookAndFeel.getTheme().getRolloverColorDark(); - } - - if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { - JTattooUtilities.fillVerGradient(g, colors, 1, 1, thumbBounds.width - 1, thumbBounds.height - 1); - - JTattooUtilities.draw3DBorder(g, frameColor, ColorHelper.darker(frameColor, 15), 0, 0, thumbBounds.width, thumbBounds.height); - - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - - int dx = 5; - int dy = thumbBounds.height / 2 - 3; - int dw = thumbBounds.width - 11; - - Color c1 = Color.white; - Color c2 = Color.darkGray; - - for (int i = 0; i < 4; i++) { - g.setColor(c1); - g.drawLine(dx, dy, dx + dw, dy); - dy++; - g.setColor(c2); - g.drawLine(dx, dy, dx + dw, dy); - dy++; - } - g2D.setComposite(composite); - } else { // HORIZONTAL - JTattooUtilities.fillHorGradient(g, colors, 1, 1, thumbBounds.width - 1, thumbBounds.height - 1); - JTattooUtilities.draw3DBorder(g, frameColor, ColorHelper.darker(frameColor, 10), 0, 0, thumbBounds.width, thumbBounds.height); - - int dx = thumbBounds.width / 2 - 3; - int dy = 5; - int dh = thumbBounds.height - 11; - - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - - Color c1 = Color.white; - Color c2 = Color.darkGray; - - for (int i = 0; i < 4; i++) { - g.setColor(c1); - g.drawLine(dx, dy, dx, dy + dh); - dx++; - g.setColor(c2); - g.drawLine(dx, dy, dx, dy + dh); - dx++; - } - g2D.setComposite(composite); - } - - g.translate(-thumbBounds.x, -thumbBounds.y); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylSpinnerUI.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylSpinnerUI.java deleted file mode 100644 index 31d02e3a3..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylSpinnerUI.java +++ /dev/null @@ -1,76 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Component; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -/** - * - * @author Michael Hagen - */ -public class AcrylSpinnerUI extends BaseSpinnerUI { - - /** - * Returns a new instance of AcrylSpinnerUI. SpinnerListUI - * delegates are allocated one per JSpinner. - * - * @param c the JSpinner (not used) - * @see ComponentUI#createUI - * @return a new BasicSpinnerUI object - */ - public static ComponentUI createUI(JComponent c) { - return new AcrylSpinnerUI(); - } - - protected Component createNextButton() { - JButton button = (JButton) super.createNextButton(); - Color frameColor = ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 50); - if (JTattooUtilities.isLeftToRight(spinner)) { - Border border = BorderFactory.createMatteBorder(0, 1, 1, 0, frameColor); - button.setBorder(border); - } else { - Border border = BorderFactory.createMatteBorder(0, 0, 1, 1, frameColor); - button.setBorder(border); - } - return button; - } - - protected Component createPreviousButton() { - JButton button = (JButton) super.createPreviousButton(); - Color frameColor = ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 50); - if (JTattooUtilities.isLeftToRight(spinner)) { - Border border = BorderFactory.createMatteBorder(0, 1, 0, 0, frameColor); - button.setBorder(border); - } else { - Border border = BorderFactory.createMatteBorder(0, 0, 0, 1, frameColor); - button.setBorder(border); - } - return button; - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylTabbedPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylTabbedPaneUI.java deleted file mode 100644 index 1a399ab61..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylTabbedPaneUI.java +++ /dev/null @@ -1,152 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.plaf.*; -import javax.swing.text.View; - -/** - * author Michael Hagen - */ -public class AcrylTabbedPaneUI extends BaseTabbedPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new AcrylTabbedPaneUI(); - } - - public void installDefaults() { - super.installDefaults(); - tabAreaInsets.bottom = 5; - } - - protected Color[] getTabColors(int tabIndex, boolean isSelected, boolean isRollover) { - if ((tabIndex >= 0) && (tabIndex < tabPane.getTabCount())) { - boolean isEnabled = tabPane.isEnabledAt(tabIndex); - Color backColor = tabPane.getBackgroundAt(tabIndex); - Color colorArr[]; - if ((backColor instanceof UIResource)) { - if (isSelected) { - colorArr = AbstractLookAndFeel.getTheme().getDefaultColors(); - } else if (isRollover && isEnabled) { - colorArr = AbstractLookAndFeel.getTheme().getRolloverColors(); - } else { - colorArr = AbstractLookAndFeel.getTheme().getTabColors(); - } - } else { - if (isSelected) { - colorArr = ColorHelper.createColorArr(ColorHelper.brighter(backColor, 60), backColor, 20); - } else if (isRollover && isEnabled) { - colorArr = ColorHelper.createColorArr(ColorHelper.brighter(backColor, 80), ColorHelper.brighter(backColor, 20), 20); - } else { - colorArr = ColorHelper.createColorArr(ColorHelper.brighter(backColor, 40), ColorHelper.darker(backColor, 10), 20); - } - } - return colorArr; - } - return AbstractLookAndFeel.getTheme().getTabColors(); - } - - protected Color[] getContentBorderColors(int tabPlacement) { - Color SEP_COLORS[] = { - ColorHelper.brighter(AbstractLookAndFeel.getControlColorLight(), 20), - AbstractLookAndFeel.getControlColorLight(), - ColorHelper.brighter(AbstractLookAndFeel.getControlColorDark(), 20), - AbstractLookAndFeel.getControlColorDark(), - ColorHelper.darker(AbstractLookAndFeel.getControlColorDark(), 20) - }; - return SEP_COLORS; - } - - protected Color getContentBorderColor() { - return ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFrameColor(), 50); - } - - protected Color getLoBorderColor(int tabIndex) { - if (tabIndex == tabPane.getSelectedIndex() && tabPane.getBackgroundAt(tabIndex) instanceof ColorUIResource) { - return ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 10); - } - return super.getLoBorderColor(tabIndex); - } - - protected Font getTabFont(boolean isSelected) { - if (isSelected) { - return super.getTabFont(isSelected).deriveFont(Font.BOLD); - } else { - return super.getTabFont(isSelected); - } - } - - protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected) { - Color backColor = tabPane.getBackgroundAt(tabIndex); - if (!(backColor instanceof UIResource)) { - super.paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected); - return; - } - g.setFont(font); - View v = getTextViewForTab(tabIndex); - if (v != null) { - // html - Graphics2D g2D = (Graphics2D) g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - v.paint(g, textRect); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } else { - // plain text - int mnemIndex = -1; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); - } - - if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) { - if (isSelected) { - Color shadowColor = ColorHelper.darker(AbstractLookAndFeel.getWindowTitleColorDark(), 30); - g.setColor(shadowColor); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x - 1, textRect.y - 1 + metrics.getAscent()); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x - 1, textRect.y + 1 + metrics.getAscent()); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x + 1, textRect.y - 1 + metrics.getAscent()); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x + 1, textRect.y + 1 + metrics.getAscent()); - g.setColor(AbstractLookAndFeel.getTheme().getTabSelectionForegroundColor()); - } else { - g.setColor(tabPane.getForegroundAt(tabIndex)); - } - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); - - } else { // tab disabled - g.setColor(tabPane.getBackgroundAt(tabIndex).brighter()); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); - g.setColor(tabPane.getBackgroundAt(tabIndex).darker()); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x - 1, textRect.y + metrics.getAscent() - 1); - } - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylTitlePane.java deleted file mode 100644 index 226ef2396..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylTitlePane.java +++ /dev/null @@ -1,215 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JRootPane; - -/** - * @author Michael Hagen - */ -public class AcrylTitlePane extends BaseTitlePane { - - public AcrylTitlePane(JRootPane root, BaseRootPaneUI ui) { - super(root, ui); - } - - public LayoutManager createLayout() { - return new TitlePaneLayout(); - } - - protected int getHorSpacing() { - return 1; - } - - protected int getVerSpacing() { - return 3; - } - - public void paintBorder(Graphics g) { - if (isActive()) { - g.setColor(AbstractLookAndFeel.getWindowBorderColor()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveBorderColor()); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } - - public void paintText(Graphics g, int x, int y, String title) { - x += paintIcon(g, x, y); - Color shadowColor = AbstractLookAndFeel.getWindowTitleColorDark(); - if (isActive()) { - shadowColor = ColorHelper.darker(shadowColor, 30); - } - g.setColor(shadowColor); - JTattooUtilities.drawString(rootPane, g, title, x - 1, y - 1); - JTattooUtilities.drawString(rootPane, g, title, x - 1, y + 1); - JTattooUtilities.drawString(rootPane, g, title, x + 1, y - 1); - JTattooUtilities.drawString(rootPane, g, title, x + 1, y + 1); - if (isActive()) { - g.setColor(AbstractLookAndFeel.getWindowTitleForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - } - JTattooUtilities.drawString(rootPane, g, title, x, y); - } -//----------------------------------------------------------------------------------------------- - protected class TitlePaneLayout implements LayoutManager { - - public void addLayoutComponent(String name, Component c) { - } - - public void removeLayoutComponent(Component c) { - } - - public Dimension preferredLayoutSize(Container c) { - int height = computeHeight(); - return new Dimension(height, height); - } - - public Dimension minimumLayoutSize(Container c) { - return preferredLayoutSize(c); - } - - protected int computeHeight() { - FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(getFont()); - return fm.getHeight() + 5; - } - - public void layoutContainer(Container c) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - layoutMacStyle(c); - } else { - layoutDefault(c); - } - } - - public void layoutDefault(Container c) { - boolean leftToRight = isLeftToRight(); - - int spacing = getHorSpacing(); - int w = getWidth(); - int h = getHeight(); - - // assumes all buttons have the same dimensions these dimensions include the borders - int btnHeight = h - getVerSpacing(); - int btnWidth = btnHeight + 10; - - if (menuBar != null) { - int mw = menuBar.getPreferredSize().width; - int mh = menuBar.getPreferredSize().height; - if (leftToRight) { - menuBar.setBounds(2, (h - mh) / 2, mw, mh); - } else { - menuBar.setBounds(getWidth() - mw, (h - mh) / 2, mw, mh); - } - } - - int x = leftToRight ? w - spacing : 0; - int y = Math.max(0, ((h - btnHeight) / 2) - 1); - - if (closeButton != null) { - x += leftToRight ? -btnWidth : spacing; - closeButton.setBounds(x, y, btnWidth, btnHeight); - if (!leftToRight) { - x += btnWidth; - } - } - - if ((maxButton != null) && (maxButton.getParent() != null)) { - if (DecorationHelper.isFrameStateSupported(Toolkit.getDefaultToolkit(), BaseRootPaneUI.MAXIMIZED_BOTH)) { - x += leftToRight ? -spacing - btnWidth : spacing; - maxButton.setBounds(x, y, btnWidth, btnHeight); - if (!leftToRight) { - x += btnWidth; - } - } - } - - if ((iconifyButton != null) && (iconifyButton.getParent() != null)) { - x += leftToRight ? -spacing - btnWidth : spacing; - iconifyButton.setBounds(x, y, btnWidth, btnHeight); - if (!leftToRight) { - x += btnWidth; - } - } - - buttonsWidth = leftToRight ? w - x : x; - - if (customTitlePanel != null) { - int maxWidth = w - buttonsWidth - spacing - 20; - if (menuBar != null) { - maxWidth -= menuBar.getPreferredSize().width; - maxWidth -= spacing; - } - int cpw = Math.min(maxWidth, customTitlePanel.getPreferredSize().width); - int cph = h; - int cpx = leftToRight ? w - buttonsWidth - cpw : buttonsWidth; - int cpy = 0; - customTitlePanel.setBounds(cpx, cpy, cpw, cph); - buttonsWidth += customTitlePanel.getPreferredSize().width; - } - } - - private void layoutMacStyle(Container c) { - int spacing = getHorSpacing(); - int h = getHeight(); - - // assumes all buttons have the same dimensions these dimensions include the borders - int btnHeight = h - getVerSpacing(); - int btnWidth = btnHeight; - - int x = 0; - int y = 0; - - if (closeButton != null) { - closeButton.setBounds(x, y, btnWidth, btnHeight); - x += btnWidth + spacing; - } - if ((iconifyButton != null) && (iconifyButton.getParent() != null)) { - iconifyButton.setBounds(x, y, btnWidth, btnHeight); - x += btnWidth + spacing; - } - if ((maxButton != null) && (maxButton.getParent() != null)) { - if (DecorationHelper.isFrameStateSupported(Toolkit.getDefaultToolkit(), BaseRootPaneUI.MAXIMIZED_BOTH)) { - maxButton.setBounds(x, y, btnWidth, btnHeight); - x += btnWidth + spacing; - } - } - - buttonsWidth = x; - - if (customTitlePanel != null) { - int cpx = buttonsWidth + 5; - int cpy = 0; - int cpw = customTitlePanel.getPreferredSize().width; - int cph = h; - customTitlePanel.setBounds(cpx, cpy, cpw, cph); - buttonsWidth += cpw + 5; - } - } - - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylToolBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylToolBarUI.java deleted file mode 100644 index 05c2a7b1e..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/acryl/AcrylToolBarUI.java +++ /dev/null @@ -1,65 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.acryl; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.JToolBar; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -public class AcrylToolBarUI extends AbstractToolBarUI { - - public static ComponentUI createUI(JComponent c) { - return new AcrylToolBarUI(); - } - - public Border getRolloverBorder() { - return AcrylBorders.getRolloverToolButtonBorder(); - } - - public Border getNonRolloverBorder() { - return AcrylBorders.getToolButtonBorder(); - } - - public boolean isButtonOpaque() { - return false; - } - - public void paint(Graphics g, JComponent c) { - int w = c.getWidth(); - int h = c.getHeight(); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getToolBarColors(), 0, 0, w, h - 2); - if ((toolBar.getOrientation() == JToolBar.HORIZONTAL) && isToolbarDecorated() && isToolBarUnderMenubar()) { - g.setColor(Color.white); - g.drawLine(0, 0, w, 0); - g.drawLine(0, h - 2, w, h - 2); - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getToolbarColorDark(), 10)); - g.drawLine(0, 1, w, 1); - g.drawLine(0, h - 1, w, h - 1); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/CheckPressedSymbol.gif b/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/CheckPressedSymbol.gif deleted file mode 100644 index 63eb455cd..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/CheckPressedSymbol.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/CheckSymbol.gif b/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/CheckSymbol.gif deleted file mode 100644 index f1de6084b..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/CheckSymbol.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/RadioSymbol.gif b/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/RadioSymbol.gif deleted file mode 100644 index 273e414a9..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/RadioSymbol.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/TreeClosedButton.gif b/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/TreeClosedButton.gif deleted file mode 100644 index 050a7e99d..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/TreeClosedButton.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/TreeOpenButton.gif b/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/TreeOpenButton.gif deleted file mode 100644 index 3e72830b5..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/TreeOpenButton.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/thumb_hor.gif b/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/thumb_hor.gif deleted file mode 100644 index d509ff9e9..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/thumb_hor.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/thumb_hor_rollover.gif b/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/thumb_hor_rollover.gif deleted file mode 100644 index 2c5c90d8c..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/thumb_hor_rollover.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/thumb_ver.gif b/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/thumb_ver.gif deleted file mode 100644 index cd4a1b9e8..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/thumb_ver.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/thumb_ver_rollover.gif b/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/thumb_ver_rollover.gif deleted file mode 100644 index f6c6a6312..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/acryl/icons/thumb_ver_rollover.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroBorderFactory.java b/src/jtattoo/src/com/jtattoo/plaf/aero/AeroBorderFactory.java deleted file mode 100644 index f2a8b8d6a..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroBorderFactory.java +++ /dev/null @@ -1,120 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aero; - -import com.jtattoo.plaf.AbstractBorderFactory; -import javax.swing.border.Border; - -/** - * @author Michael Hagen - */ -public class AeroBorderFactory implements AbstractBorderFactory { - private static AeroBorderFactory instance = null; - - private AeroBorderFactory() { - } - - public static synchronized AeroBorderFactory getInstance() { - if (instance == null) - instance = new AeroBorderFactory(); - return instance; - } - - public Border getFocusFrameBorder() { - return AeroBorders.getFocusFrameBorder(); - } - - public Border getButtonBorder() { - return AeroBorders.getButtonBorder(); - } - - public Border getToggleButtonBorder() { - return AeroBorders.getToggleButtonBorder(); - } - - public Border getTextBorder() { - return AeroBorders.getTextBorder(); - } - - public Border getSpinnerBorder() { - return AeroBorders.getSpinnerBorder(); - } - - public Border getTextFieldBorder() { - return AeroBorders.getTextFieldBorder(); - } - - public Border getComboBoxBorder() { - return AeroBorders.getComboBoxBorder(); - } - - public Border getTableHeaderBorder() { - return AeroBorders.getTableHeaderBorder(); - } - - public Border getTableScrollPaneBorder() { - return AeroBorders.getTableScrollPaneBorder(); - } - - public Border getScrollPaneBorder() { - return AeroBorders.getScrollPaneBorder(); - } - - public Border getTabbedPaneBorder() { - return AeroBorders.getTabbedPaneBorder(); - } - - public Border getMenuBarBorder() { - return AeroBorders.getMenuBarBorder(); - } - - public Border getMenuItemBorder() { - return AeroBorders.getMenuItemBorder(); - } - - public Border getPopupMenuBorder() { - return AeroBorders.getPopupMenuBorder(); - } - - public Border getInternalFrameBorder() { - return AeroBorders.getInternalFrameBorder(); - } - - public Border getPaletteBorder() { - return AeroBorders.getPaletteBorder(); - } - - public Border getToolBarBorder() { - return AeroBorders.getToolBarBorder(); - } - - public Border getProgressBarBorder() { - return AeroBorders.getProgressBarBorder(); - } - - public Border getDesktopIconBorder() { - return AeroBorders.getDesktopIconBorder(); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroBorders.java b/src/jtattoo/src/com/jtattoo/plaf/aero/AeroBorders.java deleted file mode 100644 index 79ef031cb..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroBorders.java +++ /dev/null @@ -1,310 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aero; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.AbstractButton; -import javax.swing.ButtonModel; -import javax.swing.border.Border; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class AeroBorders extends BaseBorders { - - //------------------------------------------------------------------------------------ - // Lazy access methods - //------------------------------------------------------------------------------------ - public static Border getButtonBorder() { - if (buttonBorder == null) { - buttonBorder = new ButtonBorder(); - } - return buttonBorder; - } - - public static Border getToggleButtonBorder() { - return getButtonBorder(); - } - - public static Border getRolloverToolButtonBorder() { - if (rolloverToolButtonBorder == null) { - rolloverToolButtonBorder = new RolloverToolButtonBorder(); - } - return rolloverToolButtonBorder; - } - - public static Border getInternalFrameBorder() { - if (internalFrameBorder == null) { - internalFrameBorder = new InternalFrameBorder(); - } - return internalFrameBorder; - } - - //------------------------------------------------------------------------------------ - // Implementation of border classes - //------------------------------------------------------------------------------------ - public static class ButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(4, 8, 4, 8); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Graphics2D g2D = (Graphics2D) g; - AbstractButton button = (AbstractButton)c; - ButtonModel model = button.getModel(); - if (model.isEnabled()) { - g.setColor(AbstractLookAndFeel.getFrameColor()); - } else { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 30)); - } - g.drawRect(x, y, w - 2, h - 2); - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); - g2D.setComposite(alpha); - g.setColor(Color.white); - g.drawLine(x + w - 1, y + 1, x + w - 1, y + h); - g.drawLine(x + 1, y + h - 1, x + w, y + h - 1); - g2D.setComposite(composite); - } - - public Insets getBorderInsets(Component c) { - return insets; - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - - } // class ButtonBorder - - public static class RolloverToolButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton)c; - ButtonModel model = button.getModel(); - Color loColor = AbstractLookAndFeel.getFrameColor(); - if (model.isEnabled()) { - if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - Graphics2D g2D = (Graphics2D)g; - Composite composite = g2D.getComposite(); - g.setColor(loColor); - g.drawRect(x, y, w - 1, h - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.15f); - g2D.setComposite(alpha); - g.setColor(Color.black); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(composite); - } - else if (model.isRollover()) { - Graphics2D g2D = (Graphics2D)g; - Composite composite = g2D.getComposite(); - g.setColor(loColor); - g.drawRect(x, y, w - 1, h - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - g.setColor(Color.white); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(composite); - } - } - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - - } // class RolloverToolButtonBorder - - public static class InternalFrameBorder extends BaseInternalFrameBorder { - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Color borderColor = AbstractLookAndFeel.getWindowInactiveBorderColor(); - if (isActive(c)) { - borderColor = AbstractLookAndFeel.getWindowBorderColor(); - } - if (!isResizable(c)) { - Color cHi = ColorHelper.brighter(borderColor, 40); - Color cLo = ColorHelper.darker(borderColor, 40); - JTattooUtilities.draw3DBorder(g, cHi, cLo, x, y, w, h); - cHi = ColorHelper.darker(cHi, 20); - cLo = ColorHelper.brighter(cLo, 20); - JTattooUtilities.draw3DBorder(g, cHi, cLo, x + 1, y + 1, w - 2, h - 2); - g.setColor(borderColor); - for (int i = 2; i < dw; i++) { - g.drawRect(i, i, w - (2 * i) - 1, h - (2 * i) - 1); - } - return; - } - int dt = w / 3; - int db = w * 2 / 3; - h--; - w--; - - Color cl = ColorHelper.brighter(borderColor, 10); - Color cr = AbstractLookAndFeel.getWindowInactiveBorderColor(); - g.setColor(cl); - g.drawLine(x, y, x, y + h); - g.setColor(ColorHelper.brighter(cl, 60)); - g.drawLine(x + 1, y + 1, x + 1, y + h - 1); - g.setColor(ColorHelper.brighter(cl, 40)); - g.drawLine(x + 2, y + 2, x + 2, y + h - 2); - g.setColor(ColorHelper.brighter(cl, 20)); - g.drawLine(x + 3, y + 3, x + 3, y + h - 3); - g.setColor(cl); - g.drawLine(x + 4, y + 4, x + 4, y + h - 4); - - // rechts - g.setColor(cr); - g.drawLine(x + w, y, x + w, y + h); - g.setColor(ColorHelper.brighter(cr, 30)); - g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); - g.setColor(ColorHelper.brighter(cr, 60)); - g.drawLine(x + w - 2, y + 2, x + w - 2, y + h - 2); - g.setColor(ColorHelper.brighter(cr, 90)); - g.drawLine(x + w - 3, y + 3, x + w - 3, y + h - 3); - g.setColor(cr); - g.drawLine(x + w - 4, y + 4, x + w - 4, y + h - 4); - - g.setColor(cl); - g.drawLine(x + w, y, x + w, y + trackWidth); - g.setColor(ColorHelper.brighter(cl, 20)); - g.drawLine(x + w - 1, y + 1, x + w - 1, y + trackWidth); - g.setColor(ColorHelper.brighter(cl, 40)); - g.drawLine(x + w - 2, y + 2, x + w - 2, y + trackWidth); - g.setColor(ColorHelper.brighter(cl, 60)); - g.drawLine(x + w - 3, y + 3, x + w - 3, y + trackWidth); - g.setColor(cl); - g.drawLine(x + w - 4, y + 4, x + w - 4, y + trackWidth); - - g.setColor(cl); - g.drawLine(x + w, y + h - trackWidth, x + w, y + h); - g.setColor(ColorHelper.brighter(cl, 20)); - g.drawLine(x + w - 1, y + h - trackWidth, x + w - 1, y + h - 1); - g.setColor(ColorHelper.brighter(cl, 40)); - g.drawLine(x + w - 2, y + h - trackWidth, x + w - 2, y + h - 2); - g.setColor(ColorHelper.brighter(cl, 60)); - g.drawLine(x + w - 3, y + h - trackWidth, x + w - 3, y + h - 3); - g.setColor(cl); - g.drawLine(x + w - 4, y + h - trackWidth, x + w - 4, y + h - 4); - - // oben - g.setColor(cl); - g.drawLine(x, y, x + dt, y); - g.setColor(ColorHelper.brighter(cl, 60)); - g.drawLine(x + 1, y + 1, x + dt, y + 1); - g.setColor(ColorHelper.brighter(cl, 40)); - g.drawLine(x + 2, y + 2, x + dt, y + 2); - g.setColor(ColorHelper.brighter(cl, 20)); - g.drawLine(x + 3, y + 3, x + dt, y + 3); - g.setColor(cl); - g.drawLine(x + 4, y + 4, x + dt, y + 4); - - g.setColor(cr); - g.drawLine(x + dt, y, x + w, y); - g.setColor(ColorHelper.brighter(cr, 90)); - g.drawLine(x + dt, y + 1, x + w - 1, y + 1); - g.setColor(ColorHelper.brighter(cr, 60)); - g.drawLine(x + dt, y + 2, x + w - 2, y + 2); - g.setColor(ColorHelper.brighter(cr, 30)); - g.drawLine(x + dt, y + 3, x + w - 3, y + 3); - if (isActive(c)) { - g.setColor(ColorHelper.darker(cr, 15)); - } else { - g.setColor(cr); - } - g.drawLine(x + dt, y + 4, x + w - 4, y + 4); - - g.setColor(cl); - g.drawLine(x + w - trackWidth, y, x + w, y); - g.setColor(ColorHelper.brighter(cl, 60)); - g.drawLine(x + w - trackWidth, y + 1, x + w - 1, y + 1); - g.setColor(ColorHelper.brighter(cl, 40)); - g.drawLine(x + w - trackWidth, y + 2, x + w - 2, y + 2); - g.setColor(ColorHelper.brighter(cl, 20)); - g.drawLine(x + w - trackWidth, y + 3, x + w - 3, y + 3); - g.setColor(cl); - g.drawLine(x + w - trackWidth, y + 4, x + w - 4, y + 4); - - // unten - g.setColor(cl); - g.drawLine(x, y + h, x + db, y + h); - g.setColor(ColorHelper.brighter(cl, 20)); - g.drawLine(x + 1, y + h - 1, x + db, y + h - 1); - g.setColor(ColorHelper.brighter(cl, 40)); - g.drawLine(x + 2, y + h - 2, x + db, y + h - 2); - g.setColor(ColorHelper.brighter(cl, 60)); - g.drawLine(x + 3, y + h - 3, x + db, y + h - 3); - g.setColor(cl); - g.drawLine(x + 4, y + h - 4, x + db, y + h - 4); - - g.setColor(cr); - g.drawLine(x + db, y + h, x + w, y + h); - g.setColor(ColorHelper.brighter(cr, 30)); - g.drawLine(x + db, y + h - 1, x + w - 1, y + h - 1); - g.setColor(ColorHelper.brighter(cr, 60)); - g.drawLine(x + db, y + h - 2, x + w - 2, y + h - 2); - g.setColor(ColorHelper.brighter(cr, 90)); - g.drawLine(x + db, y + h - 3, x + w - 3, y + h - 3); - g.setColor(cr); - g.drawLine(x + db, y + h - 4, x + w - 4, y + h - 4); - - g.setColor(cl); - g.drawLine(x + w - trackWidth, y + h, x + w, y + h); - g.setColor(ColorHelper.brighter(cl, 20)); - g.drawLine(x + w - trackWidth, y + h - 1, x + w - 1, y + h - 1); - g.setColor(ColorHelper.brighter(cl, 40)); - g.drawLine(x + w - trackWidth, y + h - 2, x + w - 2, y + h - 2); - g.setColor(ColorHelper.brighter(cl, 60)); - g.drawLine(x + w - trackWidth, y + h - 3, x + w - 3, y + h - 3); - g.setColor(cl); - g.drawLine(x + w - trackWidth, y + h - 4, x + w - 4, y + h - 4); - } //paintBorder - - } // class InternalFrameBorder - -} // class AeroBorders - diff --git a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroDefaultTheme.java b/src/jtattoo/src/com/jtattoo/plaf/aero/AeroDefaultTheme.java deleted file mode 100644 index e63c03798..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroDefaultTheme.java +++ /dev/null @@ -1,172 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aero; - -import com.jtattoo.plaf.AbstractTheme; -import com.jtattoo.plaf.ColorHelper; -import java.awt.Color; -import javax.swing.plaf.ColorUIResource; - -public class AeroDefaultTheme extends AbstractTheme { - - public AeroDefaultTheme() { - super(); - // Setup theme with defaults - setUpColor(); - // Overwrite defaults with user props - loadProperties(); - // Setup the color arrays - setUpColorArrs(); - } - - public String getPropertyFileName() { - return "AeroTheme.properties"; - } - - public void setUpColor() { - super.setUpColor(); - backgroundColor = new ColorUIResource(236, 236, 236); - backgroundColorLight = new ColorUIResource(255, 255, 255); - backgroundColorDark = new ColorUIResource(228, 228, 228); - alterBackgroundColor = new ColorUIResource(228, 228, 228); - frameColor = new ColorUIResource(160, 164, 168); - - selectionForegroundColor = black; - selectionBackgroundColor = new ColorUIResource(176, 196, 222); - rolloverColor = new ColorUIResource(192, 212, 230); - - buttonBackgroundColor = new ColorUIResource(220, 220, 220); - buttonColorLight = new ColorUIResource(240, 240, 240); - buttonColorDark = new ColorUIResource(120, 120, 120); - - controlBackgroundColor = backgroundColor; - controlColorLight = new ColorUIResource(150, 176, 211); - controlColorDark = new ColorUIResource(60, 95, 142); - controlHighlightColor = white; - controlShadowColor = new ColorUIResource(180, 186, 190); - controlDarkShadowColor = frameColor; - - windowTitleForegroundColor = white; - windowTitleBackgroundColor = new ColorUIResource(176, 196, 222); - windowTitleColorLight = new ColorUIResource(ColorHelper.brighter(controlColorLight, 20)); - windowTitleColorDark = new ColorUIResource(ColorHelper.brighter(controlColorDark, 20)); - windowBorderColor = controlColorDark; - - windowInactiveTitleBackgroundColor = new ColorUIResource(236, 236, 236); - windowInactiveTitleColorLight = new ColorUIResource(240, 240, 240); - windowInactiveTitleColorDark = new ColorUIResource(220, 220, 220); - windowInactiveBorderColor = new ColorUIResource(210, 210, 210); - - menuBackgroundColor = backgroundColor; - menuSelectionForegroundColor = selectionForegroundColor; - menuSelectionBackgroundColor = selectionBackgroundColor; - menuColorLight = controlColorLight; - menuColorDark = controlColorDark; - - toolbarBackgroundColor = backgroundColor; - toolbarColorLight = new ColorUIResource(240, 240, 240); - toolbarColorDark = new ColorUIResource(200, 200, 200); - - tabAreaBackgroundColor = backgroundColor; - tabSelectionForegroundColor = white; - - desktopColor = new ColorUIResource(240, 240, 240); - } - - public void setUpColorArrs() { - super.setUpColorArrs(); - Color color1[] = ColorHelper.createColorArr(controlColorLight, controlColorDark, 6); - Color color2[] = ColorHelper.createColorArr(ColorHelper.brighter(controlColorDark, 10), controlColorLight, 15); - for (int i = 0; i < 6; i++) { - DEFAULT_COLORS[i] = color1[i]; - } - for (int i = 5; i < 20; i++) { - DEFAULT_COLORS[i] = color2[i - 5]; - } - for (int i = 0; i < 20; i++) { - HIDEFAULT_COLORS[i] = ColorHelper.brighter(DEFAULT_COLORS[i], 60); - } - - ROLLOVER_COLORS = HIDEFAULT_COLORS; - ACTIVE_COLORS = DEFAULT_COLORS; - - PRESSED_COLORS = new Color[20]; - for (int i = 0; i < 20; i++) { - PRESSED_COLORS[i] = ColorHelper.brighter(DEFAULT_COLORS[i], 40); - } - - DISABLED_COLORS = ColorHelper.createColorArr(new Color(240,240,240), new Color(220, 220, 220), 20); - - color1 = ColorHelper.createColorArr(windowTitleColorLight, windowTitleColorDark, 6); - color2 = ColorHelper.createColorArr(ColorHelper.brighter(windowTitleColorDark, 10), windowTitleColorLight, 15); - for (int i = 0; i < 6; i++) { - WINDOW_TITLE_COLORS[i] = color1[i]; - } - for (int i = 5; i < 20; i++) { - WINDOW_TITLE_COLORS[i] = color2[i - 5]; - } - - MENUBAR_COLORS = ColorHelper.createColorArr(menuColorLight, menuColorDark, 20); - TOOLBAR_COLORS = ColorHelper.createColorArr(toolbarColorLight, toolbarColorDark, 20); - - BUTTON_COLORS = new Color[] { - new Color(247, 247, 247), - new Color(243, 243, 243), - new Color(240, 240, 240), - new Color(230, 230, 230), - new Color(220, 220, 220), - new Color(214, 214, 214), - new Color(218, 218, 218), - new Color(222, 222, 222), - new Color(226, 226, 226), - new Color(230, 230, 230), - new Color(234, 234, 234), - new Color(237, 237, 237), - new Color(240, 240, 240), - new Color(242, 242, 242), - new Color(244, 244, 244), - new Color(246, 246, 246), - new Color(248, 248, 248), - new Color(250, 250, 250), - new Color(252, 252, 252), - new Color(254, 254, 254), - new Color(255, 255, 255), - }; - CHECKBOX_COLORS = BUTTON_COLORS; - - SELECTED_COLORS = new Color[20]; - for (int i = 0; i < 20; i++) { - SELECTED_COLORS[i] = ColorHelper.brighter(DEFAULT_COLORS[i], 40); - } - TAB_COLORS = BUTTON_COLORS; - COL_HEADER_COLORS = BUTTON_COLORS; - THUMB_COLORS = SELECTED_COLORS; - SLIDER_COLORS = THUMB_COLORS; - PROGRESSBAR_COLORS = THUMB_COLORS; - INACTIVE_COLORS = BUTTON_COLORS; - - WINDOW_INACTIVE_TITLE_COLORS = INACTIVE_COLORS; - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroIconFactory.java b/src/jtattoo/src/com/jtattoo/plaf/aero/AeroIconFactory.java deleted file mode 100644 index 5c2d5646f..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroIconFactory.java +++ /dev/null @@ -1,213 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aero; - -import com.jtattoo.plaf.AbstractIconFactory; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class AeroIconFactory implements AbstractIconFactory { - - private static AeroIconFactory instance = null; - - private AeroIconFactory() { - } - - public static synchronized AeroIconFactory getInstance() { - if (instance == null) { - instance = new AeroIconFactory(); - } - return instance; - } - - public Icon getOptionPaneErrorIcon() { - return AeroIcons.getOptionPaneErrorIcon(); - } - - public Icon getOptionPaneWarningIcon() { - return AeroIcons.getOptionPaneWarningIcon(); - } - - public Icon getOptionPaneInformationIcon() { - return AeroIcons.getOptionPaneInformationIcon(); - } - - public Icon getOptionPaneQuestionIcon() { - return AeroIcons.getOptionPaneQuestionIcon(); - } - - public Icon getFileChooserDetailViewIcon() { - return AeroIcons.getFileChooserDetailViewIcon(); - } - - public Icon getFileChooserHomeFolderIcon() { - return AeroIcons.getFileChooserHomeFolderIcon(); - } - - public Icon getFileChooserListViewIcon() { - return AeroIcons.getFileChooserListViewIcon(); - } - - public Icon getFileChooserNewFolderIcon() { - return AeroIcons.getFileChooserNewFolderIcon(); - } - - public Icon getFileChooserUpFolderIcon() { - return AeroIcons.getFileChooserUpFolderIcon(); - } - - public Icon getMenuIcon() { - return AeroIcons.getMenuIcon(); - } - - public Icon getIconIcon() { - return AeroIcons.getIconIcon(); - } - - public Icon getMaxIcon() { - return AeroIcons.getMaxIcon(); - } - - public Icon getMinIcon() { - return AeroIcons.getMinIcon(); - } - - public Icon getCloseIcon() { - return AeroIcons.getCloseIcon(); - } - - public Icon getPaletteCloseIcon() { - return AeroIcons.getPaletteCloseIcon(); - } - - public Icon getRadioButtonIcon() { - return AeroIcons.getRadioButtonIcon(); - } - - public Icon getCheckBoxIcon() { - return AeroIcons.getCheckBoxIcon(); - } - - public Icon getComboBoxIcon() { - return AeroIcons.getComboBoxIcon(); - } - - public Icon getTreeComputerIcon() { - return AeroIcons.getTreeComputerIcon(); - } - - public Icon getTreeFloppyDriveIcon() { - return AeroIcons.getTreeFloppyDriveIcon(); - } - - public Icon getTreeHardDriveIcon() { - return AeroIcons.getTreeHardDriveIcon(); - } - - public Icon getTreeFolderIcon() { - return AeroIcons.getTreeFolderIcon(); - } - - public Icon getTreeLeafIcon() { - return AeroIcons.getTreeLeafIcon(); - } - - public Icon getTreeCollapsedIcon() { - return AeroIcons.getTreeControlIcon(true); - } - - public Icon getTreeExpandedIcon() { - return AeroIcons.getTreeControlIcon(false); - } - - public Icon getMenuArrowIcon() { - return AeroIcons.getMenuArrowIcon(); - } - - public Icon getMenuCheckBoxIcon() { - return AeroIcons.getMenuCheckBoxIcon(); - } - - public Icon getMenuRadioButtonIcon() { - return AeroIcons.getMenuRadioButtonIcon(); - } - - public Icon getUpArrowIcon() { - return AeroIcons.getUpArrowIcon(); - } - - public Icon getDownArrowIcon() { - return AeroIcons.getDownArrowIcon(); - } - - public Icon getLeftArrowIcon() { - return AeroIcons.getLeftArrowIcon(); - } - - public Icon getRightArrowIcon() { - return AeroIcons.getRightArrowIcon(); - } - - public Icon getSplitterDownArrowIcon() { - return AeroIcons.getSplitterDownArrowIcon(); - } - - public Icon getSplitterHorBumpIcon() { - return AeroIcons.getSplitterHorBumpIcon(); - } - - public Icon getSplitterLeftArrowIcon() { - return AeroIcons.getSplitterLeftArrowIcon(); - } - - public Icon getSplitterRightArrowIcon() { - return AeroIcons.getSplitterRightArrowIcon(); - } - - public Icon getSplitterUpArrowIcon() { - return AeroIcons.getSplitterUpArrowIcon(); - } - - public Icon getSplitterVerBumpIcon() { - return AeroIcons.getSplitterVerBumpIcon(); - } - - public Icon getThumbHorIcon() { - return AeroIcons.getThumbHorIcon(); - } - - public Icon getThumbVerIcon() { - return AeroIcons.getThumbVerIcon(); - } - - public Icon getThumbHorIconRollover() { - return AeroIcons.getThumbHorIconRollover(); - } - - public Icon getThumbVerIconRollover() { - return AeroIcons.getThumbVerIconRollover(); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroIcons.java b/src/jtattoo/src/com/jtattoo/plaf/aero/AeroIcons.java deleted file mode 100644 index fe81203ba..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroIcons.java +++ /dev/null @@ -1,81 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aero; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseIcons; -import java.awt.Color; -import java.awt.Insets; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class AeroIcons extends BaseIcons { - - public static Icon getIconIcon() { - if (iconIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - iconIcon = new MacIconIcon(); - } else { - iconIcon = new BaseIcons.IconSymbol(Color.black, Color.white, null, new Insets(2, 2, 2, 2)); - } - } - return iconIcon; - } - - public static Icon getMinIcon() { - if (minIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - minIcon = new MacMinIcon(); - } else { - minIcon = new BaseIcons.MinSymbol(Color.black, Color.white, null, new Insets(2, 2, 2, 2)); - } - } - return minIcon; - } - - public static Icon getMaxIcon() { - if (maxIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - maxIcon = new MacMaxIcon(); - } else { - maxIcon = new BaseIcons.MaxSymbol(Color.black, Color.white, null, new Insets(2, 2, 2, 2)); - } - } - return maxIcon; - } - - public static Icon getCloseIcon() { - if (closeIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - closeIcon = new MacCloseIcon(); - } else { - closeIcon = new BaseIcons.CloseSymbol(Color.black, Color.white, null, new Insets(2, 2, 2, 2)); - } - } - return closeIcon; - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroInternalFrameTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/aero/AeroInternalFrameTitlePane.java deleted file mode 100644 index 6a088d9bd..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroInternalFrameTitlePane.java +++ /dev/null @@ -1,119 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aero; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.*; - -/** - * @author Michael Hagen - */ -public class AeroInternalFrameTitlePane extends BaseInternalFrameTitlePane { - - public AeroInternalFrameTitlePane(JInternalFrame f) { - super(f); - } - - protected int getHorSpacing() { - return AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn() ? 1 : 0; - } - - protected int getVerSpacing() { - return AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn() ? 3 : 0; - } - - protected void createButtons() { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - super.createButtons(); - } else { - iconButton = new TitleButton(iconifyAction, ICONIFY, iconIcon); - maxButton = new TitleButton(maximizeAction, MAXIMIZE, maxIcon); - closeButton = new TitleButton(closeAction, CLOSE, closeIcon); - setButtonIcons(); - } - } - - public void paintBorder(Graphics g) { - if (isActive()) { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getWindowTitleColorDark(), 50)); - } else { - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getWindowInactiveTitleColorDark(), 10)); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } - - public void paintText(Graphics g, int x, int y, String title) { - if (isMacStyleWindowDecoration()) { - x += paintIcon(g, x, y) + 5; - } - if (isActive()) { - Color titleColor = AbstractLookAndFeel.getWindowTitleForegroundColor(); - if (ColorHelper.getGrayValue(titleColor) > 164) { - g.setColor(Color.black); - } else { - g.setColor(Color.white); - } - JTattooUtilities.drawString(frame, g, title, x + 1, y + 1); - g.setColor(AbstractLookAndFeel.getWindowTitleForegroundColor()); - JTattooUtilities.drawString(frame, g, title, x, y); - } - else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - JTattooUtilities.drawString(frame, g, title, x, y); - } - } - -//------------------------------------------------------------------------------ - private class TitleButton extends BaseTitleButton { - - public TitleButton(Action action, String accessibleName, Icon icon) { - super(action, accessibleName, icon, 1.0f); - } - - public void paint(Graphics g) { - boolean isPressed = getModel().isPressed(); - boolean isArmed = getModel().isArmed(); - boolean isRollover = getModel().isRollover(); - int width = getWidth(); - int height = getHeight(); - Color colors[] = AbstractLookAndFeel.getTheme().getButtonColors(); - if (isRollover) { - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - } - if (isPressed && isArmed) { - colors = AbstractLookAndFeel.getTheme().getPressedColors(); - } - JTattooUtilities.fillHorGradient(g, colors, 0, 0, width, height); - g.setColor(Color.lightGray); - g.drawLine(0, 0, 0, height); - g.drawLine(0, height - 1, width, height - 1); - g.setColor(Color.white); - g.drawLine(1, 0, 1, height - 2); - getIcon().paintIcon(this, g, 1, 0); - } - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroInternalFrameUI.java b/src/jtattoo/src/com/jtattoo/plaf/aero/AeroInternalFrameUI.java deleted file mode 100644 index 848a743c8..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroInternalFrameUI.java +++ /dev/null @@ -1,50 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aero; - -import com.jtattoo.plaf.BaseInternalFrameUI; -import javax.swing.JComponent; -import javax.swing.JInternalFrame; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AeroInternalFrameUI extends BaseInternalFrameUI { - - public AeroInternalFrameUI(JInternalFrame b) { - super(b); - } - - public static ComponentUI createUI(JComponent c) { - return new AeroInternalFrameUI((JInternalFrame)c); - } - - protected JComponent createNorthPane(JInternalFrame w) { - titlePane = new AeroInternalFrameTitlePane(w); - return titlePane; - } - -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroLookAndFeel.java b/src/jtattoo/src/com/jtattoo/plaf/aero/AeroLookAndFeel.java deleted file mode 100644 index be2938646..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroLookAndFeel.java +++ /dev/null @@ -1,293 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aero; - -import com.jtattoo.plaf.*; -import java.util.*; -import javax.swing.UIDefaults; - -/** - * @author Michael Hagen - */ -public class AeroLookAndFeel extends AbstractLookAndFeel { - - private static AeroDefaultTheme myTheme = null; - - private static final ArrayList themesList = new ArrayList(); - private static final HashMap themesMap = new HashMap(); - private static final Properties defaultProps = new Properties(); - private static final Properties smallFontProps = new Properties(); - private static final Properties largeFontProps = new Properties(); - private static final Properties giantFontProps = new Properties(); - private static final Properties goldProps = new Properties(); - private static final Properties goldSmallFontProps = new Properties(); - private static final Properties goldLargeFontProps = new Properties(); - private static final Properties goldGiantFontProps = new Properties(); - private static final Properties greenProps = new Properties(); - private static final Properties greenSmallFontProps = new Properties(); - private static final Properties greenLargeFontProps = new Properties(); - private static final Properties greenGiantFontProps = new Properties(); - - static { - smallFontProps.setProperty("controlTextFont", "Dialog 10"); - smallFontProps.setProperty("systemTextFont", "Dialog 10"); - smallFontProps.setProperty("userTextFont", "Dialog 10"); - smallFontProps.setProperty("menuTextFont", "Dialog 10"); - smallFontProps.setProperty("windowTitleFont", "Dialog bold 10"); - smallFontProps.setProperty("subTextFont", "Dialog 8"); - - largeFontProps.setProperty("controlTextFont", "Dialog 14"); - largeFontProps.setProperty("systemTextFont", "Dialog 14"); - largeFontProps.setProperty("userTextFont", "Dialog 14"); - largeFontProps.setProperty("menuTextFont", "Dialog 14"); - largeFontProps.setProperty("windowTitleFont", "Dialog bold 14"); - largeFontProps.setProperty("subTextFont", "Dialog 12"); - - giantFontProps.setProperty("controlTextFont", "Dialog 18"); - giantFontProps.setProperty("systemTextFont", "Dialog 18"); - giantFontProps.setProperty("userTextFont", "Dialog 18"); - giantFontProps.setProperty("menuTextFont", "Dialog 18"); - giantFontProps.setProperty("windowTitleFont", "Dialog 18"); - giantFontProps.setProperty("subTextFont", "Dialog 16"); - - goldProps.setProperty("focusCellColor", "160 160 120"); - goldProps.setProperty("selectionBackgroundColor", "232 232 180"); - goldProps.setProperty("rolloverColor", "225 225 159"); - goldProps.setProperty("controlColorLight", "248 248 180"); - goldProps.setProperty("controlColorDark", "200 200 120"); - goldProps.setProperty("windowTitleForegroundColor", "0 0 0"); - goldProps.setProperty("windowTitleBackgroundColor", "248 248 180"); - goldProps.setProperty("windowTitleColorLight", "249 249 195"); - goldProps.setProperty("windowTitleColorDark", "211 211 147"); - goldProps.setProperty("windowBorderColor", "200 200 120"); - goldProps.setProperty("menuSelectionForegroundColor", "0 0 0"); - goldProps.setProperty("menuSelectionBackgroundColor", "232 232 180"); - goldProps.setProperty("tabSelectionForegroundColor", "0 0 0"); - - greenProps.setProperty("focusCellColor", "40 100 60"); - greenProps.setProperty("selectionBackgroundColor", "150 211 176"); - greenProps.setProperty("rolloverColor", "190 228 206"); - greenProps.setProperty("controlColorLight", "150 211 176"); - greenProps.setProperty("controlColorDark", "60 142 95"); - greenProps.setProperty("windowTitleForegroundColor", "255 255 255"); - greenProps.setProperty("windowTitleBackgroundColor", "80 120 100"); - greenProps.setProperty("windowTitleColorLight", "171 219 191"); - greenProps.setProperty("windowTitleColorDark", "99 164 127"); - greenProps.setProperty("windowBorderColor", "60 142 95"); - greenProps.setProperty("menuSelectionForegroundColor", "0 0 0"); - greenProps.setProperty("menuSelectionBackgroundColor", "150 211 176"); - greenProps.setProperty("tabSelectionForegroundColor", "255 255 255"); - - String key; - String value; - Iterator iter = smallFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = smallFontProps.getProperty(key); - goldSmallFontProps.setProperty(key, value); - greenSmallFontProps.setProperty(key, value); - } - iter = largeFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = largeFontProps.getProperty(key); - goldLargeFontProps.setProperty(key, value); - greenLargeFontProps.setProperty(key, value); - } - iter = giantFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = giantFontProps.getProperty(key); - goldGiantFontProps.setProperty(key, value); - greenGiantFontProps.setProperty(key, value); - } - - iter = goldProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = goldProps.getProperty(key); - goldSmallFontProps.setProperty(key, value); - goldLargeFontProps.setProperty(key, value); - goldGiantFontProps.setProperty(key, value); - } - - iter = greenProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = greenProps.getProperty(key); - greenSmallFontProps.setProperty(key, value); - greenLargeFontProps.setProperty(key, value); - greenGiantFontProps.setProperty(key, value); - } - - themesList.add("Default"); - themesList.add("Small-Font"); - themesList.add("Large-Font"); - themesList.add("Giant-Font"); - - themesList.add("Gold"); - themesList.add("Gold-Small-Font"); - themesList.add("Gold-Large-Font"); - themesList.add("Gold-Giant-Font"); - - themesList.add("Green"); - themesList.add("Green-Small-Font"); - themesList.add("Green-Large-Font"); - themesList.add("Green-Giant-Font"); - - themesMap.put("Default", defaultProps); - themesMap.put("Small-Font", smallFontProps); - themesMap.put("Large-Font", largeFontProps); - themesMap.put("Giant-Font", giantFontProps); - - themesMap.put("Gold", goldProps); - themesMap.put("Gold-Small-Font", goldSmallFontProps); - themesMap.put("Gold-Large-Font", goldLargeFontProps); - themesMap.put("Gold-Giant-Font", goldGiantFontProps); - - themesMap.put("Green", greenProps); - themesMap.put("Green-Small-Font", greenSmallFontProps); - themesMap.put("Green-Large-Font", greenLargeFontProps); - themesMap.put("Green-Giant-Font", greenGiantFontProps); - } - - public static java.util.List getThemes() { - return themesList; - } - - public static Properties getThemeProperties(String name) { - return ((Properties)themesMap.get(name)); - } - - public static void setTheme(String name) { - setTheme((Properties) themesMap.get(name)); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - - public static void setTheme(String name, String licenseKey, String logoString) { - Properties props = (Properties) themesMap.get(name); - if (props != null) { - props.put("licenseKey", licenseKey); - props.put("logoString", logoString); - setTheme(props); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - } - - public static void setTheme(Properties themesProps) { - if (myTheme == null) { - myTheme = new AeroDefaultTheme(); - } - if ((myTheme != null) && (themesProps != null)) { - myTheme.setUpColor(); - myTheme.setProperties(themesProps); - myTheme.setUpColorArrs(); - AbstractLookAndFeel.setTheme(myTheme); - } - } - - public static void setCurrentTheme(Properties themesProps) { - setTheme(themesProps); - } - - public String getName() - { return "Aero"; } - - public String getID() - { return "Aero"; } - - public String getDescription() - { return "The Aero Look and Feel"; } - - public boolean isNativeLookAndFeel() - { return false; } - - public boolean isSupportedLookAndFeel() - { return true; } - - public AbstractBorderFactory getBorderFactory() - { return AeroBorderFactory.getInstance(); } - - public AbstractIconFactory getIconFactory() - { return AeroIconFactory.getInstance(); } - - protected void createDefaultTheme() { - if (myTheme == null) - myTheme = new AeroDefaultTheme(); - setTheme(myTheme); - } - - protected void initClassDefaults(UIDefaults table) { - super.initClassDefaults(table); - Object[] uiDefaults = { - // BaseLookAndFeel classes - "LabelUI", BaseLabelUI.class.getName(), - "ButtonUI", BaseButtonUI.class.getName(), - "RadioButtonUI", BaseRadioButtonUI.class.getName(), - "CheckBoxUI", BaseCheckBoxUI.class.getName(), - "ToggleButtonUI", BaseToggleButtonUI.class.getName(), - "SeparatorUI", BaseSeparatorUI.class.getName(), - "TextFieldUI", BaseTextFieldUI.class.getName(), - "TextAreaUI", BaseTextAreaUI.class.getName(), - "EditorPaneUI", BaseEditorPaneUI.class.getName(), - "PasswordFieldUI", BasePasswordFieldUI.class.getName(), - "ComboBoxUI", BaseComboBoxUI.class.getName(), - "ToolTipUI", BaseToolTipUI.class.getName(), - "TreeUI", BaseTreeUI.class.getName(), - "TableUI", BaseTableUI.class.getName(), - "TableHeaderUI", BaseTableHeaderUI.class.getName(), - "ScrollBarUI", BaseScrollBarUI.class.getName(), - "ScrollPaneUI", BaseScrollPaneUI.class.getName(), - "ProgressBarUI", BaseProgressBarUI.class.getName(), - "PanelUI", BasePanelUI.class.getName(), - "SplitPaneUI", BaseSplitPaneUI.class.getName(), - "SliderUI", BaseSliderUI.class.getName(), - "FileChooserUI", BaseFileChooserUI.class.getName(), - - "MenuUI", BaseMenuUI.class.getName(), - "PopupMenuUI", BasePopupMenuUI.class.getName(), - "MenuItemUI", BaseMenuItemUI.class.getName(), - "CheckBoxMenuItemUI", BaseCheckBoxMenuItemUI.class.getName(), - "RadioButtonMenuItemUI", BaseRadioButtonMenuItemUI.class.getName(), - "PopupMenuSeparatorUI", BaseSeparatorUI.class.getName(), - "DesktopPaneUI", BaseDesktopPaneUI.class.getName(), - - // AeroLookAndFeel classes - "TabbedPaneUI", AeroTabbedPaneUI.class.getName(), - "ToolBarUI", AeroToolBarUI.class.getName(), - "InternalFrameUI", AeroInternalFrameUI.class.getName(), - "RootPaneUI", AeroRootPaneUI.class.getName(), - }; - table.putDefaults(uiDefaults); - if (JTattooUtilities.getJavaVersion() >= 1.5) { - table.put("FormattedTextFieldUI", BaseFormattedTextFieldUI.class.getName()); - table.put("SpinnerUI", BaseSpinnerUI.class.getName()); - } - } - -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroRootPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/aero/AeroRootPaneUI.java deleted file mode 100644 index 066836d44..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroRootPaneUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aero; - -import com.jtattoo.plaf.BaseRootPaneUI; -import com.jtattoo.plaf.BaseTitlePane; -import javax.swing.JComponent; -import javax.swing.JRootPane; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AeroRootPaneUI extends BaseRootPaneUI -{ - public static ComponentUI createUI(JComponent c) { - return new AeroRootPaneUI(); - } - - public BaseTitlePane createTitlePane(JRootPane root) { - return new AeroTitlePane(root, this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroTabbedPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/aero/AeroTabbedPaneUI.java deleted file mode 100644 index a52ec9345..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroTabbedPaneUI.java +++ /dev/null @@ -1,119 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aero; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.text.View; - -/** - * @author Michael Hagen - */ -public class AeroTabbedPaneUI extends BaseTabbedPaneUI { - private Color sepColors[] = null; - - public static ComponentUI createUI(JComponent c) { - return new AeroTabbedPaneUI(); - } - - protected void installComponents() { - simpleButtonBorder = true; - super.installComponents(); - } - - protected Color[] getContentBorderColors(int tabPlacement) { - if (sepColors == null) { - sepColors = new Color[5]; - sepColors[0] = ColorHelper.brighter(AbstractLookAndFeel.getControlColorDark(), 40); - sepColors[1] = ColorHelper.brighter(AbstractLookAndFeel.getControlColorLight(), 40); - sepColors[2] = ColorHelper.brighter(AbstractLookAndFeel.getControlColorLight(), 60); - sepColors[3] = ColorHelper.brighter(AbstractLookAndFeel.getControlColorLight(), 20); - sepColors[4] = ColorHelper.brighter(AbstractLookAndFeel.getControlColorDark(), 30); - } - return sepColors; - } - - protected Font getTabFont(boolean isSelected) { - if (isSelected) { - return super.getTabFont(isSelected).deriveFont(Font.BOLD); - } else { - return super.getTabFont(isSelected); - } - } - - protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected) { - Color backColor = tabPane.getBackgroundAt(tabIndex); - if (!(backColor instanceof UIResource)) { - super.paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected); - return; - } - g.setFont(font); - View v = getTextViewForTab(tabIndex); - if (v != null) { - // html - Graphics2D g2D = (Graphics2D)g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - v.paint(g, textRect); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } else { - // plain text - int mnemIndex = -1; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); - } - - if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) { - if (isSelected ) { - Color titleColor = AbstractLookAndFeel.getTabSelectionForegroundColor(); - if (ColorHelper.getGrayValue(titleColor) > 164) { - g.setColor(Color.black); - } else { - g.setColor(Color.white); - } - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x + 1, textRect.y + 1 + metrics.getAscent()); - g.setColor(titleColor); - } else { - g.setColor(tabPane.getForegroundAt(tabIndex)); - } - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); - - } else { // tab disabled - g.setColor(tabPane.getBackgroundAt(tabIndex).brighter()); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); - g.setColor(tabPane.getBackgroundAt(tabIndex).darker()); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x - 1, textRect.y + metrics.getAscent() - 1); - } - } - } - -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/aero/AeroTitlePane.java deleted file mode 100644 index eb5f1185a..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroTitlePane.java +++ /dev/null @@ -1,116 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aero; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.*; - -/** - * @author Michael Hagen - */ -public class AeroTitlePane extends BaseTitlePane { - - public AeroTitlePane(JRootPane root, BaseRootPaneUI ui) { - super(root, ui); - } - - protected int getHorSpacing() { - return AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn() ? 1 : 0; - } - - protected int getVerSpacing() { - return AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn() ? 3 : 0; - } - - public void createButtons() { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - super.createButtons(); - } else { - iconifyButton = new TitleButton(iconifyAction, ICONIFY, iconifyIcon); - maxButton = new TitleButton(restoreAction, MAXIMIZE, maximizeIcon); - closeButton = new TitleButton(closeAction, CLOSE, closeIcon); - } - } - - public void paintBorder(Graphics g) { - if (isActive()) { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getWindowTitleColorDark(), 50)); - } - else { - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getWindowInactiveTitleColorDark(), 10)); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } - - public void paintText(Graphics g, int x, int y, String title) { - x += paintIcon(g, x, y); - if (isActive()) { - Color titleColor = AbstractLookAndFeel.getWindowTitleForegroundColor(); - if (ColorHelper.getGrayValue(titleColor) > 164) { - g.setColor(Color.black); - } else { - g.setColor(Color.white); - } - JTattooUtilities.drawString(rootPane, g, title, x + 1, y + 1); - g.setColor(titleColor); - JTattooUtilities.drawString(rootPane, g, title, x, y); - } - else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - JTattooUtilities.drawString(rootPane, g, title, x, y); - } - } - -//------------------------------------------------------------------------------ - private class TitleButton extends BaseTitleButton { - - public TitleButton(Action action, String accessibleName, Icon icon) { - super(action, accessibleName, icon, 1.0f); - } - - public void paint(Graphics g) { - boolean isPressed = getModel().isPressed(); - boolean isArmed = getModel().isArmed(); - boolean isRollover = getModel().isRollover(); - int width = getWidth(); - int height = getHeight(); - Color colors[] = AbstractLookAndFeel.getTheme().getButtonColors(); - if (isRollover) { - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - } - if (isPressed && isArmed) { - colors = AbstractLookAndFeel.getTheme().getPressedColors(); - } - JTattooUtilities.fillHorGradient(g, colors, 0, 0, width, height); - g.setColor(Color.lightGray); - g.drawLine(0, 0, 0, height); - g.drawLine(0, height - 1, width, height - 1); - g.setColor(Color.white); - g.drawLine(1, 0, 1, height - 2); - getIcon().paintIcon(this, g, 1, 0); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroToolBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/aero/AeroToolBarUI.java deleted file mode 100644 index f57e5c34d..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aero/AeroToolBarUI.java +++ /dev/null @@ -1,51 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aero; - -import com.jtattoo.plaf.AbstractToolBarUI; -import javax.swing.JComponent; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AeroToolBarUI extends AbstractToolBarUI { - - public static ComponentUI createUI(JComponent c) { - return new AeroToolBarUI(); - } - - public Border getRolloverBorder() { - return AeroBorders.getRolloverToolButtonBorder(); - } - - public Border getNonRolloverBorder() { - return AeroBorders.getToolButtonBorder(); - } - - public boolean isButtonOpaque() { - return false; - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumBorderFactory.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumBorderFactory.java deleted file mode 100644 index 98aa26a2c..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumBorderFactory.java +++ /dev/null @@ -1,122 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.AbstractBorderFactory; -import javax.swing.border.Border; - -/** - * @author Michael Hagen - */ -public class AluminiumBorderFactory implements AbstractBorderFactory { - - private static AluminiumBorderFactory instance = null; - - private AluminiumBorderFactory() { - } - - public static synchronized AluminiumBorderFactory getInstance() { - if (instance == null) { - instance = new AluminiumBorderFactory(); - } - return instance; - } - - public Border getFocusFrameBorder() { - return AluminiumBorders.getFocusFrameBorder(); - } - - public Border getButtonBorder() { - return AluminiumBorders.getButtonBorder(); - } - - public Border getToggleButtonBorder() { - return AluminiumBorders.getToggleButtonBorder(); - } - - public Border getTextBorder() { - return AluminiumBorders.getTextBorder(); - } - - public Border getSpinnerBorder() { - return AluminiumBorders.getSpinnerBorder(); - } - - public Border getTextFieldBorder() { - return AluminiumBorders.getTextFieldBorder(); - } - - public Border getComboBoxBorder() { - return AluminiumBorders.getComboBoxBorder(); - } - - public Border getTableHeaderBorder() { - return AluminiumBorders.getTableHeaderBorder(); - } - - public Border getTableScrollPaneBorder() { - return AluminiumBorders.getTableScrollPaneBorder(); - } - - public Border getScrollPaneBorder() { - return AluminiumBorders.getScrollPaneBorder(); - } - - public Border getTabbedPaneBorder() { - return AluminiumBorders.getTabbedPaneBorder(); - } - - public Border getMenuBarBorder() { - return AluminiumBorders.getMenuBarBorder(); - } - - public Border getMenuItemBorder() { - return AluminiumBorders.getMenuItemBorder(); - } - - public Border getPopupMenuBorder() { - return AluminiumBorders.getPopupMenuBorder(); - } - - public Border getInternalFrameBorder() { - return AluminiumBorders.getInternalFrameBorder(); - } - - public Border getPaletteBorder() { - return AluminiumBorders.getPaletteBorder(); - } - - public Border getToolBarBorder() { - return AluminiumBorders.getToolBarBorder(); - } - - public Border getProgressBarBorder() { - return AluminiumBorders.getProgressBarBorder(); - } - - public Border getDesktopIconBorder() { - return AluminiumBorders.getDesktopIconBorder(); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumBorders.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumBorders.java deleted file mode 100644 index 974797707..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumBorders.java +++ /dev/null @@ -1,198 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.AbstractButton; -import javax.swing.ButtonModel; -import javax.swing.border.Border; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class AluminiumBorders extends BaseBorders { - - //------------------------------------------------------------------------------------ - // Lazy access methods - //------------------------------------------------------------------------------------ - public static Border getButtonBorder() { - if (buttonBorder == null) { - buttonBorder = new ButtonBorder(); - } - return buttonBorder; - } - - public static Border getToggleButtonBorder() { - return getButtonBorder(); - } - - public static Border getRolloverToolButtonBorder() { - if (rolloverToolButtonBorder == null) { - rolloverToolButtonBorder = new RolloverToolButtonBorder(); - } - return rolloverToolButtonBorder; - } - - public static Border getInternalFrameBorder() { - if (internalFrameBorder == null) { - internalFrameBorder = new InternalFrameBorder(); - } - return internalFrameBorder; - } - - //------------------------------------------------------------------------------------ - // Implementation of border classes - //------------------------------------------------------------------------------------ - public static class ButtonBorder implements Border, UIResource { - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - } - - public Insets getBorderInsets(Component c) { - if (AbstractLookAndFeel.getTheme().doDrawSquareButtons()) { - return new Insets(3, 4, 3, 4); - } else { - return new Insets(2, 12, 2, 12); - } - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - Insets insets = getBorderInsets(c); - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class ButtonBorder - - public static class RolloverToolButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - Color loColor = AbstractLookAndFeel.getFrameColor(); - if (model.isEnabled()) { - if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - g.setColor(loColor); - g.drawRect(x, y, w - 1, h - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.15f); - g2D.setComposite(alpha); - g.setColor(Color.black); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(composite); - } else if (model.isRollover()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - g.setColor(loColor); - g.drawRect(x, y, w - 1, h - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - g.setColor(AbstractLookAndFeel.getTheme().getSelectionBackgroundColor()); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(composite); - } - } - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class RolloverToolButtonBorder - - public static class InternalFrameBorder extends BaseInternalFrameBorder { - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Graphics2D g2D = (Graphics2D) g; - Color titleColor = AbstractLookAndFeel.getWindowInactiveTitleBackgroundColor(); - if (isActive(c)) { - titleColor = AbstractLookAndFeel.getWindowTitleBackgroundColor(); - } - int th = getTitleHeight(c); - - g.setColor(titleColor); - g.fillRect(1, 1, w, dw); - g.fillRect(1, h - dw, w, dw - 1); - - if (isActive(c)) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 1, dw, dw, th + 1); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), w - dw, dw, dw, th + 1); - Color c1 = AbstractLookAndFeel.getTheme().getWindowTitleColorDark(); - Color c2 = AbstractLookAndFeel.getTheme().getWindowTitleColorLight(); - g2D.setPaint(new GradientPaint(0, dw + th + 1, c1, 0, h - th - (2 * dw), c2)); - g.fillRect(1, dw + th + 1, dw - 1, h - th - (2 * dw)); - g.fillRect(w - dw, dw + th + 1, dw - 1, h - th - (2 * dw)); - g2D.setPaint(null); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 1, dw, dw, th + 1); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), w - dw, dw, dw, th + 1); - Color c1 = AbstractLookAndFeel.getTheme().getWindowInactiveTitleColorDark(); - Color c2 = AbstractLookAndFeel.getTheme().getWindowInactiveTitleColorLight(); - g2D.setPaint(new GradientPaint(0, dw + th + 1, c1, 0, h - th - (2 * dw), c2)); - g.fillRect(1, dw + th + 1, dw - 1, h - th - (2 * dw)); - g.fillRect(w - dw, dw + th + 1, dw - 1, h - th - (2 * dw)); - g2D.setPaint(null); - } - - - Color borderColor = AbstractLookAndFeel.getWindowInactiveBorderColor(); - if (isActive(c)) { - borderColor = AbstractLookAndFeel.getWindowBorderColor(); - } - g.setColor(borderColor); - g.drawRect(0, 0, w - 1, h - 1); - g.drawLine(x + dw - 1, y + insets.top + th, x + dw - 1, y + h - dw); - g.drawLine(x + w - dw, y + insets.top + th, x + w - dw, y + h - dw); - g.drawLine(x + dw - 1, y + h - dw, x + w - dw, y + h - dw); - - g.setColor(new Color(220, 220, 220)); - g.drawLine(1, 1, w - 3, 1); - g.drawLine(1, 1, 1, h - 2); - } - } // class InternalFrameBorder - -} // class AluminiumBorders - diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumButtonUI.java deleted file mode 100644 index e2103223c..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumButtonUI.java +++ /dev/null @@ -1,150 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.*; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.RoundRectangle2D; -import javax.swing.*; -import javax.swing.plaf.*; -import javax.swing.plaf.basic.BasicGraphicsUtils; - -/** - * @author Michael Hagen - */ -public class AluminiumButtonUI extends BaseButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new AluminiumButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - if (!b.isContentAreaFilled() || (b.getParent() instanceof JMenuBar)) { - return; - } - - if (!(b.isBorderPainted() && (b.getBorder() instanceof UIResource))) { - super.paintBackground(g, b); - return; - } - - int width = b.getWidth(); - int height = b.getHeight(); - ButtonModel model = b.getModel(); - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - Object savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - Color[] colors; - if (model.isEnabled()) { - Color background = b.getBackground(); - if (background instanceof ColorUIResource) { - if (model.isPressed() && model.isArmed()) { - colors = AbstractLookAndFeel.getTheme().getPressedColors(); - } else { - if (b.isRolloverEnabled() && model.isRollover()) { - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - } else if (b.getRootPane() != null && b.equals(b.getRootPane().getDefaultButton())) { - colors = AbstractLookAndFeel.getTheme().getSelectedColors(); - } else { - colors = AbstractLookAndFeel.getTheme().getButtonColors(); - } - } - } else { - if (model.isPressed() && model.isArmed()) { - colors = ColorHelper.createColorArr(ColorHelper.darker(background, 30), ColorHelper.darker(background, 10), 20); - } else { - if (b.isRolloverEnabled() && model.isRollover()) { - colors = ColorHelper.createColorArr(ColorHelper.brighter(background, 50), ColorHelper.brighter(background, 10), 20); - } else { - colors = ColorHelper.createColorArr(ColorHelper.brighter(background, 30), ColorHelper.darker(background, 10), 20); - } - } - } - } else { - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } - if (AbstractLookAndFeel.getTheme().doDrawSquareButtons() - || (((width < 64) || (height < 16)) && ((b.getText() == null) || b.getText().length() == 0))) { - JTattooUtilities.fillHorGradient(g, colors, 0, 0, width - 1, height - 1); - if (model.isEnabled()) { - g2D.setColor(AbstractLookAndFeel.getFrameColor()); - } else { - g2D.setColor(ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 20)); - } - g2D.drawRect(0, 0, width - 1, height - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - g2D.setColor(Color.white); - g2D.drawRect(1, 1, width - 3, height - 3); - } else { - int d = height - 2; - Shape savedClip = g.getClip(); - Area clipArea = new Area(new RoundRectangle2D.Double(0, 0, width - 1, height - 1, d, d)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - JTattooUtilities.fillHorGradient(g, colors, 0, 0, width - 1, height - 1); - g2D.setClip(savedClip); - - if (model.isEnabled()) { - g2D.setColor(AbstractLookAndFeel.getFrameColor()); - } else { - g2D.setColor(ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 20)); - } - g2D.drawRoundRect(0, 0, width - 1, height - 1, d, d); - - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - g2D.setColor(Color.white); - g2D.drawRoundRect(1, 1, width - 3, height - 3, d - 2, d - 2); - - } - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRenderingHint); - g2D.setComposite(composite); - } - - protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { - Graphics2D g2D = (Graphics2D) g; - int width = b.getWidth(); - int height = b.getHeight(); - if (AbstractLookAndFeel.getTheme().doDrawSquareButtons() - || !b.isContentAreaFilled() - || ((width < 64) || (height < 16)) && ((b.getText() == null) || b.getText().length() == 0)) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - BasicGraphicsUtils.drawDashedRect(g, 4, 3, width - 8, height - 6); - } else { - Object savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2D.setColor(AbstractLookAndFeel.getFocusColor()); - int d = b.getHeight() - 4; - g2D.drawRoundRect(2, 2, b.getWidth() - 5, b.getHeight() - 5, d, d); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRenderingHint); - } - } -} - - - diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumCheckBoxUI.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumCheckBoxUI.java deleted file mode 100644 index e9f02bdd0..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumCheckBoxUI.java +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AluminiumCheckBoxUI extends AluminiumRadioButtonUI { - - private static AluminiumCheckBoxUI checkBoxUI = null; - - public static ComponentUI createUI(JComponent b) { - if (checkBoxUI == null) { - checkBoxUI = new AluminiumCheckBoxUI(); - } - return checkBoxUI; - } - - public void installDefaults(AbstractButton b) { - super.installDefaults(b); - icon = UIManager.getIcon("CheckBox.icon"); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumDefaultTheme.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumDefaultTheme.java deleted file mode 100644 index 17d39f09b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumDefaultTheme.java +++ /dev/null @@ -1,159 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.AbstractTheme; -import com.jtattoo.plaf.ColorHelper; -import java.awt.Color; -import javax.swing.plaf.ColorUIResource; - -public class AluminiumDefaultTheme extends AbstractTheme { - - public AluminiumDefaultTheme() { - super(); - // Setup theme with defaults - setUpColor(); - // Overwrite defaults with user props - loadProperties(); - // Setup the color arrays - setUpColorArrs(); - } - - public String getPropertyFileName() { - return "AluminiumTheme.properties"; - } - - public void setUpColor() { - super.setUpColor(); - // Defaults for AluminiumLookAndFeel - backgroundColor = new ColorUIResource(200, 200, 200); - backgroundColorLight = new ColorUIResource(240, 240, 240); - backgroundColorDark = new ColorUIResource(200, 200, 200); - alterBackgroundColor = new ColorUIResource(220, 220, 220); - - frameColor = new ColorUIResource(140, 140, 140); - backgroundPattern = true; - selectionForegroundColor = black; - selectionBackgroundColor = new ColorUIResource(224, 227, 206); - - focusColor = new ColorUIResource(255, 128, 96); - focusCellColor = focusColor; - - rolloverColor = new ColorUIResource(196, 203, 163); - rolloverColorLight = new ColorUIResource(220, 224, 201); - rolloverColorDark = new ColorUIResource(196, 203, 163); - - buttonBackgroundColor = extraLightGray; - buttonColorLight = white; - buttonColorDark = new ColorUIResource(210, 212, 214); - - controlBackgroundColor = extraLightGray; - controlColorLight = new ColorUIResource(244, 244, 244); - controlColorDark = new ColorUIResource(224, 224, 224); - controlHighlightColor = new ColorUIResource(240, 240, 240); - controlShadowColor = new ColorUIResource(180, 180, 180); - - windowTitleForegroundColor = new ColorUIResource(32, 32, 32); - windowTitleBackgroundColor = new ColorUIResource(200, 200, 200); - windowTitleColorLight = new ColorUIResource(200, 200, 200); - windowTitleColorDark = new ColorUIResource(160, 160, 160); - windowBorderColor = new ColorUIResource(120, 120, 120); - windowIconColor = new ColorUIResource(32, 32, 32); - windowIconShadowColor = new ColorUIResource(208, 208, 208); - windowIconRolloverColor = new ColorUIResource(196, 0, 0); - - windowInactiveTitleForegroundColor = black; - windowInactiveTitleBackgroundColor = new ColorUIResource(220, 220, 220); - windowInactiveTitleColorLight = new ColorUIResource(220, 220, 220); - windowInactiveTitleColorDark = new ColorUIResource(200, 200, 200); - windowInactiveBorderColor = new ColorUIResource(140, 140, 140); - - menuBackgroundColor = extraLightGray; - menuSelectionForegroundColor = selectionForegroundColor; - menuSelectionBackgroundColor = new ColorUIResource(202, 208, 172); - - menuColorLight = new ColorUIResource(210, 210, 210);//controlColorLight; - menuColorDark = new ColorUIResource(200, 200, 200);//controlColorDark; - - toolbarBackgroundColor = backgroundColor; - toolbarColorLight = new ColorUIResource(240, 240, 240); - toolbarColorDark = new ColorUIResource(200, 200, 200); - - tabAreaBackgroundColor = backgroundColor; - desktopColor = backgroundColor; - - tooltipForegroundColor = black; - tooltipBackgroundColor = new ColorUIResource(ColorHelper.brighter(selectionBackgroundColor, 40)); - } - - public void setUpColorArrs() { - super.setUpColorArrs(); - DEFAULT_COLORS = ColorHelper.createColorArr(controlColorLight, controlColorDark, 20); - HIDEFAULT_COLORS = new Color[DEFAULT_COLORS.length]; - for (int i = 0; i < DEFAULT_COLORS.length; i++) { - HIDEFAULT_COLORS[i] = ColorHelper.brighter(DEFAULT_COLORS[i], 20); - } - - ACTIVE_COLORS = DEFAULT_COLORS; - INACTIVE_COLORS = ColorHelper.createColorArr(new Color(240, 240, 240), new Color(220, 220, 220), 20); - - PRESSED_COLORS = ColorHelper.createColorArr(ColorHelper.darker(selectionBackgroundColor, 5), ColorHelper.brighter(selectionBackgroundColor, 20), 20); - DISABLED_COLORS = ColorHelper.createColorArr(Color.white, Color.lightGray, 20); - BUTTON_COLORS = new Color[]{ - new Color(240, 240, 240), - new Color(235, 235, 235), - new Color(232, 232, 232), - new Color(230, 230, 230), - new Color(228, 228, 228), - new Color(225, 225, 225), - new Color(220, 220, 220), - new Color(215, 215, 215), - new Color(210, 210, 210), - new Color(205, 205, 205), - new Color(210, 210, 210), - new Color(215, 215, 215), - new Color(220, 220, 220), - new Color(225, 225, 225), - new Color(228, 228, 228), - new Color(230, 230, 230), - new Color(232, 232, 232), - new Color(235, 235, 235),}; - ROLLOVER_COLORS = ColorHelper.createColorArr(rolloverColorLight, rolloverColorDark, 20); - WINDOW_TITLE_COLORS = ColorHelper.createColorArr(windowTitleColorLight, windowTitleColorDark, 20); - WINDOW_INACTIVE_TITLE_COLORS = ColorHelper.createColorArr(windowInactiveTitleColorLight, windowInactiveTitleColorDark, 20); - MENUBAR_COLORS = ColorHelper.createColorArr(menuColorLight, menuColorDark, 20); - TOOLBAR_COLORS = ColorHelper.createColorArr(toolbarColorLight, toolbarColorDark, 20); - TAB_COLORS = DEFAULT_COLORS; - COL_HEADER_COLORS = BUTTON_COLORS; - - SELECTED_COLORS = ColorHelper.createColorArr(ColorHelper.brighter(selectionBackgroundColor, 40), selectionBackgroundColor, 20); - - TRACK_COLORS = ColorHelper.createColorArr(new Color(210, 210, 210), new Color(230, 230, 230), 20); - //THUMB_COLORS = ColorHelper.createColorArr(new Color(202, 208, 172), new Color(180, 188, 137), 20); - THUMB_COLORS = ColorHelper.createColorArr(new Color(200, 200, 200), new Color(170, 170, 170), 20); - //SLIDER_COLORS = DEFAULT_COLORS; - SLIDER_COLORS = ColorHelper.createColorArr(new Color(180, 180, 180), new Color(150, 150, 150), 10); - PROGRESSBAR_COLORS = SLIDER_COLORS; - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumDesktopPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumDesktopPaneUI.java deleted file mode 100644 index deca33a44..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumDesktopPaneUI.java +++ /dev/null @@ -1,52 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.BaseDesktopPaneUI; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AluminiumDesktopPaneUI extends BaseDesktopPaneUI { - - private static AluminiumDesktopPaneUI desktopPaneUI = null; - - public static ComponentUI createUI(JComponent c) { - if (desktopPaneUI == null) { - desktopPaneUI = new AluminiumDesktopPaneUI(); - } - return desktopPaneUI; - } - - public void update(Graphics g, JComponent c) { - if (c.getClientProperty("backgroundTexture") == null) { - AluminiumUtils.fillComponent(g, c); - } else { - super.update(g, c); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumIconFactory.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumIconFactory.java deleted file mode 100644 index f9538bad5..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumIconFactory.java +++ /dev/null @@ -1,213 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.AbstractIconFactory; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class AluminiumIconFactory implements AbstractIconFactory { - - private static AluminiumIconFactory instance = null; - - private AluminiumIconFactory() { - } - - public static synchronized AluminiumIconFactory getInstance() { - if (instance == null) { - instance = new AluminiumIconFactory(); - } - return instance; - } - - public Icon getOptionPaneErrorIcon() { - return AluminiumIcons.getOptionPaneErrorIcon(); - } - - public Icon getOptionPaneWarningIcon() { - return AluminiumIcons.getOptionPaneWarningIcon(); - } - - public Icon getOptionPaneInformationIcon() { - return AluminiumIcons.getOptionPaneInformationIcon(); - } - - public Icon getOptionPaneQuestionIcon() { - return AluminiumIcons.getOptionPaneQuestionIcon(); - } - - public Icon getFileChooserDetailViewIcon() { - return AluminiumIcons.getFileChooserDetailViewIcon(); - } - - public Icon getFileChooserHomeFolderIcon() { - return AluminiumIcons.getFileChooserHomeFolderIcon(); - } - - public Icon getFileChooserListViewIcon() { - return AluminiumIcons.getFileChooserListViewIcon(); - } - - public Icon getFileChooserNewFolderIcon() { - return AluminiumIcons.getFileChooserNewFolderIcon(); - } - - public Icon getFileChooserUpFolderIcon() { - return AluminiumIcons.getFileChooserUpFolderIcon(); - } - - public Icon getMenuIcon() { - return AluminiumIcons.getMenuIcon(); - } - - public Icon getIconIcon() { - return AluminiumIcons.getIconIcon(); - } - - public Icon getMaxIcon() { - return AluminiumIcons.getMaxIcon(); - } - - public Icon getMinIcon() { - return AluminiumIcons.getMinIcon(); - } - - public Icon getCloseIcon() { - return AluminiumIcons.getCloseIcon(); - } - - public Icon getPaletteCloseIcon() { - return AluminiumIcons.getPaletteCloseIcon(); - } - - public Icon getRadioButtonIcon() { - return AluminiumIcons.getRadioButtonIcon(); - } - - public Icon getCheckBoxIcon() { - return AluminiumIcons.getCheckBoxIcon(); - } - - public Icon getComboBoxIcon() { - return AluminiumIcons.getComboBoxIcon(); - } - - public Icon getTreeComputerIcon() { - return AluminiumIcons.getTreeComputerIcon(); - } - - public Icon getTreeFloppyDriveIcon() { - return AluminiumIcons.getTreeFloppyDriveIcon(); - } - - public Icon getTreeHardDriveIcon() { - return AluminiumIcons.getTreeHardDriveIcon(); - } - - public Icon getTreeFolderIcon() { - return AluminiumIcons.getTreeFolderIcon(); - } - - public Icon getTreeLeafIcon() { - return AluminiumIcons.getTreeLeafIcon(); - } - - public Icon getTreeCollapsedIcon() { - return AluminiumIcons.getTreeControlIcon(true); - } - - public Icon getTreeExpandedIcon() { - return AluminiumIcons.getTreeControlIcon(false); - } - - public Icon getMenuArrowIcon() { - return AluminiumIcons.getMenuArrowIcon(); - } - - public Icon getMenuCheckBoxIcon() { - return AluminiumIcons.getMenuCheckBoxIcon(); - } - - public Icon getMenuRadioButtonIcon() { - return AluminiumIcons.getMenuRadioButtonIcon(); - } - - public Icon getUpArrowIcon() { - return AluminiumIcons.getUpArrowIcon(); - } - - public Icon getDownArrowIcon() { - return AluminiumIcons.getDownArrowIcon(); - } - - public Icon getLeftArrowIcon() { - return AluminiumIcons.getLeftArrowIcon(); - } - - public Icon getRightArrowIcon() { - return AluminiumIcons.getRightArrowIcon(); - } - - public Icon getSplitterDownArrowIcon() { - return AluminiumIcons.getSplitterDownArrowIcon(); - } - - public Icon getSplitterHorBumpIcon() { - return AluminiumIcons.getSplitterHorBumpIcon(); - } - - public Icon getSplitterLeftArrowIcon() { - return AluminiumIcons.getSplitterLeftArrowIcon(); - } - - public Icon getSplitterRightArrowIcon() { - return AluminiumIcons.getSplitterRightArrowIcon(); - } - - public Icon getSplitterUpArrowIcon() { - return AluminiumIcons.getSplitterUpArrowIcon(); - } - - public Icon getSplitterVerBumpIcon() { - return AluminiumIcons.getSplitterVerBumpIcon(); - } - - public Icon getThumbHorIcon() { - return AluminiumIcons.getThumbHorIcon(); - } - - public Icon getThumbVerIcon() { - return AluminiumIcons.getThumbVerIcon(); - } - - public Icon getThumbHorIconRollover() { - return AluminiumIcons.getThumbHorIconRollover(); - } - - public Icon getThumbVerIconRollover() { - return AluminiumIcons.getThumbVerIconRollover(); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumIcons.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumIcons.java deleted file mode 100644 index 790a6cd9a..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumIcons.java +++ /dev/null @@ -1,148 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Insets; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class AluminiumIcons extends BaseIcons { - - public static Icon getIconIcon() { - if (iconIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - iconIcon = new MacIconIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - iconIcon = new BaseIcons.IconSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(0, 0, 1, 0)); - } - } - return iconIcon; - } - - public static Icon getMinIcon() { - if (minIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - minIcon = new MacMinIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - minIcon = new BaseIcons.MinSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(0, 0, 1, 0)); - } - } - return minIcon; - } - - public static Icon getMaxIcon() { - if (maxIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - maxIcon = new MacMaxIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - maxIcon = new BaseIcons.MaxSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(0, 0, 1, 0)); - } - } - return maxIcon; - } - - public static Icon getCloseIcon() { - if (closeIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - closeIcon = new MacCloseIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - closeIcon = new BaseIcons.CloseSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(0, 0, 1, 0)); - } - } - return closeIcon; - } - - public static Icon getThumbHorIcon() { - if (thumbHorIcon == null) { - thumbHorIcon = new LazyImageIcon("aluminium/icons/thumb_hor.gif"); - } - return thumbHorIcon; - } - - public static Icon getThumbHorIconRollover() { - if (thumbHorIconRollover == null) { - thumbHorIconRollover = new LazyImageIcon("aluminium/icons/thumb_hor_rollover.gif"); - } - return thumbHorIconRollover; - } - - public static Icon getThumbVerIcon() { - if (thumbVerIcon == null) { - thumbVerIcon = new LazyImageIcon("aluminium/icons/thumb_ver.gif"); - } - return thumbVerIcon; - } - - public static Icon getThumbVerIconRollover() { - if (thumbVerIconRollover == null) { - thumbVerIconRollover = new LazyImageIcon("aluminium/icons/thumb_ver_rollover.gif"); - } - return thumbVerIconRollover; - } - - public static Icon getSplitterUpArrowIcon() { - if (splitterUpArrowIcon == null) { - splitterUpArrowIcon = new LazyImageIcon("aluminium/icons/SplitterUpArrow.gif"); - } - return splitterUpArrowIcon; - } - - public static Icon getSplitterDownArrowIcon() { - if (splitterDownArrowIcon == null) { - splitterDownArrowIcon = new LazyImageIcon("aluminium/icons/SplitterDownArrow.gif"); - } - return splitterDownArrowIcon; - } - - public static Icon getSplitterLeftArrowIcon() { - if (splitterLeftArrowIcon == null) { - splitterLeftArrowIcon = new LazyImageIcon("aluminium/icons/SplitterLeftArrow.gif"); - } - return splitterLeftArrowIcon; - } - - public static Icon getSplitterRightArrowIcon() { - if (splitterRightArrowIcon == null) { - splitterRightArrowIcon = new LazyImageIcon("aluminium/icons/SplitterRightArrow.gif"); - } - return splitterRightArrowIcon; - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumInternalFrameTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumInternalFrameTitlePane.java deleted file mode 100644 index 32c847c3e..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumInternalFrameTitlePane.java +++ /dev/null @@ -1,68 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.*; -import java.awt.Graphics; -import javax.swing.JInternalFrame; - -/** - * @author Michael Hagen - */ -public class AluminiumInternalFrameTitlePane extends BaseInternalFrameTitlePane { - - public AluminiumInternalFrameTitlePane(JInternalFrame f) { - super(f); - } - - protected boolean centerButtons() { - return false; - } - - public void paintBorder(Graphics g) { - if (isActive()) { - g.setColor(AbstractLookAndFeel.getTheme().getWindowBorderColor()); - } else { - g.setColor(AbstractLookAndFeel.getTheme().getWindowInactiveBorderColor()); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } - - public void paintText(Graphics g, int x, int y, String title) { - if (isMacStyleWindowDecoration()) { - x += paintIcon(g, x, y) + 5; - } - if (isActive()) { - g.setColor(AbstractLookAndFeel.getWindowTitleBackgroundColor()); - JTattooUtilities.drawString(frame, g, title, x + 1, y - 1); - g.setColor(AbstractLookAndFeel.getWindowTitleForegroundColor()); - JTattooUtilities.drawString(frame, g, title, x, y - 2); - } else { - g.setColor(AbstractLookAndFeel.getWindowTitleBackgroundColor()); - JTattooUtilities.drawString(frame, g, title, x + 1, y - 1); - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - JTattooUtilities.drawString(frame, g, title, x, y - 2); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumInternalFrameUI.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumInternalFrameUI.java deleted file mode 100644 index 728ad6450..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumInternalFrameUI.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.BaseInternalFrameUI; -import javax.swing.JComponent; -import javax.swing.JInternalFrame; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AluminiumInternalFrameUI extends BaseInternalFrameUI { - - public AluminiumInternalFrameUI(JInternalFrame b) { - super(b); - } - - public static ComponentUI createUI(JComponent c) { - return new AluminiumInternalFrameUI((JInternalFrame) c); - } - - protected JComponent createNorthPane(JInternalFrame w) { - titlePane = new AluminiumInternalFrameTitlePane(w); - return titlePane; - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumLookAndFeel.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumLookAndFeel.java deleted file mode 100644 index f95ad63d9..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumLookAndFeel.java +++ /dev/null @@ -1,200 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.*; -import java.util.*; -import javax.swing.UIDefaults; - -/** - * @author Michael Hagen - */ -public class AluminiumLookAndFeel extends AbstractLookAndFeel { - - private static AluminiumDefaultTheme myTheme = null; - - private static final ArrayList themesList = new ArrayList(); - private static final HashMap themesMap = new HashMap(); - private static final Properties defaultProps = new Properties(); - private static final Properties smallFontProps = new Properties(); - private static final Properties largeFontProps = new Properties(); - private static final Properties giantFontProps = new Properties(); - - static { - smallFontProps.setProperty("controlTextFont", "Dialog 10"); - smallFontProps.setProperty("systemTextFont", "Dialog 10"); - smallFontProps.setProperty("userTextFont", "Dialog 10"); - smallFontProps.setProperty("menuTextFont", "Dialog 10"); - smallFontProps.setProperty("windowTitleFont", "Dialog bold 10"); - smallFontProps.setProperty("subTextFont", "Dialog 8"); - - largeFontProps.setProperty("controlTextFont", "Dialog 14"); - largeFontProps.setProperty("systemTextFont", "Dialog 14"); - largeFontProps.setProperty("userTextFont", "Dialog 14"); - largeFontProps.setProperty("menuTextFont", "Dialog 14"); - largeFontProps.setProperty("windowTitleFont", "Dialog bold 14"); - largeFontProps.setProperty("subTextFont", "Dialog 12"); - - giantFontProps.setProperty("controlTextFont", "Dialog 18"); - giantFontProps.setProperty("systemTextFont", "Dialog 18"); - giantFontProps.setProperty("userTextFont", "Dialog 18"); - giantFontProps.setProperty("menuTextFont", "Dialog 18"); - giantFontProps.setProperty("windowTitleFont", "Dialog 18"); - giantFontProps.setProperty("subTextFont", "Dialog 16"); - - themesList.add("Default"); - themesList.add("Small-Font"); - themesList.add("Large-Font"); - themesList.add("Giant-Font"); - - themesMap.put("Default", defaultProps); - themesMap.put("Small-Font", smallFontProps); - themesMap.put("Large-Font", largeFontProps); - themesMap.put("Giant-Font", giantFontProps); - } - - public static java.util.List getThemes() { - return themesList; - } - - public static Properties getThemeProperties(String name) { - return ((Properties) themesMap.get(name)); - } - - public static void setTheme(String name) { - setTheme((Properties) themesMap.get(name)); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - - public static void setTheme(String name, String licenseKey, String logoString) { - Properties props = (Properties) themesMap.get(name); - if (props != null) { - props.put("licenseKey", licenseKey); - props.put("logoString", logoString); - setTheme(props); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - } - - public static void setTheme(Properties themesProps) { - if (myTheme == null) { - myTheme = new AluminiumDefaultTheme(); - } - if ((myTheme != null) && (themesProps != null)) { - myTheme.setUpColor(); - myTheme.setProperties(themesProps); - myTheme.setUpColorArrs(); - AbstractLookAndFeel.setTheme(myTheme); - } - } - - public static void setCurrentTheme(Properties themesProps) { - setTheme(themesProps); - } - - public String getName() { - return "Aluminium"; - } - - public String getID() { - return "Aluminium"; - } - - public String getDescription() { - return "The Aluminium Look and Feel"; - } - - public boolean isNativeLookAndFeel() { - return false; - } - - public boolean isSupportedLookAndFeel() { - return true; - } - - public AbstractBorderFactory getBorderFactory() { - return AluminiumBorderFactory.getInstance(); - } - - public AbstractIconFactory getIconFactory() { - return AluminiumIconFactory.getInstance(); - } - - protected void createDefaultTheme() { - if (myTheme == null) { - myTheme = new AluminiumDefaultTheme(); - } - setTheme(myTheme); - } - - protected void initClassDefaults(UIDefaults table) { - super.initClassDefaults(table); - Object[] uiDefaults = { - // BaseLookAndFeel classes - "LabelUI", BaseLabelUI.class.getName(), - "SeparatorUI", BaseSeparatorUI.class.getName(), - "TextFieldUI", BaseTextFieldUI.class.getName(), - "TextAreaUI", BaseTextAreaUI.class.getName(), - "EditorPaneUI", BaseEditorPaneUI.class.getName(), - "PasswordFieldUI", BasePasswordFieldUI.class.getName(), - "ComboBoxUI", BaseComboBoxUI.class.getName(), - "ToolTipUI", BaseToolTipUI.class.getName(), - "TreeUI", BaseTreeUI.class.getName(), - "TableUI", BaseTableUI.class.getName(), - "TableHeaderUI", BaseTableHeaderUI.class.getName(), - "ProgressBarUI", BaseProgressBarUI.class.getName(), - "ScrollBarUI", BaseScrollBarUI.class.getName(), - "FileChooserUI", BaseFileChooserUI.class.getName(), - "MenuUI", BaseMenuUI.class.getName(), - "PopupMenuUI", BasePopupMenuUI.class.getName(), - "MenuItemUI", BaseMenuItemUI.class.getName(), - "CheckBoxMenuItemUI", BaseCheckBoxMenuItemUI.class.getName(), - "RadioButtonMenuItemUI", BaseRadioButtonMenuItemUI.class.getName(), - // AluminiumLookAndFeel classes - "CheckBoxUI", AluminiumCheckBoxUI.class.getName(), - "RadioButtonUI", AluminiumRadioButtonUI.class.getName(), - "ButtonUI", AluminiumButtonUI.class.getName(), - "ToggleButtonUI", AluminiumToggleButtonUI.class.getName(), - "SliderUI", AluminiumSliderUI.class.getName(), - "PanelUI", AluminiumPanelUI.class.getName(), - "ScrollPaneUI", AluminiumScrollPaneUI.class.getName(), - "TabbedPaneUI", AluminiumTabbedPaneUI.class.getName(), - "SplitPaneUI", AluminiumSplitPaneUI.class.getName(), - "ToolBarUI", AluminiumToolBarUI.class.getName(), - "MenuBarUI", AluminiumMenuBarUI.class.getName(), - "PopupMenuSeparatorUI", AluminiumPopupMenuSeparatorUI.class.getName(), - "InternalFrameUI", AluminiumInternalFrameUI.class.getName(), - "RootPaneUI", AluminiumRootPaneUI.class.getName(), - "DesktopPaneUI", AluminiumDesktopPaneUI.class.getName(),}; - table.putDefaults(uiDefaults); - if (JTattooUtilities.getJavaVersion() >= 1.5) { - table.put("FormattedTextFieldUI", BaseFormattedTextFieldUI.class.getName()); - table.put("SpinnerUI", BaseSpinnerUI.class.getName()); - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumMenuBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumMenuBarUI.java deleted file mode 100644 index e5b7ad5d6..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumMenuBarUI.java +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseMenuBarUI; -import com.jtattoo.plaf.JTattooUtilities; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.JMenuBar; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AluminiumMenuBarUI extends BaseMenuBarUI { - - public static ComponentUI createUI(JComponent c) { - return new AluminiumMenuBarUI(); - } - - public void installUI(JComponent c) { - super.installUI(c); - if ((c != null) && (c instanceof JMenuBar)) { - c.setBorder(AluminiumBorders.getMenuBarBorder()); - } - } - - public void paint(Graphics g, JComponent c) { - if (JTattooUtilities.isMac() || !AbstractLookAndFeel.getTheme().isBackgroundPatternOn()) { - super.paint(g, c); - } else { - AluminiumUtils.fillComponent(g, c); - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumPanelUI.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumPanelUI.java deleted file mode 100644 index 5a5b0b06f..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumPanelUI.java +++ /dev/null @@ -1,53 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.BasePanelUI; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AluminiumPanelUI extends BasePanelUI { - - private static AluminiumPanelUI panelUI = null; - - public static ComponentUI createUI(JComponent c) { - if (panelUI == null) { - panelUI = new AluminiumPanelUI(); - } - return panelUI; - } - - public void update(Graphics g, JComponent c) { - if (c.isOpaque() && c.getBackground() instanceof ColorUIResource && c.getClientProperty("backgroundTexture") == null) { - AluminiumUtils.fillComponent(g, c); - } else { - super.update(g, c); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumPopupMenuSeparatorUI.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumPopupMenuSeparatorUI.java deleted file mode 100644 index 15681cfac..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumPopupMenuSeparatorUI.java +++ /dev/null @@ -1,65 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.JSeparator; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSeparatorUI; - -/** - * @author Michael Hagen - */ -public class AluminiumPopupMenuSeparatorUI extends BasicSeparatorUI { - - private static final Dimension size = new Dimension(1, 1); - - public static ComponentUI createUI(JComponent c) { - return new AluminiumPopupMenuSeparatorUI(); - } - - public void paint(Graphics g, JComponent c) { - boolean horizontal = true; - if (c instanceof JSeparator) { - JSeparator sep = ((JSeparator) c); - horizontal = (sep.getOrientation() == JSeparator.HORIZONTAL); - } - if (horizontal) { - g.setColor(Color.lightGray); - g.drawLine(0, 0, c.getWidth(), 0); - } else { - g.setColor(Color.lightGray); - g.drawLine(0, 0, 0, c.getHeight()); - } - } - - public Dimension getPreferredSize(JComponent c) { - return size; - } -} - - - - diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumRadioButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumRadioButtonUI.java deleted file mode 100644 index ac9b5660b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumRadioButtonUI.java +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseRadioButtonUI; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AluminiumRadioButtonUI extends BaseRadioButtonUI { - - private static AluminiumRadioButtonUI radioButtonUI = null; - - public static ComponentUI createUI(JComponent c) { - if (radioButtonUI == null) { - radioButtonUI = new AluminiumRadioButtonUI(); - } - return radioButtonUI; - } - - public void paintBackground(Graphics g, JComponent c) { - if (c.isOpaque()) { - if ((c.getBackground().equals(AbstractLookAndFeel.getBackgroundColor())) && (c.getBackground() instanceof ColorUIResource)) { - AluminiumUtils.fillComponent(g, c); - } else { - g.setColor(c.getBackground()); - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumRootPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumRootPaneUI.java deleted file mode 100644 index 9d17e9980..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumRootPaneUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.BaseRootPaneUI; -import com.jtattoo.plaf.BaseTitlePane; -import javax.swing.JComponent; -import javax.swing.JRootPane; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AluminiumRootPaneUI extends BaseRootPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new AluminiumRootPaneUI(); - } - - public BaseTitlePane createTitlePane(JRootPane root) { - return new AluminiumTitlePane(root, this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumScrollPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumScrollPaneUI.java deleted file mode 100644 index 2287fb3e5..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumScrollPaneUI.java +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.BaseScrollPaneUI; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AluminiumScrollPaneUI extends BaseScrollPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new AluminiumScrollPaneUI(); - } - - public void installDefaults(JScrollPane p) { - super.installDefaults(p); - p.getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumSliderUI.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumSliderUI.java deleted file mode 100644 index a2803a999..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumSliderUI.java +++ /dev/null @@ -1,62 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.BaseSliderUI; -import java.awt.Component; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.JSlider; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AluminiumSliderUI extends BaseSliderUI { - - public AluminiumSliderUI(JSlider slider) { - super(slider); - } - - public static ComponentUI createUI(JComponent c) { - return new AluminiumSliderUI((JSlider) c); - } - - public void paintBackground(Graphics g, JComponent c) { - if (c.isOpaque()) { - Component parent = c.getParent(); - if ((parent != null) && (parent.getBackground() instanceof ColorUIResource)) { - AluminiumUtils.fillComponent(g, c); - } else { - if (parent != null) { - g.setColor(parent.getBackground()); - } else { - g.setColor(c.getBackground()); - } - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumSplitPaneDivider.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumSplitPaneDivider.java deleted file mode 100644 index 7c9138021..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumSplitPaneDivider.java +++ /dev/null @@ -1,53 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseSplitPaneDivider; -import com.jtattoo.plaf.JTattooUtilities; -import java.awt.*; - -/** - * @author Michael Hagen - */ -public class AluminiumSplitPaneDivider extends BaseSplitPaneDivider { - - public AluminiumSplitPaneDivider(AluminiumSplitPaneUI ui) { - super(ui); - } - - public void paint(Graphics g) { - if (JTattooUtilities.isMac() || !AbstractLookAndFeel.getTheme().isBackgroundPatternOn()) { - super.paint(g); - } else { - AluminiumUtils.fillComponent(g, this); - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f); - g2D.setComposite(alpha); - super.paint(g); - g2D.setComposite(composite); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumSplitPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumSplitPaneUI.java deleted file mode 100644 index 542f49118..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumSplitPaneUI.java +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.BaseSplitPaneUI; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSplitPaneDivider; - -/** - * @author Michael Hagen - */ -public class AluminiumSplitPaneUI extends BaseSplitPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new AluminiumSplitPaneUI(); - } - - public BasicSplitPaneDivider createDefaultDivider() { - return new AluminiumSplitPaneDivider(this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumTabbedPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumTabbedPaneUI.java deleted file mode 100644 index 510672d2d..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumTabbedPaneUI.java +++ /dev/null @@ -1,128 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class AluminiumTabbedPaneUI extends BaseTabbedPaneUI { - - private static Color TOP_SELECTED_TAB_COLORS[] = null; - private static Color BOTTOM_SELECTED_TAB_COLORS[] = null; - - public static ComponentUI createUI(JComponent c) { - return new AluminiumTabbedPaneUI(); - } - - public void installDefaults() { - super.installDefaults(); - tabAreaInsets = new Insets(2, 6, 2, 6); - contentBorderInsets = new Insets(0, 0, 0, 0); - Color c = AbstractLookAndFeel.getTheme().getBackgroundColor(); - Color cHi = ColorHelper.brighter(c, 20); - Color cLo = ColorHelper.darker(c, 10); - TOP_SELECTED_TAB_COLORS = ColorHelper.createColorArr(cHi, c, 20); - BOTTOM_SELECTED_TAB_COLORS = ColorHelper.createColorArr(c, cLo, 20); - } - - protected Font getTabFont(boolean isSelected) { - if (isSelected) { - return super.getTabFont(isSelected).deriveFont(Font.BOLD); - } else { - return super.getTabFont(isSelected); - } - } - - protected Color[] getTabColors(int tabIndex, boolean isSelected, boolean isRollover) { - Color backColor = tabPane.getBackgroundAt(tabIndex); - if ((backColor instanceof UIResource) && isSelected) { - if (tabPane.getTabPlacement() == BOTTOM) { - return BOTTOM_SELECTED_TAB_COLORS; - } else { - return TOP_SELECTED_TAB_COLORS; - } - } - return super.getTabColors(tabIndex, isSelected, isRollover); - } - - protected boolean hasInnerBorder() { - return true; - } - - protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) { - Color backColor = tabPane.getBackgroundAt(tabIndex); - if (!(backColor instanceof UIResource)) { - super.paintTabBackground(g, tabPlacement, tabIndex, x, y, w, h, isSelected); - return; - } - if (JTattooUtilities.isMac() || !AbstractLookAndFeel.getTheme().isBackgroundPatternOn()) { - if (isSelected) { - Color colorArr[] = getTabColors(tabIndex, isSelected, tabIndex == rolloverIndex); - switch (tabPlacement) { - case LEFT: - JTattooUtilities.fillHorGradient(g, colorArr, x + 1, y + 1, w + 1, h - 1); - break; - case RIGHT: - JTattooUtilities.fillHorGradient(g, colorArr, x - 1, y + 1, w + 1, h - 1); - break; - case BOTTOM: - JTattooUtilities.fillHorGradient(g, colorArr, x + 1, y - 1, w - 1, h); - break; - case TOP: - default: - JTattooUtilities.fillHorGradient(g, colorArr, x + 1, y + 1, w - 1, h + 1); - break; - } - } else { - super.paintTabBackground(g, tabPlacement, tabIndex, x, y, w, h, isSelected); - } - } else { - if (isSelected) { - if (tabPane.getBackgroundAt(tabIndex) instanceof UIResource) { - g.setColor(AbstractLookAndFeel.getBackgroundColor()); - if (tabPlacement == TOP) { - AluminiumUtils.fillComponent(g, tabPane, x + 1, y + 1, w - 1, h + 1); - } else if (tabPlacement == LEFT) { - AluminiumUtils.fillComponent(g, tabPane, x + 1, y + 1, w + 1, h - 1); - } else if (tabPlacement == BOTTOM) { - AluminiumUtils.fillComponent(g, tabPane, x + 1, y - 2, w - 1, h + 1); - } else { - AluminiumUtils.fillComponent(g, tabPane, x - 1, y + 1, w + 1, h - 1); - } - } else { - super.paintTabBackground(g, tabPlacement, tabIndex, x, y, w, h, isSelected); - } - } else { - super.paintTabBackground(g, tabPlacement, tabIndex, x, y, w, h, isSelected); - } - } - } - -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumTitlePane.java deleted file mode 100644 index 4b3392ef7..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumTitlePane.java +++ /dev/null @@ -1,66 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.*; -import java.awt.Graphics; -import javax.swing.JRootPane; - -/** - * @author Michael Hagen - */ -public class AluminiumTitlePane extends BaseTitlePane { - - public AluminiumTitlePane(JRootPane root, BaseRootPaneUI ui) { - super(root, ui); - } - - protected boolean centerButtons() { - return false; - } - - public void paintBorder(Graphics g) { - if (isActive()) { - g.setColor(AbstractLookAndFeel.getTheme().getWindowBorderColor()); - } else { - g.setColor(AbstractLookAndFeel.getTheme().getWindowInactiveBorderColor()); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } - - public void paintText(Graphics g, int x, int y, String title) { - x += paintIcon(g, x, y); - if (isActive()) { - g.setColor(AbstractLookAndFeel.getWindowTitleBackgroundColor()); - JTattooUtilities.drawString(rootPane, g, title, x + 1, y); - g.setColor(AbstractLookAndFeel.getWindowTitleForegroundColor()); - JTattooUtilities.drawString(rootPane, g, title, x, y - 1); - } else { - g.setColor(AbstractLookAndFeel.getWindowTitleBackgroundColor()); - JTattooUtilities.drawString(rootPane, g, title, x + 1, y); - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - JTattooUtilities.drawString(rootPane, g, title, x, y - 1); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumToggleButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumToggleButtonUI.java deleted file mode 100644 index 2ddb9002f..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumToggleButtonUI.java +++ /dev/null @@ -1,155 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.*; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.RoundRectangle2D; -import javax.swing.*; -import javax.swing.plaf.*; -import javax.swing.plaf.basic.BasicGraphicsUtils; - -/** - * @author Michael Hagen - */ -public class AluminiumToggleButtonUI extends BaseToggleButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new AluminiumToggleButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - if (!b.isContentAreaFilled() || (b.getParent() instanceof JMenuBar)) { - return; - } - - if (!(b.isBorderPainted() && (b.getBorder() instanceof UIResource))) { - super.paintBackground(g, b); - return; - } - - int width = b.getWidth(); - int height = b.getHeight(); - ButtonModel model = b.getModel(); - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - Object savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - Color colors[]; - if (b.isEnabled()) { - Color background = b.getBackground(); - if (background instanceof ColorUIResource) { - if (model.isPressed() && model.isArmed()) { - colors = AbstractLookAndFeel.getTheme().getPressedColors(); - } else if (b.isRolloverEnabled() && model.isRollover()) { - if (model.isSelected()) { - colors = rolloverPressedColors; - } else { - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - } - } else if (model.isSelected()) { - colors = AbstractLookAndFeel.getTheme().getPressedColors(); - } else { - if (AbstractLookAndFeel.getTheme().doShowFocusFrame() && b.hasFocus()) { - colors = AbstractLookAndFeel.getTheme().getFocusColors(); - } else { - colors = AbstractLookAndFeel.getTheme().getButtonColors(); - } - } - } else { - if (model.isPressed() && model.isArmed()) { - colors = ColorHelper.createColorArr(ColorHelper.darker(background, 30), ColorHelper.darker(background, 10), 20); - } else if (b.isRolloverEnabled() && model.isRollover()) { - if (model.isSelected()) { - colors = ColorHelper.createColorArr(ColorHelper.darker(background, 20), background, 20); - } else { - colors = ColorHelper.createColorArr(ColorHelper.brighter(background, 50), ColorHelper.brighter(background, 10), 20); - } - } else if (model.isSelected()) { - colors = ColorHelper.createColorArr(ColorHelper.darker(background, 40), ColorHelper.darker(background, 20), 20); - } else { - colors = ColorHelper.createColorArr(ColorHelper.brighter(background, 30), ColorHelper.darker(background, 10), 20); - } - } - } else { // disabled - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } - if (AbstractLookAndFeel.getTheme().doDrawSquareButtons() - || (((width < 64) || (height < 16)) && ((b.getText() == null) || b.getText().length() == 0))) { - JTattooUtilities.fillHorGradient(g, colors, 0, 0, width - 1, height - 1); - if (model.isEnabled()) { - g2D.setColor(AbstractLookAndFeel.getFrameColor()); - } else { - g2D.setColor(ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 20)); - } - g2D.drawRect(0, 0, width - 1, height - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - g2D.setColor(Color.white); - g2D.drawRect(1, 1, width - 3, height - 3); - } else { - int d = height - 2; - Shape savedClip = g.getClip(); - Area clipArea = new Area(new RoundRectangle2D.Double(0, 0, width - 1, height - 1, d, d)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - JTattooUtilities.fillHorGradient(g, colors, 0, 0, width - 1, height - 1); - g2D.setClip(savedClip); - - if (model.isEnabled()) { - g2D.setColor(AbstractLookAndFeel.getFrameColor()); - } else { - g2D.setColor(ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 20)); - } - g2D.drawRoundRect(0, 0, width - 1, height - 1, d, d); - - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - g2D.setColor(Color.white); - g2D.drawRoundRect(1, 1, width - 3, height - 3, d - 2, d - 2); - - } - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRenderingHint); - g2D.setComposite(composite); - } - - protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { - Graphics2D g2D = (Graphics2D) g; - int width = b.getWidth(); - int height = b.getHeight(); - if (((width < 64) || (height < 16)) && ((b.getText() == null) || b.getText().length() == 0)) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - BasicGraphicsUtils.drawDashedRect(g, 4, 3, width - 8, height - 6); - } else { - Object savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2D.setColor(AbstractLookAndFeel.getFocusColor()); - int d = b.getHeight() - 4; - g2D.drawRoundRect(2, 2, b.getWidth() - 5, b.getHeight() - 5, d, d); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRenderingHint); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumToolBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumToolBarUI.java deleted file mode 100644 index 09be78286..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumToolBarUI.java +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.AbstractToolBarUI; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class AluminiumToolBarUI extends AbstractToolBarUI { - - public static ComponentUI createUI(JComponent c) { - return new AluminiumToolBarUI(); - } - - public Border getRolloverBorder() { - return AluminiumBorders.getRolloverToolButtonBorder(); - } - - public Border getNonRolloverBorder() { - return AluminiumBorders.getToolButtonBorder(); - } - - public boolean isButtonOpaque() { - return false; - } - - public void paint(Graphics g, JComponent c) { - AluminiumUtils.fillComponent(g, c); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumUtils.java b/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumUtils.java deleted file mode 100644 index ec29db29b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/aluminium/AluminiumUtils.java +++ /dev/null @@ -1,101 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.aluminium; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.JTattooUtilities; -import com.jtattoo.plaf.LazyImageIcon; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.Rectangle2D; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class AluminiumUtils { - - private static final Icon BG_IMAGE = new LazyImageIcon("aluminium/icons/background.jpg"); - private static final int IMAGE_WIDTH = BG_IMAGE.getIconWidth(); - private static final int IMAGE_HEIGHT = BG_IMAGE.getIconHeight(); - private static Image backgroundImage = null; - - private AluminiumUtils() { - } - - public static void fillComponent(Graphics g, Component c) { - Graphics2D g2D = (Graphics2D)g; - int w = c.getWidth(); - int h = c.getHeight(); - if (AbstractLookAndFeel.getTheme().isBackgroundPatternOn()) { - // pattern - Point p = JTattooUtilities.getRelLocation(c); - Dimension d = JTattooUtilities.getFrameSize(c); - int y = -p.y; - while (y < h) { - int x = -p.x; - while (x < w) { - BG_IMAGE.paintIcon(c, g, x, y); - x += IMAGE_WIDTH; - } - y += IMAGE_HEIGHT; - } - if (JTattooUtilities.getJavaVersion() >= 1.6) { - // higlight - if (backgroundImage == null - || backgroundImage.getWidth(null) != d.width - || backgroundImage.getHeight(null) != d.height) { - backgroundImage = c.createImage(d.width, d.height); - Graphics2D ig2D = (Graphics2D)backgroundImage.getGraphics(); - Point pt1 = new Point(0, 0); - Point pt2 = new Point(d.width, 0); - float fractions[] = {0.0f, 0.5f, 1.0f }; - Color c1 = new Color(220, 220, 220); - Color colors[] = {c1, Color.white, c1}; - ig2D.setPaint(new LinearGradientPaint(pt1, pt2, fractions, colors)); - ig2D.fillRect(0, 0, d.width, d.height); - ig2D.dispose(); - } - - Composite savedComposite = g2D.getComposite(); - g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f)); - g2D.drawImage(backgroundImage, -p.x, 0, null); - g2D.setComposite(savedComposite); - } - } else { - g.setColor(c.getBackground()); - g.fillRect(0, 0, w, h); - } - } - - public static void fillComponent(Graphics g, Component c, int x, int y, int w, int h) { - Graphics2D g2D = (Graphics2D) g; - Shape savedClip = g2D.getClip(); - Area clipArea = new Area(new Rectangle2D.Double(x, y, w, h)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - fillComponent(g, c); - g2D.setClip(savedClip); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/SplitterDownArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/SplitterDownArrow.gif deleted file mode 100644 index a3aaec29f..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/SplitterDownArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/SplitterLeftArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/SplitterLeftArrow.gif deleted file mode 100644 index e04fecb90..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/SplitterLeftArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/SplitterRightArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/SplitterRightArrow.gif deleted file mode 100644 index d5428e0b8..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/SplitterRightArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/SplitterUpArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/SplitterUpArrow.gif deleted file mode 100644 index 475c732e6..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/SplitterUpArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/background.jpg b/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/background.jpg deleted file mode 100644 index b754ad349..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/background.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/thumb_hor.gif b/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/thumb_hor.gif deleted file mode 100644 index 4582a9b19..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/thumb_hor.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/thumb_hor_rollover.gif b/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/thumb_hor_rollover.gif deleted file mode 100644 index 78f679b0e..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/thumb_hor_rollover.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/thumb_ver.gif b/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/thumb_ver.gif deleted file mode 100644 index aa9908228..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/thumb_ver.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/thumb_ver_rollover.gif b/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/thumb_ver_rollover.gif deleted file mode 100644 index be7efa0fe..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/aluminium/icons/thumb_ver_rollover.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinBorderFactory.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinBorderFactory.java deleted file mode 100644 index 2fe926128..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinBorderFactory.java +++ /dev/null @@ -1,122 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.AbstractBorderFactory; -import javax.swing.border.Border; - -/** - * @author Michael Hagen - */ -public class BernsteinBorderFactory implements AbstractBorderFactory { - - private static BernsteinBorderFactory instance = null; - - private BernsteinBorderFactory() { - } - - public static synchronized BernsteinBorderFactory getInstance() { - if (instance == null) { - instance = new BernsteinBorderFactory(); - } - return instance; - } - - public Border getFocusFrameBorder() { - return BernsteinBorders.getFocusFrameBorder(); - } - - public Border getButtonBorder() { - return BernsteinBorders.getButtonBorder(); - } - - public Border getToggleButtonBorder() { - return BernsteinBorders.getToggleButtonBorder(); - } - - public Border getTextBorder() { - return BernsteinBorders.getTextBorder(); - } - - public Border getSpinnerBorder() { - return BernsteinBorders.getSpinnerBorder(); - } - - public Border getTextFieldBorder() { - return BernsteinBorders.getTextFieldBorder(); - } - - public Border getComboBoxBorder() { - return BernsteinBorders.getComboBoxBorder(); - } - - public Border getTableHeaderBorder() { - return BernsteinBorders.getTableHeaderBorder(); - } - - public Border getTableScrollPaneBorder() { - return BernsteinBorders.getTableScrollPaneBorder(); - } - - public Border getScrollPaneBorder() { - return BernsteinBorders.getScrollPaneBorder(); - } - - public Border getTabbedPaneBorder() { - return BernsteinBorders.getTabbedPaneBorder(); - } - - public Border getMenuBarBorder() { - return BernsteinBorders.getMenuBarBorder(); - } - - public Border getMenuItemBorder() { - return BernsteinBorders.getMenuItemBorder(); - } - - public Border getPopupMenuBorder() { - return BernsteinBorders.getPopupMenuBorder(); - } - - public Border getInternalFrameBorder() { - return BernsteinBorders.getInternalFrameBorder(); - } - - public Border getPaletteBorder() { - return BernsteinBorders.getPaletteBorder(); - } - - public Border getToolBarBorder() { - return BernsteinBorders.getToolBarBorder(); - } - - public Border getProgressBarBorder() { - return BernsteinBorders.getProgressBarBorder(); - } - - public Border getDesktopIconBorder() { - return BernsteinBorders.getDesktopIconBorder(); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinBorders.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinBorders.java deleted file mode 100644 index c0910811f..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinBorders.java +++ /dev/null @@ -1,285 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.AbstractButton; -import javax.swing.ButtonModel; -import javax.swing.border.Border; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class BernsteinBorders extends BaseBorders { - - //------------------------------------------------------------------------------------ - // Lazy access methods - //------------------------------------------------------------------------------------ - public static Border getButtonBorder() { - if (buttonBorder == null) { - buttonBorder = new ButtonBorder(); - } - return buttonBorder; - } - - public static Border getToggleButtonBorder() { - return getButtonBorder(); - } - - public static Border getRolloverToolButtonBorder() { - if (rolloverToolButtonBorder == null) { - rolloverToolButtonBorder = new RolloverToolButtonBorder(); - } - return rolloverToolButtonBorder; - } - - public static Border getInternalFrameBorder() { - if (internalFrameBorder == null) { - internalFrameBorder = new InternalFrameBorder(); - } - return internalFrameBorder; - } - - //------------------------------------------------------------------------------------ - // Implementation of border classes - //------------------------------------------------------------------------------------ - public static class ButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(4, 8, 4, 8); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Color cHi = AbstractLookAndFeel.getControlDarkShadow(); - Color cLo = ColorHelper.darker(cHi, 8); - JTattooUtilities.draw3DBorder(g, cHi, cLo, x, y, w, h); - } - - public Insets getBorderInsets(Component c) { - return insets; - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class ButtonBorder - - public static class RolloverToolButtonBorder implements Border, UIResource { - - private static final Color frameHiColor = ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 60); - private static final Color frameLoColor = AbstractLookAndFeel.getFrameColor(); - private static final Insets insets = new Insets(2, 2, 2, 2); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - if (model.isEnabled()) { - if (model.isRollover()) { - JTattooUtilities.draw3DBorder(g, frameHiColor, frameLoColor, x, y, w - 1, h); - JTattooUtilities.draw3DBorder(g, Color.white, frameHiColor, x + 1, y + 1, w - 2, h - 2); - } else if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - g.setColor(frameHiColor); - g.drawRect(x, y, w - 2, h - 1); - } else { - g.setColor(AbstractLookAndFeel.getFrameColor()); - g.drawRect(x, y, w - 2, h - 1); - } - } else { - g.setColor(frameHiColor); - g.drawRect(x, y, w - 2, h - 1); - } - g.setColor(Color.white); - g.drawLine(w - 1, 0, w - 1, h - 1); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class RolloverToolButtonBorder - - public static class InternalFrameBorder extends BaseInternalFrameBorder { - - private static final Color borderColor = new Color(255, 244, 128); - private static final Color FRAME_COLORS[] = { - new Color(229, 187, 0), - new Color(251, 232, 0), - new Color(247, 225, 0), - new Color(243, 216, 0), - new Color(229, 187, 0),}; - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - if (!isResizable(c)) { - Color cHi = ColorHelper.brighter(borderColor, 40); - Color cLo = ColorHelper.darker(borderColor, 20); - JTattooUtilities.draw3DBorder(g, cHi, cLo, x, y, w, h); - cHi = ColorHelper.darker(cHi, 20); - cLo = ColorHelper.brighter(cLo, 20); - JTattooUtilities.draw3DBorder(g, cHi, cLo, x + 1, y + 1, w - 2, h - 2); - g.setColor(borderColor); - for (int i = 2; i < dw; i++) { - g.drawRect(i, i, w - (2 * i) - 1, h - (2 * i) - 1); - } - return; - } - int dt = w / 3; - int db = w * 2 / 3; - h--; - w--; - - Color cr = borderColor; - g.setColor(FRAME_COLORS[0]); - g.drawLine(x, y, x, y + h); - g.setColor(FRAME_COLORS[1]); - g.drawLine(x + 1, y + 1, x + 1, y + h - 1); - g.setColor(FRAME_COLORS[2]); - g.drawLine(x + 2, y + 2, x + 2, y + h - 2); - g.setColor(FRAME_COLORS[3]); - g.drawLine(x + 3, y + 3, x + 3, y + h - 3); - g.setColor(FRAME_COLORS[4]); - g.drawLine(x + 4, y + 4, x + 4, y + h - 4); - - // rechts - g.setColor(cr); - g.drawLine(x + w, y, x + w, y + h); - g.setColor(ColorHelper.brighter(cr, 30)); - g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); - g.setColor(ColorHelper.brighter(cr, 60)); - g.drawLine(x + w - 2, y + 2, x + w - 2, y + h - 2); - g.setColor(ColorHelper.brighter(cr, 90)); - g.drawLine(x + w - 3, y + 3, x + w - 3, y + h - 3); - g.setColor(cr); - g.drawLine(x + w - 4, y + 4, x + w - 4, y + h - 4); - - g.setColor(FRAME_COLORS[0]); - g.drawLine(x + w, y, x + w, y + trackWidth); - g.setColor(FRAME_COLORS[1]); - g.drawLine(x + w - 1, y + 1, x + w - 1, y + trackWidth); - g.setColor(FRAME_COLORS[2]); - g.drawLine(x + w - 2, y + 2, x + w - 2, y + trackWidth); - g.setColor(FRAME_COLORS[3]); - g.drawLine(x + w - 3, y + 3, x + w - 3, y + trackWidth); - g.setColor(FRAME_COLORS[4]); - g.drawLine(x + w - 4, y + 4, x + w - 4, y + trackWidth); - - g.setColor(FRAME_COLORS[0]); - g.drawLine(x + w, y + h - trackWidth, x + w, y + h); - g.setColor(FRAME_COLORS[1]); - g.drawLine(x + w - 1, y + h - trackWidth, x + w - 1, y + h - 1); - g.setColor(FRAME_COLORS[2]); - g.drawLine(x + w - 2, y + h - trackWidth, x + w - 2, y + h - 2); - g.setColor(FRAME_COLORS[3]); - g.drawLine(x + w - 3, y + h - trackWidth, x + w - 3, y + h - 3); - g.setColor(FRAME_COLORS[4]); - g.drawLine(x + w - 4, y + h - trackWidth, x + w - 4, y + h - 4); - // oben - g.setColor(FRAME_COLORS[0]); - g.drawLine(x, y, x + dt, y); - g.setColor(FRAME_COLORS[1]); - g.drawLine(x + 1, y + 1, x + dt, y + 1); - g.setColor(FRAME_COLORS[2]); - g.drawLine(x + 2, y + 2, x + dt, y + 2); - g.setColor(FRAME_COLORS[3]); - g.drawLine(x + 3, y + 3, x + dt, y + 3); - g.setColor(FRAME_COLORS[4]); - g.drawLine(x + 4, y + 4, x + dt, y + 4); - - g.setColor(cr); - g.drawLine(x + dt, y, x + w, y); - g.setColor(ColorHelper.brighter(cr, 90)); - g.drawLine(x + dt, y + 1, x + w - 1, y + 1); - g.setColor(ColorHelper.brighter(cr, 60)); - g.drawLine(x + dt, y + 2, x + w - 2, y + 2); - g.setColor(ColorHelper.brighter(cr, 30)); - g.drawLine(x + dt, y + 3, x + w - 3, y + 3); - g.setColor(cr); - g.drawLine(x + dt, y + 4, x + w - 4, y + 4); - - g.setColor(FRAME_COLORS[0]); - g.drawLine(x + w - trackWidth, y, x + w, y); - g.setColor(FRAME_COLORS[1]); - g.drawLine(x + w - trackWidth, y + 1, x + w - 1, y + 1); - g.setColor(FRAME_COLORS[2]); - g.drawLine(x + w - trackWidth, y + 2, x + w - 2, y + 2); - g.setColor(FRAME_COLORS[3]); - g.drawLine(x + w - trackWidth, y + 3, x + w - 3, y + 3); - g.setColor(FRAME_COLORS[4]); - g.drawLine(x + w - trackWidth, y + 4, x + w - 4, y + 4); - - // unten - g.setColor(FRAME_COLORS[0]); - g.drawLine(x, y + h, x + db, y + h); - g.setColor(FRAME_COLORS[1]); - g.drawLine(x + 1, y + h - 1, x + db, y + h - 1); - g.setColor(FRAME_COLORS[2]); - g.drawLine(x + 2, y + h - 2, x + db, y + h - 2); - g.setColor(FRAME_COLORS[3]); - g.drawLine(x + 3, y + h - 3, x + db, y + h - 3); - g.setColor(FRAME_COLORS[4]); - g.drawLine(x + 4, y + h - 4, x + db, y + h - 4); - - g.setColor(cr); - g.drawLine(x + db, y + h, x + w, y + h); - g.setColor(ColorHelper.brighter(cr, 30)); - g.drawLine(x + db, y + h - 1, x + w - 1, y + h - 1); - g.setColor(ColorHelper.brighter(cr, 60)); - g.drawLine(x + db, y + h - 2, x + w - 2, y + h - 2); - g.setColor(ColorHelper.brighter(cr, 90)); - g.drawLine(x + db, y + h - 3, x + w - 3, y + h - 3); - g.setColor(cr); - g.drawLine(x + db, y + h - 4, x + w - 4, y + h - 4); - - g.setColor(FRAME_COLORS[0]); - g.drawLine(x + w - trackWidth, y + h, x + w, y + h); - g.setColor(FRAME_COLORS[1]); - g.drawLine(x + w - trackWidth, y + h - 1, x + w - 1, y + h - 1); - g.setColor(FRAME_COLORS[2]); - g.drawLine(x + w - trackWidth, y + h - 2, x + w - 2, y + h - 2); - g.setColor(FRAME_COLORS[3]); - g.drawLine(x + w - trackWidth, y + h - 3, x + w - 3, y + h - 3); - g.setColor(FRAME_COLORS[4]); - g.drawLine(x + w - trackWidth, y + h - 4, x + w - 4, y + h - 4); - } - } // class InternalFrameBorder -} // class BernsteinBorders - diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinButtonUI.java deleted file mode 100644 index 5653918ce..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinButtonUI.java +++ /dev/null @@ -1,96 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Graphics; -import java.awt.Insets; -import javax.swing.*; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class BernsteinButtonUI extends BaseButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new BernsteinButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - if (!b.isContentAreaFilled() || (b.getParent() instanceof JMenuBar)) { - return; - } - - int width = b.getWidth(); - int height = b.getHeight(); - - ButtonModel model = b.getModel(); - Color colors[] = AbstractLookAndFeel.getTheme().getButtonColors(); - if (b.isEnabled()) { - Color background = b.getBackground(); - if (background instanceof ColorUIResource) { - if (model.isPressed() && model.isArmed()) { - colors = AbstractLookAndFeel.getTheme().getPressedColors(); - } else if (b.isRolloverEnabled() && model.isRollover()) { - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - } else if (AbstractLookAndFeel.getTheme().doShowFocusFrame() && b.hasFocus()) { - colors = AbstractLookAndFeel.getTheme().getFocusColors(); - } else if (JTattooUtilities.isFrameActive(b) - && (b.getRootPane() != null) - && (b.equals(b.getRootPane().getDefaultButton()))) { - colors = AbstractLookAndFeel.getTheme().getSelectedColors(); - } - } else { - if (model.isPressed() && model.isArmed()) { - colors = ColorHelper.createColorArr(ColorHelper.darker(background, 30), ColorHelper.darker(background, 10), 20); - } else { - if (b.isRolloverEnabled() && model.isRollover()) { - colors = ColorHelper.createColorArr(ColorHelper.brighter(background, 50), ColorHelper.brighter(background, 10), 20); - } else { - colors = ColorHelper.createColorArr(ColorHelper.brighter(background, 30), ColorHelper.darker(background, 10), 20); - } - } - } - } else { // disabled - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } - - if (b.isBorderPainted() && (b.getBorder() != null)) { - Insets insets = b.getBorder().getBorderInsets(b); - int x = insets.left > 0 ? 1 : 0; - int y = insets.top > 0 ? 1 : 0; - int w = insets.right > 0 ? width - 1 : width; - int h = insets.bottom > 0 ? height - 1 : height; - JTattooUtilities.fillHorGradient(g, colors, x, y, w - x, h - y); - } else { - JTattooUtilities.fillHorGradient(g, colors, 0, 0, width, height); - } - } - -} - - diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinCheckBoxUI.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinCheckBoxUI.java deleted file mode 100644 index 706f8cb1a..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinCheckBoxUI.java +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class BernsteinCheckBoxUI extends BernsteinRadioButtonUI { - - private static BernsteinCheckBoxUI checkBoxUI = null; - - public static ComponentUI createUI(JComponent b) { - if (checkBoxUI == null) { - checkBoxUI = new BernsteinCheckBoxUI(); - } - return checkBoxUI; - } - - public void installDefaults(AbstractButton b) { - super.installDefaults(b); - icon = UIManager.getIcon("CheckBox.icon"); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinDefaultTheme.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinDefaultTheme.java deleted file mode 100644 index c5fc4303f..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinDefaultTheme.java +++ /dev/null @@ -1,153 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.AbstractTheme; -import com.jtattoo.plaf.ColorHelper; -import java.awt.Color; -import javax.swing.plaf.ColorUIResource; - -/** - * @author Michael Hagen - */ -public class BernsteinDefaultTheme extends AbstractTheme { - - public BernsteinDefaultTheme() { - super(); - // Setup theme with defaults - setUpColor(); - // Overwrite defaults with user props - loadProperties(); - // Setup the color arrays - setUpColorArrs(); - } - - public String getPropertyFileName() { - return "BernsteinTheme.properties"; - } - - public void setUpColor() { - super.setUpColor(); - // Defaults for BernsteinLookAndFeel - menuOpaque = false; - menuAlpha = 0.85f; - - backgroundColor = new ColorUIResource(253, 249, 204); - backgroundColorLight = white; - backgroundColorDark = new ColorUIResource(253, 241, 176); - alterBackgroundColor = new ColorUIResource(253, 241, 176); - - selectionBackgroundColor = new ColorUIResource(250, 216, 32); - disabledForegroundColor = new ColorUIResource(164, 164, 164); - frameColor = new ColorUIResource(233, 199, 5); - focusCellColor = new ColorUIResource(139, 92, 0); - rolloverColor = new ColorUIResource(251, 220, 64); - - buttonBackgroundColor = new ColorUIResource(253, 249, 204); - - controlBackgroundColor = new ColorUIResource(253, 249, 204); - controlHighlightColor = white; - controlShadowColor = new ColorUIResource(247, 231, 34); - controlDarkShadowColor = frameColor; - controlColorLight = new ColorUIResource(252, 218, 0); - controlColorDark = new ColorUIResource(183, 142, 0); - - windowTitleBackgroundColor = selectionBackgroundColor; - windowTitleColorLight = new ColorUIResource(253, 249, 204); - windowTitleColorDark = new ColorUIResource(251, 241, 153); - windowBorderColor = new ColorUIResource(254, 240, 0); - - windowInactiveTitleBackgroundColor = backgroundColor; - windowInactiveTitleColorLight = white; - windowInactiveTitleColorDark = new ColorUIResource(236, 236, 236); - windowInactiveBorderColor = new ColorUIResource(254, 240, 0); - - menuBackgroundColor = backgroundColor; - menuSelectionBackgroundColor = selectionBackgroundColor; - - tabAreaBackgroundColor = backgroundColor; - desktopColor = new ColorUIResource(253, 249, 204); - - tooltipForegroundColor = black; - tooltipBackgroundColor = new ColorUIResource(254, 240, 80);//new ColorUIResource(240, 240, 240); - } - - public void setUpColorArrs() { - super.setUpColorArrs(); - // Generate the color arrays - DEFAULT_COLORS = new Color[]{ - new Color(247, 225, 0), - new Color(251, 232, 0), - new Color(243, 216, 0), - new Color(237, 204, 0), - new Color(239, 209, 0), - new Color(242, 215, 0), - new Color(243, 216, 0), - new Color(245, 221, 0), - new Color(246, 222, 0), - new Color(247, 225, 0), - new Color(248, 227, 0), - new Color(249, 230, 0), - new Color(251, 232, 0), - new Color(252, 235, 0), - new Color(253, 237, 0), - new Color(253, 237, 0), - new Color(254, 240, 0),}; - HIDEFAULT_COLORS = new Color[DEFAULT_COLORS.length]; - for (int i = 0; i < DEFAULT_COLORS.length; i++) { - HIDEFAULT_COLORS[i] = ColorHelper.brighter(DEFAULT_COLORS[i], 50.0); - } - - ACTIVE_COLORS = DEFAULT_COLORS; - INACTIVE_COLORS = HIDEFAULT_COLORS; - SELECTED_COLORS = DEFAULT_COLORS; - PRESSED_COLORS = new Color[DEFAULT_COLORS.length]; - for (int i = 0; i < DEFAULT_COLORS.length; i++) { - PRESSED_COLORS[i] = backgroundColor; - } - - ROLLOVER_COLORS = new Color[DEFAULT_COLORS.length]; - for (int i = 0; i < DEFAULT_COLORS.length; i++) { - ROLLOVER_COLORS[i] = ColorHelper.brighter(DEFAULT_COLORS[i], 70.0); - } - - DISABLED_COLORS = new Color[HIDEFAULT_COLORS.length]; - for (int i = 0; i < HIDEFAULT_COLORS.length; i++) { - DISABLED_COLORS[i] = ColorHelper.brighter(HIDEFAULT_COLORS[i], 40.0); - } - - WINDOW_TITLE_COLORS = ColorHelper.createColorArr(windowTitleColorLight, windowTitleColorDark, 20); - WINDOW_INACTIVE_TITLE_COLORS = ColorHelper.createColorArr(windowInactiveTitleColorLight, windowInactiveTitleColorDark, 20); - MENUBAR_COLORS = ColorHelper.createColorArr(menuColorLight, menuColorDark, 20); - TOOLBAR_COLORS = MENUBAR_COLORS; - - BUTTON_COLORS = HIDEFAULT_COLORS; - TAB_COLORS = BUTTON_COLORS; - COL_HEADER_COLORS = HIDEFAULT_COLORS; - THUMB_COLORS = HIDEFAULT_COLORS; - TRACK_COLORS = ColorHelper.createColorArr(new Color(255, 245, 200), Color.white, 20); - SLIDER_COLORS = DEFAULT_COLORS; - PROGRESSBAR_COLORS = DEFAULT_COLORS; - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinDesktopPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinDesktopPaneUI.java deleted file mode 100644 index ed31dc21b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinDesktopPaneUI.java +++ /dev/null @@ -1,52 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.BaseDesktopPaneUI; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class BernsteinDesktopPaneUI extends BaseDesktopPaneUI { - - private static BernsteinDesktopPaneUI desktopPaneUI = null; - - public static ComponentUI createUI(JComponent c) { - if (desktopPaneUI == null) { - desktopPaneUI = new BernsteinDesktopPaneUI(); - } - return desktopPaneUI; - } - - public void update(Graphics g, JComponent c) { - if (c.getClientProperty("backgroundTexture") == null) { - BernsteinUtils.fillComponent(g, c); - } else { - super.update(g, c); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinIconFactory.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinIconFactory.java deleted file mode 100644 index a7a5fe1ba..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinIconFactory.java +++ /dev/null @@ -1,213 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.AbstractIconFactory; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class BernsteinIconFactory implements AbstractIconFactory { - - private static BernsteinIconFactory instance = null; - - private BernsteinIconFactory() { - } - - public static synchronized BernsteinIconFactory getInstance() { - if (instance == null) { - instance = new BernsteinIconFactory(); - } - return instance; - } - - public Icon getOptionPaneErrorIcon() { - return BernsteinIcons.getOptionPaneErrorIcon(); - } - - public Icon getOptionPaneWarningIcon() { - return BernsteinIcons.getOptionPaneWarningIcon(); - } - - public Icon getOptionPaneInformationIcon() { - return BernsteinIcons.getOptionPaneInformationIcon(); - } - - public Icon getOptionPaneQuestionIcon() { - return BernsteinIcons.getOptionPaneQuestionIcon(); - } - - public Icon getFileChooserDetailViewIcon() { - return BernsteinIcons.getFileChooserDetailViewIcon(); - } - - public Icon getFileChooserHomeFolderIcon() { - return BernsteinIcons.getFileChooserHomeFolderIcon(); - } - - public Icon getFileChooserListViewIcon() { - return BernsteinIcons.getFileChooserListViewIcon(); - } - - public Icon getFileChooserNewFolderIcon() { - return BernsteinIcons.getFileChooserNewFolderIcon(); - } - - public Icon getFileChooserUpFolderIcon() { - return BernsteinIcons.getFileChooserUpFolderIcon(); - } - - public Icon getMenuIcon() { - return BernsteinIcons.getMenuIcon(); - } - - public Icon getIconIcon() { - return BernsteinIcons.getIconIcon(); - } - - public Icon getMaxIcon() { - return BernsteinIcons.getMaxIcon(); - } - - public Icon getMinIcon() { - return BernsteinIcons.getMinIcon(); - } - - public Icon getCloseIcon() { - return BernsteinIcons.getCloseIcon(); - } - - public Icon getPaletteCloseIcon() { - return BernsteinIcons.getPaletteCloseIcon(); - } - - public Icon getRadioButtonIcon() { - return BernsteinIcons.getRadioButtonIcon(); - } - - public Icon getCheckBoxIcon() { - return BernsteinIcons.getCheckBoxIcon(); - } - - public Icon getComboBoxIcon() { - return BernsteinIcons.getComboBoxIcon(); - } - - public Icon getTreeComputerIcon() { - return BernsteinIcons.getTreeComputerIcon(); - } - - public Icon getTreeFloppyDriveIcon() { - return BernsteinIcons.getTreeFloppyDriveIcon(); - } - - public Icon getTreeHardDriveIcon() { - return BernsteinIcons.getTreeHardDriveIcon(); - } - - public Icon getTreeFolderIcon() { - return BernsteinIcons.getTreeFolderIcon(); - } - - public Icon getTreeLeafIcon() { - return BernsteinIcons.getTreeLeafIcon(); - } - - public Icon getTreeCollapsedIcon() { - return BernsteinIcons.getTreeControlIcon(true); - } - - public Icon getTreeExpandedIcon() { - return BernsteinIcons.getTreeControlIcon(false); - } - - public Icon getMenuArrowIcon() { - return BernsteinIcons.getMenuArrowIcon(); - } - - public Icon getMenuCheckBoxIcon() { - return BernsteinIcons.getMenuCheckBoxIcon(); - } - - public Icon getMenuRadioButtonIcon() { - return BernsteinIcons.getMenuRadioButtonIcon(); - } - - public Icon getUpArrowIcon() { - return BernsteinIcons.getUpArrowIcon(); - } - - public Icon getDownArrowIcon() { - return BernsteinIcons.getDownArrowIcon(); - } - - public Icon getLeftArrowIcon() { - return BernsteinIcons.getLeftArrowIcon(); - } - - public Icon getRightArrowIcon() { - return BernsteinIcons.getRightArrowIcon(); - } - - public Icon getSplitterDownArrowIcon() { - return BernsteinIcons.getSplitterDownArrowIcon(); - } - - public Icon getSplitterHorBumpIcon() { - return BernsteinIcons.getSplitterHorBumpIcon(); - } - - public Icon getSplitterLeftArrowIcon() { - return BernsteinIcons.getSplitterLeftArrowIcon(); - } - - public Icon getSplitterRightArrowIcon() { - return BernsteinIcons.getSplitterRightArrowIcon(); - } - - public Icon getSplitterUpArrowIcon() { - return BernsteinIcons.getSplitterUpArrowIcon(); - } - - public Icon getSplitterVerBumpIcon() { - return BernsteinIcons.getSplitterVerBumpIcon(); - } - - public Icon getThumbHorIcon() { - return BernsteinIcons.getThumbHorIcon(); - } - - public Icon getThumbVerIcon() { - return BernsteinIcons.getThumbVerIcon(); - } - - public Icon getThumbHorIconRollover() { - return BernsteinIcons.getThumbHorIconRollover(); - } - - public Icon getThumbVerIconRollover() { - return BernsteinIcons.getThumbVerIconRollover(); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinIcons.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinIcons.java deleted file mode 100644 index e92a84f3e..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinIcons.java +++ /dev/null @@ -1,225 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.*; -import java.awt.Component; -import java.awt.Graphics; -import javax.swing.*; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class BernsteinIcons extends BaseIcons { - - public static Icon getRadioButtonIcon() { - if (radioButtonIcon == null) { - radioButtonIcon = new RadioButtonIcon(); - } - return radioButtonIcon; - } - - public static Icon getCheckBoxIcon() { - if (checkBoxIcon == null) { - checkBoxIcon = new CheckBoxIcon(); - } - return checkBoxIcon; - } - - public static Icon getThumbHorIcon() { - if (thumbHorIcon == null) { - thumbHorIcon = new LazyImageIcon("bernstein/icons/radio.gif"); - } - return thumbHorIcon; - } - - public static Icon getThumbVerIcon() { - if (thumbVerIcon == null) { - thumbVerIcon = new LazyImageIcon("bernstein/icons/radio.gif"); - } - return thumbVerIcon; - } - - public static Icon getThumbHorIconRollover() { - if (thumbHorIconRollover == null) { - thumbHorIconRollover = new LazyImageIcon("bernstein/icons/radio_rollover.gif"); - } - return thumbHorIconRollover; - } - - public static Icon getThumbVerIconRollover() { - if (thumbVerIconRollover == null) { - thumbVerIconRollover = new LazyImageIcon("bernstein/icons/radio_rollover.gif"); - } - return thumbVerIconRollover; - } - - public static Icon getSplitterUpArrowIcon() { - if (splitterUpArrowIcon == null) { - splitterUpArrowIcon = new LazyImageIcon("bernstein/icons/SplitterUpArrow.gif"); - } - return splitterUpArrowIcon; - } - - public static Icon getSplitterDownArrowIcon() { - if (splitterDownArrowIcon == null) { - splitterDownArrowIcon = new LazyImageIcon("bernstein/icons/SplitterDownArrow.gif"); - } - return splitterDownArrowIcon; - } - - public static Icon getSplitterLeftArrowIcon() { - if (splitterLeftArrowIcon == null) { - splitterLeftArrowIcon = new LazyImageIcon("bernstein/icons/SplitterLeftArrow.gif"); - } - return splitterLeftArrowIcon; - } - - public static Icon getSplitterRightArrowIcon() { - if (splitterRightArrowIcon == null) { - splitterRightArrowIcon = new LazyImageIcon("bernstein/icons/SplitterRightArrow.gif"); - } - return splitterRightArrowIcon; - } - - //-------------------------------------------------------------------------------------------------------- - private static class CheckBoxIcon implements Icon, UIResource { - - private static Icon checkIcon = null; - private static Icon checkSelectedIcon = null; - private static Icon checkPressedIcon = null; - private static Icon checkRolloverIcon = null; - private static Icon checkRolloverSelectedIcon = null; - private static Icon checkDisabledIcon = null; - private static Icon checkDisabledSelectedIcon = null; - - public CheckBoxIcon() { - checkIcon = new LazyImageIcon("bernstein/icons/check.gif"); - checkSelectedIcon = new LazyImageIcon("bernstein/icons/check_selected.gif"); - checkPressedIcon = new LazyImageIcon("bernstein/icons/check_pressed.gif"); - checkRolloverIcon = new LazyImageIcon("bernstein/icons/check_rollover.gif"); - checkRolloverSelectedIcon = new LazyImageIcon("bernstein/icons/check_rollover_selected.gif"); - checkDisabledIcon = new LazyImageIcon("bernstein/icons/check_disabled.gif"); - checkDisabledSelectedIcon = new LazyImageIcon("bernstein/icons/check_disabled_selected.gif"); - } - - public void paintIcon(Component c, Graphics g, int x, int y) { - if (!JTattooUtilities.isLeftToRight(c)) { - x += 2; - } - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - if (button.isEnabled()) { - if (model.isPressed() && model.isArmed()) { - checkPressedIcon.paintIcon(c, g, x, y); - } else if (model.isSelected()) { - if (button.isRolloverEnabled() && model.isRollover() && !model.isArmed()) { - checkRolloverSelectedIcon.paintIcon(c, g, x, y); - } else { - checkSelectedIcon.paintIcon(c, g, x, y); - } - } else { - if (button.isRolloverEnabled() && model.isRollover() && !model.isArmed()) { - checkRolloverIcon.paintIcon(c, g, x, y); - } else { - checkIcon.paintIcon(c, g, x, y); - } - } - } else { - if (model.isPressed() && model.isArmed()) { - checkPressedIcon.paintIcon(c, g, x, y); - } else if (model.isSelected()) { - checkDisabledSelectedIcon.paintIcon(c, g, x, y); - } else { - checkDisabledIcon.paintIcon(c, g, x, y); - } - } - } - - public int getIconWidth() { - return checkIcon.getIconWidth() + 2; - } - - public int getIconHeight() { - return checkIcon.getIconHeight(); - } - } - - private static class RadioButtonIcon implements Icon, UIResource { - - private Icon radioIcon = null; - private Icon radioSelectedIcon = null; - private Icon radioRolloverIcon = null; - private Icon radioRolloverSelectedIcon = null; - private Icon radioDisabledIcon = null; - private Icon radioDisabledSelectedIcon = null; - - public RadioButtonIcon() { - radioIcon = new LazyImageIcon("bernstein/icons/radio.gif"); - radioSelectedIcon = new LazyImageIcon("bernstein/icons/radio_selected.gif"); - radioRolloverIcon = new LazyImageIcon("bernstein/icons/radio_rollover.gif"); - radioRolloverSelectedIcon = new LazyImageIcon("bernstein/icons/radio_rollover_selected.gif"); - radioDisabledIcon = new LazyImageIcon("bernstein/icons/radio_disabled.gif"); - radioDisabledSelectedIcon = new LazyImageIcon("bernstein/icons/radio_disabled_selected.gif"); - } - - public void paintIcon(Component c, Graphics g, int x, int y) { - if (!JTattooUtilities.isLeftToRight(c)) { - x += 2; - } - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - if (button.isEnabled()) { - if (model.isSelected()) { - if (button.isRolloverEnabled() && model.isRollover()) { - radioRolloverSelectedIcon.paintIcon(c, g, x, y); - } else { - radioSelectedIcon.paintIcon(c, g, x, y); - } - } else { - if (button.isRolloverEnabled() && model.isRollover()) { - radioRolloverIcon.paintIcon(c, g, x, y); - } else { - radioIcon.paintIcon(c, g, x, y); - } - } - } else { - if (model.isSelected()) { - radioDisabledSelectedIcon.paintIcon(c, g, x, y); - } else { - radioDisabledIcon.paintIcon(c, g, x, y); - } - } - } - - public int getIconWidth() { - return radioIcon.getIconWidth() + 2; - } - - public int getIconHeight() { - return radioIcon.getIconHeight(); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinInternalFrameTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinInternalFrameTitlePane.java deleted file mode 100644 index 2909063e5..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinInternalFrameTitlePane.java +++ /dev/null @@ -1,73 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JInternalFrame; - -/** - * @author Michael Hagen - */ -public class BernsteinInternalFrameTitlePane extends BaseInternalFrameTitlePane { - - public BernsteinInternalFrameTitlePane(JInternalFrame f) { - super(f); - } - - public void paintPalette(Graphics g) { - BernsteinUtils.fillComponent(g, this); - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getDefaultColors(), 0, 0, getWidth(), getHeight()); - g2D.setComposite(composite); - if (isActive()) { - g.setColor(AbstractLookAndFeel.getTheme().getWindowBorderColor()); - } else { - g.setColor(AbstractLookAndFeel.getTheme().getWindowInactiveBorderColor()); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } - - public void paintBackground(Graphics g) { - BernsteinUtils.fillComponent(g, this); - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getDefaultColors(), 0, 0, getWidth(), getHeight()); - g2D.setComposite(composite); - if (isActive()) { - g.setColor(AbstractLookAndFeel.getTheme().getWindowBorderColor()); - } else { - g.setColor(AbstractLookAndFeel.getTheme().getWindowInactiveBorderColor()); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } - - public void paintBorder(Graphics g) { - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinInternalFrameUI.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinInternalFrameUI.java deleted file mode 100644 index 2b467770b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinInternalFrameUI.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.BaseInternalFrameUI; -import javax.swing.JComponent; -import javax.swing.JInternalFrame; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class BernsteinInternalFrameUI extends BaseInternalFrameUI { - - public BernsteinInternalFrameUI(JInternalFrame b) { - super(b); - } - - public static ComponentUI createUI(JComponent c) { - return new BernsteinInternalFrameUI((JInternalFrame) c); - } - - protected JComponent createNorthPane(JInternalFrame w) { - titlePane = new BernsteinInternalFrameTitlePane(w); - return titlePane; - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinLookAndFeel.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinLookAndFeel.java deleted file mode 100644 index 8fbe62f41..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinLookAndFeel.java +++ /dev/null @@ -1,205 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.*; -import java.util.*; -import javax.swing.UIDefaults; - -/** - * @author Michael Hagen - */ -public class BernsteinLookAndFeel extends AbstractLookAndFeel { - - private static BernsteinDefaultTheme myTheme = null; - - private static final ArrayList themesList = new ArrayList(); - private static final HashMap themesMap = new HashMap(); - private static final Properties defaultProps = new Properties(); - private static final Properties smallFontProps = new Properties(); - private static final Properties largeFontProps = new Properties(); - private static final Properties giantFontProps = new Properties(); - - static { - smallFontProps.setProperty("controlTextFont", "Dialog 10"); - smallFontProps.setProperty("systemTextFont", "Dialog 10"); - smallFontProps.setProperty("userTextFont", "Dialog 10"); - smallFontProps.setProperty("menuTextFont", "Dialog 10"); - smallFontProps.setProperty("windowTitleFont", "Dialog bold 10"); - smallFontProps.setProperty("subTextFont", "Dialog 8"); - - largeFontProps.setProperty("controlTextFont", "Dialog 14"); - largeFontProps.setProperty("systemTextFont", "Dialog 14"); - largeFontProps.setProperty("userTextFont", "Dialog 14"); - largeFontProps.setProperty("menuTextFont", "Dialog 14"); - largeFontProps.setProperty("windowTitleFont", "Dialog bold 14"); - largeFontProps.setProperty("subTextFont", "Dialog 12"); - - giantFontProps.setProperty("controlTextFont", "Dialog 18"); - giantFontProps.setProperty("systemTextFont", "Dialog 18"); - giantFontProps.setProperty("userTextFont", "Dialog 18"); - giantFontProps.setProperty("menuTextFont", "Dialog 18"); - giantFontProps.setProperty("windowTitleFont", "Dialog 18"); - giantFontProps.setProperty("subTextFont", "Dialog 16"); - - themesList.add("Default"); - themesList.add("Small-Font"); - themesList.add("Large-Font"); - themesList.add("Giant-Font"); - - themesMap.put("Default", defaultProps); - themesMap.put("Small-Font", smallFontProps); - themesMap.put("Large-Font", largeFontProps); - themesMap.put("Giant-Font", giantFontProps); - } - - public static java.util.List getThemes() { - return themesList; - } - - public static Properties getThemeProperties(String name) { - return ((Properties) themesMap.get(name)); - } - - public static void setTheme(String name) { - setTheme((Properties) themesMap.get(name)); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - - public static void setTheme(String name, String licenseKey, String logoString) { - Properties props = (Properties) themesMap.get(name); - if (props != null) { - props.put("licenseKey", licenseKey); - props.put("logoString", logoString); - setTheme(props); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - } - - public static void setTheme(Properties themesProps) { - if (myTheme == null) { - myTheme = new BernsteinDefaultTheme(); - } - if ((myTheme != null) && (themesProps != null)) { - myTheme.setUpColor(); - myTheme.setProperties(themesProps); - myTheme.setUpColorArrs(); - AbstractLookAndFeel.setTheme(myTheme); - } - } - - public static void setCurrentTheme(Properties themesProps) { - setTheme(themesProps); - } - - public String getName() { - return "Bernstein"; - } - - public String getID() { - return "Bernstein"; - } - - public String getDescription() { - return "The Bernstein Look and Feel"; - } - - public boolean isNativeLookAndFeel() { - return false; - } - - public boolean isSupportedLookAndFeel() { - return true; - } - - public AbstractBorderFactory getBorderFactory() { - return BernsteinBorderFactory.getInstance(); - } - - public AbstractIconFactory getIconFactory() { - return BernsteinIconFactory.getInstance(); - } - - protected void createDefaultTheme() { - if (myTheme == null) { - myTheme = new BernsteinDefaultTheme(); - } - setTheme(myTheme); - } - - protected void initClassDefaults(UIDefaults table) { - super.initClassDefaults(table); - Object[] uiDefaults = { - // BaseLookAndFeel classes - "ToggleButtonUI", BaseToggleButtonUI.class.getName(), - "LabelUI", BaseLabelUI.class.getName(), - "SeparatorUI", BaseSeparatorUI.class.getName(), - "TextFieldUI", BaseTextFieldUI.class.getName(), - "TextAreaUI", BaseTextAreaUI.class.getName(), - "EditorPaneUI", BaseEditorPaneUI.class.getName(), - "PasswordFieldUI", BasePasswordFieldUI.class.getName(), - "ComboBoxUI", BaseComboBoxUI.class.getName(), - "ToolTipUI", BaseToolTipUI.class.getName(), - "TreeUI", BaseTreeUI.class.getName(), - "TableUI", BaseTableUI.class.getName(), - "TableHeaderUI", BaseTableHeaderUI.class.getName(), - "ScrollBarUI", BaseScrollBarUI.class.getName(), - "ProgressBarUI", BaseProgressBarUI.class.getName(), - "FileChooserUI", BaseFileChooserUI.class.getName(), - "MenuUI", BaseMenuUI.class.getName(), - "PopupMenuUI", BasePopupMenuUI.class.getName(), - "MenuItemUI", BaseMenuItemUI.class.getName(), - "CheckBoxMenuItemUI", BaseCheckBoxMenuItemUI.class.getName(), - "RadioButtonMenuItemUI", BaseRadioButtonMenuItemUI.class.getName(), - "PopupMenuSeparatorUI", BaseSeparatorUI.class.getName(), - // BernsteinLookAndFeel classes - "CheckBoxUI", BernsteinCheckBoxUI.class.getName(), - "RadioButtonUI", BernsteinRadioButtonUI.class.getName(), - "ButtonUI", BernsteinButtonUI.class.getName(), - "SliderUI", BernsteinSliderUI.class.getName(), - "PanelUI", BernsteinPanelUI.class.getName(), - "ScrollPaneUI", BernsteinScrollPaneUI.class.getName(), - "TabbedPaneUI", BernsteinTabbedPaneUI.class.getName(), - "ToolBarUI", BernsteinToolBarUI.class.getName(), - "MenuBarUI", BernsteinMenuBarUI.class.getName(), - "SplitPaneUI", BernsteinSplitPaneUI.class.getName(), - "InternalFrameUI", BernsteinInternalFrameUI.class.getName(), - "RootPaneUI", BernsteinRootPaneUI.class.getName(), - "DesktopPaneUI", BernsteinDesktopPaneUI.class.getName(),}; - table.putDefaults(uiDefaults); - if (JTattooUtilities.getJavaVersion() >= 1.5) { - table.put("FormattedTextFieldUI", BaseFormattedTextFieldUI.class.getName()); - table.put("SpinnerUI", BaseSpinnerUI.class.getName()); - } - } - - protected void initComponentDefaults(UIDefaults table) { - super.initComponentDefaults(table); - table.put("SplitPane.centerOneTouchButtons", Boolean.FALSE); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinMenuBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinMenuBarUI.java deleted file mode 100644 index 4d5c47fc4..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinMenuBarUI.java +++ /dev/null @@ -1,53 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.JMenuBar; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicMenuBarUI; - - -/** - * @author Michael Hagen - */ -public class BernsteinMenuBarUI extends BasicMenuBarUI { - - public static ComponentUI createUI(JComponent x) { - return new BernsteinMenuBarUI(); - } - - public void installUI(JComponent c) { - super.installUI(c); - if ((c != null) && (c instanceof JMenuBar)) { - c.setBorder(BernsteinBorders.getMenuBarBorder()); - ((JMenuBar) c).setBorderPainted(true); - } - } - - public void paint(Graphics g, JComponent c) { - BernsteinUtils.fillComponent(g, c); - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinPanelUI.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinPanelUI.java deleted file mode 100644 index 53af64640..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinPanelUI.java +++ /dev/null @@ -1,53 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.BasePanelUI; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class BernsteinPanelUI extends BasePanelUI { - - private static BernsteinPanelUI panelUI = null; - - public static ComponentUI createUI(JComponent c) { - if (panelUI == null) { - panelUI = new BernsteinPanelUI(); - } - return panelUI; - } - - public void update(Graphics g, JComponent c) { - if (c.isOpaque() && c.getBackground() instanceof ColorUIResource && c.getClientProperty("backgroundTexture") == null) { - BernsteinUtils.fillComponent(g, c); - } else { - super.update(g, c); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinRadioButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinRadioButtonUI.java deleted file mode 100644 index dc25bb998..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinRadioButtonUI.java +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseRadioButtonUI; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class BernsteinRadioButtonUI extends BaseRadioButtonUI { - - private static BernsteinRadioButtonUI radioButtonUI = null; - - public static ComponentUI createUI(JComponent c) { - if (radioButtonUI == null) { - radioButtonUI = new BernsteinRadioButtonUI(); - } - return radioButtonUI; - } - - public void paintBackground(Graphics g, JComponent c) { - if (c.isOpaque()) { - if ((c.getBackground().equals(AbstractLookAndFeel.getBackgroundColor())) && (c.getBackground() instanceof ColorUIResource)) { - BernsteinUtils.fillComponent(g, c); - } else { - g.setColor(c.getBackground()); - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinRootPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinRootPaneUI.java deleted file mode 100644 index 4249c7877..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinRootPaneUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.BaseRootPaneUI; -import com.jtattoo.plaf.BaseTitlePane; -import javax.swing.JComponent; -import javax.swing.JRootPane; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class BernsteinRootPaneUI extends BaseRootPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new BernsteinRootPaneUI(); - } - - public BaseTitlePane createTitlePane(JRootPane root) { - return new BernsteinTitlePane(root, this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinScrollPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinScrollPaneUI.java deleted file mode 100644 index 3ecea48d6..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinScrollPaneUI.java +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.BaseScrollPaneUI; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class BernsteinScrollPaneUI extends BaseScrollPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new BernsteinScrollPaneUI(); - } - - public void installDefaults(JScrollPane p) { - super.installDefaults(p); - p.getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinSliderUI.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinSliderUI.java deleted file mode 100644 index 0d416c7ad..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinSliderUI.java +++ /dev/null @@ -1,62 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.BaseSliderUI; -import java.awt.Component; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.JSlider; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class BernsteinSliderUI extends BaseSliderUI { - - public BernsteinSliderUI(JSlider slider) { - super(slider); - } - - public static ComponentUI createUI(JComponent c) { - return new BernsteinSliderUI((JSlider) c); - } - - public void paintBackground(Graphics g, JComponent c) { - if (c.isOpaque()) { - Component parent = c.getParent(); - if ((parent != null) && (parent.getBackground() instanceof ColorUIResource)) { - BernsteinUtils.fillComponent(g, c); - } else { - if (parent != null) { - g.setColor(parent.getBackground()); - } else { - g.setColor(c.getBackground()); - } - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinSplitPaneDivider.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinSplitPaneDivider.java deleted file mode 100644 index 69bf3cf42..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinSplitPaneDivider.java +++ /dev/null @@ -1,42 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.BaseSplitPaneDivider; -import java.awt.Graphics; - -/** - * @author Michael Hagen - */ -public class BernsteinSplitPaneDivider extends BaseSplitPaneDivider { - - public BernsteinSplitPaneDivider(BernsteinSplitPaneUI ui) { - super(ui); - } - - public void paint(Graphics g) { - BernsteinUtils.fillComponent(g, this); - paintComponents(g); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinSplitPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinSplitPaneUI.java deleted file mode 100644 index 2428978ef..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinSplitPaneUI.java +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.BaseSplitPaneUI; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSplitPaneDivider; - -/** - * @author Michael Hagen - */ -public class BernsteinSplitPaneUI extends BaseSplitPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new BernsteinSplitPaneUI(); - } - - public BasicSplitPaneDivider createDefaultDivider() { - return new BernsteinSplitPaneDivider(this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinTabbedPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinTabbedPaneUI.java deleted file mode 100644 index 7f31ec9d0..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinTabbedPaneUI.java +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.BaseTabbedPaneUI; -import java.awt.Color; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class BernsteinTabbedPaneUI extends BaseTabbedPaneUI { - - private static Color SEP_COLORS[] = { - new Color(229, 187, 0), - new Color(254, 240, 0), - new Color(251, 232, 0), - new Color(247, 225, 0), - new Color(243, 216, 0), - new Color(229, 187, 0),}; - - public static ComponentUI createUI(JComponent c) { - return new BernsteinTabbedPaneUI(); - } - - public void installDefaults() { - super.installDefaults(); - tabAreaInsets.bottom = 6; - } - - protected Color[] getContentBorderColors(int tabPlacement) { - return SEP_COLORS; - } - -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinTitlePane.java deleted file mode 100644 index 698d3ed90..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinTitlePane.java +++ /dev/null @@ -1,66 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JRootPane; - -/** - * @author Michael Hagen - */ -public class BernsteinTitlePane extends BaseTitlePane { - - public BernsteinTitlePane(JRootPane root, BaseRootPaneUI ui) { - super(root, ui); - } - - public void paintBackground(Graphics g) { - if (backgroundImage != null) { - g.drawImage(backgroundImage, 0, 0, null); - } else { - BernsteinUtils.fillComponent(g, this); - } - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha; - if (backgroundImage != null) { - alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alphaValue); - } else { - alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - } - g2D.setComposite(alpha); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getDefaultColors(), 0, 0, getWidth(), getHeight()); - g2D.setComposite(composite); - } - - public void paintBorder(Graphics g) { - if (isActive()) { - g.setColor(AbstractLookAndFeel.getTheme().getWindowBorderColor()); - } else { - g.setColor(AbstractLookAndFeel.getTheme().getWindowInactiveBorderColor()); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinToggleButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinToggleButtonUI.java deleted file mode 100644 index bd4491914..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinToggleButtonUI.java +++ /dev/null @@ -1,41 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class BernsteinToggleButtonUI extends BaseToggleButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new BernsteinToggleButtonUI(); - } - -} - - diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinToolBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinToolBarUI.java deleted file mode 100644 index 5f958c7a0..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinToolBarUI.java +++ /dev/null @@ -1,56 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.AbstractToolBarUI; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class BernsteinToolBarUI extends AbstractToolBarUI { - - public static ComponentUI createUI(JComponent c) { - return new BernsteinToolBarUI(); - } - - public Border getRolloverBorder() { - return BernsteinBorders.getRolloverToolButtonBorder(); - } - - public Border getNonRolloverBorder() { - return BernsteinBorders.getToolButtonBorder(); - } - - public boolean isButtonOpaque() { - return true; - } - - public void paint(Graphics g, JComponent c) { - BernsteinUtils.fillComponent(g, c); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinUtils.java b/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinUtils.java deleted file mode 100644 index d6236c075..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/bernstein/BernsteinUtils.java +++ /dev/null @@ -1,62 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.bernstein; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class BernsteinUtils { - - private static final Icon BG_IMAGE = new LazyImageIcon("bernstein/icons/background.jpg"); - private static final int IMAGE_WIDTH = BG_IMAGE.getIconWidth(); - private static final int IMAGE_HEIGHT = BG_IMAGE.getIconHeight(); - - private BernsteinUtils() { - } - - public static void fillComponent(Graphics g, Component c) { - if (AbstractLookAndFeel.getTheme().isBackgroundPatternOn()) { - int w = c.getWidth(); - int h = c.getHeight(); - Point p = JTattooUtilities.getRelLocation(c); - int y = -p.y; - while (y < h) { - int x = -p.x; - while (x < w) { - BG_IMAGE.paintIcon(c, g, x, y); - x += IMAGE_WIDTH; - } - y += IMAGE_HEIGHT; - } - } else { - g.setColor(c.getBackground()); - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/SplitterDownArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/SplitterDownArrow.gif deleted file mode 100644 index 354d6981c..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/SplitterDownArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/SplitterLeftArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/SplitterLeftArrow.gif deleted file mode 100644 index cf8ed91a4..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/SplitterLeftArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/SplitterRightArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/SplitterRightArrow.gif deleted file mode 100644 index f93d26032..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/SplitterRightArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/SplitterUpArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/SplitterUpArrow.gif deleted file mode 100644 index d6df6aa31..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/SplitterUpArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/background.jpg b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/background.jpg deleted file mode 100644 index 90cef025c..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/background.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check.gif deleted file mode 100644 index e79a61dbc..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_disabled.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_disabled.gif deleted file mode 100644 index 058de23e9..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_disabled.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_disabled_selected.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_disabled_selected.gif deleted file mode 100644 index 55b9f08b2..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_disabled_selected.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_pressed.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_pressed.gif deleted file mode 100644 index 09af09e91..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_pressed.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_rollover.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_rollover.gif deleted file mode 100644 index daf876612..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_rollover.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_rollover_selected.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_rollover_selected.gif deleted file mode 100644 index a829b8cd8..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_rollover_selected.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_selected.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_selected.gif deleted file mode 100644 index 9e8417554..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/check_selected.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio.gif deleted file mode 100644 index f49237f54..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio_disabled.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio_disabled.gif deleted file mode 100644 index f3e4171ff..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio_disabled.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio_disabled_selected.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio_disabled_selected.gif deleted file mode 100644 index 884458d5a..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio_disabled_selected.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio_rollover.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio_rollover.gif deleted file mode 100644 index be96211f6..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio_rollover.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio_rollover_selected.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio_rollover_selected.gif deleted file mode 100644 index 8568b8667..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio_rollover_selected.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio_selected.gif b/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio_selected.gif deleted file mode 100644 index 36739fa43..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/bernstein/icons/radio_selected.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastBorderFactory.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastBorderFactory.java deleted file mode 100644 index ae8721a71..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastBorderFactory.java +++ /dev/null @@ -1,122 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.AbstractBorderFactory; -import javax.swing.border.Border; - -/** - * @author Michael Hagen - */ -public class FastBorderFactory implements AbstractBorderFactory { - - private static FastBorderFactory instance = null; - - private FastBorderFactory() { - } - - public static synchronized FastBorderFactory getInstance() { - if (instance == null) { - instance = new FastBorderFactory(); - } - return instance; - } - - public Border getFocusFrameBorder() { - return FastBorders.getFocusFrameBorder(); - } - - public Border getButtonBorder() { - return FastBorders.getButtonBorder(); - } - - public Border getToggleButtonBorder() { - return FastBorders.getToggleButtonBorder(); - } - - public Border getTextBorder() { - return FastBorders.getTextBorder(); - } - - public Border getSpinnerBorder() { - return FastBorders.getSpinnerBorder(); - } - - public Border getTextFieldBorder() { - return FastBorders.getTextFieldBorder(); - } - - public Border getComboBoxBorder() { - return FastBorders.getComboBoxBorder(); - } - - public Border getTableHeaderBorder() { - return FastBorders.getTableHeaderBorder(); - } - - public Border getTableScrollPaneBorder() { - return FastBorders.getTableScrollPaneBorder(); - } - - public Border getScrollPaneBorder() { - return FastBorders.getScrollPaneBorder(); - } - - public Border getTabbedPaneBorder() { - return FastBorders.getTabbedPaneBorder(); - } - - public Border getMenuBarBorder() { - return FastBorders.getMenuBarBorder(); - } - - public Border getMenuItemBorder() { - return FastBorders.getMenuItemBorder(); - } - - public Border getPopupMenuBorder() { - return FastBorders.getPopupMenuBorder(); - } - - public Border getInternalFrameBorder() { - return FastBorders.getInternalFrameBorder(); - } - - public Border getPaletteBorder() { - return FastBorders.getPaletteBorder(); - } - - public Border getToolBarBorder() { - return FastBorders.getToolBarBorder(); - } - - public Border getProgressBarBorder() { - return FastBorders.getProgressBarBorder(); - } - - public Border getDesktopIconBorder() { - return FastBorders.getDesktopIconBorder(); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastBorders.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastBorders.java deleted file mode 100644 index 45c45760d..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastBorders.java +++ /dev/null @@ -1,254 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class FastBorders extends BaseBorders { - -//------------------------------------------------------------------------------------ -// Lazy access methods -//------------------------------------------------------------------------------------ - public static Border getButtonBorder() { - if (buttonBorder == null) { - buttonBorder = new ButtonBorder(); - } - return buttonBorder; - } - - public static Border getToggleButtonBorder() { - return getButtonBorder(); - } - - public static Border getToolButtonBorder() { - if (toolButtonBorder == null) { - toolButtonBorder = new ToolButtonBorder(); - } - return toolButtonBorder; - } - - public static Border getRolloverToolButtonBorder() { - if (rolloverToolButtonBorder == null) { - rolloverToolButtonBorder = new RolloverToolButtonBorder(); - } - return rolloverToolButtonBorder; - } - - public static Border getInternalFrameBorder() { - if (internalFrameBorder == null) { - internalFrameBorder = new InternalFrameBorder(); - } - return internalFrameBorder; - } - -//------------------------------------------------------------------------------------ -// Implementation of border classes -//------------------------------------------------------------------------------------ - public static class ButtonBorder implements Border, UIResource { - - private static final Color defaultFrameColor = new Color(0, 64, 255); - private static final Insets insets = new Insets(4, 8, 4, 8); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - Color frameColor = ColorHelper.darker(button.getBackground(), 30); - if (model.isEnabled()) { - if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - g.setColor(frameColor); - g.drawRect(x, y, w - 1, h - 1); - } else { - g.setColor(frameColor); - g.drawRect(x, y, w - 1, h - 1); - g.setColor(ColorHelper.brighter(button.getBackground(), 40)); - g.drawLine(x + 1, y + 1, x + w - 2, y + 1); - g.drawLine(x + 1, y + 1, x + 1, y + h - 2); - } - if (c instanceof JButton) { - JButton b = (JButton) c; - if (b.getRootPane() != null && b.equals(b.getRootPane().getDefaultButton())) { - g.setColor(defaultFrameColor); - g.drawRect(x, y, w - 1, h - 1); - } - } - } else { - g.setColor(AbstractLookAndFeel.getDisabledForegroundColor()); - g.drawRect(x, y, w - 1, h - 1); - } - } - - public Insets getBorderInsets(Component c) { - return insets; - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class ButtonBorder - -//------------------------------------------------------------------------------ - public static class ToolButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - Color hiColor = ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 90); - Color loColor = AbstractLookAndFeel.getFrameColor(); - if (model.isEnabled()) { - if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - g.setColor(loColor); - g.drawRect(x, y, w - 1, h - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.15f); - g2D.setComposite(alpha); - g.setColor(Color.black); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(composite); - } else { - JTattooUtilities.draw3DBorder(g, hiColor, loColor, 0, 0, w, h); - } - } - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class ToolButtonBorder - -//------------------------------------------------------------------------------ - public static class RolloverToolButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - Color loColor = AbstractLookAndFeel.getFrameColor(); - if (model.isEnabled()) { - if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - g.setColor(loColor); - g.drawRect(x, y, w - 1, h - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.15f); - g2D.setComposite(alpha); - g.setColor(Color.black); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(composite); - } else if (model.isRollover()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - g.setColor(loColor); - g.drawRect(x, y, w - 1, h - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - g.setColor(Color.white); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(composite); - } - } - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class RolloverToolButtonBorder - -//------------------------------------------------------------------------------ - public static class InternalFrameBorder extends BaseInternalFrameBorder { - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - boolean active = isActive(c); - boolean resizable = isResizable(c); - Color frameColor = AbstractLookAndFeel.getFrameColor(); - Color borderColor = AbstractLookAndFeel.getWindowInactiveBorderColor(); - if (active) { - borderColor = AbstractLookAndFeel.getWindowBorderColor(); - } - Color cHi = ColorHelper.brighter(frameColor, 40); - Color cLo = frameColor; - if (!resizable) { - JTattooUtilities.draw3DBorder(g, cHi, cLo, x, y, w, h); - g.setColor(borderColor); - for (int i = 1; i < dw; i++) { - g.drawRect(i, i, w - (2 * i) - 1, h - (2 * i) - 1); - } - return; - } - JTattooUtilities.draw3DBorder(g, cHi, cLo, x, y, w, h); - cHi = ColorHelper.brighter(borderColor, 40); - cLo = ColorHelper.darker(borderColor, 20); - JTattooUtilities.draw3DBorder(g, cHi, cLo, x + 1, y + 1, w - 2, h - 2); - - g.setColor(borderColor); - g.drawRect(x + 2, y + 2, w - 5, h - 5); - g.drawRect(x + 3, y + 3, w - 7, h - 7); - JTattooUtilities.draw3DBorder(g, ColorHelper.darker(borderColor, 5), ColorHelper.brighter(borderColor, 30), x + 4, y + 4, w - 8, h - 8); - } - } // class InternalFrameBorder - -} // class FastBorders - diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastButtonUI.java deleted file mode 100644 index 3b3a10431..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastButtonUI.java +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class FastButtonUI extends BaseButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new FastButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - if (b.isContentAreaFilled() && !(b.getParent() instanceof JMenuBar)) { - Color backColor = b.getBackground(); - ButtonModel model = b.getModel(); - if (model.isEnabled()) { - if (model.isPressed() && model.isArmed()) { - backColor = ColorHelper.darker(backColor, 30); - } - } else { - backColor = ColorHelper.brighter(AbstractLookAndFeel.getDisabledForegroundColor(), 80); - } - g.setColor(backColor); - g.fillRect(0, 0, b.getWidth(), b.getHeight()); - } - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastDefaultTheme.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastDefaultTheme.java deleted file mode 100644 index ba898d056..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastDefaultTheme.java +++ /dev/null @@ -1,100 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.AbstractTheme; -import com.jtattoo.plaf.ColorHelper; -import java.awt.Color; -import javax.swing.plaf.ColorUIResource; - -/** - * @author Michael Hagen - */ -public class FastDefaultTheme extends AbstractTheme { - - public FastDefaultTheme() { - super(); - // Setup theme with defaults - setUpColor(); - // Overwrite defaults with user props - loadProperties(); - // Setup the color arrays - setUpColorArrs(); - } - - public String getPropertyFileName() { - return "FastTheme.properties"; - } - - public void setUpColor() { - super.setUpColor(); - // Defaults for FastLookAndFeel - backgroundColor = new ColorUIResource(244, 244, 244); - backgroundColorLight = new ColorUIResource(255, 255, 255); - backgroundColorDark = new ColorUIResource(232, 232, 232); - alterBackgroundColor = new ColorUIResource(232, 232, 232); - selectionBackgroundColor = new ColorUIResource(210, 210, 210); - frameColor = gray; - focusColor = new ColorUIResource(160, 160, 200); - focusCellColor = new ColorUIResource(160, 160, 200); - buttonBackgroundColor = extraLightGray; - controlBackgroundColor = new ColorUIResource(220, 220, 220); - - windowTitleBackgroundColor = new ColorUIResource(210, 210, 210); - windowBorderColor = new ColorUIResource(210, 210, 210); - - windowInactiveTitleBackgroundColor = new ColorUIResource(230, 230, 230); - windowInactiveBorderColor = new ColorUIResource(230, 230, 230); - - menuBackgroundColor = new ColorUIResource(240, 240, 240); - menuSelectionBackgroundColor = lightGray; - - toolbarBackgroundColor = new ColorUIResource(240, 240, 240); - - tabAreaBackgroundColor = backgroundColor; - desktopColor = new ColorUIResource(128, 128, 148); - } - - public void setUpColorArrs() { - super.setUpColorArrs(); - // Generate the color arrays - DEFAULT_COLORS = ColorHelper.createColorArr(controlBackgroundColor, controlBackgroundColor, 2); - HIDEFAULT_COLORS = ColorHelper.createColorArr(backgroundColor, backgroundColor, 2); - - ACTIVE_COLORS = DEFAULT_COLORS; - INACTIVE_COLORS = HIDEFAULT_COLORS; - - ROLLOVER_COLORS = ColorHelper.createColorArr(buttonBackgroundColor, buttonBackgroundColor, 2); - SELECTED_COLORS = ColorHelper.createColorArr(backgroundColor, backgroundColor, 2); - PRESSED_COLORS = ColorHelper.createColorArr(controlColorDark, controlColorDark, 2); - DISABLED_COLORS = ColorHelper.createColorArr(controlColorLight, controlColorLight, 2); - - BUTTON_COLORS = ColorHelper.createColorArr(buttonBackgroundColor, buttonBackgroundColor, 2); - COL_HEADER_COLORS = ColorHelper.createColorArr(new Color(248, 248, 248), new Color(248, 248, 248), 2); - CHECKBOX_COLORS = COL_HEADER_COLORS; - - TAB_COLORS = DEFAULT_COLORS; - - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastIconFactory.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastIconFactory.java deleted file mode 100644 index f60b612b5..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastIconFactory.java +++ /dev/null @@ -1,213 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.AbstractIconFactory; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class FastIconFactory implements AbstractIconFactory { - - private static FastIconFactory instance = null; - - private FastIconFactory() { - } - - public static synchronized FastIconFactory getInstance() { - if (instance == null) { - instance = new FastIconFactory(); - } - return instance; - } - - public Icon getOptionPaneErrorIcon() { - return FastIcons.getOptionPaneErrorIcon(); - } - - public Icon getOptionPaneWarningIcon() { - return FastIcons.getOptionPaneWarningIcon(); - } - - public Icon getOptionPaneInformationIcon() { - return FastIcons.getOptionPaneInformationIcon(); - } - - public Icon getOptionPaneQuestionIcon() { - return FastIcons.getOptionPaneQuestionIcon(); - } - - public Icon getFileChooserDetailViewIcon() { - return FastIcons.getFileChooserDetailViewIcon(); - } - - public Icon getFileChooserHomeFolderIcon() { - return FastIcons.getFileChooserHomeFolderIcon(); - } - - public Icon getFileChooserListViewIcon() { - return FastIcons.getFileChooserListViewIcon(); - } - - public Icon getFileChooserNewFolderIcon() { - return FastIcons.getFileChooserNewFolderIcon(); - } - - public Icon getFileChooserUpFolderIcon() { - return FastIcons.getFileChooserUpFolderIcon(); - } - - public Icon getMenuIcon() { - return FastIcons.getMenuIcon(); - } - - public Icon getIconIcon() { - return FastIcons.getIconIcon(); - } - - public Icon getMaxIcon() { - return FastIcons.getMaxIcon(); - } - - public Icon getMinIcon() { - return FastIcons.getMinIcon(); - } - - public Icon getCloseIcon() { - return FastIcons.getCloseIcon(); - } - - public Icon getPaletteCloseIcon() { - return FastIcons.getPaletteCloseIcon(); - } - - public Icon getRadioButtonIcon() { - return FastIcons.getRadioButtonIcon(); - } - - public Icon getCheckBoxIcon() { - return FastIcons.getCheckBoxIcon(); - } - - public Icon getComboBoxIcon() { - return FastIcons.getComboBoxIcon(); - } - - public Icon getTreeComputerIcon() { - return FastIcons.getTreeComputerIcon(); - } - - public Icon getTreeFloppyDriveIcon() { - return FastIcons.getTreeFloppyDriveIcon(); - } - - public Icon getTreeHardDriveIcon() { - return FastIcons.getTreeHardDriveIcon(); - } - - public Icon getTreeFolderIcon() { - return FastIcons.getTreeFolderIcon(); - } - - public Icon getTreeLeafIcon() { - return FastIcons.getTreeLeafIcon(); - } - - public Icon getTreeCollapsedIcon() { - return FastIcons.getTreeControlIcon(true); - } - - public Icon getTreeExpandedIcon() { - return FastIcons.getTreeControlIcon(false); - } - - public Icon getMenuArrowIcon() { - return FastIcons.getMenuArrowIcon(); - } - - public Icon getMenuCheckBoxIcon() { - return FastIcons.getMenuCheckBoxIcon(); - } - - public Icon getMenuRadioButtonIcon() { - return FastIcons.getMenuRadioButtonIcon(); - } - - public Icon getUpArrowIcon() { - return FastIcons.getUpArrowIcon(); - } - - public Icon getDownArrowIcon() { - return FastIcons.getDownArrowIcon(); - } - - public Icon getLeftArrowIcon() { - return FastIcons.getLeftArrowIcon(); - } - - public Icon getRightArrowIcon() { - return FastIcons.getRightArrowIcon(); - } - - public Icon getSplitterDownArrowIcon() { - return FastIcons.getSplitterDownArrowIcon(); - } - - public Icon getSplitterHorBumpIcon() { - return FastIcons.getSplitterHorBumpIcon(); - } - - public Icon getSplitterLeftArrowIcon() { - return FastIcons.getSplitterLeftArrowIcon(); - } - - public Icon getSplitterRightArrowIcon() { - return FastIcons.getSplitterRightArrowIcon(); - } - - public Icon getSplitterUpArrowIcon() { - return FastIcons.getSplitterUpArrowIcon(); - } - - public Icon getSplitterVerBumpIcon() { - return FastIcons.getSplitterVerBumpIcon(); - } - - public Icon getThumbHorIcon() { - return FastIcons.getThumbHorIcon(); - } - - public Icon getThumbVerIcon() { - return FastIcons.getThumbVerIcon(); - } - - public Icon getThumbHorIconRollover() { - return FastIcons.getThumbHorIconRollover(); - } - - public Icon getThumbVerIconRollover() { - return FastIcons.getThumbVerIconRollover(); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastIcons.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastIcons.java deleted file mode 100644 index dc8d20ae4..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastIcons.java +++ /dev/null @@ -1,33 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.BaseIcons; - -/** - * @author Michael Hagen - */ -public class FastIcons extends BaseIcons { - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastInternalFrameTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastInternalFrameTitlePane.java deleted file mode 100644 index fddc03cb6..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastInternalFrameTitlePane.java +++ /dev/null @@ -1,56 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.*; -import java.awt.Graphics; -import javax.swing.JInternalFrame; - -/** - * @author Michael Hagen - */ -public class FastInternalFrameTitlePane extends BaseInternalFrameTitlePane { - - public FastInternalFrameTitlePane(JInternalFrame f) { - super(f); - } - - public void paintPalette(Graphics g) { - if (JTattooUtilities.isFrameActive(this)) { - g.setColor(AbstractLookAndFeel.getWindowTitleBackgroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleBackgroundColor()); - } - g.fillRect(0, 0, getWidth(), getHeight()); - } - - public void paintBackground(Graphics g) { - if (isActive()) { - g.setColor(AbstractLookAndFeel.getWindowTitleBackgroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleBackgroundColor()); - } - g.fillRect(0, 0, getWidth(), getHeight()); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastInternalFrameUI.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastInternalFrameUI.java deleted file mode 100644 index 116e8adad..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastInternalFrameUI.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.BaseInternalFrameUI; -import javax.swing.JComponent; -import javax.swing.JInternalFrame; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class FastInternalFrameUI extends BaseInternalFrameUI { - - public FastInternalFrameUI(JInternalFrame b) { - super(b); - } - - public static ComponentUI createUI(JComponent c) { - return new FastInternalFrameUI((JInternalFrame) c); - } - - protected JComponent createNorthPane(JInternalFrame w) { - titlePane = new FastInternalFrameTitlePane(w); - return titlePane; - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastLookAndFeel.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastLookAndFeel.java deleted file mode 100644 index 744c56d48..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastLookAndFeel.java +++ /dev/null @@ -1,309 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.*; -import java.util.*; -import javax.swing.UIDefaults; -import javax.swing.plaf.basic.BasicPopupMenuUI; -import javax.swing.plaf.basic.BasicProgressBarUI; - -/** - * @author Michael Hagen - */ -public class FastLookAndFeel extends AbstractLookAndFeel { - - private static final String darkBlue = "0 32 96"; - private static final String lightBlue = "160 160 200"; - private static final String extraLightBlue = "210 210 240"; - private static final String superLightBlue = "230 230 255"; - private static final String darkGreen = "0 76 57"; - private static final String lightGreen = "172 191 186"; - private static final String extraLightGreen = "218 226 223"; - private static final String superLightGreen = "228 234 232"; - - private static FastDefaultTheme myTheme = null; - - private static final ArrayList themesList = new ArrayList(); - private static final HashMap themesMap = new HashMap(); - private static final Properties defaultProps = new Properties(); - private static final Properties smallFontProps = new Properties(); - private static final Properties largeFontProps = new Properties(); - private static final Properties giantFontProps = new Properties(); - private static final Properties blueProps = new Properties(); - private static final Properties blueSmallFontProps = new Properties(); - private static final Properties blueLargeFontProps = new Properties(); - private static final Properties blueGiantFontProps = new Properties(); - private static final Properties greenProps = new Properties(); - private static final Properties greenSmallFontProps = new Properties(); - private static final Properties greenLargeFontProps = new Properties(); - private static final Properties greenGiantFontProps = new Properties(); - - - static { - smallFontProps.setProperty("controlTextFont", "Dialog 10"); - smallFontProps.setProperty("systemTextFont", "Dialog 10"); - smallFontProps.setProperty("userTextFont", "Dialog 10"); - smallFontProps.setProperty("menuTextFont", "Dialog 10"); - smallFontProps.setProperty("windowTitleFont", "Dialog bold 10"); - smallFontProps.setProperty("subTextFont", "Dialog 8"); - - largeFontProps.setProperty("controlTextFont", "Dialog 14"); - largeFontProps.setProperty("systemTextFont", "Dialog 14"); - largeFontProps.setProperty("userTextFont", "Dialog 14"); - largeFontProps.setProperty("menuTextFont", "Dialog 14"); - largeFontProps.setProperty("windowTitleFont", "Dialog bold 14"); - largeFontProps.setProperty("subTextFont", "Dialog 12"); - - giantFontProps.setProperty("controlTextFont", "Dialog 18"); - giantFontProps.setProperty("systemTextFont", "Dialog 18"); - giantFontProps.setProperty("userTextFont", "Dialog 18"); - giantFontProps.setProperty("menuTextFont", "Dialog 18"); - giantFontProps.setProperty("windowTitleFont", "Dialog 18"); - giantFontProps.setProperty("subTextFont", "Dialog 16"); - - blueProps.setProperty("selectionBackgroundColor", extraLightBlue); - blueProps.setProperty("focusCellColor", darkBlue); - blueProps.setProperty("buttonBackgroundColor", superLightBlue); - blueProps.setProperty("controlBackgroundColor", superLightBlue); - blueProps.setProperty("windowTitleBackgroundColor", lightBlue); - blueProps.setProperty("windowTitleColorLight", superLightBlue); - blueProps.setProperty("windowTitleColorDark", extraLightBlue); - blueProps.setProperty("windowBorderColor", lightBlue); - blueProps.setProperty("windowInactiveTitleBackgroundColor", extraLightBlue); - blueProps.setProperty("windowInactiveBorderColor", extraLightBlue); - blueProps.setProperty("menuBackgroundColor", superLightBlue); - blueProps.setProperty("menuSelectionBackgroundColor", lightBlue); - blueProps.setProperty("toolbarBackgroundColor", "244 244 244"); - - greenProps.setProperty("selectionBackgroundColor", lightGreen); - greenProps.setProperty("focusCellColor", darkGreen); - greenProps.setProperty("buttonBackgroundColor", lightGreen); - greenProps.setProperty("controlBackgroundColor", extraLightGreen); - greenProps.setProperty("windowTitleBackgroundColor", lightGreen); - greenProps.setProperty("windowTitleColorLight", extraLightGreen); - greenProps.setProperty("windowTitleColorDark", lightGreen); - greenProps.setProperty("windowBorderColor", lightGreen); - greenProps.setProperty("windowInactiveTitleBackgroundColor", extraLightGreen); - greenProps.setProperty("windowInactiveBorderColor", extraLightGreen); - greenProps.setProperty("menuBackgroundColor", superLightGreen); - greenProps.setProperty("menuSelectionBackgroundColor", lightGreen); - greenProps.setProperty("toolbarBackgroundColor", "244 244 244"); - - String key; - String value; - Iterator iter = smallFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = smallFontProps.getProperty(key); - blueSmallFontProps.setProperty(key, value); - greenSmallFontProps.setProperty(key, value); - } - iter = largeFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = largeFontProps.getProperty(key); - blueLargeFontProps.setProperty(key, value); - greenLargeFontProps.setProperty(key, value); - } - iter = giantFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = giantFontProps.getProperty(key); - blueGiantFontProps.setProperty(key, value); - greenGiantFontProps.setProperty(key, value); - } - - iter = blueProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = blueProps.getProperty(key); - blueSmallFontProps.setProperty(key, value); - blueLargeFontProps.setProperty(key, value); - blueGiantFontProps.setProperty(key, value); - } - iter = greenProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = greenProps.getProperty(key); - greenSmallFontProps.setProperty(key, value); - greenLargeFontProps.setProperty(key, value); - greenGiantFontProps.setProperty(key, value); - } - - themesList.add("Default"); - themesList.add("Small-Font"); - themesList.add("Large-Font"); - themesList.add("Giant-Font"); - themesList.add("Blue"); - themesList.add("Blue-Small-Font"); - themesList.add("Blue-Large-Font"); - themesList.add("Blue-Giant-Font"); - themesList.add("Green"); - themesList.add("Green-Small-Font"); - themesList.add("Green-Large-Font"); - themesList.add("Green-Giant-Font"); - - themesMap.put("Default", defaultProps); - themesMap.put("Small-Font", smallFontProps); - themesMap.put("Large-Font", largeFontProps); - themesMap.put("Giant-Font", giantFontProps); - themesMap.put("Blue", blueProps); - themesMap.put("Blue-Small-Font", blueSmallFontProps); - themesMap.put("Blue-Large-Font", blueLargeFontProps); - themesMap.put("Blue-Giant-Font", blueGiantFontProps); - themesMap.put("Green", greenProps); - themesMap.put("Green-Small-Font", greenSmallFontProps); - themesMap.put("Green-Large-Font", greenLargeFontProps); - themesMap.put("Green-Giant-Font", greenGiantFontProps); - } - - public static java.util.List getThemes() { - return themesList; - } - - public static Properties getThemeProperties(String name) { - return ((Properties) themesMap.get(name)); - } - - public static void setTheme(String name) { - setTheme((Properties) themesMap.get(name)); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - - public static void setTheme(String name, String licenseKey, String logoString) { - Properties props = (Properties) themesMap.get(name); - if (props != null) { - props.put("licenseKey", licenseKey); - props.put("logoString", logoString); - setTheme(props); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - } - - public static void setTheme(Properties themesProps) { - if (myTheme == null) { - myTheme = new FastDefaultTheme(); - } - if ((myTheme != null) && (themesProps != null)) { - myTheme.setUpColor(); - myTheme.setProperties(themesProps); - myTheme.setUpColorArrs(); - AbstractLookAndFeel.setTheme(myTheme); - } - } - - public static void setCurrentTheme(Properties themesProps) { - setTheme(themesProps); - } - - public String getName() { - return "Fast"; - } - - public String getID() { - return "Fast"; - } - - public String getDescription() { - return "The Fast Look and Feel"; - } - - public boolean isNativeLookAndFeel() { - return false; - } - - public boolean isSupportedLookAndFeel() { - return true; - } - - public AbstractBorderFactory getBorderFactory() { - return FastBorderFactory.getInstance(); - } - - public AbstractIconFactory getIconFactory() { - return FastIconFactory.getInstance(); - } - - protected void createDefaultTheme() { - if (myTheme == null) { - myTheme = new FastDefaultTheme(); - } - setTheme(myTheme); - } - - protected void initClassDefaults(UIDefaults table) { - super.initClassDefaults(table); - Object[] uiDefaults = { - "PopupMenuUI", BasicPopupMenuUI.class.getName(), - // BaseLookAndFeel classes - "LabelUI", BaseLabelUI.class.getName(), - "SeparatorUI", BaseSeparatorUI.class.getName(), - "TextFieldUI", BaseTextFieldUI.class.getName(), - "TextAreaUI", BaseTextAreaUI.class.getName(), - "EditorPaneUI", BaseEditorPaneUI.class.getName(), - "PasswordFieldUI", BasePasswordFieldUI.class.getName(), - "ComboBoxUI", BaseComboBoxUI.class.getName(), - "CheckBoxUI", BaseCheckBoxUI.class.getName(), - "RadioButtonUI", BaseRadioButtonUI.class.getName(), - "ToolTipUI", BaseToolTipUI.class.getName(), - "TreeUI", BaseTreeUI.class.getName(), - "TableUI", BaseTableUI.class.getName(), - "PanelUI", BasePanelUI.class.getName(), - "ScrollPaneUI", BaseScrollPaneUI.class.getName(), - "ProgressBarUI", BasicProgressBarUI.class.getName(), - "FileChooserUI", BaseFileChooserUI.class.getName(), - "MenuUI", BaseMenuUI.class.getName(), - "MenuItemUI", BaseMenuItemUI.class.getName(), - "CheckBoxMenuItemUI", BaseCheckBoxMenuItemUI.class.getName(), - "RadioButtonMenuItemUI", BaseRadioButtonMenuItemUI.class.getName(), - "PopupMenuSeparatorUI", BaseSeparatorUI.class.getName(), - "DesktopPaneUI", BaseDesktopPaneUI.class.getName(), - - // FastLookAndFeel classes - "ButtonUI", FastButtonUI.class.getName(), - "ToggleButtonUI", FastToggleButtonUI.class.getName(), - "ScrollBarUI", FastScrollBarUI.class.getName(), - "SliderUI", FastSliderUI.class.getName(), - "TabbedPaneUI", FastTabbedPaneUI.class.getName(), - "SplitPaneUI", FastSplitPaneUI.class.getName(), - "ToolBarUI", FastToolBarUI.class.getName(), - "InternalFrameUI", FastInternalFrameUI.class.getName(), - "RootPaneUI", FastRootPaneUI.class.getName(),}; - table.putDefaults(uiDefaults); - if (JTattooUtilities.getJavaVersion() >= 1.5) { - table.put("FormattedTextFieldUI", BaseFormattedTextFieldUI.class.getName()); - table.put("SpinnerUI", BaseSpinnerUI.class.getName()); - } - } - - protected void initComponentDefaults(UIDefaults table) { - super.initComponentDefaults(table); - table.put("SplitPane.centerOneTouchButtons", Boolean.FALSE); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastRootPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastRootPaneUI.java deleted file mode 100644 index 5378a4af3..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastRootPaneUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.BaseRootPaneUI; -import com.jtattoo.plaf.BaseTitlePane; -import javax.swing.JComponent; -import javax.swing.JRootPane; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class FastRootPaneUI extends BaseRootPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new FastRootPaneUI(); - } - - public BaseTitlePane createTitlePane(JRootPane root) { - return new FastTitlePane(root, this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastScrollBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastScrollBarUI.java deleted file mode 100644 index 3cf0ebac3..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastScrollBarUI.java +++ /dev/null @@ -1,76 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class FastScrollBarUI extends BaseScrollBarUI { - - public static ComponentUI createUI(JComponent c) { - return new FastScrollBarUI(); - } - - protected JButton createDecreaseButton(int orientation) { - return new FastScrollButton(orientation, scrollBarWidth); - } - - protected JButton createIncreaseButton(int orientation) { - return new FastScrollButton(orientation, scrollBarWidth); - } - - protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) { - g.setColor(AbstractLookAndFeel.getControlColorLight()); - g.fillRect(trackBounds.x, trackBounds.y, trackBounds.width, trackBounds.height); - } - - protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { - if (!c.isEnabled()) { - return; - } - - g.translate(thumbBounds.x, thumbBounds.y); - - Color backColor = AbstractLookAndFeel.getTheme().getControlBackgroundColor(); - if (!JTattooUtilities.isActive(c)) { - backColor = ColorHelper.brighter(backColor, 50); - } - Color frameColorHi = ColorHelper.brighter(backColor, 40); - Color frameColorLo = ColorHelper.darker(backColor, 30); - g.setColor(backColor); - g.fillRect(1, 1, thumbBounds.width - 1, thumbBounds.height - 1); - g.setColor(frameColorLo); - g.drawRect(0, 0, thumbBounds.width - 1, thumbBounds.height - 1); - g.setColor(frameColorHi); - g.drawLine(1, 1, thumbBounds.width - 2, 1); - g.drawLine(1, 1, 1, thumbBounds.height - 2); - g.translate(-thumbBounds.x, -thumbBounds.y); - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastScrollButton.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastScrollButton.java deleted file mode 100644 index 16182cdbd..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastScrollButton.java +++ /dev/null @@ -1,85 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.Icon; - -public class FastScrollButton extends BaseScrollButton { - - public FastScrollButton(int direction, int width) { - super(direction, width); - } - - public void paint(Graphics g) { - boolean isPressed = getModel().isPressed(); - - int width = getWidth(); - int height = getHeight(); - - Color backColor = AbstractLookAndFeel.getTheme().getControlBackgroundColor(); - if (!JTattooUtilities.isActive(this)) { - backColor = ColorHelper.brighter(backColor, 50); - } - if (isPressed) { - backColor = ColorHelper.darker(backColor, 10); - } - Color hiColor = ColorHelper.brighter(backColor, 40); - Color loColor = ColorHelper.darker(backColor, 30); - g.setColor(backColor); - g.fillRect(0, 0, width, height); - - if (getDirection() == NORTH) { - Icon upArrow = BaseIcons.getUpArrowIcon(); - int x = (width / 2) - (upArrow.getIconWidth() / 2); - int y = (height / 2) - (upArrow.getIconHeight() / 2) - 1; - upArrow.paintIcon(this, g, x, y); - } else if (getDirection() == SOUTH) { - Icon downArrow = BaseIcons.getDownArrowIcon(); - int x = (width / 2) - (downArrow.getIconWidth() / 2); - int y = (height / 2) - (downArrow.getIconHeight() / 2); - downArrow.paintIcon(this, g, x, y); - } else if (getDirection() == WEST) { - Icon leftArrow = BaseIcons.getLeftArrowIcon(); - int x = (width / 2) - (leftArrow.getIconWidth() / 2) - 1; - int y = (height / 2) - (leftArrow.getIconHeight() / 2); - leftArrow.paintIcon(this, g, x, y); - } else { - Icon rightArrow = BaseIcons.getRightArrowIcon(); - int x = (width / 2) - (rightArrow.getIconWidth() / 2); - int y = (height / 2) - (rightArrow.getIconHeight() / 2); - rightArrow.paintIcon(this, g, x, y); - } - - JTattooUtilities.draw3DBorder(g, ColorHelper.brighter(loColor, 20), loColor, 0, 0, width, height); - if (!isPressed) { - g.setColor(hiColor); - g.drawLine(1, 1, width - 2, 1); - g.drawLine(1, 1, 1, height - 2); - } - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastSliderUI.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastSliderUI.java deleted file mode 100644 index 48cb936bd..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastSliderUI.java +++ /dev/null @@ -1,215 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class FastSliderUI extends BaseSliderUI { - - private static ThumbHorIcon thumbHorIcon = new ThumbHorIcon(); - private static ThumbVerIcon thumbVerIcon = new ThumbVerIcon(); - - public FastSliderUI(JSlider slider) { - super(slider); - } - - public static ComponentUI createUI(JComponent c) { - return new FastSliderUI((JSlider) c); - } - - public Icon getThumbHorIcon() { - return thumbHorIcon; - } - - public Icon getThumbHorIconRollover() { - return thumbHorIcon; - } - - public Icon getThumbVerIcon() { - return thumbVerIcon; - } - - public Icon getThumbVerIconRollover() { - return thumbVerIcon; - } - - public void paintTrack(Graphics g) { - boolean leftToRight = JTattooUtilities.isLeftToRight(slider); - - g.translate(trackRect.x, trackRect.y); - int overhang = 5; - int trackLeft = 0; - int trackTop = 0; - int trackRight; - int trackBottom; - - // Draw the track - if (slider.getOrientation() == JSlider.HORIZONTAL) { - trackBottom = (trackRect.height - 1) - overhang; - trackTop = trackBottom - (getTrackWidth() - 1); - trackRight = trackRect.width - 1; - } else { - if (leftToRight) { - trackLeft = (trackRect.width - overhang) - - getTrackWidth(); - trackRight = (trackRect.width - overhang) - 1; - } else { - trackLeft = overhang; - trackRight = overhang + getTrackWidth() - 1; - } - trackBottom = trackRect.height - 1; - } - - g.setColor(Color.gray); - g.drawRect(trackLeft, trackTop, (trackRight - trackLeft) - 1, (trackBottom - trackTop) - 1); - - int middleOfThumb; - int fillTop; - int fillLeft; - int fillBottom; - int fillRight; - - if (slider.getOrientation() == JSlider.HORIZONTAL) { - middleOfThumb = thumbRect.x + (thumbRect.width / 2); - middleOfThumb -= trackRect.x; // To compensate for the g.translate() - fillTop = trackTop + 1; - fillBottom = trackBottom - 2; - - if (!drawInverted()) { - fillLeft = trackLeft + 1; - fillRight = middleOfThumb; - } else { - fillLeft = middleOfThumb; - fillRight = trackRight - 2; - } -// if (slider.isEnabled()) { - g.setColor(AbstractLookAndFeel.getControlBackgroundColor()); - g.fillRect(fillLeft, fillTop, fillRight - fillLeft, fillBottom - fillTop + 1); -// } else { -// g.setColor(slider.getBackground()); -// g.fillRect(fillLeft, fillTop, fillRight - fillLeft, fillBottom - fillTop); -// } - } else { - middleOfThumb = thumbRect.y + (thumbRect.height / 2); - middleOfThumb -= trackRect.y; // To compensate for the g.translate() - fillLeft = trackLeft + 1; - fillRight = trackRight - 2; - - if (!drawInverted()) { - fillTop = middleOfThumb; - fillBottom = trackBottom - 2; - } else { - fillTop = trackTop + 1; - fillBottom = middleOfThumb; - } -// if (slider.isEnabled()) { - g.setColor(AbstractLookAndFeel.getControlBackgroundColor()); - g.fillRect(fillLeft, fillTop, fillRight - fillLeft + 1, fillBottom - fillTop + 1); -// } else { -// g.setColor(slider.getBackground()); -// g.fillRect(fillLeft, fillTop, fillRight - fillLeft + 1, fillBottom - fillTop + 1); -// } - } - - g.translate(-trackRect.x, -trackRect.y); - } - - private static class ThumbHorIcon implements Icon { - - private static final int WIDTH = 11; - private static final int HEIGHT = 18; - - public void paintIcon(Component c, Graphics g, int x, int y) { - int w = WIDTH - 1; - int h = HEIGHT - 1; - int dw = WIDTH / 2; - Color backColor = AbstractLookAndFeel.getControlBackgroundColor(); - Color loColor = AbstractLookAndFeel.getFrameColor(); - Color hiColor = ColorHelper.brighter(backColor, 40); - Polygon poly = new Polygon(); - poly.addPoint(x, y); - poly.addPoint(x + w, y); - poly.addPoint(x + w, y + h - dw); - poly.addPoint(x + dw, y + h); - poly.addPoint(x, y + h - dw); - g.setColor(backColor); - g.fillPolygon(poly); - g.setColor(loColor); - g.drawPolygon(poly); - g.setColor(hiColor); - g.drawLine(x + 1, y + 1, x + w - 1, y + 1); - g.drawLine(x + 1, y + 1, x + 1, y + h - dw); - } - - public int getIconWidth() { - return WIDTH; - } - - public int getIconHeight() { - return HEIGHT; - } - } - - private static class ThumbVerIcon implements Icon { - - private static final int WIDTH = 18; - private static final int HEIGHT = 11; - - public void paintIcon(Component c, Graphics g, int x, int y) { - int w = WIDTH - 1; - int h = HEIGHT - 1; - int dh = HEIGHT / 2; - Color backColor = AbstractLookAndFeel.getControlBackgroundColor(); - Color loColor = AbstractLookAndFeel.getFrameColor(); - Color hiColor = ColorHelper.brighter(backColor, 40); - Polygon poly = new Polygon(); - poly.addPoint(x, y); - poly.addPoint(x + w - dh, y); - poly.addPoint(x + w, y + dh); - poly.addPoint(x + w - dh, y + h); - poly.addPoint(x, y + h); - g.setColor(backColor); - g.fillPolygon(poly); - g.setColor(loColor); - g.drawPolygon(poly); - g.setColor(hiColor); - g.drawLine(x + 1, y + 1, x + w - dh, y + 1); - g.drawLine(x + 1, y + 1, x + 1, y + h - 1); - } - - public int getIconWidth() { - return WIDTH; - } - - public int getIconHeight() { - return HEIGHT; - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastSplitPaneDivider.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastSplitPaneDivider.java deleted file mode 100644 index 2bece6470..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastSplitPaneDivider.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseSplitPaneDivider; -import java.awt.Graphics; - -/** - * @author Michael Hagen - */ -public class FastSplitPaneDivider extends BaseSplitPaneDivider { - - public FastSplitPaneDivider(FastSplitPaneUI ui) { - super(ui); - } - - public void paint(Graphics g) { - g.setColor(AbstractLookAndFeel.getBackgroundColor()); - g.fillRect(0, 0, getSize().width, getSize().height); - paintComponents(g); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastSplitPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastSplitPaneUI.java deleted file mode 100644 index d7152e815..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastSplitPaneUI.java +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.BaseSplitPaneUI; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSplitPaneDivider; - -/** - * @author Michael Hagen - */ -public class FastSplitPaneUI extends BaseSplitPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new FastSplitPaneUI(); - } - - public BasicSplitPaneDivider createDefaultDivider() { - return new FastSplitPaneDivider(this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastTabbedPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastTabbedPaneUI.java deleted file mode 100644 index cde69f4d8..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastTabbedPaneUI.java +++ /dev/null @@ -1,110 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; - -/** - * author Michael Hagen - */ -public class FastTabbedPaneUI extends BaseTabbedPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new FastTabbedPaneUI(); - } - - public void installDefaults() { - super.installDefaults(); - roundedTabs = false; - tabAreaInsets = new Insets(2, 6, 2, 6); - contentBorderInsets = new Insets(0, 0, 0, 0); - } - - protected boolean hasInnerBorder() { - return true; - } - - protected Color[] getTabColors(int tabIndex, boolean isSelected, boolean isRollover) { - Color colorArr[] = AbstractLookAndFeel.getTheme().getTabColors(); - if ((tabIndex >= 0) && (tabIndex < tabPane.getTabCount())) { - Color backColor = tabPane.getBackgroundAt(tabIndex); - if ((backColor instanceof UIResource)) { - if (isSelected) { - colorArr = AbstractLookAndFeel.getTheme().getSelectedColors(); - } else { - if (JTattooUtilities.isFrameActive(tabPane)) { - colorArr = AbstractLookAndFeel.getTheme().getTabColors(); - } else { - colorArr = AbstractLookAndFeel.getTheme().getInActiveColors(); - } - } - } else { - colorArr = ColorHelper.createColorArr(backColor, backColor, 2); - } - } - return colorArr; - } - - protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) { - if (isTabOpaque() || isSelected) { - Color colorArr[] = getTabColors(tabIndex, isSelected, false); - g.setColor(colorArr[0]); - switch (tabPlacement) { - case TOP: - if (isSelected) { - g.fillRect(x + 1, y + 1, w - 1, h + 2); - } else { - g.fillRect(x + 1, y + 1, w - 1, h - 1); - } - break; - case LEFT: - if (isSelected) { - g.fillRect(x + 1, y + 1, w + 2, h - 1); - } else { - g.fillRect(x + 1, y + 1, w - 1, h - 1); - } - break; - case BOTTOM: - if (isSelected) { - g.fillRect(x + 1, y - 2, w - 1, h + 1); - } else { - g.fillRect(x + 1, y, w - 1, h - 1); - } - break; - case RIGHT: - if (isSelected) { - g.fillRect(x - 2, y + 1, w + 2, h - 1); - } else { - g.fillRect(x, y + 1, w, h - 1); - } - break; - } - } - } - -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastTitlePane.java deleted file mode 100644 index d9f67fecc..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastTitlePane.java +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.JRootPane; - -/** - * @author Michael Hagen - */ -public class FastTitlePane extends BaseTitlePane { - - public FastTitlePane(JRootPane root, BaseRootPaneUI ui) { - super(root, ui); - } - - public void paintBackground(Graphics g) { - if (isActive()) { - g.setColor(AbstractLookAndFeel.getWindowTitleBackgroundColor()); - g.fillRect(0, 0, getWidth(), getHeight()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleBackgroundColor()); - g.fillRect(0, 0, getWidth(), getHeight()); - } - } - - public void paintBorder(Graphics g) { - Color borderColor = AbstractLookAndFeel.getWindowInactiveBorderColor(); - if (isActive()) { - borderColor = AbstractLookAndFeel.getWindowBorderColor(); - } - JTattooUtilities.draw3DBorder(g, ColorHelper.brighter(borderColor, 30), ColorHelper.darker(borderColor, 5), 0, 0, getWidth(), getHeight()); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastToggleButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastToggleButtonUI.java deleted file mode 100644 index 47d3e99c8..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastToggleButtonUI.java +++ /dev/null @@ -1,56 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class FastToggleButtonUI extends BaseToggleButtonUI { - - public static ComponentUI createUI(JComponent b) { - return new FastToggleButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - if (b.isContentAreaFilled() && !(b.getParent() instanceof JMenuBar)) { - Color backColor = b.getBackground(); - ButtonModel model = b.getModel(); - if (model.isEnabled()) { - if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - backColor = ColorHelper.darker(backColor, 10); - } - } else { - backColor = ColorHelper.brighter(AbstractLookAndFeel.getDisabledForegroundColor(), 80); - } - g.setColor(backColor); - g.fillRect(1, 1, b.getWidth() - 2, b.getHeight() - 2); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/fast/FastToolBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/fast/FastToolBarUI.java deleted file mode 100644 index 147d39785..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/fast/FastToolBarUI.java +++ /dev/null @@ -1,52 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.fast; - -import com.jtattoo.plaf.AbstractToolBarUI; -import javax.swing.JComponent; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class FastToolBarUI extends AbstractToolBarUI { - - public static ComponentUI createUI(JComponent c) { - return new FastToolBarUI(); - } - - public Border getRolloverBorder() { - return FastBorders.getRolloverToolButtonBorder(); - } - - public Border getNonRolloverBorder() { - return FastBorders.getToolButtonBorder(); - } - - public boolean isButtonOpaque() { - return false; - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteBorderFactory.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteBorderFactory.java deleted file mode 100644 index 4a6a4f441..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteBorderFactory.java +++ /dev/null @@ -1,122 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.AbstractBorderFactory; -import javax.swing.border.Border; - -/** - * @author Michael Hagen - */ -public class GraphiteBorderFactory implements AbstractBorderFactory { - - private static GraphiteBorderFactory instance = null; - - private GraphiteBorderFactory() { - } - - public static synchronized GraphiteBorderFactory getInstance() { - if (instance == null) { - instance = new GraphiteBorderFactory(); - } - return instance; - } - - public Border getFocusFrameBorder() { - return GraphiteBorders.getFocusFrameBorder(); - } - - public Border getButtonBorder() { - return GraphiteBorders.getButtonBorder(); - } - - public Border getToggleButtonBorder() { - return GraphiteBorders.getToggleButtonBorder(); - } - - public Border getTextBorder() { - return GraphiteBorders.getTextBorder(); - } - - public Border getSpinnerBorder() { - return GraphiteBorders.getSpinnerBorder(); - } - - public Border getTextFieldBorder() { - return GraphiteBorders.getTextFieldBorder(); - } - - public Border getComboBoxBorder() { - return GraphiteBorders.getComboBoxBorder(); - } - - public Border getTableHeaderBorder() { - return GraphiteBorders.getTableHeaderBorder(); - } - - public Border getTableScrollPaneBorder() { - return GraphiteBorders.getTableScrollPaneBorder(); - } - - public Border getScrollPaneBorder() { - return GraphiteBorders.getScrollPaneBorder(); - } - - public Border getTabbedPaneBorder() { - return GraphiteBorders.getTabbedPaneBorder(); - } - - public Border getMenuBarBorder() { - return GraphiteBorders.getMenuBarBorder(); - } - - public Border getMenuItemBorder() { - return GraphiteBorders.getMenuItemBorder(); - } - - public Border getPopupMenuBorder() { - return GraphiteBorders.getPopupMenuBorder(); - } - - public Border getInternalFrameBorder() { - return GraphiteBorders.getInternalFrameBorder(); - } - - public Border getPaletteBorder() { - return GraphiteBorders.getPaletteBorder(); - } - - public Border getToolBarBorder() { - return GraphiteBorders.getToolBarBorder(); - } - - public Border getProgressBarBorder() { - return GraphiteBorders.getProgressBarBorder(); - } - - public Border getDesktopIconBorder() { - return GraphiteBorders.getDesktopIconBorder(); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteBorders.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteBorders.java deleted file mode 100644 index a6147a611..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteBorders.java +++ /dev/null @@ -1,351 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.border.AbstractBorder; -import javax.swing.border.Border; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class GraphiteBorders extends BaseBorders { - -//------------------------------------------------------------------------------------ -// Lazy access methods -//------------------------------------------------------------------------------------ - public static Border getButtonBorder() { - if (buttonBorder == null) { - buttonBorder = new ButtonBorder(); - } - return buttonBorder; - } - - public static Border getToggleButtonBorder() { - return getButtonBorder(); - } - - public static Border getRolloverToolButtonBorder() { - if (rolloverToolButtonBorder == null) { - rolloverToolButtonBorder = new RolloverToolButtonBorder(); - } - return rolloverToolButtonBorder; - } - - public static Border getMenuItemBorder() { - if (menuItemBorder == null) { - menuItemBorder = new MenuItemBorder(); - } - return menuItemBorder; - } - - public static Border getPopupMenuBorder() { - if (popupMenuBorder == null) { - if (AbstractLookAndFeel.getTheme().isMenuOpaque()) { - popupMenuBorder = new PopupMenuBorder(); - } else { - popupMenuBorder = new BasePopupMenuShadowBorder(); - } - } - return popupMenuBorder; - } - - public static Border getInternalFrameBorder() { - if (internalFrameBorder == null) { - internalFrameBorder = new InternalFrameBorder(); - } - return internalFrameBorder; - } - -//------------------------------------------------------------------------------------ -// Inner classes -//------------------------------------------------------------------------------------ - public static class ButtonBorder implements Border, UIResource { - - private static final Color defaultColorHi = new Color(220, 230, 245); - private static final Color defaultColorMed = new Color(212, 224, 243); - private static final Color defaultColorLo = new Color(200, 215, 240); - private static final Insets insets = new Insets(3, 8, 3, 8); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Graphics2D g2D = (Graphics2D) g; - AbstractButton b = (AbstractButton) c; - Color frameColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFrameColor(), 30); - if (AbstractLookAndFeel.getTheme().doShowFocusFrame() && b.hasFocus()) { - frameColor = AbstractLookAndFeel.getTheme().getFocusFrameColor(); - } - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); - g2D.setComposite(alpha); - g2D.setColor(Color.white); - g2D.drawRoundRect(x, y, w - 1, h - 1, 6, 6); - g2D.setComposite(savedComposite); - - if (b.getRootPane() != null && b.equals(b.getRootPane().getDefaultButton()) && !b.hasFocus()) { - g2D.setColor(ColorHelper.darker(frameColor, 20)); - g2D.drawRoundRect(x, y, w - 1, h - 2, 6, 6); - if (!b.getModel().isRollover()) { - g2D.setColor(defaultColorHi); - g2D.drawRoundRect(x + 1, y + 1, w - 3, h - 4, 6, 6); - g2D.setColor(defaultColorMed); - g2D.drawRoundRect(x + 2, y + 2, w - 5, h - 6, 6, 6); - g2D.setColor(defaultColorLo); - g2D.drawLine(x + 3, h - 3, w - 3, h - 3); - g2D.drawLine(w - 2, y + 4, w - 2, h - 4); - } - } else { - g2D.setColor(frameColor); - g2D.drawRoundRect(x, y, w - 1, h - 2, 6, 6); - } - - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - } - - public Insets getBorderInsets(Component c) { - return insets; - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class ButtonBorder - - public static class RolloverToolButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - Color loColor = ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 50); - if (model.isEnabled()) { - if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - g.setColor(loColor); - g.drawRect(x, y, w - 1, h - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.15f); - g2D.setComposite(alpha); - g.setColor(Color.black); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(composite); - } else if (model.isRollover()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - g.setColor(loColor); - g.drawRect(x, y, w - 1, h - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - g.setColor(Color.white); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(composite); - } - } - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class RolloverToolButtonBorder - - public static class MenuItemBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(2, 2, 2, 2); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - JMenuItem b = (JMenuItem) c; - ButtonModel model = b.getModel(); - Color borderColor = ColorHelper.darker(AbstractLookAndFeel.getMenuSelectionBackgroundColor(), 20); - g.setColor(borderColor); - if (c.getParent() instanceof JMenuBar) { - if (model.isArmed() || model.isSelected()) { - g.drawLine(x, y, x + w - 1, y); - g.drawLine(x, y + 1, x, y + h - 1); - g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); - } - } else { - if (model.isArmed() || (c instanceof JMenu && model.isSelected())) { - g.drawLine(x, y, x + w - 1, y); - g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); - } - } - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - } // class MenuItemBorder - - public static class PopupMenuBorder extends BasePopupMenuBorder { - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Color borderColor = ColorHelper.darker(AbstractLookAndFeel.getMenuSelectionBackgroundColor(), 20); - if (JTattooUtilities.isLeftToRight(c)) { - int dx = getBorderInsets(c).left; - Color logoColorHi = AbstractLookAndFeel.getTheme().getMenuSelectionBackgroundColorDark(); - Color logoColorLo = AbstractLookAndFeel.getTheme().getMenuSelectionBackgroundColor(); - Color colors[] = ColorHelper.createColorArr(logoColorHi, logoColorLo, 32); - JTattooUtilities.fillHorGradient(g, colors, x, y, dx - 1, h - 1); - paintLogo(c, g, x, y, w, h); - // - highlight - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getMenuBackgroundColor(), 40)); - g.drawLine(x + dx, y + 1, x + w - 2, y + 1); - // - outer frame - g.setColor(borderColor); - if (isMenuBarPopup(c)) { - // top - g.drawLine(x + dx - 1, y, x + w, y); - // left - g.drawLine(x, y, x, y + h - 1); - // bottom - g.drawLine(x, y + h - 1, x + w, y + h - 1); - // right - g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); - } else { - g.drawRect(x, y, w - 1, h - 1); - } - // - logo separator - g.drawLine(x + dx - 1, y + 1, x + dx - 1, y + h - 1); - } else { - int dx = getBorderInsets(c).right; - Color logoColorHi = AbstractLookAndFeel.getTheme().getMenuSelectionBackgroundColorDark(); - Color logoColorLo = AbstractLookAndFeel.getTheme().getMenuSelectionBackgroundColor(); - Color colors[] = ColorHelper.createColorArr(logoColorHi, logoColorLo, 32); - JTattooUtilities.fillHorGradient(g, colors, x + w - dx, y, dx, h - 1); - paintLogo(c, g, x, y, w, h); - // - highlight - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getMenuBackgroundColor(), 40)); - g.drawLine(x + 1, y + 1, x + w - dx - 1, y + 1); - g.drawLine(x + 1, y + 1, x + 1, y + h - 2); - // - outer frame - g.setColor(borderColor); - if (isMenuBarPopup(c)) { - // top - g.drawLine(x, y, x + w - dx, y); - // left - g.drawLine(x, y, x, y + h - 1); - // bottom - g.drawLine(x, y + h - 1, x + w, y + h - 1); - // right - g.drawLine(x + w - 1, y, x + w - 1, y + h - 1); - } else { - g.drawRect(x, y, w - 1, h - 1); - } - // - logo separator - g.drawLine(x + w - dx, y + 1, x + w - dx, y + h - 1); - } - } - - } - - public static class InternalFrameBorder extends BaseInternalFrameBorder { - - public InternalFrameBorder() { - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - int th = getTitleHeight(c); - Color titleColor = AbstractLookAndFeel.getWindowTitleColorLight(); - Color borderColor = AbstractLookAndFeel.getWindowTitleColorDark(); - Color frameColor = AbstractLookAndFeel.getWindowBorderColor(); - if (!isActive(c)) { - titleColor = AbstractLookAndFeel.getWindowInactiveTitleColorLight(); - borderColor = AbstractLookAndFeel.getWindowInactiveTitleColorDark(); - frameColor = AbstractLookAndFeel.getWindowInactiveBorderColor(); - } - - g.setColor(titleColor); - g.fillRect(x, y + 1, w, insets.top - 1); - g.setColor(titleColor); - g.fillRect(x + 1, y + h - dw, w - 2, dw - 1); - - if (isActive(c)) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 1, insets.top, dw, th + 1); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), w - dw - 1, insets.top, dw, th + 1); - g.setColor(borderColor); - JTattooUtilities.fillInverseHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 1, insets.top + th + 1, dw - 1, h - th - dw); - JTattooUtilities.fillInverseHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), w - dw, insets.top + th + 1, dw - 1, h - th - dw); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 1, insets.top, dw, th + 1); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), w - dw - 1, insets.top, dw, th + 1); - g.setColor(borderColor); - JTattooUtilities.fillInverseHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 1, insets.top + th + 1, dw - 1, h - th - dw); - JTattooUtilities.fillInverseHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), w - dw, insets.top + th + 1, dw - 1, h - th - dw); - } - - g.setColor(frameColor); - g.drawRect(x, y, w - 1, h - 1); - g.drawLine(x + dw - 1, y + insets.top + th, x + dw - 1, y + h - dw); - g.drawLine(x + w - dw, y + insets.top + th, x + w - dw, y + h - dw); - g.drawLine(x + dw - 1, y + h - dw, x + w - dw, y + h - dw); - } - } // class InternalFrameBorder -} // class GraphiteBorders - diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteButtonUI.java deleted file mode 100644 index b1c633c38..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteButtonUI.java +++ /dev/null @@ -1,70 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseButtonUI; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.RoundRectangle2D; -import javax.swing.AbstractButton; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicGraphicsUtils; - -/** - * @author Michael Hagen - */ -public class GraphiteButtonUI extends BaseButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new GraphiteButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - int w = b.getWidth(); - int h = b.getHeight(); - Graphics2D g2D = (Graphics2D) g; - Shape savedClip = g.getClip(); - if ((b.getBorder() != null) && b.isBorderPainted() && (b.getBorder() instanceof UIResource)) { - Area clipArea = new Area(new RoundRectangle2D.Double(0, 0, w - 1, h - 1, 6, 6)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - } - super.paintBackground(g, b); - g2D.setClip(savedClip); - } - - protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { - if (!AbstractLookAndFeel.getTheme().doShowFocusFrame()) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - BasicGraphicsUtils.drawDashedRect(g, 3, 2, b.getWidth() - 6, b.getHeight() - 5); - BasicGraphicsUtils.drawDashedRect(g, 4, 3, b.getWidth() - 8, b.getHeight() - 7); - } - } - -} - - diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteCheckBoxMenuItemUI.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteCheckBoxMenuItemUI.java deleted file mode 100644 index fa58c260c..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteCheckBoxMenuItemUI.java +++ /dev/null @@ -1,64 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class GraphiteCheckBoxMenuItemUI extends BaseCheckBoxMenuItemUI { - - public static ComponentUI createUI(JComponent c) { - return new GraphiteCheckBoxMenuItemUI(); - } - - protected void paintBackground(Graphics g, JComponent c, int x, int y, int w, int h) { - JMenuItem b = (JMenuItem) c; - ButtonModel model = b.getModel(); - if (model.isArmed() || (c instanceof JMenu && model.isSelected())) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getMenuSelectionColors(), x, y, w, h); - } else if (!AbstractLookAndFeel.getTheme().isMenuOpaque()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, AbstractLookAndFeel.getTheme().getMenuAlpha()); - g2D.setComposite(alpha); - g.setColor(AbstractLookAndFeel.getMenuBackgroundColor()); - g.fillRect(x, y, w, h); - g2D.setComposite(composite); - } else { - g.setColor(AbstractLookAndFeel.getMenuBackgroundColor()); - g.fillRect(x, y, w, h); - } - if (menuItem.isSelected() && menuItem.isArmed()) { - g.setColor(AbstractLookAndFeel.getMenuSelectionForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getMenuForegroundColor()); - } - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteCheckBoxUI.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteCheckBoxUI.java deleted file mode 100644 index c392df9cb..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteCheckBoxUI.java +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class GraphiteCheckBoxUI extends GraphiteRadioButtonUI { - - private static GraphiteCheckBoxUI checkBoxUI = null; - - public static ComponentUI createUI(JComponent b) { - if (checkBoxUI == null) { - checkBoxUI = new GraphiteCheckBoxUI(); - } - return checkBoxUI; - } - - public void installDefaults(AbstractButton b) { - super.installDefaults(b); - icon = UIManager.getIcon("CheckBox.icon"); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteDefaultTheme.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteDefaultTheme.java deleted file mode 100644 index 27dd0fa2d..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteDefaultTheme.java +++ /dev/null @@ -1,174 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Font; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.FontUIResource; - -public class GraphiteDefaultTheme extends AbstractTheme { - - public GraphiteDefaultTheme() { - super(); - // Setup theme with defaults - setUpColor(); - // Overwrite defaults with user props - loadProperties(); - // Setup the color arrays - setUpColorArrs(); - } - - public String getPropertyFileName() { - return "GraphiteTheme.properties"; - } - - public void setUpColor() { - super.setUpColor(); - -// showFocusFrame = true; - - foregroundColor = black; - backgroundColor = new ColorUIResource(224, 224, 224); - backgroundColorLight = white; - backgroundColorDark = lightGray; - alterBackgroundColor = new ColorUIResource(220, 220, 220); - disabledForegroundColor = new ColorUIResource(128, 128, 128); - disabledBackgroundColor = new ColorUIResource(240, 240, 240); - inputBackgroundColor = white; - inputForegroundColor = black; - - selectionForegroundColor = white; - selectionBackgroundColor = new ColorUIResource(80, 80, 80); - selectionBackgroundColorLight = new ColorUIResource(96, 96, 96); - selectionBackgroundColorDark = new ColorUIResource(64, 64, 64); - - focusColor = orange; - focusCellColor = orange; - frameColor = new ColorUIResource(144, 144, 144); - gridColor = new ColorUIResource(200, 200, 200); - - rolloverColor = orange; - rolloverColorLight = new ColorUIResource(255, 213, 113); - rolloverColorDark = new ColorUIResource(240, 168, 0); - - buttonForegroundColor = black; - buttonBackgroundColor = extraLightGray; - buttonColorLight = white; - buttonColorDark = extraLightGray; - - controlForegroundColor = black; - controlBackgroundColor = extraLightGray; - controlShadowColor = new ColorUIResource(164, 164, 164); - controlDarkShadowColor = new ColorUIResource(64, 64, 64); - controlColorLight = new ColorUIResource(96, 96, 96); - controlColorDark = new ColorUIResource(40, 40, 40); - - windowTitleForegroundColor = white; - windowTitleBackgroundColor = gray; - windowTitleColorLight = new ColorUIResource(88, 88, 88); - windowTitleColorDark = new ColorUIResource(24, 24, 24); - windowBorderColor = black; - windowIconColor = white; - windowIconShadowColor = black; - windowIconRolloverColor = orange; - - windowInactiveTitleForegroundColor = white; - windowInactiveTitleBackgroundColor = new ColorUIResource(224, 224, 224); - windowInactiveTitleColorLight = new ColorUIResource(64, 64, 64); - windowInactiveTitleColorDark = new ColorUIResource(0, 0, 0); - windowInactiveBorderColor = black; - - menuForegroundColor = black; - menuBackgroundColor = new ColorUIResource(240, 240, 240); - menuSelectionForegroundColor = black; - menuSelectionBackgroundColor = new ColorUIResource(32, 32, 32); - menuSelectionBackgroundColorLight = new ColorUIResource(255, 213, 113); - menuSelectionBackgroundColorDark = new ColorUIResource(240, 168, 0); - menuColorLight = new ColorUIResource(240, 240, 240); - menuColorDark = new ColorUIResource(220, 220, 220); - - toolbarForegroundColor = black; - toolbarBackgroundColor = backgroundColor; - toolbarColorLight = menuColorLight; - toolbarColorDark = menuColorDark; - - tabAreaBackgroundColor = backgroundColor; - tabSelectionForegroundColor = white; - desktopColor = backgroundColor; - tooltipForegroundColor = black; - tooltipBackgroundColor = yellow; - - controlFont = new FontUIResource("Dialog", Font.PLAIN, 13); - systemFont = new FontUIResource("Dialog", Font.PLAIN, 13); - userFont = new FontUIResource("Dialog", Font.PLAIN, 13); - smallFont = new FontUIResource("Dialog", Font.PLAIN, 12); - menuFont = new FontUIResource("Dialog", Font.PLAIN, 13); - windowTitleFont = new FontUIResource("Dialog", Font.BOLD, 13); - } - - public void setUpColorArrs() { - super.setUpColorArrs(); - BUTTON_COLORS = ColorHelper.createColorArr(buttonColorLight, buttonColorDark, 24); - CHECKBOX_COLORS = BUTTON_COLORS; - DEFAULT_COLORS = ColorHelper.createColorArr(controlColorLight, controlColorDark, 24); - HIDEFAULT_COLORS = new Color[20]; - for (int i = 0; i < 20; i++) { - HIDEFAULT_COLORS[i] = ColorHelper.brighter(DEFAULT_COLORS[i], 40); - } - SELECTED_COLORS = DEFAULT_COLORS; - SELECTION_COLORS = ColorHelper.createColorArr(selectionBackgroundColorLight, selectionBackgroundColorDark, 20); - MENU_SELECTION_COLORS = ColorHelper.createColorArr(menuSelectionBackgroundColorLight, menuSelectionBackgroundColorDark, 20); - ROLLOVER_COLORS = ColorHelper.createColorArr(rolloverColorLight, rolloverColorDark, 24); - PRESSED_COLORS = ColorHelper.createColorArr(menuColorDark, menuColorLight, 24); - DISABLED_COLORS = ColorHelper.createColorArr(superLightGray, extraLightGray, 24); - ACTIVE_COLORS = DEFAULT_COLORS; - INACTIVE_COLORS = BUTTON_COLORS; - - WINDOW_TITLE_COLORS = ColorHelper.createColorArr(windowTitleColorLight, windowTitleColorDark, 24); - WINDOW_INACTIVE_TITLE_COLORS = ColorHelper.createColorArr(windowInactiveTitleColorLight, windowInactiveTitleColorDark, 24); - - TOOLBAR_COLORS = ColorHelper.createColorArr(toolbarColorLight, toolbarColorDark, 24); - MENUBAR_COLORS = ColorHelper.createColorArr(menuColorLight, menuColorDark, 24); - - TAB_COLORS = BUTTON_COLORS; - COL_HEADER_COLORS = BUTTON_COLORS; - Color hiColor = backgroundColorLight; - Color loColor = ColorHelper.darker(backgroundColor, 4); - TRACK_COLORS = ColorHelper.createColorArr(loColor, hiColor, 24); - if ("true".equals(System.getProperty("graphiteBrightThumb"))) { - hiColor = backgroundColorDark; - loColor = ColorHelper.darker(backgroundColorDark, 10); - THUMB_COLORS = ColorHelper.createColorArr(hiColor, loColor, 24); - } else { - THUMB_COLORS = DEFAULT_COLORS; - } - - SLIDER_COLORS = DEFAULT_COLORS; - PROGRESSBAR_COLORS = DEFAULT_COLORS; - } - - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteIconFactory.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteIconFactory.java deleted file mode 100644 index 5abcbeced..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteIconFactory.java +++ /dev/null @@ -1,171 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.AbstractIconFactory; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class GraphiteIconFactory implements AbstractIconFactory -{ - private static GraphiteIconFactory instance = null; - - private GraphiteIconFactory() - { } - - public static synchronized GraphiteIconFactory getInstance() - { - if (instance == null) - instance = new GraphiteIconFactory(); - return instance; - } - - public Icon getOptionPaneErrorIcon() - { return GraphiteIcons.getOptionPaneErrorIcon(); } - - public Icon getOptionPaneWarningIcon() - { return GraphiteIcons.getOptionPaneWarningIcon(); } - - public Icon getOptionPaneInformationIcon() - { return GraphiteIcons.getOptionPaneInformationIcon(); } - - public Icon getOptionPaneQuestionIcon() - { return GraphiteIcons.getOptionPaneQuestionIcon(); } - - public Icon getFileChooserDetailViewIcon() - { return GraphiteIcons.getFileChooserDetailViewIcon(); } - - public Icon getFileChooserHomeFolderIcon() - { return GraphiteIcons.getFileChooserHomeFolderIcon(); } - - public Icon getFileChooserListViewIcon() - { return GraphiteIcons.getFileChooserListViewIcon(); } - - public Icon getFileChooserNewFolderIcon() - { return GraphiteIcons.getFileChooserNewFolderIcon(); } - - public Icon getFileChooserUpFolderIcon() - { return GraphiteIcons.getFileChooserUpFolderIcon(); } - - public Icon getMenuIcon() - { return GraphiteIcons.getMenuIcon(); } - - public Icon getIconIcon() - { return GraphiteIcons.getIconIcon(); } - - public Icon getMaxIcon() - { return GraphiteIcons.getMaxIcon(); } - - public Icon getMinIcon() - { return GraphiteIcons.getMinIcon(); } - - public Icon getCloseIcon() - { return GraphiteIcons.getCloseIcon(); } - - public Icon getPaletteCloseIcon() - { return GraphiteIcons.getPaletteCloseIcon(); } - - public Icon getRadioButtonIcon() - { return GraphiteIcons.getRadioButtonIcon(); } - - public Icon getCheckBoxIcon() - { return GraphiteIcons.getCheckBoxIcon(); } - - public Icon getComboBoxIcon() - { return GraphiteIcons.getComboBoxIcon(); } - - public Icon getTreeComputerIcon() - { return GraphiteIcons.getTreeComputerIcon(); } - - public Icon getTreeFloppyDriveIcon() - { return GraphiteIcons.getTreeFloppyDriveIcon(); } - - public Icon getTreeHardDriveIcon() - { return GraphiteIcons.getTreeHardDriveIcon(); } - - public Icon getTreeFolderIcon() - { return GraphiteIcons.getTreeFolderIcon(); } - - public Icon getTreeLeafIcon() - { return GraphiteIcons.getTreeLeafIcon(); } - - public Icon getTreeCollapsedIcon() - { return GraphiteIcons.getTreeControlIcon(true); } - - public Icon getTreeExpandedIcon() - { return GraphiteIcons.getTreeControlIcon(false); } - - public Icon getMenuArrowIcon() - { return GraphiteIcons.getMenuArrowIcon(); } - - public Icon getMenuCheckBoxIcon() - { return GraphiteIcons.getMenuCheckBoxIcon(); } - - public Icon getMenuRadioButtonIcon() - { return GraphiteIcons.getMenuRadioButtonIcon(); } - - public Icon getUpArrowIcon() - { return GraphiteIcons.getUpArrowIcon(); } - - public Icon getDownArrowIcon() - { return GraphiteIcons.getDownArrowIcon(); } - - public Icon getLeftArrowIcon() - { return GraphiteIcons.getLeftArrowIcon(); } - - public Icon getRightArrowIcon() - { return GraphiteIcons.getRightArrowIcon(); } - - public Icon getSplitterDownArrowIcon() - { return GraphiteIcons.getSplitterDownArrowIcon(); } - - public Icon getSplitterHorBumpIcon() - { return GraphiteIcons.getSplitterHorBumpIcon(); } - - public Icon getSplitterLeftArrowIcon() - { return GraphiteIcons.getSplitterLeftArrowIcon(); } - - public Icon getSplitterRightArrowIcon() - { return GraphiteIcons.getSplitterRightArrowIcon(); } - - public Icon getSplitterUpArrowIcon() - { return GraphiteIcons.getSplitterUpArrowIcon(); } - - public Icon getSplitterVerBumpIcon() - { return GraphiteIcons.getSplitterVerBumpIcon(); } - - public Icon getThumbHorIcon() - { return GraphiteIcons.getThumbHorIcon(); } - - public Icon getThumbVerIcon() - { return GraphiteIcons.getThumbVerIcon(); } - - public Icon getThumbHorIconRollover() - { return GraphiteIcons.getThumbHorIconRollover(); } - - public Icon getThumbVerIconRollover() - { return GraphiteIcons.getThumbVerIconRollover(); } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteIcons.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteIcons.java deleted file mode 100644 index 62166f705..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteIcons.java +++ /dev/null @@ -1,93 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseIcons; -import java.awt.Color; -import java.awt.Insets; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class GraphiteIcons extends BaseIcons { - - public static Icon getIconIcon() { - if (iconIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - iconIcon = new MacIconIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - iconIcon = new BaseIcons.IconSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(1, 1, 1, 1)); - } - } - return iconIcon; - } - - public static Icon getMinIcon() { - if (minIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - minIcon = new MacMinIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - minIcon = new BaseIcons.MinSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(1, 1, 1, 1)); - } - } - return minIcon; - } - - public static Icon getMaxIcon() { - if (maxIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - maxIcon = new MacMaxIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - maxIcon = new BaseIcons.MaxSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(1, 1, 1, 1)); - } - } - return maxIcon; - } - - public static Icon getCloseIcon() { - if (closeIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - closeIcon = new MacCloseIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - closeIcon = new BaseIcons.CloseSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(1, 1, 1, 1)); - } - } - return closeIcon; - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteInternalFrameTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteInternalFrameTitlePane.java deleted file mode 100644 index 211533d0b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteInternalFrameTitlePane.java +++ /dev/null @@ -1,77 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JInternalFrame; - -/** - * @author Michael Hagen - */ -public class GraphiteInternalFrameTitlePane extends BaseInternalFrameTitlePane { - - public GraphiteInternalFrameTitlePane(JInternalFrame f) { - super(f); - } - - protected int getHorSpacing() { - return AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn() ? 1 : 0; - } - - protected int getVerSpacing() { - return AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn() ? 3 : 0; - } - - protected boolean centerButtons() { - return false; - } - - public void paintBorder(Graphics g) { - if (isActive()) { - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getWindowBorderColor(), 10)); - } else { - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getWindowInactiveBorderColor(), 10)); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } - - public void paintText(Graphics g, int x, int y, String title) { - if (isMacStyleWindowDecoration()) { - x += paintIcon(g, x, y) + 5; - } - Graphics2D g2D = (Graphics2D)g; - Color fc = AbstractLookAndFeel.getWindowTitleForegroundColor(); - if (fc.equals(Color.white)) { - Color bc = AbstractLookAndFeel.getWindowTitleColorDark(); - g2D.setColor(bc); - JTattooUtilities.drawString(frame, g, title, x - 1, y - 1); - g2D.setColor(ColorHelper.darker(bc, 30)); - JTattooUtilities.drawString(frame, g, title, x + 1, y + 1); - } - g.setColor(fc); - JTattooUtilities.drawString(frame, g, title, x, y); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteInternalFrameUI.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteInternalFrameUI.java deleted file mode 100644 index f16793d61..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteInternalFrameUI.java +++ /dev/null @@ -1,50 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.BaseInternalFrameUI; -import javax.swing.JComponent; -import javax.swing.JInternalFrame; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class GraphiteInternalFrameUI extends BaseInternalFrameUI { - - public GraphiteInternalFrameUI(JInternalFrame b) { - super(b); - } - - public static ComponentUI createUI(JComponent c) { - return new GraphiteInternalFrameUI((JInternalFrame)c); - } - - protected JComponent createNorthPane(JInternalFrame w) { - titlePane = new GraphiteInternalFrameTitlePane(w); - return titlePane; - } - -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteLookAndFeel.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteLookAndFeel.java deleted file mode 100644 index 0370d800f..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteLookAndFeel.java +++ /dev/null @@ -1,333 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.*; -import java.util.*; -import javax.swing.UIDefaults; - -/** - * @author Michael Hagen - */ -public class GraphiteLookAndFeel extends AbstractLookAndFeel { - private static GraphiteDefaultTheme myTheme = null; - private static final ArrayList themesList = new ArrayList(); - private static final HashMap themesMap = new HashMap(); - private static final Properties defaultProps = new Properties(); - private static final Properties smallFontProps = new Properties(); - private static final Properties mediumFontProps = new Properties(); - private static final Properties largeFontProps = new Properties(); - private static final Properties greenProps = new Properties(); - private static final Properties greenSmallFontProps = new Properties(); - private static final Properties greenMediumFontProps = new Properties(); - private static final Properties greenLargeFontProps = new Properties(); - private static final Properties blueProps = new Properties(); - private static final Properties blueSmallFontProps = new Properties(); - private static final Properties blueMediumFontProps = new Properties(); - private static final Properties blueLargeFontProps = new Properties(); - - static { - smallFontProps.setProperty("controlTextFont", "Dialog 12"); - smallFontProps.setProperty("systemTextFont", "Dialog 12"); - smallFontProps.setProperty("userTextFont", "Dialog 12"); - smallFontProps.setProperty("menuTextFont", "Dialog 12"); - smallFontProps.setProperty("windowTitleFont", "Dialog bold 12"); - smallFontProps.setProperty("subTextFont", "Dialog 11"); - - mediumFontProps.setProperty("controlTextFont", "Dialog 15"); - mediumFontProps.setProperty("systemTextFont", "Dialog 15"); - mediumFontProps.setProperty("userTextFont", "Dialog 15"); - mediumFontProps.setProperty("menuTextFont", "Dialog 15"); - mediumFontProps.setProperty("windowTitleFont", "Dialog bold 15"); - mediumFontProps.setProperty("subTextFont", "Dialog 13"); - - largeFontProps.setProperty("controlTextFont", "Dialog 16"); - largeFontProps.setProperty("systemTextFont", "Dialog 16"); - largeFontProps.setProperty("userTextFont", "Dialog 16"); - largeFontProps.setProperty("menuTextFont", "Dialog 16"); - largeFontProps.setProperty("windowTitleFont", "Dialog bold 16"); - largeFontProps.setProperty("subTextFont", "Dialog 14"); - - greenProps.setProperty("windowTitleForegroundColor", "255 255 255"); - greenProps.setProperty("windowTitleBackgroundColor", "0 96 52"); - greenProps.setProperty("windowTitleColorLight", "0 136 57"); - greenProps.setProperty("windowTitleColorDark", "0 88 47"); - greenProps.setProperty("windowBorderColor", "0 88 47"); - greenProps.setProperty("windowInactiveTitleForegroundColor", "255 255 255"); - greenProps.setProperty("windowInactiveTitleBackgroundColor", "0 96 50"); - greenProps.setProperty("windowInactiveTitleColorLight", "0 119 51"); - greenProps.setProperty("windowInactiveTitleColorDark", "0 88 47"); - greenProps.setProperty("windowInactiveBorderColor", "0 88 47"); - greenProps.setProperty("backgroundColor", "231 244 219"); - greenProps.setProperty("backgroundColorLight", "255 255 255"); - greenProps.setProperty("backgroundColorDark", "208 234 185"); - greenProps.setProperty("alterBackgroundColor", "208 234 185"); - greenProps.setProperty("frameColor", "114 180 54"); - greenProps.setProperty("disabledForegroundColor", "96 96 96"); - greenProps.setProperty("disabledBackgroundColor", "228 240 216"); - greenProps.setProperty("selectionForegroundColor", "255 255 255"); - greenProps.setProperty("selectionBackgroundColor", "48 136 53"); - greenProps.setProperty("controlBackgroundColor", "231 244 219"); - greenProps.setProperty("controlColorLight", "40 170 60"); - greenProps.setProperty("controlColorDark", "48 136 53"); - greenProps.setProperty("controlDarkShadowColor", "112 176 53"); - greenProps.setProperty("buttonColorLight", "255 255 255"); - greenProps.setProperty("buttonColorDark", "231 244 219"); - greenProps.setProperty("menuBackgroundColor", "255 255 255"); - greenProps.setProperty("menuColorDark", "218 238 200"); - greenProps.setProperty("menuColorLight", "231 244 219"); - greenProps.setProperty("menuSelectionBackgroundColor", "72 51 0"); - greenProps.setProperty("toolbarBackgroundColor", "231 244 219"); - greenProps.setProperty("toolbarColorLight", "231 244 219"); - greenProps.setProperty("toolbarColorDark", "208 234 185"); - - blueProps.setProperty("windowTitleForegroundColor", "255 255 255"); - blueProps.setProperty("windowTitleBackgroundColor", "1 49 157"); - blueProps.setProperty("windowTitleColorLight", "1 40 131"); - blueProps.setProperty("windowTitleColorDark", "1 30 97"); - blueProps.setProperty("windowBorderColor", "0 24 83"); - blueProps.setProperty("windowInactiveTitleForegroundColor", "255 255 255"); - blueProps.setProperty("windowInactiveTitleBackgroundColor", "55 87 129"); - blueProps.setProperty("windowInactiveTitleColorLight", "1 35 116"); - blueProps.setProperty("windowInactiveTitleColorDark", "1 30 97"); - blueProps.setProperty("windowInactiveBorderColor", "0 24 83"); - blueProps.setProperty("backgroundColor", "228 235 243"); - blueProps.setProperty("backgroundColorLight", "255 255 255"); - blueProps.setProperty("backgroundColorDark", "188 204 226"); - blueProps.setProperty("alterBackgroundColor", "208 220 234"); - blueProps.setProperty("frameColor", "120 153 197"); - blueProps.setProperty("disabledForegroundColor", "96 96 96"); - blueProps.setProperty("disabledBackgroundColor", "225 232 240"); - blueProps.setProperty("selectionForegroundColor", "255 255 255"); - blueProps.setProperty("selectionBackgroundColor", "1 38 124"); - blueProps.setProperty("controlBackgroundColor", "228 235 243"); - blueProps.setProperty("controlColorLight", "1 40 131"); - blueProps.setProperty("controlColorDark", "1 30 98"); - blueProps.setProperty("controlDarkShadowColor", "64 100 149"); - blueProps.setProperty("buttonColorLight", "255 255 255"); - blueProps.setProperty("buttonColorDark", "228 235 243"); - blueProps.setProperty("menuBackgroundColor", "255 255 255"); - blueProps.setProperty("menuColorDark", "208 220 234"); - blueProps.setProperty("menuColorLight", "228 235 243"); - blueProps.setProperty("menuSelectionBackgroundColor", "72 51 0"); - blueProps.setProperty("toolbarBackgroundColor", "228 235 243"); - blueProps.setProperty("toolbarColorLight", "228 235 243"); - blueProps.setProperty("toolbarColorDark", "188 204 226"); - - String key; - String value; - Iterator iter = smallFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = smallFontProps.getProperty(key); - greenSmallFontProps.setProperty(key, value); - blueSmallFontProps.setProperty(key, value); - } - - iter = mediumFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = mediumFontProps.getProperty(key); - greenMediumFontProps.setProperty(key, value); - blueMediumFontProps.setProperty(key, value); - } - - iter = largeFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = largeFontProps.getProperty(key); - greenLargeFontProps.setProperty(key, value); - blueLargeFontProps.setProperty(key, value); - } - - iter = greenProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = greenProps.getProperty(key); - greenSmallFontProps.setProperty(key, value); - greenMediumFontProps.setProperty(key, value); - greenLargeFontProps.setProperty(key, value); - } - - iter = blueProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = blueProps.getProperty(key); - blueSmallFontProps.setProperty(key, value); - blueMediumFontProps.setProperty(key, value); - blueLargeFontProps.setProperty(key, value); - } - - themesList.add("Default"); - themesList.add("Small-Font"); - themesList.add("Medium-Font"); - themesList.add("Large-Font"); - - themesList.add("Green"); - themesList.add("Green-Small-Font"); - themesList.add("Green-Medium-Font"); - themesList.add("Green-Large-Font"); - - themesList.add("Blue"); - themesList.add("Blue-Small-Font"); - themesList.add("Blue-Medium-Font"); - themesList.add("Blue-Large-Font"); - - themesMap.put("Default", defaultProps); - themesMap.put("Small-Font", smallFontProps); - themesMap.put("Medium-Font", mediumFontProps); - themesMap.put("Large-Font", largeFontProps); - - themesMap.put("Green", greenProps); - themesMap.put("Green-Small-Font", greenSmallFontProps); - themesMap.put("Green-Medium-Font", greenMediumFontProps); - themesMap.put("Green-Large-Font", greenLargeFontProps); - - themesMap.put("Blue", blueProps); - themesMap.put("Blue-Small-Font", blueSmallFontProps); - themesMap.put("Blue-Medium-Font", blueMediumFontProps); - themesMap.put("Blue-Large-Font", blueLargeFontProps); - } - - public static java.util.List getThemes() { - return themesList; - } - - public static Properties getThemeProperties(String name) { - return ((Properties)themesMap.get(name)); - } - - public static void setTheme(String name) { - setTheme((Properties)themesMap.get(name)); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - - public static void setTheme(String name, String licenseKey, String logoString) { - Properties props = (Properties)themesMap.get(name); - if (props != null) { - props.put("licenseKey", licenseKey); - props.put("logoString", logoString); - setTheme(props); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - } - - public static void setTheme(Properties themesProps) { - if (myTheme == null) { - myTheme = new GraphiteDefaultTheme(); - } - if ((myTheme != null) && (themesProps != null)) { - myTheme.setUpColor(); - myTheme.setProperties(themesProps); - myTheme.setUpColorArrs(); - AbstractLookAndFeel.setTheme(myTheme); - } - } - - public static void setCurrentTheme(Properties themesProps) { - setTheme(themesProps); - } - - public String getName() - { return "Graphite"; } - - public String getID() - { return "Graphite"; } - - public String getDescription() - { return "The Graphite Look and Feel"; } - - public boolean isNativeLookAndFeel() - { return false; } - - public boolean isSupportedLookAndFeel() - { return true; } - - public AbstractBorderFactory getBorderFactory() - { return GraphiteBorderFactory.getInstance(); } - - public AbstractIconFactory getIconFactory() - { return GraphiteIconFactory.getInstance(); } - - protected void createDefaultTheme() { - if (myTheme == null) { - myTheme = new GraphiteDefaultTheme(); - } - setTheme(myTheme); - } - - protected void initClassDefaults(UIDefaults table) { - super.initClassDefaults(table); - Object[] uiDefaults = { - // BaseLookAndFeel classes - "LabelUI", BaseLabelUI.class.getName(), - "ToggleButtonUI", BaseToggleButtonUI.class.getName(), - "SeparatorUI", BaseSeparatorUI.class.getName(), - "TextFieldUI", BaseTextFieldUI.class.getName(), - "TextAreaUI", BaseTextAreaUI.class.getName(), - "EditorPaneUI", BaseEditorPaneUI.class.getName(), - "PasswordFieldUI", BasePasswordFieldUI.class.getName(), - "ComboBoxUI", BaseComboBoxUI.class.getName(), - "ToolTipUI", BaseToolTipUI.class.getName(), - "TreeUI", BaseTreeUI.class.getName(), - "TableUI", BaseTableUI.class.getName(), - "TableHeaderUI", BaseTableHeaderUI.class.getName(), - "ScrollBarUI", BaseScrollBarUI.class.getName(), - "ScrollPaneUI", BaseScrollPaneUI.class.getName(), - "ProgressBarUI", BaseProgressBarUI.class.getName(), - "PanelUI", BasePanelUI.class.getName(), - "SplitPaneUI", BaseSplitPaneUI.class.getName(), - "SliderUI", BaseSliderUI.class.getName(), - "FileChooserUI", BaseFileChooserUI.class.getName(), - - "MenuBarUI", BaseMenuBarUI.class.getName(), - "PopupMenuUI", BasePopupMenuUI.class.getName(), - "PopupMenuSeparatorUI", BaseSeparatorUI.class.getName(), - "DesktopPaneUI", BaseDesktopPaneUI.class.getName(), - - // GraphiteLookAndFeel classes - "RadioButtonUI", GraphiteRadioButtonUI.class.getName(), - "CheckBoxUI", GraphiteCheckBoxUI.class.getName(), - "ButtonUI", GraphiteButtonUI.class.getName(), - "MenuUI", GraphiteMenuUI.class.getName(), - "MenuItemUI", GraphiteMenuItemUI.class.getName(), - "CheckBoxMenuItemUI", GraphiteCheckBoxMenuItemUI.class.getName(), - "RadioButtonMenuItemUI", GraphiteRadioButtonMenuItemUI.class.getName(), - "TabbedPaneUI", GraphiteTabbedPaneUI.class.getName(), - "ToolBarUI", GraphiteToolBarUI.class.getName(), - "InternalFrameUI", GraphiteInternalFrameUI.class.getName(), - "RootPaneUI", GraphiteRootPaneUI.class.getName(), - }; - table.putDefaults(uiDefaults); - if (JTattooUtilities.getJavaVersion() >= 1.5) { - table.put("FormattedTextFieldUI", BaseFormattedTextFieldUI.class.getName()); - table.put("SpinnerUI", BaseSpinnerUI.class.getName()); - } - } - -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteMenuItemUI.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteMenuItemUI.java deleted file mode 100644 index 9260e2f24..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteMenuItemUI.java +++ /dev/null @@ -1,64 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class GraphiteMenuItemUI extends BaseMenuItemUI { - - public static ComponentUI createUI(JComponent c) { - return new GraphiteMenuItemUI(); - } - - protected void paintBackground(Graphics g, JComponent c, int x, int y, int w, int h) { - JMenuItem b = (JMenuItem) c; - ButtonModel model = b.getModel(); - if (model.isArmed() || (c instanceof JMenu && model.isSelected())) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getMenuSelectionColors(), x, y, w, h); - } else if (!AbstractLookAndFeel.getTheme().isMenuOpaque()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, AbstractLookAndFeel.getTheme().getMenuAlpha()); - g2D.setComposite(alpha); - g.setColor(AbstractLookAndFeel.getMenuBackgroundColor()); - g.fillRect(x, y, w, h); - g2D.setComposite(composite); - } else { - g.setColor(AbstractLookAndFeel.getMenuBackgroundColor()); - g.fillRect(x, y, w, h); - } - if (menuItem.isSelected() && menuItem.isArmed()) { - g.setColor(AbstractLookAndFeel.getMenuSelectionForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getMenuForegroundColor()); - } - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteMenuUI.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteMenuUI.java deleted file mode 100644 index 0d0aad1cc..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteMenuUI.java +++ /dev/null @@ -1,75 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class GraphiteMenuUI extends BaseMenuUI { - - public static ComponentUI createUI(JComponent c) { - return new GraphiteMenuUI(); - } - - protected void paintBackground(Graphics g, JComponent c, int x, int y, int w, int h) { - JMenuItem b = (JMenuItem) c; - ButtonModel model = b.getModel(); - if (c.getParent() instanceof JMenuBar) { - if (model.isRollover() || model.isArmed() || (c instanceof JMenu && model.isSelected())) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getMenuSelectionColors(), x, y, w, h); - } - if (model.isRollover() && !model.isSelected()) { - Color colArr[] = AbstractLookAndFeel.getTheme().getMenuSelectionColors(); - Color frameColor = ColorHelper.darker(colArr[colArr.length - 1], 5); - g.setColor(frameColor); - g.drawRect(x, y, w - 1, h - 1); - } - } else { - if (model.isArmed() || (c instanceof JMenu && model.isSelected())) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getMenuSelectionColors(), x, y, w, h); - } else if (!AbstractLookAndFeel.getTheme().isMenuOpaque()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, AbstractLookAndFeel.getTheme().getMenuAlpha()); - g2D.setComposite(alpha); - g.setColor(AbstractLookAndFeel.getMenuBackgroundColor()); - g.fillRect(x, y, w, h); - g2D.setComposite(composite); - } else { - g.setColor(AbstractLookAndFeel.getMenuBackgroundColor()); - g.fillRect(x, y, w, h); - } - } - if (menuItem.isSelected() && menuItem.isArmed()) { - g.setColor(AbstractLookAndFeel.getMenuSelectionForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getMenuForegroundColor()); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteRadioButtonMenuItemUI.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteRadioButtonMenuItemUI.java deleted file mode 100644 index 6a6ec2eea..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteRadioButtonMenuItemUI.java +++ /dev/null @@ -1,64 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class GraphiteRadioButtonMenuItemUI extends BaseRadioButtonMenuItemUI { - - public static ComponentUI createUI(JComponent c) { - return new GraphiteRadioButtonMenuItemUI(); - } - - protected void paintBackground(Graphics g, JComponent c, int x, int y, int w, int h) { - JMenuItem b = (JMenuItem) c; - ButtonModel model = b.getModel(); - if (model.isArmed() || (c instanceof JMenu && model.isSelected())) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getMenuSelectionColors(), x, y, w, h); - } else if (!AbstractLookAndFeel.getTheme().isMenuOpaque()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, AbstractLookAndFeel.getTheme().getMenuAlpha()); - g2D.setComposite(alpha); - g.setColor(AbstractLookAndFeel.getMenuBackgroundColor()); - g.fillRect(x, y, w, h); - g2D.setComposite(composite); - } else { - g.setColor(AbstractLookAndFeel.getMenuBackgroundColor()); - g.fillRect(x, y, w, h); - } - if (menuItem.isSelected() && menuItem.isArmed()) { - g.setColor(AbstractLookAndFeel.getMenuSelectionForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getMenuForegroundColor()); - } - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteRadioButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteRadioButtonUI.java deleted file mode 100644 index e6490bbc0..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteRadioButtonUI.java +++ /dev/null @@ -1,53 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseRadioButtonUI; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicGraphicsUtils; - -/** - * @author Michael Hagen - */ -public class GraphiteRadioButtonUI extends BaseRadioButtonUI { - - private static GraphiteRadioButtonUI radioButtonUI = null; - - public static ComponentUI createUI(JComponent c) { - if (radioButtonUI == null) { - radioButtonUI = new GraphiteRadioButtonUI(); - } - return radioButtonUI; - } - - protected void paintFocus(Graphics g, Rectangle t, Dimension d) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - BasicGraphicsUtils.drawDashedRect(g, t.x - 3, t.y - 1, t.width + 6, t.height + 2); - BasicGraphicsUtils.drawDashedRect(g, t.x - 2, t.y, t.width + 4, t.height); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteRootPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteRootPaneUI.java deleted file mode 100644 index 74c7f0dd0..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteRootPaneUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.BaseRootPaneUI; -import com.jtattoo.plaf.BaseTitlePane; -import javax.swing.JComponent; -import javax.swing.JRootPane; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class GraphiteRootPaneUI extends BaseRootPaneUI -{ - public static ComponentUI createUI(JComponent c) { - return new GraphiteRootPaneUI(); - } - - public BaseTitlePane createTitlePane(JRootPane root) { - return new GraphiteTitlePane(root, this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteTabbedPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteTabbedPaneUI.java deleted file mode 100644 index fe0af1286..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteTabbedPaneUI.java +++ /dev/null @@ -1,141 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicGraphicsUtils; -import javax.swing.text.View; - -/** - * @author Michael Hagen - */ -public class GraphiteTabbedPaneUI extends BaseTabbedPaneUI { - - private Color sepColors[] = null; - - public static ComponentUI createUI(JComponent c) { - return new GraphiteTabbedPaneUI(); - } - - protected void installComponents() { - simpleButtonBorder = true; - super.installComponents(); - } - - protected Color getLoBorderColor(int tabIndex) { - if (tabIndex == tabPane.getSelectedIndex() && tabPane.getBackgroundAt(tabIndex) instanceof ColorUIResource) { - return super.getLoBorderColor(tabIndex); - } - return AbstractLookAndFeel.getControlShadow(); - } - - protected Color[] getContentBorderColors(int tabPlacement) { - if (sepColors == null) { - sepColors = new Color[5]; - sepColors[0] = getLoBorderColor(0); - sepColors[1] = AbstractLookAndFeel.getControlColorDark(); - sepColors[2] = ColorHelper.darker(AbstractLookAndFeel.getControlColorDark(), 4); - sepColors[3] = ColorHelper.darker(AbstractLookAndFeel.getControlColorDark(), 8); - sepColors[4] = ColorHelper.darker(AbstractLookAndFeel.getControlColorDark(), 12); - } - return sepColors; - } - - protected Font getTabFont(boolean isSelected) { - if (isSelected) { - return super.getTabFont(isSelected).deriveFont(Font.BOLD); - } else { - return super.getTabFont(isSelected); - } - } - - protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected) { - Color backColor = tabPane.getBackgroundAt(tabIndex); - if (!(backColor instanceof UIResource)) { - super.paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected); - return; - } - g.setFont(font); - View v = getTextViewForTab(tabIndex); - if (v != null) { - // html - Graphics2D g2D = (Graphics2D)g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - v.paint(g, textRect); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } else { - // plain text - int mnemIndex = -1; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); - } - - if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) { - if (isSelected) { - if (ColorHelper.getGrayValue(AbstractLookAndFeel.getControlColorDark()) > 128) { - g.setColor(tabPane.getForegroundAt(tabIndex)); - } else { - Color titleColor = AbstractLookAndFeel.getWindowTitleForegroundColor(); - if (ColorHelper.getGrayValue(titleColor) > 164) { - g.setColor(Color.black); - } else { - g.setColor(Color.white); - } - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x + 1, textRect.y + 1 + metrics.getAscent()); - g.setColor(titleColor); - } - } else { - g.setColor(tabPane.getForegroundAt(tabIndex)); - } - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); - - } else { // tab disabled - g.setColor(Color.white); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x + 1, textRect.y + metrics.getAscent() + 1); - g.setColor(AbstractLookAndFeel.getDisabledForegroundColor()); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); - } - } - } - - protected void paintFocusIndicator(Graphics g, int tabPlacement, Rectangle[] rects, int tabIndex, Rectangle iconRect, Rectangle textRect, boolean isSelected) { - if (tabPane.isRequestFocusEnabled() && tabPane.hasFocus() && isSelected && tabIndex >= 0 && textRect.width > 8) { - g.setColor(AbstractLookAndFeel.getTheme().getFocusColor()); - BasicGraphicsUtils.drawDashedRect(g, textRect.x - 4, textRect.y, textRect.width + 8, textRect.height); - BasicGraphicsUtils.drawDashedRect(g, textRect.x - 3, textRect.y + 1, textRect.width + 6, textRect.height - 2); - } - } - -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteTitlePane.java deleted file mode 100644 index f809a0d09..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteTitlePane.java +++ /dev/null @@ -1,76 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JRootPane; - -/** - * @author Michael Hagen - */ -public class GraphiteTitlePane extends BaseTitlePane { - - public GraphiteTitlePane(JRootPane root, BaseRootPaneUI ui) { - super(root, ui); - } - - protected int getHorSpacing() { - return AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn() ? 1 : 0; - } - - protected int getVerSpacing() { - return AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn() ? 3 : 0; - } - - protected boolean centerButtons() { - return false; - } - - - public void paintBorder(Graphics g) { - if (isActive()) { - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getWindowBorderColor(), 10)); - } else { - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getWindowInactiveBorderColor(), 10)); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } - - public void paintText(Graphics g, int x, int y, String title) { - x += paintIcon(g, x, y); - Graphics2D g2D = (Graphics2D)g; - Color fc = AbstractLookAndFeel.getWindowTitleForegroundColor(); - if (fc.equals(Color.white)) { - Color bc = AbstractLookAndFeel.getWindowTitleColorDark(); - g2D.setColor(bc); - JTattooUtilities.drawString(rootPane, g, title, x-1, y-1); - g2D.setColor(ColorHelper.darker(bc, 30)); - JTattooUtilities.drawString(rootPane, g, title, x+1, y+1); - } - g.setColor(fc); - JTattooUtilities.drawString(rootPane, g, title, x, y); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteToolBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteToolBarUI.java deleted file mode 100644 index 35b830e3e..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/graphite/GraphiteToolBarUI.java +++ /dev/null @@ -1,51 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.graphite; - -import com.jtattoo.plaf.AbstractToolBarUI; -import javax.swing.JComponent; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class GraphiteToolBarUI extends AbstractToolBarUI { - - public static ComponentUI createUI(JComponent c) { - return new GraphiteToolBarUI(); - } - - public Border getRolloverBorder() { - return GraphiteBorders.getRolloverToolButtonBorder(); - } - - public Border getNonRolloverBorder() { - return GraphiteBorders.getToolButtonBorder(); - } - - public boolean isButtonOpaque() { - return false; - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiBorderFactory.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiBorderFactory.java deleted file mode 100644 index 5a35445d4..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiBorderFactory.java +++ /dev/null @@ -1,122 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.AbstractBorderFactory; -import javax.swing.border.Border; - -/** - * @author Michael Hagen - */ -public class HiFiBorderFactory implements AbstractBorderFactory { - - private static HiFiBorderFactory instance = null; - - private HiFiBorderFactory() { - } - - public static synchronized HiFiBorderFactory getInstance() { - if (instance == null) { - instance = new HiFiBorderFactory(); - } - return instance; - } - - public Border getFocusFrameBorder() { - return HiFiBorders.getFocusFrameBorder(); - } - - public Border getButtonBorder() { - return HiFiBorders.getButtonBorder(); - } - - public Border getToggleButtonBorder() { - return HiFiBorders.getToggleButtonBorder(); - } - - public Border getTextBorder() { - return HiFiBorders.getTextBorder(); - } - - public Border getSpinnerBorder() { - return HiFiBorders.getSpinnerBorder(); - } - - public Border getTextFieldBorder() { - return HiFiBorders.getTextFieldBorder(); - } - - public Border getComboBoxBorder() { - return HiFiBorders.getComboBoxBorder(); - } - - public Border getTableHeaderBorder() { - return HiFiBorders.getTableHeaderBorder(); - } - - public Border getTableScrollPaneBorder() { - return HiFiBorders.getTableScrollPaneBorder(); - } - - public Border getScrollPaneBorder() { - return HiFiBorders.getScrollPaneBorder(); - } - - public Border getTabbedPaneBorder() { - return HiFiBorders.getTabbedPaneBorder(); - } - - public Border getMenuBarBorder() { - return HiFiBorders.getMenuBarBorder(); - } - - public Border getMenuItemBorder() { - return HiFiBorders.getMenuItemBorder(); - } - - public Border getPopupMenuBorder() { - return HiFiBorders.getPopupMenuBorder(); - } - - public Border getInternalFrameBorder() { - return HiFiBorders.getInternalFrameBorder(); - } - - public Border getPaletteBorder() { - return HiFiBorders.getPaletteBorder(); - } - - public Border getToolBarBorder() { - return HiFiBorders.getToolBarBorder(); - } - - public Border getProgressBarBorder() { - return HiFiBorders.getProgressBarBorder(); - } - - public Border getDesktopIconBorder() { - return HiFiBorders.getDesktopIconBorder(); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiBorders.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiBorders.java deleted file mode 100644 index 63d0a4022..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiBorders.java +++ /dev/null @@ -1,329 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.border.AbstractBorder; -import javax.swing.border.Border; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class HiFiBorders extends BaseBorders { - - //------------------------------------------------------------------------------------ - // Lazy access methods - //------------------------------------------------------------------------------------ - public static Border getButtonBorder() { - if (buttonBorder == null) { - buttonBorder = new ButtonBorder(); - } - return buttonBorder; - } - - public static Border getToggleButtonBorder() { - return getButtonBorder(); - } - - public static Border getRolloverToolButtonBorder() { - if (rolloverToolButtonBorder == null) { - rolloverToolButtonBorder = new RolloverToolButtonBorder(); - } - return rolloverToolButtonBorder; - } - - public static Border getScrollPaneBorder() { - if (scrollPaneBorder == null) { - scrollPaneBorder = new ScrollPaneBorder(); - } - return scrollPaneBorder; - } - - public static Border getTableScrollPaneBorder() { - if (tableScrollPaneBorder == null) { - tableScrollPaneBorder = new ScrollPaneBorder(); - } - return tableScrollPaneBorder; - } - - public static Border getInternalFrameBorder() { - if (internalFrameBorder == null) { - internalFrameBorder = new InternalFrameBorder(); - } - return internalFrameBorder; - } - - public static Border getToolBarBorder() { - if (toolBarBorder == null) { - toolBarBorder = new ToolBarBorder(); - } - return toolBarBorder; - } - -//------------------------------------------------------------------------------------ -// Implementation of border classes -//------------------------------------------------------------------------------------ - public static class ButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(4, 8, 4, 8); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Graphics2D g2D = (Graphics2D) g; - g.translate(x, y); - - Color hiFrameColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getButtonBackgroundColor(), 14); - Color frameColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getButtonBackgroundColor(), 6); - Color loFrameColor = ColorHelper.darker(AbstractLookAndFeel.getTheme().getButtonBackgroundColor(), 50); - - g.setColor(hiFrameColor); - g.drawLine(1, 0, w - 3, 0); - g.drawLine(0, 1, 0, h - 3); - g.setColor(frameColor); - g.drawLine(w - 2, 0, w - 2, h - 2); - g.drawLine(1, h - 2, w - 3, h - 2); - - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); - g2D.setComposite(alpha); - g2D.setColor(loFrameColor); - g.drawLine(1, 1, w - 3, 1); - g.drawLine(1, 2, 1, h - 3); - g.setColor(Color.black); - g.drawLine(w - 1, 1, w - 1, h - 1); - g.drawLine(1, h - 1, w - 1, h - 1); - alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f); - g2D.setComposite(alpha); - g.drawLine(1, h - 2, 2, h - 1); - g2D.setComposite(composite); - - g.translate(-x, -y); - } - - public Insets getBorderInsets(Component c) { - return insets; - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class ButtonBorder - -//------------------------------------------------------------------------------------------------- - public static class RolloverToolButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(2, 2, 2, 2); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - Color c1; - Color c2; - if (JTattooUtilities.isActive((JComponent) c)) { - c1 = ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 60); - c2 = AbstractLookAndFeel.getFrameColor(); - } else { - c1 = AbstractLookAndFeel.getFrameColor(); - c2 = ColorHelper.darker(AbstractLookAndFeel.getFrameColor(), 20); - } - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - JTattooUtilities.draw3DBorder(g, c1, c2, 0, 0, w, h); - alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f); - g2D.setComposite(alpha); - JTattooUtilities.draw3DBorder(g, c2, c1, 1, 1, w - 2, h - 2); - g2D.setComposite(composite); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class RolloverToolButtonBorder - -//------------------------------------------------------------------------------------------------- - public static class ScrollPaneBorder implements Border, UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Color frameColor = AbstractLookAndFeel.getTheme().getFrameColor(); - JTattooUtilities.draw3DBorder(g, frameColor, ColorHelper.brighter(frameColor, 10), x, y, w, h); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class ScrollPaneBorder - -//------------------------------------------------------------------------------------------------- - public static class TabbedPaneBorder implements Border, UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Color frameColor = AbstractLookAndFeel.getTheme().getFrameColor(); - JTattooUtilities.draw3DBorder(g, frameColor, ColorHelper.brighter(frameColor, 10), x, y, w, h); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class TabbedPaneBorder - -//------------------------------------------------------------------------------------------------- - public static class InternalFrameBorder extends BaseInternalFrameBorder { - - public InternalFrameBorder() { - insets.top = 3; - } - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - boolean active = isActive(c); - int th = getTitleHeight(c); - Color titleColor = AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors()[0]; - Color borderColor = AbstractLookAndFeel.getWindowInactiveTitleColorDark(); - Color frameColor = AbstractLookAndFeel.getWindowInactiveBorderColor(); - if (active) { - titleColor = AbstractLookAndFeel.getTheme().getWindowTitleColors()[0]; - borderColor = AbstractLookAndFeel.getWindowTitleColorDark(); - frameColor = AbstractLookAndFeel.getWindowBorderColor(); - } - g.setColor(titleColor); - g.fillRect(x, y + 1, w, insets.top - 1); - g.setColor(borderColor); - g.fillRect(x + 1, y + h - dw, w - 2, dw - 1); - if (active) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 1, insets.top, dw, th + 1); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), w - dw, insets.top, dw, th + 1); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 1, insets.top, dw - 1, th + 1); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), w - dw, insets.top, dw - 1, th + 1); - } - g.setColor(borderColor); - g.fillRect(1, insets.top + th + 1, dw - 1, h - th - dw); - g.fillRect(w - dw, insets.top + th + 1, dw - 1, h - th - dw); - g.setColor(frameColor); - g.drawRect(x, y, w - 1, h - 1); - } - } // class InternalFrameBorder - - public static class ToolBarBorder extends AbstractBorder implements UIResource, SwingConstants { - - private static final LazyImageIcon HOR_RUBBER_ICON = new LazyImageIcon("hifi/icons/HorRubber.gif"); - private static final LazyImageIcon VER_RUBBER_ICON = new LazyImageIcon("hifi/icons/VerRubber.gif"); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - if (((JToolBar) c).isFloatable()) { - if (((JToolBar) c).getOrientation() == HORIZONTAL) { - int x1 = 4; - int y1 = (h - HOR_RUBBER_ICON.getIconHeight()) / 2; - HOR_RUBBER_ICON.paintIcon(c, g, x1, y1); - } else { - int x1 = (w - VER_RUBBER_ICON.getIconWidth()) / 2 + 2; - int y1 = 4; - VER_RUBBER_ICON.paintIcon(c, g, x1, y1); - } - } - } - - public Insets getBorderInsets(Component c) { - Insets insets = new Insets(2, 2, 2, 2); - if (((JToolBar) c).isFloatable()) { - if (((JToolBar) c).getOrientation() == HORIZONTAL) { - if (JTattooUtilities.isLeftToRight(c)) { - insets.left = 15; - } else { - insets.right = 15; - } - } else { - insets.top = 15; - } - } - Insets margin = ((JToolBar) c).getMargin(); - if (margin != null) { - insets.left += margin.left; - insets.top += margin.top; - insets.right += margin.right; - insets.bottom += margin.bottom; - } - return insets; - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - Insets insets = getBorderInsets(c); - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - } // class ToolBarBorder -} // class HiFiBorders - diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiButtonUI.java deleted file mode 100644 index 0f65e617b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiButtonUI.java +++ /dev/null @@ -1,98 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.*; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.Rectangle2D; -import javax.swing.*; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class HiFiButtonUI extends BaseButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new HiFiButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - if (!b.isContentAreaFilled() || (b.getParent() instanceof JMenuBar)) { - return; - } - int width = b.getWidth(); - int height = b.getHeight(); - Graphics2D g2D = (Graphics2D) g; - Shape savedClip = g.getClip(); - if ((b.getBorder() != null) && b.isBorderPainted() && (b.getBorder() instanceof UIResource)) { - Area clipArea = new Area(new Rectangle2D.Double(1, 1, width - 2, height - 2)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - } - super.paintBackground(g, b); - g2D.setClip(savedClip); - } - - protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) { - ButtonModel model = b.getModel(); - FontMetrics fm = g.getFontMetrics(); - int mnemIndex; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = b.getDisplayedMnemonicIndex(); - } else { - mnemIndex = JTattooUtilities.findDisplayedMnemonicIndex(b.getText(), model.getMnemonic()); - } - int offs = 0; - if (model.isArmed() && model.isPressed()) { - offs = 1; - } - - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - Color fc = b.getForeground(); - if (fc instanceof ColorUIResource) { - if (model.isPressed() && model.isArmed()) { - fc = AbstractLookAndFeel.getTheme().getSelectionForegroundColor(); - } - } - if (!model.isEnabled()) { - fc = AbstractLookAndFeel.getTheme().getDisabledForegroundColor(); - } - if (ColorHelper.getGrayValue(fc) > 64) { - g2D.setColor(Color.black); - } else { - g2D.setColor(Color.white); - } - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x + offs + 1, textRect.y + offs + fm.getAscent() + 1); - g2D.setComposite(composite); - g2D.setColor(fc); - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x + offs, textRect.y + offs + fm.getAscent()); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiCheckBoxUI.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiCheckBoxUI.java deleted file mode 100644 index 31a8e7324..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiCheckBoxUI.java +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class HiFiCheckBoxUI extends HiFiRadioButtonUI { - - private static HiFiCheckBoxUI checkBoxUI = null; - - public static ComponentUI createUI(JComponent b) { - if (checkBoxUI == null) { - checkBoxUI = new HiFiCheckBoxUI(); - } - return checkBoxUI; - } - - public void installDefaults(AbstractButton b) { - super.installDefaults(b); - icon = UIManager.getIcon("CheckBox.icon"); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiComboBoxUI.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiComboBoxUI.java deleted file mode 100644 index 778bbdc52..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiComboBoxUI.java +++ /dev/null @@ -1,98 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.BaseComboBoxUI; -import com.jtattoo.plaf.NoFocusButton; -import java.awt.*; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.border.AbstractBorder; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class HiFiComboBoxUI extends BaseComboBoxUI { - - public static ComponentUI createUI(JComponent c) { - return new HiFiComboBoxUI(); - } - - public JButton createArrowButton() { - JButton button = new NoFocusButton(HiFiIcons.getComboBoxIcon()); - button.setBorder(new ArrowButtonBorder()); - return button; - } - - protected void setButtonBorder() { - } - -//-------------------------------------------------------------------------------------------------- - static class ArrowButtonBorder extends AbstractBorder { - - private static final Insets insets = new Insets(1, 3, 1, 2); - private static final Color frameLoColor = new Color(120, 120, 120); - private static final Color frameLowerColor = new Color(104, 104, 104); - private static final Color frameLowerLoColor = new Color(64, 64, 64); - private static final Color frameLowestColor = new Color(32, 32, 32); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Graphics2D g2D = (Graphics2D) g; - g.translate(x, y); - - g.setColor(frameLoColor); - g.drawLine(1, 0, w - 1, 0); - g.drawLine(1, 1, 1, h - 2); - g.setColor(frameLowerColor); - g.drawLine(w - 1, 1, w - 1, h - 2); - g.drawLine(2, h - 1, w - 2, h - 1); - - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); - g2D.setComposite(alpha); - g.setColor(frameLowestColor); - g.drawLine(2, 1, w - 2, 1); - g.drawLine(2, 2, 2, h - 3); - g.setColor(frameLowerLoColor); - g.drawLine(0, 0, 0, h); - g2D.setComposite(composite); - - g.translate(-x, -y); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiDefaultTheme.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiDefaultTheme.java deleted file mode 100644 index 2e01be888..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiDefaultTheme.java +++ /dev/null @@ -1,158 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.AbstractTheme; -import com.jtattoo.plaf.ColorHelper; -import java.awt.Color; -import java.awt.Font; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.FontUIResource; - -/** - * @author Michael Hagen - */ -public class HiFiDefaultTheme extends AbstractTheme { - - public HiFiDefaultTheme() { - super(); - // Setup theme with defaults - setUpColor(); - // Overwrite defaults with user props - loadProperties(); - // Setup the color arrays - setUpColorArrs(); - } - - public String getPropertyFileName() { - return "HiFiTheme.properties"; - } - - public void setUpColor() { - super.setUpColor(); - - // Defaults for HiFiLookAndFeel - textShadow = true; - foregroundColor = extraLightGray; - disabledForegroundColor = gray; - disabledBackgroundColor = new ColorUIResource(48, 48, 48); - - backgroundColor = new ColorUIResource(48, 48, 48); - backgroundColorLight = new ColorUIResource(48, 48, 48); - backgroundColorDark = new ColorUIResource(16, 16, 16); - alterBackgroundColor = new ColorUIResource(64, 64, 64); - selectionForegroundColor = white; - selectionBackgroundColor = new ColorUIResource(40, 40, 40); - frameColor = black; - gridColor = black; - focusCellColor = orange; - - inputBackgroundColor = new ColorUIResource(80, 80, 80); - inputForegroundColor = foregroundColor; - - rolloverColor = new ColorUIResource(112, 112, 112); - rolloverColorLight = new ColorUIResource(128, 128, 128); - rolloverColorDark = new ColorUIResource(96, 96, 96); - - buttonForegroundColor = foregroundColor; - buttonBackgroundColor = new ColorUIResource(96, 96, 96); - buttonColorLight = new ColorUIResource(96, 96, 96); - buttonColorDark = new ColorUIResource(32, 32, 32); - - controlForegroundColor = foregroundColor; - controlBackgroundColor = new ColorUIResource(64, 64, 64); // netbeans use this for selected tab in the toolbar - controlColorLight = new ColorUIResource(96, 96, 96); - controlColorDark = new ColorUIResource(32, 32, 32); - controlHighlightColor = new ColorUIResource(96, 96, 96); - controlShadowColor = new ColorUIResource(32, 32, 32); - controlDarkShadowColor = black; - - windowTitleForegroundColor = foregroundColor; - windowTitleBackgroundColor = new ColorUIResource(96, 96, 96); - windowTitleColorLight = new ColorUIResource(96, 96, 96); - windowTitleColorDark = new ColorUIResource(32, 32, 32);//new ColorUIResource(16, 16, 16); - windowBorderColor = black; - windowIconColor = lightGray; - windowIconShadowColor = black; - windowIconRolloverColor = orange; - - windowInactiveTitleForegroundColor = new ColorUIResource(196, 196, 196); - windowInactiveTitleBackgroundColor = new ColorUIResource(64, 64, 64); - windowInactiveTitleColorLight = new ColorUIResource(64, 64, 64); - windowInactiveTitleColorDark = new ColorUIResource(32, 32, 32); - windowInactiveBorderColor = black; - - menuForegroundColor = foregroundColor; - menuBackgroundColor = new ColorUIResource(32, 32, 32); - menuSelectionForegroundColor = white; - menuSelectionBackgroundColor = new ColorUIResource(96, 96, 96); - menuColorLight = new ColorUIResource(96, 96, 96); - menuColorDark = new ColorUIResource(32, 32, 32); - - toolbarBackgroundColor = new ColorUIResource(48, 48, 48); - toolbarColorLight = new ColorUIResource(96, 96, 96); - toolbarColorDark = new ColorUIResource(32, 32, 32); - - tabAreaBackgroundColor = backgroundColor; - tabSelectionForegroundColor = selectionForegroundColor; - - desktopColor = new ColorUIResource(64, 64, 64); - - tooltipForegroundColor = white; - tooltipBackgroundColor = new ColorUIResource(24, 24, 24); - - controlFont = new FontUIResource("Dialog", Font.BOLD, 12); - systemFont = new FontUIResource("Dialog", Font.BOLD, 12); - userFont = new FontUIResource("Dialog", Font.BOLD, 12); - menuFont = new FontUIResource("Dialog", Font.BOLD, 12); - windowTitleFont = new FontUIResource("Dialog", Font.BOLD, 12); - smallFont = new FontUIResource("Dialog", Font.PLAIN, 10); - } - - public void setUpColorArrs() { - super.setUpColorArrs(); - DEFAULT_COLORS = ColorHelper.createColorArr(controlColorLight, controlColorDark, 20); - HIDEFAULT_COLORS = ColorHelper.createColorArr(ColorHelper.brighter(controlColorLight, 15), ColorHelper.brighter(controlColorDark, 15), 20); - ACTIVE_COLORS = DEFAULT_COLORS; - INACTIVE_COLORS = ColorHelper.createColorArr(new Color(64, 64, 64), new Color(32, 32, 32), 20); - SELECTED_COLORS = HIDEFAULT_COLORS; - BUTTON_COLORS = ColorHelper.createColorArr(buttonColorLight, buttonColorDark, 20); - ROLLOVER_COLORS = HIDEFAULT_COLORS; - PRESSED_COLORS = ColorHelper.createColorArr(black, controlColorDark, 20); - - //DISABLED_COLORS = ColorHelper.createColorArr(ColorHelper.darker(controlColorLight, 10), ColorHelper.darker(controlColorDark, 10), 20); - DISABLED_COLORS = ColorHelper.createColorArr(ColorHelper.brighter(controlColorDark, 5), ColorHelper.darker(controlColorDark, 10), 20); - - WINDOW_TITLE_COLORS = ColorHelper.createColorArr(windowTitleColorLight, windowTitleColorDark, 20); - WINDOW_INACTIVE_TITLE_COLORS = ColorHelper.createColorArr(windowInactiveTitleColorLight, windowInactiveTitleColorDark, 20); - MENUBAR_COLORS = DEFAULT_COLORS; - TOOLBAR_COLORS = MENUBAR_COLORS; - TRACK_COLORS = ColorHelper.createColorArr(ColorHelper.darker(backgroundColor, 10), ColorHelper.brighter(backgroundColor, 5), 20); - SLIDER_COLORS = DEFAULT_COLORS; - PROGRESSBAR_COLORS = DEFAULT_COLORS; - THUMB_COLORS = DEFAULT_COLORS; - TAB_COLORS = DEFAULT_COLORS; - COL_HEADER_COLORS = DEFAULT_COLORS; - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiIconFactory.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiIconFactory.java deleted file mode 100644 index a02411d36..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiIconFactory.java +++ /dev/null @@ -1,213 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.AbstractIconFactory; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class HiFiIconFactory implements AbstractIconFactory { - - private static HiFiIconFactory instance = null; - - private HiFiIconFactory() { - } - - public static synchronized HiFiIconFactory getInstance() { - if (instance == null) { - instance = new HiFiIconFactory(); - } - return instance; - } - - public Icon getOptionPaneErrorIcon() { - return HiFiIcons.getOptionPaneErrorIcon(); - } - - public Icon getOptionPaneWarningIcon() { - return HiFiIcons.getOptionPaneWarningIcon(); - } - - public Icon getOptionPaneInformationIcon() { - return HiFiIcons.getOptionPaneInformationIcon(); - } - - public Icon getOptionPaneQuestionIcon() { - return HiFiIcons.getOptionPaneQuestionIcon(); - } - - public Icon getFileChooserDetailViewIcon() { - return HiFiIcons.getFileChooserDetailViewIcon(); - } - - public Icon getFileChooserHomeFolderIcon() { - return HiFiIcons.getFileChooserHomeFolderIcon(); - } - - public Icon getFileChooserListViewIcon() { - return HiFiIcons.getFileChooserListViewIcon(); - } - - public Icon getFileChooserNewFolderIcon() { - return HiFiIcons.getFileChooserNewFolderIcon(); - } - - public Icon getFileChooserUpFolderIcon() { - return HiFiIcons.getFileChooserUpFolderIcon(); - } - - public Icon getMenuIcon() { - return HiFiIcons.getMenuIcon(); - } - - public Icon getIconIcon() { - return HiFiIcons.getIconIcon(); - } - - public Icon getMaxIcon() { - return HiFiIcons.getMaxIcon(); - } - - public Icon getMinIcon() { - return HiFiIcons.getMinIcon(); - } - - public Icon getCloseIcon() { - return HiFiIcons.getCloseIcon(); - } - - public Icon getPaletteCloseIcon() { - return HiFiIcons.getPaletteCloseIcon(); - } - - public Icon getRadioButtonIcon() { - return HiFiIcons.getRadioButtonIcon(); - } - - public Icon getCheckBoxIcon() { - return HiFiIcons.getCheckBoxIcon(); - } - - public Icon getComboBoxIcon() { - return HiFiIcons.getComboBoxIcon(); - } - - public Icon getTreeComputerIcon() { - return HiFiIcons.getTreeComputerIcon(); - } - - public Icon getTreeFloppyDriveIcon() { - return HiFiIcons.getTreeFloppyDriveIcon(); - } - - public Icon getTreeHardDriveIcon() { - return HiFiIcons.getTreeHardDriveIcon(); - } - - public Icon getTreeFolderIcon() { - return HiFiIcons.getTreeFolderIcon(); - } - - public Icon getTreeLeafIcon() { - return HiFiIcons.getTreeLeafIcon(); - } - - public Icon getTreeCollapsedIcon() { - return HiFiIcons.getTreeControlIcon(true); - } - - public Icon getTreeExpandedIcon() { - return HiFiIcons.getTreeControlIcon(false); - } - - public Icon getMenuArrowIcon() { - return HiFiIcons.getMenuArrowIcon(); - } - - public Icon getMenuCheckBoxIcon() { - return HiFiIcons.getMenuCheckBoxIcon(); - } - - public Icon getMenuRadioButtonIcon() { - return HiFiIcons.getMenuRadioButtonIcon(); - } - - public Icon getUpArrowIcon() { - return HiFiIcons.getUpArrowIcon(); - } - - public Icon getDownArrowIcon() { - return HiFiIcons.getDownArrowIcon(); - } - - public Icon getLeftArrowIcon() { - return HiFiIcons.getLeftArrowIcon(); - } - - public Icon getRightArrowIcon() { - return HiFiIcons.getRightArrowIcon(); - } - - public Icon getSplitterDownArrowIcon() { - return HiFiIcons.getSplitterDownArrowIcon(); - } - - public Icon getSplitterHorBumpIcon() { - return HiFiIcons.getSplitterHorBumpIcon(); - } - - public Icon getSplitterLeftArrowIcon() { - return HiFiIcons.getSplitterLeftArrowIcon(); - } - - public Icon getSplitterRightArrowIcon() { - return HiFiIcons.getSplitterRightArrowIcon(); - } - - public Icon getSplitterUpArrowIcon() { - return HiFiIcons.getSplitterUpArrowIcon(); - } - - public Icon getSplitterVerBumpIcon() { - return HiFiIcons.getSplitterVerBumpIcon(); - } - - public Icon getThumbHorIcon() { - return HiFiIcons.getThumbHorIcon(); - } - - public Icon getThumbVerIcon() { - return HiFiIcons.getThumbVerIcon(); - } - - public Icon getThumbHorIconRollover() { - return HiFiIcons.getThumbHorIconRollover(); - } - - public Icon getThumbVerIconRollover() { - return HiFiIcons.getThumbVerIconRollover(); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiIcons.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiIcons.java deleted file mode 100644 index 105782b73..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiIcons.java +++ /dev/null @@ -1,385 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.*; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.Ellipse2D; -import java.io.Serializable; -import javax.swing.*; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class HiFiIcons extends BaseIcons { - - public static Icon getIconIcon() { - if (iconIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - iconIcon = new MacIconIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - iconIcon = new BaseIcons.IconSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(-1, -1, 0, 0)); - } - } - return iconIcon; - } - - public static Icon getMinIcon() { - if (minIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - minIcon = new MacMinIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - minIcon = new BaseIcons.MinSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(-1, -1, 0, 0)); - } - } - return minIcon; - } - - public static Icon getMaxIcon() { - if (maxIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - maxIcon = new MacMaxIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - maxIcon = new BaseIcons.MaxSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(-1, -1, 0, 0)); - } - } - return maxIcon; - } - - public static Icon getCloseIcon() { - if (closeIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - closeIcon = new MacCloseIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - closeIcon = new BaseIcons.CloseSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(-1, -1, 0, 0)); - } - } - return closeIcon; - } - - public static Icon getRadioButtonIcon() { - if (radioButtonIcon == null) { - radioButtonIcon = new RadioButtonIcon(); - } - return radioButtonIcon; - } - - public static Icon getCheckBoxIcon() { - if (checkBoxIcon == null) { - checkBoxIcon = new CheckBoxIcon(); - } - return checkBoxIcon; - } - - public static Icon getTreeControlIcon(boolean isCollapsed) { - if (isCollapsed) { - if (treeClosedIcon == null) { - treeClosedIcon = new LazyImageIcon("hifi/icons/TreeClosedButton.gif"); - } - return treeClosedIcon; - } else { - if (treeOpenIcon == null) { - treeOpenIcon = new LazyImageIcon("hifi/icons/TreeOpenButton.gif"); - } - return treeOpenIcon; - } - } - - public static Icon getMenuArrowIcon() { - if (menuArrowIcon == null) { - menuArrowIcon = new LazyMenuArrowImageIcon("hifi/icons/RightArrow.gif", "hifi/icons/LeftArrow.gif"); - } - return menuArrowIcon; - } - - public static Icon getComboBoxIcon() { - return getDownArrowIcon(); - } - - public static Icon getSplitterUpArrowIcon() { - if (splitterUpArrowIcon == null) { - splitterUpArrowIcon = new LazyImageIcon("hifi/icons/SplitterUpArrow.gif"); - } - return splitterUpArrowIcon; - } - - public static Icon getSplitterDownArrowIcon() { - if (splitterDownArrowIcon == null) { - splitterDownArrowIcon = new LazyImageIcon("hifi/icons/SplitterDownArrow.gif"); - } - return splitterDownArrowIcon; - } - - public static Icon getSplitterLeftArrowIcon() { - if (splitterLeftArrowIcon == null) { - splitterLeftArrowIcon = new LazyImageIcon("hifi/icons/SplitterLeftArrow.gif"); - } - return splitterLeftArrowIcon; - } - - public static Icon getSplitterRightArrowIcon() { - if (splitterRightArrowIcon == null) { - splitterRightArrowIcon = new LazyImageIcon("hifi/icons/SplitterRightArrow.gif"); - } - return splitterRightArrowIcon; - } - - public static Icon getSplitterHorBumpIcon() { - if (splitterHorBumpIcon == null) { - splitterHorBumpIcon = new LazyImageIcon("hifi/icons/SplitterHorBumps.gif"); - } - return splitterHorBumpIcon; - } - - public static Icon getSplitterVerBumpIcon() { - if (splitterVerBumpIcon == null) { - splitterVerBumpIcon = new LazyImageIcon("hifi/icons/SplitterVerBumps.gif"); - } - return splitterVerBumpIcon; - } - - public static Icon getThumbHorIcon() { - if (thumbHorIcon == null) { - thumbHorIcon = new LazyImageIcon("hifi/icons/thumb_hor.gif"); - } - return thumbHorIcon; - } - - public static Icon getThumbVerIcon() { - if (thumbVerIcon == null) { - thumbVerIcon = new LazyImageIcon("hifi/icons/thumb_ver.gif"); - } - return thumbVerIcon; - } - - public static Icon getThumbHorIconRollover() { - if (thumbHorIconRollover == null) { - thumbHorIconRollover = new LazyImageIcon("hifi/icons/thumb_hor_rollover.gif"); - } - return thumbHorIconRollover; - } - - public static Icon getThumbVerIconRollover() { - if (thumbVerIconRollover == null) { - thumbVerIconRollover = new LazyImageIcon("hifi/icons/thumb_ver_rollover.gif"); - } - return thumbVerIconRollover; - } - //-------------------------------------------------------------------------------------------------------- - - private static class CheckBoxIcon implements Icon, UIResource, Serializable { - - private static Icon checkIcon = new LazyImageIcon("hifi/icons/CheckSymbol.gif"); - private static Icon checkPressedIcon = new LazyImageIcon("hifi/icons/CheckPressedSymbol.gif"); - private static Icon baseCheckIcon = new LazyImageIcon("icons/CheckSymbol.gif"); - - private final int WIDTH = 17; - private final int HEIGHT = 17; - - public void paintIcon(Component c, Graphics g, int x, int y) { - if (!JTattooUtilities.isLeftToRight(c)) { - x += 4; - } - - g.translate(x, y); - - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - Graphics2D g2D = (Graphics2D) g; - - boolean isRollover = button.isRolloverEnabled() && model.isRollover(); - Color colors[]; - if (button.isEnabled()) { - if (isRollover) { - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - } else if (model.isPressed()) { - colors = AbstractLookAndFeel.getTheme().getPressedColors(); - } else { - colors = AbstractLookAndFeel.getTheme().getButtonColors(); - } - } else { - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } - JTattooUtilities.fillHorGradient(g, colors, 1, 1, WIDTH - 1, HEIGHT - 1); - - Color hiFrameColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getButtonBackgroundColor(), 14); - Color frameColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getButtonBackgroundColor(), 6); - Color loFrameColor = ColorHelper.darker(AbstractLookAndFeel.getTheme().getButtonBackgroundColor(), 50); - - g.setColor(hiFrameColor); - g.drawLine(1, 0, WIDTH - 3, 0); - g.drawLine(0, 1, 0, HEIGHT - 3); - g.setColor(frameColor); - g.drawLine(WIDTH - 2, 1, WIDTH - 2, HEIGHT - 3); - g.drawLine(1, HEIGHT - 2, WIDTH - 3, HEIGHT - 2); - - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); - g2D.setComposite(alpha); - g2D.setColor(loFrameColor); - g.drawLine(1, 1, WIDTH - 3, 1); - g.drawLine(1, 2, 1, HEIGHT - 3); - g.setColor(Color.black); - g.drawLine(WIDTH - 1, 1, WIDTH - 1, HEIGHT - 1); - g.drawLine(1, HEIGHT - 1, WIDTH - 1, HEIGHT - 1); - alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f); - g2D.setComposite(alpha); - g.drawLine(1, HEIGHT - 2, 2, HEIGHT - 1); - g2D.setComposite(composite); - - int xi = ((WIDTH - checkIcon.getIconWidth()) / 2); - int yi = ((HEIGHT - checkIcon.getIconHeight()) / 2); - if (model.isPressed() && model.isArmed()) { - checkPressedIcon.paintIcon(c, g, xi, yi); - } else if (model.isSelected()) { - if (ColorHelper.getGrayValue(AbstractLookAndFeel.getButtonForegroundColor()) > 128) { - checkIcon.paintIcon(c, g, xi, yi); - } else { - baseCheckIcon.paintIcon(c, g, xi, yi); - } - } - g.translate(-x, -y); - } - - public int getIconWidth() { - return WIDTH + 4; - } - - public int getIconHeight() { - return HEIGHT; - } - } - - private static class RadioButtonIcon implements Icon, UIResource, Serializable { - - private static Icon radioIcon = new LazyImageIcon("hifi/icons/RadioSymbol.gif"); - private static Icon baseRadioIcon = new LazyImageIcon("icons/RadioSymbol.gif"); - private final int WIDTH = 16; - private final int HEIGHT = 16; - - public void paintIcon(Component c, Graphics g, int x, int y) { - if (!JTattooUtilities.isLeftToRight(c)) { - x += 4; - } - - Graphics2D g2D = (Graphics2D) g; - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - boolean isRollover = button.isRolloverEnabled() && model.isRollover(); - Color colors[]; - if (button.isEnabled()) { - if (model.isPressed()) { - colors = AbstractLookAndFeel.getTheme().getPressedColors(); - } else if (isRollover) { - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - } else { - colors = AbstractLookAndFeel.getTheme().getButtonColors(); - } - } else { - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } - Color hiFrameColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getButtonBackgroundColor(), 20); - Color loFrameColor = ColorHelper.darker(AbstractLookAndFeel.getTheme().getButtonBackgroundColor(), 60); - - Shape savedClip = g.getClip(); - Area clipArea = new Area(new Ellipse2D.Double(x, y, WIDTH + 1, HEIGHT + 1)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - JTattooUtilities.fillHorGradient(g, colors, x, y, WIDTH, HEIGHT); - g2D.setClip(savedClip); - - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - if (ColorHelper.getGrayValue(AbstractLookAndFeel.getButtonForegroundColor()) > 128) { - g.setColor(hiFrameColor); - g.drawOval(x, y, WIDTH, HEIGHT); - } else { - g.setColor(loFrameColor); - g.drawOval(x - 1, y - 1, WIDTH + 2, HEIGHT + 2); - g.drawOval(x, y, WIDTH, HEIGHT); - } - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - - if (model.isSelected()) { - int xi = x + ((WIDTH - radioIcon.getIconWidth()) / 2) + 1; - int yi = y + ((HEIGHT - radioIcon.getIconHeight()) / 2) + 1; - if (ColorHelper.getGrayValue(AbstractLookAndFeel.getButtonForegroundColor()) > 128) { - radioIcon.paintIcon(c, g, xi, yi); - } else { - baseRadioIcon.paintIcon(c, g, xi, yi); - } - } - } - - public int getIconWidth() { - return WIDTH + 4; - } - - public int getIconHeight() { - return HEIGHT; - } - } - - public static Icon getUpArrowIcon() { - if (upArrowIcon == null) { - upArrowIcon = new LazyImageIcon("hifi/icons/UpArrow.gif"); - } - return upArrowIcon; - } - - public static Icon getDownArrowIcon() { - if (downArrowIcon == null) { - downArrowIcon = new LazyImageIcon("hifi/icons/DownArrow.gif"); - } - return downArrowIcon; - } - - public static Icon getLeftArrowIcon() { - if (leftArrowIcon == null) { - leftArrowIcon = new LazyImageIcon("hifi/icons/LeftArrow.gif"); - } - return leftArrowIcon; - } - - public static Icon getRightArrowIcon() { - if (rightArrowIcon == null) { - rightArrowIcon = new LazyImageIcon("hifi/icons/RightArrow.gif"); - } - return rightArrowIcon; - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiInternalFrameTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiInternalFrameTitlePane.java deleted file mode 100644 index 679c7f4df..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiInternalFrameTitlePane.java +++ /dev/null @@ -1,56 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.JInternalFrame; - -/** - * @author Michael Hagen - */ -public class HiFiInternalFrameTitlePane extends BaseInternalFrameTitlePane { - - public HiFiInternalFrameTitlePane(JInternalFrame f) { - super(f); - } - - public void paintText(Graphics g, int x, int y, String title) { - if (isMacStyleWindowDecoration()) { - x += paintIcon(g, x, y) + 5; - } - g.setColor(Color.black); - JTattooUtilities.drawString(frame, g, title, x + 1, y); - if (isActive()) { - g.setColor(AbstractLookAndFeel.getWindowTitleForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - } - JTattooUtilities.drawString(frame, g, title, x, y - 1); - } - - public void paintBorder(Graphics g) { - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiInternalFrameUI.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiInternalFrameUI.java deleted file mode 100644 index 3d946e467..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiInternalFrameUI.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.BaseInternalFrameUI; -import javax.swing.JComponent; -import javax.swing.JInternalFrame; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class HiFiInternalFrameUI extends BaseInternalFrameUI { - - public HiFiInternalFrameUI(JInternalFrame b) { - super(b); - } - - public static ComponentUI createUI(JComponent c) { - return new HiFiInternalFrameUI((JInternalFrame) c); - } - - protected JComponent createNorthPane(JInternalFrame w) { - titlePane = new HiFiInternalFrameTitlePane(w); - return titlePane; - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiLabelUI.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiLabelUI.java deleted file mode 100644 index c981bcc90..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiLabelUI.java +++ /dev/null @@ -1,77 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicLabelUI; - -/** - * @author Michael Hagen - */ -public class HiFiLabelUI extends BasicLabelUI { - - private static HiFiLabelUI hifiLabelUI = null; - - public static ComponentUI createUI(JComponent c) { - if (hifiLabelUI == null) { - hifiLabelUI = new HiFiLabelUI(); - } - return hifiLabelUI; - } - - protected void paintEnabledText(JLabel l, Graphics g, String s, int textX, int textY) { - int mnemIndex; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = l.getDisplayedMnemonicIndex(); - } else { - mnemIndex = JTattooUtilities.findDisplayedMnemonicIndex(l.getText(), l.getDisplayedMnemonic()); - } - Color fc = l.getForeground(); - if (AbstractLookAndFeel.getTheme().isTextShadowOn() && ColorHelper.getGrayValue(fc) > 128) { - g.setColor(Color.black); - JTattooUtilities.drawStringUnderlineCharAt(l, g, s, mnemIndex, textX + 1, textY + 1); - } - g.setColor(fc); - JTattooUtilities.drawStringUnderlineCharAt(l, g, s, mnemIndex, textX, textY); - } - - protected void paintDisabledText(JLabel l, Graphics g, String s, int textX, int textY) { - int mnemIndex; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = l.getDisplayedMnemonicIndex(); - } else { - mnemIndex = JTattooUtilities.findDisplayedMnemonicIndex(l.getText(), l.getDisplayedMnemonic()); - } - g.setColor(Color.black); - JTattooUtilities.drawStringUnderlineCharAt(l, g, s, mnemIndex, textX + 1, textY + 1); - g.setColor(AbstractLookAndFeel.getDisabledForegroundColor()); - JTattooUtilities.drawStringUnderlineCharAt(l, g, s, mnemIndex, textX, textY); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiLookAndFeel.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiLookAndFeel.java deleted file mode 100644 index 35c651c43..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiLookAndFeel.java +++ /dev/null @@ -1,207 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.*; -import java.util.*; -import javax.swing.UIDefaults; - -/** - * @author Michael Hagen - */ -public class HiFiLookAndFeel extends AbstractLookAndFeel { - - private static HiFiDefaultTheme myTheme = null; - - private static final ArrayList themesList = new ArrayList(); - private static final HashMap themesMap = new HashMap(); - private static final Properties defaultProps = new Properties(); - private static final Properties smallFontProps = new Properties(); - private static final Properties largeFontProps = new Properties(); - private static final Properties giantFontProps = new Properties(); - - static { - smallFontProps.setProperty("controlTextFont", "Dialog bold 10"); - smallFontProps.setProperty("systemTextFont", "Dialog bold 10"); - smallFontProps.setProperty("userTextFont", "Dialog 10"); - smallFontProps.setProperty("menuTextFont", "Dialog bold 10"); - smallFontProps.setProperty("windowTitleFont", "Dialog bold 10"); - smallFontProps.setProperty("subTextFont", "Dialog 8"); - - largeFontProps.setProperty("controlTextFont", "Dialog bold 14"); - largeFontProps.setProperty("systemTextFont", "Dialog bold 14"); - largeFontProps.setProperty("userTextFont", "Dialog bold 14"); - largeFontProps.setProperty("menuTextFont", "Dialog bold 14"); - largeFontProps.setProperty("windowTitleFont", "Dialog bold 14"); - largeFontProps.setProperty("subTextFont", "Dialog 12"); - - giantFontProps.setProperty("controlTextFont", "Dialog 18"); - giantFontProps.setProperty("systemTextFont", "Dialog 18"); - giantFontProps.setProperty("userTextFont", "Dialog 18"); - giantFontProps.setProperty("menuTextFont", "Dialog 18"); - giantFontProps.setProperty("windowTitleFont", "Dialog 18"); - giantFontProps.setProperty("subTextFont", "Dialog 16"); - - themesList.add("Default"); - themesList.add("Small-Font"); - themesList.add("Large-Font"); - themesList.add("Giant-Font"); - - themesMap.put("Default", defaultProps); - themesMap.put("Small-Font", smallFontProps); - themesMap.put("Large-Font", largeFontProps); - themesMap.put("Giant-Font", giantFontProps); - } - - public static java.util.List getThemes() { - return themesList; - } - - public static Properties getThemeProperties(String name) { - return ((Properties) themesMap.get(name)); - } - - public static void setTheme(String name) { - setTheme((Properties) themesMap.get(name)); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - - public static void setTheme(String name, String licenseKey, String logoString) { - Properties props = (Properties) themesMap.get(name); - if (props != null) { - props.put("licenseKey", licenseKey); - props.put("logoString", logoString); - setTheme(props); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - } - - public static void setTheme(Properties themesProps) { - if (myTheme == null) { - myTheme = new HiFiDefaultTheme(); - } - if ((myTheme != null) && (themesProps != null)) { - myTheme.setUpColor(); - myTheme.setProperties(themesProps); - myTheme.setUpColorArrs(); - AbstractLookAndFeel.setTheme(myTheme); - } - } - - public static void setCurrentTheme(Properties themesProps) { - setTheme(themesProps); - } - - public String getName() { - return "HiFi"; - } - - public String getID() { - return "HiFi"; - } - - public String getDescription() { - return "The HiFi Look and Feel"; - } - - public boolean isNativeLookAndFeel() { - return false; - } - - public boolean isSupportedLookAndFeel() { - return true; - } - - public AbstractBorderFactory getBorderFactory() { - return HiFiBorderFactory.getInstance(); - } - - public AbstractIconFactory getIconFactory() { - return HiFiIconFactory.getInstance(); - } - - protected void createDefaultTheme() { - if (myTheme == null) { - myTheme = new HiFiDefaultTheme(); - } - setTheme(myTheme); - } - - protected void initComponentDefaults(UIDefaults table) { - super.initComponentDefaults(table); - table.put("ScrollBar.incrementButtonGap", new Integer(-1)); - table.put("ScrollBar.decrementButtonGap", new Integer(-1)); - } - - protected void initClassDefaults(UIDefaults table) { - super.initClassDefaults(table); - Object[] uiDefaults = { - // BaseLookAndFeel classes - "SeparatorUI", BaseSeparatorUI.class.getName(), - "TextFieldUI", BaseTextFieldUI.class.getName(), - "TextAreaUI", BaseTextAreaUI.class.getName(), - "EditorPaneUI", BaseEditorPaneUI.class.getName(), - "PasswordFieldUI", BasePasswordFieldUI.class.getName(), - "ToolTipUI", BaseToolTipUI.class.getName(), - "TreeUI", BaseTreeUI.class.getName(), - "TableUI", BaseTableUI.class.getName(), - "TableHeaderUI", BaseTableHeaderUI.class.getName(), - "SplitPaneUI", BaseSplitPaneUI.class.getName(), - "ProgressBarUI", BaseProgressBarUI.class.getName(), - "FileChooserUI", BaseFileChooserUI.class.getName(), - "MenuUI", BaseMenuUI.class.getName(), - "PopupMenuUI", BasePopupMenuUI.class.getName(), - "MenuItemUI", BaseMenuItemUI.class.getName(), - "CheckBoxMenuItemUI", BaseCheckBoxMenuItemUI.class.getName(), - "RadioButtonMenuItemUI", BaseRadioButtonMenuItemUI.class.getName(), - "PopupMenuSeparatorUI", BaseSeparatorUI.class.getName(), - "DesktopPaneUI", BaseDesktopPaneUI.class.getName(), - - // HiFiLookAndFeel classes - "LabelUI", HiFiLabelUI.class.getName(), - "CheckBoxUI", HiFiCheckBoxUI.class.getName(), - "RadioButtonUI", HiFiRadioButtonUI.class.getName(), - "ButtonUI", HiFiButtonUI.class.getName(), - "ToggleButtonUI", HiFiToggleButtonUI.class.getName(), - "ComboBoxUI", HiFiComboBoxUI.class.getName(), - "SliderUI", HiFiSliderUI.class.getName(), - "PanelUI", HiFiPanelUI.class.getName(), - "ScrollPaneUI", HiFiScrollPaneUI.class.getName(), - "TabbedPaneUI", HiFiTabbedPaneUI.class.getName(), - "ScrollBarUI", HiFiScrollBarUI.class.getName(), - "ToolBarUI", HiFiToolBarUI.class.getName(), - "MenuBarUI", HiFiMenuBarUI.class.getName(), - "InternalFrameUI", HiFiInternalFrameUI.class.getName(), - "RootPaneUI", HiFiRootPaneUI.class.getName(),}; - table.putDefaults(uiDefaults); - if (JTattooUtilities.getJavaVersion() >= 1.5) { - table.put("FormattedTextFieldUI", BaseFormattedTextFieldUI.class.getName()); - table.put("SpinnerUI", BaseSpinnerUI.class.getName()); - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiMenuBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiMenuBarUI.java deleted file mode 100644 index 1fddb7743..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiMenuBarUI.java +++ /dev/null @@ -1,52 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.JMenuBar; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicMenuBarUI; - - -/** - * @author Michael Hagen - */ -public class HiFiMenuBarUI extends BasicMenuBarUI { - - public static ComponentUI createUI(JComponent c) { - return new HiFiMenuBarUI(); - } - - public void installUI(JComponent c) { - super.installUI(c); - if ((c != null) && (c instanceof JMenuBar)) { - c.setBorder(HiFiBorders.getMenuBarBorder()); - } - } - - public void paint(Graphics g, JComponent c) { - HiFiUtils.fillComponent(g, c); - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiPanelUI.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiPanelUI.java deleted file mode 100644 index bb063bb16..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiPanelUI.java +++ /dev/null @@ -1,53 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.BasePanelUI; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class HiFiPanelUI extends BasePanelUI { - - private static HiFiPanelUI panelUI = null; - - public static ComponentUI createUI(JComponent c) { - if (panelUI == null) { - panelUI = new HiFiPanelUI(); - } - return panelUI; - } - - public void update(Graphics g, JComponent c) { - if (c.isOpaque() && c.getBackground() instanceof ColorUIResource && c.getClientProperty("backgroundTexture") == null) { - HiFiUtils.fillComponent(g, c); - } else { - super.update(g, c); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiRadioButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiRadioButtonUI.java deleted file mode 100644 index 745a25f46..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiRadioButtonUI.java +++ /dev/null @@ -1,91 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicHTML; -import javax.swing.text.View; - -/** - * @author Michael Hagen - */ -public class HiFiRadioButtonUI extends BaseRadioButtonUI { - - private static HiFiRadioButtonUI radioButtonUI = null; - - public static ComponentUI createUI(JComponent c) { - if (radioButtonUI == null) { - radioButtonUI = new HiFiRadioButtonUI(); - } - return radioButtonUI; - } - - protected void paintText(Graphics g, JComponent c, String text, Rectangle textRect) { - View v = (View) c.getClientProperty(BasicHTML.propertyKey); - if (v != null) { - v.paint(g, textRect); - } else { - AbstractButton b = (AbstractButton) c; - ButtonModel model = b.getModel(); - int mnemIndex; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = b.getDisplayedMnemonicIndex(); - } else { - mnemIndex = JTattooUtilities.findDisplayedMnemonicIndex(b.getText(), model.getMnemonic()); - } - Font f = c.getFont(); - g.setFont(f); - FontMetrics fm = g.getFontMetrics(); - if (model.isEnabled()) { - Color fc = b.getForeground(); - if (AbstractLookAndFeel.getTheme().isTextShadowOn() && ColorHelper.getGrayValue(fc) > 128) { - g.setColor(Color.black); - JTattooUtilities.drawStringUnderlineCharAt(c, g, text, mnemIndex, textRect.x + 1, textRect.y + 1 + fm.getAscent()); - } - g.setColor(fc); - JTattooUtilities.drawStringUnderlineCharAt(c, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); - } else { - g.setColor(Color.black); - JTattooUtilities.drawStringUnderlineCharAt(c, g, text, mnemIndex, textRect.x + 1, textRect.y + 1 + fm.getAscent()); - g.setColor(AbstractLookAndFeel.getDisabledForegroundColor()); - JTattooUtilities.drawStringUnderlineCharAt(c, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); - } - } - } - - public void paintBackground(Graphics g, JComponent c) { - if (c.isOpaque()) { - if ((c.getBackground().equals(AbstractLookAndFeel.getBackgroundColor())) && (c.getBackground() instanceof ColorUIResource)) { - HiFiUtils.fillComponent(g, c); - } else { - g.setColor(c.getBackground()); - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiRootPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiRootPaneUI.java deleted file mode 100644 index 68a3e282b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiRootPaneUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.BaseRootPaneUI; -import com.jtattoo.plaf.BaseTitlePane; -import javax.swing.JComponent; -import javax.swing.JRootPane; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class HiFiRootPaneUI extends BaseRootPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new HiFiRootPaneUI(); - } - - public BaseTitlePane createTitlePane(JRootPane root) { - return new HiFiTitlePane(root, this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiScrollBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiScrollBarUI.java deleted file mode 100644 index b80004400..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiScrollBarUI.java +++ /dev/null @@ -1,72 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; - -/** - * - * @author Michael Hagen - */ -public class HiFiScrollBarUI extends XPScrollBarUI { - - public static ComponentUI createUI(JComponent c) { - return new HiFiScrollBarUI(); - } - - protected void installDefaults() { - super.installDefaults(); - Color colors[] = AbstractLookAndFeel.getTheme().getThumbColors(); - rolloverColors = new Color[colors.length]; - dragColors = new Color[colors.length]; - for (int i = 0; i < colors.length; i++) { - rolloverColors[i] = ColorHelper.brighter(colors[i], 8); - dragColors[i] = ColorHelper.darker(colors[i], 8); - } - } - - protected JButton createDecreaseButton(int orientation) { - return new HiFiScrollButton(orientation, scrollBarWidth); - } - - protected JButton createIncreaseButton(int orientation) { - return new HiFiScrollButton(orientation, scrollBarWidth); - } - - protected Color getFrameColor() { - Color frameColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getButtonBackgroundColor(), 8); - if (isDragging) { - return ColorHelper.darker(frameColor, 8); - } else if (isRollover) { - return ColorHelper.brighter(frameColor, 16); - } else { - return frameColor; - } - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiScrollButton.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiScrollButton.java deleted file mode 100644 index 03fb42ac7..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiScrollButton.java +++ /dev/null @@ -1,83 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class HiFiScrollButton extends XPScrollButton { - - protected static Icon upArrowIcon = null; - protected static Icon downArrowIcon = null; - protected static Icon leftArrowIcon = null; - protected static Icon rightArrowIcon = null; - - public HiFiScrollButton(int direction, int width) { - super(direction, width); - } - - public Icon getUpArrowIcon() { - if (upArrowIcon == null) { - upArrowIcon = new LazyImageIcon("hifi/icons/UpArrow.gif"); - } - return upArrowIcon; - } - - public Icon getDownArrowIcon() { - if (downArrowIcon == null) { - downArrowIcon = new LazyImageIcon("hifi/icons/DownArrow.gif"); - } - return downArrowIcon; - } - - public Icon getLeftArrowIcon() { - if (leftArrowIcon == null) { - leftArrowIcon = new LazyImageIcon("hifi/icons/LeftArrow.gif"); - } - return leftArrowIcon; - } - - public Icon getRightArrowIcon() { - if (rightArrowIcon == null) { - rightArrowIcon = new LazyImageIcon("hifi/icons/RightArrow.gif"); - } - return rightArrowIcon; - } - - public Color getFrameColor() { - Color frameColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getButtonBackgroundColor(), 8); - if (getModel().isPressed()) { - return ColorHelper.darker(frameColor, 8); - } else if (getModel().isRollover()) { - return ColorHelper.brighter(frameColor, 16); - } else { - return frameColor; - } - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiScrollPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiScrollPaneUI.java deleted file mode 100644 index af9734314..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiScrollPaneUI.java +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.BaseScrollPaneUI; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class HiFiScrollPaneUI extends BaseScrollPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new HiFiScrollPaneUI(); - } - - public void installDefaults(JScrollPane p) { - super.installDefaults(p); - p.getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiSliderUI.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiSliderUI.java deleted file mode 100644 index f245cf070..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiSliderUI.java +++ /dev/null @@ -1,62 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.BaseSliderUI; -import java.awt.Component; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.JSlider; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class HiFiSliderUI extends BaseSliderUI { - - public HiFiSliderUI(JSlider slider) { - super(slider); - } - - public static ComponentUI createUI(JComponent c) { - return new HiFiSliderUI((JSlider) c); - } - - public void paintBackground(Graphics g, JComponent c) { - if (c.isOpaque()) { - Component parent = c.getParent(); - if ((parent != null) && (parent.getBackground() instanceof ColorUIResource)) { - HiFiUtils.fillComponent(g, c); - } else { - if (parent != null) { - g.setColor(parent.getBackground()); - } else { - g.setColor(c.getBackground()); - } - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiTabbedPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiTabbedPaneUI.java deleted file mode 100644 index 91ec0fb42..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiTabbedPaneUI.java +++ /dev/null @@ -1,103 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.text.View; - -/** - * @author Michael Hagen - */ -public class HiFiTabbedPaneUI extends BaseTabbedPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new HiFiTabbedPaneUI(); - } - - protected Color[] getContentBorderColors(int tabPlacement) { - Color SEP_COLORS[] = { - ColorHelper.darker(AbstractLookAndFeel.getBackgroundColor(), 40), - ColorHelper.brighter(AbstractLookAndFeel.getBackgroundColor(), 20), - ColorHelper.darker(AbstractLookAndFeel.getBackgroundColor(), 20), - ColorHelper.darker(AbstractLookAndFeel.getBackgroundColor(), 40), - ColorHelper.darker(AbstractLookAndFeel.getBackgroundColor(), 60), - }; - return SEP_COLORS; - } - - protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected) { - Color backColor = tabPane.getBackgroundAt(tabIndex); - if (!(backColor instanceof UIResource)) { - super.paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected); - return; - } - g.setFont(font); - View v = getTextViewForTab(tabIndex); - if (v != null) { - // html - Graphics2D g2D = (Graphics2D) g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - v.paint(g, textRect); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } else { - // plain text - int mnemIndex = -1; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); - } - - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - Color fc = tabPane.getForegroundAt(tabIndex); - if (isSelected) { - fc = AbstractLookAndFeel.getTheme().getTabSelectionForegroundColor(); - } - if (!tabPane.isEnabled() || !tabPane.isEnabledAt(tabIndex)) { - fc = AbstractLookAndFeel.getTheme().getDisabledForegroundColor(); - } - if (ColorHelper.getGrayValue(fc) > 128) { - g2D.setColor(Color.black); - } else { - g2D.setColor(Color.white); - } - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x + 1, textRect.y + 1 + metrics.getAscent()); - g2D.setComposite(composite); - g2D.setColor(fc); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); - } - } - -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiTitlePane.java deleted file mode 100644 index d903d3d02..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiTitlePane.java +++ /dev/null @@ -1,55 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.JRootPane; - -/** - * @author Michael Hagen - */ -public class HiFiTitlePane extends BaseTitlePane { - - public HiFiTitlePane(JRootPane root, BaseRootPaneUI ui) { - super(root, ui); - } - - public void paintText(Graphics g, int x, int y, String title) { - x += paintIcon(g, x, y); - g.setColor(Color.black); - JTattooUtilities.drawString(rootPane, g, title, x + 1, y + 1); - if (isActive()) { - g.setColor(AbstractLookAndFeel.getWindowTitleForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - } - JTattooUtilities.drawString(rootPane, g, title, x, y); - } - - protected void paintBorder(Graphics g) { - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiToggleButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiToggleButtonUI.java deleted file mode 100644 index ddd2427eb..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiToggleButtonUI.java +++ /dev/null @@ -1,78 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class HiFiToggleButtonUI extends BaseToggleButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new HiFiToggleButtonUI(); - } - - protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) { - ButtonModel model = b.getModel(); - FontMetrics fm = g.getFontMetrics(); - int mnemIndex; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = b.getDisplayedMnemonicIndex(); - } else { - mnemIndex = JTattooUtilities.findDisplayedMnemonicIndex(b.getText(), model.getMnemonic()); - } - int offs = 0; - if (model.isArmed() && model.isPressed()) { - offs = 1; - } - - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - Color fc = b.getForeground(); - if (fc instanceof ColorUIResource) { - if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - fc = AbstractLookAndFeel.getTheme().getSelectionForegroundColor(); - } - } - if (!model.isEnabled()) { - fc = AbstractLookAndFeel.getTheme().getDisabledForegroundColor(); - } - if (ColorHelper.getGrayValue(fc) > 128) { - g2D.setColor(Color.black); - } else { - g2D.setColor(Color.white); - } - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x + offs + 1, textRect.y + offs + fm.getAscent() + 1); - g2D.setComposite(composite); - g2D.setColor(fc); - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x + offs, textRect.y + offs + fm.getAscent()); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiToolBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiToolBarUI.java deleted file mode 100644 index 68c7bf745..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiToolBarUI.java +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.AbstractToolBarUI; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class HiFiToolBarUI extends AbstractToolBarUI { - - public static ComponentUI createUI(JComponent c) { - return new HiFiToolBarUI(); - } - - public Border getRolloverBorder() { - return HiFiBorders.getRolloverToolButtonBorder(); - } - - public Border getNonRolloverBorder() { - return HiFiBorders.getToolButtonBorder(); - } - - public boolean isButtonOpaque() { - return true; - } - - public void paint(Graphics g, JComponent c) { - HiFiUtils.fillComponent(g, c); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiUtils.java b/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiUtils.java deleted file mode 100644 index 316129686..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/hifi/HiFiUtils.java +++ /dev/null @@ -1,56 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.hifi; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.JTattooUtilities; -import java.awt.*; - -/** - * @author Michael Hagen - */ -public class HiFiUtils { - - private HiFiUtils() { - } - - public static void fillComponent(Graphics g, Component c) { - if (AbstractLookAndFeel.getTheme().isBackgroundPatternOn()) { - int w = c.getWidth(); - int h = c.getHeight(); - Point p = JTattooUtilities.getRelLocation(c); - int y = 2 - (p.y % 3); - g.setColor(AbstractLookAndFeel.getTheme().getBackgroundColorLight()); - g.fillRect(0, 0, w, h); - g.setColor(AbstractLookAndFeel.getTheme().getBackgroundColorDark()); - while (y < h) { - g.drawLine(0, y, w, y); - y += 3; - } - } else { - g.setColor(c.getBackground()); - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/CheckPressedSymbol.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/CheckPressedSymbol.gif deleted file mode 100644 index bc2782036..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/CheckPressedSymbol.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/CheckSymbol.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/CheckSymbol.gif deleted file mode 100644 index d2326a890..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/CheckSymbol.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/DownArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/DownArrow.gif deleted file mode 100644 index 9730e700d..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/DownArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/HorRubber.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/HorRubber.gif deleted file mode 100644 index c54e65327..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/HorRubber.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/LeftArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/LeftArrow.gif deleted file mode 100644 index 7b6ea77b8..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/LeftArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/RadioSymbol.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/RadioSymbol.gif deleted file mode 100644 index 57c60e5a4..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/RadioSymbol.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/RightArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/RightArrow.gif deleted file mode 100644 index 7437f8e8d..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/RightArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterDownArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterDownArrow.gif deleted file mode 100644 index cd8dcc12b..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterDownArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterHorBumps.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterHorBumps.gif deleted file mode 100644 index bd4d4bdde..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterHorBumps.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterLeftArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterLeftArrow.gif deleted file mode 100644 index c7c543885..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterLeftArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterRightArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterRightArrow.gif deleted file mode 100644 index d8bf53adc..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterRightArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterUpArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterUpArrow.gif deleted file mode 100644 index e0f490af8..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterUpArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterVerBumps.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterVerBumps.gif deleted file mode 100644 index cd6e164e4..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/SplitterVerBumps.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/TreeClosedButton.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/TreeClosedButton.gif deleted file mode 100644 index 8d19dac38..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/TreeClosedButton.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/TreeOpenButton.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/TreeOpenButton.gif deleted file mode 100644 index 7b3558189..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/TreeOpenButton.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/UpArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/UpArrow.gif deleted file mode 100644 index 8e24ce3d9..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/UpArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/VerRubber.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/VerRubber.gif deleted file mode 100644 index 331232410..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/VerRubber.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/thumb_hor.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/thumb_hor.gif deleted file mode 100644 index 9c88f538c..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/thumb_hor.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/thumb_hor_rollover.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/thumb_hor_rollover.gif deleted file mode 100644 index 95ed5116e..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/thumb_hor_rollover.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/thumb_ver.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/thumb_ver.gif deleted file mode 100644 index 84764693b..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/thumb_ver.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/thumb_ver_rollover.gif b/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/thumb_ver_rollover.gif deleted file mode 100644 index c3517a041..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/hifi/icons/thumb_ver_rollover.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/CheckPressedSymbol.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/CheckPressedSymbol.gif deleted file mode 100644 index bc2782036..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/CheckPressedSymbol.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/CheckSymbol.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/CheckSymbol.gif deleted file mode 100644 index e974ac257..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/CheckSymbol.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/CheckSymbolDisabled.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/CheckSymbolDisabled.gif deleted file mode 100644 index 69ac0b8e3..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/CheckSymbolDisabled.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/Computer.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/Computer.gif deleted file mode 100644 index 4f574d13b..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/Computer.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/DetailsView.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/DetailsView.gif deleted file mode 100644 index 3adc8a428..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/DetailsView.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/Directory.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/Directory.gif deleted file mode 100644 index df94437e4..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/Directory.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/DownArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/DownArrow.gif deleted file mode 100644 index 4cff7f38f..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/DownArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/DownArrowInverse.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/DownArrowInverse.gif deleted file mode 100644 index 66a3547f4..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/DownArrowInverse.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/File.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/File.gif deleted file mode 100644 index f239de3ad..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/File.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/FloppyDrive.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/FloppyDrive.gif deleted file mode 100644 index 394f51ff3..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/FloppyDrive.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/HardDrive.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/HardDrive.gif deleted file mode 100644 index 3109a2d19..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/HardDrive.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/Home.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/Home.gif deleted file mode 100644 index 130bdb680..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/Home.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/HomeFolder.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/HomeFolder.gif deleted file mode 100644 index 130bdb680..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/HomeFolder.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/JavaCup.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/JavaCup.gif deleted file mode 100644 index 8640ef343..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/JavaCup.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/LeftArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/LeftArrow.gif deleted file mode 100644 index b82ddc035..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/LeftArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/LeftArrowInverse.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/LeftArrowInverse.gif deleted file mode 100644 index 147cb5232..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/LeftArrowInverse.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/ListView.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/ListView.gif deleted file mode 100644 index 57ff6ee43..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/ListView.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/MenuArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/MenuArrow.gif deleted file mode 100644 index 17b7e29fb..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/MenuArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/MenuLeftArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/MenuLeftArrow.gif deleted file mode 100644 index 72e394a45..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/MenuLeftArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/MenuRightArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/MenuRightArrow.gif deleted file mode 100644 index 17b7e29fb..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/MenuRightArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/NewFolder.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/NewFolder.gif deleted file mode 100644 index 9a42123d1..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/NewFolder.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/OptionPaneError.png b/src/jtattoo/src/com/jtattoo/plaf/icons/OptionPaneError.png deleted file mode 100644 index 6ce796154..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/OptionPaneError.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/OptionPaneInformation.png b/src/jtattoo/src/com/jtattoo/plaf/icons/OptionPaneInformation.png deleted file mode 100644 index a72fa00cf..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/OptionPaneInformation.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/OptionPaneQuestion.png b/src/jtattoo/src/com/jtattoo/plaf/icons/OptionPaneQuestion.png deleted file mode 100644 index 8a9eb1a82..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/OptionPaneQuestion.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/OptionPaneWarning.png b/src/jtattoo/src/com/jtattoo/plaf/icons/OptionPaneWarning.png deleted file mode 100644 index 2a9f5fe5c..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/OptionPaneWarning.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/RadioSymbol.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/RadioSymbol.gif deleted file mode 100644 index f08a67dd6..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/RadioSymbol.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/RadioSymbolDisabled.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/RadioSymbolDisabled.gif deleted file mode 100644 index a552bc45f..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/RadioSymbolDisabled.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/Resizing.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/Resizing.gif deleted file mode 100644 index 090e53734..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/Resizing.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/RightArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/RightArrow.gif deleted file mode 100644 index 33aa81c6a..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/RightArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/RightArrowInverse.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/RightArrowInverse.gif deleted file mode 100644 index 01bfb2f98..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/RightArrowInverse.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterDownArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterDownArrow.gif deleted file mode 100644 index 431228b47..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterDownArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterHorBumps.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterHorBumps.gif deleted file mode 100644 index 152e12ee1..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterHorBumps.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterHorBumpsSmall.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterHorBumpsSmall.gif deleted file mode 100644 index 669868d1a..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterHorBumpsSmall.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterLeftArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterLeftArrow.gif deleted file mode 100644 index 1f9afddf1..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterLeftArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterRightArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterRightArrow.gif deleted file mode 100644 index 5a586e5b8..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterRightArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterUpArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterUpArrow.gif deleted file mode 100644 index 2afe20832..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterUpArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterVerBumps.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterVerBumps.gif deleted file mode 100644 index e828eb4ae..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterVerBumps.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterVerBumpsSmall.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterVerBumpsSmall.gif deleted file mode 100644 index 7c0bfe9ef..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/SplitterVerBumpsSmall.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/TreeClosed.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/TreeClosed.gif deleted file mode 100644 index df94437e4..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/TreeClosed.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/TreeClosedButton.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/TreeClosedButton.gif deleted file mode 100644 index 76b8bd268..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/TreeClosedButton.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/TreeLeaf.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/TreeLeaf.gif deleted file mode 100644 index 5d79d47f7..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/TreeLeaf.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/TreeOpen.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/TreeOpen.gif deleted file mode 100644 index 75256be01..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/TreeOpen.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/TreeOpenButton.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/TreeOpenButton.gif deleted file mode 100644 index ccc6fee90..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/TreeOpenButton.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/UpArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/UpArrow.gif deleted file mode 100644 index de6f0a575..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/UpArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/UpArrowInverse.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/UpArrowInverse.gif deleted file mode 100644 index 438158713..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/UpArrowInverse.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/UpFolder.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/UpFolder.gif deleted file mode 100644 index d6de89f91..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/UpFolder.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/closer_10x10.png b/src/jtattoo/src/com/jtattoo/plaf/icons/closer_10x10.png deleted file mode 100644 index 60a0346a0..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/closer_10x10.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/closer_12x12.png b/src/jtattoo/src/com/jtattoo/plaf/icons/closer_12x12.png deleted file mode 100644 index 7909acca4..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/closer_12x12.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/empty_8x8.png b/src/jtattoo/src/com/jtattoo/plaf/icons/empty_8x8.png deleted file mode 100644 index 9659f87e8..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/empty_8x8.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/iconizer_10x10.png b/src/jtattoo/src/com/jtattoo/plaf/icons/iconizer_10x10.png deleted file mode 100644 index 241b8742b..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/iconizer_10x10.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/iconizer_12x12.png b/src/jtattoo/src/com/jtattoo/plaf/icons/iconizer_12x12.png deleted file mode 100644 index 84f0eefd1..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/iconizer_12x12.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/maximizer_10x10.png b/src/jtattoo/src/com/jtattoo/plaf/icons/maximizer_10x10.png deleted file mode 100644 index b4dabaae4..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/maximizer_10x10.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/maximizer_12x12.png b/src/jtattoo/src/com/jtattoo/plaf/icons/maximizer_12x12.png deleted file mode 100644 index 92eea1c96..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/maximizer_12x12.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/minimizer_10x10.png b/src/jtattoo/src/com/jtattoo/plaf/icons/minimizer_10x10.png deleted file mode 100644 index e9f998754..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/minimizer_10x10.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/minimizer_12x12.png b/src/jtattoo/src/com/jtattoo/plaf/icons/minimizer_12x12.png deleted file mode 100644 index 54057a8e7..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/minimizer_12x12.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_blue_24x24.png b/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_blue_24x24.png deleted file mode 100644 index 96e9c5321..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_blue_24x24.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_blue_28x28.png b/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_blue_28x28.png deleted file mode 100644 index 4f5e489f8..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_blue_28x28.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_blue_32x32.png b/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_blue_32x32.png deleted file mode 100644 index a57fc5c0c..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_blue_32x32.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_green_24x24.png b/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_green_24x24.png deleted file mode 100644 index 53ebaab68..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_green_24x24.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_green_28x28.png b/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_green_28x28.png deleted file mode 100644 index c60b700cf..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_green_28x28.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_green_32x32.png b/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_green_32x32.png deleted file mode 100644 index deaefb262..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_green_32x32.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_grey_24x24.png b/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_grey_24x24.png deleted file mode 100644 index 5bb9ccbd1..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_grey_24x24.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_grey_28x28.png b/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_grey_28x28.png deleted file mode 100644 index c515435a8..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_grey_28x28.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_grey_32x32.png b/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_grey_32x32.png deleted file mode 100644 index 303f312f6..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_grey_32x32.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_red_24x24.png b/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_red_24x24.png deleted file mode 100644 index 95d856f79..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_red_24x24.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_red_28x28.png b/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_red_28x28.png deleted file mode 100644 index fabf91b6a..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_red_28x28.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_red_32x32.png b/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_red_32x32.png deleted file mode 100644 index ff2e35b73..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_red_32x32.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_yellow_24x24.png b/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_yellow_24x24.png deleted file mode 100644 index d8edbfd4f..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_yellow_24x24.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_yellow_28x28.png b/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_yellow_28x28.png deleted file mode 100644 index 7ee077747..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_yellow_28x28.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_yellow_32x32.png b/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_yellow_32x32.png deleted file mode 100644 index 0b2c52c7c..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/pearl_yellow_32x32.png and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/thumb_hor.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/thumb_hor.gif deleted file mode 100644 index 517489e6b..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/thumb_hor.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/thumb_hor_rollover.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/thumb_hor_rollover.gif deleted file mode 100644 index 18b5c0168..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/thumb_hor_rollover.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/thumb_ver.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/thumb_ver.gif deleted file mode 100644 index bdeb826ad..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/thumb_ver.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/icons/thumb_ver_rollover.gif b/src/jtattoo/src/com/jtattoo/plaf/icons/thumb_ver_rollover.gif deleted file mode 100644 index 21c752053..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/icons/thumb_ver_rollover.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaBorderFactory.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaBorderFactory.java deleted file mode 100644 index d2086e98f..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaBorderFactory.java +++ /dev/null @@ -1,122 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.AbstractBorderFactory; -import javax.swing.border.Border; - -/** - * @author Michael Hagen - */ -public class LunaBorderFactory implements AbstractBorderFactory { - - private static LunaBorderFactory instance = null; - - private LunaBorderFactory() { - } - - public static synchronized LunaBorderFactory getInstance() { - if (instance == null) { - instance = new LunaBorderFactory(); - } - return instance; - } - - public Border getFocusFrameBorder() { - return LunaBorders.getFocusFrameBorder(); - } - - public Border getButtonBorder() { - return LunaBorders.getButtonBorder(); - } - - public Border getToggleButtonBorder() { - return LunaBorders.getToggleButtonBorder(); - } - - public Border getTextBorder() { - return LunaBorders.getTextBorder(); - } - - public Border getSpinnerBorder() { - return LunaBorders.getSpinnerBorder(); - } - - public Border getTextFieldBorder() { - return LunaBorders.getTextFieldBorder(); - } - - public Border getComboBoxBorder() { - return LunaBorders.getComboBoxBorder(); - } - - public Border getTableHeaderBorder() { - return LunaBorders.getTableHeaderBorder(); - } - - public Border getTableScrollPaneBorder() { - return LunaBorders.getTableScrollPaneBorder(); - } - - public Border getScrollPaneBorder() { - return LunaBorders.getScrollPaneBorder(); - } - - public Border getTabbedPaneBorder() { - return LunaBorders.getTabbedPaneBorder(); - } - - public Border getMenuBarBorder() { - return LunaBorders.getMenuBarBorder(); - } - - public Border getMenuItemBorder() { - return LunaBorders.getMenuItemBorder(); - } - - public Border getPopupMenuBorder() { - return LunaBorders.getPopupMenuBorder(); - } - - public Border getInternalFrameBorder() { - return LunaBorders.getInternalFrameBorder(); - } - - public Border getPaletteBorder() { - return LunaBorders.getPaletteBorder(); - } - - public Border getToolBarBorder() { - return LunaBorders.getToolBarBorder(); - } - - public Border getProgressBarBorder() { - return LunaBorders.getProgressBarBorder(); - } - - public Border getDesktopIconBorder() { - return LunaBorders.getDesktopIconBorder(); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaBorders.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaBorders.java deleted file mode 100644 index 7bf539592..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaBorders.java +++ /dev/null @@ -1,377 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.AbstractButton; -import javax.swing.ButtonModel; -import javax.swing.border.AbstractBorder; -import javax.swing.border.Border; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class LunaBorders extends BaseBorders { - - //------------------------------------------------------------------------------------ - // Lazy access methods - //------------------------------------------------------------------------------------ - public static Border getTextBorder() { - if (textFieldBorder == null) { - textFieldBorder = new TextFieldBorder(); - } - return textFieldBorder; - } - - public static Border getTextFieldBorder() { - return getTextBorder(); - } - - public static Border getComboBoxBorder() { - if (comboBoxBorder == null) { - comboBoxBorder = new ComboBoxBorder(); - } - return comboBoxBorder; - } - - public static Border getScrollPaneBorder() { - if (scrollPaneBorder == null) { - scrollPaneBorder = new ScrollPaneBorder(false); - } - return scrollPaneBorder; - } - - public static Border getTableScrollPaneBorder() { - if (tableScrollPaneBorder == null) { - tableScrollPaneBorder = new ScrollPaneBorder(true); - } - return tableScrollPaneBorder; - } - - public static Border getButtonBorder() { - if (buttonBorder == null) { - buttonBorder = new ButtonBorder(); - } - return buttonBorder; - } - - public static Border getToggleButtonBorder() { - return getButtonBorder(); - } - - public static Border getRolloverToolButtonBorder() { - if (rolloverToolButtonBorder == null) { - rolloverToolButtonBorder = new RolloverToolButtonBorder(); - } - return rolloverToolButtonBorder; - } - - public static Border getInternalFrameBorder() { - if (internalFrameBorder == null) { - internalFrameBorder = new InternalFrameBorder(); - } - return internalFrameBorder; - } - - public static Border getTableHeaderBorder() { - if (tableHeaderBorder == null) { - tableHeaderBorder = new TableHeaderBorder(); - } - return tableHeaderBorder; - } - - //------------------------------------------------------------------------------------ - // Implementation of border classes - //------------------------------------------------------------------------------------ - public static class ButtonBorder implements Border, UIResource { - - private static final Color defaultColorHi = new Color(220, 230, 245); - private static final Color defaultColorMed = new Color(212, 224, 243); - private static final Color defaultColorLo = new Color(200, 215, 240); - private static final Insets insets = new Insets(3, 6, 3, 6); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - Graphics2D g2D = (Graphics2D) g; - Color frameColor = AbstractLookAndFeel.getTheme().getFrameColor(); - if (!JTattooUtilities.isFrameActive(button)) { - frameColor = ColorHelper.brighter(frameColor, 40); - } - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - - if (button.getRootPane() != null && button.equals(button.getRootPane().getDefaultButton())) { - if (!button.getModel().isRollover()) { - g2D.setColor(defaultColorHi); - g2D.drawRoundRect(x + 1, y + 1, w - 4, h - 5, 6, 6); - g2D.setColor(defaultColorMed); - g2D.drawRoundRect(x + 2, y + 2, w - 6, h - 6, 6, 6); - g2D.setColor(defaultColorLo); - g2D.drawLine(x + 3, h - 3, w - 3, h - 3); - g2D.drawLine(w - 3, y + 4, w - 3, h - 4); - } - } - - g2D.setColor(Color.white); - g2D.drawRoundRect(x, y, w - 1, h - 1, 6, 6); - - g2D.setColor(frameColor); - g2D.drawRoundRect(x, y, w - 2, h - 2, 6, 6); - - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - } - - public Insets getBorderInsets(Component c) { - return insets; - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class ButtonBorder - - public static class RolloverToolButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(2, 2, 2, 2); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - if (model.isEnabled()) { - if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - Color frameColor = ColorHelper.darker(AbstractLookAndFeel.getToolbarBackgroundColor(), 20); - g.setColor(frameColor); - g.drawRect(x, y, w - 1, h - 1); - - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f); - g2D.setComposite(alpha); - g.setColor(Color.black); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(composite); - } else if (model.isRollover()) { - Color frameColor = AbstractLookAndFeel.getToolbarBackgroundColor(); - Color frameHiColor = ColorHelper.darker(frameColor, 5); - Color frameLoColor = ColorHelper.darker(frameColor, 30); - JTattooUtilities.draw3DBorder(g, frameHiColor, frameLoColor, x, y, w, h); - frameHiColor = Color.white; - frameLoColor = ColorHelper.brighter(frameLoColor, 60); - JTattooUtilities.draw3DBorder(g, frameHiColor, frameLoColor, x + 1, y + 1, w - 2, h - 2); - - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f); - g2D.setComposite(alpha); - g.setColor(Color.white); - g.fillRect(x + 2, y + 2, w - 4, h - 4); - g2D.setComposite(composite); - } else if (model.isSelected()) { - Color frameColor = AbstractLookAndFeel.getToolbarBackgroundColor(); - Color frameHiColor = Color.white; - Color frameLoColor = ColorHelper.darker(frameColor, 30); - JTattooUtilities.draw3DBorder(g, frameLoColor, frameHiColor, x, y, w, h); - } - } - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class RolloverToolButtonBorder - - public static class ComboBoxBorder extends AbstractBorder implements UIResource { - - private static final Color fieldBorderColor = new Color(127, 157, 185); - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - width--; - height--; - g.setColor(fieldBorderColor); - g.drawRect(x, y, width, height); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - } // class ComboBoxBorder - - public static class TextFieldBorder extends AbstractBorder implements UIResource { - - private static final Color fieldBorderColor = new Color(127, 157, 185); - private static final Insets insets = new Insets(2, 2, 2, 2); - - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - width--; - height--; - g.setColor(fieldBorderColor); - g.drawRect(x, y, width, height); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - } // class TextFieldBorder - - public static class ScrollPaneBorder extends AbstractBorder implements UIResource { - - private static final Color fieldBorderColor = new Color(127, 157, 185); - private static final Insets insets = new Insets(2, 2, 2, 2); - private static final Insets tableInsets = new Insets(1, 1, 1, 1); - private boolean tableBorder = false; - - public ScrollPaneBorder(boolean tableBorder) { - this.tableBorder = tableBorder; - } - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - g.setColor(fieldBorderColor); - g.drawRect(x, y, w - 1, h - 1); - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getTheme().getBackgroundColor(), 50)); - g.drawRect(x + 1, y + 1, w - 3, h - 3); - } - - public Insets getBorderInsets(Component c) { - if (tableBorder) { - return new Insets(tableInsets.top, tableInsets.left, tableInsets.bottom, tableInsets.right); - } else { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - Insets ins = getBorderInsets(c); - borderInsets.left = ins.left; - borderInsets.top = ins.top; - borderInsets.right = ins.right; - borderInsets.bottom = ins.bottom; - return borderInsets; - } - } // class ScrollPaneBorder - - public static class InternalFrameBorder extends BaseInternalFrameBorder { - - public InternalFrameBorder() { - insets.top = 3; - } - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - boolean active = isActive(c); - int th = getTitleHeight(c); - Color titleColor = AbstractLookAndFeel.getWindowTitleColorLight(); - Color borderColor = AbstractLookAndFeel.getWindowBorderColor(); - if (!active) { - titleColor = ColorHelper.brighter(titleColor, 20); - borderColor = ColorHelper.brighter(borderColor, 20); - } - g.setColor(titleColor); - g.fillRect(x, y + 1, w, insets.top - 1); - g.setColor(borderColor); - g.fillRect(x + 1, y + h - dw, w - 2, dw - 1); - g.fillRect(1, insets.top + th + 1, dw - 1, h - th - dw); - g.fillRect(w - dw, insets.top + th + 1, dw - 1, h - th - dw); - - if (active) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 1, insets.top, dw, th + 1); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), w - dw, insets.top, dw, th + 1); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 1, insets.top, dw, th + 1); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), w - dw, insets.top, dw, th + 1); - } - - g.setColor(ColorHelper.darker(borderColor, 15)); - g.drawRect(x, y, w - 1, h - 1); - g.drawLine(x + dw - 1, y + insets.top + th, x + dw - 1, y + h - dw); - g.drawLine(x + w - dw, y + insets.top + th, x + w - dw, y + h - dw); - g.drawLine(x + dw - 1, y + h - dw, x + w - dw, y + h - dw); - } - } // class InternalFrameBorder - - public static class TableHeaderBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(0, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getControlBackgroundColor(), 40)); - g.drawLine(0, 0, 0, h - 1); - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getControlBackgroundColor(), 20)); - g.drawLine(w - 1, 0, w - 1, h - 1); - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getControlBackgroundColor(), 10)); - g.drawLine(0, h - 1, w - 1, h - 1); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - } // class TableHeaderBorder -} // class LunaBorders - diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaButtonUI.java deleted file mode 100644 index 9d2200f12..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaButtonUI.java +++ /dev/null @@ -1,75 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseButtonUI; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.RoundRectangle2D; -import javax.swing.AbstractButton; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicGraphicsUtils; - -/** - * @author Michael Hagen - */ -public class LunaButtonUI extends BaseButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new LunaButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - int w = b.getWidth(); - int h = b.getHeight(); - Graphics2D g2D = (Graphics2D) g; - Shape savedClip = g.getClip(); - if ((b.getBorder() != null) && b.isBorderPainted() && (b.getBorder() instanceof UIResource)) { - Area clipArea = new Area(new RoundRectangle2D.Double(0, 0, w - 1, h - 1, 6, 6)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - } - super.paintBackground(g, b); - if (b.isContentAreaFilled() && b.isRolloverEnabled() && b.getModel().isRollover() && (b.getBorder() != null) && b.isBorderPainted()) { - g.setColor(AbstractLookAndFeel.getTheme().getFocusColor()); - Insets ins = b.getBorder().getBorderInsets(b); - if ((ins.top == 0) && (ins.left == 1)) { - g.drawRect(1, 0, w - 2, h - 1); - g.drawRect(2, 1, w - 4, h - 3); - } else { - g.drawRect(1, 1, w - 4, h - 4); - g.drawRect(2, 2, w - 6, h - 6); - } - } - g2D.setClip(savedClip); - } - - protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { - g.setColor(Color.black); - BasicGraphicsUtils.drawDashedRect(g, 3, 3, b.getWidth() - 6, b.getHeight() - 6); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaComboBoxUI.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaComboBoxUI.java deleted file mode 100644 index 5daf92e33..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaComboBoxUI.java +++ /dev/null @@ -1,109 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -public class LunaComboBoxUI extends BaseComboBoxUI { - - public static ComponentUI createUI(JComponent c) { - return new LunaComboBoxUI(); - } - - public JButton createArrowButton() { - return new ArrowButton(); - } - - protected void setButtonBorder() { - } - -//-------------------------------------------------------------------------------------------------- - static class ArrowButton extends NoFocusButton { - - public ArrowButton() { - setBorder(BorderFactory.createEmptyBorder()); - setBorderPainted(false); - setContentAreaFilled(false); - } - - public void paint(Graphics g) { - Graphics2D g2D = (Graphics2D) g; - - boolean isPressed = getModel().isPressed(); - boolean isRollover = getModel().isRollover(); - - int width = getWidth(); - int height = getHeight(); - - Color[] tc = AbstractLookAndFeel.getTheme().getThumbColors(); - Color c1 = tc[0]; - Color c2 = tc[tc.length - 1]; - - if (isPressed) { - c1 = ColorHelper.darker(c1, 5); - c2 = ColorHelper.darker(c2, 5); - } else if (isRollover) { - c1 = ColorHelper.brighter(c1, 20); - c2 = ColorHelper.brighter(c2, 20); - } - - g2D.setPaint(new GradientPaint(0, 0, c1, width, height, c2)); - g.fillRect(0, 0, width, height); - g2D.setPaint(null); - g2D.setColor(Color.white); - if (JTattooUtilities.isLeftToRight(this)) { - g2D.drawRect(1, 0, width - 2, height - 1); - } else { - g2D.drawRect(0, 0, width - 2, height - 1); - } - - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - g2D.setColor(c2); - if (JTattooUtilities.isLeftToRight(this)) { - g.drawLine(2, 1, width - 2, 1); - g.drawLine(2, 2, 2, height - 2); - } else { - g.drawLine(1, 1, width - 3, 1); - g.drawLine(1, 2, 1, height - 2); - } - g2D.setComposite(composite); - - // paint the icon - Icon icon = LunaIcons.getComboBoxIcon(); - int x = (width - icon.getIconWidth()) / 2; - int y = (height - icon.getIconHeight()) / 2; - int dx = (JTattooUtilities.isLeftToRight(this)) ? 0 : -1; - if (getModel().isPressed() && getModel().isArmed()) { - icon.paintIcon(this, g, x + dx + 2, y + 1); - } else { - icon.paintIcon(this, g, x + dx + 1, y); - } - } - } // end class ArrowButton -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaDefaultTheme.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaDefaultTheme.java deleted file mode 100644 index 45d27dc92..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaDefaultTheme.java +++ /dev/null @@ -1,162 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.AbstractTheme; -import com.jtattoo.plaf.ColorHelper; -import java.awt.Color; -import javax.swing.plaf.ColorUIResource; - -public class LunaDefaultTheme extends AbstractTheme { - - public LunaDefaultTheme() { - super(); - // Setup theme with defaults - setUpColor(); - // Overwrite defaults with user props - loadProperties(); - // Setup the color arrays - setUpColorArrs(); - } - - public String getPropertyFileName() { - return "LunaTheme.properties"; - } - - public void setUpColor() { - super.setUpColor(); - - // Defaults for AbstractLookAndFeel - backgroundColor = new ColorUIResource(240, 238, 225); - backgroundColorLight = new ColorUIResource(255, 255, 255); - backgroundColorDark = new ColorUIResource(232, 228, 208); - alterBackgroundColor = new ColorUIResource(232, 228, 208); - - selectionForegroundColor = black; - selectionBackgroundColor = new ColorUIResource(194, 208, 243);//new ColorUIResource(200, 210, 240); - - frameColor = new ColorUIResource(0, 88, 168); // new ColorUIResource(0, 60, 116); - focusCellColor = new ColorUIResource(0, 60, 116); - - buttonBackgroundColor = new ColorUIResource(236, 233, 216); - buttonColorLight = white; - buttonColorDark = new ColorUIResource(214, 208, 197); - - rolloverColor = lightOrange; - - controlForegroundColor = black; - controlBackgroundColor = new ColorUIResource(236, 233, 216); - controlColorLight = white; - controlColorDark = new ColorUIResource(214, 208, 197); - - windowTitleForegroundColor = white; - windowTitleBackgroundColor = new ColorUIResource(194, 208, 243); //new ColorUIResource(139, 185, 254); - windowTitleColorLight = new ColorUIResource(139, 185, 254); - windowTitleColorDark = new ColorUIResource(2, 80, 196); - windowBorderColor = new ColorUIResource(2, 80, 196); - - windowInactiveTitleForegroundColor = white; - windowInactiveTitleBackgroundColor = new ColorUIResource(240, 238, 225); // new ColorUIResource(141, 186, 253); - windowInactiveTitleColorLight = new ColorUIResource(141, 186, 253); - windowInactiveTitleColorDark = new ColorUIResource(39, 106, 204); - windowInactiveBorderColor = new ColorUIResource(39, 106, 204); - - menuBackgroundColor = backgroundColor; - menuSelectionForegroundColor = white; - menuSelectionBackgroundColor = new ColorUIResource(49, 106, 197); - menuColorLight = new ColorUIResource(248, 247, 241); - menuColorDark = backgroundColor; - - toolbarBackgroundColor = backgroundColor; - toolbarColorLight = menuColorLight; - toolbarColorDark = backgroundColor; - - tabAreaBackgroundColor = backgroundColor; - desktopColor = backgroundColor; - } - - public void setUpColorArrs() { - super.setUpColorArrs(); - - // Generate the color arrays - DEFAULT_COLORS = ColorHelper.createColorArr(controlColorLight, controlColorDark, 20); - HIDEFAULT_COLORS = ColorHelper.createColorArr(ColorHelper.brighter(controlColorLight, 90), ColorHelper.brighter(controlColorDark, 30), 20); - - ACTIVE_COLORS = DEFAULT_COLORS; - INACTIVE_COLORS = ColorHelper.createColorArr(new Color(248, 247, 241), backgroundColor, 20); - - ROLLOVER_COLORS = ColorHelper.createColorArr(ColorHelper.brighter(controlColorLight, 30), ColorHelper.brighter(controlColorDark, 20), 30); - SELECTED_COLORS = DEFAULT_COLORS; - PRESSED_COLORS = ColorHelper.createColorArr(controlColorDark, controlColorLight, 20); - DISABLED_COLORS = ColorHelper.createColorArr(Color.white, Color.lightGray, 20); - - // Generate the color arrays - Color topHi = windowTitleColorLight; - Color topLo = ColorHelper.darker(windowTitleColorLight, 10); - Color bottomHi = ColorHelper.brighter(windowTitleColorDark, 15); - Color bottomLo = windowTitleColorDark; - - WINDOW_TITLE_COLORS = new Color[20]; - Color[] topColors = ColorHelper.createColorArr(topHi, topLo, 8); - System.arraycopy(topColors, 0, WINDOW_TITLE_COLORS, 0, 8); - Color[] bottomColors = ColorHelper.createColorArr(bottomHi, bottomLo, 12); - System.arraycopy(bottomColors, 0, WINDOW_TITLE_COLORS, 8, 12); - - WINDOW_INACTIVE_TITLE_COLORS = new Color[WINDOW_TITLE_COLORS.length]; - for (int i = 0; i < WINDOW_INACTIVE_TITLE_COLORS.length; i++) { - WINDOW_INACTIVE_TITLE_COLORS[i] = ColorHelper.brighter(WINDOW_TITLE_COLORS[i], 20); - } - - MENUBAR_COLORS = ColorHelper.createColorArr(menuColorLight, menuColorDark, 20); - TOOLBAR_COLORS = ColorHelper.createColorArr(toolbarColorLight, toolbarColorDark, 20); - - BUTTON_COLORS = new Color[]{ - new Color(255, 255, 255), - new Color(254, 254, 254), - new Color(252, 252, 251), - new Color(251, 251, 249), - new Color(250, 250, 248), - new Color(249, 249, 246), - new Color(248, 248, 244), - new Color(247, 247, 243), - new Color(246, 246, 242), - new Color(245, 245, 240), - new Color(244, 244, 239), - new Color(243, 243, 238), - new Color(242, 242, 236), - new Color(241, 241, 235), - new Color(240, 240, 234), - new Color(236, 235, 230), - new Color(226, 223, 214), - new Color(214, 208, 197),}; - TAB_COLORS = ColorHelper.createColorArr(Color.white, new Color(236, 235, 230), 20); - COL_HEADER_COLORS = TAB_COLORS; - CHECKBOX_COLORS = TAB_COLORS; - TRACK_COLORS = ColorHelper.createColorArr(new Color(243, 241, 236), new Color(254, 254, 251), 20); - THUMB_COLORS = ColorHelper.createColorArr(new Color(218, 230, 254), new Color(180, 197, 240), 20); - //SLIDER_COLORS = ColorHelper.createColorArr(new Color(218, 230, 254), new Color(180, 197, 240), 20); - SLIDER_COLORS = THUMB_COLORS;//ColorHelper.createColorArr(new Color(243, 241, 236), new Color(254, 254, 251), 20); - PROGRESSBAR_COLORS = THUMB_COLORS; - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaIconFactory.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaIconFactory.java deleted file mode 100644 index b6727e72b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaIconFactory.java +++ /dev/null @@ -1,213 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.AbstractIconFactory; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class LunaIconFactory implements AbstractIconFactory { - - private static LunaIconFactory instance = null; - - private LunaIconFactory() { - } - - public static synchronized LunaIconFactory getInstance() { - if (instance == null) { - instance = new LunaIconFactory(); - } - return instance; - } - - public Icon getOptionPaneErrorIcon() { - return LunaIcons.getOptionPaneErrorIcon(); - } - - public Icon getOptionPaneWarningIcon() { - return LunaIcons.getOptionPaneWarningIcon(); - } - - public Icon getOptionPaneInformationIcon() { - return LunaIcons.getOptionPaneInformationIcon(); - } - - public Icon getOptionPaneQuestionIcon() { - return LunaIcons.getOptionPaneQuestionIcon(); - } - - public Icon getFileChooserDetailViewIcon() { - return LunaIcons.getFileChooserDetailViewIcon(); - } - - public Icon getFileChooserHomeFolderIcon() { - return LunaIcons.getFileChooserHomeFolderIcon(); - } - - public Icon getFileChooserListViewIcon() { - return LunaIcons.getFileChooserListViewIcon(); - } - - public Icon getFileChooserNewFolderIcon() { - return LunaIcons.getFileChooserNewFolderIcon(); - } - - public Icon getFileChooserUpFolderIcon() { - return LunaIcons.getFileChooserUpFolderIcon(); - } - - public Icon getMenuIcon() { - return LunaIcons.getMenuIcon(); - } - - public Icon getIconIcon() { - return LunaIcons.getIconIcon(); - } - - public Icon getMaxIcon() { - return LunaIcons.getMaxIcon(); - } - - public Icon getMinIcon() { - return LunaIcons.getMinIcon(); - } - - public Icon getCloseIcon() { - return LunaIcons.getCloseIcon(); - } - - public Icon getPaletteCloseIcon() { - return LunaIcons.getPaletteCloseIcon(); - } - - public Icon getRadioButtonIcon() { - return LunaIcons.getRadioButtonIcon(); - } - - public Icon getCheckBoxIcon() { - return LunaIcons.getCheckBoxIcon(); - } - - public Icon getComboBoxIcon() { - return LunaIcons.getComboBoxIcon(); - } - - public Icon getTreeComputerIcon() { - return LunaIcons.getTreeComputerIcon(); - } - - public Icon getTreeFloppyDriveIcon() { - return LunaIcons.getTreeFloppyDriveIcon(); - } - - public Icon getTreeHardDriveIcon() { - return LunaIcons.getTreeHardDriveIcon(); - } - - public Icon getTreeFolderIcon() { - return LunaIcons.getTreeFolderIcon(); - } - - public Icon getTreeLeafIcon() { - return LunaIcons.getTreeLeafIcon(); - } - - public Icon getTreeCollapsedIcon() { - return LunaIcons.getTreeControlIcon(true); - } - - public Icon getTreeExpandedIcon() { - return LunaIcons.getTreeControlIcon(false); - } - - public Icon getMenuArrowIcon() { - return LunaIcons.getMenuArrowIcon(); - } - - public Icon getMenuCheckBoxIcon() { - return LunaIcons.getMenuCheckBoxIcon(); - } - - public Icon getMenuRadioButtonIcon() { - return LunaIcons.getMenuRadioButtonIcon(); - } - - public Icon getUpArrowIcon() { - return LunaIcons.getUpArrowIcon(); - } - - public Icon getDownArrowIcon() { - return LunaIcons.getDownArrowIcon(); - } - - public Icon getLeftArrowIcon() { - return LunaIcons.getLeftArrowIcon(); - } - - public Icon getRightArrowIcon() { - return LunaIcons.getRightArrowIcon(); - } - - public Icon getSplitterDownArrowIcon() { - return LunaIcons.getSplitterDownArrowIcon(); - } - - public Icon getSplitterHorBumpIcon() { - return LunaIcons.getSplitterHorBumpIcon(); - } - - public Icon getSplitterLeftArrowIcon() { - return LunaIcons.getSplitterLeftArrowIcon(); - } - - public Icon getSplitterRightArrowIcon() { - return LunaIcons.getSplitterRightArrowIcon(); - } - - public Icon getSplitterUpArrowIcon() { - return LunaIcons.getSplitterUpArrowIcon(); - } - - public Icon getSplitterVerBumpIcon() { - return LunaIcons.getSplitterVerBumpIcon(); - } - - public Icon getThumbHorIcon() { - return LunaIcons.getThumbHorIcon(); - } - - public Icon getThumbVerIcon() { - return LunaIcons.getThumbVerIcon(); - } - - public Icon getThumbHorIconRollover() { - return LunaIcons.getThumbHorIconRollover(); - } - - public Icon getThumbVerIconRollover() { - return LunaIcons.getThumbVerIconRollover(); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaIcons.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaIcons.java deleted file mode 100644 index 2aaf90397..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaIcons.java +++ /dev/null @@ -1,184 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.Icon; -import javax.swing.JButton; - -/** - * @author Michael Hagen - */ -public class LunaIcons extends BaseIcons { - - public static Icon getComboBoxIcon() { - if (comboBoxIcon == null) { - comboBoxIcon = new LazyImageIcon("luna/icons/DownArrow.gif"); - } - return comboBoxIcon; - } - - public static Icon getIconIcon() { - if (iconIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - iconIcon = new MacIconIcon(); - } else { - iconIcon = new TitleButtonIcon(TitleButtonIcon.ICON_ICON_TYP); - } - } - return iconIcon; - } - - public static Icon getMinIcon() { - if (minIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - minIcon = new MacMinIcon(); - } else { - minIcon = new TitleButtonIcon(TitleButtonIcon.MIN_ICON_TYP); - } - } - return minIcon; - } - - public static Icon getMaxIcon() { - if (maxIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - maxIcon = new MacMaxIcon(); - } else { - maxIcon = new TitleButtonIcon(TitleButtonIcon.MAX_ICON_TYP); - } - } - return maxIcon; - } - - public static Icon getCloseIcon() { - if (closeIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - closeIcon = new MacCloseIcon(); - } else { - closeIcon = new TitleButtonIcon(TitleButtonIcon.CLOSE_ICON_TYP); - } - } - return closeIcon; - } - -//------------------------------------------------------------------------------ - private static class TitleButtonIcon implements Icon { - - private static Color blueFrameColor = Color.white; - private static Color blueColorLight = new Color(154, 183, 250); - private static Color blueColorDark = new Color(0, 69, 211); - private static Color closerColorLight = new Color(241, 172, 154); - private static Color closerColorDark = new Color(224, 56, 2); - public static final int ICON_ICON_TYP = 0; - public static final int MIN_ICON_TYP = 1; - public static final int MAX_ICON_TYP = 2; - public static final int CLOSE_ICON_TYP = 3; - private int iconTyp = ICON_ICON_TYP; - - public TitleButtonIcon(int typ) { - iconTyp = typ; - } - - public int getIconHeight() { - return 20; - } - - public int getIconWidth() { - return 20; - } - - public void paintIcon(Component c, Graphics g, int x, int y) { - int w = c.getWidth(); - int h = c.getHeight(); - - JButton b = (JButton) c; - Graphics2D g2D = (Graphics2D) g; - - boolean isActive = JTattooUtilities.isActive(b); - boolean isPressed = b.getModel().isPressed(); - boolean isArmed = b.getModel().isArmed(); - boolean isRollover = b.getModel().isRollover(); - - Color fc = blueFrameColor; - Color cHi = blueColorLight; - Color cLo = blueColorDark; - if (iconTyp == CLOSE_ICON_TYP) { - cHi = closerColorLight; - cLo = closerColorDark; - } - - if (!isActive) { - cHi = ColorHelper.brighter(cHi, 20); - cLo = ColorHelper.brighter(cLo, 10); - } - if (isPressed && isArmed) { - Color cTemp = ColorHelper.darker(cLo, 10); - cLo = ColorHelper.darker(cHi, 10); - cHi = cTemp; - } else if (isRollover) { - cHi = ColorHelper.brighter(cHi, 30); - cLo = ColorHelper.brighter(cLo, 30); - } - - g2D.setPaint(new GradientPaint(0, 0, cHi, w, h, cLo)); - g.fillRect(1, 1, w - 2, h - 2); - - g.setColor(fc); - g.drawLine(1, 0, w - 2, 0); - g.drawLine(0, 1, 0, h - 2); - g.drawLine(1, h - 1, w - 2, h - 1); - g.drawLine(w - 1, 1, w - 1, h - 2); - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f); - g2D.setComposite(alpha); - g2D.setColor(cLo); - g.drawLine(2, 1, w - 2, 1); - g.drawLine(1, 2, 1, h - 2); - g2D.setColor(ColorHelper.darker(cLo, 40)); - g.drawLine(2, h - 2, w - 2, h - 2); - g.drawLine(w - 2, 2, w - 2, h - 2); - - g2D.setComposite(composite); - - // Paint the icon - cHi = Color.white; - cLo = ColorHelper.darker(cLo, 30); - Icon icon = null; - if (iconTyp == ICON_ICON_TYP) { - icon = new BaseIcons.IconSymbol(cHi, cLo, null, new Insets(0, 0, 0, 1)); - } else if (iconTyp == MIN_ICON_TYP) { - icon = new BaseIcons.MinSymbol(cHi, cLo, null, new Insets(0, 0, 0, 0)); - } else if (iconTyp == MAX_ICON_TYP) { - icon = new BaseIcons.MaxSymbol(cHi, cLo, null, new Insets(0, 0, 0, 1)); - } else if (iconTyp == CLOSE_ICON_TYP) { - icon = new BaseIcons.CloseSymbol(cHi, cLo, null, new Insets(0, 0, 0, 1)); - } - if (icon != null) { - icon.paintIcon(c, g, 0, 0); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaInternalFrameTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaInternalFrameTitlePane.java deleted file mode 100644 index 706f57865..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaInternalFrameTitlePane.java +++ /dev/null @@ -1,78 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.JInternalFrame; - -/** - * @author Michael Hagen - */ -public class LunaInternalFrameTitlePane extends BaseInternalFrameTitlePane { - - private static final Color frameColor = new Color(0, 25, 207); - - public LunaInternalFrameTitlePane(JInternalFrame f) { - super(f); - } - - protected int getHorSpacing() { - return 2; - } - - protected int getVerSpacing() { - return 5; - } - - protected boolean centerButtons() { - return false; - } - - public void paintText(Graphics g, int x, int y, String title) { - if (isMacStyleWindowDecoration()) { - x += paintIcon(g, x, y) + 5; - } - if (isActive()) { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getTheme().getWindowBorderColor(), 10)); - JTattooUtilities.drawString(frame, g, title, x - 1, y - 2); - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getTheme().getWindowBorderColor(), 25)); - JTattooUtilities.drawString(frame, g, title, x + 1, y); - g.setColor(AbstractLookAndFeel.getWindowTitleForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - } - JTattooUtilities.drawString(frame, g, title, x, y - 1); - } - - public void paintBorder(Graphics g) { - if (!JTattooUtilities.isActive(this)) { - g.setColor(ColorHelper.brighter(frameColor, 20)); - } else { - g.setColor(frameColor); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaInternalFrameUI.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaInternalFrameUI.java deleted file mode 100644 index c36ad0316..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaInternalFrameUI.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.BaseInternalFrameUI; -import javax.swing.JComponent; -import javax.swing.JInternalFrame; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class LunaInternalFrameUI extends BaseInternalFrameUI { - - public LunaInternalFrameUI(JInternalFrame b) { - super(b); - } - - public static ComponentUI createUI(JComponent c) { - return new LunaInternalFrameUI((JInternalFrame) c); - } - - protected JComponent createNorthPane(JInternalFrame w) { - titlePane = new LunaInternalFrameTitlePane(w); - return titlePane; - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaLookAndFeel.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaLookAndFeel.java deleted file mode 100644 index 4a5db2a47..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaLookAndFeel.java +++ /dev/null @@ -1,207 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.*; -import java.util.*; -import javax.swing.UIDefaults; - -/** - * @author Michael Hagen - */ -public class LunaLookAndFeel extends AbstractLookAndFeel { - - private static LunaDefaultTheme myTheme = null; - - private static final ArrayList themesList = new ArrayList(); - private static final HashMap themesMap = new HashMap(); - private static final Properties defaultProps = new Properties(); - private static final Properties smallFontProps = new Properties(); - private static final Properties largeFontProps = new Properties(); - private static final Properties giantFontProps = new Properties(); - - static { - smallFontProps.setProperty("controlTextFont", "Dialog 10"); - smallFontProps.setProperty("systemTextFont", "Dialog 10"); - smallFontProps.setProperty("userTextFont", "Dialog 10"); - smallFontProps.setProperty("menuTextFont", "Dialog 10"); - smallFontProps.setProperty("windowTitleFont", "Dialog bold 10"); - smallFontProps.setProperty("subTextFont", "Dialog 8"); - - largeFontProps.setProperty("controlTextFont", "Dialog 14"); - largeFontProps.setProperty("systemTextFont", "Dialog 14"); - largeFontProps.setProperty("userTextFont", "Dialog 14"); - largeFontProps.setProperty("menuTextFont", "Dialog 14"); - largeFontProps.setProperty("windowTitleFont", "Dialog bold 14"); - largeFontProps.setProperty("subTextFont", "Dialog 12"); - - giantFontProps.setProperty("controlTextFont", "Dialog 18"); - giantFontProps.setProperty("systemTextFont", "Dialog 18"); - giantFontProps.setProperty("userTextFont", "Dialog 18"); - giantFontProps.setProperty("menuTextFont", "Dialog 18"); - giantFontProps.setProperty("windowTitleFont", "Dialog 18"); - giantFontProps.setProperty("subTextFont", "Dialog 16"); - - themesList.add("Default"); - themesList.add("Small-Font"); - themesList.add("Large-Font"); - themesList.add("Giant-Font"); - - themesMap.put("Default", defaultProps); - themesMap.put("Small-Font", smallFontProps); - themesMap.put("Large-Font", largeFontProps); - themesMap.put("Giant-Font", giantFontProps); - } - - public static java.util.List getThemes() { - return themesList; - } - - public static Properties getThemeProperties(String name) { - return ((Properties) themesMap.get(name)); - } - - public static void setTheme(String name) { - setTheme((Properties) themesMap.get(name)); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - - public static void setTheme(String name, String licenseKey, String logoString) { - Properties props = (Properties) themesMap.get(name); - if (props != null) { - props.put("licenseKey", licenseKey); - props.put("logoString", logoString); - setTheme(props); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - } - - public static void setTheme(Properties themesProps) { - if (myTheme == null) { - myTheme = new LunaDefaultTheme(); - } - if ((myTheme != null) && (themesProps != null)) { - myTheme.setUpColor(); - myTheme.setProperties(themesProps); - myTheme.setUpColorArrs(); - AbstractLookAndFeel.setTheme(myTheme); - } - } - - public static void setCurrentTheme(Properties themesProps) { - setTheme(themesProps); - } - - public String getName() { - return "XP"; - } - - public String getID() { - return "XP"; - } - - public String getDescription() { - return "The XP Look and Feel"; - } - - public boolean isNativeLookAndFeel() { - return false; - } - - public boolean isSupportedLookAndFeel() { - return true; - } - - public AbstractBorderFactory getBorderFactory() { - return LunaBorderFactory.getInstance(); - } - - public AbstractIconFactory getIconFactory() { - return LunaIconFactory.getInstance(); - } - - protected void createDefaultTheme() { - if (myTheme == null) { - myTheme = new LunaDefaultTheme(); - } - setTheme(myTheme); - } - - protected void initComponentDefaults(UIDefaults table) { - super.initComponentDefaults(table); - table.put("ScrollBar.incrementButtonGap", new Integer(-1)); - table.put("ScrollBar.decrementButtonGap", new Integer(-1)); - } - - protected void initClassDefaults(UIDefaults table) { - super.initClassDefaults(table); - Object[] uiDefaults = { - // BaseLookAndFeel classes - "LabelUI", BaseLabelUI.class.getName(), - "ToggleButtonUI", BaseToggleButtonUI.class.getName(), - "SeparatorUI", BaseSeparatorUI.class.getName(), - "TextFieldUI", BaseTextFieldUI.class.getName(), - "TextAreaUI", BaseTextAreaUI.class.getName(), - "EditorPaneUI", BaseEditorPaneUI.class.getName(), - "PasswordFieldUI", BasePasswordFieldUI.class.getName(), - "CheckBoxUI", BaseCheckBoxUI.class.getName(), - "RadioButtonUI", BaseRadioButtonUI.class.getName(), - "ToolTipUI", BaseToolTipUI.class.getName(), - "TreeUI", BaseTreeUI.class.getName(), - "TableUI", BaseTableUI.class.getName(), - "SliderUI", BaseSliderUI.class.getName(), - "ProgressBarUI", BaseProgressBarUI.class.getName(), - "ScrollPaneUI", BaseScrollPaneUI.class.getName(), - "PanelUI", BasePanelUI.class.getName(), - "SplitPaneUI", BaseSplitPaneUI.class.getName(), - "FileChooserUI", BaseFileChooserUI.class.getName(), - "MenuBarUI", BaseMenuBarUI.class.getName(), - "MenuUI", BaseMenuUI.class.getName(), - "PopupMenuUI", BasePopupMenuUI.class.getName(), - "MenuItemUI", BaseMenuItemUI.class.getName(), - "CheckBoxMenuItemUI", BaseCheckBoxMenuItemUI.class.getName(), - "RadioButtonMenuItemUI", BaseRadioButtonMenuItemUI.class.getName(), - "PopupMenuSeparatorUI", BaseSeparatorUI.class.getName(), - "DesktopPaneUI", BaseDesktopPaneUI.class.getName(), - - // LunaLookAndFeel classes - "ButtonUI", LunaButtonUI.class.getName(), - "ComboBoxUI", LunaComboBoxUI.class.getName(), - "ScrollBarUI", LunaScrollBarUI.class.getName(), - "TabbedPaneUI", LunaTabbedPaneUI.class.getName(), - "TableHeaderUI", LunaTableHeaderUI.class.getName(), - "ToolBarUI", LunaToolBarUI.class.getName(), - "InternalFrameUI", LunaInternalFrameUI.class.getName(), - "RootPaneUI", LunaRootPaneUI.class.getName(),}; - table.putDefaults(uiDefaults); - if (JTattooUtilities.getJavaVersion() >= 1.5) { - table.put("FormattedTextFieldUI", BaseFormattedTextFieldUI.class.getName()); - table.put("SpinnerUI", BaseSpinnerUI.class.getName()); - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaRootPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaRootPaneUI.java deleted file mode 100644 index 5ed76e408..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaRootPaneUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.BaseRootPaneUI; -import com.jtattoo.plaf.BaseTitlePane; -import javax.swing.JComponent; -import javax.swing.JRootPane; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class LunaRootPaneUI extends BaseRootPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new LunaRootPaneUI(); - } - - public BaseTitlePane createTitlePane(JRootPane root) { - return new LunaTitlePane(root, this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaScrollBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaScrollBarUI.java deleted file mode 100644 index 924c089d4..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaScrollBarUI.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.XPScrollBarUI; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; - -/** - * - * @author Michael Hagen - */ -public class LunaScrollBarUI extends XPScrollBarUI { - - public static ComponentUI createUI(JComponent c) { - return new LunaScrollBarUI(); - } - - protected JButton createDecreaseButton(int orientation) { - return new LunaScrollButton(orientation, scrollBarWidth); - } - - protected JButton createIncreaseButton(int orientation) { - return new LunaScrollButton(orientation, scrollBarWidth); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaScrollButton.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaScrollButton.java deleted file mode 100644 index 81355332f..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaScrollButton.java +++ /dev/null @@ -1,72 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.LazyImageIcon; -import com.jtattoo.plaf.XPScrollButton; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class LunaScrollButton extends XPScrollButton { - - protected static Icon upArrowIcon = null; - protected static Icon downArrowIcon = null; - protected static Icon leftArrowIcon = null; - protected static Icon rightArrowIcon = null; - - public LunaScrollButton(int direction, int width) { - super(direction, width); - } - - public Icon getUpArrowIcon() { - if (upArrowIcon == null) { - upArrowIcon = new LazyImageIcon("luna/icons/UpArrow.gif"); - } - return upArrowIcon; - } - - public Icon getDownArrowIcon() { - if (downArrowIcon == null) { - downArrowIcon = new LazyImageIcon("luna/icons/DownArrow.gif"); - } - return downArrowIcon; - } - - public Icon getLeftArrowIcon() { - if (leftArrowIcon == null) { - leftArrowIcon = new LazyImageIcon("luna/icons/LeftArrow.gif"); - } - return leftArrowIcon; - } - - public Icon getRightArrowIcon() { - if (rightArrowIcon == null) { - rightArrowIcon = new LazyImageIcon("luna/icons/RightArrow.gif"); - } - return rightArrowIcon; - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaTabbedPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaTabbedPaneUI.java deleted file mode 100644 index 9bc3597a1..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaTabbedPaneUI.java +++ /dev/null @@ -1,115 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseTabbedPaneUI; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; - -/** - * author Michael Hagen - */ -public class LunaTabbedPaneUI extends BaseTabbedPaneUI { - - private static Color[] selectedTabColors = new Color[]{AbstractLookAndFeel.getBackgroundColor()}; - private static Color sepColors[] = {AbstractLookAndFeel.getControlDarkShadow()}; - - public static ComponentUI createUI(JComponent c) { - return new LunaTabbedPaneUI(); - } - - public void installDefaults() { - super.installDefaults(); - selectedTabColors = new Color[]{AbstractLookAndFeel.getBackgroundColor()}; - tabAreaInsets = new Insets(2, 6, 2, 6); - contentBorderInsets = new Insets(0, 0, 0, 0); - } - - protected void installComponents() { - simpleButtonBorder = true; - super.installComponents(); - } - - protected Font getTabFont(boolean isSelected) { - if (isSelected) { - return super.getTabFont(isSelected).deriveFont(Font.BOLD); - } else { - return super.getTabFont(isSelected); - } - } - - protected Color[] getTabColors(int tabIndex, boolean isSelected, boolean isRollover) { - if (isSelected && (tabPane.getBackgroundAt(tabIndex) instanceof UIResource)) { - return selectedTabColors; - } else { - return super.getTabColors(tabIndex, isSelected, isRollover); - } - } - - protected Color[] getContentBorderColors(int tabPlacement) { - return sepColors; - } - - protected boolean hasInnerBorder() { - return true; - } - - protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) { - Color backColor = tabPane.getBackgroundAt(tabIndex); - if (isSelected && (backColor instanceof UIResource)) { - if (tabPane.getBackgroundAt(tabIndex) instanceof UIResource) { - g.setColor(AbstractLookAndFeel.getBackgroundColor()); - } else { - g.setColor(tabPane.getBackgroundAt(tabIndex)); - } - if (tabPlacement == TOP) { - g.fillRect(x + 1, y + 1, w - 1, h + 2); - } else if (tabPlacement == LEFT) { - g.fillRect(x + 1, y + 1, w + 2, h - 1); - } else if (tabPlacement == BOTTOM) { - g.fillRect(x + 1, y - 2, w - 1, h + 2); - } else { - g.fillRect(x - 2, y + 1, w + 2, h - 1); - } - } else { - super.paintTabBackground(g, tabPlacement, tabIndex, x, y, w, h, isSelected); - if (!isSelected && tabIndex == rolloverIndex && tabPane.isEnabledAt(tabIndex)) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - if (tabPlacement == TOP) { - g.fillRect(x + 2, y + 1, w - 3, 2); - } else if (tabPlacement == LEFT) { - g.fillRect(x, y + 1, w - 1, 2); - } else if (tabPlacement == BOTTOM) { - g.fillRect(x + 2, y + h - 3, w - 3, 2); - } else { - g.fillRect(x, y + 1, w - 1, 2); - } - } - } - } - -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaTableHeaderUI.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaTableHeaderUI.java deleted file mode 100644 index 6dd00ff8b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaTableHeaderUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.BaseTableHeaderUI; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; - -/** - * - * @author Michael Hagen - */ -public class LunaTableHeaderUI extends BaseTableHeaderUI { - - public static ComponentUI createUI(JComponent c) { - return new LunaTableHeaderUI(); - } - - protected boolean drawRolloverBar() { - return true; - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaTitlePane.java deleted file mode 100644 index 57082f250..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaTitlePane.java +++ /dev/null @@ -1,74 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JRootPane; - -/** - * @author Michael Hagen - */ -public class LunaTitlePane extends BaseTitlePane { - - public LunaTitlePane(JRootPane root, BaseRootPaneUI ui) { - super(root, ui); - } - - protected int getHorSpacing() { - return 2; - } - - protected int getVerSpacing() { - return 5; - } - - protected boolean centerButtons() { - return false; - } - - public void paintBorder(Graphics g) { - if (isActive()) { - g.setColor(AbstractLookAndFeel.getTheme().getFrameColor()); - } else { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFrameColor(), 40)); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } - - public void paintText(Graphics g, int x, int y, String title) { - x += paintIcon(g, x, y); - if (isActive()) { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getTheme().getWindowBorderColor(), 10)); - JTattooUtilities.drawString(rootPane, g, title, x - 1, y - 2); - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getTheme().getWindowBorderColor(), 25)); - JTattooUtilities.drawString(rootPane, g, title, x + 1, y); - g.setColor(AbstractLookAndFeel.getWindowTitleForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - } - JTattooUtilities.drawString(rootPane, g, title, x, y - 1); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaToolBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/luna/LunaToolBarUI.java deleted file mode 100644 index 8a48ac504..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/luna/LunaToolBarUI.java +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.luna; - -import com.jtattoo.plaf.*; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -public class LunaToolBarUI extends AbstractToolBarUI { - - public static ComponentUI createUI(JComponent c) { - return new LunaToolBarUI(); - } - - public Border getRolloverBorder() { - return LunaBorders.getRolloverToolButtonBorder(); - } - - public Border getNonRolloverBorder() { - return LunaBorders.getToolButtonBorder(); - } - - public boolean isButtonOpaque() { - return false; - } - - public void paint(Graphics g, JComponent c) { - int w = c.getWidth(); - int h = c.getHeight(); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getToolBarColors(), 0, 0, w, h); - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getToolbarColorDark(), 10)); - g.drawLine(0, 0, w, 0); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/icons/DownArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/luna/icons/DownArrow.gif deleted file mode 100644 index 53d2f1577..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/luna/icons/DownArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/icons/LeftArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/luna/icons/LeftArrow.gif deleted file mode 100644 index 5df254275..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/luna/icons/LeftArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/icons/RightArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/luna/icons/RightArrow.gif deleted file mode 100644 index 808180eda..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/luna/icons/RightArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/luna/icons/UpArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/luna/icons/UpArrow.gif deleted file mode 100644 index 58ee69c93..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/luna/icons/UpArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinBorderFactory.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinBorderFactory.java deleted file mode 100644 index 80094fb5d..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinBorderFactory.java +++ /dev/null @@ -1,122 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.AbstractBorderFactory; -import javax.swing.border.Border; - -/** - * @author Michael Hagen - */ -public class McWinBorderFactory implements AbstractBorderFactory { - - private static McWinBorderFactory instance = null; - - private McWinBorderFactory() { - } - - public static synchronized McWinBorderFactory getInstance() { - if (instance == null) { - instance = new McWinBorderFactory(); - } - return instance; - } - - public Border getFocusFrameBorder() { - return McWinBorders.getFocusFrameBorder(); - } - - public Border getButtonBorder() { - return McWinBorders.getButtonBorder(); - } - - public Border getToggleButtonBorder() { - return McWinBorders.getToggleButtonBorder(); - } - - public Border getTextBorder() { - return McWinBorders.getTextBorder(); - } - - public Border getSpinnerBorder() { - return McWinBorders.getSpinnerBorder(); - } - - public Border getTextFieldBorder() { - return McWinBorders.getTextFieldBorder(); - } - - public Border getComboBoxBorder() { - return McWinBorders.getComboBoxBorder(); - } - - public Border getTableHeaderBorder() { - return McWinBorders.getTableHeaderBorder(); - } - - public Border getTableScrollPaneBorder() { - return McWinBorders.getTableScrollPaneBorder(); - } - - public Border getScrollPaneBorder() { - return McWinBorders.getScrollPaneBorder(); - } - - public Border getTabbedPaneBorder() { - return McWinBorders.getTabbedPaneBorder(); - } - - public Border getMenuBarBorder() { - return McWinBorders.getMenuBarBorder(); - } - - public Border getMenuItemBorder() { - return McWinBorders.getMenuItemBorder(); - } - - public Border getPopupMenuBorder() { - return McWinBorders.getPopupMenuBorder(); - } - - public Border getInternalFrameBorder() { - return McWinBorders.getInternalFrameBorder(); - } - - public Border getPaletteBorder() { - return McWinBorders.getPaletteBorder(); - } - - public Border getToolBarBorder() { - return McWinBorders.getToolBarBorder(); - } - - public Border getProgressBarBorder() { - return McWinBorders.getProgressBarBorder(); - } - - public Border getDesktopIconBorder() { - return McWinBorders.getDesktopIconBorder(); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinBorders.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinBorders.java deleted file mode 100644 index ec70d47c4..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinBorders.java +++ /dev/null @@ -1,190 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.AbstractButton; -import javax.swing.ButtonModel; -import javax.swing.border.Border; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class McWinBorders extends BaseBorders { - - //------------------------------------------------------------------------------------ - // Lazy access methods - //------------------------------------------------------------------------------------ - public static Border getButtonBorder() { - if (buttonBorder == null) { - buttonBorder = new ButtonBorder(); - } - return buttonBorder; - } - - public static Border getToggleButtonBorder() { - return getButtonBorder(); - } - - public static Border getRolloverToolButtonBorder() { - if (rolloverToolButtonBorder == null) { - rolloverToolButtonBorder = new RolloverToolButtonBorder(); - } - return rolloverToolButtonBorder; - } - - public static Border getInternalFrameBorder() { - if (internalFrameBorder == null) { - internalFrameBorder = new InternalFrameBorder(); - } - return internalFrameBorder; - } - - public static Border getTabbedPaneBorder() { - return null; - } - - //------------------------------------------------------------------------------------ - // Implementation of border classes - //------------------------------------------------------------------------------------ - public static class ButtonBorder implements Border, UIResource { - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - } - - public Insets getBorderInsets(Component c) { - if (AbstractLookAndFeel.getTheme().doDrawSquareButtons()) { - return new Insets(3, 4, 3, 4); - } else { - return new Insets(2, 12, 2, 12); - } - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - Insets insets = getBorderInsets(c); - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class ButtonBorder - - public static class RolloverToolButtonBorder implements Border, UIResource { - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - Color frameColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFrameColor(), 40); - if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - frameColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFrameColor(), 20); - } else if (model.isRollover()) { - frameColor = AbstractLookAndFeel.getTheme().getRolloverColor(); - } - g.setColor(frameColor); - g.drawRect(x, y, w - 2, h - 1); - g.setColor(AbstractLookAndFeel.getTheme().getToolbarBackgroundColor()); - g.drawLine(w - 1, 0, w - 1, h - 1); - } - - public Insets getBorderInsets(Component c) { - return new Insets(1, 1, 1, 1); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.top = 1; - borderInsets.left = 1; - borderInsets.bottom = 1; - borderInsets.right = 1; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class RolloverToolButtonBorder - - public static class InternalFrameBorder extends BaseInternalFrameBorder { - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - boolean active = isActive(c); - boolean resizable = isResizable(c); - int th = getTitleHeight(c); - Color frameColor = AbstractLookAndFeel.getWindowInactiveBorderColor(); - Color titleColor = AbstractLookAndFeel.getWindowInactiveTitleColorLight(); - Color borderColor = AbstractLookAndFeel.getWindowInactiveTitleColorDark(); - if (active) { - frameColor = AbstractLookAndFeel.getWindowBorderColor(); - titleColor = AbstractLookAndFeel.getWindowTitleColorLight(); - borderColor = AbstractLookAndFeel.getWindowTitleColorDark(); - } - if (!resizable) { - Insets borderInsets = getBorderInsets(c); - g.setColor(frameColor); - g.drawRect(x, y, w - 1, h - 1); - if (active) { - g.setColor(AbstractLookAndFeel.getWindowTitleColorDark()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleColorDark()); - } - for (int i = 1; i < borderInsets.left; i++) { - g.drawRect(i, i, w - (2 * i) - 1, h - (2 * i) - 1); - } - g.setColor(ColorHelper.brighter(frameColor, 20)); - g.drawLine(borderInsets.left - 1, y + th + borderInsets.top, borderInsets.left - 1, y + h - borderInsets.bottom); - g.drawLine(w - borderInsets.right, y + th + borderInsets.top, w - borderInsets.right, y + h - borderInsets.bottom); - g.drawLine(borderInsets.left - 1, y + h - borderInsets.bottom, w - borderInsets.right, y + h - borderInsets.bottom); - return; - } - g.setColor(titleColor); - g.fillRect(x, y + 1, w, dw - 1); - g.setColor(borderColor); - g.fillRect(x + 1, y + h - dw, w - 2, dw - 1); - if (active) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 1, dw, dw, th + 1); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), w - dw, dw, dw, th + 1); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 1, dw, dw, th + 1); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), w - dw, dw, dw, th + 1); - } - g.setColor(borderColor); - g.fillRect(1, insets.top + th + 1, dw - 1, h - th - dw); - g.fillRect(w - dw, insets.top + th + 1, dw - 1, h - th - dw); - - g.setColor(ColorHelper.darker(frameColor, 10)); - g.drawRect(x, y, w - 1, h - 1); - g.setColor(frameColor); - g.drawLine(x + dw - 1, y + dw + th, x + dw - 1, y + h - dw); - g.drawLine(x + w - dw, y + dw + th, x + w - dw, y + h - dw); - g.drawLine(x + dw - 1, y + h - dw, x + w - dw, y + h - dw); - } - } // class InternalFrameBorder -} // class McWinBorders - diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinButtonUI.java deleted file mode 100644 index 5282ff2fb..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinButtonUI.java +++ /dev/null @@ -1,172 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.*; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.RoundRectangle2D; -import javax.swing.*; -import javax.swing.plaf.*; -import javax.swing.plaf.basic.BasicGraphicsUtils; - -/** - * @author Michael Hagen - */ -public class McWinButtonUI extends BaseButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new McWinButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - if (b.getParent() instanceof JToolBar) { - b.setContentAreaFilled(true); - } - if (!b.isContentAreaFilled() || (b.getParent() instanceof JMenuBar)) { - return; - } - - int width = b.getWidth(); - int height = b.getHeight(); - - if (!(b.isBorderPainted() && (b.getBorder() instanceof UIResource)) - || (b.getParent() instanceof JToolBar)) { - super.paintBackground(g, b); - if ((b.getParent() instanceof JToolBar)) { - g.setColor(Color.lightGray); - g.drawRect(0, 0, width - 2, height - 1); - g.setColor(AbstractLookAndFeel.getTheme().getToolbarBackgroundColor()); - g.drawLine(width - 1, 0, width - 1, height - 1); - } - return; - } - - ButtonModel model = b.getModel(); - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - Object savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - Color colors[] = AbstractLookAndFeel.getTheme().getButtonColors(); - if (b.isEnabled()) { - Color background = b.getBackground(); - if (background instanceof ColorUIResource) { - if (model.isPressed() && model.isArmed()) { - colors = AbstractLookAndFeel.getTheme().getPressedColors(); - } else if (b.isRolloverEnabled() && model.isRollover()) { - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - } else { - if (b.getRootPane() != null && b.equals(b.getRootPane().getDefaultButton())) { - if (JTattooUtilities.isFrameActive(b)) { - if (AbstractLookAndFeel.getTheme().doShowFocusFrame() && b.hasFocus()) { - colors = AbstractLookAndFeel.getTheme().getFocusColors(); - } else { - if (AbstractLookAndFeel.getTheme().isBrightMode()) { - colors = new Color[AbstractLookAndFeel.getTheme().getSelectedColors().length]; - for (int i = 0; i < colors.length; i++) { - colors[i] = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getSelectedColors()[i], 30); - } - } else { - colors = AbstractLookAndFeel.getTheme().getSelectedColors(); - } - } - } - } else { - if (AbstractLookAndFeel.getTheme().doShowFocusFrame() && b.hasFocus()) { - colors = AbstractLookAndFeel.getTheme().getFocusColors(); - } - } - } - } else { // backgound != ColorUIResource - if (model.isPressed() && model.isArmed()) { - colors = ColorHelper.createColorArr(ColorHelper.darker(background, 30), ColorHelper.darker(background, 10), 20); - } else { - if (b.isRolloverEnabled() && model.isRollover()) { - colors = ColorHelper.createColorArr(ColorHelper.brighter(background, 50), ColorHelper.brighter(background, 10), 20); - } else { - colors = ColorHelper.createColorArr(ColorHelper.brighter(background, 30), ColorHelper.darker(background, 10), 20); - } - } - } - } else { // disabled - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } - - if (AbstractLookAndFeel.getTheme().doDrawSquareButtons() - || (((width < 64) || (height < 16)) && ((b.getText() == null) || b.getText().length() == 0))) { - JTattooUtilities.fillHorGradient(g, colors, 0, 0, width - 1, height - 1); - Color frameColor = colors[colors.length / 2]; - g2D.setColor(ColorHelper.darker(frameColor, 25)); - g2D.drawRect(0, 0, width - 1, height - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - g2D.setColor(Color.white); - g2D.drawRect(1, 1, width - 3, height - 3); - } else { - int d = height - 2; - Color frameColor = colors[colors.length / 2]; - - Shape savedClip = g.getClip(); - Area clipArea = new Area(new RoundRectangle2D.Double(0, 0, width - 1, height - 1, d, d)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - JTattooUtilities.fillHorGradient(g, colors, 0, 0, width - 1, height - 1); - g2D.setClip(savedClip); - - g2D.setColor(ColorHelper.darker(frameColor, 25)); - g2D.drawRoundRect(0, 0, width - 1, height - 1, d, d); - - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - g2D.setColor(Color.white); - g2D.drawRoundRect(1, 1, width - 3, height - 3, d - 2, d - 2); - - } - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRenderingHint); - g2D.setComposite(composite); - } - - protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { - Graphics2D g2D = (Graphics2D) g; - int width = b.getWidth(); - int height = b.getHeight(); - if (AbstractLookAndFeel.getTheme().doDrawSquareButtons() - || !b.isContentAreaFilled() - || ((width < 64) || (height < 16)) && ((b.getText() == null) || b.getText().length() == 0)) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - BasicGraphicsUtils.drawDashedRect(g, 4, 3, width - 8, height - 6); - } else { - Object savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2D.setColor(AbstractLookAndFeel.getFocusColor()); - int d = b.getHeight() - 4; - g2D.drawRoundRect(2, 2, b.getWidth() - 5, b.getHeight() - 5, d, d); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRenderingHint); - } - } - -} - - diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinCheckBoxUI.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinCheckBoxUI.java deleted file mode 100644 index d67d20274..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinCheckBoxUI.java +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class McWinCheckBoxUI extends McWinRadioButtonUI { - - private static McWinCheckBoxUI checkBoxUI = null; - - public static ComponentUI createUI(JComponent b) { - if (checkBoxUI == null) { - checkBoxUI = new McWinCheckBoxUI(); - } - return checkBoxUI; - } - - public void installDefaults(AbstractButton b) { - super.installDefaults(b); - icon = UIManager.getIcon("CheckBox.icon"); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinComboBoxUI.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinComboBoxUI.java deleted file mode 100644 index 5124a635f..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinComboBoxUI.java +++ /dev/null @@ -1,87 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.*; -import java.awt.Dimension; -import java.awt.Graphics; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class McWinComboBoxUI extends BaseComboBoxUI { - - public static ComponentUI createUI(JComponent c) { - return new McWinComboBoxUI(); - } - - public JButton createArrowButton() { - ArrowButton button = new ArrowButton(); - if (JTattooUtilities.isLeftToRight(comboBox)) { - Border border = BorderFactory.createMatteBorder(0, 1, 0, 0, AbstractLookAndFeel.getFrameColor()); - button.setBorder(border); - } else { - Border border = BorderFactory.createMatteBorder(0, 0, 0, 1, AbstractLookAndFeel.getFrameColor()); - button.setBorder(border); - } - return button; - } - -//-------------------------------------------------------------------------------------------------- - static class ArrowButton extends NoFocusButton { - - public void paint(Graphics g) { - Dimension size = getSize(); - if (isEnabled()) { - if (getModel().isArmed() && getModel().isPressed()) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getPressedColors(), 0, 0, size.width, size.height); - } else if (getModel().isRollover()) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getRolloverColors(), 0, 0, size.width, size.height); - } else if (JTattooUtilities.isActive(this)) { - if (AbstractLookAndFeel.getTheme().isBrightMode()) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getButtonColors(), 0, 0, size.width, size.height); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getDefaultColors(), 0, 0, size.width, size.height); - } - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getInActiveColors(), 0, 0, size.width, size.height); - } - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getDisabledColors(), 0, 0, size.width, size.height); - } - Icon icon = BaseIcons.getComboBoxIcon(); - int x = (size.width - icon.getIconWidth()) / 2; - int y = (size.height - icon.getIconHeight()) / 2; - if (getModel().isPressed() && getModel().isArmed()) { - icon.paintIcon(this, g, x + 2, y + 1); - } else { - icon.paintIcon(this, g, x + 1, y); - } - paintBorder(g); - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinDefaultTheme.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinDefaultTheme.java deleted file mode 100644 index 4a54d83f1..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinDefaultTheme.java +++ /dev/null @@ -1,221 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.AbstractTheme; -import com.jtattoo.plaf.ColorHelper; -import java.awt.Color; -import javax.swing.plaf.ColorUIResource; - -/** - * @author Michael Hagen - */ -public class McWinDefaultTheme extends AbstractTheme { - - public McWinDefaultTheme() { - super(); - // Setup theme with defaults - setUpColor(); - // Overwrite defaults with user props - loadProperties(); - // Setup the color arrays - setUpColorArrs(); - } - - public String getPropertyFileName() { - return "McWinTheme.properties"; - } - - public void setUpColor() { - super.setUpColor(); - - // Defaults for McWinLookAndFeel - menuOpaque = false; - menuAlpha = 0.85f; - - backgroundColor = superLightGray; - backgroundColorLight = white; - backgroundColorDark = new ColorUIResource(240, 240, 240); - alterBackgroundColor = new ColorUIResource(240, 240, 240); - - selectionBackgroundColor = new ColorUIResource(212, 224, 243); - - frameColor = new ColorUIResource(140, 144, 148); - focusCellColor = orange; - - buttonBackgroundColor = superLightGray; - - controlBackgroundColor = superLightGray; - controlColorLight = new ColorUIResource(106, 150, 192); - controlColorDark = lightGray; - - rolloverColor = new ColorUIResource(164, 217, 190); - rolloverColorLight = new ColorUIResource(182, 224, 203); - rolloverColorDark = new ColorUIResource(106, 192, 150); - - windowTitleForegroundColor = new ColorUIResource(22, 34, 44); - windowTitleBackgroundColor = new ColorUIResource(212, 224, 243); - windowTitleColorLight = new ColorUIResource(231, 235, 248); - windowTitleColorDark = new ColorUIResource(193, 211, 236); - windowBorderColor = new ColorUIResource(154, 168, 182); - - windowInactiveTitleForegroundColor = extraDarkGray; - windowInactiveTitleBackgroundColor = backgroundColor; - windowInactiveTitleColorLight = white; - windowInactiveTitleColorDark = new ColorUIResource(236, 236, 236); - windowInactiveBorderColor = lightGray; - - menuBackgroundColor = white; - menuSelectionBackgroundColor = selectionBackgroundColor; - - toolbarBackgroundColor = white; - - tabAreaBackgroundColor = backgroundColor; - desktopColor = new ColorUIResource(232, 232, 232); - } - - public void setUpColorArrs() { - super.setUpColorArrs(); - - if (controlColorLight.equals(new ColorUIResource(106, 150, 192))) { - // Generate the color arrays - DEFAULT_COLORS = new Color[]{ - new Color(106, 150, 192), - new Color(154, 190, 209), - new Color(182, 208, 231), - new Color(200, 223, 255), - new Color(189, 218, 246), - new Color(167, 204, 231), - new Color(148, 191, 226), - new Color(144, 181, 225), - new Color(145, 182, 226), - new Color(151, 188, 230), - new Color(160, 198, 235), - new Color(168, 206, 242), - new Color(174, 213, 244), - new Color(183, 222, 251), - new Color(191, 230, 255), - new Color(202, 237, 255), - new Color(206, 247, 253), - new Color(211, 255, 254), - new Color(208, 255, 254), - new Color(206, 249, 255), - new Color(202, 237, 255),}; - } else { - Color color1[] = ColorHelper.createColorArr(controlColorLight, controlColorDark, 6); - color1[0] = controlColorDark; - Color color2[] = ColorHelper.createColorArr(ColorHelper.brighter(controlColorDark, 10), controlColorLight, 15); - System.arraycopy(color1, 0, DEFAULT_COLORS, 0, 6); - for (int i = 5; i < 20; i++) { - DEFAULT_COLORS[i] = color2[i - 5]; - } - } - if (rolloverColorDark.equals(new ColorUIResource(106, 192, 150))) { - ROLLOVER_COLORS = new Color[]{ - new Color(106, 192, 150), - new Color(154, 209, 190), - new Color(173, 220, 198), - new Color(182, 232, 203), - new Color(180, 234, 207), - new Color(167, 231, 204), - new Color(148, 226, 191), - new Color(144, 225, 181), - new Color(145, 226, 182), - new Color(151, 230, 188), - new Color(160, 235, 198), - new Color(168, 242, 206), - new Color(174, 244, 213), - new Color(183, 251, 222), - new Color(191, 255, 230), - new Color(202, 255, 237), - new Color(206, 253, 247), - new Color(211, 254, 255), - new Color(208, 254, 255), - new Color(206, 249, 255), - new Color(196, 247, 227),}; - } else { - Color color1[] = ColorHelper.createColorArr(rolloverColorLight, rolloverColorDark, 6); - color1[0] = rolloverColorDark; - Color color2[] = ColorHelper.createColorArr(ColorHelper.brighter(rolloverColorDark, 10), rolloverColorLight, 15); - System.arraycopy(color1, 0, ROLLOVER_COLORS, 0, 6); - for (int i = 5; i < 20; i++) { - ROLLOVER_COLORS[i] = color2[i - 5]; - } - } - - HIDEFAULT_COLORS = new Color[]{ - new Color(250, 250, 250), - new Color(250, 250, 250), - new Color(240, 240, 240), - new Color(230, 230, 230), - new Color(220, 220, 220), - new Color(214, 214, 214), - new Color(218, 218, 218), - new Color(222, 222, 222), - new Color(226, 226, 226), - new Color(230, 230, 230), - new Color(234, 234, 234), - new Color(237, 237, 237), - new Color(240, 240, 240), - new Color(242, 242, 242), - new Color(244, 244, 244), - new Color(246, 246, 246), - new Color(248, 248, 248), - new Color(250, 250, 250), - new Color(252, 252, 252), - new Color(254, 254, 254), - new Color(255, 255, 255),}; - - ACTIVE_COLORS = DEFAULT_COLORS; - INACTIVE_COLORS = HIDEFAULT_COLORS; - SELECTED_COLORS = DEFAULT_COLORS; - - PRESSED_COLORS = ColorHelper.createColorArr(lightGray, extraLightGray, 20); - DISABLED_COLORS = new Color[HIDEFAULT_COLORS.length]; - for (int i = 0; i < HIDEFAULT_COLORS.length; i++) { - DISABLED_COLORS[i] = ColorHelper.brighter(HIDEFAULT_COLORS[i], 40.0); - } - - WINDOW_TITLE_COLORS = ColorHelper.createColorArr(windowTitleColorLight, windowTitleColorDark, 20); - WINDOW_INACTIVE_TITLE_COLORS = ColorHelper.createColorArr(windowInactiveTitleColorLight, windowInactiveTitleColorDark, 20); - MENUBAR_COLORS = ColorHelper.createColorArr(menuColorLight, menuColorDark, 20); - TOOLBAR_COLORS = MENUBAR_COLORS; - - BUTTON_COLORS = HIDEFAULT_COLORS; - TAB_COLORS = BUTTON_COLORS; - if (isBrightMode()) { - COL_HEADER_COLORS = HIDEFAULT_COLORS; - } else { - COL_HEADER_COLORS = DEFAULT_COLORS; - } - if (isBrightMode()) { - THUMB_COLORS = HIDEFAULT_COLORS; - } else { - THUMB_COLORS = DEFAULT_COLORS; - } - TRACK_COLORS = ColorHelper.createColorArr(new Color(220, 220, 220), Color.white, 20); - SLIDER_COLORS = DEFAULT_COLORS; - PROGRESSBAR_COLORS = DEFAULT_COLORS; - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinIconFactory.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinIconFactory.java deleted file mode 100644 index be86a963d..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinIconFactory.java +++ /dev/null @@ -1,213 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.AbstractIconFactory; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class McWinIconFactory implements AbstractIconFactory { - - private static McWinIconFactory instance = null; - - private McWinIconFactory() { - } - - public static synchronized McWinIconFactory getInstance() { - if (instance == null) { - instance = new McWinIconFactory(); - } - return instance; - } - - public Icon getOptionPaneErrorIcon() { - return McWinIcons.getOptionPaneErrorIcon(); - } - - public Icon getOptionPaneWarningIcon() { - return McWinIcons.getOptionPaneWarningIcon(); - } - - public Icon getOptionPaneInformationIcon() { - return McWinIcons.getOptionPaneInformationIcon(); - } - - public Icon getOptionPaneQuestionIcon() { - return McWinIcons.getOptionPaneQuestionIcon(); - } - - public Icon getFileChooserDetailViewIcon() { - return McWinIcons.getFileChooserDetailViewIcon(); - } - - public Icon getFileChooserHomeFolderIcon() { - return McWinIcons.getFileChooserHomeFolderIcon(); - } - - public Icon getFileChooserListViewIcon() { - return McWinIcons.getFileChooserListViewIcon(); - } - - public Icon getFileChooserNewFolderIcon() { - return McWinIcons.getFileChooserNewFolderIcon(); - } - - public Icon getFileChooserUpFolderIcon() { - return McWinIcons.getFileChooserUpFolderIcon(); - } - - public Icon getMenuIcon() { - return McWinIcons.getMenuIcon(); - } - - public Icon getIconIcon() { - return McWinIcons.getIconIcon(); - } - - public Icon getMaxIcon() { - return McWinIcons.getMaxIcon(); - } - - public Icon getMinIcon() { - return McWinIcons.getMinIcon(); - } - - public Icon getCloseIcon() { - return McWinIcons.getCloseIcon(); - } - - public Icon getPaletteCloseIcon() { - return McWinIcons.getPaletteCloseIcon(); - } - - public Icon getRadioButtonIcon() { - return McWinIcons.getRadioButtonIcon(); - } - - public Icon getCheckBoxIcon() { - return McWinIcons.getCheckBoxIcon(); - } - - public Icon getComboBoxIcon() { - return McWinIcons.getComboBoxIcon(); - } - - public Icon getTreeComputerIcon() { - return McWinIcons.getTreeComputerIcon(); - } - - public Icon getTreeFloppyDriveIcon() { - return McWinIcons.getTreeFloppyDriveIcon(); - } - - public Icon getTreeHardDriveIcon() { - return McWinIcons.getTreeHardDriveIcon(); - } - - public Icon getTreeFolderIcon() { - return McWinIcons.getTreeFolderIcon(); - } - - public Icon getTreeLeafIcon() { - return McWinIcons.getTreeLeafIcon(); - } - - public Icon getTreeCollapsedIcon() { - return McWinIcons.getTreeControlIcon(true); - } - - public Icon getTreeExpandedIcon() { - return McWinIcons.getTreeControlIcon(false); - } - - public Icon getMenuArrowIcon() { - return McWinIcons.getMenuArrowIcon(); - } - - public Icon getMenuCheckBoxIcon() { - return McWinIcons.getMenuCheckBoxIcon(); - } - - public Icon getMenuRadioButtonIcon() { - return McWinIcons.getMenuRadioButtonIcon(); - } - - public Icon getUpArrowIcon() { - return McWinIcons.getUpArrowIcon(); - } - - public Icon getDownArrowIcon() { - return McWinIcons.getDownArrowIcon(); - } - - public Icon getLeftArrowIcon() { - return McWinIcons.getLeftArrowIcon(); - } - - public Icon getRightArrowIcon() { - return McWinIcons.getRightArrowIcon(); - } - - public Icon getSplitterDownArrowIcon() { - return McWinIcons.getSplitterDownArrowIcon(); - } - - public Icon getSplitterHorBumpIcon() { - return McWinIcons.getSplitterHorBumpIcon(); - } - - public Icon getSplitterLeftArrowIcon() { - return McWinIcons.getSplitterLeftArrowIcon(); - } - - public Icon getSplitterRightArrowIcon() { - return McWinIcons.getSplitterRightArrowIcon(); - } - - public Icon getSplitterUpArrowIcon() { - return McWinIcons.getSplitterUpArrowIcon(); - } - - public Icon getSplitterVerBumpIcon() { - return McWinIcons.getSplitterVerBumpIcon(); - } - - public Icon getThumbHorIcon() { - return McWinIcons.getThumbHorIcon(); - } - - public Icon getThumbVerIcon() { - return McWinIcons.getThumbVerIcon(); - } - - public Icon getThumbHorIconRollover() { - return McWinIcons.getThumbHorIconRollover(); - } - - public Icon getThumbVerIconRollover() { - return McWinIcons.getThumbVerIconRollover(); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinIcons.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinIcons.java deleted file mode 100644 index 07f868299..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinIcons.java +++ /dev/null @@ -1,291 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.*; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.Ellipse2D; -import java.io.Serializable; -import javax.swing.*; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class McWinIcons extends BaseIcons { - - public static Icon getIconIcon() { - if (iconIcon == null) { - iconIcon = new MacIconIcon(); - } - return iconIcon; - } - - public static Icon getMinIcon() { - if (minIcon == null) { - minIcon = new MacMinIcon(); - } - return minIcon; - } - - public static Icon getMaxIcon() { - if (maxIcon == null) { - maxIcon = new MacMaxIcon(); - } - return maxIcon; - } - - public static Icon getCloseIcon() { - if (closeIcon == null) { - closeIcon = new MacCloseIcon(); - } - return closeIcon; - } - - public static Icon getRadioButtonIcon() { - if (radioButtonIcon == null) { - radioButtonIcon = new RadioButtonIcon(); - } - return radioButtonIcon; - } - - public static Icon getCheckBoxIcon() { - if (checkBoxIcon == null) { - checkBoxIcon = new CheckBoxIcon(); - } - return checkBoxIcon; - } - - public static Icon getThumbHorIcon() { - if (thumbHorIcon == null) { - thumbHorIcon = new ThumbIcon(false); - } - return thumbHorIcon; - } - - public static Icon getThumbVerIcon() { - if (thumbVerIcon == null) { - thumbVerIcon = new ThumbIcon(false); - } - return thumbVerIcon; - } - - public static Icon getThumbHorIconRollover() { - if (thumbHorIconRollover == null) { - thumbHorIconRollover = new ThumbIcon(true); - } - return thumbHorIconRollover; - } - - public static Icon getThumbVerIconRollover() { - if (thumbVerIconRollover == null) { - thumbVerIconRollover = new ThumbIcon(true); - } - return thumbVerIconRollover; - } - - -//-------------------------------------------------------------------------------------------------------- - private static class CheckBoxIcon implements Icon, UIResource, Serializable { - - private static Icon checkIcon = new LazyImageIcon("mcwin/icons/CheckSymbol.gif"); - private static Icon checkDisabledIcon = new LazyImageIcon("mcwin/icons/CheckSymbolDisabled.gif"); - private static Icon checkPressedIcon = new LazyImageIcon("mcwin/icons/CheckPressedSymbol.gif"); - - private final static int WIDTH = 13; - private final static int HEIGHT = 14; - - public void paintIcon(Component c, Graphics g, int x, int y) { - if (!JTattooUtilities.isLeftToRight(c)) { - x += 3; - } - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - Color colors[]; - if (button.isEnabled()) { - if (button.isRolloverEnabled() && model.isRollover()) { - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - } else if (!JTattooUtilities.isFrameActive(button)) { - colors = AbstractLookAndFeel.getTheme().getInActiveColors(); - } else if (button.isSelected()) { - colors = AbstractLookAndFeel.getTheme().getDefaultColors(); - } else { - colors = AbstractLookAndFeel.getTheme().getButtonColors(); - } - JTattooUtilities.fillHorGradient(g, colors, x + 1, y + 1, WIDTH - 1, HEIGHT - 1); - g.setColor(AbstractLookAndFeel.getFrameColor()); - g.drawRect(x, y, WIDTH, HEIGHT); - } else { - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - JTattooUtilities.fillHorGradient(g, colors, x + 1, y + 1, WIDTH - 1, HEIGHT - 1); - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 20)); - g.drawRect(x, y, WIDTH, HEIGHT); - } - if (button.isEnabled() && !model.isRollover() && !model.isPressed() && !model.isSelected()) { - g.setColor(Color.white); - g.drawLine(x + 1, y + 1, x + 1, y + HEIGHT - 2); - g.drawLine(x + WIDTH - 1, y + 1, x + WIDTH - 1, y + HEIGHT - 2); - } - if (model.isPressed()) { - int xi = x + ((WIDTH - checkPressedIcon.getIconWidth()) / 2) + 1; - int yi = y + ((HEIGHT - checkPressedIcon.getIconHeight()) / 2) + 1; - checkPressedIcon.paintIcon(c, g, xi, yi); - } else if (model.isSelected()) { - int xi = x + ((WIDTH - checkIcon.getIconWidth()) / 2) + 1; - int yi = y + ((HEIGHT - checkIcon.getIconHeight()) / 2); - if (model.isEnabled()) - checkIcon.paintIcon(c, g, xi + 2, yi); - else - checkDisabledIcon.paintIcon(c, g, xi + 2, yi); - } - } - - public int getIconWidth() { - return WIDTH + 6; - } - - public int getIconHeight() { - return HEIGHT; - } - } - - private static class RadioButtonIcon implements Icon, UIResource, Serializable { - - private static Icon radioIcon = new LazyImageIcon("mcwin/icons/RadioSymbol.gif"); - private static Icon radioDisabledIcon = new LazyImageIcon("mcwin/icons/RadioSymbolDisabled.gif"); - - private final static int WIDTH = 14; - private final static int HEIGHT = 14; - - public void paintIcon(Component c, Graphics g, int x, int y) { - if (!JTattooUtilities.isLeftToRight(c)) { - x += 3; - } - Graphics2D g2D = (Graphics2D) g; - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - Color colors[]; - if (button.isEnabled()) { - if (button.isRolloverEnabled() && model.isRollover() && !model.isArmed()) { - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - } else if (!JTattooUtilities.isFrameActive(button)) { - colors = AbstractLookAndFeel.getTheme().getInActiveColors(); - } else if (button.isSelected()) { - colors = AbstractLookAndFeel.getTheme().getDefaultColors(); - } else { - colors = AbstractLookAndFeel.getTheme().getButtonColors(); - } - } else { - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } - - Shape savedClip = g.getClip(); - Area clipArea = new Area(new Ellipse2D.Double(x, y, WIDTH + 1, HEIGHT + 1)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - JTattooUtilities.fillHorGradient(g, colors, x, y, WIDTH, HEIGHT); - g2D.setClip(savedClip); - - if (button.isEnabled()) { - g2D.setColor(AbstractLookAndFeel.getFrameColor()); - } else { - g2D.setColor(ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 20)); - } - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2D.drawOval(x, y, WIDTH, HEIGHT); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - - if (model.isSelected()) { - int xi = x + ((WIDTH - radioIcon.getIconWidth()) / 2) + 1; - int yi = y + ((HEIGHT - radioIcon.getIconHeight()) / 2) + 1; - if (model.isEnabled()) - radioIcon.paintIcon(c, g, xi, yi); - else - radioDisabledIcon.paintIcon(c, g, xi, yi); - } - } - - public int getIconWidth() { - return WIDTH + 4; - } - - public int getIconHeight() { - return HEIGHT; - } - } - - private static class ThumbIcon implements Icon, UIResource, Serializable { - - private final static int WIDTH = 15; - private final static int HEIGHT = 15; - private boolean isRollover = false; - - public ThumbIcon(boolean isRollover) { - this.isRollover = isRollover; - } - - public void paintIcon(Component c, Graphics g, int x, int y) { - Graphics2D g2D = (Graphics2D) g; - Color colors[]; - if (isRollover) { - colors = AbstractLookAndFeel.getTheme().getRolloverColors(); - } else { - if (AbstractLookAndFeel.getTheme().isBrightMode()) { - colors = AbstractLookAndFeel.getTheme().getButtonColors(); - } else { - colors = AbstractLookAndFeel.getTheme().getSelectedColors(); - } - } - - Shape savedClip = g2D.getClip(); - if (savedClip != null) { - Area clipArea = new Area(new Ellipse2D.Double(x + 1, y + 1, WIDTH, HEIGHT)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - JTattooUtilities.fillHorGradient(g, colors, x + 1, y + 1, WIDTH, HEIGHT); - g2D.setClip(savedClip); - } else { - Area ellipseArea = new Area(new Ellipse2D.Double(x + 1, y + 1, WIDTH, HEIGHT)); - g2D.setClip(ellipseArea); - JTattooUtilities.fillHorGradient(g, colors, x, y, WIDTH, HEIGHT); - g2D.setClip(null); - } - g2D.setColor(AbstractLookAndFeel.getFrameColor()); - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2D.drawOval(x + 1, y + 1, WIDTH - 1, HEIGHT - 1); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - } - - public int getIconWidth() { - return WIDTH + 2; - } - - public int getIconHeight() { - return HEIGHT + 2; - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinInternalFrameTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinInternalFrameTitlePane.java deleted file mode 100644 index bd972824b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinInternalFrameTitlePane.java +++ /dev/null @@ -1,224 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.Icon; -import javax.swing.JInternalFrame; - -/** - * @author Michael Hagen - */ -public class McWinInternalFrameTitlePane extends BaseInternalFrameTitlePane { - - public McWinInternalFrameTitlePane(JInternalFrame f) { - super(f); - } - - protected LayoutManager createLayout() { - return new MyTitlePaneLayout(); - } - - public void paintBorder(Graphics g) { - if (JTattooUtilities.isActive(this)) { - g.setColor(AbstractLookAndFeel.getWindowBorderColor()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveBorderColor()); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } - - public void paintText(Graphics g, int x, int y, String title) { - if (isMacStyleWindowDecoration()) { - x += paintIcon(g, x, y) + 5; - } - if (isActive()) { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getWindowTitleColorLight(), 40)); - JTattooUtilities.drawString(frame, g, title, x, y - 1); - g.setColor(AbstractLookAndFeel.getWindowTitleForegroundColor()); - JTattooUtilities.drawString(frame, g, title, x, y - 2); - } else { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getWindowInactiveTitleColorLight(), 40)); - JTattooUtilities.drawString(frame, g, title, x, y - 1); - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - JTattooUtilities.drawString(frame, g, title, x, y - 2); - } - } - -//------------------------------------------------------------------------------ -// inner classes -//------------------------------------------------------------------------------ - class MyTitlePaneLayout extends TitlePaneLayout { - - public void addLayoutComponent(String name, Component c) { - } - - public void removeLayoutComponent(Component c) { - } - - public Dimension preferredLayoutSize(Container c) { - return minimumLayoutSize(c); - } - - public Dimension minimumLayoutSize(Container c) { - int width = 30; - if (frame.isClosable()) { - width += 21; - } - if (frame.isMaximizable()) { - width += 16 + (frame.isClosable() ? 10 : 4); - } - if (frame.isIconifiable()) { - width += 16 + (frame.isMaximizable() ? 2 : (frame.isClosable() ? 10 : 4)); - } - FontMetrics fm = getFontMetrics(getFont()); - String frameTitle = frame.getTitle(); - int title_w = frameTitle != null ? fm.stringWidth(frameTitle) : 0; - int title_length = frameTitle != null ? frameTitle.length() : 0; - - if (title_length > 2) { - int subtitle_w = fm.stringWidth(frame.getTitle().substring(0, 2) + "..."); - width += (title_w < subtitle_w) ? title_w : subtitle_w; - } else { - width += title_w; - } - - int height = paletteTitleHeight; - if (!isPalette) { - int fontHeight = fm.getHeight() + 5; - Icon icon = isMacStyleWindowDecoration() ? null : frame.getFrameIcon(); - int iconHeight = 0; - if (icon != null) { - iconHeight = Math.min(icon.getIconHeight(), 18); - } - iconHeight += 5; - height = Math.max(fontHeight, iconHeight); - } - return new Dimension(width, height); - } - - public void layoutContainer(Container c) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - layoutMacStyle(c); - } else { - layoutDefault(c); - } - } - - public void layoutDefault(Container c) { - boolean leftToRight = JTattooUtilities.isLeftToRight(frame); - - int spacing = getHorSpacing(); - int w = getWidth(); - int h = getHeight(); - - // assumes all buttons have the same dimensions these dimensions include the borders - int buttonHeight = h - getVerSpacing() - 1; - int buttonWidth = buttonHeight; - - int x = leftToRight ? w - spacing : 0; - int y = Math.max(0, ((h - buttonHeight) / 2) - 1); - - if (frame.isClosable()) { - x += leftToRight ? -buttonWidth : spacing; - closeButton.setBounds(x, y, buttonWidth, buttonHeight); - if (!leftToRight) { - x += buttonWidth; - } - } - - if (frame.isMaximizable() && !isPalette) { - x += leftToRight ? -spacing - buttonWidth : spacing; - maxButton.setBounds(x, y, buttonWidth, buttonHeight); - if (!leftToRight) { - x += buttonWidth; - } - } - - if (frame.isIconifiable() && !isPalette) { - x += leftToRight ? -spacing - buttonWidth : spacing; - iconButton.setBounds(x, y, buttonWidth, buttonHeight); - if (!leftToRight) { - x += buttonWidth; - } - } - - buttonsWidth = leftToRight ? w - x : x; - - if (customTitlePanel != null) { - int maxWidth = w - buttonsWidth - spacing - 20; - Icon icon = frame.getFrameIcon(); - if (icon != null) { - maxWidth -= icon.getIconWidth(); - maxWidth -= spacing; - } - int cpw = Math.min(maxWidth, customTitlePanel.getPreferredSize().width); - int cph = h; - int cpx = leftToRight ? w - buttonsWidth - cpw : buttonsWidth; - int cpy = 0; - customTitlePanel.setBounds(cpx, cpy, cpw, cph); - buttonsWidth += customTitlePanel.getPreferredSize().width; - } - } - - private void layoutMacStyle(Container c) { - int spacing = getHorSpacing(); - int h = getHeight(); - - // assumes all buttons have the same dimensions these dimensions include the borders - int btnHeight = h - getVerSpacing(); - int btnWidth = btnHeight; - - int x = 0; - int y = 0; - - if (frame.isClosable()) { - closeButton.setBounds(x, y, btnWidth, btnHeight); - x += btnWidth + spacing; - } - if (frame.isIconifiable() && !isPalette) { - iconButton.setBounds(x, y, btnWidth, btnHeight); - x += btnWidth + spacing; - } - if (frame.isMaximizable() && !isPalette) { - maxButton.setBounds(x, y, btnWidth, btnHeight); - x += btnWidth + spacing; - } - - buttonsWidth = x; - - if (customTitlePanel != null) { - int cpx = buttonsWidth + 5; - int cpy = 0; - int cpw = customTitlePanel.getPreferredSize().width; - int cph = h; - customTitlePanel.setBounds(cpx, cpy, cpw, cph); - buttonsWidth += cpw + 5; - } - } - - } // end class MyTitlePaneLayout - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinInternalFrameUI.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinInternalFrameUI.java deleted file mode 100644 index 382bebaf1..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinInternalFrameUI.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.BaseInternalFrameUI; -import javax.swing.JComponent; -import javax.swing.JInternalFrame; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class McWinInternalFrameUI extends BaseInternalFrameUI { - - public McWinInternalFrameUI(JInternalFrame b) { - super(b); - } - - public static ComponentUI createUI(JComponent c) { - return new McWinInternalFrameUI((JInternalFrame) c); - } - - protected JComponent createNorthPane(JInternalFrame w) { - titlePane = new McWinInternalFrameTitlePane(w); - return titlePane; - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinLookAndFeel.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinLookAndFeel.java deleted file mode 100644 index e83519b75..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinLookAndFeel.java +++ /dev/null @@ -1,321 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.*; -import java.util.*; -import javax.swing.UIDefaults; -import javax.swing.plaf.InsetsUIResource; - -/** - * @author Michael Hagen - */ -public class McWinLookAndFeel extends AbstractLookAndFeel { - - private static McWinDefaultTheme myTheme = null; - - private static final ArrayList themesList = new ArrayList(); - private static final HashMap themesMap = new HashMap(); - private static final Properties defaultProps = new Properties(); - private static final Properties smallFontProps = new Properties(); - private static final Properties largeFontProps = new Properties(); - private static final Properties giantFontProps = new Properties(); - private static final Properties modernProps = new Properties(); - private static final Properties modernSmallFontProps = new Properties(); - private static final Properties modernLargeFontProps = new Properties(); - private static final Properties modernGiantFontProps = new Properties(); - private static final Properties pinkProps = new Properties(); - private static final Properties pinkSmallFontProps = new Properties(); - private static final Properties pinkLargeFontProps = new Properties(); - private static final Properties pinkGiantFontProps = new Properties(); - - static { - smallFontProps.setProperty("controlTextFont", "Dialog 10"); - smallFontProps.setProperty("systemTextFont", "Dialog 10"); - smallFontProps.setProperty("userTextFont", "Dialog 10"); - smallFontProps.setProperty("menuTextFont", "Dialog 10"); - smallFontProps.setProperty("windowTitleFont", "Dialog bold 10"); - smallFontProps.setProperty("subTextFont", "Dialog 8"); - - largeFontProps.setProperty("controlTextFont", "Dialog 14"); - largeFontProps.setProperty("systemTextFont", "Dialog 14"); - largeFontProps.setProperty("userTextFont", "Dialog 14"); - largeFontProps.setProperty("menuTextFont", "Dialog 14"); - largeFontProps.setProperty("windowTitleFont", "Dialog bold 14"); - largeFontProps.setProperty("subTextFont", "Dialog 12"); - - giantFontProps.setProperty("controlTextFont", "Dialog 18"); - giantFontProps.setProperty("systemTextFont", "Dialog 18"); - giantFontProps.setProperty("userTextFont", "Dialog 18"); - giantFontProps.setProperty("menuTextFont", "Dialog 18"); - giantFontProps.setProperty("windowTitleFont", "Dialog 18"); - giantFontProps.setProperty("subTextFont", "Dialog 16"); - - modernProps.setProperty("brightMode", "on"); - modernProps.setProperty("menuOpaque", "on"); - modernProps.setProperty("backgroundPattern", "off"); - modernProps.setProperty("drawSquareButtons", "on"); - modernProps.setProperty("windowTitleForegroundColor", "54 68 84"); - modernProps.setProperty("windowTitleColorLight", "204 208 212"); - modernProps.setProperty("windowTitleColorDark", "172 179 185"); - modernProps.setProperty("windowBorderColor", "150 158 167"); - modernProps.setProperty("windowInactiveTitleForegroundColor", "67 84 103"); - modernProps.setProperty("windowInactiveTitleColorLight", "232 234 236"); - modernProps.setProperty("windowInactiveTitleColorDark", "221 223 225"); - modernProps.setProperty("windowInactiveBorderColor", "172 179 185"); - modernProps.setProperty("backgroundColor", "226 228 231"); - modernProps.setProperty("selectionBackgroundColor", "201 205 240"); - modernProps.setProperty("rolloverColor", "228 228 192"); - modernProps.setProperty("rolloverColorLight", "248 248 184"); - modernProps.setProperty("rolloverColorDark", "220 220 172"); - modernProps.setProperty("controlColorLight", "194 204 216"); - modernProps.setProperty("controlColorDark", "160 177 197"); - modernProps.setProperty("menuBackgroundColor", "242 244 247"); - modernProps.setProperty("menuColorLight", "242 244 247"); - modernProps.setProperty("menuColorDark", "226 228 231"); - modernProps.setProperty("menuSelectionBackgroundColor", "220 220 172"); - modernProps.setProperty("toolbarBackgroundColor", "226 228 231"); - modernProps.setProperty("desktopColor", "208 211 216"); - - pinkProps.setProperty("backgroundColorLight", "248 244 248"); - pinkProps.setProperty("backgroundColorDark", "255 255 255"); - pinkProps.setProperty("focusCellColor", "160 120 160"); - pinkProps.setProperty("selectionBackgroundColor", "248 202 248"); - pinkProps.setProperty("rolloverColor", "240 145 240"); - pinkProps.setProperty("controlColorLight", "255 220 255"); - pinkProps.setProperty("controlColorDark", "248 140 248"); - pinkProps.setProperty("rolloverColorLight", "240 180 240"); - pinkProps.setProperty("rolloverColorDark", "232 120 232"); - pinkProps.setProperty("windowTitleForegroundColor", "0 0 0"); - pinkProps.setProperty("windowTitleBackgroundColor", "248 180 248"); - pinkProps.setProperty("windowTitleColorLight", "248 180 248"); - pinkProps.setProperty("windowTitleColorDark", "200 120 200"); - pinkProps.setProperty("windowBorderColor", "200 120 200"); - pinkProps.setProperty("menuSelectionForegroundColor", "0 0 0"); - pinkProps.setProperty("menuSelectionBackgroundColor", "248 202 248"); - pinkProps.setProperty("desktopColor", "242 242 242"); - - String key; - String value; - Iterator iter = smallFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = smallFontProps.getProperty(key); - modernSmallFontProps.setProperty(key, value); - pinkSmallFontProps.setProperty(key, value); - } - iter = largeFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = largeFontProps.getProperty(key); - modernLargeFontProps.setProperty(key, value); - pinkLargeFontProps.setProperty(key, value); - } - iter = giantFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = giantFontProps.getProperty(key); - modernGiantFontProps.setProperty(key, value); - pinkGiantFontProps.setProperty(key, value); - } - - iter = modernProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = modernProps.getProperty(key); - modernSmallFontProps.setProperty(key, value); - modernLargeFontProps.setProperty(key, value); - modernGiantFontProps.setProperty(key, value); - } - iter = pinkProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = pinkProps.getProperty(key); - pinkSmallFontProps.setProperty(key, value); - pinkLargeFontProps.setProperty(key, value); - pinkGiantFontProps.setProperty(key, value); - } - - themesList.add("Default"); - themesList.add("Small-Font"); - themesList.add("Large-Font"); - themesList.add("Giant-Font"); - - themesList.add("Modern"); - themesList.add("Modern-Small-Font"); - themesList.add("Modern-Large-Font"); - themesList.add("Modern-Giant-Font"); - - themesList.add("Pink"); - themesList.add("Pink-Small-Font"); - themesList.add("Pink-Large-Font"); - themesList.add("Pink-Giant-Font"); - - themesMap.put("Default", defaultProps); - themesMap.put("Small-Font", smallFontProps); - themesMap.put("Large-Font", largeFontProps); - themesMap.put("Giant-Font", giantFontProps); - - themesMap.put("Modern", modernProps); - themesMap.put("Modern-Small-Font", modernSmallFontProps); - themesMap.put("Modern-Large-Font", modernLargeFontProps); - themesMap.put("Modern-Giant-Font", modernGiantFontProps); - - themesMap.put("Pink", pinkProps); - themesMap.put("Pink-Small-Font", pinkSmallFontProps); - themesMap.put("Pink-Large-Font", pinkLargeFontProps); - themesMap.put("Pink-Giant-Font", pinkGiantFontProps); - } - - public static java.util.List getThemes() { - return themesList; - } - - public static Properties getThemeProperties(String name) { - return ((Properties) themesMap.get(name)); - } - - public static void setTheme(String name) { - setTheme((Properties) themesMap.get(name)); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - - public static void setTheme(String name, String licenseKey, String logoString) { - Properties props = (Properties) themesMap.get(name); - if (props != null) { - props.put("licenseKey", licenseKey); - props.put("logoString", logoString); - setTheme(props); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - } - - public static void setTheme(Properties themesProps) { - if (myTheme == null) { - myTheme = new McWinDefaultTheme(); - } - if ((myTheme != null) && (themesProps != null)) { - myTheme.setUpColor(); - myTheme.setProperties(themesProps); - myTheme.setUpColorArrs(); - AbstractLookAndFeel.setTheme(myTheme); - } - } - - public static void setCurrentTheme(Properties themesProps) { - setTheme(themesProps); - } - - public String getName() { - return "McWin"; - } - - public String getID() { - return "McWin"; - } - - public String getDescription() { - return "The McWin Look and Feel"; - } - - public boolean isNativeLookAndFeel() { - return false; - } - - public boolean isSupportedLookAndFeel() { - return true; - } - - public AbstractBorderFactory getBorderFactory() { - return McWinBorderFactory.getInstance(); - } - - public AbstractIconFactory getIconFactory() { - return McWinIconFactory.getInstance(); - } - - protected void createDefaultTheme() { - if (myTheme == null) { - myTheme = new McWinDefaultTheme(); - } - setTheme(myTheme); - } - - protected void initClassDefaults(UIDefaults table) { - super.initClassDefaults(table); - Object[] uiDefaults = { - // BaseLookAndFeel classes - "LabelUI", BaseLabelUI.class.getName(), - "SeparatorUI", BaseSeparatorUI.class.getName(), - "TextFieldUI", BaseTextFieldUI.class.getName(), - "TextAreaUI", BaseTextAreaUI.class.getName(), - "EditorPaneUI", BaseEditorPaneUI.class.getName(), - "PasswordFieldUI", BasePasswordFieldUI.class.getName(), - "ToolTipUI", BaseToolTipUI.class.getName(), - "TreeUI", BaseTreeUI.class.getName(), - "TableUI", BaseTableUI.class.getName(), - "TableHeaderUI", BaseTableHeaderUI.class.getName(), - "ScrollBarUI", BaseScrollBarUI.class.getName(), - "ProgressBarUI", BaseProgressBarUI.class.getName(), - "FileChooserUI", BaseFileChooserUI.class.getName(), - "MenuUI", BaseMenuUI.class.getName(), - "PopupMenuUI", BasePopupMenuUI.class.getName(), - "MenuItemUI", BaseMenuItemUI.class.getName(), - "CheckBoxMenuItemUI", BaseCheckBoxMenuItemUI.class.getName(), - "RadioButtonMenuItemUI", BaseRadioButtonMenuItemUI.class.getName(), - "PopupMenuSeparatorUI", BaseSeparatorUI.class.getName(), - "DesktopPaneUI", BaseDesktopPaneUI.class.getName(), - - // McWinLookAndFeel classes - "CheckBoxUI", McWinCheckBoxUI.class.getName(), - "RadioButtonUI", McWinRadioButtonUI.class.getName(), - "ButtonUI", McWinButtonUI.class.getName(), - "ToggleButtonUI", McWinToggleButtonUI.class.getName(), - "ComboBoxUI", McWinComboBoxUI.class.getName(), - "SliderUI", McWinSliderUI.class.getName(), - "PanelUI", McWinPanelUI.class.getName(), - "ScrollPaneUI", McWinScrollPaneUI.class.getName(), - "TabbedPaneUI", McWinTabbedPaneUI.class.getName(), - "ToolBarUI", McWinToolBarUI.class.getName(), - "MenuBarUI", McWinMenuBarUI.class.getName(), - "SplitPaneUI", McWinSplitPaneUI.class.getName(), - "InternalFrameUI", McWinInternalFrameUI.class.getName(), - "RootPaneUI", McWinRootPaneUI.class.getName(),}; - table.putDefaults(uiDefaults); - if (JTattooUtilities.getJavaVersion() >= 1.5) { - table.put("FormattedTextFieldUI", BaseFormattedTextFieldUI.class.getName()); - table.put("SpinnerUI", BaseSpinnerUI.class.getName()); - } - } - - protected void initComponentDefaults(UIDefaults table) { - super.initComponentDefaults(table); - table.put("SplitPane.centerOneTouchButtons", Boolean.FALSE); - table.put("TabbedPane.tabAreaInsets", new InsetsUIResource(5, 5, 6, 5)); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinMenuBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinMenuBarUI.java deleted file mode 100644 index a8954bde5..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinMenuBarUI.java +++ /dev/null @@ -1,59 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.JMenuBar; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class McWinMenuBarUI extends BaseMenuBarUI { - - private static final Color shadowColors[] = ColorHelper.createColorArr(Color.white, new Color(240, 240, 240), 8); - - public static ComponentUI createUI(JComponent x) { - return new McWinMenuBarUI(); - } - - public void installUI(JComponent c) { - super.installUI(c); - if ((c != null) && (c instanceof JMenuBar)) { - c.setBorder(McWinBorders.getMenuBarBorder()); - ((JMenuBar) c).setBorderPainted(true); - } - } - - public void paint(Graphics g, JComponent c) { - if (AbstractLookAndFeel.getTheme().isBackgroundPatternOn()) { - McWinUtils.fillComponent(g, c, shadowColors); - } else { - super.paint(g, c); - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinPanelUI.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinPanelUI.java deleted file mode 100644 index b0ab6dce6..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinPanelUI.java +++ /dev/null @@ -1,53 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.BasePanelUI; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class McWinPanelUI extends BasePanelUI { - - private static McWinPanelUI panelUI = null; - - public static ComponentUI createUI(JComponent c) { - if (panelUI == null) { - panelUI = new McWinPanelUI(); - } - return panelUI; - } - - public void update(Graphics g, JComponent c) { - if (c.isOpaque() && c.getBackground() instanceof ColorUIResource && c.getClientProperty("backgroundTexture") == null) { - McWinUtils.fillComponent(g, c); - } else { - super.update(g, c); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinRadioButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinRadioButtonUI.java deleted file mode 100644 index 595d720fb..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinRadioButtonUI.java +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseRadioButtonUI; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class McWinRadioButtonUI extends BaseRadioButtonUI { - - private static McWinRadioButtonUI radioButtonUI = null; - - public static ComponentUI createUI(JComponent c) { - if (radioButtonUI == null) { - radioButtonUI = new McWinRadioButtonUI(); - } - return radioButtonUI; - } - - public void paintBackground(Graphics g, JComponent c) { - if (c.isOpaque()) { - if ((c.getBackground().equals(AbstractLookAndFeel.getBackgroundColor())) && (c.getBackground() instanceof ColorUIResource)) { - McWinUtils.fillComponent(g, c); - } else { - g.setColor(c.getBackground()); - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinRootPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinRootPaneUI.java deleted file mode 100644 index 0f92747ab..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinRootPaneUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.BaseRootPaneUI; -import com.jtattoo.plaf.BaseTitlePane; -import javax.swing.JComponent; -import javax.swing.JRootPane; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class McWinRootPaneUI extends BaseRootPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new McWinRootPaneUI(); - } - - public BaseTitlePane createTitlePane(JRootPane root) { - return new McWinTitlePane(root, this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinScrollPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinScrollPaneUI.java deleted file mode 100644 index 39546fbeb..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinScrollPaneUI.java +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.BaseScrollPaneUI; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class McWinScrollPaneUI extends BaseScrollPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new McWinScrollPaneUI(); - } - - public void installDefaults(JScrollPane p) { - super.installDefaults(p); - p.getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinSliderUI.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinSliderUI.java deleted file mode 100644 index f992935b3..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinSliderUI.java +++ /dev/null @@ -1,62 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.BaseSliderUI; -import java.awt.Component; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.JSlider; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class McWinSliderUI extends BaseSliderUI { - - public McWinSliderUI(JSlider slider) { - super(slider); - } - - public static ComponentUI createUI(JComponent c) { - return new McWinSliderUI((JSlider) c); - } - - public void paintBackground(Graphics g, JComponent c) { - if (c.isOpaque()) { - Component parent = c.getParent(); - if ((parent != null) && (parent.getBackground() instanceof ColorUIResource)) { - McWinUtils.fillComponent(g, c); - } else { - if (parent != null) { - g.setColor(parent.getBackground()); - } else { - g.setColor(c.getBackground()); - } - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinSplitPaneDivider.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinSplitPaneDivider.java deleted file mode 100644 index 164ff47eb..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinSplitPaneDivider.java +++ /dev/null @@ -1,51 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseSplitPaneDivider; -import java.awt.Graphics; - -/** - * @author Michael Hagen - */ -public class McWinSplitPaneDivider extends BaseSplitPaneDivider { - - public McWinSplitPaneDivider(McWinSplitPaneUI ui) { - super(ui); - } - - public void paint(Graphics g) { - if (AbstractLookAndFeel.getTheme().isBrightMode()) { - centerOneTouchButtons = true; - doLayout(); - super.paint(g); - } else { - centerOneTouchButtons = false; - doLayout(); - McWinUtils.fillComponent(g, this); - paintComponents(g); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinSplitPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinSplitPaneUI.java deleted file mode 100644 index f5853cdaf..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinSplitPaneUI.java +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.BaseSplitPaneUI; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSplitPaneDivider; - -/** - * @author Michael Hagen - */ -public class McWinSplitPaneUI extends BaseSplitPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new McWinSplitPaneUI(); - } - - public BasicSplitPaneDivider createDefaultDivider() { - return new McWinSplitPaneDivider(this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinTabbedPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinTabbedPaneUI.java deleted file mode 100644 index a53178c0d..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinTabbedPaneUI.java +++ /dev/null @@ -1,89 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import javax.swing.JComponent; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class McWinTabbedPaneUI extends BaseTabbedPaneUI { - - private Color sepColors[] = null; - private Color altSepColors[] = null; - - public static ComponentUI createUI(JComponent c) { - return new McWinTabbedPaneUI(); - } - - public void installDefaults() { - super.installDefaults(); - tabAreaInsets.bottom = 5; - } - - protected Color[] getContentBorderColors(int tabPlacement) { - Color controlColorLight = AbstractLookAndFeel.getTheme().getControlColorLight(); - if (!controlColorLight.equals(new ColorUIResource(106, 150, 192))) { - controlColorLight = ColorHelper.brighter(controlColorLight, 6); - Color controlColorDark = AbstractLookAndFeel.getTheme().getControlColorDark(); - if (sepColors == null) { - sepColors = new Color[5]; - sepColors[0] = controlColorDark; - sepColors[1] = controlColorLight; - sepColors[2] = controlColorLight; - sepColors[3] = controlColorLight; - sepColors[4] = controlColorDark; - } - return sepColors; - } else { - if (tabPlacement == TOP || tabPlacement == LEFT) { - if (sepColors == null) { - int len = AbstractLookAndFeel.getTheme().getDefaultColors().length; - sepColors = new Color[5]; - sepColors[0] = AbstractLookAndFeel.getTheme().getDefaultColors()[0]; - sepColors[1] = AbstractLookAndFeel.getTheme().getDefaultColors()[len - 6]; - sepColors[2] = AbstractLookAndFeel.getTheme().getDefaultColors()[2]; - sepColors[3] = AbstractLookAndFeel.getTheme().getDefaultColors()[1]; - sepColors[4] = AbstractLookAndFeel.getTheme().getDefaultColors()[0]; - } - return sepColors; - } else { - if (altSepColors == null) { - altSepColors = new Color[5]; - altSepColors[0] = AbstractLookAndFeel.getTheme().getDefaultColors()[9]; - altSepColors[1] = AbstractLookAndFeel.getTheme().getDefaultColors()[8]; - altSepColors[2] = AbstractLookAndFeel.getTheme().getDefaultColors()[7]; - altSepColors[3] = AbstractLookAndFeel.getTheme().getDefaultColors()[6]; - altSepColors[4] = AbstractLookAndFeel.getTheme().getDefaultColors()[0]; - } - return altSepColors; - } - } - } - -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinTitlePane.java deleted file mode 100644 index aeca56e19..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinTitlePane.java +++ /dev/null @@ -1,206 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JRootPane; - -/** - * @author Michael Hagen - */ -public class McWinTitlePane extends BaseTitlePane { - - public McWinTitlePane(JRootPane root, BaseRootPaneUI ui) { - super(root, ui); - } - - public LayoutManager createLayout() { - return new TitlePaneLayout(); - } - - public void paintBorder(Graphics g) { - if (isActive()) { - g.setColor(AbstractLookAndFeel.getTheme().getWindowBorderColor()); - } else { - g.setColor(AbstractLookAndFeel.getTheme().getWindowInactiveBorderColor()); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } - - public void paintText(Graphics g, int x, int y, String title) { - x += paintIcon(g, x, y); - if (isActive()) { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getWindowTitleColorLight(), 40)); - JTattooUtilities.drawString(rootPane, g, title, x, y + 1); - g.setColor(AbstractLookAndFeel.getWindowTitleForegroundColor()); - JTattooUtilities.drawString(rootPane, g, title, x, y); - } else { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getWindowInactiveTitleColorLight(), 40)); - JTattooUtilities.drawString(rootPane, g, title, x, y + 1); - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - JTattooUtilities.drawString(rootPane, g, title, x, y); - } - } - -//------------------------------------------------------------------------------ -// inner classes -//------------------------------------------------------------------------------ - protected class TitlePaneLayout implements LayoutManager { - - public void addLayoutComponent(String name, Component c) { - } - - public void removeLayoutComponent(Component c) { - } - - public Dimension preferredLayoutSize(Container c) { - int height = computeHeight(); - return new Dimension(height, height); - } - - public Dimension minimumLayoutSize(Container c) { - return preferredLayoutSize(c); - } - - protected int computeHeight() { - FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(getFont()); - return fm.getHeight() + 5; - } - - public void layoutContainer(Container c) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - layoutMacStyle(c); - } else { - layoutDefault(c); - } - } - - public void layoutDefault(Container c) { - boolean leftToRight = isLeftToRight(); - - int w = getWidth(); - int h = getHeight(); - - // assumes all buttons have the same dimensions these dimensions include the borders - int spacing = getHorSpacing(); - int buttonHeight = h - getVerSpacing() - 1; - int buttonWidth = buttonHeight; - - if (menuBar != null) { - int mw = menuBar.getPreferredSize().width; - int mh = menuBar.getPreferredSize().height; - if (leftToRight) { - menuBar.setBounds(2, (h - mh) / 2, mw, mh); - } else { - menuBar.setBounds(getWidth() - mw, (h - mh) / 2, mw, mh); - } - } - - int x = leftToRight ? w - spacing : 0; - int y = Math.max(0, ((h - buttonHeight) / 2) - 1); - - if (closeButton != null) { - x += leftToRight ? -buttonWidth : spacing; - closeButton.setBounds(x, y, buttonWidth, buttonHeight); - if (!leftToRight) { - x += buttonWidth; - } - } - - if ((maxButton != null) && (maxButton.getParent() != null)) { - if (DecorationHelper.isFrameStateSupported(Toolkit.getDefaultToolkit(), BaseRootPaneUI.MAXIMIZED_BOTH)) { - x += leftToRight ? -spacing - buttonWidth : spacing; - maxButton.setBounds(x, y, buttonWidth, buttonHeight); - if (!leftToRight) { - x += buttonWidth; - } - } - } - - if ((iconifyButton != null) && (iconifyButton.getParent() != null)) { - x += leftToRight ? -spacing - buttonWidth : spacing; - iconifyButton.setBounds(x, y, buttonWidth, buttonHeight); - if (!leftToRight) { - x += buttonWidth; - } - } - - buttonsWidth = leftToRight ? w - x : x; - - if (customTitlePanel != null) { - int maxWidth = w - buttonsWidth - spacing - 20; - if (menuBar != null) { - maxWidth -= menuBar.getPreferredSize().width; - maxWidth -= spacing; - } - int cpw = Math.min(maxWidth, customTitlePanel.getPreferredSize().width); - int cph = h; - int cpx = leftToRight ? w - buttonsWidth - cpw : buttonsWidth; - int cpy = 0; - customTitlePanel.setBounds(cpx, cpy, cpw, cph); - buttonsWidth += customTitlePanel.getPreferredSize().width; - } - } - - private void layoutMacStyle(Container c) { - int spacing = getHorSpacing(); - int h = getHeight(); - - // assumes all buttons have the same dimensions these dimensions include the borders - int btnHeight = h - getVerSpacing(); - int btnWidth = btnHeight; - - int x = 0; - int y = 0; - - if (closeButton != null) { - closeButton.setBounds(x, y, btnWidth, btnHeight); - x += btnWidth + spacing; - } - if ((iconifyButton != null) && (iconifyButton.getParent() != null)) { - iconifyButton.setBounds(x, y, btnWidth, btnHeight); - x += btnWidth + spacing; - } - if ((maxButton != null) && (maxButton.getParent() != null)) { - if (DecorationHelper.isFrameStateSupported(Toolkit.getDefaultToolkit(), BaseRootPaneUI.MAXIMIZED_BOTH)) { - maxButton.setBounds(x, y, btnWidth, btnHeight); - x += btnWidth + spacing; - } - } - - buttonsWidth = x; - - if (customTitlePanel != null) { - int cpx = buttonsWidth + 5; - int cpy = 0; - int cpw = customTitlePanel.getPreferredSize().width; - int cph = h; - customTitlePanel.setBounds(cpx, cpy, cpw, cph); - buttonsWidth += cpw + 5; - } - } - } // TitlePaneLayout - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinToggleButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinToggleButtonUI.java deleted file mode 100644 index 0fd13f487..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinToggleButtonUI.java +++ /dev/null @@ -1,59 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.BaseToggleButtonUI; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class McWinToggleButtonUI extends BaseToggleButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new McWinToggleButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - if (!b.isContentAreaFilled() || (b.getParent() instanceof JMenuBar)) { - return; - } - super.paintBackground(g, b); - int width = b.getWidth(); - int height = b.getHeight(); - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - g2D.setColor(Color.lightGray); - g2D.drawRect(0, 0, width - 2, height - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - g2D.setColor(Color.white); - g2D.drawLine(width - 1, 0, width - 1, height - 1); - g2D.setComposite(composite); - } -} - - diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinToolBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinToolBarUI.java deleted file mode 100644 index 3dce63427..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinToolBarUI.java +++ /dev/null @@ -1,56 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.AbstractToolBarUI; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class McWinToolBarUI extends AbstractToolBarUI { - - public static ComponentUI createUI(JComponent c) { - return new McWinToolBarUI(); - } - - public Border getRolloverBorder() { - return McWinBorders.getRolloverToolButtonBorder(); - } - - public Border getNonRolloverBorder() { - return McWinBorders.getToolButtonBorder(); - } - - public boolean isButtonOpaque() { - return true; - } - - public void paint(Graphics g, JComponent c) { - McWinUtils.fillComponent(g, c); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinUtils.java b/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinUtils.java deleted file mode 100644 index 76c1feaea..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mcwin/McWinUtils.java +++ /dev/null @@ -1,73 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mcwin; - -import com.jtattoo.plaf.*; -import java.awt.*; - -/** - * @author Michael Hagen - */ -public class McWinUtils { - - private McWinUtils() { - } - - public static void fillComponent(Graphics g, Component c, Color[] colors) { - int w = c.getWidth(); - int h = c.getHeight(); - JTattooUtilities.fillHorGradient(g, colors, 0, 0, w, h); - if (AbstractLookAndFeel.getTheme().isBackgroundPatternOn()) { - Point p = JTattooUtilities.getRelLocation(c); - int y = 2 - (p.y % 3); - Color lc = AbstractLookAndFeel.getTheme().getBackgroundColorDark(); - Color lineColor = ColorHelper.brighter(ColorHelper.median(lc, colors[colors.length - 1]), 50); - while (y < h) { - g.setColor(lineColor); - g.drawLine(0, y, w, y); - lineColor = ColorHelper.darker(lineColor, 1.5); - y += 3; - } - } - } - - public static void fillComponent(Graphics g, Component c) { - if (AbstractLookAndFeel.getTheme().isBackgroundPatternOn()) { - int w = c.getWidth(); - int h = c.getHeight(); - Point p = JTattooUtilities.getRelLocation(c); - int y = 2 - (p.y % 3); - g.setColor(AbstractLookAndFeel.getTheme().getBackgroundColorLight()); - g.fillRect(0, 0, w, h); - g.setColor(AbstractLookAndFeel.getTheme().getBackgroundColorDark()); - while (y < h) { - g.drawLine(0, y, w, y); - y += 3; - } - } else { - g.setColor(c.getBackground()); - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/icons/CheckPressedSymbol.gif b/src/jtattoo/src/com/jtattoo/plaf/mcwin/icons/CheckPressedSymbol.gif deleted file mode 100644 index bc2782036..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/mcwin/icons/CheckPressedSymbol.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/icons/CheckSymbol.gif b/src/jtattoo/src/com/jtattoo/plaf/mcwin/icons/CheckSymbol.gif deleted file mode 100644 index 4288bb750..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/mcwin/icons/CheckSymbol.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/icons/CheckSymbolDisabled.gif b/src/jtattoo/src/com/jtattoo/plaf/mcwin/icons/CheckSymbolDisabled.gif deleted file mode 100644 index 9ddfb56ea..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/mcwin/icons/CheckSymbolDisabled.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/icons/RadioSymbol.gif b/src/jtattoo/src/com/jtattoo/plaf/mcwin/icons/RadioSymbol.gif deleted file mode 100644 index 46a5833c6..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/mcwin/icons/RadioSymbol.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/mcwin/icons/RadioSymbolDisabled.gif b/src/jtattoo/src/com/jtattoo/plaf/mcwin/icons/RadioSymbolDisabled.gif deleted file mode 100644 index c030089ec..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/mcwin/icons/RadioSymbolDisabled.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintBorderFactory.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintBorderFactory.java deleted file mode 100644 index d13d77ba6..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintBorderFactory.java +++ /dev/null @@ -1,122 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.AbstractBorderFactory; -import javax.swing.border.Border; - -/** - * @author Michael Hagen - */ -public class MintBorderFactory implements AbstractBorderFactory { - - private static MintBorderFactory instance = null; - - private MintBorderFactory() { - } - - public static synchronized MintBorderFactory getInstance() { - if (instance == null) { - instance = new MintBorderFactory(); - } - return instance; - } - - public Border getFocusFrameBorder() { - return MintBorders.getFocusFrameBorder(); - } - - public Border getButtonBorder() { - return MintBorders.getButtonBorder(); - } - - public Border getToggleButtonBorder() { - return MintBorders.getToggleButtonBorder(); - } - - public Border getTextBorder() { - return MintBorders.getTextBorder(); - } - - public Border getSpinnerBorder() { - return MintBorders.getSpinnerBorder(); - } - - public Border getTextFieldBorder() { - return MintBorders.getTextFieldBorder(); - } - - public Border getComboBoxBorder() { - return MintBorders.getComboBoxBorder(); - } - - public Border getTableHeaderBorder() { - return MintBorders.getTableHeaderBorder(); - } - - public Border getTableScrollPaneBorder() { - return MintBorders.getTableScrollPaneBorder(); - } - - public Border getScrollPaneBorder() { - return MintBorders.getScrollPaneBorder(); - } - - public Border getTabbedPaneBorder() { - return MintBorders.getTabbedPaneBorder(); - } - - public Border getMenuBarBorder() { - return MintBorders.getMenuBarBorder(); - } - - public Border getMenuItemBorder() { - return MintBorders.getMenuItemBorder(); - } - - public Border getPopupMenuBorder() { - return MintBorders.getPopupMenuBorder(); - } - - public Border getInternalFrameBorder() { - return MintBorders.getInternalFrameBorder(); - } - - public Border getPaletteBorder() { - return MintBorders.getPaletteBorder(); - } - - public Border getToolBarBorder() { - return MintBorders.getToolBarBorder(); - } - - public Border getProgressBarBorder() { - return MintBorders.getProgressBarBorder(); - } - - public Border getDesktopIconBorder() { - return MintBorders.getDesktopIconBorder(); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintBorders.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintBorders.java deleted file mode 100644 index 456fed471..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintBorders.java +++ /dev/null @@ -1,223 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.AbstractButton; -import javax.swing.ButtonModel; -import javax.swing.border.Border; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class MintBorders extends BaseBorders { - - //------------------------------------------------------------------------------------ - // Lazy access methods - //------------------------------------------------------------------------------------ - public static Border getButtonBorder() { - if (buttonBorder == null) { - buttonBorder = new ButtonBorder(); - } - return buttonBorder; - } - - public static Border getToggleButtonBorder() { - if (buttonBorder == null) { - buttonBorder = new ButtonBorder(); - } - return buttonBorder; - } - - public static Border getRolloverToolButtonBorder() { - if (rolloverToolButtonBorder == null) { - rolloverToolButtonBorder = new RolloverToolButtonBorder(); - } - return rolloverToolButtonBorder; - } - - public static Border getInternalFrameBorder() { - if (internalFrameBorder == null) { - internalFrameBorder = new InternalFrameBorder(); - } - return internalFrameBorder; - } - - //------------------------------------------------------------------------------------ - // Implementation of border classes - //------------------------------------------------------------------------------------ - public static class ButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(3, 8, 5, 10); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - } - - public Insets getBorderInsets(Component c) { - return insets; - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class ButtonBorder - - public static class RolloverToolButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - Color frameColor = ColorHelper.darker(AbstractLookAndFeel.getToolbarBackgroundColor(), 20); - if (model.isEnabled()) { - if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - g.setColor(frameColor); - g.drawRect(x, y, w - 1, h - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.15f); - g2D.setComposite(alpha); - g.setColor(Color.black); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(composite); - } else if (model.isRollover()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - g.setColor(frameColor); - g.drawRect(x, y, w - 1, h - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - g.setColor(Color.white); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(composite); - } - } - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class RolloverToolButtonBorder - - public static class InternalFrameBorder extends BaseInternalFrameBorder { - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - boolean active = isActive(c); - boolean resizable = isResizable(c); - if (!resizable) { - Color frameColor = AbstractLookAndFeel.getFrameColor(); - Color borderColor = AbstractLookAndFeel.getWindowInactiveBorderColor(); - if (active) { - borderColor = AbstractLookAndFeel.getWindowBorderColor(); - } - Color cHi = ColorHelper.brighter(frameColor, 40); - Color cLo = frameColor; - JTattooUtilities.draw3DBorder(g, cHi, cLo, x, y, w, h); - g.setColor(borderColor); - for (int i = 1; i < dw; i++) { - g.drawRect(i, i, w - (2 * i) - 1, h - (2 * i) - 1); - } - return; - } - h--; - w--; - Color color = AbstractLookAndFeel.getWindowInactiveBorderColor(); - if (active) { - color = AbstractLookAndFeel.getWindowBorderColor(); - } - - // links - g.setColor(color); - g.drawLine(x, y, x, y + h); - g.setColor(ColorHelper.brighter(color, 60)); - g.drawLine(x + 1, y + 1, x + 1, y + h - 1); - g.setColor(ColorHelper.brighter(color, 40)); - g.drawLine(x + 2, y + 2, x + 2, y + h - 2); - g.setColor(ColorHelper.brighter(color, 20)); - g.drawLine(x + 3, y + 3, x + 3, y + h - 3); - g.setColor(color); - g.drawLine(x + 4, y + 4, x + 4, y + h - 4); - - // rechts - g.setColor(color); - g.drawLine(x + w, y, x + w, y + h); - g.setColor(ColorHelper.brighter(color, 20)); - g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); - g.setColor(ColorHelper.brighter(color, 40)); - g.drawLine(x + w - 2, y + 2, x + w - 2, y + h - 2); - g.setColor(ColorHelper.brighter(color, 60)); - g.drawLine(x + w - 3, y + 3, x + w - 3, y + h - 3); - g.setColor(color); - g.drawLine(x + w - 4, y + 4, x + w - 4, y + h - 4); - - // oben - g.setColor(color); - g.drawLine(x, y, x + w, y); - g.setColor(ColorHelper.brighter(color, 60)); - g.drawLine(x + 1, y + 1, x + w - 1, y + 1); - g.setColor(ColorHelper.brighter(color, 40)); - g.drawLine(x + 2, y + 2, x + w - 2, y + 2); - g.setColor(ColorHelper.brighter(color, 20)); - g.drawLine(x + 3, y + 3, x + w - 3, y + 3); - g.setColor(color); - g.drawLine(x + 4, y + 4, x + w - 4, y + 4); - - // unten - g.setColor(color); - g.drawLine(x, y + h, x + w, y + h); - g.setColor(ColorHelper.brighter(color, 20)); - g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1); - g.setColor(ColorHelper.brighter(color, 40)); - g.drawLine(x + 2, y + h - 2, x + w - 2, y + h - 2); - g.setColor(ColorHelper.brighter(color, 60)); - g.drawLine(x + 3, y + h - 3, x + w - 3, y + h - 3); - g.setColor(color); - g.drawLine(x + 4, y + h - 4, x + w - 4, y + h - 4); - } - } // class InternalFrameBorder -} // class MintBorders - diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintButtonUI.java deleted file mode 100644 index 9583bde2e..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintButtonUI.java +++ /dev/null @@ -1,142 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicGraphicsUtils; - -/** - * @author Michael Hagen - */ -public class MintButtonUI extends BaseButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new MintButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - if (!b.isContentAreaFilled() || (b.getParent() instanceof JMenuBar)) { - return; - } - - if (!(b.isBorderPainted() && (b.getBorder() instanceof UIResource))) { - super.paintBackground(g, b); - return; - } - - if ((b.getWidth() < 32) || (b.getHeight() < 16)) { - ButtonModel model = b.getModel(); - Color color = AbstractLookAndFeel.getTheme().getButtonBackgroundColor(); - if (model.isPressed() && model.isArmed()) { - color = AbstractLookAndFeel.getTheme().getSelectionBackgroundColor(); - } else if (b.isRolloverEnabled() && model.isRollover()) { - color = AbstractLookAndFeel.getTheme().getRolloverColor(); - } - g.setColor(color); - g.fillRect(0, 0, b.getWidth(), b.getHeight()); - JTattooUtilities.draw3DBorder(g, Color.white, Color.lightGray, 0, 0, b.getWidth(), b.getHeight()); - return; - } - - Graphics2D g2D = (Graphics2D) g; - int width = b.getWidth() - 2; - int height = b.getHeight() - 2; - ButtonModel model = b.getModel(); - - if (model.isPressed() && model.isArmed()) { - Color color = AbstractLookAndFeel.getTheme().getSelectionBackgroundColor(); - g2D.setColor(color); - g2D.fillRoundRect(0, 0, width, height, height, height); - g2D.setColor(ColorHelper.darker(color, 40)); - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2D.drawRoundRect(0, 0, width - 1, height - 1, height, height); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - return; - } - - Color colors[] = AbstractLookAndFeel.getTheme().getButtonColors(); - if (!model.isEnabled()) { - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } else if (b.isRolloverEnabled() && model.isRollover()) { - Color[] src = AbstractLookAndFeel.getTheme().getRolloverColors(); - colors = new Color[src.length]; - System.arraycopy(src, 0, colors, 0, colors.length); - colors[colors.length - 2] = ColorHelper.darker(colors[colors.length - 2], 15); - } - - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - // Paint shadow - Color color = b.getParent().getBackground(); - g2D.setColor(ColorHelper.darker(color, 6)); - g2D.drawRoundRect(2, 2, width - 1, height - 1, height, height); - g2D.setColor(ColorHelper.darker(color, 18)); - g2D.drawRoundRect(1, 1, width - 1, height - 1, height, height); - // paint background - int x = 0; - int y = 0; - int w = width; - int h = height; - for (int i = colors.length - 1; i >= 0; i--) { - g2D.setColor(colors[i]); - g2D.fillRoundRect(x, y, w, h, h, h); - h--; - w--; - if (((i + 1) % 4) == 0) { - x++; - y++; - } - if (h == 0) { - break; - } - } - g2D.setColor(Color.white); - g2D.drawRoundRect(1, 1, width - 3, height - 3, height - 2, height - 2); - g2D.drawRoundRect(1, 1, width - 3, height - 3, height - 2, height - 2); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - } - - protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { - Graphics2D g2D = (Graphics2D) g; - int width = b.getWidth(); - int height = b.getHeight(); - if (!b.isContentAreaFilled() - || ((width < 64) || (height < 16)) && ((b.getText() == null) || b.getText().length() == 0)) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - BasicGraphicsUtils.drawDashedRect(g, 4, 3, width - 8, height - 6); - } else { - Object savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2D.setColor(AbstractLookAndFeel.getFocusColor()); - int d = height - 6; - g2D.drawRoundRect(2, 2, width - 7, height - 7, d, d); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRenderingHint); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintComboBoxUI.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintComboBoxUI.java deleted file mode 100644 index faf82e8aa..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintComboBoxUI.java +++ /dev/null @@ -1,80 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.*; -import java.awt.Dimension; -import java.awt.Graphics; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -public class MintComboBoxUI extends BaseComboBoxUI { - - public static ComponentUI createUI(JComponent c) { - return new MintComboBoxUI(); - } - - public JButton createArrowButton() { - ArrowButton button = new ArrowButton(); - if (JTattooUtilities.isLeftToRight(comboBox)) { - Border border = BorderFactory.createMatteBorder(0, 1, 0, 0, AbstractLookAndFeel.getFrameColor()); - button.setBorder(border); - } else { - Border border = BorderFactory.createMatteBorder(0, 0, 0, 1, AbstractLookAndFeel.getFrameColor()); - button.setBorder(border); - } - return button; - } - -//------------------------------------------------------------------------------------ - static class ArrowButton extends NoFocusButton { - - public void paint(Graphics g) { - Dimension size = getSize(); - if (isEnabled()) { - if (getModel().isArmed() && getModel().isPressed()) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getPressedColors(), 0, 0, size.width, size.height); - } else if (getModel().isRollover()) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getRolloverColors(), 0, 0, size.width, size.height); - } else if (JTattooUtilities.isActive(this)) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getDefaultColors(), 0, 0, size.width, size.height); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getInActiveColors(), 0, 0, size.width, size.height); - } - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getDisabledColors(), 0, 0, size.width, size.height); - } - Icon icon = BaseIcons.getComboBoxIcon(); - int x = (size.width - icon.getIconWidth()) / 2; - int y = (size.height - icon.getIconHeight()) / 2; - if (getModel().isPressed() && getModel().isArmed()) { - icon.paintIcon(this, g, x + 2, y + 1); - } else { - icon.paintIcon(this, g, x + 1, y); - } - paintBorder(g); - } - } // end class ArrowButton -} // end class MintComboBox diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintDefaultTheme.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintDefaultTheme.java deleted file mode 100644 index db68d88d8..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintDefaultTheme.java +++ /dev/null @@ -1,186 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.AbstractTheme; -import com.jtattoo.plaf.ColorHelper; -import java.awt.Color; -import java.awt.Font; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.FontUIResource; - -public class MintDefaultTheme extends AbstractTheme { - - public MintDefaultTheme() { - super(); - // Setup theme with defaults - setUpColor(); - // Overwrite defaults with user props - loadProperties(); - // Setup the color arrays - setUpColorArrs(); - } - - public String getPropertyFileName() { - return "MintTheme.properties"; - } - - public void setUpColor() { - super.setUpColor(); - - // Defaults for MintLookAndFeel - backgroundColor = new ColorUIResource(236, 242, 242); - backgroundColorLight = new ColorUIResource(236, 242, 242); - backgroundColorDark = new ColorUIResource(220, 228, 228); - alterBackgroundColor = new ColorUIResource(220, 228, 228); - selectionBackgroundColor = new ColorUIResource(220, 228, 228); - selectionForegroundColor = black; - frameColor = new ColorUIResource(140, 140, 140); - focusCellColor = focusColor; - - rolloverColor = new ColorUIResource(255, 230, 170); - rolloverColorLight = new ColorUIResource(255, 230, 170); - rolloverColorDark = new ColorUIResource(255, 191, 43); - - buttonBackgroundColor = new ColorUIResource(240, 248, 248); - buttonColorLight = white; - buttonColorDark = new ColorUIResource(220, 228, 228); - - controlBackgroundColor = backgroundColor; // netbeans use this for selected tab in the toolbar - controlColorLight = new ColorUIResource(223, 234, 234); - controlColorDark = new ColorUIResource(180, 203, 203); - controlHighlightColor = white; - controlShadowColor = new ColorUIResource(172, 186, 186); - controlDarkShadowColor = new ColorUIResource(160, 164, 164); - - windowTitleForegroundColor = black; - windowTitleBackgroundColor = new ColorUIResource(180, 203, 203);//new ColorUIResource(180, 203, 203); - windowTitleColorLight = new ColorUIResource(223, 234, 234); - windowTitleColorDark = new ColorUIResource(180, 203, 203); - windowBorderColor = new ColorUIResource(154, 186, 186); - - windowInactiveTitleBackgroundColor = new ColorUIResource(220, 228, 228);//new ColorUIResource(220, 220, 220); - windowInactiveTitleColorLight = backgroundColor; - windowInactiveTitleColorDark = new ColorUIResource(220, 228, 228); - windowInactiveBorderColor = new ColorUIResource(192, 211, 211); - - menuBackgroundColor = white;//backgroundColor; - menuSelectionBackgroundColor = selectionBackgroundColor; - menuSelectionForegroundColor = selectionForegroundColor; - menuColorLight = backgroundColor; - menuColorDark = new ColorUIResource(220, 228, 228); - - toolbarBackgroundColor = backgroundColor; - toolbarColorLight = menuColorLight; - toolbarColorDark = menuColorDark; - - tabAreaBackgroundColor = backgroundColor; - desktopColor = new ColorUIResource(220, 228, 228); - } - - public void setUpColorArrs() { - super.setUpColorArrs(); - - // Generate the color arrays - DEFAULT_COLORS = ColorHelper.createColorArr(controlColorLight, controlColorDark, 20); - HIDEFAULT_COLORS = ColorHelper.createColorArr(ColorHelper.brighter(controlColorLight, 40), ColorHelper.brighter(controlColorDark, 40), 20); - ACTIVE_COLORS = DEFAULT_COLORS; - ROLLOVER_COLORS = ColorHelper.createColorArr(rolloverColorLight, rolloverColorDark, 20); - SELECTED_COLORS = DEFAULT_COLORS; - PRESSED_COLORS = ColorHelper.createColorArr(ColorHelper.darker(controlColorLight, 10), ColorHelper.darker(controlColorDark, 10), 20); - DISABLED_COLORS = ColorHelper.createColorArr(new Color(248, 248, 248), new Color(224, 224, 224), 20); - WINDOW_TITLE_COLORS = ColorHelper.createColorArr(windowTitleColorLight, windowTitleColorDark, 20); - WINDOW_INACTIVE_TITLE_COLORS = ColorHelper.createColorArr(windowInactiveTitleColorLight, windowInactiveTitleColorDark, 20); - MENUBAR_COLORS = ColorHelper.createColorArr(menuColorLight, menuColorDark, 20); - TOOLBAR_COLORS = ColorHelper.createColorArr(toolbarColorLight, toolbarColorDark, 20); - BUTTON_COLORS = new Color[]{ - new Color(255, 255, 255), - new Color(254, 255, 254), - new Color(253, 255, 254), - new Color(252, 255, 254), - new Color(251, 254, 253), - new Color(250, 253, 252), - new Color(250, 253, 252), - new Color(248, 250, 249), - new Color(244, 248, 246), - new Color(240, 245, 243), - new Color(238, 242, 240), - new Color(232, 237, 235), - new Color(232, 237, 235), - new Color(224, 230, 227), - new Color(214, 221, 217), - new Color(204, 212, 208), - new Color(160, 164, 162),}; - TAB_COLORS = ColorHelper.createColorArr(buttonColorLight, buttonColorDark, 20); - CHECKBOX_COLORS = TAB_COLORS; - COL_HEADER_COLORS = ColorHelper.createColorArr(buttonColorLight, buttonColorDark, 20); - TRACK_COLORS = ColorHelper.createColorArr(new Color(238, 238, 238), Color.white, 20); - THUMB_COLORS = DEFAULT_COLORS; - SLIDER_COLORS = DEFAULT_COLORS; - PROGRESSBAR_COLORS = DEFAULT_COLORS; - INACTIVE_COLORS = ColorHelper.createColorArr(buttonColorLight, buttonColorDark, 20); - } - - public FontUIResource getControlTextFont() { - if (controlFont == null) { - controlFont = new FontUIResource("Dialog", Font.PLAIN, 12); - } - return controlFont; - } - - public FontUIResource getSystemTextFont() { - if (systemFont == null) { - systemFont = new FontUIResource("Dialog", Font.PLAIN, 12); - } - return systemFont; - } - - public FontUIResource getUserTextFont() { - if (userFont == null) { - userFont = new FontUIResource("Dialog", Font.PLAIN, 12); - } - return userFont; - } - - public FontUIResource getMenuTextFont() { - if (menuFont == null) { - menuFont = new FontUIResource("Dialog", Font.PLAIN, 12); - } - return menuFont; - } - - public FontUIResource getWindowTitleFont() { - if (windowTitleFont == null) { - windowTitleFont = new FontUIResource("Dialog", Font.BOLD, 12); - } - return windowTitleFont; - } - - public FontUIResource getSubTextFont() { - if (smallFont == null) { - smallFont = new FontUIResource("Dialog", Font.PLAIN, 10); - } - return smallFont; - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintIconFactory.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintIconFactory.java deleted file mode 100644 index 25d1ed07b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintIconFactory.java +++ /dev/null @@ -1,213 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.AbstractIconFactory; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class MintIconFactory implements AbstractIconFactory { - - private static MintIconFactory instance = null; - - private MintIconFactory() { - } - - public static synchronized MintIconFactory getInstance() { - if (instance == null) { - instance = new MintIconFactory(); - } - return instance; - } - - public Icon getOptionPaneErrorIcon() { - return MintIcons.getOptionPaneErrorIcon(); - } - - public Icon getOptionPaneWarningIcon() { - return MintIcons.getOptionPaneWarningIcon(); - } - - public Icon getOptionPaneInformationIcon() { - return MintIcons.getOptionPaneInformationIcon(); - } - - public Icon getOptionPaneQuestionIcon() { - return MintIcons.getOptionPaneQuestionIcon(); - } - - public Icon getFileChooserDetailViewIcon() { - return MintIcons.getFileChooserDetailViewIcon(); - } - - public Icon getFileChooserHomeFolderIcon() { - return MintIcons.getFileChooserHomeFolderIcon(); - } - - public Icon getFileChooserListViewIcon() { - return MintIcons.getFileChooserListViewIcon(); - } - - public Icon getFileChooserNewFolderIcon() { - return MintIcons.getFileChooserNewFolderIcon(); - } - - public Icon getFileChooserUpFolderIcon() { - return MintIcons.getFileChooserUpFolderIcon(); - } - - public Icon getMenuIcon() { - return MintIcons.getMenuIcon(); - } - - public Icon getIconIcon() { - return MintIcons.getIconIcon(); - } - - public Icon getMaxIcon() { - return MintIcons.getMaxIcon(); - } - - public Icon getMinIcon() { - return MintIcons.getMinIcon(); - } - - public Icon getCloseIcon() { - return MintIcons.getCloseIcon(); - } - - public Icon getPaletteCloseIcon() { - return MintIcons.getPaletteCloseIcon(); - } - - public Icon getRadioButtonIcon() { - return MintIcons.getRadioButtonIcon(); - } - - public Icon getCheckBoxIcon() { - return MintIcons.getCheckBoxIcon(); - } - - public Icon getComboBoxIcon() { - return MintIcons.getComboBoxIcon(); - } - - public Icon getTreeComputerIcon() { - return MintIcons.getTreeComputerIcon(); - } - - public Icon getTreeFloppyDriveIcon() { - return MintIcons.getTreeFloppyDriveIcon(); - } - - public Icon getTreeHardDriveIcon() { - return MintIcons.getTreeHardDriveIcon(); - } - - public Icon getTreeFolderIcon() { - return MintIcons.getTreeFolderIcon(); - } - - public Icon getTreeLeafIcon() { - return MintIcons.getTreeLeafIcon(); - } - - public Icon getTreeCollapsedIcon() { - return MintIcons.getTreeControlIcon(true); - } - - public Icon getTreeExpandedIcon() { - return MintIcons.getTreeControlIcon(false); - } - - public Icon getMenuArrowIcon() { - return MintIcons.getMenuArrowIcon(); - } - - public Icon getMenuCheckBoxIcon() { - return MintIcons.getMenuCheckBoxIcon(); - } - - public Icon getMenuRadioButtonIcon() { - return MintIcons.getMenuRadioButtonIcon(); - } - - public Icon getUpArrowIcon() { - return MintIcons.getUpArrowIcon(); - } - - public Icon getDownArrowIcon() { - return MintIcons.getDownArrowIcon(); - } - - public Icon getLeftArrowIcon() { - return MintIcons.getLeftArrowIcon(); - } - - public Icon getRightArrowIcon() { - return MintIcons.getRightArrowIcon(); - } - - public Icon getSplitterDownArrowIcon() { - return MintIcons.getSplitterDownArrowIcon(); - } - - public Icon getSplitterHorBumpIcon() { - return MintIcons.getSplitterHorBumpIcon(); - } - - public Icon getSplitterLeftArrowIcon() { - return MintIcons.getSplitterLeftArrowIcon(); - } - - public Icon getSplitterRightArrowIcon() { - return MintIcons.getSplitterRightArrowIcon(); - } - - public Icon getSplitterUpArrowIcon() { - return MintIcons.getSplitterUpArrowIcon(); - } - - public Icon getSplitterVerBumpIcon() { - return MintIcons.getSplitterVerBumpIcon(); - } - - public Icon getThumbHorIcon() { - return MintIcons.getThumbHorIcon(); - } - - public Icon getThumbVerIcon() { - return MintIcons.getThumbVerIcon(); - } - - public Icon getThumbHorIconRollover() { - return MintIcons.getThumbHorIconRollover(); - } - - public Icon getThumbVerIconRollover() { - return MintIcons.getThumbVerIconRollover(); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintIcons.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintIcons.java deleted file mode 100644 index 2dc40f633..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintIcons.java +++ /dev/null @@ -1,174 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.*; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.RoundRectangle2D; -import javax.swing.Icon; -import javax.swing.JButton; - -/** - * @author Michael Hagen - */ -public class MintIcons extends BaseIcons { - - public static Icon getIconIcon() { - if (iconIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - iconIcon = new MacIconIcon(); - } else { - iconIcon = new TitleButtonIcon(TitleButtonIcon.ICON_ICON_TYP); - } - } - return iconIcon; - } - - public static Icon getMinIcon() { - if (minIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - minIcon = new MacMinIcon(); - } else { - minIcon = new TitleButtonIcon(TitleButtonIcon.MIN_ICON_TYP); - } - } - return minIcon; - } - - public static Icon getMaxIcon() { - if (maxIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - maxIcon = new MacMaxIcon(); - } else { - maxIcon = new TitleButtonIcon(TitleButtonIcon.MAX_ICON_TYP); - } - } - return maxIcon; - } - - public static Icon getCloseIcon() { - if (closeIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - closeIcon = new MacCloseIcon(); - } else { - closeIcon = new TitleButtonIcon(TitleButtonIcon.CLOSE_ICON_TYP); - } - } - return closeIcon; - } - -//------------------------------------------------------------------------------ - private static class TitleButtonIcon implements Icon { - - private static Color closerColorLight = new Color(241, 172, 154); - private static Color closerColorDark = new Color(224, 56, 2); - public static final int ICON_ICON_TYP = 0; - public static final int MIN_ICON_TYP = 1; - public static final int MAX_ICON_TYP = 2; - public static final int CLOSE_ICON_TYP = 3; - private int iconTyp = ICON_ICON_TYP; - - public TitleButtonIcon(int typ) { - iconTyp = typ; - } - - public int getIconHeight() { - return 20; - } - - public int getIconWidth() { - return 20; - } - - public void paintIcon(Component c, Graphics g, int x, int y) { - int w = c.getWidth(); - int h = c.getHeight(); - - JButton b = (JButton) c; - Graphics2D g2D = (Graphics2D) g; - - boolean isActive = JTattooUtilities.isActive(b); - boolean isPressed = b.getModel().isPressed(); - boolean isArmed = b.getModel().isArmed(); - boolean isRollover = b.getModel().isRollover(); - - Color cHi = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getWindowTitleColorLight(), 40); - Color cLo = ColorHelper.darker(AbstractLookAndFeel.getTheme().getWindowTitleColorDark(), 10); - if (iconTyp == CLOSE_ICON_TYP) { - cHi = closerColorLight; - cLo = closerColorDark; - } - - Color fcHi = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getWindowTitleColorDark(), 80); - Color fcLo = ColorHelper.darker(AbstractLookAndFeel.getTheme().getWindowTitleColorDark(), 40); - - if (!isActive) { - cHi = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getWindowInactiveTitleColorLight(), 40); - cLo = ColorHelper.darker(AbstractLookAndFeel.getTheme().getWindowInactiveTitleColorDark(), 10); - fcHi = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getWindowInactiveTitleColorLight(), 60); - fcLo = ColorHelper.darker(AbstractLookAndFeel.getTheme().getWindowInactiveTitleColorDark(), 10); - } - if (isPressed && isArmed) { - Color cTemp = ColorHelper.darker(cLo, 10); - cLo = ColorHelper.darker(cHi, 10); - cHi = cTemp; - } else if (isRollover) { - cHi = ColorHelper.brighter(cHi, 30); - cLo = ColorHelper.brighter(cLo, 30); - } - - Shape savedClip = g.getClip(); - Area area = new Area(new RoundRectangle2D.Double(1, 1, w - 1, h - 1, 3, 3)); - g2D.setClip(area); - - g2D.setPaint(new GradientPaint(0, 0, fcLo, w, h, fcHi)); - g.fillRect(1, 1, w - 1, h - 1); - - g2D.setPaint(new GradientPaint(0, 0, ColorHelper.brighter(cHi, 80), w, h, ColorHelper.darker(cLo, 30))); - g.fillRect(2, 2, w - 3, h - 3); - - g2D.setPaint(new GradientPaint(0, 0, cHi, w, h, cLo)); - g.fillRect(3, 3, w - 5, h - 5); - - g2D.setClip(savedClip); - - cHi = Color.white; - cLo = ColorHelper.darker(cLo, 30); - Icon icon = null; - if (iconTyp == ICON_ICON_TYP) { - icon = new BaseIcons.IconSymbol(cHi, cLo, null); - } else if (iconTyp == MIN_ICON_TYP) { - icon = new BaseIcons.MinSymbol(cHi, cLo, null); - } else if (iconTyp == MAX_ICON_TYP) { - icon = new BaseIcons.MaxSymbol(cHi, cLo, null); - } else if (iconTyp == CLOSE_ICON_TYP) { - icon = new BaseIcons.CloseSymbol(cHi, cLo, null); - } - if (icon != null) { - icon.paintIcon(c, g, 0, 0); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintInternalFrameTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintInternalFrameTitlePane.java deleted file mode 100644 index 8c572adad..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintInternalFrameTitlePane.java +++ /dev/null @@ -1,64 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.JInternalFrame; - -/** - * @author Michael Hagen - */ -public class MintInternalFrameTitlePane extends BaseInternalFrameTitlePane { - - public MintInternalFrameTitlePane(JInternalFrame f) { - super(f); - } - - public void paintPalette(Graphics g) { - if (JTattooUtilities.isFrameActive(this)) { - JTattooUtilities.fillVerGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 0, 0, getWidth(), getHeight()); - } else { - JTattooUtilities.fillVerGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 0, 0, getWidth(), getHeight()); - } - } - - public void paintBackground(Graphics g) { - if (JTattooUtilities.isActive(this)) { - setBackground(AbstractLookAndFeel.getTheme().getWindowTitleBackgroundColor()); - JTattooUtilities.fillVerGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 0, 0, getWidth(), getHeight()); - } else { - setBackground(AbstractLookAndFeel.getTheme().getWindowInactiveTitleBackgroundColor()); - JTattooUtilities.fillVerGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 0, 0, getWidth(), getHeight()); - } - } - - public void paintBorder(Graphics g) { - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getTheme().getWindowTitleColorDark(), 10)); - g.drawLine(0, getHeight() - 2, getWidth(), getHeight() - 2); - g.setColor(Color.white); - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintInternalFrameUI.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintInternalFrameUI.java deleted file mode 100644 index 5a3e0f0e2..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintInternalFrameUI.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.BaseInternalFrameUI; -import javax.swing.JComponent; -import javax.swing.JInternalFrame; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class MintInternalFrameUI extends BaseInternalFrameUI { - - public MintInternalFrameUI(JInternalFrame b) { - super(b); - } - - public static ComponentUI createUI(JComponent c) { - return new MintInternalFrameUI((JInternalFrame) c); - } - - protected JComponent createNorthPane(JInternalFrame w) { - titlePane = new MintInternalFrameTitlePane(w); - return titlePane; - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintLookAndFeel.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintLookAndFeel.java deleted file mode 100644 index 6d0a67653..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintLookAndFeel.java +++ /dev/null @@ -1,209 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.*; -import java.util.*; -import javax.swing.UIDefaults; - -/** - * @author Michael Hagen - */ -public class MintLookAndFeel extends AbstractLookAndFeel { - - private static MintDefaultTheme myTheme = null; - - private static final ArrayList themesList = new ArrayList(); - private static final HashMap themesMap = new HashMap(); - private static final Properties defaultProps = new Properties(); - private static final Properties smallFontProps = new Properties(); - private static final Properties largeFontProps = new Properties(); - private static final Properties giantFontProps = new Properties(); - - static { - smallFontProps.setProperty("controlTextFont", "Dialog 10"); - smallFontProps.setProperty("systemTextFont", "Dialog 10"); - smallFontProps.setProperty("userTextFont", "Dialog 10"); - smallFontProps.setProperty("menuTextFont", "Dialog 10"); - smallFontProps.setProperty("windowTitleFont", "Dialog bold 10"); - smallFontProps.setProperty("subTextFont", "Dialog 8"); - - largeFontProps.setProperty("controlTextFont", "Dialog 14"); - largeFontProps.setProperty("systemTextFont", "Dialog 14"); - largeFontProps.setProperty("userTextFont", "Dialog 14"); - largeFontProps.setProperty("menuTextFont", "Dialog 14"); - largeFontProps.setProperty("windowTitleFont", "Dialog bold 14"); - largeFontProps.setProperty("subTextFont", "Dialog 12"); - - giantFontProps.setProperty("controlTextFont", "Dialog 18"); - giantFontProps.setProperty("systemTextFont", "Dialog 18"); - giantFontProps.setProperty("userTextFont", "Dialog 18"); - giantFontProps.setProperty("menuTextFont", "Dialog 18"); - giantFontProps.setProperty("windowTitleFont", "Dialog 18"); - giantFontProps.setProperty("subTextFont", "Dialog 16"); - - - themesList.add("Default"); - themesList.add("Small-Font"); - themesList.add("Large-Font"); - themesList.add("Giant-Font"); - - themesMap.put("Default", defaultProps); - themesMap.put("Small-Font", smallFontProps); - themesMap.put("Large-Font", largeFontProps); - themesMap.put("Giant-Font", giantFontProps); - - } - - public static java.util.List getThemes() { - return themesList; - } - - public static Properties getThemeProperties(String name) { - return ((Properties) themesMap.get(name)); - } - - public static void setTheme(String name) { - setTheme((Properties) themesMap.get(name)); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - - public static void setTheme(String name, String licenseKey, String logoString) { - Properties props = (Properties) themesMap.get(name); - if (props != null) { - props.put("licenseKey", licenseKey); - props.put("logoString", logoString); - setTheme(props); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - } - - public static void setTheme(Properties themesProps) { - if (myTheme == null) { - myTheme = new MintDefaultTheme(); - } - if ((myTheme != null) && (themesProps != null)) { - myTheme.setUpColor(); - myTheme.setProperties(themesProps); - myTheme.setUpColorArrs(); - AbstractLookAndFeel.setTheme(myTheme); - } - } - - public static void setCurrentTheme(Properties themesProps) { - setTheme(themesProps); - } - - public String getName() { - return "Mint"; - } - - public String getID() { - return "Mint"; - } - - public String getDescription() { - return "The Mint Look and Feel"; - } - - public boolean isNativeLookAndFeel() { - return false; - } - - public boolean isSupportedLookAndFeel() { - return true; - } - - public AbstractBorderFactory getBorderFactory() { - return MintBorderFactory.getInstance(); - } - - public AbstractIconFactory getIconFactory() { - return MintIconFactory.getInstance(); - } - - protected void createDefaultTheme() { - if (myTheme == null) { - myTheme = new MintDefaultTheme(); - } - setTheme(myTheme); - } - - protected void initComponentDefaults(UIDefaults table) { - super.initComponentDefaults(table); - table.put("ScrollBar.incrementButtonGap", new Integer(-1)); - table.put("ScrollBar.decrementButtonGap", new Integer(-1)); - } - - protected void initClassDefaults(UIDefaults table) { - super.initClassDefaults(table); - Object[] uiDefaults = { - // BaseLookAndFeel classes - "LabelUI", BaseLabelUI.class.getName(), - "SeparatorUI", BaseSeparatorUI.class.getName(), - "RadioButtonUI", BaseRadioButtonUI.class.getName(), - "CheckBoxUI", BaseCheckBoxUI.class.getName(), - "TextFieldUI", BaseTextFieldUI.class.getName(), - "TextAreaUI", BaseTextAreaUI.class.getName(), - "EditorPaneUI", BaseEditorPaneUI.class.getName(), - "PasswordFieldUI", BasePasswordFieldUI.class.getName(), - "ToolTipUI", BaseToolTipUI.class.getName(), - "TreeUI", BaseTreeUI.class.getName(), - "TableUI", BaseTableUI.class.getName(), - "TableHeaderUI", BaseTableHeaderUI.class.getName(), - "PanelUI", BasePanelUI.class.getName(), - "ScrollPaneUI", BaseScrollPaneUI.class.getName(), - "ProgressBarUI", BaseProgressBarUI.class.getName(), - "SliderUI", BaseSliderUI.class.getName(), - "SplitPaneUI", BaseSplitPaneUI.class.getName(), - "FileChooserUI", BaseFileChooserUI.class.getName(), - "MenuUI", BaseMenuUI.class.getName(), - "PopupMenuUI", BasePopupMenuUI.class.getName(), - "MenuItemUI", BaseMenuItemUI.class.getName(), - "CheckBoxMenuItemUI", BaseCheckBoxMenuItemUI.class.getName(), - "RadioButtonMenuItemUI", BaseRadioButtonMenuItemUI.class.getName(), - "PopupMenuSeparatorUI", BaseSeparatorUI.class.getName(), - "DesktopPaneUI", BaseDesktopPaneUI.class.getName(), - - // MintLookAndFeel classes - "ButtonUI", MintButtonUI.class.getName(), - "ToggleButtonUI", MintToggleButtonUI.class.getName(), - "ComboBoxUI", MintComboBoxUI.class.getName(), - "TabbedPaneUI", MintTabbedPaneUI.class.getName(), - "ScrollBarUI", MintScrollBarUI.class.getName(), - "ToolBarUI", MintToolBarUI.class.getName(), - "MenuBarUI", MintMenuBarUI.class.getName(), - "InternalFrameUI", MintInternalFrameUI.class.getName(), - "RootPaneUI", MintRootPaneUI.class.getName(),}; - table.putDefaults(uiDefaults); - if (JTattooUtilities.getJavaVersion() >= 1.5) { - table.put("FormattedTextFieldUI", BaseFormattedTextFieldUI.class.getName()); - table.put("SpinnerUI", BaseSpinnerUI.class.getName()); - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintMenuBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintMenuBarUI.java deleted file mode 100644 index 98e7ac572..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintMenuBarUI.java +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.JTattooUtilities; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicMenuBarUI; - -/** - * @author Michael Hagen - */ -public class MintMenuBarUI extends BasicMenuBarUI { - - public static ComponentUI createUI(JComponent c) { - return new MintMenuBarUI(); - } - - public void paint(Graphics g, JComponent c) { - int w = c.getWidth(); - int h = c.getHeight(); - JTattooUtilities.fillVerGradient(g, AbstractLookAndFeel.getTheme().getMenuBarColors(), 0, 0, w, h); - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintRootPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintRootPaneUI.java deleted file mode 100644 index b28b4a586..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintRootPaneUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.BaseRootPaneUI; -import com.jtattoo.plaf.BaseTitlePane; -import javax.swing.JComponent; -import javax.swing.JRootPane; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class MintRootPaneUI extends BaseRootPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new MintRootPaneUI(); - } - - public BaseTitlePane createTitlePane(JRootPane root) { - return new MintTitlePane(root, this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintScrollBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintScrollBarUI.java deleted file mode 100644 index 3f9151fc7..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintScrollBarUI.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.XPScrollBarUI; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; - -/** - * - * @author Michael Hagen - */ -public class MintScrollBarUI extends XPScrollBarUI { - - public static ComponentUI createUI(JComponent c) { - return new MintScrollBarUI(); - } - - protected JButton createDecreaseButton(int orientation) { - return new MintScrollButton(orientation, scrollBarWidth); - } - - protected JButton createIncreaseButton(int orientation) { - return new MintScrollButton(orientation, scrollBarWidth); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintScrollButton.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintScrollButton.java deleted file mode 100644 index 4e0e99e39..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintScrollButton.java +++ /dev/null @@ -1,72 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.LazyImageIcon; -import com.jtattoo.plaf.XPScrollButton; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class MintScrollButton extends XPScrollButton { - - protected static Icon upArrowIcon = null; - protected static Icon downArrowIcon = null; - protected static Icon leftArrowIcon = null; - protected static Icon rightArrowIcon = null; - - public MintScrollButton(int direction, int width) { - super(direction, width); - } - - public Icon getUpArrowIcon() { - if (upArrowIcon == null) { - upArrowIcon = new LazyImageIcon("mint/icons/UpArrow.gif"); - } - return upArrowIcon; - } - - public Icon getDownArrowIcon() { - if (downArrowIcon == null) { - downArrowIcon = new LazyImageIcon("mint/icons/DownArrow.gif"); - } - return downArrowIcon; - } - - public Icon getLeftArrowIcon() { - if (leftArrowIcon == null) { - leftArrowIcon = new LazyImageIcon("mint/icons/LeftArrow.gif"); - } - return leftArrowIcon; - } - - public Icon getRightArrowIcon() { - if (rightArrowIcon == null) { - rightArrowIcon = new LazyImageIcon("mint/icons/RightArrow.gif"); - } - return rightArrowIcon; - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintTabbedPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintTabbedPaneUI.java deleted file mode 100644 index b21d4cb51..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintTabbedPaneUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.BaseTabbedPaneUI; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class MintTabbedPaneUI extends BaseTabbedPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new MintTabbedPaneUI(); - } - - public void installDefaults() { - super.installDefaults(); - tabAreaInsets.bottom = 6; - } - -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintTitlePane.java deleted file mode 100644 index 339ee3c43..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintTitlePane.java +++ /dev/null @@ -1,67 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JRootPane; - -/** - * @author Michael Hagen - */ -public class MintTitlePane extends BaseTitlePane { - - public MintTitlePane(JRootPane root, BaseRootPaneUI ui) { - super(root, ui); - } - - public void createButtons() { - iconifyButton = new BaseTitleButton(iconifyAction, ICONIFY, iconifyIcon, 1.0f); - maxButton = new BaseTitleButton(restoreAction, MAXIMIZE, maximizeIcon, 1.0f); - closeButton = new BaseTitleButton(closeAction, CLOSE, closeIcon, 1.0f); - } - - public void paintBackground(Graphics g) { - if (isActive()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - if (backgroundImage != null) { - g.drawImage(backgroundImage, 0, 0, null); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alphaValue); - g2D.setComposite(alpha); - } - JTattooUtilities.fillVerGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 0, 0, getWidth(), getHeight()); - g2D.setComposite(composite); - } else { - JTattooUtilities.fillVerGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 0, 0, getWidth(), getHeight()); - } - } - - public void paintBorder(Graphics g) { - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getTheme().getWindowTitleColorDark(), 10)); - g.drawLine(0, getHeight() - 2, getWidth(), getHeight() - 2); - g.setColor(Color.white); - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintToggleButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintToggleButtonUI.java deleted file mode 100644 index d37cee4b5..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintToggleButtonUI.java +++ /dev/null @@ -1,129 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.*; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.RoundRectangle2D; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class MintToggleButtonUI extends BaseToggleButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new MintToggleButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - if (!b.isContentAreaFilled() || (b.getParent() instanceof JMenuBar)) { - return; - } - - if (!(b.isBorderPainted() && (b.getBorder() instanceof UIResource))) { - super.paintBackground(g, b); - return; - } - Graphics2D g2D = (Graphics2D) g; - int width = b.getWidth() - 2; - int height = b.getHeight() - 2; - ButtonModel model = b.getModel(); - if (model.isPressed() && model.isArmed()) { - Color color = AbstractLookAndFeel.getTheme().getSelectionBackgroundColor(); - g2D.setColor(color); - g2D.fillRoundRect(0, 0, width, height, height, height); - g2D.setColor(AbstractLookAndFeel.getTheme().getFrameColor()); - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2D.drawRoundRect(0, 0, width - 1, height - 1, height, height); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - return; - } else if (model.isSelected()) { - Color frameColor = b.getParent().getBackground(); - Color[] colors = ColorHelper.createColorArr(AbstractLookAndFeel.getTheme().getBackgroundColor(), Color.white, 20); - Shape savedClip = g2D.getClip(); - Area area = new Area(new Area(new RoundRectangle2D.Double(0, 0, width, height, height, height))); - g2D.setClip(area); - JTattooUtilities.fillHorGradient(g, colors, 0, 0, width, height); - g2D.setClip(savedClip); - JTattooUtilities.drawRound3DBorder(g, ColorHelper.darker(frameColor, 5), ColorHelper.brighter(frameColor, 80), 0, 0, width, height); - JTattooUtilities.drawRound3DBorder(g, ColorHelper.darker(frameColor, 20), ColorHelper.brighter(frameColor, 10), 1, 1, width - 2, height - 2); - return; - } - - Color colors[] = AbstractLookAndFeel.getTheme().getButtonColors(); - if (!model.isEnabled()) { - colors = AbstractLookAndFeel.getTheme().getDisabledColors(); - } else if (b.isRolloverEnabled() && model.isRollover()) { - Color[] src = AbstractLookAndFeel.getTheme().getRolloverColors(); - colors = new Color[src.length]; - System.arraycopy(src, 0, colors, 0, colors.length); - colors[colors.length - 2] = ColorHelper.darker(colors[colors.length - 2], 15); - } - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - // Paint shadow - Color color = b.getParent().getBackground(); - g2D.setColor(ColorHelper.darker(color, 6)); - g2D.drawRoundRect(2, 2, width - 1, height - 1, height, height); - g2D.setColor(ColorHelper.darker(color, 18)); - g2D.drawRoundRect(1, 1, width - 1, height - 1, height, height); - // paint background - int x = 0; - int y = 0; - int w = width; - int h = height; - for (int i = colors.length - 1; i >= 0; i--) { - g2D.setColor(colors[i]); - g2D.fillRoundRect(x, y, w, h, h, h); - h--; - w--; - if (((i + 1) % 4) == 0) { - x++; - y++; - } - if (h == 0) { - break; - } - } - g2D.setColor(Color.white); - g2D.drawRoundRect(1, 1, width - 3, height - 3, height - 2, height - 2); - g2D.drawRoundRect(1, 1, width - 3, height - 3, height - 2, height - 2); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - } - - protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { - Graphics2D g2D = (Graphics2D) g; - Object savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2D.setColor(AbstractLookAndFeel.getFocusColor()); - int d = b.getHeight() - 6; - g2D.drawRoundRect(2, 2, b.getWidth() - 7, b.getHeight() - 7, d, d); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRenderingHint); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/MintToolBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/mint/MintToolBarUI.java deleted file mode 100644 index 3da6e1925..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/mint/MintToolBarUI.java +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.mint; - -import com.jtattoo.plaf.*; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class MintToolBarUI extends AbstractToolBarUI { - - public static ComponentUI createUI(JComponent c) { - return new MintToolBarUI(); - } - - public Border getRolloverBorder() { - return MintBorders.getRolloverToolButtonBorder(); - } - - public Border getNonRolloverBorder() { - return MintBorders.getToolButtonBorder(); - } - - public boolean isButtonOpaque() { - return false; - } - - public void paint(Graphics g, JComponent c) { - JTattooUtilities.fillVerGradient(g, AbstractLookAndFeel.getTheme().getToolBarColors(), 0, 0, c.getWidth(), c.getHeight()); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/icons/DownArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/mint/icons/DownArrow.gif deleted file mode 100644 index 53d2f1577..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/mint/icons/DownArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/icons/LeftArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/mint/icons/LeftArrow.gif deleted file mode 100644 index 5df254275..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/mint/icons/LeftArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/icons/RightArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/mint/icons/RightArrow.gif deleted file mode 100644 index 808180eda..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/mint/icons/RightArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/mint/icons/UpArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/mint/icons/UpArrow.gif deleted file mode 100644 index 58ee69c93..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/mint/icons/UpArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/noire/NoireDefaultTheme.java b/src/jtattoo/src/com/jtattoo/plaf/noire/NoireDefaultTheme.java deleted file mode 100644 index e1ba3c710..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/noire/NoireDefaultTheme.java +++ /dev/null @@ -1,194 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.noire; - -import com.jtattoo.plaf.AbstractTheme; -import com.jtattoo.plaf.ColorHelper; -import java.awt.Color; -import java.awt.Font; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.FontUIResource; - -/** - * @author Michael Hagen - */ -public class NoireDefaultTheme extends AbstractTheme { - - public NoireDefaultTheme() { - super(); - // Setup theme with defaults - setUpColor(); - // Overwrite defaults with user props - loadProperties(); - // Setup the color arrays - setUpColorArrs(); - } - - public String getPropertyFileName() { - return "NoireTheme.properties"; - } - - public void setUpColor() { - super.setUpColor(); - - // Defaults for NoireLookAndFeel - textShadow = true; - foregroundColor = white; - disabledForegroundColor = gray; - disabledBackgroundColor = new ColorUIResource(48, 48, 48); - - backgroundColor = new ColorUIResource(24, 26, 28); - backgroundColorLight = new ColorUIResource(24, 26, 28); - backgroundColorDark = new ColorUIResource(4, 5, 6); - alterBackgroundColor = new ColorUIResource(78, 84, 90); - - selectionForegroundColor = new ColorUIResource(255, 220, 120); - selectionBackgroundColor = black; - frameColor = black; - gridColor = black; - focusCellColor = orange; - - inputBackgroundColor = new ColorUIResource(52, 55, 59); - inputForegroundColor = foregroundColor; - - rolloverColor = new ColorUIResource(240, 168, 0); - rolloverColorLight = new ColorUIResource(240, 168, 0); - rolloverColorDark = new ColorUIResource(196, 137, 0); - - buttonForegroundColor = black; - buttonBackgroundColor = new ColorUIResource(120, 129, 148); - buttonColorLight = new ColorUIResource(232, 238, 244); - buttonColorDark = new ColorUIResource(196, 200, 208); - - controlForegroundColor = foregroundColor; - controlBackgroundColor = new ColorUIResource(52, 55, 59); // netbeans use this for selected tab in the toolbar - controlColorLight = new ColorUIResource(44, 47, 50); - controlColorDark = new ColorUIResource(16, 18, 20); - controlHighlightColor = new ColorUIResource(96, 96, 96); - controlShadowColor = new ColorUIResource(32, 32, 32); - controlDarkShadowColor = black; - - windowTitleForegroundColor = foregroundColor; - windowTitleBackgroundColor = new ColorUIResource(144, 148, 149); - windowTitleColorLight = new ColorUIResource(64, 67, 60); - windowTitleColorDark = black; - windowBorderColor = black; - windowIconColor = lightGray; - windowIconShadowColor = black; - windowIconRolloverColor = orange; - - windowInactiveTitleForegroundColor = new ColorUIResource(196, 196, 196); - windowInactiveTitleBackgroundColor = new ColorUIResource(64, 64, 64); - windowInactiveTitleColorLight = new ColorUIResource(64, 64, 64); - windowInactiveTitleColorDark = new ColorUIResource(32, 32, 32); - windowInactiveBorderColor = black; - - menuForegroundColor = white; - menuBackgroundColor = new ColorUIResource(24, 26, 28); - menuSelectionForegroundColor = black; - menuSelectionBackgroundColor = new ColorUIResource(196, 137, 0); - menuColorLight = new ColorUIResource(96, 96, 96); - menuColorDark = new ColorUIResource(32, 32, 32); - - toolbarBackgroundColor = new ColorUIResource(24, 26, 28); - toolbarColorLight = new ColorUIResource(96, 96, 96); - toolbarColorDark = new ColorUIResource(32, 32, 32); - - tabAreaBackgroundColor = backgroundColor; - desktopColor = new ColorUIResource(52, 55, 59); - - tooltipForegroundColor = white; - tooltipBackgroundColor = black;//new ColorUIResource(16, 16, 16); - - controlFont = new FontUIResource("Dialog", Font.BOLD, 12); - systemFont = new FontUIResource("Dialog", Font.BOLD, 12); - userFont = new FontUIResource("Dialog", Font.BOLD, 12); - menuFont = new FontUIResource("Dialog", Font.BOLD, 12); - windowTitleFont = new FontUIResource("Dialog", Font.BOLD, 12); - smallFont = new FontUIResource("Dialog", Font.PLAIN, 10); - } - - public void setUpColorArrs() { - super.setUpColorArrs(); - Color topHi = ColorHelper.brighter(buttonColorLight, 50); - Color topLo = buttonColorLight; - Color bottomHi = buttonColorDark; - Color bottomLo = ColorHelper.darker(buttonColorDark, 40); - Color topColors[] = ColorHelper.createColorArr(topHi, topLo, 10); - Color bottomColors[] = ColorHelper.createColorArr(bottomHi, bottomLo, 12); - BUTTON_COLORS = new Color[22]; - System.arraycopy(topColors, 0, BUTTON_COLORS, 0, 10); - System.arraycopy(bottomColors, 0, BUTTON_COLORS, 10, 12); - - topHi = ColorHelper.brighter(controlColorLight, 40); - topLo = ColorHelper.brighter(controlColorDark, 40); - bottomHi = controlColorLight; - bottomLo = controlColorDark; - topColors = ColorHelper.createColorArr(topHi, topLo, 10); - bottomColors = ColorHelper.createColorArr(bottomHi, bottomLo, 12); - DEFAULT_COLORS = new Color[22]; - System.arraycopy(topColors, 0, DEFAULT_COLORS, 0, 10); - System.arraycopy(bottomColors, 0, DEFAULT_COLORS, 10, 12); - - HIDEFAULT_COLORS = ColorHelper.createColorArr(ColorHelper.brighter(controlColorLight, 15), ColorHelper.brighter(controlColorDark, 15), 20); - ACTIVE_COLORS = ColorHelper.createColorArr(controlColorLight, controlColorDark, 20); - INACTIVE_COLORS = ColorHelper.createColorArr(new Color(64, 64, 64), new Color(32, 32, 32), 20); - - SELECTED_COLORS = BUTTON_COLORS; - - topHi = ColorHelper.brighter(rolloverColorLight, 40); - topLo = rolloverColorLight; - bottomHi = rolloverColorDark; - bottomLo = ColorHelper.darker(rolloverColorDark, 20); - topColors = ColorHelper.createColorArr(topHi, topLo, 10); - bottomColors = ColorHelper.createColorArr(bottomHi, bottomLo, 12); - ROLLOVER_COLORS = new Color[22]; - System.arraycopy(topColors, 0, ROLLOVER_COLORS, 0, 10); - System.arraycopy(bottomColors, 0, ROLLOVER_COLORS, 10, 12); - - PRESSED_COLORS = ColorHelper.createColorArr(new Color(64, 64, 64), new Color(96, 96, 96), 20); - DISABLED_COLORS = ColorHelper.createColorArr(new Color(80, 80, 80), new Color(64, 64, 64), 20); - topHi = ColorHelper.brighter(windowTitleColorLight, 40); - topLo = ColorHelper.brighter(windowTitleColorDark, 40); - bottomHi = windowTitleColorLight; - bottomLo = windowTitleColorDark; - topColors = ColorHelper.createColorArr(topHi, topLo, 8); - bottomColors = ColorHelper.createColorArr(bottomHi, bottomLo, 12); - WINDOW_TITLE_COLORS = new Color[20]; - System.arraycopy(topColors, 0, WINDOW_TITLE_COLORS, 0, 8); - System.arraycopy(bottomColors, 0, WINDOW_TITLE_COLORS, 8, 12); - WINDOW_INACTIVE_TITLE_COLORS = ColorHelper.createColorArr(windowInactiveTitleColorLight, windowInactiveTitleColorDark, 20); - MENUBAR_COLORS = DEFAULT_COLORS; - TOOLBAR_COLORS = MENUBAR_COLORS; - SLIDER_COLORS = BUTTON_COLORS; - PROGRESSBAR_COLORS = DEFAULT_COLORS; - //THUMB_COLORS = ColorHelper.createColorArr(controlColorLight, controlColorDark, 20); - THUMB_COLORS = DEFAULT_COLORS; - //TRACK_COLORS = ColorHelper.createColorArr(ColorHelper.darker(backgroundColor, 10), ColorHelper.brighter(backgroundColor, 5), 20); - TRACK_COLORS = ColorHelper.createColorArr(ColorHelper.darker(inputBackgroundColor, 5), ColorHelper.brighter(inputBackgroundColor, 10), 20); - - TAB_COLORS = DEFAULT_COLORS; - COL_HEADER_COLORS = DEFAULT_COLORS; - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/noire/NoireLookAndFeel.java b/src/jtattoo/src/com/jtattoo/plaf/noire/NoireLookAndFeel.java deleted file mode 100644 index 0e3c854f5..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/noire/NoireLookAndFeel.java +++ /dev/null @@ -1,199 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.noire; - -import com.jtattoo.plaf.*; -import com.jtattoo.plaf.hifi.*; -import java.util.*; -import javax.swing.UIDefaults; - -/** - * @author Michael Hagen - */ -public class NoireLookAndFeel extends AbstractLookAndFeel { - - private static NoireDefaultTheme myTheme = null; - - private static final ArrayList themesList = new ArrayList(); - private static final HashMap themesMap = new HashMap(); - private static final Properties defaultProps = new Properties(); - private static final Properties smallFontProps = new Properties(); - private static final Properties largeFontProps = new Properties(); - private static final Properties giantFontProps = new Properties(); - - static { - smallFontProps.setProperty("controlTextFont", "Dialog bold 10"); - smallFontProps.setProperty("systemTextFont", "Dialog bold 10"); - smallFontProps.setProperty("userTextFont", "Dialog 10"); - smallFontProps.setProperty("menuTextFont", "Dialog bold 10"); - smallFontProps.setProperty("windowTitleFont", "Dialog bold 10"); - smallFontProps.setProperty("subTextFont", "Dialog 8"); - - largeFontProps.setProperty("controlTextFont", "Dialog bold 14"); - largeFontProps.setProperty("systemTextFont", "Dialog bold 14"); - largeFontProps.setProperty("userTextFont", "Dialog bold 14"); - largeFontProps.setProperty("menuTextFont", "Dialog bold 14"); - largeFontProps.setProperty("windowTitleFont", "Dialog bold 14"); - largeFontProps.setProperty("subTextFont", "Dialog 12"); - - giantFontProps.setProperty("controlTextFont", "Dialog 18"); - giantFontProps.setProperty("systemTextFont", "Dialog 18"); - giantFontProps.setProperty("userTextFont", "Dialog 18"); - giantFontProps.setProperty("menuTextFont", "Dialog 18"); - giantFontProps.setProperty("windowTitleFont", "Dialog 18"); - giantFontProps.setProperty("subTextFont", "Dialog 16"); - - themesList.add("Default"); - themesList.add("Small-Font"); - themesList.add("Large-Font"); - themesList.add("Giant-Font"); - - themesMap.put("Default", defaultProps); - themesMap.put("Small-Font", smallFontProps); - themesMap.put("Large-Font", largeFontProps); - themesMap.put("Giant-Font", giantFontProps); - - } - - public static java.util.List getThemes() { - return themesList; - } - - public static Properties getThemeProperties(String name) { - return ((Properties) themesMap.get(name)); - } - - public static void setTheme(String name) { - AbstractTheme.setInternalName(name); - setTheme((Properties) themesMap.get(name)); - } - - public static void setTheme(String name, String licenseKey, String logoString) { - Properties props = (Properties) themesMap.get(name); - if (props != null) { - props.put("licenseKey", licenseKey); - props.put("logoString", logoString); - AbstractTheme.setInternalName(name); - setTheme(props); - } - } - - public static void setTheme(Properties themesProps) { - if (myTheme == null) { - myTheme = new NoireDefaultTheme(); - } - if ((myTheme != null) && (themesProps != null)) { - myTheme.setUpColor(); - myTheme.setProperties(themesProps); - myTheme.setUpColorArrs(); - AbstractLookAndFeel.setTheme(myTheme); - } - } - - public static void setCurrentTheme(Properties themesProps) { - setTheme(themesProps); - } - - public String getName() { - return "Noire"; - } - - public String getID() { - return "Noire"; - } - - public String getDescription() { - return "The Noire Look and Feel"; - } - - public boolean isNativeLookAndFeel() { - return false; - } - - public boolean isSupportedLookAndFeel() { - return true; - } - - public AbstractBorderFactory getBorderFactory() { - return HiFiBorderFactory.getInstance(); - } - - public AbstractIconFactory getIconFactory() { - return HiFiIconFactory.getInstance(); - } - - protected void createDefaultTheme() { - if (myTheme == null) { - myTheme = new NoireDefaultTheme(); - } - setTheme(myTheme); - } - - protected void initClassDefaults(UIDefaults table) { - super.initClassDefaults(table); - Object[] uiDefaults = { - // BaseLookAndFeel classes - "SeparatorUI", BaseSeparatorUI.class.getName(), - "TextFieldUI", BaseTextFieldUI.class.getName(), - "TextAreaUI", BaseTextAreaUI.class.getName(), - "EditorPaneUI", BaseEditorPaneUI.class.getName(), - "PasswordFieldUI", BasePasswordFieldUI.class.getName(), - "ComboBoxUI", BaseComboBoxUI.class.getName(), - "ToolTipUI", BaseToolTipUI.class.getName(), - "TreeUI", BaseTreeUI.class.getName(), - "TableUI", BaseTableUI.class.getName(), - "TableHeaderUI", BaseTableHeaderUI.class.getName(), - "SplitPaneUI", BaseSplitPaneUI.class.getName(), - "ProgressBarUI", BaseProgressBarUI.class.getName(), - "FileChooserUI", BaseFileChooserUI.class.getName(), - "ScrollBarUI", BaseScrollBarUI.class.getName(), - "MenuUI", BaseMenuUI.class.getName(), - "PopupMenuUI", BasePopupMenuUI.class.getName(), - "MenuItemUI", BaseMenuItemUI.class.getName(), - "CheckBoxMenuItemUI", BaseCheckBoxMenuItemUI.class.getName(), - "RadioButtonMenuItemUI", BaseRadioButtonMenuItemUI.class.getName(), - "PopupMenuSeparatorUI", BaseSeparatorUI.class.getName(), - "DesktopPaneUI", BaseDesktopPaneUI.class.getName(), - - // HiFiLookAndFeel classes - "LabelUI", HiFiLabelUI.class.getName(), - "CheckBoxUI", HiFiCheckBoxUI.class.getName(), - "RadioButtonUI", HiFiRadioButtonUI.class.getName(), - "ButtonUI", HiFiButtonUI.class.getName(), - "ToggleButtonUI", HiFiToggleButtonUI.class.getName(), - "SliderUI", HiFiSliderUI.class.getName(), - "PanelUI", HiFiPanelUI.class.getName(), - "ScrollPaneUI", HiFiScrollPaneUI.class.getName(), - "TabbedPaneUI", HiFiTabbedPaneUI.class.getName(), - "ToolBarUI", HiFiToolBarUI.class.getName(), - "MenuBarUI", HiFiMenuBarUI.class.getName(), - "InternalFrameUI", HiFiInternalFrameUI.class.getName(), - "RootPaneUI", HiFiRootPaneUI.class.getName(),}; - table.putDefaults(uiDefaults); - if (JTattooUtilities.getJavaVersion() >= 1.5) { - table.put("FormattedTextFieldUI", BaseFormattedTextFieldUI.class.getName()); - table.put("SpinnerUI", BaseSpinnerUI.class.getName()); - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartBorderFactory.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartBorderFactory.java deleted file mode 100644 index c09640c8a..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartBorderFactory.java +++ /dev/null @@ -1,122 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.AbstractBorderFactory; -import javax.swing.border.Border; - -/** - * @author Michael Hagen - */ -public class SmartBorderFactory implements AbstractBorderFactory { - - private static SmartBorderFactory instance = null; - - private SmartBorderFactory() { - } - - public static synchronized SmartBorderFactory getInstance() { - if (instance == null) { - instance = new SmartBorderFactory(); - } - return instance; - } - - public Border getFocusFrameBorder() { - return SmartBorders.getFocusFrameBorder(); - } - - public Border getButtonBorder() { - return SmartBorders.getButtonBorder(); - } - - public Border getToggleButtonBorder() { - return SmartBorders.getToggleButtonBorder(); - } - - public Border getTextBorder() { - return SmartBorders.getTextBorder(); - } - - public Border getSpinnerBorder() { - return SmartBorders.getSpinnerBorder(); - } - - public Border getTextFieldBorder() { - return SmartBorders.getTextFieldBorder(); - } - - public Border getComboBoxBorder() { - return SmartBorders.getComboBoxBorder(); - } - - public Border getTableHeaderBorder() { - return SmartBorders.getTableHeaderBorder(); - } - - public Border getTableScrollPaneBorder() { - return SmartBorders.getTableScrollPaneBorder(); - } - - public Border getScrollPaneBorder() { - return SmartBorders.getScrollPaneBorder(); - } - - public Border getTabbedPaneBorder() { - return SmartBorders.getTabbedPaneBorder(); - } - - public Border getMenuBarBorder() { - return SmartBorders.getMenuBarBorder(); - } - - public Border getMenuItemBorder() { - return SmartBorders.getMenuItemBorder(); - } - - public Border getPopupMenuBorder() { - return SmartBorders.getPopupMenuBorder(); - } - - public Border getInternalFrameBorder() { - return SmartBorders.getInternalFrameBorder(); - } - - public Border getPaletteBorder() { - return SmartBorders.getPaletteBorder(); - } - - public Border getToolBarBorder() { - return SmartBorders.getToolBarBorder(); - } - - public Border getProgressBarBorder() { - return SmartBorders.getProgressBarBorder(); - } - - public Border getDesktopIconBorder() { - return SmartBorders.getDesktopIconBorder(); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartBorders.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartBorders.java deleted file mode 100644 index 5c387d364..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartBorders.java +++ /dev/null @@ -1,329 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.border.AbstractBorder; -import javax.swing.border.Border; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class SmartBorders extends BaseBorders { - - //------------------------------------------------------------------------------------ - // Lazy access methods - //------------------------------------------------------------------------------------ - public static Border getButtonBorder() { - if (buttonBorder == null) { - buttonBorder = new ButtonBorder(); - } - return buttonBorder; - } - - public static Border getToggleButtonBorder() { - return getButtonBorder(); - } - - public static Border getRolloverToolButtonBorder() { - if (rolloverToolButtonBorder == null) { - rolloverToolButtonBorder = new RolloverToolButtonBorder(); - } - return rolloverToolButtonBorder; - } - - public static Border getInternalFrameBorder() { - if (internalFrameBorder == null) { - internalFrameBorder = new InternalFrameBorder(); - } - return internalFrameBorder; - } - - public static Border getPaletteBorder() { - if (paletteBorder == null) { - paletteBorder = new PaletteBorder(); - } - return paletteBorder; - } - - //------------------------------------------------------------------------------------ - // Implementation of border classes - //------------------------------------------------------------------------------------ - public static class ButtonBorder implements Border, UIResource { - - private static final Color defaultColorHi = new Color(220, 230, 245); - private static final Color defaultColorMed = new Color(212, 224, 243); - private static final Color defaultColorLo = new Color(200, 215, 240); - private static final Insets insets = new Insets(3, 6, 3, 6); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - Graphics2D g2D = (Graphics2D) g; - Color frameColor = AbstractLookAndFeel.getTheme().getFrameColor(); - if (!JTattooUtilities.isFrameActive(button)) { - frameColor = ColorHelper.brighter(frameColor, 40); - } - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - if (button.getRootPane() != null && button.equals(button.getRootPane().getDefaultButton())) { - if (!button.getModel().isRollover()) { - g2D.setColor(defaultColorHi); - g2D.drawRoundRect(x + 1, y + 1, w - 4, h - 2, 6, 6); - g2D.setColor(defaultColorMed); - g2D.drawRoundRect(x + 2, y + 2, w - 6, h - 6, 6, 6); - g2D.setColor(defaultColorLo); - g2D.drawLine(x + 3, h - 3, w - 3, h - 3); - g2D.drawLine(w - 3, y + 4, w - 3, h - 4); - } - } - - g2D.setColor(Color.white); - g2D.drawRoundRect(x, y, w - 1, h - 1, 6, 6); - - g2D.setColor(frameColor); - g2D.drawRoundRect(x, y, w - 2, h - 2, 6, 6); - - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - } - - public Insets getBorderInsets(Component c) { - return insets; - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class ButtonBorder - - public static class RolloverToolButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(2, 2, 2, 2); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - if (model.isEnabled()) { - if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - Color frameColor = ColorHelper.darker(AbstractLookAndFeel.getToolbarBackgroundColor(), 30); - g.setColor(frameColor); - g.drawRect(x, y, w - 1, h - 1); - - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f); - g2D.setComposite(alpha); - g.setColor(Color.black); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(composite); - } else if (model.isRollover()) { - Color frameColor = AbstractLookAndFeel.getToolbarBackgroundColor(); - Color frameHiColor = ColorHelper.darker(frameColor, 5); - Color frameLoColor = ColorHelper.darker(frameColor, 20); - JTattooUtilities.draw3DBorder(g, frameHiColor, frameLoColor, x, y, w, h); - frameHiColor = Color.white; - frameLoColor = ColorHelper.brighter(frameLoColor, 60); - JTattooUtilities.draw3DBorder(g, frameHiColor, frameLoColor, x + 1, y + 1, w - 2, h - 2); - - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - g.setColor(Color.white); - g.fillRect(x + 2, y + 2, w - 4, h - 4); - g2D.setComposite(composite); - - g.setColor(AbstractLookAndFeel.getFocusColor()); - g.drawLine(x + 1, y + 1, x + w - 1, y + 1); - g.drawLine(x + 1, y + 2, x + w - 2, y + 2); - } else if (model.isSelected()) { - Color frameColor = AbstractLookAndFeel.getToolbarBackgroundColor(); - Color frameHiColor = Color.white; - Color frameLoColor = ColorHelper.darker(frameColor, 30); - JTattooUtilities.draw3DBorder(g, frameLoColor, frameHiColor, x, y, w, h); - } - } - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class RolloverToolButtonBorder - - public static class InternalFrameBorder extends BaseInternalFrameBorder { - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Graphics2D g2D = (Graphics2D) g; - boolean active = isActive(c); - boolean resizable = isResizable(c); - int th = getTitleHeight(c); - Color frameColor = AbstractLookAndFeel.getWindowInactiveBorderColor(); - Color titleColor = AbstractLookAndFeel.getWindowInactiveTitleColorLight(); - if (active) { - titleColor = AbstractLookAndFeel.getWindowTitleColorLight(); - frameColor = AbstractLookAndFeel.getWindowBorderColor(); - } - - if (!resizable) { - Insets bi = getBorderInsets(c); - g.setColor(frameColor); - g.drawRect(x, y, w - 1, h - 1); - if (active) { - g.setColor(AbstractLookAndFeel.getWindowTitleColorDark()); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleColorDark()); - } - for (int i = 1; i < bi.left; i++) { - g.drawRect(i, i, w - (2 * i) - 1, h - (2 * i) - 1); - } - g.setColor(frameColor); - g.drawLine(bi.left - 1, y + th + bi.top, bi.left - 1, y + h - bi.bottom); - g.drawLine(w - bi.right, y + th + bi.top, w - bi.right, y + h - bi.bottom); - g.drawLine(bi.left - 1, y + h - bi.bottom, w - bi.right, y + h - bi.bottom); - return; - } - g.setColor(titleColor); - g.fillRect(x, y + 1, w, dw - 1); - g.fillRect(x + 1, y + h - dw, w - 2, dw - 1); - Color color = ColorHelper.brighter(AbstractLookAndFeel.getWindowTitleColorDark(), 30); - if (active) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 1, dw, dw, th + 1); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), w - dw, dw, dw, th + 1); - - Color c1 = AbstractLookAndFeel.getTheme().getWindowTitleColorDark(); - Color c2 = AbstractLookAndFeel.getTheme().getWindowTitleColorLight(); - g2D.setPaint(new GradientPaint(0, dw + th + 1, c1, 0, h - th - (2 * dw), c2)); - g.fillRect(1, dw + th + 1, dw - 1, h - th - (2 * dw)); - g.fillRect(w - dw, dw + th + 1, dw - 1, h - th - (2 * dw)); - g2D.setPaint(null); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 1, dw, dw, th + 1); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), w - dw, dw, dw, th + 1); - - Color c1 = AbstractLookAndFeel.getTheme().getWindowInactiveTitleColorDark(); - Color c2 = AbstractLookAndFeel.getTheme().getWindowInactiveTitleColorLight(); - g2D.setPaint(new GradientPaint(0, dw + th + 1, c1, 0, h - th - (2 * dw), c2)); - g.fillRect(1, dw + th + 1, dw - 1, h - th - (2 * dw)); - g.fillRect(w - dw, dw + th + 1, dw - 1, h - th - (2 * dw)); - g2D.setPaint(null); - } - if (active && resizable) { - int d = dw + 12; - // unten - color = AbstractLookAndFeel.getWindowTitleColorDark(); - Color cHi = ColorHelper.brighter(color, 30); - Color cLo = ColorHelper.darker(color, 20); - - // links - g.setColor(color); - g.fillRect(x + 1, y + h - d, dw - 1, d - 1); - g.fillRect(x + dw, y + h - dw, d - dw - 1, d - dw - 1); - - g.setColor(cLo); - g.drawLine(x + 1, y + h - d - 2, x + dw - 2, y + h - d - 2); - g.drawLine(x + dw - 2, y + h - d - 2, x + dw - 2, y + h - dw); - g.drawLine(x + dw - 2, y + h - dw, x + d - 1, y + h - dw); - g.drawLine(x + d - 1, y + h - dw, x + d - 1, y + h - 1); - - g.setColor(cHi); - g.drawLine(x + 1, y + h - d - 1, x + dw - 3, y + h - d - 1); - g.drawLine(x + dw - 1, y + h - d - 1, x + dw - 1, y + h - dw - 1); - g.drawLine(x + dw - 1, y + h - dw + 1, x + d - 2, y + h - dw + 1); - g.drawLine(x + d - 2, y + h - dw + 1, x + d - 2, y + h - 1); - - // rechts - g.setColor(color); - g.fillRect(x + w - d - 1, y + h - dw, d, dw - 1); - g.fillRect(x + w - dw, y + h - d - 1, dw - 1, d); - - g.setColor(cLo); - g.drawLine(x + w - dw - 1, y + h - d - 2, x + w - 1, y + h - d - 2); - g.drawLine(x + w - dw, y + h - d - 2, x + w - dw, y + h - dw); - g.drawLine(x + w - d - 1, y + h - dw, x + w - dw, y + h - dw); - g.drawLine(x + w - d - 1, y + h - dw, x + w - d - 1, y + h - 1); - - g.setColor(cHi); - g.drawLine(x + w - dw + 1, y + h - d - 1, x + w - 1, y + h - d - 1); - g.drawLine(x + w - dw + 1, y + h - d - 1, x + w - dw + 1, y + h - dw); - g.drawLine(x + w - d, y + h - dw + 1, x + w - dw + 1, y + h - dw + 1); - g.drawLine(x + w - d, y + h - dw + 1, x + w - d, y + h - 1); - } - g.setColor(frameColor); - g.drawRect(x, y, w - 1, h - 1); - g.drawLine(x + dw - 1, y + dw + th, x + dw - 1, y + h - dw); - g.drawLine(x + w - dw, y + dw + th, x + w - dw, y + h - dw); - g.drawLine(x + dw - 1, y + h - dw, x + w - dw, y + h - dw); - } - } // class InternalFrameBorder - - public static class PaletteBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - if (JTattooUtilities.isFrameActive((JComponent) c)) { - g.setColor(AbstractLookAndFeel.getFrameColor()); - } else { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 40)); - } - g.drawRect(x, y, w - 1, h - 1); - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - } // class PaletteBorder -} // class SmartBorders - diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartButtonUI.java deleted file mode 100644 index a54f20c80..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartButtonUI.java +++ /dev/null @@ -1,73 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseButtonUI; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.RoundRectangle2D; -import javax.swing.AbstractButton; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class SmartButtonUI extends BaseButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new SmartButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - int w = b.getWidth(); - int h = b.getHeight(); - Graphics2D g2D = (Graphics2D) g; - Shape savedClip = g.getClip(); - if ((b.getBorder() != null) && b.isBorderPainted() && (b.getBorder() instanceof UIResource)) { - Area clipArea = new Area(new RoundRectangle2D.Double(0, 0, w - 1, h - 1, 6, 6)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - } - super.paintBackground(g, b); - if (b.isContentAreaFilled() && b.isRolloverEnabled() && b.getModel().isRollover() && b.isBorderPainted() && (b.getBorder() != null)) { - g.setColor(AbstractLookAndFeel.getTheme().getFocusColor()); - Insets ins = b.getBorder().getBorderInsets(b); - if (ins.top == 0) { - g.drawLine(1, 0, w - 1, 0); - g.drawLine(1, 1, w - 1, 1); - g.drawLine(1, 2, w - 1, 2); - } else { - g.drawLine(1, 1, w - 1, 1); - g.drawLine(1, 2, w - 1, 2); - g.drawLine(1, 3, w - 1, 3); - } - } - g2D.setClip(savedClip); - } -} - - diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartComboBoxUI.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartComboBoxUI.java deleted file mode 100644 index 78381b7d4..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartComboBoxUI.java +++ /dev/null @@ -1,65 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.*; -import java.awt.Graphics; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class SmartComboBoxUI extends BaseComboBoxUI { - - public static ComponentUI createUI(JComponent c) { - return new SmartComboBoxUI(); - } - - public JButton createArrowButton() { - ArrowButton button = new ArrowButton(); - if (JTattooUtilities.isLeftToRight(comboBox)) { - Border border = BorderFactory.createMatteBorder(0, 1, 0, 0, AbstractLookAndFeel.getFrameColor()); - button.setBorder(border); - } else { - Border border = BorderFactory.createMatteBorder(0, 0, 0, 1, AbstractLookAndFeel.getFrameColor()); - button.setBorder(border); - } - return button; - } - -//-------------------------------------------------------------------------------------------------- - static class ArrowButton extends BaseComboBoxUI.ArrowButton { - - public void paint(Graphics g) { - super.paint(g); - if (getModel().isRollover()) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - g.drawLine(1, 0, getWidth() - 1, 0); - g.drawLine(1, 1, getWidth() - 1, 1); - } - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartDefaultTheme.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartDefaultTheme.java deleted file mode 100644 index ed3a404c1..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartDefaultTheme.java +++ /dev/null @@ -1,130 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.AbstractTheme; -import com.jtattoo.plaf.ColorHelper; -import java.awt.Color; -import javax.swing.plaf.ColorUIResource; - -public class SmartDefaultTheme extends AbstractTheme { - - public SmartDefaultTheme() { - super(); - // Setup theme with defaults - setUpColor(); - // Overwrite defaults with user props - loadProperties(); - // Setup the color arrays - setUpColorArrs(); - } - - public String getPropertyFileName() { - return "SmartTheme.properties"; - } - - public void setUpColor() { - super.setUpColor(); - - // Defaults for SmartLookAndFeel - backgroundColor = new ColorUIResource(244, 242, 232); - backgroundColorLight = new ColorUIResource(255, 255, 255); - backgroundColorDark = new ColorUIResource(236, 233, 215); - alterBackgroundColor = new ColorUIResource(236, 233, 215); - - selectionBackgroundColor = new ColorUIResource(201, 218, 254); - selectionBackgroundColorLight = new ColorUIResource(201, 218, 254); - selectionBackgroundColorDark = new ColorUIResource(201, 218, 254); - frameColor = new ColorUIResource(128, 124, 112); - focusCellColor = new ColorUIResource(255, 230, 120); - - buttonBackgroundColor = new ColorUIResource(218, 230, 254); - buttonColorLight = white; - buttonColorDark = backgroundColor; - - rolloverColor = new ColorUIResource(218, 230, 254); - rolloverColorLight = new ColorUIResource(236, 242, 255); - rolloverColorDark = new ColorUIResource(191, 211, 253); - - controlForegroundColor = black; - controlBackgroundColor = backgroundColor; - controlColorLight = new ColorUIResource(218, 230, 254); - controlColorDark = new ColorUIResource(180, 197, 240); - controlShadowColor = new ColorUIResource(164, 164, 164); - controlDarkShadowColor = new ColorUIResource(148, 148, 148); - - windowTitleBackgroundColor = new ColorUIResource(180, 197, 240); - windowTitleColorLight = new ColorUIResource(218, 230, 254); - windowTitleColorDark = new ColorUIResource(180, 197, 240); - windowBorderColor = new ColorUIResource(128, 129, 132); - - windowInactiveTitleBackgroundColor = backgroundColor; - windowInactiveTitleColorLight = new ColorUIResource(244, 242, 234); - windowInactiveTitleColorDark = new ColorUIResource(230, 224, 202); - windowInactiveBorderColor = new ColorUIResource(164, 165, 169); - - menuBackgroundColor = new ColorUIResource(248, 247, 239); - menuSelectionForegroundColor = black; - menuSelectionBackgroundColor = selectionBackgroundColor; - menuColorLight = new ColorUIResource(248, 245, 235); - menuColorDark = backgroundColor; - - toolbarBackgroundColor = backgroundColor; - toolbarColorLight = menuColorLight; - toolbarColorDark = menuColorDark; - - tabAreaBackgroundColor = backgroundColor; - desktopColor = backgroundColor; - } - - public void setUpColorArrs() { - super.setUpColorArrs(); - - // Generate the color arrays - DEFAULT_COLORS = ColorHelper.createColorArr(controlColorLight, controlColorDark, 20); - HIDEFAULT_COLORS = ColorHelper.createColorArr(ColorHelper.brighter(controlColorLight, 90), ColorHelper.brighter(controlColorDark, 30), 20); - - ACTIVE_COLORS = DEFAULT_COLORS; - INACTIVE_COLORS = ColorHelper.createColorArr(Color.white, backgroundColor, 20); - - ROLLOVER_COLORS = ColorHelper.createColorArr(rolloverColorLight, rolloverColorDark, 20); - SELECTED_COLORS = DEFAULT_COLORS; - PRESSED_COLORS = ColorHelper.createColorArr(controlColorDark, controlColorLight, 20); - DISABLED_COLORS = ColorHelper.createColorArr(Color.white, new Color(230, 230, 230), 20); - - WINDOW_TITLE_COLORS = ColorHelper.createColorArr(windowTitleColorLight, windowTitleColorDark, 20); - WINDOW_INACTIVE_TITLE_COLORS = ColorHelper.createColorArr(windowInactiveTitleColorLight, windowInactiveTitleColorDark, 20); - MENUBAR_COLORS = ColorHelper.createColorArr(menuColorLight, menuColorDark, 20); - TOOLBAR_COLORS = ColorHelper.createColorArr(toolbarColorLight, toolbarColorDark, 20); - - BUTTON_COLORS = ColorHelper.createColorArr(buttonColorLight, buttonColorDark, 20); - TAB_COLORS = ColorHelper.createColorArr(Color.white, backgroundColor, 20); - CHECKBOX_COLORS = TAB_COLORS; - COL_HEADER_COLORS = MENUBAR_COLORS; - TRACK_COLORS = ColorHelper.createColorArr(backgroundColor, Color.white, 16); - THUMB_COLORS = DEFAULT_COLORS; - SLIDER_COLORS = DEFAULT_COLORS; - PROGRESSBAR_COLORS = DEFAULT_COLORS; - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartIconFactory.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartIconFactory.java deleted file mode 100644 index 86c86e932..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartIconFactory.java +++ /dev/null @@ -1,213 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.AbstractIconFactory; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class SmartIconFactory implements AbstractIconFactory { - - private static SmartIconFactory instance = null; - - private SmartIconFactory() { - } - - public static synchronized SmartIconFactory getInstance() { - if (instance == null) { - instance = new SmartIconFactory(); - } - return instance; - } - - public Icon getOptionPaneErrorIcon() { - return SmartIcons.getOptionPaneErrorIcon(); - } - - public Icon getOptionPaneWarningIcon() { - return SmartIcons.getOptionPaneWarningIcon(); - } - - public Icon getOptionPaneInformationIcon() { - return SmartIcons.getOptionPaneInformationIcon(); - } - - public Icon getOptionPaneQuestionIcon() { - return SmartIcons.getOptionPaneQuestionIcon(); - } - - public Icon getFileChooserDetailViewIcon() { - return SmartIcons.getFileChooserDetailViewIcon(); - } - - public Icon getFileChooserHomeFolderIcon() { - return SmartIcons.getFileChooserHomeFolderIcon(); - } - - public Icon getFileChooserListViewIcon() { - return SmartIcons.getFileChooserListViewIcon(); - } - - public Icon getFileChooserNewFolderIcon() { - return SmartIcons.getFileChooserNewFolderIcon(); - } - - public Icon getFileChooserUpFolderIcon() { - return SmartIcons.getFileChooserUpFolderIcon(); - } - - public Icon getMenuIcon() { - return SmartIcons.getMenuIcon(); - } - - public Icon getIconIcon() { - return SmartIcons.getIconIcon(); - } - - public Icon getMaxIcon() { - return SmartIcons.getMaxIcon(); - } - - public Icon getMinIcon() { - return SmartIcons.getMinIcon(); - } - - public Icon getCloseIcon() { - return SmartIcons.getCloseIcon(); - } - - public Icon getPaletteCloseIcon() { - return SmartIcons.getPaletteCloseIcon(); - } - - public Icon getRadioButtonIcon() { - return SmartIcons.getRadioButtonIcon(); - } - - public Icon getCheckBoxIcon() { - return SmartIcons.getCheckBoxIcon(); - } - - public Icon getComboBoxIcon() { - return SmartIcons.getComboBoxIcon(); - } - - public Icon getTreeComputerIcon() { - return SmartIcons.getTreeComputerIcon(); - } - - public Icon getTreeFloppyDriveIcon() { - return SmartIcons.getTreeFloppyDriveIcon(); - } - - public Icon getTreeHardDriveIcon() { - return SmartIcons.getTreeHardDriveIcon(); - } - - public Icon getTreeFolderIcon() { - return SmartIcons.getTreeFolderIcon(); - } - - public Icon getTreeLeafIcon() { - return SmartIcons.getTreeLeafIcon(); - } - - public Icon getTreeCollapsedIcon() { - return SmartIcons.getTreeControlIcon(true); - } - - public Icon getTreeExpandedIcon() { - return SmartIcons.getTreeControlIcon(false); - } - - public Icon getMenuArrowIcon() { - return SmartIcons.getMenuArrowIcon(); - } - - public Icon getMenuCheckBoxIcon() { - return SmartIcons.getMenuCheckBoxIcon(); - } - - public Icon getMenuRadioButtonIcon() { - return SmartIcons.getMenuRadioButtonIcon(); - } - - public Icon getUpArrowIcon() { - return SmartIcons.getUpArrowIcon(); - } - - public Icon getDownArrowIcon() { - return SmartIcons.getDownArrowIcon(); - } - - public Icon getLeftArrowIcon() { - return SmartIcons.getLeftArrowIcon(); - } - - public Icon getRightArrowIcon() { - return SmartIcons.getRightArrowIcon(); - } - - public Icon getSplitterDownArrowIcon() { - return SmartIcons.getSplitterDownArrowIcon(); - } - - public Icon getSplitterHorBumpIcon() { - return SmartIcons.getSplitterHorBumpIcon(); - } - - public Icon getSplitterLeftArrowIcon() { - return SmartIcons.getSplitterLeftArrowIcon(); - } - - public Icon getSplitterRightArrowIcon() { - return SmartIcons.getSplitterRightArrowIcon(); - } - - public Icon getSplitterUpArrowIcon() { - return SmartIcons.getSplitterUpArrowIcon(); - } - - public Icon getSplitterVerBumpIcon() { - return SmartIcons.getSplitterVerBumpIcon(); - } - - public Icon getThumbHorIcon() { - return SmartIcons.getThumbHorIcon(); - } - - public Icon getThumbVerIcon() { - return SmartIcons.getThumbVerIcon(); - } - - public Icon getThumbHorIconRollover() { - return SmartIcons.getThumbHorIconRollover(); - } - - public Icon getThumbVerIconRollover() { - return SmartIcons.getThumbVerIconRollover(); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartIcons.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartIcons.java deleted file mode 100644 index 42f265614..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartIcons.java +++ /dev/null @@ -1,174 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.*; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.RoundRectangle2D; -import javax.swing.Icon; -import javax.swing.JButton; - -/** - * @author Michael Hagen - */ -public class SmartIcons extends BaseIcons { - - public static Icon getIconIcon() { - if (iconIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - iconIcon = new MacIconIcon(); - } else { - iconIcon = new TitleButtonIcon(TitleButtonIcon.ICON_ICON_TYP); - } - } - return iconIcon; - } - - public static Icon getMinIcon() { - if (minIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - minIcon = new MacMinIcon(); - } else { - minIcon = new TitleButtonIcon(TitleButtonIcon.MIN_ICON_TYP); - } - } - return minIcon; - } - - public static Icon getMaxIcon() { - if (maxIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - maxIcon = new MacMaxIcon(); - } else { - maxIcon = new TitleButtonIcon(TitleButtonIcon.MAX_ICON_TYP); - } - } - return maxIcon; - } - - public static Icon getCloseIcon() { - if (closeIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - closeIcon = new MacCloseIcon(); - } else { - closeIcon = new TitleButtonIcon(TitleButtonIcon.CLOSE_ICON_TYP); - } - } - return closeIcon; - } - -//------------------------------------------------------------------------------ - private static class TitleButtonIcon implements Icon { - - private static Color closerColorLight = new Color(241, 172, 154); - private static Color closerColorDark = new Color(224, 56, 2); - public static final int ICON_ICON_TYP = 0; - public static final int MIN_ICON_TYP = 1; - public static final int MAX_ICON_TYP = 2; - public static final int CLOSE_ICON_TYP = 3; - private int iconTyp = ICON_ICON_TYP; - - public TitleButtonIcon(int typ) { - iconTyp = typ; - } - - public int getIconHeight() { - return 20; - } - - public int getIconWidth() { - return 20; - } - - public void paintIcon(Component c, Graphics g, int x, int y) { - int w = c.getWidth(); - int h = c.getHeight(); - - JButton b = (JButton) c; - Graphics2D g2D = (Graphics2D) g; - - boolean isActive = JTattooUtilities.isActive(b); - boolean isPressed = b.getModel().isPressed(); - boolean isArmed = b.getModel().isArmed(); - boolean isRollover = b.getModel().isRollover(); - - Color cHi = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getWindowTitleColorLight(), 40); - Color cLo = ColorHelper.darker(AbstractLookAndFeel.getTheme().getWindowTitleColorDark(), 10); - if (iconTyp == CLOSE_ICON_TYP) { - cHi = closerColorLight; - cLo = closerColorDark; - } - - Color fcHi = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getWindowTitleColorDark(), 80); - Color fcLo = ColorHelper.darker(AbstractLookAndFeel.getTheme().getWindowTitleColorDark(), 40); - - if (!isActive) { - cHi = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getWindowInactiveTitleColorLight(), 40); - cLo = ColorHelper.darker(AbstractLookAndFeel.getTheme().getWindowInactiveTitleColorDark(), 10); - fcHi = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getWindowInactiveTitleColorLight(), 60); - fcLo = ColorHelper.darker(AbstractLookAndFeel.getTheme().getWindowInactiveTitleColorDark(), 10); - } - if (isPressed && isArmed) { - Color cTemp = ColorHelper.darker(cLo, 10); - cLo = ColorHelper.darker(cHi, 10); - cHi = cTemp; - } else if (isRollover) { - cHi = ColorHelper.brighter(cHi, 30); - cLo = ColorHelper.brighter(cLo, 30); - } - - Shape savedClip = g.getClip(); - Area area = new Area(new RoundRectangle2D.Double(1, 1, w - 1, h - 1, 3, 3)); - g2D.setClip(area); - - g2D.setPaint(new GradientPaint(0, 0, fcLo, w, h, fcHi)); - g.fillRect(1, 1, w - 1, h - 1); - - g2D.setPaint(new GradientPaint(0, 0, ColorHelper.brighter(cHi, 80), w, h, ColorHelper.darker(cLo, 30))); - g.fillRect(2, 2, w - 3, h - 3); - - g2D.setPaint(new GradientPaint(0, 0, cHi, w, h, cLo)); - g.fillRect(3, 3, w - 5, h - 5); - - g2D.setClip(savedClip); - - cHi = Color.white; - cLo = ColorHelper.darker(cLo, 30); - Icon icon = null; - if (iconTyp == ICON_ICON_TYP) { - icon = new BaseIcons.IconSymbol(cHi, cLo, null); - } else if (iconTyp == MIN_ICON_TYP) { - icon = new BaseIcons.MinSymbol(cHi, cLo, null); - } else if (iconTyp == MAX_ICON_TYP) { - icon = new BaseIcons.MaxSymbol(cHi, cLo, null); - } else if (iconTyp == CLOSE_ICON_TYP) { - icon = new BaseIcons.CloseSymbol(cHi, cLo, null); - } - if (icon != null) { - icon.paintIcon(c, g, 0, 0); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartInternalFrameTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartInternalFrameTitlePane.java deleted file mode 100644 index 17b98da9a..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartInternalFrameTitlePane.java +++ /dev/null @@ -1,174 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.Icon; -import javax.swing.JInternalFrame; - -/** - * @author Michael Hagen - */ -public class SmartInternalFrameTitlePane extends BaseInternalFrameTitlePane { - - public SmartInternalFrameTitlePane(JInternalFrame f) { - super(f); - } - - public void paintPalette(Graphics g) { - int width = getWidth(); - int height = getHeight(); - - Color backColor; - Color frameColor; - if (JTattooUtilities.isFrameActive(this)) { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 0, 0, width, height); - backColor = AbstractLookAndFeel.getTheme().getWindowTitleColors()[10]; - frameColor = ColorHelper.darker(AbstractLookAndFeel.getWindowTitleColorDark(), 15); - } else { - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 0, 0, width, height); - backColor = AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors()[10]; - frameColor = ColorHelper.darker(AbstractLookAndFeel.getWindowInactiveTitleColorDark(), 15); - } - g.setColor(frameColor); - g.drawLine(0, height - 1, width, height - 1); - - int dx = 8; - int dy = 2; - int dw = width - buttonsWidth - 2 * 8; - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - - float dc1 = 50.0f; - float dc2 = 5.0f; - Color c1 = ColorHelper.brighter(backColor, dc1); - Color c2; - while ((dy + 2) < height) { - c2 = ColorHelper.darker(backColor, dc2); - dc2 += 5.0f; - g.setColor(c1); - g.drawLine(dx, dy, dx + dw, dy); - dy++; - g.setColor(c2); - g.drawLine(dx, dy, dx + dw, dy); - dy += 2; - } - g2D.setComposite(composite); - } - - public void paintBackground(Graphics g) { - Graphics2D g2D = (Graphics2D) g; - int width = getWidth(); - int height = getHeight(); - Color backColor; - Color frameColor; - if (JTattooUtilities.isActive(this)) { - backColor = AbstractLookAndFeel.getTheme().getWindowTitleColors()[10]; - frameColor = AbstractLookAndFeel.getTheme().getFrameColor(); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 0, 0, width, height); - } else { - backColor = AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors()[10]; - frameColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFrameColor(), 40); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 0, 0, width, height); - } - - int iconWidth = 0; - Icon icon = frame.getFrameIcon(); - if (icon != null) { - iconWidth = icon.getIconWidth() + 5; - } - - int titleWidth = 0; - String frameTitle = frame.getTitle(); - if (frameTitle != null) { - Font f = getFont(); - g.setFont(f); - FontMetrics fm = g.getFontMetrics(); - titleWidth = fm.stringWidth(JTattooUtilities.getClippedText(frame.getTitle(), fm, getWidth() - iconWidth - buttonsWidth - 15)) + 10; - } - - int dx; - int dw; - boolean leftToRight = JTattooUtilities.isLeftToRight(frame); - int xOffset = leftToRight ? iconWidth + 10 + titleWidth : width - 10 - iconWidth - titleWidth; - - if (leftToRight) { - dw = width - buttonsWidth - xOffset - 10; - dx = xOffset; - } else { - dw = xOffset - buttonsWidth - 10; - dx = buttonsWidth + 10; - } - int dy = 3; - - if (!AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn() && (dw > 0)) { - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - - float dc1 = 50.0f; - float dc2 = 5.0f; - - Color c1 = ColorHelper.brighter(backColor, dc1); - Color c2; - while ((dy + 5) < height) { - c2 = ColorHelper.darker(backColor, dc2); - dc2 += 5.0f; - g.setColor(c1); - g.drawLine(dx, dy, dx + dw, dy); - dy++; - g.setColor(c2); - g.drawLine(dx, dy, dx + dw, dy); - dy += 3; - } - g2D.setComposite(composite); - } - g.setColor(frameColor); - g.drawLine(0, height - 1, width, height - 1); - } - - public void paintBorder(Graphics g) { - } - - public void paintText(Graphics g, int x, int y, String title) { - if (isMacStyleWindowDecoration()) { - x += paintIcon(g, x, y) + 5; - } - if (isActive()) { - Color titleColor = AbstractLookAndFeel.getWindowTitleForegroundColor(); - if (ColorHelper.getGrayValue(titleColor) > 164) { - g.setColor(Color.black); - JTattooUtilities.drawString(frame, g, title, x + 1, y); - } - g.setColor(titleColor); - JTattooUtilities.drawString(frame, g, title, x, y - 1); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - JTattooUtilities.drawString(frame, g, title, x, y - 1); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartInternalFrameUI.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartInternalFrameUI.java deleted file mode 100644 index 6d6899016..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartInternalFrameUI.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.BaseInternalFrameUI; -import javax.swing.JComponent; -import javax.swing.JInternalFrame; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class SmartInternalFrameUI extends BaseInternalFrameUI { - - public SmartInternalFrameUI(JInternalFrame b) { - super(b); - } - - public static ComponentUI createUI(JComponent c) { - return new SmartInternalFrameUI((JInternalFrame) c); - } - - protected JComponent createNorthPane(JInternalFrame w) { - titlePane = new SmartInternalFrameTitlePane(w); - return titlePane; - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartLookAndFeel.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartLookAndFeel.java deleted file mode 100644 index fda09176c..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartLookAndFeel.java +++ /dev/null @@ -1,499 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.*; -import java.util.*; -import javax.swing.UIDefaults; - -/** - * @author Michael Hagen - */ -public class SmartLookAndFeel extends AbstractLookAndFeel { - - private static SmartDefaultTheme myTheme = null; - - private static final ArrayList themesList = new ArrayList(); - private static final HashMap themesMap = new HashMap(); - private static final Properties defaultProps = new Properties(); - private static final Properties smallFontProps = new Properties(); - private static final Properties largeFontProps = new Properties(); - private static final Properties giantFontProps = new Properties(); - private static final Properties goldProps = new Properties(); - private static final Properties goldSmallFontProps = new Properties(); - private static final Properties goldLargeFontProps = new Properties(); - private static final Properties goldGiantFontProps = new Properties(); - private static final Properties greenProps = new Properties(); - private static final Properties greenSmallFontProps = new Properties(); - private static final Properties greenLargeFontProps = new Properties(); - private static final Properties greenGiantFontProps = new Properties(); - private static final Properties brownProps = new Properties(); - private static final Properties brownSmallFontProps = new Properties(); - private static final Properties brownLargeFontProps = new Properties(); - private static final Properties brownGiantFontProps = new Properties(); - private static final Properties lemmonProps = new Properties(); - private static final Properties lemmonSmallFontProps = new Properties(); - private static final Properties lemmonLargeFontProps = new Properties(); - private static final Properties lemmonGiantFontProps = new Properties(); - private static final Properties grayProps = new Properties(); - private static final Properties graySmallFontProps = new Properties(); - private static final Properties grayLargeFontProps = new Properties(); - private static final Properties grayGiantFontProps = new Properties(); - - static { - smallFontProps.setProperty("controlTextFont", "Dialog 10"); - smallFontProps.setProperty("systemTextFont", "Dialog 10"); - smallFontProps.setProperty("userTextFont", "Dialog 10"); - smallFontProps.setProperty("menuTextFont", "Dialog 10"); - smallFontProps.setProperty("windowTitleFont", "Dialog bold 10"); - smallFontProps.setProperty("subTextFont", "Dialog 8"); - - largeFontProps.setProperty("controlTextFont", "Dialog 14"); - largeFontProps.setProperty("systemTextFont", "Dialog 14"); - largeFontProps.setProperty("userTextFont", "Dialog 14"); - largeFontProps.setProperty("menuTextFont", "Dialog 14"); - largeFontProps.setProperty("windowTitleFont", "Dialog bold 14"); - largeFontProps.setProperty("subTextFont", "Dialog 12"); - - giantFontProps.setProperty("controlTextFont", "Dialog 18"); - giantFontProps.setProperty("systemTextFont", "Dialog 18"); - giantFontProps.setProperty("userTextFont", "Dialog 18"); - giantFontProps.setProperty("menuTextFont", "Dialog 18"); - giantFontProps.setProperty("windowTitleFont", "Dialog 18"); - giantFontProps.setProperty("subTextFont", "Dialog 16"); - - goldProps.setProperty("focusCellColor", "160 160 120"); - goldProps.setProperty("backgroundColor", "240 240 240"); - goldProps.setProperty("backgroundColorLight", "255 255 255"); - goldProps.setProperty("backgroundColorDark", "230 230 230"); - goldProps.setProperty("alterBackgroundColor", "230 230 230"); - goldProps.setProperty("selectionBackgroundColor", "232 232 180"); - goldProps.setProperty("controlBackgroundColor", "240 240 240"); - goldProps.setProperty("controlColorLight", "248 248 180"); - goldProps.setProperty("controlColorDark", "200 200 120"); - goldProps.setProperty("buttonColorLight", "255 255 255"); - goldProps.setProperty("buttonColorDark", "230 230 230"); - goldProps.setProperty("rolloverColor", "220 220 169"); - goldProps.setProperty("rolloverColorLight", "250 250 240"); - goldProps.setProperty("rolloverColorDark", "220 220 169"); - goldProps.setProperty("windowTitleBackgroundColor", "248 248 180"); - goldProps.setProperty("windowTitleColorLight", "248 248 180"); - goldProps.setProperty("windowTitleColorDark", "200 200 120"); - goldProps.setProperty("windowInactiveBackgroundColor", "240 240 240"); - goldProps.setProperty("windowInactiveTitleColorLight", "248 248 248"); - goldProps.setProperty("windowInactiveTitleColorDark", "220 220 220"); - goldProps.setProperty("menuBackgroundColor", "248 248 248"); - goldProps.setProperty("menuColorLight", "248 248 248"); - goldProps.setProperty("menuColorDark", "230 230 230"); - goldProps.setProperty("menuSelectionBackgroundColor", "232 232 180"); - goldProps.setProperty("toolbarBackgroundColor", "248 248 248"); - goldProps.setProperty("toolbarColorLight", "248 248 248"); - goldProps.setProperty("toolbarColorDark", "230 230 230"); - goldProps.setProperty("desktopColor", "240 240 240"); - - greenProps.setProperty("frameColor", "140 140 140"); - greenProps.setProperty("focusCellColor", "40 100 60"); - greenProps.setProperty("backgroundColor", "240 240 240"); - greenProps.setProperty("backgroundColorLight", "255 255 255"); - greenProps.setProperty("backgroundColorDark", "230 230 230"); - greenProps.setProperty("alterBackgroundColor", "230 230 230"); - greenProps.setProperty("selectionBackgroundColor", "160 210 170"); - greenProps.setProperty("controlBackgroundColor", "240 240 240"); - greenProps.setProperty("controlColorLight", "120 199 153"); - greenProps.setProperty("controlColorDark", "60 142 95"); - greenProps.setProperty("buttonColorLight", "255 255 255"); - greenProps.setProperty("buttonColorDark", "230 230 230"); - greenProps.setProperty("rolloverColor", "150 211 176"); - greenProps.setProperty("rolloverColorLight", "200 232 214"); - greenProps.setProperty("rolloverColorDark", "131 203 162"); - greenProps.setProperty("windowTitleForegroundColor", "255 255 255"); - greenProps.setProperty("windowTitleBackgroundColor", "100 160 140"); - greenProps.setProperty("windowTitleColorLight", "120 199 153"); - greenProps.setProperty("windowTitleColorDark", "60 142 95"); - greenProps.setProperty("windowInactiveForegroundColor", "0 0 0"); - greenProps.setProperty("windowInactiveBackgroundColor", "240 240 240"); - greenProps.setProperty("windowInactiveTitleColorLight", "248 248 248"); - greenProps.setProperty("windowInactiveTitleColorDark", "220 220 220"); - greenProps.setProperty("menuBackgroundColor", "248 248 248"); - greenProps.setProperty("menuColorLight", "248 248 248"); - greenProps.setProperty("menuColorDark", "230 230 230"); - greenProps.setProperty("menuSelectionBackgroundColor", "160 210 170"); - greenProps.setProperty("toolbarBackgroundColor", "248 248 248"); - greenProps.setProperty("toolbarColorLight", "248 248 248"); - greenProps.setProperty("toolbarColorDark", "230 230 230"); - greenProps.setProperty("desktopColor", "240 240 240"); - - brownProps.setProperty("frameColor", "128 124 112"); - brownProps.setProperty("focusCellColor", "255 230 120"); - brownProps.setProperty("backgroundColor", "236 233 216"); - brownProps.setProperty("backgroundColorLight", "255 255 255"); - brownProps.setProperty("backgroundColorDark", "226 222 194"); - brownProps.setProperty("alterBackgroundColor", "226 222 194"); - brownProps.setProperty("selectionBackgroundColor", "224 220 192"); - brownProps.setProperty("controlBackgroundColor", "236 233 216"); - brownProps.setProperty("controlColorLight", "242 240 230"); - brownProps.setProperty("controlColorDark", "215 208 172"); - brownProps.setProperty("buttonColorLight", "255 255 255"); - brownProps.setProperty("buttonColorDark", "244 242 232"); - brownProps.setProperty("rolloverColor", "210 203 164"); - brownProps.setProperty("rolloverColorLight", "236 233 216"); - brownProps.setProperty("rolloverColorDark", "215 208 172"); - brownProps.setProperty("windowTitleForegroundColor", "0 0 0"); - brownProps.setProperty("windowTitleBackgroundColor", "236 233 216"); - brownProps.setProperty("windowTitleColorLight", "236 233 216"); - brownProps.setProperty("windowTitleColorDark", "215 208 172"); - brownProps.setProperty("windowInactiveBackgroundColor", "240 240 230"); - brownProps.setProperty("windowInactiveTitleColorLight", "242 240 230"); - brownProps.setProperty("windowInactiveTitleColorDark", "236 233 216"); - brownProps.setProperty("menuBackgroundColor", "236 233 216"); - brownProps.setProperty("menuColorLight", "248 245 235"); - brownProps.setProperty("menuColorDark", "236 233 216"); - brownProps.setProperty("menuSelectionBackgroundColor", "215 208 172"); - brownProps.setProperty("toolbarBackgroundColor", "248 248 248"); - brownProps.setProperty("toolbarColorLight", "248 245 235"); - brownProps.setProperty("toolbarColorDark", "236 233 216"); - brownProps.setProperty("desktopColor", "236 233 216"); - - lemmonProps.setProperty("frameColor", "91 121 13"); - lemmonProps.setProperty("backgroundColor", "227 231 230"); - lemmonProps.setProperty("backgroundColorLight", "255 255 255"); - lemmonProps.setProperty("backgroundColorDark", "218 222 221"); - lemmonProps.setProperty("alterBackgroundColor", "218 222 221"); - lemmonProps.setProperty("selectionBackgroundColor", "175 232 28"); - lemmonProps.setProperty("rolloverColor", "243 254 180"); - lemmonProps.setProperty("rolloverColorLight", "243 254 180"); - lemmonProps.setProperty("rolloverColorDark", "231 253 104"); - lemmonProps.setProperty("windowTitleBackgroundColor", "236 253 138"); - lemmonProps.setProperty("windowTitleColorLight", "236 253 138"); - lemmonProps.setProperty("windowTitleColorDark", "170 229 23"); - lemmonProps.setProperty("windowInactiveTitleBackgroundColor", "240 240 240"); - lemmonProps.setProperty("windowInactiveTitleColorLight", "240 240 240"); - lemmonProps.setProperty("windowInactiveTitleColorDark", "226 226 226"); - lemmonProps.setProperty("controlBackgroundColor", "227 231 230"); - lemmonProps.setProperty("controlColorLight", "236 253 138"); - lemmonProps.setProperty("controlColorDark", "170 229 23"); - lemmonProps.setProperty("buttonColorLight", "236 253 138"); - lemmonProps.setProperty("buttonColorDark", "170 229 23"); - lemmonProps.setProperty("menuBackgroundColor", "227 231 230"); - lemmonProps.setProperty("menuSelectionBackgroundColor", "175 232 28"); - lemmonProps.setProperty("menuBackgroundColorLight", "238 240 240"); - lemmonProps.setProperty("menuColorLight", "238 240 240"); - lemmonProps.setProperty("menuColorDark", "224 228 227"); - lemmonProps.setProperty("toolbarBackgroundColor", "238 240 240"); - lemmonProps.setProperty("toolbarColorLight", "238 240 240"); - lemmonProps.setProperty("toolbarColorDark", "224 228 227"); - lemmonProps.setProperty("desktopColor", "227 231 230"); - - grayProps.setProperty("backgroundColor", "244 244 244"); - grayProps.setProperty("backgroundColorLight", "255 255 255"); - grayProps.setProperty("backgroundColorDark", "230 230 230"); - grayProps.setProperty("alterBackgroundColor", "230 230 230"); - grayProps.setProperty("selectionForegroundColor", "255 255 255"); - grayProps.setProperty("selectionBackgroundColor", "128 128 128"); - grayProps.setProperty("controlBackgroundColor", "244 244 244"); - grayProps.setProperty("controlColorLight", "192 192 192"); - grayProps.setProperty("controlColorDark", "128 128 128"); - grayProps.setProperty("buttonColorLight", "255 255 255"); - grayProps.setProperty("buttonColorDark", "232 232 232"); - grayProps.setProperty("rolloverColor", "212 212 212"); - grayProps.setProperty("rolloverColorLight", "232 232 232"); - grayProps.setProperty("rolloverColorDark", "200 200 200"); - grayProps.setProperty("windowTitleForegroundColor", "255 255 255"); - grayProps.setProperty("windowTitleBackgroundColor", "64 64 64"); - grayProps.setProperty("windowTitleColorLight", "164 164 164"); - grayProps.setProperty("windowTitleColorDark", "96 96 96"); - grayProps.setProperty("windowInactiveForegroundColor", "0 0 0"); - grayProps.setProperty("windowInactiveBackgroundColor", "240 240 240"); - grayProps.setProperty("windowInactiveTitleColorLight", "244 244 244"); - grayProps.setProperty("windowInactiveTitleColorDark", "212 212 212"); - grayProps.setProperty("menuBackgroundColor", "255 255 255"); - grayProps.setProperty("menuColorLight", "252 252 252"); - grayProps.setProperty("menuColorDark", "232 232 232"); - grayProps.setProperty("menuSelectionForegroundColor", "255 255 255"); - grayProps.setProperty("menuSelectionBackgroundColor", "128 128 128"); - grayProps.setProperty("toolbarBackgroundColor", "248 248 248"); - grayProps.setProperty("toolbarColorLight", "252 252 252"); - grayProps.setProperty("toolbarColorDark", "232 232 232"); - grayProps.setProperty("desktopColor", "240 240 240"); - - String key; - String value; - Iterator iter = smallFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = smallFontProps.getProperty(key); - goldSmallFontProps.setProperty(key, value); - greenSmallFontProps.setProperty(key, value); - brownSmallFontProps.setProperty(key, value); - lemmonSmallFontProps.setProperty(key, value); - graySmallFontProps.setProperty(key, value); - } - iter = largeFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = largeFontProps.getProperty(key); - goldLargeFontProps.setProperty(key, value); - greenLargeFontProps.setProperty(key, value); - brownLargeFontProps.setProperty(key, value); - lemmonLargeFontProps.setProperty(key, value); - grayLargeFontProps.setProperty(key, value); - } - iter = giantFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = giantFontProps.getProperty(key); - goldGiantFontProps.setProperty(key, value); - greenGiantFontProps.setProperty(key, value); - brownGiantFontProps.setProperty(key, value); - lemmonGiantFontProps.setProperty(key, value); - grayGiantFontProps.setProperty(key, value); - } - - iter = goldProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = goldProps.getProperty(key); - goldSmallFontProps.setProperty(key, value); - goldLargeFontProps.setProperty(key, value); - goldGiantFontProps.setProperty(key, value); - } - iter = greenProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = greenProps.getProperty(key); - greenSmallFontProps.setProperty(key, value); - greenLargeFontProps.setProperty(key, value); - greenGiantFontProps.setProperty(key, value); - } - iter = brownProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = brownProps.getProperty(key); - brownSmallFontProps.setProperty(key, value); - brownLargeFontProps.setProperty(key, value); - brownGiantFontProps.setProperty(key, value); - } - iter = lemmonProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = lemmonProps.getProperty(key); - lemmonSmallFontProps.setProperty(key, value); - lemmonLargeFontProps.setProperty(key, value); - lemmonGiantFontProps.setProperty(key, value); - } - iter = grayProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String) iter.next(); - value = grayProps.getProperty(key); - graySmallFontProps.setProperty(key, value); - grayLargeFontProps.setProperty(key, value); - grayGiantFontProps.setProperty(key, value); - } - - themesList.add("Default"); - themesList.add("Small-Font"); - themesList.add("Large-Font"); - themesList.add("Giant-Font"); - - themesList.add("Gold"); - themesList.add("Gold-Small-Font"); - themesList.add("Gold-Large-Font"); - themesList.add("Gold-Giant-Font"); - - themesList.add("Green"); - themesList.add("Green-Small-Font"); - themesList.add("Green-Large-Font"); - themesList.add("Green-Giant-Font"); - - themesList.add("Brown"); - themesList.add("Brown-Small-Font"); - themesList.add("Brown-Large-Font"); - themesList.add("Brown-Giant-Font"); - - themesList.add("Lemmon"); - themesList.add("Lemmon-Small-Font"); - themesList.add("Lemmon-Large-Font"); - themesList.add("Lemmon-Giant-Font"); - - themesList.add("Gray"); - themesList.add("Gray-Small-Font"); - themesList.add("Gray-Large-Font"); - themesList.add("Gray-Giant-Font"); - - themesMap.put("Default", defaultProps); - themesMap.put("Small-Font", smallFontProps); - themesMap.put("Large-Font", largeFontProps); - themesMap.put("Giant-Font", giantFontProps); - - themesMap.put("Gold", goldProps); - themesMap.put("Gold-Small-Font", goldSmallFontProps); - themesMap.put("Gold-Large-Font", goldLargeFontProps); - themesMap.put("Gold-Giant-Font", goldGiantFontProps); - - themesMap.put("Green", greenProps); - themesMap.put("Green-Small-Font", greenSmallFontProps); - themesMap.put("Green-Large-Font", greenLargeFontProps); - themesMap.put("Green-Giant-Font", greenGiantFontProps); - - themesMap.put("Brown", brownProps); - themesMap.put("Brown-Small-Font", brownSmallFontProps); - themesMap.put("Brown-Large-Font", brownLargeFontProps); - themesMap.put("Brown-Giant-Font", brownGiantFontProps); - - themesMap.put("Lemmon", lemmonProps); - themesMap.put("Lemmon-Small-Font", lemmonSmallFontProps); - themesMap.put("Lemmon-Large-Font", lemmonLargeFontProps); - themesMap.put("Lemmon-Giant-Font", lemmonGiantFontProps); - - themesMap.put("Gray", grayProps); - themesMap.put("Gray-Small-Font", graySmallFontProps); - themesMap.put("Gray-Large-Font", grayLargeFontProps); - themesMap.put("Gray-Giant-Font", grayGiantFontProps); - } - - public static java.util.List getThemes() { - return themesList; - } - - public static Properties getThemeProperties(String name) { - return ((Properties) themesMap.get(name)); - } - - public static void setTheme(String name) { - setTheme((Properties) themesMap.get(name)); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - - public static void setTheme(String name, String licenseKey, String logoString) { - Properties props = (Properties) themesMap.get(name); - if (props != null) { - props.put("licenseKey", licenseKey); - props.put("logoString", logoString); - setTheme(props); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - } - - public static void setTheme(Properties themesProps) { - if (myTheme == null) { - myTheme = new SmartDefaultTheme(); - } - if ((myTheme != null) && (themesProps != null)) { - myTheme.setUpColor(); - myTheme.setProperties(themesProps); - myTheme.setUpColorArrs(); - AbstractLookAndFeel.setTheme(myTheme); - } - } - - public static void setCurrentTheme(Properties themesProps) { - setTheme(themesProps); - } - - public String getName() { - return "Smart"; - } - - public String getID() { - return "Smart"; - } - - public String getDescription() { - return "The Smart Look and Feel"; - } - - public boolean isNativeLookAndFeel() { - return false; - } - - public boolean isSupportedLookAndFeel() { - return true; - } - - public AbstractBorderFactory getBorderFactory() { - return SmartBorderFactory.getInstance(); - } - - public AbstractIconFactory getIconFactory() { - return SmartIconFactory.getInstance(); - } - - protected void createDefaultTheme() { - if (myTheme == null) { - myTheme = new SmartDefaultTheme(); - } - setTheme(myTheme); - } - - protected void initClassDefaults(UIDefaults table) { - super.initClassDefaults(table); - Object[] uiDefaults = { - // BaseLookAndFeel classes - "LabelUI", BaseLabelUI.class.getName(), - "SeparatorUI", BaseSeparatorUI.class.getName(), - "TextFieldUI", BaseTextFieldUI.class.getName(), - "TextAreaUI", BaseTextAreaUI.class.getName(), - "EditorPaneUI", BaseEditorPaneUI.class.getName(), - "PasswordFieldUI", BasePasswordFieldUI.class.getName(), - "CheckBoxUI", BaseCheckBoxUI.class.getName(), - "RadioButtonUI", BaseRadioButtonUI.class.getName(), - "SplitPaneUI", BaseSplitPaneUI.class.getName(), - "ToolTipUI", BaseToolTipUI.class.getName(), - "TreeUI", BaseTreeUI.class.getName(), - "TableUI", BaseTableUI.class.getName(), - "SliderUI", BaseSliderUI.class.getName(), - "ProgressBarUI", BaseProgressBarUI.class.getName(), - "ScrollPaneUI", BaseScrollPaneUI.class.getName(), - "PanelUI", BasePanelUI.class.getName(), - "FileChooserUI", BaseFileChooserUI.class.getName(), - "MenuBarUI", BaseMenuBarUI.class.getName(), - "MenuUI", BaseMenuUI.class.getName(), - "PopupMenuUI", BasePopupMenuUI.class.getName(), - "MenuItemUI", BaseMenuItemUI.class.getName(), - "CheckBoxMenuItemUI", BaseCheckBoxMenuItemUI.class.getName(), - "RadioButtonMenuItemUI", BaseRadioButtonMenuItemUI.class.getName(), - "PopupMenuSeparatorUI", BaseSeparatorUI.class.getName(), - "DesktopPaneUI", BaseDesktopPaneUI.class.getName(), - - // SmartLookAndFeel classes - "ButtonUI", SmartButtonUI.class.getName(), - "ToggleButtonUI", SmartToggleButtonUI.class.getName(), - "ComboBoxUI", SmartComboBoxUI.class.getName(), - "ScrollBarUI", SmartScrollBarUI.class.getName(), - "TabbedPaneUI", SmartTabbedPaneUI.class.getName(), - "TableHeaderUI", SmartTableHeaderUI.class.getName(), - "ToolBarUI", SmartToolBarUI.class.getName(), - "InternalFrameUI", SmartInternalFrameUI.class.getName(), - "RootPaneUI", SmartRootPaneUI.class.getName(),}; - table.putDefaults(uiDefaults); - if (JTattooUtilities.getJavaVersion() >= 1.5) { - table.put("FormattedTextFieldUI", BaseFormattedTextFieldUI.class.getName()); - table.put("SpinnerUI", BaseSpinnerUI.class.getName()); - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartRootPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartRootPaneUI.java deleted file mode 100644 index 2d34ae313..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartRootPaneUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.BaseRootPaneUI; -import com.jtattoo.plaf.BaseTitlePane; -import javax.swing.JComponent; -import javax.swing.JRootPane; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class SmartRootPaneUI extends BaseRootPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new SmartRootPaneUI(); - } - - public BaseTitlePane createTitlePane(JRootPane root) { - return new SmartTitlePane(root, this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartScrollBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartScrollBarUI.java deleted file mode 100644 index 74265d0ee..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartScrollBarUI.java +++ /dev/null @@ -1,64 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseScrollBarUI; -import java.awt.Graphics; -import java.awt.Rectangle; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * - * @author Michael Hagen - */ -public class SmartScrollBarUI extends BaseScrollBarUI { - - public static ComponentUI createUI(JComponent c) { - return new SmartScrollBarUI(); - } - - protected JButton createDecreaseButton(int orientation) { - return new SmartScrollButton(orientation, scrollBarWidth); - } - - protected JButton createIncreaseButton(int orientation) { - return new SmartScrollButton(orientation, scrollBarWidth); - } - - protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { - super.paintThumb(g, c, thumbBounds); - if (isRollover) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { - g.drawLine(thumbBounds.x + 1, thumbBounds.y + 1, thumbBounds.x + thumbBounds.width - 2, thumbBounds.y + 1); - g.drawLine(thumbBounds.x + 1, thumbBounds.y + 2, thumbBounds.x + thumbBounds.width - 2, thumbBounds.y + 2); - } else { - g.drawLine(thumbBounds.x + 1, thumbBounds.y + 1, thumbBounds.x + 1, thumbBounds.y + thumbBounds.height - 2); - g.drawLine(thumbBounds.x + 2, thumbBounds.y + 1, thumbBounds.x + 2, thumbBounds.y + thumbBounds.height - 2); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartScrollButton.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartScrollButton.java deleted file mode 100644 index 7079c40cf..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartScrollButton.java +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseScrollButton; -import java.awt.Graphics; - -/** - * @author Michael Hagen - */ -public class SmartScrollButton extends BaseScrollButton { - - public SmartScrollButton(int direction, int width) { - super(direction, width); - } - - public void paint(Graphics g) { - super.paint(g); - if (getModel().isRollover()) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - g.drawLine(1, 1, getWidth() - 2, 1); - g.drawLine(1, 2, getWidth() - 2, 2); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartTabbedPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartTabbedPaneUI.java deleted file mode 100644 index e010ddb0b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartTabbedPaneUI.java +++ /dev/null @@ -1,95 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseTabbedPaneUI; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; - -/** - * author Michael Hagen - */ -public class SmartTabbedPaneUI extends BaseTabbedPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new SmartTabbedPaneUI(); - } - - public void installDefaults() { - super.installDefaults(); - tabAreaInsets = new Insets(2, 6, 2, 6); - contentBorderInsets = new Insets(0, 0, 0, 0); - } - - protected Color getGapColor(int tabIndex) { - if (tabIndex == tabPane.getSelectedIndex()) { - return tabPane.getBackgroundAt(tabIndex); - } - return super.getGapColor(tabIndex); - } - - protected Font getTabFont(boolean isSelected) { - if (isSelected) { - return super.getTabFont(isSelected).deriveFont(Font.BOLD); - } else { - return super.getTabFont(isSelected); - } - } - - protected boolean hasInnerBorder() { - return true; - } - - protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) { - if (isSelected) { - g.setColor(tabPane.getBackgroundAt(tabIndex)); - if (tabPlacement == TOP) { - g.fillRect(x + 1, y + 1, w - 1, h + 2); - } else if (tabPlacement == LEFT) { - g.fillRect(x + 1, y + 1, w + 2, h - 1); - } else if (tabPlacement == BOTTOM) { - g.fillRect(x + 1, y - 2, w - 1, h + 1); - } else { - g.fillRect(x - 2, y + 1, w + 2, h - 1); - } - } else { - super.paintTabBackground(g, tabPlacement, tabIndex, x, y, w, h, isSelected); - if (!isSelected && tabIndex == rolloverIndex && tabPane.isEnabledAt(tabIndex)) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - if (tabPlacement == TOP) { - g.fillRect(x + 2, y + 1, w - 3, 2); - } else if (tabPlacement == LEFT) { - g.fillRect(x, y + 1, w - 1, 2); - } else if (tabPlacement == BOTTOM) { - g.fillRect(x + 2, y + h - 3, w - 3, 2); - } else { - g.fillRect(x, y + 1, w - 1, 2); - } - } - } - } - -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartTableHeaderUI.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartTableHeaderUI.java deleted file mode 100644 index 8b1666d67..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartTableHeaderUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.BaseTableHeaderUI; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; - -/** - * - * @author Michael Hagen - */ -public class SmartTableHeaderUI extends BaseTableHeaderUI { - - public static ComponentUI createUI(JComponent c) { - return new SmartTableHeaderUI(); - } - - protected boolean drawRolloverBar() { - return true; - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartTitlePane.java deleted file mode 100644 index 6d7d1b133..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartTitlePane.java +++ /dev/null @@ -1,147 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JDialog; -import javax.swing.JRootPane; - -/** - * @author Michael Hagen - */ -public class SmartTitlePane extends BaseTitlePane { - - public SmartTitlePane(JRootPane root, BaseRootPaneUI ui) { - super(root, ui); - } - - public void createButtons() { - iconifyButton = new BaseTitleButton(iconifyAction, ICONIFY, iconifyIcon, 1.0f); - maxButton = new BaseTitleButton(restoreAction, MAXIMIZE, maximizeIcon, 1.0f); - closeButton = new BaseTitleButton(closeAction, CLOSE, closeIcon, 1.0f); - } - - public void paintBorder(Graphics g) { - if (isActive()) { - g.setColor(AbstractLookAndFeel.getTheme().getFrameColor()); - } else { - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFrameColor(), 40)); - } - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } - - public void paintBackground(Graphics g) { - Graphics2D g2D = (Graphics2D) g; - int width = getWidth(); - int height = getHeight(); - Color backColor; - Color frameColor; - if (JTattooUtilities.isActive(this)) { - backColor = AbstractLookAndFeel.getTheme().getWindowTitleColors()[10]; - frameColor = AbstractLookAndFeel.getTheme().getFrameColor(); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 0, 0, width, height); - } else { - backColor = AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors()[10]; - frameColor = ColorHelper.brighter(AbstractLookAndFeel.getTheme().getFrameColor(), 40); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 0, 0, width, height); - } - - int iconWidth = 0; - if (menuBar != null) { - iconWidth = menuBar.getWidth() + 5; - } - - int titleWidth = 0; - String frameTitle = getTitle(); - if (frameTitle != null) { - Font f = getFont(); - g.setFont(f); - FontMetrics fm = g.getFontMetrics(); - titleWidth = fm.stringWidth(JTattooUtilities.getClippedText(getTitle(), fm, getWidth() - iconWidth - buttonsWidth - 15)) + 10; - if (getWindow() instanceof JDialog) { - Image image = getFrameIconImage(); - if (image != null) { - titleWidth += getHeight(); - } - } - } - - int dx; - int dw; - boolean leftToRight = isLeftToRight(); - int xOffset = leftToRight ? iconWidth + 10 + titleWidth : width - 10 - iconWidth - titleWidth; - - if (leftToRight) { - dw = width - buttonsWidth - xOffset - 10; - dx = xOffset; - } else { - dw = xOffset - buttonsWidth - 10; - dx = buttonsWidth + 10; - } - int dy = 3; - - if (!AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn() && (dw > 0)) { - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - - float dc1 = 50.0f; - float dc2 = 5.0f; - - Color c1 = ColorHelper.brighter(backColor, dc1); - Color c2; - while ((dy + 5) < height) { - c2 = ColorHelper.darker(backColor, dc2); - dc2 += 5.0f; - g.setColor(c1); - g.drawLine(dx, dy, dx + dw, dy); - dy++; - g.setColor(c2); - g.drawLine(dx, dy, dx + dw, dy); - dy += 3; - } - g2D.setComposite(composite); - } - g.setColor(frameColor); - g.drawLine(0, height - 1, width, height - 1); - } - - public void paintText(Graphics g, int x, int y, String title) { - x += paintIcon(g, x, y); - if (isActive()) { - Color titleColor = AbstractLookAndFeel.getWindowTitleForegroundColor(); - if (ColorHelper.getGrayValue(titleColor) > 164) { - g.setColor(Color.black); - JTattooUtilities.drawString(rootPane, g, title, x + 1, y + 1); - } - g.setColor(titleColor); - JTattooUtilities.drawString(rootPane, g, title, x, y); - } else { - g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor()); - JTattooUtilities.drawString(rootPane, g, title, x, y); - } - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartToggleButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartToggleButtonUI.java deleted file mode 100644 index b4a5c5aef..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartToggleButtonUI.java +++ /dev/null @@ -1,53 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseToggleButtonUI; -import java.awt.Graphics; -import javax.swing.AbstractButton; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class SmartToggleButtonUI extends BaseToggleButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new SmartToggleButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - super.paintBackground(g, b); - if (b.isContentAreaFilled() && b.isRolloverEnabled() && b.getModel().isRollover() && b.isBorderPainted() && (b.getBorder() != null)) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - g.drawLine(1, 1, b.getWidth() - 1, 1); - g.drawLine(1, 2, b.getWidth() - 1, 2); - g.drawLine(1, 3, b.getWidth() - 1, 3); - } - } -} - - diff --git a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartToolBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/smart/SmartToolBarUI.java deleted file mode 100644 index d8ecdee06..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/smart/SmartToolBarUI.java +++ /dev/null @@ -1,65 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.smart; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.JToolBar; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -public class SmartToolBarUI extends AbstractToolBarUI { - - public static ComponentUI createUI(JComponent c) { - return new SmartToolBarUI(); - } - - public Border getRolloverBorder() { - return SmartBorders.getRolloverToolButtonBorder(); - } - - public Border getNonRolloverBorder() { - return SmartBorders.getToolButtonBorder(); - } - - public boolean isButtonOpaque() { - return false; - } - - public void paint(Graphics g, JComponent c) { - int w = c.getWidth(); - int h = c.getHeight(); - JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getToolBarColors(), 0, 0, w, h - 2); - if ((toolBar.getOrientation() == JToolBar.HORIZONTAL) && isToolbarDecorated() && isToolBarUnderMenubar()) { - g.setColor(Color.white); - g.drawLine(0, 0, w, 0); - g.drawLine(0, h - 2, w, h - 2); - g.setColor(ColorHelper.darker(AbstractLookAndFeel.getToolbarColorDark(), 10)); - g.drawLine(0, 1, w, 1); - g.drawLine(0, h - 1, w, h - 1); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureBorderFactory.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureBorderFactory.java deleted file mode 100644 index cf853a79f..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureBorderFactory.java +++ /dev/null @@ -1,121 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.AbstractBorderFactory; -import javax.swing.border.Border; - -/** - * @author Michael Hagen - */ -public class TextureBorderFactory implements AbstractBorderFactory { - - private static TextureBorderFactory instance = null; - - private TextureBorderFactory() { - } - - public static synchronized TextureBorderFactory getInstance() { - if (instance == null) - instance = new TextureBorderFactory(); - return instance; - } - - public Border getFocusFrameBorder() { - return TextureBorders.getFocusFrameBorder(); - } - - public Border getButtonBorder() { - return TextureBorders.getButtonBorder(); - } - - public Border getToggleButtonBorder() { - return TextureBorders.getToggleButtonBorder(); - } - - public Border getTextBorder() { - return TextureBorders.getTextBorder(); - } - - public Border getSpinnerBorder() { - return TextureBorders.getSpinnerBorder(); - } - - public Border getTextFieldBorder() { - return TextureBorders.getTextFieldBorder(); - } - - public Border getComboBoxBorder() { - return TextureBorders.getComboBoxBorder(); - } - - public Border getTableHeaderBorder() { - return TextureBorders.getTableHeaderBorder(); - } - - public Border getTableScrollPaneBorder() { - return TextureBorders.getTableScrollPaneBorder(); - } - - public Border getScrollPaneBorder() { - return TextureBorders.getScrollPaneBorder(); - } - - public Border getTabbedPaneBorder() { - return TextureBorders.getTabbedPaneBorder(); - } - - public Border getMenuBarBorder() { - return TextureBorders.getMenuBarBorder(); - } - - public Border getMenuItemBorder() { - return TextureBorders.getMenuItemBorder(); - } - - public Border getPopupMenuBorder() { - return TextureBorders.getPopupMenuBorder(); - } - - public Border getInternalFrameBorder() { - return TextureBorders.getInternalFrameBorder(); - } - - public Border getPaletteBorder() { - return TextureBorders.getPaletteBorder(); - } - - public Border getToolBarBorder() { - return TextureBorders.getToolBarBorder(); - } - - public Border getProgressBarBorder() { - return TextureBorders.getProgressBarBorder(); - } - - public Border getDesktopIconBorder() { - return TextureBorders.getDesktopIconBorder(); - } -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureBorders.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureBorders.java deleted file mode 100644 index d1d15654f..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureBorders.java +++ /dev/null @@ -1,487 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.border.AbstractBorder; -import javax.swing.border.Border; -import javax.swing.plaf.UIResource; - -/** - * @author Michael Hagen - */ -public class TextureBorders extends BaseBorders { - -//------------------------------------------------------------------------------------ -// Lazy access methods -//------------------------------------------------------------------------------------ - public static Border getButtonBorder() { - if (buttonBorder == null) { - buttonBorder = new ButtonBorder(); - } - return buttonBorder; - } - - public static Border getToggleButtonBorder() { - return getButtonBorder(); - } - - public static Border getRolloverToolButtonBorder() { - if (rolloverToolButtonBorder == null) { - rolloverToolButtonBorder = new RolloverToolButtonBorder(); - } - return rolloverToolButtonBorder; - } - - public static Border getMenuItemBorder() { - if (menuItemBorder == null) { - menuItemBorder = new MenuItemBorder(); - } - return menuItemBorder; - } - - public static Border getPopupMenuBorder() { - if (popupMenuBorder == null) { - popupMenuBorder = new PopupMenuBorder(); - } - return popupMenuBorder; - } - - public static Border getInternalFrameBorder() { - if (internalFrameBorder == null) { - internalFrameBorder = new InternalFrameBorder(); - } - return internalFrameBorder; - } - - public static Border getToolBarBorder() { - if (toolBarBorder == null) { - toolBarBorder = new ToolBarBorder(); - } - return toolBarBorder; - } - -//------------------------------------------------------------------------------------ -// Inner classes -//------------------------------------------------------------------------------------ - public static class ButtonBorder implements Border, UIResource { - - private static final Color defaultColorHi = new Color(220, 230, 245); - private static final Color defaultColorMed = new Color(212, 224, 243); - private static final Color defaultColorLo = new Color(200, 215, 240); - private static final Insets insets = new Insets(3, 4, 3, 4); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Graphics2D g2D = (Graphics2D) g; - AbstractButton b = (AbstractButton) c; - Color frameColor = AbstractLookAndFeel.getTheme().getFrameColor(); - if (AbstractLookAndFeel.getTheme().doShowFocusFrame() && b.hasFocus()) { - frameColor = AbstractLookAndFeel.getTheme().getFocusFrameColor(); - } - if (!b.isEnabled()) { - frameColor = ColorHelper.brighter(frameColor, 20); - } else if (b.getModel().isRollover()) { - frameColor = ColorHelper.darker(frameColor, 20); - } - Object savedRederingHint = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - Composite saveComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - g2D.setColor(Color.white); - g2D.drawRoundRect(x, y, w - 1, h - 1, 6, 6); - g2D.setComposite(saveComposite); - - if (b.getRootPane() != null && b.equals(b.getRootPane().getDefaultButton()) && !b.hasFocus()) { - g2D.setColor(ColorHelper.darker(frameColor, 20)); - g2D.drawRoundRect(x, y, w - 1, h - 2, 6, 6); - if (!b.getModel().isRollover()) { - g2D.setColor(defaultColorHi); - g2D.drawRoundRect(x + 1, y + 1, w - 3, h - 4, 6, 6); - g2D.setColor(defaultColorMed); - g2D.drawRoundRect(x + 2, y + 2, w - 5, h - 6, 6, 6); - g2D.setColor(defaultColorLo); - g2D.drawLine(x + 3, h - 3, w - 3, h - 3); - g2D.drawLine(w - 2, y + 4, w - 2, h - 4); - } - } else { - g2D.setColor(frameColor); - g2D.drawRoundRect(x, y, w - 1, h - 2, 6, 6); - g2D.setColor(ColorHelper.brighter(frameColor, 20)); - g2D.drawLine(x + 2, y, w - 3, y); - g2D.setColor(ColorHelper.darker(frameColor, 10)); - g2D.drawLine(x + 2, h - 2, w - 3, h - 2); - } - - g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedRederingHint); - } - - public Insets getBorderInsets(Component c) { - return insets; - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class ButtonBorder - - public static class RolloverToolButtonBorder implements Border, UIResource { - - private static final Insets insets = new Insets(1, 1, 1, 1); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - AbstractButton button = (AbstractButton) c; - ButtonModel model = button.getModel(); - Color loColor = ColorHelper.brighter(AbstractLookAndFeel.getFrameColor(), 50); - if (model.isEnabled()) { - if ((model.isPressed() && model.isArmed()) || model.isSelected()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - g.setColor(loColor); - g.drawRect(x, y, w - 1, h - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.15f); - g2D.setComposite(alpha); - g.setColor(Color.black); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(composite); - } else if (model.isRollover()) { - Graphics2D g2D = (Graphics2D) g; - Composite composite = g2D.getComposite(); - g.setColor(loColor); - g.drawRect(x, y, w - 1, h - 1); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - g.setColor(Color.white); - g.fillRect(x + 1, y + 1, w - 2, h - 2); - g2D.setComposite(composite); - } - } - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return true; - } - } // class RolloverToolButtonBorder - - public static class PopupMenuBorder extends BasePopupMenuBorder { - - private static final float shadowAlpha[] = {0.6f, 0.4f, 0.2f, 0.1f}; - - public PopupMenuBorder() { - shadowSize = 4; - leftLogoInsets = new Insets(1, 18, 1, 1); - rightLogoInsets = new Insets(1, 1, 1, 18); - insets = new Insets(1, 1, 1, 1); - } - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - Graphics2D g2D = (Graphics2D) g; - Color frameColor = AbstractLookAndFeel.getFrameColor(); - g.setColor(frameColor); - if (JTattooUtilities.isLeftToRight(c)) { - int dx = getBorderInsets(c).left; - // Top - - if (hasLogo(c)) { - TextureUtils.fillComponent(g, c, x, y, dx, h - 1 - shadowSize, TextureUtils.ROLLOVER_TEXTURE_TYPE); - paintLogo(c, g, x, y, w, h); - } - g.setColor(frameColor); - if (isMenuBarPopup(c)) { - g.drawLine(x + dx, y, x + w - shadowSize - 1, y); - } else { - g.drawLine(x, y, x + w - shadowSize - 1, y); - } - // Left - g.drawLine(x, y, x, y + h - shadowSize - 1); - // Bottom - g.drawLine(x, y + h - shadowSize - 1, x + w - shadowSize - 1, y + h - shadowSize - 1); - // Right - g.drawLine(x + w - shadowSize - 1, y, x + w - shadowSize - 1, y + h - shadowSize - 1); - } else { - int dx = getBorderInsets(c).right - shadowSize; - // Top - if (hasLogo(c)) { - TextureUtils.fillComponent(g, c, x + w - dx - shadowSize, y, dx - 1, h - 1 - shadowSize, TextureUtils.ROLLOVER_TEXTURE_TYPE); - paintLogo(c, g, x, y, w, h); - } - g.setColor(frameColor); - if (isMenuBarPopup(c)) { - g.drawLine(x, y, x + w - dx - shadowSize - 1, y); - } else { - g.drawLine(x, y, x + w - shadowSize - 1, y); - } - - // Left - g.drawLine(x, y, x, y + h - shadowSize - 1); - // Bottom - g.drawLine(x, y + h - shadowSize - 1, x + w - shadowSize - 1, y + h - shadowSize - 1); - // Right - g.drawLine(x + w - shadowSize - 1, y, x + w - shadowSize - 1, y + h - shadowSize - 1); - } - - // paint the shadow - Composite savedComposite = g2D.getComposite(); - g2D.setColor(Color.black); - for (int i = 0; i < shadowSize; i++) { - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, shadowAlpha[i]); - g2D.setComposite(alpha); - // bottom - g.drawLine(x + shadowSize, y + h - shadowSize + i, x + w - shadowSize + i, y + h - shadowSize + i); - // right - g.drawLine(x + w - shadowSize + i, y + shadowSize, x + w - shadowSize + i, y + h - shadowSize - 1 + i); - } - g2D.setComposite(savedComposite); - } - } // class PopupMenuTextureBorder - - public static class MenuItemBorder extends AbstractBorder implements UIResource { - - private static final Insets insets = new Insets(2, 2, 2, 2); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - JMenuItem b = (JMenuItem) c; - ButtonModel model = b.getModel(); - Color frameColor = AbstractLookAndFeel.getFrameColor(); - if (c.getParent() instanceof JMenuBar) { - if (model.isArmed() || model.isSelected()) { - g.setColor(frameColor); - g.drawLine(x, y, x + w - 1, y); - g.drawLine(x, y, x, y + h - 1); - g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); - } - } else { - if (model.isArmed() || (c instanceof JMenu && model.isSelected())) { - g.setColor(frameColor); - g.drawLine(x, y, x + w - 1, y); - g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); - } - } - } - - public Insets getBorderInsets(Component c) { - return new Insets(insets.top, insets.left, insets.bottom, insets.right); - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - - public boolean isBorderOpaque() { - return false; - } - } // class MenuItemBorder - - public static class InternalFrameBorder extends BaseInternalFrameBorder { - - private static final Color FRAME_BORDER_COLOR = new Color(128, 128, 128); - private static final Color FRAME_COLORS[] = new Color[]{new Color(144, 144, 144), new Color(180, 180, 180), new Color(216, 216, 216), new Color(236, 236, 236), new Color(164, 164, 164), new Color(196, 196, 196), new Color(184, 184, 184), new Color(172, 172, 172)}; - - public Insets getBorderInsets(Component c) { - if (isResizable(c)) { - return new Insets(5, 8, 6, 8); - } else { - return new Insets(paletteInsets.top, paletteInsets.left, paletteInsets.bottom, paletteInsets.right); - } - } - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - boolean isJFrameBorder = false; - if (c instanceof JRootPane) { - JRootPane jp = (JRootPane) c; - if (jp.getParent() instanceof JFrame) { - isJFrameBorder = true; - } - } - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); -// if (!AbstractLookAndFeel.getTheme().isDarkTexture()) { -// if (isActive(c)) { -// g.setColor(AbstractLookAndFeel.getTheme().getWindowBorderColor()); -// } else { -// g.setColor(AbstractLookAndFeel.getTheme().getWindowInactiveBorderColor()); -// } -// g.drawRect(0, 0, w - 1, h - 1); -// if (isActive(c)) { -// g.setColor(AbstractLookAndFeel.getTheme().getWindowTitleBackgroundColor()); -// } else { -// g.setColor(AbstractLookAndFeel.getTheme().getWindowInactiveTitleBackgroundColor()); -// } -// g.drawRect(1, 1, w - 3, h - 3); -// g.drawRect(2, 2, w - 5, h - 5); -// g.drawRect(3, 3, w - 7, h - 7); -// if (isActive(c)) { -// g.setColor(AbstractLookAndFeel.getTheme().getWindowBorderColor()); -// } else { -// g.setColor(AbstractLookAndFeel.getTheme().getWindowInactiveBorderColor()); -// } -// g.drawRect(4, 4, w - 9, h - 9); -// return; -// } else - if (!isJFrameBorder) { - TextureUtils.fillComponent(g, c, 1, 1, w - 1, h - 1, TextureUtils.WINDOW_TEXTURE_TYPE); - g.setColor(AbstractLookAndFeel.getTheme().getWindowBorderColor()); - g.drawRect(0, 0, w - 1, h - 1); - } else { - Insets bi = getBorderInsets(c); - Color frameColor = AbstractLookAndFeel.getTheme().getWindowBorderColor(); - // top - g.setColor(frameColor); - g.drawLine(x, y, w, y); - TextureUtils.fillComponent(g, c, 1, 1, w, bi.top - 1, TextureUtils.WINDOW_TEXTURE_TYPE); - // bottom - g.setColor(frameColor); - g.drawLine(x, y + h - 1, w, y + h - 1); - TextureUtils.fillComponent(g, c, 1, h - bi.bottom, w, bi.bottom - 1, TextureUtils.WINDOW_TEXTURE_TYPE); - - g.setColor(FRAME_BORDER_COLOR); - g.drawLine(x, y, x, y + h); - g.drawLine(x + w - 1, y, x + w - 1, y + h); - // left - for (int i = 1; i < FRAME_COLORS.length; i++) { - g2D.setColor(FRAME_COLORS[i]); - g2D.drawLine(i, 0, i, h); - } - // right - for (int i = 0; i < FRAME_COLORS.length - 1; i++) { - g2D.setColor(FRAME_COLORS[i]); - g2D.drawLine(w - 8 + i, 0, w - 8 + i, h); - } - g.setColor(ColorHelper.brighter(FRAME_BORDER_COLOR, 20)); - g.drawLine(x, y, x + bi.left - 1, y); - g.drawLine(x + w - bi.right, y, x + w - 1, y); - - } // JFrame border - if (isResizable(c)) { - // top - float alphaValue = 0.4f; - float alphaDelta = 0.1f; - g2D.setColor(Color.white); - if (!AbstractLookAndFeel.getTheme().isDarkTexture()) { - alphaValue = 0.8f; - alphaDelta = 0.2f; - } - for (int i = 1; i < 5; i++) { - g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alphaValue)); - g2D.drawLine(1, i, w - 2, i); - alphaValue -= alphaDelta; - } - // bottom - alphaValue = 0.3f; - alphaDelta = 0.05f; - g2D.setColor(Color.black); - if (!AbstractLookAndFeel.getTheme().isDarkTexture()) { - alphaValue = 0.14f; - alphaDelta = 0.02f; - } - for (int i = 1; i < 6; i++) { - g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alphaValue)); - g2D.drawLine(1, h - i, w - 2, h - i); - alphaValue -= alphaDelta; - } - } - g2D.setComposite(savedComposite); - } - } // class InternalFrameBorder - - public static class ToolBarBorder extends AbstractBorder implements UIResource, SwingConstants { - - private static final LazyImageIcon HOR_RUBBER_ICON = new LazyImageIcon("texture/icons/HorRubber.gif"); - private static final LazyImageIcon VER_RUBBER_ICON = new LazyImageIcon("texture/icons/VerRubber.gif"); - - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - if (((JToolBar) c).isFloatable()) { - if (((JToolBar) c).getOrientation() == HORIZONTAL) { - int x1 = 4; - int y1 = (h - HOR_RUBBER_ICON.getIconHeight()) / 2; - HOR_RUBBER_ICON.paintIcon(c, g, x1, y1); - } else { - int x1 = (w - VER_RUBBER_ICON.getIconWidth()) / 2 + 2; - int y1 = 4; - VER_RUBBER_ICON.paintIcon(c, g, x1, y1); - } - } - } - - public Insets getBorderInsets(Component c) { - Insets insets = new Insets(2, 2, 2, 2); - if (((JToolBar) c).isFloatable()) { - if (((JToolBar) c).getOrientation() == HORIZONTAL) { - if (JTattooUtilities.isLeftToRight(c)) { - insets.left = 15; - } else { - insets.right = 15; - } - } else { - insets.top = 15; - } - } - Insets margin = ((JToolBar) c).getMargin(); - if (margin != null) { - insets.left += margin.left; - insets.top += margin.top; - insets.right += margin.right; - insets.bottom += margin.bottom; - } - return insets; - } - - public Insets getBorderInsets(Component c, Insets borderInsets) { - Insets insets = getBorderInsets(c); - borderInsets.left = insets.left; - borderInsets.top = insets.top; - borderInsets.right = insets.right; - borderInsets.bottom = insets.bottom; - return borderInsets; - } - } // class ToolBarBorder -} // class TextureBorders - diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureButtonUI.java deleted file mode 100644 index 62cec13c6..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureButtonUI.java +++ /dev/null @@ -1,138 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.*; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.RoundRectangle2D; -import javax.swing.*; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicGraphicsUtils; - -/** - * @author Michael Hagen - */ -public class TextureButtonUI extends BaseButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new TextureButtonUI(); - } - - protected void paintBackground(Graphics g, AbstractButton b) { - Graphics2D g2D = (Graphics2D) g; - Shape savedClip = g.getClip(); - if ((b.getBorder() != null) && b.isBorderPainted() && (b.getBorder() instanceof UIResource)) { - int w = b.getWidth(); - int h = b.getHeight(); - Area clipArea = new Area(new RoundRectangle2D.Double(0, 0, w - 1, h - 1, 6, 6)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - } - super.paintBackground(g, b); - g2D.setClip(savedClip); - } - - protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect) { - AbstractButton b = (AbstractButton)c; - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - if (!b.isContentAreaFilled()) { - if (!b.isEnabled()) { - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - } else { - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.9f); - g2D.setComposite(alpha); - } - } - super.paintIcon(g, c, iconRect); - g2D.setComposite(savedComposite); - } - - protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) { - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - ButtonModel model = b.getModel(); - FontMetrics fm = g.getFontMetrics(); - int mnemIndex; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = b.getDisplayedMnemonicIndex(); - } else { - mnemIndex = JTattooUtilities.findDisplayedMnemonicIndex(b.getText(), model.getMnemonic()); - } - - if (model.isEnabled()) { - int offs = 0; - if (model.isArmed() && model.isPressed()) { - offs = 1; - } - Color fc = b.getForeground(); - if (fc instanceof ColorUIResource) { - if (model.isPressed()) { - fc = AbstractLookAndFeel.getTheme().getPressedForegroundColor(); - } else if (b.isRolloverEnabled() && model.isRollover()) { - fc = AbstractLookAndFeel.getTheme().getRolloverForegroundColor(); - } - } - if (AbstractLookAndFeel.getTheme().isTextShadowOn() && ColorHelper.getGrayValue(fc) > 164) { - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - g.setColor(Color.black); - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x + offs, textRect.y + offs + fm.getAscent() + 1); - g2D.setComposite(savedComposite); - } - g.setColor(fc); - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x + offs, textRect.y + offs + fm.getAscent()); - } else { - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f); - g2D.setComposite(alpha); - Color fc = b.getForeground(); - if (ColorHelper.getGrayValue(fc) > 164) { - fc = ColorHelper.brighter(AbstractLookAndFeel.getDisabledForegroundColor(), 40); - g.setColor(Color.black); - } else { - fc = AbstractLookAndFeel.getDisabledForegroundColor(); - g.setColor(Color.white); - } - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x, textRect.y + 1 + fm.getAscent()); - g2D.setComposite(savedComposite); - g.setColor(fc); - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); - } - } - - protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { - if (!AbstractLookAndFeel.getTheme().doShowFocusFrame()) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - BasicGraphicsUtils.drawDashedRect(g, 3, 2, b.getWidth() - 6, b.getHeight() - 5); - BasicGraphicsUtils.drawDashedRect(g, 4, 3, b.getWidth() - 8, b.getHeight() - 7); - } - } - -} - - diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureCheckBoxMenuItemUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureCheckBoxMenuItemUI.java deleted file mode 100644 index a7742b194..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureCheckBoxMenuItemUI.java +++ /dev/null @@ -1,79 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class TextureCheckBoxMenuItemUI extends BaseCheckBoxMenuItemUI { - - public static ComponentUI createUI(JComponent c) { - return new TextureCheckBoxMenuItemUI(); - } - - protected void paintBackground(Graphics g, JComponent c, int x, int y, int w, int h) { -// if (!AbstractLookAndFeel.getTheme().isDarkTexture()) { -// super.paintBackground(g, c, x, y, w, h); -// return; -// } - JMenuItem b = (JMenuItem) c; - ButtonModel model = b.getModel(); - if (model.isArmed() || (c instanceof JMenu && model.isSelected())) { - TextureUtils.fillComponent(g, c, TextureUtils.ROLLOVER_TEXTURE_TYPE); - } else { - TextureUtils.fillComponent(g, c, TextureUtils.MENUBAR_TEXTURE_TYPE); - } - } - - protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { - if (!AbstractLookAndFeel.getTheme().isDarkTexture()) { - super.paintText(g, menuItem, textRect, text); - return; - } - ButtonModel model = menuItem.getModel(); - FontMetrics fm = menuItem.getFontMetrics(menuItem.getFont()); - int mnemIndex = menuItem.getDisplayedMnemonicIndex(); - if (!menuItem.isArmed()) { - g.setColor(Color.black); - JTattooUtilities.drawStringUnderlineCharAt(menuItem, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent() - 1); - } - if(!model.isEnabled()) { - // *** paint the text disabled - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getDisabledForegroundColor(), 40)); - } else { - // *** paint the text normally - if (menuItem.isArmed()) { - g.setColor(AbstractLookAndFeel.getMenuSelectionForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getMenuForegroundColor()); - } - } - JTattooUtilities.drawStringUnderlineCharAt(menuItem, g,text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureCheckBoxUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureCheckBoxUI.java deleted file mode 100644 index 3559c0569..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureCheckBoxUI.java +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class TextureCheckBoxUI extends TextureRadioButtonUI { - - private static TextureCheckBoxUI checkBoxUI = null; - - public static ComponentUI createUI(JComponent b) { - if (checkBoxUI == null) { - checkBoxUI = new TextureCheckBoxUI(); - } - return checkBoxUI; - } - - public void installDefaults(AbstractButton b) { - super.installDefaults(b); - icon = UIManager.getIcon("CheckBox.icon"); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureComboBoxUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureComboBoxUI.java deleted file mode 100644 index 196b48687..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureComboBoxUI.java +++ /dev/null @@ -1,109 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.*; -import com.jtattoo.plaf.luna.LunaIcons; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -public class TextureComboBoxUI extends BaseComboBoxUI { - - public static ComponentUI createUI(JComponent c) { - return new TextureComboBoxUI(); - } - - public JButton createArrowButton() { - return new ArrowButton(); - } - - protected void setButtonBorder() { - } - -//-------------------------------------------------------------------------------------------------- - static class ArrowButton extends NoFocusButton { - - public ArrowButton() { - setBorder(BorderFactory.createEmptyBorder()); - setBorderPainted(false); - setContentAreaFilled(false); - } - - public void paint(Graphics g) { - Graphics2D g2D = (Graphics2D) g; - - boolean isPressed = getModel().isPressed(); - boolean isRollover = getModel().isRollover(); - - int width = getWidth(); - int height = getHeight(); - - Color[] tc = AbstractLookAndFeel.getTheme().getThumbColors(); - Color c1 = tc[0]; - Color c2 = tc[tc.length - 1]; - if (isPressed) { - c1 = ColorHelper.darker(c1, 5); - c2 = ColorHelper.darker(c2, 5); - } else if (isRollover) { - c1 = ColorHelper.brighter(c1, 20); - c2 = ColorHelper.brighter(c2, 20); - } - - g2D.setPaint(new GradientPaint(0, 0, c1, width, height, c2)); - g2D.fillRect(0, 0, width, height); - g2D.setPaint(null); - g2D.setColor(Color.white); - if (JTattooUtilities.isLeftToRight(this)) { - g2D.drawRect(1, 0, width - 2, height - 1); - } else { - g2D.drawRect(0, 0, width - 2, height - 1); - } - - Composite composite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - g2D.setColor(c2); - if (JTattooUtilities.isLeftToRight(this)) { - g.drawLine(2, 1, width - 2, 1); - g.drawLine(2, 2, 2, height - 2); - } else { - g.drawLine(1, 1, width - 3, 1); - g.drawLine(1, 2, 1, height - 2); - } - g2D.setComposite(composite); - - // paint the icon - Icon icon = LunaIcons.getComboBoxIcon(); - int x = (width - icon.getIconWidth()) / 2; - int y = (height - icon.getIconHeight()) / 2; - int dx = (JTattooUtilities.isLeftToRight(this)) ? 0 : -1; - if (getModel().isPressed() && getModel().isArmed()) { - icon.paintIcon(this, g, x + dx + 2, y + 1); - } else { - icon.paintIcon(this, g, x + dx + 1, y); - } - } - } // end class ArrowButton -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureDefaultTheme.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureDefaultTheme.java deleted file mode 100644 index c86c88b75..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureDefaultTheme.java +++ /dev/null @@ -1,194 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.AbstractTheme; -import com.jtattoo.plaf.ColorHelper; -import java.awt.Color; -import java.awt.Font; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.FontUIResource; - -public class TextureDefaultTheme extends AbstractTheme { - - public TextureDefaultTheme() { - super(); - // Setup theme with defaults - setUpColor(); - // Overwrite defaults with user props - loadProperties(); - // Setup the color arrays - setUpColorArrs(); - } - - public String getPropertyFileName() { - return "TextureTheme.properties"; - } - - public void setUpColor() { - super.setUpColor(); - - menuOpaque = false; - menuAlpha = 1.0f; - showFocusFrame = true; - textShadow = true; - - foregroundColor = black; - backgroundColor = new ColorUIResource(242, 232, 220); - backgroundColorLight = new ColorUIResource(224, 215, 205); - backgroundColorDark = new ColorUIResource(197, 184, 168); - - alterBackgroundColor = new ColorUIResource(219, 206, 189); - disabledForegroundColor = new ColorUIResource(114, 94, 80); - disabledBackgroundColor = new ColorUIResource(244, 242, 232); - inputBackgroundColor = white; - inputForegroundColor = black; - - selectionForegroundColor = black; - selectionBackgroundColor = new ColorUIResource(200, 215, 240); - selectionBackgroundColorLight = new ColorUIResource(128, 128, 128); - selectionBackgroundColorDark = new ColorUIResource(64, 64, 64); - - focusColor = orange; - focusCellColor = orange; - frameColor = new ColorUIResource(172, 162, 145); - gridColor = new ColorUIResource(204, 197, 183); - - rolloverColor = new ColorUIResource(176, 163, 138); - rolloverColorLight = new ColorUIResource(226, 222, 214); - rolloverColorDark = new ColorUIResource(208, 200, 185); - - buttonForegroundColor = black; - buttonBackgroundColor = extraLightGray; - buttonColorLight = new ColorUIResource(247, 244, 239); - buttonColorDark = new ColorUIResource(219, 216, 211); - - controlForegroundColor = black; - controlBackgroundColor = new ColorUIResource(240, 230, 217); - controlHighlightColor = white; - controlShadowColor = new ColorUIResource(172, 162, 145); - controlDarkShadowColor = new ColorUIResource(100, 80, 60); - controlColorLight = new ColorUIResource(239, 230, 221); - controlColorDark = new ColorUIResource(220, 207, 192); - - windowTitleForegroundColor = white; - windowTitleBackgroundColor = new ColorUIResource(200, 215, 240); - windowTitleColorLight = new ColorUIResource(96, 96, 96); - windowTitleColorDark = new ColorUIResource(48, 48, 48); - windowBorderColor = black; - windowIconColor = white; - windowIconShadowColor = black; - windowIconRolloverColor = orange; - - windowInactiveTitleForegroundColor = white; - windowInactiveTitleBackgroundColor = new ColorUIResource(242, 232, 220); - windowInactiveTitleColorLight = new ColorUIResource(96, 96, 96); - windowInactiveTitleColorDark = new ColorUIResource(48, 48, 48); - windowInactiveBorderColor = black; - - menuForegroundColor = white; - menuBackgroundColor = new ColorUIResource(240, 240, 240); - menuSelectionForegroundColor = black; - menuSelectionBackgroundColor = new ColorUIResource(32, 32, 32); - menuSelectionBackgroundColorLight = new ColorUIResource(255, 213, 113); - menuSelectionBackgroundColorDark = new ColorUIResource(240, 168, 0); - menuColorLight = new ColorUIResource(240, 240, 240); - menuColorDark = new ColorUIResource(220, 220, 220); - - toolbarForegroundColor = white; - toolbarBackgroundColor = new ColorUIResource(52, 52, 52); - toolbarColorLight = menuColorLight; - toolbarColorDark = menuColorDark; - - tabAreaBackgroundColor = backgroundColor; - tabSelectionForegroundColor = white; - - desktopColor = new ColorUIResource(220, 207, 192); - tooltipForegroundColor = black; - tooltipBackgroundColor = new ColorUIResource(244, 235, 228); - - controlFont = new FontUIResource("Dialog", Font.PLAIN, 13); - systemFont = new FontUIResource("Dialog", Font.PLAIN, 13); - userFont = new FontUIResource("Dialog", Font.PLAIN, 13); - smallFont = new FontUIResource("Dialog", Font.PLAIN, 12); - menuFont = new FontUIResource("Dialog", Font.PLAIN, 13); - windowTitleFont = new FontUIResource("Dialog", Font.BOLD, 13); - } - - public void setUpColorArrs() { - super.setUpColorArrs(); - - Color topHi = white; - Color topLo = buttonColorLight; - Color bottomHi = ColorHelper.brighter(buttonColorDark, 40); - Color bottomLo = buttonColorDark; - Color topColors[] = ColorHelper.createColorArr(topHi, topLo, 11); - Color bottomColors[] = ColorHelper.createColorArr(bottomHi, bottomLo, 13); - BUTTON_COLORS = new Color[24]; - System.arraycopy(topColors, 0, BUTTON_COLORS, 0, 11); - System.arraycopy(bottomColors, 0, BUTTON_COLORS, 11, 13); - CHECKBOX_COLORS = BUTTON_COLORS; - - DEFAULT_COLORS = ColorHelper.createColorArr(controlColorLight, controlColorDark, 24); - HIDEFAULT_COLORS = new Color[20]; - for (int i = 0; i < 20; i++) { - HIDEFAULT_COLORS[i] = ColorHelper.brighter(DEFAULT_COLORS[i], 40); - } - SELECTED_COLORS = ColorHelper.createColorArr(selectionBackgroundColorLight, selectionBackgroundColorDark, 20); - SELECTION_COLORS = SELECTED_COLORS;//ColorHelper.createColorArr(selectionBackgroundColorLight, selectionBackgroundColorDark, 20); - MENU_SELECTION_COLORS = ColorHelper.createColorArr(menuSelectionBackgroundColorLight, menuSelectionBackgroundColorDark, 20); - - topHi = rolloverColorLight; - topLo = rolloverColorDark; - bottomHi = ColorHelper.darker(rolloverColorDark, 6); - bottomLo = ColorHelper.darker(rolloverColorDark, 10); - topColors = ColorHelper.createColorArr(topHi, topLo, 11); - bottomColors = ColorHelper.createColorArr(bottomHi, bottomLo, 13); - ROLLOVER_COLORS = new Color[24]; - System.arraycopy(topColors, 0, ROLLOVER_COLORS, 0, 11); - System.arraycopy(bottomColors, 0, ROLLOVER_COLORS, 11, 13); - PRESSED_COLORS = ColorHelper.createColorArr(buttonColorDark, buttonColorLight, 24); - DISABLED_COLORS = ColorHelper.createColorArr(superLightGray, extraLightGray, 24); - ACTIVE_COLORS = DEFAULT_COLORS; - INACTIVE_COLORS = BUTTON_COLORS; - - WINDOW_TITLE_COLORS = ColorHelper.createColorArr(windowTitleColorLight, windowTitleColorDark, 24); - WINDOW_INACTIVE_TITLE_COLORS = ColorHelper.createColorArr(windowInactiveTitleColorLight, windowInactiveTitleColorDark, 24); - - TOOLBAR_COLORS = ColorHelper.createColorArr(toolbarColorLight, toolbarColorDark, 24); - MENUBAR_COLORS = ColorHelper.createColorArr(menuColorLight, menuColorDark, 24); - - TAB_COLORS = BUTTON_COLORS;//ColorHelper.createColorArr(controlColorLight, controlColorDark, 24); - COL_HEADER_COLORS = BUTTON_COLORS; - - THUMB_COLORS = ColorHelper.createColorArr(backgroundColorLight, backgroundColorDark, 24); - Color hiColor = ColorHelper.brighter(backgroundColor, 30); - Color loColor = ColorHelper.brighter(backgroundColor, 10); - TRACK_COLORS = ColorHelper.createColorArr(loColor, hiColor, 24); - - SLIDER_COLORS = THUMB_COLORS; - PROGRESSBAR_COLORS = SLIDER_COLORS; - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureIconFactory.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureIconFactory.java deleted file mode 100644 index 3b0b3416b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureIconFactory.java +++ /dev/null @@ -1,213 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.AbstractIconFactory; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class TextureIconFactory implements AbstractIconFactory { - - private static TextureIconFactory instance = null; - - private TextureIconFactory() { - } - - public static synchronized TextureIconFactory getInstance() { - if (instance == null) { - instance = new TextureIconFactory(); - } - return instance; - } - - public Icon getOptionPaneErrorIcon() { - return TextureIcons.getOptionPaneErrorIcon(); - } - - public Icon getOptionPaneWarningIcon() { - return TextureIcons.getOptionPaneWarningIcon(); - } - - public Icon getOptionPaneInformationIcon() { - return TextureIcons.getOptionPaneInformationIcon(); - } - - public Icon getOptionPaneQuestionIcon() { - return TextureIcons.getOptionPaneQuestionIcon(); - } - - public Icon getFileChooserDetailViewIcon() { - return TextureIcons.getFileChooserDetailViewIcon(); - } - - public Icon getFileChooserHomeFolderIcon() { - return TextureIcons.getFileChooserHomeFolderIcon(); - } - - public Icon getFileChooserListViewIcon() { - return TextureIcons.getFileChooserListViewIcon(); - } - - public Icon getFileChooserNewFolderIcon() { - return TextureIcons.getFileChooserNewFolderIcon(); - } - - public Icon getFileChooserUpFolderIcon() { - return TextureIcons.getFileChooserUpFolderIcon(); - } - - public Icon getMenuIcon() { - return TextureIcons.getMenuIcon(); - } - - public Icon getIconIcon() { - return TextureIcons.getIconIcon(); - } - - public Icon getMaxIcon() { - return TextureIcons.getMaxIcon(); - } - - public Icon getMinIcon() { - return TextureIcons.getMinIcon(); - } - - public Icon getCloseIcon() { - return TextureIcons.getCloseIcon(); - } - - public Icon getPaletteCloseIcon() { - return TextureIcons.getPaletteCloseIcon(); - } - - public Icon getRadioButtonIcon() { - return TextureIcons.getRadioButtonIcon(); - } - - public Icon getCheckBoxIcon() { - return TextureIcons.getCheckBoxIcon(); - } - - public Icon getComboBoxIcon() { - return TextureIcons.getComboBoxIcon(); - } - - public Icon getTreeComputerIcon() { - return TextureIcons.getTreeComputerIcon(); - } - - public Icon getTreeFloppyDriveIcon() { - return TextureIcons.getTreeFloppyDriveIcon(); - } - - public Icon getTreeHardDriveIcon() { - return TextureIcons.getTreeHardDriveIcon(); - } - - public Icon getTreeFolderIcon() { - return TextureIcons.getTreeFolderIcon(); - } - - public Icon getTreeLeafIcon() { - return TextureIcons.getTreeLeafIcon(); - } - - public Icon getTreeCollapsedIcon() { - return TextureIcons.getTreeControlIcon(true); - } - - public Icon getTreeExpandedIcon() { - return TextureIcons.getTreeControlIcon(false); - } - - public Icon getMenuArrowIcon() { - return TextureIcons.getMenuArrowIcon(); - } - - public Icon getMenuCheckBoxIcon() { - return TextureIcons.getMenuCheckBoxIcon(); - } - - public Icon getMenuRadioButtonIcon() { - return TextureIcons.getMenuRadioButtonIcon(); - } - - public Icon getUpArrowIcon() { - return TextureIcons.getUpArrowIcon(); - } - - public Icon getDownArrowIcon() { - return TextureIcons.getDownArrowIcon(); - } - - public Icon getLeftArrowIcon() { - return TextureIcons.getLeftArrowIcon(); - } - - public Icon getRightArrowIcon() { - return TextureIcons.getRightArrowIcon(); - } - - public Icon getSplitterDownArrowIcon() { - return TextureIcons.getSplitterDownArrowIcon(); - } - - public Icon getSplitterHorBumpIcon() { - return TextureIcons.getSplitterHorBumpIcon(); - } - - public Icon getSplitterLeftArrowIcon() { - return TextureIcons.getSplitterLeftArrowIcon(); - } - - public Icon getSplitterRightArrowIcon() { - return TextureIcons.getSplitterRightArrowIcon(); - } - - public Icon getSplitterUpArrowIcon() { - return TextureIcons.getSplitterUpArrowIcon(); - } - - public Icon getSplitterVerBumpIcon() { - return TextureIcons.getSplitterVerBumpIcon(); - } - - public Icon getThumbHorIcon() { - return TextureIcons.getThumbHorIcon(); - } - - public Icon getThumbVerIcon() { - return TextureIcons.getThumbVerIcon(); - } - - public Icon getThumbHorIconRollover() { - return TextureIcons.getThumbHorIconRollover(); - } - - public Icon getThumbVerIconRollover() { - return TextureIcons.getThumbVerIconRollover(); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureIcons.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureIcons.java deleted file mode 100644 index b50071c09..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureIcons.java +++ /dev/null @@ -1,162 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.*; -import java.awt.Color; -import java.awt.Insets; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class TextureIcons extends BaseIcons { - - public static void setUp() { - iconIcon = null; - maxIcon = null; - minIcon = null; - closeIcon = null; - splitterHorBumpIcon = null; - splitterVerBumpIcon = null; - thumbHorIcon = null; - thumbVerIcon = null; - thumbHorIconRollover = null; - thumbVerIconRollover = null; - } - - public static Icon getIconIcon() { - if (iconIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - iconIcon = new MacIconIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - iconIcon = new BaseIcons.IconSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(1, 1, 1, 1)); - } - } - return iconIcon; - } - - public static Icon getMinIcon() { - if (minIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - minIcon = new MacMinIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - minIcon = new BaseIcons.MinSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(1, 1, 1, 1)); - } - } - return minIcon; - } - - public static Icon getMaxIcon() { - if (maxIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - maxIcon = new MacMaxIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - maxIcon = new BaseIcons.MaxSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(1, 1, 1, 1)); - } - } - return maxIcon; - } - - public static Icon getCloseIcon() { - if (closeIcon == null) { - if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) { - closeIcon = new MacCloseIcon(); - } else { - Color iconColor = AbstractLookAndFeel.getTheme().getWindowIconColor(); - Color iconShadowColor = AbstractLookAndFeel.getTheme().getWindowIconShadowColor(); - Color iconRolloverColor = AbstractLookAndFeel.getTheme().getWindowIconRolloverColor(); - closeIcon = new BaseIcons.CloseSymbol(iconColor, iconShadowColor, iconRolloverColor, new Insets(1, 1, 1, 1)); - } - } - return closeIcon; - } - - public static Icon getSplitterHorBumpIcon() { - if (splitterHorBumpIcon == null) { - splitterHorBumpIcon = new LazyImageIcon("texture/icons/SplitterHorBumps.gif"); - } - return splitterHorBumpIcon; - } - - public static Icon getSplitterVerBumpIcon() { - if (splitterVerBumpIcon == null) { - splitterVerBumpIcon = new LazyImageIcon("texture/icons/SplitterVerBumps.gif"); - } - return splitterVerBumpIcon; - } - - public static Icon getThumbHorIcon() { - if ("Default".equals(AbstractLookAndFeel.getTheme().getName())) { - if (thumbHorIcon == null) { - thumbHorIcon = new LazyImageIcon("texture/icons/thumb_hor.gif"); - } - return thumbHorIcon; - } else { - return BaseIcons.getThumbHorIcon(); - } - } - - public static Icon getThumbVerIcon() { - if ("Default".equals(AbstractLookAndFeel.getTheme().getName())) { - if (thumbVerIcon == null) { - thumbVerIcon = new LazyImageIcon("texture/icons/thumb_ver.gif"); - } - return thumbVerIcon; - } else { - return BaseIcons.getThumbVerIcon(); - } - } - - public static Icon getThumbHorIconRollover() { - if ("Default".equals(AbstractLookAndFeel.getTheme().getName())) { - if (thumbHorIconRollover == null) { - thumbHorIconRollover = new LazyImageIcon("texture/icons/thumb_hor_rollover.gif"); - } - return thumbHorIconRollover; - } else { - return BaseIcons.getThumbHorIconRollover(); - } - } - - public static Icon getThumbVerIconRollover() { - if ("Default".equals(AbstractLookAndFeel.getTheme().getName())) { - if (thumbVerIconRollover == null) { - thumbVerIconRollover = new LazyImageIcon("texture/icons/thumb_ver_rollover.gif"); - } - return thumbVerIconRollover; - } else { - return BaseIcons.getThumbVerIconRollover(); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureInternalFrameTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureInternalFrameTitlePane.java deleted file mode 100644 index 2372dafd5..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureInternalFrameTitlePane.java +++ /dev/null @@ -1,90 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.*; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.Rectangle2D; -import javax.swing.JInternalFrame; - -/** - * @author Michael Hagen - */ -public class TextureInternalFrameTitlePane extends BaseInternalFrameTitlePane { - - public TextureInternalFrameTitlePane(JInternalFrame f) { - super(f); - } - - protected int getHorSpacing() { - return AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn() ? 1 : 0; - } - - protected int getVerSpacing() { - return AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn() ? 3 : 0; - } - - protected boolean centerButtons() { - return false; - } - - public void paintPalette(Graphics g) { - TextureUtils.fillComponent(g, this, TextureUtils.WINDOW_TEXTURE_TYPE); - } - - public void paintBackground(Graphics g) { - TextureUtils.fillComponent(g, this, TextureUtils.WINDOW_TEXTURE_TYPE); - } - - public void paintBorder(Graphics g) { - } - - public void paintText(Graphics g, int x, int y, String title) { - if (isMacStyleWindowDecoration()) { - x += paintIcon(g, x, y) + 5; - } - Graphics2D g2D = (Graphics2D)g; - Shape savedClip = g2D.getClip(); - Color fc = AbstractLookAndFeel.getWindowTitleForegroundColor(); - if (fc.equals(Color.white)) { - Color bc = AbstractLookAndFeel.getWindowTitleColorDark(); - g2D.setColor(bc); - JTattooUtilities.drawString(frame, g, title, x-1, y-1); - g2D.setColor(ColorHelper.darker(bc, 30)); - JTattooUtilities.drawString(frame, g, title, x+1, y+1); - } - g.setColor(fc); - JTattooUtilities.drawString(frame, g, title, x, y); - - Area clipArea = new Area(new Rectangle2D.Double(x, (getHeight() / 2), getWidth(), getHeight())); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - g.setColor(ColorHelper.darker(fc, 20)); - JTattooUtilities.drawString(frame, g, title, x, y); - - g2D.setClip(savedClip); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureInternalFrameUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureInternalFrameUI.java deleted file mode 100644 index 58d246244..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureInternalFrameUI.java +++ /dev/null @@ -1,50 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.BaseInternalFrameUI; -import javax.swing.JComponent; -import javax.swing.JInternalFrame; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class TextureInternalFrameUI extends BaseInternalFrameUI { - - public TextureInternalFrameUI(JInternalFrame b) { - super(b); - } - - public static ComponentUI createUI(JComponent c) { - return new TextureInternalFrameUI((JInternalFrame)c); - } - - protected JComponent createNorthPane(JInternalFrame w) { - titlePane = new TextureInternalFrameTitlePane(w); - return titlePane; - } - -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureLabelUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureLabelUI.java deleted file mode 100644 index a18be44b4..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureLabelUI.java +++ /dev/null @@ -1,88 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicLabelUI; - -/** - * @author Michael Hagen - */ -public class TextureLabelUI extends BasicLabelUI { - - private static TextureLabelUI hifiLabelUI = null; - - public static ComponentUI createUI(JComponent c) { - if (hifiLabelUI == null) { - hifiLabelUI = new TextureLabelUI(); - } - return hifiLabelUI; - } - - protected void paintEnabledText(JLabel l, Graphics g, String s, int textX, int textY) { - int mnemIndex; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = l.getDisplayedMnemonicIndex(); - } else { - mnemIndex = JTattooUtilities.findDisplayedMnemonicIndex(l.getText(), l.getDisplayedMnemonic()); - } - Color fc = l.getForeground(); - if (AbstractLookAndFeel.getTheme().isTextShadowOn() && ColorHelper.getGrayValue(fc) > 164) { - g.setColor(Color.black); - JTattooUtilities.drawStringUnderlineCharAt(l, g, s, mnemIndex, textX, textY + 1); - } - g.setColor(fc); - JTattooUtilities.drawStringUnderlineCharAt(l, g, s, mnemIndex, textX, textY); - } - - protected void paintDisabledText(JLabel l, Graphics g, String s, int textX, int textY) { - int mnemIndex; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = l.getDisplayedMnemonicIndex(); - } else { - mnemIndex = JTattooUtilities.findDisplayedMnemonicIndex(l.getText(), l.getDisplayedMnemonic()); - } - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f); - g2D.setComposite(alpha); - Color fc = l.getForeground(); - if (ColorHelper.getGrayValue(fc) > 164) { - fc = ColorHelper.brighter(AbstractLookAndFeel.getDisabledForegroundColor(), 40); - g.setColor(Color.black); - } else { - fc = AbstractLookAndFeel.getDisabledForegroundColor(); - g.setColor(Color.white); - } - JTattooUtilities.drawStringUnderlineCharAt(l, g, s, mnemIndex, textX, textY + 1); - g2D.setComposite(savedComposite); - g.setColor(fc); - JTattooUtilities.drawStringUnderlineCharAt(l, g, s, mnemIndex, textX, textY); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureLookAndFeel.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureLookAndFeel.java deleted file mode 100644 index 1cda7b8df..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureLookAndFeel.java +++ /dev/null @@ -1,461 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.*; -import java.util.*; -import javax.swing.UIDefaults; -import javax.swing.plaf.InsetsUIResource; - -/** - * @author Michael Hagen - */ -public class TextureLookAndFeel extends AbstractLookAndFeel { - - private static TextureDefaultTheme myTheme = null; - private static final ArrayList themesList = new ArrayList(); - private static final HashMap themesMap = new HashMap(); - private static final Properties defaultProps = new Properties(); - private static final Properties smallFontProps = new Properties(); - private static final Properties mediumFontProps = new Properties(); - private static final Properties largeFontProps = new Properties(); - private static final Properties rockProps = new Properties(); - private static final Properties rockSmallFontProps = new Properties(); - private static final Properties rockMediumFontProps = new Properties(); - private static final Properties rockLargeFontProps = new Properties(); - private static final Properties textileProps = new Properties(); - private static final Properties textileSmallFontProps = new Properties(); - private static final Properties textileMediumFontProps = new Properties(); - private static final Properties textileLargeFontProps = new Properties(); - private static final Properties snowProps = new Properties(); - private static final Properties snowSmallFontProps = new Properties(); - private static final Properties snowMediumFontProps = new Properties(); - private static final Properties snowLargeFontProps = new Properties(); - - static { - smallFontProps.setProperty("controlTextFont", "Dialog 12"); - smallFontProps.setProperty("systemTextFont", "Dialog 12"); - smallFontProps.setProperty("userTextFont", "Dialog 12"); - smallFontProps.setProperty("menuTextFont", "Dialog 12"); - smallFontProps.setProperty("windowTitleFont", "Dialog bold 12"); - smallFontProps.setProperty("subTextFont", "Dialog 11"); - - mediumFontProps.setProperty("controlTextFont", "Dialog 15"); - mediumFontProps.setProperty("systemTextFont", "Dialog 15"); - mediumFontProps.setProperty("userTextFont", "Dialog 15"); - mediumFontProps.setProperty("menuTextFont", "Dialog 15"); - mediumFontProps.setProperty("windowTitleFont", "Dialog bold 15"); - mediumFontProps.setProperty("subTextFont", "Dialog 13"); - - largeFontProps.setProperty("controlTextFont", "Dialog 16"); - largeFontProps.setProperty("systemTextFont", "Dialog 16"); - largeFontProps.setProperty("userTextFont", "Dialog 16"); - largeFontProps.setProperty("menuTextFont", "Dialog 16"); - largeFontProps.setProperty("windowTitleFont", "Dialog bold 16"); - largeFontProps.setProperty("subTextFont", "Dialog 14"); - - rockProps.setProperty("textureSet", "Rock"); - rockProps.setProperty("backgroundColor", "240 240 240"); - rockProps.setProperty("backgroundColorLight", "220 220 220"); - rockProps.setProperty("backgroundColorDark", "200 200 200"); - rockProps.setProperty("alterBackgroundColor", "180 180 180"); - - rockProps.setProperty("frameColor", "164 164 164"); - rockProps.setProperty("gridColor", "196 196 196"); - - rockProps.setProperty("disabledForegroundColor", "96 96 96"); - rockProps.setProperty("disabledBackgroundColor", "240 240 240"); - - rockProps.setProperty("rolloverColor", "160 160 160"); - rockProps.setProperty("rolloverColorLight", "230 230 230"); - rockProps.setProperty("rolloverColorDark", "210 210 210"); - - rockProps.setProperty("controlBackgroundColor", "248 248 248"); - rockProps.setProperty("controlShadowColor", "160 160 160"); - rockProps.setProperty("controlDarkShadowColor", "110 110 110"); - rockProps.setProperty("controlColorLight", "248 248 248"); - rockProps.setProperty("controlColorDark", " 210 210 210"); - - rockProps.setProperty("buttonColorLight", "255 255 255"); - rockProps.setProperty("buttonColorDark", "230 230 230"); - - rockProps.setProperty("menuBackgroundColor", "64 64 64"); - rockProps.setProperty("menuColorLight", "96 96 96"); - rockProps.setProperty("menuColorDark", "48 48 48"); - rockProps.setProperty("menuSelectionBackgroundColor", "48 48 48"); - rockProps.setProperty("toolbarBackgroundColor", "64 64 64"); - rockProps.setProperty("toolbarColorLight", "96 96 96"); - rockProps.setProperty("toolbarColorDark", "48 48 48"); - rockProps.setProperty("desktopColor", "220 220 220"); - rockProps.setProperty("tooltipBackgroundColor", "248 248 248"); - - textileProps.setProperty("textureSet", "Textile"); - textileProps.setProperty("backgroundColor", "240 240 240"); - textileProps.setProperty("backgroundColorLight", "184 194 218"); - textileProps.setProperty("backgroundColorDark", "152 168 201"); - textileProps.setProperty("alterBackgroundColor", "180 180 180"); - - textileProps.setProperty("frameColor", "164 164 164"); - textileProps.setProperty("gridColor", "196 196 196"); - - textileProps.setProperty("disabledForegroundColor", "96 96 96"); - textileProps.setProperty("disabledBackgroundColor", "240 240 240"); - - textileProps.setProperty("selectionForegroundColor", "0 0 0"); - textileProps.setProperty("selectionBackgroundColor", "184 194 218"); - textileProps.setProperty("selectionBackgroundColorLight", "184 194 218"); - textileProps.setProperty("selectionBackgroundColorDark", "112 134 180"); - - textileProps.setProperty("rolloverForegroundColor", "255 255 255"); - textileProps.setProperty("rolloverColor", "132 148 176"); - textileProps.setProperty("rolloverColorLight", "184 194 218"); - textileProps.setProperty("rolloverColorDark", "152 168 201"); - - textileProps.setProperty("controlBackgroundColor", "248 248 248"); - textileProps.setProperty("controlShadowColor", "160 160 160"); - textileProps.setProperty("controlDarkShadowColor", "160 160 160"); - textileProps.setProperty("controlColorLight", "240 240 240"); - textileProps.setProperty("controlColorDark", " 210 210 210"); - - textileProps.setProperty("pressedForegroundColor", "0 0 0"); - textileProps.setProperty("buttonColorLight", "255 255 255"); - textileProps.setProperty("buttonColorDark", "230 230 230"); - - textileProps.setProperty("windowBorderColor", "27 42 111"); - textileProps.setProperty("windowTitleBackgroundColor", "40 54 114"); - textileProps.setProperty("windowTitleColorLight", "80 112 162"); - textileProps.setProperty("windowTitleColorDark", "44 59 126"); - - textileProps.setProperty("menuForegroundColor", "215 221 234"); - textileProps.setProperty("menuBackgroundColor", "64 64 64"); - textileProps.setProperty("menuColorLight", "96 96 96"); - textileProps.setProperty("menuColorDark", "48 48 48"); - textileProps.setProperty("menuSelectionForegroundColor", "255 255 255"); - textileProps.setProperty("menuSelectionBackgroundColor", "48 48 48"); - - textileProps.setProperty("toolbarBackgroundColor", "64 78 102"); - textileProps.setProperty("toolbarColorLight", "76 91 120"); - textileProps.setProperty("toolbarColorDark", "64 78 102"); - - textileProps.setProperty("desktopColor", "152 168 201"); - textileProps.setProperty("tooltipBackgroundColor", "255 255 220"); - - snowProps.setProperty("textureSet", "Snow"); - snowProps.setProperty("darkTexture", "off"); - snowProps.setProperty("backgroundColor", "240 240 240"); - snowProps.setProperty("backgroundColorLight", "225 234 247"); - snowProps.setProperty("backgroundColorDark", "188 206 237"); - snowProps.setProperty("alterBackgroundColor", "180 180 180"); - - snowProps.setProperty("selectionBackgroundColorLight", "225 234 247"); - snowProps.setProperty("selectionBackgroundColorDark", "188 206 237"); - - snowProps.setProperty("frameColor", "164 164 164"); - snowProps.setProperty("gridColor", "196 196 196"); - - snowProps.setProperty("disabledForegroundColor", "96 96 96"); - snowProps.setProperty("disabledBackgroundColor", "240 240 240"); - - snowProps.setProperty("rolloverColor", "225 234 247"); - snowProps.setProperty("rolloverColorLight", "245 248 252"); - snowProps.setProperty("rolloverColorDark", "225 234 247"); - - snowProps.setProperty("controlBackgroundColor", "248 248 248"); - snowProps.setProperty("controlShadowColor", "160 160 160"); - snowProps.setProperty("controlDarkShadowColor", "180 180 180"); - snowProps.setProperty("controlColorLight", "240 240 240"); - snowProps.setProperty("controlColorDark", " 210 210 210"); - - snowProps.setProperty("buttonColorLight", "255 255 255"); - snowProps.setProperty("buttonColorDark", "230 230 230"); - - snowProps.setProperty("windowTitleForegroundColor", "48 64 96"); - snowProps.setProperty("windowTitleBackgroundColor", "200 215 240"); - snowProps.setProperty("windowTitleColorLight", "250 250 250"); - snowProps.setProperty("windowTitleColorDark", "230 230 230"); - snowProps.setProperty("windowBorderColor", "160 160 160"); - snowProps.setProperty("windowIconColor", "48 64 96"); - snowProps.setProperty("windowIconShadowColor", "255 255 255"); - snowProps.setProperty("windowIconRolloverColor", "200 0 0"); - - snowProps.setProperty("windowInactiveTitleForegroundColor", "48 64 96"); - snowProps.setProperty("windowInactiveTitleBackgroundColor", "240 240 240"); - snowProps.setProperty("windowInactiveTitleColorLight", "250 250 250"); - snowProps.setProperty("windowInactiveTitleColorDark", "230 230 230"); - snowProps.setProperty("windowInactiveBorderColor", "180 180 180"); - - snowProps.setProperty("menuForegroundColor", "0 0 0"); - snowProps.setProperty("menuBackgroundColor", "250 250 250"); - snowProps.setProperty("menuColorLight", "250 250 250"); - snowProps.setProperty("menuColorDark", "230 230 230"); - snowProps.setProperty("menuSelectionForegroundColor", "0 0 0"); - snowProps.setProperty("menuSelectionBackgroundColor", "188 206 237"); - - snowProps.setProperty("toolbarBackgroundColor", "64 64 64"); - snowProps.setProperty("toolbarColorLight", "250 250 250"); - snowProps.setProperty("toolbarColorDark", "230 230 230"); - - snowProps.setProperty("tabSelectionForegroundColor", "0 0 0"); - snowProps.setProperty("desktopColor", "240 240 240"); - snowProps.setProperty("tooltipBackgroundColor", "242 246 254"); - - String key; - String value; - Iterator iter = smallFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = smallFontProps.getProperty(key); - rockSmallFontProps.setProperty(key, value); - textileSmallFontProps.setProperty(key, value); - snowSmallFontProps.setProperty(key, value); - //... - } - - iter = mediumFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = mediumFontProps.getProperty(key); - rockMediumFontProps.setProperty(key, value); - textileMediumFontProps.setProperty(key, value); - snowMediumFontProps.setProperty(key, value); - //... - } - - iter = largeFontProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = largeFontProps.getProperty(key); - rockLargeFontProps.setProperty(key, value); - textileLargeFontProps.setProperty(key, value); - snowLargeFontProps.setProperty(key, value); - //.. - } - - iter = rockProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = rockProps.getProperty(key); - rockSmallFontProps.setProperty(key, value); - rockMediumFontProps.setProperty(key, value); - rockLargeFontProps.setProperty(key, value); - } - iter = textileProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = textileProps.getProperty(key); - textileSmallFontProps.setProperty(key, value); - textileMediumFontProps.setProperty(key, value); - textileLargeFontProps.setProperty(key, value); - } - iter = snowProps.keySet().iterator(); - while (iter.hasNext()) { - key = (String)iter.next(); - value = snowProps.getProperty(key); - snowSmallFontProps.setProperty(key, value); - snowMediumFontProps.setProperty(key, value); - snowLargeFontProps.setProperty(key, value); - } - - //... - - themesList.add("Default"); - themesList.add("Small-Font"); - themesList.add("Medium-Font"); - themesList.add("Large-Font"); - - themesList.add("Rock"); - themesList.add("Rock-Small-Font"); - themesList.add("Rock-Medium-Font"); - themesList.add("Rock-Large-Font"); - - themesList.add("Textile"); - themesList.add("Textile-Small-Font"); - themesList.add("Textile-Medium-Font"); - themesList.add("Textile-Large-Font"); - - themesList.add("Snow"); - themesList.add("Snow-Small-Font"); - themesList.add("Snow-Medium-Font"); - themesList.add("Snow-Large-Font"); - - themesMap.put("Default", defaultProps); - themesMap.put("Small-Font", smallFontProps); - themesMap.put("Medium-Font", mediumFontProps); - themesMap.put("Large-Font", largeFontProps); - - themesMap.put("Rock", rockProps); - themesMap.put("Rock-Small-Font", rockSmallFontProps); - themesMap.put("Rock-Medium-Font", rockMediumFontProps); - themesMap.put("Rock-Large-Font", rockLargeFontProps); - - themesMap.put("Textile", textileProps); - themesMap.put("Textile-Small-Font", textileSmallFontProps); - themesMap.put("Textile-Medium-Font", textileMediumFontProps); - themesMap.put("Textile-Large-Font", textileLargeFontProps); - - themesMap.put("Snow", snowProps); - themesMap.put("Snow-Small-Font", snowSmallFontProps); - themesMap.put("Snow-Medium-Font", snowMediumFontProps); - themesMap.put("Snow-Large-Font", snowLargeFontProps); - } - - public static java.util.List getThemes() { - return themesList; - } - - public static Properties getThemeProperties(String name) { - return ((Properties) themesMap.get(name)); - } - - public static void setTheme(String name) { - setTheme((Properties) themesMap.get(name)); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - - public static void setTheme(String name, String licenseKey, String logoString) { - Properties props = (Properties) themesMap.get(name); - if (props != null) { - props.put("licenseKey", licenseKey); - props.put("logoString", logoString); - setTheme(props); - if (myTheme != null) { - AbstractTheme.setInternalName(name); - } - } - } - - public static void setTheme(Properties themesProps) { - if (myTheme == null) { - myTheme = new TextureDefaultTheme(); - } - if ((myTheme != null) && (themesProps != null)) { - TextureIcons.setUp(); - myTheme.setUpColor(); - myTheme.setProperties(themesProps); - myTheme.setUpColorArrs(); - AbstractLookAndFeel.setTheme(myTheme); - // Setup textures - TextureUtils.setUpTextures(); - } - } - - public static void setCurrentTheme(Properties themesProps) { - setTheme(themesProps); - } - - public String getName() { - return "Texture"; - } - - public String getID() { - return "Texture"; - } - - public String getDescription() { - return "The Texture Look and Feel"; - } - - public boolean isNativeLookAndFeel() { - return false; - } - - public boolean isSupportedLookAndFeel() { - return true; - } - - public AbstractBorderFactory getBorderFactory() { - return TextureBorderFactory.getInstance(); - } - - public AbstractIconFactory getIconFactory() { - return TextureIconFactory.getInstance(); - } - - protected void createDefaultTheme() { - if (myTheme == null) { - myTheme = new TextureDefaultTheme(); - } - setTheme(myTheme); - // Setup textures - TextureUtils.setUpTextures(); - } - - protected void initComponentDefaults(UIDefaults table) { - super.initComponentDefaults(table); - table.put("SplitPane.dividerSize", new Integer(8)); - table.put("TabbedPane.tabAreaInsets", new InsetsUIResource(5, 5, 6, 5)); - table.put("ScrollBar.incrementButtonGap", new Integer(-1)); - table.put("ScrollBar.decrementButtonGap", new Integer(-1)); - } - - protected void initClassDefaults(UIDefaults table) { - super.initClassDefaults(table); - Object[] uiDefaults = { - // BaseLookAndFeel classes - "TextFieldUI", BaseTextFieldUI.class.getName(), - "TextAreaUI", BaseTextAreaUI.class.getName(), - "EditorPaneUI", BaseEditorPaneUI.class.getName(), - "PasswordFieldUI", BasePasswordFieldUI.class.getName(), - "ToolTipUI", BaseToolTipUI.class.getName(), - "TreeUI", BaseTreeUI.class.getName(), - "TableUI", BaseTableUI.class.getName(), - "TableHeaderUI", BaseTableHeaderUI.class.getName(), - "ProgressBarUI", BaseProgressBarUI.class.getName(), - "FileChooserUI", BaseFileChooserUI.class.getName(), - "PopupMenuUI", BasePopupMenuUI.class.getName(), - "DesktopPaneUI", BaseDesktopPaneUI.class.getName(), - - // TextureLookAndFeel classes - "LabelUI", TextureLabelUI.class.getName(), - "PanelUI", TexturePanelUI.class.getName(), - "RadioButtonUI", TextureRadioButtonUI.class.getName(), - "CheckBoxUI", TextureCheckBoxUI.class.getName(), - "ButtonUI", TextureButtonUI.class.getName(), - "ToggleButtonUI", TextureToggleButtonUI.class.getName(), - "ComboBoxUI", TextureComboBoxUI.class.getName(), - "MenuBarUI", TextureMenuBarUI.class.getName(), - "MenuUI", TextureMenuUI.class.getName(), - "MenuItemUI", TextureMenuItemUI.class.getName(), - "CheckBoxMenuItemUI", TextureCheckBoxMenuItemUI.class.getName(), - "RadioButtonMenuItemUI", TextureRadioButtonMenuItemUI.class.getName(), - "PopupMenuSeparatorUI", TexturePopupMenuSeparatorUI.class.getName(), - "SeparatorUI", TextureSeparatorUI.class.getName(), - "TabbedPaneUI", TextureTabbedPaneUI.class.getName(), - "SliderUI", TextureSliderUI.class.getName(), - "SplitPaneUI", TextureSplitPaneUI.class.getName(), - "ScrollPaneUI", TextureScrollPaneUI.class.getName(), - "ScrollBarUI", TextureScrollBarUI.class.getName(), - "ToolBarUI", TextureToolBarUI.class.getName(), - "InternalFrameUI", TextureInternalFrameUI.class.getName(), - "RootPaneUI", TextureRootPaneUI.class.getName(),}; - table.putDefaults(uiDefaults); - if (JTattooUtilities.getJavaVersion() >= 1.5) { - table.put("FormattedTextFieldUI", BaseFormattedTextFieldUI.class.getName()); - table.put("SpinnerUI", BaseSpinnerUI.class.getName()); - } - } - -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureMenuBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureMenuBarUI.java deleted file mode 100644 index 8708356c0..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureMenuBarUI.java +++ /dev/null @@ -1,68 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.JMenuBar; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicMenuBarUI; - - -/** - * @author Michael Hagen - */ -public class TextureMenuBarUI extends BasicMenuBarUI { - - public static ComponentUI createUI(JComponent x) { - return new TextureMenuBarUI(); - } - - public void installUI(JComponent c) { - super.installUI(c); - if ((c != null) && (c instanceof JMenuBar)) { - c.setBorder(TextureBorders.getMenuBarBorder()); - ((JMenuBar) c).setBorderPainted(true); - } - } - - public void paint(Graphics g, JComponent c) { - TextureUtils.fillComponent(g, c, TextureUtils.MENUBAR_TEXTURE_TYPE); - - if (AbstractLookAndFeel.getTheme().isDarkTexture()) { - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - g2D.setColor(Color.black); - g2D.drawLine(0, 0, c.getWidth() - 1, 0); - alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f); - g2D.setComposite(alpha); - g2D.setColor(Color.white); - g2D.drawLine(0, c.getHeight() - 1, c.getWidth() - 1, c.getHeight() - 1); - g2D.setComposite(savedComposite); - } - } -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureMenuItemUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureMenuItemUI.java deleted file mode 100644 index eb0f45375..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureMenuItemUI.java +++ /dev/null @@ -1,79 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class TextureMenuItemUI extends BaseMenuItemUI { - - public static ComponentUI createUI(JComponent c) { - return new TextureMenuItemUI(); - } - - protected void paintBackground(Graphics g, JComponent c, int x, int y, int w, int h) { -// if (!AbstractLookAndFeel.getTheme().isDarkTexture()) { -// super.paintBackground(g, c, x, y, w, h); -// return; -// } - JMenuItem b = (JMenuItem) c; - ButtonModel model = b.getModel(); - if (model.isArmed() || (c instanceof JMenu && model.isSelected())) { - TextureUtils.fillComponent(g, c, TextureUtils.ROLLOVER_TEXTURE_TYPE); - } else { - TextureUtils.fillComponent(g, c, TextureUtils.MENUBAR_TEXTURE_TYPE); - } - } - - protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { - if (!AbstractLookAndFeel.getTheme().isDarkTexture()) { - super.paintText(g, menuItem, textRect, text); - return; - } - ButtonModel model = menuItem.getModel(); - FontMetrics fm = menuItem.getFontMetrics(menuItem.getFont()); - int mnemIndex = menuItem.getDisplayedMnemonicIndex(); - if (!menuItem.isArmed()) { - g.setColor(Color.black); - JTattooUtilities.drawStringUnderlineCharAt(menuItem, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent() - 1); - } - if (!model.isEnabled()) { - // *** paint the text disabled - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getDisabledForegroundColor(), 40)); - } else { - // *** paint the text normally - if (menuItem.isArmed()) { - g.setColor(AbstractLookAndFeel.getMenuSelectionForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getMenuForegroundColor()); - } - } - JTattooUtilities.drawStringUnderlineCharAt(menuItem, g,text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureMenuUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureMenuUI.java deleted file mode 100644 index dd5ae794c..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureMenuUI.java +++ /dev/null @@ -1,95 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class TextureMenuUI extends BaseMenuUI { - - public TextureMenuUI() { - paintRolloverBorder = false; - } - - public static ComponentUI createUI(JComponent c) { - return new TextureMenuUI(); - } - - protected void paintBackground(Graphics g, JComponent c, int x, int y, int w, int h) { -// if (!AbstractLookAndFeel.getTheme().isDarkTexture()) { -// super.paintBackground(g, c, x, y, w, h); -// return; -// } - JMenuItem b = (JMenuItem) c; - ButtonModel model = b.getModel(); - if (c.getParent() instanceof JMenuBar) { - if (model.isRollover() || model.isArmed() || (c instanceof JMenu && model.isSelected())) { - TextureUtils.fillComponent(g, c, TextureUtils.ROLLOVER_TEXTURE_TYPE); - } - } else { - if (model.isArmed() || (c instanceof JMenu && model.isSelected())) { - TextureUtils.fillComponent(g, c, TextureUtils.ROLLOVER_TEXTURE_TYPE); - } else { - TextureUtils.fillComponent(g, c, TextureUtils.MENUBAR_TEXTURE_TYPE); - } - } - } - - protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { - if (!AbstractLookAndFeel.getTheme().isDarkTexture()) { - super.paintText(g, menuItem, textRect, text); - return; - } - ButtonModel model = menuItem.getModel(); - FontMetrics fm = menuItem.getFontMetrics(menuItem.getFont()); - int mnemIndex = menuItem.getDisplayedMnemonicIndex(); - if (!model.isEnabled()) { - // *** paint the text disabled - g.setColor(Color.black); - JTattooUtilities.drawStringUnderlineCharAt(menuItem, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent() - 1); - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getDisabledForegroundColor(), 40)); - } else { - // *** paint the text normally - g.setColor(AbstractLookAndFeel.getMenuForegroundColor()); - if (menuItem.getParent() instanceof JMenuBar) { - if (model.isRollover() || model.isArmed() || (menuItem instanceof JMenu && model.isSelected())) { - g.setColor(AbstractLookAndFeel.getMenuSelectionForegroundColor()); - } - } else if (menuItem.isArmed() || menuItem.isSelected()) { - g.setColor(AbstractLookAndFeel.getMenuSelectionForegroundColor()); - } else { - g.setColor(Color.black); - JTattooUtilities.drawStringUnderlineCharAt(menuItem, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent() - 1); - g.setColor(AbstractLookAndFeel.getMenuForegroundColor()); - } - } - JTattooUtilities.drawStringUnderlineCharAt(menuItem, g,text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TexturePanelUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TexturePanelUI.java deleted file mode 100644 index 03ac3f754..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TexturePanelUI.java +++ /dev/null @@ -1,53 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.BasePanelUI; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class TexturePanelUI extends BasePanelUI { - - private static TexturePanelUI panelUI = null; - - public static ComponentUI createUI(JComponent c) { - if (panelUI == null) { - panelUI = new TexturePanelUI(); - } - return panelUI; - } - - public void update(Graphics g, JComponent c) { - if (c.isOpaque() && c.getBackground() instanceof ColorUIResource && c.getClientProperty("backgroundTexture") == null) { - TextureUtils.fillComponent(g, c, TextureUtils.getTextureType(c)); - } else { - super.update(g, c); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TexturePopupMenuSeparatorUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TexturePopupMenuSeparatorUI.java deleted file mode 100644 index 8bc060969..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TexturePopupMenuSeparatorUI.java +++ /dev/null @@ -1,94 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSeparatorUI; - -/** - * @author Michael Hagen - */ -public class TexturePopupMenuSeparatorUI extends BasicSeparatorUI { - - private static final Dimension size = new Dimension(8, 8); - private static final Color colors[] = new Color[] { Color.black, new Color(164, 164, 164), new Color(48, 48, 48), new Color(128, 128, 128) }; - - public static ComponentUI createUI(JComponent c) { - return new TexturePopupMenuSeparatorUI(); - } - - public void paint(Graphics g, JComponent c) { - TextureUtils.fillComponent(g, c, TextureUtils.MENUBAR_TEXTURE_TYPE); - if (AbstractLookAndFeel.getTheme().getTextureSet().equals("Default")) { - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - int w = c.getWidth(); - drawLine(g, 2, w, colors[0]); - drawLine(g, 3, w, colors[1]); - drawLine(g, 4, w, colors[2]); - drawLine(g, 5, w, colors[3]); - g2D.setComposite(savedComposite); - } else { - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - if (AbstractLookAndFeel.getTheme().isDarkTexture()) { - g.setColor(Color.black); - } else { - g.setColor(Color.gray); - } - g.drawLine(1, 3, c.getWidth() - 2, 3); - alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f); - g2D.setComposite(alpha); - g.setColor(Color.white); - g.drawLine(1, 4, c.getWidth() - 2, 4); - g2D.setComposite(savedComposite); - } - } - - private void drawLine(Graphics g, int y, int w, Color color) { - g.setColor(color); - int dw = 3; - int dx = 2; - int x = dx; - while (x < w) { - g.drawLine(x, y, x + dw - 1, y); - x += dx + dw; - } - } - - public Dimension getPreferredSize(JComponent c) { - return size; - } -} - - - - diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureRadioButtonMenuItemUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureRadioButtonMenuItemUI.java deleted file mode 100644 index d218a47e2..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureRadioButtonMenuItemUI.java +++ /dev/null @@ -1,80 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class TextureRadioButtonMenuItemUI extends BaseRadioButtonMenuItemUI { - - public static ComponentUI createUI(JComponent c) { - return new TextureRadioButtonMenuItemUI(); - } - - protected void paintBackground(Graphics g, JComponent c, int x, int y, int w, int h) { -// if (!AbstractLookAndFeel.getTheme().isDarkTexture()) { -// super.paintBackground(g, c, x, y, w, h); -// return; -// } - JMenuItem b = (JMenuItem) c; - ButtonModel model = b.getModel(); - if (model.isArmed() || (c instanceof JMenu && model.isSelected())) { - TextureUtils.fillComponent(g, c, TextureUtils.ROLLOVER_TEXTURE_TYPE); - } else { - TextureUtils.fillComponent(g, c, TextureUtils.MENUBAR_TEXTURE_TYPE); - } - } - - protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { - if (!AbstractLookAndFeel.getTheme().isDarkTexture()) { - super.paintText(g, menuItem, textRect, text); - return; - } - ButtonModel model = menuItem.getModel(); - FontMetrics fm = menuItem.getFontMetrics(menuItem.getFont()); - int mnemIndex = menuItem.getDisplayedMnemonicIndex(); - if (!menuItem.isArmed()) { - g.setColor(Color.black); - JTattooUtilities.drawStringUnderlineCharAt(menuItem, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent() - 1); - } - if (!model.isEnabled()) { - // *** paint the text disabled - g.setColor(ColorHelper.brighter(AbstractLookAndFeel.getDisabledForegroundColor(), 40)); - } else { - // *** paint the text normally - if (menuItem.isArmed()) { - g.setColor(AbstractLookAndFeel.getMenuSelectionForegroundColor()); - } else { - g.setColor(AbstractLookAndFeel.getMenuForegroundColor()); - } - } - JTattooUtilities.drawStringUnderlineCharAt(menuItem, g,text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureRadioButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureRadioButtonUI.java deleted file mode 100644 index 7927c64cb..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureRadioButtonUI.java +++ /dev/null @@ -1,65 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseRadioButtonUI; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicGraphicsUtils; - -/** - * @author Michael Hagen - */ -public class TextureRadioButtonUI extends BaseRadioButtonUI { - - private static TextureRadioButtonUI radioButtonUI = null; - - public static ComponentUI createUI(JComponent c) { - if (radioButtonUI == null) { - radioButtonUI = new TextureRadioButtonUI(); - } - return radioButtonUI; - } - - public void paintBackground(Graphics g, JComponent c) { - if (c.isOpaque()) { - if ((c.getBackground().equals(AbstractLookAndFeel.getBackgroundColor())) && (c.getBackground() instanceof ColorUIResource)) { - TextureUtils.fillComponent(g, c, TextureUtils.BACKGROUND_TEXTURE_TYPE); - } else { - g.setColor(c.getBackground()); - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } - } - - protected void paintFocus(Graphics g, Rectangle t, Dimension d) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - BasicGraphicsUtils.drawDashedRect(g, t.x - 3, t.y - 1, t.width + 6, t.height + 2); - BasicGraphicsUtils.drawDashedRect(g, t.x - 2, t.y, t.width + 4, t.height); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureRootPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureRootPaneUI.java deleted file mode 100644 index 71021e066..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureRootPaneUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.BaseRootPaneUI; -import com.jtattoo.plaf.BaseTitlePane; -import javax.swing.JComponent; -import javax.swing.JRootPane; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class TextureRootPaneUI extends BaseRootPaneUI -{ - public static ComponentUI createUI(JComponent c) { - return new TextureRootPaneUI(); - } - - public BaseTitlePane createTitlePane(JRootPane root) { - return new TextureTitlePane(root, this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureScrollBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureScrollBarUI.java deleted file mode 100644 index 2f0281d68..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureScrollBarUI.java +++ /dev/null @@ -1,63 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.XPScrollBarUI; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; - -/** - * - * @author Michael Hagen - */ -public class TextureScrollBarUI extends XPScrollBarUI { - -// private static Color rolloverColors[] = null; -// private static Color dragColors[] = null; - - public static ComponentUI createUI(JComponent c) { - return new TextureScrollBarUI(); - } - -// protected void installDefaults() { -// super.installDefaults(); -// Color colors[] = AbstractLookAndFeel.getTheme().getThumbColors(); -// rolloverColors = new Color[colors.length]; -// dragColors = new Color[colors.length]; -// for (int i = 0; i < colors.length; i++) { -// rolloverColors[i] = ColorHelper.darker(colors[i], 6); -// dragColors[i] = ColorHelper.darker(colors[i], 12); -// } -// } - - protected JButton createDecreaseButton(int orientation) { - return new TextureScrollButton(orientation, scrollBarWidth); - } - - protected JButton createIncreaseButton(int orientation) { - return new TextureScrollButton(orientation, scrollBarWidth); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureScrollButton.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureScrollButton.java deleted file mode 100644 index 32253bcd0..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureScrollButton.java +++ /dev/null @@ -1,72 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.LazyImageIcon; -import com.jtattoo.plaf.XPScrollButton; -import javax.swing.Icon; - -/** - * @author Michael Hagen - */ -public class TextureScrollButton extends XPScrollButton { - - protected static Icon upArrowIcon = null; - protected static Icon downArrowIcon = null; - protected static Icon leftArrowIcon = null; - protected static Icon rightArrowIcon = null; - - public TextureScrollButton(int direction, int width) { - super(direction, width); - } - - public Icon getUpArrowIcon() { - if (upArrowIcon == null) { - upArrowIcon = new LazyImageIcon("texture/icons/UpArrow.gif"); - } - return upArrowIcon; - } - - public Icon getDownArrowIcon() { - if (downArrowIcon == null) { - downArrowIcon = new LazyImageIcon("texture/icons/DownArrow.gif"); - } - return downArrowIcon; - } - - public Icon getLeftArrowIcon() { - if (leftArrowIcon == null) { - leftArrowIcon = new LazyImageIcon("texture/icons/LeftArrow.gif"); - } - return leftArrowIcon; - } - - public Icon getRightArrowIcon() { - if (rightArrowIcon == null) { - rightArrowIcon = new LazyImageIcon("texture/icons/RightArrow.gif"); - } - return rightArrowIcon; - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureScrollPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureScrollPaneUI.java deleted file mode 100644 index ad9810347..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureScrollPaneUI.java +++ /dev/null @@ -1,56 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.BaseScrollPaneUI; -import java.awt.Graphics; -import javax.swing.*; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class TextureScrollPaneUI extends BaseScrollPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new TextureScrollPaneUI(); - } - - public void installDefaults(JScrollPane p) { - super.installDefaults(p); - p.getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE); - } - - public void update(Graphics g, JComponent c) { - if (c.getBackground() instanceof ColorUIResource) { - if (c.isOpaque()) { - TextureUtils.fillComponent(g, c, TextureUtils.getTextureType(c)); - } - } else { - super.update(g, c); - } - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureSeparatorUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureSeparatorUI.java deleted file mode 100644 index f3eb1ecec..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureSeparatorUI.java +++ /dev/null @@ -1,65 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.JSeparator; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSeparatorUI; - -/** - * @author Michael Hagen - */ -public class TextureSeparatorUI extends BasicSeparatorUI { - - public static ComponentUI createUI(JComponent c) { - return new TextureSeparatorUI(); - } - - public void paint(Graphics g, JComponent c) { - boolean horizontal = true; - if (c instanceof JSeparator) { - horizontal = (((JSeparator) c).getOrientation() == JSeparator.HORIZONTAL); - } - if (horizontal) { - int w = c.getWidth(); - g.setColor(AbstractLookAndFeel.getFrameColor()); - g.drawLine(0, 0, w, 0); - } else { - int h = c.getHeight(); - g.setColor(AbstractLookAndFeel.getFrameColor()); - g.drawLine(0, 0, 0, h); - } - } - - public Dimension getPreferredSize(JComponent c) { - if (((JSeparator) c).getOrientation() == JSeparator.VERTICAL) { - return new Dimension(1, 0); - } else { - return new Dimension(0, 1); - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureSliderUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureSliderUI.java deleted file mode 100644 index d7cf0a46a..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureSliderUI.java +++ /dev/null @@ -1,62 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.BaseSliderUI; -import java.awt.Component; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.JSlider; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class TextureSliderUI extends BaseSliderUI { - - public TextureSliderUI(JSlider slider) { - super(slider); - } - - public static ComponentUI createUI(JComponent c) { - return new TextureSliderUI((JSlider) c); - } - - public void paintBackground(Graphics g, JComponent c) { - if (c.isOpaque()) { - Component parent = c.getParent(); - if ((parent != null) && (parent.getBackground() instanceof ColorUIResource)) { - TextureUtils.fillComponent(g, c, TextureUtils.BACKGROUND_TEXTURE_TYPE); - } else { - if (parent != null) { - g.setColor(parent.getBackground()); - } else { - g.setColor(c.getBackground()); - } - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - } - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureSplitPaneDivider.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureSplitPaneDivider.java deleted file mode 100644 index a060015d8..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureSplitPaneDivider.java +++ /dev/null @@ -1,102 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.AbstractLookAndFeel; -import com.jtattoo.plaf.BaseSplitPaneDivider; -import java.awt.*; -import javax.swing.*; - -/** - * @author Michael Hagen - */ -public class TextureSplitPaneDivider extends BaseSplitPaneDivider { - - public TextureSplitPaneDivider(TextureSplitPaneUI ui) { - super(ui); - } - - public void paint(Graphics g) { - if (!isFlatMode()) { - TextureUtils.fillComponent(g, this, TextureUtils.getTextureType(splitPane)); - - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); - g2D.setComposite(alpha); - - int width = getSize().width; - int height = getSize().height; - int dx = 0; - int dy = 0; - if ((width % 2) == 1) { - dx = 1; - } - if ((height % 2) == 1) { - dy = 1; - } - - Icon horBumps = null; - Icon verBumps = null; - if (UIManager.getLookAndFeel() instanceof AbstractLookAndFeel) { - AbstractLookAndFeel laf = (AbstractLookAndFeel) UIManager.getLookAndFeel(); - horBumps = laf.getIconFactory().getSplitterHorBumpIcon(); - verBumps = laf.getIconFactory().getSplitterVerBumpIcon(); - } - if (orientation == JSplitPane.HORIZONTAL_SPLIT) { - if ((horBumps != null) && (width > horBumps.getIconWidth())) { - if (splitPane.isOneTouchExpandable() && centerOneTouchButtons) { - int centerY = height / 2; - int x = (width - horBumps.getIconWidth()) / 2 + dx; - int y = centerY - horBumps.getIconHeight() - 40; - horBumps.paintIcon(this, g, x, y); - y = centerY + 40; - horBumps.paintIcon(this, g, x, y); - } else { - int x = (width - horBumps.getIconWidth()) / 2 + dx; - int y = (height - horBumps.getIconHeight()) / 2; - horBumps.paintIcon(this, g, x, y); - } - } - } else { - if ((verBumps != null) && (height > verBumps.getIconHeight())) { - if (splitPane.isOneTouchExpandable() && centerOneTouchButtons) { - int centerX = width / 2; - int x = centerX - verBumps.getIconWidth() - 40; - int y = (height - verBumps.getIconHeight()) / 2 + dy; - verBumps.paintIcon(this, g, x, y); - x = centerX + 40; - verBumps.paintIcon(this, g, x, y); - } else { - int x = (width - verBumps.getIconWidth()) / 2; - int y = (height - verBumps.getIconHeight()) / 2 + dy; - verBumps.paintIcon(this, g, x, y); - } - } - } - g2D.setComposite(savedComposite); - } - paintComponents(g); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureSplitPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureSplitPaneUI.java deleted file mode 100644 index 5a6adfb6b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureSplitPaneUI.java +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.BaseSplitPaneUI; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSplitPaneDivider; - -/** - * @author Michael Hagen - */ -public class TextureSplitPaneUI extends BaseSplitPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new TextureSplitPaneUI(); - } - - public BasicSplitPaneDivider createDefaultDivider() { - return new TextureSplitPaneDivider(this); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureTabbedPaneUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureTabbedPaneUI.java deleted file mode 100644 index c946b2872..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureTabbedPaneUI.java +++ /dev/null @@ -1,301 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.*; -import java.awt.*; -import java.awt.geom.*; -import javax.swing.JComponent; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.text.View; - -/** - * @author Michael Hagen - */ -public class TextureTabbedPaneUI extends BaseTabbedPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new TextureTabbedPaneUI(); - } - - protected void installComponents() { - simpleButtonBorder = true; - super.installComponents(); - } - - protected Color[] getContentBorderColors(int tabPlacement) { - Color c = AbstractLookAndFeel.getTheme().getSelectionBackgroundColorDark(); - return new Color[] { getLoBorderColor(0), c, c, c, ColorHelper.darker(c, 10) }; - } - - protected Color getLoBorderColor(int tabIndex) { - if (tabIndex == tabPane.getSelectedIndex() - && tabPane.getBackgroundAt(tabIndex) instanceof ColorUIResource - && AbstractLookAndFeel.getTheme().isDarkTexture()) { - return ColorHelper.darker(super.getLoBorderColor(tabIndex), 20); - } - return AbstractLookAndFeel.getFrameColor(); - } - - protected Font getTabFont(boolean isSelected) { - if (isSelected) { - return super.getTabFont(isSelected).deriveFont(Font.BOLD); - } else { - return super.getTabFont(isSelected); - } - } - - protected int getTexture() { - return TextureUtils.BACKGROUND_TEXTURE_TYPE; - } - - protected int getSelectedTexture() { - return TextureUtils.SELECTED_TEXTURE_TYPE; - } - - protected int getUnSelectedTexture(int tabIndex) { - if (tabIndex == rolloverIndex && tabPane.isEnabledAt(tabIndex)) { - return TextureUtils.ROLLOVER_TEXTURE_TYPE; - } - return TextureUtils.ALTER_BACKGROUND_TEXTURE_TYPE; - } - - protected void paintContentBorder(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) { - int textureType = TextureUtils.getTextureType(tabPane); - int tabAreaHeight = calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight); - int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth); - // paint the background - if (tabPane.isOpaque()) { - int xt = tabPlacement == RIGHT ? w - tabAreaWidth : 0; - int yt = tabPlacement == BOTTOM ? h - tabAreaHeight : 0; - int wt = tabPlacement == TOP || tabPlacement == BOTTOM ? w : tabAreaWidth; - int ht = tabPlacement == LEFT || tabPlacement == RIGHT ? h : tabAreaHeight; - g.setColor(tabAreaBackground); - g.fillRect(xt, yt, wt, ht); - } - if (isContentOpaque()) { - int xt = tabPlacement == LEFT ? tabAreaWidth : 0; - int yt = tabPlacement == TOP ? tabAreaHeight : 0; - int wt = tabPlacement == LEFT || tabPlacement == RIGHT ? w - tabAreaWidth : w; - int ht = tabPlacement == TOP || tabPlacement == BOTTOM ? h - tabAreaHeight : h; - TextureUtils.fillComponent(g, tabPane, xt, yt, wt, ht, textureType); - } - - int sepHeight = tabAreaInsets.bottom; - if (sepHeight > 0) { - Insets bi = new Insets(0, 0, 0, 0); - if (tabPane.getBorder() != null) { - bi = tabPane.getBorder().getBorderInsets(tabPane); - } - switch (tabPlacement) { - case TOP: { - TextureUtils.fillComponent(g, tabPane, x, y + tabAreaHeight - sepHeight + bi.top, w, sepHeight, getSelectedTexture()); - if (textureType == TextureUtils.MENUBAR_TEXTURE_TYPE) { - Graphics2D g2D = (Graphics2D) g; - Composite saveComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); - g2D.setComposite(alpha); - g2D.setColor(Color.black); - g2D.drawLine(x, y, w, y); - g2D.drawLine(w, y, w, y + tabAreaHeight - sepHeight); - alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f); - g2D.setComposite(alpha); - g2D.setColor(Color.white); - g2D.drawLine(x, y + tabAreaHeight - sepHeight, w, y + tabAreaHeight - sepHeight); - alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f); - g2D.setComposite(alpha); - g2D.drawLine(x, y + 1, x, y + tabAreaHeight - sepHeight - 1); - g2D.setComposite(saveComposite); - } - break; - } - case LEFT: { - TextureUtils.fillComponent(g, tabPane, x + tabAreaWidth - sepHeight + bi.left, y, sepHeight, h, getSelectedTexture()); - break; - } - case BOTTOM: { - TextureUtils.fillComponent(g, tabPane, x, y + h - tabAreaHeight - bi.bottom, w, sepHeight, getSelectedTexture()); - break; - } - case RIGHT: { - TextureUtils.fillComponent(g, tabPane, x + w - tabAreaWidth - bi.right, y, sepHeight, h, getSelectedTexture()); - break; - } - } - } - } - - protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) { - Color backColor = tabPane.getBackgroundAt(tabIndex); - if (!(backColor instanceof UIResource) || !AbstractLookAndFeel.getTheme().isDarkTexture()) { - super.paintTabBackground(g, tabPlacement, tabIndex, x, y, w, h, isSelected); - return; - } - if (isTabOpaque() || isSelected) { - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - Shape savedClip = g.getClip(); - Area orgClipArea = new Area(savedClip); - int d = 2 * GAP; - switch (tabPlacement) { - case TOP: - default: - if (isSelected) { - Area clipArea = new Area(new RoundRectangle2D.Double(x, y, w , h + 4, d, d)); - Area rectArea = new Area(new Rectangle2D.Double(x, y, w, h + 1)); - clipArea.intersect(rectArea); - clipArea.intersect(orgClipArea); - g2D.setClip(clipArea); - TextureUtils.fillRect(g, tabPane, x, y, w, h + 4, getSelectedTexture()); - g2D.setClip(savedClip); - } else { - Area clipArea = new Area(new RoundRectangle2D.Double(x, y, w, h + 4, d, d)); - Area rectArea = new Area(new Rectangle2D.Double(x, y, w, h)); - clipArea.intersect(rectArea); - clipArea.intersect(orgClipArea); - g2D.setClip(clipArea); - TextureUtils.fillRect(g, tabPane, x, y, w, h + 4, getUnSelectedTexture(tabIndex)); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); - g2D.setComposite(alpha); - Color colors[] = AbstractLookAndFeel.getTheme().getButtonColors(); - JTattooUtilities.fillHorGradient(g, colors, x, y, w, h + 4); - g2D.setComposite(savedComposite); - g2D.setClip(savedClip); - } - break; - case LEFT: - if (isSelected) { - TextureUtils.fillComponent(g, tabPane, x + 1, y + 1, w, h - 1, getSelectedTexture()); - } else { - TextureUtils.fillComponent(g, tabPane, x + 1, y + 1, w - 1, h - 1, getUnSelectedTexture(tabIndex)); - } - break; - case BOTTOM: - if (isSelected) { - Area clipArea = new Area(new RoundRectangle2D.Double(x, y - 4, w, h + 4, d, d)); - Area rectArea = new Area(new Rectangle2D.Double(x, y - 1, w, h + 1)); - clipArea.intersect(rectArea); - clipArea.intersect(orgClipArea); - g2D.setClip(clipArea); - TextureUtils.fillRect(g, tabPane, x, y - 4, w, h + 4, getSelectedTexture()); - g2D.setClip(savedClip); - } else { - Area clipArea = new Area(new RoundRectangle2D.Double(x, y - 4, w, h + 4, d, d)); - Area rectArea = new Area(new Rectangle2D.Double(x, y, w, h)); - clipArea.intersect(rectArea); - clipArea.intersect(orgClipArea); - g2D.setClip(clipArea); - TextureUtils.fillRect(g, tabPane, x, y - 4, w, h + 4, getUnSelectedTexture(tabIndex)); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); - g2D.setComposite(alpha); - Color colors[] = AbstractLookAndFeel.getTheme().getButtonColors(); - JTattooUtilities.fillHorGradient(g, colors, x, y - 4, w, h + 4); - g2D.setComposite(savedComposite); - g2D.setClip(savedClip); - } - break; - case RIGHT: - if (isSelected) { - TextureUtils.fillComponent(g, tabPane, x, y + 1, w, h - 1, getSelectedTexture()); - } else { - TextureUtils.fillComponent(g, tabPane, x, y + 1, w, h - 1, getUnSelectedTexture(tabIndex)); - } - break; - } - } - } - - protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected) { - Color backColor = tabPane.getBackgroundAt(tabIndex); - if (!(backColor instanceof UIResource) || !AbstractLookAndFeel.getTheme().isDarkTexture()) { - super.paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected); - return; - } - g.setFont(font); - View v = getTextViewForTab(tabIndex); - if (v != null) { - // html - Graphics2D g2D = (Graphics2D)g; - Object savedRenderingHint = null; - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - savedRenderingHint = g2D.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, AbstractLookAndFeel.getTheme().getTextAntiAliasingHint()); - } - v.paint(g, textRect); - if (AbstractLookAndFeel.getTheme().isTextAntiAliasingOn()) { - g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedRenderingHint); - } - } else { - // plain text - int mnemIndex = -1; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); - } - - if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) { - if (isSelected) { - Color titleColor = AbstractLookAndFeel.getTabSelectionForegroundColor(); - if (ColorHelper.getGrayValue(titleColor) > 164) { - g.setColor(Color.black); - } else { - g.setColor(Color.white); - } - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x + 1, textRect.y + 1 + metrics.getAscent()); - g.setColor(titleColor); - Graphics2D g2D = (Graphics2D)g; - Shape savedClip = g2D.getClip(); - - Area clipArea = new Area(new Rectangle2D.Double(textRect.x, textRect.y, textRect.width, textRect.height / 2 + 1)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); - - clipArea = new Area(new Rectangle2D.Double(textRect.x, textRect.y + (textRect.height / 2) + 1, textRect.width, textRect.height)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - g2D.setColor(ColorHelper.darker(titleColor, 20)); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); - g2D.setClip(savedClip); - } else { - g.setColor(tabPane.getForegroundAt(tabIndex)); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); - } - - } else { // tab disabled - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); - g2D.setComposite(alpha); - g.setColor(Color.white); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent() + 1); - g2D.setComposite(savedComposite); - g.setColor(AbstractLookAndFeel.getDisabledForegroundColor()); - JTattooUtilities.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); - } - } - } - -} \ No newline at end of file diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureTitlePane.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureTitlePane.java deleted file mode 100644 index 7e046a033..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureTitlePane.java +++ /dev/null @@ -1,88 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.*; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.Rectangle2D; -import javax.swing.JRootPane; - -/** - * @author Michael Hagen - */ -public class TextureTitlePane extends BaseTitlePane { - - public TextureTitlePane(JRootPane root, BaseRootPaneUI ui) { - super(root, ui); - } - - protected int getHorSpacing() { - return AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn() ? 1 : 0; - } - - protected int getVerSpacing() { - return AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn() ? 3 : 0; - } - - protected boolean centerButtons() { - return false; - } - - public void paintBorder(Graphics g) { - } - - public void paintBackground(Graphics g) { - TextureUtils.fillComponent(g, this, TextureUtils.WINDOW_TEXTURE_TYPE); - } - - public void paintText(Graphics g, int x, int y, String title) { - x += paintIcon(g, x, y); - Graphics2D g2D = (Graphics2D)g; - Shape savedClip = g2D.getClip(); - Color fc = AbstractLookAndFeel.getWindowTitleForegroundColor(); - if (fc.equals(Color.white)) { - Color bc = AbstractLookAndFeel.getWindowTitleColorDark(); - g2D.setColor(bc); - JTattooUtilities.drawString(rootPane, g, title, x-1, y-1); - g2D.setColor(ColorHelper.darker(bc, 30)); - JTattooUtilities.drawString(rootPane, g, title, x+1, y+1); - } - g.setColor(fc); - - Area clipArea = new Area(new Rectangle2D.Double(x, 0, getWidth(), getHeight() / 2)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - JTattooUtilities.drawString(rootPane, g, title, x, y); - - clipArea = new Area(new Rectangle2D.Double(x, (getHeight() / 2), getWidth(), getHeight())); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - g.setColor(ColorHelper.darker(fc, 20)); - JTattooUtilities.drawString(rootPane, g, title, x, y); - - g2D.setClip(savedClip); - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureToggleButtonUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureToggleButtonUI.java deleted file mode 100644 index d2edd5139..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureToggleButtonUI.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.*; -import java.awt.*; -import javax.swing.*; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicGraphicsUtils; - -/** - * @author Michael Hagen - */ -public class TextureToggleButtonUI extends BaseToggleButtonUI { - - public static ComponentUI createUI(JComponent c) { - return new TextureToggleButtonUI(); - } - - protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect) { - AbstractButton b = (AbstractButton)c; - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - if (!b.isContentAreaFilled()) { - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.9f); - g2D.setComposite(alpha); - } - super.paintIcon(g, c, iconRect); - g2D.setComposite(savedComposite); - } - - protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) { - Graphics2D g2D = (Graphics2D) g; - Composite savedComposite = g2D.getComposite(); - ButtonModel model = b.getModel(); - FontMetrics fm = g.getFontMetrics(); - int mnemIndex; - if (JTattooUtilities.getJavaVersion() >= 1.4) { - mnemIndex = b.getDisplayedMnemonicIndex(); - } else { - mnemIndex = JTattooUtilities.findDisplayedMnemonicIndex(b.getText(), model.getMnemonic()); - } - - if (model.isEnabled()) { - int offs = 0; - if (model.isArmed() && model.isPressed()) { - offs = 1; - } - Color fc = b.getForeground(); - if (fc instanceof ColorUIResource) { - if (model.isPressed() || model.isSelected()) { - fc = AbstractLookAndFeel.getTheme().getPressedForegroundColor(); - } else if (b.isRolloverEnabled() && model.isRollover()) { - fc = AbstractLookAndFeel.getTheme().getRolloverForegroundColor(); - } - } - if (AbstractLookAndFeel.getTheme().isTextShadowOn() && ColorHelper.getGrayValue(fc) > 164) { - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f); - g2D.setComposite(alpha); - g.setColor(Color.black); - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x + offs, textRect.y + offs + fm.getAscent() + 1); - g2D.setComposite(savedComposite); - } - g.setColor(fc); - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x + offs, textRect.y + offs + fm.getAscent()); - } else { - AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f); - g2D.setComposite(alpha); - Color fc = b.getForeground(); - if (ColorHelper.getGrayValue(fc) > 164) { - fc = ColorHelper.brighter(AbstractLookAndFeel.getDisabledForegroundColor(), 40); - g.setColor(Color.black); - } else { - fc = AbstractLookAndFeel.getDisabledForegroundColor(); - g.setColor(Color.white); - } - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x, textRect.y + 1 + fm.getAscent()); - g2D.setComposite(savedComposite); - g.setColor(fc); - JTattooUtilities.drawStringUnderlineCharAt(b, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); - } - } - - protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { - if (!AbstractLookAndFeel.getTheme().doShowFocusFrame()) { - g.setColor(AbstractLookAndFeel.getFocusColor()); - BasicGraphicsUtils.drawDashedRect(g, 3, 2, b.getWidth() - 6, b.getHeight() - 5); - BasicGraphicsUtils.drawDashedRect(g, 4, 3, b.getWidth() - 8, b.getHeight() - 7); - } - } - -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureToolBarUI.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureToolBarUI.java deleted file mode 100644 index 705d1a39c..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureToolBarUI.java +++ /dev/null @@ -1,58 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.AbstractToolBarUI; -import java.awt.Graphics; -import javax.swing.JComponent; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; - -/** - * @author Michael Hagen - */ -public class TextureToolBarUI extends AbstractToolBarUI -{ - public static ComponentUI createUI(JComponent c) { - return new TextureToolBarUI(); - } - - public Border getRolloverBorder() { - return TextureBorders.getRolloverToolButtonBorder(); - } - - public Border getNonRolloverBorder() { - return TextureBorders.getToolButtonBorder(); - } - - public boolean isButtonOpaque() { - return false; - } - - public void paint(Graphics g, JComponent c) { - TextureUtils.fillComponent(g, c, TextureUtils.getTextureType(c)); - } - -} - diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureUtils.java b/src/jtattoo/src/com/jtattoo/plaf/texture/TextureUtils.java deleted file mode 100644 index 2fabd439b..000000000 --- a/src/jtattoo/src/com/jtattoo/plaf/texture/TextureUtils.java +++ /dev/null @@ -1,238 +0,0 @@ -/* -* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved. -* -* JTattoo is multiple licensed. If your are an open source developer you can use -* it under the terms and conditions of the GNU General Public License version 2.0 -* or later as published by the Free Software Foundation. -* -* see: gpl-2.0.txt -* -* If you pay for a license you will become a registered user who could use the -* software under the terms and conditions of the GNU Lesser General Public License -* version 2.0 or later with classpath exception as published by the Free Software -* Foundation. -* -* see: lgpl-2.0.txt -* see: classpath-exception.txt -* -* Registered users could also use JTattoo under the terms and conditions of the -* Apache License, Version 2.0 as published by the Apache Software Foundation. -* -* see: APACHE-LICENSE-2.0.txt -*/ - -package com.jtattoo.plaf.texture; - -import com.jtattoo.plaf.*; -import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.Rectangle2D; -import javax.swing.Icon; -import javax.swing.JComponent; - -/** - * @author Michael Hagen - */ -public class TextureUtils { - - public static final int WINDOW_TEXTURE_TYPE = 0; - public static final int BACKGROUND_TEXTURE_TYPE = 1; - public static final int ALTER_BACKGROUND_TEXTURE_TYPE = 2; - public static final int SELECTED_TEXTURE_TYPE = 3; - public static final int ROLLOVER_TEXTURE_TYPE = 4; - public static final int PRESSED_TEXTURE_TYPE = 5; - public static final int DISABLED_TEXTURE_TYPE = 6; - public static final int MENUBAR_TEXTURE_TYPE = 7; - public static final int LAST_TEXTURE_TYPE = 7; - - public static final String WINDOW_TEXTURE_KEY = "WindowTexture"; - public static final String BACKGROUND_TEXTURE_KEY = "BackgroundTexture"; - public static final String ALTER_BACKGROUND_TEXTURE_KEY = "AlterBackgroundTexture"; - public static final String SELECTED_TEXTURE_KEY = "SelectedTexture"; - public static final String ROLLOVER_TEXTURE_KEY = "RolloverTexture"; - public static final String PRESSED_TEXTURE_KEY = "PressedTexture"; - public static final String DISABLED_TEXTURE_KEY = "DisabledTexture"; - public static final String MENUBAR_TEXTURE_KEY = "MenubarTexture"; - - private static Icon windowTexture = null; - private static Icon backgroundTexture = null; - private static Icon alterBackgroundTexture = null; - private static Icon selectedTexture = null; - private static Icon rolloverTexture = null; - private static Icon pressedTexture = null; - private static Icon disabledTexture = null; - private static Icon menubarTexture = null; - - private TextureUtils() { - } - - public static void setUpTextures() { - String textureSet = "Default"; - if (AbstractLookAndFeel.getTheme() != null) { - textureSet = AbstractLookAndFeel.getTheme().getTextureSet(); - } - if (textureSet.startsWith("Rock")) { - windowTexture = new LazyImageIcon("texture/patterns/rock/window_texture.jpg"); - backgroundTexture = new LazyImageIcon("texture/patterns/rock/background_texture.jpg"); - alterBackgroundTexture = new LazyImageIcon("texture/patterns/rock/alter_background_texture.jpg"); - //selectedTexture = new LazyImageIcon("texture/patterns/rock/selected_texture.jpg"); - selectedTexture = new LazyImageIcon("texture/patterns/rock/window_texture.jpg"); - rolloverTexture = new LazyImageIcon("texture/patterns/rock/rollover_texture.jpg"); - pressedTexture = new LazyImageIcon("texture/patterns/rock/pressed_texture.jpg"); - //disabledTexture = new LazyImageIcon("texture/patterns/rock/disabled_texture.jpg"); - disabledTexture = new LazyImageIcon("texture/patterns/rock/background_texture.jpg"); - menubarTexture = new LazyImageIcon("texture/patterns/rock/menubar_texture.jpg"); - } else if (textureSet.startsWith("Textile")) { - windowTexture = new LazyImageIcon("texture/patterns/textile/window_texture.jpg"); - backgroundTexture = new LazyImageIcon("texture/patterns/textile/background_texture.jpg"); - alterBackgroundTexture = new LazyImageIcon("texture/patterns/textile/alter_background_texture.jpg"); - //selectedTexture = new LazyImageIcon("texture/patterns/textile/selected_texture.jpg"); - selectedTexture = new LazyImageIcon("texture/patterns/textile/window_texture.jpg"); - rolloverTexture = new LazyImageIcon("texture/patterns/textile/rollover_texture.jpg"); - //pressedTexture = new LazyImageIcon("texture/patterns/textile/pressed_texture.jpg"); - pressedTexture = new LazyImageIcon("texture/patterns/textile/rollover_texture.jpg"); - //disabledTexture = new LazyImageIcon("texture/patterns/textile/disabled_texture.jpg"); - disabledTexture = new LazyImageIcon("texture/patterns/textile/background_texture.jpg"); - menubarTexture = new LazyImageIcon("texture/patterns/textile/menubar_texture.jpg"); - } else if (textureSet.startsWith("Snow")) { - windowTexture = new LazyImageIcon("texture/patterns/snow/window_texture.jpg"); - backgroundTexture = new LazyImageIcon("texture/patterns/snow/background_texture.jpg"); - alterBackgroundTexture = new LazyImageIcon("texture/patterns/snow/alter_background_texture.jpg"); - selectedTexture = new LazyImageIcon("texture/patterns/snow/selected_texture.jpg"); - rolloverTexture = new LazyImageIcon("texture/patterns/snow/rollover_texture.jpg"); - pressedTexture = new LazyImageIcon("texture/patterns/snow/pressed_texture.jpg"); - //disabledTexture = new LazyImageIcon("texture/patterns/snow/disabled_texture.jpg"); - disabledTexture = new LazyImageIcon("texture/patterns/snow/background_texture.jpg"); - //menubarTexture = new LazyImageIcon("texture/patterns/snow/menubar_texture.jpg"); - menubarTexture = new LazyImageIcon("texture/patterns/snow/window_texture.jpg"); - } else { - windowTexture = new LazyImageIcon("texture/patterns/leather/window_texture.jpg"); - backgroundTexture = new LazyImageIcon("texture/patterns/leather/background_texture.jpg"); - alterBackgroundTexture = new LazyImageIcon("texture/patterns/leather/alter_background_texture.jpg"); - //selectedTexture = new LazyImageIcon("texture/patterns/leather/selected_texture.jpg"); - selectedTexture = new LazyImageIcon("texture/patterns/leather/window_texture.jpg"); - rolloverTexture = new LazyImageIcon("texture/patterns/leather/rollover_texture.jpg"); - pressedTexture = new LazyImageIcon("texture/patterns/leather/pressed_texture.jpg"); - //disabledTexture = new LazyImageIcon("texture/patterns/leather/disabled_texture.jpg"); - disabledTexture = new LazyImageIcon("texture/patterns/leather/background_texture.jpg"); - menubarTexture = new LazyImageIcon("texture/patterns/leather/menubar_texture.jpg"); - } - - Icon texture = AbstractLookAndFeel.getTheme().getWindowTexture(); - if (texture != null) { - windowTexture = texture; - } - texture = AbstractLookAndFeel.getTheme().getBackgroundTexture(); - if (texture != null) { - backgroundTexture = texture; - } - texture = AbstractLookAndFeel.getTheme().getAlterBackgroundTexture(); - if (texture != null) { - alterBackgroundTexture = texture; - } - texture = AbstractLookAndFeel.getTheme().getSelectedTexture(); - if (texture != null) { - selectedTexture = texture; - } - texture = AbstractLookAndFeel.getTheme().getRolloverTexture(); - if (texture != null) { - rolloverTexture = texture; - } - texture = AbstractLookAndFeel.getTheme().getPressedTexture(); - if (texture != null) { - pressedTexture = texture; - } - texture = AbstractLookAndFeel.getTheme().getDisabledTexture(); - if (texture != null) { - disabledTexture = texture; - } - texture = AbstractLookAndFeel.getTheme().getMenubarTexture(); - if (texture != null) { - menubarTexture = texture; - } - } - - public static int getTextureType(JComponent c) { - int textureType = TextureUtils.BACKGROUND_TEXTURE_TYPE; - Object textureProperty = c.getClientProperty("textureType"); - if (textureProperty instanceof Integer) { - int bt = ((Integer)textureProperty).intValue(); - if (bt >= 0 && bt <= TextureUtils.LAST_TEXTURE_TYPE) { - textureType = bt; - } - } - return textureType; - } - - private static Icon getTexture(int textureType) { - Icon texture = null; - switch (textureType) { - case WINDOW_TEXTURE_TYPE: texture = windowTexture; break; - case BACKGROUND_TEXTURE_TYPE: texture = backgroundTexture; break; - case ALTER_BACKGROUND_TEXTURE_TYPE: texture = alterBackgroundTexture; break; - case SELECTED_TEXTURE_TYPE: texture = selectedTexture; break; - case ROLLOVER_TEXTURE_TYPE: texture = rolloverTexture; break; - case PRESSED_TEXTURE_TYPE: texture = pressedTexture; break; - case DISABLED_TEXTURE_TYPE: texture = disabledTexture; break; - case MENUBAR_TEXTURE_TYPE: texture = menubarTexture; break; - } - return texture; - } - - public static void fillComponent(Graphics g, Component c, int textureType) { - JTattooUtilities.fillComponent(g, c, getTexture(textureType)); - } - - public static void fillComponent(Graphics g, Component c, int x, int y, int w, int h, int textureType) { - Graphics2D g2D = (Graphics2D) g; - Shape savedClip = g2D.getClip(); - Area clipArea = new Area(new Rectangle2D.Double(x, y, w, h)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - Icon texture = getTexture(textureType); - if (texture != null) { - int tw = texture.getIconWidth(); - int th = texture.getIconHeight(); - Point p = JTattooUtilities.getRelLocation(c); - int ys = y - p.y; - while (ys < (y + h)) { - int xs = x - p.x; - while (xs < (x + w)) { - texture.paintIcon(c, g, xs, ys); - xs += tw; - } - ys += th; - } - } else { - g.setColor(c.getBackground()); - g.fillRect(x, y, w, h); - } - g2D.setClip(savedClip); - } - - public static void fillRect(Graphics g, Component c, int x, int y, int w, int h, int textureType) { - Graphics2D g2D = (Graphics2D) g; - Shape savedClip = g2D.getClip(); - Area clipArea = new Area(new Rectangle2D.Double(x, y, w, h)); - clipArea.intersect(new Area(savedClip)); - g2D.setClip(clipArea); - Icon texture = getTexture(textureType); - if (texture != null) { - int tw = texture.getIconWidth(); - int th = texture.getIconHeight(); - int ys = y; - while (ys < (y + h)) { - int xs = x; - while (xs < (x + w)) { - texture.paintIcon(c, g, xs, ys); - xs += tw; - } - ys += th; - } - } else { - g.setColor(c.getBackground()); - g.fillRect(x, y, w, h); - } - g2D.setClip(savedClip); - } -} diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/DownArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/texture/icons/DownArrow.gif deleted file mode 100644 index 53d2f1577..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/DownArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/HorRubber.gif b/src/jtattoo/src/com/jtattoo/plaf/texture/icons/HorRubber.gif deleted file mode 100644 index c54e65327..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/HorRubber.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/LeftArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/texture/icons/LeftArrow.gif deleted file mode 100644 index 5df254275..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/LeftArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/RightArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/texture/icons/RightArrow.gif deleted file mode 100644 index 808180eda..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/RightArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/SplitterHorBumps.gif b/src/jtattoo/src/com/jtattoo/plaf/texture/icons/SplitterHorBumps.gif deleted file mode 100644 index 2d3e03622..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/SplitterHorBumps.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/SplitterVerBumps.gif b/src/jtattoo/src/com/jtattoo/plaf/texture/icons/SplitterVerBumps.gif deleted file mode 100644 index 2528534b9..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/SplitterVerBumps.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/UpArrow.gif b/src/jtattoo/src/com/jtattoo/plaf/texture/icons/UpArrow.gif deleted file mode 100644 index 58ee69c93..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/UpArrow.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/VerRubber.gif b/src/jtattoo/src/com/jtattoo/plaf/texture/icons/VerRubber.gif deleted file mode 100644 index 331232410..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/VerRubber.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/thumb_hor.gif b/src/jtattoo/src/com/jtattoo/plaf/texture/icons/thumb_hor.gif deleted file mode 100644 index 5003babc8..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/thumb_hor.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/thumb_hor_rollover.gif b/src/jtattoo/src/com/jtattoo/plaf/texture/icons/thumb_hor_rollover.gif deleted file mode 100644 index 0a7aa097e..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/thumb_hor_rollover.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/thumb_ver.gif b/src/jtattoo/src/com/jtattoo/plaf/texture/icons/thumb_ver.gif deleted file mode 100644 index ba23871e9..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/thumb_ver.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/thumb_ver_rollover.gif b/src/jtattoo/src/com/jtattoo/plaf/texture/icons/thumb_ver_rollover.gif deleted file mode 100644 index 74d5fcb7e..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/icons/thumb_ver_rollover.gif and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/alter_background_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/alter_background_texture.jpg deleted file mode 100644 index 18c55dd80..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/alter_background_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/background_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/background_texture.jpg deleted file mode 100644 index 9463b01bf..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/background_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/menubar_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/menubar_texture.jpg deleted file mode 100644 index 144eee869..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/menubar_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/pressed_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/pressed_texture.jpg deleted file mode 100644 index 8069784ee..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/pressed_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/rollover_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/rollover_texture.jpg deleted file mode 100644 index 468b2cacb..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/rollover_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/window_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/window_texture.jpg deleted file mode 100644 index 189629503..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/leather/window_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/alter_background_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/alter_background_texture.jpg deleted file mode 100644 index 275d4a165..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/alter_background_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/background_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/background_texture.jpg deleted file mode 100644 index d1215e901..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/background_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/menubar_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/menubar_texture.jpg deleted file mode 100644 index d0b426fc2..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/menubar_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/pressed_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/pressed_texture.jpg deleted file mode 100644 index ae98a6419..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/pressed_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/rollover_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/rollover_texture.jpg deleted file mode 100644 index 2038c2943..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/rollover_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/window_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/window_texture.jpg deleted file mode 100644 index 9e622f6e3..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/rock/window_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/alter_background_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/alter_background_texture.jpg deleted file mode 100644 index c8d8fada2..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/alter_background_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/background_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/background_texture.jpg deleted file mode 100644 index 25f68589e..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/background_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/pressed_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/pressed_texture.jpg deleted file mode 100644 index c97a54c4d..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/pressed_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/rollover_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/rollover_texture.jpg deleted file mode 100644 index fcf0aeeb9..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/rollover_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/selected_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/selected_texture.jpg deleted file mode 100644 index 21f869848..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/selected_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/window_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/window_texture.jpg deleted file mode 100644 index a9220bad5..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/snow/window_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/textile/alter_background_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/textile/alter_background_texture.jpg deleted file mode 100644 index f4761f026..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/textile/alter_background_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/textile/background_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/textile/background_texture.jpg deleted file mode 100644 index eef328775..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/textile/background_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/textile/menubar_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/textile/menubar_texture.jpg deleted file mode 100644 index d17922412..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/textile/menubar_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/textile/rollover_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/textile/rollover_texture.jpg deleted file mode 100644 index 2ee2c5907..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/textile/rollover_texture.jpg and /dev/null differ diff --git a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/textile/window_texture.jpg b/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/textile/window_texture.jpg deleted file mode 100644 index 6911e551b..000000000 Binary files a/src/jtattoo/src/com/jtattoo/plaf/texture/patterns/textile/window_texture.jpg and /dev/null differ diff --git a/src/plugins/apple/ApplePlugin.iml b/src/plugins/apple/ApplePlugin.iml deleted file mode 100644 index 069e88071..000000000 --- a/src/plugins/apple/ApplePlugin.iml +++ /dev/null @@ -1,191 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/apple/build.xml b/src/plugins/apple/build.xml deleted file mode 100644 index 2877cf310..000000000 --- a/src/plugins/apple/build.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/plugins/apple/resources/images/X.png b/src/plugins/apple/resources/images/X.png deleted file mode 100644 index d3ebbad4c..000000000 Binary files a/src/plugins/apple/resources/images/X.png and /dev/null differ diff --git a/src/plugins/apple/resources/images/badge.png b/src/plugins/apple/resources/images/badge.png deleted file mode 100644 index 2e1f46ac0..000000000 Binary files a/src/plugins/apple/resources/images/badge.png and /dev/null differ diff --git a/src/plugins/apple/resources/images/bounce.png b/src/plugins/apple/resources/images/bounce.png deleted file mode 100644 index a75403d3e..000000000 Binary files a/src/plugins/apple/resources/images/bounce.png and /dev/null differ diff --git a/src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/AppleBounce.java b/src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/AppleBounce.java deleted file mode 100644 index 18644e6a5..000000000 --- a/src/plugins/apple/src/com/jivesoftware/spark/plugin/apple/AppleBounce.java +++ /dev/null @@ -1,125 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.jivesoftware.spark.plugin.apple; - -import org.jivesoftware.spark.SparkManager; - -import com.apple.eawt.Application; - -/** - * Utilities for dealing with the apple dockicon - * - * @author Wolf.Posdorfer - */ -public final class AppleBounce { - - private boolean _flash; - final Application _app; - private AppleProperties _props; - - @SuppressWarnings("deprecation") - public AppleBounce(AppleProperties props) { - _app = new Application(); - _props = props; - - final Thread iconThread = new Thread(new Runnable() { - - public void run() { - while (true) { - if (!_flash) { - setDockBadge(_app, getMessageCount()); - try { - Thread.sleep(100); - } catch (InterruptedException e) { - } - } else { - - setDockBadge(_app, getMessageCount()); - try { - Thread.sleep(500); - } catch (InterruptedException e) { - } - setDockBadge(_app, getMessageCount()); - try { - Thread.sleep(500); - } catch (InterruptedException e) { - } - - } - - } - } - }); - - iconThread.start(); - - } - - /** - * Sets Flashing to false - */ - public void resetDock() { - if (_flash) { - _flash = false; - } - } - - /** - * Returns a String of the current unread message count - * - * @return String like "10" - */ - public static String getMessageCount() { - int no = SparkManager.getChatManager().getChatContainer().getTotalNumberOfUnreadMessages(); - - if (no > 999) - no = 999; - - if (no == 0) { - return ""; - } else { - return "" + no; - } - - } - - /** - * Sets the Dock badge off the {@link Application} to the specified String - * - * @param app - * @param s - */ - public void setDockBadge(Application app, String s) { - if (_props.getDockBadges()) - app.setDockIconBadge(s); - } - - /** - * Bounce the application's dock icon to get the user's attention. - * - * @param critical - * Bounce the icon repeatedly if this is true. Bounce it only - * once if this is false. - */ - public void bounceDockIcon(boolean critical) { - _app.requestUserAttention(critical); - } - -} diff --git a/src/plugins/apple/src/plugin.xml b/src/plugins/apple/src/plugin.xml deleted file mode 100644 index 7c904f2c7..000000000 --- a/src/plugins/apple/src/plugin.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - Mac OSX Plugin - 2.1 - Wolf Posdorfer - http://www.jivesoftware.com - 9posdorf@informatik.uni-hamburg.de - Adds MacOSX features to Spark - com.jivesoftware.spark.plugin.apple.ApplePlugin - 2.7.0 - Mac - 1.7.0 - - diff --git a/src/plugins/battleships/build/build.xml b/src/plugins/battleships/build/build.xml deleted file mode 100644 index 3c48a7d8e..000000000 --- a/src/plugins/battleships/build/build.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/battleships/plugin.xml b/src/plugins/battleships/plugin.xml deleted file mode 100644 index 65218ca20..000000000 --- a/src/plugins/battleships/plugin.xml +++ /dev/null @@ -1,12 +0,0 @@ - - Battleships - battleship.BattleshipPlugin - Wolf Posdorfer - 0.1 - http://www.jivesoftware.com - Battleship plugin for Spark - 9posdorf@informatik.uni-hamburg.de - 2.7.0 - Windows,Linux,Mac - 1.7.0 - diff --git a/src/plugins/battleships/src/java/battleship/BattleshipPlugin.java b/src/plugins/battleships/src/java/battleship/BattleshipPlugin.java deleted file mode 100644 index 9deb89102..000000000 --- a/src/plugins/battleships/src/java/battleship/BattleshipPlugin.java +++ /dev/null @@ -1,146 +0,0 @@ -package battleship; - -import java.awt.Color; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.StanzaListener; -import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.packet.Stanza; -import org.jivesoftware.smack.provider.ProviderManager; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.ChatRoom; - -import battleship.listener.ChatRoomOpeningListener; -import battleship.packets.GameOfferPacket; -import battleship.packets.MoveAnswerPacket; -import battleship.packets.MovePacket; -import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; - - -public class BattleshipPlugin implements Plugin{ - - - private StanzaListener _gameofferListener; - private ChatRoomOpeningListener _chatRoomListener; - - @Override - public void initialize() { - - ProviderManager.addIQProvider(GameOfferPacket.ELEMENT_NAME, GameOfferPacket.NAMESPACE, GameOfferPacket.class); - ProviderManager.addExtensionProvider(MovePacket.ELEMENT_NAME, MovePacket.NAMESPACE, MovePacket.class); - ProviderManager.addExtensionProvider(MoveAnswerPacket.ELEMENT_NAME, MoveAnswerPacket.NAMESPACE, MoveAnswerPacket.class); - - - _gameofferListener = new StanzaListener() { - - @Override - public void processPacket(Stanza stanza) { - GameOfferPacket invitation = (GameOfferPacket) stanza; - if (invitation.getType() == IQ.Type.get) { - showInvitationInChat(invitation); - } - } - }; - - SparkManager.getConnection().addAsyncStanzaListener(_gameofferListener, - new StanzaTypeFilter(GameOfferPacket.class)); - - _chatRoomListener = new ChatRoomOpeningListener(); - - SparkManager.getChatManager().addChatRoomListener(_chatRoomListener); - - - - } - - private void showInvitationInChat(final GameOfferPacket invitation) { - invitation.setType(IQ.Type.result); - invitation.setTo(invitation.getFrom()); - - - final ChatRoom room = SparkManager.getChatManager().getChatRoom(XmppStringUtils.parseBareJid(invitation.getFrom())); - - String name = XmppStringUtils.parseLocalpart(invitation.getFrom()); - final JPanel panel = new JPanel(); - JLabel text = new JLabel("Game request from" + name); - JLabel game = new JLabel("Battleships"); - game.setFont(new Font("Dialog", Font.BOLD, 24)); - game.setForeground(Color.RED); - JButton accept = new JButton(Res.getString("button.accept").replace("&", "")); - JButton decline = new JButton(Res.getString("button.decline").replace("&", "")); - panel.add(text); - panel.add(game); - panel.add(accept); - panel.add(decline); - room.getTranscriptWindow().addComponent(panel); - - accept.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - try - { - SparkManager.getConnection().sendStanza(invitation); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to send invitation accept to " + invitation.getTo(), e1 ); - } - invitation.setStartingPlayer(!invitation.isStartingPlayer()); - ChatRoomOpeningListener.createWindow(invitation, invitation.getFrom()); - panel.remove(3); - panel.remove(2); - panel.repaint(); - panel.revalidate(); - } - }); - - decline.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - invitation.setType(IQ.Type.error); - try - { - SparkManager.getConnection().sendStanza(invitation); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to send invitation decline to " + invitation.getTo(), e1 ); - } - panel.remove(3); - panel.remove(2); - panel.repaint(); - panel.revalidate(); - } - }); - - - } - - @Override - public void shutdown() { - - } - - @Override - public boolean canShutDown() { - return false; - } - - @Override - public void uninstall() { - - } - -} diff --git a/src/plugins/battleships/src/java/battleship/BsRes.java b/src/plugins/battleships/src/java/battleship/BsRes.java deleted file mode 100644 index c37613241..000000000 --- a/src/plugins/battleships/src/java/battleship/BsRes.java +++ /dev/null @@ -1,37 +0,0 @@ -package battleship; - -import java.text.MessageFormat; -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; - -import org.jivesoftware.spark.util.log.Log; - - -public class BsRes { - private static PropertyResourceBundle prb; - - static ClassLoader cl = BsRes.class.getClassLoader(); - - static { - prb = (PropertyResourceBundle) ResourceBundle - .getBundle("i18n/battleships_i18n"); - } - - public static final String getString(String propertyName) { - try { - return prb.getString(propertyName); - } catch (Exception e) { - Log.error(e); - return propertyName; - } - } - - public static String getString(String propertyName, Object... obj) { - String str = prb.getString(propertyName); - if (str == null) { - return propertyName; - } - - return MessageFormat.format(str, obj); - } -} diff --git a/src/plugins/battleships/src/java/battleship/gui/GUI.java b/src/plugins/battleships/src/java/battleship/gui/GUI.java deleted file mode 100644 index 9cfe72948..000000000 --- a/src/plugins/battleships/src/java/battleship/gui/GUI.java +++ /dev/null @@ -1,137 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package battleship.gui; - -import java.awt.BorderLayout; - -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import org.jivesoftware.smack.StanzaListener; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.filter.PacketExtensionFilter; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Stanza; - -import battleship.listener.ShipPlacementListener; -import battleship.logic.GameBoard; -import battleship.observer.Observeable; -import battleship.observer.Observer; -import battleship.packets.MoveAnswerPacket; -import battleship.packets.MovePacket; - -public class GUI extends JPanel implements Observer{ - - private static final long serialVersionUID = -7538765009749015196L; - - private Display _display; - private GameboardGUI _myfield; - private GameboardGUI _theirfield; - private JFrame _owner; - private XMPPConnection _connection; - private int _gameID; - private GameBoard _gameboard; - - private ShipPlacementListener _splistener; - - public GUI(boolean imStarting, JFrame owner, XMPPConnection connection, int gameID) { - setLayout(new BorderLayout()); - _owner = owner; - _connection = connection; - _gameID = gameID; - _gameboard = new GameBoard(imStarting); - - _display = new Display(); - _myfield = new GameboardGUI(); - _theirfield = new GameboardGUI(); - - JPanel West = new JPanel(new BorderLayout(0, 5)); - JPanel wnorth = new JPanel(new BorderLayout()); - wnorth.add(new JLabel("Their Board"), BorderLayout.NORTH); - wnorth.add(_theirfield, BorderLayout.SOUTH); - - JPanel wsouth = new JPanel(new BorderLayout()); - wsouth.add(new JLabel("My Board"), BorderLayout.NORTH); - wsouth.add(_myfield); - - JPanel East = new JPanel(); - West.add(wsouth, BorderLayout.SOUTH); - West.add(wnorth, BorderLayout.NORTH); - East.add(_display); - - add(East, BorderLayout.EAST); - add(West, BorderLayout.WEST); - - _connection.addAsyncStanzaListener(new StanzaListener() { - - @Override - public void processPacket(Stanza stanza) { - - MovePacket move = (MovePacket) stanza.getExtension( - MovePacket.ELEMENT_NAME, MovePacket.NAMESPACE); - - if (move.getGameID() == _gameID) { - boolean opponentMadeHit = _gameboard.placeBomb(move.getPositionX(), move.getPositionY()); - - if(opponentMadeHit) - { - Message m = createAnswer(move, stanza.getFrom()); - _connection.sendStanza(m); - } - } - - } - }, new PacketExtensionFilter(MovePacket.ELEMENT_NAME, - MovePacket.NAMESPACE)); - - // Start placing of the Ships - _splistener = new ShipPlacementListener(_display, _gameboard, _myfield); - _splistener.addObserver(this); - - _myfield.initiateShipPlacement(_splistener); - - } - - - private Message createAnswer(MovePacket incoming, String from) - { - Message answer = new Message(); - answer.setTo(from); - - MoveAnswerPacket map = new MoveAnswerPacket(); - map.setGameID(incoming.getGameID()); - map.setPositionX(incoming.getPositionX()); - map.setPositionY(incoming.getPositionY()); - - - return answer; - } - - - @Override - public void update(Observeable obs) { - //TODO Initial ship placement is done - // Start with normal moves - obs.removeObserver(this); - - } - -} diff --git a/src/plugins/battleships/src/java/battleship/gui/GameboardGUI.java b/src/plugins/battleships/src/java/battleship/gui/GameboardGUI.java deleted file mode 100644 index 5e326f17a..000000000 --- a/src/plugins/battleships/src/java/battleship/gui/GameboardGUI.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package battleship.gui; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridLayout; -import java.awt.Image; -import java.awt.geom.AffineTransform; - -import javax.swing.BorderFactory; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import battleship.listener.ShipPlacementListener; -import battleship.types.Types; - -public class GameboardGUI extends JPanel{ - private static final long serialVersionUID = -6429298293488133059L; - - private Image _bg; - - private JLabel[][] _labels; - - public GameboardGUI() - { - ClassLoader cl = getClass().getClassLoader(); - _bg = new ImageIcon(cl.getResource("water.png")).getImage(); - - - setLayout(new GridLayout(10,10)); - - _labels = new JLabel[10][10]; - - for(int x =0 ; x<10;x++) - { - for(int y=0 ;y < 10; y++) - { - _labels[x][y] = new JLabel("empty"); - _labels[x][y].setBorder(BorderFactory.createLineBorder(Color.lightGray)); - add(_labels[x][y]); - } - } - - this.setPreferredSize(new Dimension(400,400)); - - } - - public void setField(int x, int y, Types t) - { - System.out.println("setting field"+x+","+y); - _labels[x][y].setIcon(t.getImage()); - repaint(); - revalidate(); - } - - - - public void paintComponent(Graphics g) { - super.paintComponent(g); - final Image backgroundImage = _bg; - double scaleX = getWidth() / (double) backgroundImage.getWidth(null); - double scaleY = getHeight() / (double) backgroundImage.getHeight(null); - AffineTransform xform = AffineTransform - .getScaleInstance(scaleX, scaleY); - ((Graphics2D) g).drawImage(backgroundImage, xform, this); - } - - - public void initiateShipPlacement(ShipPlacementListener spl) - { - for(int x =0 ; x<10;x++) - { - for(int y=0 ;y < 10; y++) - { - _labels[x][y].addMouseListener(spl); - } - } - - } - - public JLabel[][] getLabels() - { - return _labels; - } - - - -} diff --git a/src/plugins/battleships/src/java/battleship/listener/ChatRoomOpeningListener.java b/src/plugins/battleships/src/java/battleship/listener/ChatRoomOpeningListener.java deleted file mode 100644 index 534b8b8d1..000000000 --- a/src/plugins/battleships/src/java/battleship/listener/ChatRoomOpeningListener.java +++ /dev/null @@ -1,108 +0,0 @@ -package battleship.listener; - -import java.awt.Color; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JFrame; - - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.StanzaListener; -import org.jivesoftware.smack.filter.PacketIDFilter; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.packet.Stanza; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomButton; -import org.jivesoftware.spark.ui.ChatRoomListenerAdapter; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; - - -import battleship.BsRes; -import battleship.gui.GUI; -import battleship.packets.GameOfferPacket; -import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; - -public class ChatRoomOpeningListener extends ChatRoomListenerAdapter { - - @Override - public void chatRoomOpened(final ChatRoom room) { - - if (!(room instanceof ChatRoomImpl)) // Check for 1on1 Chat - { - return; - } - - final ChatRoomButton sendGameButton = new ChatRoomButton("BS"); - room.getToolBar().addChatRoomButton(sendGameButton); - final String opponentJID = ((ChatRoomImpl) room).getJID(); - - sendGameButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - - final GameOfferPacket offer = new GameOfferPacket(); - offer.setTo(opponentJID); - offer.setType(IQ.Type.get); - - room.getTranscriptWindow().insertCustomText( - BsRes.getString("request"), false, false, - Color.BLUE); - try - { - SparkManager.getConnection().sendStanza(offer); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to send offer to " + opponentJID, e1 ); - } - - SparkManager.getConnection().addAsyncStanzaListener( - new StanzaListener() { - @Override - public void processPacket(Stanza stanza) { - - GameOfferPacket answer = (GameOfferPacket) stanza; - answer.setStartingPlayer(offer - .isStartingPlayer()); - answer.setGameID(offer.getGameID()); - String name = XmppStringUtils.parseLocalpart(opponentJID); - if (answer.getType() == IQ.Type.result) { - // ACCEPT - - room.getTranscriptWindow() - .insertCustomText(BsRes.getString("accepted", name), false, - false, Color.BLUE); - - createWindow(answer, opponentJID); - } else { - // DECLINE - room.getTranscriptWindow() - .insertCustomText(BsRes.getString("declined", name), false, - false, Color.RED); - } - - } - }, new PacketIDFilter(offer.getPacketID())); - - } - - }); - - } - - public static void createWindow(GameOfferPacket answer, String opponentJID) { - - JFrame frame = new JFrame(BsRes.getString("versus", XmppStringUtils.parseLocalpart(opponentJID))); - frame.add(new GUI(answer.isStartingPlayer(),frame,SparkManager.getConnection(),answer.getGameID())); - frame.pack(); - frame.setLocationRelativeTo(SparkManager.getChatManager().getChatContainer()); - frame.setVisible(true); - - - } -} diff --git a/src/plugins/battleships/src/java/battleship/logic/GameBoard.java b/src/plugins/battleships/src/java/battleship/logic/GameBoard.java deleted file mode 100644 index 7292f7d69..000000000 --- a/src/plugins/battleships/src/java/battleship/logic/GameBoard.java +++ /dev/null @@ -1,171 +0,0 @@ -package battleship.logic; - -import java.util.ArrayList; -import java.util.List; - -import battleship.types.Direction; -import battleship.types.Ship; - -public class GameBoard { - - private Ship[][] _fields; - private Shipmodel[] _myships; - - private boolean myTurn; - - public GameBoard(boolean myTurn) { - this.myTurn = myTurn; - - _fields = new Ship[12][12]; - // Construct a 12x12 Gameboard with a surrounding void - // actual game is in [1][1] to [10][10] - _myships = new Shipmodel[5]; - _myships[0] = new Shipmodel(2); - _myships[1] = new Shipmodel(3); - _myships[2] = new Shipmodel(3); - _myships[3] = new Shipmodel(4); - _myships[4] = new Shipmodel(5); - - for (int x = 0; x < _fields.length; x++) { - for (int y = 0; y < _fields.length; y++) { - _fields[x][y] = Ship.EMPTY; - } - } - - } - - /** - * Places a Bomb of the Opponent on your field - * @param x - * @param y - * @return True if the Opponent hit a Ship, else false - */ - public boolean placeBomb(int x, int y) - { - // Add one to subtract the void fields - x = x+1; - y = y+1; - - if(_fields[x][y] != Ship.EMPTY) - { - Shipmodel smo =_myships[_fields[x][y].inArrayPosition()]; - smo.setBomb(); - return true; - } - else - { - myTurn=!myTurn; // Now its my turn - return false; - } - } - - /** - * Places a Ship on the Board - * Returns false if not placeable - * @param x - * @param y - * @param s - * @param dir - * @return - */ - public List placeShip(int x, int y, Ship s, Direction dir) { - boolean placementOK = true; - - x = x+1; - y = y+1; - List liste = new ArrayList(); - - System.out.println("placing ship"); - if (dir == Direction.HORIZONTAL) // Left to Right - { - for (int i = x; i < x+s.getFields(); i++) { - if (!checkSurrounding(i, y)) - System.out.println("checking "+i+","+y); - placementOK = false; - } - - if (placementOK) { - for (int i = x,j = 0; i < x+s.getFields(); i++,j++) { - _fields[i][y] = s; - System.out.println("adding coord at horiz"+j); - liste.add( new CoordinatePair(i, y)); - } - } - } else // top to bottom - { - - for (int i = y; i < y+s.getFields(); i++) { - if (!checkSurrounding(x, i)) - System.out.println("checking "+i+","+y); - placementOK = false; - } - - if (placementOK) { - for (int i = y,j=0; i < y+s.getFields(); i++,j++) { - _fields[x][i] = s; - liste.add(new CoordinatePair(x, i)); - System.out.println("adding coord at vert"+j); - - } - } - } - - System.out.println("placement ok? "+placementOK); - - if (!placementOK) - return null; - else - return liste; - } - - /** - * Checks the surrounding fields for collision - * @param x - * @param y - * @return - */ - private boolean checkSurrounding(int x, int y) { - - if(x < 1 || x > 10) - { - System.out.println("1"); - return false; - } - if(y < 1 || y > 10) - { - System.out.println("2"); - return false; - } - - if (_fields[x - 1][y - 1] != Ship.EMPTY - || _fields[x][y - 1] != Ship.EMPTY - || _fields[x + 1][y - 1] != Ship.EMPTY) - { - System.out.println("3"); - return false; - } - else if (_fields[x - 1][y] != Ship.EMPTY - || _fields[x][y] != Ship.EMPTY - || _fields[x + 1][y] != Ship.EMPTY) - { - System.out.println("4"); - return false; - } - else if (_fields[x - 1][y + 1] != Ship.EMPTY - || _fields[x][y + 1] != Ship.EMPTY - || _fields[x + 1][y + 1] != Ship.EMPTY) - { - System.out.println("5"); - return false; - } - else - return true; - } - - public int getField(int x, int y) - { - Ship s = _fields[x][y]; - return s.getFields(); - } - -} diff --git a/src/plugins/battleships/src/java/battleship/logic/Shipmodel.java b/src/plugins/battleships/src/java/battleship/logic/Shipmodel.java deleted file mode 100644 index 6370dd1fc..000000000 --- a/src/plugins/battleships/src/java/battleship/logic/Shipmodel.java +++ /dev/null @@ -1,41 +0,0 @@ -package battleship.logic; - -public class Shipmodel { - - - private int[] _ship; - - public Shipmodel(int size) - { - _ship = new int[size]; - } - - public void setBomb() - { - - for(int i=0; i<_ship.length;i++) - { - if(_ship[i]==0) - { - _ship[i]=1; - break; - } - } - } - - public boolean isDestroyed() - { - boolean dest = true; - for(int i=0; i<_ship.length && dest; i++) - { - dest= _ship[i]!=0; - } - - return dest; - } - - public int getSize() - { - return _ship.length; - } -} diff --git a/src/plugins/battleships/src/java/battleship/packets/GameOfferPacket.java b/src/plugins/battleships/src/java/battleship/packets/GameOfferPacket.java deleted file mode 100644 index eadef2c3a..000000000 --- a/src/plugins/battleships/src/java/battleship/packets/GameOfferPacket.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package battleship.packets; - -import java.util.Random; - -import org.jivesoftware.smack.packet.IQ; - -/** - * The Game Offer Packet - * - * @author wolf.posdorfer - * @version 20.06.2011 - */ -public class GameOfferPacket extends IQ { - - public static final String ELEMENT_NAME = "battleship"; - public static final String NAMESPACE = "battleship"; - - private int gameID; - private boolean imTheStartingPlayer; - - public GameOfferPacket() { - super(ELEMENT_NAME, NAMESPACE); - imTheStartingPlayer = new Random().nextBoolean(); - gameID = Math.abs(new Random().nextInt()); - } - - /** - * Returns the game ID. - * - * @return the game ID. - */ - public int getGameID() { - return gameID; - } - - /** - * Sets the game ID. - * - * @param gameID - * the game ID. - */ - public void setGameID(int gameID) { - this.gameID = gameID; - } - - /** - * Returns true if the user making the game invitation is the starting - * player. - * - * @return true if the user making the game invite is the starting player. - */ - public boolean isStartingPlayer() { - return imTheStartingPlayer; - } - - /** - * Sets whether the user making the game invitation is the starting player. - * - * @param startingPlayer - * true if the user making the game invite is the starting - * player. - */ - public void setStartingPlayer(boolean startingPlayer) { - this.imTheStartingPlayer = startingPlayer; - } - - @Override - protected IQChildElementXmlStringBuilder getIQChildElementBuilder( IQChildElementXmlStringBuilder buf ) - { - buf.rightAngleBracket(); - buf.append("<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">"); - if (getType() == IQ.Type.get) { - buf.append("").append(Integer.toString( gameID )).append(""); - buf.append("").append(Boolean.toString( imTheStartingPlayer )).append(""); - buf.append(getExtensionsXML()); - } - buf.append(""); - return buf; - } - -} diff --git a/src/plugins/battleships/src/java/battleship/packets/MoveAnswerPacket.java b/src/plugins/battleships/src/java/battleship/packets/MoveAnswerPacket.java deleted file mode 100644 index 13812e875..000000000 --- a/src/plugins/battleships/src/java/battleship/packets/MoveAnswerPacket.java +++ /dev/null @@ -1,118 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package battleship.packets; - -import org.jivesoftware.smack.packet.ExtensionElement; - -/** - * The MoveAnswer Packet Extension - * - * @author wolf.posdorfer - * @version 20.06.2011 - */ -public class MoveAnswerPacket implements ExtensionElement -{ - - public static final String ELEMENT_NAME = "bs-move"; - public static final String NAMESPACE = "battleship"; - - private int posx; - private int posy; - private int gameID; - private int hit; - private int shiptype; - - public int getGameID() { - return gameID; - } - - public void setGameID(int gameID) { - this.gameID = gameID; - } - - @Override - public String getElementName() { - return ELEMENT_NAME; - } - - @Override - public String getNamespace() { - return NAMESPACE; - } - - public int getPositionX() { - return posx; - } - - public void setPositionX(int posx) { - this.posx = posx; - } - - public int getPositionY() { - return posy; - } - - public void setPositionY(int posy) { - this.posy = posy; - } - - public int getHit() - { - return hit; - } - - public void setHit(int hit) - { - this.hit = hit; - } - - public void setShiptype(int x) - { - this.shiptype = x; - } - - public int getShiptype() - { - return shiptype; - } - - - @Override - public String toXML() { - - StringBuffer buf = new StringBuffer(); - buf.append("<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">"); - - buf.append("").append(gameID).append(""); - - buf.append("").append(posx).append(""); - - buf.append("").append(posy).append(""); - - buf.append("").append(hit).append(""); - - buf.append("").append(shiptype).append(""); - - buf.append(""); - return buf.toString(); - - } - -} diff --git a/src/plugins/battleships/src/java/battleship/packets/MovePacket.java b/src/plugins/battleships/src/java/battleship/packets/MovePacket.java deleted file mode 100644 index ef580429e..000000000 --- a/src/plugins/battleships/src/java/battleship/packets/MovePacket.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package battleship.packets; - -import org.jivesoftware.smack.packet.ExtensionElement; - -/** - * The Move Packet extension - * - * @author wolf.posdorfer - * @version 20.06.2011 - */ -public class MovePacket implements ExtensionElement { - - public static final String ELEMENT_NAME = "bs-move"; - public static final String NAMESPACE = "battleship"; - - private int posx; - private int posy; - private int gameID; - - public int getGameID() { - return gameID; - } - - public void setGameID(int gameID) { - this.gameID = gameID; - } - - @Override - public String getElementName() { - return ELEMENT_NAME; - } - - @Override - public String getNamespace() { - return NAMESPACE; - } - - public int getPositionX() { - return posx; - } - - public void setPositionX(int posx) { - this.posx = posx; - } - - public int getPositionY() { - return posy; - } - - public void setPositionY(int posy) { - this.posy = posy; - } - - @Override - public String toXML() { - - StringBuffer buf = new StringBuffer(); - buf.append("<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">"); - - buf.append("").append(gameID).append(""); - - buf.append("").append(posx).append(""); - - buf.append("").append(posy).append(""); - - buf.append(""); - return buf.toString(); - - } - -} diff --git a/src/plugins/battleships/src/java/battleship/types/Direction.java b/src/plugins/battleships/src/java/battleship/types/Direction.java deleted file mode 100644 index 50f2420ac..000000000 --- a/src/plugins/battleships/src/java/battleship/types/Direction.java +++ /dev/null @@ -1,7 +0,0 @@ -package battleship.types; - -public enum Direction { - - HORIZONTAL, VERTICAL; - -} diff --git a/src/plugins/battleships/src/java/battleship/types/Ship.java b/src/plugins/battleships/src/java/battleship/types/Ship.java deleted file mode 100644 index 199d728ad..000000000 --- a/src/plugins/battleships/src/java/battleship/types/Ship.java +++ /dev/null @@ -1,129 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package battleship.types; - -import java.awt.Image; - -import javax.swing.ImageIcon; - -public enum Ship { - - EMPTY("empty.png"), TWO("2.png"), THREE("3.png"), THREE2("3.png"), FOUR("4.png"), FIVE("5.png"); - - private String image; - - private Ship(String s) { - image = s; - } - - public ImageIcon getImage() { - ClassLoader cl = getClass().getClassLoader(); - return new ImageIcon(cl.getResource(image)); - } - - public static Ship valueOf(int x) { - switch (x) { - case 2: - return TWO; - case 3: - return THREE; - case 4: - return THREE2; - case 5: - return FOUR; - case 6: - return FIVE; - default: - return EMPTY; - } - - } - - /** - * Returns the Position inside the Array - * @return - */ - public int inArrayPosition() { - switch (this) { - case TWO: - return 0; - case THREE: - return 1; - case THREE2: - return 2; - case FOUR: - return 3; - case FIVE: - return 4; - default: - return 0; - } - } - - /** - * Returns the Occupying Fields - * @return - */ - public int getFields() { - switch (this) { - case TWO: - return 2; - case THREE: - return 3; - case THREE2: - return 3; - case FOUR: - return 4; - case FIVE: - return 5; - } - - return 0; - } - - public ImageIcon getScaledInstance(int w, int h, int hints) { - Image img = getImage().getImage(); - return new ImageIcon(img.getScaledInstance(w, h, hints)); - } - - /** - * Returns the next Bigger Ship
        - * 2 -> 3.1 -> 3.2 -> 4 -> 5 -> 2..... - * - * @return - */ - public Ship increment() { - - switch (this) { - case TWO: - return THREE; - case THREE: - return THREE2; - case THREE2: - return FOUR; - case FOUR: - return FIVE; - case FIVE: - return TWO; - } - - return TWO; - } -} diff --git a/src/plugins/battleships/src/java/battleship/types/Types.java b/src/plugins/battleships/src/java/battleship/types/Types.java deleted file mode 100644 index 4da485d6e..000000000 --- a/src/plugins/battleships/src/java/battleship/types/Types.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package battleship.types; - -import javax.swing.ImageIcon; - -public enum Types { - - EMPTY("empty.png"), - MISS("miss.png"), - SHIP("ship.png"), - SHIPHIT("shiphit.png"); - - public Types getValue(int x) { - switch (x) { - case 1: - return MISS; - case 2: - return SHIP; - case 3: - return SHIPHIT; - default: - return EMPTY; - } - - } - - private String _iconme; - - private Types(String iconme) { - _iconme=iconme; - } - - public ImageIcon getImage() - { - ClassLoader cl = getClass().getClassLoader(); - return new ImageIcon(cl.getResource(_iconme)); - } -} diff --git a/src/plugins/battleships/src/resources/4.png b/src/plugins/battleships/src/resources/4.png deleted file mode 100644 index 52dcb74e4..000000000 Binary files a/src/plugins/battleships/src/resources/4.png and /dev/null differ diff --git a/src/plugins/battleships/src/resources/_hit.png b/src/plugins/battleships/src/resources/_hit.png deleted file mode 100644 index 40498950c..000000000 Binary files a/src/plugins/battleships/src/resources/_hit.png and /dev/null differ diff --git a/src/plugins/battleships/src/resources/_nohit.png b/src/plugins/battleships/src/resources/_nohit.png deleted file mode 100644 index 56cb0232c..000000000 Binary files a/src/plugins/battleships/src/resources/_nohit.png and /dev/null differ diff --git a/src/plugins/battleships/src/resources/empty.png b/src/plugins/battleships/src/resources/empty.png deleted file mode 100644 index fe4a113fd..000000000 Binary files a/src/plugins/battleships/src/resources/empty.png and /dev/null differ diff --git a/src/plugins/battleships/src/resources/i18n/battleships_i18n.properties b/src/plugins/battleships/src/resources/i18n/battleships_i18n.properties deleted file mode 100644 index 6b574f3ad..000000000 --- a/src/plugins/battleships/src/resources/i18n/battleships_i18n.properties +++ /dev/null @@ -1,11 +0,0 @@ -########################### -# Battleships # -# by wolf.posdorfer # -########################### - -title = Battleships -versus = Battleships versus {0} -request = You requested a game of Battleships -has.request = {0} has requested a game of Battleships -accepted = {0} has accepted the invitation -declined = {0} has declined the invitation diff --git a/src/plugins/battleships/src/resources/i18n/battleships_i18n_lt.properties b/src/plugins/battleships/src/resources/i18n/battleships_i18n_lt.properties deleted file mode 100644 index 9b5f8b4dd..000000000 --- a/src/plugins/battleships/src/resources/i18n/battleships_i18n_lt.properties +++ /dev/null @@ -1,12 +0,0 @@ -########################### -# Battleships # -# by wolf.posdorfer # -########################### -# translation by wroot - -title = J\u016bros m\u016b\u0161is -versus = J\u016bros m\u016b\u0161is prie\u0161 {0} -request = J\u016bs u\u017eklaus\u0117t J\u016bros m\u016b\u0161is \u017eaidimo -has.request = {0} u\u017eklaus\u0117 J\u016bros m\u016b\u0161is \u017eaidimo -accepted = {0} pri\u0117m\u0117 pakvietim\u0105 -declined = {0} atmet\u0117 pakvietim\u0105 \ No newline at end of file diff --git a/src/plugins/battleships/src/resources/miss.png b/src/plugins/battleships/src/resources/miss.png deleted file mode 100644 index 99c4a7619..000000000 Binary files a/src/plugins/battleships/src/resources/miss.png and /dev/null differ diff --git a/src/plugins/battleships/src/resources/ship.png b/src/plugins/battleships/src/resources/ship.png deleted file mode 100644 index 729f7502b..000000000 Binary files a/src/plugins/battleships/src/resources/ship.png and /dev/null differ diff --git a/src/plugins/battleships/src/resources/shiphit.png b/src/plugins/battleships/src/resources/shiphit.png deleted file mode 100644 index 68134c8b3..000000000 Binary files a/src/plugins/battleships/src/resources/shiphit.png and /dev/null differ diff --git a/src/plugins/battleships/src/resources/water.png b/src/plugins/battleships/src/resources/water.png deleted file mode 100644 index 8d2a0e32c..000000000 Binary files a/src/plugins/battleships/src/resources/water.png and /dev/null differ diff --git a/src/plugins/fastpath/Fastpath.iml b/src/plugins/fastpath/Fastpath.iml deleted file mode 100644 index eea9b3dfc..000000000 --- a/src/plugins/fastpath/Fastpath.iml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/fastpath/build/build.xml b/src/plugins/fastpath/build/build.xml deleted file mode 100644 index ad5129902..000000000 --- a/src/plugins/fastpath/build/build.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/fastpath/plugin.xml b/src/plugins/fastpath/plugin.xml deleted file mode 100644 index a90fb2618..000000000 --- a/src/plugins/fastpath/plugin.xml +++ /dev/null @@ -1,11 +0,0 @@ - - Fastpath - 3.2.2 - Jive Software - spark@jivesoftware.com - http://www.jivesoftware.com - Adds Fastpath functionality to Spark - org.jivesoftware.fastpath.FastpathPlugin - 2.7.0 - 1.7.0 - diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/internal/FormUtils.java b/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/internal/FormUtils.java deleted file mode 100644 index 11e505cb5..000000000 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/internal/FormUtils.java +++ /dev/null @@ -1,210 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.fastpath.internal; - -import org.jivesoftware.smack.packet.Message; -import org.jxmpp.util.XmppStringUtils; - -import java.util.Date; - -/** - * The WebUtils class is a utility class for some of the most - * mundane procedures in the WebChat client and in servlet programming. This - * will be moved over to a more suitable class down the line. Probably be handled - * in the com.jivesoftware.web.utils package to be used throughout Jive. - */ -final public class FormUtils { - private FormUtils() { - } - - /** - * Check to see if string has been assigned a value. This is generally used - * in web applications/applet when a user request a parameter from the parameter stack. - * - * @param str - the string to check. - * @return true if String has been assigned a value, false otherwise. - */ - final public static boolean isNotNull(String str) { - if (str != null && str.trim().length() > 0) { - return true; - } - - return false; - } - - /** - * Checks to see if the String is boolean value and will return the appropriate - * value - * - * @param str - the String to check - * @return true if the string is not null and the value is equal to true, false - * otherwise. - */ - final public static boolean isTrue(String str) { - return (str != null && str.equalsIgnoreCase("true")); - } - - - /** - * Checks to see if the data is applicable to be added to metadata. - * - * @param data the data to check for validity. - * @return true if the data is valid. - */ - public static boolean isValidData(String data) { - char[] chars = data.toCharArray(); - for (int i = 0; i < chars.length; i++) { - char c = chars[i]; - if (Character.isLetterOrDigit(c)) { - return true; - } - } - return false; - } - - - - /** - * Replaces all instances of oldString with newString in string. - * - * @param string the String to search to perform replacements on - * @param oldString the String that should be replaced by newString - * @param newString the String that will replace all instances of oldString - * @return a String will all instances of oldString replaced by newString - */ - public static final String replace(String string, String oldString, String newString) { - if (string == null) { - return null; - } - // If the newString is null or zero length, just return the string since there's nothing - // to replace. - if (newString == null) { - return string; - } - int i = 0; - // Make sure that oldString appears at least once before doing any processing. - if ((i = string.indexOf(oldString, i)) >= 0) { - // Use char []'s, as they are more efficient to deal with. - char[] string2 = string.toCharArray(); - char[] newString2 = newString.toCharArray(); - int oLength = oldString.length(); - StringBuffer buf = new StringBuffer(string2.length); - buf.append(string2, 0, i).append(newString2); - i += oLength; - int j = i; - // Replace all remaining instances of oldString with newString. - while ((i = string.indexOf(oldString, i)) > 0) { - buf.append(string2, j, i - j).append(newString2); - i += oLength; - j = i; - } - buf.append(string2, j, string2.length - j); - return buf.toString(); - } - return string; - } - - /** - * Validate the given text - to pass it must contain letters, digits, '@', '-', '_', '.', ',' - * or a space character. - * - * @param text the text to check - * @return true if the given text is valid, false otherwise. - */ - public boolean validateChars(String text) { - for (int i = 0; i < text.length(); i++) { - char ch = text.charAt(i); - if (!Character.isLetterOrDigit(ch) && ch != '@' && ch != '-' && ch != '_' - && ch != '.' && ch != ',' && ch != ' ') { - return false; - } - } - return true; - } - - - public static String getPushedURL(String body) { - String urlToPush = null; - int index = body.indexOf("]"); - urlToPush = body.substring(index + 1); - int index2 = urlToPush.indexOf("http://"); - int httpsIndex = urlToPush.indexOf("https"); - if (index2 == -1 && httpsIndex == -1) { - urlToPush = "http://" + urlToPush; - } - - return urlToPush; - } - - /** - * Returns the nickname of the user who sent the message. - * - * @param message the message sent. - * @return the nickname of the user who sent the message. - */ - public static String getNickname(Message message) { - String from = XmppStringUtils.parseResource(message.getFrom()); - return from; - } - - /** - * Returns better looking time String. - * @param seconds the number of seconds to calculate. - */ - public static String getTimeFromLong(long seconds) { - final String HOURS = "h"; - final String MINUTES = "min"; - final String SECONDS = "sec"; - - final long MS_IN_A_DAY = 1000 * 60 * 60 * 24; - final long MS_IN_AN_HOUR = 1000 * 60 * 60; - final long MS_IN_A_MINUTE = 1000 * 60; - final long MS_IN_A_SECOND = 1000; - Date currentTime = new Date(); - long numDays = seconds / MS_IN_A_DAY; - seconds = seconds % MS_IN_A_DAY; - long numHours = seconds / MS_IN_AN_HOUR; - seconds = seconds % MS_IN_AN_HOUR; - long numMinutes = seconds / MS_IN_A_MINUTE; - seconds = seconds % MS_IN_A_MINUTE; - long numSeconds = seconds / MS_IN_A_SECOND; - seconds = seconds % MS_IN_A_SECOND; - long numMilliseconds = seconds; - - StringBuffer buf = new StringBuffer(); - if (numHours > 0) { - buf.append(numHours + " " + HOURS + ", "); - } - - if (numMinutes > 0) { - buf.append(numMinutes + " " + MINUTES); - } - - String result = buf.toString(); - - if (numMinutes < 1) { - result = "less than 1 minute"; - } - - return result; - } - - -} \ No newline at end of file diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/Workpane.java b/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/Workpane.java deleted file mode 100644 index ef0896a35..000000000 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/Workpane.java +++ /dev/null @@ -1,875 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.fastpath.workspace; - -import java.applet.Applet; -import java.applet.AudioClip; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.Frame; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import javax.swing.BorderFactory; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTabbedPane; -import javax.swing.ScrollPaneConstants; -import javax.swing.SwingUtilities; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import org.jivesoftware.MainWindow; -import org.jivesoftware.Spark; -import org.jivesoftware.fastpath.FastpathPlugin; -import org.jivesoftware.fastpath.FpRes; -import org.jivesoftware.fastpath.resources.FastpathRes; -import org.jivesoftware.fastpath.workspace.assistants.ChatMacroMenu; -import org.jivesoftware.fastpath.workspace.assistants.CoBrowser; -import org.jivesoftware.fastpath.workspace.assistants.Notes; -import org.jivesoftware.fastpath.workspace.assistants.RoomInformation; -import org.jivesoftware.fastpath.workspace.assistants.UserHistory; -import org.jivesoftware.fastpath.workspace.invite.InvitationManager; -import org.jivesoftware.fastpath.workspace.invite.WorkgroupInvitationDialog; -import org.jivesoftware.fastpath.workspace.macros.MacrosEditor; -import org.jivesoftware.fastpath.workspace.panes.AgentConversations; -import org.jivesoftware.fastpath.workspace.panes.BackgroundPane; -import org.jivesoftware.fastpath.workspace.panes.ChatHistory; -import org.jivesoftware.fastpath.workspace.panes.ChatQueue; -import org.jivesoftware.fastpath.workspace.panes.InvitationPane; -import org.jivesoftware.fastpath.workspace.panes.OnlineAgents; -import org.jivesoftware.fastpath.workspace.panes.QueueActivity; -import org.jivesoftware.fastpath.workspace.panes.UserInvitationPane; -import org.jivesoftware.fastpath.workspace.search.ChatSearch; -import org.jivesoftware.fastpath.workspace.util.RequestUtils; -import org.jivesoftware.resource.SoundsRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smackx.xdata.Form; -import org.jivesoftware.smackx.muc.MultiUserChat; -import org.jivesoftware.smackx.workgroup.MetaData; -import org.jivesoftware.smackx.workgroup.agent.InvitationRequest; -import org.jivesoftware.smackx.workgroup.agent.Offer; -import org.jivesoftware.smackx.workgroup.agent.OfferListener; -import org.jivesoftware.smackx.workgroup.agent.RevokedOffer; -import org.jivesoftware.smackx.workgroup.agent.TransferRequest; -import org.jivesoftware.smackx.workgroup.user.Workgroup; -import org.jivesoftware.spark.DataManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.UserManager; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.search.SearchManager; -import org.jivesoftware.spark.ui.ChatContainer; -import org.jivesoftware.spark.ui.ChatFrame; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomButton; -import org.jivesoftware.spark.ui.ChatRoomListenerAdapter; -import org.jivesoftware.spark.ui.ChatRoomNotFoundException; -import org.jivesoftware.spark.ui.PresenceListener; -import org.jivesoftware.spark.ui.conferences.ConferenceUtils; -import org.jivesoftware.spark.ui.conferences.GroupChatParticipantList; -import org.jivesoftware.spark.ui.conferences.RoomInvitationListener; -import org.jivesoftware.spark.ui.rooms.GroupChatRoom; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; -import org.jxmpp.util.XmppStringUtils; - -public class Workpane { - // Tracks all the offers coming into the client. - private Map offerMap = new HashMap(); - private Map inviteMap = new HashMap(); - private Map invitations = new HashMap(); - - - private Map fastpathRooms = new HashMap(); - - private OnlineAgents onlineAgentsPane; - private AgentConversations agentCons; - private ChatOfferListener offerListener; - private RoomInvitationListener roomInviteListener; - private ChatSearch chatSearch; - - private QueueActivity queueActivity; - - private RolloverButton historyButton; - private RolloverButton workgroupGroupButton; - private RolloverButton macrosButton; - - - public static final String INITIAL_RESPONSE_PROPERTY = "initialResponse"; - - private JPanel toolbar; - - private List listeners = new ArrayList(); - - private PresenceChangeListener presenceListener = new PresenceChangeListener(); - - /** - * Type of states a fastpath room can be in. - */ - public static enum RoomState { - /** - * The room contains an incoming request. - */ - incomingRequest, - /** - * The rooms contains an invitation from another agent. - */ - invitationRequest, - /** - * The room is in an active state. - */ - activeRoom - } - - public Workpane() { - onlineAgentsPane = new OnlineAgents(); - agentCons = new AgentConversations(); - offerListener = new ChatOfferListener(); - roomInviteListener = new InviteListener(); - chatSearch = new ChatSearch(); - - addOnlineAgents(); - handleRoomOpenings(); - - FastpathPlugin.getUI().getMainPanel().addTab(FpRes.getString("tab.current.chats"), null, agentCons); - - - SearchManager.getInstance().addSearchService(chatSearch); - - // Add Queue Activity Menu - queueActivity = new QueueActivity(); - setupQueueViewer(); - - // Add presence listener. This is used to send presence changes to the workgroup itself. - SparkManager.getSessionManager().addPresenceListener(presenceListener); - - toolbar = new JPanel(new FlowLayout(FlowLayout.LEFT)); - toolbar.setOpaque(false); - historyButton = new RolloverButton(); - ResourceUtils.resButton(historyButton, FpRes.getString("button.history")); - toolbar.add(historyButton); - historyButton.setIcon(FastpathRes.getImageIcon(FastpathRes.HISTORY_16x16)); - historyButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - final ChatHistory chatHistory = new ChatHistory(); - chatHistory.showDialog(); - } - }); - - workgroupGroupButton = new RolloverButton(); - ResourceUtils.resButton(workgroupGroupButton, FpRes.getString("button.conference")); - workgroupGroupButton.setIcon(FastpathRes.getImageIcon(FastpathRes.CONFERENCE_IMAGE_16x16)); - toolbar.add(workgroupGroupButton); - workgroupGroupButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - final Workgroup workgroup = FastpathPlugin.getWorkgroup(); - String serviceName = "conference." + SparkManager.getSessionManager().getServerAddress(); - final String roomName = "workgroup-" + XmppStringUtils.parseLocalpart(workgroup.getWorkgroupJID()) + "@" + serviceName; - ConferenceUtils.joinConferenceOnSeperateThread("Workgroup Chat", roomName, null); - } - }); - - - macrosButton = new RolloverButton(FastpathRes.getImageIcon(FastpathRes.NOTEBOOK_IMAGE)); - ResourceUtils.resButton(macrosButton, FpRes.getString("button.macros")); - macrosButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - MacrosEditor editor = new MacrosEditor(); - editor.showEditor(macrosButton); - } - }); - toolbar.add(macrosButton); - - FastpathPlugin.getMainPanel().add(toolbar, new GridBagConstraints(0, 2, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 2, 2, 2), 0, 0)); - - } - - - public void unload() { - FastpathPlugin.getUI().getMainPanel().removeComponent(onlineAgentsPane); - - // Remove offer listener - FastpathPlugin.getAgentSession().removeOfferListener(offerListener); - - // Add own invitation listener - SparkManager.getChatManager().removeInvitationListener(roomInviteListener); - - // Remove Chat Search - SearchManager.getInstance().removeSearchService(chatSearch); - - // Remove Queue Listener - queueActivity.removeListener(); - FastpathPlugin.getUI().getMainPanel().removeComponent(queueActivity); - - FastpathPlugin.getUI().getMainPanel().removeComponent(agentCons); - agentCons = null; - - FastpathPlugin.getMainPanel().remove(toolbar); - - SparkManager.getSessionManager().removePresenceListener(presenceListener); - } - - - private void addOnlineAgents() { - FastpathPlugin.getUI().getMainPanel().addTab(FpRes.getString("tab.online.agents"), null, onlineAgentsPane); - } - - public void listenForOffers() { - FastpathPlugin.getAgentSession().addOfferListener(offerListener); - - // Add own invitation listener - SparkManager.getChatManager().addInvitationListener(roomInviteListener); - } - - public Map getMetadata(String sessionID) { - Map map = null; - if (offerMap.get(sessionID) != null) { - Offer offer = (Offer)offerMap.get(sessionID); - map = offer.getMetaData(); - } - else if (inviteMap.get(sessionID) != null) { - map = (Map)inviteMap.get(sessionID); - } - return map; - } - - private void handleRoomOpenings() { - SparkManager.getChatManager().addChatRoomListener(new ChatRoomListenerAdapter() { - public void chatRoomOpened(ChatRoom room) { - if (!(room instanceof GroupChatRoom)) { - return; - } - String roomName = room.getRoomname(); - String sessionID = XmppStringUtils.parseLocalpart(roomName); - if (offerMap.get(sessionID) != null) { - Offer offer = (Offer)offerMap.get(sessionID); - Map metadata = offer.getMetaData(); - decorateRoom(room, metadata); - } - } - - public void chatRoomClosed(ChatRoom room) { - String roomName = room.getRoomname(); - String sessionID = XmppStringUtils.parseLocalpart(roomName); - offerMap.remove(sessionID); - } - }); - } - - public void checkForDecoration(ChatRoom chatRoom, String sessionID) { - if (inviteMap.get(sessionID) != null) { - Map metadata = (Map)inviteMap.get(sessionID); - decorateRoom(chatRoom, metadata); - } - } - - public void decorateRoom(ChatRoom room, Map metadata) { - String roomName = room.getRoomname(); - String sessionID = XmppStringUtils.parseLocalpart(roomName); - - - RequestUtils utils = new RequestUtils(metadata); - - addRoomInfo(sessionID, utils, room); - - addButtons(sessionID, utils, room); - - // Specify to use Typing notifications. - GroupChatRoom groupChat = (GroupChatRoom)room; - groupChat.setSendAndReceiveTypingNotifications(true); - - Properties props = FastpathPlugin.getLitWorkspace().getWorkgroupProperties(); - String initialResponse = props.getProperty(INITIAL_RESPONSE_PROPERTY); - if (ModelUtil.hasLength(initialResponse)) { - Message message = new Message(); - message.setBody(initialResponse); - GroupChatRoom groupChatRoom = (GroupChatRoom)room; - groupChatRoom.sendMessageWithoutNotification(message); - } - } - - private void addButtons(final String sessionID, final RequestUtils utils, final ChatRoom room) { - final ChatRoomButton inviteButton = new ChatRoomButton(FastpathRes.getImageIcon(FastpathRes.CHAT_INVITE_IMAGE_24x24)); - final ChatRoomButton transferButton = new ChatRoomButton(FastpathRes.getImageIcon(FastpathRes.CHAT_TRANSFER_IMAGE_24x24)); - final RolloverButton cannedResponses = new RolloverButton(FastpathRes.getImageIcon(FastpathRes.DOWN_ARROW_IMAGE)); - final ChatRoomButton endButton = new ChatRoomButton(FastpathRes.getImageIcon(FastpathRes.CHAT_ENDED_IMAGE_24x24)); - final ChatRoomButton cobrowseButton = new ChatRoomButton(FastpathRes.getImageIcon(FastpathRes.CHAT_COBROWSE_IMAGE_24x24)); - - // Set tooltips - inviteButton.setToolTipText("Invite another user to join in this conversation."); - transferButton.setToolTipText("Transfer this conversation to another agent."); - endButton.setToolTipText("End this conversation."); - cobrowseButton.setToolTipText("Start a co-browsing session with this user."); - - // Update Canned Response button. - ResourceUtils.resButton(cannedResponses, FpRes.getString("button.canned.responses")); - - room.getToolBar().addChatRoomButton(inviteButton); - room.getToolBar().addChatRoomButton(transferButton); - room.getToolBar().addChatRoomButton(cobrowseButton); - room.getToolBar().addChatRoomButton(endButton); - - inviteButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - inviteOrTransfer(room, utils.getWorkgroup(), sessionID, false); - } - }); - - cobrowseButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - CoBrowser browser = new CoBrowser(sessionID, room); - browser.showDialog(); - } - }); - - - transferButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent actionEvent) { - inviteOrTransfer(room, utils.getWorkgroup(), sessionID, true); - } - }); - - room.getEditorBar().add(cannedResponses); - cannedResponses.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - final ChatMacroMenu chatMacroMenu = new ChatMacroMenu(room); - chatMacroMenu.show(cannedResponses, e.getX(), e.getY()); - } - }); - - endButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent actionEvent) { - final GroupChatRoom groupChatRoom = (GroupChatRoom)room; - groupChatRoom.leaveChatRoom(); - } - }); - - // Set Room is Active - addFastpathChatRoom(room, RoomState.activeRoom); - } - - - /** - * Invite or transfer this conversation to another agent, queue or workgroup. - * - * @param room the ChatRoom. - * @param sessionID the current sessionid of this conversation. - * @param transfer true if you wish to transfer this room. - */ - private void inviteOrTransfer(ChatRoom room, String workgroup, String sessionID, boolean transfer) { - WorkgroupInvitationDialog dialog = new WorkgroupInvitationDialog(); - - boolean ok = dialog.hasSelectedAgent(room, transfer); - if (ok) { - String jid = dialog.getSelectedJID(); - jid = UserManager.escapeJID(jid); - - String message = dialog.getMessage(); - - // Determine who to send to. - if (jid.contains("/")) { - // Queueu - InvitationManager.transferOrInviteToQueue(room, workgroup, sessionID, jid, message, transfer); - } - else if ( XmppStringUtils.parseDomain(jid).startsWith("workgroup")) { - InvitationManager.transferOrInviteToWorkgroup(room, workgroup, sessionID, jid, message, transfer); - } - else { - InvitationManager.transferOrInviteUser(room, workgroup, sessionID, jid, message, transfer); - } - } - } - - - private void addRoomInfo(final String sessionID, final RequestUtils utils, final ChatRoom room) { - final JTabbedPane tabbedPane = new JTabbedPane(); - - GroupChatParticipantList participantList = ((GroupChatRoom)room).getConferenceRoomInfo(); - - room.getSplitPane().setRightComponent(tabbedPane); - - Form form = null; - try { - form = FastpathPlugin.getWorkgroup().getWorkgroupForm(); - } - catch (XMPPException | SmackException e) { - Log.error(e); - return; - } - - final BackgroundPane transcriptAlert = new BackgroundPane() { - public Dimension getPreferredSize() { - final Dimension size = super.getPreferredSize(); - size.width = 0; - return size; - } - }; - transcriptAlert.setLayout(new GridBagLayout()); - - JLabel userImage = new JLabel(FastpathRes.getImageIcon(FastpathRes.FASTPATH_IMAGE_24x24)); - userImage.setHorizontalAlignment(JLabel.LEFT); - userImage.setText(utils.getUsername()); - transcriptAlert.add(userImage, new GridBagConstraints(0, 0, 4, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - userImage.setFont(new Font("Dialog", Font.BOLD, 12)); - - - final RoomInformation roomInformation = new RoomInformation(); - roomInformation.showFormInformation(form, utils); - final UserHistory userHistory = new UserHistory(utils.getUserID()); - - final JScrollPane userScroll = new JScrollPane(roomInformation); - final JScrollPane historyScroll = new JScrollPane(userHistory); - historyScroll.getVerticalScrollBar().setBlockIncrement(50); - historyScroll.getVerticalScrollBar().setUnitIncrement(20); - - tabbedPane.addTab(FpRes.getString("tab.user.info"), userScroll); - tabbedPane.addTab(FpRes.getString("tab.participants"), participantList); - tabbedPane.addTab(FpRes.getString("tab.user.history"), historyScroll); - - final Notes notes = new Notes(sessionID, room); - - tabbedPane.addTab(FpRes.getString("tab.notes"), notes); - - - tabbedPane.addChangeListener(new ChangeListener() { - boolean loaded; - - public void stateChanged(ChangeEvent e) { - if (!loaded) { - if (tabbedPane.getSelectedComponent() == historyScroll) { - userHistory.loadHistory(); - loaded = true; - } - } - } - }); - - - final GroupChatRoom groupRoom = (GroupChatRoom)room; - groupRoom.showPresenceMessages(false); - room.getTranscriptWindow().clear(); - - - groupRoom.showPresenceMessages(true); - - final ChatFrame frame = SparkManager.getChatManager().getChatContainer().getChatFrame(); - if (frame != null) { - int height = frame.getHeight(); - int width = frame.getWidth(); - if (height < 400) { - height = 400; - } - - if (width < 600) { - width = 600; - } - - frame.setSize(width, height); - frame.validate(); - frame.repaint(); - } - - fireFastPathChatOpened(room, sessionID, utils, tabbedPane); - DataManager.getInstance().setMetadataForRoom(room, utils.getMetadata()); - } - - public void blink() { - final MainWindow mainWindow = SparkManager.getMainWindow(); - - if (mainWindow.isFocused()) { - return; - } - else { - // Set to new tab. - if (Spark.isWindows()) { - mainWindow.addWindowListener(new WindowAdapter() { - public void windowActivated(WindowEvent e) { - SparkManager.getNativeManager().stopFlashing(mainWindow); - } - }); - - - if (!mainWindow.isFocused() && mainWindow.isVisible()) { - SparkManager.getNativeManager().flashWindow(mainWindow); - } - else if (!mainWindow.isVisible()) { - mainWindow.setState(Frame.ICONIFIED); - mainWindow.setVisible(true); - SparkManager.getNativeManager().flashWindow(mainWindow); - } - } - } - } - - private class ChatOfferListener implements OfferListener { - ChatQueue chatQueue; - private SparkToaster toasterManager; - - public void offerReceived(final Offer offer) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - handleOffer(offer); - } - }); - } - - private void handleOffer(final Offer offer) { - if (offer.getContent() instanceof InvitationRequest || offer.getContent() instanceof TransferRequest) { - handleOfferInvite(offer); - return; - } - - - chatQueue = new ChatQueue(); - chatQueue.offerRecieved(offer); - - toasterManager = new SparkToaster(); - toasterManager.setHidable(false); - - - toasterManager.setToasterHeight((int)chatQueue.getPreferredSize().getHeight() + 40); - - int width = (int)chatQueue.getPreferredSize().getWidth() + 40; - if (width < 300) { - width = 300; - } - toasterManager.setToasterWidth(width); - toasterManager.setDisplayTime(500000000); - - - final JScrollPane pane = new JScrollPane(chatQueue, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - pane.setBorder(BorderFactory.createEmptyBorder()); - toasterManager.showToaster("Incoming Fastpath Request", pane); - toasterManager.hideTitle(); - - chatQueue.getAcceptButton().addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - toasterManager.close(); - chatQueue.setVisible(false); - - offerMap.put(offer.getSessionID(), offer); - try - { - offer.accept(); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to accept offer from " + offer.getUserJID(), e1 ); - } - } - }); - - chatQueue.getDeclineButton().addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - toasterManager.close(); - chatQueue.setVisible(false); - try - { - offer.reject(); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to reject offer from " + offer.getUserJID(), e1 ); - } - SparkManager.getWorkspace().remove(chatQueue); - offerMap.remove(offer.getSessionID()); - } - }); - - final Runnable soundThread = new Runnable() { - public void run() { - URL url = SoundsRes.getURL(SoundsRes.INCOMING_USER); - if (url != null) { - final AudioClip clip = Applet.newAudioClip(url); - SparkManager.getSoundManager().playClip(clip); - } - } - }; - - TaskEngine.getInstance().submit(soundThread); - } - - public void offerRevoked(final RevokedOffer revokedOffer) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - SparkManager.getNativeManager().stopFlashing(SparkManager.getMainWindow()); - if (toasterManager != null) { - toasterManager.close(); - } - - // If the ChatQueue is visible, dispose of it. - if (chatQueue != null) { - chatQueue.setVisible(false); - return; - } - - UserInvitationPane pane = invitations.get(revokedOffer.getSessionID()); - if (pane != null) { - pane.dispose(); - invitations.remove(revokedOffer.getSessionID()); - } - } - }); - } - } - - - private class InviteListener implements RoomInvitationListener { - // Add own invitation listener - @Override - public boolean handleInvitation(final XMPPConnection conn, final MultiUserChat chat, final String inviter, final String reason, final String password, final Message message) { - if (offerMap.containsKey(reason)) { - RequestUtils utils = new RequestUtils(getMetadata(reason)); - String roomName = utils.getUsername(); - - // Create the Group Chat Room - GroupChatRoom groupChatRoom = ConferenceUtils.enterRoomOnSameThread(roomName, chat.getRoom(), password); - groupChatRoom.getSplitPane().setDividerSize(5); - groupChatRoom.getVerticalSlipPane().setDividerLocation(0.6); - groupChatRoom.getSplitPane().setDividerLocation(0.6); - - groupChatRoom.getConferenceRoomInfo().setNicknameChangeAllowed(false); - - groupChatRoom.getToolBar().setVisible(true); - fastpathRooms.put(groupChatRoom, RoomState.activeRoom); - - final ChatContainer chatContainer = SparkManager.getChatManager().getChatContainer(); - chatContainer.setChatRoomTitle(groupChatRoom, roomName); - try { - if (chatContainer.getActiveChatRoom() == groupChatRoom) { - chatContainer.getChatFrame().setTitle(roomName); - } - } - catch (ChatRoomNotFoundException e) { - Log.debug(e.getMessage()); - } - - SparkManager.getChatManager().notifySparkTabHandlers(groupChatRoom); - - // Change subject line. - groupChatRoom.getSubjectPanel().setRoomLabel("Fastpath Conversation with " + roomName + ""); - - return true; - } - else if (message != null) { - MetaData metaDataExt = (MetaData)message.getExtension(MetaData.ELEMENT_NAME, MetaData.NAMESPACE); - if (metaDataExt != null) { - Map metadata = metaDataExt.getMetaData(); - metadata.put("sessionID", XmppStringUtils.parseLocalpart(chat.getRoom())); - - RequestUtils utils = new RequestUtils(metadata); - inviteMap.put(utils.getSessionID(), metadata); - InvitationPane pane = new InvitationPane(utils, chat.getRoom(), inviter, reason, password, message); - return true; - } - } - - return false; - } - } - - /** - * Handles incoming invitations or transfers. - * - * @param offer the Offer - */ - public void handleOfferInvite(final Offer offer) { - Map metadata = offer.getMetaData(); - String sessionID = offer.getSessionID(); - metadata.put("sessionID", sessionID); - - RequestUtils utils = new RequestUtils(metadata); - inviteMap.put(sessionID, metadata); - - UserInvitationPane invitationPane = null; - - if (offer.getContent() instanceof InvitationRequest) { - InvitationRequest request = (InvitationRequest)offer.getContent(); - invitationPane = new UserInvitationPane(offer, utils, request.getRoom(), request.getInviter(), request.getReason()); - } - else if (offer.getContent() instanceof TransferRequest) { - TransferRequest request = (TransferRequest)offer.getContent(); - invitationPane = new UserInvitationPane(offer, utils, request.getRoom(), request.getInviter(), request.getReason()); - } - - invitationPane.setAcceptListener(new UserInvitationPane.AcceptListener() { - public void yesOption() { - // Remove - invitations.remove(offer.getSessionID()); - } - - public void noOption() { - invitations.remove(offer.getSessionID()); - } - }); - - invitations.put(offer.getSessionID(), invitationPane); - } - - - public Properties getWorkgroupProperties() { - String workgroupName = XmppStringUtils.parseLocalpart(FastpathPlugin.getWorkgroup().getWorkgroupJID()); - - File workgroupDir = new File(Spark.getSparkUserHome(), "workgroups/" + workgroupName); - workgroupDir.mkdirs(); - - File propertiesFile = new File(workgroupDir, "workgroup.properties"); - Properties props = new Properties(); - try { - props.load(new FileInputStream(propertiesFile)); - } - catch (IOException e) { - // File does not exist. - } - return props; - } - - public void saveProperties(Properties props) { - String workgroupName = XmppStringUtils.parseLocalpart(FastpathPlugin.getWorkgroup().getWorkgroupJID()); - - File propertiesFile = new File(new File(Spark.getSparkUserHome(), "workgroups/" + workgroupName), "workgroup.properties"); - - try { - props.store(new FileOutputStream(propertiesFile), "Workgroup Properties"); - } - catch (IOException e) { - Log.error("Unable to save group properties.", e); - } - } - - private Message getMessage(String messageText, RequestUtils util, boolean transfer) { - Map metadata = new HashMap(); - metadata.put("messageText", messageText); - metadata.put("username", util.getUsername()); - metadata.put("userID", util.getUserID()); - metadata.put("transfer", Boolean.toString(transfer)); - metadata.put("question", util.getQuestion()); - metadata.put("email", util.getEmailAddress()); - metadata.put("workgroup", util.getWorkgroup()); - - if (ModelUtil.hasLength(util.getRequestLocation())) { - metadata.put("Location", util.getRequestLocation()); - } - - // Add Metadata as message extension - final MetaData data = new MetaData(metadata); - Message message = new Message(); - message.addExtension(data); - return message; - - } - - private RequestUtils getRequestUtils(String sessionID) { - Map map = getMetadata(sessionID); - if (map != null) { - return new RequestUtils(map); - } - return null; - } - - private void setupQueueViewer() { - FastpathPlugin.getUI().getMainPanel().addTab(FpRes.getString("tab.queue.activity"), null, queueActivity); - } - - public void addFastPathListener(FastpathListener listener) { - listeners.add(listener); - } - - public void removeFastPathListener(FastpathListener listener) { - listeners.remove(listener); - } - - - private void fireFastPathChatOpened(ChatRoom room, String sessionID, RequestUtils utils, JTabbedPane tabbedPane) { - final Iterator list = new ArrayList(listeners).iterator(); - while (list.hasNext()) { - FastpathListener listener = (FastpathListener)list.next(); - listener.fastpathRoomOpened(room, sessionID, utils, tabbedPane); - } - } - - - private class PresenceChangeListener implements PresenceListener { - public void presenceChanged(Presence presence) { - String status = presence.getStatus(); - if (status == null) { - status = ""; - } - - try { - if (FastpathPlugin.getAgentSession().isOnline()) { - Presence.Mode mode = presence.getMode(); - if (status == null) { - status = ""; - } - if (mode == null) { - mode = Presence.Mode.available; - } - FastpathPlugin.getAgentSession().setStatus(presence.getMode(), status); - } - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - } - } - - public void addFastpathChatRoom(ChatRoom chatRoom, RoomState state) { - fastpathRooms.put(chatRoom, state); - } - - public void removeFastpathChatRoom(ChatRoom chatRoom) { - fastpathRooms.remove(chatRoom); - } - - public RoomState getRoomState(ChatRoom chatRoom) { - return fastpathRooms.get(chatRoom); - } - - -} diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/UserHistory.java b/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/UserHistory.java deleted file mode 100644 index 150f5286c..000000000 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/assistants/UserHistory.java +++ /dev/null @@ -1,207 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.fastpath.workspace.assistants; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; - -import javax.swing.DefaultListModel; -import javax.swing.JFrame; -import javax.swing.JList; -import javax.swing.JPanel; - -import org.jivesoftware.fastpath.FastpathPlugin; -import org.jivesoftware.fastpath.FpRes; -import org.jivesoftware.fastpath.workspace.panes.ChatViewer; -import org.jivesoftware.fastpath.workspace.panes.HistoryItemRenderer; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.workgroup.packet.Transcript; -import org.jivesoftware.smackx.workgroup.packet.Transcripts; -import org.jivesoftware.smackx.workgroup.packet.Transcripts.TranscriptSummary; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; - -public class UserHistory extends JPanel { - private static final long serialVersionUID = -1067239194964815379L; - private DefaultListModel model = new DefaultListModel(); - private JFrame userFrame; - private JList list; - private String userID; - - private JFrame frame; - - public UserHistory(String userID) { - this.userID = userID; - - list = new JList(model); - list.setCellRenderer(new HistoryItemRenderer()); - - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.setBackground(Color.white); - mainPanel.add(list, BorderLayout.CENTER); - - setLayout(new BorderLayout()); - add(mainPanel, BorderLayout.CENTER); - - list.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - UserHistoryItem historyItem = (UserHistoryItem)list.getSelectedValue(); - showTranscript(historyItem.getSessionID()); - } - } - }); - - - } - - public void loadHistory() { - - SwingWorker transcriptThread = new SwingWorker() { - final List transcriptList = new ArrayList(); - - public Object construct() { - try { - Transcripts transcripts = FastpathPlugin.getAgentSession().getTranscripts(userID); - Iterator iter = transcripts.getSummaries().iterator(); - while (iter.hasNext()) { - Transcripts.TranscriptSummary summary = (Transcripts.TranscriptSummary)iter.next(); - transcriptList.add(summary); - } - } - catch (XMPPException | SmackException e) { - Log.error("Error getting transcripts.", e); - } - - Collections.sort(transcriptList, timeComparator); - return transcriptList; - } - - public void finished() { - init(transcriptList); - } - }; - - transcriptThread.start(); - } - - public void init(Collection transcriptList) { - model.removeAllElements(); - Iterator iter = transcriptList.iterator(); - while (iter.hasNext()) { - Transcripts.TranscriptSummary summary = iter.next(); - - - UserHistoryItem item = new UserHistoryItem(summary.getAgentDetails(), summary.getJoinTime(), summary.getLeftTime()); - item.setSessionID(summary.getSessionID()); - model.addElement(item); - } - - list.validate(); - list.repaint(); - - } - - private void showTranscript(String sessionID) { - if (frame == null) { - frame = new JFrame(FpRes.getString("title.transcript")); - frame.setIconImage(SparkManager.getMainWindow().getIconImage()); - } - - if (frame.isVisible()) { - return; - } - - Transcript transcript = null; - try { - transcript = FastpathPlugin.getAgentSession().getTranscript(sessionID); - } - catch (XMPPException | SmackException e) { - Log.error("Error showing transcripts.", e); - } - - if (transcript == null) { - return; - } - final ChatViewer chatViewer = new ChatViewer(transcript); - frame.getContentPane().removeAll(); - frame.getContentPane().setLayout(new BorderLayout()); - frame.getContentPane().add(chatViewer, BorderLayout.CENTER); - frame.pack(); - frame.setSize(600, 400); - - frame.setLocationRelativeTo(SparkManager.getMainWindow()); - frame.setVisible(true); - } - - - /** - * Lets make sure that the panel doesn't stretch past the - * scrollpane view pane. - * - * @return the preferred dimension - */ - public Dimension getPreferredSize() { - final Dimension size = super.getPreferredSize(); - size.width = 0; - return size; - } - - private final Comparator timeComparator = new Comparator() { - public int compare(Object o1, Object o2) { - final Transcripts.TranscriptSummary item1 = (Transcripts.TranscriptSummary)o1; - final Transcripts.TranscriptSummary item2 = (Transcripts.TranscriptSummary)o2; - - long int1 = item1.getJoinTime().getTime(); - long int2 = item2.getJoinTime().getTime(); - - - if (int1 == int2) { - return 0; - } - - if (int1 > int2) { - return -1; - } - - if (int1 < int2) { - return 1; - } - - return 0; - } - }; - - -} - - diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/AgentConversations.java b/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/AgentConversations.java deleted file mode 100644 index bd80b4b07..000000000 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/AgentConversations.java +++ /dev/null @@ -1,392 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.fastpath.workspace.panes; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.DefaultListModel; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import org.jivesoftware.fastpath.FastpathPlugin; -import org.jivesoftware.fastpath.FpRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smackx.muc.MultiUserChatManager; -import org.jivesoftware.smackx.xdata.Form; -import org.jivesoftware.smackx.muc.Affiliate; -import org.jivesoftware.smackx.muc.MultiUserChat; -import org.jivesoftware.smackx.workgroup.agent.AgentRoster; -import org.jivesoftware.smackx.workgroup.agent.AgentRosterListener; -import org.jivesoftware.smackx.workgroup.packet.AgentStatus; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.tabbedPane.SparkTab; -import org.jivesoftware.spark.component.tabbedPane.SparkTabbedPaneListener; -import org.jivesoftware.spark.ui.conferences.ConferenceUtils; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -/** - * UI to show all chats occuring. - */ -public final class AgentConversations extends JPanel implements ChangeListener { - - private static final long serialVersionUID = 1L; - private DefaultListModel model = new DefaultListModel(); - private JList list; - - private Map sessionMap = new HashMap(); - - /** - * Add listeners and construct UI. - */ - public AgentConversations() { - FastpathPlugin.getUI().getMainPanel().addSparkTabbedPaneListener(new SparkTabbedPaneListener() { - public void tabRemoved(SparkTab tab, Component component, int index) { - } - - public void tabAdded(SparkTab tab, Component component, int index) { - } - - public void tabSelected(SparkTab tab, Component component, int index) { - stateChanged(null); - } - - public void allTabsRemoved() { - } - - - public boolean canTabClose(SparkTab tab, Component component) { - return true; - } - }); - } - - private void init() { - list = new JList(model); - - this.setLayout(new BorderLayout()); - this.setBackground(Color.white); - this.setForeground(Color.white); - - JScrollPane scrollPane = new JScrollPane(list); - scrollPane.setBorder(BorderFactory.createEmptyBorder()); - this.add(scrollPane, BorderLayout.CENTER); - - list.setCellRenderer(new FastpathPanelRenderer()); - - list.addMouseListener(new MouseAdapter() { - public void mousePressed(MouseEvent mouseEvent) { - int index = list.locationToIndex(mouseEvent.getPoint()); - list.setSelectedIndex(index); - checkPopup(mouseEvent); - } - - public void mouseReleased(MouseEvent mouseEvent) { - int index = list.locationToIndex(mouseEvent.getPoint()); - list.setSelectedIndex(index); - checkPopup(mouseEvent); - } - }); - } - - - private void addAgentChat(String agentID, String name, String email, String question, Date startDate, String sessionID) { - if (sessionMap.containsKey(sessionID)) { - return; - } - - AgentConversation item = new AgentConversation(agentID, name, startDate, email, question, sessionID); - model.addElement(item); - sessionMap.put(sessionID, item); - } - - private void removeConversation(String sessionID) { - AgentConversation item = sessionMap.get(sessionID); - if (item != null) { - model.removeElement(item); - } - } - - public void stateChanged(ChangeEvent e) { - if (FastpathPlugin.getUI().getMainPanel().getSelectedComponent() == this && list == null) { - init(); - - SwingWorker agentWorker = new SwingWorker() { - AgentRoster agentRoster; - Collection agentSet; - - public Object construct() { - try - { - agentRoster = FastpathPlugin.getAgentSession().getAgentRoster(); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to get agent roster.", e1 ); - } - agentSet = agentRoster.getAgents(); - return agentSet; - } - - public void finished() { - agentRoster.addListener(new AgentRosterListener() { - public void agentAdded(String jid) { - } - - public void agentRemoved(String jid) { - - } - - public void presenceChanged(Presence presence) { - String agentJID = XmppStringUtils.parseBareJid(presence.getFrom()); - AgentStatus agentStatus = (AgentStatus)presence.getExtension("agent-status", "http://jabber.org/protocol/workgroup"); - - String status = presence.getStatus(); - if (status == null) { - status = "Available"; - } - - if (agentStatus != null) { - List list = agentStatus.getCurrentChats(); - - removeOldChats(agentJID, list); - - // Add new ones. - Iterator iter = list.iterator(); - while (iter.hasNext()) { - AgentStatus.ChatInfo chatInfo = (AgentStatus.ChatInfo)iter.next(); - Date startDate = chatInfo.getDate(); - String username = chatInfo.getUserID(); - - String nickname = chatInfo.getUsername(); - if (!ModelUtil.hasLength(nickname)) { - nickname = "Not specified"; - } - - String question = chatInfo.getQuestion(); - if (!ModelUtil.hasLength(question)) { - question = "No question asked"; - } - - String email = chatInfo.getEmail(); - if (!ModelUtil.hasLength(email)) { - email = "Not specified"; - } - addAgentChat(agentJID, nickname, email, question, startDate, chatInfo.getSessionID()); - } - } - calculateNumberOfChats(agentRoster); - } - - - }); - } - }; - - agentWorker.start(); - } - } - - private void calculateNumberOfChats(AgentRoster agentRoster) { - int counter = 0; - // TODO: CHECK FASTPATH - //for (String agent : agentRoster.getAgents()) { - for (Iterator it = agentRoster.getAgents().iterator(); it.hasNext();) { - String agent = (String)it.next(); - Presence presence = agentRoster.getPresence(agent); - if (presence.isAvailable()) { - AgentStatus agentStatus = (AgentStatus)presence.getExtension("agent-status", "http://jabber.org/protocol/workgroup"); - if (agentStatus != null) { - counter += agentStatus.getCurrentChats().size(); - } - } - } - - FastpathPlugin.getUI().setTitleForComponent(FpRes.getString("message.current.chats", counter), this); - } - - private boolean newListHasSession(String sessionID, List chatList) { - // Add new ones. - Iterator iter = chatList.iterator(); - while (iter.hasNext()) { - AgentStatus.ChatInfo chatInfo = (AgentStatus.ChatInfo)iter.next(); - String session = chatInfo.getSessionID(); - if (session.equalsIgnoreCase(sessionID)) { - return true; - } - } - return false; - } - - private void removeOldChats(String agentJID, List chatList) { - for (AgentConversation agent : sessionMap.values()) { - if (agent.getAgentJID().equals(agentJID)) { - String sessionID = agent.getSessionID(); - boolean listHasID = newListHasSession(sessionID, chatList); - if (!listHasID) { - removeConversation(sessionID); - } - } - } - } - - - private void checkPopup(MouseEvent e) { - if (e.isPopupTrigger()) { - // Check if monitor - try { - AgentConversation item = (AgentConversation)list.getSelectedValue(); - boolean isMonitor = FastpathPlugin.getAgentSession().hasMonitorPrivileges(SparkManager.getConnection()); - if (isMonitor) { - JPopupMenu menu = new JPopupMenu(); - - final String sessionID = item.getSessionID(); - - - Action joinAction = new AbstractAction() { - private static final long serialVersionUID = 8239167390330425891L; - - public void actionPerformed(ActionEvent actionEvent) { - // Get Conference - try { - final MultiUserChatManager multiUserChatManager = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ); - Collection col = multiUserChatManager.getServiceNames(); - if (col.size() == 0) { - return; - } - - String serviceName = (String)col.iterator().next(); - String roomName = sessionID + "@" + serviceName; - - LocalPreferences pref = SettingsManager.getLocalPreferences(); - - final String nickname = pref.getNickname(); - MultiUserChat muc = multiUserChatManager.getMultiUserChat( roomName ); - - ConferenceUtils.enterRoom(muc, roomName, nickname, null); - - if (muc.isJoined()) { - // Try and remove myself as an owner if I am one. - Collection owners = null; - try { - owners = muc.getOwners(); - } - catch (XMPPException | SmackException e1) { - return; - } - Iterator iter = owners.iterator(); - - List list = new ArrayList(); - while (iter.hasNext()) { - Affiliate affilitate = (Affiliate)iter.next(); - String jid = affilitate.getJid(); - if (!jid.equals(SparkManager.getSessionManager().getBareAddress())) { - list.add(jid); - } - } - if (list.size() > 0) { - Form form = muc.getConfigurationForm().createAnswerForm(); - form.setAnswer("muc#roomconfig_roomowners", list); - - // new DataFormDialog(groupChat, form); - muc.sendConfigurationForm(form); - } - } - } - catch (Exception e1) { - Log.error(e1); - } - } - }; - - joinAction.putValue(Action.NAME, FpRes.getString("menuitem.join.chat")); - menu.add(joinAction); - - Action monitorAction = new AbstractAction() { - private static final long serialVersionUID = -2072254190661466657L; - - public void actionPerformed(ActionEvent actionEvent) { - - // Make user an owner. - try { - FastpathPlugin.getAgentSession().makeRoomOwner(SparkManager.getConnection(), sessionID); - - final MultiUserChatManager multiUserChatManager = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ); - Collection col = multiUserChatManager.getServiceNames(); - if (col.size() == 0) { - return; - } - - String serviceName = (String)col.iterator().next(); - String roomName = sessionID + "@" + serviceName; - - LocalPreferences pref = SettingsManager.getLocalPreferences(); - final String nickname = pref.getNickname(); - MultiUserChat muc = multiUserChatManager.getMultiUserChat( roomName); - - ConferenceUtils.enterRoom(muc, roomName, nickname, null); - - } - catch (XMPPException | SmackException e1) { - Log.error(e1); - } - } - }; - - monitorAction.putValue(Action.NAME, FpRes.getString("menuitem.monitor.chat")); - menu.add(monitorAction); - menu.show(list, e.getX(), e.getY()); - } - } - catch (XMPPException | SmackException e1) { - Log.error(e1); - return; - } - } - } - - -} diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/CurrentActivity.java b/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/CurrentActivity.java deleted file mode 100644 index 5be2d8c25..000000000 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/CurrentActivity.java +++ /dev/null @@ -1,355 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.fastpath.workspace.panes; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.Iterator; -import java.util.List; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.DefaultListModel; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; - -import org.jivesoftware.fastpath.FastpathPlugin; -import org.jivesoftware.fastpath.FpRes; -import org.jivesoftware.fastpath.resources.FastpathRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smackx.muc.MultiUserChatManager; -import org.jivesoftware.smackx.xdata.Form; -import org.jivesoftware.smackx.muc.Affiliate; -import org.jivesoftware.smackx.muc.MultiUserChat; -import org.jivesoftware.smackx.workgroup.agent.AgentRoster; -import org.jivesoftware.smackx.workgroup.agent.AgentRosterListener; -import org.jivesoftware.smackx.workgroup.packet.AgentStatus; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.UserManager; -import org.jivesoftware.spark.ui.conferences.ConferenceUtils; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -/** - * UI to show all chats occuring. - */ -public final class CurrentActivity extends JPanel { - - private static final long serialVersionUID = 1L; - private DefaultListModel model = new DefaultListModel(); - private JList list = new JList(model); - private JFrame mainFrame; - private JLabel activeConversations; - private int counter = 0; - - /** - * Add listeners and construct UI. - */ - public CurrentActivity() { - init(); - } - - private void init() { - this.setLayout(new BorderLayout()); - - - final BackgroundPane titlePane = new BackgroundPane() { - private static final long serialVersionUID = 3127229816651522537L; - - public Dimension getPreferredSize() { - final Dimension size = super.getPreferredSize(); - size.width = 0; - return size; - } - }; - - titlePane.setLayout(new GridBagLayout()); - titlePane.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.LIGHT_GRAY)); - - - JLabel userImage = new JLabel(FastpathRes.getImageIcon(FastpathRes.FASTPATH_IMAGE_24x24)); - userImage.setHorizontalAlignment(JLabel.LEFT); - userImage.setText(FpRes.getString("title.current.active.conversation")); - titlePane.add(userImage, new GridBagConstraints(0, 0, 4, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - userImage.setFont(new Font("Dialog", Font.BOLD, 12)); - - activeConversations = new JLabel("0"); - titlePane.add(new JLabel(FpRes.getString("title.number.of.active.conversations") +":"), new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - titlePane.add(activeConversations, new GridBagConstraints(1, 1, 1, 3, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - - this.add(titlePane, BorderLayout.NORTH); - - this.add(list, BorderLayout.CENTER); - - list.setCellRenderer(new HistoryItemRenderer()); - - // Add current chats - addCurrentChats(); - - list.addMouseListener(new MouseAdapter() { - public void mouseReleased(MouseEvent mouseEvent) { - checkPopup(mouseEvent); - } - - public void mousePressed(MouseEvent mouseEvent) { - checkPopup(mouseEvent); - } - }); - } - - public void addCurrentChats() { - SwingWorker agentWorker = new SwingWorker() { - AgentRoster agentRoster; - Collection agentSet; - - public Object construct() { - try - { - agentRoster = FastpathPlugin.getAgentSession().getAgentRoster(); - } - catch ( SmackException.NotConnectedException e ) - { - Log.error( "Unable to get agent roster.", e ); - } - agentSet = agentRoster.getAgents(); - return agentSet; - } - - public void finished() { - agentRoster.addListener(new AgentRosterListener() { - public void agentAdded(String jid) { - } - - public void agentRemoved(String jid) { - } - - public void presenceChanged(Presence presence) { - String agentJID = XmppStringUtils.parseBareJid(presence.getFrom()); - agentJID = UserManager.unescapeJID(agentJID); - AgentStatus agentStatus = (AgentStatus)presence.getExtension("agent-status", "http://jabber.org/protocol/workgroup"); - - String status = presence.getStatus(); - if (status == null) { - status = "Available"; - } - - if (agentStatus != null) { - List list = agentStatus.getCurrentChats(); - - // Add new ones. - Iterator iter = list.iterator(); - while (iter.hasNext()) { - AgentStatus.ChatInfo chatInfo = (AgentStatus.ChatInfo)iter.next(); - Date startDate = chatInfo.getDate(); - String username = chatInfo.getUserID(); - - String nickname = chatInfo.getUsername(); - if (!ModelUtil.hasLength(nickname)) { - nickname = FpRes.getString("message.not.specified"); - } - - String question = chatInfo.getQuestion(); - if (!ModelUtil.hasLength(question)) { - question = "No question asked"; - } - - String email = chatInfo.getEmail(); - if (!ModelUtil.hasLength(email)) { - email = FpRes.getString("message.not.specified"); - } - addAgentChat(agentJID, nickname, email, question, startDate, chatInfo.getSessionID()); - } - } - - } - }); - } - }; - - agentWorker.start(); - } - - - private void addAgentChat(String agent, String visitor, String email, String question, Date startDate, String session) { - // Update counter. - counter++; - activeConversations.setText(Integer.toString(counter)); - - // Conversation Item - ConversationItem item = new ConversationItem(agent, visitor, startDate, email, question, session); - model.addElement(item); - } - - private void checkPopup(MouseEvent e) { - if (e.isPopupTrigger()) { - // Check if monitor - try { - boolean isMonitor = FastpathPlugin.getAgentSession().hasMonitorPrivileges(SparkManager.getConnection()); - if (isMonitor) { - JPopupMenu menu = new JPopupMenu(); - - int location = list.locationToIndex(e.getPoint()); - list.setSelectedIndex(location); - ConversationItem item = (ConversationItem)list.getSelectedValue(); - final String sessionID = item.getSessionID(); - - - Action joinAction = new AbstractAction() { - private static final long serialVersionUID = -3198414924157880065L; - - public void actionPerformed(ActionEvent actionEvent) { - // Get Conference - try { - final MultiUserChatManager multiUserChatManager = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ); - Collection col = multiUserChatManager.getServiceNames(); - if (col.size() == 0) { - return; - } - - String serviceName = (String)col.iterator().next(); - String roomName = sessionID + "@" + serviceName; - - final LocalPreferences pref = SettingsManager.getLocalPreferences(); - final String nickname = pref.getNickname(); - MultiUserChat muc = multiUserChatManager.getMultiUserChat(roomName); - - ConferenceUtils.enterRoom(muc, roomName, nickname, null); - - if (muc.isJoined()) { - // Try and remove myself as an owner if I am one. - Collection owners = null; - try { - owners = muc.getOwners(); - } - catch (XMPPException | SmackException e1) { - return; - } - Iterator iter = owners.iterator(); - - List list = new ArrayList(); - while (iter.hasNext()) { - Affiliate affilitate = (Affiliate)iter.next(); - String jid = affilitate.getJid(); - if (!jid.equals(SparkManager.getSessionManager().getBareAddress())) { - list.add(jid); - } - } - if (list.size() > 0) { - Form form = muc.getConfigurationForm().createAnswerForm(); - form.setAnswer("muc#roomconfig_roomowners", list); - - // new DataFormDialog(groupChat, form); - muc.sendConfigurationForm(form); - } - } - } - catch (Exception e1) { - Log.error(e1); - } - } - }; - - joinAction.putValue(Action.NAME, FpRes.getString("menuitem.join.chat")); - menu.add(joinAction); - - Action monitorAction = new AbstractAction() { - private static final long serialVersionUID = 7292337790553806820L; - - public void actionPerformed(ActionEvent actionEvent) { - - // Make user an owner. - try { - FastpathPlugin.getAgentSession().makeRoomOwner(SparkManager.getConnection(), sessionID); - MultiUserChatManager manager = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ); - Collection col = manager.getServiceNames(); - if (col.size() == 0) { - return; - } - - String serviceName = (String)col.iterator().next(); - String roomName = sessionID + "@" + serviceName; - - LocalPreferences pref = SettingsManager.getLocalPreferences(); - final String nickname = pref.getNickname(); - MultiUserChat muc = manager.getMultiUserChat( roomName ); - - ConferenceUtils.enterRoom(muc, roomName, nickname, null); - - } - catch (XMPPException | SmackException e1) { - Log.error(e1); - } - } - }; - - monitorAction.putValue(Action.NAME, FpRes.getString("menuitem.monitor.chat")); - menu.add(monitorAction); - menu.show(list, e.getX(), e.getY()); - } - } - catch (XMPPException | SmackException e1) { - Log.error(e1); - return; - } - } - } - - public void showDialog() { - if (mainFrame == null) { - mainFrame = new JFrame(FpRes.getString("title.current.conversations")); - } - if (mainFrame.isVisible()) { - return; - } - mainFrame.setIconImage(SparkManager.getMainWindow().getIconImage()); - mainFrame.getContentPane().setLayout(new BorderLayout()); - mainFrame.getContentPane().add(new JScrollPane(this)); - mainFrame.pack(); - mainFrame.setSize(400, 400); - mainFrame.setLocationRelativeTo(SparkManager.getMainWindow()); - mainFrame.setVisible(true); - } - - -} \ No newline at end of file diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/InvitationPane.java b/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/InvitationPane.java deleted file mode 100644 index 5c9e63525..000000000 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/panes/InvitationPane.java +++ /dev/null @@ -1,294 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.fastpath.workspace.panes; - -import java.awt.Color; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import javax.swing.JLabel; -import javax.swing.JPanel; - -import org.jivesoftware.fastpath.FastpathPlugin; -import org.jivesoftware.fastpath.FpRes; -import org.jivesoftware.fastpath.resources.FastpathRes; -import org.jivesoftware.fastpath.workspace.Workpane.RoomState; -import org.jivesoftware.fastpath.workspace.assistants.RoomInformation; -import org.jivesoftware.fastpath.workspace.util.RequestUtils; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smackx.muc.MultiUserChatManager; -import org.jivesoftware.smackx.xdata.Form; -import org.jivesoftware.smackx.muc.Affiliate; -import org.jivesoftware.smackx.muc.MultiUserChat; -import org.jivesoftware.smackx.workgroup.MetaData; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.ChatNotFoundException; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.LinkLabel; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.component.WrappedLabel; -import org.jivesoftware.spark.ui.ChatContainer; -import org.jivesoftware.spark.ui.conferences.ConferenceUtils; -import org.jivesoftware.spark.ui.rooms.GroupChatRoom; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; - -public class InvitationPane { - - private Map metadata = null; - private GroupChatRoom chatRoom; - - public InvitationPane(final RequestUtils request, final String room, final String inviter, String reason, final String password, final Message message) { - final JPanel transcriptAlert = new JPanel(); - transcriptAlert.setBackground(Color.white); - transcriptAlert.setLayout(new GridBagLayout()); - - - JLabel userImage = new JLabel(FastpathRes.getImageIcon(FastpathRes.FASTPATH_IMAGE_16x16)); - userImage.setHorizontalAlignment(JLabel.LEFT); - String title = FpRes.getString("title.fastpath.invitation"); - if (request.isTransfer()) { - title = FpRes.getString("title.fastpath.transfer"); - } - - - userImage.setText(title); - transcriptAlert.add(userImage, new GridBagConstraints(0, 0, 4, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0)); - userImage.setFont(new Font("Dialog", Font.BOLD, 12)); - - final JLabel inviterLabel = new JLabel(FpRes.getString("from") + ":"); - inviterLabel.setFont(new Font("Dialog", Font.BOLD, 11)); - final WrappedLabel inviterValueLabel = new WrappedLabel(); - - String nickname = SparkManager.getUserManager().getUserNicknameFromJID(inviter); - inviterValueLabel.setText(nickname); - transcriptAlert.add(inviterLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - transcriptAlert.add(inviterValueLabel, new GridBagConstraints(1, 1, 3, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0)); - - - final JLabel nameLabel = new JLabel(FpRes.getString("room") + ":"); - nameLabel.setFont(new Font("Dialog", Font.BOLD, 11)); - final WrappedLabel valueLabel = new WrappedLabel(); - valueLabel.setText(room); - transcriptAlert.add(nameLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - transcriptAlert.add(valueLabel, new GridBagConstraints(1, 2, 3, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0)); - - final JLabel messageLabel = new JLabel(FpRes.getString("message") + ":"); - messageLabel.setFont(new Font("Dialog", Font.BOLD, 11)); - final WrappedLabel messageValueLabel = new WrappedLabel(); - messageValueLabel.setText(reason); - transcriptAlert.add(messageLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - transcriptAlert.add(messageValueLabel, new GridBagConstraints(1, 3, 3, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0)); - - // Add accept button and reject button. - final RolloverButton acceptButton = new RolloverButton("Accept", FastpathRes.getImageIcon(FastpathRes.CIRCLE_CHECK_IMAGE)); - final RolloverButton rejectButton = new RolloverButton("Decline", FastpathRes.getImageIcon(FastpathRes.SMALL_DELETE)); - - ResourceUtils.resButton(acceptButton, FpRes.getString("button.accept")); - ResourceUtils.resButton(rejectButton, FpRes.getString("button.reject")); - - LinkLabel infoButton = new LinkLabel(FpRes.getString("message.view.more.information"), null, Color.blue, Color.red); - transcriptAlert.add(infoButton, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - transcriptAlert.add(acceptButton, new GridBagConstraints(1, 4, 1, 1, 1.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - transcriptAlert.add(rejectButton, new GridBagConstraints(2, 4, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - transcriptAlert.add(new JLabel(), new GridBagConstraints(2, 5, 1, 1, 0.0, 1.0, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); - - - MetaData metaDataExt = (MetaData)message.getExtension(MetaData.ELEMENT_NAME, MetaData.NAMESPACE); - if (metaDataExt != null) { - metadata = metaDataExt.getMetaData(); - } - - - infoButton.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - RoomInformation roomInformation = new RoomInformation(); - if (metadata != null) { - roomInformation.showAllInformation(metadata); - roomInformation.showRoomInformation(); - } - - } - }); - - - acceptButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent actionEvent) { - SwingWorker waiter = new SwingWorker() { - public Object construct() { - try { - Thread.sleep(50); - } - catch (InterruptedException e) { - Log.error(e); - } - return true; - } - - public void finished() { - String roomName = request.getUsername(); - chatRoom.getSplitPane().getRightComponent().setVisible(true); - chatRoom.getBottomPanel().setVisible(true); - - chatRoom.getScrollPaneForTranscriptWindow().setVisible(true); - chatRoom.getEditorBar().setVisible(true); - chatRoom.getChatInputEditor().setEnabled(true); - chatRoom.getToolBar().setVisible(true); - chatRoom.getVerticalSlipPane().setDividerLocation(0.8); - chatRoom.getSplitPane().setDividerLocation(0.8); - transcriptAlert.setVisible(false); - - String name = XmppStringUtils.parseLocalpart(roomName); - - try { - chatRoom.setTabTitle(roomName); - chatRoom.getConferenceRoomInfo().setNicknameChangeAllowed(false); - - chatRoom.getToolBar().setVisible(true); - chatRoom.getEditorBar().setVisible(true); - chatRoom.getChatInputEditor().setEnabled(true); - - ChatContainer chatContainer = SparkManager.getChatManager().getChatContainer(); - chatContainer.setChatRoomTitle(chatRoom, roomName); - if (chatContainer.getActiveChatRoom() == chatRoom) { - chatContainer.getChatFrame().setTitle(roomName); - } - - } - catch (Exception e) { - Log.error(e); - } - - ConferenceUtils.enterRoomOnSameThread(roomName, room, password); - removeOwner(chatRoom.getMultiUserChat()); - - FastpathPlugin.getLitWorkspace().checkForDecoration(chatRoom, request.getSessionID()); - } - }; - - waiter.start(); - } - }); - - // Add to Chat window - ChatManager chatManager = SparkManager.getChatManager(); - - try { - chatRoom = chatManager.getGroupChat(room); - } - catch (ChatNotFoundException e) { - MultiUserChat chat = MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).getMultiUserChat( room ); - chatRoom = new GroupChatRoom(chat); - } - - chatRoom.setTabTitle(title); - chatRoom.setTabIcon(SparkRes.getImageIcon(SparkRes.FASTPATH_IMAGE_16x16)); - chatRoom.getChatWindowPanel().add(transcriptAlert, new GridBagConstraints(0, 9, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(1, 0, 1, 0), 0, 0)); - - // set invisible - chatRoom.getSplitPane().getRightComponent().setVisible(false); - chatRoom.getBottomPanel().setVisible(false); - chatRoom.getScrollPaneForTranscriptWindow().setVisible(false); - - SparkManager.getChatManager().getChatContainer().addChatRoom(chatRoom); - - FastpathPlugin.getLitWorkspace().addFastpathChatRoom(chatRoom, RoomState.invitationRequest); - - rejectButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent actionEvent) { - // Add to Chat window - ChatManager chatManager = SparkManager.getChatManager(); - chatManager.removeChat(chatRoom); - - try - { - MultiUserChatManager.getInstanceFor( SparkManager.getConnection() ).decline( room, inviter, "No thank you" ); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to deline invatation from " + inviter + " to join room " + room, e ); - } - } - }); - - } - - /** - * Removes oneself as an owner of the room. - * - * @param muc the MultiUserChat of the chat room. - */ - private void removeOwner(MultiUserChat muc) { - if (muc.isJoined()) { - // Try and remove myself as an owner if I am one. - Collection owners = null; - try { - owners = muc.getOwners(); - } - catch (XMPPException | SmackException e1) { - return; - } - - if (owners == null) { - return; - } - - Iterator iter = owners.iterator(); - - List list = new ArrayList(); - while (iter.hasNext()) { - Affiliate affilitate = (Affiliate)iter.next(); - String jid = affilitate.getJid(); - if (!jid.equals(SparkManager.getSessionManager().getBareAddress())) { - list.add(jid); - } - } - if (list.size() > 0) { - try { - Form form = muc.getConfigurationForm().createAnswerForm(); - form.setAnswer("muc#roomconfig_roomowners", list); - - // new DataFormDialog(groupChat, form); - muc.sendConfigurationForm(form); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - } - } - } -} diff --git a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/util/RequestUtils.java b/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/util/RequestUtils.java deleted file mode 100644 index 573371d36..000000000 --- a/src/plugins/fastpath/src/java/org/jivesoftware/fastpath/workspace/util/RequestUtils.java +++ /dev/null @@ -1,185 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.fastpath.workspace.util; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - - -public class RequestUtils { - private Map metadata; - - public RequestUtils(Map requestData) { - this.metadata = requestData; - } - - public Map getMetadata() { - return metadata; - } - - /** - * Returns a Question if one was asked. - * - * @return the question the visitor asked before joining the queue. If not question - * was asked, null will be returned. - */ - public String getQuestion() { - if (getMetadata() == null) { - return null; - } - - final String question = getFirstValue("question"); //NOTRANS - return question; - } - - /** - * Returns the nickname of the Visitor. - * - * @return the nickname of the visitor. - */ - public String getUsername() { - if (getMetadata() == null) { - return null; - } - - final String vistorName = getFirstValue("username");//NOTRANS - return vistorName; - } - - /** - * Return the Users Email address, if specified. - * - * @return the users email address, otherwise will return null if an email - * address was not specified. - */ - public String getEmailAddress() { - if (getMetadata() == null) { - return null; - } - - final String emailAddress = getFirstValue("email");//NOTRANS - return emailAddress; - } - - /** - * Return the request location. - * - * @return the url (string format) of where the user made the initial request. - */ - public String getRequestLocation() { - if (getMetadata() == null) { - return null; - } - - final String requestLocation = getFirstValue("Location");//NOTRANS - return requestLocation; - } - - /** - * Returns the Unique Identifier of the user. - * - * @return the unique id of the user. - */ - public String getUserID() { - if (getMetadata() == null) { - return null; - } - - final String userID = getFirstValue("userID");//NOTRANS - return userID; - } - - public String getInviter() { - if (getMetadata() == null) { - return null; - } - - final String inviter = getFirstValue("inviter");//NOTRANS - return inviter; - } - - public String getWorkgroup() { - if (getMetadata() == null) { - return null; - } - - final String workgroup = getFirstValue("workgroup");//NOTRANS - return workgroup; - } - - public boolean isTransfer() { - if (getMetadata() == null) { - return false; - } - - boolean isTransfer = Boolean.valueOf(getFirstValue("transfer")).booleanValue();//NOTRANS - return isTransfer; - } - - public boolean isInviteOrTransfer() { - if (getMetadata() == null) { - return false; - } - - return getMetadata().containsKey("transfer"); //NOTRANS - } - - public String getSessionID() { - if (getMetadata() == null) { - return null; - } - - final String workgroup = getFirstValue("sessionID");//NOTRANS - return workgroup; - } - - public Map getMap() { - final Map returnMap = new HashMap(metadata); - returnMap.remove("sessionID"); - returnMap.remove("transfer"); - returnMap.remove("workgroup"); - returnMap.remove("inviter"); - returnMap.remove("username"); - returnMap.remove("question"); - returnMap.remove("userID"); - //returnMap.remove("email"); - return returnMap; - } - - public String getValue(String key) { - return getFirstValue(key); - } - - private String getFirstValue(String key) { - Object o = getMetadata().get(key); - if (o instanceof List) { - final List list = (List)getMetadata().get(key); - if (list.size() > 0) { - return (String)list.get(0); - } - } - else if (o instanceof String) { - return (String)o; - } - return null; - } - -} diff --git a/src/plugins/fastpath/src/resources/fastpath.properties b/src/plugins/fastpath/src/resources/fastpath.properties deleted file mode 100644 index efca7f2f2..000000000 --- a/src/plugins/fastpath/src/resources/fastpath.properties +++ /dev/null @@ -1,244 +0,0 @@ -APP_NAME = Spark -VERSION = Version 1.0 Release - -SPARK_IMAGE = images/spark.png -WELCOME = Welcome -ID_CARD_48x48 = images/id_card.png - -# LOGIN DIALOG -LOGIN_DIALOG_LOGIN = &Login -LOGIN_DIALOG_QUIT = &Quit -LOGIN_DIALOG_USERNAME = &Username: -LOGIN_DIALOG_PASSWORD = &Password: -LOGIN_DIALOG_WORKSPACE = &Workgroup: -LOGIN_DIALOG_LOGIN_TITLE = Spark -LOGIN_DIALOG_AUTHENTICATING = Authenticating... - -#MainWindow -MAIN_IMAGE = images/message.png -MAIN_IMAGE_ICO = images/icon_16.ico -SMALL_CHECK = images/smallCheck.png -SMALL_DELETE = images/smallDelete.png -AVAILABLE_USER = images/availableUser.png -AWAY_USER = images/awayUser.png -FIND_IMAGE = images/find.png -SMALL_ADD_IMAGE = images/small_add.png -DOCUMENT_EXCHANGE_IMAGE = images/document_exchange.png -SMALL_DOCUMENT_ADD = images/document_add.png -SMALL_CIRCLE_DELETE = images/small_delete.png -SMALL_DOCUMENT_VIEW = images/document_view.png -SMALL_USER1_MESSAGE = images/user1_message-16x16.png -USER1_MESSAGE_24x24 = images/user1_message-24x24.png -SMALL_USER1_TIME = images/user1_time.png -SMALL_USER1_NEW = images/user1_new.png -SMALL_USER1_STOPWATCH = images/stopwatch_pause.png -SMALL_USER1_MOBILEPHONE = images/user1_mobilephone.png -SMALL_USER1_INFORMATION = images/user1_information.png -SMALL_ENTRY = images/small_entry.gif -SMALL_AGENT_IMAGE = images/small_agent.png -CHATTING_AGENT_IMAGE = images/user1.png -CHATTING_CUSTOMER_IMAGE = images/user2.png -INFORMATION_IMAGE = images/information.png -BLANK_IMAGE = images/blank.gif -USER_HEADSET_24x24 = images/user_headset24.png -FOLDER_CLOSED = images/folder_closed.png -FOLDER = images/folder.png -SMALL_PIN_BLUE = images/pin_blue.png -SMALL_DATA_FIND_IMAGE = images/data_find.png -SMALL_BUSINESS_MAN_VIEW = images/businessman_view.png -SMALL_ALL_AGENTS_IMAGE = images/user1_earth.png -SMALL_WORKGROUP_QUEUE_IMAGE = images/users_into.png -SMALL_ALL_CHATS_IMAGE = images/users_family.png -SMALL_CURRENT_AGENTS = images/users2.png -HELP2_24x24 = images/help_24x24.png -SMALL_ALARM_CLOCK = images/alarmclock.png -SMALL_SCROLL_REFRESH = images/scroll_refresh.png -SMALL_QUESTION = images/help_16x16.png -USER1_32x32 = images/User1_32x32.png -DATA_DELETE_16x16 = images/data_delete.png -DATA_REFRESH_16x16 = images/data_refresh.png -USER1_BACK_16x16 = images/user1_back.png -FONT_16x16 = images/font.png -DOCUMENT_FIND_16x16 = images/document_find.png -DOCUMENT_INFO_32x32 = images/document_info.png -DOCUMENT_16x16 = images/document.png -SMALL_CLOSE_BUTTON = images/deleteitem.gif -COPY_16x16 = images/copy.png -BLANK_24x24 = images/blank_24x24.png -PUSH_URL_16x16 = images/earth_connection-16x16.png -LINK_16x16 = images/link-16x16.png -LINK_DELETE_16x16 = images/link_delete.png -EARTH_LOCK_16x16 = images/earth_lock-16x16.png -LOCK_16x16 = images/lock-16x16.png -LOCK_UNLOCK_16x16 = images/lock_unlock-16x16.png -ONLINE_ICO = images/icon1.ico -OFFLINE_ICO = images/icon2.ico -INFORMATION_ICO = images/icon3.ico -SAVE_AS_16x16 = images/save_as.png -NOTE_EDIT_16x16 = images/note_edit.png -ADDRESS_BOOK_16x16 = images/address_book.png -MEGAPHONE_16x16 = images/megaphone.png -EARTH_VIEW_16x16 = images/earth_view.png -HISTORY_16x16 = images/history.png -DOWNLOAD_16x16 = images/download.png -RED_FLAG_16x16 = images/flag_red.png -GREEN_FLAG_16x16 = images/flag_green.png -YELLOW_FLAG_16x16 = images/flag_yellow.png -FUNNEL_DOWN_16x16 = images/funnel_down.png -MAIL_16x16 = images/mail_16x16.png -MAIL_FORWARD_16x16 = images/mail_forward_16x16.png -MAIL_INTO_16x16 = images/mail_into_16x16.png -RED_BALL = images/red-ball.png -GREEN_BALL = images/green-ball.png -BLUE_BALL = images/blue-ball.png -YELLOW_BALL = images/yellow-ball.png -PAWN_GLASS_GREEN = images/pawn_glass_green.png -PAWN_GLASS_RED = images/pawn_glass_red.png -PAWN_GLASS_WHITE = images/pawn_glass_white.png -PAWN_GLASS_YELLOW = images/pawn_glass_yellow.png -PLUS_SIGN = images/plus-sign.png -MINUS_SIGN = images/minus-sign.png -MAGICIAN_IMAGE = images/magician.png -FIND_TEXT_IMAGE = images/find_text.png -LOGIN_KEY_IMAGE = images/login-key.png -BRICKWALL_IMAGE = images/brickwall.png -MODERATOR_IMAGE = images/moderator.gif -DESKTOP_IMAGE = images/desktop.png -SPELL_CHECK_IMAGE = images/text_ok.png -BUSY_IMAGE = images/busy.gif -CLOSE_IMAGE = images/close.png -VIEW_IMAGE = images/view.png -MOBILE_PHONE_IMAGE = images/mobilephone.png -ON_PHONE_IMAGE = images/on-phone.png -REFRESH_IMAGE = images/refresh.png -CLOSE_WHITE_X_IMAGE = images/close_white.png -CLOSE_DARK_X_IMAGE = images/close_dark.png - - -# Global Values -ERROR_INVALID_WORKGROUP = The workgroup is not valid. Please use a valid workgroup. -ERROR_DIALOG_TITLE = Login Error -INVALID_USERNAME_PASSWORD = Invalid username or password. -SERVER_UNAVAILABLE = Can't connect to server: invalid name or server not reachable. -UNRECOVERABLE_ERROR = Invalid username or password. - -#Chat Window Images - - - -#Chat window text -SEND = &Send -ADD_TO_KB = You can assign any response as either a question or an answer add them directly to the knowledge base for future reference. - -#Kbase Window -GO = &Go -ADD_TO_CHAT = &Add document -ADD_LINK_TO_CHAT = Add &link -VIEW = &View -SEARCH = &Search: - -#Chat Queue -ACCEPT_CHAT = &Accept -REJECT_CHAT = &Refuse -TIME_LEFT = Time left: - -#MainWindow -MAIN_TITLE = Spark -TOOLBOX = Toolbox -CHAT_QUEUE = Chat Queue -CURRENT_CHATS = My Chats -CURRENT_AGENTS = Online Agents -ALL_CHATS = All Chats -WORKGROUP_QUEUE = Queues -CHAT_WORKSPACE = Chat Workspace - -#GroupChat -CREATE_FAQ_ENTRY = Create a new FAQ entry? -CREATE_FAQ_TITLE = Create New FAQ -FAQ_TAB_TITLE = Analyzer -KNOWLEDGE_BASE_TAB_TITLE = Search -PROFILE_TAB_TITLE = Profile -CO_BROWSER_TAB_TITLE = Co-Browser -FORUM_TAB_TITLE = Forums - -#Images -CONFERENCE_IMAGE_24x24 = images/conference_24x24.png -CONFERENCE_IMAGE_16x16 = images/conference_16x16.png -PROFILE_IMAGE_24x24 = images/profile_24x24.png -SEARCH_USER_16x16 = images/search_user_16x16.png -SEND_FILE_24x24 = images/send_file_24x24.png -ADD_IMAGE_24x24 = images/add_24x24.png -TELEPHONE_24x24 = images/telephone_24x24.png -IM_DND = images/im_dnd.png -IM_AWAY = images/im_away.png -MESSAGE_AWAY = images/message_away.png -MESSAGE_DND = images/message_dnd.png -ERASER_IMAGE = images/eraser.gif -TOOLBAR_BACKGROUND = images/toolbar.png -TRAFFIC_LIGHT_IMAGE = images/traffic-light.png -SERVER_ICON = images/server.png -BOOKMARK_ICON = images/bookmark.png -ADD_BOOKMARK_ICON = images/bookmark_add.png -DELETE_BOOKMARK_ICON = images/bookmark_delete.png -CLEAR_BALL_ICON = images/bullet_ball_glass_clear.png -CALL_ICON = images/call.png -PROFILE_ICON = images/profile.png -SEND_FILE_ICON = images/document_into.png -ADD_CONTACT_IMAGE = images/add_contact.png -JOIN_GROUPCHAT_IMAGE = images/join_groupchat.png -DOWN_ARROW_IMAGE = images/down_arrow.gif -PRINTER_IMAGE_16x16 = images/printer.png -SEND_MAIL_IMAGE_16x16 = images/sendmail.png -SEARCH_IMAGE_32x32 = images/search_32x32.png -MAIL_IMAGE_32x32 = images/mail_32x32.png -PREFERENCES_IMAGE = images/preferences.png -NOTEBOOK_IMAGE = images/notebook.png -TEXT_BOLD = images/text_bold.png -TEXT_ITALIC = images/text_italics.png -TEXT_UNDERLINE = images/text_underlined.png -TEXT_NORMAL = images/text_normal.png -SMALL_USER_ENTER = images/smallUserEnter.png -SMALL_USER_DELETE = images/smallUserDelete.png -QUESTIONS_ANSWERS = images/questionsAnswers.png -SMALL_MESSAGE_IMAGE = images/message.png -SMALL_MESSAGE_EDIT_IMAGE = images/message_edit.png -SMALL_ABOUT_IMAGE = images/about.png -DOOR_IMAGE = images/door.gif -STAR_BLUE_IMAGE = images/star_blue.png -STAR_RED_IMAGE = images/star_red.png -STAR_GREY_IMAGE = images/star_grey.png -STAR_YELLOW_IMAGE = images/star_yellow.png -STAR_GREEN_IMAGE = images/star_green.png -LEFT_ARROW_IMAGE = images/arrow_left_green.png -RIGHT_ARROW_IMAGE = images/arrow_right_green.png -BACKGROUND_IMAGE = images/background.png -FREE_TO_CHAT_IMAGE = images/im_free_chat.png -SOUND_PREFERENCES_IMAGE = images/text_loudspeaker.png -SPARK_LOGOUT_IMAGE = images/spark_100.jpg -PHOTO_IMAGE = images/photo_scenery.png -PLUGIN_IMAGE = images/plugin-16x16.gif -SMALL_PROFILE_IMAGE = images/small_profile.png -CHANGELOG_IMAGE = images/doc-changelog-16x16.gif -README_IMAGE = images/doc-readme-16x16.gif -DOWN_OPTION_IMAGE = images/option.png -STICKY_NOTE_IMAGE = images/sticky.png -HISTORY_24x24 = images/history-24x24.png -PANE_UP_ARROW_IMAGE = images/metallic_up.png -PANE_DOWN_ARROW_IMAGE = images/metallic_down.png - -#Fastpath Icons -FASTPATH_IMAGE_16x16 = images/fastpath16.png -FASTPATH_IMAGE_24x24 = images/fastpath24.png -FASTPATH_IMAGE_32x32 = images/fastpath32.png -FASTPATH_IMAGE-64x63 = images/fastpath64.png -CIRCLE_CHECK_IMAGE = images/check.png -TRANSFER_IMAGE_24x24 = images/transfer-24x24.png -FASTPATH_OFFLINE_IMAGE_16x16 = images/fastpath16_offline.png -FASTPATH_OFFLINE_IMAGE_24x24 = images/fastpath24_offline.png -USER1_ADD_16x16 = images/user1_add.png -END_BUTTON_24x24 = images/end_button_24x24.png -POWERED_BY_IMAGE = images/powered_by.png -CHAT_INVITE_IMAGE_24x24 = images/icon_chatinvite_24x24.png -CHAT_TRANSFER_IMAGE_24x24 = images/icon_chattransfer_24x24.png -CHAT_COBROWSE_IMAGE_24x24 = images/icon_cobrowse_24x24.png -CHAT_ENDED_IMAGE_24x24 = images/icon_endchat1_24x24.png \ No newline at end of file diff --git a/src/plugins/fastpath/src/resources/i18n/fastpath_i18n_de.properties b/src/plugins/fastpath/src/resources/i18n/fastpath_i18n_de.properties deleted file mode 100644 index 57dbdc77e..000000000 --- a/src/plugins/fastpath/src/resources/i18n/fastpath_i18n_de.properties +++ /dev/null @@ -1,155 +0,0 @@ -workgroup = Arbeitsgruppe -join = Betreten -logout = Abmelden -cobrowsing.session = Co-Browsing-Sitzung -back = Zurück -go = Go -duration = Dauer -agents = Agents -date = Datum -invite.agent = Einladungen -invite = Einladen -transfer.to.agent = Weiterleitungen -transfer = Weiterleiten -workgroups = Arbeitsgruppe -transfer.to = Weiterleiten an -cancel = Abbrechen -agent = Agent -visitor = Besucher -email = E-Mail -question = Frage -start.time = Startzeit -seconds = Sekunden -name = Name -from = Von -room = Raum -message = Nachricht -number.in.queue = # in der Warteschleife -average.wait.time = Durchschnittliche Wartezeit -last.queue.activity = Letzte Warteschleifen-Aktivität -query = Suche -chat.with = Chat mit - - - -button.logout = Abme&lden -button.history = Verlauf -button.conference = &Konferenz -button.macros = &Makros -button.invite = &Einladen -button.transfer = &Transfer -button.canned.responses = &Vorgefertigte Antworten -button.end = B&eenden -button.co.browse = &Co-Browse -button.edit.canned.responses = Vorgefertigte Antworten b&earbeiten -button.start.cobrowsing.session = Co-Browsing-Sitzung starten -button.save.note = Notiz &speichern -button.new = &Neu -button.delete = &Löschen -button.save = &Speichern -button.accept = &Annehmen -button.reject = &Zurückweisen - - -checkbox.allow.user.to.follow = Nutzer die Nachverfolgung erlauben - -label.notes = &Notizen -label.message.to.agent = Nachricht an Agent -label.select.agent = Agent auswählen -label.title = &Titel -label.type = T&yp -label.response = Antwo&rt -label.initial.response = Ursprüngl&iche Antwort - - - -message.workgroup.logged.into = Angemeldet in der Arbeitsgruppe {0} -message.incoming.request = {0} -message.start.cobrowsing = Co-Browsing-Sitzung mit Seite {0} starten -message.send.cobrowsing.message = Einladung zum Co-Browsing mit Seite {0} senden -message.click.to.add.notes = Klicken Sie hier, um Notizen hinzuzufügen -message.chat.notes = Chat-Notizen werden diesem Chat beigefügt und können über die Chat-Suche durchsucht werden. -message.notes.updated = Notizen wurden aktualisiert -message.unable.to.update.notes = Die Notiz konnte nicht gespeichert werden. Bitte versuchen Sie es erneut. -message.view.more.information = Weitere Informationen anzeigen... -message.conversation.transferred = Das Gespräch wurde weitergeleitet -message.invitation.rejected = Die Einladung zum Gespräch wurde von {0} zurückgewiesen -message.please.join.me.in.conference = Bitte treten Sie der Konferenz bei. -message.user.has.been.invited = {0} wurde in das Gespräch eingeladen. -message.waiting.for.user = Warte auf {0}, den Transfer anzunehmen. -message.transfering.to.user = Ich übergebe dieses Gespräch an Sie. -message.join.me.in.chat = Bitte betreten Sie diesen Chat. -message.transfer.to.another.agent = Dieses Gespräch an einen anderen Agent, eine andere Arbeitsgruppe oder Warteschleife übergeben. -message.invite.another.agent = Andere einladen, dieses Gespräch zu betreten. -message.no.agent.selected.error = Es wurde kein Agent ausgewählt -message.jid.invalid.error = Geben Sie eine gültige JID ein -message.message.required.error = Geben Sie eine Nachricht ein -message.specify.personal.macros = Geben Sie persönliche Makros an, die Sie in Chats mit Ihren Kunden verwenden können. -message.macros.not.saved = Ihre Makros konnten nicht gespeichert werden. -message.add.new.response = Neue Antwort hinzufügen -message.current.chats = Derzeitige Chats ({0}) -message.transcript.not.found.error = Abschrift konnte nicht gefunden werden -message.incoming.chat.request = Eingehende Chat-Anfrage von {0} -message.user.joined.room = {0} hat den Raum betreten. -message.user.left.room = {0} hat den Raum verlassen. -message.not.specified = Nicht angegeben -message.user.not.logged.in = Der Benutzer ist nicht bei der Arbeitsgruppe angemeldet. -message.agent.is.not.in.chat = Agent ist derzeit in keinen Chats. -message.find.previous.conversations = Geben Sie Text ein, den Sie in vorherigen Gesprächen finden möchten - -menuitem.global.canned.responses = Globale vorgefertige Antworten -menuitem.no.entries = Keine Einträge in der Kategorie -menuitem.join.chat = Chat betreten -menuitem.monitor.chat = Chat überwachen - -tab.fastpath = Fastpath -tab.current.chats = Derzeitige Chats -tab.online.agents = Angemeldete Agents -tab.user.info = Benutzerinfo -tab.participants = Teilnehmer -tab.user.history = Benutzerverlauf -tab.notes = Notizen -tab.queue.activity = Warteschleifen-Aktivität -tab.transcript = Abschrift - -title.cobrowsing.for = Co-Browsing für {0} -title.chat.notes = Chatnotizen -title.notes = Notizen -title.request.information = Informationen über die Anfrage -title.information = Informationen -title.transcript = Abschrift -title.transfer = Transfer -title.invitation = Einladung -title.error = Fehler -title.contact.list = Kontaktliste -title.personal.macros = Persönliche Makros -title.response.name = Name der Antwort -title.response.text = Text der Antwort -title.personal = Persönlich -title.create.canned.response = Vorgefertigte Antwort erstellen -title.previous.chats = Vorherige Chats -title.personal.chats = Persönliche Chats -title.chat.transcript = Chatabschrift -title.current.active.conversations = Derzeitig aktive Gespräche -title.number.of.active.conversations = # der aktiven Gespräche -title.current.conversations = Derzeitige Gespräche -title.fastpath.invitation = Fastpath-Einladung -title.fastpath.transfer = Fastpath-Weiterleitung -title.workgroup = {0} Arbeitsgruppe -title.chat.transcripts = Chat-Abschriften -title.search.results = Suchergebnisse -title.chat.transcripts.search = Chatabschrift-Suche -title.number.of.conversations.found = # Gespräche gefunden: - - -tooltip.allow.cobrowsing = Erlaubt dem aktuellen Besucher, die Browsernavigation zu verfolgen. -tooltip.hide.cobrowsing = Browsernavigation dem aktuellen Besucher verbergen. -tooltip.back.one.page = Eine Seite zurückgehen -tooltip.push.url = Einen Link übergeben -tooltip.push.current.page = Aktuelle URL dem Besucher übergeben -tooltip.save.transcript = Chatabschrift speichern -tooltip.print.transcript = Chatabschrift drucken - -# TO DO -org.jivesoftware.fastpath.workspace.search -org.jivesoftware.fastpath.workspace.utils \ No newline at end of file diff --git a/src/plugins/fastpath/src/resources/i18n/fastpath_i18n_lt.properties b/src/plugins/fastpath/src/resources/i18n/fastpath_i18n_lt.properties deleted file mode 100644 index 76bf4f09b..000000000 --- a/src/plugins/fastpath/src/resources/i18n/fastpath_i18n_lt.properties +++ /dev/null @@ -1,151 +0,0 @@ -workgroup = Darbo grup\u0117 -join = Prisijungti -logout = Atsijungti -cobrowsing.session = Nar\u0161ymas kartu -back = Atgal -go = Pirmyn -duration = Trukm\u0117 -agents = Agentai -date = Data -invite.agent = Pakvietimai -invite = Pakviesti -transfer.to.agent = Nukreipimai -transfer = Nukreipimas -workgroups = Darbo grup\u0117s -transfer.to = Nukreipti \u012f -cancel = At\u0161aukti -agent = Agentas -visitor = Lankytojas -email = El. pa\u0161tas -question = Klausimas -start.time = Start Time -seconds = Sekund\u017Ei\u0173 -name = Vardas -from = Siunt\u0117jas -room = Kambarys -message = \u017dinu&t\u0117 -number.in.queue = # eil\u0117je -average.wait.time = Vidutin\u0117 laukimo trukm\u0117 -last.queue.activity = Paskutinis \u012fvykis eil\u0117je -query = U\u017eklausa -chat.with = Pokalbis su - - - -button.logout = &Atsijungti -button.history = \u017d&urnalai -button.conference = &Grupinis pokalbis -button.macros = &Skriptai -button.invite = &Pakviesti -button.transfer = &Nukreipti -button.canned.responses = &Paruo\u0161ti atsakymai -button.end = &Pabaigti -button.co.browse = &Nar\u0161yti kartu -button.edit.canned.responses = &Redaguoti paruo\u0161tus atsakymus -button.start.cobrowsing.session = Prad\u0117t nar\u0161ym\u0105 kartu -button.save.note = \u012e&ra\u0161yti u\u017era\u0161\u0105 -button.new = &Naujas -button.delete = &Pa\u0161alinti -button.save = \u012e&ra\u0161yti -button.accept = &Priimti -button.reject = &Atmesti - - -checkbox.allow.user.to.follow = Leisti abonentui sekti - -label.notes = &U\u017era\u0161ai -label.message.to.agent = \u017dinu&t\u0117 agentui -label.select.agent = Pasirinkite agent\u0105 -label.title = &Pavadinimas -label.type = &Tipas -label.response = &Atsakymas -label.initial.response = &Pradinis atsakymas - - - -message.workgroup.logged.into = Prisijung\u0119s prie {0} darbo grup\u0117s -message.incoming.request = {0} -message.start.cobrowsing = Prad\u0117t nar\u0161ym\u0105 kartu puslapyje {0} -message.send.cobrowsing.message = Nusi\u0173stas pakvietimas nar\u0161yti kartu puslapyje {0} -message.click.to.add.notes = Paspauskite \u010dia, kad prid\u0117ti u\u017era\u0161us. -message.chat.notes = Pokalbio u\u017era\u0161ai yra priskirti \u0161iam pokalbiui ir juos galima bus rasti pokalbio paie\u0161koje. -message.notes.updated = U\u017era\u0161ai buvo atnaujinti -message.unable.to.update.notes = Ne\u012fmanoma i\u0161saugoti u\u017era\u0161o. Pra\u0161ome bandyti dar kart\u0105. -message.view.more.information = Per\u017ei\u016br\u0117ti daugiau informacijos... -message.conversation.transferred = Pokalbis buvo nukreiptas. -message.invitation.rejected = {0} atmet\u0117 pakvietim\u0105 \u012f pokalb\u012f. -message.please.join.me.in.conference = Pra\u0161au prisijungi prie man\u0119s konferecijoje -message.user.has.been.invited = {0} buvo pakviestas prisijungti prie \u0161io pokalbio. -message.waiting.for.user = Laukiama kol {0} patvirtins \u0161\u012f nukreipim\u0105. -message.transfering.to.user = Nukreipiu \u0161\u012f pokalb\u012f jums. -message.join.me.in.chat = Pra\u0161au prisijungi prie man\u0119s \u0161iame pokalbyje. -message.transfer.to.another.agent =Nukreipti \u0161\u012f pokalb\u012f \u012f kit\u0105 agent\u0105, darbo grup\u0119 ar eil\u0119. -message.invite.another.agent = Pakviesti kitus prisijungti prie \u0161io pokalbio. -message.no.agent.selected.error = Nebuvo pasirinktas agentas -message.jid.invalid.error = \u012eveskite teising\u0105 identifikatori\u0173 (JID) -message.message.required.error = \u012eveskite \u017einut\u0119 -message.specify.personal.macros = Nustatykite asmeninius skriptus naudojimui pokalbiuose su klientais. -message.macros.not.saved = J\u016bs\u0173 skriptai nebuvo i\u0161saugoti. -message.add.new.response = Prid\u0117ti nauj\u0105 atsakym\u0105 -message.current.chats = Vykstantys pokalbiai ({0}) -message.transcript.not.found.error = Pokalbio \u017eurnalas nerastas -message.incoming.chat.request = \u012eeinanti u\u017eklausa i\u0161 {0} -message.user.joined.room = {0} apsilank\u0117 kambaryje. -message.user.left.room = {0} i\u0161\u0117jo i\u0161 kambario. -message.not.specified = Nenurodyta -message.user.not.logged.in = Abonentas neprisijung\u0119s prie darbo grup\u0117s. -message.agent.is.not.in.chat = \u0160iuo metu agentas nedalyvauja pokalbiuose. -message.find.previous.conversations = \u012eveskite tekst\u0105 norim\u0105 rasti buvusiuose pokalbiuose. - -menuitem.global.canned.responses = Bendri paruo\u0161ti atsakymai -menuitem.no.entries = Kategorijoje n\u0117ra \u012fra\u0161\u0173 -menuitem.join.chat = Prisijungti prie pokalbio -menuitem.monitor.chat = Steb\u0117ti pokalb\u012f - -tab.fastpath = Fastpath -tab.current.chats = Vykstantys pokalbiai -tab.online.agents = Prisijung\u0119 agentai -tab.user.info = Abonento informacija -tab.participants Dalyviai -tab.user.history = Abonento \u017eurnalas -tab.notes = U\u017era\u0161ai -tab.queue.activity = Eil\u0117s b\u016bsena -tab.transcript = Pokalbio \u017eurnalas - -title.cobrowsing.for = Nar\u0161ymas kartu su {0} -title.chat.notes = Pokalbio u\u017era\u0161ai -title.notes = U\u017era\u0161ai -title.request.information = U\u017eklausos informacija -title.information = Informacija -title.transcript = Pokalbio \u017eurnalas -title.transfer = Nukreipimas -title.invitation = Pakvietimas -title.error = Klaida -title.contact.list = Adresat\u0173 s\u0105ra\u0161as -title.personal.macros = Asmeniniai skriptai -title.response.name = Atsakymo pavadinimas -title.response.text = Atsakymo tekstas -title.personal = Asmeniniai -title.create.canned.response = Sukurti paruo\u0161t\u0105 atsakym\u0105 -title.previous.chats = \u012evyk\u0119 pokalbiai -title.personal.chats = Asmeniniai pokalbiai -title.chat.transcript = Pokalbio \u017eurnalas -title.current.active.conversations = Vykstantys pokalbiai -title.number.of.active.conversations = # vyksantys pokalbiai -title.current.conversations = Vykstantys pokalbiai -title.fastpath.invitation = Fastpath pakvietimas -title.fastpath.transfer = Fastpath nukreipimas -title.workgroup = {0} darbo grup\u0117 -title.chat.transcripts = Pokalbi\u0173 \u017eurnalai -title.search.results = Paie\u0161kos rezultatai -title.chat.transcripts.search = Paie\u0161ka pokalbi\u0173 \u017eurnaluose -title.number.of.conversations.found = # rast\u0173 pokalbi\u0173: - - -tooltip.allow.cobrowsing = Leid\u017eia \u0161iam lankytojui sekti j\u016bs\u0173 nar\u0161ym\u0105. -tooltip.hide.cobrowsing = Pasl\u0117pia j\u016bs\u0173 nar\u0161ym\u0105 nuo \u0161io lankytojo. -tooltip.back.one.page = Gr\u012f\u017eti \u012f buvus\u012f puslap\u012f -tooltip.push.url = Nusi\u0173sti nuorod\u0105 -tooltip.push.current.page = Nusi\u0173sti esam\u0105 nuorod\u0105 lankytojui -tooltip.save.transcript = \u012era\u0161yti pokalbio \u017eurnal\u0105 -tooltip.print.transcript = Atspausdinti pokalbio \u017eurnal\u0105 \ No newline at end of file diff --git a/src/plugins/fastpath/src/resources/i18n/fastpath_i18n_pl.properties b/src/plugins/fastpath/src/resources/i18n/fastpath_i18n_pl.properties deleted file mode 100644 index 26186782c..000000000 --- a/src/plugins/fastpath/src/resources/i18n/fastpath_i18n_pl.properties +++ /dev/null @@ -1,155 +0,0 @@ -workgroup = Grupa robocza -join = Do\u0142\u0105cz -logout = Wyloguj -cobrowsing.session = Sesja jednoczesnego przegl\u0105dania -back = Wstecz -go = Dalej -duration = Czas trwania -agents = Agenci -date = Data -invite.agent = Zaproszenia -invite = Zapro\u015b -transfer.to.agent = Transfery -transfer = Transfer -workgroups = Grupy robocze -transfer.to = Transferuj do -cancel = Anuluj -agent = Agent -visitor = Go\u015b\u0107 -email = E-mail -question = Pytanie -start.time = Czas pocz\u0105tku -seconds = Sekundy -name = Nazwa -from = Z -room = Pok\u00f3j -message = Wiadomo\u015b\u0107 -number.in.queue = # W kolejce -average.wait.time = \u015aredni czas oczekiwania -last.queue.activity = Ostatnia aktywno\u015b\u0107 w kolejce -query = Zapytanie -chat.with = Rozmowa z - - - -button.logout = Wyloguj -button.history = Historia -button.conference = Konferencja -button.macros = Makra -button.invite = Zapro\u015b -button.transfer = Transfer -button.canned.responses = Gotowe odpowiedzi -button.end = Zako\u0144cz -button.co.browse = Przegl\u0105d jednoczesny -button.edit.canned.responses = Edytuj gotowe odpowiedzi -button.start.cobrowsing.session = Rozpocznij sesj\u0119 jednoczesnego przegl\u0105dania -button.save.note = Zapisz notatk\u0119 -button.new = Nowy -button.delete = Usu\u0144 -button.save = Zapisz -button.accept = Akceptuj -button.reject = Odrzu\u0107 - - -checkbox.allow.user.to.follow = Pozw\u00f3l u\u017cytkownikowi na \u015bledzenie - -label.notes = Notatki -label.message.to.agent = Wiadomo\u015b\u0107 do agenta -label.select.agent = Wybierz agenta -label.title = Tytu\u0142 -label.type = Typ -label.response = Odpowied\u017a -label.initial.response = Zainicjuj odpowied\u017a - - - -message.workgroup.logged.into = Zalogowany do {0} grupy roboczej -message.incoming.request = {0} -message.start.cobrowsing = Rozpocznij sesj\u0119 jednoczesnego przegl\u0105dania ze stron\u0105 {0} -message.send.cobrowsing.message = Wy\u015blij zaproszenie do jednoczesnego przegl\u0105dania ze stron\u0105 {0} -message.click.to.add.notes = Kliknij aby doda\u0107 notatki. -message.chat.notes = Notatki s\u0105 zwi\u0105zane z t\u0105 rozmow\u0105 i b\u0119dzie mo\u017cna je wyszuka\u0107 poprzez szukajk\u0119 rozmowy. -message.notes.updated = Notatki zosta\u0142y zaktualizowane -message.unable.to.update.notes = Nie mo\u017cna zatwierdzi\u0107 notatki. Spr\u00f3buj ponownie. -message.view.more.information = Zobacz wi\u0119cej informacji... -message.conversation.transferred = Rozmowa zosta\u0142a przes\u0142ana. -message.invitation.rejected = Zaproszenie do rozmowy zosta\u0142o odrzucone przez {0} -message.please.join.me.in.conference = Do\u0142\u0105cz do mnie w konferencji -message.user.has.been.invited = {0} zosta\u0142 zaproszony by do\u0142\u0105czy\u0107 do tej rozmowy. -message.waiting.for.user = Oczekiwanie na {0} by zaakceptowa\u0142 ten przesy\u0142. -message.transfering.to.user = Przesy\u0142am t\u0105 rozmow\u0119 do Ciebie. -message.join.me.in.chat = Do\u0142\u0105cz do mnie w tej rozmowie. -message.transfer.to.another.agent = Prze\u015blij t\u0105 rozmow\u0119 do innego agenta, grupy roboczej lub kolejki. -message.invite.another.agent = Zapro\u015b innych by do\u0142\u0105czyli do tej rozmowy. -message.no.agent.selected.error = \u017baden agent nie zosta\u0142 wybrany -message.jid.invalid.error = Wprowad\u017a poprawny JID -message.message.required.error = Wpisz wiadomo\u015b\u0107 -message.specify.personal.macros = Okre\u015bl osobiste makra do u\u017cycia w Twoich rozmowach z odbiorc\u0105. -message.macros.not.saved = Twoje makra nie zosta\u0142y zapisane. -message.add.new.response = Dodaj now\u0105 odpowied\u017a -message.current.chats = Obecne rozmowy ({0}) -message.transcript.not.found.error = Zapis nie m\u00f3g\u0142 zostaæ odnaleziony -message.incoming.chat.request = Przychodz\u0105ca pro\u015bba rozmowy od {0} -message.user.joined.room = {0} do\u0142\u0105czy\u0142 do pokoju. -message.user.left.room = {0} opu\u015bci\u0142 pok\u00f3j. -message.not.specified = Nieokre\u015blone -message.user.not.logged.in = U\u017cytkownik nie jest zalogowany w grupie roboczej. -message.agent.is.not.in.chat = Agent nie jest obecnie w \u017cadnych rozmowach. -message.find.previous.conversations = Wprowad\u017a tekst by odnale\u017a\u0107 go we wcze\u015bniejszych rozmowach. - -menuitem.global.canned.responses = Og\u00f3lne gotowe odpowiedzi -menuitem.no.entries = Brak wpis\u00f3w w kategorii -menuitem.join.chat = Do\u0142\u0105cz do rozmowy -menuitem.monitor.chat = Monitoruj rozmow\u0119 - -tab.fastpath = Fastpath -tab.current.chats = Obecne rozmowy -tab.online.agents = Dost\u0119pni agenci -tab.user.info = Informacje o u\u017cytkowniku -tab.participants = Uczestnicy -tab.user.history = Historia u\u017cytkownika -tab.notes = Notatki -tab.queue.activity = Aktywno\u015b\u0107 kolejki -tab.transcript = Transkrypcja - -title.cobrowsing.for = Jednoczesne przegl\u0105danie dla {0} -title.chat.notes = Notatki z rozm\u00f3w -title.notes = Notatki -title.request.information = Pro\u015bba o informacje -title.information = Informacja -title.transcript = Transkrypcja -title.transfer = Transfer -title.invitation = Zaproszenie -title.error = B\u0142\u0105d -title.contact.list = Lista kontakt\u00f3w -title.personal.macros = Osobiste makra -title.response.name = Nazwa odpowiedzi -title.response.text = Tekst odpowiedzi -title.personal = Osobiste -title.create.canned.response = Utw\u00f3rz gotow\u0105 odpowied\u017a -title.previous.chats = Poprzednie rozmowy -title.personal.chats = Osobiste rozmowy -title.chat.transcript = Transkrypcja rozmowy -title.current.active.conversations = Aktualne aktywne rozmowy -title.number.of.active.conversations = # aktywnych rozm\u00f3w -title.current.conversations = Aktualne rozmowy -title.fastpath.invitation = Zaproszenie Fastpath -title.fastpath.transfer = Transfer Fastpath -title.workgroup = {0} grupa robocza -title.chat.transcripts = Transkrypty rozmowy -title.search.results = Wyniki wyszukiwania -title.chat.transcripts.search = Wyszukiwanie transkrypt\u00f3w rozm\u00f3w -title.number.of.conversations.found = # rozm\u00f3w znaleziono: - - -tooltip.allow.cobrowsing = Pozwala obecnemu go\u015bciowi na stosowanie Twojej nawigacji przegl\u0105daj\u0105cej. -tooltip.hide.cobrowsing = Ukrywa Twoj\u0105 nawigacj\u0119 przegl\u0105daj\u0105c\u0105 przed obecnym go\u015bciem. -tooltip.back.one.page = Wraca o jedn\u0105 stron\u0119 -tooltip.push.url = Wypycha link -tooltip.push.current.page = Wypycha obecny URL do go\u015bcia -tooltip.save.transcript = Zapisuje transkrypt rozmowy -tooltip.print.transcript = Drukuje transkrypt rozmowy - -# TO DO -org.jivesoftware.fastpath.workspace.search -org.jivesoftware.fastpath.workspace.utils \ No newline at end of file diff --git a/src/plugins/fastpath/src/resources/i18n/fastpath_i18n_pt_BR.properties b/src/plugins/fastpath/src/resources/i18n/fastpath_i18n_pt_BR.properties deleted file mode 100644 index af2997915..000000000 --- a/src/plugins/fastpath/src/resources/i18n/fastpath_i18n_pt_BR.properties +++ /dev/null @@ -1,162 +0,0 @@ -workgroup = Grupo de Trabalho -join = Entrar -logout = Logout -cobrowsing.session = Iniciar Navega\u00E7\u00E3o -back = Voltar -go = Ir -duration = Dura\u00E7\u00E3o -agents = Atendentes -date = Data -invite.agent = Convites -invite = Convidar -transfer.to.agent = Transfer\u00EAncias -transfer = Transfer\u00EAncia -workgroups = Grupos de Trabalho -transfer.to = Transferir Para -cancel = Cancelar -agent = Atendente -visitor = Visitante -email = Email -question = Quest\u00E3o -start.time = Tempo de In\u00EDcio -seconds = Segundos -name = Nome -from = De -room = Sala -message = Mensagem -number.in.queue = # Em Espera -average.wait.time = Tempo M\u00E9dio de Espera -last.queue.activity = Atividade da \u00DAltima Fila -query = Consulta -chat.with = Chat com -# NOVO -ask.assistance = Solicitar Assist\u00EAncia -queues = Filas - -button.logout = &Logout -button.history = &Hist\u00F3rico -button.conference = &Confer\u00EAncia -button.macros = &Macros -button.invite = &Convidar -button.transfer = &Transfer\u00EAncia -button.canned.responses = &Respostas Prontas -button.end = &Fim -button.co.browse = &Iniciar Navega\u00E7\u00E3o -button.edit.canned.responses = &Editar Respostas Prontas -button.start.cobrowsing.session = Iniciar Navega\u00E7\u00E3o Conjunta -button.save.note = &Salvar Nota -button.new = &Novo -button.delete = &Deletar -button.save = &Salvar -button.accept = &Aceitar -button.reject = &Rejeitar -# Novo -button.invite.another.user = Convidar outro atendente para se unir a esta conversa -button.transfer.conversation = Transferir Conversa para outro atendente -button.end.conversation = Terminar Conversa -button.start.cobrowse.user = Iniciar co-browsing com este usu\u00E1rio. - -checkbox.allow.user.to.follow = Permitir Usu\u00E1rio Seguir - -label.notes = &Notas -label.message.to.agent = Mensagem para o atendente -label.select.agent = Selecionar Atendente -label.title = &T\u00EDtulo -label.type = T&ipo -label.response = &Resposta -label.initial.response = &Resposta Inicial - - - -message.workgroup.logged.into = Logado no Grupo de Trabalho {0} -message.incoming.request = {0} -message.start.cobrowsing = Iniciar uma sess\u00E3o de Co-Navega\u00E7\u00E3o com a p\u00E1gina {0} -message.send.cobrowsing.message = Enviado um convite de Co-Navega\u00E7\u00E3o com a p\u00E1gina {0} -message.click.to.add.notes = Clique aqui para adicionar notas. -message.chat.notes = Anota\u00E7\u00F5es de Chat est\u00E3o associadas a este chat e ser\u00E3o localizadas pela busca do chat. -message.notes.updated = Notas foram atualizadas. -message.unable.to.update.notes = Incapaz de enviar nota. Por favor tente novamente. -message.view.more.information = Ver mais informa\u00E7\u00F5es... -message.conversation.transferred = Esta conversa\u00E7\u00E3o foi transferida. -message.invitation.rejected = O convite de conversa foi rejeitado por {0} -message.please.join.me.in.conference = Por favor junte-se a mim nesta confer\u00EAncia. -message.user.has.been.invited = {0} foi convidado para se juntar a esta conversa. -message.waiting.for.user = Aguardando por {0} para aceitar esta transfer\u00EAncia. -message.transfering.to.user = Eu estou transferindo esta conversa para voc\u00EA. -message.join.me.in.chat = Por favor participe comigo deste chat. -message.transfer.to.another.agent = Transfira esta conversa para outro atendente, Grupo de Trabalho ou Fila. -message.invite.another.agent = Convide outras pessoas para se juntar a esta conversa. -message.no.agent.selected.error = Nenhum atendente foi selecionado -message.jid.invalid.error = Deixe um JID v\u00E1lido -message.message.required.error = Deixe uma mensagem -message.specify.personal.macros = Especifique macros pessoais para uso em chats com seus cliente. -message.macros.not.saved = Suas macros n\u00E3o poder\u00E3o ser salvas. -message.add.new.response = Adicionar nova resposta -message.current.chats = Chats atuais ({0}) -message.transcript.not.found.error = C\u00F3pia n\u00E3o pode ser localizada -message.incoming.chat.request = Pedido de Chat vindo de {0} -message.user.joined.room = {0} se juntou a sala. -message.user.left.room = {0} deixou a sala. -message.not.specified = N\u00E3o especificado -message.user.not.logged.in = O usu\u00E1rio n\u00E3o est\u00E1 conectado ao Grupo de Trabalho. -message.agent.is.not.in.chat = Atendente n\u00E3o est\u00E1 em nenhum bate-papo. -message.find.previous.conversations = Insira o texto para procurar em conversas anteriores. -# Novo -message.less.one.minute = menos de 1 minuto - -menuitem.global.canned.responses = Respostas Prontas Globais -menuitem.no.entries = Sem entradas na Categoria -menuitem.join.chat = Entrar no Chat -menuitem.monitor.chat = Monitorar Chat - -tab.fastpath = Fastpath -tab.current.chats = Chats Atuais -tab.online.agents = Atendente Online -tab.user.info = Informa\u00E7\u00E3o de Usu\u00E1rio -tab.participants = Participantes -tab.user.history = Hist\u00F3rico de Usu\u00E1rio -tab.notes = Notas -tab.queue.activity = Atividade da Fila -tab.transcript = C\u00F3pia - -title.cobrowsing.for = Co-Navega\u00E7\u00E3o Para {0} -title.chat.notes = Anota\u00E7\u00F5es do Chat -title.notes = Notas -title.request.information = Pedido de Informa\u00E7\u00E3o -title.information = Informa\u00E7\u00E3o -title.transcript = Transcript -title.transfer = Transfer\u00EAncia -title.invitation = Convite -title.error = Erro -title.contact.list = Lista de Contato -title.personal.macros = Macros Pessoais -title.response.name = Nome de Resposta -title.response.text = Texto Resposta -title.personal = Pessoal -title.create.canned.response = Criar resposta pronta -title.previous.chats = Chats Anteriores -title.personal.chats = Chats Pessoais -title.chat.transcript = C\u00F3pia Chat -title.current.active.conversations = Conversas Ativas Atuais -title.number.of.active.conversations = # de conversas atuais -title.current.conversations = Conversas Atuais -title.fastpath.invitation = Convite -title.fastpath.transfer = Transfer\u00EAncia -title.workgroup = {0} Grupo de Trabalho -title.chat.transcripts = C\u00F3pias de Chats -title.search.results = Buscar Resultados -title.chat.transcripts.search = Pesquisa C\u00F3pias de Chat -title.number.of.conversations.found = # conversas encontradas: - - -tooltip.allow.cobrowsing = Permite visitante atual seguir sua navega\u00E7\u00E3o. -tooltip.hide.cobrowsing = Mostra a sua navega\u00E7\u00E3o ao visitante. -tooltip.back.one.page = Voltar uma p\u00E1gina -tooltip.push.url = Envie um link -tooltip.push.current.page = Envie a URL atual visitante -tooltip.save.transcript = Salvar C\u00F3pia de Chat -tooltip.print.transcript = Imprimir C\u00F3pia de Chat - -# TO DO -org.jivesoftware.fastpath.workspace.search -org.jivesoftware.fastpath.workspace.utils \ No newline at end of file diff --git a/src/plugins/fastpath/src/resources/images/icon_chattransfer_24x24.png b/src/plugins/fastpath/src/resources/images/icon_chattransfer_24x24.png deleted file mode 100644 index 2a6012f82..000000000 Binary files a/src/plugins/fastpath/src/resources/images/icon_chattransfer_24x24.png and /dev/null differ diff --git a/src/plugins/fastpath/src/resources/images/icon_cobrowse_24x24.png b/src/plugins/fastpath/src/resources/images/icon_cobrowse_24x24.png deleted file mode 100644 index d7a56960e..000000000 Binary files a/src/plugins/fastpath/src/resources/images/icon_cobrowse_24x24.png and /dev/null differ diff --git a/src/plugins/fastpath/src/resources/images/icon_endchat1_24x24.png b/src/plugins/fastpath/src/resources/images/icon_endchat1_24x24.png deleted file mode 100644 index d3273862d..000000000 Binary files a/src/plugins/fastpath/src/resources/images/icon_endchat1_24x24.png and /dev/null differ diff --git a/src/plugins/flashing/build/build.xml b/src/plugins/flashing/build/build.xml deleted file mode 100644 index 073cbf3d1..000000000 --- a/src/plugins/flashing/build/build.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/flashing/plugin.xml b/src/plugins/flashing/plugin.xml deleted file mode 100644 index 70a924a3e..000000000 --- a/src/plugins/flashing/plugin.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - Window Flashing Plugin - 1.1 - Michael Will - http://www.igniterealtime.org - michael-will@gmx.net - Flash window on new messages. - org.jivesoftware.spark.plugin.flashing.FlashingPlugin - 2.7.0 - Windows - 1.7.0 - \ No newline at end of file diff --git a/src/plugins/flashing/resources/i18n/flashing_i18n_fr.properties b/src/plugins/flashing/resources/i18n/flashing_i18n_fr.properties deleted file mode 100644 index 0ae3d6368..000000000 --- a/src/plugins/flashing/resources/i18n/flashing_i18n_fr.properties +++ /dev/null @@ -1,6 +0,0 @@ -title.flashing = Clignotement de la barre des t\u00E2ches - -flashing.enable = &Activer le clignotement -flashing.type = &Taper -flashing.type.continuous = Continue -flashing.type.temporary = Temporaire \ No newline at end of file diff --git a/src/plugins/flashing/resources/i18n/flashing_i18n_lt.properties b/src/plugins/flashing/resources/i18n/flashing_i18n_lt.properties deleted file mode 100644 index 9ca43d747..000000000 --- a/src/plugins/flashing/resources/i18n/flashing_i18n_lt.properties +++ /dev/null @@ -1,6 +0,0 @@ -title.flashing = Mirg\u0117jimas - -flashing.enable = \u012ejungti informacin\u012f mirg\u0117jim\u0105 u\u017eduo\u010di\u0173 juostoje -flashing.type = B\u016bdas -flashing.type.continuous = Mirg\u0117ti be galo -flashing.type.temporary = Pamirg\u0117jus nustoti \ No newline at end of file diff --git a/src/plugins/flashing/resources/i18n/flashing_i18n_pl.properties b/src/plugins/flashing/resources/i18n/flashing_i18n_pl.properties deleted file mode 100644 index c075fd1b1..000000000 --- a/src/plugins/flashing/resources/i18n/flashing_i18n_pl.properties +++ /dev/null @@ -1,6 +0,0 @@ -title.flashing = Migotanie paska zada\u0144 - -flashing.enable = W\u0142\u0105cz migotanie paska zada\u0144 -flashing.type = Rodzaj migotania -flashing.type.continuous = Ci\u0105g\u0142y -flashing.type.temporary = Tymczasowy \ No newline at end of file diff --git a/src/plugins/flashing/resources/i18n/flashing_i18n_ru_RU.properties b/src/plugins/flashing/resources/i18n/flashing_i18n_ru_RU.properties deleted file mode 100644 index 0cc5771f8..000000000 --- a/src/plugins/flashing/resources/i18n/flashing_i18n_ru_RU.properties +++ /dev/null @@ -1,6 +0,0 @@ -title.flashing = \u041c\u0438\u0433\u0430\u043d\u0438\u0435 \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u0437\u0430\u0434\u0430\u0447 - -flashing.enable = &\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043c\u0438\u0433\u0430\u043d\u0438\u0435 \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u0437\u0430\u0434\u0430\u0447 -flashing.type = &\u0422\u0438\u043f -flashing.type.continuous = \u041d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e -flashing.type.temporary = \u0412\u0440\u0435\u043c\u0435\u043d\u043d\u043e diff --git a/src/plugins/flashing/resources/i18n/flashing_i18n_zh_CN.properties b/src/plugins/flashing/resources/i18n/flashing_i18n_zh_CN.properties deleted file mode 100644 index 033e1a2de..000000000 --- a/src/plugins/flashing/resources/i18n/flashing_i18n_zh_CN.properties +++ /dev/null @@ -1,8 +0,0 @@ -#Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net) - -flashing.enable = \u5141\u8BB8\u4EFB\u52A1\u680F\u95EA\u52A8 -flashing.type = \u7C7B\u578B -flashing.type.continuous = \u6301\u7EED -flashing.type.temporary = \u4E34\u65F6 - -title.flashing = \u4EFB\u52A1\u680F\u95EA\u52A8 diff --git a/src/plugins/flashing/resources/i18n/flashing_i18n_zh_TW.properties b/src/plugins/flashing/resources/i18n/flashing_i18n_zh_TW.properties deleted file mode 100644 index c11e747a9..000000000 --- a/src/plugins/flashing/resources/i18n/flashing_i18n_zh_TW.properties +++ /dev/null @@ -1,6 +0,0 @@ -title.flashing = \u5de5\u5177\u5217\u9583\u52d5 - -flashing.enable = \u555f\u52d5\u5de5\u5177\u5217\u9583\u52d5 -flashing.type = \u9583\u52d5\u985e\u578b -flashing.type.continuous = \u6301\u7e8c\u9583\u52d5 -flashing.type.temporary = \u81e8\u6642\u9583\u52d5 \ No newline at end of file diff --git a/src/plugins/google/GooglePlugin.iml b/src/plugins/google/GooglePlugin.iml deleted file mode 100644 index 478f900d4..000000000 --- a/src/plugins/google/GooglePlugin.iml +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/google/build/build.xml b/src/plugins/google/build/build.xml deleted file mode 100644 index 2b5732036..000000000 --- a/src/plugins/google/build/build.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/google/plugin.xml b/src/plugins/google/plugin.xml deleted file mode 100644 index aa4176d51..000000000 --- a/src/plugins/google/plugin.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - Google Plugin - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Adds Google Desktop Search to Spark. - org.jivesoftware.spark.plugin.GooglePlugin - 2.7.0 - 1.7.0 - diff --git a/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GoogleDocument.java b/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GoogleDocument.java deleted file mode 100644 index 223587330..000000000 --- a/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GoogleDocument.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.plugin; - -import java.awt.Color; -import java.awt.Desktop; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.File; -import java.net.URI; -import java.net.URL; - -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.UserManager; -import org.jivesoftware.spark.component.LinkLabel; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.filetransfer.SparkTransferManager; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; - -public class GoogleDocument extends JPanel { - - private static final long serialVersionUID = -2460486842621050765L; - private GoogleSearchResult result; - - public GoogleDocument(final ChatRoom room, final GoogleSearchResult result) { - setLayout(new GridBagLayout()); - setBackground(Color.white); - - this.result = result; - - ClassLoader cl = getClass().getClassLoader(); - URL imageURL = cl.getResource("images/send_file_24x24.png"); - RolloverButton sendButton = new RolloverButton(new ImageIcon(imageURL)); - String url = result.getURL(); - String title = result.getSubject(); - - Icon icon = result.getIcon(); - if (icon == null || icon.getIconWidth() == -1) { - icon = SparkRes.getImageIcon(SparkRes.DOCUMENT_16x16); - } - - LinkLabel documentLabel = new LinkLabel(title, url, Color.blue, Color.red); - - add(sendButton, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(new JLabel(icon), new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - add(documentLabel, new GridBagConstraints(2, 0, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - documentLabel.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent mouseEvent) { - mouseEvent.consume(); - try { - File file = new File(result.getURL()); - if (file.exists()) { - Runtime.getRuntime().exec("rundll32 SHELL32.DLL,ShellExec_RunDLL " + result.getURL()); - } - else { - // Assume it's .html - Desktop.getDesktop().browse(new URI(result.getURL())); - } - } - catch (Exception e1) { - // Nothing to do - } - } - }); - - sendButton.addActionListener( actionEvent -> { - SparkTransferManager transferManager = SparkManager.getTransferManager(); - ChatRoomImpl chatRoom = (ChatRoomImpl)room; - File file = new File(result.getURL()); - if (file.exists()) { - UserManager userManager = SparkManager.getUserManager(); - String fullJID = userManager.getFullJID(chatRoom.getParticipantJID()); - if (fullJID != null) - transferManager.sendFile(file, fullJID); - - } - else { - Message message = new Message(); - message.setBody(result.getURL()); - chatRoom.sendMessage(message); - - chatRoom.getTranscriptWindow().insertNotificationMessage("Sent URL: " + result.getURL(), ChatManager.NOTIFICATION_COLOR); - } - - } - - ); - } - - public GoogleSearchResult getSearchResult() { - return result; - } - -} diff --git a/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GoogleFileViewer.java b/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GoogleFileViewer.java deleted file mode 100644 index 88e7fa161..000000000 --- a/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GoogleFileViewer.java +++ /dev/null @@ -1,210 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.plugin; - - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.EventQueue; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.File; -import java.io.IOException; -import java.util.Collection; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.Icon; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.ListSelectionModel; -import javax.swing.table.TableCellRenderer; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.component.Table; -import org.jivesoftware.spark.component.TitlePanel; -import org.jivesoftware.spark.component.browser.BrowserFactory; -import org.jivesoftware.spark.component.browser.BrowserViewer; -import org.jivesoftware.spark.util.GraphicUtils; -import org.jivesoftware.spark.util.log.Log; - -public class GoogleFileViewer { - DocumentTable table; - - public void viewFiles(final Collection col, final boolean showFiles) { - - EventQueue.invokeLater( () -> { - table = new DocumentTable(); - TitlePanel titlePanel = new TitlePanel("Google Search", "Results from your search.", null, true); - - final JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BorderLayout()); - mainPanel.add(titlePanel, BorderLayout.NORTH); - - JScrollPane pane = new JScrollPane(table); - pane.getViewport().setBackground(Color.white); - - mainPanel.add(pane, BorderLayout.CENTER); - - // Build Viewer - - - for (GoogleSearchResult aCol : col) { - GoogleSearchResult result = aCol; - Icon icon = result.getIcon(); - if (icon.getIconWidth() == -1) { - icon = SparkRes.getImageIcon(SparkRes.SMALL_DOCUMENT_VIEW); - } - JLabel label = new JLabel(icon); - label.setName(result.getCachedURL()); - String url = result.getURL(); - - boolean isFile = new File(url).exists(); - - if (isFile && showFiles) { - Object[] obj = {label, result.getSubject(), result.getURL()}; - table.getTableModel().addRow(obj); - } else if (!isFile) { - Object[] obj = {label, result.getSubject(), result.getURL()}; - table.getTableModel().addRow(obj); - } - - } - - // Create Frame - JFrame frame = new JFrame("Google Search"); - - - frame.setIconImage(SparkRes.getImageIcon(SparkRes.SMALL_DOCUMENT_VIEW).getImage()); - frame.getContentPane().setLayout(new BorderLayout()); - frame.getContentPane().add(mainPanel, BorderLayout.CENTER); - frame.pack(); - frame.setSize(600, 400); - GraphicUtils.centerWindowOnScreen(frame); - frame.setVisible(true); - } ); - - - - - } - - - private final class DocumentTable extends Table { - private static final long serialVersionUID = 2740929154486852378L; - - public DocumentTable() { - super(new String[]{" ", "Document Title", "Location"}); - getColumnModel().setColumnMargin(0); - getColumnModel().getColumn(0).setMaxWidth(30); - - setSelectionBackground(Table.SELECTION_COLOR); - setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - setRowSelectionAllowed(true); - - - addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - int row = getSelectedRow(); - JLabel label = (JLabel)getValueAt(row, 0); - String title = (String)getValueAt(row, 1); - JFrame frame = new JFrame("Viewing Document - " + title); - frame.setIconImage(SparkRes.getImageIcon(SparkRes.SMALL_DOCUMENT_VIEW).getImage()); - BrowserViewer viewer = BrowserFactory.getBrowser(); - - frame.getContentPane().setLayout(new BorderLayout()); - frame.getContentPane().add(viewer, BorderLayout.CENTER); - - frame.pack(); - frame.setSize(600, 400); - - frame.setLocationRelativeTo(table); - frame.setVisible(true); - try { - viewer.loadURL(label.getName()); - } - catch (Exception e1) { - Log.error(e1); - } - - - } - } - - public void mouseReleased(MouseEvent e) { - checkPopup(e); - } - - public void mousePressed(MouseEvent e) { - checkPopup(e); - } - }); - - } - - // Handle image rendering correctly - public TableCellRenderer getCellRenderer(int row, int column) { - Object o = getValueAt(row, column); - if (o != null) { - if (o instanceof JLabel) { - return new JLabelRenderer(false); - } - } - return super.getCellRenderer(row, column); - } - - private void checkPopup(MouseEvent e) { - if (e.isPopupTrigger()) { - final JPopupMenu popupMenu = new JPopupMenu(); - - Action action = new AbstractAction() { - private static final long serialVersionUID = 5747717080614743622L; - - public void actionPerformed(ActionEvent e) { - int selectedRow = table.getSelectedRow(); - if (selectedRow != -1) { - String location = (String)table.getValueAt(selectedRow, 2); - File file = new File(location); - try { - Runtime.getRuntime().exec("explorer \"" + file.getParentFile().getAbsolutePath() + "\""); - } - catch (IOException e1) { - Log.error(e1); - } - - } - } - }; - - action.putValue(Action.NAME, "Open Location"); - popupMenu.add(action); - popupMenu.show(table, e.getX(), e.getY()); - - - } - } - - } -} diff --git a/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GooglePlugin.java b/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GooglePlugin.java deleted file mode 100644 index 269b077bf..000000000 --- a/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GooglePlugin.java +++ /dev/null @@ -1,242 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.plugin; - - -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smackx.vcardtemp.packet.VCard; -import org.jivesoftware.spark.ui.ContactList; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ChatRoomListenerAdapter; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.component.VerticalFlowLayout; -import org.jivesoftware.spark.component.panes.CollapsiblePane; -import org.jivesoftware.sparkimpl.profile.VCardManager; - -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; -import java.net.URL; -import java.util.Iterator; -import java.util.List; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.ImageIcon; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.text.BadLocationException; - -public class GooglePlugin implements Plugin { - public void initialize() { - // Add "Find Reference to." - ContactList contactList = SparkManager.getWorkspace().getContactList(); - contactList.addContextMenuListener(new ContextMenuListener() { - public void poppingUp(Object object, JPopupMenu popup) { - if (object instanceof ContactItem) { - final ContactItem item = (ContactItem)object; - final Action findReferenceAction = new AbstractAction() { - private static final long serialVersionUID = 6791538529104540239L; - - public void actionPerformed(ActionEvent actionEvent) { - findReferences(item); - } - }; - ClassLoader cl = getClass().getClassLoader(); - URL url = cl.getResource("images/google.gif"); - ImageIcon icon = new ImageIcon(url); - findReferenceAction.putValue(Action.SMALL_ICON, icon); - findReferenceAction.putValue(Action.NAME, "Find documents relating to " + item.getNickname()); - popup.add(findReferenceAction); - } - } - - public void poppingDown(JPopupMenu popup) { - - } - - public boolean handleDefaultAction(MouseEvent e) { - return false; - } - }); - - SparkManager.getSearchManager().addSearchService(new GoogleSearchable()); - - - SparkManager.getChatManager().addChatRoomListener(new ChatRoomListenerAdapter() { - public void chatRoomOpened(final ChatRoom room) { - ClassLoader cl = getClass().getClassLoader(); - URL url = cl.getResource("images/google.gif"); - ImageIcon icon = new ImageIcon(url); - final RolloverButton searchButton = new RolloverButton(icon); - - JPanel buttonPanel = room.getEditorBar(); - buttonPanel.add(searchButton); - - searchButton.addActionListener( actionEvent -> { - String text = room.getChatInputEditor().getSelectedText(); - if(text == null){ - text = room.getTranscriptWindow().getSelectedText(); - } - if (ModelUtil.hasLength(text)) { - GoogleSearch search = new GoogleSearch(); - List list = search.searchText(text, 4); - if(list.size() == 0){ - return; - } - - CollapsiblePane pane = new CollapsiblePane("Search Results"); - JPanel panel = new JPanel(); - pane.setContentPane(panel); - - panel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); - - - for (GoogleSearchResult aList : list) { - GoogleSearchResult result = aList; - GoogleDocument document = new GoogleDocument(room, result); - panel.add(document); - } - - room.getTranscriptWindow().addComponent(pane); - try { - room.getTranscriptWindow().insertText("\n"); - } - catch (BadLocationException e) { - Log.error(e); - } - - } - } ); - - - room.getTranscriptWindow().addContextMenuListener(new ContextMenuListener() { - public void poppingUp(Object object, JPopupMenu popup) { - final Action searchConversationAction = new AbstractAction() { - private static final long serialVersionUID = -5696144571481817379L; - - public void actionPerformed(ActionEvent actionEvent) { - searchConversation(room); - } - }; - - final Action searchAction = new AbstractAction() { - private static final long serialVersionUID = 5437636852619141730L; - - public void actionPerformed(ActionEvent actionEvent) { - searchText(room.getTranscriptWindow().getSelectedText()); - } - }; - - searchAction.putValue(Action.NAME, "Google Selected Text"); - - searchConversationAction.putValue(Action.NAME, "Google Conversation"); - - if (room.getTranscriptWindow().getSelectedText() != null) { - popup.add(searchAction); - } - else { - popup.add(searchConversationAction); - } - } - - public void poppingDown(JPopupMenu popup) { - - } - - public boolean handleDefaultAction(MouseEvent e) { - return false; - } - }); - - - } - - public void chatRoomClosed(ChatRoom room) { - } - }); - } - - private void findReferences(ContactItem item) { - GoogleSearch search = new GoogleSearch(); - - VCardManager vcardManager = SparkManager.getVCardManager(); - - VCard vcard = vcardManager.getVCard(item.getJID()); - String emailHome = vcard.getEmailHome(); - String emailWork = vcard.getEmailWork(); - - StringBuilder buf = new StringBuilder(); - if (emailHome != null) { - buf.append(emailHome); - buf.append(" "); - } - - - if (emailWork != null) { - buf.append(emailWork); - } - - if (buf.toString().trim().length() == 0) { - JOptionPane.showMessageDialog(SparkManager.getMainWindow(), "No profile for " + item.getJID(), "No User Profile", JOptionPane.ERROR_MESSAGE); - return; - } - - - search.search(buf.toString(), false); - } - - private void searchConversation(ChatRoom room) { - GoogleSearch search = new GoogleSearch(); - List transcripts = room.getTranscripts(); - Iterator iter = transcripts.iterator(); - - StringBuilder buf = new StringBuilder(); - while (iter.hasNext()) { - Message message = iter.next(); - buf.append(message.getBody()); - } - - search.search(buf.toString(), true); - } - - private void searchText(String text) { - GoogleSearch search = new GoogleSearch(); - search.search(text, true); - } - - public void shutdown() { - - } - - public boolean canShutDown() { - return false; - } - - public void uninstall() { - - } - - -} diff --git a/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GoogleSearch.java b/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GoogleSearch.java deleted file mode 100644 index 34e59f47f..000000000 --- a/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GoogleSearch.java +++ /dev/null @@ -1,322 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.plugin; - - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.util.URLFileSystem; -import org.jivesoftware.spark.util.WinRegistry; -import org.jivesoftware.spark.util.log.Log; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -public class GoogleSearch { - final ImageIcon icon; - private DocumentBuilder db; - - String searchUrl; - String searchBase; - - public GoogleSearch() { - // Initialize icon to use. - icon = SparkRes.getImageIcon(SparkRes.SEARCH_IMAGE_32x32); - - // Google Desktop API tosearch - try { - searchUrl = WinRegistry.readString(WinRegistry.HKEY_CURRENT_USER, "Software\\Google\\Google Desktop\\API", "search_url"); - searchBase = searchUrl.substring(0, searchUrl.indexOf('/', 8)); - - db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - } - catch (Exception e) { - // Nothing to do - } - } - - /** - * Return the name of the title to use on the Search Tab. - * - * @return the name of the title to use on the Search Tab. - */ - public String getTabTitle() { - return "Google Desktop"; - } - - /** - * Return the icon to use on the Search Tab. - * - * @return the icon to use. - */ - public Icon getTabIcon() { - return icon; - } - - /** - * Executed when a search has been started. - * - * @param query the query to search on. - * @param showFiles Show the files - */ - public void search(String query, boolean showFiles) { - final List list = new ArrayList<>(); - - if (query == null || "".equals(query)) { - return; - } - - Document doc = null; - try { - URL url = new URL(searchUrl + URLEncoder.encode(query, "UTF-8") + "&format=xml&num=50"); - String content = URLFileSystem.getContents(url); - doc = db.parse(new ByteArrayInputStream(content.getBytes())); - } - catch (IOException e) { - Log.error(e); - } - catch (SAXException e) { - Log.error(e); - } - - if (doc == null) { - return; - } - - try { - Element e = doc.getDocumentElement(); - int count = Integer.parseInt(e.getAttribute("count")); - NodeList elems = e.getElementsByTagName("result"); - for (int i = 0; i < elems.getLength(); i++) { - int relevance = (int)((double)(count - i) / count * 100); - GoogleSearchResult result = new GoogleSearchResult(searchBase, query, relevance, (Element)elems.item(i)); - list.add(result); - } - } - catch (Exception e1) { - Log.error(e1); - } - - if (list.size() > 0) { - new GoogleFileViewer().viewFiles(list, showFiles); - } - - - } - - /** - * Executed when a search has been started. - * - * @param query the query to search on. - * @param maxDocuments Max documents to return - * @return List containing search resilts. - */ - public List searchText(String query, int maxDocuments) { - final List list = new ArrayList<>(); - - if (query == null || "".equals(query)) { - return null; - } - - Document doc = null; - try { - URL url = new URL(searchUrl + URLEncoder.encode(query, "UTF-8") + "&format=xml&num=50"); - String content = URLFileSystem.getContents(url); - doc = db.parse(new ByteArrayInputStream(content.getBytes())); - } - catch (IOException e) { - Log.error(e); - } - catch (SAXException e) { - Log.error(e); - } - - try { - Element e = doc.getDocumentElement(); - int count = Integer.parseInt(e.getAttribute("count")); - NodeList elems = e.getElementsByTagName("result"); - for (int i = 0; i < elems.getLength(); i++) { - int relevance = (int)((double)(count - i) / count * 100); - GoogleSearchResult result = new GoogleSearchResult(searchBase, query, relevance, (Element)elems.item(i)); - if ( !result.getURL().contains( "googlemail" ) ) { - list.add(result); - } - if (list.size() == maxDocuments) { - break; - } - } - } - catch (Exception e1) { - Log.error(e1); - } - - return list; - } - - /** - * Executed when a search has been started. - * - * @param query the query to search on. - */ - public void searchConversations(String query) { - final List list = new ArrayList<>(); - - if (query == null || "".equals(query)) { - return; - } - - Document doc = null; - try { - URL url = new URL(searchUrl + URLEncoder.encode(query, "UTF-8") + "&format=xml&num=50"); - String content = URLFileSystem.getContents(url); - doc = db.parse(new ByteArrayInputStream(content.getBytes())); - } - catch (IOException e) { - Log.error(e); - } - catch (SAXException e) { - Log.error(e); - } - - if (doc == null) { - return; - } - - try { - Element e = doc.getDocumentElement(); - int count = Integer.parseInt(e.getAttribute("count")); - NodeList elems = e.getElementsByTagName("result"); - for (int i = 0; i < elems.getLength(); i++) { - int relevance = (int)((double)(count - i) / count * 100); - GoogleSearchResult result = new GoogleSearchResult(searchBase, query, relevance, (Element)elems.item(i)); - list.add(result); - } - } - catch (Exception e1) { - Log.error(e1); - } - - for (GoogleSearchResult result : list) { - String url = result.getURL(); - System.out.println(url); - } - - - } - - /** - * Executed when a search has been started. - * - * @param query the query to search on. - * @return Collection of search documents retreived. - */ - public Collection searchDocuments(String query) { - final Set set = new HashSet<>(); - - if (query == null || "".equals(query)) { - return null; - } - - Document doc = null; - try { - URL url = new URL(searchUrl + URLEncoder.encode(query, "UTF-8") + "&format=xml&num=50"); - String content = URLFileSystem.getContents(url); - doc = db.parse(new ByteArrayInputStream(content.getBytes())); - } - catch (IOException e) { - Log.error(e); - } - catch (SAXException e) { - Log.error(e); - } - - if (doc == null) { - return null; - } - - try { - Element e = doc.getDocumentElement(); - int count = Integer.parseInt(e.getAttribute("count")); - NodeList elems = e.getElementsByTagName("result"); - for (int i = 0; i < elems.getLength(); i++) { - int relevance = (int)((double)(count - i) / count * 100); - GoogleSearchResult result = new GoogleSearchResult(searchBase, query, relevance, (Element)elems.item(i)); - String url = result.getURL(); - File file = new File(url); - if (file.exists() && !file.getName().endsWith(".class")) { - boolean exists = false; - for (GoogleSearchResult r : set) { - if (r.getSubject().equals(result.getSubject())) { - exists = true; - break; - } - } - - if (!exists) { - set.add(result); - } - } - } - } - catch (Exception e1) { - Log.error(e1); - } - - - return set; - - } - - - /** - * Return true if you wish this to be searched by the Chat Analyzer. - * - * @return true if you wish this to be searched by the Chat Analyzer. - */ - public boolean isUsedForChatAnalysis() { - return false; - } - - /** - * Return the title headers for the result table. Please note that the SearchResult - * should return the values in the exact order as this method defines. - * - * @return the field headers to use. - */ - public String[] getFieldHeaders() { - return new String[]{"Title", "Subject"}; - } -} diff --git a/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GoogleSearchResult.java b/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GoogleSearchResult.java deleted file mode 100644 index 8affa477f..000000000 --- a/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GoogleSearchResult.java +++ /dev/null @@ -1,221 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.plugin; - -import org.jivesoftware.spark.component.browser.BrowserFactory; -import org.jivesoftware.spark.component.browser.BrowserViewer; -import org.jivesoftware.spark.util.StringUtils; -import org.jivesoftware.spark.util.log.Log; -import org.w3c.dom.Element; - -import java.awt.BorderLayout; -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JComponent; -import javax.swing.JPanel; - - -/** - * The GoogleSearchResult is one instance of a found item from a Google Search. - * - * @author Derek DeMoro - */ -public class GoogleSearchResult { - private String searchBase; - private String query; - private int relevance; - String id; - String title; - String url; - String time; - String snippet; - String icon; - String cacheUrl; - String from; - - public GoogleSearchResult(String searchBase, String query, int relevance, Element element) { - this.searchBase = searchBase; - this.query = query; - this.relevance = relevance; - this.id = getContent("id", element); - this.title = getContent("title", element); - this.url = getContent("url", element); - this.time = getContent("time", element); - this.snippet = getContent("snippet", element); - this.icon = getContent("icon", element); - this.cacheUrl = getContent("cache_url", element); - this.from = getContent("from", element); - } - - private String getContent(String field, Element element) { - try { - return (element.getElementsByTagName(field).item(0)).getChildNodes().item(0).getNodeValue(); - } - catch (Exception e) { - return null; - } - } - - public String getCachedURL() { - return cacheUrl; - } - - public void setQuery(String query) { - this.query = query; - } - - public String getQuery() { - return query; - } - - public String getUniqueID() { - return id; - } - - public String getSubject() { - title = StringUtils.stripTags(title); - - return title.replaceAll("<[^>]+>", ""); - } - - public String getAuthor() { - return from != null ? from : "unknown"; - } - - public String getToolTip() { - return snippet; - } - - /** - * Return the relevance of this document pertaining to the query. - * - * @return the relevance of this document. - */ - public int getRelevance() { - return relevance; - } - - public Date getPostedDate() { - return new Date(Long.parseLong(time)); - } - - /** - * Return the icon to be used to identify the type of search result. - * - * @return the icon to be use. - */ - public Icon getIcon() { - try { - return new ImageIcon(new URL(searchBase + icon)); - } - catch (MalformedURLException e) { - return null; - } - } - - /** - * Return the component to use to display this document. - * - * @return the component to use to display this document. - */ - public JComponent getDocumentViewer() { - BrowserViewer viewer = BrowserFactory.getBrowser(); - File file = new File(url); - if (file.exists()) { - try { - viewer.loadURL(cacheUrl); - } - catch (Exception e) { - Log.error(e); - } - } - else { - try { - viewer.loadURL(url); - } - catch (Exception e) { - try { - viewer.loadURL(cacheUrl); - } - catch (Exception e1) { - Log.error(e1); - } - } - } - - JPanel p = new JPanel(); - p.setLayout(new BorderLayout()); - p.add(viewer, BorderLayout.CENTER); - - return p; - } - - public String getURL() { - return url; - } - - /** - * Return the values to populate the table with. Please see - * GoogleSearchPlugin#getFieldHeaders() for the type of data to return. - * - * @return the values to populate the table with. - */ - public List getFieldValues() { - final List returnList = new ArrayList<>(); - returnList.add(StringUtils.stripTags(snippet)); - returnList.add(getSubject()); - return returnList; - } - - /** - * Value returned if item is dragged. - * - * @return the value returned if this item is dragged. - */ - public String getDraggableValue() { - return ""; - } - - /** - * Returns the date when this object was created. - * - * @return the date when this object was created. - */ - public Date getCreationDate() { - return null; - } - - /** - * Returns a summary of the search result item. This will be displayed in the "All" tab of a search result. - * - * @return the summary of the search result. - */ - public String getSummary() { - return getSubject(); - } - -} diff --git a/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GoogleSearchable.java b/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GoogleSearchable.java deleted file mode 100644 index 673c30ca6..000000000 --- a/src/plugins/google/src/java/org/jivesoftware/spark/plugin/GoogleSearchable.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.plugin; - - -import org.jivesoftware.spark.search.Searchable; - -import java.net.URL; -import java.util.Collection; - -import javax.swing.Icon; -import javax.swing.ImageIcon; - -public class GoogleSearchable implements Searchable { - - public Icon getIcon() { - ClassLoader cl = getClass().getClassLoader(); - URL url = cl.getResource("images/google.gif"); - return new ImageIcon(url); - } - - public String getName() { - return "Google"; - } - - public String getDefaultText() { - return "Find Documents on your computer."; - } - - public String getToolTip() { - return "Search for documents on your computer using Google Desktop."; - } - - public void search(String query) { - GoogleSearch search = new GoogleSearch(); - Collection list = search.searchDocuments(query); - - GoogleFileViewer viewer = new GoogleFileViewer(); - viewer.viewFiles(list, true); - } -} diff --git a/src/plugins/google/src/resources/images/google.gif b/src/plugins/google/src/resources/images/google.gif deleted file mode 100644 index 5f2ee5d2e..000000000 Binary files a/src/plugins/google/src/resources/images/google.gif and /dev/null differ diff --git a/src/plugins/growl/GrowlPlugin.iml b/src/plugins/growl/GrowlPlugin.iml deleted file mode 100644 index 0675afbdc..000000000 --- a/src/plugins/growl/GrowlPlugin.iml +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/growl/build.xml b/src/plugins/growl/build.xml deleted file mode 100644 index 49ecebced..000000000 --- a/src/plugins/growl/build.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/growl/build/lib/libgrowl.jnilib b/src/plugins/growl/build/lib/libgrowl.jnilib deleted file mode 100644 index 182162e88..000000000 Binary files a/src/plugins/growl/build/lib/libgrowl.jnilib and /dev/null differ diff --git a/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlMessageListener.java b/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlMessageListener.java deleted file mode 100644 index 444c00232..000000000 --- a/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlMessageListener.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.jivesoftware.spark.plugin.growl; - -import info.growl.GrowlException; - -import javax.swing.SwingUtilities; - -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.ui.ChatFrame; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.GlobalMessageListener; -import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; - -/** - * {@link GrowlMessageListener} implements the {@link GlobalMessageListener} and - * creates Growl Notifications on Message received - * - * @author Wolf.Posdorfer - */ -public class GrowlMessageListener implements GlobalMessageListener { - - private GrowlTalker _growltalker; - - public GrowlMessageListener() { - try { - - _growltalker = new GrowlTalker(); - } catch (GrowlException e) { - Log.error("growl error",e); - } - } - - public void messageReceived(final ChatRoom chatRoom, final Message message) { - - SwingUtilities.invokeLater( () -> { - final ChatFrame chatFrame = SparkManager.getChatManager().getChatContainer() - .getChatFrame(); - - if (!chatFrame.isInFocus()) { - showGrowlNotification(message); - } - } ); - - } - - /** - * Show a global Growl Notification - * - * @param message - * , {@link Message} containing Body and Sender - */ - private void showGrowlNotification(Message message) { - try { - String name = SparkManager.getUserManager().getUserNicknameFromJID(message.getFrom()); - String jid = message.getFrom(); - - if (name == null) { - name = XmppStringUtils.parseLocalpart(message.getFrom()); - } - - _growltalker.sendNotificationWithCallback(name, message.getBody(), jid); - - } catch (Exception e) { - Log.error(e.getMessage(), e); - } - - } - - public void messageSent(ChatRoom room, Message message) { - - } - -} diff --git a/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlPlugin.java b/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlPlugin.java deleted file mode 100644 index dd31a96df..000000000 --- a/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlPlugin.java +++ /dev/null @@ -1,114 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.jivesoftware.spark.plugin.growl; - -import org.jivesoftware.Spark; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.Plugin; - -import java.io.*; - -/** - * Provides support for Growl Notifications on Mac OS X. Growl can be acquired - * at http://growl.info - * - * - * @author Wolf.Posdorfer - */ -public class GrowlPlugin implements Plugin { - - private GrowlMessageListener growlListener; - - public void initialize() { - boolean b = placeLibs(); - try { - Thread.sleep(1500); - } catch (InterruptedException e) { - } - - if (!b) { - placeLibs(); - try { - Thread.sleep(1500); - } catch (InterruptedException e) { - } - } - - GrowlPreference preference = new GrowlPreference(); - // SparkManager.getPreferenceManager().addPreference(preference); - growlListener = new GrowlMessageListener(); - SparkManager.getChatManager().addGlobalMessageListener(growlListener); - } - - public void shutdown() { - SparkManager.getChatManager().removeGlobalMessageListener(growlListener); - } - - public boolean canShutDown() { - return true; - } - - public void uninstall() { - SparkManager.getChatManager().removeGlobalMessageListener(growlListener); - } - - /** - * Places the libgrowl.jnilib into /Library/Java/Extensions - * - * @return - */ - private boolean placeLibs() { - - boolean result; - - File f = new File(Spark.getUserHome() + "/Library/Java/Extensions/libgrowl.jnilib"); - - if (f.exists()) { - return true; - } - - String home = Spark.getSparkUserHome() + "/plugins/growl/lib/"; - File library = new File(home + "libgrowl.jnilib"); - - System.out.println(f.exists() + " " + library.exists()); - - try { - InputStream in = new FileInputStream(library); - OutputStream out = new FileOutputStream(f); - - // Transfer bytes from in to out - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - in.close(); - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - - result = f.exists(); - - return result; - - } - -} diff --git a/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlPreference.java b/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlPreference.java deleted file mode 100644 index 5a7d6ca6b..000000000 --- a/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlPreference.java +++ /dev/null @@ -1,118 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.jivesoftware.spark.plugin.growl; - -import javax.swing.Icon; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JPanel; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.preference.Preference; - -/** - * - * Simple Class for GrowlPreference Panel
        - * currently not in use - * - * @author wolf.posdorfer - * - */ -public class GrowlPreference implements Preference { - - JPanel _panel; - private static final long serialVersionUID = 7485099198887907166L; - - public GrowlPreference() { - - } - - @Override - public void commit() { - - } - - @Override - public Object getData() { - return ""; - } - - @Override - public String getErrorMessage() { - return "error with growlplugin"; - } - - @Override - public JComponent getGUI() { - _panel = new JPanel(); - JButton button = new JButton("Test"); - JButton button2 = new JButton("test2"); - - _panel.add(button); - _panel.add(button2); - - return _panel; - } - - @Override - public Icon getIcon() { - return SparkRes.getImageIcon(SparkRes.DUMMY_CONTACT_IMAGE); - } - - @Override - public String getListName() { - return "growl"; - } - - @Override - public String getNamespace() { - - return "growler"; - } - - @Override - public String getTitle() { - - return "GROWL"; - } - - @Override - public String getTooltip() { - - return "tooltip"; - } - - @Override - public boolean isDataValid() { - - return true; - } - - @Override - public void load() { - - } - - @Override - public void shutdown() { - - } - -} diff --git a/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlTalker.java b/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlTalker.java deleted file mode 100644 index 6a15614af..000000000 --- a/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlTalker.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.jivesoftware.spark.plugin.growl; - -import info.growl.Growl; -import info.growl.GrowlCallbackListener; -import info.growl.GrowlException; -import info.growl.GrowlUtils; - -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; - -/** - * GrowlTalker Class to send Messages to the GrowlInstance - * - * @author Wolf.Posdorfer - * - */ -public class GrowlTalker implements GrowlCallbackListener { - - private Growl _growl; - private final String SPARK = "Spark"; - - public GrowlTalker() throws GrowlException { - - _growl = GrowlUtils.getGrowlInstance(SPARK); - - _growl.addNotification(SPARK, true); - _growl.addCallbackListener(this); - - _growl.register(); - - } - - @Override - public void notificationWasClicked(String arg0) { - String jid = XmppStringUtils.parseBareJid(arg0); - ChatRoom room = SparkManager.getChatManager().getChatRoom(jid); - - SparkManager.getChatManager().getChatContainer().activateChatRoom(room); - SparkManager.getChatManager().getChatContainer().requestFocusInWindow(); - - } - - /** - * Sends a simple Notification - * - * @param name - * @param title - * @param body - */ - public void sendNotification(String title, String body) { - try { - _growl.sendNotification(SPARK, title, body); - } catch (GrowlException e) { - Log.error("growl error", e); - } - - } - - /** - * Sends a notification with a CallBackContext - * - * @param title - * the title to display - * @param body - * the body to display - * @param callbackContext - * a callback context - */ - public void sendNotificationWithCallback(String title, String body, String callbackContext) { - try { - _growl.sendNotification(SPARK, title, body, callbackContext); - } catch (GrowlException e) { - System.out.println("growl error" + e); - } - - } - -} diff --git a/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlTest.java b/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlTest.java deleted file mode 100644 index eb25d16f9..000000000 --- a/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.jivesoftware.spark.plugin.growl; - - -import info.growl.Growl; -import info.growl.GrowlCallbackListener; -import info.growl.GrowlException; -import info.growl.GrowlUtils; - -import java.awt.event.ActionEvent; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.JButton; -import javax.swing.JFrame; - -/** - * Simple Test Class to test Growl behaviour - * - * @author wolf.posdorfer - * - */ -public class GrowlTest { - - public static void main(String[] args) throws GrowlException { - - new GrowlTest(); - } - - final String appName = "Eclipse"; - - public GrowlTest() throws GrowlException { - - JFrame f = new JFrame("test"); - f.setVisible(true); - f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - Growl growl = GrowlUtils.getGrowlInstance(appName); - growl.addNotification(appName, true); - - GrowlCallbackListener listener = clickContext -> System.out.println(clickContext + " was clicked"); - - growl.addCallbackListener(listener); - growl.register(); - - Action action = new AbstractAction("CLICK") { - private static final long serialVersionUID = -7415179834807796108L; - - public void actionPerformed(ActionEvent ae) { - try { - Growl gu = GrowlUtils.getGrowlInstance(appName); - gu.sendNotification(appName, "title", "body", "callbackcontext"); - } catch (GrowlException ge) { - ge.printStackTrace(); - } - } - }; - - JButton button = new JButton(action); - f.setSize(200, 200); - - f.add(button); - - } - -} diff --git a/src/plugins/growl/src/info/growl/DummyGrowl.java b/src/plugins/growl/src/info/growl/DummyGrowl.java deleted file mode 100644 index 135fbe066..000000000 --- a/src/plugins/growl/src/info/growl/DummyGrowl.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2008, Michael Stringer - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Growl nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package info.growl; - -import java.awt.image.RenderedImage; - -/** - * Dummy implementation of the Growl API for situations where the native code - * cannot be loaded (non-Mac systems). - * - * @author Michael Stringer - * @version 0.1 - */ -class DummyGrowl implements Growl { - - /** - * {@inheritDoc} - */ - public void addNotification(String name, boolean enabledByDefault) { - // does nothing - } - - /** - * {@inheritDoc} - */ - public void register() throws GrowlException { - // does nothing - } - - /** - * {@inheritDoc} - */ - public void sendNotification(String name, String title, String body) - throws GrowlException { - // does nothing - } - - /** - * {@inheritDoc} - */ - public void sendNotification(String name, String title, String body, - RenderedImage icon) throws GrowlException { - // does nothing - } - - /** - * {@inheritDoc} - */ - public void setIcon(RenderedImage icon) throws GrowlException { - // does nothing - } - - /** - * {@inheritDoc} - */ - public void sendNotification(String name, String title, String body, - String callbackContext) throws GrowlException { - // does nothing - } - - /** - * {@inheritDoc} - */ - public void sendNotification(String name, String title, String body, - String callbackContext, RenderedImage icon) throws GrowlException { - // does nothing - } - - /** - * {@inheritDoc} - */ - public void addCallbackListener(GrowlCallbackListener listener) { - // does nothing - } -} diff --git a/src/plugins/growl/src/info/growl/Growl.java b/src/plugins/growl/src/info/growl/Growl.java deleted file mode 100644 index 9ea3abeda..000000000 --- a/src/plugins/growl/src/info/growl/Growl.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2008, Michael Stringer - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Growl nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package info.growl; - -import java.awt.image.RenderedImage; - -/** - * Interface for sending notifications to Growl. - * - * @author Michael Stringer - * @version 0.1 - */ -public interface Growl { - /** - * Registers this Growl object with the Growl service. - * - * @throws GrowlException - * If an error occurs during the registration. - */ - public void register() throws GrowlException; - - /** - * Sets the icon to display for notifications from this Growl. - * - * This must be called before calling {@link #register()}. If the - * icon is changed after {@link #register()} has been called then another - * call to {@link #register()} must be made. - * - * @param icon - * The icon to display. - * @throws GrowlException - * If an error occurs while setting the icon. - */ - public void setIcon(RenderedImage icon) throws GrowlException; - - /** - * Adds a notification type for this Growl. This must - * be called before calling {@link #register()}. If the another - * notification type is added after {@link #register()} has been called then - * another call to {@link #register()} must be made. - * - * @param name - * The name of the notification type. This is what appears in - * the Growl settings. - * @param enabledByDefault - * true if this notification type should be - * enabled by default. This can be overridden by the user in - * the Growl settings. - */ - public void addNotification(String name, boolean enabledByDefault); - - /** - * Adds a click callback listener. - * - * @param listener - * The callback listener to add. - */ - public void addCallbackListener(GrowlCallbackListener listener); - - /** - * Sends a notification to Growl for displaying. This must be called - * after calling {@link #register()}. - * - * @param name - * Name of the notification type that has been registered. - * @param title - * The title of the notification. - * @param body - * The body of the notification. - * @throws GrowlException - * If the notification could not be sent. - */ - public void sendNotification(String name, String title, String body) - throws GrowlException; - - /** - * Sends a notification to Growl for displaying. This must be called - * after calling {@link #register()}. - * - * @param name - * Name of the notification type that has been registered. - * @param title - * The title of the notification. - * @param body - * The body of the notification. - * @param icon - * The icon to display with the notification. - * @throws GrowlException - * If the notification could not be sent. - */ - public void sendNotification(String name, String title, String body, - RenderedImage icon) throws GrowlException; - - /** - * Sends a notification to Growl for displaying. This must be called - * after calling {@link #register()}. - * - * @param name - * Name of the notification type that has been registered. - * @param title - * The title of the notification. - * @param body - * The body of the notification. - * @param callbackContext - * A unique ID that will be sent to any registered - * {@link GrowlCallbackListener}s. If this is - * null then clicks will be ignored. - * @throws GrowlException - * If the notification could not be sent. - */ - public void sendNotification(String name, String title, String body, - String callbackContext) throws GrowlException; - - /** - * Sends a notification to Growl for displaying. This must be called - * after calling {@link #register()}. - * - * @param name - * Name of the notification type that has been registered. - * @param title - * The title of the notification. - * @param body - * The body of the notification. - * @param callbackContext - * A unique ID that will be sent to any registered - * {@link GrowlCallbackListener}s. If this is - * null then clicks will be ignored. - * @param icon - * The icon to display with the notification. - * @throws GrowlException - * If the notification could not be sent. - */ - public void sendNotification(String name, String title, String body, - String callbackContext, RenderedImage icon) throws GrowlException; -} diff --git a/src/plugins/growl/src/info/growl/GrowlCallbackListener.java b/src/plugins/growl/src/info/growl/GrowlCallbackListener.java deleted file mode 100644 index f294d9d99..000000000 --- a/src/plugins/growl/src/info/growl/GrowlCallbackListener.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2008, Michael Stringer - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Growl nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package info.growl; - -/** - * Callback interface for handling users clicking on notifications. - * - * @author Michael Stringer - * @version 0.1 - */ -public interface GrowlCallbackListener { - - /** - * Signals that the user has clicked on a notification with an identifier of - * clickContext. - * - * @param clickContext - * The ID of the notification clicked. - */ - public void notificationWasClicked(String clickContext); -} diff --git a/src/plugins/growl/src/info/growl/GrowlException.java b/src/plugins/growl/src/info/growl/GrowlException.java deleted file mode 100644 index d4759966c..000000000 --- a/src/plugins/growl/src/info/growl/GrowlException.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2008, Michael Stringer - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Growl nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package info.growl; - -/** - * An exception class for handling errors while sending messages to Growl. - * - * @author Michael Stringer - * @version 0.1 - */ -public class GrowlException extends Exception { - private static final long serialVersionUID = 2642457707267962686L; - - /** - * Creates a new GrowlException. - * - * @param message - * The error message. - */ - public GrowlException(String message) { - super(message); - } - - /** - * Creates a new GrowlException. - * - * @param message - * The error message. - * @param cause - * The underlying cause. - */ - public GrowlException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/plugins/growl/src/info/growl/GrowlNative.java b/src/plugins/growl/src/info/growl/GrowlNative.java deleted file mode 100644 index de9dcce54..000000000 --- a/src/plugins/growl/src/info/growl/GrowlNative.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2008, Michael Stringer - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Growl nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package info.growl; - -import java.awt.image.RenderedImage; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import javax.imageio.ImageIO; - -import org.jivesoftware.spark.util.log.Log; - -/** - * Growl notification implementation. This uses JNI to send messages to Growl. - * - * @author Michael Stringer - * @version 0.1 - */ -class GrowlNative implements Growl { - private String appName; - private List notifications; - private List callbackListeners; - private byte[] imageData; - - private native void sendNotification(String appName, String name, - String title, String message, String callbackContext, byte[] icon); - - private native void registerApp(String appName, byte[] image, - List notifications); - - /** - * Creates a new GrowlNative instance for the specified - * application name. - * - * @param appName - * The name of the application sending notifications. - */ - GrowlNative(String appName) { - notifications = new ArrayList<>(); - callbackListeners = new ArrayList<>(); - this.appName = appName; - } - - void fireCallbacks(String callbackContext) { - for (GrowlCallbackListener listener : callbackListeners) { - listener.notificationWasClicked(callbackContext); - } - } - - /** - * {@inheritDoc} - */ - public void register() throws GrowlException { - registerApp(appName, imageData, notifications); - } - - /** - * {@inheritDoc} - */ - public void addNotification(String name, boolean enabledByDefault) { - notifications.add(new NotificationType(name, enabledByDefault)); - } - - /** - * {@inheritDoc} - */ - public void addCallbackListener(GrowlCallbackListener listener) { - callbackListeners.add(listener); - } - - /** - * {@inheritDoc} - */ - public void setIcon(RenderedImage icon) throws GrowlException { - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ImageIO.write(icon, "png", baos); - - imageData = baos.toByteArray(); - } catch (IOException e) { - Log.error("Growl error",e); - } - } - - /** - * {@inheritDoc} - */ - public void sendNotification(String name, String title, String body) - throws GrowlException { - if (!notifications.contains(new NotificationType(name, false))) { - System.out.println("contains: " + notifications); - throw new GrowlException("Unregistered notification name [" + name - + "]"); - } - sendNotification(appName, name, title, body, null, null); - } - - /** - * {@inheritDoc} - */ - public void sendNotification(String name, String title, String body, - RenderedImage icon) throws GrowlException { - if (!notifications.contains(new NotificationType(name, false))) { - System.out.println("contains: " + notifications); - throw new GrowlException("Unregistered notification name [" + name - + "]"); - } - - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ImageIO.write(icon, "png", baos); - - byte[] image = baos.toByteArray(); - - sendNotification(appName, name, title, body, null, image); - } catch (IOException ioe) { - throw new GrowlException("Failed to convert Image", ioe); - } - } - - /** - * {@inheritDoc} - */ - public void sendNotification(String name, String title, String body, - String callbackContext) throws GrowlException { - if (!notifications.contains(new NotificationType(name, false))) { - System.out.println("contains: " + notifications); - throw new GrowlException("Unregistered notification name [" + name - + "]"); - } - - sendNotification(appName, name, title, body, callbackContext, null); - } - - /** - * {@inheritDoc} - */ - public void sendNotification(String name, String title, String body, - String callbackContext, RenderedImage icon) throws GrowlException { - if (!notifications.contains(new NotificationType(name, false))) { - System.out.println("contains: " + notifications); - throw new GrowlException("Unregistered notification name [" + name - + "]"); - } - - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ImageIO.write(icon, "png", baos); - - byte[] image = baos.toByteArray(); - - sendNotification(appName, name, title, body, callbackContext, image); - } catch (IOException ioe) { - throw new GrowlException("Failed to convert Image", ioe); - } - } - - private class NotificationType { - private String name; - private boolean enabledByDefault; - - public NotificationType(String name, boolean enabledByDefault) { - this.name = name; - this.enabledByDefault = enabledByDefault; - } - - public String getName() { - return name; - } - - public boolean isEnabledByDefault() { - return enabledByDefault; - } - - public boolean equals(Object other) { - if (!(other instanceof NotificationType)) { - return false; - } - - NotificationType otherType = (NotificationType) other; - - return name.equals(otherType.name); - } - } -} diff --git a/src/plugins/growl/src/info/growl/GrowlUtils.java b/src/plugins/growl/src/info/growl/GrowlUtils.java deleted file mode 100644 index fcb4ef751..000000000 --- a/src/plugins/growl/src/info/growl/GrowlUtils.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2008, Michael Stringer - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Growl nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package info.growl; - -import java.util.HashMap; -import java.util.Map; - -/** - * Utility class for sending notifications using Growl. - * - * @author Michael Stringer - * @version 0.1 - */ -public final class GrowlUtils { - private static final boolean GROWL_LOADED; - private static Map instances = new HashMap<>(); - - -// public GrowlUtils(String pathtoload) -// { -// try { -// System.load(pathtoload); -// }catch (UnsatisfiedLinkError ule) { -// System.out.println("Failed to load Growl library from "+pathtoload); -// } -// } -// -// public Growl getGrowl(String appName) -// { -// -// Growl stuff = new GrowlNative(appName); -// return stuff; -// } - - static { - boolean loaded = false; - try { - System.loadLibrary("growl"); - loaded = true; - } catch (UnsatisfiedLinkError ule) { - System.out.println("Failed to load Growl library"); - } - - GROWL_LOADED = loaded; - } - - /** - * Utility method - should not be instantiated. - */ - private GrowlUtils() { - - } - - /** - * Gets a Growl instance to use for the specified application - * name. Multiple calls to this method will return the same instance. - * - * @param appName - * The name of the application. - * @return The Growl instance to use. - */ - public static Growl getGrowlInstance(String appName) { - Growl instance = instances.get(appName); - - if (instance == null) { - if (GROWL_LOADED) { - instance = new GrowlNative(appName); - } else { - instance = new DummyGrowl(); - } - - instances.put(appName, instance); - } - - return instance; - } - - /** - * Gets whether messages can be sent to Growl. If this returns - * false then {@link #getGrowlInstance(String)} will return a - * dummy object. - * - * @return true if messages can be sent to Growl. - */ - public static boolean isGrowlLoaded() { - return GROWL_LOADED; - } -} diff --git a/src/plugins/growl/src/info/growl/test/TestGrowl.java b/src/plugins/growl/src/info/growl/test/TestGrowl.java deleted file mode 100644 index 909d438a6..000000000 --- a/src/plugins/growl/src/info/growl/test/TestGrowl.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2008, Michael Stringer - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Growl nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package info.growl.test; - -import info.growl.Growl; -import info.growl.GrowlCallbackListener; -import info.growl.GrowlException; -import info.growl.GrowlUtils; - -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.image.BufferedImage; -import java.io.IOException; - -import javax.imageio.ImageIO; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; - -/** - * Simple test class for Growl. - * - * @author Michael Stringer - * @version 0.1 - */ -public class TestGrowl extends JFrame { - private static final String APP_NAME = "Test Java App"; - private static final String NOTIF_3_CALLBACK = "Notif3"; - - public TestGrowl() { - super("Growl for Java"); - setSize(320, 290); - - buildComponents(); - setVisible(true); - setDefaultCloseOperation(EXIT_ON_CLOSE); - } - - private void buildComponents() { - getContentPane().setLayout(new GridLayout(6, 1)); - - Action action = new AbstractAction("Register") { - public void actionPerformed(ActionEvent ae) { - try { - Growl growl = GrowlUtils.getGrowlInstance(APP_NAME); - - growl.addNotification("Test Notification 1", true); - growl.addNotification("Test Notification 2", false); - growl.addNotification("Test Notification 3", true); - - GrowlCallbackListener listener = clickContext -> SwingUtilities.invokeLater( () -> { -if (NOTIF_3_CALLBACK.equals(clickContext)) { -JOptionPane -.showMessageDialog( -TestGrowl.this, -"User clicked on 'Test Notification 3'"); -} -} ); - - growl.addCallbackListener(listener); - growl.register(); - } catch (GrowlException ge) { - ge.printStackTrace(); - } - } - }; - - getContentPane().add(new JButton(action)); - - action = new AbstractAction("Send 'Test Notification 1'") { - public void actionPerformed(ActionEvent ae) { - try { - Growl growl = GrowlUtils.getGrowlInstance(APP_NAME); - - growl.sendNotification("Test Notification 1", - "Test Notif 1", "This is a test"); - } catch (GrowlException ge) { - ge.printStackTrace(); - } - } - }; - getContentPane().add(new JButton(action)); - - action = new AbstractAction("Send 'Test Notification 2'") { - public void actionPerformed(ActionEvent ae) { - try { - Growl growl = GrowlUtils.getGrowlInstance(APP_NAME); - BufferedImage image = ImageIO.read(TestGrowl.class - .getResource("/images/duke.gif")); - growl.sendNotification("Test Notification 2", - "Test Notif 2", "This is another test", image); - } catch (GrowlException ge) { - ge.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - }; - getContentPane().add(new JButton(action)); - - action = new AbstractAction("Test Callback 'Notification 3'") { - public void actionPerformed(ActionEvent ae) { - try { - Growl growl = GrowlUtils.getGrowlInstance(APP_NAME); - - growl.sendNotification("Test Notification 3", - "Callback Test", "Click me - I dares you!", NOTIF_3_CALLBACK); - } catch (GrowlException ge) { - ge.printStackTrace(); - } - } - }; - getContentPane().add(new JButton(action)); - - action = new AbstractAction("Reg & Test App 2") { - public void actionPerformed(ActionEvent ae) { - try { - Growl growl = GrowlUtils.getGrowlInstance("Other App"); - - growl.addNotification("A Notification", true); - - BufferedImage image = ImageIO.read(TestGrowl.class - .getResource("/images/duke.gif")); - growl.setIcon(image); - - growl.register(); - growl.sendNotification("A Notification", "Testin", - "Blah de blah blah"); - } catch (GrowlException ge) { - ge.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - }; - getContentPane().add(new JButton(action)); - - action = new AbstractAction("Exit") { - public void actionPerformed(ActionEvent ae) { - System.exit(0); - } - }; - getContentPane().add(new JButton(action)); - } - - public static final void main(String[] args) { - new TestGrowl(); - } -} diff --git a/src/plugins/growl/src/plugin.xml b/src/plugins/growl/src/plugin.xml deleted file mode 100644 index 900dccb16..000000000 --- a/src/plugins/growl/src/plugin.xml +++ /dev/null @@ -1,12 +0,0 @@ - - Growl Plugin - 2.0 - Wolf Posdorfer - http://www.jivesoftware.com - andrew@jivesoftware.com - Provides Growl notifications on Mac OS X.(http://growl.info) - com.jivesoftware.spark.plugin.growl.GrowlPlugin - 2.7.0 - Mac - 1.7.0 - \ No newline at end of file diff --git a/src/plugins/jingle/build/build.xml b/src/plugins/jingle/build/build.xml deleted file mode 100644 index 72680ced6..000000000 --- a/src/plugins/jingle/build/build.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/jingle/build/lib/dist/Speex.jar b/src/plugins/jingle/build/lib/dist/Speex.jar deleted file mode 100644 index e11d07caf..000000000 Binary files a/src/plugins/jingle/build/lib/dist/Speex.jar and /dev/null differ diff --git a/src/plugins/jingle/build/lib/dist/commons-logging-1.1.jar b/src/plugins/jingle/build/lib/dist/commons-logging-1.1.jar deleted file mode 100644 index 2ff9bbd90..000000000 Binary files a/src/plugins/jingle/build/lib/dist/commons-logging-1.1.jar and /dev/null differ diff --git a/src/plugins/jingle/build/lib/dist/commons-logging-adapters-1.1.jar b/src/plugins/jingle/build/lib/dist/commons-logging-adapters-1.1.jar deleted file mode 100644 index 6eec9a525..000000000 Binary files a/src/plugins/jingle/build/lib/dist/commons-logging-adapters-1.1.jar and /dev/null differ diff --git a/src/plugins/jingle/build/lib/dist/commons-logging-api-1.1.jar b/src/plugins/jingle/build/lib/dist/commons-logging-api-1.1.jar deleted file mode 100644 index d1abcbb47..000000000 Binary files a/src/plugins/jingle/build/lib/dist/commons-logging-api-1.1.jar and /dev/null differ diff --git a/src/plugins/jingle/build/lib/dist/concurrent.jar b/src/plugins/jingle/build/lib/dist/concurrent.jar deleted file mode 100644 index 26cb11ebf..000000000 Binary files a/src/plugins/jingle/build/lib/dist/concurrent.jar and /dev/null differ diff --git a/src/plugins/jingle/build/lib/dist/jspeex-0.9.7-jfcom.jar b/src/plugins/jingle/build/lib/dist/jspeex-0.9.7-jfcom.jar deleted file mode 100644 index f2631b1f4..000000000 Binary files a/src/plugins/jingle/build/lib/dist/jspeex-0.9.7-jfcom.jar and /dev/null differ diff --git a/src/plugins/jingle/build/lib/dist/log4j-1.2.8.jar b/src/plugins/jingle/build/lib/dist/log4j-1.2.8.jar deleted file mode 100644 index 493a3ccc1..000000000 Binary files a/src/plugins/jingle/build/lib/dist/log4j-1.2.8.jar and /dev/null differ diff --git a/src/plugins/jingle/build/lib/dist/smack-jingle-old-4.1.7.jar b/src/plugins/jingle/build/lib/dist/smack-jingle-old-4.1.7.jar deleted file mode 100644 index 5bdd21cf3..000000000 Binary files a/src/plugins/jingle/build/lib/dist/smack-jingle-old-4.1.7.jar and /dev/null differ diff --git a/src/plugins/jingle/build/projects/JinglePlugin.iml b/src/plugins/jingle/build/projects/JinglePlugin.iml deleted file mode 100644 index 07952d1e2..000000000 --- a/src/plugins/jingle/build/projects/JinglePlugin.iml +++ /dev/null @@ -1,252 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/jingle/plugin.xml b/src/plugins/jingle/plugin.xml deleted file mode 100644 index cc72a9794..000000000 --- a/src/plugins/jingle/plugin.xml +++ /dev/null @@ -1,12 +0,0 @@ - - Jingle Client - 1.0 - Jive Software - http://www.jivesoftware.org - derek@jivesoftware.com - Allows for PC to PC calling. - org.jivesoftware.sparkplugin.JinglePlugin - 2.7.0 - Windows,mac,linux - 1.7.0 - \ No newline at end of file diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/CallPanelButton.java b/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/CallPanelButton.java deleted file mode 100644 index 0c078ff74..000000000 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/CallPanelButton.java +++ /dev/null @@ -1,155 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin; - - -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Image; -import java.awt.Insets; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; - -import javax.swing.Icon; -import javax.swing.JButton; - -/** - * - */ -public class CallPanelButton extends JButton implements MouseListener { - - private static final long serialVersionUID = -2299269454442767625L; - private Icon normalIcon; - private Icon hoverIcon; - private Icon downIcon; - private Image backgroundImage; - private String text; - - private boolean selected; - - public CallPanelButton(Image image, String text) { - super(); - - this.text = text; - - normalIcon = JinglePhoneRes.getImageIcon("CALLPANEL_BIG_BUTTON"); - hoverIcon = JinglePhoneRes.getImageIcon("CALLPANEL_BIG_BUTTON_HOVER"); - downIcon = JinglePhoneRes.getImageIcon("CALLPANEL_BIG_BUTTON_DOWN"); - backgroundImage = image; - - setIcon(normalIcon); - - decorate(); - - addMouseListener(this); - - setDisabledIcon(normalIcon); - } - - /** - * Decorates the button with the approriate UI configurations. - */ - private void decorate() { - setBorderPainted(false); - setOpaque(true); - - setContentAreaFilled(false); - setMargin(new Insets(0, 0, 0, 0)); - } - - - public void mouseClicked(MouseEvent e) { - } - - public void mousePressed(MouseEvent e) { - setIcon(downIcon); - } - - public void mouseReleased(MouseEvent e) { - if (!selected) { - setIcon(normalIcon); - } - - } - - public void mouseEntered(MouseEvent e) { - if (!selected) { - setIcon(hoverIcon); - } - setCursor(new Cursor(Cursor.HAND_CURSOR)); - } - - public void mouseExited(MouseEvent e) { - if (!selected) { - setIcon(normalIcon); - } - setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - - public void setButtonSelected(boolean selected) { - this.selected = selected; - if (selected) { - setIcon(downIcon); - } - else { - setIcon(normalIcon); - } - } - - - public void paintComponent(Graphics g) { - super.paintComponent(g); - int width = getWidth(); - int height = getHeight(); - - int x = (width - backgroundImage.getWidth(null)) / 2; - int y = (height - backgroundImage.getHeight(null)) / 2; - g.drawImage(backgroundImage, x, y - 5, null); - - if (isEnabled()) { - g.setColor(Color.black); - } - else { - g.setColor(Color.lightGray); - } - g.setFont(new Font("Dialog", Font.PLAIN, 11)); - - - int stringWidth = g.getFontMetrics().stringWidth(text); - - x = (width - stringWidth) / 2; - y = height - 12; - g.drawString(text, x, y); - - } - - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - if (!enabled) { - removeMouseListener(this); - } - else { - addMouseListener(this); - } - } -} - diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/ControlPanel.java b/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/ControlPanel.java deleted file mode 100644 index 81373e134..000000000 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/ControlPanel.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin; - -import javax.swing.JPanel; -import javax.swing.BorderFactory; - -import java.awt.Color; -import java.awt.LayoutManager; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GradientPaint; -import java.awt.image.BufferedImage; - -public class ControlPanel extends JPanel { - - private static final long serialVersionUID = -6406576262620829080L; - - public ControlPanel() { - setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230))); - } - - public ControlPanel(LayoutManager layout) { - super(layout); - setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230))); - } - - public void paintComponent(Graphics g) { - final BufferedImage bufferedImage = new BufferedImage(2, getHeight(), BufferedImage.TYPE_INT_RGB); - Graphics2D g2d = bufferedImage.createGraphics(); - - GradientPaint paint = new GradientPaint(0, 0, Color.white, 0, getHeight(), new Color(235, 241, 246), true); - - g2d.setPaint(paint); - g2d.fillRect(0, 0, getWidth(), getHeight()); - g2d.dispose(); - - g.drawImage(bufferedImage, 0, 0, getWidth(), getHeight(), null); - } -} \ No newline at end of file diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/GenericNotification.java b/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/GenericNotification.java deleted file mode 100644 index 3bbf3b8b7..000000000 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/GenericNotification.java +++ /dev/null @@ -1,103 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin; - -import org.jivesoftware.spark.component.FileDragLabel; - -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import java.awt.Color; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; - -/** - * UI for simple chat room notifications with Jingle. - */ -public class GenericNotification extends JPanel { - - private static final long serialVersionUID = -90291335105747619L; - private FileDragLabel imageLabel = new FileDragLabel(); - private JLabel titleLabel = new JLabel(); - - /** - * Creates a generic notification panel. - * - * @param title the title of the notification. - * @param icon the icon to use in the notification. - */ - public GenericNotification(String title, Icon icon) { - setLayout(new GridBagLayout()); - - setBackground(new Color(250, 249, 242)); - add(imageLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - add(titleLabel, new GridBagConstraints(1, 0, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - titleLabel.setFont(new Font("Dialog", Font.BOLD, 11)); - titleLabel.setForeground(new Color(211, 174, 102)); - - setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.white)); - - titleLabel.setText(title); - imageLabel.setIcon(icon); - } - - /** - * Sets the title of the notification. - * - * @param title the title. - */ - public void setTitle(String title) { - titleLabel.setText(title); - } - - /** - * Sets the icon. - * - * @param icon the icon. - */ - public void setIcon(Icon icon) { - imageLabel.setIcon(icon); - } - - - /** - * Changes the background color. If alert is true, the background will reflect that the ui - * needs attention. - * - * @param alert true to notify users that their attention is needed. - */ - public void showAlert(boolean alert) { - if (alert) { - titleLabel.setForeground(new Color(211, 174, 102)); - setBackground(new Color(250, 249, 242)); - } - else { - setBackground(new Color(239, 245, 250)); - titleLabel.setForeground(new Color(65, 139, 179)); - } - } - - -} diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/IncomingCall.java b/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/IncomingCall.java deleted file mode 100644 index 65428c079..000000000 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/IncomingCall.java +++ /dev/null @@ -1,332 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.jingleold.JingleSession; -import org.jivesoftware.smackx.jingleold.JingleSessionRequest; -import org.jivesoftware.smackx.jingleold.listeners.JingleSessionListener; -import org.jivesoftware.smackx.jingleold.media.PayloadType; -import org.jivesoftware.smackx.jingleold.nat.TransportCandidate; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.phone.PhoneManager; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomClosingListener; -import org.jivesoftware.spark.util.SwingTimerTask; -import org.jivesoftware.spark.util.TaskEngine; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster; -import org.jxmpp.util.XmppStringUtils; - -import javax.swing.*; -import java.applet.Applet; -import java.applet.AudioClip; -import java.awt.*; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.TimerTask; - -/** - * Incoming call handles a single incoming Jingle call. - */ -public class IncomingCall implements JingleSessionListener, ChatRoomClosingListener { - - private SparkToaster toasterManager; - - private AudioClip ringing; - - private ChatRoom chatRoom; - - private Map callMap = new HashMap<>(); - - private GenericNotification notificationUI; - - private JingleSession session; - - private boolean established = false; - - private boolean mediaReceived = false; - - private TimerTask mediaReceivedTask; - - private static final long WAIT_FOR_MEDIA_DELAY = 20000; - - /** - * Initializes a new IncomingCall with the required JingleSession. - * - * @param request the JingleSessionRequest - */ - public IncomingCall(final JingleSessionRequest request) { - - try { - ringing = Applet.newAudioClip(JinglePhoneRes.getURL("RINGING")); - } - catch (Exception e) { - Log.error(e); - } - - notificationUI = new GenericNotification(JingleResources.getString("label.establishing.call"), SparkRes.getImageIcon(SparkRes.BUSY_IMAGE)); - - // Accept the request - try { - session = request.accept(); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - - session.addListener(this); - - showIncomingCall(request); - } - - - /** - * Appends the JingleRoom to the ChatRoom. - */ - private void showCallAnsweredState() { - SwingUtilities.invokeLater( () -> { - final SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy h:mm a"); - notificationUI.setTitle("Voice chat started on " + formatter.format(new Date())); - notificationUI.showAlert(false); - notificationUI.setIcon(null); - - if (ringing != null) { - ringing.stop(); - } - - final JingleRoom roomUI = new JingleRoom(session, chatRoom); - chatRoom.getChatPanel().add(roomUI, new GridBagConstraints(1, 1, 1, 1, 0.05, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - chatRoom.getChatPanel().invalidate(); - chatRoom.getChatPanel().validate(); - chatRoom.getChatPanel().repaint(); - callMap.put(chatRoom, roomUI); - - // Add state - JingleStateManager.getInstance().addJingleSession(chatRoom, JingleStateManager.JingleRoomState.inJingleCall); - - // Notify state change - SparkManager.getChatManager().notifySparkTabHandlers(chatRoom); - } ); - } - - /** - * Removes the JingleRoom from the ChatRoom. - */ - private void showCallEndedState(final String reason) { - SwingUtilities.invokeLater( () -> { - if (ringing != null) { - ringing.stop(); - } - - notificationUI.setTitle(reason); - notificationUI.setIcon(null); - notificationUI.showAlert(false); - - - if (chatRoom != null) { - JingleRoom room = callMap.get(chatRoom); - if (room != null) { - chatRoom.getChatPanel().remove(room); - } - - callMap.remove(chatRoom); - chatRoom.getChatPanel().invalidate(); - chatRoom.getChatPanel().validate(); - chatRoom.getChatPanel().repaint(); - } - - // Add state - JingleStateManager.getInstance().removeJingleSession(chatRoom); - - // Notify state change - SparkManager.getChatManager().notifySparkTabHandlers(chatRoom); - } ); - } - - /** - * Called if an incoming Jingle Session is rejected. - */ - public void rejectIncomingCall() { - // Close toaster if it's up. - if (toasterManager != null) { - toasterManager.close(); - } - - if (session != null) { - try { - session.terminate(); - session = null; - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - } - - if (ringing != null) { - ringing.stop(); - } - } - - /** - * Returns the JingleSession associated with this incoming call. - * - * @return the session. - */ - public JingleSession getSession() { - return session; - } - - private void notifyRoom() { - notificationUI.showAlert(true); - chatRoom.getTranscriptWindow().addComponent(notificationUI); - } - - /** - * Notifies user of an incoming call. The UI allows for users to either accept or reject - * the incoming session. - * - * @param request the JingleSession. - */ - private void showIncomingCall(final JingleSessionRequest request) { - toasterManager = new SparkToaster(); - toasterManager.setHidable(false); - - final IncomingCallUI incomingCall = new IncomingCallUI(request.getFrom()); - toasterManager.setToasterHeight(175); - toasterManager.setToasterWidth(300); - toasterManager.setDisplayTime(500000000); - - toasterManager.showToaster("Incoming Voice Chat", incomingCall); - toasterManager.hideTitle(); - - incomingCall.getAcceptButton().addActionListener( e -> acceptSession(request) ); - - incomingCall.getRejectButton().addActionListener( e -> rejectIncomingCall() ); - - // Start the ringing. - final Runnable ringer = () -> ringing.loop(); - - TaskEngine.getInstance().submit(ringer); - - // End after 30 seconds max. - TimerTask endTask = new SwingTimerTask() { - public void doRun() { - if (!session.isFullyEstablished()) { - rejectIncomingCall(); - } - } - }; - - TaskEngine.getInstance().schedule(endTask, 30000); - } - - /** - * Accepts a JingleSessionRequest. - * - * @param request the request. - */ - private void acceptSession(JingleSessionRequest request) { - toasterManager.close(); - - if (ringing != null) { - ringing.stop(); - } - - // Start the call - session.startIncoming(); - - if (chatRoom == null) { - chatRoom = SparkManager.getChatManager().getChatRoom( XmppStringUtils.parseBareJid(request.getFrom()) ); - SparkManager.getChatManager().getChatContainer().activateChatRoom(chatRoom); - SparkManager.getChatManager().getChatContainer().getChatFrame().toFront(); - notifyRoom(); - } - } - - public void sessionMediaReceived(JingleSession jingleSession, String participant) { - mediaReceived = true; - TaskEngine.getInstance().cancelScheduledTask(mediaReceivedTask); - showCallAnsweredState(); - } - - public void sessionEstablished(PayloadType payloadType, TransportCandidate transportCandidate, TransportCandidate transportCandidate1, JingleSession jingleSession) { - - established = true; - mediaReceivedTask = new SwingTimerTask() { - public void doRun() { - if (!mediaReceived) { - if (session != null) { - try { - session.terminate("No Media Received. This may be caused by firewall configuration problems."); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - } - } - } - }; - TaskEngine.getInstance().schedule(mediaReceivedTask, WAIT_FOR_MEDIA_DELAY, WAIT_FOR_MEDIA_DELAY); - } - - public void sessionDeclined(String string, JingleSession jingleSession) { - showCallEndedState("Voice chat was rejected"); - } - - public void sessionRedirected(String string, JingleSession jingleSession) { - } - - public void sessionClosed(String string, JingleSession jingleSession) { - if (established && mediaReceived) { - final SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy h:mm a"); - showCallEndedState("Voice chat ended on " + formatter.format(new Date())); - } else { - showCallEndedState("Voice chat ended: " + string); - } - if(PhoneManager.isUseStaticLocator()&&PhoneManager.isUsingMediaLocator()){ - PhoneManager.setUsingMediaLocator(false); - } - } - - public void sessionClosedOnError(XMPPException xmppException, JingleSession jingleSession) { - showCallEndedState("Voice chat ended due an error: " + xmppException.getMessage()); - if(PhoneManager.isUseStaticLocator()&&PhoneManager.isUsingMediaLocator()){ - PhoneManager.setUsingMediaLocator(false); - } - } - - public void closing() { - if (session != null) { - try { - session.terminate(); - } - catch (XMPPException | SmackException e) { - Log.error(e); - } - } - - JingleStateManager.getInstance().removeJingleSession(chatRoom); - } -} diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/IncomingCallUI.java b/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/IncomingCallUI.java deleted file mode 100644 index f16efb37a..000000000 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/IncomingCallUI.java +++ /dev/null @@ -1,246 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin; - -import java.awt.Color; -import java.awt.Font; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.image.BufferedImage; - -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smackx.vcardtemp.packet.VCard; -import org.jivesoftware.spark.PresenceManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; - -public class IncomingCallUI extends JPanel { - private static final long serialVersionUID = -7758898282948774412L; - private JLabel avatarLabel = new JLabel(); - private JLabel titleLabel = new JLabel(); - private JLabel professionLabel = new JLabel(); - - private RolloverButton acceptButton; - private RolloverButton rejectButton; - - private VCard vcard; - private String jid; - - - public IncomingCallUI(String jid) { - setLayout(new GridBagLayout()); - - this.jid = XmppStringUtils.parseBareJid(jid); - - vcard = SparkManager.getVCardManager().getVCardFromMemory(XmppStringUtils.parseBareJid(jid)); - - final JLabel topLabel = new JLabel(); - topLabel.setIcon(JinglePhoneRes.getImageIcon("INCOMING_CALL_IMAGE")); - topLabel.setHorizontalTextPosition(JLabel.RIGHT); - topLabel.setFont(new Font("Dialog", Font.BOLD, 15)); - topLabel.setText(JingleResources.getString("label.voice.request.from")); - topLabel.setForeground(Color.DARK_GRAY); - - // Add Top Label - add(topLabel, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - // Add Calller Block - buildCallerBlock(); - - // Add Buttons - addButtons(); - - - } - - - /** - * Builds the part of the incoming call UI with the Callers information. - */ - private void buildCallerBlock() { - final JPanel panel = new JPanel(new GridBagLayout()); - panel.setBackground(Color.white); - panel.setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230), 1)); - - // Add Avatar - panel.add(avatarLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 0, 5, 0), 0, 0)); - - // Add Avatar information - panel.add(titleLabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 0), 0, 0)); - panel.add(professionLabel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 0, 0), 0, 0)); - - // Add History labels - // panel.add(lastCalledLabel, new GridBagConstraints(0, 3, 2, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(15, 5, 0, 0), 0, 0)); - // panel.add(durationLabel, new GridBagConstraints(0, 4, 2, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 0), 0, 0)); - - // Set default settings - titleLabel.setForeground(new Color(64, 103, 162)); - titleLabel.setFont(new Font("Dialog", Font.BOLD, 16)); - - - if (vcard != null) { - handleVCardInformation(vcard); - } - else { - updateWithGenericInfo(); - } - - // Add to panel - add(panel, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - } - - private void addButtons() { - // Build Accept Button - acceptButton = new RolloverButton(" " + JingleResources.getString("button.accept"), JinglePhoneRes.getImageIcon("TOASTER_ACCEPT_BUTTON")); - acceptButton.setHorizontalTextPosition(JLabel.CENTER); - acceptButton.setFont(new Font("Dialog", Font.BOLD, 11)); - acceptButton.setForeground(new Color(91, 175, 41)); - acceptButton.setMargin(new Insets(0, 0, 0, 0)); - - // Build Reject Button - rejectButton = new RolloverButton(" " + JingleResources.getString("button.accept"), JinglePhoneRes.getImageIcon("TOASTER_REJECT_BUTTON")); - rejectButton.setHorizontalTextPosition(JLabel.CENTER); - rejectButton.setFont(new Font("Dialog", Font.BOLD, 11)); - rejectButton.setForeground(new Color(153, 32, 10)); - rejectButton.setMargin(new Insets(0, 0, 0, 0)); - - final JPanel panel = new JPanel(new GridBagLayout()); - panel.setOpaque(false); - panel.add(acceptButton, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - panel.add(rejectButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - add(panel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - } - - private void updateWithGenericInfo() { - String title = SparkManager.getUserManager().getUserNicknameFromJID(jid); - Icon icon = PresenceManager.getIconFromPresence(PresenceManager.getPresence(jid)); - - titleLabel.setText(title); - titleLabel.setIcon(icon); - - avatarLabel.setIcon(SparkRes.getImageIcon(SparkRes.DEFAULT_AVATAR_64x64_IMAGE)); - avatarLabel.invalidate(); - avatarLabel.validate(); - avatarLabel.repaint(); - - - invalidate(); - validate(); - repaint(); - } - - private void handleVCardInformation(VCard vcard) { - if (vcard.getError() != null) { - updateWithGenericInfo(); - return; - } - - // Nickname label should show presence and nickname. - String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid); - - String firstName = vcard.getFirstName(); - String lastName = vcard.getLastName(); - if (ModelUtil.hasLength(firstName) && ModelUtil.hasLength(lastName)) { - titleLabel.setText(firstName + " " + lastName); - } - else if (ModelUtil.hasLength(firstName)) { - titleLabel.setText(firstName); - } - else { - titleLabel.setText(nickname); - } - - - Icon icon = PresenceManager.getIconFromPresence(PresenceManager.getPresence(jid)); - - - titleLabel.setIcon(icon); - - - String jobTitle = vcard.getField("TITLE"); - if (jobTitle != null) { - professionLabel.setText(jobTitle); - } - - - byte[] avatarBytes = null; - try { - avatarBytes = vcard.getAvatar(); - } - catch (Exception e) { - Log.error("Cannot retrieve avatar bytes.", e); - } - - if (avatarBytes != null) { - try { - ImageIcon avatarIcon = new ImageIcon(avatarBytes); - avatarLabel.setIcon(avatarIcon); - avatarLabel.invalidate(); - avatarLabel.validate(); - avatarLabel.repaint(); - } - catch (Exception e) { - // no issue - } - } - - - invalidate(); - validate(); - repaint(); - } - - public RolloverButton getAcceptButton() { - return acceptButton; - } - - public RolloverButton getRejectButton() { - return rejectButton; - } - - - public void paintComponent(Graphics g) { - BufferedImage cache = new BufferedImage(2, getHeight(), BufferedImage.TYPE_INT_RGB); - Graphics2D g2d = cache.createGraphics(); - - GradientPaint paint = new GradientPaint(0, 0, new Color(233, 240, 247), 0, getHeight(), Color.white, true); - - g2d.setPaint(paint); - g2d.fillRect(0, 0, getWidth(), getHeight()); - g2d.dispose(); - - g.drawImage(cache, 0, 0, getWidth(), getHeight(), null); - } -} - diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JavaMixer.java b/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JavaMixer.java deleted file mode 100644 index cc5ffdd3c..000000000 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JavaMixer.java +++ /dev/null @@ -1,460 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin; - -import javax.sound.sampled.*; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.TreePath; -import javax.swing.tree.TreeNode; -import javax.swing.*; -import javax.swing.border.TitledBorder; -import javax.swing.border.EtchedBorder; -import java.util.List; -import java.util.ArrayList; -import java.util.Enumeration; -import java.awt.*; - -/** - * Pure Java Audio Mixer. Control Volume and Settings for any Sound device in the OS. - * - * @author Thiago Camargo - */ - -public class JavaMixer { - - private static final Line.Info[] EMPTY_PORT_INFO_ARRAY = new Line.Info[0]; - DefaultMutableTreeNode root = new DefaultMutableTreeNode("Sound Mixers", true); - JTree tree = new JTree(root); - - public JavaMixer() { - List portMixers = getPortMixers(); - if (portMixers.size() == 0) System.err.println("No Mixers Found."); - for (Mixer mixer : portMixers) { - JavaMixer.MixerNode mixerNode = new JavaMixer.MixerNode(mixer); - createMixerChildren(mixerNode); - root.add(mixerNode); - } - } - - public JTree getTree() { - return tree; - } - - public Component getPrefferedMasterVolume() { - TreePath path = findByName(new TreePath(root), new String[]{"SPEAKER", "Volume"}); - - if (path == null) { - path = findByName(new TreePath(root), new String[]{"Master target", "Master", "Mute"}); - } - - if (path != null) { - if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) - return ((JavaMixer.ControlNode) path.getLastPathComponent()).getComponent(); - } - return null; - } - - public Component getPrefferedInputVolume() { - TreePath path = findByName(new TreePath(root), new String[]{"MICROPHONE", "Volume"}); - - if (path == null) { - path = findByName(new TreePath(root), new String[]{"Capture source", "Capture", "Volume"}); - } - - if (path != null) { - if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) - return ((JavaMixer.ControlNode) path.getLastPathComponent()).getComponent(); - } - return null; - } - - public void setMicrophoneInput() { - TreePath path = findByName(new TreePath(root), new String[]{"MICROPHONE", "Select"}); - - if (path == null) { - path = findByName(new TreePath(root), new String[]{"Capture source", "Capture", "Mute"}); - } - - if (path != null) { - if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) { - BooleanControl bControl = (BooleanControl) (((JavaMixer.ControlNode) path.getLastPathComponent()).getControl()); - bControl.setValue(true); - } - } - } - - public void setMuteForMicrophoneOutput() { - TreePath path = findByName(new TreePath(root), new String[]{"SPEAKER", "Microfone", "Mute"}); - - if (path == null) { - path = findByName(new TreePath(root), new String[]{"MIC target", "mic", "Mute"}); - } - - if (path != null) { - if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) { - BooleanControl bControl = (BooleanControl) (((JavaMixer.ControlNode) path.getLastPathComponent()).getControl()); - bControl.setValue(true); - } - } - } - - /** - * Returns the Mixers that support Port lines. - * - * @return List Port Mixers - */ - private List getPortMixers() { - List supportingMixers = new ArrayList<>(); - Mixer.Info[] aMixerInfos = AudioSystem.getMixerInfo(); - for (Mixer.Info aMixerInfo : aMixerInfos) { - Mixer mixer = AudioSystem.getMixer(aMixerInfo); - boolean bSupportsPorts = arePortsSupported(mixer); - if (bSupportsPorts) { - supportingMixers.add(mixer); - } - } - return supportingMixers; - } - - private boolean arePortsSupported(Mixer mixer) { - Line.Info[] infos; - infos = mixer.getSourceLineInfo(); - for (Line.Info info : infos) { - if (info instanceof Port.Info) { - return true; - } else if (info instanceof DataLine.Info) { - return true; - } - } - infos = mixer.getTargetLineInfo(); - for (Line.Info info : infos) { - if (info instanceof Port.Info) { - return true; - } else if (info instanceof DataLine.Info) { - return true; - } - } - return false; - } - - private void createMixerChildren(JavaMixer.MixerNode mixerNode) { - Mixer mixer = mixerNode.getMixer(); - Line.Info[] infosToCheck = getPortInfo(mixer); - for (Line.Info anInfosToCheck : infosToCheck) { - if (mixer.isLineSupported(anInfosToCheck)) { - Port port = null; - DataLine dLine = null; - - int maxLines = mixer.getMaxLines(anInfosToCheck); - // Workaround to prevent a JVM crash on Mac OS X (Intel) 1.5.0_07 JVM - if (maxLines > 0) { - try { - if (anInfosToCheck instanceof Port.Info) { - port = (Port) mixer.getLine(anInfosToCheck); - port.open(); - } - else if (anInfosToCheck instanceof DataLine.Info) { - dLine = (DataLine) mixer.getLine(anInfosToCheck); - if (!dLine.isOpen()) { - dLine.open(); - } - } - } - catch (LineUnavailableException e) { - e.printStackTrace(); - } - catch (Exception e) { - // Do Nothing - } - } - if (port != null) { - JavaMixer.PortNode portNode = new JavaMixer.PortNode(port); - createPortChildren(portNode); - mixerNode.add(portNode); - } else if (dLine != null) { - JavaMixer.PortNode portNode = new JavaMixer.PortNode(dLine); - createPortChildren(portNode); - mixerNode.add(portNode); - } - } - } - } - - private Line.Info[] getPortInfo(Mixer mixer) { - Line.Info[] infos; - List portInfoList = new ArrayList<>(); - infos = mixer.getSourceLineInfo(); - for (Line.Info info : infos) { - if (info instanceof Port.Info || info instanceof DataLine.Info) { - portInfoList.add( info ); - } - } - infos = mixer.getTargetLineInfo(); - for (Line.Info info1 : infos) { - if (info1 instanceof Port.Info || info1 instanceof DataLine.Info) { - portInfoList.add( info1 ); - } - } - return portInfoList.toArray(EMPTY_PORT_INFO_ARRAY); - } - - private void createPortChildren(JavaMixer.PortNode portNode) { - Control[] aControls = portNode.getPort().getControls(); - for (Control aControl : aControls) { - JavaMixer.ControlNode controlNode = new JavaMixer.ControlNode(aControl); - createControlChildren(controlNode); - portNode.add(controlNode); - } - } - - private void createControlChildren(JavaMixer.ControlNode controlNode) { - if (controlNode.getControl() instanceof CompoundControl) { - CompoundControl control = (CompoundControl) controlNode.getControl(); - Control[] aControls = control.getMemberControls(); - for (Control con : aControls) { - JavaMixer.ControlNode conNode = new JavaMixer.ControlNode(con); - createControlChildren(conNode); - controlNode.add(conNode); - } - } - } - - /** - * Returns whether the type of a FloatControl is BALANCE or PAN. - * - * @param control FloatControl control - * @return boolean is Balance or Pan - */ - private static boolean isBalanceOrPan(FloatControl control) { - Control.Type type = control.getType(); - return type.equals(FloatControl.Type.PAN) || type.equals(FloatControl.Type.BALANCE); - } - - public class MixerNode extends DefaultMutableTreeNode { - - private static final long serialVersionUID = -987278469391244202L; - private Mixer mixer; - - public MixerNode(Mixer mixer) { - super(mixer.getMixerInfo(), true); - this.mixer = mixer; - } - - public Mixer getMixer() { - return mixer; - } - - } - - public class PortNode extends DefaultMutableTreeNode { - - private static final long serialVersionUID = -7774055649714159518L; - private Line port; - - public PortNode(Line port) { - super(port.getLineInfo(), true); - this.port = port; - } - - public Line getPort() { - return port; - } - - } - - public class ControlNode extends DefaultMutableTreeNode { - - private static final long serialVersionUID = 2014062750235264630L; - private Control control; - private Component component; - - public ControlNode(Control control) { - super(control.getType(), true); - this.control = control; - if (control instanceof BooleanControl) { - component = createControlComponent((BooleanControl) control); - } else if (control instanceof EnumControl) { - component = createControlComponent((EnumControl) control); - } else if (control instanceof FloatControl) { - component = createControlComponent((FloatControl) control); - } else { - component = null; - } - } - - public Control getControl() { - return control; - } - - public Component getComponent() { - return component; - } - - private JComponent createControlComponent(BooleanControl control) { - AbstractButton button; - String strControlName = control.getType().toString(); - ButtonModel model = new JavaMixer.BooleanControlButtonModel(control); - button = new JCheckBox(strControlName); - button.setModel(model); - return button; - } - - private JComponent createControlComponent(EnumControl control) { - JPanel component = new JPanel(); - String strControlName = control.getType().toString(); - component.setBorder(new TitledBorder(new EtchedBorder(), strControlName)); - return component; - } - - private JComponent createControlComponent(FloatControl control) { - int orientation = isBalanceOrPan(control) ? JSlider.HORIZONTAL : JSlider.VERTICAL; - BoundedRangeModel model = new JavaMixer.FloatControlBoundedRangeModel(control); - JSlider slider = new JSlider(model); - slider.setOrientation(orientation); - slider.setPaintLabels(true); - slider.setPaintTicks(true); - slider.setSize(10, 50); - return slider; - } - - } - - public class BooleanControlButtonModel extends DefaultButtonModel { - private static final long serialVersionUID = -4667054823378068382L; - private BooleanControl control; - - public BooleanControlButtonModel(BooleanControl control) { - this.control = control; - this.addActionListener( e -> setSelected(!isSelected()) ); - } - - public void setSelected(boolean bSelected) { - control.setValue(bSelected); - } - - public boolean isSelected() { - return control.getValue(); - } - } - - public class FloatControlBoundedRangeModel extends DefaultBoundedRangeModel { - private static final long serialVersionUID = 4469386606588434901L; - private FloatControl control; - private float factor; - - public FloatControlBoundedRangeModel(FloatControl control) { - this.control = control; - float range = 100; - float steps = range / 100; - factor = range / steps; - int min = (int) (control.getMinimum() * factor); - int max = (int) (control.getMaximum() * factor); - int value = (int) (control.getValue() * factor); - setRangeProperties(value, 0, min, max, false); - } - - private float getScaleFactor() { - return factor; - } - - public void setValue(int nValue) { - super.setValue(nValue); - control.setValue((float) nValue / getScaleFactor()); - } - - public int getValue() { - return (int) (control.getValue() * getScaleFactor()); - } - - } - - public static void main(String[] args) { - final JavaMixer sm = new JavaMixer(); - final JFrame jf = new JFrame("Mixer Test"); - final JPanel jp = new JPanel(); - jf.add(jp); - jp.add(sm.getTree()); - jf.setSize(600, 500); - jf.setVisible(true); - jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - sm.getTree().addTreeSelectionListener( e -> { - TreePath path = e.getPath(); - if (path.getLastPathComponent() instanceof ControlNode) { - ControlNode controlNode = (ControlNode) path.getLastPathComponent(); - if (!(controlNode.getControl() instanceof CompoundControl)) { - if (jp.getComponentCount() > 1) - jp.remove(1); - jp.add(controlNode.getComponent(), 1); - jp.repaint(); - } - } - } ); - jp.add(sm.getPrefferedMasterVolume()); - jp.add(sm.getPrefferedMasterVolume()); - jp.add(sm.getPrefferedInputVolume()); - jp.repaint(); - sm.setMicrophoneInput(); - sm.setMuteForMicrophoneOutput(); - } - - public TreePath find(TreePath path, Object[] nodes) { - return find2(path, nodes, 0, false); - } - - public TreePath findByName(TreePath path, String[] names) { - return find2(path, names, 0, true); - } - - private TreePath find2(TreePath parent, Object[] nodes, int depth, boolean byName) { - TreeNode node = (TreeNode) parent.getLastPathComponent(); - if (depth > nodes.length - 1) { - return parent; - } - - if (node.getChildCount() >= 0) { - for (Enumeration e = node.children(); e.hasMoreElements();) { - TreeNode n = e.nextElement(); - TreePath path = parent.pathByAddingChild(n); - boolean find; - - if (byName) { - find = n.toString().toUpperCase().contains( nodes[ depth ].toString().toUpperCase() ); - } else { - find = n.equals(nodes[depth]); - } - - if (find) { - TreePath result = find2(path, nodes, depth + 1, byName); - if (result != null) { - return result; - } - } else { - TreePath result = find2(path, nodes, depth, byName); - if (result != null) { - return result; - } - } - } - } - - return null; - } -} diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JinglePhoneRes.java b/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JinglePhoneRes.java deleted file mode 100644 index 299c50fee..000000000 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JinglePhoneRes.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin; - -import javax.swing.*; -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; -import java.net.URL; - -/** - * Use for Phone Res Internationalization. - * - * @author Derek DeMoro - */ -public class JinglePhoneRes { - private static PropertyResourceBundle prb; - - private JinglePhoneRes() { - - } - - static ClassLoader cl = JinglePhoneRes.class.getClassLoader(); - - static { - JinglePhoneRes.prb = (PropertyResourceBundle) ResourceBundle.getBundle("org/jivesoftware/sparkplugin/jingle"); - } - - public static final String getString(String propertyName) { - return JinglePhoneRes.prb.getString(propertyName); - } - - public static final ImageIcon getImageIcon(String imageName) { - try { - final String iconURI = JinglePhoneRes.getString(imageName); - final URL imageURL = JinglePhoneRes.cl.getResource(iconURI); - return new ImageIcon(imageURL); - } - catch (Exception ex) { - System.out.println(imageName + " not found."); - } - return null; - } - - public static final URL getURL(String propertyName) { - return JinglePhoneRes.cl.getResource(JinglePhoneRes.getString(propertyName)); - } - - -} diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JinglePlugin.java b/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JinglePlugin.java deleted file mode 100644 index 3f165c343..000000000 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JinglePlugin.java +++ /dev/null @@ -1,383 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.*; -import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; -import org.jivesoftware.smackx.disco.packet.DiscoverInfo; -import org.jivesoftware.smackx.jingleold.JingleManager; -import org.jivesoftware.smackx.jingleold.JingleSession; -import org.jivesoftware.smackx.jingleold.JingleSessionRequest; -import org.jivesoftware.smackx.jingleold.media.JingleMediaManager; -import org.jivesoftware.smackx.jingleold.mediaimpl.jmf.JmfMediaManager; -import org.jivesoftware.smackx.jingleold.mediaimpl.jspeex.SpeexMediaManager; -import org.jivesoftware.smackx.jingleold.nat.BridgedTransportManager; -import org.jivesoftware.smackx.jingleold.nat.ICETransportManager; -import org.jivesoftware.smackx.jingleold.nat.JingleTransportManager; -import org.jivesoftware.smackx.jingleold.nat.STUN; -import org.jivesoftware.spark.PresenceManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.phone.Phone; -import org.jivesoftware.spark.phone.PhoneManager; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.TranscriptWindow; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.gateways.transports.TransportUtils; -import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; -import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import org.jxmpp.util.XmppStringUtils; - -import javax.swing.*; -import javax.swing.text.BadLocationException; -import javax.swing.text.Style; -import javax.swing.text.StyleConstants; -import javax.swing.text.StyledDocument; -import java.awt.event.ActionEvent; -import java.util.*; - - -/** - * A simple Jingle Plugin for Spark that uses server Media Proxy for the transport and NAT Traversal - */ -public class JinglePlugin implements Plugin, Phone, ConnectionListener { - - private JingleManager jingleManager; - - private static final String JINGLE_NAMESPACE = "http://www.xmpp.org/extensions/xep-0166.html#ns"; - private String stunServer = ""; - private int stunPort = 0; - private boolean readyToConnect = false; - private Map jingleFeature = new HashMap<>(); - private boolean fallbackStunEnabled = false; - - public void initialize() { - // Add Jingle to discovered items list. - SparkManager.addFeature(JINGLE_NAMESPACE); - - final LocalPreferences localPref = SettingsManager.getLocalPreferences(); - - //If there is a server entered in spark.properties use it as fallback - if (!localPref.getStunFallbackHost().equals("")) { - fallbackStunEnabled = true; - } - - // Get the default port - stunPort = localPref.getStunFallbackPort(); - - // Set Jingle Enabled - JingleManager.setJingleServiceEnabled(); - JingleManager.setServiceEnabled(SparkManager.getConnection(), true); - - // Add to PhoneManager - PhoneManager.getInstance().addPhone(this); - - // Adds a tab handler. - SparkManager.getChatManager() - .addSparkTabHandler(new JingleTabHandler()); - - final SwingWorker jingleLoadingThread = new SwingWorker() - { - public Object construct() - { - if ( fallbackStunEnabled ) - { - stunServer = localPref.getStunFallbackHost(); - readyToConnect = true; - } - - try - { - - if ( STUN.serviceAvailable( SparkManager.getConnection() ) ) - { - STUN stun = STUN - .getSTUNServer( SparkManager.getConnection() ); - if ( stun != null ) - { - List servers = stun - .getServers(); - if ( servers.size() > 0 ) - { - stunServer = servers.get( 0 ).getServer(); - stunPort = Integer.parseInt( servers.get( 0 ) - .getPort() ); - readyToConnect = true; - } - } - } - - - if ( readyToConnect ) - { - JingleTransportManager transportManager = new ICETransportManager( SparkManager.getConnection(), stunServer, stunPort ); - List mediaManagers = new ArrayList<>(); - - // Get the Locator from the Settings - String locator = SettingsManager.getLocalPreferences().getAudioDevice(); - - mediaManagers.add( new JmfMediaManager( locator, transportManager ) ); - mediaManagers.add( new SpeexMediaManager( transportManager ) ); - //mediaManagers.add(new ScreenShareMediaManager(transportManager)); - - jingleManager = new JingleManager( SparkManager.getConnection(), mediaManagers ); - - if ( transportManager instanceof BridgedTransportManager ) - { - jingleManager.addCreationListener( (BridgedTransportManager) transportManager ); - } - else if ( transportManager instanceof ICETransportManager ) - { - jingleManager.addCreationListener( (ICETransportManager) transportManager ); - } - } - } - catch ( XMPPException | SmackException e ) - { - Log.error( "Unable to initialize", e ); - } - return true; - } - - public void finished() - { - addListeners(); - } - }; - - jingleLoadingThread.start(); - - // Add Presence listener for better service discovery. - addPresenceListener(); - - SparkManager.getConnection().addConnectionListener( this ); - } - - - /** - * Adds Jingle and ChatRoom listeners. - */ - private void addListeners() { - - if (jingleManager == null) { - if (readyToConnect) - { - Log.error("Unable to resolve Jingle Connection (Host: "+stunServer+" Port: "+stunPort+")"); - } - return; - - } - - - // Listen in for new incoming Jingle requests. - jingleManager.addJingleSessionRequestListener( request -> SwingUtilities.invokeLater( () -> incomingJingleSession(request) ) ); - } - - - public Collection getPhoneActions(final String jid) { - // Do not even disco gateway clients. - if (TransportUtils.isFromGateway(jid) || jingleManager == null) { - return Collections.emptyList(); - } - - Boolean supportsJingle = jingleFeature.get(XmppStringUtils.parseBareJid(jid)); - if (supportsJingle == null) { - // Disco for event. - // Obtain the ServiceDiscoveryManager associated with my XMPPConnection - ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(SparkManager.getConnection()); - - String fullJID = PresenceManager.getFullyQualifiedJID(jid); - - // Get the items of a given XMPP entity - DiscoverInfo discoverInfo = null; - try { - discoverInfo = discoManager.discoverInfo(fullJID); - } - catch (XMPPException | SmackException e) { - Log.debug("Unable to disco " + fullJID); - } - - if (discoverInfo != null) { - // Get the discovered items of the queried XMPP entity - supportsJingle = discoverInfo.containsFeature(JINGLE_NAMESPACE); - jingleFeature.put(jid, supportsJingle); - } - else { - jingleFeature.put(jid, false); - supportsJingle = false; - } - } - - if (!supportsJingle) { - return Collections.emptyList(); - } - - final List actions = new ArrayList<>(); - Action action = new AbstractAction() { - private static final long serialVersionUID = 1467355627829748086L; - - public void actionPerformed(ActionEvent e) { - try - { - placeCall(jid); - } - catch ( SmackException e1 ) - { - Log.warning( "Unable to place call to " + jid, e1 ); - } - } - }; - - action.putValue(Action.NAME, "" + JingleResources.getString("label.computer.to.computer") + ""); - action.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.COMPUTER_IMAGE_16x16)); - actions.add(action); - return actions; - } - - - public void placeCall(String jid) throws SmackException - { - - // cancel call request if no Media Locator available - if (PhoneManager.isUseStaticLocator() && PhoneManager.isUsingMediaLocator()) { - return; - } - - PhoneManager.setUsingMediaLocator(true); - - jid = SparkManager.getUserManager().getFullJID(jid); - - ChatRoom room = SparkManager.getChatManager().getChatRoom( XmppStringUtils.parseBareJid(jid)); - if (JingleStateManager.getInstance().getJingleRoomState(room) != null) { - return; - } - - SparkManager.getChatManager().getChatContainer().activateChatRoom(room); - - // Create a new Jingle Call with a full JID - JingleSession session = null; - try { - session = jingleManager.createOutgoingJingleSession(jid); - } - catch (XMPPException e) { - Log.error(e); - } - - TranscriptWindow transcriptWindow = room.getTranscriptWindow(); - StyledDocument doc = (StyledDocument)transcriptWindow.getDocument(); - Style style = doc.addStyle("StyleName", null); - - OutgoingCall outgoingCall = new OutgoingCall(); - outgoingCall.handleOutgoingCall(session, room, jid); - StyleConstants.setComponent(style, outgoingCall); - - // Insert the image at the end of the text - try { - doc.insertString(doc.getLength(), "ignored text", style); - doc.insertString(doc.getLength(), "\n", null); - } - catch (BadLocationException e) { - Log.error(e); - } - - room.scrollToBottom(); - } - - public void shutdown() { - } - - public boolean canShutDown() { - return false; - } - - public void uninstall() { - } - - /** - * Notify user that a new incoming jingle request has been receieved. - * - * @param request the JingleSessionRequest. - */ - private void incomingJingleSession(JingleSessionRequest request) { - if (PhoneManager.isUseStaticLocator() && PhoneManager.isUsingMediaLocator()) { - request.reject(); - } - else { - PhoneManager.setUsingMediaLocator(true); - new IncomingCall(request); - } - } - - /** - * Adds a presence listener to remove offline users from discovered features. - */ - private void addPresenceListener() { - // Check presence changes - SparkManager.getConnection().addAsyncStanzaListener( stanza -> { - Presence presence = (Presence)stanza; - if (!presence.isAvailable()) { - String from = presence.getFrom(); - if (ModelUtil.hasLength(from)) { - // Remove from - jingleFeature.remove(from); - } - } - - - }, new StanzaTypeFilter(Presence.class)); - } - - @Override - public void connected( XMPPConnection xmppConnection ) { - SparkManager.addFeature(JINGLE_NAMESPACE); - } - - @Override - public void authenticated( XMPPConnection xmppConnection, boolean b ) { - } - - @Override - public void connectionClosed() { - } - - @Override - public void connectionClosedOnError(Exception e) { - } - - @Override - public void reconnectingIn(int seconds) { - } - - @Override - public void reconnectionSuccessful() { - // Add Jingle to discovered items list. - SparkManager.addFeature(JINGLE_NAMESPACE); - } - - @Override - public void reconnectionFailed(Exception e) { - - } -} diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JingleResources.java b/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JingleResources.java deleted file mode 100644 index 9a24daa78..000000000 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/JingleResources.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin; - -import java.text.MessageFormat; -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; - -import org.jivesoftware.spark.util.log.Log; - -public class JingleResources { - private static PropertyResourceBundle prb; - - static ClassLoader cl = JingleResources.class.getClassLoader(); - - static { - prb = (PropertyResourceBundle)ResourceBundle.getBundle("i18n/jingle_i18n"); - } - - public static final String getString(String propertyName) { - try { - return prb.getString(propertyName); - } - catch (Exception e) { - Log.error(e); - return propertyName; - } - } - - public static String getString(String propertyName, Object... obj) { - String str = prb.getString(propertyName); - if (str == null) { - return propertyName; - } - - return MessageFormat.format(str, obj); - } -} \ No newline at end of file diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/PreviousConversationPanel.java b/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/PreviousConversationPanel.java deleted file mode 100644 index 46458b6b1..000000000 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/PreviousConversationPanel.java +++ /dev/null @@ -1,204 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin; - -import org.jivesoftware.spark.component.TimeTrackingLabel; -import org.jivesoftware.spark.component.VerticalFlowLayout; - -import javax.swing.BorderFactory; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import java.awt.Color; -import java.awt.FlowLayout; -import java.awt.Font; -import java.text.SimpleDateFormat; -import java.util.Date; - -/** - * - */ -public class PreviousConversationPanel extends JPanel { - - private static final long serialVersionUID = -8392478440078855765L; - - private final Color greenColor = new Color(91, 175, 41); - - private final JLabel currentCallLabel = new JLabel(); - private final JPanel timePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 0)); - - private final JLabel today = new JLabel(); - private final JLabel statusLabel = new JLabel(); - - final JLabel previousLabel = new JLabel("Previous Conversations:"); - private final JLabel oldConversation = new JLabel(); - - private final SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy, h:mm a"); - - - private TimeTrackingLabel durationLabel; - - private Date startTime; - - - public PreviousConversationPanel() { - setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 5, 0, true, false)); - - setBackground(Color.white); - setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230))); - - // Set Default Color for Current Call Label - currentCallLabel.setText("Current Call:"); - currentCallLabel.setFont(new Font("Dialog", Font.BOLD, 13)); - currentCallLabel.setForeground(greenColor); - - // Set default color for previous label. - previousLabel.setForeground(new Color(64, 103, 162)); - previousLabel.setFont(new Font("Dialog", Font.BOLD, 13)); - - statusLabel.setFont(new Font("Dialog", Font.BOLD, 12)); - - // Add Duration timer - durationLabel = new TimeTrackingLabel(new Date(), this); - durationLabel.setFont(new Font("Dialog", Font.BOLD, 12)); - durationLabel.stopTimer(); - - // Build Time Panel - - timePanel.setOpaque(false); - - today.setForeground(Color.black); - today.setFont(new Font("Dialog", Font.PLAIN, 12)); - - today.setText(formatter.format(new Date()) + " - Time: "); - timePanel.add(today); - timePanel.add(durationLabel); - - oldConversation.setForeground(new Color(211, 0, 0)); - oldConversation.setFont(new Font("Dialog", Font.BOLD, 12)); - - } - - /** - * Builds the previous history list. - * - * @param jid the jid of the user. - */ - public void addPreviousConversations(String jid) { - startTime = new Date(); - - currentCallLabel.setText("Current Call:"); - currentCallLabel.setFont(new Font("Dialog", Font.BOLD, 13)); - currentCallLabel.setForeground(greenColor); - - today.setText(formatter.format(new Date()) + " - Time: "); - - // Add Current Call and Time Panel - add(currentCallLabel); - add(timePanel); - add(statusLabel); - statusLabel.setVisible(false); - - // Give some space. - add(new JLabel()); - - add(previousLabel); - - add(oldConversation); - - - int count = 0; - /* - final CallList callList = SoftPhoneManager.getInstance().getLogManager().getCallList(); - for (HistoryCall call : callList.getList()) { - String number = TelephoneUtils.getNumbersFromPhone(call.getNumber()); - if (number.equals(TelephoneUtils.getNumbersFromPhone(phoneNumber))) { - count++; - if (count > 4) { - break; - } - - final Date callDate = new Date(call.getTime()); - final long duration = call.getCallLength(); - - StringBuilder builder = new StringBuilder(); - builder.append(formatter.format(callDate)); - builder.append(" "); - builder.append("("); - builder.append(ModelUtil.getTimeFromLong(duration)); - builder.append(")"); - - final JLabel callLabel = new JLabel(builder.toString()); - callLabel.setForeground(Color.black); - callLabel.setFont(new Font("Dialog", Font.PLAIN, 12)); - add(callLabel); - } - } - */ - - if (count == 0) { - final JLabel label = new JLabel("No previous conversations."); - label.setForeground(Color.gray); - add(label); - } - - durationLabel.resetTime(); - durationLabel.startTimer(); - - invalidate(); - validate(); - repaint(); - } - - public void callEnded() { - durationLabel.stopTimer(); - - currentCallLabel.setForeground(Color.black); - currentCallLabel.setText(JingleResources.getString("label.call.ended")); - - today.setText("Time: "); - } - - public void transferring() { - statusLabel.setText("Transferring..."); - statusLabel.setVisible(true); - } - - public void transfer(String user) { - durationLabel.stopTimer(); - statusLabel.setVisible(false); - - currentCallLabel.setForeground(Color.black); - currentCallLabel.setText(JingleResources.getString("label.call.ended")); - - today.setText("Time: "); - currentCallLabel.setText(JingleResources.getString("label.call.transfer",user)); - - Date now = new Date(); - final SimpleDateFormat timeFormatter = new SimpleDateFormat("h:mm"); - - - String end = timeFormatter.format(now); - - oldConversation.setText(formatter.format(startTime) + " - " + end + " (" + durationLabel.getText() + ")"); - } - - -} diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/RosterMemberCallButton.java b/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/RosterMemberCallButton.java deleted file mode 100644 index 0eef8d341..000000000 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/RosterMemberCallButton.java +++ /dev/null @@ -1,137 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin; - -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Image; -import java.awt.Insets; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; - -import javax.swing.Icon; -import javax.swing.JButton; - -/** - * - */ -public class RosterMemberCallButton extends JButton implements MouseListener { - - private static final long serialVersionUID = 8056708231977922612L; - private Icon normalIcon; - private Icon hoverIcon; - private Icon downIcon; - private Image backgroundImage; - private String text; - - private boolean selected; - - public RosterMemberCallButton(Image image, String text) { - super(); - - this.text = text; - - normalIcon = JinglePhoneRes.getImageIcon("ROSTERPANEL_BUTTON"); - hoverIcon = JinglePhoneRes.getImageIcon("ROSTERPANEL_BUTTON_HOVER"); - downIcon = JinglePhoneRes.getImageIcon("ROSTERPANEL_BUTTON_DOWN"); - backgroundImage = image; - - setIcon(normalIcon); - - decorate(); - - addMouseListener(this); - } - - /** - * Decorates the button with the approriate UI configurations. - */ - private void decorate() { - setBorderPainted(false); - setOpaque(true); - - setContentAreaFilled(false); - setMargin(new Insets(0, 0, 0, 0)); - } - - - public void mouseClicked(MouseEvent e) { - } - - public void mousePressed(MouseEvent e) { - setIcon(downIcon); - } - - public void mouseReleased(MouseEvent e) { - if (!selected) { - setIcon(normalIcon); - } - - } - - public void mouseEntered(MouseEvent e) { - if (!selected) { - setIcon(hoverIcon); - } - setCursor(new Cursor(Cursor.HAND_CURSOR)); - } - - public void mouseExited(MouseEvent e) { - if (!selected) { - setIcon(normalIcon); - } - setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - - public void setButtonSelected(boolean selected) { - this.selected = selected; - if (selected) { - setIcon(downIcon); - } - else { - setIcon(normalIcon); - } - } - - - public void paintComponent(Graphics g) { - super.paintComponent(g); - int width = getWidth(); - int height = getHeight(); - - int x = (width - backgroundImage.getWidth(null)) / 2; - int y = (height - backgroundImage.getHeight(null)) / 2; - g.drawImage(backgroundImage, 5, y, null); - - g.setColor(Color.black); - g.setFont(new Font("Dialog", Font.PLAIN, 11)); - - - int stringWidth = g.getFontMetrics().stringWidth(text); - - x = (width - stringWidth) / 2; - y = (height + 11) / 2; - g.drawString(text, x, y); - - } - -} diff --git a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/jingle.properties b/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/jingle.properties deleted file mode 100644 index 97978cf39..000000000 --- a/src/plugins/jingle/src/java/org/jivesoftware/sparkplugin/jingle.properties +++ /dev/null @@ -1,113 +0,0 @@ -RINGING = sounds/ringing.wav - - -# Images -CHAT_ROOM_DIAL_BUTTON = images/phone_call.png - -# Images -AT_SYMBOL_IMAGE = images/at.gif -CARD_IMAGE = images/card.gif -COMP_IMAGE = images/comp.gif -ERROR_IMAGE = images/error.gif -INFORM_IMAGE = images/inform.gif -LOGO_IMAGE = images/logo.gif -OFF_IMAGE = images/off.gif -ON_PHONE_IMAGE = images/on-phone.png -ON_IMAGE = images/on.gif -ANSWER_PHONE_IMAGE = images/phone_pick_up.png -HANG_UP_PHONE_IMAGE = images/btn_phone-hangup_24x24.png -HANG_UP_PHONE_77x24_IMAGE = images/btn_phone-hangup.png -HANG_UP_PHONE_16x16_IMAGE = images/icon_phone-hangup_16x16.png -HANG_UP_PHONE_24x24_IMAGE = images/icon_phone-hangup_24x24.png -CLEAR_IMAGE = images/close_dark.png -RECEIVER_IMAGE = images/receiver.png -HISTORY_IMAGE = images/icon_phone-history_16x16.png -ON_HOLD_IMAGE = images/icon_phone-hold_16x16.png -RECEIVER2_IMAGE = images/receiver2.png -MUTE_IMAGE = images/icon_phone-mute_16x16.png -MICROPHONE_IMAGE = images/microphone.png -VOICEMAIL_IMAGE = images/icon_phone-voicemail_16x16.png -VOLUME_IMAGE = images/volume.png -TRANSFER_IMAGE = images/transfer.png -CHAT_IMAGE = images/message.png -TELEPHONE_IMAGE = images/telephone.png -DIAL_PAD_16x16_IMAGE = images/dialpad_16x16.png -CONTACT_48x48_IMAGE = images/contact_48x48.png -CALL_OUT_32x32_IMAGE = images/callOut_32x32.png -HOLD_32x32_IMAGE = images/hold_32x32.png -MUTE_32x32_IMAGE = images/mute_32x32.png -NO_MUTE_32x32_IMAGE = images/noMute_32x32.png -RESUME_CALL_32x32_IMAGE = images/resumeCall_32x32.png -REJECT_32x32_IMAGE = images/reject_32x32.png -VOICEMAIL_16x16_IMAGE = images/voicemail_16x16.png -CALLLIST_16x16_IMAGE = images/callList_16x16.png -CALLIN_16x16_IMAGE = images/callIn_16x16.png -DIAL_24x24_IMAGE = images/CallStart_24x24.png -DIAL_16x16_IMAGE = images/CallStart_16x16.png -DELETE_32x32_IMAGE = images/delete_32x32.png -TITLE_PANE = images/titlePane.png -ICON_NUMBERPAD_IMAGE = images/icon_numberpad_12x15.png -DIAL_BUTTON_IMAGE = images/btn_phone-dial_24x24.png -DIAL_BUTTON_HOVER_IMAGE = images/btn_phone-dial-hover_24x24.png -DIAL_BUTTON_DOWN_IMAGE = images/btn_phone-dial-down_24x24.png -DIAL_BUTTON_DISABLED_IMAGE = images/btn_phone-dial-disabled_24x24.png -DIVIDER_IMAGE = images/divider.png -INCOMING_CALL_IMAGE = images/icon_call-incoming_42x22.png -TOASTER_ACCEPT_BUTTON = images/toaster_btn-accept.png -TOASTER_REJECT_BUTTON = images/toaster_btn-reject.png -CALL_PICKUP_IMAGE = images/icon_phone-pickup_24x24.png -CALL_REJECT_IMAGE = images/icon_phone-reject_24x24.png -MICROPHONE_IMAGE = images/icon_microphone_16x16.png -SPEAKER_IMAGE = images/icon_speaker_16x16.png -TRANSFER_IMAGE = images/icon_phone-transfer_16x16.png -PHONE_CALL_IMAGE = images/icon_phone-call_16x16.png -PHONE_CALL_24x24_IMAGE = images/phone_call.png -DELETE_24x24_IMAGE = images/delete_24x24.png -MUTE_128x128_IMAGE = images/mute_128x128.png -ON_PHONE_128x128_IMAGE = images/on_phone_128x128.png -HOLD_128x128_IMAGE = images/hold_128x128.png -PHONE_HANG_UP_128x128_IMAGE = images/phone_hang_up_128x128.png -MICROPHONE_24x24_IMAGE = images/icon_microphone_24x24.png -ON_HOLD_24x24_IMAGE = images/icon_phone-hold_24x24.png -MUTED_24x24_IMAGE = images/icon_phone-mute_24x24.png -TRANSFER_24x24_IMAGE = images/icon_phone-transfer_24x24.png -BRIEFCASE_IMAGE = images/briefcase.png - -# Registartion Panel -CLOSE_BUTTON = images/btn_phone-reg_close.png -CLOSE_BUTTON_DOWN = images/btn_phone-reg_close-down.png -CLOSE_BUTTON_HOVER = images/btn_phone-reg_close-hover.png -NORMAL_PHONE_ICON = images/icon_reciever_22x22.png -RECTANGLE_BUTTON = images/btn_phone-reg_retry.png -RECTANGLE_BUTTON_DOWN = images/btn_phone-reg_retry-down.png -RECTANGLE_BUTTON_HOVER = images/btn_phone-reg_retry-hover.png - -# Context Menus -WORK_IMAGE = images/icon_work_16x16.png -MOBILE_IMAGE = images/icon_mobile_16x16.png -HOME_IMAGE = images/home.png - -# Personal Panel -HANGUP_BIG_BUTTON = images/btn_phone-hangup-big.png -HANGUP_BIG_BUTTON_DOWN = images/btn_phone-hangup-big-down.png -HANGUP_BIG_BUTTON_HOVER = images/btn_phone-hangup-big-hover.png -CALLPANEL_BIG_BUTTON = images/btn_phone-big.png -CALLPANEL_BIG_BUTTON_HOVER = images/btn_phone-big-hover.png -CALLPANEL_BIG_BUTTON_DOWN = images/btn_phone-big-down.png - -# Roster Panel -ROSTERPANEL_BUTTON = images/btn_phone-sm.png -ROSTERPANEL_BUTTON_DOWN = images/btn_phone-sm-down.png -ROSTERPANEL_BUTTON_HOVER = images/btn_phone-sm-hover.png -LARGE_PHONE_ICON = images/receiver2_48x48.png - -# Dial Pad -DIALPAD_BUTTON = images/btn_dialpad.png -DIALPAD_BUTTON_DOWN = images/btn_dialpad-down.png -DIALPAD_BUTTON_HOVER = images/btn_dialpad-hover.png - -# Redial Button -REDIAL_BUTTON = images/btn_phone-redial-big.png -REDIAL_BUTTON_DOWN = images/btn_phone-redial-big-down.png -REDIAL_BUTTON_HOVER = images/btn_phone-redial-big-hover.png -REDIAL_IMAGE = images/phone_recall.png \ No newline at end of file diff --git a/src/plugins/jingle/src/resources/i18n/jingle_i18n_lt.properties b/src/plugins/jingle/src/resources/i18n/jingle_i18n_lt.properties deleted file mode 100644 index c29d688e7..000000000 --- a/src/plugins/jingle/src/resources/i18n/jingle_i18n_lt.properties +++ /dev/null @@ -1,12 +0,0 @@ -button.accept = Priimti -button.reject = Atmesti - -label.voice.request.from = Jums skambina ... -label.mute.call = U\u017etildyti \u0161\u012f skambut\u012f. -label.computer.to.computer = I\u0161 kompiuterio \u012f kompiuter\u012f -label.mute = Nutildyti -label.unmute = I\u0161jungti nutildym\u0105 -label.establishing.call = Lukterkite, u\u017emezgamas ry\u0161ys... -label.outgoing.voicechat = Skambutis pokalbiui balsu su abonentu {0} -label.call.ended = Pokalbis baigtas. -label.call.transfer = Skambutis peradresuotas abonentui {0} \ No newline at end of file diff --git a/src/plugins/jingle/src/resources/i18n/jingle_i18n_pl.properties b/src/plugins/jingle/src/resources/i18n/jingle_i18n_pl.properties deleted file mode 100644 index 7124f4a88..000000000 --- a/src/plugins/jingle/src/resources/i18n/jingle_i18n_pl.properties +++ /dev/null @@ -1,12 +0,0 @@ -button.accept = Akceptuj -button.reject = Odrzu\u0107 - -label.voice.request.from = Pro\u015bba o rozmow\u0119 g\u0142osow\u0105 od ... -label.mute.call = Wycisz to po\u0142\u0105czenie. -label.computer.to.computer = Po\u0142\u0105czenie komputer-komputer -label.mute = Wycisz -label.unmute = W\u0142\u0105cz g\u0142os -label.establishing.call = Ustanawianie po\u0142\u0105czenia. Prosz\u0119 czeka\u0107... -label.outgoing.voicechat = Wychodz\u0105ca rozmowa g\u0142osowa do {0} -label.call.ended = Po\u0142\u0105czenie zako\u0144czone. -label.call.transfer = Po\u0142\u0105czenie przekazane do {0} \ No newline at end of file diff --git a/src/plugins/jingle/src/resources/i18n/jingle_i18n_zh_CN.properties b/src/plugins/jingle/src/resources/i18n/jingle_i18n_zh_CN.properties deleted file mode 100644 index 589ef5a09..000000000 --- a/src/plugins/jingle/src/resources/i18n/jingle_i18n_zh_CN.properties +++ /dev/null @@ -1,14 +0,0 @@ -#Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net) - -button.accept = \u63A5\u53D7 -button.reject = \u62D2\u7EDD - -label.call.ended = \u547C\u53EB\u7ED3\u675F\u3002 -label.call.transfer = \u547C\u53EB\u8F6C\u79FB\u81F3 {0} -label.computer.to.computer = \u8BA1\u7B97\u673A\u5BF9\u8BA1\u7B97\u673A -label.establishing.call = \u6B63\u5728\u8FDE\u63A5\u4E2D\uFF0C\u8BF7\u7A0D\u5019 -label.mute = \u9759\u97F3 -label.mute.call = \u9759\u97F3\u6B64\u547C\u53EB\u3002 -label.outgoing.voicechat = \u4E0E{0}\u8FDB\u884C\u8BED\u97F3\u4EA4\u8C08 -label.unmute = \u53D6\u6D88\u9759\u97F3 -label.voice.request.from = \u8BED\u97F3\u4EA4\u8C08\u8BF7\u6C42\u6765\u81EA ... diff --git a/src/plugins/jingle/src/resources/i18n/jingle_i18n_zh_TW.properties b/src/plugins/jingle/src/resources/i18n/jingle_i18n_zh_TW.properties deleted file mode 100644 index 766c6188b..000000000 --- a/src/plugins/jingle/src/resources/i18n/jingle_i18n_zh_TW.properties +++ /dev/null @@ -1,12 +0,0 @@ -button.accept = \u63a5\u53d7 -button.reject = \u62d2\u7d55 - -label.voice.request.from = \u4f86\u81ea ... \u8a9e\u97f3\u804a\u5929\u8acb\u6c42 -label.mute.call = \u901a\u8a71\u975c\u97f3. -label.computer.to.computer = \u96fb\u8166\u5c0d\u96fb\u8166 -label.mute = \u975c\u97f3 -label.unmute = \u89e3\u9664\u975c\u97f3 -label.establishing.call = \u5efa\u7acb\u8a9e\u97f3\u804a\u5929. \u8acb\u7a0d\u5019... -label.outgoing.voicechat = \u5373\u5c07\u7d50\u675f\u7684\u8a9e\u97f3\u804a\u5929 {0} -label.call.ended = \u901a\u8a71\u7d50\u675f. -label.call.transfer = \u901a\u8a71\u8f49\u63a5\u5230 {0} \ No newline at end of file diff --git a/src/plugins/linux/LinuxPlugin.iml b/src/plugins/linux/LinuxPlugin.iml deleted file mode 100644 index aa2271cc0..000000000 --- a/src/plugins/linux/LinuxPlugin.iml +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/linux/build/build.xml b/src/plugins/linux/build/build.xml deleted file mode 100644 index 27012a7af..000000000 --- a/src/plugins/linux/build/build.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/linux/changelog.html b/src/plugins/linux/changelog.html deleted file mode 100644 index 4354c3963..000000000 --- a/src/plugins/linux/changelog.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - System Tray For Spark - - - - -

        -System Tray Plugin Change Log -

        - -

        1.0.0 -- August 10th, 2007

        -
          -
        • Initial release.
        • -
        - - - - - - diff --git a/src/plugins/linux/plugin.xml b/src/plugins/linux/plugin.xml deleted file mode 100644 index 2d0db1fce..000000000 --- a/src/plugins/linux/plugin.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - Notification and System Tray Plugin for Spark IM - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Adds System Tray functionality. - org.jivesoftware.spark.plugins.SystemTrayPlugin - 2.7.0 - 1.7.0 - - diff --git a/src/plugins/linux/readme.html b/src/plugins/linux/readme.html deleted file mode 100644 index 94f513568..000000000 --- a/src/plugins/linux/readme.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - System Tray Spark Plug Readme - - - - -

        -System Tray Plugin Readme -

        - -

        Overview

        - -

        -The plugin allows for Linux specific functionallity such as system tray. -

        - -

        Installation

        - -

        Simply install plugin via the Plugin Viewer in Spark

        - - - diff --git a/src/plugins/linux/src/java/org/jivesoftware/spark/plugins/SparkSystemTray.java b/src/plugins/linux/src/java/org/jivesoftware/spark/plugins/SparkSystemTray.java deleted file mode 100644 index f59c4473b..000000000 --- a/src/plugins/linux/src/java/org/jivesoftware/spark/plugins/SparkSystemTray.java +++ /dev/null @@ -1,345 +0,0 @@ -/** - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2006 Jive Software. All rights reserved. - * - * This software is published under the terms of the GNU Lesser Public License (LGPL), - * a copy of which is included in this distribution. - */ - -package org.jivesoftware.spark.plugins; - -import org.jivesoftware.MainWindowListener; -import org.jivesoftware.Spark; -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.Workspace; -import org.jivesoftware.spark.component.ImageTitlePanel; -import org.jivesoftware.spark.component.WrappedLabel; -import org.jivesoftware.spark.ui.PresenceListener; -import org.jivesoftware.spark.ui.status.StatusBar; -import org.jivesoftware.spark.ui.status.StatusItem; -import org.jdesktop.jdic.tray.SystemTray; -import org.jdesktop.jdic.tray.TrayIcon; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Frame; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.MenuItem; -import java.awt.Point; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - -import javax.swing.*; - -/** - * Handles tray icon operations inside of Spark. Use to display incoming chat requests, incoming messages - * and general notifications. - */ -public final class SparkSystemTray implements ActionListener, MainWindowListener { - private SystemTray systemTray; - private TrayIcon trayIcon; - private JPopupMenu notificationDialog; - private WrappedLabel messageLabel = new WrappedLabel(); - - - private final JMenuItem openMenu = new JMenuItem(Res.getString("menuitem.open")); - private final JMenuItem hideMenu = new JMenuItem(Res.getString("menuitem.hide")); - private final JMenuItem exitMenu = new JMenuItem(Res.getString("menuitem.exit")); - private final JMenuItem logoutMenu = new JMenuItem(Res.getString("menuitem.logout.no.status")); - - // Define DND MenuItems - private final JMenu statusMenu = new JMenu(Res.getString("menuitem.status")); - - private ImageTitlePanel headerLabel = new ImageTitlePanel(); - - private JFrame hideWindow = null; - - private ImageIcon availableIcon; - private ImageIcon awayIcon; - private ImageIcon dndIcon; - - /** - * Creates a new instance of notifications. - */ - public SparkSystemTray() { - if(Spark.isMac()){ - return; - } - - setupNotificationDialog(); - - // Handle tray image. - availableIcon = Default.getImageIcon(Default.TRAY_IMAGE); - if (availableIcon == null) { - availableIcon = SparkRes.getImageIcon(SparkRes.TRAY_IMAGE); - } - - awayIcon = SparkRes.getImageIcon(SparkRes.MESSAGE_AWAY); - dndIcon = SparkRes.getImageIcon(SparkRes.MESSAGE_DND); - - trayIcon = new TrayIcon(new ImageIcon(availableIcon.getImage())); - trayIcon.setIconAutoSize(true); - systemTray = SystemTray.getDefaultSystemTray(); - setTrayIcon(availableIcon); - - trayIcon.setToolTip(Default.getString(Default.APPLICATION_NAME)); // NORES - - JPopupMenu popupMenu = new JPopupMenu(Res.getString("title.tray.information")); - - // Add DND Menus - addStatusMenuItems(); - - // Add Open Menu - openMenu.setFont(new Font("Dialog", Font.BOLD, 11)); - popupMenu.add(openMenu); - - // Add Hide Menu - popupMenu.add(hideMenu); - popupMenu.addSeparator(); - // Add Spark Home Menu - - popupMenu.add(statusMenu); - - // Add Listeners - openMenu.addActionListener(this); - hideMenu.addActionListener(this); - - - Action logoutAction = new AbstractAction() { - public void actionPerformed(ActionEvent actionEvent) { - SparkManager.getMainWindow().logout(false); - } - }; - - logoutAction.putValue(Action.NAME, Res.getString("menuitem.logout.no.status")); - logoutMenu.addActionListener(logoutAction); - - if (Spark.isWindows()) { - popupMenu.add(logoutMenu); - } - - // Add Exit Menu - popupMenu.add(exitMenu); - exitMenu.addActionListener(this); - - SparkManager.getMainWindow().addMainWindowListener(this); - - trayIcon.setPopupMenu(popupMenu); - systemTray.addTrayIcon(trayIcon); - - trayIcon.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - showMainWindow(); - } - }); - - - SparkManager.getSessionManager().addPresenceListener(new PresenceListener() { - public void presenceChanged(Presence presence) { - changePresence(presence); - } - }); - } - - /** - * Change the presence of the tray. - * - * @param presence the new presence. - */ - public void changePresence(Presence presence) { - if (Spark.isMac()) { - return; - } - - if (presence.getMode() == Presence.Mode.available || presence.getMode() == Presence.Mode.chat) { - setTrayIcon(availableIcon); - } - else if (presence.getMode() == Presence.Mode.away || presence.getMode() == Presence.Mode.xa) { - setTrayIcon(awayIcon); - } - else { - setTrayIcon(dndIcon); - } - - // Get Status Text - if (presence.isAvailable()) { - String status = presence.getStatus(); - trayIcon.setToolTip(Default.getString(Default.APPLICATION_NAME) + "\n" + status); - } - } - - - /** - * Stops the icon from flashing. - */ - public void stopFlashing() { - Workspace workspace = SparkManager.getWorkspace(); - - StatusBar statusBox = workspace.getStatusBar(); - Presence presence = statusBox.getPresence(); - - changePresence(presence); - - } - - public void actionPerformed(ActionEvent e) { - Object o = e.getSource(); - if (!(o instanceof MenuItem)) { - /* - MainWindow window = SparkManager.getMainWindow(); - if (window.isVisible() && window.getState() == Frame.NORMAL) { - long now = System.currentTimeMillis(); - if (now - madeVisibleTime > 1000) { - window.setVisible(false); - return; - } - } - - madeVisibleTime = System.currentTimeMillis(); - */ - showMainWindow(); - return; - } - - final JMenuItem item = (JMenuItem)e.getSource(); - if (item == openMenu) { - showMainWindow(); - } - else if (item == hideMenu) { - SparkManager.getMainWindow().setVisible(false); - hideMenu.setEnabled(false); - } - else if (item == exitMenu) { - SparkManager.getMainWindow().shutdown(); - } - else { - final String status = item.getText(); - - // Change Status - Workspace workspace = SparkManager.getWorkspace(); - StatusItem statusItem = workspace.getStatusBar().getStatusItem(status); - if (statusItem != null) { - SparkManager.getSessionManager().changePresence(statusItem.getPresence()); - } - } - } - - /** - * Brings the MainWindow to the front. - */ - private void showMainWindow() { - if (hideWindow != null) { - hideWindow.dispose(); - } - - SparkManager.getMainWindow().setState(Frame.NORMAL); - SparkManager.getMainWindow().setVisible(true); - - notificationDialog.setVisible(false); - - hideMenu.setEnabled(true); - - SparkManager.getMainWindow().toFront(); - } - - - /** - * Add all Registered DND's to MenuItems. - */ - private void addStatusMenuItems() { - Workspace workspace = SparkManager.getWorkspace(); - StatusBar statusBar = workspace.getStatusBar(); - - for (Object o : statusBar.getStatusList()) { - StatusItem item = (StatusItem) o; - final JMenuItem menuItem = new JMenuItem(item.getText()); - menuItem.addActionListener(this); - statusMenu.add(menuItem); - } - } - - public void shutdown() { - systemTray.removeTrayIcon(trayIcon); - } - - public void mainWindowActivated() { - } - - public void mainWindowDeactivated() { - } - - /** - * Setup notification dialog. - */ - private void setupNotificationDialog() { - notificationDialog = new JPopupMenu(); - notificationDialog.setFocusable(false); - notificationDialog.setLayout(new BorderLayout()); - - final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - - Point newLoc = new Point((int)screenSize.getWidth() - 200, (int)screenSize.getHeight() - 150); - - JPanel mainPanel = new JPanel(); - mainPanel.setBackground(Color.white); - mainPanel.setLayout(new GridBagLayout()); - mainPanel.setBorder(BorderFactory.createLineBorder(Color.black, 1)); - - // Add Header Label - mainPanel.add(headerLabel, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); - - // Add Message Label - final JScrollPane messageScroller = new JScrollPane(messageLabel); - mainPanel.add(messageScroller, new GridBagConstraints(0, 2, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - messageScroller.setBackground(Color.white); - messageScroller.setForeground(Color.white); - messageLabel.setBackground(Color.white); - messageScroller.getViewport().setBackground(Color.white); - - // JButton okButton = new JButton("Ok"); - mainPanel.setPreferredSize(new Dimension(200, 150)); - - headerLabel.setTitle("Spark"); // NORES - headerLabel.setTitleFont(new Font("Dialog", Font.BOLD, 10)); - - messageLabel.setFont(new Font("Dialog", Font.PLAIN, 11)); - - notificationDialog.add(mainPanel, BorderLayout.CENTER); - notificationDialog.pack(); - notificationDialog.setPreferredSize(new Dimension(200, 150)); - notificationDialog.setLocation(newLoc); - messageLabel.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - notificationDialog.setVisible(false); - showMainWindow(); - } - }); - - mainPanel.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - notificationDialog.setVisible(false); - showMainWindow(); - } - }); - } - - private void setTrayIcon(ImageIcon icon) { - trayIcon.setIcon(new ImageIcon(icon.getImage())); - - } - - -} diff --git a/src/plugins/linux/src/java/org/jivesoftware/spark/plugins/SystemTrayPlugin.java b/src/plugins/linux/src/java/org/jivesoftware/spark/plugins/SystemTrayPlugin.java deleted file mode 100644 index 77deacbda..000000000 --- a/src/plugins/linux/src/java/org/jivesoftware/spark/plugins/SystemTrayPlugin.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * $Revision$ - * $Date$ - * - * Copyright (C) 1999-2005 Jive Software. All rights reserved. - * This software is the proprietary information of Jive Software. Use is subject to license terms. - */ - -package org.jivesoftware.spark.plugins; - -import org.jivesoftware.spark.plugin.Plugin; - -/** - * - */ -public class SystemTrayPlugin implements Plugin { - - public void initialize() { - // Add System Tray - new SparkSystemTray(); - } - - public void shutdown() { - } - - public boolean canShutDown() { - return false; - } - - public void uninstall() { - } -} diff --git a/src/plugins/otr/build/build.xml b/src/plugins/otr/build/build.xml deleted file mode 100644 index 5aec98d67..000000000 --- a/src/plugins/otr/build/build.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/otr/build/lib/dist/bcprov-jdk15on-1.47.jar b/src/plugins/otr/build/lib/dist/bcprov-jdk15on-1.47.jar deleted file mode 100644 index 0b80922e6..000000000 Binary files a/src/plugins/otr/build/lib/dist/bcprov-jdk15on-1.47.jar and /dev/null differ diff --git a/src/plugins/otr/build/lib/dist/otr4j-0.9.jar b/src/plugins/otr/build/lib/dist/otr4j-0.9.jar deleted file mode 100644 index f84cf156e..000000000 Binary files a/src/plugins/otr/build/lib/dist/otr4j-0.9.jar and /dev/null differ diff --git a/src/plugins/otr/plugin.xml b/src/plugins/otr/plugin.xml deleted file mode 100644 index e6b8f4f12..000000000 --- a/src/plugins/otr/plugin.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - OTR Plugin - 0.4 Beta - Holger Bergunde - http://www.stytrix.de - holger@bergunde.de - Adds OTR support to Spark - 2.7.0 - 1.7.0 - org.jivesoftware.spark.otrplug.OTRPlugin - Windows,Linux,Mac - \ No newline at end of file diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRManager.java b/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRManager.java deleted file mode 100644 index 14116f238..000000000 --- a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRManager.java +++ /dev/null @@ -1,162 +0,0 @@ -package org.jivesoftware.spark.otrplug; - -import java.io.IOException; - -import java.util.HashMap; - -import java.util.Map; - -import javax.swing.Icon; - -import net.java.otr4j.session.SessionID; - -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; - -import org.jivesoftware.spark.otrplug.impl.MyOtrKeyManager; -import org.jivesoftware.spark.otrplug.impl.OTRSession; -import org.jivesoftware.spark.otrplug.util.OTRProperties; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomListenerAdapter; -import org.jivesoftware.spark.ui.ContactItem; -import org.jivesoftware.spark.ui.ContactItemHandler; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; - -/** - * OTRManager controls the whole OTR process. It checks if a new chat window is - * opened and creates an OTR session if there is no available. - * - * @author Bergunde Holger - * - */ - -public class OTRManager extends ChatRoomListenerAdapter implements ContactItemHandler { - - private static OTRManager singleton; - private static Object LOCK = new Object(); - private Map _activeSessions = new HashMap(); - final ChatManager chatManager = SparkManager.getChatManager(); - private static MyOtrKeyManager _keyManager; - - private OTRManager() { - chatManager.addChatRoomListener(this); - chatManager.addContactItemHandler(this); - } - - @Override - public void chatRoomOpened(ChatRoom room) { - super.chatRoomOpened(room); - if (room instanceof ChatRoomImpl) { - createOTRSession((ChatRoomImpl) room, ((ChatRoomImpl) room).getParticipantJID()); - } - } - - @Override - public void chatRoomClosed(ChatRoom room) { - super.chatRoomClosed(room); - if (OTRProperties.getInstance().getOTRCloseOnChatClose()) { - if (room instanceof ChatRoomImpl) { - ChatRoomImpl myroom = (ChatRoomImpl) room; - if (_activeSessions.containsKey(myroom.getParticipantJID())) { - OTRSession searchedSession = _activeSessions.get(myroom.getParticipantJID()); - searchedSession.stopSession(); - _activeSessions.remove(myroom.getParticipantJID()); - } - } - } - } - - /** - * OTRManager is a sigleton. Use this method to get the instance. - * - * @return - */ - public static OTRManager getInstance() { - // Synchronize on LOCK to ensure that we don't end up creating - // two singletons. - synchronized (LOCK) { - if (null == singleton) { - OTRManager controller = new OTRManager(); - singleton = controller; - try { - _keyManager = new MyOtrKeyManager(SparkManager.getUserDirectory().getPath() + "/otrkey.priv"); - // we should generate a local keyprint if there is no - // avaiable - String key = _keyManager.getLocalFingerprint(new SessionID(SparkManager.getConnection().getUser(), "none", "Scytale")); - if (key == null) { - _keyManager.generateLocalKeyPair(new SessionID(SparkManager.getConnection().getUser(), "none", "Scytale")); - } - - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return controller; - } - } - return singleton; - } - - /** - * Starts the OTR session with specified JID. - * - * @param jid - * participant - */ - public void startOtrWithUser(String jid) { - if (_activeSessions.containsKey(jid)) { - _activeSessions.get(jid).startSession(); - } - } - - private void createOTRSession(ChatRoomImpl chatroom, String jid) { - if (!_activeSessions.containsKey(jid)) { - _activeSessions.put(jid, startOTRSession(chatroom, jid)); - } else { - _activeSessions.get(jid).updateChatRoom(chatroom); - } - } - - /** - * Returns the OtrKeyManager to store and load keys - * - * @return - */ - public MyOtrKeyManager getKeyManager() { - return _keyManager; - } - - private OTRSession startOTRSession(ChatRoomImpl chatroom, String jid) { - return new OTRSession(chatroom, SparkManager.getConnection().getUser(), jid); - } - - @Override - public boolean handlePresence(ContactItem item, Presence presence) { - if (OTRProperties.getInstance().getOTRCloseOnDisc()) { - if (!presence.isAvailable() && _activeSessions.containsKey(item.getJID())) { - _activeSessions.get(item.getJID()).stopSession(); - } - } - return false; - } - - @Override - public Icon getIcon(String jid) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Icon getTabIcon(Presence presence) { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean handleDoubleClick(ContactItem item) { - // TODO Auto-generated method stub - return false; - } - -} diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRPlugin.java b/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRPlugin.java deleted file mode 100644 index 0b38086d1..000000000 --- a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRPlugin.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.jivesoftware.spark.otrplug; - -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.otrplug.pref.OTRPreferences; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.preference.Preference; - -/** - * OTR Plugin - * - * @author Bergunde Holger - */ - -public class OTRPlugin implements Plugin { - - OTRManager _manager; - - @Override - public void initialize() { - // Create OTRManager singleton - - _manager = OTRManager.getInstance(); - - // The following will add an Entry into the Spark Preferences Window - Preference mypreference = new OTRPreferences(); - SparkManager.getPreferenceManager().addPreference(mypreference); - - } - - @Override - public void shutdown() { - // TODO Auto-generated method stub - - } - - @Override - public boolean canShutDown() { - // TODO Auto-generated method stub - return false; - } - - @Override - public void uninstall() { - // TODO Auto-generated method stub - - } - -} diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/impl/MyOtrKeyManager.java b/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/impl/MyOtrKeyManager.java deleted file mode 100644 index bf34ac038..000000000 --- a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/impl/MyOtrKeyManager.java +++ /dev/null @@ -1,379 +0,0 @@ -package org.jivesoftware.spark.otrplug.impl; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; -import java.util.List; -import java.util.Properties; -import java.util.Vector; - -import org.bouncycastle.util.encoders.Base64; - -import net.java.otr4j.OtrKeyManager; -import net.java.otr4j.OtrKeyManagerListener; -import net.java.otr4j.OtrKeyManagerStore; -import net.java.otr4j.crypto.OtrCryptoEngineImpl; -import net.java.otr4j.crypto.OtrCryptoException; -import net.java.otr4j.session.SessionID; - -/** - * An implementation of the OtrKeyManager provided by otr4j. It stores the local - * key chain - * - * @author Bergunde Holger - * - */ -public class MyOtrKeyManager implements OtrKeyManager { - - private OtrKeyManagerStore store; - - /** - * Use this consturctor if you want to use your own implementation for key - * storage - * - * @param store - * Imlementation of OtrKeyManagerStore - */ - public MyOtrKeyManager(OtrKeyManagerStore store) { - this.store = store; - } - - /** - * Inner class, own implemented key sotrage - * - * @author Bergunde Holger - * - */ - class DefaultPropertiesStore implements OtrKeyManagerStore { - private final Properties properties = new Properties(); - private String filepath; - - public DefaultPropertiesStore(String filepath) throws IOException { - if (filepath == null || filepath.length() < 1) - throw new IllegalArgumentException(); - this.filepath = filepath; - properties.clear(); - - InputStream in = new BufferedInputStream(new FileInputStream(getConfigurationFile())); - try { - properties.load(in); - } finally { - in.close(); - } - } - - private File getConfigurationFile() throws IOException { - File configFile = new File(filepath); - if (!configFile.exists()) - configFile.createNewFile(); - return configFile; - } - - public void setProperty(String id, boolean value) { - properties.setProperty(id, "true"); - try { - this.store(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void store() throws FileNotFoundException, IOException { - OutputStream out = new FileOutputStream(getConfigurationFile()); - properties.store(out, null); - out.close(); - } - - public void setProperty(String id, byte[] value) { - properties.setProperty(id, new String(Base64.encode(value))); - try { - this.store(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void removeProperty(String id) { - properties.remove(id); - try { - this.store(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public byte[] getPropertyBytes(String id) { - String value = properties.getProperty(id); - if (value == null) - return null; - return Base64.decode(value); - } - - public boolean getPropertyBoolean(String id, boolean defaultValue) { - try { - return Boolean.valueOf(properties.get(id).toString()); - } catch (Exception e) { - return defaultValue; - } - } - } - - /** - * Use this consturctor if key manager should use his own implementation of - * key storage - * - * @param filepath - * file where the keys should be stored - * @throws IOException - */ - public MyOtrKeyManager(String filepath) throws IOException { - this.store = new DefaultPropertiesStore(filepath); - } - - private List listeners = new Vector(); - - /** - * Adds listener to key manager - */ - public void addListener(OtrKeyManagerListener l) { - synchronized (listeners) { - if (!listeners.contains(l)) - listeners.add(l); - } - } - - /** - * Remove listener from key manager - */ - public void removeListener(OtrKeyManagerListener l) { - synchronized (listeners) { - listeners.remove(l); - } - } - - /** - * Generate a local key pair. Be careful. If there is already an key pair, - * it will override it - * - * @param sessionID - * the sessionID that is identified with the local machine - */ - public void generateLocalKeyPair(SessionID sessionID) { - if (sessionID == null) - return; - - String accountID = sessionID.getAccountID(); - KeyPair keyPair; - try { - keyPair = KeyPairGenerator.getInstance("DSA").genKeyPair(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - return; - } - - // Store Public Key. - PublicKey pubKey = keyPair.getPublic(); - X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(pubKey.getEncoded()); - - this.store.setProperty(accountID + ".publicKey", x509EncodedKeySpec.getEncoded()); - - // Store Private Key. - PrivateKey privKey = keyPair.getPrivate(); - PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privKey.getEncoded()); - - this.store.setProperty(accountID + ".privateKey", pkcs8EncodedKeySpec.getEncoded()); - } - - /** - * - * Returns the local finger print for specified session. If there is no - * finger print you might generate one. - * - * @return the local finger print for this sessionID - */ - public String getLocalFingerprint(SessionID sessionID) { - KeyPair keyPair = loadLocalKeyPair(sessionID); - - if (keyPair == null) - return null; - - PublicKey pubKey = keyPair.getPublic(); - - try { - return new OtrCryptoEngineImpl().getFingerprint(pubKey); - } catch (OtrCryptoException e) { - e.printStackTrace(); - return null; - } - } - - /** - * Return remote finger print for specified sessionID. - * - * @return finger print for remote contact - */ - public String getRemoteFingerprint(SessionID sessionID) { - PublicKey remotePublicKey = loadRemotePublicKey(sessionID); - if (remotePublicKey == null) - return null; - try { - return new OtrCryptoEngineImpl().getFingerprint(remotePublicKey); - } catch (OtrCryptoException e) { - e.printStackTrace(); - return null; - } - } - - /** - * check if the specified sessionID is verified for this machine - * - */ - public boolean isVerified(SessionID sessionID) { - if (sessionID == null) - return false; - - return this.store.getPropertyBoolean(sessionID.getUserID() + ".publicKey.verified", false); - } - - /** - * Returns the key pair (private and public key) for the local machine - * - * @param sessionID - * sessionID for currect machine - */ - public KeyPair loadLocalKeyPair(SessionID sessionID) { - if (sessionID == null) - return null; - - String accountID = sessionID.getAccountID(); - // Load Private Key. - byte[] b64PrivKey = this.store.getPropertyBytes(accountID + ".privateKey"); - if (b64PrivKey == null) - return null; - - PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(b64PrivKey); - - // Load Public Key. - byte[] b64PubKey = this.store.getPropertyBytes(accountID + ".publicKey"); - if (b64PubKey == null) - return null; - - X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(b64PubKey); - - PublicKey publicKey; - PrivateKey privateKey; - - // Generate KeyPair. - KeyFactory keyFactory; - try { - keyFactory = KeyFactory.getInstance("DSA"); - publicKey = keyFactory.generatePublic(publicKeySpec); - privateKey = keyFactory.generatePrivate(privateKeySpec); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - return null; - } catch (InvalidKeySpecException e) { - e.printStackTrace(); - return null; - } - - return new KeyPair(publicKey, privateKey); - } - - /** - * Loads the public key for the specified sessionID. If there is no key - * stored, you will get 'null' - */ - public PublicKey loadRemotePublicKey(SessionID sessionID) { - if (sessionID == null) - return null; - - String userID = sessionID.getUserID(); - - byte[] b64PubKey = this.store.getPropertyBytes(userID + ".publicKey"); - if (b64PubKey == null) - return null; - - X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(b64PubKey); - - // Generate KeyPair. - KeyFactory keyFactory; - try { - keyFactory = KeyFactory.getInstance("DSA"); - return keyFactory.generatePublic(publicKeySpec); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - return null; - } catch (InvalidKeySpecException e) { - e.printStackTrace(); - return null; - } - } - - /** - * Stores the public key for a specified user from sessionID - * - * @param sessionID - * sessionID to identifiy the owner of the key - * @param pubKey - * the key which should be stored - */ - public void savePublicKey(SessionID sessionID, PublicKey pubKey) { - if (sessionID == null) - return; - - X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(pubKey.getEncoded()); - - String userID = sessionID.getUserID(); - this.store.setProperty(userID + ".publicKey", x509EncodedKeySpec.getEncoded()); - - this.store.removeProperty(userID + ".publicKey.verified"); - } - - /** - * Removes the verification for the specified sessionID - */ - public void unverify(SessionID sessionID) { - if (sessionID == null) - return; - - if (!isVerified(sessionID)) - return; - - this.store.removeProperty(sessionID.getUserID() + ".publicKey.verified"); - for (OtrKeyManagerListener l : listeners) - l.verificationStatusChanged(sessionID); - - } - - /** - * Verify the specified sessionID - */ - public void verify(SessionID sessionID) { - if (sessionID == null) - return; - - if (this.isVerified(sessionID)) - return; - - this.store.setProperty(sessionID.getUserID() + ".publicKey.verified", true); - - for (OtrKeyManagerListener l : listeners) - l.verificationStatusChanged(sessionID); - } - -} diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/impl/OTREngineHost.java b/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/impl/OTREngineHost.java deleted file mode 100644 index 5889953e5..000000000 --- a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/impl/OTREngineHost.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.jivesoftware.spark.otrplug.impl; - -import java.awt.Color; -import java.security.KeyPair; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.otrplug.OTRManager; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; - -import net.java.otr4j.OtrEngineHost; -import net.java.otr4j.OtrPolicy; -import net.java.otr4j.session.SessionID; -import org.jivesoftware.spark.util.log.Log; - -/** - * - * Implementation of OtrEngineHost provided from otr4j. It handles the message - * injection to specified chat window and handles key pair. - * - * @author Bergunde Holger - */ -public class OTREngineHost implements OtrEngineHost { - - private ChatRoomImpl _chatRoom; - private OtrPolicy _policy; - - public OTREngineHost(OtrPolicy policy, ChatRoomImpl chatroom) { - _policy = policy; - _chatRoom = chatroom; - } - - @Override - public KeyPair getKeyPair(SessionID arg0) { - return OTRManager.getInstance().getKeyManager().loadLocalKeyPair(arg0); - } - - @Override - public OtrPolicy getSessionPolicy(SessionID arg0) { - return _policy; - } - - @Override - public void injectMessage(SessionID arg0, String arg1) { - Message injection = new Message(); - injection.setType(Message.Type.chat); - injection.setTo(_chatRoom.getParticipantJID()); - injection.setFrom(SparkManager.getSessionManager().getJID()); - String threadID = StringUtils.randomString(6); - injection.setThread(threadID); - injection.setBody(arg1); - try - { - SparkManager.getConnection().sendStanza(injection); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to send injection to " + injection.getTo(), e ); - } - } - - @Override - public void showError(SessionID arg0, String arg1) { - _chatRoom.getTranscriptWindow().insertNotificationMessage(arg1, Color.red); - - } - - @Override - public void showWarning(SessionID arg0, String arg1) { - _chatRoom.getTranscriptWindow().insertNotificationMessage(arg1, Color.red); - - } - -} diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/impl/OTRSession.java b/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/impl/OTRSession.java deleted file mode 100644 index 4fd3b4bf6..000000000 --- a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/impl/OTRSession.java +++ /dev/null @@ -1,238 +0,0 @@ -package org.jivesoftware.spark.otrplug.impl; - -import java.awt.Color; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.security.PublicKey; - -import javax.swing.ImageIcon; -import javax.swing.JOptionPane; -import javax.swing.UIManager; - -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.spark.otrplug.OTRManager; -import org.jivesoftware.spark.otrplug.ui.OTRConnectionPanel; -import org.jivesoftware.spark.otrplug.util.OTRProperties; -import org.jivesoftware.spark.otrplug.util.OTRResources; -import org.jivesoftware.spark.ui.ChatRoomButton; -import org.jivesoftware.spark.ui.MessageEventListener; -import org.jivesoftware.resource.Res; - -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.util.UIComponentRegistry; - -import net.java.otr4j.OtrEngineHost; -import net.java.otr4j.OtrEngineImpl; -import net.java.otr4j.OtrEngineListener; -import net.java.otr4j.OtrPolicy; -import net.java.otr4j.OtrPolicyImpl; -import net.java.otr4j.session.SessionID; -import net.java.otr4j.session.SessionStatus; - -/** - * OTRSession are unique for every conversation. It handles the otrEngine for - * the chat and controls if the chat is encrypted or not. - * - * @author Bergunde Holger - */ -public class OTRSession { - - private ChatRoomImpl _chatRoom; - private String _myJID; - private String _remoteJID; - private OtrEngineHost _otrEngineHost; - private SessionID _mySession; - private OtrEngineImpl _engine; - private OTRManager _manager = OTRManager.getInstance(); - final ChatRoomButton _otrButton = UIComponentRegistry.getButtonFactory().createOtrButton(); - private OTRConnectionPanel _conPanel; - private MessageEventListener _msgEvnt; - private boolean _OtrEnabled = false; - private OtrEngineListener _otrListener; - - /** - * OTRSession Constructor - * - * @param chatroom - * chat room related to this OTR session - * @param myJID - * my own JID - * @param remoteJID - * the JID of the participant - */ - public OTRSession(ChatRoomImpl chatroom, String myJID, String remoteJID) { - _chatRoom = chatroom; - _myJID = myJID; - _remoteJID = remoteJID; - _otrEngineHost = new OTREngineHost(new OtrPolicyImpl(OtrPolicy.ALLOW_V2 | OtrPolicy.ERROR_START_AKE), _chatRoom); - _mySession = new SessionID(_myJID, _remoteJID, "Scytale"); - - _engine = new OtrEngineImpl(_otrEngineHost); - - setUpMessageListener(); - - createButton(); - - // Only initialize the actionListener once - _otrButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) { - stopSession(); - } else { - startSession(); - } - - } - }); - - _otrButton.setToolTipText(OTRResources.getString("otr.chat.button.tooltip")); - - _OtrEnabled = OTRProperties.getInstance().getIsOTREnabled(); - } - - /** - * Maybe you want to update the chat room because it was reopend but the OTR - * session is still alive. - * - * @param chatroom - * the chat room related to this OTR session - */ - public void updateChatRoom(ChatRoomImpl chatroom) { - _OtrEnabled = OTRProperties.getInstance().getIsOTREnabled(); - _chatRoom = chatroom; - setUpMessageListener(); - createButton(); - } - - private void setUpMessageListener() { - _conPanel = new OTRConnectionPanel(_chatRoom); - _chatRoom.removeMessageEventListener(_msgEvnt); - _msgEvnt = new MessageEventListener() { - - @Override - public void sendingMessage(Message message) { - String oldmsg = message.getBody(); - if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) { - message.setBody(null); - String mesg = _engine.transformSending(_mySession, oldmsg); - message.setBody(mesg); - - } - } - - @Override - public void receivingMessage(Message message) { - if (message.getBody() != null && _OtrEnabled) { - String old = message.getBody(); - message.setBody(null); - String mesg = null; - if (old.length() > 2) { - mesg = _engine.transformReceiving(_mySession, old); - } - if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) { - message.setBody(mesg); - } else { - if (old.length() > 3 && old.substring(0, 4).equals("?OTR")) { - old = null; - } - message.setBody(old); - } - } else if (!_OtrEnabled) { - String old = message.getBody(); - message.setBody(null); - if (old.length() > 3 && old.substring(0, 4).equals("?OTR")) { - _chatRoom.getTranscriptWindow().insertNotificationMessage(OTRResources.getString("otr.not.enabled"), Color.gray); - } else { - message.setBody(old); - } - } - - } - }; - _chatRoom.addMessageEventListener(_msgEvnt); - } - - private void createButton() { - - if (OTRProperties.getInstance().getIsOTREnabled()) { - final ClassLoader cl = getClass().getClassLoader(); - - ImageIcon otricon = null; - if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) { - otricon = new ImageIcon(cl.getResource("otr_on.png")); - _conPanel.successfullyCon(); - } else { - otricon = new ImageIcon(cl.getResource("otr_off.png")); - } - - _otrButton.setIcon(otricon); - - _engine.removeOtrEngineListener(_otrListener); - _chatRoom.getToolBar().addChatRoomButton(_otrButton); - _otrListener = new OtrEngineListener() { - - @Override - public void sessionStatusChanged(SessionID arg0) { - UIManager.put("OptionPane.yesButtonText", Res.getString("yes")); - UIManager.put("OptionPane.noButtonText", Res.getString("no")); - UIManager.put("OptionPane.cancelButtonText", Res.getString("cancel")); - - if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) { - _conPanel.successfullyCon(); - - String otrkey = _manager.getKeyManager().getRemoteFingerprint(_mySession); - if (otrkey == null) { - PublicKey pubkey = _engine.getRemotePublicKey(_mySession); - _manager.getKeyManager().savePublicKey(_mySession, pubkey); - otrkey = _manager.getKeyManager().getRemoteFingerprint(_mySession); - } - - if (!OTRManager.getInstance().getKeyManager().isVerified(_mySession)) { - final int n = JOptionPane.showConfirmDialog(_otrButton, - OTRResources.getString("otr.start.session.with", _remoteJID) + "\n" + OTRResources.getString("otr.key.not.verified.text") + "\n" + otrkey - + "\n" + OTRResources.getString("otr.question.verify"), OTRResources.getString("otr.key.not.verified.title"), - JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); - - if (n == JOptionPane.YES_OPTION) { - _manager.getKeyManager().verify(_mySession); - } - - } - _otrButton.setIcon(new ImageIcon(cl.getResource("otr_on.png"))); - } else if (_engine.getSessionStatus(_mySession).equals(SessionStatus.FINISHED)) { - _otrButton.setIcon(new ImageIcon(cl.getResource("otr_off.png"))); - stopSession(); - } else if (_engine.getSessionStatus(_mySession).equals(SessionStatus.PLAINTEXT)) { - _otrButton.setIcon(new ImageIcon(cl.getResource("otr_off.png"))); - stopSession(); - } - - } - }; - _engine.addOtrEngineListener(_otrListener); - } - } - - /** - * Start the OTR session manually from outside - */ - public void startSession() { - _conPanel.tryToStart(); - _engine.startSession(_mySession); - } - - /** - * Stop the OTR session manually from outside - */ - public void stopSession() { - _conPanel.connectionClosed(); - if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) { - final ClassLoader cl = getClass().getClassLoader(); - _otrButton.setIcon(new ImageIcon(cl.getResource("otr_off.png"))); - _engine.endSession(_mySession); - } - } - -} diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/pref/OTRKeyTable.java b/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/pref/OTRKeyTable.java deleted file mode 100644 index f62c65e2b..000000000 --- a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/pref/OTRKeyTable.java +++ /dev/null @@ -1,103 +0,0 @@ -package org.jivesoftware.spark.otrplug.pref; - -import java.awt.BorderLayout; - -import java.util.Vector; - -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTable; - -import javax.swing.event.TableModelListener; -import javax.swing.table.DefaultTableModel; - -import org.jivesoftware.spark.otrplug.util.OTRResources; - -/** - * OTRKeyTable displays a key table. You can add keys using the addEntry() - * mathod - * - * @author Bergunde Holger - */ -public class OTRKeyTable extends JPanel { - - /** - * - */ - private static final long serialVersionUID = -2922785387942547350L; - private JTable _table; - private DefaultTableModel _tableModel; - - public OTRKeyTable() { - - final String[] header = { OTRResources.getString("otr.table.jid"), OTRResources.getString("otr.table.public.key"), OTRResources.getString("otr.key.verified") }; - - _tableModel = new MyTableModel(header); - _table = new JTable(_tableModel); - _table.getTableHeader().setReorderingAllowed(false); - - this.setLayout(new BorderLayout()); - this.add(new JScrollPane(_table), BorderLayout.CENTER); - - } - - class MyTableModel extends DefaultTableModel { - /** - * - */ - private static final long serialVersionUID = -2930577433474767242L; - - public MyTableModel(String[] headers) { - super(headers, 0); - } - - @Override - public boolean isCellEditable(int row, int column) { - if (column == 2) - return true; - else - return false; - - } - - @Override - public Class getColumnClass(int columnIndex) { - if (columnIndex == 2) { - return Boolean.class; - } else - return String.class; - } - } - - public void addTableChangeListener(TableModelListener listener) { - _tableModel.addTableModelListener(listener); - } - - /** - * Adds a key to the table - * - * @param jid - * @param hash - * @param verified - */ - public void addEntry(String jid, String hash, boolean verified) { - Vector data = new Vector(3); - - data.add(jid); - data.add(hash); - data.add(verified); - - _tableModel.addRow(data); - } - - /** - * Returns a specified row - * - * @param row - * @param col - */ - public Object getValueAt(int row, int col) { - return _tableModel.getValueAt(row, col); - } - -} \ No newline at end of file diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/pref/OTRPrefPanel.java b/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/pref/OTRPrefPanel.java deleted file mode 100644 index 07b77a518..000000000 --- a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/pref/OTRPrefPanel.java +++ /dev/null @@ -1,193 +0,0 @@ -package org.jivesoftware.spark.otrplug.pref; - -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import javax.swing.JTextField; -import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; - -import net.java.otr4j.session.SessionID; - -import org.jivesoftware.smack.roster.Roster; -import org.jivesoftware.smack.roster.RosterEntry; -import org.jivesoftware.spark.SparkManager; - -import org.jivesoftware.spark.otrplug.OTRManager; -import org.jivesoftware.spark.otrplug.impl.MyOtrKeyManager; -import org.jivesoftware.spark.otrplug.util.OTRProperties; -import org.jivesoftware.spark.otrplug.util.OTRResources; - -/** - * - * OTR preference panel for Spark Preferences - * - * @author Bergund Holger - * - */ -public class OTRPrefPanel extends JPanel { - - private static final long serialVersionUID = -7125162190413040003L; - private OTRManager _manager; - private JCheckBox _enableOTR; - private JCheckBox _closeSessionOff; - private JCheckBox _closeSessionOnWindowClose; - private JLabel _currentKeyLabel; - private JButton _renewPrivateKey; - private OTRKeyTable _keytable; - private JTextField _privateKey; - private MyOtrKeyManager _keyManager; - private OTRProperties _properties; - - public OTRPrefPanel() { - - _manager = OTRManager.getInstance(); - _keyManager = _manager.getKeyManager(); - _properties = OTRProperties.getInstance(); - setLayout(new GridBagLayout()); - init(); - buildGUI(); - OtrEnableSwitch(); - } - - private void OtrEnableSwitch() { - if (!_enableOTR.isSelected()) { - _closeSessionOff.setEnabled(false); - _closeSessionOnWindowClose.setEnabled(false); - _renewPrivateKey.setEnabled(false); - _keytable.setEnabled(false); - } else { - _closeSessionOff.setEnabled(true); - _closeSessionOnWindowClose.setEnabled(true); - _renewPrivateKey.setEnabled(true); - _keytable.setEnabled(true); - } - } - - private void init() { - - _enableOTR = new JCheckBox(); - _enableOTR.setText(OTRResources.getString("otr.enable")); - _enableOTR.setSelected(_properties.getIsOTREnabled()); - - _enableOTR.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - OtrEnableSwitch(); - } - }); - - _closeSessionOff = new JCheckBox(); - _closeSessionOff.setText(OTRResources.getString("otr.close.session.on.contact.off")); - _closeSessionOff.setSelected(_properties.getOTRCloseOnDisc()); - - _closeSessionOnWindowClose = new JCheckBox(); - _closeSessionOnWindowClose.setText(OTRResources.getString("otr.close.session.on.window.close")); - _closeSessionOnWindowClose.setSelected(_properties.getOTRCloseOnChatClose()); - - _currentKeyLabel = new JLabel(); - _currentKeyLabel.setText(OTRResources.getString("current.priv.key")); - - _renewPrivateKey = new JButton(); - _renewPrivateKey.setText(OTRResources.getString("renew.current.key")); - _renewPrivateKey.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - SessionID mySession = new SessionID(SparkManager.getConnection().getUser(), "no one", "Scytale"); - _manager.getKeyManager().generateLocalKeyPair(mySession); - _privateKey.setText(getCurrentLocalKey()); - } - }); - - _privateKey = new JTextField(); - _privateKey.setEditable(false); - _privateKey.setText(getCurrentLocalKey()); - - _keytable = new OTRKeyTable(); - - loadRemoteKeys(); - - } - - private void loadRemoteKeys() { - - for (RosterEntry entry : Roster.getInstanceFor( SparkManager.getConnection() ).getEntries()) { - SessionID curSession = new SessionID(SparkManager.getConnection().getUser(), entry.getUser(), "Scytale"); - String remoteKey = _keyManager.getRemoteFingerprint(curSession); - if (remoteKey != null) { - boolean isVerified = _keyManager.isVerified(curSession); - _keytable.addEntry(entry.getUser(), remoteKey, isVerified); - } - } - - _keytable.addTableChangeListener(new TableModelListener() { - - @Override - public void tableChanged(TableModelEvent e) { - int col = e.getColumn(); - int row = e.getFirstRow(); - - if (col == 2) { - boolean selection = (Boolean) _keytable.getValueAt(row, col); - String JID = (String) _keytable.getValueAt(row, 0); - SessionID curSelectedSession = new SessionID(SparkManager.getConnection().getUser(), JID, "Scytale"); - if (!selection) { - _keyManager.verify(curSelectedSession); - } else { - _keyManager.unverify(curSelectedSession); - } - } - } - }); - - } - - private void buildGUI() { - this.setBorder(BorderFactory.createTitledBorder(OTRResources.getString("otr.settings"))); - this.add(_enableOTR, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); - this.add(_closeSessionOff, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(10, 0, 0, 0), 0, 0)); - this.add(_closeSessionOnWindowClose, - new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); - this.add(_currentKeyLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 5, 0, 0), 0, 0)); - this.add(_privateKey, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(10, 0, 0, 5), 0, 0)); - this.add(_renewPrivateKey, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 5), 0, 0)); - this.add(_keytable, new GridBagConstraints(0, 5, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(20, 5, 10, 5), 0, 0)); - } - - private String getCurrentLocalKey() { - SessionID mySession = new SessionID(SparkManager.getConnection().getUser(), "no one", "Scytale"); - String myKey = _keyManager.getLocalFingerprint(mySession); - return myKey; - } - - public JComponent getGUI() { - _keytable = new OTRKeyTable(); - loadRemoteKeys(); - return this; - } - - public boolean isOTREnabled() { - return _enableOTR.isSelected(); - } - - public boolean isCloseOnDisc() { - return _closeSessionOff.isSelected(); - } - - public boolean isCloseOnChatClose() { - return _closeSessionOnWindowClose.isSelected(); - } - -} diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/ui/OTRConnectionPanel.java b/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/ui/OTRConnectionPanel.java deleted file mode 100644 index 479f03abb..000000000 --- a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/ui/OTRConnectionPanel.java +++ /dev/null @@ -1,152 +0,0 @@ -package org.jivesoftware.spark.otrplug.ui; - -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Timer; -import java.util.TimerTask; - -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.text.BadLocationException; -import javax.swing.text.Style; -import javax.swing.text.StyleConstants; -import javax.swing.text.StyledDocument; - -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.otrplug.OTRManager; -import org.jivesoftware.spark.otrplug.util.OTRResources; -import org.jivesoftware.spark.ui.TranscriptWindow; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; - -/** - * Shows StyledDocuments in transcript window for info if the session - * established successfully or not - * - * @author Bergunde Holger - */ -public class OTRConnectionPanel { - - private ChatRoomImpl _chatRoom; - private JLabel _label; - private ImageIcon _icon; - private JPanel _conPanel; - private int _i; - private StyledDocument _doc; - private TranscriptWindow _transcriptWindow; - private JButton _retry; - private boolean _succesfull = false; - private boolean _waiting = false; - - public OTRConnectionPanel(ChatRoomImpl chatroom) { - _chatRoom = chatroom; - _transcriptWindow = _chatRoom.getTranscriptWindow(); - _doc = _transcriptWindow.getStyledDocument(); - _retry = new JButton(OTRResources.getString("otr.retry")); - _retry.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - OTRManager.getInstance().startOtrWithUser(_chatRoom.getParticipantJID()); - - } - }); - - _retry.setVisible(false); - - } - - /** - * Indicates that OTR is trying to establish an OTR session. This will - * inject a styledDocument. You have 10 seconds to approve that the - * connection was successful using method successfullyCon() - * - */ - public void tryToStart() { - if (!_succesfull && !_waiting) { - renewPanel(); - _icon.setImage(SparkRes.getImageIcon(SparkRes.BUSY_IMAGE).getImage()); - - _conPanel.setVisible(true); - - _i = 10; - _label.setText(OTRResources.getString("otr.try.to.connect.for.seconds", _i)); - - Timer t = new Timer(); - TimerTask task = new TimerTask() { - - @Override - public void run() { - - if (_i > 0 && !_succesfull) { - _waiting = true; - _label.setText(OTRResources.getString("otr.try.to.connect.for.seconds", _i)); - decI(); - } else if (!_succesfull) { - _waiting = true; - _icon.setImage(SparkRes.getImageIcon(SparkRes.SMALL_DELETE).getImage()); - _label.setText(OTRResources.getString("otr.failed.to.establish", _i)); - _retry.setVisible(true); - - this.cancel(); - } else { - this.cancel(); - } - } - }; - t.scheduleAtFixedRate(task, 0, 1000); - } - } - - private void renewPanel() { - _conPanel = new JPanel(new GridBagLayout()); - _label = new JLabel(); - _icon = new ImageIcon(); - - _conPanel.add(new JLabel(_icon), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 10, 0, 0), 0, 0)); - _conPanel.add(_label, new GridBagConstraints(1, 0, 1, 1, 0.7, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 15, 0, 0), 0, 0)); - _conPanel.add(_retry, new GridBagConstraints(2, 0, 1, 1, 2.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 10, 0, 0), 0, 0)); - - _transcriptWindow.addComponent(_conPanel); - _chatRoom.scrollToBottom(); - } - - /** - * Indicates in the transcript window, that the OTR session has been closed - */ - public void connectionClosed() { - if (_succesfull) { - renewPanel(); - _succesfull = false; - _label.setText(OTRResources.getString("otr.disconnected")); - _icon.setImage(SparkRes.getImageIcon(SparkRes.SMALL_STOP).getImage()); - _conPanel.setVisible(true); - } - } - - private void decI() { - --_i; - } - - /** - * Should be called after you called tryToStart(). It will indicate that the - * session is now encrypted - */ - public void successfullyCon() { - if (!_succesfull) { - if (!_waiting) - renewPanel(); - _retry.setVisible(false); - _conPanel.setVisible(true); - _succesfull = true; - _waiting = false; - _icon.setImage(SparkRes.getImageIcon(SparkRes.SMALL_CHECK).getImage()); - _label.setText(OTRResources.getString("otr.successfull")); - } - } - -} diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/util/OTRResources.java b/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/util/OTRResources.java deleted file mode 100644 index 11a546ca2..000000000 --- a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/util/OTRResources.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.jivesoftware.spark.otrplug.util; - -/** - * OTRResources needed to load icons and language files into OTR plugin - * - * @author Bergunde Holger - */ -import java.text.MessageFormat; -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; - -import javax.swing.ImageIcon; - -import org.jivesoftware.spark.util.log.Log; - -public class OTRResources { - - private static PropertyResourceBundle prb; - - static ClassLoader cl = OTRResources.class.getClassLoader(); - - static { - prb = (PropertyResourceBundle) ResourceBundle.getBundle("i18n/otrplugin_i18n"); - } - - /** - * Returns a string from the language file - * - * @param propertyName - * @return - */ - public static final String getString(String propertyName) { - try { - return prb.getString(propertyName); - } catch (Exception e) { - Log.error(e); - return propertyName; - } - } - - /** - * Returns an ImageIcon from OTR resources folder - * - * @param fileName - * @return - */ - public static ImageIcon getIcon(String fileName) { - final ClassLoader cl = OTRResources.class.getClassLoader(); - ImageIcon icon = new ImageIcon(cl.getResource(fileName)); - return icon; - } - - /** - * Returns a string with wildcards - * - * @param propertyName - * @param obj - */ - public static String getString(String propertyName, Object... obj) { - String str = prb.getString(propertyName); - if (str == null) { - return propertyName; - } - - return MessageFormat.format(str, obj); - } - -} diff --git a/src/plugins/otr/src/resources/i18n/otrplugin_i18n.properties b/src/plugins/otr/src/resources/i18n/otrplugin_i18n.properties deleted file mode 100644 index 26d1826d7..000000000 --- a/src/plugins/otr/src/resources/i18n/otrplugin_i18n.properties +++ /dev/null @@ -1,30 +0,0 @@ - -# OTR language file - -otr.title = Off-the-Record Messaging -otr.list.entry = OTR Messaging -otr.settings = OTR Settings -otr.enable = OTR Enabled -current.priv.key = Current private key: -renew.current.key = Generate a new key -otr.close.session.on.window.close = Close OTR session when chat window is closed -otr.close.session.on.contact.off = Close OTR session when contact went offline -otr.key.not.verified.title = Key not verified -otr.question.verify = Verify? -otr.key.not.verified.text = Following key is not verified! -otr.start.session.with = OTR encrypted Session with {0} -otr.not.enabled = You recieved an OTR request. You should enable OTR in preferences. -otr.chat.is.still.encrypted = This conversation is still encrypted. -otr.chat.button.tooltip = Message encryption -#Table Columns -otr.table.jid = User's JID -otr.table.public.key = Public key -otr.key.verified = Verified - - -#OTR Panel in Chat -otr.retry = Retry -otr.try.to.connect.for.seconds = Trying to establish an OTR session. {0}s remaining... -otr.failed.to.establish = Failed to establish OTR session. Timeout. -otr.successfull = OTR successfully establish. Messages will be encrypted. -otr.disconnected = OTR session closed. Messages are no longer encrypted. \ No newline at end of file diff --git a/src/plugins/otr/src/resources/i18n/otrplugin_i18n_de.properties b/src/plugins/otr/src/resources/i18n/otrplugin_i18n_de.properties deleted file mode 100644 index ddd6bba3f..000000000 --- a/src/plugins/otr/src/resources/i18n/otrplugin_i18n_de.properties +++ /dev/null @@ -1,30 +0,0 @@ - -# OTR language file - -otr.title = Off-the-Record Nachrichten Verschlüsselung -otr.list.entry = OTR Verschlüsselung -otr.settings = OTR Einstellungen -otr.enable = OTR Aktivieren -current.priv.key = Aktueller privater Schlüssel: -renew.current.key = Neuen Schlüssel generieren -otr.close.session.on.window.close = OTR Sitzung schließen, wenn Chatfenster geschlossen wird -otr.close.session.on.contact.off = OTR Sitzung schließen, wenn Kontakt sich abmeldet -otr.key.not.verified.title = Schlüssel nicht beglaubigt -otr.question.verify = Beglaubigen? -otr.key.not.verified.text = Folgender Schlüssel ist nicht beglaubigt: -otr.start.session.with = OTR Sitzung mit {0} -otr.chat.button.tooltip = Nachrichtenverschlüsselung -otr.not.enabled = Sie haben eine OTR Anfrage empfagen. Sie sollten OTR in den Einstellungen aktivieren. -otr.chat.is.still.encrypted = OTR Sitzung aktiv. Nachrichten werden verschlüsselt. -#Table Columns -otr.table.jid = Kontakt -otr.table.public.key = Öffentlicher Schlüssel -otr.key.verified = Beglaubigt - - -#OTR Panel in Chat -otr.retry = Wiederholen -otr.try.to.connect.for.seconds = Versuche eine OTR Sitzung aufzubauen. {0}s verbleibend... -otr.failed.to.establish = Fehler beim erstellen der Sitzung. Zeit abgelaufen. -otr.successfull = Sitzung erfolgreich erstellt. Nachrichten werden jetzt verschlüsselt. -otr.disconnected = Sitzung geschlossen. Nachrichten sind ab jetzt nicht mehr verschlüsselt! \ No newline at end of file diff --git a/src/plugins/otr/src/resources/i18n/otrplugin_i18n_fr.properties b/src/plugins/otr/src/resources/i18n/otrplugin_i18n_fr.properties deleted file mode 100644 index 9c9a49c4b..000000000 --- a/src/plugins/otr/src/resources/i18n/otrplugin_i18n_fr.properties +++ /dev/null @@ -1,30 +0,0 @@ - -# OTR language file - -otr.title = OTR (Off-The-Record Messaging - Messages S\u00E9curis\u00E9s) -otr.list.entry = Messagerie S\u00E9curis\u00E9e OTR -otr.settings = R\u00E9glages de l'OTR -otr.enable = OTR Activ\u00E9 -current.priv.key = Cl\u00E9 priv\u00E9e actuelle: -renew.current.key = G\u00E9n\u00E9rer une nouvelle cl\u00E9 -otr.close.session.on.window.close = Terminer la session OTR quand la fen\u00EAtre de conversation est ferm\u00E9e -otr.close.session.on.contact.off = Terminer la session OTR quand le contact se d\u00E9connecte -otr.key.not.verified.title = Cl\u00E9 non v\u00E9rifi\u00E9e -otr.question.verify = V\u00E9rifier? -otr.key.not.verified.text = Cette cl\u00E9 n'est pas v\u00E9rifi\u00E9e! -otr.start.session.with = Session crypt\u00E9e par OTR avec {0} -otr.not.enabled = Vous avez reГ§u une demande de session crypt\u00E9e OTR. Vous devez activer l'OTR dans le menu Spark/Pr\u00E9f\u00E9rences/OTR. -otr.chat.is.still.encrypted = Cette conversation est toujours crypt\u00E9e. -otr.chat.button.tooltip = Chiffrement du message -#Table Columns -otr.table.jid = JID de l'utilisateur -otr.table.public.key = Cl\u00E9 publique -otr.key.verified = V\u00E9rifi\u00E9 - - -#OTR Panel in Chat -otr.retry = R\u00E9essayer -otr.try.to.connect.for.seconds = D\u00E9marrage d'une session chiffr\u00E9e OTR. {0}s restantes... -otr.failed.to.establish = Echec lors du d\u00E9marrage de la session OTR. Timeout. -otr.successfull = La session OTR a d\u00E9marr\u00E9 avec succГÐs. Les messages seront chiffr\u00E9s. -otr.disconnected = La session OTR a \u00E9t\u00E9 arr\u00EAt\u00E9e. Les messages ne seront plus chiffr\u00E9s. diff --git a/src/plugins/otr/src/resources/i18n/otrplugin_i18n_lt.properties b/src/plugins/otr/src/resources/i18n/otrplugin_i18n_lt.properties deleted file mode 100644 index 7b6e9d383..000000000 --- a/src/plugins/otr/src/resources/i18n/otrplugin_i18n_lt.properties +++ /dev/null @@ -1,30 +0,0 @@ - -# OTR language file - -otr.title = Konfidencialus (OTR) susira\u0161in\u0117jimas -otr.list.entry = OTR susira\u0161in\u0117jimas -otr.settings = OTR nustatymai -otr.enable = OTR \u012fjungtas -current.priv.key = Einamas privatus raktas: -renew.current.key = Generuoti nauj\u0105 rakt\u0105 -otr.close.session.on.window.close = U\u017ebaigti OTR sesij\u0105, kai u\u017edaromas pokalbio langas -otr.close.session.on.contact.off = U\u017ebaigti OTR sesij\u0105, kai adresatas atsijungia -otr.key.not.verified.title = Raktas nepatikrintas -otr.question.verify = Patikrinti? -otr.key.not.verified.text = Raktas n\u0117ra patikrintas! -otr.start.session.with = OTR u\u017e\u0161ifruota sesija su {0} -otr.not.enabled = J\u016bs gavote OTR u\u017eklaus\u0105. J\u016bs turite \u012fjungti OTR nustatymuose. -otr.chat.is.still.encrypted = \u0160is pokalbis vis dar yra u\u017e\u0161ifruotas. -otr.chat.button.tooltip = Pokalbio \u0161ifravimas -#Table Columns -otr.table.jid = Vartotojo JID -otr.table.public.key = Vie\u0161as raktas -otr.key.verified = Patikrintas - - -#OTR Panel in Chat -otr.retry = Pakartoti -otr.try.to.connect.for.seconds = Bandoma u\u017emegzti OTR sesij\u0105. {0} s liko... -otr.failed.to.establish = Nepavyko u\u017emegzti OTR sesijos. Baig\u0117si laikas. -otr.successfull = OTR sesija s\u0117kmingai u\u017emegzta. \u017Dinut\u0117s bus u\u017e\u0161ifruotos. -otr.disconnected = OTR sesija uzdaryta. \u017Dinut\u0117s daugiau nebus \u0161ifruojamos. \ No newline at end of file diff --git a/src/plugins/otr/src/resources/i18n/otrplugin_i18n_pl.properties b/src/plugins/otr/src/resources/i18n/otrplugin_i18n_pl.properties deleted file mode 100644 index c9332d10d..000000000 --- a/src/plugins/otr/src/resources/i18n/otrplugin_i18n_pl.properties +++ /dev/null @@ -1,30 +0,0 @@ - -# Plik jêzykowy Panelu OTR - -otr.title = Komunikacja szyfrowana -otr.list.entry = Szyfrowana komunikacja -otr.settings = Ustawienia OTR -otr.enable = OTR W\u0142\u0105czona -current.priv.key = Bie\u017C\u0105cy prywatny klucz: -renew.current.key = Generuj nowy klucz -otr.close.session.on.window.close = Zamknij sesj\u0119 OTR gdy okno rozmowy zostanie zamkni\u0119te -otr.close.session.on.contact.off = Zamknij sesj\u0119 OTR gdy kontakt si\u0119 wyloguje -otr.key.not.verified.title = Klucz niezweryfikowany -otr.question.verify = Zweryfikowa\u0107? -otr.key.not.verified.text = Podany klucz nie zosta\u0142 zweryfikowany! -otr.start.session.with = Szyfrowana sesja OTR z {0} -otr.not.enabled = Otrzyma\u0142e\u015B \u017C\u0105danie szyfrowanej sesji OTR. W\u0142\u0105cz szyfrowan\u0105 komunikacj\u0119 OTR w ustawieniach. -otr.chat.is.still.encrypted = Rozmowa jest wci\u0105\u017C szyfrowana. -otr.chat.button.tooltip = Wiadomo\u015B\u0107 szyfrowana - -#Kolumny tabeli -otr.table.jid = JID u\u017Cytkownika -otr.table.public.key = Klucz publiczny -otr.key.verified = Zweryfikowany klucz - -#OTR Panel w rozmowie -otr.retry = Pon\u00F3w -otr.try.to.connect.for.seconds = Pr\u00F3buj\u0119 ustanowi\u0107 sesj\u0119 OTR. Pozosta\u0142o {0}s ... -otr.failed.to.establish = Nie ustanowiono sesji OTR. Przekroczono czas. -otr.successfull = Ustanowiono sesj\u0119 szyfrowan\u0105 OTR. Wiadomo\u015Bci b\u0119d\u0105 szyfrowane. -otr.disconnected = Sesja szyfrowana OTR zosta\u0142a zamkni\u0119ta. Wiadomo\u015Bci nie b\u0119d\u0105 szyfrowane. \ No newline at end of file diff --git a/src/plugins/otr/src/resources/i18n/otrplugin_i18n_zh_TW.properties b/src/plugins/otr/src/resources/i18n/otrplugin_i18n_zh_TW.properties deleted file mode 100644 index 94b05d89e..000000000 --- a/src/plugins/otr/src/resources/i18n/otrplugin_i18n_zh_TW.properties +++ /dev/null @@ -1,30 +0,0 @@ - -# OTR language file - -otr.title = \u52a0\u5bc6\u8a0a\u606f -otr.list.entry = \u52a0\u5bc6\u8a0a\u606f -otr.settings = \u52a0\u5bc6\u8a0a\u606f\u8a2d\u5b9a -otr.enable = \u555f\u52d5\u52a0\u5bc6\u529f\u80fd -current.priv.key = \u76ee\u524d\u79c1\u9470: -renew.current.key = \u7522\u751f\u4e00\u500b\u65b0\u7684\u79c1\u9470 -otr.close.session.on.window.close = \u7576\u804a\u5929\u8996\u7a97\u95dc\u9589\u6642,\u95dc\u9589\u52a0\u5bc6\u6703\u8b70 -otr.close.session.on.contact.off = \u7576\u806f\u7d61\u4eba\u96e2\u7dda\u6642,\u95dc\u9589\u52a0\u5bc6\u6703\u8b70 -otr.key.not.verified.title = \u79c1\u9470\u672a\u9a57\u8b49 -otr.question.verify = \u662f\u5426\u9a57\u8b49? -otr.key.not.verified.text = \u4ee5\u4e0b\u79c1\u9470\u672a\u9a57\u8b49! -otr.start.session.with = \u8207 {0} \u9032\u884c\u4e0d\u516c\u958b\u7684\u52a0\u5bc6\u6703\u8b70 -otr.not.enabled = \u60a8\u6536\u5230\u4e00\u500b\u662f\u5426\u52a0\u5bc6\u7684\u8a62\u554f. \u60a8\u61c9\u8a72\u5728\u8a2d\u5b9a\u4e2d\u555f\u52d5\u52a0\u5bc6\u529f\u80fd. -otr.chat.is.still.encrypted = \u9019\u500b\u5c0d\u8a71\u76ee\u524d\u4ecd\u5728\u52a0\u5bc6\u72c0\u614b. -otr.chat.button.tooltip = \u8a0a\u606f\u52a0\u5bc6 -#Table Columns -otr.table.jid = \u806f\u7d61\u4eba\u7684 JID -otr.table.public.key = \u516c\u9470 -otr.key.verified = \u9a57\u8b49 - - -#OTR Panel in Chat -otr.retry = \u91cd\u8a66 -otr.try.to.connect.for.seconds = \u5617\u8a66\u5efa\u7acb\u4e00\u500b\u52a0\u5bc6\u6703\u8b70. \u5269\u4e0b {0}\u79d2 ... -otr.failed.to.establish = \u7121\u6cd5\u5efa\u7acb\u52a0\u5bc6\u6703\u8b70. \u5efa\u7acb\u6642\u9593\u903e\u6642. -otr.successfull = \u6210\u529f\u5efa\u7acb\u52a0\u5bc6\u72c0\u614b. \u8a0a\u606f\u5c07\u88ab\u52a0\u5bc6. -otr.disconnected = \u95dc\u9589\u52a0\u5bc6\u6703\u8b70. \u8a0a\u606f\u4e0d\u5728\u52a0\u5bc6\u72c0\u614b. \ No newline at end of file diff --git a/src/plugins/otr/src/resources/otr_on.png b/src/plugins/otr/src/resources/otr_on.png deleted file mode 100644 index 5f7b79ea1..000000000 Binary files a/src/plugins/otr/src/resources/otr_on.png and /dev/null differ diff --git a/src/plugins/otr/src/resources/otr_pref.png b/src/plugins/otr/src/resources/otr_pref.png deleted file mode 100644 index a8d18a590..000000000 Binary files a/src/plugins/otr/src/resources/otr_pref.png and /dev/null differ diff --git a/src/plugins/reversi/Reversi.ipr b/src/plugins/reversi/Reversi.ipr deleted file mode 100644 index bb2d8bffa..000000000 --- a/src/plugins/reversi/Reversi.ipr +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/reversi/ReversiPlugin.iml b/src/plugins/reversi/ReversiPlugin.iml deleted file mode 100644 index 288c6b4e2..000000000 --- a/src/plugins/reversi/ReversiPlugin.iml +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/reversi/build/build.xml b/src/plugins/reversi/build/build.xml deleted file mode 100644 index 84ea39d80..000000000 --- a/src/plugins/reversi/build/build.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/reversi/plugin.xml b/src/plugins/reversi/plugin.xml deleted file mode 100644 index 9c48d69aa..000000000 --- a/src/plugins/reversi/plugin.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - Reversi - 1.3 - Matt Tucker, Bill Lynch, Holger Bergunde - http://www.jivesoftware.org - plugins@jivesoftware.org - Multiplayer game of Reversi - org.jivesoftware.game.reversi.ReversiPlugin - 2.7.0 - 1.7.0 - - diff --git a/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/GameForfeit.java b/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/GameForfeit.java deleted file mode 100644 index 63851a88c..000000000 --- a/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/GameForfeit.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.game.reversi; - -import org.jivesoftware.smack.packet.ExtensionElement; - -/** - * A packet extension sent to indicate that the player forfeits the game. - */ -public class GameForfeit implements ExtensionElement { - - public static final String ELEMENT_NAME = "reversi-forfeit"; - public static final String NAMESPACE = "http://jivesoftware.org/protocol/game/reversi"; - - private int gameID; - - public String getElementName() { - return ELEMENT_NAME; - } - - public String getNamespace() { - return NAMESPACE; - } - - public String toXML() { - StringBuffer buf = new StringBuffer(); - buf.append("<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">"); - buf.append("").append(gameID).append(""); - buf.append(""); - return buf.toString(); - } - - /** - * Returns the game ID that this forfeit pertains to. - * - * @return the game ID. - */ - public int getGameID() { - return gameID; - } - - /** - * Sets the game ID that this forfeit pertains to. - * - * @param gameID the game ID. - */ - public void setGameID(int gameID) { - this.gameID = gameID; - } -} \ No newline at end of file diff --git a/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/GameMove.java b/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/GameMove.java deleted file mode 100644 index 5c551b668..000000000 --- a/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/GameMove.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.game.reversi; - -import org.jivesoftware.smack.packet.ExtensionElement; - -/** - * A packet extension that represents an individual game move. Each move is simply an integer - * indicating the position on the board the user wishes to place their stone. It's assumed that - * both players maintain their own copy of the game model and only send valid moves. If an - * invalid move is received from the opponent, the player should immediately terminate the game.

        - * - * The game board is 64 squares; see {@link ReversiModel} for full details. - * - * @author Matt Tucker - */ -public class GameMove implements ExtensionElement { - - public static final String ELEMENT_NAME = "reversi-move"; - public static final String NAMESPACE = "http://jivesoftware.org/protocol/game/reversi"; - - private int gameID; - private int position; - - public String getElementName() { - return ELEMENT_NAME; - } - - public String getNamespace() { - return NAMESPACE; - } - - public String toXML() { - StringBuffer buf = new StringBuffer(); - buf.append("<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">"); - buf.append("").append(gameID).append(""); - buf.append("").append(position).append(""); - buf.append(""); - return buf.toString(); - } - - /** - * Returns the game ID that this move pertains to. - * - * @return the game ID. - */ - public int getGameID() { - return gameID; - } - - /** - * Sets the game ID that this move pertains to. - * - * @param gameID the game ID. - */ - public void setGameID(int gameID) { - this.gameID = gameID; - } - - /** - * Returns the move position; an integer between 0 and 63. - * - * @return the move position. - */ - public int getPosition() { - return position; - } - - /** - * Sets the move position; an integer between 0 and 63. - * - * @param position the move position. - */ - public void setPosition(int position) { - if (position < 0 || position > 63) { - throw new IllegalArgumentException("Position " + position + " invalid; must be between 0 and 63."); - } - this.position = position; - } -} diff --git a/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/GameOffer.java b/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/GameOffer.java deleted file mode 100644 index bbe82c6a1..000000000 --- a/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/GameOffer.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.game.reversi; - -import org.jivesoftware.smack.packet.IQ; - -import java.util.Random; - -/** - * An IQ packet that's an offer to start a new Reversi game. The offer indicates whether the player - * making the offer will be the starting player (black). The starting player is selected randomly - * by default, which is recommended. - * - * @author Matt Tucker - */ -public class GameOffer extends IQ { - - public static final String ELEMENT_NAME = "reversi"; - public static final String NAMESPACE = "http://jivesoftware.org/protocol/game/reversi"; - - private static Random random = new Random(); - private int gameID; - - private boolean startingPlayer; - - /** - * Constructs a new game offer with a random game ID and random value for the starting player. - */ - public GameOffer() { - super(); - // Randomly choose if the user making the game offer will be the starting player (black). - startingPlayer = random.nextBoolean(); - gameID = Math.abs(random.nextInt()); - } - - /** - * Returns the game ID. - * - * @return the game ID. - */ - public int getGameID() { - return gameID; - } - - /** - * Sets the game ID. - * - * @param gameID the game ID. - */ - public void setGameID(int gameID) { - this.gameID = gameID; - } - - /** - * Returns true if the user making the game invitation is the starting player. - * - * @return true if the user making the game invite is the starting player. - */ - public boolean isStartingPlayer() { - return startingPlayer; - } - - /** - * Sets whether the user making the game invitation is the starting player. - * - * @param startingPlayer true if the user making the game invite is the starting player. - */ - public void setStartingPlayer(boolean startingPlayer) { - this.startingPlayer = startingPlayer; - } - - public String getChildElementXML() { - StringBuffer buf = new StringBuffer(); - buf.append("<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">"); - if (getType() == IQ.Type.get) { - buf.append("").append(gameID).append(""); - buf.append("").append(startingPlayer).append(""); - buf.append(getExtensionsXML()); - } - buf.append(""); - return buf.toString(); - } -} diff --git a/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/ReversiPanel.java b/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/ReversiPanel.java deleted file mode 100644 index 9beaf4003..000000000 --- a/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/ReversiPanel.java +++ /dev/null @@ -1,370 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.game.reversi; - -import javax.swing.*; - -import java.util.*; -import java.util.List; -import java.awt.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.StanzaListener; -import org.jivesoftware.smack.filter.PacketExtensionFilter; -import org.jivesoftware.smack.packet.DefaultExtensionElement; -import org.jivesoftware.smack.packet.Stanza; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.spark.util.log.Log; - -/** - * The game UI, which is created after both players have accepted a new game. - * - * @author Bill Lynch - */ -public class ReversiPanel extends JPanel { - - private static final long serialVersionUID = 3591458286918924065L; - private static final int BOARD_SIZE = 320; - private static final int INFO_PANEL_HEIGHT = 50; - private static final int BORDER_SIZE = 5; - public static final int TOTAL_WIDTH = BOARD_SIZE + (BORDER_SIZE*2); - public static final int TOTAL_HEIGHT = TOTAL_WIDTH + INFO_PANEL_HEIGHT; // frame width + 50 for the info panel - private static final int NUM_BLOCKS = 8; - private static final int BLOCK_SIZE = BOARD_SIZE/NUM_BLOCKS; - - private static final int DISC_SIZE = (int)(BLOCK_SIZE*0.8); // 80% of block size - - private XMPPConnection connection; - private int otherPlayer; - private int gameID; - private String opponentJID; - private StanzaListener gameMoveListener; - - private List blocks = new ArrayList(); - // Main game object - private ReversiModel reversi; - - // All images used by the game. - - ImageIcon imageIcon = ReversiRes.getImageIcon(ReversiRes.REVERSI_ICON); - - private Image imageBackground = ReversiRes.getImageIcon(ReversiRes.REVERSI_BOARD).getImage(); - private Image imageScoreWhite = ReversiRes.getImageIcon(ReversiRes.REVERSI_SCORE_WHITE).getImage(); - private Image imageScoreBlack = ReversiRes.getImageIcon(ReversiRes.REVERSI_SCORE_BLACK).getImage(); - private Image imageTurnBlack = ReversiRes.getImageIcon(ReversiRes.REVERSI_LABEL_BLACK).getImage(); - private Image imageTurnWhite = ReversiRes.getImageIcon(ReversiRes.REVERSI_LABEL_WHITE).getImage(); - private Image imageButtonResign = ReversiRes.getImageIcon(ReversiRes.REVERSI_RESIGN).getImage(); - private Image imageYou = ReversiRes.getImageIcon(ReversiRes.REVERSI_YOU).getImage(); - private Image imageThem = ReversiRes.getImageIcon(ReversiRes.REVERSI_THEM).getImage(); - - /** - * Creates a new Reversi panel. - * - * @param connection Connection associated. - * @param gameID Game ID number - * @param startingPlayer Whether we are the starting player or not - * @param opponentJID JID of opponent - */ - public ReversiPanel(XMPPConnection connection, final int gameID, boolean startingPlayer, String opponentJID) { - this.connection = connection; - this.gameID = gameID; - this.opponentJID = opponentJID; - otherPlayer = startingPlayer? ReversiModel.WHITE : ReversiModel.BLACK; - - // Load all images. - - // Start the game - reversi = new ReversiModel(); - - if (connection != null) { - gameMoveListener = new StanzaListener() { - public void processPacket(Stanza stanza) { - GameMove move = (GameMove)stanza.getExtension(GameMove.ELEMENT_NAME, GameMove.NAMESPACE); - // If this is a move for the current game. - if (move.getGameID() == gameID) { - int position = move.getPosition(); - // Make sure that the other player is allowed to make the move right now. - if (reversi.getCurrentPlayer() == otherPlayer && reversi.isValidMove(position)) { - reversi.makeMove(position); - // Redraw board. - ReversiPanel.this.repaint(); - } - else { - // TODO: other user automatically forfeits! - } - // Execute move. - } - } - }; - - connection.addAsyncStanzaListener(gameMoveListener, new PacketExtensionFilter(GameMove.ELEMENT_NAME, - GameMove.NAMESPACE)); - // TODO: at end of game, remove listener. - } - - setOpaque(false); - - // Use absolute layout - setLayout(null); - // Set its size: - setPreferredSize(new Dimension(TOTAL_WIDTH, TOTAL_HEIGHT)); - - // Make a new panel which is the game board grid: - JPanel reversiBoard = new JPanel(new GridLayout(NUM_BLOCKS,NUM_BLOCKS,0,0)); - reversiBoard.setOpaque(false); - for (int i=0; i reversi.getWhiteScore()) - { - if (me == ReversiModel.BLACK) - whoWins = "YOU WIN!"; - else - whoWins = "YOU LOST!"; - } else if(reversi.getBlackScore() < reversi.getWhiteScore()) - { - if (me == ReversiModel.WHITE) - whoWins = "YOU WIN!"; - else - whoWins = "YOU LOST!"; - } - g.drawString(whoWins, 130, BOARD_SIZE + BORDER_SIZE*2 + 20); - } - if (reversi.getCurrentPlayer() == otherPlayer) { - g.drawImage(imageThem, 163, BOARD_SIZE + BORDER_SIZE*2 + 31, null); - } - else { - g.drawImage(imageYou, 163, BOARD_SIZE + BORDER_SIZE*2 + 31, null); - } - - // The resign button. - g.drawImage(imageButtonResign, 281, BOARD_SIZE + BORDER_SIZE*2 + 17, null); - } - - /** - * A Reversi block (one of the squares of the grid). - */ - public class ReversiBlock extends JPanel { - - private static final long serialVersionUID = -8504469339731900770L; - private ReversiPanel ui; - private int index; - - public ReversiBlock(ReversiPanel ui, int index) { - super(); - this.ui = ui; - this.index = index; - setPreferredSize(new Dimension(BLOCK_SIZE,BLOCK_SIZE)); - addMouseListener(new ReversiBlockMouseListener(this)); - setOpaque(false); - } - - /** - * Returns a handle on the game UI. - * - * @return ReversiPanel of block. - */ - public ReversiPanel getReversiUI() { - return ui; - } - - /** - * This block's index (0->63). - * - * @return Index of block - */ - public int getIndex() { - return index; - } - - protected void paintComponent(Graphics g) { - super.paintComponent(g); - - // Turn on anti-aliasing: - ((Graphics2D)g).setRenderingHint( - RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON - ); - - // Draw a disc in the block if the game says we should. - int boardValue = reversi.getBoardValue(index); - if (boardValue == org.jivesoftware.game.reversi.ReversiModel.BLACK) { - drawDisc(g, Color.BLACK); - } - else if (reversi.getBoardValue(index) == org.jivesoftware.game.reversi.ReversiModel.WHITE) { - drawDisc(g, Color.WHITE); - } - } - - /** - * Draws the disc. - * - * @param g Graphics to draw - * @param color Color - */ - private void drawDisc(Graphics g, Color color) { - int position = BLOCK_SIZE - ((BLOCK_SIZE+DISC_SIZE)/2); - g.setColor(color); - g.fillOval(position, position, DISC_SIZE, DISC_SIZE); - } - } - - /** - * A mouse listener for a Reversi block. - */ - public class ReversiBlockMouseListener extends MouseAdapter { - - private ReversiBlock block; - - public ReversiBlockMouseListener(ReversiBlock block) { - this.block = block; - } - - /** - * Highlight the block if this block is a valid move. - */ - public void mouseEntered(MouseEvent e) { - super.mouseEntered(e); - if (reversi.getCurrentPlayer() != otherPlayer && reversi.isValidMove(block.getIndex())) - { - block.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - block.setBorder(BorderFactory.createLineBorder(Color.WHITE)); - } - } - - /** - * Set the block color back to the default. - */ - public void mouseExited(MouseEvent e) { - super.mouseExited(e); - block.setCursor(Cursor.getDefaultCursor()); - block.setBorder(null); - } - - /** - * If the click box is a valid move, register a move in this box. - */ - public void mouseClicked(MouseEvent e) { - super.mouseClicked(e); - // Make sure that it's our turn and that it's a valid move. - if (reversi.getCurrentPlayer() != otherPlayer && reversi.isValidMove(block.getIndex())) - { - // Update the game model. - reversi.makeMove(block.getIndex()); - - // Send the move to the other player. - Message message = new Message(opponentJID); - GameMove move = new GameMove(); - move.setGameID(gameID); - move.setPosition(block.getIndex()); - message.addExtension(move); - try - { - connection.sendStanza(message); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to send move to " + message.getTo(), e1 ); - } - - // Repaint board. - ReversiPanel.this.repaint(); - - // Repaint all blocks. -// for (Iterator it = block.getReversiUI().getBlocks().iterator(); it.hasNext();) { -// ReversiBlock component = (ReversiBlock)it.next(); -// component.repaint(); -// } - - } - } - } - - public List getBlocks() { - return blocks; - } -} diff --git a/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/ReversiPlugin.java b/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/ReversiPlugin.java deleted file mode 100644 index 12392cee5..000000000 --- a/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/ReversiPlugin.java +++ /dev/null @@ -1,419 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.game.reversi; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Image; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.concurrent.ConcurrentHashMap; - -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JSplitPane; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.StanzaListener; -import org.jivesoftware.smack.filter.PacketIDFilter; -import org.jivesoftware.smack.filter.StanzaIdFilter; -import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.packet.Stanza; -import org.jivesoftware.smack.provider.ProviderManager; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.BackgroundPanel; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomButton; -import org.jivesoftware.spark.ui.ChatRoomListener; -import org.jivesoftware.spark.ui.ChatRoomListenerAdapter; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; - -/** - * Reversi plugin. Reversi is a two-player, turn-based game. See - * {@link ReversiModel} for more details on how the game works. - * - * @author Matt Tucker - * @author Bill Lynch - */ -public class ReversiPlugin implements Plugin { - - private ChatRoomListener chatRoomListener; - private StanzaListener gameOfferListener; - - private ConcurrentHashMap gameOffers; - private ConcurrentHashMap gameInvitations; - - private JPanel inviteAlert; - - public void initialize() { - // Offers and invitations hold all pending game offers we've sent to - // other users or incoming - // invitations. The map key is always the opponent's JID. The map value - // is a transcript alert - // UI component. - gameOffers = new ConcurrentHashMap(); - gameInvitations = new ConcurrentHashMap(); - - // Add Reversi item to chat toolbar. - addToolbarButton(); - - // Add Smack providers. The plugin uses custom XMPP extensions to - // communicate game offers - // and current game state. Adding the Smack providers lets us use the - // custom protocol. - ProviderManager.addIQProvider(GameOffer.ELEMENT_NAME, GameOffer.NAMESPACE, GameOffer.class); - ProviderManager.addExtensionProvider(GameMove.ELEMENT_NAME, GameMove.NAMESPACE, GameMove.class); - ProviderManager.addExtensionProvider(GameForfeit.ELEMENT_NAME, GameForfeit.NAMESPACE, GameForfeit.class); - - // Add IQ listener to listen for incoming game invitations. - gameOfferListener = new StanzaListener() { - public void processPacket(Stanza stanza) { - GameOffer invitation = (GameOffer) stanza; - if (invitation.getType() == IQ.Type.get) { - showInvitationAlert(invitation); - } else if (invitation.getType() == IQ.Type.error) { - handleErrorIQ(invitation); - } - } - }; - SparkManager.getConnection().addAsyncStanzaListener(gameOfferListener, new StanzaTypeFilter(GameOffer.class)); - } - - public void shutdown() { - // Remove Reversi button from chat toolbar. - removeToolbarButton(); - // Remove IQ listener - SparkManager.getConnection().removeAsyncStanzaListener(gameOfferListener); -// -// // See if there are any pending offers or invitations. If so, cancel -// // them. -// for (Iterator i = gameOffers.keySet().iterator(); i.hasNext();i.next()) { -// System.out.println("gameoffer"); -// -// } -// System.out.println(gameInvitations.size()); -// for (Iterator i = gameInvitations.keySet().iterator(); i.hasNext(); i.next()) { -// -// } - gameOffers.clear(); - gameInvitations.clear(); - - // Remove Smack providers. - ProviderManager.removeIQProvider(GameOffer.ELEMENT_NAME, GameOffer.NAMESPACE); - ProviderManager.removeExtensionProvider(GameMove.ELEMENT_NAME, GameMove.NAMESPACE); - ProviderManager.removeExtensionProvider(GameForfeit.ELEMENT_NAME, GameForfeit.NAMESPACE); - } - - public boolean canShutDown() { - // The plugin is able to fully clean itself up, so return true. - return true; - } - - public void uninstall() { - // Do nothing. Reversi has no permanent resources so shutdown can - // already do a full cleanup. - } - - /** - * Display an alert that allows the user to accept or reject a game - * invitation. - * - * @param invitation - * the game invitation. - */ - private void showInvitationAlert(final GameOffer invitation) { - // Got an offer to start a new game. So, make sure that a chat is - // started with the other - // user and show an invite panel. - final ChatRoom room = SparkManager.getChatManager().getChatRoom( XmppStringUtils.parseBareJid(invitation.getFrom()) ); - - inviteAlert = new JPanel(); - inviteAlert.setLayout(new BorderLayout()); - - JPanel invitePanel = new JPanel() { - private static final long serialVersionUID = 5942001917654498678L; - - protected void paintComponent(Graphics g) { - ImageIcon imageIcon = ReversiRes.getImageIcon(ReversiRes.REVERSI_ICON); - Image image = imageIcon.getImage(); - g.drawImage(image, 0, 0, null); - } - }; - invitePanel.setPreferredSize(new Dimension(24, 24)); - inviteAlert.add(invitePanel, BorderLayout.WEST); - JPanel content = new JPanel(new BorderLayout()); - String opponentName = invitation.getFrom(); // TODO: convert to more - // readable name. - content.add(new JLabel(opponentName + " is requesting a Reversi game ..."), BorderLayout.CENTER); - JPanel buttonPanel = new JPanel(); - - // The accept button. When clicked, accept the game offer. - final JButton acceptButton = new JButton("Accept"); - final JButton declineButton = new JButton("Decline"); - - acceptButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - // Accept the game offer by sending a positive reply packet. - GameOffer reply = new GameOffer(); - reply.setTo(invitation.getFrom()); - reply.setStanzaId(invitation.getStanzaId()); - reply.setType(IQ.Type.result); - try - { - SparkManager.getConnection().sendStanza(reply); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to accept game offer from " + invitation.getFrom(), e1 ); - } - - // Hide the response panel. TODO: make this work. - room.getTranscriptWindow().remove(inviteAlert); - inviteAlert.remove(1); - inviteAlert.add(new JLabel("Starting game..."), BorderLayout.CENTER); - declineButton.setEnabled(false); - acceptButton.setEnabled(false); - // Remove the invitation from the map. - gameInvitations.remove(invitation.getFrom()); - // Show the game board. - showReversiBoard(invitation.getGameID(), room, !invitation.isStartingPlayer(), invitation.getFrom()); - } - }); - buttonPanel.add(acceptButton); - - // The decline button. When clicked, reject the game offer. - - declineButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - // Reject the game offer by sending an error packet. - GameOffer reply = new GameOffer(); - reply.setTo(invitation.getFrom()); - reply.setStanzaId(invitation.getPacketID()); - reply.setType(IQ.Type.error); - try - { - SparkManager.getConnection().sendStanza(reply); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to decline game offer from " + invitation.getFrom(), e1 ); - } - - // Hide the response panel. TODO: make this work. - room.getTranscriptWindow().remove(inviteAlert); - - declineButton.setVisible(false); - acceptButton.setVisible(false); - // Remove the invitation from the map. - gameInvitations.remove(invitation.getFrom()); - } - }); - buttonPanel.add(declineButton); - content.add(buttonPanel, BorderLayout.SOUTH); - inviteAlert.add(content, BorderLayout.CENTER); - - // Add the invitation to the Map of invites. If there's a pending - // invite, remove it - // before adding the new one (possible if the opponent sends two invites - // in a row). - Object oldInvitation = gameInvitations.put(invitation.getFrom(), inviteAlert); - if (oldInvitation != null) { - // TODO: clean it up by removing it from the transcript window. - } - - // Add the response panel to the transcript window. - room.getTranscriptWindow().addComponent(inviteAlert); - } - - private void handleErrorIQ(final GameOffer invitation) { - // Maybe the initiator canceled the game offer, lets check that - if (gameInvitations.containsKey(invitation.getFrom())) { - inviteAlert.remove(1); - JLabel userCanceled = new JLabel("The other player rejected the game invitation"); - inviteAlert.add(userCanceled); - gameInvitations.remove(invitation.getFrom()); - } - } - - /** - * Adds the Reversi toolbar button. - */ - private void addToolbarButton() { - ChatManager manager = SparkManager.getChatManager(); - chatRoomListener = new ChatRoomListenerAdapter() { - - ImageIcon icon = ReversiRes.getImageIcon(ReversiRes.REVERSI_ICON); - - public void chatRoomOpened(final ChatRoom room) { - if(!(room instanceof ChatRoomImpl)) - { - // Don't do anything if this is not a 1on1-Chat - return; - } - ChatRoomButton button = new ChatRoomButton(icon); - button.setToolTipText("Reversi"); - room.getToolBar().addChatRoomButton(button); - - // Add a button listener that sends out a game invite on a user - // click. - button.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - // Show "requesting a game panel" - final JPanel request = new JPanel(); - request.setLayout(new BorderLayout()); - JPanel requestPanel = new JPanel() { - private static final long serialVersionUID = 4490592207923738251L; - - protected void paintComponent(Graphics g) { - g.drawImage(icon.getImage(), 0, 0, null); - } - }; - requestPanel.setPreferredSize(new Dimension(24, 24)); - request.add(requestPanel, BorderLayout.WEST); - - String opponentJID = ((ChatRoomImpl) room).getJID(); - String opponentName = "[" + opponentJID + "]"; // TODO: - // convert - // to - // more - // readable - // name. - - final JPanel content = new JPanel(new BorderLayout()); - final JLabel label = new JLabel("Requesting a Reversi game with " + opponentName + ", please wait..."); - content.add(label, BorderLayout.CENTER); - JPanel buttonPanel = new JPanel(); - final JButton cancelButton = new JButton("Cancel"); - cancelButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - GameOffer reply = new GameOffer(); - reply.setTo(((ChatRoomImpl) room).getJID()); - reply.setType(IQ.Type.error); - try - { - SparkManager.getConnection().sendStanza(reply); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to send invitation cancellation to " + reply.getTo(), e1 ); - } - cancelButton.setText("Canceled"); - cancelButton.setEnabled(false); - } - }); - buttonPanel.add(cancelButton, BorderLayout.SOUTH); - content.add(buttonPanel, BorderLayout.SOUTH); - request.add(content, BorderLayout.CENTER); - room.getTranscriptWindow().addComponent(request); - - final GameOffer offer = new GameOffer(); - offer.setTo(opponentJID); - - // Add a listener for a reply to our offer. - SparkManager.getConnection().addAsyncStanzaListener(new StanzaListener() { - public void processPacket(Stanza stanza) { - GameOffer offerReply = ((GameOffer) stanza); - - if (offerReply.getType() == IQ.Type.result) { - // Remove the offer panel - room.getTranscriptWindow().remove(request); - content.remove(1); - label.setText("Starting game..."); - // Show game board (using original offer!). - showReversiBoard(offer.getGameID(), room, offer.isStartingPlayer(), offerReply.getFrom()); - } else if (offerReply.getType() == IQ.Type.error) { - cancelButton.setVisible(false); - JPanel userDeclinedPanel = new JPanel(new BorderLayout()); - JLabel userDeclined = new JLabel("User declined..."); - userDeclinedPanel.add(userDeclined, BorderLayout.SOUTH); - request.add(userDeclinedPanel, BorderLayout.SOUTH); - } - // TODO: Handle error case - } - }, new StanzaIdFilter(offer.getStanzaId())); - - try - { - SparkManager.getConnection().sendStanza(offer); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to send invitation to " + offer.getTo(), e1 ); - } - } - }); - - } - - public void chatRoomClosed(ChatRoom room) { - super.chatRoomClosed(room); - // TODO: if game is in progress, close it down. What we need is - // an API that lets us see - // TODO: if there's a transcript alert currently there. - } - }; - manager.addChatRoomListener(chatRoomListener); - } - - /** - * Displays the game board. This is called after an offer has been accepted - * or after accepting an invitation. - * - * @param gameID - * the game ID. - * @param room - * the chat room to display the game board in. - * @param startingPlayer - * true if this player is the starting player (black). - * @param opponentJID - * the opponent's JID. - */ - private void showReversiBoard(int gameID, ChatRoom room, boolean startingPlayer, String opponentJID) { - JSplitPane pane = room.getSplitPane(); - pane.setResizeWeight(1.0); - BackgroundPanel reversiBackground = new BackgroundPanel(); - reversiBackground.setLayout(new BorderLayout()); - reversiBackground.setOpaque(false); - ReversiPanel reversi = new ReversiPanel(SparkManager.getConnection(), gameID, startingPlayer, opponentJID); - reversiBackground.add(reversi, BorderLayout.CENTER); - pane.setRightComponent(reversiBackground); - reversi.setMinimumSize(new Dimension(ReversiPanel.TOTAL_WIDTH, ReversiPanel.TOTAL_HEIGHT)); - } - - /** - * Removes the Reversi toolbar button. - */ - private void removeToolbarButton() { - ChatManager manager = SparkManager.getChatManager(); - manager.removeChatRoomListener(chatRoomListener); - // TODO: remove actual buttons from toolbar. - } -} \ No newline at end of file diff --git a/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/ReversiRes.java b/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/ReversiRes.java deleted file mode 100644 index fac573e40..000000000 --- a/src/plugins/reversi/src/java/org/jivesoftware/game/reversi/ReversiRes.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.jivesoftware.game.reversi; - -import java.net.URL; -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; - -import javax.swing.ImageIcon; - -public class ReversiRes { - private static PropertyResourceBundle prb; - public static final String REVERSI_ICON = "REVERSI_ICON"; - public static final String REVERSI_BOARD="REVERSI_BOARD"; - public static final String REVERSI_SCORE_WHITE="REVERSI_SCORE_WHITE"; - public static final String REVERSI_SCORE_BLACK="REVERSI_SCORE_BLACK"; - public static final String REVERSI_LABEL_BLACK="REVERSI_LABEL_BLACK"; - public static final String REVERSI_LABEL_WHITE="REVERSI_LABEL_WHITE"; - public static final String REVERSI_RESIGN="REVERSI_RESIGN"; - public static final String REVERSI_YOU="REVERSI_YOU"; - public static final String REVERSI_THEM="REVERSI_THEM"; - - - - private ReversiRes() { - - } - - static ClassLoader cl = ReversiRes.class.getClassLoader(); - - static { - ReversiRes.prb = (PropertyResourceBundle) ResourceBundle.getBundle("reversi"); - } - - public static final String getString(String propertyName) { - return ReversiRes.prb.getString(propertyName); - } - - public static final ImageIcon getImageIcon(String imageName) { - try { - final String iconURI = ReversiRes.getString(imageName); - final URL imageURL = ReversiRes.cl.getResource(iconURI); - return new ImageIcon(imageURL); - } - catch (Exception ex) { - System.out.println(imageName + " not found."); - } - return null; - } - - public static final URL getURL(String propertyName) { - return ReversiRes.cl.getResource(ReversiRes.getString(propertyName)); - } - -} diff --git a/src/plugins/reversi/src/resources/images/button-resign.png b/src/plugins/reversi/src/resources/images/button-resign.png deleted file mode 100644 index 5bdf13ea7..000000000 Binary files a/src/plugins/reversi/src/resources/images/button-resign.png and /dev/null differ diff --git a/src/plugins/reversi/src/resources/images/reversi-board.png b/src/plugins/reversi/src/resources/images/reversi-board.png deleted file mode 100644 index fbfaa63b6..000000000 Binary files a/src/plugins/reversi/src/resources/images/reversi-board.png and /dev/null differ diff --git a/src/plugins/reversi/src/resources/images/reversi-icon.png b/src/plugins/reversi/src/resources/images/reversi-icon.png deleted file mode 100644 index 420a1d3cd..000000000 Binary files a/src/plugins/reversi/src/resources/images/reversi-icon.png and /dev/null differ diff --git a/src/plugins/reversi/src/resources/images/score-button-black.png b/src/plugins/reversi/src/resources/images/score-button-black.png deleted file mode 100644 index 4e526ee74..000000000 Binary files a/src/plugins/reversi/src/resources/images/score-button-black.png and /dev/null differ diff --git a/src/plugins/reversi/src/resources/images/score-button-white.png b/src/plugins/reversi/src/resources/images/score-button-white.png deleted file mode 100644 index f27955904..000000000 Binary files a/src/plugins/reversi/src/resources/images/score-button-white.png and /dev/null differ diff --git a/src/plugins/reversi/src/resources/images/them.png b/src/plugins/reversi/src/resources/images/them.png deleted file mode 100644 index 2a7aac78f..000000000 Binary files a/src/plugins/reversi/src/resources/images/them.png and /dev/null differ diff --git a/src/plugins/reversi/src/resources/images/turn-label-black.png b/src/plugins/reversi/src/resources/images/turn-label-black.png deleted file mode 100644 index 0dd29f155..000000000 Binary files a/src/plugins/reversi/src/resources/images/turn-label-black.png and /dev/null differ diff --git a/src/plugins/reversi/src/resources/images/turn-label-white.png b/src/plugins/reversi/src/resources/images/turn-label-white.png deleted file mode 100644 index ebb096fcc..000000000 Binary files a/src/plugins/reversi/src/resources/images/turn-label-white.png and /dev/null differ diff --git a/src/plugins/reversi/src/resources/images/you.png b/src/plugins/reversi/src/resources/images/you.png deleted file mode 100644 index 1996514b0..000000000 Binary files a/src/plugins/reversi/src/resources/images/you.png and /dev/null differ diff --git a/src/plugins/reversi/src/resources/reversi-board.psd b/src/plugins/reversi/src/resources/reversi-board.psd deleted file mode 100644 index 9252fb8f6..000000000 Binary files a/src/plugins/reversi/src/resources/reversi-board.psd and /dev/null differ diff --git a/src/plugins/reversi/src/resources/reversi-icon.psd b/src/plugins/reversi/src/resources/reversi-icon.psd deleted file mode 100644 index dac125474..000000000 Binary files a/src/plugins/reversi/src/resources/reversi-icon.psd and /dev/null differ diff --git a/src/plugins/roar/build/build.xml b/src/plugins/roar/build/build.xml deleted file mode 100644 index 381da741a..000000000 --- a/src/plugins/roar/build/build.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/roar/plugin.xml b/src/plugins/roar/plugin.xml deleted file mode 100644 index b405829bb..000000000 --- a/src/plugins/roar/plugin.xml +++ /dev/null @@ -1,12 +0,0 @@ - - Roar!!! - org.jivesoftware.spark.roar.Roar - Wolf Posdorfer - 0.4.1 - http://www.jivesoftware.com - Shows awesome Popups - 9posdorf@informatik.uni-hamburg.de - 2.7.0 - Windows,Linux,Mac - 1.7.0 - diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/RoarMessageListener.java b/src/plugins/roar/src/java/org/jivesoftware/spark/roar/RoarMessageListener.java deleted file mode 100644 index 0292b4bee..000000000 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/RoarMessageListener.java +++ /dev/null @@ -1,178 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.roar; - -import java.util.HashMap; - -import javax.swing.JFrame; - -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.roar.displaytype.PropertyBundle; -import org.jivesoftware.spark.roar.displaytype.RoarDisplayType; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomNotFoundException; -import org.jivesoftware.spark.ui.GlobalMessageListener; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.ui.rooms.GroupChatRoom; - -/** - * Message Listener
        - * - * @author wolf.posdorfer - * - */ -public class RoarMessageListener implements GlobalMessageListener { - - private RoarDisplayType _displaytype; - private RoarProperties _properties; - - private HashMap _rooms = new HashMap<>(); - - public RoarMessageListener() { - _displaytype = RoarProperties.getInstance().getDisplayTypeClass(); - _properties = RoarProperties.getInstance(); - } - - @Override - public void messageReceived(ChatRoom room, Message message) { - - try { - ChatRoom activeroom = SparkManager.getChatManager().getChatContainer().getActiveChatRoom(); - - int framestate = SparkManager.getChatManager().getChatContainer().getChatFrame().getState(); - - if (framestate == JFrame.NORMAL && activeroom.equals(room) && room.isShowing() - && (isOldGroupChat(room) || isMessageFromRoom(room, message))) { - // Do Nothing - } else { - decideForRoomAndMessage(room, message); - } - - } catch (ChatRoomNotFoundException e) { - // i dont care - } - - } - - private void decideForRoomAndMessage(ChatRoom room, Message message) { - if (doesMessageMatchKeywords(message)) { - _displaytype.messageReceived(room, message, isKeyWordDifferent() ? getKeywordBundle() : getSingleBundle()); - } else if (room instanceof ChatRoomImpl && !isSingleRoomDisabled()) { - _displaytype.messageReceived(room, message, getSingleBundle()); - } else if (room instanceof GroupChatRoom && !isMutliRoomDisabled()) { - _displaytype.messageReceived(room, message, isMultiRoomDifferent() ? getMultiBundle() : getSingleBundle()); - } - } - - private boolean doesMessageMatchKeywords(Message message) { - for (String keyword : _properties.getKeywords()) { - if (message.getBody().contains(keyword)) { - return true; - } - } - return false; - } - - private boolean isSingleRoomDisabled() - { - return _properties.getBoolean("roar.disable.single", false); - } - - private boolean isMutliRoomDisabled() - { - return _properties.getBoolean("group.disable", false); - } - - private boolean isKeyWordDifferent() - { - return _properties.getBoolean("keyword.different.enabled", false); - } - - private boolean isMultiRoomDifferent() - { - return _properties.getBoolean("group.different.enabled", false); - } - - private PropertyBundle getSingleBundle() { - return new PropertyBundle(_properties.getBackgroundColor(), _properties.getHeaderColor(), - _properties.getTextColor(), _properties.getDuration()); - } - - private PropertyBundle getMultiBundle() { - return new PropertyBundle( - _properties.getColor(RoarProperties.BACKGROUNDCOLOR_GROUP, _properties.getBackgroundColor()), - _properties.getColor(RoarProperties.HEADERCOLOR_GROUP, _properties.getHeaderColor()), - _properties.getColor(RoarProperties.TEXTCOLOR_GROUP, _properties.getTextColor()), - _properties.getInt("group.duration")); - } - private PropertyBundle getKeywordBundle() { - return new PropertyBundle( - _properties.getColor(RoarProperties.BACKGROUNDCOLOR_KEYWORD, _properties.getBackgroundColor()), - _properties.getColor(RoarProperties.HEADERCOLOR_KEYWORD, _properties.getHeaderColor()), - _properties.getColor(RoarProperties.TEXTCOLOR_KEYWORD, _properties.getTextColor()), - _properties.getInt("keyword.duration")); - } - - private boolean isOldGroupChat(ChatRoom room) { - - boolean result = false; - - if (room.getChatType() == Message.Type.groupchat) { - - if (_rooms.containsKey(room.getRoomname()) && _rooms.get(room.getRoomname()) == -1L) { - return true; - } - - if (!_rooms.containsKey(room.getRoomname())) { - _rooms.put(room.getRoomname(), System.currentTimeMillis()); - return true; - } else { - long start = _rooms.get(room.getRoomname()); - long now = System.currentTimeMillis(); - - result = (now - start) < 1500; - if (result) { - _rooms.put(room.getRoomname(), -1L); - } - - } - } - - return result; - } - - @Override - public void messageSent(ChatRoom room, Message message) { - _displaytype.messageSent(room, message); - } - - /** - * Check if the message comes directly from the room - * - * @param room - * @param message - * @return boolean - */ - private boolean isMessageFromRoom(ChatRoom room, Message message) { - return message.getFrom().equals(room.getRoomname()); - } - -} diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/RoarProperties.java b/src/plugins/roar/src/java/org/jivesoftware/spark/roar/RoarProperties.java deleted file mode 100644 index fd491785c..000000000 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/RoarProperties.java +++ /dev/null @@ -1,288 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.roar; - -import java.awt.Color; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Properties; - -import org.jivesoftware.Spark; -import org.jivesoftware.spark.roar.displaytype.BottomRight; -import org.jivesoftware.spark.roar.displaytype.SystemNotification; -import org.jivesoftware.spark.roar.displaytype.RoarDisplayType; -import org.jivesoftware.spark.roar.displaytype.SparkToasterHandler; -import org.jivesoftware.spark.roar.displaytype.TopRight; - -/** - * RoarProperties file stuff - * - * @author wolf.posdorfer - * - */ -public class RoarProperties { - private Properties props; - private File configFile; - - public static final String ACTIVE = "active"; - public static final String AMOUNT = "amount"; - public static final String ROARDISPLAYTYPE = "roardisplaytype"; - - public static final String BACKGROUNDCOLOR = "backgroundcolor"; - public static final String HEADERCOLOR = "headercolor"; - public static final String TEXTCOLOR = "textcolor"; - public static final String DURATION = "duration"; - - public static final String BACKGROUNDCOLOR_GROUP = "backgroundcolor.group"; - public static final String HEADERCOLOR_GROUP = "headercolor.group"; - public static final String TEXTCOLOR_GROUP = "textcolor.group"; - public static final String DURATION_GROUP = "duration.group"; - - public static final String BACKGROUNDCOLOR_KEYWORD = "backgroundcolor.keyword"; - public static final String HEADERCOLOR_KEYWORD = "headercolor.keyword"; - public static final String TEXTCOLOR_KEYWORD = "textcolor.keyword"; - public static final String DURATION_KEYWORD = "duration.keyword"; - - private static final Object LOCK = new Object(); - private static RoarProperties instance = null; - - private List keywords = null; - - private RoarDisplayType[] displayTypes = new RoarDisplayType[]{new TopRight(), new BottomRight(), new SparkToasterHandler(), new SystemNotification()}; - - - /** - * returns the Instance of this Properties file - * - * @return - */ - public static RoarProperties getInstance() { - synchronized (LOCK) { - if (instance == null) { - instance = new RoarProperties(); - } - return instance; - } - } - - private RoarProperties() { - this.props = new Properties(); - - try { - props.load(new FileInputStream(getConfigFile())); - } catch (IOException e) { - // Can't load ConfigFile - } - - } - - private File getConfigFile() { - if (configFile == null) - configFile = new File(Spark.getSparkUserHome(), "roar.properties"); - - return configFile; - } - - public void save() { - try { - props.store(new FileOutputStream(getConfigFile()), "Storing ROAR properties"); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public List getDisplayTypes() { - return Arrays.asList(displayTypes); - } - - public boolean getShowingPopups() { - return getBoolean(ACTIVE, false); - } - - public void setShowingPopups(boolean popups) { - setBoolean(ACTIVE, popups); - } - - public Color getBackgroundColor() { - return getColor(BACKGROUNDCOLOR, Color.BLACK); - } - - public void setBackgroundColor(Color c) { - setColor(BACKGROUNDCOLOR, c); - } - - public Color getHeaderColor() { - return getColor(HEADERCOLOR, Color.RED); - } - - public void setHeaderColor(Color c) { - setColor(HEADERCOLOR, c); - } - - public Color getTextColor() { - return getColor(TEXTCOLOR, Color.WHITE); - } - - public void setTextColor(Color c) { - setColor(TEXTCOLOR, c); - } - - public int getDuration() { - int dur = getInt(DURATION); - return dur < 0 ? 3000 : getInt(DURATION); - } - - public void setDuration(int dur) { - setInt(DURATION, dur); - } - - public int getMaximumPopups() { - return getInt(AMOUNT); - } - - public void setMaximumPopups(int amount) { - setInt(AMOUNT, amount); - } - - public void setDisplayType(String classstring) { - System.out.println("setting displaytype to: "+ classstring); - props.setProperty(ROARDISPLAYTYPE, classstring); - } - - public String getDisplayType() { - return props.getProperty(ROARDISPLAYTYPE, displayTypes[0].getName()); // TopRight is default - } - - public void setKeywords(String commaseparated) { - props.setProperty("keywords", commaseparated); - - String[] pkeys = props.getProperty("keywords").split(","); - if (pkeys.length > 0) { - keywords = Arrays.asList(pkeys); - } else { - keywords = Collections.emptyList(); - } - } - - /** - * Returns a cached version of the keywords, loads them from properties if it hasn't before. - */ - public List getKeywords() { - if (keywords == null) { - final String propertyValue = props.getProperty("keywords"); - if ( propertyValue != null ) - { - String[] pkeys = propertyValue.split( "," ); - if ( pkeys.length > 0 ) - { - keywords = Arrays.asList( pkeys ); - } - } - - if ( keywords == null ) { - keywords = Collections.emptyList(); - } - } - - return Collections.unmodifiableList(keywords); - } - - public RoarDisplayType getDisplayTypeClass() { - - String stringInProperty = getDisplayType(); - for (RoarDisplayType type : displayTypes) { - if (type.getName().equals(stringInProperty)) { - return type; - } - } - return displayTypes[0]; // TopRight is default - } - - // =============================================================================== - // =============================================================================== - // =============================================================================== - public boolean getBoolean(String property, boolean defaultValue) { - return Boolean.parseBoolean(props.getProperty(property, Boolean.toString(defaultValue))); - } - - public void setBoolean(String property, boolean value) { - props.setProperty(property, Boolean.toString(value)); - } - - public int getInt(String property) { - return Integer.parseInt(props.getProperty(property, "0")); - } - - public void setInt(String property, int integer) { - props.setProperty(property, "" + integer); - } - - public void setColor(String property, Color color) { - props.setProperty(property, convertColor(color)); - } - - public Color getColor(String property, Color defaultcolor) { - try { - return convertString(props.getProperty(property)); - } catch (Exception e) { - return defaultcolor; - } - - } - - public String getProperty(String property) { - return props.getProperty(property); - } - - public void setProperty(String property, String value) { - props.setProperty(property, value); - } - - /** - * Converts a {@link String} matching xxx,xxx,xxx to a {@link Color}
        - * where xxx is a number from 0 to 255 - * - * @param s - * @return - */ - public static Color convertString(String s) throws Exception { - String[] arr = s.split(","); - return new Color(Integer.parseInt(arr[0]), Integer.parseInt(arr[1]), Integer.parseInt(arr[2])); - - } - - /** - * Converts a {@link Color} to a {@link String} in this format:
        - * xxx,xxx,xxx
        - * where xxx is a number from 0 to 255 - * - * @param color - * @return - */ - public static String convertColor(Color color) { - return color.getRed() + "," + color.getGreen() + "," + color.getBlue(); - } - -} diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/RoarResources.java b/src/plugins/roar/src/java/org/jivesoftware/spark/roar/RoarResources.java deleted file mode 100644 index 52e921591..000000000 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/RoarResources.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.jivesoftware.spark.roar; - -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; - -import org.jivesoftware.spark.util.log.Log; - -public class RoarResources { - - private static PropertyResourceBundle prb; - - static ClassLoader cl = RoarResources.class.getClassLoader(); - - static { - prb = (PropertyResourceBundle) ResourceBundle.getBundle("i18n/roar_i18n"); - } - - public static final String getString(String propertyName) { - try { - return prb.getString(propertyName); - } catch (Exception e) { - Log.error(e); - return propertyName; - } - } - -} diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/MacNotificationCenter.java b/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/MacNotificationCenter.java deleted file mode 100644 index 184438d6e..000000000 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/MacNotificationCenter.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.jivesoftware.spark.roar.displaytype; - -import java.io.File; - -import org.jivesoftware.Spark; - -import com.sun.jna.Library; -import com.sun.jna.Native; - -/** - * Provides Notification-Center integration for OSX 10.8+
        - *
        - * - * NSUserNotificationsBridge is based on - * https://github.com/petesh/OSxNotificationCenter - * - * @author wolf.posdorfer - */ -public class MacNotificationCenter { - - interface NSUserNotificationsBridge extends Library { - - final File dylib = new File(Spark.getPluginDirectory().getAbsolutePath() - + "/roar/NSUserNotificationsBridge.dylib"); - - NSUserNotificationsBridge instance = (NSUserNotificationsBridge) Native.loadLibrary(dylib.getAbsolutePath(), - NSUserNotificationsBridge.class); - - public int sendNotification(String title, String subtitle, String text, int timeoffset, String sound); - } - - public static void sendNotification(String title, String bodyText) { - NSUserNotificationsBridge.instance.sendNotification(title, "", bodyText, 0, "Ping"); - } - -} diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/RoarDisplayType.java b/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/RoarDisplayType.java deleted file mode 100644 index 466fb36b0..000000000 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/displaytype/RoarDisplayType.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.jivesoftware.spark.roar.displaytype; - -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.spark.ui.ChatRoom; - -public interface RoarDisplayType { - - /** - * Do stuff when a message is received - */ - public void messageReceived(ChatRoom room, Message message, PropertyBundle bundle); - - /** - * Do stuff when a message is sent - */ - public void messageSent(ChatRoom room, Message message); - - /** - * Do stuff when the Popup closes - * - * @param type - * , the owner of the Popup - */ - public void closingRoarPanel(int x, int y); - - public String getName(); - - public String getLocalizedName(); - - public String getWarningMessage(); -} \ No newline at end of file diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/gui/RoarPreferencePanel.java b/src/plugins/roar/src/java/org/jivesoftware/spark/roar/gui/RoarPreferencePanel.java deleted file mode 100644 index b4dedf586..000000000 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/gui/RoarPreferencePanel.java +++ /dev/null @@ -1,500 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.roar.gui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.HashMap; -import java.util.List; - -import javax.swing.BorderFactory; -import javax.swing.DefaultListModel; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSlider; -import javax.swing.JTextField; -import javax.swing.event.ChangeEvent; - -import org.jivesoftware.spark.component.VerticalFlowLayout; -import org.jivesoftware.spark.roar.RoarProperties; -import org.jivesoftware.spark.roar.RoarResources; -import org.jivesoftware.spark.roar.displaytype.RoarDisplayType; -import org.jivesoftware.spark.util.ColorPick; - -/** - * Super Awesome Preference Panel - * - * @author wolf.posdorfer - * - */ -public class RoarPreferencePanel extends JPanel { - - private static final long serialVersionUID = -5334936099931215962L; - - // private Image _backgroundimage; - - private JTextField _duration; - private JTextField _amount; - private JCheckBox _enabledCheckbox; - - private JComboBox _typelist; - - private JList _singleColorlist; - private ColorPick _singleColorpicker; - - private HashMap _colormap; - - private HashMap _components; - - private Insets INSETS = new Insets(5, 5, 5, 5); - - public RoarPreferencePanel() { - - _components = new HashMap<>(); - _colormap = new HashMap<>(); - for (ColorTypes e : ColorTypes.values()) { - _colormap.put(e, Color.BLACK); - } - - this.setLayout(new BorderLayout()); - - // ClassLoader cl = getClass().getClassLoader(); - // _backgroundimage = new ImageIcon(cl.getResource("background2.png")).getImage(); - - _duration = new JTextField(); - _amount = new JTextField(); - _enabledCheckbox = new JCheckBox(RoarResources.getString("roar.enabled")); - - _singleColorpicker = new ColorPick(false); - _singleColorpicker.addChangeListener( e -> stateChangedSingleColorPicker(e) ); - - DefaultListModel listModel = new DefaultListModel<>(); - listModel.addElement(ColorTypes.BACKGROUNDCOLOR); - listModel.addElement(ColorTypes.HEADERCOLOR); - listModel.addElement(ColorTypes.TEXTCOLOR); - _singleColorlist = new JList<>(listModel); - - List roarDisplayTypes = RoarProperties.getInstance().getDisplayTypes(); - String[] _typelistdata = new String[ roarDisplayTypes.size() ]; - for (int i = 0; i < roarDisplayTypes.size(); i++) { - _typelistdata[i] = roarDisplayTypes.get(i).getLocalizedName(); - } - - _typelist = new JComboBox<>( _typelistdata ); - _typelist.addActionListener( e -> updateWarningLabel(getDisplayTypeClass().getWarningMessage()) ); - - add(makeGeneralSettingsPanel()); - _singleColorlist.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - colorListMouseClicked(e); - } - }); - } - - private JComponent makeGeneralSettingsPanel() { - JPanel generalPanel = new JPanel(); - generalPanel.setLayout(new GridBagLayout()); - generalPanel.setBorder(BorderFactory.createTitledBorder(RoarResources.getString("roar.settings"))); - - int rowcount = 0; - generalPanel.add(_enabledCheckbox, - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - - rowcount++; - generalPanel.add(new JLabel(RoarResources.getString("roar.amount")), - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - generalPanel.add(_amount, - new GridBagConstraints(1, rowcount, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - - rowcount++; - generalPanel.add(new JLabel(RoarResources.getString("roar.location")), - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - generalPanel.add(_typelist, - new GridBagConstraints(1, rowcount, 1, 1, 0.8, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - - - rowcount++; - JLabel warningLabel = new JLabel("placeholder :-)"); - //warningLabel.setForeground(Color.RED); - generalPanel.add(warningLabel, - new GridBagConstraints(1, rowcount, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - - - _components.put("label.warning", warningLabel); - - JPanel panel = new JPanel(new VerticalFlowLayout()); - panel.add(generalPanel); - panel.add(makeSinglePanel()); - panel.add(makeGroupChatPanel()); - panel.add(makeKeyWordPanel()); - - JScrollPane scroll = new JScrollPane(panel); - - return scroll; - } - - private JPanel makeSinglePanel() { - JPanel singlePanel = new JPanel(); - singlePanel.setLayout(new GridBagLayout()); - singlePanel.setBorder(BorderFactory.createTitledBorder(RoarResources.getString("roar.single"))); - JCheckBox disableSingle = new JCheckBox(RoarResources.getString("roar.single.disable")); - - // row - int rowcount = 0; - singlePanel.add(_singleColorlist, - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - singlePanel.add(_singleColorpicker, - new GridBagConstraints(1, rowcount, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - - rowcount++; - singlePanel.add(new JLabel(RoarResources.getString("roar.duration")), - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - singlePanel.add(_duration, - new GridBagConstraints(1, rowcount, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - - rowcount++; - singlePanel.add(disableSingle, - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - - _components.put("roar.disable.single", disableSingle); - return singlePanel; - } - - private JPanel makeGroupChatPanel() { - JPanel groupPanel = new JPanel(); - groupPanel.setLayout(new GridBagLayout()); - groupPanel.setBorder(BorderFactory.createTitledBorder(RoarResources.getString("roar.group"))); - - final JCheckBox enableDifferentGroup = new JCheckBox(RoarResources.getString("roar.group.different")); - JCheckBox disableGroup = new JCheckBox(RoarResources.getString("roar.group.disable")); - JTextField durationGroup = new JTextField(); - - enableDifferentGroup.addActionListener( e -> toggleDifferentSettingsForGroup(enableDifferentGroup.isSelected()) ); - - int rowcount = 0; - groupPanel.add(enableDifferentGroup, - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - - rowcount++; - groupPanel.add(new JLabel(RoarResources.getString("roar.duration")), - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - groupPanel.add(durationGroup, - new GridBagConstraints(1, rowcount, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - - rowcount++; - groupPanel.add(disableGroup, - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - - _components.put("group.different.enabled", enableDifferentGroup); - _components.put("group.duration", durationGroup); - _components.put("group.disable", disableGroup); - - return groupPanel; - } - - private JPanel makeKeyWordPanel() { - JPanel panel = new JPanel(); - panel.setLayout(new GridBagLayout()); - panel.setBorder(BorderFactory.createTitledBorder(RoarResources.getString("roar.keyword"))); - - final JCheckBox differentKeyword = new JCheckBox(RoarResources.getString("roar.keyword.different")); - differentKeyword.addActionListener( e -> toggleDifferentSettingsForKeyword(differentKeyword.isSelected()) ); - - JTextField durationKeyword = new JTextField(); - JTextField keywords = new JTextField(); - - int rowcount = 0; - panel.add(differentKeyword, - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - - rowcount++; - panel.add(new JLabel(RoarResources.getString("roar.duration")), - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - panel.add(durationKeyword, - new GridBagConstraints(1, rowcount, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - - rowcount++; - panel.add(new JLabel(RoarResources.getString("roar.keyword.keyword")), - new GridBagConstraints(0, rowcount, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - panel.add(keywords, new GridBagConstraints(1, rowcount, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, INSETS, 0, 0)); - - _components.put("keyword.different.enabled", differentKeyword); - _components.put("keyword.duration", durationKeyword); - _components.put("keywords", keywords); - - return panel; - } - - public void initializeValues() { - RoarProperties props = RoarProperties.getInstance(); - - _enabledCheckbox.setSelected(props.getShowingPopups()); - _amount.setText("" + props.getMaximumPopups()); - setDisplayType(props.getDisplayType()); - - setColor(ColorTypes.BACKGROUNDCOLOR, props.getBackgroundColor()); - setColor(ColorTypes.BACKGROUNDCOLOR_GROUP, props.getColor(RoarProperties.BACKGROUNDCOLOR_GROUP, props.getBackgroundColor())); - setColor(ColorTypes.BACKGROUNDCOLOR_KEYWORD, props.getColor(RoarProperties.BACKGROUNDCOLOR_KEYWORD, props.getBackgroundColor())); - setColor(ColorTypes.HEADERCOLOR, props.getHeaderColor()); - setColor(ColorTypes.HEADERCOLOR_GROUP, props.getColor(RoarProperties.HEADERCOLOR_GROUP, props.getHeaderColor())); - setColor(ColorTypes.HEADERCOLOR_KEYWORD, props.getColor(RoarProperties.HEADERCOLOR_KEYWORD, props.getHeaderColor())); - setColor(ColorTypes.TEXTCOLOR, props.getTextColor()); - setColor(ColorTypes.TEXTCOLOR_GROUP, props.getColor(RoarProperties.TEXTCOLOR_GROUP, props.getTextColor())); - setColor(ColorTypes.TEXTCOLOR_KEYWORD, props.getColor(RoarProperties.TEXTCOLOR_KEYWORD, props.getTextColor())); - - retrieveComponent("roar.disable.single", JCheckBox.class).setSelected(props.getBoolean("roar.disable.single", false)); - _duration.setText("" + props.getDuration()); - retrieveComponent("keyword.duration", JTextField.class).setText("" + props.getInt("keyword.duration")); - retrieveComponent("group.duration", JTextField.class).setText("" + props.getInt("group.duration")); - retrieveComponent("keywords", JTextField.class).setText(props.getProperty("keywords")); - - retrieveComponent("group.disable", JCheckBox.class).setSelected(props.getBoolean("group.disable", false)); - - boolean group_different_enabled = props.getBoolean("group.different.enabled", false); - retrieveComponent("group.different.enabled", JCheckBox.class).setSelected(group_different_enabled); - toggleDifferentSettingsForGroup(group_different_enabled); - - boolean keyword_different_enabled = props.getBoolean("keyword.different.enabled", false); - retrieveComponent("keyword.different.enabled", JCheckBox.class).setSelected(keyword_different_enabled); - toggleDifferentSettingsForKeyword(keyword_different_enabled); - } - - public void storeValues() { - RoarProperties props = RoarProperties.getInstance(); - props.setShowingPopups(_enabledCheckbox.isSelected()); - props.setDisplayType(this.getDisplayType()); - props.setMaximumPopups(this.getAmount()); - - props.setDuration(this.getDuration()); - props.setInt("group.duration", getIntFromTextField("group.duration")); - props.setInt("keyword.duration", getIntFromTextField("keyword.duration")); - - props.setKeywords(retrieveComponent("keywords", JTextField.class).getText()); - - props.setBackgroundColor(getColor(ColorTypes.BACKGROUNDCOLOR)); - props.setColor(RoarProperties.BACKGROUNDCOLOR_GROUP, getColor(ColorTypes.BACKGROUNDCOLOR_GROUP)); - props.setColor(RoarProperties.BACKGROUNDCOLOR_KEYWORD, getColor(ColorTypes.BACKGROUNDCOLOR_KEYWORD)); - props.setTextColor(getColor(ColorTypes.TEXTCOLOR)); - props.setColor(RoarProperties.TEXTCOLOR_GROUP, getColor(ColorTypes.TEXTCOLOR_GROUP)); - props.setColor(RoarProperties.TEXTCOLOR_KEYWORD, getColor(ColorTypes.TEXTCOLOR_KEYWORD)); - props.setHeaderColor(getColor(ColorTypes.HEADERCOLOR)); - props.setColor(RoarProperties.HEADERCOLOR_GROUP, getColor(ColorTypes.HEADERCOLOR_GROUP)); - props.setColor(RoarProperties.HEADERCOLOR_KEYWORD, getColor(ColorTypes.HEADERCOLOR_KEYWORD)); - - props.setBoolean("roar.disable.single", retrieveComponent("roar.disable.single", JCheckBox.class).isSelected()); - props.setBoolean("group.different.enabled", retrieveComponent("group.different.enabled", JCheckBox.class).isSelected()); - props.setBoolean("keyword.different.enabled", retrieveComponent("keyword.different.enabled", JCheckBox.class).isSelected()); - props.setBoolean("group.disable", retrieveComponent("group.disable", JCheckBox.class).isSelected()); - - props.save(); - } - - @SuppressWarnings("unchecked") - private K retrieveComponent(String key, Class classs) { - return (K) _components.get(key); - } - - private int getIntFromTextField(String key) { - JTextField field = retrieveComponent(key, JTextField.class); - - try { - return Integer.parseInt(field.getText()); - } catch (Exception e) { - return 3000; - } - } - - /** - * returns the popup duration - * - * @return int - */ - public int getDuration() { - try { - return Integer.parseInt(_duration.getText()); - } catch (Exception e) { - return 3000; - } - } - - /** - * Amount of Windows on Screen - * - * @return int - */ - public int getAmount() { - return Integer.parseInt(_amount.getText()); - } - - public Color getColor(ColorTypes type) { - return _colormap.get(type); - } - - public void setColor(ColorTypes type, Color color) { - _colormap.put(type, color); - } - - private void colorListMouseClicked(MouseEvent e) { - if (e.getSource() == _singleColorlist) { - ColorTypes key = _singleColorlist.getSelectedValue(); - _singleColorpicker.setColor(_colormap.get(key)); - } - } - - public void setDisplayType(String t) { - for (RoarDisplayType type : RoarProperties.getInstance().getDisplayTypes()) { - if (type.getName().equals(t)) { - _typelist.setSelectedItem(type.getLocalizedName()); - updateWarningLabel(type.getWarningMessage()); - return; - } - } - } - - - public void updateWarningLabel(String text) { - retrieveComponent("label.warning", JLabel.class).setText("" + text + ""); - } - - - public RoarDisplayType getDisplayTypeClass() { - String o = (String) _typelist.getSelectedItem(); - - for (RoarDisplayType type : RoarProperties.getInstance().getDisplayTypes()) { - if (type.getLocalizedName().equals(o)) { - return type; - } - } - return RoarProperties.getInstance().getDisplayTypes().get(0); - // topright is default - } - - public String getDisplayType() { - return getDisplayTypeClass().getName(); - } - - private void toggleDifferentSettingsForKeyword(boolean isSelected) { - - DefaultListModel model = (DefaultListModel) _singleColorlist.getModel(); - JTextField duration = retrieveComponent("keyword.duration", JTextField.class); - - if (isSelected) { - if (!model.contains(ColorTypes.BACKGROUNDCOLOR_KEYWORD)) { - model.addElement(ColorTypes.BACKGROUNDCOLOR_KEYWORD); - model.addElement(ColorTypes.HEADERCOLOR_KEYWORD); - model.addElement(ColorTypes.TEXTCOLOR_KEYWORD); - } - duration.setEnabled(true); - } else { - model.removeElement(ColorTypes.BACKGROUNDCOLOR_KEYWORD); - model.removeElement(ColorTypes.HEADERCOLOR_KEYWORD); - model.removeElement(ColorTypes.TEXTCOLOR_KEYWORD); - duration.setEnabled(false); - duration.setText(_duration.getText()); - } - } - - private void toggleDifferentSettingsForGroup(boolean isSelected) { - - DefaultListModel model = (DefaultListModel) _singleColorlist.getModel(); - JTextField duration = retrieveComponent("group.duration", JTextField.class); - - if (isSelected) { - if (!model.contains(ColorTypes.BACKGROUNDCOLOR_GROUP)) { - model.addElement(ColorTypes.BACKGROUNDCOLOR_GROUP); - model.addElement(ColorTypes.HEADERCOLOR_GROUP); - model.addElement(ColorTypes.TEXTCOLOR_GROUP); - } - duration.setEnabled(true); - } else { - model.removeElement(ColorTypes.BACKGROUNDCOLOR_GROUP); - model.removeElement(ColorTypes.HEADERCOLOR_GROUP); - model.removeElement(ColorTypes.TEXTCOLOR_GROUP); - duration.setEnabled(false); - duration.setText(_duration.getText()); - } - } - - private void stateChangedSingleColorPicker(ChangeEvent e) { - if (e.getSource() instanceof JSlider) { - _colormap.put( _singleColorlist.getSelectedValue(), _singleColorpicker.getColor()); - } - } - - // ============================================================================================================ - // ============================================================================================================ - // ============================================================================================================ - // public void paintComponent(Graphics g) { - // CENTER LOGO - // int imgwi = _backgroundimage.getWidth(null); - // int imghe = _backgroundimage.getHeight(null); - // int x = this.getSize().width; - // x = (x/2)-(imgwi/2) < 0 ? 0 : (x/2)-(imgwi/2) ; - // - // int y = this.getSize().height; - // y = (y/2) -(imghe/2)< 0 ? 0 : y/2-(imghe/2) ; - // - // LOGO in bottom right corner - // - // int x = this.getSize().width - _backgroundimage.getWidth(null); - // int y = this.getSize().height - _backgroundimage.getHeight(null); - // - // super.paintComponent(g); - // g.drawImage(_backgroundimage, x, y, this); - // } - // ============================================================================================================ - // ============================================================================================================ - // ============================================================================================================ - public enum ColorTypes { - BACKGROUNDCOLOR(RoarResources.getString("roar.background")), - HEADERCOLOR(RoarResources.getString("roar.header")), - TEXTCOLOR(RoarResources.getString("roar.text")), - - BACKGROUNDCOLOR_GROUP(RoarResources.getString("roar.background.group")), - HEADERCOLOR_GROUP(RoarResources.getString("roar.header.group")), - TEXTCOLOR_GROUP(RoarResources.getString("roar.text.group")), - - BACKGROUNDCOLOR_KEYWORD(RoarResources.getString("roar.background.keyword")), - HEADERCOLOR_KEYWORD(RoarResources.getString("roar.header.keyword")), - TEXTCOLOR_KEYWORD(RoarResources.getString("roar.text.keyword")); - - private String string; - - private ColorTypes(String c) { - string = c; - } - - public String toString() { - return string; - } - - } - -} diff --git a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/gui/SparkToaster.java b/src/plugins/roar/src/java/org/jivesoftware/spark/roar/gui/SparkToaster.java deleted file mode 100644 index 3c1ce04a8..000000000 --- a/src/plugins/roar/src/java/org/jivesoftware/spark/roar/gui/SparkToaster.java +++ /dev/null @@ -1,685 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.roar.gui; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.EventQueue; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GraphicsEnvironment; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Image; -import java.awt.Insets; -import java.awt.Rectangle; -import java.awt.Window; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.geom.AffineTransform; - -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.border.Border; - -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.SparkRes; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.util.ImageCombiner; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.log.Log; - -/** - * Class to show tosters in multiplatform - * - * @author daniele piras - */ -public class SparkToaster { - - /** - * The default Hand cursor. - */ - public static final Cursor HAND_CURSOR = new Cursor(Cursor.HAND_CURSOR); - - /** - * The default Text Cursor. - */ - public static final Cursor DEFAULT_CURSOR = new Cursor( - Cursor.DEFAULT_CURSOR); - - // Width of the toster - private int toasterWidth = 200; - - // Height of the toster - private int toasterHeight = 150; - - // Step for the toaster - private int step = 20; - - // Step time - private int stepTime = 20; - - // Show time - private int displayTime = 3000; - - // Current number of toaster... - private int currentNumberOfToaster = 0; - - // Last opened toaster - private int maxToaster = 0; - - // Font used to display message - private Font font; - - // Color for border - private Color borderColor; - - // Color for toaster - private Color toasterColor; - - // Set message color - private Color messageColor; - - // Set the margin - int margin; - - // Flag that indicate if use alwaysOnTop or not. - // method always on top start only SINCE JDK 5 ! - boolean useAlwaysOnTop = true; - - private String title; - - private Border border; - - private Action customAction; - - private Window window; - - private JPanel mainPanel = new JPanel(); - - private TitleLabel titleLabel; - - private boolean hideable = true; - - /** - * Constructor to initialized toaster component... - */ - public SparkToaster() { - // Set default font... - font = new Font("Dialog", Font.PLAIN, 11); - - // Border color - borderColor = new Color(245, 153, 15); - toasterColor = Color.WHITE; - messageColor = Color.BLACK; - useAlwaysOnTop = true; - } - - /** - * Class that rappresent a single toaster - * - * @author daniele piras - */ - class SingleToaster extends javax.swing.JWindow { - private static final long serialVersionUID = 1L; - - // Label to store Icon - - // Text area for the message - private JTextArea message = new JTextArea(); - - /** - * Simple costructor that initialized components... - */ - public SingleToaster() { - initComponents(); - } - - /** - * Function to initialized components - */ - private void initComponents() { - message.setFont(getToasterMessageFont()); - - mainPanel.setBackground(Color.white); - message.setOpaque(false); - mainPanel.setLayout(new GridBagLayout()); - message.setMargin(new Insets(2, 2, 2, 2)); - message.setLineWrap(true); - message.setWrapStyleWord(true); - - message.setForeground(getMessageColor()); - titleLabel = new TitleLabel(getTitle(), true); - titleLabel.setForeground(new Color(87, 166, 211)); - titleLabel.setFont(new Font("Dialog", Font.BOLD, 13)); - - mainPanel.add(titleLabel, - new GridBagConstraints(0, 0, 3, 1, 1.0, 0.0, - GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, - 0), 0, 0)); - - titleLabel.getCloseButton().addActionListener( e -> { - setVisible(false); - dispose(); - } ); - - if (border != null) { - mainPanel.setBorder(border); - } - - message.setForeground(Color.BLACK); - - message.setOpaque(false); - - getContentPane().add(mainPanel); - - mainPanel.addMouseListener(new PaneMouseListener()); - message.addMouseListener(new PaneMouseListener()); - - pack(); - setSize(toasterWidth, toasterHeight); - mainPanel - .setBorder(BorderFactory.createLineBorder(Color.lightGray)); - } - - /** - * Start toaster animation... - */ - public void animate() { - (new Animation(this)).start(); - } - - private class PaneMouseListener extends MouseAdapter { - - public void mouseClicked(MouseEvent e) { - if (customAction != null) { - customAction.actionPerformed(null); - } - - if (hideable) { - setVisible(false); - dispose(); - } - } - - public void mouseEntered(MouseEvent e) { - message.setCursor(HAND_CURSOR); - setCursor(HAND_CURSOR); - } - - public void mouseExited(MouseEvent e) { - message.setCursor(DEFAULT_CURSOR); - setCursor(DEFAULT_CURSOR); - } - } - } - - /** - * Class that manage the animation - */ - class Animation extends Thread { - SingleToaster toaster; - - public Animation(SingleToaster toaster) { - this.toaster = toaster; - } - - /** - * Animate vertically the toaster. The toaster could be moved from - * bottom to upper or to upper to bottom - * - * @param posx - * X position for toaster. - * @param fromY - * Y from position - * @param toY - * Y to position - * @throws InterruptedException - * if animation is interrupted - */ - protected void animateVertically(int posx, int fromY, int toY) - throws InterruptedException { - - toaster.setLocation(posx, fromY); - if (toY < fromY) { - for (int i = fromY; i > toY; i -= step) { - toaster.setLocation(posx, i); - Thread.sleep(stepTime); - } - } else { - for (int i = fromY; i < toY; i += step) { - toaster.setLocation(posx, i); - Thread.sleep(stepTime); - } - } - toaster.setLocation(posx, toY); - toaster.invalidate(); - toaster.validate(); - toaster.repaint(); - } - - public void run() { - try { - boolean animateFromBottom = true; - GraphicsEnvironment ge = GraphicsEnvironment - .getLocalGraphicsEnvironment(); - Rectangle screenRect = ge.getMaximumWindowBounds(); - - int screenHeight = screenRect.height; - - int startYPosition; - int stopYPosition; - - if (screenRect.y > 0) { - animateFromBottom = false; // Animate from top! - } - - int maxToasterInSceen = screenHeight / toasterHeight; - - int posx = screenRect.width - toasterWidth - 1; - - toaster.setLocation(posx, screenHeight); - try { - EventQueue.invokeAndWait( () -> toaster.setVisible(true) ); - } catch (Exception e) { - Log.error(e); - } - if (useAlwaysOnTop) { - toaster.setAlwaysOnTop(true); - } - - if (animateFromBottom) { - startYPosition = screenHeight; - stopYPosition = startYPosition - toasterHeight - 1; - if (currentNumberOfToaster > 0) { - stopYPosition = stopYPosition - - (maxToaster % maxToasterInSceen * toasterHeight); - } else { - maxToaster = 0; - } - } else { - startYPosition = screenRect.y - toasterHeight; - stopYPosition = screenRect.y; - - if (currentNumberOfToaster > 0) { - stopYPosition = stopYPosition - + (maxToaster % maxToasterInSceen * toasterHeight); - } else { - maxToaster = 0; - } - } - - currentNumberOfToaster++; - maxToaster++; - - animateVertically(posx, startYPosition, stopYPosition); - Thread.sleep(displayTime); - animateVertically(posx, stopYPosition, startYPosition); - - currentNumberOfToaster--; - toaster.setVisible(false); - toaster.dispose(); - } catch (Exception e) { - Log.error(e); - } - } - } - - /** - * Show a toaster with the specified message and the associated icon. - * - * @param icon - * Icon to show in toaster popup. - * @param msg - * Message to show in toaster popup. - */ - public void showToaster(Icon icon, String msg) { - SingleToaster singleToaster = new SingleToaster(); - final JScrollPane pane = new JScrollPane(singleToaster.message); - pane.setOpaque(false); - pane.setBorder(BorderFactory.createEmptyBorder()); - pane.getViewport().setBackground(Color.white); - mainPanel.add(pane, new GridBagConstraints(1, 2, 3, 1, 1.0, 1.0, - GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, - 5, 2, 5), 0, 0)); - - if (icon != null) { - titleLabel.setIcon(icon); - } - if (ModelUtil.hasLength(msg) && msg.startsWith("/me ")) { - msg = msg.replaceFirst("/me", getTitle()); - singleToaster.message.setForeground(Color.MAGENTA); - } - singleToaster.message.setText(msg); - singleToaster.message.setCaretPosition(0); - singleToaster.animate(); - window = singleToaster; - } - - /** - * Show a toaster with the specified message and the associated icon. - * - * @param title - * Title to use in toaster popup - * @param comp - * Component to add to toaster popup - */ - public void showToaster(final String title, final Component comp) { - SingleToaster singleToaster = new SingleToaster(); - mainPanel.add(comp, new GridBagConstraints(1, 2, 3, 1, 1.0, 1.0, - GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, - 0, 0, 0), 0, 0)); - - titleLabel.setTitle(title); - singleToaster.animate(); - window = singleToaster; - } - - public void showToaster(Icon icon) { - SingleToaster singleToaster = new SingleToaster(); - if (icon != null) { - titleLabel.setIcon(icon); - } - singleToaster.animate(); - window = singleToaster; - } - - public void showToaster() { - SingleToaster singleToaster = new SingleToaster(); - singleToaster.animate(); - window = singleToaster; - } - - /** - * Show a toaster with the specified message. - * - * @param msg - * Message to display. - */ - public void showToaster(String msg) { - showToaster(null, msg); - } - - /** - * @return Returns the font - */ - public Font getToasterMessageFont() { - return font; - } - - /** - * Set the font for the message - * - * @param f - * Font to set on toaster messages. - */ - public void setToasterMessageFont(Font f) { - font = f; - } - - /** - * @return Returns the borderColor. - */ - public Color getBorderColor() { - return borderColor; - } - - /** - * @param borderColor - * The borderColor to set. - */ - public void setBorderColor(Color borderColor) { - this.borderColor = borderColor; - } - - /** - * @return Returns the displayTime. - */ - public int getDisplayTime() { - return displayTime; - } - - /** - * @param displayTime - * The displayTime to set. - */ - public void setDisplayTime(int displayTime) { - this.displayTime = displayTime; - } - - /** - * @return Returns the margin. - */ - public int getMargin() { - return margin; - } - - /** - * @param margin - * The margin to set. - */ - public void setMargin(int margin) { - this.margin = margin; - } - - /** - * @return Returns the messageColor. - */ - public Color getMessageColor() { - return messageColor; - } - - /** - * @param messageColor - * The messageColor to set. - */ - public void setMessageColor(Color messageColor) { - this.messageColor = messageColor; - } - - /** - * @return Returns the step. - */ - public int getStep() { - return step; - } - - /** - * @param step - * The step to set. - */ - public void setStep(int step) { - this.step = step; - } - - /** - * @return Returns the stepTime. - */ - public int getStepTime() { - return stepTime; - } - - /** - * @param stepTime - * The stepTime to set. - */ - public void setStepTime(int stepTime) { - this.stepTime = stepTime; - } - - /** - * @return Returns the toasterColor. - */ - public Color getToasterColor() { - return toasterColor; - } - - /** - * @param toasterColor - * The toasterColor to set. - */ - public void setToasterColor(Color toasterColor) { - this.toasterColor = toasterColor; - } - - /** - * @return Returns the toasterHeight. - */ - public int getToasterHeight() { - return toasterHeight; - } - - /** - * @param toasterHeight - * The toasterHeight to set. - */ - public void setToasterHeight(int toasterHeight) { - this.toasterHeight = toasterHeight; - } - - /** - * @return Returns the toasterWidth. - */ - public int getToasterWidth() { - return toasterWidth; - } - - /** - * @param toasterWidth - * The toasterWidth to set. - */ - public void setToasterWidth(int toasterWidth) { - this.toasterWidth = toasterWidth; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public Border getBorder() { - return border; - } - - public void setBorder(Border border) { - this.border = border; - } - - public void setCustomAction(Action action) { - this.customAction = action; - } - - public void setComponent(Component comp) { - mainPanel.add(comp, new GridBagConstraints(1, 2, 3, 1, 1.0, 1.0, - GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, - 5, 2, 5), 0, 0)); - } - - public void close() { - if (window != null) { - window.dispose(); - } - } - - public Window getWindow() { - return window; - } - - public void hideTitle() { - titleLabel.setVisible(false); - } - - class TitleLabel extends JPanel { - private static final long serialVersionUID = -5163519932953987400L; - private JLabel label; - private RolloverButton closeButton; - - public TitleLabel(String text, final boolean showCloseIcon) { - setLayout(new GridBagLayout()); - label = new JLabel(text); - label.setFont(new Font("Dialog", Font.BOLD, 11)); - label.setHorizontalTextPosition(JLabel.LEFT); - label.setHorizontalAlignment(JLabel.LEFT); - - add(label, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(5, 5, 5, 5), 0, 0)); - - closeButton = new RolloverButton( - SparkRes.getImageIcon(SparkRes.CLOSE_IMAGE)); - if (showCloseIcon) { - add(closeButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, - GridBagConstraints.EAST, GridBagConstraints.NONE, - new Insets(5, 5, 5, 5), 0, 0)); - } - - setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, - Color.lightGray)); - } - - public void setIcon(Icon icon) { - if (icon.getIconHeight() > 64 || icon.getIconWidth() > 64) { - Image image = ImageCombiner.iconToImage(icon); - label.setIcon(new ImageIcon(image.getScaledInstance(-1, 64, - Image.SCALE_SMOOTH))); - } else { - label.setIcon(icon); - } - } - - public RolloverButton getCloseButton() { - return closeButton; - } - - public void setTitle(String title) { - label.setText(title); - } - - public void paintComponent(Graphics g) { - final Image backgroundImage = Default.getImageIcon( - Default.TOP_BOTTOM_BACKGROUND_IMAGE).getImage(); - double scaleX = getWidth() - / (double) backgroundImage.getWidth(null); - double scaleY = getHeight() - / (double) backgroundImage.getHeight(null); - AffineTransform xform = AffineTransform.getScaleInstance(scaleX, - scaleY); - ((Graphics2D) g).drawImage(backgroundImage, xform, this); - } - } - - public void setHidable(boolean hideable) { - this.hideable = hideable; - } - - -} diff --git a/src/plugins/roar/src/resources/background2.png b/src/plugins/roar/src/resources/background2.png deleted file mode 100644 index 942a5d7da..000000000 Binary files a/src/plugins/roar/src/resources/background2.png and /dev/null differ diff --git a/src/plugins/roar/src/resources/i18n/roar_i18n_de.properties b/src/plugins/roar/src/resources/i18n/roar_i18n_de.properties deleted file mode 100644 index b8234c04d..000000000 --- a/src/plugins/roar/src/resources/i18n/roar_i18n_de.properties +++ /dev/null @@ -1,36 +0,0 @@ - -# Roar language file - -roar.settings = Roar Einstellungen -roar.enabled = Popups aktiv -roar.duration = Dauer in ms (0 = unbegrenzt): -roar.amount = Maximale Anzahl von Popups (0 = unbegrenzt): -roar.location = Popupecke auswählen (benötigt Neustart) -roar.display.topright = oben rechts -roar.display.bottomright = unten rechts -roar.background = Hintergrundfarbe -roar.background.group = Hintergrundfarbe Gruppenchat -roar.background.keyword = Hintergrundfarbe Stichwort -roar.header = Überschrift -roar.header.group = Überschrift Gruppenchat -roar.header.keyword = Überschrift Stichwort -roar.text = Textfarbe -roar.text.group = Textfarbe Gruppenchat -roar.text.keyword = Textfarbe Stichwort - -roar.single = Einzelchat -roar.single.disable = Roar für Einzelchats deaktivieren -roar.group = Gruppenchat -roar.group.different = Andere Einstellungen für Gruppenchats verwenden -roar.group.disable = Roar für Gruppenchats deaktivieren -roar.keyword = Stichwortsuche -roar.keyword.different = Andere Einstellungen für Stichwortsuche verwenden -roar.keyword.keyword = Stichworte (kommagetrennt) - -roar.display.system = Betriebssystem-Mitteilung - -roar.warning.topright = Roar-spezifische Popups. Flexibel anpassbar. -roar.warning.bottomright = Roar-spezifische Popups. Flexibel anpassbar. -roar.warning.toaster = Spark Toaster Popups. Farben sind nicht anpassbar. -roar.warning.system = Betriebssystemabhängige Popups. Farben und Dauer sind nicht anpassbar. -roar.warning.system.mac = Benutzt das Mitteilungs-Center (OSX 10.8 und neuer).
        Farben und Dauer sind nicht anpassbar.
        Weitere Einstellungen unter: Mac-Systemeinstellungen -> Mitteilungen. \ No newline at end of file diff --git a/src/plugins/roar/src/resources/i18n/roar_i18n_fr.properties b/src/plugins/roar/src/resources/i18n/roar_i18n_fr.properties deleted file mode 100644 index 857360451..000000000 --- a/src/plugins/roar/src/resources/i18n/roar_i18n_fr.properties +++ /dev/null @@ -1,12 +0,0 @@ -# Roar language file - -roar.settings = Param\u00E8tres Roar -roar.enabled = Popups activ\u00E9s -roar.duration = Dur\u00E9e en ms (0 = infini): -roar.amount = Popups maximals affich\u00E9s \u00E0 l'\u00E9cran (0 = infini): -roar.location = Changer l'emplacement de d\u00E9part du popup (n\u00E9cessite un red\u00E9marrage) -roar.display.topright = En haut \u00E0 droite -roar.display.bottomright = En bas \u00E0 droite -roar.background = Couleur de fond -roar.header = Couleur de l'ent\u00EAte -roar.text = Couleur du texte diff --git a/src/plugins/roar/src/resources/i18n/roar_i18n_lt.properties b/src/plugins/roar/src/resources/i18n/roar_i18n_lt.properties deleted file mode 100644 index f66ad44e5..000000000 --- a/src/plugins/roar/src/resources/i18n/roar_i18n_lt.properties +++ /dev/null @@ -1,13 +0,0 @@ - -# Roar language file - -roar.settings = Roar Nustatymai -roar.enabled = \u012ejungti i\u0161\u0161okan\u010dius langus -roar.duration = Rodymo trukm\u0117 (ms) (0 = neribojama): -roar.amount = Maksimalus lang\u0173 skai\u010dius ekrane (0 = neribojama): -roar.location = Pakeisti lang\u0173 atsiradymo prad\u017eios viet\u0105 (reikalingas perkrovimas) -roar.display.topright = Vir\u0161uje de\u0161in\u0117je -roar.display.bottomright = Apa\u010dioje de\u0161in\u0117je -roar.background = Fono spalva -roar.header = Antra\u0161t\u0117s spalva -roar.text = Teksto spalva \ No newline at end of file diff --git a/src/plugins/roar/src/resources/i18n/roar_i18n_pl.properties b/src/plugins/roar/src/resources/i18n/roar_i18n_pl.properties deleted file mode 100644 index baa639734..000000000 --- a/src/plugins/roar/src/resources/i18n/roar_i18n_pl.properties +++ /dev/null @@ -1,14 +0,0 @@ - -# Plik jêzykowy Panelu ROAR - -roar.settings = Ustawienia ROAR -roar.enabled = W\u0142\u0105cz wyskakuj\u0105ce powiadomienia -roar.duration = Czas trwania w ms (0 = bez limitu): -roar.amount = Maksymalna ilo\u015b\u0107 powiadomie\u0144 na ekranie (0 = bez limitu): -roar.location = Zmiana miejsca wyskakuj\u0105cych powiadomie\u0144 (wymagany restart) -roar.display.topright = G\u00F3rna prawa -roar.display.bottomright = Dolna prawa -roar.background = Kolor t\u0142a -roar.header = Kolor nag\u0142\u00F3wka -roar.text = Kolor tekstu - diff --git a/src/plugins/roar/src/resources/i18n/roar_i18n_zh_TW.properties b/src/plugins/roar/src/resources/i18n/roar_i18n_zh_TW.properties deleted file mode 100644 index ab8bb09d3..000000000 --- a/src/plugins/roar/src/resources/i18n/roar_i18n_zh_TW.properties +++ /dev/null @@ -1,15 +0,0 @@ - -# Roar language file -tooltip.roar = \u4fbf\u5229\u8cbc - -roar.settings = \u4fbf\u5229\u8cbc\u8a2d\u5b9a -roar.enabled = \u555f\u52d5\u5f48\u51fa\u4fbf\u5229\u8cbc -roar.duration = \u4fbf\u5229\u8cbc\u986f\u793a\u6642\u9593\u70ba\u591a\u5c11\u6beb\u79d2 (0 = \u7121\u9650\u6642): -roar.amount = \u4fbf\u5229\u8cbc\u5f48\u51fa\u5728\u87a2\u5e55\u4e0a\u7684\u6700\u5927\u7bc4\u570d (0 = \u7121\u9650\u6642): -roar.location = \u8b8a\u66f4\u4fbf\u5229\u8cbc\u5f48\u51fa\u4f4d\u7f6e (\u9700\u8981\u91cd\u65b0\u555f\u52d5) -roar.display.topright = \u53f3\u4e0a\u65b9 -roar.display.bottomright = \u53f3\u4e0b\u65b9 -roar.display.sparktoaster = Spark \u901a\u77e5\u8996\u7a97\u5373\u70ba\u4fbf\u5229\u8cbc -roar.background = \u4fbf\u5229\u8cbc\u80cc\u666f\u984f\u8272 -roar.header = \u4fbf\u5229\u8cbc\u6a19\u984c\u984f\u8272 -roar.text = \u4fbf\u5229\u8cbc\u8a0a\u606f\u984f\u8272 \ No newline at end of file diff --git a/src/plugins/sip/build/build.xml b/src/plugins/sip/build/build.xml deleted file mode 100644 index 0ed803317..000000000 --- a/src/plugins/sip/build/build.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/sip/build/projects/SparkPhone.iml b/src/plugins/sip/build/projects/SparkPhone.iml deleted file mode 100644 index 4d0d90b65..000000000 --- a/src/plugins/sip/build/projects/SparkPhone.iml +++ /dev/null @@ -1,225 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/sip/plugin.xml b/src/plugins/sip/plugin.xml deleted file mode 100644 index 71f168b84..000000000 --- a/src/plugins/sip/plugin.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - Phone Client - 1.1.1 - Jive Software - http://www.jivesoftware.org - thiago@jivesoftware.com - SIP Softphone Plugin - org.jivesoftware.sparkplugin.SoftPhonePlugin - 2.7.0 - Windows,Mac,Linux - 1.7.0 - - diff --git a/src/plugins/sip/src/java/net/java/sipmack/common/Log.java b/src/plugins/sip/src/java/net/java/sipmack/common/Log.java deleted file mode 100644 index e447c5ce6..000000000 --- a/src/plugins/sip/src/java/net/java/sipmack/common/Log.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.java.sipmack.common; - -/** - * Creates and writes out messages. - */ - -public class Log { - - private static boolean debugger = false; - - static { - - if (System.getProperty("debugger") != null - && System.getProperty("debugger").equals("true")) - debugger = true; - - } - - public static void debug(String message) { - if (debugger) - System.out.println((message != null ? message : "")); - } - - public static void debug(String method, String message) { - if (debugger) - System.out.println((method != null ? method : "") + " - " - + (message != null ? message : "")); - } - - public static void error(String method, Exception e) { - System.out.println((method != null ? method : "") + " - " - + (e != null ? e.toString() : "")); - e.printStackTrace(); - } - - public static void error(Exception e) { - error("", e); - } - - public static void error(String method, Error e) { - System.out.println((method != null ? method : "") + " - " - + (e != null ? e.toString() : "")); - } - - public static void error(String method, Throwable e) { - System.out.println((method != null ? method : "") + " - " - + (e != null ? e.toString() : "")); - } - -} diff --git a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_it.properties b/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_it.properties deleted file mode 100644 index ec8a28032..000000000 --- a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_it.properties +++ /dev/null @@ -1,115 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## - -phone.starting = Starting Phone... -phone.failed = Failed to start phone -phone.tryagain = Try again -phone.call = Call -phone.voicemail = Voice Mail -phone.viewcallhistory = View Call History -phone.placecall = Place phone call. -phone.hangup = End Call -phone.tips.hangup = Hang up phone conversation -phone.home = Home -phone.work = Work -phone.cell = Cell -phone.currentcall = Current Call -phone.incomingcall = Incoming Call -phone.noprevious = No previous conversations. -phone.callended = Call Ended -phone.transferto = Call transferred to -phone.connected = Connected -phone.lastcalled = Last called -phone.never = Never -phone.duration = Duration -phone.accept = Accept -phone.reject = Reject -phone.callback = Call Back -phone.delete = Delete -phone.enternumber = Enter a number to call. -phone.invalidnumber = Invalid Number -phone.outgoingcall = Outgoing call to -phone.callhistory = Call History -phone.dialed = Dialed -phone.dialedcalls = Dialed Calls -phone.received = Received -phone.receivedcalls = Received Calls -phone.missed = Missed -phone.missedcalls = Missed Calls -phone.unknown = Unknown -phone.placecallto = Placed call to -phone.receivedcallfrom = Received Call from -phone.missedcallfrom = Missed call from -phone.incomingcallfrom = Incoming call from -phone.contactdetails = Contact Details -phone.noinfo = No Information Available -phone.viewfullprofile = View Full Profile -phone.tips.mute = Mute this call -phone.mute = Mute -phone.unmute = Unmute -phone.tips.hold = Place this call on Hold -phone.hold = Hold -phone.onhold = On Hold -phone.time = Time -phone.tips.transfer = Transfer this call -phone.transfer = Transfer -phone.transferring = Transferring -phone.transfered = Transfered -phone.callstartedat = Call Started at -phone.callendedat = Call Ended at -phone.onphonewith = On the phone with -phone.callendedwith = Call ended with -phone.previousconversations = Previous Conversations -phone.closeconfirm = Closing this room will end the call. Continue? -phone.confirmation = Confirmation -phone.all = All -phone.allcalls = All Calls -phone.tocall = Call -btn.add = Add -btn.edit = Edit -btn.del = Delete -btn.dial = Call -book.name = Name -book.number = Number -frame.title = Phonebook -book.search = Search -btn.ok = OK -btn.cancel = Cancel -frame.add = "Add Entry" -frame.edit = "Edit Entry" -book.exists = "The phonebook-entry you wish to add is already existing." -book.noEntry = "No Entry Selected!" -book.fillFields = "Please fill all Fields" -book.warning = "Attention" -title.sip.codecs.title = Codecs -codecs.select = < Select -codecs.unselect = Unselect > -codecs.up = Up ^ -codecs.down = Down v -codecs.audio.selected = Selected Audio Codecs -codecs.audio.avail = Available Audio Codecs \ No newline at end of file diff --git a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_lt.properties b/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_lt.properties deleted file mode 100644 index 3f10ccd05..000000000 --- a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_lt.properties +++ /dev/null @@ -1,116 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## - -phone.starting = Telefonas startuoja... -phone.failed = Nepavyko paleist telefono -phone.tryagain = Bandykit dar kart\u0105 -phone.call = Skambutis -phone.voicemail = Balso pa\u0161tas -phone.viewcallhistory = Per\u017ei\u016br\u0117ti skambu\u010di\u0173 istorij\u0105 -phone.placecall = Paskambinti telefonu -phone.hangup = U\u017ebaigti skambut\u012f -phone.tips.hangup = Nutraukt telefono pokalb\u012f -phone.home = Namai -phone.work = Darbas -phone.cell = Mobilus -phone.currentcall = Einamasis skambutis -phone.incomingcall = \u012eeinantis skambutis -phone.noprevious = Prie\u0161 tai pokalbi\u0173 nebuvo -phone.callended = Skambutis nutruko -phone.transferto = Skambutis peradresuotas -phone.connected = Susijungta -phone.lastcalled = Paskutin\u012f kart\u0105 skambinta -phone.never = Niekada -phone.duration = Trukm\u0117 -phone.accept = Priimti -phone.reject = Atsisakyti -phone.callback = Perskambinti -phone.delete = I\u0161trinti -phone.enternumber = \u012eveskite numer\u012f skambu\u010diui -phone.invalidnumber = Neteisingas numeris -phone.outgoingcall = I\u0161einantis skambutis -phone.callhistory = Skambu\u010di\u0173 istorija -phone.dialed = Skambinta -phone.dialedcalls = Rinkti numeriai -phone.received = Gauta -phone.receivedcalls = Gauti skambu\u010diai -phone.missed = Praleista -phone.missedcalls = Praleisti skambu\u010diai -phone.unknown = Ne\u017einomas -phone.placecallto = Paskambinta -phone.receivedcallfrom = Skambutis gautas i\u0161 -phone.missedcallfrom = Praleistas skambutis nuo -phone.incomingcallfrom = \u012eeinantis skambutis nuo -phone.contactdetails = Adresato informacija -phone.noinfo = N\u0117ra informacijos -phone.viewfullprofile = Per\u017ei\u016breti piln\u0105 profil\u012f -phone.tips.mute = Nutildinti \u0161\u012f skambut\u012f -phone.mute = Nutildinti -phone.unmute = Nuimti nutildinim\u0105 -phone.tips.hold = Perjungti \u0161\u012f skambut\u012f \u012f laukimo b\u016bsen\u0105 -phone.hold = Laukti -phone.onhold = Laukimo b\u016bsenoje -phone.time = Laikas -phone.tips.transfer = Peradresuoti \u0161\u012f skambut\u012f -phone.transfer = Peradresuoti -phone.transferring = Skambutis peradresuojamas -phone.transfered = Skambutis peradresuotas -phone.callstartedat = Pokalbis prad\u0117tas -phone.callendedat = Pokalbis baigtas -phone.onphonewith = Kalba telefonu su -phone.callendedwith = Baig\u0117si pokalbis su -phone.previousconversations = Senesni pokalbiai -phone.closeconfirm = U\u017edarius \u0161\u012f kambar\u012f, pokalbis bus nutrauktas. T\u0119sti? -phone.confirmation = Patvirtinimas -phone.all = Visi -phone.allcalls = Visi skambu\u010diai -phone.tocall = Skambinti -phone.enabled = Telefonas \u012fjungtas -btn.add = Prid\u0117ti -btn.edit = Redaguoti -btn.del = I\u0161trinti -btn.dial = Skambinti -book.name = Vardas -book.number = Numeris -frame.title = Telefon\u0173 knyga -book.search = Paie\u0161ka -btn.ok = Gerai -btn.cancel = At\u0161aukti -frame.add = "Prid\u0117ti \u012fra\u0161\u0105" -frame.edit = "Redaguoti \u012fra\u0161\u0105" -book.exists = "Telefon\u0173 knygos \u012fra\u012fas, kur\u012f j\u016bs norite prid\u0117ti, jau egzistuoja." -book.noEntry = "Nepasirinktas \u012fra\u012fas!" -book.fillFields = "Pra\u012fome u\u017epildyti visus laukus" -book.warning = "D\u0117mesio" -title.sip.codecs.title = Kodekai -codecs.select = \u21E6 Pasirinkti -codecs.unselect = I\u0161mesti \u21E8 -codecs.up = Vir\u0161un \u21E7 -codecs.down = \u017Demyn \u21E9 -codecs.audio.selected = Pasirinkti garso kodekai -codecs.audio.avail = Turimi garso kodekai \ No newline at end of file diff --git a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_pl.properties b/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_pl.properties deleted file mode 100644 index 8508085a8..000000000 --- a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_pl.properties +++ /dev/null @@ -1,116 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## - -phone.starting = Uruchamianie telefonu... -phone.failed = B\u0142\u0105d uruchomienia telefonu -phone.tryagain = Spr\u00F3buj ponownie -phone.call = Dzwo\u0144 -phone.voicemail = Wiadomo\u015B\u0107 g\u0142osowa -phone.viewcallhistory = Przegl\u0105dnij histori\u0119 rozm\u00F3w -phone.placecall = Dzwo\u0144. -phone.hangup = Od\u0142\u00F3\u017C s\u0142uchawk\u0119 -phone.tips.hangup = Zako\u0144cz rozmow\u0119 telefoniczn\u0105 -phone.home = Dom -phone.work = Praca -phone.cell = Kom\u00F3rka -phone.currentcall = Bie\u017C\u0105ce po\u0142\u0105czenie -phone.incomingcall = Przychodz\u0105ce po\u0142\u0105czenie -phone.noprevious = Brak wcze\u015Bniejszych rozm\u00F3w. -phone.callended = Po\u0142\u0105czenie zako\u0144czono -phone.transferto = Po\u0142\u0105czenie przekazano do -phone.connected = Po\u0142\u0105czono -phone.lastcalled = Ostatni dzwoni\u0105cy -phone.never = Nigdy -phone.duration = Czas trwania -phone.accept = Akceptuj -phone.reject = Odrzu\u0107 -phone.callback = Oddzwo\u0144 -phone.delete = Usu\u0144 -phone.enternumber = Podaj numer telefonu. -phone.invalidnumber = Niepoprawny numer -phone.outgoingcall = Po\u0142\u0105czenie wychodz\u0105ce do -phone.callhistory = Historia rozm\u00F3w -phone.dialed = Wybrany -phone.dialedcalls = Wybrane po\u0142\u0105czenia -phone.received = Odebrane -phone.receivedcalls = Odebrane po\u0142\u0105czenia -phone.missed = Nieodebrane -phone.missedcalls = Nieodebrane po\u0142\u0105czenia -phone.unknown = Nieznane -phone.placecallto = Dzwoniono do -phone.receivedcallfrom = Odebrane po\u0142\u0105czenie od -phone.missedcallfrom = Nieodebrane po\u0142\u0105czenie od -phone.incomingcallfrom = Przychodz\u0105ce po\u0142\u0105czenie od -phone.contactdetails = Szczeg\u00F3\u0142y kontaktu -phone.noinfo = Brak dost\u0119pnych informacji -phone.viewfullprofile = Zobacz pe\u0142ny profil -phone.tips.mute = Wycisz te po\u0142\u0105czenie -phone.mute = Wycisz -phone.unmute = W\u0142\u0105cz d\u017Awi\u0119k -phone.tips.hold = Zawie\u015B obecne po\u0142\u0105czenie odbieraj\u0105c oczekuj\u0105ce -phone.hold = Wstrzymaj -phone.onhold = Wstrzymane -phone.time = Czas -phone.tips.transfer = Przeka\u017C to po\u0142\u0105czenie -phone.transfer = Przekaz -phone.transferring = Przekazuj\u0119 -phone.transfered = Przekazano -phone.callstartedat = Po\u0142\u0105czenie rozpocz\u0119to o -phone.callendedat = Po\u0142\u0105czenie zako\u0144czono o -phone.onphonewith = po\u0142\u0105czenie z -phone.callendedwith = Zako\u0144czono po\u0142\u0105czenie z -phone.previousconversations = Poprzednie rozmowy -phone.closeconfirm = Zamkni\u0119cie pokoju zako\u0144czy po\u0142\u0105czenie. Kontynuowa\u0107? -phone.confirmation = Potwierdzenie -phone.all = Wszystkie -phone.allcalls = Wszystkie po\u0142\u0105czenia -phone.tocall = Po\u0142\u0105cz -phone.enabled = Telefon w\u0142\u0105czony -btn.add = Dodaj -btn.edit = Edytuj -btn.del = Usu\u0144 -btn.dial = Zadzwo\u0144 -book.name = Nazwa -book.number = Numer -frame.title = Ksi\u0105\u017Cka telefoniczna -book.search = Szukaj -btn.ok = OK -btn.cancel = Anuluj -frame.add = "Dodaj wpis" -frame.edit = "Edytuj wpis" -book.exists = "Wpis, kt\u00F3ry chcesz doda\u0107 ju\u017C istnieje." -book.noEntry = "Brak wybranych wpis\u00F3w!" -book.fillFields = "Prosz\u0119 wype\u0142ni\u0107 wszystkie pola" -book.warning = "Uwaga" -title.sip.codecs.title = Kodeki -codecs.select = \u21E6 Zaznacz -codecs.unselect = Odznacz \u21E8 -codecs.up = W g\u00F3r\u0119 \u21E7 -codecs.down = W d\u00F3\u0142 \u21E9 -codecs.audio.selected = Wybierz kodeki d\u017Awi\u0119ku -codecs.audio.avail = Dost\u0119pne kodeki d\u017Awi\u0119ku \ No newline at end of file diff --git a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_zh_TW.properties b/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_zh_TW.properties deleted file mode 100644 index 6e3c8451e..000000000 --- a/src/plugins/sip/src/java/org/jivesoftware/spark/plugin/phone/resource/sip_spark_i18n_zh_TW.properties +++ /dev/null @@ -1,115 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## - -phone.starting = \u958b\u555f\u901a\u8a71\u4e2d... -phone.failed = \u958b\u555f\u901a\u8a71\u5931\u6557 -phone.tryagain = \u91cd\u8a66 -phone.call = \u547c\u53eb -phone.voicemail = \u8a9e\u97f3\u90f5\u4ef6 -phone.viewcallhistory = \u67e5\u770b\u901a\u8a71\u7d00\u9304 -phone.placecall = \u64a5\u6253\u96fb\u8a71 -phone.hangup = \u7d50\u675f\u901a\u8a71 -phone.tips.hangup = \u639b\u6389\u6b64\u901a\u8a9e\u97f3\u804a\u5929 -phone.home = \u9996\u9801 -phone.work = \u5de5\u4f5c -phone.cell = \u5143\u4ef6 -phone.currentcall = \u76ee\u524d\u547c\u53eb -phone.incomingcall = \u4f86\u96fb -phone.noprevious = \u6c92\u6709\u4ee5\u524d\u7684\u5c0d\u8a71. -phone.callended = \u901a\u8a71\u7d50\u675f -phone.transferto = \u8f49\u63a5\u96fb\u8a71\u5230 -phone.connected = \u9023\u63a5 -phone.lastcalled = \u6700\u5f8c\u901a\u8a71 -phone.never = \u5f9e\u672a -phone.duration = \u6301\u7e8c\u6642\u9593 -phone.accept = \u63a5\u53d7 -phone.reject = \u62d2\u7d55 -phone.callback = \u56de\u8986\u96fb\u8a71 -phone.delete = \u522a\u9664 -phone.enternumber = \u8f38\u5165\u8981\u64a5\u6253\u7684\u865f\u78bc. -phone.invalidnumber = \u7121\u6548\u7684\u865f\u78bc -phone.outgoingcall = \u5df2\u64a5\u51fa -phone.callhistory = \u901a\u8a71\u7d00\u9304 -phone.dialed = \u5df2\u64a5 -phone.dialedcalls = \u5df2\u64a5\u96fb\u8a71 -phone.received = \u63a5\u807d -phone.receivedcalls = \u63a5\u807d\u96fb\u8a71 -phone.missed = \u6f0f\u63a5 -phone.missedcalls = \u6f0f\u63a5\u96fb\u8a71 -phone.unknown = \u4e0d\u660e\u96fb\u8a71 -phone.placecallto = \u5df2\u64a5\u96fb\u8a71\u5230 -phone.receivedcallfrom = \u5f9e\u54ea\u88e1\u63a5\u5230\u96fb\u8a71 -phone.missedcallfrom = \u5f9e\u54ea\u88e1\u6f0f\u63a5\u96fb\u8a71 -phone.incomingcallfrom = \u5f9e\u54ea\u88e1\u4f86\u96fb -phone.contactdetails = \u806f\u7d61\u65b9\u5f0f -phone.noinfo = \u7121\u53ef\u7528\u8cc7\u6599 -phone.viewfullprofile = \u67e5\u770b\u5b8c\u6574\u500b\u4eba\u8cc7\u6599 -phone.tips.mute = \u975c\u97f3\u901a\u8a71 -phone.mute = \u975c\u97f3 -phone.unmute = \u53d6\u6d88\u975c\u97f3 -phone.tips.hold = \u9019\u901a\u96fb\u8a71\u7b49\u5f85\u63a5\u807d -phone.hold = \u901a\u8a71\u4fdd\u7559 -phone.onhold = \u7b49\u5019\u63a5\u807d -phone.time = \u6642\u9593 -phone.tips.transfer = \u5c07\u9019\u901a\u96fb\u8a71\u8f49\u63a5 -phone.transfer = \u8f49\u63a5 -phone.transferring = \u8f49\u63a5\u4e2d -phone.transfered = \u5df2\u8f49\u63a5 -phone.callstartedat = \u5728\u54ea\u88e1\u958b\u59cb\u547c\u53eb -phone.callendedat = \u5728\u54ea\u88e1\u7d50\u675f\u547c\u53eb -phone.onphonewith = \u548c\u8ab0\u901a\u8a71\u4e2d -phone.callendedwith = \u548c\u8ab0\u901a\u8a71\u7d50\u675f -phone.previousconversations = \u4e4b\u524d\u7684\u901a\u8a71 -phone.closeconfirm = \u96e2\u958b\u9019\u500b\u6703\u8b70\u5ba4\u5c07\u7d50\u675f\u901a\u8a71,\u7e7c\u7e8c\u55ce? -phone.confirmation = \u78ba\u8a8d -phone.all = \u5168\u90e8 -phone.allcalls = \u5168\u90e8\u547c\u53eb -phone.tocall = \u547c\u53eb -phone.enabled = \u555f\u52d5\u96fb\u8a71 -btn.add = \u65b0\u589e -btn.edit = \u7de8\u8f2f -btn.del = \u522a\u9664 -btn.dial = \u64a5\u865f -book.name = \u59d3\u540d -book.number = \u96fb\u8a71\u865f\u78bc -frame.title = \u96fb\u8a71\u7c3f -book.search = \u641c\u5c0b -btn.ok = \u78ba\u5b9a -btn.cancel = \u53d6\u6d88 -frame.add = "\u65b0\u589e\u9805\u76ee" -frame.edit = "\u7de8\u8f2f\u9805\u76ee" -book.exists = "\u60a8\u60f3\u8981\u65b0\u589e\u7684\u96fb\u8a71\u7c3f\u5df2\u7d93\u5b58\u5728." -book.noEntry = "\u6c92\u6709\u5165\u53e3\u9078\u64c7!" -book.fillFields = "\u8acb\u586b\u5beb\u6240\u6709\u5340\u57df" -book.warning = "\u6ce8\u610f" -title.sip.codecs.title = \u7de8\u78bc\u89e3\u78bc\u5668 -codecs.select = < \u9078\u64c7 -codecs.unselect = \u53d6\u6d88\u9078\u64c7 > -codecs.up = \u5411\u4e0a ^ -codecs.down = \u5411\u4e0b v -codecs.audio.selected = \u9078\u64c7\u7684\u97f3\u983b\u7de8\u78bc\u89e3\u78bc\u5668 \ No newline at end of file diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/CallPanelButton.java b/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/CallPanelButton.java deleted file mode 100644 index 18ed3b84e..000000000 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/CallPanelButton.java +++ /dev/null @@ -1,164 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin.components; - -import org.jivesoftware.spark.plugin.phone.resource.PhoneRes; - -import javax.swing.Icon; -import javax.swing.JButton; -import javax.swing.JFrame; - -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Image; -import java.awt.Insets; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; - -/** - * - */ -public class CallPanelButton extends JButton implements MouseListener { - - private static final long serialVersionUID = 3376625276352251288L; - private Icon normalIcon; - private Icon hoverIcon; - private Icon downIcon; - private Image backgroundImage; - private String text; - - private boolean selected; - - public CallPanelButton(Image image, String text) { - super(); - - this.text = text; - - normalIcon = PhoneRes.getImageIcon("CALLPANEL_BIG_BUTTON"); - hoverIcon = PhoneRes.getImageIcon("CALLPANEL_BIG_BUTTON_HOVER"); - downIcon = PhoneRes.getImageIcon("CALLPANEL_BIG_BUTTON_DOWN"); - backgroundImage = image; - - setIcon(normalIcon); - - decorate(); - - addMouseListener(this); - - setDisabledIcon(normalIcon); - } - - /** - * Decorates the button with the approriate UI configurations. - */ - private void decorate() { - setBorderPainted(false); - setOpaque(true); - - setContentAreaFilled(false); - setMargin(new Insets(0, 0, 0, 0)); - } - - - public void mouseClicked(MouseEvent e) { - } - - public void mousePressed(MouseEvent e) { - setIcon(downIcon); - } - - public void mouseReleased(MouseEvent e) { - if (!selected) { - setIcon(normalIcon); - } - - } - - public void mouseEntered(MouseEvent e) { - if (!selected) { - setIcon(hoverIcon); - } - setCursor(new Cursor(Cursor.HAND_CURSOR)); - } - - public void mouseExited(MouseEvent e) { - if (!selected) { - setIcon(normalIcon); - } - setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - - public void setButtonSelected(boolean selected) { - this.selected = selected; - if (selected) { - setIcon(downIcon); - } - else { - setIcon(normalIcon); - } - } - - - public void paintComponent(Graphics g) { - super.paintComponent(g); - int width = getWidth(); - int height = getHeight(); - - int x = (width - backgroundImage.getWidth(null)) / 2; - int y = (height - backgroundImage.getHeight(null)) / 2; - g.drawImage(backgroundImage, x, y - 5, null); - - if (isEnabled()) { - g.setColor(Color.black); - } - else { - g.setColor(Color.lightGray); - } - g.setFont(new Font("Dialog", Font.PLAIN, 11)); - - - int stringWidth = g.getFontMetrics().stringWidth(text); - - x = (width - stringWidth) / 2; - y = height - 12; - g.drawString(text, x, y); - - } - - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - if (!enabled) { - removeMouseListener(this); - } - else { - addMouseListener(this); - } - } - - - public static void main(String args[]) { - JFrame frame = new JFrame(); - frame.add(new EndCallButton()); - frame.pack(); - frame.setVisible(true); - } -} diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/RosterMemberCallButton.java b/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/RosterMemberCallButton.java deleted file mode 100644 index 14fdba57e..000000000 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/components/RosterMemberCallButton.java +++ /dev/null @@ -1,146 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin.components; - -import org.jivesoftware.spark.plugin.phone.resource.PhoneRes; - -import javax.swing.Icon; -import javax.swing.JButton; -import javax.swing.JFrame; - -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Image; -import java.awt.Insets; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; - -/** - * - */ -public class RosterMemberCallButton extends JButton implements MouseListener { - - private static final long serialVersionUID = 6038719724559294212L; - private Icon normalIcon; - private Icon hoverIcon; - private Icon downIcon; - private Image backgroundImage; - private String text; - - private boolean selected; - - public RosterMemberCallButton(Image image, String text) { - super(); - - this.text = text; - - normalIcon = PhoneRes.getImageIcon("ROSTERPANEL_BUTTON"); - hoverIcon = PhoneRes.getImageIcon("ROSTERPANEL_BUTTON_HOVER"); - downIcon = PhoneRes.getImageIcon("ROSTERPANEL_BUTTON_DOWN"); - backgroundImage = image; - - setIcon(normalIcon); - - decorate(); - - addMouseListener(this); - } - - /** - * Decorates the button with the approriate UI configurations. - */ - private void decorate() { - setBorderPainted(false); - setOpaque(true); - - setContentAreaFilled(false); - setMargin(new Insets(0, 0, 0, 0)); - } - - - public void mouseClicked(MouseEvent e) { - } - - public void mousePressed(MouseEvent e) { - setIcon(downIcon); - } - - public void mouseReleased(MouseEvent e) { - if (!selected) { - setIcon(normalIcon); - } - - } - - public void mouseEntered(MouseEvent e) { - if (!selected) { - setIcon(hoverIcon); - } - setCursor(new Cursor(Cursor.HAND_CURSOR)); - } - - public void mouseExited(MouseEvent e) { - if (!selected) { - setIcon(normalIcon); - } - setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - - public void setButtonSelected(boolean selected) { - this.selected = selected; - if (selected) { - setIcon(downIcon); - } - else { - setIcon(normalIcon); - } - } - - - public void paintComponent(Graphics g) { - super.paintComponent(g); - int width = getWidth(); - int height = getHeight(); - - int x = (width - backgroundImage.getWidth(null)) / 2; - int y = (height - backgroundImage.getHeight(null)) / 2; - g.drawImage(backgroundImage, 5, y, null); - - g.setColor(Color.black); - g.setFont(new Font("Dialog", Font.PLAIN, 11)); - - - int stringWidth = g.getFontMetrics().stringWidth(text); - - x = (width - stringWidth) / 2; - y = (height + 11) / 2; - g.drawString(text, x, y); - - } - - public static void main(String args[]) { - JFrame frame = new JFrame(); - frame.add(new RosterMemberCallButton(PhoneRes.getImageIcon("MUTE_IMAGE").getImage(), "Mute")); - frame.pack(); - frame.setVisible(true); - } -} diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/IncomingCallUI.java b/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/IncomingCallUI.java deleted file mode 100644 index 1d69a10fa..000000000 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/IncomingCallUI.java +++ /dev/null @@ -1,259 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin.ui.call; - -import java.awt.Color; -import java.awt.Font; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.image.BufferedImage; -import java.text.SimpleDateFormat; -import java.util.Date; - -import javax.swing.BorderFactory; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import net.java.sipmack.sip.InterlocutorUI; -import net.java.sipmack.softphone.SoftPhoneManager; - -import org.jivesoftware.smackx.vcardtemp.packet.VCard; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.component.RolloverButton; -import org.jivesoftware.spark.plugin.phone.resource.PhoneRes; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkplugin.callhistory.HistoryCall; -import org.jivesoftware.sparkplugin.callhistory.TelephoneUtils; - - -public class IncomingCallUI extends JPanel { - - private static final long serialVersionUID = -7451049865930942296L; - private JLabel avatarLabel = new JLabel(); - private JLabel titleLabel = new JLabel(); - private JLabel professionLabel = new JLabel(); - private JLabel phoneLabel = new JLabel(); - private JLabel lastCalledLabel = new JLabel(); - private JLabel durationLabel = new JLabel(); - - private RolloverButton acceptButton; - private RolloverButton rejectButton; - - private final SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); - - - public IncomingCallUI(InterlocutorUI ic) { - setLayout(new GridBagLayout()); - - final JLabel topLabel = new JLabel(); - topLabel.setIcon(PhoneRes.getImageIcon("INCOMING_CALL_IMAGE")); - topLabel.setHorizontalTextPosition(JLabel.RIGHT); - topLabel.setFont(new Font("Dialog", Font.BOLD, 15)); - topLabel.setText(PhoneRes.getIString("phone.incomingcallfrom")+"..."); - topLabel.setForeground(Color.gray); - - - final String phoneNumber = ic.getCall().getNumber(); - - // Add Top Label - add(topLabel, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); - - boolean callerID = !ic.getCall().getNumber().equals(ic.getCall().getRemoteName()); - String title = ic.getCall().getRemoteName(); - if(!callerID){ - title = phoneNumber; - } - - // Add Caller Block - buildCallerBlock(title, phoneNumber); - - // Add Buttons - addButtons(); - } - - - /** - * Builds the part of the incoming call UI with the Callers information. - */ - private void buildCallerBlock(String callerID, String phoneNumber) { - final JPanel panel = new JPanel(new GridBagLayout()); - panel.setBackground(Color.white); - panel.setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230), 1)); - - // Add Avatar - panel.add(avatarLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 0, 5, 0), 0, 0)); - - // Add Avatar information - panel.add(titleLabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 0), 0, 0)); - panel.add(professionLabel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 0, 0), 0, 0)); - panel.add(phoneLabel, new GridBagConstraints(1, 2, 1, 1, 0.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 0, 0), 0, 0)); - - // Add History labels - panel.add(lastCalledLabel, new GridBagConstraints(0, 3, 2, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(15, 5, 0, 0), 0, 0)); - panel.add(durationLabel, new GridBagConstraints(0, 4, 2, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 0), 0, 0)); - - // Set default settings - titleLabel.setForeground(new Color(64, 103, 162)); - titleLabel.setFont(new Font("Dialog", Font.BOLD, 16)); - - final VCard vcard = SparkManager.getVCardManager().searchPhoneNumber(phoneNumber); - if (vcard != null) { - handleVCardInformation(vcard, phoneNumber); - } - else { - avatarLabel.setVisible(false); - professionLabel.setVisible(false); - phoneLabel.setVisible(true); - - titleLabel.setText(callerID); - phoneLabel.setText(phoneNumber); - } - - // Update with previous call history. - Date lastDate = null; - long callLength = 0; - for (HistoryCall call : SoftPhoneManager.getInstance().getLogManager().getCallHistory()) { - String number = TelephoneUtils.removeInvalidChars(call.getNumber()); - if (number.equals(TelephoneUtils.removeInvalidChars(phoneNumber))) { - lastDate = new Date(call.getTime()); - } - - callLength = call.getCallLength(); - } - - final StringBuilder builder = new StringBuilder(); - builder.append(PhoneRes.getIString("phone.lastcalled")+": "); - if (lastDate == null) { - builder.append(PhoneRes.getIString("phone.never")); - durationLabel.setVisible(false); - } - else { - builder.append(formatter.format(lastDate)); - durationLabel.setText(PhoneRes.getIString("phone.duration")+": " + ModelUtil.getTimeFromLong(callLength*1000)); - } - - lastCalledLabel.setText(builder.toString()); - - // Add To Panel - add(panel, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); - } - - private void addButtons() { - // Build Accept Button - acceptButton = new RolloverButton(" "+PhoneRes.getIString("phone.accept"), PhoneRes.getImageIcon("TOASTER_ACCEPT_BUTTON")); - acceptButton.setHorizontalTextPosition(JLabel.CENTER); - acceptButton.setFont(new Font("Dialog", Font.BOLD, 11)); - acceptButton.setForeground(new Color(91, 175, 41)); - acceptButton.setMargin(new Insets(0, 0, 0, 0)); - - // Build Reject Button - rejectButton = new RolloverButton(" "+PhoneRes.getIString("phone.reject"), PhoneRes.getImageIcon("TOASTER_REJECT_BUTTON")); - rejectButton.setHorizontalTextPosition(JLabel.CENTER); - rejectButton.setFont(new Font("Dialog", Font.BOLD, 11)); - rejectButton.setForeground(new Color(153, 32, 10)); - rejectButton.setMargin(new Insets(0, 0, 0, 0)); - - final JPanel panel = new JPanel(new GridBagLayout()); - panel.setOpaque(false); - panel.add(acceptButton, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - panel.add(rejectButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - - add(panel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); - } - - private void handleVCardInformation(VCard vcard, String phoneNumber) { - if (vcard.getError() != null) { - return; - } - - - String firstName = vcard.getFirstName(); - String lastName = vcard.getLastName(); - if (ModelUtil.hasLength(firstName) && ModelUtil.hasLength(lastName)) { - titleLabel.setText(firstName + " " + lastName); - } - else if (ModelUtil.hasLength(firstName)) { - titleLabel.setText(firstName); - } - - phoneLabel.setText(phoneNumber); - - - String jobTitle = vcard.getField("TITLE"); - if (jobTitle != null) { - professionLabel.setText(jobTitle); - } - - - byte[] avatarBytes = null; - try { - avatarBytes = vcard.getAvatar(); - } - catch (Exception e) { - Log.error("Cannot retrieve avatar bytes.", e); - } - - if (avatarBytes != null) { - try { - ImageIcon avatarIcon = new ImageIcon(avatarBytes); - avatarLabel.setIcon(avatarIcon); - avatarLabel.invalidate(); - avatarLabel.validate(); - avatarLabel.repaint(); - } - catch (Exception e) { - // no issue - } - } - - - invalidate(); - validate(); - repaint(); - } - - public RolloverButton getAcceptButton() { - return acceptButton; - } - - public RolloverButton getRejectButton() { - return rejectButton; - } - - - public void paintComponent(Graphics g) { - BufferedImage cache = new BufferedImage(2, getHeight(), BufferedImage.TYPE_INT_RGB); - Graphics2D g2d = cache.createGraphics(); - - GradientPaint paint = new GradientPaint(0, 0, new Color(233, 240, 247), 0, getHeight(), Color.white, true); - - g2d.setPaint(paint); - g2d.fillRect(0, 0, getWidth(), getHeight()); - g2d.dispose(); - - g.drawImage(cache, 0, 0, getWidth(), getHeight(), null); - } -} diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/PreviousConversationPanel.java b/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/PreviousConversationPanel.java deleted file mode 100644 index 75a24d42e..000000000 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/call/PreviousConversationPanel.java +++ /dev/null @@ -1,229 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jivesoftware.sparkplugin.ui.call; - -import org.jivesoftware.sparkplugin.callhistory.HistoryCall; -import org.jivesoftware.sparkplugin.callhistory.TelephoneUtils; -import org.jivesoftware.spark.plugin.phone.resource.PhoneRes; -import net.java.sipmack.softphone.SoftPhoneManager; -import org.jivesoftware.spark.component.TimeTrackingLabel; -import org.jivesoftware.spark.component.VerticalFlowLayout; -import org.jivesoftware.spark.util.ModelUtil; - -import java.awt.Color; -import java.awt.FlowLayout; -import java.awt.Font; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.List; - -import javax.swing.BorderFactory; -import javax.swing.JLabel; -import javax.swing.JPanel; - -/** - * - */ -public class PreviousConversationPanel extends JPanel { - - - private static final long serialVersionUID = -3462528114523564888L; - - private final Color greenColor = new Color(91, 175, 41); - - private final JLabel currentCallLabel = new JLabel(); - private final JPanel timePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 0)); - - private final JLabel today = new JLabel(); - private final JLabel statusLabel = new JLabel(); - - final JLabel previousLabel = new JLabel(PhoneRes.getIString("phone.previousconversations")+":"); - private final JLabel oldConversation = new JLabel(); - - private final SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy, h:mm a"); - - - private TimeTrackingLabel durationLabel; - - private Date startTime; - - - public PreviousConversationPanel() { - setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 5, 0, true, false)); - - setBackground(Color.white); - setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230))); - - // Set Default Color for Current Call Label - currentCallLabel.setText(PhoneRes.getIString("phone.currentcall")+":"); - currentCallLabel.setFont(new Font("Dialog", Font.BOLD, 13)); - currentCallLabel.setForeground(greenColor); - - // Set default color for previous label. - previousLabel.setForeground(new Color(64, 103, 162)); - previousLabel.setFont(new Font("Dialog", Font.BOLD, 13)); - - statusLabel.setFont(new Font("Dialog", Font.BOLD, 12)); - - // Add Duration timer - durationLabel = new TimeTrackingLabel(new Date(), this); - durationLabel.setFont(new Font("Dialog", Font.BOLD, 12)); - durationLabel.stopTimer(); - - // Build Time Panel - - timePanel.setOpaque(false); - - today.setForeground(Color.black); - today.setFont(new Font("Dialog", Font.PLAIN, 12)); - - today.setText(formatter.format(new Date()) + " - "+PhoneRes.getIString("phone.time")+": "); - timePanel.add(today); - timePanel.add(durationLabel); - - oldConversation.setForeground(new Color(211, 0, 0)); - oldConversation.setFont(new Font("Dialog", Font.BOLD, 12)); - - } - - /** - * Builds the previous history list. - * - * @param phoneNumber the phone number to use for history checking. - */ - public void addPreviousConversations(String phoneNumber) { - startTime = new Date(); - - currentCallLabel.setText(PhoneRes.getIString("phone.currentcall")+":"); - currentCallLabel.setFont(new Font("Dialog", Font.BOLD, 13)); - currentCallLabel.setForeground(greenColor); - - today.setText(formatter.format(new Date()) + " - "+PhoneRes.getIString("phone.time")+": "); - - // Add Current Call and Time Panel - add(currentCallLabel); - add(timePanel); - add(statusLabel); - statusLabel.setVisible(false); - - // Give some space. - add(new JLabel()); - - add(previousLabel); - - add(oldConversation); - - - int count = 0; - final List calls = new ArrayList(SoftPhoneManager.getInstance().getLogManager().getCallHistory()); - Collections.sort(calls, itemComparator); - - for (HistoryCall call : calls){ - String number = TelephoneUtils.removeInvalidChars(call.getNumber()); - if (number.equals(TelephoneUtils.removeInvalidChars(phoneNumber))) { - count++; - if (count > 4) { - break; - } - - final Date callDate = new Date(call.getTime()); - final long duration = call.getCallLength(); - - StringBuilder builder = new StringBuilder(); - builder.append(formatter.format(callDate)); - builder.append(" "); - builder.append("("); - builder.append(ModelUtil.getTimeFromLong(duration*1000)); - builder.append(")"); - - final JLabel callLabel = new JLabel(builder.toString()); - callLabel.setForeground(Color.black); - callLabel.setFont(new Font("Dialog", Font.PLAIN, 12)); - add(callLabel); - } - } - - if (count == 0) { - final JLabel label = new JLabel(PhoneRes.getIString("phone.noprevious")); - label.setForeground(Color.gray); - add(label); - } - - durationLabel.resetTime(); - durationLabel.startTimer(); - - invalidate(); - validate(); - repaint(); - } - - public void callEnded() { - durationLabel.stopTimer(); - - currentCallLabel.setForeground(Color.black); - currentCallLabel.setText(PhoneRes.getIString("phone.callended")); - - today.setText(PhoneRes.getIString("phone.time")+": "); - } - - public void transferring() { - statusLabel.setText(PhoneRes.getIString("phone.transferring")); - statusLabel.setVisible(true); - } - - public void transfer(String user) { - durationLabel.stopTimer(); - statusLabel.setVisible(false); - - currentCallLabel.setForeground(Color.black); - currentCallLabel.setText(PhoneRes.getIString("phone.callended")); - - today.setText(PhoneRes.getIString("phone.time")+": "); - currentCallLabel.setText(PhoneRes.getIString("phone.transferto") + " " + user); - - Date now = new Date(); - final SimpleDateFormat timeFormatter = new SimpleDateFormat("h:mm"); - - - String end = timeFormatter.format(now); - - oldConversation.setText(formatter.format(startTime) + " - " + end + " (" + durationLabel.getText() + ")"); - } - - final Comparator itemComparator = new Comparator() { - public int compare(HistoryCall contactItemOne, HistoryCall contactItemTwo) { - final HistoryCall time1 = contactItemOne; - final HistoryCall time2 = contactItemTwo; - if (time1.getTime() < time2.getTime()) { - return 1; - } - else if (time1.getTime() > time2.getTime()) { - return -1; - } - return 0; - - } - }; - -} diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/components/ControlPanel.java b/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/components/ControlPanel.java deleted file mode 100644 index 22277f0a4..000000000 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/components/ControlPanel.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin.ui.components; - -import java.awt.Color; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.LayoutManager; -import java.awt.image.BufferedImage; - -import javax.swing.BorderFactory; -import javax.swing.JPanel; - -/** - * Base Panel for Controls. - * - * @author Derek DeMoro - */ -public class ControlPanel extends JPanel { - - private static final long serialVersionUID = -8596701082529183291L; - - public ControlPanel() { - setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230))); - } - - public ControlPanel(LayoutManager layout) { - super(layout); - setBorder(BorderFactory.createLineBorder(new Color(197, 213, 230))); - } - - public void paintComponent(Graphics g) { - final BufferedImage bufferedImage = new BufferedImage(2, getHeight(), BufferedImage.TYPE_INT_RGB); - Graphics2D g2d = bufferedImage.createGraphics(); - - GradientPaint paint = new GradientPaint(0, 0, Color.white, 0, getHeight(), new Color(235, 241, 246), true); - - g2d.setPaint(paint); - g2d.fillRect(0, 0, getWidth(), getHeight()); - g2d.dispose(); - - g.drawImage(bufferedImage, 0, 0, getWidth(), getHeight(), null); - } -} diff --git a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/components/JavaMixer.java b/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/components/JavaMixer.java deleted file mode 100644 index 6d267dea8..000000000 --- a/src/plugins/sip/src/java/org/jivesoftware/sparkplugin/ui/components/JavaMixer.java +++ /dev/null @@ -1,492 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.sparkplugin.ui.components; -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; - -import javax.sound.sampled.AudioSystem; -import javax.sound.sampled.BooleanControl; -import javax.sound.sampled.CompoundControl; -import javax.sound.sampled.Control; -import javax.sound.sampled.DataLine; -import javax.sound.sampled.EnumControl; -import javax.sound.sampled.FloatControl; -import javax.sound.sampled.Line; -import javax.sound.sampled.LineUnavailableException; -import javax.sound.sampled.Mixer; -import javax.sound.sampled.Port; -import javax.swing.AbstractButton; -import javax.swing.BoundedRangeModel; -import javax.swing.ButtonModel; -import javax.swing.DefaultBoundedRangeModel; -import javax.swing.DefaultButtonModel; -import javax.swing.JCheckBox; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.JSlider; -import javax.swing.JTree; -import javax.swing.border.EtchedBorder; -import javax.swing.border.TitledBorder; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; - -/** - * Pure Java Audio Mixer. Control Volume and Settings for any Sound device in the OS. - * - * @author Thiago Camargo - */ - -public class JavaMixer { - - private static final Line.Info[] EMPTY_PORT_INFO_ARRAY = new Line.Info[0]; - DefaultMutableTreeNode root = new DefaultMutableTreeNode("Sound Mixers", true); - JTree tree = new JTree(root); - - public JavaMixer() { - List portMixers = getPortMixers(); - if (portMixers.size() == 0) System.err.println("No Mixers Found."); - for (Mixer mixer : portMixers) { - JavaMixer.MixerNode mixerNode = new JavaMixer.MixerNode(mixer); - createMixerChildren(mixerNode); - root.add(mixerNode); - } - } - - public JTree getTree() { - return tree; - } - - public Component getPrefferedMasterVolume() { - TreePath path = findByName(new TreePath(root), new String[]{"SPEAKER", "Volume"}); - - if (path == null) { - path = findByName(new TreePath(root), new String[]{"Master target", "Master", "Mute"}); - } - - if (path != null) { - if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) - return ((JavaMixer.ControlNode) path.getLastPathComponent()).getComponent(); - } - return null; - } - - public Component getPrefferedInputVolume() { - TreePath path = findByName(new TreePath(root), new String[]{"MICROPHONE", "Volume"}); - - if (path == null) { - path = findByName(new TreePath(root), new String[]{"Capture source", "Capture", "Volume"}); - } - - if (path != null) { - if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) - return ((JavaMixer.ControlNode) path.getLastPathComponent()).getComponent(); - } - return null; - } - - public void setMicrophoneInput() { - TreePath path = findByName(new TreePath(root), new String[]{"MICROPHONE", "Select"}); - - if (path == null) { - path = findByName(new TreePath(root), new String[]{"Capture source", "Capture", "Mute"}); - } - - if (path != null) { - if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) { - BooleanControl bControl = (BooleanControl) (((JavaMixer.ControlNode) path.getLastPathComponent()).getControl()); - bControl.setValue(true); - } - } - } - - public void setMuteForMicrophoneOutput() { - TreePath path = findByName(new TreePath(root), new String[]{"SPEAKER", "Microfone", "Mute"}); - - if (path == null) { - path = findByName(new TreePath(root), new String[]{"MIC target", "mic", "Mute"}); - } - - if (path != null) { - if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) { - BooleanControl bControl = (BooleanControl) (((JavaMixer.ControlNode) path.getLastPathComponent()).getControl()); - bControl.setValue(true); - } - } - } - - /** - * Returns the Mixers that support Port lines. - * - * @return List Port Mixers - */ - private List getPortMixers() { - List supportingMixers = new ArrayList(); - Mixer.Info[] aMixerInfos = AudioSystem.getMixerInfo(); - for (Mixer.Info aMixerInfo : aMixerInfos) { - Mixer mixer = AudioSystem.getMixer(aMixerInfo); - boolean bSupportsPorts = arePortsSupported(mixer); - if (bSupportsPorts) { - supportingMixers.add(mixer); - } - } - return supportingMixers; - } - - private boolean arePortsSupported(Mixer mixer) { - Line.Info[] infos; - infos = mixer.getSourceLineInfo(); - for (Line.Info info : infos) { - if (info instanceof Port.Info) { - return true; - } else if (info instanceof DataLine.Info) { - return true; - } - } - infos = mixer.getTargetLineInfo(); - for (Line.Info info : infos) { - if (info instanceof Port.Info) { - return true; - } else if (info instanceof DataLine.Info) { - return true; - } - } - return false; - } - - private void createMixerChildren(JavaMixer.MixerNode mixerNode) { - Mixer mixer = mixerNode.getMixer(); - Line.Info[] infosToCheck = getPortInfo(mixer); - - for (Line.Info anInfosToCheck : infosToCheck) { - if (mixer.isLineSupported(anInfosToCheck)) { - Port port = null; - DataLine dLine = null; - - int maxLines = mixer.getMaxLines(anInfosToCheck); - // Workaround to prevent a JVM crash on Mac OS X (Intel) 1.5.0_07 JVM - if (maxLines > 0) { - try { - if (anInfosToCheck instanceof Port.Info) { - port = (Port) mixer.getLine(anInfosToCheck); - port.open(); - } - else if (anInfosToCheck instanceof DataLine.Info) { - dLine = (DataLine) mixer.getLine(anInfosToCheck); - if (!dLine.isOpen()) { - dLine.open(); - } - } - } - catch (LineUnavailableException e) { - // Do Nothing - } - catch (Exception e) { - // Do Nothing - } - } - if (port != null) { - JavaMixer.PortNode portNode = new JavaMixer.PortNode(port); - createPortChildren(portNode); - mixerNode.add(portNode); - } else if (dLine != null) { - JavaMixer.PortNode portNode = new JavaMixer.PortNode(dLine); - createPortChildren(portNode); - mixerNode.add(portNode); - } - } - } - } - - private Line.Info[] getPortInfo(Mixer mixer) { - Line.Info[] infos; - List portInfoList = new ArrayList(); - infos = mixer.getSourceLineInfo(); - for (Line.Info info : infos) { - if (info instanceof Port.Info || info instanceof DataLine.Info) { - portInfoList.add((Line.Info) info); - } - } - infos = mixer.getTargetLineInfo(); - for (Line.Info info1 : infos) { - if (info1 instanceof Port.Info || info1 instanceof DataLine.Info) { - portInfoList.add((Line.Info) info1); - } - } - return portInfoList.toArray(EMPTY_PORT_INFO_ARRAY); - } - - private void createPortChildren(JavaMixer.PortNode portNode) { - Control[] aControls = portNode.getPort().getControls(); - for (Control aControl : aControls) { - JavaMixer.ControlNode controlNode = new JavaMixer.ControlNode(aControl); - createControlChildren(controlNode); - portNode.add(controlNode); - } - } - - private void createControlChildren(JavaMixer.ControlNode controlNode) { - if (controlNode.getControl() instanceof CompoundControl) { - CompoundControl control = (CompoundControl) controlNode.getControl(); - Control[] aControls = control.getMemberControls(); - for (Control con : aControls) { - JavaMixer.ControlNode conNode = new JavaMixer.ControlNode(con); - createControlChildren(conNode); - controlNode.add(conNode); - } - } - } - - /** - * Returns whether the type of a FloatControl is BALANCE or PAN. - * - * @param control FloatControl control - * @return boolean is Balance or Pan - */ - private static boolean isBalanceOrPan(FloatControl control) { - Control.Type type = control.getType(); - return type.equals(FloatControl.Type.PAN) || type.equals(FloatControl.Type.BALANCE); - } - - public class MixerNode extends DefaultMutableTreeNode { - - private static final long serialVersionUID = 5514718793497318648L; - Mixer mixer; - - public MixerNode(Mixer mixer) { - super(mixer.getMixerInfo(), true); - this.mixer = mixer; - } - - public Mixer getMixer() { - return mixer; - } - - } - - public class PortNode extends DefaultMutableTreeNode { - - private static final long serialVersionUID = -4388437363589688167L; - Line port; - - public PortNode(Line port) { - super(port.getLineInfo(), true); - this.port = port; - } - - public Line getPort() { - return port; - } - - } - - public class ControlNode extends DefaultMutableTreeNode { - - private static final long serialVersionUID = 8840473247266403685L; - Control control; - Component component; - - public ControlNode(Control control) { - super(control.getType(), true); - this.control = control; - if (control instanceof BooleanControl) { - component = createControlComponent((BooleanControl) control); - } else if (control instanceof EnumControl) { - component = createControlComponent((EnumControl) control); - } else if (control instanceof FloatControl) { - component = createControlComponent((FloatControl) control); - } else { - component = null; - } - } - - public Control getControl() { - return control; - } - - public Component getComponent() { - return component; - } - - private JComponent createControlComponent(BooleanControl control) { - AbstractButton button; - String strControlName = control.getType().toString(); - ButtonModel model = new JavaMixer.BooleanControlButtonModel(control); - button = new JCheckBox(strControlName); - button.setModel(model); - return button; - } - - private JComponent createControlComponent(EnumControl control) { - JPanel component = new JPanel(); - String strControlName = control.getType().toString(); - component.setBorder(new TitledBorder(new EtchedBorder(), strControlName)); - return component; - } - - private JComponent createControlComponent(FloatControl control) { - int orientation = isBalanceOrPan(control) ? JSlider.HORIZONTAL : JSlider.VERTICAL; - BoundedRangeModel model = new JavaMixer.FloatControlBoundedRangeModel(control); - JSlider slider = new JSlider(model); - slider.setOrientation(orientation); - slider.setPaintLabels(true); - slider.setPaintTicks(true); - slider.setSize(10, 50); - return slider; - } - - } - - public class BooleanControlButtonModel extends DefaultButtonModel { - private static final long serialVersionUID = -8264153878420797906L; - private BooleanControl control; - - public BooleanControlButtonModel(BooleanControl control) { - this.control = control; - this.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - setSelected(!isSelected()); - } - }); - } - - public void setSelected(boolean bSelected) { - control.setValue(bSelected); - } - - public boolean isSelected() { - return control.getValue(); - } - } - - public class FloatControlBoundedRangeModel extends DefaultBoundedRangeModel { - - private static final long serialVersionUID = 7826447995854231838L; - private FloatControl control; - private float factor; - - public FloatControlBoundedRangeModel(FloatControl control) { - this.control = control; - float range = 100; - float steps = range / 100; - factor = range / steps; - int min = (int) (control.getMinimum() * factor); - int max = (int) (control.getMaximum() * factor); - int value = (int) (control.getValue() * factor); - setRangeProperties(value, 0, min, max, false); - } - - private float getScaleFactor() { - return factor; - } - - public void setValue(int nValue) { - super.setValue(nValue); - control.setValue((float) nValue / getScaleFactor()); - } - - public int getValue() { - return (int) (control.getValue() * getScaleFactor()); - } - - } - - public static void main(String[] args) { - final JavaMixer sm = new JavaMixer(); - final JFrame jf = new JFrame("Mixer Test"); - final JPanel jp = new JPanel(); - jf.add(jp); - jp.add(sm.getTree()); - jf.setSize(600, 500); - jf.setVisible(true); - jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - sm.getTree().addTreeSelectionListener(new TreeSelectionListener() { - public void valueChanged(TreeSelectionEvent e) { - TreePath path = e.getPath(); - if (path.getLastPathComponent() instanceof JavaMixer.ControlNode) { - JavaMixer.ControlNode controlNode = (JavaMixer.ControlNode) path.getLastPathComponent(); - if (!(controlNode.getControl() instanceof CompoundControl)) { - if (jp.getComponentCount() > 1) - jp.remove(1); - jp.add(controlNode.getComponent(), 1); - jp.repaint(); - } - } - } - }); - jp.add(sm.getPrefferedMasterVolume()); - jp.add(sm.getPrefferedMasterVolume()); - jp.add(sm.getPrefferedInputVolume()); - jp.repaint(); - sm.setMicrophoneInput(); - sm.setMuteForMicrophoneOutput(); - } - - public TreePath find(TreePath path, Object[] nodes) { - return find2(path, nodes, 0, false); - } - - public TreePath findByName(TreePath path, String[] names) { - return find2(path, names, 0, true); - } - - private TreePath find2(TreePath parent, Object[] nodes, int depth, boolean byName) { - TreeNode node = (TreeNode) parent.getLastPathComponent(); - if (depth > nodes.length - 1) { - return parent; - } - - if (node.getChildCount() >= 0) { - for (Enumeration e = node.children(); e.hasMoreElements();) { - TreeNode n = e.nextElement(); - TreePath path = parent.pathByAddingChild(n); - boolean find; - - if (byName) { - find = n.toString().toUpperCase().indexOf(nodes[depth].toString().toUpperCase()) > -1; - } else { - find = n.equals(nodes[depth]); - } - - if (find) { - TreePath result = find2(path, nodes, depth + 1, byName); - if (result != null) { - return result; - } - } else { - TreePath result = find2(path, nodes, depth, byName); - if (result != null) { - return result; - } - } - } - } - - return null; - } -} diff --git a/src/plugins/sip/src/resources/images/add_number.png b/src/plugins/sip/src/resources/images/add_number.png deleted file mode 100755 index a871081ed..000000000 Binary files a/src/plugins/sip/src/resources/images/add_number.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/btn_dialpad_background.png b/src/plugins/sip/src/resources/images/btn_dialpad_background.png deleted file mode 100644 index 270ec3ea7..000000000 Binary files a/src/plugins/sip/src/resources/images/btn_dialpad_background.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/btn_phone-dial-disabled_24x24.png b/src/plugins/sip/src/resources/images/btn_phone-dial-disabled_24x24.png deleted file mode 100644 index 16983c672..000000000 Binary files a/src/plugins/sip/src/resources/images/btn_phone-dial-disabled_24x24.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/btn_phone-hangup.png b/src/plugins/sip/src/resources/images/btn_phone-hangup.png deleted file mode 100644 index 40e80bd00..000000000 Binary files a/src/plugins/sip/src/resources/images/btn_phone-hangup.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/btn_phone-hangup_24x24.png b/src/plugins/sip/src/resources/images/btn_phone-hangup_24x24.png deleted file mode 100644 index 2f7b7e3ab..000000000 Binary files a/src/plugins/sip/src/resources/images/btn_phone-hangup_24x24.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/btn_phone-redial-big.png b/src/plugins/sip/src/resources/images/btn_phone-redial-big.png deleted file mode 100644 index e900706e3..000000000 Binary files a/src/plugins/sip/src/resources/images/btn_phone-redial-big.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/btn_phone-reg_close-hover.png b/src/plugins/sip/src/resources/images/btn_phone-reg_close-hover.png deleted file mode 100644 index 9086f61de..000000000 Binary files a/src/plugins/sip/src/resources/images/btn_phone-reg_close-hover.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/btn_phone-reg_close.png b/src/plugins/sip/src/resources/images/btn_phone-reg_close.png deleted file mode 100644 index 88853e71e..000000000 Binary files a/src/plugins/sip/src/resources/images/btn_phone-reg_close.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/btn_phone-sm.png b/src/plugins/sip/src/resources/images/btn_phone-sm.png deleted file mode 100644 index ec6248d75..000000000 Binary files a/src/plugins/sip/src/resources/images/btn_phone-sm.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/callList_16x16.png b/src/plugins/sip/src/resources/images/callList_16x16.png deleted file mode 100644 index 3c016099f..000000000 Binary files a/src/plugins/sip/src/resources/images/callList_16x16.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/callOut_32x32.png b/src/plugins/sip/src/resources/images/callOut_32x32.png deleted file mode 100644 index 1078435b7..000000000 Binary files a/src/plugins/sip/src/resources/images/callOut_32x32.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/close_dark.png b/src/plugins/sip/src/resources/images/close_dark.png deleted file mode 100644 index 87a082c64..000000000 Binary files a/src/plugins/sip/src/resources/images/close_dark.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/contact_48x48.png b/src/plugins/sip/src/resources/images/contact_48x48.png deleted file mode 100644 index 1f5e1d86b..000000000 Binary files a/src/plugins/sip/src/resources/images/contact_48x48.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/del_number.png b/src/plugins/sip/src/resources/images/del_number.png deleted file mode 100755 index 587921026..000000000 Binary files a/src/plugins/sip/src/resources/images/del_number.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/delete_24x24.png b/src/plugins/sip/src/resources/images/delete_24x24.png deleted file mode 100644 index 587921026..000000000 Binary files a/src/plugins/sip/src/resources/images/delete_24x24.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/delete_32x32.png b/src/plugins/sip/src/resources/images/delete_32x32.png deleted file mode 100644 index 7a8f47a7f..000000000 Binary files a/src/plugins/sip/src/resources/images/delete_32x32.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/dial.png b/src/plugins/sip/src/resources/images/dial.png deleted file mode 100644 index 8e5d5f0e4..000000000 Binary files a/src/plugins/sip/src/resources/images/dial.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/hangup_32x32.png b/src/plugins/sip/src/resources/images/hangup_32x32.png deleted file mode 100644 index 60e9fa8c7..000000000 Binary files a/src/plugins/sip/src/resources/images/hangup_32x32.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/history.png b/src/plugins/sip/src/resources/images/history.png deleted file mode 100644 index c3a970fc1..000000000 Binary files a/src/plugins/sip/src/resources/images/history.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/hold_128x128.png b/src/plugins/sip/src/resources/images/hold_128x128.png deleted file mode 100644 index 710ba62f1..000000000 Binary files a/src/plugins/sip/src/resources/images/hold_128x128.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/icon_call-incoming_42x22.png b/src/plugins/sip/src/resources/images/icon_call-incoming_42x22.png deleted file mode 100644 index dd0fa2cff..000000000 Binary files a/src/plugins/sip/src/resources/images/icon_call-incoming_42x22.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/icon_grey_microphone_16x16.png b/src/plugins/sip/src/resources/images/icon_grey_microphone_16x16.png deleted file mode 100644 index 2a31a30a6..000000000 Binary files a/src/plugins/sip/src/resources/images/icon_grey_microphone_16x16.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/icon_grey_phone-hangup_24x24.png b/src/plugins/sip/src/resources/images/icon_grey_phone-hangup_24x24.png deleted file mode 100644 index 6d45abc9a..000000000 Binary files a/src/plugins/sip/src/resources/images/icon_grey_phone-hangup_24x24.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/icon_grey_phone-hold_24x24.png b/src/plugins/sip/src/resources/images/icon_grey_phone-hold_24x24.png deleted file mode 100644 index bc12dfaa0..000000000 Binary files a/src/plugins/sip/src/resources/images/icon_grey_phone-hold_24x24.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/icon_grey_phone-mute_24x24.png b/src/plugins/sip/src/resources/images/icon_grey_phone-mute_24x24.png deleted file mode 100644 index 5d9c09695..000000000 Binary files a/src/plugins/sip/src/resources/images/icon_grey_phone-mute_24x24.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/icon_grey_phone-redial_24x24.png b/src/plugins/sip/src/resources/images/icon_grey_phone-redial_24x24.png deleted file mode 100644 index f39ad3efb..000000000 Binary files a/src/plugins/sip/src/resources/images/icon_grey_phone-redial_24x24.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/icon_grey_phone-transfer_24x24.png b/src/plugins/sip/src/resources/images/icon_grey_phone-transfer_24x24.png deleted file mode 100644 index 241081d7c..000000000 Binary files a/src/plugins/sip/src/resources/images/icon_grey_phone-transfer_24x24.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/icon_grey_speaker_16x16.png b/src/plugins/sip/src/resources/images/icon_grey_speaker_16x16.png deleted file mode 100644 index 3ec288c35..000000000 Binary files a/src/plugins/sip/src/resources/images/icon_grey_speaker_16x16.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/icon_microphone_16x16.png b/src/plugins/sip/src/resources/images/icon_microphone_16x16.png deleted file mode 100644 index 1a6ccbbf8..000000000 Binary files a/src/plugins/sip/src/resources/images/icon_microphone_16x16.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/icon_microphone_24x24.png b/src/plugins/sip/src/resources/images/icon_microphone_24x24.png deleted file mode 100644 index b319dedc2..000000000 Binary files a/src/plugins/sip/src/resources/images/icon_microphone_24x24.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/icon_phone-hold_24x24.png b/src/plugins/sip/src/resources/images/icon_phone-hold_24x24.png deleted file mode 100644 index cc11ec6d8..000000000 Binary files a/src/plugins/sip/src/resources/images/icon_phone-hold_24x24.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/icon_phone-mute_24x24.png b/src/plugins/sip/src/resources/images/icon_phone-mute_24x24.png deleted file mode 100644 index c40ab90bb..000000000 Binary files a/src/plugins/sip/src/resources/images/icon_phone-mute_24x24.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/icon_phone-reject_24x24.png b/src/plugins/sip/src/resources/images/icon_phone-reject_24x24.png deleted file mode 100644 index 497b848fa..000000000 Binary files a/src/plugins/sip/src/resources/images/icon_phone-reject_24x24.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/icon_phone-transfer_24x24.png b/src/plugins/sip/src/resources/images/icon_phone-transfer_24x24.png deleted file mode 100644 index 0c8bedf08..000000000 Binary files a/src/plugins/sip/src/resources/images/icon_phone-transfer_24x24.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/log_history.png b/src/plugins/sip/src/resources/images/log_history.png deleted file mode 100644 index c3a970fc1..000000000 Binary files a/src/plugins/sip/src/resources/images/log_history.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/microphone.png b/src/plugins/sip/src/resources/images/microphone.png deleted file mode 100644 index 1a6ccbbf8..000000000 Binary files a/src/plugins/sip/src/resources/images/microphone.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/mute_128x128.png b/src/plugins/sip/src/resources/images/mute_128x128.png deleted file mode 100644 index a4781401d..000000000 Binary files a/src/plugins/sip/src/resources/images/mute_128x128.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/mute_32x32.png b/src/plugins/sip/src/resources/images/mute_32x32.png deleted file mode 100644 index 40e08dccf..000000000 Binary files a/src/plugins/sip/src/resources/images/mute_32x32.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/noMute_32x32.png b/src/plugins/sip/src/resources/images/noMute_32x32.png deleted file mode 100644 index 30a67d142..000000000 Binary files a/src/plugins/sip/src/resources/images/noMute_32x32.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/on_phone_128x128.png b/src/plugins/sip/src/resources/images/on_phone_128x128.png deleted file mode 100644 index 7d30ec888..000000000 Binary files a/src/plugins/sip/src/resources/images/on_phone_128x128.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/phone_call.png b/src/plugins/sip/src/resources/images/phone_call.png deleted file mode 100644 index aced012e8..000000000 Binary files a/src/plugins/sip/src/resources/images/phone_call.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/phone_hang_up_128x128.png b/src/plugins/sip/src/resources/images/phone_hang_up_128x128.png deleted file mode 100644 index e3ed60215..000000000 Binary files a/src/plugins/sip/src/resources/images/phone_hang_up_128x128.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/phone_hold.png b/src/plugins/sip/src/resources/images/phone_hold.png deleted file mode 100644 index cc11ec6d8..000000000 Binary files a/src/plugins/sip/src/resources/images/phone_hold.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/phone_recall.png b/src/plugins/sip/src/resources/images/phone_recall.png deleted file mode 100644 index 102f91bdb..000000000 Binary files a/src/plugins/sip/src/resources/images/phone_recall.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/receiver2.png b/src/plugins/sip/src/resources/images/receiver2.png deleted file mode 100644 index f7d6a1e18..000000000 Binary files a/src/plugins/sip/src/resources/images/receiver2.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/receiver2_48x48.png b/src/plugins/sip/src/resources/images/receiver2_48x48.png deleted file mode 100644 index ca34cce19..000000000 Binary files a/src/plugins/sip/src/resources/images/receiver2_48x48.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/reject_32x32.png b/src/plugins/sip/src/resources/images/reject_32x32.png deleted file mode 100644 index 4fc908b66..000000000 Binary files a/src/plugins/sip/src/resources/images/reject_32x32.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/resumeCall_32x32.png b/src/plugins/sip/src/resources/images/resumeCall_32x32.png deleted file mode 100644 index fbba5a0f0..000000000 Binary files a/src/plugins/sip/src/resources/images/resumeCall_32x32.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/titlePane.png b/src/plugins/sip/src/resources/images/titlePane.png deleted file mode 100644 index d104e07d4..000000000 Binary files a/src/plugins/sip/src/resources/images/titlePane.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/toaster_btn-accept.png b/src/plugins/sip/src/resources/images/toaster_btn-accept.png deleted file mode 100644 index 9ebab0c09..000000000 Binary files a/src/plugins/sip/src/resources/images/toaster_btn-accept.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/toaster_btn-reject.png b/src/plugins/sip/src/resources/images/toaster_btn-reject.png deleted file mode 100644 index 5946e12d3..000000000 Binary files a/src/plugins/sip/src/resources/images/toaster_btn-reject.png and /dev/null differ diff --git a/src/plugins/sip/src/resources/images/voicemail.png b/src/plugins/sip/src/resources/images/voicemail.png deleted file mode 100644 index a8e55595a..000000000 Binary files a/src/plugins/sip/src/resources/images/voicemail.png and /dev/null differ diff --git a/src/plugins/spelling/build/build.xml b/src/plugins/spelling/build/build.xml deleted file mode 100755 index 55ab7e204..000000000 --- a/src/plugins/spelling/build/build.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/spelling/build/lib/jmyspell-core.jar b/src/plugins/spelling/build/lib/jmyspell-core.jar deleted file mode 100644 index fecbb3974..000000000 Binary files a/src/plugins/spelling/build/lib/jmyspell-core.jar and /dev/null differ diff --git a/src/plugins/spelling/build/lib/jmyspell-myspell-dictionary.jar b/src/plugins/spelling/build/lib/jmyspell-myspell-dictionary.jar deleted file mode 100644 index 4da6ab5ad..000000000 Binary files a/src/plugins/spelling/build/lib/jmyspell-myspell-dictionary.jar and /dev/null differ diff --git a/src/plugins/spelling/build/lib/jmyspell-swing.jar b/src/plugins/spelling/build/lib/jmyspell-swing.jar deleted file mode 100644 index 75282b1e6..000000000 Binary files a/src/plugins/spelling/build/lib/jmyspell-swing.jar and /dev/null differ diff --git a/src/plugins/spelling/build/lib/version.txt b/src/plugins/spelling/build/lib/version.txt deleted file mode 100644 index 01f308d55..000000000 --- a/src/plugins/spelling/build/lib/version.txt +++ /dev/null @@ -1,4 +0,0 @@ -File | Version | License | URL -----------------+-------------------+-----------+------------------------------------------- -jmyspell-core | SVN-89 | LGPL | http://kenai.com/projects/jmyspell/ -jmyspell-swing | SVN-80 + [#1902] | LGPL | http://kenai.com/projects/jmyspell/ diff --git a/src/plugins/spelling/plugin.xml b/src/plugins/spelling/plugin.xml deleted file mode 100755 index 0595d60bb..000000000 --- a/src/plugins/spelling/plugin.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - Spellchecker Plugin - 0.6 - Michael Will - http://www.igniterealtime.org - michael-will@gmx.net - Spellchecker Plugin - org.jivesoftware.spellchecker.SpellcheckerPlugin - 2.7.0 - Windows,Mac,Linux - 1.7.0 - - diff --git a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckerResource.java b/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckerResource.java deleted file mode 100644 index 0fe7fe9ed..000000000 --- a/src/plugins/spelling/src/java/org/jivesoftware/spellchecker/SpellcheckerResource.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spellchecker; - -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; - -import org.jivesoftware.spark.util.log.Log; - -public class SpellcheckerResource { - private static PropertyResourceBundle prb; - - static ClassLoader cl = SpellcheckerResource.class.getClassLoader(); - - static { - prb = (PropertyResourceBundle) ResourceBundle - .getBundle("i18n/spellchecker_i18n"); - } - - public static final String getString(String propertyName) { - try { - return prb.getString(propertyName); - } catch (Exception e) { - Log.error(e); - return propertyName; - } - - } - -} diff --git a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_de.properties b/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_de.properties deleted file mode 100644 index 90fbd4f68..000000000 --- a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_de.properties +++ /dev/null @@ -1,9 +0,0 @@ -title.spellchecker = Rechtschreibprüfung - -preference.spellcheckingEnabled = &Rechtschreibprüfung aktivieren -preference.autoSpellcheckingEnabled = &Automatische Rechtschreibprüfung aktivieren -preference.language = &Sprache -preference.ignore.uppercasedword = &Groß- und Kleinschreibung ignorieren -button.check.spelling = Rechtschreibung überprüfen -preference.show.langauage.in.chat.windows = Erlaube Auswahl der Sprache im Chatfenster -dialog.no.mistakes = Keine Rechtschreibfehler \ No newline at end of file diff --git a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_fr.properties b/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_fr.properties deleted file mode 100644 index f32e70c84..000000000 --- a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_fr.properties +++ /dev/null @@ -1,9 +0,0 @@ -title.spellchecker = Correcteur - -preference.spellcheckingEnabled = Activer le &correcteur -preference.autoSpellcheckingEnabled = Activer la correction &automatique -preference.language = &Langue -preference.ignore.uppercasedword = &Ignorer les majuscules -preference.show.langauage.in.chat.windows = Autoriser la s\u00E9lection de langue dans la fen\u00EAtre de chat -dialog.no.mistakes = Aucune faute d'ortographe -button.check.spelling = V\u00E9rifier l'orthographe \ No newline at end of file diff --git a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_lt.properties b/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_lt.properties deleted file mode 100644 index 988e50373..000000000 --- a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_lt.properties +++ /dev/null @@ -1,9 +0,0 @@ -title.spellchecker = Ra\u0161ybos tikrinimas - -preference.spellcheckingEnabled = \u012ejungti ra\u0161ybos tikrinim\u0105 -preference.autoSpellcheckingEnabled = \u012ejungti automatin\u012f ra\u0161ybos tikrinim\u0105 -preference.language = &Kalba -preference.ignore.uppercasedword = &Neskirti did\u017ei\u0173j\u0173 ir ma\u017e\u0173j\u0173 raid\u017ei\u0173 -preference.show.langauage.in.chat.windows = Leisti pasirinkti kalb\u0105 pokalbio lange -dialog.no.mistakes = Nerasta ra\u0161ybos klaid\u0173 -button.check.spelling = Patikrint ra\u0161yb\u0105 \ No newline at end of file diff --git a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_pl.properties b/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_pl.properties deleted file mode 100644 index c40c913a7..000000000 --- a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_pl.properties +++ /dev/null @@ -1,9 +0,0 @@ -title.spellchecker = Sprawdzanie pisowni - -preference.spellcheckingEnabled = W\u0142\u0105cz sprawdzanie pisowni -preference.autoSpellcheckingEnabled = W\u0142\u0105cz automatyczne sprawdzanie pisowni -preference.language = J\u0119zyk - s\u0142ownik -preference.ignore.uppercasedword = Ignoruj g\u00f3rne i dolne s\u0142owa -preference.show.langauage.in.chat.windows = Zezwalaj na wyb\u00f3r j\u0119zyka w oknie rozmowy -dialog.no.mistakes = Brak b\u0119\u0142d\u00f3w -button.check.spelling = Sprawd\u017a pisowni\u0119 \ No newline at end of file diff --git a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_ru_RU.properties b/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_ru_RU.properties deleted file mode 100644 index 7adddc7be..000000000 --- a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_ru_RU.properties +++ /dev/null @@ -1,9 +0,0 @@ -title.spellchecker = \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u0430\u0432\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f - -preference.spellcheckingEnabled = \u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043f\u0440\u0430\u0432\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f -preference.autoSpellcheckingEnabled = \u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043f\u0440\u0430\u0432\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f -preference.language=&\u042f\u0437\u044b\u043a -preference.ignore.uppercasedword=\u041d\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u0442\u044c \u0437\u0430\u0433\u043b\u0430\u0432\u043d\u044b\u0439\u0435 \u0438 \u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0435 -preference.show.langauage.in.chat.windows=\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0432\u044b\u0431\u043e\u0440 \u044f\u0437\u044b\u043a\u0430 \u0432 \u043e\u043a\u043d\u0435 \u0447\u0430\u0442\u0430 -dialog.no.mistakes=\u041d\u0435\u0442 \u043e\u0440\u0444\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u0448\u0438\u0431\u043e\u043a -button.check.spelling=\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043f\u0440\u0430\u0432\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 diff --git a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_zh_CN.properties b/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_zh_CN.properties deleted file mode 100644 index 484547742..000000000 --- a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_zh_CN.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net) - -preference.autoSpellcheckingEnabled = \u5F00\u542F\u81EA\u52A8\u62FC\u5199\u68C0\u67E5 -preference.spellcheckingEnabled = \u5F00\u542F\u62FC\u5199\u68C0\u67E5 - -title.spellchecker = \u62FC\u5199\u68C0\u67E5 diff --git a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_zh_TW.properties b/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_zh_TW.properties deleted file mode 100644 index a8725c59c..000000000 --- a/src/plugins/spelling/src/resources/i18n/spellchecker_i18n_zh_TW.properties +++ /dev/null @@ -1,9 +0,0 @@ -title.spellchecker = \u62fc\u5beb\u6aa2\u67e5 - -preference.spellcheckingEnabled = \u555f\u52d5\u62fc\u5beb\u6aa2\u67e5 -preference.autoSpellcheckingEnabled = \u555f\u52d5\u81ea\u52d5\u62fc\u5beb\u6aa2\u67e5 -preference.language = \u8a9e\u8a00 -preference.ignore.uppercasedword = \u5ffd\u7565\u5927\u5beb\u548c\u5c0f\u5beb\u5dee\u7570 -preference.show.langauage.in.chat.windows = \u5141\u8a31\u5728\u804a\u5929\u8996\u7a97\u9078\u64c7\u8a9e\u8a00 -dialog.no.mistakes = \u6c92\u6709\u62fc\u5beb\u932f\u8aa4 -button.check.spelling = \u62fc\u5beb\u6aa2\u67e5 \ No newline at end of file diff --git a/src/plugins/tictactoe/build/build.xml b/src/plugins/tictactoe/build/build.xml deleted file mode 100644 index 24cf0cec9..000000000 --- a/src/plugins/tictactoe/build/build.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/tictactoe/plugin.xml b/src/plugins/tictactoe/plugin.xml deleted file mode 100644 index 6bc2672e0..000000000 --- a/src/plugins/tictactoe/plugin.xml +++ /dev/null @@ -1,12 +0,0 @@ - - TicTacToe of Doom - tic.tac.toe.TicTacToePlugin - Wolf Posdorfer - 0.1 - http://www.jivesoftware.com - The most sophisticated TicTacToe Game ever created - 9posdorf@informatik.uni-hamburg.de - 2.7.0 - Windows,Linux,Mac - 1.7.0 - diff --git a/src/plugins/tictactoe/src/java/tic/tac/toe/GameBoard.java b/src/plugins/tictactoe/src/java/tic/tac/toe/GameBoard.java deleted file mode 100644 index 2e3038e8f..000000000 --- a/src/plugins/tictactoe/src/java/tic/tac/toe/GameBoard.java +++ /dev/null @@ -1,218 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package tic.tac.toe; - -import java.util.ArrayList; -import java.util.Arrays; - -/** - * Class to represent the TicTacToe gameboard - * - * @author wolf.posdorfer - * @version 16.06.2011 - */ -public class GameBoard { - - private int[][] _board; - - private int _currentPlayer; - - private int _winner; - - public GameBoard() { - - _board = new int[3][3]; - - for (int[] x : _board) { - Arrays.fill(x, Mark.BLANK.ordinal()); - } - - _currentPlayer = Mark.X.ordinal(); - _winner = 0; - - } - - public boolean isGameFinished() { - return _winner != 0; - } - - public int getWinner() - { - return _winner; - } - - public Mark getMarkAtPos(int x, int y) { - - return Mark.valueOf(_board[x][y]); - } - - public Mark getCurrentPlayer() { - return Mark.valueOf(_currentPlayer); - } - - public void placeMark(int x, int y) { - _board[x][y] = _currentPlayer; - - if (didCurrentPlayerWin()) { - _winner = _currentPlayer; - } - - if (isBoardFull() && _winner < 1) { - // Setting to Tie - _winner = -1; - } - - _currentPlayer = _currentPlayer == 1 ? 2 : 1; - - } - - /** - * Checks if the Currentplayer has won the game - * - * @return current player won the game? - */ - private boolean didCurrentPlayerWin() { - - for (int x = 0; x < 3; x++) { - - if (_board[x][0] == _currentPlayer - && _board[x][1] == _currentPlayer - && _board[x][2] == _currentPlayer) { - return true; - } - - } - - for (int y = 0; y < 3; y++) { - if (_board[0][y] == _currentPlayer - && _board[1][y] == _currentPlayer - && _board[2][y] == _currentPlayer) { - return true; - } - } - - if (_board[0][0] == _currentPlayer && _board[1][1] == _currentPlayer - && _board[2][2] == _currentPlayer) { - return true; - } - if (_board[2][0] == _currentPlayer && _board[1][1] == _currentPlayer - && _board[0][2] == _currentPlayer) { - return true; - } - - return false; - - } - - /** - * Checks if the Board is Full - * - * @return board is full? - */ - private boolean isBoardFull() { - - for (int x = 0; x < 3; x++) { - for (int y = 0; y < 3; y++) { - - if (_board[x][y] == 0) { - return false; - } - } - } - - return true; - - } - /** - * Returns the winning positions in an arraylist of Pairs - * @return ArrayList with 3 entries - */ - public Pair[] getWinningPositions() - { - ArrayList liste = new ArrayList(); - - if(_winner == -1) - { - // TIE - return null; - } - - Mark m = Mark.valueOf(_winner); - - for (int x = 0; x < 3; x++) { - - if (_board[x][0] == _winner - && _board[x][1] == _winner - && _board[x][2] == _winner) { - new Pair(x, 0,m); - - liste.add(new Pair(x, 0, m)); - liste.add(new Pair(x, 1, m)); - liste.add(new Pair(x, 2, m)); - return liste.toArray(new Pair[3]); - - } - - } - - for (int y = 0; y < 3; y++) { - if (_board[0][y] == _winner - && _board[1][y] == _winner - && _board[2][y] == _winner) { - - liste.add(new Pair(0, y, m)); - liste.add(new Pair(1, y, m)); - liste.add(new Pair(2, y, m)); - return liste.toArray(new Pair[3]); - } - } - - if (_board[0][0] == _winner && _board[1][1] == _winner - && _board[2][2] == _winner) { - - liste.add(new Pair(0, 0, m)); - liste.add(new Pair(1, 1, m)); - liste.add(new Pair(2, 2, m)); - - return liste.toArray(new Pair[3]); - } - if (_board[2][0] == _winner && _board[1][1] == _winner - && _board[0][2] == _winner) { - liste.add(new Pair(2, 0, m)); - liste.add(new Pair(1, 1, m)); - liste.add(new Pair(0, 2, m)); - return liste.toArray(new Pair[3]); - } - - return null; - - } - - /** - * Checks if the palced move is Valid - * @param x - * @param y - * @return - */ - public boolean isValidMove(Mark markplaced, int x , int y) - { - return _board[x][y] == 0 && _currentPlayer == markplaced.getValue(); - } -} diff --git a/src/plugins/tictactoe/src/java/tic/tac/toe/Mark.java b/src/plugins/tictactoe/src/java/tic/tac/toe/Mark.java deleted file mode 100644 index 6e9267ef0..000000000 --- a/src/plugins/tictactoe/src/java/tic/tac/toe/Mark.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package tic.tac.toe; - -import javax.swing.ImageIcon; - -/** - * The Variations of Marks - * - * @author wolf.posdorfer - * @version 16.06.2011 - */ -public enum Mark { - BLANK (0, "empty.png", "empty.png"), - X (1, "x.png", "x.blue.png"), - O (2, "o.png", "o.blue.png"); - - private int value; - private String icon; - private String redicon; - - public static Mark valueOf(int x) { - switch (x) { - case 0: - return BLANK; - case 1: - return X; - case 2: - return O; - default: - return BLANK; - } - } - - public ImageIcon getImage() { - ClassLoader cl = getClass().getClassLoader(); - return new ImageIcon(cl.getResource(icon)); - - } - - public ImageIcon getRedImage() - { - ClassLoader cl = getClass().getClassLoader(); - return new ImageIcon(cl.getResource(redicon)); - } - - public int getValue() { - return value; - } - - private Mark(int value, String icon, String redicon) { - this.value = value; - this.icon = icon; - this.redicon = redicon; - } -} diff --git a/src/plugins/tictactoe/src/java/tic/tac/toe/TTTRes.java b/src/plugins/tictactoe/src/java/tic/tac/toe/TTTRes.java deleted file mode 100644 index 840807e63..000000000 --- a/src/plugins/tictactoe/src/java/tic/tac/toe/TTTRes.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package tic.tac.toe; - -import java.text.MessageFormat; -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; - -import org.jivesoftware.spark.util.log.Log; - -/** - * Resource Bundle for TicTacToe - * - * @author wolf.posdorfer - * @version 16.06.2011 - */ -public class TTTRes { - - private static PropertyResourceBundle prb; - - static ClassLoader cl = TTTRes.class.getClassLoader(); - - static { - prb = (PropertyResourceBundle) ResourceBundle - .getBundle("i18n/tictactoe_i18n"); - } - - public static final String getString(String propertyName) { - try { - return prb.getString(propertyName); - } catch (Exception e) { - Log.error(e); - return propertyName; - } - } - - public static String getString(String propertyName, Object... obj) { - String str = prb.getString(propertyName); - if (str == null) { - return propertyName; - } - - return MessageFormat.format(str, obj); - } - -} diff --git a/src/plugins/tictactoe/src/java/tic/tac/toe/TicTacToePlugin.java b/src/plugins/tictactoe/src/java/tic/tac/toe/TicTacToePlugin.java deleted file mode 100644 index f38f2b433..000000000 --- a/src/plugins/tictactoe/src/java/tic/tac/toe/TicTacToePlugin.java +++ /dev/null @@ -1,312 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package tic.tac.toe; - -import java.awt.Color; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.HashSet; - -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import org.jivesoftware.resource.Res; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.StanzaListener; -import org.jivesoftware.smack.filter.PacketIDFilter; -import org.jivesoftware.smack.filter.StanzaTypeFilter; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.packet.Stanza; -import org.jivesoftware.smack.provider.ProviderManager; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomButton; -import org.jivesoftware.spark.ui.ChatRoomListener; -import org.jivesoftware.spark.ui.ChatRoomListenerAdapter; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; -import tic.tac.toe.packet.GameOfferPacket; -import tic.tac.toe.packet.InvalidMove; -import tic.tac.toe.packet.MovePacket; -import tic.tac.toe.ui.GamePanel; - - -/** - * Tic Tac Toe plugin for Spark - * - * @author wolf.posdorfer - * @version 16.06.2011 - * - */ -public class TicTacToePlugin implements Plugin { - - private ChatRoomListener _chatRoomListener; - private StanzaListener _gameOfferListener; - - private HashSet _currentInvitations; - - private ImageIcon buttonimg; - - - - @Override - public void initialize() { - ClassLoader cl = getClass().getClassLoader(); - buttonimg = new ImageIcon(cl.getResource("ttt.button.png")); - _currentInvitations = new HashSet(); - - ProviderManager.addIQProvider(GameOfferPacket.ELEMENT_NAME, GameOfferPacket.NAMESPACE,GameOfferPacket.class); - ProviderManager.addExtensionProvider(MovePacket.ELEMENT_NAME, MovePacket.NAMESPACE, MovePacket.class); - ProviderManager.addExtensionProvider(InvalidMove.ELEMENT_NAME, InvalidMove.NAMESPACE, InvalidMove.class); - - // Add IQ listener to listen for incoming game invitations. - _gameOfferListener = new StanzaListener() { - public void processPacket(Stanza stanza) { - GameOfferPacket invitation = (GameOfferPacket) stanza; - if (invitation.getType() == IQ.Type.get) { - showInvitationAlert(invitation); - } - } - - }; - - SparkManager.getConnection().addAsyncStanzaListener(_gameOfferListener, - new StanzaTypeFilter(GameOfferPacket.class)); - - addButtonToToolBar(); - - } - /** - * Add the TTT-Button to every opening Chatroom - * and create Listeners for it - */ - private void addButtonToToolBar() { - - - _chatRoomListener = new ChatRoomListenerAdapter() { - @Override - public void chatRoomOpened(final ChatRoom room) { - - if(!(room instanceof ChatRoomImpl)) - { - // Don't do anything if this is not a 1on1-Chat - return; - } - - final ChatRoomButton sendGameButton = new ChatRoomButton(buttonimg); - room.getToolBar().addChatRoomButton(sendGameButton); - - final String opponentJID = ((ChatRoomImpl) room).getJID(); - - sendGameButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - - if(_currentInvitations.contains(XmppStringUtils.parseBareJid(opponentJID))) - { - return; - } - - final GameOfferPacket offer = new GameOfferPacket(); - offer.setTo(opponentJID); - offer.setType(IQ.Type.get ); - - _currentInvitations.add(XmppStringUtils.parseBareJid(opponentJID)); - room.getTranscriptWindow().insertCustomText - (TTTRes.getString("ttt.request.sent"), false, false, Color.BLUE); - try - { - SparkManager.getConnection().sendStanza(offer); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to send offer to " + opponentJID, e1 ); - } - - SparkManager.getConnection().addAsyncStanzaListener( - new StanzaListener() { - @Override - public void processPacket(Stanza stanza) { - - GameOfferPacket answer = (GameOfferPacket)stanza; - answer.setStartingPlayer(offer.isStartingPlayer()); - answer.setGameID(offer.getGameID()); - if (answer.getType() == IQ.Type.result) { - // ACCEPT - _currentInvitations.remove(XmppStringUtils.parseBareJid(opponentJID)); - - room.getTranscriptWindow().insertCustomText - (TTTRes.getString("ttt.request.accept"), false, false, Color.BLUE); - - createTTTWindow(answer, opponentJID); - } else { - // DECLINE - room.getTranscriptWindow().insertCustomText - (TTTRes.getString("ttt.request.decline"), false, false, Color.RED); - _currentInvitations.remove(XmppStringUtils.parseBareJid(opponentJID)); - } - - } - }, - new PacketIDFilter(offer.getPacketID())); - } - }); - - } - - @Override - public void chatRoomClosed(ChatRoom room) { - if (room instanceof ChatRoomImpl) { - ChatRoomImpl cri = (ChatRoomImpl) room; - _currentInvitations.remove(cri.getParticipantJID()); - } - } - }; - - - SparkManager.getChatManager().addChatRoomListener(_chatRoomListener); - - } - - @Override - public void shutdown() { - - _currentInvitations.clear(); - SparkManager.getChatManager().removeChatRoomListener(_chatRoomListener); - SparkManager.getConnection().removeAsyncStanzaListener(_gameOfferListener); - - } - - @Override - public boolean canShutDown() { - return false; - } - - @Override - public void uninstall() { - - } - - /** - * insert the Invitation Dialog into the Chat - * - * @param invitation - */ - private void showInvitationAlert(final GameOfferPacket invitation) { - - - invitation.setType(IQ.Type.result); - invitation.setTo(invitation.getFrom()); - - - final ChatRoom room = SparkManager.getChatManager().getChatRoom( XmppStringUtils.parseBareJid(invitation.getFrom())); - - String name = XmppStringUtils.parseLocalpart(invitation.getFrom()); - - final JPanel panel = new JPanel(); - JLabel text = new JLabel(TTTRes.getString("ttt.game.request",name)); - JLabel game = new JLabel(TTTRes.getString("ttt.game.name")); - game.setFont(new Font("Dialog", Font.BOLD, 24)); - game.setForeground(Color.RED); - JButton accept = new JButton(Res.getString("button.accept").replace("&", "")); - JButton decline = new JButton(Res.getString("button.decline").replace("&", "")); - panel.add(text); - panel.add(game); - panel.add(accept); - panel.add(decline); - - room.getTranscriptWindow().addComponent(panel); - - accept.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - try - { - SparkManager.getConnection().sendStanza(invitation); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to send invitation accept to " + invitation.getTo(), e1 ); - } - invitation.setStartingPlayer(!invitation.isStartingPlayer()); - createTTTWindow(invitation, invitation.getFrom()); - panel.remove(3); - panel.remove(2); - panel.repaint(); - panel.revalidate(); - } - }); - - decline.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - invitation.setType(IQ.Type.error); - try - { - SparkManager.getConnection().sendStanza(invitation); - } - catch ( SmackException.NotConnectedException e1 ) - { - Log.warning( "Unable to send invitation decline to " + invitation.getTo(), e1 ); - } - panel.remove(3); - panel.remove(2); - panel.repaint(); - panel.revalidate(); - } - }); - - - } - - - /** - * Creates The TicTacToe Window and starts the Game - * @param gop - * @param opponentJID - */ - private void createTTTWindow(GameOfferPacket gop, String opponentJID) { - - String name = XmppStringUtils.parseLocalpart(opponentJID); - - // tictactoe versus ${name} - JFrame f = new JFrame(TTTRes.getString("ttt.window.title", TTTRes.getString("ttt.game.name"),name)); - - f.setIconImage(buttonimg.getImage()); - GamePanel gp = new GamePanel(SparkManager.getConnection(), - gop.getGameID(), gop.isStartingPlayer(), opponentJID,f); - f.add(gp); - f.pack(); - f.setLocationRelativeTo(SparkManager.getChatManager().getChatContainer()); - f.setVisible(true); - - } - -} \ No newline at end of file diff --git a/src/plugins/tictactoe/src/java/tic/tac/toe/packet/GameOfferPacket.java b/src/plugins/tictactoe/src/java/tic/tac/toe/packet/GameOfferPacket.java deleted file mode 100644 index 0fbae3487..000000000 --- a/src/plugins/tictactoe/src/java/tic/tac/toe/packet/GameOfferPacket.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package tic.tac.toe.packet; - -import java.util.Random; - -import org.jivesoftware.smack.packet.IQ; - -/** - * The Game Offer Packet - * - * @author wolf.posdorfer - * @version 16.06.2011 - */ -public class GameOfferPacket extends IQ { - - public static final String ELEMENT_NAME = "tictactoe"; - public static final String NAMESPACE = "tictactoe"; - - private int gameID; - private boolean imTheStartingPlayer; - - public GameOfferPacket() { - super(); - imTheStartingPlayer = new Random().nextBoolean(); - gameID = Math.abs(new Random().nextInt()); - } - - /** - * Returns the game ID. - * - * @return the game ID. - */ - public int getGameID() { - return gameID; - } - - /** - * Sets the game ID. - * - * @param gameID - * the game ID. - */ - public void setGameID(int gameID) { - this.gameID = gameID; - } - - /** - * Returns true if the user making the game invitation is the starting - * player. - * - * @return true if the user making the game invite is the starting player. - */ - public boolean isStartingPlayer() { - return imTheStartingPlayer; - } - - /** - * Sets whether the user making the game invitation is the starting player. - * - * @param startingPlayer - * true if the user making the game invite is the starting - * player. - */ - public void setStartingPlayer(boolean startingPlayer) { - this.imTheStartingPlayer = startingPlayer; - } - - public String getChildElementXML() { - StringBuffer buf = new StringBuffer(); - buf.append("<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">"); - if (getType() == IQ.Type.get) { - buf.append("").append(gameID).append(""); - buf.append("").append(imTheStartingPlayer) - .append(""); - buf.append(getExtensionsXML()); - } - buf.append(""); - return buf.toString(); - } - -} diff --git a/src/plugins/tictactoe/src/java/tic/tac/toe/packet/InvalidMove.java b/src/plugins/tictactoe/src/java/tic/tac/toe/packet/InvalidMove.java deleted file mode 100644 index bffa35d06..000000000 --- a/src/plugins/tictactoe/src/java/tic/tac/toe/packet/InvalidMove.java +++ /dev/null @@ -1,63 +0,0 @@ -package tic.tac.toe.packet; - -import org.jivesoftware.smack.packet.ExtensionElement; - -public class InvalidMove implements ExtensionElement { - - public static final String ELEMENT_NAME = "ttt-invalid"; - public static final String NAMESPACE = "tictactoe"; - - private int _gameID; - private int _posx; - private int _posy; - - @Override - public String getElementName() { - return ELEMENT_NAME; - } - - @Override - public String getNamespace() { - return NAMESPACE; - } - - public int getGameID() { - return _gameID; - } - - public void setGameID(int gameID) { - _gameID = gameID; - } - - public int getPositionX() { - return _posx; - } - - public int getPositionY() { - return _posy; - } - - public void setPositionX(int x) { - _posx = x; - } - - public void setPositionY(int y) { - _posy = y; - } - - @Override - public String toXML() { - StringBuffer buf = new StringBuffer(); - buf.append("<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">"); - - buf.append("").append(_gameID).append(""); - - buf.append("").append(_posx).append(""); - - buf.append("").append(_posy).append(""); - - buf.append(""); - return buf.toString(); - } - -} diff --git a/src/plugins/tictactoe/src/java/tic/tac/toe/packet/MovePacket.java b/src/plugins/tictactoe/src/java/tic/tac/toe/packet/MovePacket.java deleted file mode 100644 index 763875a5a..000000000 --- a/src/plugins/tictactoe/src/java/tic/tac/toe/packet/MovePacket.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package tic.tac.toe.packet; - -import org.jivesoftware.smack.packet.ExtensionElement; - -/** - * The Move Packet extension - * - * @author wolf.posdorfer - * @version 16.06.2011 - */ -public class MovePacket implements ExtensionElement { - - public static final String ELEMENT_NAME = "ttt-move"; - public static final String NAMESPACE = "tictactoe"; - - private int posx; - private int posy; - private int gameID; - - public int getGameID() { - return gameID; - } - - public void setGameID(int gameID) { - this.gameID = gameID; - } - - @Override - public String getElementName() { - return ELEMENT_NAME; - } - - @Override - public String getNamespace() { - return NAMESPACE; - } - - public int getPositionX() { - return posx; - } - - public void setPositionX(int posx) { - this.posx = posx; - } - - public int getPositionY() { - return posy; - } - - public void setPositionY(int posy) { - this.posy = posy; - } - - @Override - public String toXML() { - - StringBuffer buf = new StringBuffer(); - buf.append("<" + ELEMENT_NAME + " xmlns=\"" + NAMESPACE + "\">"); - - buf.append("").append(gameID).append(""); - - buf.append("").append(posx).append(""); - - buf.append("").append(posy).append(""); - - buf.append(""); - return buf.toString(); - - } - -} diff --git a/src/plugins/tictactoe/src/java/tic/tac/toe/ui/GameBoardPanel.java b/src/plugins/tictactoe/src/java/tic/tac/toe/ui/GameBoardPanel.java deleted file mode 100644 index baa27346f..000000000 --- a/src/plugins/tictactoe/src/java/tic/tac/toe/ui/GameBoardPanel.java +++ /dev/null @@ -1,138 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package tic.tac.toe.ui; - -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridLayout; -import java.awt.Image; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.geom.AffineTransform; - -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import tic.tac.toe.Mark; -import tic.tac.toe.Pair; - -/** - * The Gui to the Logical Board - * - * @author wolf.posdorfer - * @version 16.06.2011 - */ -public class GameBoardPanel extends JPanel { - - private static final long serialVersionUID = -178497456422566485L; - - private Image _backgroundimage; - - private JLabel[][] _labels; - - private GamePanel _owner; - - public GameBoardPanel(GamePanel gamepanel) { - - _owner = gamepanel; - - setLayout(new GridLayout(3, 3)); - - _labels = new JLabel[3][3]; - - for (int x = 0; x < 3; x++) { - for (int y = 0; y < 3; y++) { - JLabel toadd = new JLabel(Mark.BLANK.getImage()); - toadd.setOpaque(false); - - final int xx = x; - final int yy = y; - - toadd.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (_owner.myTurn() && _owner.isFree(xx, yy)) { - placeMark(_owner.getMyMark(), xx, yy); - } - } - - }); - - _labels[x][y] = toadd; - - add(_labels[x][y]); - } - } - - ClassLoader cl = getClass().getClassLoader(); - _backgroundimage = new ImageIcon(cl.getResource("board.png")) - .getImage(); - - setPreferredSize(new Dimension(500, 500)); - - } - - /** - * Places the Mark, and tells the Owner to place the mark on the logical - * board - * - * @param m - * @param x - * @param y - */ - public void placeMark(Mark m, int x, int y) { - - _labels[x][y].setIcon(m.getImage()); - - // Notify the Owner about Change - _owner.onGameBoardPlaceMark(m, x, y); - - this.invalidate(); - this.repaint(); - this.revalidate(); - } - - public void colorizeWinners(Pair[] pairs) - { - if(pairs!=null) - { - for(Pair p : pairs) - { - _labels[p.getX()][p.getY()].setIcon(p.getMark().getRedImage()); - } - } - this.repaint(); - this.revalidate(); - - } - - public void paintComponent(Graphics g) { - super.paintComponent(g); - final Image backgroundImage = _backgroundimage; - double scaleX = getWidth() / (double) backgroundImage.getWidth(null); - double scaleY = getHeight() / (double) backgroundImage.getHeight(null); - AffineTransform xform = AffineTransform - .getScaleInstance(scaleX, scaleY); - ((Graphics2D) g).drawImage(backgroundImage, xform, this); - } - -} diff --git a/src/plugins/tictactoe/src/java/tic/tac/toe/ui/GamePanel.java b/src/plugins/tictactoe/src/java/tic/tac/toe/ui/GamePanel.java deleted file mode 100644 index 4a6ff21f9..000000000 --- a/src/plugins/tictactoe/src/java/tic/tac/toe/ui/GamePanel.java +++ /dev/null @@ -1,238 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package tic.tac.toe.ui; - -import java.awt.BorderLayout; -import java.awt.Color; -import javax.swing.JFrame; -import javax.swing.JPanel; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.StanzaListener; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.filter.PacketExtensionFilter; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Stanza; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ShakeWindow; -import org.jivesoftware.spark.util.log.Log; -import org.jxmpp.util.XmppStringUtils; -import tic.tac.toe.GameBoard; -import tic.tac.toe.Mark; -import tic.tac.toe.TTTRes; -import tic.tac.toe.packet.InvalidMove; -import tic.tac.toe.packet.MovePacket; - -/** - * Holds the GameBoard and the Playerdisplay - * - * @author wolf.posdorfer - * @version 16.06.2011 - */ -public class GamePanel extends JPanel { - - private static final long serialVersionUID = 5481864290352375841L; - - private GameBoardPanel _gameboardpanel; - - private PlayerDisplay _playerdisplay; - - private Mark me; - - private GameBoard _gameboard; - - private XMPPConnection _connection; - - private int _gameID; - - private String _opponent; - private JFrame _frame; - - public GamePanel(XMPPConnection connection, final int gameID, - boolean imStarting, String opponentJID, JFrame frame) { - - _frame = frame; - - _opponent = opponentJID; - - _gameID = gameID; - _gameboard = new GameBoard(); - _connection = connection; - _gameboardpanel = new GameBoardPanel(this); - - if (imStarting) { - me = Mark.X; - } else { - me = Mark.O; - } - - _playerdisplay = new PlayerDisplay(me, opponentJID); - - setLayout(new BorderLayout()); - - add(_gameboardpanel, BorderLayout.CENTER); - add(_playerdisplay, BorderLayout.SOUTH); - _connection.addAsyncStanzaListener(new StanzaListener() { - - @Override - public void processPacket(Stanza stanza) throws SmackException.NotConnectedException - { - - MovePacket move = (MovePacket) stanza.getExtension( - MovePacket.ELEMENT_NAME, MovePacket.NAMESPACE); - - if (move.getGameID() == _gameID) { - - if(_gameboard.isValidMove(getYourMark() ,move.getPositionX(), move.getPositionY())) - { - _gameboardpanel.placeMark(getYourMark(), - move.getPositionX(), move.getPositionY()); - } - else - { - InvalidMove inval = new InvalidMove(); - inval.setGameID(move.getGameID()); - inval.setPositionX(move.getPositionX()); - inval.setPositionY(move.getPositionY()); - Message message =new Message(_opponent); - message.addExtension(inval); - _connection.sendStanza(message); - - ChatRoom cr = SparkManager.getChatManager().getChatRoom( XmppStringUtils.parseBareJid(_opponent)); - cr.getTranscriptWindow().insertCustomText(_opponent+"seems to be cheating\n"+ - "He tried placing a wrong Move", true, false, Color.red); - - } - } - - } - }, new PacketExtensionFilter(MovePacket.ELEMENT_NAME, - MovePacket.NAMESPACE)); - - _connection.addAsyncStanzaListener(new StanzaListener() { - - @Override - public void processPacket(Stanza stanza) { - - //InvalidMove im = (InvalidMove)packet.getExtension(InvalidMove.ELEMENT_NAME, InvalidMove.NAMESPACE); - ChatRoom cr = SparkManager.getChatManager().getChatRoom(XmppStringUtils.parseBareJid(_opponent)); - cr.getTranscriptWindow().insertCustomText("You seem to be Cheating\n"+ - "You placed a wrong Move", true, false, Color.red); - ShakeWindow sw = new ShakeWindow(_frame); - sw.startRandomMovement(10); - - } - }, new PacketExtensionFilter(InvalidMove.ELEMENT_NAME, - InvalidMove.NAMESPACE)); - - } - - public PlayerDisplay getPlayerDisplay() { - return _playerdisplay; - } - - public GameBoardPanel getGameBoardPanel() { - return _gameboardpanel; - } - - /** - * being called from GameBoardPanel, places the Mark on the Logical Board - * and sends the Move if it was one - * - * @param m - * @param x - * @param y - */ - public void onGameBoardPlaceMark(Mark m, int x, int y) { - - _gameboard.placeMark(x, y); - _playerdisplay.setCurrentPlayer(_gameboard.getCurrentPlayer()); - - if (m == getMyMark()) { - - MovePacket move = new MovePacket(); - move.setGameID(_gameID); - move.setPositionX(x); - move.setPositionY(y); - - Message message = new Message(_opponent); - message.addExtension(move); - - try - { - _connection.sendStanza(message); - } - catch ( SmackException.NotConnectedException e ) - { - Log.warning( "Unable to send move to " + message.getTo(), e ); - } - - } - - if (_gameboard.isGameFinished()) { - _gameboardpanel.colorizeWinners(_gameboard.getWinningPositions()); - - if (_gameboard.getWinner() == getMyMark().getValue()) { - - remove(_playerdisplay); - add(new GameEndsUI(TTTRes.getString("ttt.win"), Color.GREEN), BorderLayout.SOUTH); - - } - if (_gameboard.getWinner() == getYourMark().getValue()) { - remove(_playerdisplay); - add(new GameEndsUI(TTTRes.getString("ttt.lose"), Color.RED), BorderLayout.SOUTH); - } - if (_gameboard.getWinner() == -1) { - remove(_playerdisplay); - add(new GameEndsUI(TTTRes.getString("ttt.tie"), Color.BLACK), BorderLayout.SOUTH); - } - - - ShakeWindow sw = new ShakeWindow(_frame); - sw.startShake(); - repaint(); - revalidate(); - - } - } - - public Mark getMyMark() { - return me; - } - - public Mark getYourMark() { - if (me == Mark.X) - return Mark.O; - else - return Mark.X; - } - - public boolean myTurn() { - return _playerdisplay.getCurrentPlayer() == getMyMark() - && !_gameboard.isGameFinished(); - } - - public boolean isFree(int x, int y) { - return _gameboard.getMarkAtPos(x, y) == Mark.BLANK; - } - -} diff --git a/src/plugins/tictactoe/src/resources/board.png b/src/plugins/tictactoe/src/resources/board.png deleted file mode 100644 index 778fcacd9..000000000 Binary files a/src/plugins/tictactoe/src/resources/board.png and /dev/null differ diff --git a/src/plugins/tictactoe/src/resources/empty.png b/src/plugins/tictactoe/src/resources/empty.png deleted file mode 100644 index d20db708e..000000000 Binary files a/src/plugins/tictactoe/src/resources/empty.png and /dev/null differ diff --git a/src/plugins/tictactoe/src/resources/i18n/tictactoe_i18n_lt.properties b/src/plugins/tictactoe/src/resources/i18n/tictactoe_i18n_lt.properties deleted file mode 100644 index de82c1ba7..000000000 --- a/src/plugins/tictactoe/src/resources/i18n/tictactoe_i18n_lt.properties +++ /dev/null @@ -1,16 +0,0 @@ -########################### -# Tic Tac Toe # -# by wolf.posdorfer # -########################### - -ttt.game.request = {0} u\u017eklaus\u0117 Kry\u017eiukai-nuliukai \u017eaidimo -ttt.game.name = Kry\u017eiukai-nuliukai -ttt.window.title = {0} prie\u0161 {1} -ttt.win = Sveikiname, j\u016bs laim\u0117jote! -ttt.lose = Apgail\u0117staujame, j\u016bs pralaim\u0117jote! -ttt.tie = \u017Daidimas baig\u0117si lygiosiomis. -ttt.display.me = A\u0161 esu: -ttt.display.current = \u0161iuo metu \u017eaid\u017eia: -ttt.request.decline = \u017Daidimas pra\u0161ymas buvo atmestas. -ttt.request.accept = \u017Daidimas prasideda. -ttt.request.sent = Siun\u010diama \u017eaidimo u\u017eklausa... \ No newline at end of file diff --git a/src/plugins/tictactoe/src/resources/o.blue.png b/src/plugins/tictactoe/src/resources/o.blue.png deleted file mode 100644 index a976eefad..000000000 Binary files a/src/plugins/tictactoe/src/resources/o.blue.png and /dev/null differ diff --git a/src/plugins/tictactoe/src/resources/o.png b/src/plugins/tictactoe/src/resources/o.png deleted file mode 100644 index 70e336c27..000000000 Binary files a/src/plugins/tictactoe/src/resources/o.png and /dev/null differ diff --git a/src/plugins/tictactoe/src/resources/x.blue.png b/src/plugins/tictactoe/src/resources/x.blue.png deleted file mode 100644 index 3623ea237..000000000 Binary files a/src/plugins/tictactoe/src/resources/x.blue.png and /dev/null differ diff --git a/src/plugins/tictactoe/src/resources/x.png b/src/plugins/tictactoe/src/resources/x.png deleted file mode 100644 index e32a791b7..000000000 Binary files a/src/plugins/tictactoe/src/resources/x.png and /dev/null differ diff --git a/src/plugins/transferguard/TransferGuard.iml b/src/plugins/transferguard/TransferGuard.iml deleted file mode 100644 index 3c4652619..000000000 --- a/src/plugins/transferguard/TransferGuard.iml +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/transferguard/build/build.xml b/src/plugins/transferguard/build/build.xml deleted file mode 100644 index 299cabf1c..000000000 --- a/src/plugins/transferguard/build/build.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/transferguard/plugin.xml b/src/plugins/transferguard/plugin.xml deleted file mode 100644 index 77234bce0..000000000 --- a/src/plugins/transferguard/plugin.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - Transfer Guard - 1.0.2 - Pete Matern, Tim Jentz - http://www.jivesoftware.org - pete@jivesoftware.com - Adds the ability to automatically reject file transfers based on preference configuration - org.jivesoftware.spark.plugins.transfersettings.FileTransferSettingsPlugin - 2.7.0 - 1.7.0 - - diff --git a/src/plugins/transferguard/src/java/org/jivesoftware/spark/plugins/transfersettings/TGuardRes.java b/src/plugins/transferguard/src/java/org/jivesoftware/spark/plugins/transfersettings/TGuardRes.java deleted file mode 100644 index 1ee202ebe..000000000 --- a/src/plugins/transferguard/src/java/org/jivesoftware/spark/plugins/transfersettings/TGuardRes.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.jivesoftware.spark.plugins.transfersettings; - -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; - - -/** - * Use for Transferguard Ressource Internationalization. - * - * @author tim.jentz - */ -public class TGuardRes { - private static PropertyResourceBundle prb; - - private TGuardRes() { - - } - - static ClassLoader cl = TGuardRes.class.getClassLoader(); - - static { - prb = (PropertyResourceBundle) ResourceBundle - .getBundle("i18n/transferguard_i18n"); - } - - public static final String getString(String propertyName) { - return prb.getString(propertyName); - } - - -} \ No newline at end of file diff --git a/src/plugins/transferguard/src/resources/i18n/transferguard_i18n_lt.properties b/src/plugins/transferguard/src/resources/i18n/transferguard_i18n_lt.properties deleted file mode 100644 index 16d685cd8..000000000 --- a/src/plugins/transferguard/src/resources/i18n/transferguard_i18n_lt.properties +++ /dev/null @@ -1,54 +0,0 @@ -## -## Transferguard Language File -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## -## REVISION HISTORY (by Transferguard version): -## -## 1.0.1 -## Added key: 'guard.settings.tooltips.blockedtypes' -## Added key: 'guard.settings.tooltips.blockedperson' -## Added key: 'guard.settings.tooltips.textarea' -## Added key: 'guard.settings.title.extensions' -## Added key: 'guard.settings.title.person' -## Added key: 'guard.settings.title.rejectresponse' -## Added key: 'guard.settings.label.maxsize' -## Added key: 'guard.settings.title.filesize' -## Added key: 'guard.settings.limitcheck' -## Added key: 'guard.settings.title.settings' -## - -guard.settings.title.list = Persiuntim\u0173 apsauga -guard.settings.title.settings = Byl\u0173 persiuntimo nustatymai -guard.settings.tooltips.blockedtypes = \u012eveskite byl\u0173 i\u0161pl\u0117timus, kuriuos norite blokuoti (pvz. '*.doc'), atskiriant kableliais -guard.settings.tooltips.blockedperson = \u012eveskite "JID'us" vartotoj\u0173 i\u0161 kuri\u0173 nenorite gauti byl\u0173 persiuntim\u0173 (pvz. 'kazkas@domain.com'), atskiriant kableliais -guard.settings.tooltips.textarea = \u012eveskite prane\u0161imo tekst\u0105, kuris bus parodytas vartotojams, kuri\u0173 siuntimus blokuosite. Palikite \u0161\u012f laukel\u012f tu\u0161\u010di\u0105, jei nenorite si\u0173sti jiems prane\u0161imo. -guard.settings.title.extensions = Blokuojami byl\u0173 i\u0161pl\u0117timai -guard.settings.title.person = Blokuojami siunt\u0117jai -guard.settings.title.rejectresponse = Automatinis siuntimo blokavimo prane\u0161imas -guard.settings.label.maxsize = Maksimalus dydis kilobaitais (KB): -guard.settings.title.filesize = Bylos dydis -guard.settings.limitcheck = Apriboti bylos dyd\u012f diff --git a/src/plugins/transferguard/src/resources/i18n/transferguard_i18n_pl.properties b/src/plugins/transferguard/src/resources/i18n/transferguard_i18n_pl.properties deleted file mode 100644 index f9bc559ab..000000000 --- a/src/plugins/transferguard/src/resources/i18n/transferguard_i18n_pl.properties +++ /dev/null @@ -1,53 +0,0 @@ -## -## Transferguard Language File -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## -## REVISION HISTORY (by Transferguard version): -## -## 1.0.1 -## Added key: 'guard.settings.tooltips.blockedtypes' -## Added key: 'guard.settings.tooltips.blockedperson' -## Added key: 'guard.settings.tooltips.textarea' -## Added key: 'guard.settings.title.extensions' -## Added key: 'guard.settings.title.person' -## Added key: 'guard.settings.title.rejectresponse' -## Added key: 'guard.settings.label.maxsize' -## Added key: 'guard.settings.title.filesize' -## Added key: 'guard.settings.limitcheck' -## Added key: 'guard.settings.title.settings' -## - -guard.settings.title.settings = Ustawienia transferu plik\u00F3w -guard.settings.tooltips.blockedtypes = Wpisz rozszerzenia plik\u00F3w, kt\u00F3rych przesy\u0142 chcesz blokowa\u0107 (np. '*.doc'), oddzielaj\u0105c je przecinkami -guard.settings.tooltips.blockedperson = Wpisz identyfikator JID u\u017Cytkownik\u00F3w, od kt\u00F3rych chcesz blokowa\u0107 przesy\u0142 plik\u00F3w, oddzielaj\u0105c je przecinkami -guard.settings.tooltips.textarea = Wpisz wiadomo\u015B\u0107, kt\u00F3r\u0105 chcesz wysy\u0142a\u0107 tym kt\u00F3rym blokujesz przesy\u0142anie plik\u00F3w. Pozostaw puste je\u015Bli nie chcesz wysy\u0142a\u0107 im wiadomo\u015Bci. -guard.settings.title.extensions = Blokowane rozszerzenia plik\u00F3w -guard.settings.title.person = Zablokowani przesy\u0142aj\u0105cy pliki -guard.settings.title.rejectresponse = Automatyczna odpowied\u017A odrzucenia -guard.settings.label.maxsize = Maksymalna wielko\u015B\u0107 w KB: -guard.settings.title.filesize = Rozmiar pliku -guard.settings.limitcheck = Ograniczenie wielko\u015Bci pliku \ No newline at end of file diff --git a/src/plugins/transferguard/src/resources/i18n/transferguard_i18n_zh_TW.properties b/src/plugins/transferguard/src/resources/i18n/transferguard_i18n_zh_TW.properties deleted file mode 100644 index 765a59276..000000000 --- a/src/plugins/transferguard/src/resources/i18n/transferguard_i18n_zh_TW.properties +++ /dev/null @@ -1,54 +0,0 @@ -## -## Transferguard Language File -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## -## REVISION HISTORY (by Transferguard version): -## -## 1.0.1 -## Added key: 'tooltip.transferguard' -## Added key: 'guard.settings.tooltips.blockedtypes' -## Added key: 'guard.settings.tooltips.blockedperson' -## Added key: 'guard.settings.tooltips.textarea' -## Added key: 'guard.settings.title.extensions' -## Added key: 'guard.settings.title.person' -## Added key: 'guard.settings.title.rejectresponse' -## Added key: 'guard.settings.label.maxsize' -## Added key: 'guard.settings.title.filesize' -## Added key: 'guard.settings.limitcheck' -## Added key: 'guard.settings.title.settings' -## -guard.settings.title.list = \u6a94\u6848\u50b3\u8f38\u8a2d\u5b9a -guard.settings.title.settings = \u6a94\u6848\u50b3\u8f38\u8a2d\u5b9a -guard.settings.tooltips.blockedtypes = \u8f38\u5165\u60a8\u5e0c\u671b\u963b\u64cb\u7684\u6a94\u6848\u7dad\u78bc (\u4f8b\u5982. '*.doc'), \u7528\u9017\u865f\u5206\u9694 -guard.settings.tooltips.blockedperson = \u8f38\u5165\u8981\u963b\u64cb\u5f9e\u54ea\u4f4d\u806f\u7d61\u4eba\u7684 JID \u6240\u50b3\u8f38\u7684\u6a94\u6848 (\u4f8b\u5982. 'loser@domain.com'), \u7528\u9017\u865f\u5206\u9694 -guard.settings.tooltips.textarea = \u8f38\u5165\u60a8\u60f3\u767c\u9001\u7d66\u90a3\u4e9b\u88ab\u60a8\u963b\u64cb\u7684\u6a94\u6848\u7684\u8a0a\u606f. \u5982\u679c\u60a8\u4e0d\u60f3\u767c\u9001\u8a0a\u606f,\u4e0b\u65b9\u6b04\u4f4d\u4e0d\u9700\u8f38\u5165. -guard.settings.title.extensions = \u963b\u64cb\u6a94\u6848\u7dad\u78bc -guard.settings.title.person = \u963b\u64cb\u50b3\u8f38\u8005 -guard.settings.title.rejectresponse = \u81ea\u52d5\u56de\u8986\u963b\u64cb\u7684\u8a0a\u606f -guard.settings.label.maxsize = \u6a94\u6848\u5927\u5c0f\u6700\u5927\u70ba\u591a\u5c11 KB: -guard.settings.title.filesize = \u6a94\u6848\u5927\u5c0f -guard.settings.limitcheck = \u9650\u5236\u6a94\u6848\u5927\u5c0f \ No newline at end of file diff --git a/src/plugins/transferguard/src/resources/images/knight.png b/src/plugins/transferguard/src/resources/images/knight.png deleted file mode 100644 index 3f159e96a..000000000 Binary files a/src/plugins/transferguard/src/resources/images/knight.png and /dev/null differ diff --git a/src/plugins/translator/Translator.iml b/src/plugins/translator/Translator.iml deleted file mode 100644 index 630314a8a..000000000 --- a/src/plugins/translator/Translator.iml +++ /dev/null @@ -1,191 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/translator/Translator.ipr b/src/plugins/translator/Translator.ipr deleted file mode 100644 index c83303595..000000000 --- a/src/plugins/translator/Translator.ipr +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/translator/build/build.xml b/src/plugins/translator/build/build.xml deleted file mode 100644 index c6267b83d..000000000 --- a/src/plugins/translator/build/build.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/translator/build/lib/dist/Tidy.jar b/src/plugins/translator/build/lib/dist/Tidy.jar deleted file mode 100644 index 753f4fe6b..000000000 Binary files a/src/plugins/translator/build/lib/dist/Tidy.jar and /dev/null differ diff --git a/src/plugins/translator/build/lib/dist/httpunit.jar b/src/plugins/translator/build/lib/dist/httpunit.jar deleted file mode 100644 index 71780d70d..000000000 Binary files a/src/plugins/translator/build/lib/dist/httpunit.jar and /dev/null differ diff --git a/src/plugins/translator/build/project/Translator.iml b/src/plugins/translator/build/project/Translator.iml deleted file mode 100644 index a8eb84241..000000000 --- a/src/plugins/translator/build/project/Translator.iml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/translator/build/project/Translator.ipr b/src/plugins/translator/build/project/Translator.ipr deleted file mode 100644 index fe708ed93..000000000 --- a/src/plugins/translator/build/project/Translator.ipr +++ /dev/null @@ -1,410 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/translator/build/project/Translator.iws b/src/plugins/translator/build/project/Translator.iws deleted file mode 100644 index 5bde0aa27..000000000 --- a/src/plugins/translator/build/project/Translator.iws +++ /dev/null @@ -1,608 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plugins/translator/changelog.html b/src/plugins/translator/changelog.html deleted file mode 100644 index 7948e020a..000000000 --- a/src/plugins/translator/changelog.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - - Translator Spark Plug Log - - - - -

        -Translator Spark plug Changelog -

        -

        1.4 -- March 17th, 2011

        -
          -
        • Adjusted to Google's new translator layout for Spark 2.6.x
        • -
        - -

        1.3 -- February 7th, 2007

        -
          -
        • Fixed issue with Spark 2.5 Beta and Higher
        • -
        - -

        1.0.1 -- September 19th, 2006

        -
          -
        • Moved over to Spark 2.0 code base.
        • -
        - - -

        1.0.0 -- February 9th, 2006

        -
          -
        • Initial release.
        • -
        - - - - - - diff --git a/src/plugins/translator/plugin.xml b/src/plugins/translator/plugin.xml deleted file mode 100644 index b4df0c08d..000000000 --- a/src/plugins/translator/plugin.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - Translator Plugin - org.jivesoftware.spark.translator.TranslatorPlugin - Jive Software - 1.5 - http://www.jivesoftware.com - Translates instant messages between users using Google Translation Service. - spark@jivesoftware.com - 2.7.0 - 1.7.0 - diff --git a/src/plugins/translator/readme.html b/src/plugins/translator/readme.html deleted file mode 100644 index 5d462182d..000000000 --- a/src/plugins/translator/readme.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - Translator Spark Plug Readme - - - - -

        -Translator Plugin Readme -

        - -

        Overview

        - -

        -The plugin allows for blocking of file transfers dependent on file type or users. -

        - -

        Installation

        - -

        Simply install plugin via the Plugin Viewer in Spark

        - - - diff --git a/src/plugins/translator/src/java/org/jivesoftware/spark/translator/TranslatorPlugin.java b/src/plugins/translator/src/java/org/jivesoftware/spark/translator/TranslatorPlugin.java deleted file mode 100644 index 83320bbff..000000000 --- a/src/plugins/translator/src/java/org/jivesoftware/spark/translator/TranslatorPlugin.java +++ /dev/null @@ -1,127 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.translator; - -import java.awt.Color; - -import javax.swing.JComboBox; - -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.spark.ChatManager; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.plugin.Plugin; -import org.jivesoftware.spark.ui.ChatRoom; -import org.jivesoftware.spark.ui.ChatRoomListenerAdapter; -import org.jivesoftware.spark.ui.MessageEventListener; -import org.jivesoftware.spark.ui.TranscriptWindow; -import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; -import org.jxmpp.util.XmppStringUtils; - -/** - * A plugin that uses google's translation service to translate instant messages between two users. - * - * @author Jive Software - */ -public class TranslatorPlugin implements Plugin { - - /** - * Called after Spark is loaded to initialize the new plugin. - */ - public void initialize() { - // Retrieve ChatManager from the SparkManager - final ChatManager chatManager = SparkManager.getChatManager(); - - // Add to a new ChatRoom when the ChatRoom opens. - chatManager.addChatRoomListener(new ChatRoomListenerAdapter() { - public void chatRoomOpened(ChatRoom room) { - // only do the translation for single chat - if (room instanceof ChatRoomImpl) { - final ChatRoomImpl roomImpl = (ChatRoomImpl)room; - - // Create a new ChatRoomButton. - final JComboBox translatorBox = new JComboBox<>(TranslatorUtil.TranslationType.getTypes()); - - translatorBox.addActionListener( e -> { - // Set the focus back to the message box. - roomImpl.getChatInputEditor().requestFocusInWindow(); - } ); - - roomImpl.addChatRoomComponent(translatorBox); - - // do the translation for outgoing messages. - final MessageEventListener messageListener = new MessageEventListener() { - public void sendingMessage(Message message) { - String currentBody = message.getBody(); - String oldBody = message.getBody(); - TranslatorUtil.TranslationType type = - (TranslatorUtil.TranslationType)translatorBox.getSelectedItem(); - if (type != null && type != TranslatorUtil.TranslationType.None) { - message.setBody(null); - currentBody = TranslatorUtil.translate(currentBody, type); - TranscriptWindow transcriptWindow = chatManager.getChatRoom( XmppStringUtils.parseBareJid( message.getTo() ) ).getTranscriptWindow(); - if(oldBody.equals(currentBody.substring(0,currentBody.length()-1))) - { - transcriptWindow.insertNotificationMessage("Could not translate: "+currentBody, ChatManager.ERROR_COLOR); - } - else - { - transcriptWindow.insertNotificationMessage("-> "+currentBody, Color.gray); - message.setBody(currentBody); - } - } - } - - - public void receivingMessage(Message message) { - // do nothing - } - }; - roomImpl.addMessageEventListener(messageListener); - } - } - }); - } - - /** - * Called when Spark is shutting down to allow for persistence of information - * or releasing of resources. - */ - public void shutdown() { - - } - - /** - * Return true if the Spark can shutdown on users request. - * - * @return true if Spark can shutdown on users request. - */ - public boolean canShutDown() { - return true; - } - - /** - * Is called when a user explicitly asked to uninstall this plugin. - * The plugin owner is responsible to clean up any resources and - * remove any components install in Spark. - */ - public void uninstall() { - // Remove all resources belonging to this plugin. - } -} diff --git a/src/plugins/translator/src/java/org/jivesoftware/spark/translator/TranslatorUtil.java b/src/plugins/translator/src/java/org/jivesoftware/spark/translator/TranslatorUtil.java deleted file mode 100644 index 4b09f0e36..000000000 --- a/src/plugins/translator/src/java/org/jivesoftware/spark/translator/TranslatorUtil.java +++ /dev/null @@ -1,240 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.spark.translator; - -import java.io.IOException; -import java.net.MalformedURLException; - -import javax.xml.transform.TransformerException; - -import org.jivesoftware.spark.util.log.Log; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -import com.meterware.httpunit.GetMethodWebRequest; -import com.meterware.httpunit.HttpUnitOptions; -import com.meterware.httpunit.WebConversation; -import com.meterware.httpunit.WebRequest; -import com.meterware.httpunit.WebResponse; -import com.sun.org.apache.xpath.internal.XPathAPI; - -/** - * A utility class that uses google's translation service to translate text to various languages. - */ -public class TranslatorUtil { - private TranslatorUtil() { - - } - - public static String translate(String text, TranslationType type) { - if (type == null) { - return text; - } - - return useGoogleTranslator(text, type); - } - - private static String useGoogleTranslator(String text, TranslationType type) { - - String response = ""; - String urlString = "http://translate.google.com/translate_t?text=" + text + "&langpair=" + type.getID(); - // disable scripting to avoid requiring js.jar - HttpUnitOptions.setScriptingEnabled(false); - - // create the conversation object which will maintain state for us - WebConversation wc = new WebConversation(); - - // Obtain the google translation page - WebRequest webRequest = new GetMethodWebRequest(urlString); - // required to prevent a 403 forbidden error from google - webRequest.setHeaderField("User-agent", "Mozilla/4.0"); - - try { - WebResponse webResponse = wc.getResponse(webRequest); - //NodeList list = webResponse.getDOM().getDocumentElement().getElementsByTagName("div"); - try { - NodeList list2 = XPathAPI.selectNodeList(webResponse.getDOM(), "//span[@id='result_box']/span/text()"); - - for (int i = 0; i < list2.getLength(); ++i) - { - response = response + list2.item(i).getNodeValue()+" "; - } - - - } catch (TransformerException e) { - Log.warning("Translator error",e); - } - -// int length = list.getLength(); -// for (int i = 0; i < length; i++) { -// Element element = (Element)list.item(i); -// if ("result_box".equals(element.getAttribute("id"))) { -// Node translation = element.getFirstChild(); -// if (translation != null) { -// response = translation.getNodeValue(); -// } -// } -// } - } - catch (MalformedURLException e) { - Log.error("Could not for url: " + e); - } - catch (IOException e) { - Log.error("Could not get response: " + e); - } - catch (SAXException e) { - Log.error("Could not parse response content: " + e); - } - - return response; - } - - /** - * A typesafe enum class for translation types. - */ - public static final class TranslationType { - private final String id; - private final String name; - - private TranslationType(String id, String name) { - this.id = id; - this.name = name; - } - - public String getID() { - return id; - } - - public String getName() { - return name; - } - - public static TranslationType[] getTypes() { - return types; - } - - public String toString() { - return name; - } - - /** - * Type representing no translation. - */ - public static final TranslationType None = new TranslationType("", "No Translation"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType EnglishToGerman = new TranslationType("en%7Cde", "English to German"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType EnglishToSpanish = new TranslationType("en%7Ces", "English to Spanish"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType EnglishToFrench = new TranslationType("en%7Cfr", "English to French"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType EnglishToItalian = new TranslationType("en%7Cit", "English to Italian"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType EnglishToPortuguese = new TranslationType("en%7Cpt", "English to Portuguese"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType EnglishToJapanese = new TranslationType("en%7Cja", "English to Japanese"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType EnglishToKorean = new TranslationType("en%7Cko", "English to Korean"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType EnglishToChineseSimplified = new TranslationType("en%7Czh-CN", "English to Chinese (Simplified)"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType GermanToEnglish = new TranslationType("de%7Cen", "German to English"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType GermanToFrench = new TranslationType("de%7Cfr", "German to French"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType SpanishToEnglish = new TranslationType("es%7Cen", "Spanish to English"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType FrenchToEnglish = new TranslationType("fr%7Cen", "French to English"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType FrenchToGerman = new TranslationType("fr%7Cde", "French to German"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType ItalianToEnglish = new TranslationType("it%7Cen", "Italian to English"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType PortugueseToEnglish = new TranslationType("pt%7Cen", "Portuguese to English"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType JapaneseToEnglish = new TranslationType("ja%7Cen", "Japanese to English"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType KoreanToEnglish = new TranslationType("ko%7Cen", "Korean to English"); - /** - * Type representing a translation from english to german. - */ - public static final TranslationType ChineseSimplifiedToEnglish = new TranslationType("zh-CN%7Cen", "Chinese (Simplified) to English"); - - /** - * Array containing all TranslationTypes - */ - private static final TranslationType[] types = { - None, - EnglishToGerman, - EnglishToSpanish, - EnglishToFrench, - EnglishToItalian, - EnglishToPortuguese, - EnglishToJapanese, - EnglishToKorean, - EnglishToChineseSimplified, - GermanToEnglish, - GermanToFrench, - SpanishToEnglish, - FrenchToEnglish, - FrenchToGerman, - ItalianToEnglish, - PortugueseToEnglish, - JapaneseToEnglish, - KoreanToEnglish, - ChineseSimplifiedToEnglish - }; - } -} - diff --git a/src/plugins/translator/src/test/com/jivesoftware/spark/translator/TestTranslator.java b/src/plugins/translator/src/test/com/jivesoftware/spark/translator/TestTranslator.java deleted file mode 100644 index 2ae8c06ae..000000000 --- a/src/plugins/translator/src/test/com/jivesoftware/spark/translator/TestTranslator.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * $RCSfile: ,v $ - * $Revision: $ - * $Date: $ - * - * Copyright (C) 2004-2011 Jive Software. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.jivesoftware.spark.translator; - -import org.jivesoftware.spark.translator.TranslatorUtil; -import org.jivesoftware.spark.translator.TranslatorUtil.TranslationType; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.IOException; -import java.util.*; - -/** - * A simple class to test translation functionality. - */ -public class TestTranslator { - - public static void main(String[] args) { - Map translationMap = initalizeTranslationMap(); - - boolean again = true; - while (again) { - System.out.println("Please enter some text"); - BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); - String text = ""; - try { - text = reader.readLine(); - } catch (IOException e) { - System.out.println("Could not read text:" + e); - } - - if (text == null) { - System.out.println("Sorry, I didnt get that."); - continue; - } - - System.out.println("Great, now enter the translation id. Below are the following choices:"); - - for (Map.Entry o : translationMap.entrySet()) { - System.out.println(o.getKey() + " - " + o.getValue().getName()); - } - - String translationID = ""; - try { - translationID = reader.readLine(); - } catch (IOException e) { - System.out.println("Could not read translationID:" + e); - } - - Integer id = Integer.valueOf(translationID); - TranslatorUtil.TranslationType type = translationMap.get(id); - - if (type == null) { - System.out.println("Not a valid translation type."); - continue; - } - - String result = TranslatorUtil.translate(text, type); - - System.out.println("Your original text:\n" + text); - System.out.println("Has been translated from: " + type.getName()); - System.out.println("The result is:\n" + result); - - System.out.println("Do you want to continue testing?"); - String cont; - try { - cont = reader.readLine(); - if ("yes".equals(cont.toLowerCase().trim()) || "y".equals(cont.toLowerCase().trim())) { - again = true; - } else { - again = false; - } - } catch (IOException e) { - System.out.println("Could not read text:" + e); - } - } - } - - private static Map initalizeTranslationMap() { - TranslatorUtil.TranslationType[] types = TranslatorUtil.TranslationType.getTypes(); - Map map = new TreeMap<>( new Comparator() - { - public int compare( Integer i1, Integer i2 ) - { - return i1.compareTo( i2 ); - } - } ); - - for (int i = 1; i < types.length; i++) { - map.put(i, types[i]); - } - - return map; - } -} diff --git a/src/resources/META-INF/plugins.xml b/src/resources/META-INF/plugins.xml deleted file mode 100644 index 3a4e416bc..000000000 --- a/src/resources/META-INF/plugins.xml +++ /dev/null @@ -1,195 +0,0 @@ - - - - - Jabber Browser - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Used for discovering items on a XMPP server. - org.jivesoftware.sparkimpl.plugin.jabber.JabberBrowser - - - Asterisks Phone Plugin - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Adds phone-pbx capabilities within Spark. Users can make calls, take incoming calls and be - notified of presence changes. - - org.jivesoftware.sparkimpl.plugin.phone.PhonePlugin - - - Jabber Version - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Displays which version of Spark users are running. - org.jivesoftware.sparkimpl.plugin.jabber.JabberVersion - - - Sounds Plugin - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Adds sound preferences for Spark. - org.jivesoftware.sparkimpl.preference.sounds.SoundPlugin - - - Layout Plugin - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Persists users layouts on subsequent loads - org.jivesoftware.sparkimpl.plugin.layout.LayoutPlugin - - - Chat Post Loader - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Allows users to specify command-line arguments to control Spark on startup. - org.jivesoftware.sparkimpl.plugin.chat.ChatArgumentsPlugin - - - Presence Change Plugin - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Tracks users presenences during the runtime of Spark. - org.jivesoftware.sparkimpl.plugin.chat.PresenceChangePlugin - - - Plugin Viewer Plugin - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Allows users to download, install and uninstall 3rd party plugins - org.jivesoftware.sparkimpl.plugin.viewer.PluginViewer - - - Emoticon Plugin - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Allows users to use a pick list for Emoticons. - org.jivesoftware.sparkimpl.plugin.emoticons.EmoticonPlugin - - - Sparklers Plugin - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Allows users set Active Sparklers within a Chat Conversation. - org.jivesoftware.sparkimpl.plugin.sparklers.SparklersPlugin - - - Notes Plugin - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Allows users to have scratch paper within Spark. - org.jivesoftware.sparkimpl.plugin.scratchpad.ScratchPadPlugin - - - Buzz Plugin - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Allows users to shake a users frame. - org.jivesoftware.sparkimpl.plugin.alerts.BuzzPlugin - - - Notifications Plugin - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Adds generic notification handling to Spark. - org.jivesoftware.sparkimpl.preference.notifications.NotificationPlugin - - - Shortcut Plugin - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Adds simple IRC style shortcuts. - org.jivesoftware.sparkimpl.plugin.chat.ShortcutPlugin - - - History Plugin - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Adds a simple shortcut to view most previous conversations. - org.jivesoftware.sparkimpl.plugin.history.ConversationHistoryPlugin - - - Contact List Assistant - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Adds simple extras to use with the Contact List. - org.jivesoftware.sparkimpl.plugin.chat.ContactListAssistantPlugin - - - My Favorites - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Adds simple extras to show your most popular contacts. - org.jivesoftware.sparkimpl.plugin.history.FrequentContactsPlugin - - - Language Plugin - 1.0 - Derek DeMoro - http://www.jivesoftware.com - derek@jivesoftware.com - Allows users to explicitly set their language. - org.jivesoftware.sparkimpl.plugin.language.LanguagePlugin - - - SystemTray - 1.0 - Michael Will - http://www.igniterealtime.org - michael-will@gmx.net - SystemTray. - org.jivesoftware.sparkimpl.plugin.systray.SysTrayPlugin - - - UserIdle - 1.0 - Michael Will - http://www.igniterealtime.org - michael-will@gmx.net - SystemTray. - org.jivesoftware.sparkimpl.plugin.idle.UserIdlePlugin - - - Privacy Lists - 2.0 - Holger Bergunde - http://www.igniterealtime.org - 9bergund@informatik.uni-hamburg.de - Privacy lists. - org.jivesoftware.sparkimpl.plugin.privacy.PrivacyPlugin - - diff --git a/src/resources/PkgInfo b/src/resources/PkgInfo deleted file mode 100644 index bd04210fb..000000000 --- a/src/resources/PkgInfo +++ /dev/null @@ -1 +0,0 @@ -APPL???? \ No newline at end of file diff --git a/src/resources/i18n/CompareLocales.java b/src/resources/i18n/CompareLocales.java deleted file mode 100644 index f9f257892..000000000 --- a/src/resources/i18n/CompareLocales.java +++ /dev/null @@ -1,85 +0,0 @@ -import java.io.File; -import java.io.FileInputStream; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Properties; - -/** - * To Run in Terminal: - * javac CompareLocales.java - * java CompareLocales - * - * - * - * - * Use this Class to compare your locale with the standard english to find - * missing entries - * - * @author wolf.posdorfer - * - */ -public class CompareLocales { - - static HashMap_englishlist = new HashMap<>(); - static HashMap _mylocalelist = new HashMap<>(); - - static String _path = "C:\\Dokumente und Einstellungen\\wolf.posdorfer\\Desktop\\eclipse\\spark\\src\\resources\\i18n\\spark_i18n"; - static String english = _path + ".properties"; - static String totest = _path + "_pl.properties"; - - public static void main(String[] args) { - - readFile(new File(english), _englishlist); - readFile(new File(totest), _mylocalelist); - - - for(String key : _englishlist.keySet()) - { - if(!_mylocalelist.containsKey(key)) - { - System.out.println(key +" = "+ _englishlist.get(key)); - } - } - - for(String key : _mylocalelist.keySet()) - { - - if(!_englishlist.containsKey(key)) - { - System.out.println("Not Found in English: "+key +" = "+ _mylocalelist.get(key)); - } - } - - - System.out.println("standardlist has: " + _englishlist.size() + " , my local has " + _mylocalelist.size()); - - - } - - - /** - * Reads a file into the Destination - * - * @param file - * @param destination - */ - public static void readFile(File file, HashMap destination) { - - Properties props = new Properties(); - - try { - - props.load(new FileInputStream(file)); - } catch (Exception e) { - System.err.println("error with file"); - } - - Enumeration enume = props.keys(); - while(enume.hasMoreElements()) - { - String s = (String) enume.nextElement(); - destination.put(s, props.getProperty(s)); - } - - } -} diff --git a/src/resources/i18n/spark_i18n.properties b/src/resources/i18n/spark_i18n.properties deleted file mode 100644 index 7942d26be..000000000 --- a/src/resources/i18n/spark_i18n.properties +++ /dev/null @@ -1,1121 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.0.1 -## Added key: 'message.restart.spark.changes' -## Added key: 'message.enter.icq' -## Added key: 'title.icq.registration' -## Added key: 'button.quit' -## -## -## -## 2.0.2 -## Added key: 'button.new' -## Added key: 'label.group' -## Added key: 'label.jabber.id' -## Added key: 'label.enter.group.name' -## Added key: 'title.new.roster.group' -## Added key: 'title.add.contact.group' -## Added key: 'message.add.contact.to.list' -## Added key: 'title.add.contact' -## Added key: 'tab.conferences' -## Added key: 'message.autenticating' -## Added key: 'title.file.transfer.preferences' -## Added key: 'menuitem.about' -## Added key: 'message.invalid.status' -## Added key: 'message.cannot.add.contact.to.shared.group -## Added key: 'message.specify.contact.jid' -## Added key: 'message.invalid.jid.error' -## Added key: 'message.specify.group' -## Added key: 'add' -## -## -## -## 2.0.5 -## Added key: 'Broadcast' -## Added key: 'label.user.on.public.network' -## Added key: 'label.network' -## -## -## 2.0.6 -## Added key: 'button.add.user' -## Added key: 'menuitem.sign.in' -## Added key: 'menuitem.sign.out' -## Added key: 'menuitem.sign.in.at.login' -## Added key: 'menuitem.enter.login.information' -## Added key: 'menuitem.delete.login.information' -## Added key: 'button.save' -## -## -## 2.5 -## Added key: 'button.start.chat' -## Added key: 'button.send.email' -## Added key: 'available' -## Added key: 'checkbox.tabs.on.top' -## Added key: 'user.has.signed.in' -## Added key: 'user.has.signed.off' -## Added key: 'label.unable.to.add.contact' -## Added key: 'label.conflict.error' -## Added key: 'message.room.creation.error' -## Added key: 'checkbox.allow.buzz' -## Added key: 'message.disconnected.group.chat.error' -## Added key: 'menuitem.show.offline.group' -## Added key: 'menuitem.move.to' -## Added key: 'menuitem.copy.to' -## Added key: 'label.message.style' -## Added key: 'label.emoticons' -## Added key: 'checkbox.enable.emoticons' -## Added key: 'message.unable.to.retrieve.last.activity' -## Added key: 'checkbox.use.system.look.and.feel' -## -## 2.5.2 -## Added key: 'tooltip.place.voice.call' -## Added key: 'message.buzz.alert.notification' -## Added key: 'message.buzz.sent' -## -## 2.5.2 -## Added key: 'menuitem.user.guide' -## -## -## -## 2.5.7 -## Added key: 'menuitem.languages' -## Added key: 'message.restart.required' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'message.send.to.these.people' -## Added key: 'message' -## Added key: 'message.normal' -## Added key: 'message.alert.notify' -## -## 2.5.8 -## Added key: 'message.enter.simple' -## Added key: 'message.enter.irc' -## Added key: 'message.enter.gadugadu' -## Added key: 'title.simple.registration' -## Added key: 'title.irc.registration' -## Added key: 'title.gadugadu.registration' -## Added key: 'message.username.error' -## Added key: 'message.password.error' -## Added key: 'message.nickname.error' -## -## 2.5.9 -## Added key: 'message.gateway.username.error. -## Added key: 'message.gateway.password.error. -## Added key: 'message.gateway.nickname.error. -## Added key: 'answer' -## Added key: 'online' -## Added key: 'online' -## Added key: 'offline' -## Added key: 'participants' -## Added key: 'unfiled' -## Added key: 'while.offline' -## Added key: 'action.clear' -## Added key: 'action.copy ' -## Added key: 'action.cut' -## Added key: 'action.paste' -## Added key: 'action.print' -## Added key: 'action.save' -## Added key: 'action.select.all' -## Added key: 'button.add2' -## Added key: 'button.copy.to.clipboard' -## Added key: 'button.reconnect2' -## Added key: 'button.tasks.active' -## Added key: 'button.tasks.all' -## Added key: 'button.view.notes' -## Added key: 'button.view.profile' -## Added key: 'button.view.tasklist' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.show.avatars.in.contaclist' -## Added key: 'checkbox.use.compression' -## Added key: 'group.empty' -## Added key: 'group.offline' -## Added key: 'label.add.task' -## Added key: 'label.chatroom.fontsize' -## Added key: 'label.contactlist.fontsize' -## Added key: 'label.due' -## Added key: 'label.show' -## Added key: 'label.timeformat' -## Added key: 'menuitem.dial' -## Added key: 'menuitem.view.logs' -## Added key: 'message.disconnected.shutdown' -## Added key: 'message.invalid.username.password' -## Added key: 'message.no.updates' -## Added key: 'message.reconnect.attempting' -## Added key: 'message.reconnect.failed' -## Added key: 'message.reconnect.wait' -## Added key: 'message.send.picture' -## Added key: 'message.server.unavailable' -## Added key: 'message.unrecoverable.error' -## Added key: 'message.waiting.for.user.to.join' -## Added key: 'status.available' -## Added key: 'status.away' -## Added key: 'status.custom.messages' -## Added key: 'status.do.not.disturb' -## Added key: 'status.extended.away' -## Added key: 'status.free.to.chat' -## Added key: 'status.on.phone' -## Added key: 'status.online' -## Added key: 'status.pending' -## Added key: 'title.about' -## Added key: 'title.appearance' -## Added key: 'title.appearance.preferences' -## Added key: 'title.login.error' -## Added key: 'title.no.updates' -## Added key: 'title.notes' -## Added key: 'title.tasks' -## Added key: 'tooltip.appearance' -## Added key: 'tooltip.file.transfer' -## Added key: 'tooltip.send.email' -## Added key: 'tooltip.start.chat' -## Added key: 'delete.log.permanently' -## Added key: 'delete.permanently' -## Added key: 'label.contactlist.avatarsize' -## Added key: 'title.qq.registration' -## Added key: 'message.enter.qq' -## -## 2.6.0 -## -## Added key: 'apply' -## Added key: 'title.subscription.request' -## Added key: 'label.add.to.roster' -## Added key: 'label.audio.device' -## Added key: 'label.video.device' -## Added key: 'button.re.detect' -## -## 2.6.0 beta 1 -## Added key: 'menuitem.block.contact' -## Added key: 'menuitem.unblock.contact' -## Removed key: 'status.available' -## Added key: 'message.nickname.not.acceptable' -## Added key: 'button.login' -## Added key: 'administrator' -## Added key: 'menuitem.add.groupchat.showrolesinsteadofstatus' -## Added key: 'checkbox.click.single.tray' -## 2.7.0 beta 1 -## Added key: 'message.search.period.month.one' -## Added key: 'message.search.period.year.one' -## Added key: 'message.search.period.none' -## Added key: 'message.search.page.timeperiod' -## Added key: 'message.search.page.counter' -## Added key: 'message.search.page.right' -## Added key: 'message.search.page.left' -## Added key: 'checkbox.sort.asc.history' -## Added key: 'message.file.transfer.dirnull' -## Added key: 'message.file.transfer.nodir' -## Added key: 'message.file.transfer.cantwritedir' -## Added key: 'message.file.transfer.direrror.setdir' - -accept = Accept -active = Active -add = Add -administrator = Administrator -answer = Answer -apply = Apply -available = Available -broadcast = Broadcast -cancel = Cancel -close = Close -create = Create -date = Date -description = Description -from = From -invite = Invite -join = Join -no = No -not.registered = Not registered -occupants = Occupants -offline = Offline -online = Online -ok = Ok -open = Open -open.folder = Open folder -participants = Participants -refresh = Refresh -reject = Reject -retry = Retry -room.name = Room Name -save = Save -subject = Subject -unfiled = Unfiled -use.default = Use Default -user.has.signed.in = has signed in. -user.has.signed.off = has signed off. -while.offline = While offline -yes = Yes - -action.clear = Clear -action.copy = Copy -action.cut = Cut -action.paste = Paste -action.print = Print -action.save = Save -action.select.all = Select all - -button.accept = Accept -button.add = A&dd -button.add.a.contact = Add a contact -button.add.bookmark = Add bookmark -button.add.service = Add service -button.add.user = Add user -button.add2 = Add -button.advanced = A&dvanced -button.approve = Approve -button.bookmark.room = Bookmark room -button.browse = &Browse... -button.browse2 = Browse... -button.browse3 = Browse... -button.cancel = Cancel -button.clear = Clear -button.close = Close -button.copy.to.clipboard = Copy to clipboard -button.create.account = Create account -button.create.room = Create or join room -button.decline = Decline -button.deny = Deny -button.dial.number = Dial number -button.find = Find -button.join = Join -button.join.room = Join selected room -button.login = &Login -button.new = New -button.profile = Profile -button.quit = Quit -button.re.detect = &Re-detect -button.reconnect = Reconnect -button.reconnect2 = Reconnect -button.refresh = Refresh -button.register = Register -button.reject = Reject -button.remove.bookmark = Remove bookmark -button.roster = Roster -button.save = Save -button.save.for.future.use = Save for future use -button.search = Search -button.send = Send -button.send.email = Email -button.start.chat = Chat -button.tasks.active = Active -button.tasks.all = All -button.unset.file.explorer = Unset File Browser -button.update = Update -button.view.notes = View notes -button.view.profile = View full profile -button.view.tasklist = View task list - -checkbox.allow.buzz = Allow users to &buzz you -checkbox.auto.discover.port = Automatically discover host and port -checkbox.auto.login = &Auto login -checkbox.login.as.invisible = L&ogin as invisible -checkbox.disable.chat.history = &Disable chat history -checkbox.sort.asc.history = Sort messages in contact history by date ascending -checkbox.disable.prev.chat.history = Disable &showing previous conversation in chat -checkbox.enable.emoticons = E&nable emoticons -checkbox.graying.out = Dim idle contacts (requires restart) -checkbox.idle.enabled = &Idle enabled -checkbox.launch.on.startup = &Launch on startup -checkbox.reconnet.info = Specify reconnection display: -checkbox.reconnect.panel.big = Display as Panel -checkbox.reconnect.panel.small = Display in contact group -checkbox.reconnect.panel.icon = Display as icon -checkbox.notify.user.comes.online = Notify when a user &comes online -checkbox.notify.user.goes.offline = &Notify when a user goes offline -checkbox.notify.typing.systemtray = &Show typing notification in the system tray -checkbox.notify.systemtray = Show new &messages in the system tray -checkbox.permanent = Room is permanent -checkbox.play.sound.on.invitation = Play sound when &invitation is received -checkbox.play.sound.on.new.message = &Play sound when new message arrives -checkbox.play.sound.on.outgoing.message = Play sound when message is &sent -checkbox.play.sound.when.offline = Play sound when user goes &offline -checkbox.private.room = Room is private -checkbox.save.password = Sa&ve password -checkbox.show.avatars.in.contactlist = Show &avatars in contact list -checkbox.show.notifications.in.conference = Show ¬ifications in conference rooms -checkbox.show.time.in.chat.window = Show &time in chat window -checkbox.show.toaster = Show a &toast popup -checkbox.disable.asterisk.toaster = Disable phone toast popup -checkbox.split.chat.window = Dock windows (requires restart) -checkbox.start.in.tray = &Start in system tray -checkbox.click.single.tray = &Use single click in system tray to bring spark to front -checkbox.tabs.on.top = Chat tabs &appear on top (requires restart) -checkbox.use.compression = Use compression -checkbox.use.debugger.on.startup = Start debugger on startup -checkbox.use.proxy.server = Use proxy server -checkbox.use.system.look.and.feel = Use system &look And feel (requires restart) -checkbox.window.to.front = Bring &window to front -checkbox.broadcast.hide.offline.user = Hide offline user -checkbox.use.krbconf = Use krb5.conf or krb5.ini -checkbox.use.krb.dns = Use DNS -checkbox.use.specify.below = Specify below -checkbox.use.pki.authentication = Use PKI authentication -checkbox.transport.tab.setting = Show available transports in tab (requires restart) -checkbox.conference.tab.setting = Show conference service in tab (requires restart) -checkbox.use.hostname.as.resource = Use hostname as resource -checkbox.use.version.as.resource = Use Spark version as resource - -delete.log.permanently = Permanently delete log -delete.permanently = Permanently delete? - -gateway.username.password.error = Username and/or password need to be supplied - -group.chat.window.information = Chat window information -group.comma.delimited = Comma delimited -group.conferences.found = Conference services Found -group.connection = Connection -group.empty = There are no online contacts in this group -group.general.information = General information -group.login.information = Login information -group.notification.options = Notification options -group.offline = Offline group -group.search.form = Search form -group.search.results = Search results -group.chat.name.notification = Seen your name... -group.chat.name.match = Your name has been said in group chat: - -label.na = n/a -label.cell = Cell -label.work = Work -label.home = Home -label.accounts = A&ccounts -label.passwordreset = Password reset -label.add.conference.service = Add conference service -label.add.jid = Add JID -label.add.task = Add task -label.auto.login = Auto login -label.available.users.in.roster = Available users in roster -label.avatar = Avatar: -label.cancel = Cancel -label.change.password.to = Change &password to -label.chatroom.fontsize = Chat room &font size: -label.city = City -label.close = Close -label.company = Company -label.confirm.password = &Confirm password -label.conflict.error = Unable to login due to account already signed in -label.contact.to.find = Find contact -label.recent.conversation = Recent Conversations -label.frequent.contacts = Frequent Contacts -label.contactlist.avatarsize = Contact list avatar &size: -label.contactlist.fontsize = &Contact List font size: -label.country = Country -label.create.account = Create account -label.department = Department -label.dial = Dial -label.display.time = Display Time: -label.downloads = Downloads -label.due = Due -label.email.address = Email address -label.emoticons = &Emoticons -label.enter.address = Enter address -label.enter.group.name = Enter new group name -label.fax = Fax -label.find = Find -label.first.name = First name -label.group = Group -label.host = Host -label.invited.users = Invited users -label.jabber.address = Jabber address -label.jabber.id = Jabber ID -label.jid = JID -label.job.title = Job title -label.last.name = Last name -label.local.time = Local time -label.message = Message -label.message.style = Message style -label.middle.name = Middle name -label.minutes.before.stale.chat = &Minutes before an inactive room becomes stale -label.mobile = Mobile -label.name = Name -label.network = Network -label.new.nickname = New nickname -label.nickname = Nickname -label.number = Number -label.ok = OK -label.old.ssl = Use old SSL port method -label.os = Operating system -label.pager = Pager -label.password = &Password -label.phone = Phone -label.port = Port -label.postal.code = Postal code -label.presence = Presence -label.priority = Priority -label.protocol = Protocol -label.received = Received -label.rename.to = Rename to -label.resource = Resource -label.response.timeout = &Response timeout (sec) -label.room = Room -label.room.name = Room name -label.room.topic = Room topic -label.search = Search -label.search.service = Search service -label.seconds = Seconds -label.server = &Server -label.server.address = Server address -label.show = Show: -label.software = Software -label.state.and.province = State/province -label.street.address = Street address -label.time = Time: {0} -label.time.till.idle = &Time till idle (min) -label.time.till.idlemessage = Automatic idl&e message -label.timeformat = Use {0} -label.transfer.download.directory = &Download directory: -label.transfer.timeout = &Transfer timeout (min): -label.unable.to.add.contact = Unable to add contact -label.use.default = Use default -label.user.on.public.network = User is on a public network -label.username = &Username -label.version = Version -label.web.page = Web page -label.xmpp.port = &XMPP port -label.krb.realm = Realm -label.krb.kdc = KDC -label.which.pki.method = Which PKI method? -label.choose.file = Choose file -label.trust.store.password = Trust store password -label.enter.password = Enter password -label.move.focus.forwards = Move focus forwards -label.move.focus.backwards = Move focus backwards -label.keystore.location = Keystore location -label.truststore.location = Truststore location -label.pkcs.library.file = PKCS#11 library file -label.x509.certificate = X.509 certificate -label.apple.keychain = Apple KeyChain -label.add.to.roster = Add user to your roster -label.audio.device = &Audio device -label.video.device = &Video device - -menuitem.about = About -menuitem.actions = Actions -menuitem.bookmarks = Bookmarks -menuitem.add = Add -menuitem.add.as.contact = Add as a contact -menuitem.add.contact = Add contact -menuitem.add.contact.group = Add contact group -menuitem.add.groupchat.myname = Highlight my &name when someone says it -menuitem.add.groupchat.mytext = &Highlight my text when I say something -menuitem.add.groupchat.popname = Show &toast popup when someone says my name -menuitem.add.groupchat.showjoinleavemessage = &Show join and leave messages -menuitem.add.groupchat.showrolesinsteadofstatus = Show chat role icons instead of presence icons -menuitem.add.groupchat.auto.accept.invite = &Automatically accept groupchat invites -menuitem.add.groupchat.random.colors = Names have &random colors -menuitem.always.on.top = Always on top -menuitem.alert.when.online = Alert when user is available -menuitem.ban = Ban -menuitem.ban.user = Ban user -menuitem.block.user = Block user -menuitem.broadcast.to.group = Broadcast message to group -menuitem.browse.service = Browse service -menuitem.change.nickname = Change nickname -menuitem.change.subject = Change subject -menuitem.chat = Chat -menuitem.check.for.updates = Check for &updates -menuitem.connect = File -menuitem.contacts = Contacts -menuitem.copy.to = Copy to -menuitem.delete = Delete -menuitem.delete.login.information = Delete login information -menuitem.destroy.room = Destroy room -menuitem.dial = Dial -menuitem.edit = Edit -menuitem.edit.my.profile = Edit my profile... -menuitem.edit.status.message = Edit custom status messages... -menuitem.enter.login.information = Enter login information -menuitem.exit = Exit -menuitem.affiliation = Affiliation -menuitem.grant.moderator = Grant moderator -menuitem.grant.member = Grant Membership -menuitem.grant.admin = Grant Admin -menuitem.grant.owner = Grant Ownership -menuitem.grant.voice = Grant voice -menuitem.help = Help -menuitem.hide = Hide -menuitem.invite.group.to.conference = Invite group to conference -menuitem.invite.users = Invite users -menuitem.join.on.startup = Join on startup -menuitem.join.room = Join selected room -menuitem.kick.user = Kick user -menuitem.languages = Languages -menuitem.logout.no.status = Log out -menuitem.logout.with.status = Log out with reason -menuitem.lookup.profile = Lookup profile... -menuitem.move.to = Move to -menuitem.online.help = Spark forums -menuitem.open = Open -menuitem.open.with = Open with... -menuitem.plugins = Plugins -menuitem.preferences = Preferences -menuitem.remove = Remove -menuitem.remove.alert.when.online = Remove alert -menuitem.remove.bookmark = Remove bookmark -menuitem.remove.from.group = Remove From group -menuitem.remove.from.roster = Remove from roster -menuitem.block.contact = Block contact -menuitem.unblock.contact = Unblock contact -menuitem.remove.service = Remove service -menuitem.rename = Rename -menuitem.revoke.moderator = Revoke moderator -menuitem.revoke.voice = Revoke voice -menuitem.revoke.member = Revoke Membership -menuitem.revoke.admin = Revoke Admin -menuitem.revoke.owner = Revoke Ownership -menuitem.save = Save -menuitem.save.as = Save as... -menuitem.send.a.file = Send a file -menuitem.send.a.message = Send broadcast to selected users... -menuitem.set.status.message = Set status message... -menuitem.show.empty.groups = Show empty groups -menuitem.show.offline.group = Group offline users -menuitem.show.traffic = Show traffic window -menuitem.sign.in = Sign in -menuitem.sign.in.at.login = Sign in at login -menuitem.sign.out = Sign out -menuitem.start.a.chat = Start a chat -menuitem.start.a.conference = Start a conference... -menuitem.status = Status -menuitem.subscribe.to = Subscribe to -menuitem.unban = Unban user on current list -menuitem.unblock.user = Unblock user on current list -menuitem.user.guide = User guide -menuitem.view.client.version = View client version -menuitem.view.contact.history = View contact history -menuitem.view.downloads = View downloads -menuitem.view.last.activity = View last activity -menuitem.view.logs = View logs -menuitem.view.profile = View profile -menuitem.view.room.info = View room info -menuitem.voice = Voice -menuitem.show.offline.users = Show offline users -menuitem.show.contact.statusmessage = Show status message -menuitem.bookmark.room = Bookmark room -menuitem.refresh = Refresh -menuitem.create.room = Create or join room -menuitem.expand.all.groups = Expand all groups -menuitem.collapse.all.groups = Collapse all groups -menuitem.inivite.again = Invite again -menuitem.chatframe.option = Options -menuitem.add.groupchat.invitetobookmark = Automatically invite users to bookmarked room - -message.invite.to.groupchat = {0} is inviting you to join a group chat -message = Message -message.account.create = Create a new chat account -message.account.created = New account has been created -message.account.error = Specify the server to create the account on -message.add.a.contact = Add a contact -message.add.conference.service = Add a conference service -message.add.contact.to.list = Add a user to your contact list -message.add.favorite.room = Add room to favorites list or join directly -message.add.this.user.to.your.roster = Add this user to your buddy list -message.add.to.roster = Add To roster -message.add.user = Add user to your roster? -message.alert.notify = Alert notification -message.already.exists = Account already exists, please try a different username -message.approve.subscription = Allow {0} to add you to their roster? -message.autenticating = Authenticating -message.away.idle = Away due to idle -message.bookmark.temporary.room.error = You cannot bookmark temporary rooms -message.broadcast.from = Broadcast from {0} -message.broadcast.no.user.selected = Please select at least one recipient -message.broadcast.no.text = Please enter text to broadcast -message.broadcast.message.sent = The broadcast message has been sent -message.broadcast.to = Enter message to broadcast to {0} -message.broadcasted.to = The message has been broadcasted to the following users\:\n{0} -message.buzz.alert.notification = Get the user's attention -message.buzz.message = {0} wants your attention -message.buzz.sent = Requested users attention -message.calling = Calling {0} -message.came.online = {0} is online at {1} -message.cannot.add.contact.to.shared.group = You cannot add new contacts to a shared group -message.chat.session.ended = Chat session has ended on {0} -message.click.to.open = Click to open -message.client.information = Client information for {0} -message.close.other.chats = Close all other chats -message.close.stale.chats = Close stale chats -message.close.this.chat = Close this chat -message.conference.info.error = Unable to retrieve conference information, please try back later -message.conference.service.error = Unable to locate the conference service -message.confirm.destruction.of.room = Destroying the room removes all users from the room, continue? -message.confirmation.password.error = Specify a confirmation password -message.connecting.please.wait = Connecting, please wait... -message.connection.failed = Unable to connect to {0} -message.create.account = Account could not be created -message.create.or.join.room = Create or join a conference chat room -message.current.status = Let others know your current status or activity -message.default.error = An error has been detected. Please report to support@jivesoftware.com -message.delete.all.history = Delete all previous conversations? -message.delete.confirmation = Are you sure you want to delete {0}? -message.disable.transport = Remove login information from {0}? -message.disconnected.conflict.error = Your connection was closed due to the same user logging in from another location -message.disconnected.error = Your connection was closed due to an error -message.disconnected.group.chat.error = Your connection was closed due to an error, Spark will automatically re-join the channel when reconnection is successful -message.disconnected.shutdown = Your connection was closed because the server was shut down -message.downloading = Downloading {0} -message.downloading.spark.plug = Downloading Spark-Plug -message.end.chat = Would you like to end this chat? -message.end.conversation = Would you like to end this session? -message.enter.aim = Enter your AIM username and password below -message.enter.broadcast.message = Enter message to broadcast to selected users -message.enter.gadugadu = Enter your GaduGadu username and password below -message.enter.gtalk = Enter your GTalk username and password below -message.enter.icq = Enter your ICQ username and password below -message.enter.irc = Enter your IRC username, password and nickname below -message.enter.sametime = Enter your Sametime username and password below -message.enter.facebook = Enter your Facebook username and password below -message.enter.myspace = Enter your MySpace username and password below -message.enter.jabber.id = Enter Jabber ID -message.enter.message.to.broadcast = Enter message to broadcast to your entire roster list -message.enter.msn = Enter your MSN username and password below -message.enter.new.subject = Enter new subject -message.enter.qq = Enter your QQ Number and password below -message.enter.room.password = Enter room password -message.enter.simple = Enter your SIMPLE username and password below -message.enter.valid.jid = Enter a valid Jabber ID -message.enter.xmpp = Enter your XMPP username and password below -message.enter.yahoo = Enter your username and password to connect to Yahoo -message.error.during.file.transfer = There was an error during file transfer -message.file.exists.question = The file already exists, overwrite? -message.file.size = File Size: {0} -message.file.transfer.canceled = You have canceled the file transfer -message.file.transfer.rejected = The file transfer was not accepted by {0} -message.file.transfer.dirnull = Download directory for file transfer is not valid -message.file.transfer.nodir = Download directory for file transfer does not exist -message.file.transfer.cantwritedir Can't write to the directory for file transfer -message.file.transfer.notification = File transfer notification -message.file.transfer.short.message = is sending you a file called\: -message.file.transfer.chat.window = File transfer request: -message.file.transfer.file.too.big.error = The selected file is too big.\nThe maximum filezise is {0} the selected file has {1} -message.file.transfer.file.too.big.warning = The selected file is too big.\nProceed anyway? -message.file.transfer.direrror.setdir = Click here to change the directory -message.find.conference.services = Find conference services -message.forbidden.error = Received a forbidden error from the server -message.gateway.username.error = Username needs to be supplied -message.gateway.password.error = Password needs to be supplied -message.gateway.nickname.error = Nickname needs to be supplied -message.general.error = You have lost your connection to the server due to {0} -message.generic.reconnect.message = You have lost your connection to the server, to login again, click on the reconnect button below -message.idle.for = Idle for {0} -message.image.too.large = This image is too large to use, please specify an image 16k or smaller -message.invalid.jabber.id = Not a valid Jabber ID -message.invalid.jid.error = The JID specified is invalid -message.invalid.status = Specify a valid status message -message.invalid.username.password = Invalid username or password -message.invite.users.to.conference = Invite users to a conference room -message.is.shared.group = {0} is a shared group -message.is.typing.a.message = {0} is typing a message... -message.join.conference.room = Join conference room -message.kicked.error = You are not able to kick {0} out of this room -message.last.message.received = Last message received on {0} -message.loading.please.wait = Loading. Please wait... -message.locked.workstation = User has locked their workstation -message.name.of.group = Name of group -message.name.of.search.service.question = Name of search service? -message.negotiate.file.transfer = Negotiating file transfer, please wait... -message.negotiate.stream = Negotiating connection stream, please wait... -message.negotiation.file.transfer = Negotiating file transfer with {0}, please wait... -message.new.message = New message from {0} -message.new.spark.available = {0} is now available, would you like to install? -message.nickname.in.use = Nickname in use, please specify another Nickname -message.nickname.not.acceptable = Nickname change is not enabled! -message.no.avatar.found = No avatar was configured by the user -message.no.caller.id = No caller ID available -message.no.description.available = No description available -message.no.history.found = There is no previous conversation history for this user -message.no.results.found = No search results were returned by the server -message.no.room.to.join.error = No room to join -message.no.subject.available = No subject available -message.no.updates = There are no updates -message.normal = Normal message -message.number.to.call = Specify number to dial -message.offline = The user is offline and will receive the message on their next login -message.offline.error = The user will be unable to receive offline messages -message.participants.in.room = Participants in room -message.password.error = Specify a password for this account -message.password.private.room.error = Specify password for the private room -message.passwords.no.match = Passwords do not match -message.please.join.in.conference = Please join me in a conference -message.plugins.not.available = Unable to contact the plugin repository -message.prompt.plugin.uninstall = Are you sure you want to deactivate {0}? -message.received.file = You have received a file from {0} -message.receiving.file = You are receiving a file from {0} -message.reconnect.attempting = Attempting... -message.reconnect.failed = Reconnect failed -message.reconnect.wait = Reconnecting in {0} seconds -message.register.transports = Register with these available transports -message.registering = Registering with {0}, please wait... -message.registration.transport.failed = Unable to register with gateway -message.restart.spark = You will need to shut down the client to \n install the new version, would you like to do that now? -message.restart.spark.changes = Plugin will be removed on the next startup of Spark -message.restart.spark.to.install = You need to shut down the client to install latest version, would you like to do that now? -message.restart.required = You will need to restart Spark to have your changes take effect, restart now? -message.room.creation.error = The room could not be created -message.room.destroyed = This room has been destroyed due to the following reason: {0} -message.room.destruction.reason = Reason for destroying the room? -message.room.information.for = Room information for {0} -message.save.profile = To save changes to your profile, click save -message.search.for.contacts = Search for contacts -message.search.input.short = Please provide atleast five letters. -message.search.for.other.people = Search for other people on the server -message.search.service.not.available = Unable to contact search service -message.searching.please.wait = Searching, please wait... -message.select.add.room.to.add = Please select a room to add to your service list -message.select.one.or.more = Select one or more users in your roster -message.select.room.to.enter = Specify room to enter -message.select.room.to.join = Select room to join -message.send.a.broadcast = Send a broadcast -message.send.file.to.user = Send files to this user -message.send.picture = Capture and send anything you see on your screen -message.send.to.these.people = Send to these people -message.sending.file.to = Sending file to {0} -message.sent.offline.files = You have just been sent offline file(s). -message.server.unavailable = Can't connect to server: invalid name or server not reachable -message.service.already.exists = Service is already in your service list -message.shared.group = Shared group -message.spark.secure = Spark is running in secure mode -message.specify.contact.jid = Please specify the contact JID (ex. ddman@jabber.org) -message.specify.group = Specify contact group to add the new user to -message.specify.information.for.conference = Specify information for conference room -message.specify.name.error = Specify a valid name -message.specify.users.to.join.conference = Specify users to join this conference room -message.specify.valid.time.error = Specify a valid timeout and port -message.subject.change.error = You are not allowed to change the subject of this room -message.subject.has.been.changed.to = {1} changed the subject to "{0}" -message.supply.resource = Supply a valid resource -message.supply.valid.port = Supply a valid port -message.supply.valid.timeout = Supply a valid time out value -message.timeout.error = The timeout must be 5 seconds or greater -message.total.downloaded = Total downloaded -message.transfer.cancelled = The file transfer was canceled -message.transfer.complete = The file transfer was complete ({0}) -message.transfer.progressbar.text.received = {0} received @ {1} {2} -message.transfer.progressbar.text.sent = {0} sent @ {1} {2} -message.transfer.rate = Transfer rate -message.transfer.refused = The file transfer was refused -message.transfer.waiting.on.user = Waiting for {0} to accept file transfer -message.unable.to.load.profile = Unable to locate a profile for {0} -message.unable.to.retrieve.last.activity = Unable to determine last activity for {0} -message.unable.to.save.password = Unable to change password, please contact your server admin -message.unable.to.send.file = You were unable to send the file to {0} -message.unable.to.use.hostname.as.resource = Unable to use hostname as resource -message.unrecoverable.error = Invalid username or password -message.update.room.list = Update room list -message.updating.cancelled = Updating has been canceled -message.user.banned = {0} has been banned from this room. Reason: {1} -message.user.given.voice = {0} has been given a voice in this room -message.user.granted.admin = {0} has been granted administrator privileges -message.user.granted.membership = {0} has been given membership privileges -message.user.granted.moderator = {0} has been granted moderator privileges -message.user.granted.owner = {0} has been granted owner privileges -message.user.is.sending.you.a.file = {0} is sending you a file -message.user.joined.room = {0} has joined the room -message.user.kicked.from.room = {0} has been kicked out of the room by {1}. Reason: {2} -message.user.left.room = {0} has left the room -message.user.nickname.changed = {0} is now known as {1} -message.user.now.available.to.chat = {0} is online at {1} -message.user.revoked.admin = Administrator privileges have been revoked for {0} -message.user.revoked.membership = Membership has been revoked for {0} -message.user.revoked.moderator = Moderator privileges have been revoked for {0} -message.user.revoked.owner = Owner privileges have been revoked for {0} -message.user.voice.revoked = Voice has been revoked for {0} -message.username.error = Specify a username for the account -message.username.password.error = Username and/or password need to be supplied. -message.vcard.not.supported = Server does not support VCards, unable to save your VCard -message.version = Version: {0} -message.view.information.about.this.user = View information about this user -message.waiting.for.user.to.join = Waiting for {0} to join -message.went.offline = {0} went offline at {1} -message.you.have.been.banned = You have been banned from this room -message.you.have.been.kicked = You have been kicked out of this room -message.you.have.sent = You have sent a file to {0} -message.your.admin.granted = You have been granted administrator privileges -message.your.banned = You have been banned from this room -message.your.kicked = You have been kicked by {0} -message.your.membership.granted = You have been granted membership privileges -message.your.membership.revoked = Your membership has been revoked -message.your.moderator.granted = You have been granted moderator privileges -message.your.moderator.revoked = Your moderator privileges have been revoked -message.your.ownership.granted = Your have been granted owner privileges -message.your.ownership.revoked = Your owner privileges have been revoked -message.your.revoked.granted = Your admin privileges have been revoked -message.your.voice.granted = You have been given a voice in this chat -message.your.voice.revoked = Your voice has been revoked -message.groupchat.require.password = This group chat room requires a password to enter -message.groupchat.registered.member = Successfully registered with {0} -message.search.for.history = Search conversation history -message.search.period.month.one = one month per page -message.search.period.year.one = one year per page -message.search.period.none = show all on one page -message.search.page.timeperiod = choose the timespan of messages, which are displayed per page -message.search.page.counter = the current index of your page and the amount of all pages -message.search.page.right = navigate one page forward -message.search.page.left = navigate one page backward - -status.away = Away -status.custom.messages = Custom messages -status.do.not.disturb = Do not disturb -status.extended.away = Extended away -status.free.to.chat = Free to chat -status.on.phone = On the phone -status.online = Online -status.pending = Pending -status.invisible = Invisible -status.offline = Offline - -tab.available.plugins = Available plugins -tab.avatar = Avatar -tab.business = Business -tab.conferences = Conferences -tab.contacts = Contacts -tab.general = General -tab.home = Home -tab.installed.plugins = Installed plugins -tab.deactivated.plugins = Deactivated plugins -tab.personal = Personal -tab.proxy = Proxy -tab.sso = SSO -tab.pki = PKI - -title.about = About -title.password.required = Password required -title.task.notification = Task notification -title.client.logs = Client logs -title.advanced.connection.preferences = Advanced connection preferences -title.account.create.registration = Account registration -title.bookmarks = Bookmarks -title.account.created = Account created -title.add.contact = Add contact -title.add.contact.group = Add contact group -title.add.new.group = Add new group -title.add.search.service = Add search service -title.add.to.roster = Add to roster -title.address = Address -title.advanced.connection.sso = Using Single Sign-On (SSO) -title.advanced.connection.usesso = Use Single Sign-On (SSO) via GSSAPI -title.advanced.connection.sso.account = This will use the Desktop Account for "{0}" to login to the server. -title.advanced.connection.sso.unable = Unable to connect using Single Sign-On. Please check your principal and server settings. -title.advanced.connection.sso.noprincipal = Spark is unable to find the principal to use for Single Sign-On. This will prevent SSO from working. -title.alert = Alert -title.appearance = Appearance -title.appearance.preferences = Customization -title.available.transports = Available transports -title.broadcast.message = Broadcast message -title.browse.conference.services = Browse conference services -title.browse.room.service = Browse conference rooms - {0} -title.cancelled = Cancelled -title.change.nickname = Change nickname -title.change.subject = Change subject -title.chat = Chat -title.choose.directory = Choose directory -title.choose.incoming.sound = Choose incoming sound file -title.choose.offline.sound = Choose offline sound file -title.choose.outgoing.sound = Choose outgoing sound file -title.conference.invitation = Conference invitation -title.conference.rooms = Conference rooms -title.configure.chat.room = Configure chat room -title.configure.room = Configure room -title.confirmation = Confirmation -title.create.new.account = Create new account -title.create.or.bookmark.room = Join or bookmark room -title.create.or.join = Create/join -title.create.problem = Account creation problem -title.delete.file = Do you really want to delete this file? -title.dial.phone = Dial phone -title.disable.transport = Remove login information -title.download.complete = Download complete -title.downloading.im.client = Download IM client -title.downloads = Downloads -title.edit.custom.message = Edit custom messages -title.edit.profile = Edit profile information -title.enter.reason = Enter reason -title.error = Error -title.error.couldnt.open.file = Could not open the file -title.error.delete.file = Could not delete file -title.error.find.app = Could not find a matching application -title.error.rename.file = Could not rename the file -title.file = File -title.filesize = Size -title.file.exists = File exists -title.file.transfer = File transfer -title.file.transfer.preferences = File transfer preferences -title.find.conference.service = Find conference service -title.find.contacts = Find contacts -title.gadugadu.registration = GaduGadu account credentials -title.general.media = Media settings -title.general.chat.settings = General chat settings -title.group.chat = Group chat -title.group.chat.settings = Group chat settings -title.gtalk.registration = GTalk account credentials -title.history.for = Conversation history for {0} -title.icq.registration = ICQ account credentials -title.irc.registration = IRC account credentials -title.aim.registration = AIM account credentials -title.sametime.registration = Sametime account credentials -title.facebook.registration = Facebook account credentials -title.myspace.registration = MySpace account credentials -title.incoming.call = Incoming call -title.input.fileexplorer = Please input the name of your file browser: -title.input.newname = Please input the new name\: -title.input.openwith = Please input the name of the application which you want to use: -title.invite.to.conference = Invite To conference -title.jabber.browser = Browser -title.join.conference.room = Join conference room -title.last.activity = Last activity -title.login = Login -title.login.error = Login error -title.login.settings = Login settings -title.login.no.account = Unable to determine -title.lookup.profile = Lookup profile -title.msn.registration = MSN account credentials -title.name = Name -title.new.client.available = New client available -title.new.roster.group = New roster group -title.new.version.available = New version available -title.no.updates = No updates -title.notes = Notes -title.notification = Notification -title.notifications = Notifications -title.occupants = Occupants -title.on.the.phone = On the phone -title.password = Password -title.passwords.no.match = Confirm passwords -title.person.search = Person search -title.plugins = Plugins -title.preferences = Preferences -title.profile.information = Profile information -title.profile.not.found = Profile not found -title.qq.registration = QQ account credentials -title.register.account = Register new account -title.registration.error = Registration error -title.reminder = Reminder -title.rename.roster.group = Rename roster group -title.room.destroyed = Room destroyed -title.room.information = Room information -title.roster = Roster -title.select.file.to.send = Select file(s) to send -title.set.status.message = Set status message -title.simple.registration = SIMPLE account credentials -title.sound.preferences = Sound preferences -title.sounds = Sounds -title.spark.preferences = Spark preferences -title.start.chat = Start chat -title.status.message = Status message -title.tasks = Tasks -title.transports = Transports -title.tray.information = Tray information -title.upgrading.client = Upgrading client -title.version.and.time = Version and time -title.view.bookmarks = View bookmarks -title.view.profile.for = Viewing profile for {0} -title.view.room.information = View room information -title.waiting.to.call = Waiting to place call -title.xmpp.registration = XMPP account credentials -title.yahoo.registration = Yahoo account credentials -title.appearance.showVCards = Show &VCards in the contact list -title.subscription.request = Subscription request - -tooltip.place.a.call = Place a call to this individual -tooltip.appearance = Change the appearance of your conversations -tooltip.file.transfer = Preferences for file transfer -tooltip.notifications = Notification preferences for incoming chats -tooltip.place.voice.call = Place a phone call to this user -tooltip.send.email = Send an e-mail -tooltip.start.chat = Start a conversation -tooltip.view.changelog = View change log -tooltip.view.history = View conversation history -tooltip.view.readme = View readme - -tree.conference.services = Conference services -tree.users.in.room = Users in room - -lookandfeel.select = Select Look & Feel -lookandfeel.change.now = Change now -lookandfeel.tooltip.restart.no = No restart is needed -lookandfeel.tooltip.restart.yes = To toggle a System Look&Feel press Save and restart Spark. -lookandfeel.color.label = Colors -lookandfeel.color.red = Red -lookandfeel.color.green = Green -lookandfeel.color.blue = Blue -lookandfeel.color.opacity = Opacity -lookandfeel.color.saved = Color saved - - -##Settings for the privacy plugin -privacy.title.preferences = Spark Privacy Preferences -privacy.title.panel = Please use right mouse button -privacy.label.iq.desc = Query -privacy.label.pin.desc = Presence in -privacy.label.pout.desc = Presence out -privacy.label.msg.desc = Messages -privacy.border.information = Privacy Information -privacy.label.information = Use right click menu to add or delete lists or items -privacy.root.node = Privacy Lists -privacy.label.preferences = Privacy Plugin -pricacy.tooltip.preferences = Spark privacy settings -privacy.label.list.is.active = Current active list: -privacy.label.list.is.default = Default list: -privacy.border.block = Block -privacy.pick.one.or.more = Pick one or more items to add to the list -privacy.title.add.picker = Add Items to List -privacy.node.contacts = Contacts -privacy.node.groups = Groups -privacy.menu.add.contacts = Add Contacts to list -privacy.menu.add.groups = Add Groups to list -privacy.menu.add.rem.items = Remove {0} items from list -privacy.menu.remove = Remove -privacy.menu.activate.list = Activate -privacy.menu.default.list = Set as default -privacy.menu.add.list = Add list -privacy.menu.remove.list = Remove list -privacy.dialog.add.list = Please enter list name -privacy.dialog.rem.list = Do you really want to remove {0}? -privacy.status.menu.entry = Privacy Lists -privacy.name.for.default.list = Default -privacy.button.no.list.selected = No list selected -privacy.menuitem.deactivate.current.list = Deactivate {0} -privacy.label.not.supported = Privacy lists are not supported by server. - -##Stunfallback in media settings -stun.border.label = STUN fallback server -stun.server.addr = STUN Server: -stun.server.port = STUN Port: - -composing = {0} is typing... -paused = {0} has stopped typing -active = {0} is paying attention -inactive = {0} is doing something else -gone = {0} is doing something else - -#!# -action.viewlog=View Log - -dialog.confirm.to.reveal.visibility.title=Are you sure? -dialog.confirm.to.reveal.visibility.msg=If you are going to proceed your invisibility will be revealed -dialog.confirm.close.all.conferences.if.invisible.msg=If you want to proceed all conference room will be closed diff --git a/src/resources/i18n/spark_i18n_cs.properties b/src/resources/i18n/spark_i18n_cs.properties deleted file mode 100644 index 9d0880465..000000000 --- a/src/resources/i18n/spark_i18n_cs.properties +++ /dev/null @@ -1,733 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.0.1 -## Added key: 'message.restart.spark.changes' -## Added key: 'message.enter.icq' -## Added key: 'title.icq.registration' -## Added key: 'button.quit' -## -## -## -## 2.0.2 -## Added key: 'button.new' -## Added key: 'label.group' -## Added key: 'label.jabber.id' -## Added key: 'label.enter.group.name' -## Added key: 'title.new.roster.group' -## Added key: 'title.add.contact.group' -## Added key: 'message.add.contact.to.list' -## Added key: 'title.add.contact' -## Added key: 'tab.conferences' -## Added key: 'message.autenticating' -## Added key: 'title.file.transfer.preferences' -## Added key: 'menuitem.about' -## Added key: 'message.invalid.status' -## Added key: 'message.cannot.add.contact.to.shared.group -## Added key: 'message.specify.contact.jid' -## Added key: 'message.invalid.jid.error' -## Added key: 'message.specify.group' -## Added key: 'add' -## -## -## -## 2.0.5 -## Added key: 'Broadcast' -## Added key: 'label.user.on.public.network' -## Added key: 'label.network' -## -## -## 2.0.6 -## Added key: 'button.add.user' -## Added key: 'menuitem.sign.in' -## Added key: 'menuitem.sign.out' -## Added key: 'menuitem.sign.in.at.login' -## Added key: 'menuitem.enter.login.information' -## Added key: 'menuitem.delete.login.information' -## Added key: 'button.save' -## -## -## 2.5 -## Added key: 'button.start.chat' -## Added key: 'button.send.email' -## Added key: 'available' -## Added key: 'checkbox.tabs.on.top' -## Added key: 'user.has.signed.in' -## Added key: 'user.has.signed.off' -## Added key: 'label.unable.to.add.contact' -## Added key: 'label.conflict.error' -## Added key: 'message.room.creation.error' -## Added key: 'checkbox.allow.buzz' -## Added key: 'message.disconnected.group.chat.error' -## Added key: 'menuitem.show.offline.group' -## Added key: 'menuitem.move.to' -## Added key: 'menuitem.copy.to' -## Added key: 'label.message.style' -## Added key: 'label.emoticons' -## Added key: 'checkbox.enable.emoticons' -## Added key: 'message.unable.to.retrieve.last.activity' -## Added key: 'checkbox.use.system.look.and.feel' -## -## 2.5.2 -## Added key: 'tooltip.place.voice.call' -## Added key: 'message.buzz.alert.notification' -## Added kye: 'message.buzz.sent' -## -## 2.5.2 -## Added key: 'menuitem.user.guide' -## -## -## -## 2.5.7 -## Added key: 'menuitem.languages' -## Added key: 'message.restart.required' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'message.send.to.these.people' -## Added key: 'message' -## Added key: 'message.normal' -## Added key: 'message.alert.notify' -## -## 2.5.8 -## Added key: 'message.enter.simple' -## Added key: 'message.enter.irc' -## Added key: 'message.enter.gadugadu' -## Added key: 'title.simple.registration' -## Added key: 'title.irc.registration' -## Added key: 'title.gadugadu.registration' -## Added key: 'message.username.error' -## Added key: 'message.password.error' -## Added key: 'message.nickname.error' - - -ok = Ok -cancel = Storno -add = P\u0159idat -use.default = Pou\u017e\u00edt v\u00fdchoz\u00ed -close = Zav\u0159\u00edt -create = Vytvo\u0159it -invite = Pozvat -date = Datum -from = Od -room.name = Jm\u00e9no m\u00edstnosti -join = P\u0159ijmout -description = Popis -subject = P\u0159edm\u011bt -occupants = Obyvatel\u00e9 -accept = P\u0159ijmout -reject = Odm\u00edtnout -open = Otev\u0159\u00edt -open.folder = Otev\u0159\u00edt slo\u017eku -retry = Opakovat -active = Aktivn\u00ed -not.registered = Nen\u00ed registrov\u00e1n -save = Ulo\u017eit -yes = Ano -no = Ne -broadcast = Vys\u00edlat -available = Dostupn\u00fd -user.has.signed.in = p\u0159ihl\u00e1sil/a se. -user.has.signed.off = odhl\u00e1sil/a se. -message = Zpr\u00e1va - - -button.create.account = &Vytvo\u0159it \u00fa\u010det -button.close = Za&v\u0159\u00edt -button.advanced = Da&l\u0161\u00ed -button.browse = &Proch\u00e1zet... -button.browse2 = P&roch\u00e1zet... -button.browse3 = Pr&och\u00e1zet... -button.approve = &Schv\u00e1lit -button.deny = &Zam\u00edtnout -button.accept = &Povolit -button.profile = &Profil -button.add.a.contact = &P\u0159idat kontakt -button.reconnect = &Znovu p\u0159ipojit -button.add = &P\u0159idat -button.roster = &P\u0159ehled -button.add.bookmark = P\u0159idat z\u00e1lo\u017eku -button.remove.bookmark = Odebrat z\u00e1lo\u017eku -button.bookmark.room = &Z\u00e1lo\u017ekov\u00e1 m\u00edstnost -button.create.room = &Vytvo\u0159it nebo P\u0159ipojit se do m\u00edstnosti -button.join.room = &P\u0159ipojit se do vybran\u00e9 m\u00edstnosti -button.refresh = &Obnovit -button.find = &Naj\u00edt -button.update = &Aktualizovat -button.cancel = &Storno -button.decline = &Odm\u00edtnout -button.join = &P\u0159ipojit -button.save.for.future.use = &Ulo\u017eit na p\u0159\u00edst\u011b -button.register = &Registrovat -button.dial.number = &Vyto\u010dit \u010d\u00edslo -button.clear = &Smazat -button.search = &Naj\u00edt -button.add.service = &P\u0159idat slu\u017ebu -button.quit = &Odej\u00edt -button.new = &Nov\u00fd -button.add.user = &P\u0159idat u\u017eivatele -button.save = &Ulo\u017eit -button.start.chat = Chat -button.send.email = Email -button.send = Poslat - - - -checkbox.save.password = &Ulo\u017eit heslo -checkbox.auto.login = &Auto p\u0159ihl\u00e1\u0161en\u00ed -checkbox.use.proxy.server = &Pou\u017e\u00edt server Proxy -checkbox.auto.discover.port = &Automaticky naj\u00edt server a port -checkbox.permanent = M\u00edstnost je &st\u00e1l\u00e1 -checkbox.private.room = M\u00edstnost &je soukrom\u00e1 -checkbox.show.time.in.chat.window = &Uk\u00e1zat \u010das v chat okn\u011b -checkbox.show.notifications.in.conference = &Uk\u00e1zat notifikace v m\u00edstnostech konference -checkbox.disable.chat.history = &Vypnout historii chatu -checkbox.show.toaster = Uk\u00e1zat &Toast popup -checkbox.window.to.front = &P\u0159en\u00e9st okno dop\u0159edu -checkbox.play.sound.on.new.message = P\u0159ehr\u00e1t zvuk kdy\u017e p\u0159ijde nov\u00e1 &zpr\u00e1va -checkbox.play.sound.when.offline = P\u0159ehr\u00e1t zvuk kdy\u017e u\u017eivatel jde &offline -checkbox.play.sound.on.outgoing.message = P\u0159ehr\u00e1t zvuk kdy\u017e je zpr\u00e1va &posl\u00e1na -checkbox.play.sound.on.invitation = P\u0159ehr\u00e1t zvuk kdy\u017e p\u0159ijde &pozv\u00e1nka -checkbox.idle.enabled = &Ne\u010dinn\u00fd Zapnuto -checkbox.launch.on.startup = &Spustit p\u0159i startu -checkbox.start.in.tray = &Spustit v minimalizovan\u00e9m re\u017eimu -checkbox.split.chat.window = Dokovat &Okna (Pot\u0159ebuje restart) -checkbox.tabs.on.top = &Chat z\u00e1lo\u017eky naho\u0159e (Pot\u0159ebuje restart) -checkbox.allow.buzz = Povolit u\u017eivatel\u016fm pro&zv\u00e1n\u011bt t\u011b -checkbox.enable.emoticons = Povolit Sm&ajl\u00edky -checkbox.use.system.look.and.feel = Pou\u017e\u00edt &barvy a prost\u0159ed\u00ed syst\u00e9mu (Pot\u0159ebuje restart) -checkbox.notify.user.goes.offline = Ozn\u00e1mit kdy\u017e u\u017eivatel odejde offline. -checkbox.notify.user.comes.online = Ozn\u00e1mit kdy\u017e u\u017eivatel p\u0159ijde online. - - -label.user.on.public.network = U\u017eivatel je na ve\u0159ejn\u00e9 s\u00edti -label.change.password.to = &Zm\u011bnit heslo na -label.username = &U\u017eivatelsk\u00e9 jm\u00e9no -label.name = &Jm\u00e9no -label.room.name = J&m\u00e9no M\u00edstnosti -label.room.topic= &T\u00e9ma M\u00edstnosti -label.password = &Heslo -label.confirm.password = &Potvrdit Heslo -label.server = &Server -label.create.account = Vytvo\u0159it \u00fa\u010det -label.close = Z&av\u0159\u00edt -label.ok = OK -label.cancel = Storno -label.use.default = Pou\u017e\u00edt v\u00fdchyoz\u00ed -label.port = &Port -label.auto.login = &Auto Login -label.old.ssl = P&ou\u017e\u00edt starou SSL port metodu -label.host = &Host -label.resource = &Zdroj -label.protocol = &Protokol -label.accounts = &\u00da\u010dty -label.receieved = &P\u0159ijato -label.transfer.timeout = &Timeout P\u0159enosu (min): -label.transfer.download.directory = &Slo\u017eka pro stahov\u00e1n\u00ed: -label.find = &Naj\u00edt -label.rename.to = P\u0159ejmenovat na -label.contact.to.find = Naj\u00edt Kontakt -label.available.users.in.roster = &Dostupn\u00ed u\u017eivatel\u00e9 v seznamu -label.time = \u010cas: {0} -label.add.conference.service = &P\u0159idat slu\u017ebu konference -label.add.jid = &P\u0159idat JID -label.message = &Zpr\u00e1va -label.room = &M\u00edsnost -label.invited.users = P\u0159izvan\u00ed U\u017eivatel\u00e9 -label.new.nickname = Nov\u00e1 P\u0159ezd\u00edvka -label.server.address = Adresa &Serveru -label.nickname = P\u0159&ezd\u00edvka -label.presence = &P\u0159\u00edtomnost -label.priority = P&riorita -label.enter.address = Vlo\u017e Adresu -label.jabber.address = &Jabber Adresa -label.local.time = &M\u00edstn\u00ed \u010cas -label.software = &Software -label.version = &Verze -label.os = &Opera\u010dn\u00ed Syst\u00e9m -label.number = &\u010c\u00edslo -label.dial = &Volat -label.minutes.before.stale.chat = &Minuty p\u0159ed zv\u011btr\u00e1n\u00edm m\u00edstnosti -label.company = &Spole\u010dnost -label.street.address = &Adresa -label.city = &M\u011bsto -label.state.and.province = S&t\u00e1t -label.postal.code = &PS\u010c -label.country = K&raj -label.job.title = &Pracovn\u00ed za\u0159azen\u00ed -label.department = &Odd\u011blen\u00ed -label.phone = &Telefon -label.fax = &Fax -label.mobile = &Mobil -label.web.page = &Webov\u00e1 Prezentace -label.pager = &Pager -label.first.name = &Jm\u00e9no -label.middle.name = &P\u0159ost\u0159edn\u00ed jm\u00e9no -label.last.name = P\u0159\u00ed&jmen\u00ed -label.email.address = &Emailov\u00e1 Adresa -label.jid = &JID -label.search.service = &Slu\u017eba hled\u00e1n\u00ed -label.xmpp.port = &XMPP Port -label.response.timeout = &Timeout odezvy (sec) -label.time.till.idle = \u010c&as do ne\u010dinnosti (min) -label.jabber.id = &Jabber ID -label.group = &Skupina -label.enter.group.name = Zadej nov\u00e9 jm\u00e9no skupiny -label.network = &S\u00ed\u0165 -label.unable.to.add.contact = Nem\u016f\u017eu p\u0159idat kontakt. -label.conflict.error = Nemohu se p\u0159ihl\u00e1sit, proto\u017ee \u00fa\u010det je ji\u017e p\u0159ihl\u00e1\u0161en. -label.message.style = &Styl Zpr\u00e1vy -label.emoticons = S&majl\u00edci - - -message.username.error = Zadej u\u017eivatelsk\u00e9 jm\u00e9no pro \u00fa\u010det. -message.password.error = Zadej heslo pro tento \u00fa\u010det. -message.confirmation.password.error = Zadej potvrzen\u00ed hesla. -message.account.error = Zadej server na kter\u00e9m m\u00e1m vytvo\u0159it \u00fa\u010det. -message.registering = Registruji s {0}. Pros\u00edm vy\u010dkejte... -message.connection.failed = Nemohu se p\u0159ipojit k {0}. -message.create.account = \u00da\u010det nem\u016f\u017ee b\u00fdt vytvo\u0159en. -message.already.exists = \u00da\u010det ji\u017e existuje. Pros\u00edm vyberte si jin\u00e9 u\u017eivatelsk\u00e9 jm\u00e9no. -message.account.created = Nov\u00fd \u00fa\u010det byl vytvo\u0159en. -message.account.create = Vytvo\u0159it nov\u00fd chat \u00fa\u010det. -message.connecting.please.wait = P\u0159ipojuji. Pros\u00edm vy\u010dkejte... -message.supply.valid.timeout = Zadej platnou time out hodnotu. -message.supply.valid.port = Zadej platn\u00fd port. -message.supply.resource = Zadej platn\u00fd zdroj. -message.current.status = Povol ostatn\u00edm vid\u011bt tv\u016fj status a aktivitu. -message.disconnected.error = Va\u0161e p\u0159ipojen\u00ed bylo ukon\u010deno d\u00edky chyb\u011b. -message.disconnected.group.chat.error = Va\u0161e p\u0159ipojen\u00ed bylo ukon\u010deno d\u00edky chyb\u011b. Budete se muset znovu p\u0159ipojit do m\u00edstosti po nalogov\u00e1n\u00ed se. -message.disconnected.conflict.error = Va\u0161e p\u0159ipojen\u00ed bylo ukon\u010deno d\u00edky chyb\u011b: Stejn\u00fd u\u017eivatel se p\u0159ihla\u0161uje odjinud. -message.locked.workstation = U\u017eivatel si uzamkl pracovn\u00ed stanici. -message.away.idle = Pry\u010d d\u00edky ne\u010dinnosti. -message.default.error = Chyba byla detekov\u00e1na. Pros\u00edm reportujte na support@jivesoftware.com. -message.new.message = Nov\u00e1 zpr\u00e1va od {0}. -message.send.file.to.user = Po\u0161li soubory tomuto u\u017eivateli. -message.send.picture = Zachy\u0165te a po\u0161lete cokoliv co vid\u00edte na obrazovce. -message.sent.offline.files = You have just been sent offline file(s). -message.spark.secure = Spark be\u017e\u00ed v zabezpe\u010den\u00e9m m\u00f3du. -message.search.for.contacts = Naj\u00edt kontakty. -message.end.conversation = P\u0159ejete si ukon\u010dit tuto relaci? -message.end.chat = P\u0159ejete si ukon\u010dit tento chat? -message.close.this.chat = Zav\u0159\u00edt tento chat -message.close.other.chats = Zav\u0159\u00edt v\u0161echny ostatn\u00ed chaty -message.close.stale.chats = Zav\u0159\u00edt zv\u011btral\u00e9 chaty -message.last.message.received = Posledn\u00ed zpr\u00e1va p\u0159ijata v {0} -message.shared.group = Sd\u00edlen\u00e1 skupina -message.is.shared.group = {0} je sd\u00edlen\u00e1 skupina. -message.delete.confirmation = Opravdu smazat {0}? -message.idle.for = Ne\u010dinn\u00fd {0} -message.enter.broadcast.message = Zadejte zpr\u00e1vu pro rozesl\u00e1n\u00ed vybran\u00fdm u\u017eivatel\u016fm. -message.name.of.group = Jm\u00e9no skupiny -message.approve.subscription = Povolit {0} p\u0159idat si v\u00e1s do sv\u00e9ho seznamu? -message.add.user = P\u0159idat u\u017eivatele do seznamu? -message.general.error = Spojen\u00ed se serverem ztraceno: {0}. -message.add.a.contact = P\u0159idat kontakt. -message.generic.reconnect.message = Spojen\u00ed se serverem ztraceno. Nalogujte se znovu tla\u010d\u00edtkem n\u00ed\u017ee. -message.select.one.or.more = Vyberte jednoho nebo v\u00edce u\u017eivatel\u016f ze seznamu. -message.add.conference.service = P\u0159idat slu\u017ebu konference. -message.service.already.exists = Slu\u017eba uz je ve va\u0161em seznamu slu\u017eeb. -message.searching.please.wait = Hled\u00e1m. Pockejte pros\u00edm... -message.conference.service.error = Nemohu naj\u00edt konferen\u010dn\u00ed slu\u017ebu. -message.create.or.join.room = Vytvo\u0159it nebo se p\u0159ipojit do konferen\u010dn\u00ed m\u00edstnosti -message.specify.name.error = Zadej platn\u00e9 jm\u00e9no. -message.password.private.room.error = Zadej heslo pro priv\u00e1tn\u00ed m\u00edstnost -message.passwords.no.match = Hesla se neshoduj\u00ed. -message.enter.valid.jid = Zadej platn\u00e9 Jabber ID -message.please.join.in.conference = Pros\u00edm p\u0159ipojte se ke m\u011b v konferenci. -message.invite.users.to.conference = Pozvi u\u017eivatele do konferen\u010dn\u00ed m\u00edstnosti. -message.specify.users.to.join.conference = Vyber u\u017eivatele co se p\u0159ipoj\u00ed do t\u00e9to konferen\u010dn\u00ed m\u00edstnosti. -message.no.room.to.join.error = \u017d\u00e1dn\u00e1 m\u00edstnost na p\u0159ipojen\u00ed se -message.participants.in.room = \u00da\u010dastn\u00edci v m\u00edstnosti -message.you.have.been.kicked = Byl jste vyhozen z t\u00e9to m\u00edstnosti. -message.kicked.error = Nejste schopen vyhodit {0} z t\u00e9to m\u00edstnosti. -message.you.have.been.banned = Byl jste vypov\u011bzen z t\u00e9to m\u00edstnosti. -message.nickname.in.use = P\u0159ezd\u00edvka se pou\u017e\u00edv\u00e1. Pros\u00edm vyberte si jinou p\u0159ezd\u00edvku -message.update.room.list = Obnoven\u00ed seznamu m\u00edstnost\u00ed -message.join.conference.room = P\u0159ipojit se do konferen\u010dn\u00ed m\u00edstnosti -message.select.add.room.to.add = Pros\u00edm vyberte m\u00edstnost na p\u0159idan\u00ed do va\u0161eho seznamu slu\u017eeb -message.bookmark.temporary.room.error = Do\u010dasn\u00e9 m\u00edstnosti nemohou b\u00fdt v z\u00e1lo\u017ek\u00e1ch -message.select.room.to.join = Vyber m\u00edstnost na p\u0159ipojen\u00ed se -message.conference.info.error = Nejsem schopen st\u00e1hnout informace o konferenci. Pros\u00edm zkuste to pozd\u011bji. -message.add.favorite.room = P\u0159idat m\u00edstnost do obl\u00edben\u00fdch nebo p\u0159ipojit p\u0159\u00edmo. -message.select.room.to.enter = Vyberte m\u00edstnost pro vstup. -message.find.conference.services = Naj\u00edt konferen\u010dn\u00ed slu\u017eby -message.specify.information.for.conference = Zadej informace pro konferen\u010dn\u00ed m\u00edstnost. -message.no.description.available = \u017d\u00e1dn\u00fd popis -message.no.subject.available = \u017d\u00e1dn\u00fd p\u0159edm\u011bt -message.room.information.for = Informace o m\u00edstnosti {0} -message.view.information.about.this.user = Prohl\u00ed\u017eet informace o tomto u\u017eivateli. -message.add.this.user.to.your.roster = P\u0159idat u\u017eivatele do va\u0161eho k\u00e1mo\u0161 seznamu. -message.came.online = {0} je online v {1} -message.went.offline = {0} \u0161el offline v {1} -message.offline.error = U\u017eivatel nebude schopen p\u0159ijmout offline zpr\u00e1vu. -message.offline = U\u017eivatel je offline a dostane va\u0161\u00ed zpr\u00e1vu p\u0159i p\u0159\u00ed\u0161t\u00edm p\u0159ihl\u00e1\u0161en\u00ed. -message.is.typing.a.message = {0} p\u00ed\u0161e zpr\u00e1vu... -message.enter.new.subject = Zadej nov\u00fd p\u0159edm\u011bt -message.confirm.destruction.of.room = Zni\u010den\u00ed m\u00edstnosti odebere v\u0161echny u\u017eivatele z m\u00edstosti. Pokra\u010dovat? -message.room.destruction.reason = D\u016fvod pro zni\u010den\u00ed m\u00edstnosti? -message.user.left.room = {0} ode\u0161el z m\u00edstnosti. -message.user.joined.room = {0} p\u0159i\u0161el do m\u00edstnosti. -message.chat.session.ended = Chat relace ukon\u010dena v {0} -message.subject.change.error = Nem\u00e1te pr\u00e1vo na zm\u011bnu p\u0159edm\u011btu m\u00edstnosti. -message.forbidden.error = Dostal jsem chybu ze serveru: Zam\u00edtnuto -message.room.destroyed = Tato m\u00edstnost byla zni\u010dena s t\u00edmto d\u016fvodem: {0} -message.subject.has.been.changed.to = P\u0159edm\u011bt byl zm\u011bn\u011bn na {0}. -message.user.kicked.from.room = {0} byl vyhozen z m\u00edstnosti. -message.user.given.voice = {0} bylo mu povoleno hovo\u0159it v t\u00e9to m\u00edstnosti. -message.user.voice.revoked = {0} bylo mu zak\u00e1z\u00e1no hovo\u0159it. -message.user.banned = {0} byl vypov\u011bzen z m\u00edstnosti. -message.user.granted.membership = {0} dostal \u010dlensk\u00e1 pr\u00e1va. -message.user.revoked.membership = \u010clensk\u00e1 pr\u00e1va byla odebr\u00e1na {0}. -message.user.granted.moderator = {0} dostal pr\u00e1va moder\u00e1tora. -message.user.revoked.moderator = Pr\u00e1va moder\u00e1tora byla odebr\u00e1na {0}. -message.user.granted.owner = {0} dostal pr\u00e1va vlastn\u00edka. -message.user.revoked.owner = Pr\u00e1va vlastn\u00edka byla odebr\u00e1na {0}. -message.user.granted.admin = {0} dostal pr\u00e1va administr\u00e1tora. -message.user.revoked.admin = Administr\u00e1torsk\u00e1 pr\u00e1va byla odebr\u00e1na {0}. -message.user.nickname.changed = {0} je te\u010f zn\u00e1m jako {1}. -message.your.kicked = Byl jste vyhozen od {0}. -message.your.voice.granted = Byl v\u00e1m umo\u017en\u011bno hovo\u0159it. -message.your.voice.revoked = Bylo v\u00e1m znemo\u017en\u011bno hovo\u0159it. -message.your.banned = Byl jste banned z t\u00e9to m\u00edstnosti. -message.your.membership.granted = Byla v\u00e1m d\u00e1na \u010dlensk\u00e1 pr\u00e1va. -message.your.membership.revoked = Byla v\u00e1m odebr\u00e1na \u010dlensk\u00e1 pr\u00e1va. -message.your.moderator.granted = Byla v\u00e1m d\u00e1na pr\u00e1va moder\u00e1tora. -message.your.moderator.revoked = Byla v\u00e1m odebr\u00e1na pr\u00e1va moder\u00e1tora. -message.your.ownership.granted = Byla v\u00e1m d\u00e1na pr\u00e1va vlastn\u00edka. -message.your.ownership.revoked = Byla v\u00e1m odebr\u00e1na pr\u00e1va vlastn\u00edka. -message.your.admin.granted = Byla v\u00e1m d\u00e1na pr\u00e1va administr\u00e1tora. -message.your.revoked.granted = Byla v\u00e1m odebr\u00e1na pr\u00e1va administr\u00e1tora. -message.send.a.broadcast = Po\u0161li v\u0161em -message.broadcast.from = Hromadn\u00e1 zpr\u00e1va od {0} -message.enter.message.to.broadcast = Zadejte zpr\u00e1vu na rozesl\u00e1n\u00ed do cel\u00e9ho va\u0161eho seznamu. -message.broadcast.message.sent = Hromadn\u00e1 zpr\u00e1va byla posl\u00e1na. -message.broadcast.to = Zadej zpr\u00e1vu na hromadn\u00e9 zasl\u00e1n\u00ed {0} -message.broadcasted.to = Zpr\u00e1va byla rozesl\u00e1na t\u011bmto u\u017eivatel\u016fm:\n{0} -message.user.now.available.to.chat = {0} je online v {1} -message.user.is.sending.you.a.file = {0} pos\u00edl\u00e1 v\u00e1m soubor. -message.file.transfer.canceled = Zru\u0161il jste p\u0159enos souboru. -message.negotiate.file.transfer = Domlouv\u00e1m p\u0159enos souboru. Po\u010dkejte pros\u00edm... -message.negotiate.stream = Domlouv\u00e1m ustaven\u00ed spojen\u00ed. Pros\u00edm po\u010dkejte... -message.receiving.file = Dost\u00e1v\u00e1te soubor od {0} -message.click.to.open = Klikn\u011bte pro otev\u0159en\u00ed -message.error.during.file.transfer = P\u0159i p\u0159enosu soubor\u016f se vyskytla chyba. -message.transfer.refused = P\u0159enos soubor\u016f byl odm\u00edtnut. -message.transfer.cancelled = P\u0159enos soubor\u016f byl zru\u0161en. -message.received.file = Dostal jste soubor od {0}. -message.file.exists.question = Soubor ji\u017e existuje. P\u0159epsat? -message.transfer.waiting.on.user = \u010cek\u00e1m na {0} pro potvrzen\u00ed p\u0159enosu souboru. -message.negotiation.file.transfer = Domlouv\u00e1m p\u0159enos souboru s {0}. Pros\u00edm po\u010dkejte... -message.unable.to.send.file = Nebyl jste schopen poslat soubor {0}. -message.sending.file.to = Pos\u00edl\u00e1m soubor {0}. -message.you.have.sent = Poslal jste soubor {0}. -message.file.transfer.rejected = P\u0159enos soubor\u016f nebyl odsouhlasen {0}. -message.disable.transport = Odstranit p\u0159ihla\u0161ovac\u00ed informace z {0}? -message.register.transports = Registrovat s t\u011bmito mo\u017en\u00fdmy transporty. -message.enter.aim = Zadejte svoje AIM u\u017eivatelsk\u00e9 jm\u00e9no a heslo n\u00ed\u017ee. -message.enter.msn = Zadejte svoje MSN u\u017eivatelsk\u00e9 jm\u00e9no a heslo n\u00ed\u017ee. -message.enter.gtalk = Zadejte svoje GTalk u\u017eivatelsk\u00e9 jm\u00e9no a heslo n\u00ed\u017ee. -message.enter.xmpp = Zadejte svoje XMPP u\u017eivatelsk\u00e9 jm\u00e9no a heslo n\u00ed\u017ee. -message.enter.yahoo = Zadejte svoje u\u017eivatelsk\u00e9 jm\u00e9no a heslo na p\u0159ipojen\u00ed k Yahoo. -message.enter.icq = Zadejte svoje ICQ u\u017eivatelsk\u00e9 jm\u00e9no a heslo n\u00ed\u017ee. -message.enter.irc = Zadejte svoje IRC u\u017eivatelsk\u00e9 jm\u00e9no, heslo a p\u0159ezd\u00edvku n\u00ed\u017ee. -message.enter.simple = Zadejte svoje SIMPLE u\u017eivatelsk\u00e9 jm\u00e9no a heslo n\u00ed\u017ee. -message.enter.gadugadu = Zadejte svoje GaduGadu u\u017eivatelsk\u00e9 jm\u00e9no a heslo n\u00ed\u017ee. -message.username.error = U\u017eivatelsk\u00e9 jm\u00e9no mus\u00ed b\u00fdt zad\u00e1no. -message.password.error = Heslo mus\u00ed b\u00fdt zad\u00e1no. -message.nickname.error = P\u0159ezd\u00edvka mus\u00ed b\u00fdt zad\u00e1na. -message.username.password.error = U\u017eivatelsk\u00e9 jm\u00e9no a/nebo heslo mus\u00ed b\u00fdt zad\u00e1no. -message.registration.transport.failed = Nemohu v\u00e1s registrovat s br\u00e1nou. -message.client.information = Klient informace o {0} -message.calling = Vol\u00e1 {0} -message.number.to.call = Zadejte \u010d\u00edslo pro vyt\u00e1\u010den\u00ed -message.no.caller.id = Nemohu zobrazit \u010d\u00edslo volaj\u00edc\u00edho. -message.no.history.found = Nen\u00ed \u017e\u00e1dn\u00e1 historie komunikace pro tohoto u\u017eivatele. -message.prompt.plugin.uninstall = Jste si jist \u017ee chcete odinstalovat {0}? -message.restart.spark.changes = Plugin bude odebr\u00e1n p\u0159i p\u0159\u00ed\u0161t\u00edm startu Sparka. -message.loading.please.wait = Na\u010d\u00edt\u00e1m. Pros\u00edm po\u010dkejte... -message.plugins.not.available = Nemohu se p\u0159ipojit ke skladi\u0161ti plugin\u016f. -message.downloading = Stahuji {0} -message.downloading.spark.plug = Stahuji Spark-Plug -message.unable.to.save.password = Nemohu zm\u011bnit heslo. Kontaktujte spr\u00e1vce va\u0161eho serveru. -message.delete.all.history = Smazat v\u0161echny p\u0159edchoz\u00ed konverzace? -message.no.avatar.found = Tento u\u017eivatel nem\u00e1 nastaven \u017e\u00e1dn\u00e9ho avatara. -message.image.too.large = Tento obr\u00e1zek je p\u0159\u00edli\u0161 velk\u00fd. Zadejte obr\u00e1zek o velikosti 16k nebo men\u0161\u00ed. -message.save.profile = Pro zaps\u00e1n\u00ed zm\u011bn do va\u0161eho profilu klikn\u011bte na Ulo\u017eit. -message.unable.to.load.profile = Nemohu naj\u00edt profil pro {0} -message.enter.jabber.id = Vlo\u017ete Jabber ID -message.invalid.jabber.id = Nen\u00ed platn\u00e9 Jabber ID -message.vcard.not.supported = Server nepodporuje VCards. Nemohu ulo\u017eit va\u0161\u00ed VCard. -message.search.service.not.available = Nemohu kontaktovat slu\u017ebu hled\u00e1n\u00ed. -message.no.results.found = Server nevr\u00e1til \u017e\u00e1dn\u00e9 v\u00fdsledky hled\u00e1n\u00ed. -message.name.of.search.service.question = Jm\u00e9no slu\u017eby hled\u00e1n\u00ed? -message.search.for.other.people = Naj\u00edt ostatn\u00ed lidi na serveru. -message.specify.valid.time.error = Zadejte platny timeout a port. -message.timeout.error = Timeout mus\u00ed b\u00fdt 5 vte\u0159in nebo del\u0161\u00ed. -message.version = Verze: {0} -message.file.size = Velikost souboru: {0} -message.restart.spark = Budete pot\u0159ebovat vypnout klienta pro instalaci nov\u00e9 verze. \n Prov\u00e9st te\u010f? -message.updating.cancelled = Update byl zru\u0161en. -message.transfer.rate = Rychlost p\u0159enosu -message.total.downloaded = Celkem sta\u017eeno -message.new.spark.available = {0} je te\u010f dostupn\u00e1. P\u0159ejete si nainstalovat? -message.restart.spark.to.install = Budete pot\u0159ebovat vypnout klienta pro instalaci posledn\u00ed verze. \n Prov\u00e9st te\u010f? -message.add.to.roster = P\u0159idat do seznamu -message.enter.room.password = Zadejte heslo do m\u00edstnosti -message.add.contact.to.list = P\u0159idat u\u017eivatele do va\u0161eho senzamu kontakt\u016f -message.autenticating = Autentikace -message.invalid.status = Zadejte platnou zpr\u00e1vu stavu. -message.cannot.add.contact.to.shared.group = Nem\u016f\u017eete p\u0159id\u00e1vat nov\u00e9 kontakty do sd\u00edlene skupiny. -message.specify.contact.jid = Pros\u00edm zadejte JID kontaktu (nap\u0159. ddman@jabber.org) -message.invalid.jid.error = Zadan\u00e9 JID je neplatn\u00e9. -message.specify.group = Vyberte skupinu kontakt\u016f pro p\u0159id\u00e1n\u00ed nov\u00e9ho u\u017eivatele. -message.room.creation.error = M\u00edstnost nem\u016f\u017ee b\u00fdt vytvo\u0159ena. -message.unable.to.retrieve.last.activity = Nemohu zjistit posledn\u00ed aktivitu od {0}. -message.buzz.alert.notification = Vyvolejte u\u017eivatelovu pozornost. -message.buzz.sent = Poslat notifikaci v\u00fdstrahy u\u017eivateli. -message.restart.required = Budete muset restartovat Sparka, aby se va\u0161e zm\u011bny provedly. Restartovat te\u010f? -message.send.to.these.people = Poslat t\u011bmto lidem -message.normal = Norml\u00e1ln\u00ed zpr\u00e1va -message.alert.notify = Notifikace v\u00fdstrahy - -title.passwords.no.match = Potvr\u010fte hesla. -title.create.problem = Probl\u00e9m s vytvo\u0159en\u00edm \u00fa\u010dtu -title.account.created = \u00da\u010det vytvo\u0159en -title.create.new.account = Vytvo\u0159it nov\u00fd \u00fa\u010det -title.account.create.registration = Registrace \u00fa\u010dtu -title.register.account = Registrovat nov\u00fd \u00fa\u010det -title.notification = Notifikace -title.advanced.connection.preferences = Podrobn\u00e9 nastaven\u00e1 p\u0159ipojen\u00ed -title.preferences = Mo\u017enosti -title.error = Chyba -title.status.message = Zpr\u00e1va statusu -title.spark.preferences = Spark Mo\u017enosti -title.alert = V\u00fdstraha -title.tray.information = Tray Informace -title.select.file.to.send = Vyberte soubor(y) pro posl\u00e1n\u00ed -title.choose.directory = Vyberte slo\u017eku -title.confirmation = Potvrzen\u00ed -title.last.activity = Posledn\u00ed aktivita -title.add.new.group = P\u0159idat novou skupinu -title.add.to.roster = P\u0159idat do seznamu -title.find.contacts = Naj\u00edt kontakty -title.rename.roster.group = P\u0159ejmenovat skupiny seznamu -title.roster = Seznam -title.create.or.join = Vytvo\u0159it/P\u0159ipojit -title.conference.rooms = Konferen\u010dn\u00ed m\u00edstnosti -title.invite.to.conference = P\u0159izvat do konference -title.room.information = Informace o m\u00edstnosti -title.change.nickname = Zm\u011bnit p\u0159ezd\u00edvku -title.group.chat = Skupinov\u00fd chat -title.create.or.bookmark.room = P\u0159ipojit se nebo Bookmarkovat m\u00edstnost -title.browse.room.service = Proch\u00e1zet konferen\u010dn\u00ed m\u00edstnosti - {0} -title.name = Jm\u00e9no -title.address = Adresa -title.occupants = \u00da\u010dastn\u00edci -title.browse.conference.services = Proch\u00e1zet konferen\u010dn\u00ed slu\u017eby -title.find.conference.service = Naj\u00edt konferen\u010dn\u00ed slu\u017ebu -title.configure.chat.room = Nastavit chat m\u00edstnost -title.conference.invitation = Pozv\u00e1n\u00ed konference -title.join.conference.room = P\u0159ipojit konferen\u010dn\u00ed m\u00edstnost -title.view.room.information = Prohl\u00e9dnout informace m\u00edstnosti -title.configure.room = Nastavit M\u00edstnost -title.change.subject = Zm\u011bnit P\u0159edm\u011bt -title.enter.reason = Zadat D\u016fvod -title.room.destroyed = M\u00edstnost Zni\u010dena -title.edit.custom.message = Editovat Osobn\u00ed Zpr\u00e1vy -title.set.status.message = Nastavit Status Zpr\u00e1vu -title.broadcast.message = Hromadn\u011b Rozeslan\u00e1 Zpr\u00e1va -title.start.chat = Za\u010d\u00edt Chat -title.view.bookmarks = Prohl\u00e9dnout Z\u00e1lo\u017eky -title.downloads = Downloady -title.file.exists = Soubor Existuje -title.disable.transport = Odstranit P\u0159ihla\u0161ovac\u00ed Informace -title.available.transports = Dostupn\u00e9 Transporty -title.transports = Trasnporty -title.aim.registration = AIM P\u0159ihla\u0161ovac\u00ed \u00dadaje -title.gtalk.registration = GTalk P\u0159ihla\u0161ovac\u00ed \u00dadaje -title.xmpp.registration = XMPP P\u0159ihla\u0161ovac\u00ed \u00dadaje -title.msn.registration = MSN P\u0159ihla\u0161ovac\u00ed \u00dadaje -title.yahoo.registration = Yahoo P\u0159ihla\u0161ovac\u00ed \u00dadaje -title.icq.registration = ICQ P\u0159ihla\u0161ovac\u00ed \u00dadaje -title.irc.registration = IRC P\u0159ihla\u0161ovac\u00ed \u00dadaje -title.simple.registration = SIMPLE P\u0159ihla\u0161ovac\u00ed \u00dadaje -title.gadugadu.registration = GaduGadu P\u0159ihla\u0161ovac\u00ed \u00dadaje -title.registration.error = Chyba Registrace -title.jabber.browser = Prohl\u00ed\u017ee\u010d -title.version.and.time = Verze a \u010cas -title.waiting.to.call = \u010cek\u00e1n\u00ed na uskute\u010dn\u011bn\u00ed hovoru -title.incoming.call = P\u0159\u00edchoz\u00ed Hovor -title.on.the.phone = Volaj\u00edc\u00ed -title.dial.phone = Vyto\u010dit Telefon -title.history.for = Historie Konverzace Pro {0} -title.reminder = Upom\u00edna\u010d -title.plugins = Pluginy -title.general.chat.settings = Obecn\u00e9 Nastaven\u00ed Chatu -title.chat = Chat -title.notifications = Notifikace -title.sound.preferences = Mo\u017enosti zvuku -title.sounds = Zvuky -title.choose.incoming.sound = Vyberte P\u0159\u00edchoz\u00ed Zvukov\u00fd Soubor -title.choose.outgoing.sound = Vyberte Odchoz\u00ed Zvukov\u00fd Soubor -title.choose.offline.sound = Vyberte Offline Zvukov\u00fd soubor -title.edit.profile = Editovat Informace Profilu -title.profile.information = Informace Profilu -title.profile.not.found = Profil Nenalezen -title.view.profile.for = Prohl\u00ed\u017een\u00ed Profilu Pro {0} -title.lookup.profile = Vyhled\u00e1n\u00ed Profilu -title.add.search.service = P\u0159idat Slu\u017ebu Hled\u00e1n\u00ed -title.person.search = Hled\u00e1n\u00ed Lid\u00ed -title.login.settings = Nastaven\u00ed P\u0159ihl\u00e1\u0161en\u00ed -title.login = P\u0159ihl\u00e1\u0161en\u00ed -title.downloading.im.client = St\u00e1hnout IM Klienta -title.upgrading.client = Upgraduji Klienta -title.cancelled = Zru\u0161eno -title.new.version.available = Dostupn\u00e1 Nov\u00e1 Verze -title.new.client.available = Dostupn\u00fd Nov\u00fd Klient -title.password = Heslo -title.download.complete = Stahov\u00e1n\u00ed Dokon\u010deno -title.new.roster.group = Nov\u00e1 Skupina Seznamu -title.add.contact.group = P\u0159idat Skupinu Kontakt\u016f -title.add.contact = P\u0159idat Kontakt -title.file.transfer.preferences = Mo\u017enosti P\u0159enosu Souboru -title.file.transfer = P\u0159enos Souboru - -menuitem.contacts = Kontakty -menuitem.actions = Akce -menuitem.exit = Konec -menuitem.plugins = &Pluginy -menuitem.logout.no.status = Odhl\u00e1sit se -menuitem.logout.with.status = Odhl\u00e1sit se s d\u016fvodem -menuitem.show.traffic = Uk\u00e1zat Okno S\u00ed\u0165ov\u00e9ho Provozu -menuitem.check.for.updates = Zkontrolovat Updaty -menuitem.help = N\u00e1pov\u011bda -menuitem.preferences = Mo\u017enosti -menuitem.about = O n\u00e1s -menuitem.online.help = Spark Forums -menuitem.user.guide = U\u017eivatelsk\u00e1 P\u0159\u00edru\u010dka -menuitem.open = Otev\u0159\u00edt -menuitem.hide = Schovat -menuitem.status = Status -menuitem.view.downloads = Prohl\u00e9dnout Downloady -menuitem.save = Ulo\u017eit -menuitem.add = P\u0159idat -menuitem.add.contact = P\u0159idat Kontakt -menuitem.add.contact.group = P\u0159idat Skupinu Kontakt\u016f -menuitem.remove.from.group = Odebrat Ze Skupiny -menuitem.start.a.chat = Za\u010d\u00edt Chat -menuitem.rename = P\u0159ejmenovat -menuitem.delete = Smazat -menuitem.edit = Upravit -menuitem.remove.from.roster = Odebrat ze Seznamu -menuitem.view.profile = Prohl\u00e9dnout Profil -menuitem.subscribe.to = Odeb\u00edrat -menuitem.send.a.message = Poslat hromadnou zp\u00e1vu vybran\u00fdm u\u017eivatel\u016fm... -menuitem.show.empty.groups = Uk\u00e1zat Pr\u00e1zdn\u00e9 Skupiny -menuitem.send.a.file = Poslat Soubor -menuitem.view.last.activity = Prohl\u00e9dnout Posledn\u00ed Aktivitu -menuitem.unban = Unban -menuitem.ban = Ban -menuitem.browse.service = Proch\u00e1zet Slu\u017eby -menuitem.remove.service = Odebrat Slu\u017ebu -menuitem.join.room = P\u0159ipojit M\u00edstnost -menuitem.remove.bookmark = Odebrat Z\u00e1lo\u017eku -menuitem.join.on.startup = P\u0159ipojit P\u0159i Startu -menuitem.view.room.info = Prohl\u00e9dnout Informace o M\u00edstnosti -menuitem.remove = Odebrat -menuitem.change.nickname = Zm\u011bnit P\u0159ezd\u00edvku -menuitem.block.user = Blokovat U\u017eivatele -menuitem.unblock.user = Odblokovat U\u017eivatele -menuitem.kick.user = Vyhodit U\u017eivatele -menuitem.voice = Hlas -menuitem.revoke.voice = Odebrat Hlas -menuitem.grant.voice = D\u00e1t Hlas -menuitem.ban.user = Ban U\u017eivatele -menuitem.grant.moderator = D\u00e1t Moder\u00e1tora -menuitem.revoke.moderator = Odebrat Moder\u00e1tora -menuitem.invite.users = Pozvat U\u017eivatele -menuitem.invite.group.to.conference = Pozvat skupinu do konference -menuitem.start.a.conference = Za\u010d\u00edt konferenci... -menuitem.change.subject = Zm\u011bnit P\u0159edm\u011bt -menuitem.destroy.room = Zni\u010dit M\u00edstnost -menuitem.set.status.message = Nastavit status zpr\u00e1vu... -menuitem.edit.status.message = Editovat osobn\u00ed status zpr\u00e1vu... -menuitem.broadcast.to.group = Hromadn\u011b zaslat zpr\u00e1vu skupin\u011b -menuitem.alert.when.online = Varovat kdy\u017e je u\u017eivatel dostupn\u00fd -menuitem.remove.alert.when.online = Odebrat Varov\u00e1n\u00ed -menuitem.save.as = Ulo\u017eit jako... -menuitem.view.client.version = Zobrazit Verzi Klienta -menuitem.view.contact.history = Zobrazit Historii Kontaktu -menuitem.edit.my.profile = &Upravit M\u016fj Profil... -menuitem.lookup.profile = &Vyhledat Profil... -menuitem.add.as.contact = P\u0159idat jako kontakt -menuitem.chat = Chat -menuitem.sign.in = Zapsat se -menuitem.sign.out = Odepsat se -menuitem.sign.in.at.login = Zapsat se p\u0159i p\u0159ihl\u00e1\u0161en\u00ed -menuitem.enter.login.information = Zadejte p\u0159ihla\u0161ovac\u00ed informace -menuitem.delete.login.information = Smazat p\u0159ihla\u0161ovac\u00ed informace -menuitem.show.offline.group = Skupina u\u017eivatel\u016f offline -menuitem.move.to = P\u0159esunout do -menuitem.copy.to = Kop\u00edrovat do -menuitem.languages = Jazyky - -tree.conference.services = Konferen\u010dn\u00ed Slu\u017eby -tree.users.in.room = U\u017eivatel\u00e9 V M\u00edstnosti - -tab.general = Obecn\u00e9 -tab.proxy = Proxy -tab.contacts = Kontakty -tab.installed.plugins = Instalovan\u00e9 Pluginy -tab.available.plugins = Dostupn\u00e9 Pluginy -tab.personal = Osobn\u00ed -tab.business = Obchodn\u00ed -tab.home = Dom\u00e1c\u00ed -tab.avatar = Avatar -tab.conferences = Konference - -group.connection = P\u0159ipojen\u00ed -group.conferences.found = Konferen\u010dn\u00ed Slu\u017eby Nalezeny -group.comma.delimited = Odd\u011blen\u00e9 \u010c\u00e1rkou -group.general.information = Obecn\u00e9 Informace -group.chat.window.information = Informace Chat Okna -group.notification.options = Mo\u017enosti Notifikac\u00ed -group.search.form = Vyhled\u00e1vac\u00ed Formul\u00e1\u0159 -group.search.results = V\u00fdsledky Vyhled\u00e1v\u00e1n\u00ed -group.login.information = P\u0159ihla\u0161ovac\u00ed Informace - -tooltip.place.a.call = Zavolejte tomuto \u010dlov\u011bku -tooltip.view.history = Zobrazit historii konverzace -tooltip.view.changelog = Zopbrazit Change Log -tooltip.view.readme = Zobrazit \u010cti m\u011b -tooltip.notifications = Nastaven\u00ed upozor\u0148ov\u00e1n\u00ed na p\u0159\u00edchoz\u00ed chaty. -tooltip.place.voice.call = Telefonovat. - - - -#!# \ No newline at end of file diff --git a/src/resources/i18n/spark_i18n_de.properties b/src/resources/i18n/spark_i18n_de.properties deleted file mode 100644 index 803350999..000000000 --- a/src/resources/i18n/spark_i18n_de.properties +++ /dev/null @@ -1,1096 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.0.1 -## Added key: 'message.restart.spark.changes' -## Added key: 'message.enter.icq' -## Added key: 'title.icq.registration' -## Added key: 'button.quit' -## -## -## -## 2.0.2 -## Added key: 'button.new' -## Added key: 'label.group' -## Added key: 'label.jabber.id' -## Added key: 'label.enter.group.name' -## Added key: 'title.new.roster.group' -## Added key: 'title.add.contact.group' -## Added key: 'message.add.contact.to.list' -## Added key: 'title.add.contact' -## Added key: 'tab.conferences' -## Added key: 'message.autenticating' -## Added key: 'title.file.transfer.preferences' -## Added key: 'menuitem.about' -## Added key: 'message.invalid.status' -## Added key: 'message.cannot.add.contact.to.shared.group -## Added key: 'message.specify.contact.jid' -## Added key: 'message.invalid.jid.error' -## Added key: 'message.specify.group' -## Added key: 'add' -## -## -## -## 2.0.5 -## Added key: 'Broadcast' -## Added key: 'label.user.on.public.network' -## Added key: 'label.network' -## -## -## 2.0.6 -## Added key: 'button.add.user' -## Added key: 'menuitem.sign.in' -## Added key: 'menuitem.sign.out' -## Added key: 'menuitem.sign.in.at.login' -## Added key: 'menuitem.enter.login.information' -## Added key: 'menuitem.delete.login.information' -## Added key: 'button.save' -## -## -## 2.5 -## Added key: 'button.start.chat' -## Added key: 'button.send.email' -## Added key: 'available' -## Added key: 'checkbox.tabs.on.top' -## Added key: 'user.has.signed.in' -## Added key: 'user.has.signed.off' -## Added key: 'label.unable.to.add.contact' -## Added key: 'label.conflict.error' -## Added key: 'message.room.creation.error' -## Added key: 'checkbox.allow.buzz' -## Added key: 'message.disconnected.group.chat.error' -## Added key: 'menuitem.show.offline.group' -## Added key: 'menuitem.move.to' -## Added key: 'menuitem.copy.to' -## Added key: 'label.message.style' -## Added key: 'label.emoticons' -## Added key: 'checkbox.enable.emoticons' -## Added key: 'message.unable.to.retrieve.last.activity' -## Added key: 'checkbox.use.system.look.and.feel' -## -## 2.5.2 -## Added key: 'tooltip.place.voice.call' -## Added key: 'message.buzz.alert.notification' -## Added key: 'message.buzz.sent' -## -## 2.5.2 -## Added key: 'menuitem.user.guide' -## -## -## -## 2.5.7 -## Added key: 'menuitem.languages' -## Added key: 'message.restart.required' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'message.send.to.these.people' -## Added key: 'message' -## Added key: 'message.normal' -## Added key: 'message.alert.notify' -## -## 2.5.8 -## Added key: 'message.enter.simple' -## Added key: 'message.enter.irc' -## Added key: 'message.enter.gadugadu' -## Added key: 'title.simple.registration' -## Added key: 'title.irc.registration' -## Added key: 'title.gadugadu.registration' -## Added key: 'message.username.error' -## Added key: 'message.password.error' -## Added key: 'message.nickname.error' -## -## 2.5.9 -## Added key: 'message.gateway.username.error. -## Added key: 'message.gateway.password.error. -## Added key: 'message.gateway.nickname.error. -## Added key: 'answer' -## Added key: 'online' -## Added key: 'online' -## Added key: 'offline' -## Added key: 'participants' -## Added key: 'unfiled' -## Added key: 'while.offline' -## Added key: 'action.clear' -## Added key: 'action.copy ' -## Added key: 'action.cut' -## Added key: 'action.paste' -## Added key: 'action.print' -## Added key: 'action.save' -## Added key: 'action.select.all' -## Added key: 'button.add2' -## Added key: 'button.copy.to.clipboard' -## Added key: 'button.reconnect2' -## Added key: 'button.tasks.active' -## Added key: 'button.tasks.all' -## Added key: 'button.view.notes' -## Added key: 'button.view.profile' -## Added key: 'button.view.tasklist' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.show.avatars.in.contaclist' -## Added key: 'checkbox.use.compression' -## Added key: 'group.empty' -## Added key: 'group.offline' -## Added key: 'label.add.task' -## Added key: 'label.chatroom.fontsize' -## Added key: 'label.contactlist.fontsize' -## Added key: 'label.due' -## Added key: 'label.show' -## Added key: 'label.timeformat' -## Added key: 'menuitem.dial' -## Added key: 'menuitem.view.logs' -## Added key: 'message.disconnected.shutdown' -## Added key: 'message.invalid.username.password' -## Added key: 'message.no.updates' -## Added key: 'message.reconnect.attempting' -## Added key: 'message.reconnect.failed' -## Added key: 'message.reconnect.wait' -## Added key: 'message.send.picture' -## Added key: 'message.server.unavailable' -## Added key: 'message.unrecoverable.error' -## Added key: 'message.waiting.for.user.to.join' -## Added key: 'status.available' -## Added key: 'status.away' -## Added key: 'status.custom.messages' -## Added key: 'status.do.not.disturb' -## Added key: 'status.extended.away' -## Added key: 'status.free.to.chat' -## Added key: 'status.on.phone' -## Added key: 'status.online' -## Added key: 'status.pending' -## Added key: 'title.about' -## Added key: 'title.appearance' -## Added key: 'title.appearance.preferences' -## Added key: 'title.login.error' -## Added key: 'title.no.updates' -## Added key: 'title.notes' -## Added key: 'title.tasks' -## Added key: 'tooltip.appearance' -## Added key: 'tooltip.file.transfer' -## Added key: 'tooltip.send.email' -## Added key: 'tooltip.start.chat' -## Added key: 'delete.log.permanently' -## Added key: 'delete.permanently' -## Added key: 'label.contactlist.avatarsize' -## Added key: 'title.qq.registration' -## Added key: 'message.enter.qq' -## -## 2.6.0 -## -## Added key: 'apply' -## Added key: 'title.subscription.request' -## Added key: 'label.add.to.roster' -## Added key: 'label.audio.device' -## Added key: 'label.video.device' -## Added key: 'button.re.detect' -## -## 2.6.0 beta 1 -## Added key: 'menuitem.block.contact' -## Added key: 'menuitem.unblock.contact' -## Removed key: 'status.available' -## Added key: 'message.nickname.not.acceptable' -## Added key: 'button.login' -## Added key: 'administrator' -## Added key: 'menuitem.add.groupchat.showrolesinsteadofstatus' -## Added key: 'checkbox.click.single.tray' -## 2.7.0 beta 1 -## Added key: 'message.search.period.month.one' -## Added key: 'message.search.period.year.one' -## Added key: 'message.search.period.none' -## Added key: 'message.search.page.timeperiod' -## Added key: 'message.search.page.counter' -## Added key: 'message.search.page.right' -## Added key: 'message.search.page.left' -## Added key: 'checkbox.sort.asc.history' -## Added key: 'message.file.transfer.dirnull' -## Added key: 'message.file.transfer.nodir' -## Added key: 'message.file.transfer.cantwritedir' -## Added key: 'message.file.transfer.direrror.setdir' - -accept = Akzeptieren -active = Aktiv -add = Hinzufügen -administrator = Administrator -answer = Antwort -apply = Übernehmen -available = Anwesend -broadcast = Rundnachricht -cancel = Abbrechen -close = Schließen -create = Erstellen -date = Datum -description = Beschreibung -from = Von -invite = Einladen -join = Beitreten -no = Nein -not.registered = Nicht registriert -occupants = Teilnehmer -offline = Offline -online = Online -ok = Ok -open = Öffnen -open.folder = Verzeichnis öffnen -participants = Teilnehmer -refresh = Aktualisieren -reject = Zurückweisen -retry = Wiederholen -room.name = Raumname -save = Speichern -subject = Thema -unfiled = Nicht kategorisiert -use.default = Voreinstellungen laden -user.has.signed.in = hat sich eingeloggt. -user.has.signed.off = hat sich ausgeloggt. -while.offline = Während offline -yes = Ja - -action.clear = Löschen -action.copy = Kopieren -action.cut = Ausschneiden -action.paste = Einfügen -action.print = Drucken -action.save = Speichern -action.select.all = Alles auswählen - -button.accept = &Akzeptieren -button.add = &Hinzufügen -button.add.a.contact = &Kontakt hinzufügen -button.add.bookmark = Lesezeichen hinzufügen -button.add.service = &Hinzufügen -button.add.user = &Hinzufügen -button.add2 = Hinzufügen -button.advanced = &Erweitert -button.approve = &Annehmen -button.bookmark.room = &Raum als Lesezeichen setzen -button.browse = &Anzeigen... -button.browse2 = A&nzeigen... -button.browse3 = An&zeigen... -button.cancel = &Abbrechen -button.clear = &Löschen -button.close = Schließen -button.copy.to.clipboard = In Zwischenablage kopieren -button.create.account = &Account erstellen -button.create.room = &Raum erstellen oder beitreten -button.decline = &Ablehnen -button.deny = &Verweigern -button.dial.number = &Nummer wählen -button.find = &Finden -button.join = &Beitreten -button.join.room = &Ausgewählten Raum betreten -button.login = &Login -button.new = &Neu -button.profile = &Profil -button.quit = Beenden -button.re.detect = Wiede&rerkennen -button.reconnect = &Verbindung wiederherstellen -button.reconnect2 = Wiederverbinden -button.refresh = &Aktualisieren -button.register = &Registrierung -button.reject = Ablehnen -button.remove.bookmark = Lesezeichen löschen -button.roster = &Kontaktliste -button.save = &Speichern -button.save.for.future.use = &Speichern für spätere Verwendung -button.search = &Suchen -button.send = Senden -button.send.email = Email -button.start.chat = Chat -button.tasks.active = Aktiv -button.tasks.all = Alles -button.unset.file.explorer = entferne gespeicherten File-Browser -button.update = &Aktualisieren -button.view.notes = Notizen anschauen -button.view.profile = Gesamtes Profil anzeigen -button.view.tasklist = Aufgabenliste anschauen - -checkbox.allow.buzz = "&Buzzer"-Funktion aktivieren.checkbox.save.password = Pass&wort speichern -checkbox.auto.discover.port = &Host und Port automatisch bestimmen -checkbox.auto.login = &Automatisches Login -checkbox.login.as.invisible = Unsichtbar einl&oggen -checkbox.disable.chat.history = &Den Chatverlauf nicht speichern -checkbox.sort.asc.history = Nachrichten in Kontaktverlauf aufsteigend nach Datum sortieren -checkbox.disable.prev.chat.history = Die letzte &Unterhaltung nicht anzeigen -checkbox.enable.emoticons = &Emoticons aktivieren -checkbox.graying.out = Nichtstuende Kontakte ausgrauen (benötigt Neustart von Spark) -checkbox.idle.enabled = &Automatisches 'Away' bei Inaktivität aktivieren -checkbox.launch.on.startup = &Spark bei Systemstart ausführen -checkbox.reconnet.info = Art des Wiederverbindens: -checkbox.reconnect.panel.big = Zeige ein Panel -checkbox.reconnect.panel.small = Zeige eine Gruppe -checkbox.reconnect.panel.icon = Zeige ein Icon -checkbox.notify.user.comes.online = &Benachrichtigen, wenn ein User online kommt -checkbox.notify.user.goes.offline = Benachrichtigen, wenn ein &User offline geht -checkbox.notify.typing.systemtray = Zeige &Schreibhinweise im System-Tray -checkbox.notify.systemtray = Zeige &neue Nachrichten im System-Tray -checkbox.permanent = Raum ist &permanent Online -checkbox.play.sound.on.invitation = Klang abspielen bei Eintreffen einer &Konferenzeinladung -checkbox.play.sound.on.new.message = Klang abspielen, wenn eine neue &Nachricht eintrifft -checkbox.play.sound.on.outgoing.message = &Klang abspielen, wenn Nachricht ge&sendet wird -checkbox.play.sound.when.offline = Klang abspielen, wenn ein &Teilnehmer &offline geht -checkbox.private.room = Raum &ist privat -checkbox.save.password = Pass&wort speichern -checkbox.show.avatars.in.contactlist = &Zeige Avatare in der Kontaktliste -checkbox.show.notifications.in.conference = &Anzeigen von Benachrichtigungen in Konferenzräumen -checkbox.show.time.in.chat.window = &Zeit im Chatfenster anzeigen -checkbox.show.toaster = Informationen in einem &Popup anzeigen -checkbox.disable.asterisk.toaster = Popups von Anrufen deaktivieren -checkbox.split.chat.window = &Fenster 'andocken' (benötigt Neustart von Spark) -checkbox.start.in.tray = Spark automatisch in der &Taskleiste starten -checkbox.click.single.tray = &Einfachen Klick im System Tray verwenden, um Spark in den Vordergrund zu bringen -checkbox.tabs.on.top = &Chat-Tabs oben anzeigen (benötigt Neustart von Spark) -checkbox.use.compression = Komprimierung verwenden -checkbox.use.debugger.on.startup = Debugger beim Starten öffnen -checkbox.use.proxy.server = &Proxy-Server benutzen -checkbox.use.system.look.and.feel = System-Look-And-&Feel verwenden (benötigt Neustart von Spark) -checkbox.window.to.front = &Fenster in den Vordergrund bringen -checkbox.broadcast.hide.offline.user = Offline User ausblenden -checkbox.use.krbconf = Verwende krb5.conf oder krb5.ini -checkbox.use.krb.dns = Verwende DNS -checkbox.use.specify.below = Specify Below -checkbox.use.pki.authentication = Verwende PKI Authentifizierung -checkbox.transport.tab.setting = Zeige verfügbare Transports in einem Tab an (benötigt Neustart von Spark) -checkbox.conference.tab.setting = Zeige den Konferenzreiter (benötigt Neustart von Spark) -checkbox.use.hostname.as.resource = Hostnamen als Ressource benutzen -checkbox.use.version.as.resource = Spark-Version als Ressource benutzen - -delete.log.permanently = Logs permanent löschen -delete.permanently = Permanent löschen? - -gateway.username.password.error = Benutzername und/oder Passwort muss eingetragen sein - -group.chat.window.information = Chat-Fenster Informationen -group.comma.delimited = Komma separiert -group.conferences.found = Konferenzen gefunden -group.connection = Verbindung -group.empty = Keine Offline-User in dieser Gruppe -group.general.information = Allgemeine Informationen -group.login.information = Login-Informationen -group.notification.options = Optionen zur Benachrichtigung -group.offline = Offline-Gruppe -group.search.form = Suchformular -group.search.results = Suchergebnisse -group.chat.name.notification = Deinen Nick gesehen... -group.chat.name.match = Dein Name wurde im Gruppenchat erwähnt: - -label.na = n/a -label.cell = &Mobil -label.work = &Geschäftlich -label.home = &Privat -label.accounts = A&ccounts -label.passwordreset = Passwort zurücksetzen -label.add.conference.service = &Service für Konferenzen hinzufügen -label.add.jid = &JID hinzufügen -label.add.task = Aufgabe hinzufügen -label.auto.login = &Automatisches Login -label.available.users.in.roster = &Verfügbare Teilnehmer in der Kontaktliste -label.avatar = Avatar: -label.cancel = Abbrechen -label.change.password.to = &Neues Passwort eingeben -label.chatroom.fontsize = &Chatroom-Schriftgröße: -label.city = Sta&dt -label.close = &Schließen -label.company = &Firma -label.confirm.password = Neues Passwort &wiederholen -label.conflict.error = User ist bereits angemeldet. Login wird verweigert. -label.contact.to.find = Kontakt finden -label.recent.conversation = Kürzliche Konversationen -label.frequent.contacts = Meistgenutzte Kontakte -label.contactlist.avatarsize = Kontaktliste &Avatargröße: -label.contactlist.fontsize = Kontaktliste &Schriftgröße: -label.country = &Land -label.create.account = &Account erstellen -label.department = &Abteilung -label.dial = &Wählen -label.display.time = Anzeigedauer: -label.downloads = Downloads -label.due = Due -label.email.address = &E-Mail-Adresse -label.emoticons = E&moticons -label.enter.address = Adresse eingeben -label.enter.group.name = Namen für neue Gruppe eingeben -label.fax = Fa&x -label.find = &Finden -label.first.name = &Vorname -label.group = &Gruppe -label.host = &Host -label.invited.users = Eingeladene Teilnehmer -label.jabber.address = &Jabber-Adresse -label.jabber.id = &Jabber-ID -label.jid = &JID -label.job.title = &Beruf -label.last.name = &Nachname -label.local.time = &Lokale Zeit -label.message = &Nachricht -label.message.style = &Nachrichtenstil -label.middle.name = &Zweiter Vorname -label.minutes.before.stale.chat = &Ein Chatfenster als 'inaktiv' kennzeichnen nach (min) -label.mobile = &Mobil -label.name = &Name -label.network = Netzwerk -label.new.nickname = Neuer angezeigter Name -label.nickname = &Angezeigter Name -label.number = &Nummer -label.ok = OK -label.old.ssl = &Benutze ALTE SSL-Port-Methode -label.os = &Bestriebssystem -label.pager = Pa&ger -label.password = &Passwort -label.phone = &Telefon -label.port = &Port -label.postal.code = &Postleitzahl -label.presence = S&tatus -label.priority = P&riorität -label.protocol = &Protokoll -label.received = Empfangen -label.rename.to = Umbenennen zu -label.resource = &Ressource -label.response.timeout = &Zeitspanne bis zum Abbruch (sec) -label.room = &Raum -label.room.name = &Raumname -label.room.topic = Raum&thema -label.search = Suchen -label.search.service = &Such-Service -label.seconds = Sekunden -label.server = &Server -label.server.address = &Server-Adresse -label.show = Zeigen: -label.software = &Software -label.state.and.province = Staat/&Region -label.street.address = &Straße -label.time = Zeit: {0} -label.time.till.idle = Zeitspanne für automatisches 'Away' bei &Inaktivität (min) -label.time.till.idlemessage = Stat&usnachricht für automatisches 'Away' -label.timeformat = Benutze {0} -label.transfer.download.directory = &Download-Verzeichnis: -label.transfer.timeout = &Zeitspanne bis zum Abbruch des Transfers (min): -label.unable.to.add.contact = Kann Kontakt nicht hinzufügen. -label.use.default = Standard nutzen -label.user.on.public.network = Teilnehmer befindet sich in einem öffentlichen Netzwerk -label.username = &Benutzername -label.version = &Version -label.web.page = &Internetseite -label.xmpp.port = &XMPP-Port -label.krb.realm = Realm -label.krb.kdc = KDC -label.which.pki.method = Welche PKI Methode? -label.choose.file = Datei auswählen -label.trust.store.password = Trust-Store-Passwort -label.enter.password = Password eingeben -label.move.focus.forwards = Move Focus Forwards -label.move.focus.backwards = Move Focus Backwards -label.keystore.location = Keystore-Pfad -label.truststore.location = Truststore-Pfad -label.pkcs.library.file = PKCS11-Bibliotheksdatei -label.x509.certificate = X.509-Zertifikat -label.apple.keychain = Apple-KeyChain -label.add.to.roster = Benutzer zur Kontaktliste hinzufügen -label.audio.device = &Audiogerät -label.video.device = &Videogerät - -menuitem.about = Über -menuitem.actions = Aktionen -menuitem.bookmarks = Lesezeichen -menuitem.add = Hinzufügen -menuitem.add.as.contact = Als Kontakt hinzufügen -menuitem.add.contact = Kontakt hinzufügen -menuitem.add.contact.group = Kontaktgruppe hinzufügen -menuitem.add.groupchat.myname = Meinen &Namen hervorheben, wenn ihn jemand schreibt -menuitem.add.groupchat.mytext = Meinen &Text hervorheben, wenn ich etwas schreibe -menuitem.add.groupchat.popname = &Zeige ein Popup, wenn jemand meinen Namen schreibt -menuitem.add.groupchat.showjoinleavemessage = Zeige an, wenn jemand den &Raum betritt oder verlässt -menuitem.add.groupchat.showrolesinsteadofstatus = Zeige &Chatrecht-Icons anstelle von Statusicons -menuitem.add.groupchat.auto.accept.invite = &Konferenzeinladungen automatisch akzeptieren -menuitem.add.groupchat.random.colors = Zeige Namen mit zufälligen &Farben -menuitem.always.on.top = Immer im Vordergrund -menuitem.alert.when.online = Benachrichtigen, wenn Teilnehmer verfügbar -menuitem.ban = Verbannen -menuitem.ban.user = Teilnehmer sperren -menuitem.block.user = Teilnehmer blockieren -menuitem.broadcast.to.group = Rundnachricht an Gruppe -menuitem.browse.service = Services anzeigen -menuitem.change.nickname = Angezeigten Namen ändern -menuitem.change.subject = Konferenzthema ändern -menuitem.chat = Chat -menuitem.check.for.updates = Ist eine neuere &Version verfügbar? -menuitem.connect = Datei -menuitem.contacts = Kontakte -menuitem.copy.to = Kopieren nach -menuitem.delete = Löschen -menuitem.delete.login.information = Anmeldeinformationen löschen -menuitem.destroy.room = Raum löschen -menuitem.dial = Wählen -menuitem.edit = Ändern -menuitem.edit.my.profile = &Profil ändern... -menuitem.edit.status.message = Statusnachrichten ändern... -menuitem.enter.login.information = Anmeldeinformationen eingeben -menuitem.exit = Beenden -menuitem.affiliation = Raumassoziierung -menuitem.grant.moderator = Moderatorenstatus geben -menuitem.grant.member = Mitgliedsstatus geben -menuitem.grant.admin = Adminstatus geben -menuitem.grant.owner = Besitzerstatus geben -menuitem.grant.voice = Schreibrecht geben -menuitem.help = &Hilfe -menuitem.hide = Minimieren -menuitem.invite.group.to.conference = Gruppe zu einer Konferenz einladen -menuitem.invite.users = Teilnehmer einladen -menuitem.join.on.startup = Beim Starten beitreten -menuitem.join.room = Raum beitreten -menuitem.kick.user = Teilnehmer rauswerfen -menuitem.languages = Sprachen -menuitem.logout.no.status = Ausloggen -menuitem.logout.with.status = Ausloggen mit Nachricht -menuitem.lookup.profile = &Profil suchen... -menuitem.move.to = Verschieben nach -menuitem.online.help = Online-Hilfe -menuitem.open = Öffnen -menuitem.open.with = Öffnen mit... -menuitem.plugins = Plugins -menuitem.preferences = Einstellungen -menuitem.remove = Entfernen -menuitem.remove.alert.when.online = Benachrichtigung entfernen -menuitem.remove.bookmark = Lesezeichen entfernen -menuitem.remove.from.group = Aus dieser Gruppe entfernen -menuitem.remove.from.roster = Von Kontaktliste entfernen -menuitem.block.contact = Kontakt auf akueller Liste blockieren -menuitem.unblock.contact = Blockierung eines Kontaktes aufheben -menuitem.remove.service = Service entfernen -menuitem.rename = Umbenennen -menuitem.revoke.moderator = Moderatorenstatus widerrufen -menuitem.revoke.voice = Schreibrecht entziehen -menuitem.revoke.member = Mitgliedsstatus widerrufen -menuitem.revoke.admin = Adminstatus widerrufen -menuitem.revoke.owner = Besitzerstatus widerrufen -menuitem.save = Speichern -menuitem.save.as = Speichern als... -menuitem.send.a.file = Datei senden -menuitem.send.a.message = Nachricht senden... -menuitem.set.status.message = Statusnachricht setzen... -menuitem.show.empty.groups = Leere Gruppen anzeigen -menuitem.show.offline.group = Offline User gruppieren -menuitem.show.traffic = Verbindungsdaten -menuitem.sign.in = Einloggen -menuitem.sign.in.at.login = Einloggen während des Anmeldens -menuitem.sign.out = Ausloggen -menuitem.start.a.chat = Chat starten -menuitem.start.a.conference = Eine Konferenz starten... -menuitem.status = Status -menuitem.subscribe.to = Kontaktanfrage senden -menuitem.unban = Teilnehmer entsperren -menuitem.unblock.user = Blockierung auf aktueller Liste aufheben -menuitem.user.guide = Benutzerhandbuch -menuitem.view.client.version = Programm Version anzeigen -menuitem.view.contact.history = Kontaktverlauf anzeigen -menuitem.view.downloads = Downloads anzeigen -menuitem.view.last.activity = Letzte Aktivität sehen -menuitem.view.logs = Logs anzeigen -menuitem.view.profile = Profil anzeigen -menuitem.view.room.info = Rauminformationen anzeigen -menuitem.voice = Schreibrecht -menuitem.show.offline.users = Zeige Offline User -menuitem.show.contact.statusmessage = Statusnachricht anzeigen -menuitem.bookmark.room = Raum als Lesezeichen setzen -menuitem.refresh = Aktualisieren -menuitem.create.room = Raum erstellen oder beitreten -menuitem.expand.all.groups = Öffne alle Gruppen -menuitem.collapse.all.groups = Schließe alle Gruppen -menuitem.inivite.again = Nochmals einladen -menuitem.chatframe.option = Einstellungen -menuitem.add.groupchat.invitetobookmark = Automatically invite users to bookmarked room - -message.username.error = Wählen Sie einen Benutzernamen für diesem Account. -message.password.error = Wähle Sie Passwort für diesem Account. -message.confirmation.password.error = Wiederholen Sie das Passwort. -message.account.error = Server auf dem der Account erstellt werden soll. -message.registering = Registrierung mit {0}. Bitte warten... -message.connection.failed = Es konnte keine Verbindung zu {0} hergestellt werden. -message.create.account = Account konnte nicht erstellt werden. -message.already.exists = Account ist bereits angelegt. Bitte einen anderen Benutzernamen wählen. -message.account.created = Der Account wurde erstellt. -message.account.create = Einen neuen Chat-Account erstellen. -message.connecting.please.wait = Verbinde - Bitte warten... -message.supply.valid.timeout = Bitte einen korrekten Wert eingeben. -message.supply.valid.port = Bitte einen korrekten Port eingeben. -message.supply.resource = Bitte die korrekte Ressource eingeben. -message.current.status = Andere Teilnehmer können meinen Status einsehen. -message.disconnected.error = Die Verbindung wurde aufgrund eines Fehlers abgebrochen. -message.disconnected.group.chat.error = Die Verbindung wurde wegen eines Fehlers unterbrochen. Spark wird diesen Chatraum automatisch betreten, wenn die Verbindung wieder hergestellt wurde. -message.disconnected.conflict.error = Die Verbindung wurde abgebrochen, da mit ihren Zugangsdaten ein weiteres Login registriert wurde. -message.locked.workstation = Computer gesperrt -message.away.idle = Abwesend -message.default.error = Ein Fehler wurde erkannt. Bitte schicken Sie eine Fehlerbeschreibung an support@jivesoftware.com. -message.new.message = Neue Nachricht von {0}. -message.send.file.to.user = Dateien an diesen Teilnehmer senden. -message.send.picture = Bildschirminhalt versenden. -message.sent.offline.files = Sie haben offline Dateien gesendet. -message.spark.secure = Sichere Verbindung aktiv. -message.search.for.contacts = Nach Kontakten suchen. -message.search.input.short = Bitte gib mehr als fünf Zeichen ein. -message.end.conversation = Soll diese Sitzung beendet werden? -message.end.chat = Soll dieser Chat beendet werden? -message.close.this.chat = Diesen Chat schließen -message.close.other.chats = Alle anderen Chats schließen -message.close.stale.chats = Inaktive Chats schließen -message.last.message.received = Letzte Nachricht empfangen um {0} -message.shared.group = Gemeinsame Gruppen -message.is.shared.group = {0} ist eine gemeinsame Gruppe. -message.delete.confirmation = {0} - Wirklich löschen? -message.idle.for = Inaktiv seit {0} -message.enter.broadcast.message = Nachricht eingeben zur Weiterleitung an die ausgewählten Benutzer. -message.name.of.group = Name der Gruppe -message.approve.subscription = Wollen Sie {0} erlauben ihren Kontakt der Kontaktliste hinzuzufügen? -message.add.user = Teilnehmer der Kontaktliste hinzufügen? -message.general.error = Die Verbindung zum Server wurde abgebrochen wegen {0}. -message.add.a.contact = Kontakt hinzufügen -message.generic.reconnect.message = Die Verbindung zum Server ist abgebrochen. Für eine erneute Verbindung bitte auf die Schaltfläche Verbindung wiederherstellen klicken. -message.select.one.or.more = Wählen Sie einen oder mehrere Teilnehmer aus. -message.add.conference.service = Füge eine Konferenz hinzu. -message.service.already.exists = Dieser Service ist bereits in der Liste vorhanden. -message.searching.please.wait = Suche läuft. Bitte warten... -message.conference.service.error = Der Konferenz-Service konnte nicht gefunden werden. -message.create.or.join.room = Konferenz erstellen oder einer bestehen beitreten -message.specify.name.error = Bitte einen erlaubten Namen wählen. -message.password.private.room.error = Bitte ein Passwort für diesen Raum wählen -message.passwords.no.match = Passwörter stimmen nicht überein. -message.enter.valid.jid = Bitte eine korrekte Jabber ID eingeben -message.please.join.in.conference = Bitte treten Sie dieser Konferenz bei. -message.invite.users.to.conference = Teilnehmer zu einer Konferenz einladen. -message.specify.users.to.join.conference = Teilnehmer auswählen die diesem Raum beitreten sollen. -message.no.room.to.join.error = Kein Raum zum Beitreten vorhanden -message.participants.in.room = Teilnehmer im Raum -message.you.have.been.kicked = Sie wurden aus dem Raum ausgeladen. -message.kicked.error = Sie haben nicht das Recht {0} aus dem Raum auszuladen. -message.you.have.been.banned = Der Zugriff auf diesem Raum wurde Ihnen entzogen. -message.nickname.in.use = Ausgewählter Name ist bereits in Benutzung. Bitte einen anderen Namen wählen. -message.nickname.not.acceptable = Das ändern von Spitzname ist nicht erlaubt! -message.update.room.list = Aktualisiere Raumliste -message.join.conference.room = Konferenz beitreten -message.select.add.room.to.add = Bitte einen Raum wählen um ihn der Service-Liste hinzuzufügen. -message.bookmark.temporary.room.error = Temporäre Räume können nicht in die Lesezeichen aufgenommen werden. -message.select.room.to.join = Wählen Sie einen Raum aus dem Sie Beitreten möchten. -message.conference.info.error = Konnte keine Informationen zu dieser Konferenz erhalten. Bitte versuchen Sie es später noch einmal. -message.add.favorite.room = Raum zu den Lesezeichen hinzufügen oder direkt betreten. -message.select.room.to.enter = Wählen Sie einen Raum aus. -message.find.conference.services = Konferenzen suchen -message.specify.information.for.conference = Bitte Informationen zu dieser Konferenz eingeben. -message.no.description.available = Keine Beschreibung verfügbar -message.no.subject.available = Kein Konferenzthema verfügbar -message.room.information.for = Rauminformation für {0} -message.view.information.about.this.user = Informationen über diesen Teilnehmer anzeigen. -message.add.this.user.to.your.roster = Diesen Teilnehmer zu meiner Kontaktliste hinzufügen. -message.came.online = {0} ist online seit {1} -message.went.offline = {0} ist offline seit {1} -message.offline.error = Der Teilnehmer kann keine Offline-Nachrichten empfangen. -message.offline = Der Teilnehmer ist offline und wird die Nachricht nach seinem nächsten Login erhalten. -message.is.typing.a.message = {0} schreibt eine Nachricht... -message.enter.new.subject = Neues Konferenzthema eingeben -message.confirm.destruction.of.room = Raum löschen und alle Teilnehmer aus diesem Raum entfernen. Fortfahren? -message.room.destruction.reason = Grund für das Löschen dieses Raumes? -message.user.left.room = {0} hat den Raum verlassen. -message.user.joined.room = {0} hat den Raum betreten. -message.chat.session.ended = Chatsitzung wurde beendet um {0} -message.subject.change.error = Sie haben keine Rechte das Konferenzthema in diesem Raum zu ändern. -message.forbidden.error = Sie haben nicht die Rechte für diese Aktion. -message.room.destroyed = Dieser Raum wurde aus dem folgenden Grund gelöscht: {0} -message.subject.has.been.changed.to = Das Thema der Konferenz wurde von {1} in "{0}" geändert. -message.user.kicked.from.room = {0} wurde von {1} aus dem Raum geworfen. Grund: {2} -message.user.given.voice = {0} hat jetzt Schreibenrechte. -message.user.voice.revoked = Schreibrechte wurde {0} entzogen. -message.user.banned = {0} wurde für diesen Raum gesperrt. Grund: {2} -message.user.granted.membership = {0} ist jetzt Mitglied. -message.user.revoked.membership = Mitgliedschaft für {0} wurde widerufen. -message.user.granted.moderator = {0} ist jetzt Moderator. -message.user.revoked.moderator = Moderatorrechte wurden {0} entzogen. -message.user.granted.owner = {0} ist jetzt Besitzer. -message.user.revoked.owner = Besitzerrechte wurden {0} entzogen. -message.user.granted.admin = {0} ist jetzt Administrator. -message.user.revoked.admin = Administratorrechte wurden {0} entzogen. -message.user.nickname.changed = {0} nennt sich jetzt {1}. -message.your.kicked = Sie wurden von {0} ausgeladen. -message.your.voice.revoked = Das Schreibrecht wurde Ihnen entzogen. -message.your.banned = Sie sind für diesen Raum gesperrt. -message.your.membership.granted = Sie sind jetzt Mitglied. -message.your.membership.revoked = Ihre Mitgliedschaft wurde widerufen. -message.your.moderator.granted = Sie haben jetzt Moderatorenrechte. -message.your.moderator.revoked = Ihre Moderatorrechte wurden widerufen. -message.your.ownership.granted = Sie sind jetzt Besitzer. -message.your.ownership.revoked = Ihre Besitzerrechte wurden widerufen. -message.your.admin.granted = Sie sind jetzt Administrator. -message.your.revoked.granted = Ihre Administratorenrechte wurden widerufen. -message.send.a.broadcast = Rundnachricht senden -message.broadcast.from = Rundnachricht von {0} -message.broadcast.no.user.selected = Bitte mindestens einen Empfänger auswählen -message.broadcast.no.text = Bitte Text für die Rundnachricht eingeben -message.enter.message.to.broadcast = Eine Nachricht an alle Teilnehmer Ihrer Kontaktliste senden. -message.broadcast.message.sent = Die Rundnachricht wurde versendet. -message.broadcast.to = Eine Rundnachricht eingeben für {0} -message.broadcasted.to = Die Nachricht wurde gesendet an:\n{0} -message.user.now.available.to.chat = {0} ist online seit {1} -message.user.is.sending.you.a.file = {0} sendet ihnen eine Datei. -message.file.transfer.canceled = Sie haben den Dateitransfer abgebrochen. -message.file.transfer.dirnull = Das Download-Verzeichnis für den Dateitransfer wurde nicht festgelegt -message.file.transfer.nodir = Das Download-Verzeichnis für den Dateitransfer wurde nicht gefunden -message.file.transfer.cantwritedir = Sie haben keine ausreichenden Schreibrechte auf dem Download-Verzeichnis -message.file.transfer.direrror.setdir = Bitte klicken Sie hier, um den Download-Pfad neu zu setzen -message.negotiate.file.transfer = Dateitransfer wird vorbereitet. Bitte warten... -message.negotiate.stream = Verbindungsdaten werden vorbereitet. Bitte warten... -message.receiving.file = Sie haben eine Datei von {0} erhalten -message.received.file = Sie haben eine Datei von {0} erhalten. -message.click.to.open = Öffnen -message.error.during.file.transfer = Während des Dateitransfers ist ein Fehler aufgetreten. -message.transfer.refused = Der Dateitransfer wurde verweigert. -message.transfer.cancelled = Der Dateitransfer wurde abgebrochen. -message.transfer.complete = Der Dateitransfer war erfolgreich ({0}) -message.transfer.progressbar.text.received = {0} empfangen @ {1} {2} -message.transfer.progressbar.text.sent = {0} gesendet @ {1} {2} -message.file.transfer.file.too.big.error = Die ausgewählte Datei ist zu groß.\nEs dürfen maximal {0} versandt werden, die ausgewählte Datei hat {1} -message.file.transfer.file.too.big.warning = Die ausgewählte Datei ist zu groß.\nDennoch fortfahren? -message.file.exists.question = Die Datei existiert bereits. Überschreiben? -message.transfer.waiting.on.user = {0} muss den Dateitransfer akzeptieren. Bitte warten... -message.negotiation.file.transfer = Dateitransfer mit {0} wird initialisiert. Bitte warten... -message.unable.to.send.file = Die Datei konnte nicht an {0} übertragen werden. -message.sending.file.to = Sende Datei an {0}. -message.you.have.sent = Datei wurde an {0} gesendet. -message.file.transfer.rejected = Der Dateitransfer wurde von {0} abgelehnt. -message.disable.transport = Soll der aktive Transport unterbunden werden? -message.register.transports = Bei den verfügbaren Transportprotokollen registrieren. -message.enter.aim = Geben Sie ihr AIM Login und Passwort ein. -message.enter.msn = Geben Sie ihr MSN Login und Passwort ein. -message.enter.yahoo = Geben Sie Ihr Login und Passwort für Yahoo ein. -message.enter.icq = Geben Sie Ihr Login und Passwort für ICQ ein. -message.enter.sametime = Geben Sie Ihr Login und Passwort für Sametime ein. -message.enter.facebook = Geben Sie Ihr Login und Passwort für Facebook ein. -message.enter.myspace = Geben Sie Ihr Login und Passwort für MySpace ein. -message.username.password.error = Benutzername und/oder Passwort muss eingegeben werden. -message.registration.transport.failed = Registrierung mit dem Transportprotokoll schlug fehl. -message.client.information = Programminformationen für {0} -message.calling = Rufe {0} -message.number.to.call = Bitte eine Nummer eingeben -message.no.caller.id = Keine Ruf-ID verfügbar. -message.no.history.found = Es sind keine weiteren Nachrichten verfügbar. -message.prompt.plugin.uninstall = Dieses Plugin {0} wirklich deaktivieren? -message.restart.spark = Das Programm muss neugestartet werden damit die Änderungen aktiviert werden. -message.loading.please.wait = Lade. Bitte warten... -message.plugins.not.available = Konnte keine Verbindung mit der Pluginliste herstellen. -message.downloading = Lade {0} herunter -message.downloading.spark.plug = Lade Plugin -message.unable.to.save.password = Passwort konnte nicht geändert werden. Kontaktieren Sie bitte den Administrator. -message.delete.all.history = Lösche alle älteren Nachrichten? -message.no.avatar.found = Der Teilnehmer hat keinen Avatar eingerichtet. -message.image.too.large = Das Bild ist zu groß! Bitte ein Bild mit 16Kb oder kleiner wählen. -message.save.profile = Auf Speichern klicken um die Änderungen zu sichern. -message.unable.to.load.profile = Profil von {0} konnte nicht gefunden werden -message.enter.jabber.id = Jabber ID eingeben -message.invalid.jabber.id = Keine korrekte Jabber ID -message.vcard.not.supported = Der Server unterstützt keine VCards. Ihre VCard konnte nicht gespeichert werden. -message.search.service.not.available = Die Verbindung zum Suchservice konnte nicht hergestellt werden. -message.no.results.found = Es wurden keine Suchergebnisse gefunden. -message.name.of.search.service.question = Name des Suchservices? -message.search.for.other.people = Nach weiteren Personen suchen -message.specify.valid.time.error = Bitte korrekte Werte eingeben. -message.timeout.error = Die Zeitspanne muss mindestens 5 Sekunden betragen. -message.version = Version: {0} -message.file.size = Dateigröße: {0} -message.updating.cancelled = Das Updaten wurde verweigert. -message.transfer.rate = Datendurchsatz -message.total.downloaded = Total Downloaded -message.new.spark.available = {0} ist jetzt verfügbar. Soll die Installation durchgeführt werden? -message.restart.spark.to.install = Das Programm muss beendet werden um eine Version zu installieren. Programm beenden? -message.add.to.roster = Zur Kontaktliste hinzufügen -message.enter.room.password = Passwort für diesen Raum eingeben -message.add.contact.to.list = Teilnehmer zur Kontaktliste hinzufügen -message.autenticating = Authentifizierung -message.invalid.status = Bitte eine gültige Status Message eingeben. -message.cannot.add.contact.to.shared.group = Es können keine neue Kontakte zu der Gruppe hinzugefügt werden. -message.specify.contact.jid = Bitte die JID des Kontakts eingeben (bsp. jemand@jabber.org) -message.invalid.jid.error = Die eingegebene JID ist ungültig. -message.specify.group = Bitte die Gruppe angeben der der neue Kontakt hinzugefügt werde soll. -message.room.creation.error = Der Raum kann nicht erstellt werden. -message.unable.to.retrieve.last.activity = Keine letzte Aktivität für {0} vorhanden -message.buzz.alert.notification = Sich beim Benutzer bemerkbar machen. -message.buzz.message = {0} möchte deine Aufmerksamkeit -message.buzz.sent = Benutzer wurde um Aufmerksamkeit gebeten. -message.invite.to.groupchat = Sie wurden von {0} zu einem Gruppen-Chat eingeladen -title.advanced.connection.preferences = Erweiterte Verbindungseinstellungen -title.passwords.no.match = Passwörter stimmen nicht überein. Bitte Eingabe wiederholen. -title.create.problem = Problem beim Anlegen eines Accounts -title.account.created = Account erstellt -title.create.new.account = Neuen Account erstellen -title.account.create.registration = Account Registrieren -title.register.account = Neuen Account registrieren -title.notification = Benachrichtigungen -title.advanced.connection.sso = Verwende Single Sign-On (SSO) -title.advanced.connection.usesso = Verwende Single Sign-On (SSO) über GSSAPI -title.advanced.connection.sso.account = Den Desktopaccount "{0}" benutzen um mit dem Server zu verbinden. -title.advanced.connection.sso.unable = Single Sign-On fehlgeschlagen. Bitte die Einstellungen überprüfen. -title.advanced.connection.sso.noprincipal = Spark kann den Klienten für Single Sign-On nicht finden. -title.preferences = Einstellungen -title.error = Fehler -title.client.logs = Client Logs -title.status.message = Statusnachricht -title.spark.preferences = Spark Einstellungen -title.alert = Benachrichtigung -title.tray.information = Tray Information -title.select.file.to.send = Datei(en) zum senden auswählen -title.choose.directory = Verzeichnis wählen -title.confirmation = Bestätigung -title.last.activity = Letzte Aktivität -title.add.new.group = Neue Gruppe hinzufügen -title.add.to.roster = Der Kontaktliste hinzufügen -title.find.contacts = Kontakte finden -title.rename.roster.group = Kontakt Gruppe umbenennen -title.roster = Kontaktliste -title.create.or.join = Erstellen/Beitreten -title.conference.rooms = Konferenzräume -title.invite.to.conference = Zu einer Konferenz einladen -title.room.information = Raum Informationen -title.change.nickname = Angezeigten Name ändern -title.group.chat.settings = Konferenz Einstellungen -title.group.chat = Konferenz -title.create.or.bookmark.room = Raum als Lesezeichen setzen oder dem Raum beitreten -title.browse.room.service = Liste der Konferenzen - {0} -title.name = Name -title.address = Adresse -title.occupants = Teilnehmer -title.browse.conference.services = Services zu Konferenzen anzeigen -title.find.conference.service = Konferenzservice finden -title.configure.chat.room = Konferenzraum konfigurieren -title.conference.invitation = Conference Invitation -title.join.conference.room = Konferenzraum beitreten -title.view.room.information = Raum Informationen -title.configure.room = Raum konfigurieren -title.change.subject = Konferenzthema ändern -title.enter.reason = Geben Sie einen Grund ein -title.room.destroyed = Raum löschen -title.edit.custom.message = Eigene Nachrichten ändern -title.set.status.message = Statusnachricht setzen -title.broadcast.message = Rundnachricht -title.start.chat = Chat starten -title.view.bookmarks = Lesezeichen anzeigen -title.downloads = Downloads -title.file.exists = Datei existiert -title.disable.transport = Transport deaktivieren -title.available.transports = Verfügbare Transport Protokolle -title.transports = Transports -title.aim.registration = AIM Registrierung -title.msn.registration = MSN Registrierung -title.yahoo.registration = Yahoo Registrierung -title.icq.registration = ICQ Registrierung -title.facebook.registration = Facebook Registrierung -title.myspace.registration = MySpace Registrierung -title.sametime.registration = Sametime Registrierung -title.registration.error = Fehler in der Registrierung -title.jabber.browser = Browser -title.version.and.time = Version und Zeit -title.waiting.to.call = Warten auf Anruf -title.incoming.call = Ankommender Anruf -title.on.the.phone = Telefoniert -title.dial.phone = Rufnummer wählen -title.history.for = Nachrichtenverlauf für {0} -title.reminder = Erinnerung -title.plugins = Plugins -title.general.chat.settings = Allgemeine Chat-Einstellungen -title.chat = Chat -title.notifications = Benachrichtigungen -title.sound.preferences = Klangeinstellungen -title.sounds = Klänge -title.choose.incoming.sound = Klangdatei für ankommende Nachrichten auswählen -title.choose.outgoing.sound = Klangdatei für ausgehende Nachrichten auswählen -title.choose.offline.sound = Klangdatei für Offline auswählen -title.edit.profile = Profil Informationen ändern -title.profile.information = Profil Informationen -title.profile.not.found = Profil nicht gefunden -title.view.profile.for = Profil von {0} -title.lookup.profile = Profil suchen -title.add.search.service = Such-Service hinzufügen -title.person.search = Suche nach Personen -title.login.settings = Login Einstellungen -title.login.no.account = Unbestimmbar -title.login = Login -title.downloading.im.client = Download IM Programm -title.upgrading.client = Programm upgraden -title.cancelled = Abgebrochen -title.new.version.available = Neue Version verfügbar -title.new.client.available = Neues Programm verfügbar -title.password = Passwort -title.download.complete = Download abgeschlossen -title.new.roster.group = Neue Kontakt Gruppe -title.add.contact.group = Neue Kontakt Gruppe hinzufügen -title.add.contact = Neuen Kontakt hinzufügen -title.file.transfer.preferences = Datei Transfer Einstellungen -title.file.transfer = Datei Transfer -title.appearance.preferences = Anpassung -title.appearance.showVCards = Zeige &VCards in der Kontaktliste -title.input.fileexplorer = Geben sie den Namen ihres File Browsers ein: -title.input.openwith = Geben sie den Namen des Programms ein, welches sie nutzen möchten: -title.error.find.app = Es konnte keine passende Anwendung gefunden werden. -title.input.newname = Geben sie den neuen Namen ein: -title.error.rename.file = Datei konnte nicht umbenannt werden! -title.file = Datei -title.filesize = Dateigröße -title.error.delete.file = Datei konnte nicht gelöscht werden! -title.error.couldnt.open.file = Datei konnte nicht geöffnet werden! Eventuell Dateityp unbekannt! -title.bookmarks = Lesezeichen -title.task.notification = Task notification -status.away = Abwesend -status.custom.messages = Benutzerdefinierte Nachricht -status.do.not.disturb = Nicht stören -status.on.phone = Am Telefon -status.online = Verfügbar -tree.conference.services = Konferenzen -tree.users.in.room = Teilnehmer im Raum -tab.general = Allgemein -tab.proxy = Proxy -tab.contacts = Kontakte -tab.installed.plugins = Installierte Plugins -tab.available.plugins = Verfügbare Plugins -tab.deactivated.plugins = Deaktivierte Plugins -tab.personal = Persönlich -tab.business = Geschäftlich -tab.home = Privat -tab.avatar = Avatar -tab.conferences = Konferenzen -tab.sso = SSO -tab.pki = PKI -tooltip.place.a.call = Diesen Teilnehmer Anrufen -tooltip.view.history = Nachrichtenverlauf anzeigen -tooltip.view.changelog = Änderungen anzeigen -tooltip.view.readme = ReadMe anzeigen -tooltip.notifications = Einstellungen der Benachrichtigungen für eingehende Chats. -tooltip.place.voice.call = VOIP Anruf starten. -message = Nachricht -message.alert.notify = Warnungsbenachrichtigung -message.disconnected.shutdown = Deine Verbindung wurde unterbrochen, weil der Server heruntergefahren wurde -message.enter.gadugadu = GaduGadu Benutzername und Passwort eingeben -message.enter.gtalk = GTalk Benutzername und Passwort eingeben -message.enter.irc = IRC Benutzername und Passwort eingeben -message.enter.qq = QQ Benutzername und Passwort eingeben -message.enter.simple = SIMPLE Benutzername und Passwort eingeben -message.enter.xmpp = XMPP Benutzername und Passwort eingeben -message.file.transfer.notification = Dateitransferbenachrichtigung -message.file.transfer.short.message = sendet dir eine Datei mit Namen\: -message.file.transfer.chat.window = Dateitransfer angefordert: -message.gateway.username.error = Benutzername muss eingegeben werden -message.gateway.password.error = Passwort muss eingegeben werden -message.gateway.nickname.error = Spitzname muss eingegeben werden -message.invalid.username.password = Ungültiges Passwort oder Benutzername -message.no.updates = Es gibt keine Aktualisierungen -message.normal = Normale Nachricht -message.reconnect.attempting = Versuche... -message.reconnect.failed = Wiederverbinden gescheitert -message.reconnect.wait = Wiederverbinden in {0} Sekunden -message.restart.spark.changes = Das Plugin wird beim nächsten Start von Spark entfernt -message.restart.required = Du musst Spark neustarten damit die Änderungen wirksam werden, möchtest du jetzt Neustarten? -message.send.to.these.people = Sende an diese Leute -message.server.unavailable = Kann nicht mit Server verbinden: Ungültiger Name oder Server nicht erreichbar -message.unrecoverable.error = Ungültiger Benutzername oder Passwort -message.waiting.for.user.to.join = Warte auf {0} zum Beitritt -message.your.voice.granted = Du hast Schreibrechte in diesem Chat bekommen -message.groupchat.require.password = Dieser GruppenChat benötigt ein Passwort -message.groupchat.registered.member = Registrierung mit {0} erfolgreich -message.search.for.history = Durchsuche Gesprächsverlauf -status.extended.away = Nicht verfügbar -status.free.to.chat = Bereit zu chatten -status.pending = Schwebend -title.about = Über -title.password.required = Passwort benötigt -title.appearance = Erscheinung -title.delete.file = Möchtest du diese Datei wirklich löschen? -title.gadugadu.registration = GaduGadu Account Informationen -title.general.media = Medien Einstellungen -title.gtalk.registration = GTalk Account Informationen -title.irc.registration = IRC Account Informationen -title.login.error = Login Fehler -title.no.updates = Keine Aktualisierungen -title.notes = Notizen -title.qq.registration = QQ Account Informationen -title.simple.registration = SIMPLE Account Informationen -title.tasks = Aufgaben -title.xmpp.registration = XMPP Account Informationen -title.subscription.request = Kontaktanfrage -tooltip.appearance = Ändere das Aussehen der Unterhaltungen -tooltip.file.transfer = Präferenzen für Dateitransfers -tooltip.send.email = Sende eine e-Mail -tooltip.start.chat = Starte eine Konversation - -lookandfeel.select = Wähle ein Thema -lookandfeel.change.now = Jetzt ändern -lookandfeel.tooltip.restart.no = Es wird kein Neustart benötigt -lookandfeel.tooltip.restart.yes = Um ein System Look&Feel auszuwählen, bitte Speichern und Spark neustarten. -lookandfeel.color.label = Farben -lookandfeel.color.red = Rot -lookandfeel.color.green = Grün -lookandfeel.color.blue = Blau -lookandfeel.color.opacity = Deckkraft -lookandfeel.color.saved = Farben gespeichert - - -##Settings for the privacy plugin -privacy.title.preferences = Privatsphäreeinstellungen -privacy.title.panel = Benutzen Sie die rechte Maustaste -privacy.label.iq.desc = Abfragen -privacy.label.pin.desc = Anwesenheit empfangen -privacy.label.pout.desc = Anwesenheit senden -privacy.label.msg.desc = Nachrichten -privacy.border.information = Legende -privacy.label.information = Benutzen Sie die rechte Maustaste um Elemente hinzuzufügen oder zu entfernen -privacy.root.node = Privatsphärelisten -privacy.label.preferences = Privatsphäre -pricacy.tooltip.preferences = Spark Privatsphäreeinstellungen -privacy.label.list.is.active = Aktuell aktive Liste: -privacy.label.list.is.default = Standardliste: -privacy.border.block = Sperren -privacy.pick.one.or.more = Wähle ein oder mehrere Elemente aus der Liste -privacy.title.add.picker = Elemente zur Liste hinzufügen -privacy.node.contacts = Kontakte -privacy.node.groups = Gruppen -privacy.menu.add.contacts = Kontakt zur Liste hinzufügen -privacy.menu.add.groups = Gruppe zur Liste hinzufügen -privacy.menu.add.rem.items = Entferne {0} Elemente von der Liste -privacy.menu.remove = Entferne -privacy.menu.activate.list = Aktivieren -privacy.menu.default.list = Als Standard setzen -privacy.menu.add.list = Liste hinzufügen -privacy.menu.remove.list = Liste entfernen -privacy.dialog.add.list = Bitte den Namen der Liste eingeben -privacy.dialog.rem.list = Möchten Sie wirklich "{0}" entfernen? -privacy.status.menu.entry = Privatsphäre -privacy.name.for.default.list = Standard -privacy.button.no.list.selected = Keine list ausgewählt -privacy.menuitem.deactivate.current.list = {0} deaktivieren -privacy.label.not.supported = Privatsphärelisten werden vom Server leider nicht unterstüzt. - - -##Stunfallback in media settings -stun.border.label = STUN Ausweichserver -stun.server.addr = STUN Server: -stun.server.port = STUN Port: - -#!# \ No newline at end of file diff --git a/src/resources/i18n/spark_i18n_es.properties b/src/resources/i18n/spark_i18n_es.properties deleted file mode 100644 index d348768ea..000000000 --- a/src/resources/i18n/spark_i18n_es.properties +++ /dev/null @@ -1,775 +0,0 @@ -# Traduccion al espanol por Jeffrey Steve Borbon Sanabria (jeffto@aclibre.org) -# Correcci\u00f3n de Juan Gabriel -# Noviembre 2008 - -accept = Aceptar - -action.clear = Limpiar -action.copy = Copiar -action.cut = Cortar -action.paste = Pegar -action.print = Imprimir -action.save = Guardar -action.select.all = Seleccionar todo -active = Activar -add = Agregar -answer = Respuesta -apply = Aplicar -available = Disponible -broadcast = Difusi\u00f3n - -button.accept = &Aceptar -button.add = &Agregar -button.add.a.contact = &Agregar contacto -button.add.bookmark = Agregar favorito -button.add.service = &Agregar servicio -button.add.user = &Agregar usuario -button.add2 = &Agregar -button.advanced = A&vanzado -button.approve = &Aprobar -button.bookmark.room = Cuarto &favorito -button.browse = &Consultar... -button.browse2 = C&onsultar... -button.browse3 = Co&nsultar... -button.cancel = &Cancelar -button.clear = &Limpiar -button.close = C&errar -button.copy.to.clipboard = Copiar al portapapeles -button.create.account = &Crear cuenta -button.create.room = &Crear o ingresar a cuarto -button.decline = &Declinar -button.deny = &Denegar -button.dial.number = &Discar n\u00famero -button.find = &Buscar -button.join = &Ingresar -button.join.room = &Ingresar cuarto seleccionado -button.new = &Nuevo -button.profile = &Perfil -button.quit = &Salir -button.reconnect = &Reconectar -button.reconnect2 = Reconectar -button.refresh = &Refrescar -button.register = &Registrar -button.remove.bookmark = Eliminar favorito -button.roster = &Lista -button.save = &Guardar -button.save.for.future.use = &Guardar para uso futuro -button.search = &Buscar -button.send = Enviar -button.send.email = Email -button.start.chat = Chat -button.tasks.active = Activo -button.tasks.all = Todo -button.unset.file.explorer = Deshabilitar el Explorador de archivos -button.update = &Actualizar -button.view.notes = Ver notas -button.view.profile = Ver perfil completo -button.view.tasklist = Ver lista de tareas -cancel = Cancelar - -checkbox.allow.buzz = Permitir la recepci\u00f3n de &zumbidos -checkbox.auto.discover.port = &Descubrir autom\u00e1ticamente servidor y puerto -checkbox.auto.login = Login &autom\u00e1tico -checkbox.broadcast.hide.offline.user = Ocultar usuario desconectado -checkbox.disable.chat.history = &Deshabilitar Historial de Chat -checkbox.disable.prev.chat.history = &Deshabilitar Mostrar conversaciones anteriores en el chat -checkbox.enable.emoticons = Habilitar Em&oticones -checkbox.idle.enabled = Activar detecci\u00f3n de tiempo &ocioso -checkbox.launch.on.startup = &Iniciar luego de arranque -checkbox.notify.user.comes.online = Notificar cuando un usuario se conecta -checkbox.notify.user.goes.offline = Notificar cuando un usuario se desconecta -checkbox.permanent = El cuarto es &permanente -checkbox.play.sound.on.invitation = Ejecutar sonido cuando reciba una &invitaci\u00f3n -checkbox.play.sound.on.new.message = Ejecutar sonido cuando &llegan nuevos mensajes -checkbox.play.sound.on.outgoing.message = Ejecutar sonido cuando un mensaje es &enviado -checkbox.play.sound.when.offline = Ejecutar sonido cuando un usuario se &desconecta -checkbox.private.room = El cuarto &es privado -checkbox.save.password = &Guardar contrase\u00f1a -checkbox.show.avatars.in.contactlist = Mostrar &avatares en la Lista de Contactos -checkbox.show.notifications.in.conference = &Mostrar notificaciones en Cuartos de conferencia -checkbox.show.time.in.chat.window = &Mostrar hora en ventana de chat -checkbox.show.toaster = Mostrar ventana de &Avisos -checkbox.split.chat.window = Fijar Ventanas (Requiere reiniciar) -checkbox.start.in.tray = &Iniciar en la bandeja del sistema -checkbox.tabs.on.top = Las solapas de &chat aparecen arriba (Requiere reiniciar) -checkbox.use.compression = Usar Co&mpresi\u00f3n -checkbox.use.proxy.server = &Usar servidor Proxy -checkbox.use.system.look.and.feel = Usar apariencia del sistema (Requiere reiniciar) -checkbox.window.to.front = &Traer ventana al frente -close = Cerrar -create = Crear -date = Fecha - -delete.log.permanently = Borrar registro permanentemente -delete.permanently = \u00bfBorrar permanente? -description = Descripci\u00f3n -from = Desde - -gateway.username.password.error = El nombre de usuario y/o contrase\u00f1a debe ser reemplazado. -group.chat.name.match = Tu nombre ha sido dicho en el grupo de chat. -group.chat.name.notification = Tu nombre apareci\u00f3... - -group.chat.window.information = Informaci\u00f3n de la conversaci\u00f3n -group.comma.delimited = Delimitado por comas -group.conferences.found = Servicio de conferencia encontrado -group.connection = Conexi\u00f3n -group.empty = No hay contactos en l\u00ednea en este grupo. -group.general.information = Informaci\u00f3n general -group.login.information = Informaci\u00f3n de login -group.notification.options = Opciones de notificaci\u00f3n -group.offline = Grupo de usuarios desconectados -group.search.form = Formulario de b\u00fasqueda -group.search.results = Resultados de la b\u00fasqueda -invite = Invitar -join = Ingresar - -label.accounts = &Cuentas -label.add.conference.service = &Agregar servicio de conferencia -label.add.jid = &Agregar JID -label.add.task = Agregar tarea -label.auto.login = Login &autom\u00e1tico -label.available.users.in.roster = &Contactos disponibles en lista -label.cancel = Cancelar -label.change.password.to = &Cambiar contrase\u00f1a a -label.chatroom.fontsize = Tama\u00f1o de letra del Cuarto de Chat: -label.city = &Ciudad -label.close = C&errar -label.company = &Compa\u00f1\u00eda -label.confirm.password = &Confirmar contrase\u00f1a -label.conflict.error = No se pudo hacer el login ya que la cuenta est\u00e1 siendo utilizada. -label.contact.to.find = Buscar contacto -label.contactlist.avatarsize = Tama\u00f1o de avatar de lista de contactos: -label.contactlist.fontsize = Tama\u00f1o de fuente de &lista de contactos: -label.country = P&a\u00eds -label.create.account = Crear &cuenta -label.department = &Departmento -label.dial = &Discar -label.downloads = Descargas -label.due = Debido -label.email.address = &Direcci\u00f3n de Email -label.emoticons = &Emoticones -label.enter.address = Ingresar direcci\u00f3n -label.enter.group.name = Ingrese un nuevo nombre de grupo -label.fax = &Fax -label.find = &Buscar -label.first.name = &Primer nombre -label.group = &Grupo -label.host = &Servidor -label.invited.users = Usuarios invitados -label.jabber.address = &Direcci\u00f3n Jabber -label.jabber.id = &Jabber ID -label.jid = &JID -label.job.title = &Puesto de trabajo -label.last.name = &Apellido -label.local.time = &Hora local -label.message = &Mensaje -label.message.style = Estilo de &Mensaje -label.middle.name = &Segundo nombre -label.minutes.before.stale.chat = &Minutos para considerar un cuarto inactivo como caducado -label.mobile = &Celular -label.name = &Nombre -label.network = Red -label.new.nickname = Nuevo Apodo -label.nickname = &Apodo -label.number = &N\u00famero -label.ok = OK -label.old.ssl = &Usar viejo m\u00e9todo de SSL -label.os = &Sistema Operativo -label.pager = &Localizador -label.password = &Contrase\u00f1a -label.phone = &Tel\u00e9fono -label.port = &Puerto -label.postal.code = &C\u00f3digo postal -label.presence = &Presencia -label.priority = P&rioridad -label.protocol = &Protocolo -label.received = Recibido -label.rename.to = Renombrar a -label.resource = &Recurso -label.response.timeout = &Tiempo m\u00e1ximo de espera (seg) -label.room = &Cuarto -label.room.name = &Nombre del cuarto -label.room.topic = &Tema del cuarto -label.search.service = &Servicio de b\u00fasqueda -label.server = &Servidor -label.server.address = &Direcci\u00f3n del servidor -label.show = Mostrar: -label.software = &Software -label.state.and.province = E&stado/Provincia -label.street.address = &Direcci\u00f3n -label.time = Tiempo: {0} -label.time.till.idle = &Tiempo para considerarse Ocioso (min) -label.timeformat = Usar {0} -label.transfer.download.directory = &Carpeta para descargas: -label.transfer.timeout = Tiempo m\u00ednimo de espera para &transferencias: -label.unable.to.add.contact = No se pudo agregar el contacto. -label.use.default = Usar predeterminado -label.user.on.public.network = El usuario est\u00e1 en una red p\u00fablica -label.username = &Nombre de usuario -label.version = &Versi\u00f3n -label.web.page = &P\u00e1gina web -label.xmpp.port = &Puerto XMPP - -menuitem.about = Acerca de -menuitem.actions = Acciones -menuitem.add = Agregar -menuitem.add.as.contact = Agregar como contacto -menuitem.add.contact = Agregar contacto -menuitem.add.contact.group = Agregar contacto al grupo -menuitem.add.groupchat.myname = Destacar mi nombre cuando alguien lo dice -menuitem.add.groupchat.mytext = Destacar mi texto cuando yo digo algo -menuitem.add.groupchat.popname = Mostrar mensaje emergente cuando alguien dice mi nombre -menuitem.alert.when.online = Alertar cuando el usuario est\u00e9 disponible -menuitem.ban = Censurar -menuitem.ban.user = Censurar usuario -menuitem.block.user = Bloquear usuario -menuitem.bookmark.room = Agregar sala a Favoritos -menuitem.broadcast.to.group = Difundir mensaje al grupo -menuitem.browse.service = Buscar servicio -menuitem.change.nickname = Cambiar apodo -menuitem.change.subject = Cambiar tema -menuitem.chat = Chat -menuitem.check.for.updates = Verificar actualizaciones -menuitem.contacts = Contactos -menuitem.copy.to = Copiar a -menuitem.create.room = Crear o unirse a una sala de chat -menuitem.delete = Eliminar -menuitem.delete.login.information = Eliminar informaci\u00f3n de conexi\u00f3n -menuitem.destroy.room = Destruir cuarto -menuitem.dial = Marcar -menuitem.edit = Editar -menuitem.edit.my.profile = &Editar mi perfil... -menuitem.edit.status.message = Editar mensaje de estado personalizado... -menuitem.enter.login.information = Ingresar informaci\u00f3n de conexi\u00f3n -menuitem.exit = Salir -menuitem.grant.moderator = Conceder Moderador -menuitem.grant.voice = Conceder Chat de Voz -menuitem.help = Ayuda -menuitem.hide = Ocultar -menuitem.invite.group.to.conference = Invitar grupo a conferencia -menuitem.invite.users = Invitar usuarios -menuitem.join.on.startup = Ingresar al comienzo -menuitem.join.room = Ingresar al cuarto -menuitem.kick.user = Desconectar usuario -menuitem.languages = Idiomas -menuitem.logout.no.status = Cerrar la sesi\u00f3n -menuitem.logout.with.status = Cerrar sesi\u00f3n con un motivo -menuitem.lookup.profile = &Buscar perfil... -menuitem.move.to = Mover a -menuitem.online.help = Foro de Spark -menuitem.open = Abrir -menuitem.open.with = Abrir con... -menuitem.plugins = &Plugins -menuitem.preferences = Preferencias -menuitem.refresh = Actualizar -menuitem.remove = Eliminar -menuitem.remove.alert.when.online = Eliminar alerta -menuitem.remove.bookmark = Eliminar favorito -menuitem.remove.from.group = Eliminar del grupo -menuitem.remove.from.roster = Eliminar de la Lista -menuitem.remove.service = Eliminar servicio -menuitem.rename = Renombrar -menuitem.revoke.moderator = Revocar moderador -menuitem.revoke.voice = Revocar Chat de Voz -menuitem.save = Guardar -menuitem.save.as = Guardar como... -menuitem.send.a.file = Enviar un archivo -menuitem.send.a.message = Enviar un mensaje a usuarios seleccionados... -menuitem.set.status.message = Configurar mensaje de estado ... -menuitem.show.contact.statusmessage = Mostrar mensaje de estado -menuitem.show.empty.groups = Mostrar grupos vac\u00edos -menuitem.show.offline.group = Agrupar usuarios desconectados -menuitem.show.offline.users = Mostrar usuarios desconectados -menuitem.show.traffic = Mostrar ventana de tr\u00e1fico -menuitem.sign.in = Conectarse -menuitem.sign.in.at.login = Conectarse al iniciar sesi\u00f3n -menuitem.sign.out = Desconectarse -menuitem.start.a.chat = Comenzar una conversaci\u00f3n -menuitem.start.a.conference = Comenzar una conferencia... -menuitem.status = Estado -menuitem.subscribe.to = Subscribirse a -menuitem.unban = Habilitar -menuitem.unblock.user = Desbloquear usuario -menuitem.user.guide = Gu\u00eda del usuario -menuitem.view.client.version = Ver versi\u00f3n del cliente -menuitem.view.contact.history = Ver historial del contacto -menuitem.view.downloads = Ver descargas -menuitem.view.last.activity = Ver \u00faltima actividad -menuitem.view.logs = Ver registros -menuitem.view.profile = Ver perfil -menuitem.view.room.info = Ver informaci\u00f3n del cuarto -menuitem.voice = Chat de voz - -message = &Mensaje -message.account.create = Crear una nueva cuenta de chat. -message.account.created = La cuenta ha sido creada exitosamente. -message.account.error = Especificar el servidor donde crear la cuenta. -message.add.a.contact = Agregar un contacto. -message.add.conference.service = Agregar un servicio de conferencia. -message.add.contact.to.list = Agregar un usuario a la lista de contactos -message.add.favorite.room = Agregar cuarto como favorito o ingresar directamente. -message.add.this.user.to.your.roster = Agregar este usuario a su lista de contactos. -message.add.to.roster = Agregar a la lista -message.add.user = \u00bfDesea agregar el usuario a su lista de contactos? -message.alert.notify = Notificaci\u00f3n de alerta -message.already.exists = La cuenta ya existe. Intente con otro nombre de usuario. -message.approve.subscription = \u00bfPermitir a {0} que lo agregue a su lista de contactos? -message.autenticating = Autenticando -message.away.idle = Ausente por inactividad. -message.bookmark.temporary.room.error = No se pueden guardar cuartos temporales como favoritos -message.broadcast.from = Difusi\u00f3n enviada por {0} -message.broadcast.message.sent = El mensaje para difundir ha sido enviado. -message.broadcast.to = Ingrese el mensaje para difundir a {0} -message.broadcasted.to = El mensaje a sido enviado a los siguientes usuarios:\n{0} -message.buzz.alert.notification = Obtener la atenci\u00f3n del usuario. -message.buzz.sent = Enviar notificaciones de alertas al usuario. -message.calling = Llamando {0} -message.came.online = {0} est\u00e1 disponible en {1} -message.cannot.add.contact.to.shared.group = No puede agregar nuevos contactos a un grupo compartido. -message.chat.session.ended = La sesi\u00f3n de chat ha finalizado a las {0} -message.click.to.open = Haga clic para abrir -message.client.information = Informaci\u00f3n del cliente para {0} -message.close.other.chats = Cerrar dem\u00e1s conversaciones -message.close.stale.chats = Cerrar conversaciones viejas -message.close.this.chat = Cerrar esta chat -message.conference.info.error = No se ha podido obtener informaci\u00f3n de la conferencia. Intente nuevamente en un momento. -message.conference.service.error = No se ha podido encontrar el servicio de conferencia. -message.confirm.destruction.of.room = Al destruir el cuarto los usuarios seran eliminados del cuarto. \u00bfContinuar? -message.confirmation.password.error = Especificar la contrase\u00f1a de confirmaci\u00f3n. -message.connecting.please.wait = Conectando. Aguarde un momento... -message.connection.failed = No se ha podido establecer una conexi\u00f3n con {0}. -message.create.account = No se ha podido crear la cuenta. -message.create.or.join.room = Crear o ingresar a cuarto de conferencia -message.current.status = Permitir a otros ver mi estado actual o mi actividad. -message.default.error = Un error ha sido detectado. Por favor rep\u00f3rtelo a support@jivesoftware.com. -message.delete.all.history = \u00bfEliminar todas las conversaciones previas? -message.delete.confirmation = \u00bfEst\u00e1 seguro que desea eliminar {0}? -message.disable.transport = \u00bfDesea eliminar la informaci\u00f3n de login de {0}? -message.disconnected.conflict.error = Su conexi\u00f3n se ha cerrado ya que el mismo usuario ha sido utilizado desde otra ubicaci\u00f3n. -message.disconnected.error = Su conexi\u00f3n se ha cerrado por un error. -message.disconnected.group.chat.error = La conexi\u00f3n se ha cerrado debido a un error. Necesitas reconectarte para ingresar nuevamente al cuarto. -message.disconnected.shutdown = Su conexi\u00f3n ha sido cerrada porque el servidor ha sido apagado. -message.downloading = Descargando {0} -message.downloading.spark.plug = Descargando Spark-Plug -message.end.chat = \u00bfDesea finalizar esta conversaci\u00f3n? -message.end.conversation = \u00bfDesea finalizar esta sesi\u00f3n? -message.enter.aim = Ingrese su usuario de AIM y contrase\u00f1a. -message.enter.broadcast.message = Ingrese un mensaje para difundir a los usuarios seleccionados. -message.enter.gadugadu = Ingrese su usuario y contrase\u00f1a de de GaduGadu. -message.enter.gtalk = Ingrese su usuario y contrase\u00f1a de Gtalk. -message.enter.icq = Ingrese su usuario y contrase\u00f1a de ICQ. -message.enter.irc = Ingrese su usuario, contrase\u00f1a y apodo de IRC. -message.enter.jabber.id = Ingrese un Jabber ID -message.enter.message.to.broadcast = Ingresar mensaje para difundir a su lista de contactos. -message.enter.msn = Ingrese su usuario de MSN y contrase\u00f1a. -message.enter.new.subject = Ingrese un tema -message.enter.qq = Ingrese su n\u00famero QQ y contrase\u00f1a. -message.enter.room.password = Ingresar la contrase\u00f1a de cuarto -message.enter.simple = Ingrese su usuario y contrase\u00f1a de SIMPLE. -message.enter.valid.jid = Ingrese un Jabber ID v\u00e1lido -message.enter.xmpp = Ingrese su usuario y contrase\u00f1a de XMPP. -message.enter.yahoo = Ingrese su usuario y contrase\u00f1a para conectarse a Yahoo. -message.error.during.file.transfer = Hubo un error transfiriendo el archivo. -message.file.exists.question = El archivo ya existe. \u00bfSobreescribir? -message.file.size = Tama\u00f1o del archivo: {0} -message.file.transfer.canceled = Ha cancelado la transferencia del archivo. -message.file.transfer.chat.window = Solicitud de Transferencia de archivos -message.file.transfer.notification = Notificaci\u00f3n de Transferencia de archivos -message.file.transfer.rejected = La transferencia del archivo no ha sido aceptada por {0}. -message.file.transfer.short.message = te est\u00e1 enviando un archivo llamado: -message.find.conference.services = Buscar servicios de conferencia -message.forbidden.error = Se ha recibido un error de prohibici\u00f3n del servidor. -message.gateway.nickname.error = El apodo es requerido. -message.gateway.password.error = La contrase\u00f1a es requerida. -message.gateway.username.error = El nombre de usuario es requerido. -message.general.error = Ha perdido su conexi\u00f3n al servidor debido a: {0}. -message.generic.reconnect.message = Ha perdido su conexi\u00f3n al servidor. Para ingresar nuevamente, haga clic en Reconectar. -message.idle.for = Inactivo por {0} -message.image.too.large = Esta imagen es muy pesada para ser usada. Utilice una imagen de 16k o menos. -message.invalid.jabber.id = El Jabber ID no es v\u00e1lido -message.invalid.jid.error = El JID especificado es inv\u00e1lido. -message.invalid.status = Especifique un mensaje de estado v\u00e1lido. -message.invalid.username.password = Usuario o contrase\u00f1a inv\u00e1lidos. -message.invite.users.to.conference = Invitar usuarios al cuarto de conferencia. -message.is.shared.group = {0} es un grupo compartido. -message.is.typing.a.message = {0} est\u00e1 escribiendo un mensaje... -message.join.conference.room = Ingresar al Cuarto de conferencia -message.kicked.error = No ha sido capaz de echar {0} del cuarto. -message.last.message.received = \u00daltimo mensaje recibido el {0} -message.loading.please.wait = Cargando. Espere un momento... -message.locked.workstation = El usuario a bloqueado su estaci\u00f3n de trabajo. -message.name.of.group = Nombre del grupo -message.name.of.search.service.question = \u00bfNombre del servicio de b\u00fasqueda? -message.negotiate.file.transfer = Negociando transferencia de archivo. Aguarde un momento... -message.negotiate.stream = Negociando conexi\u00f3n. Aguarde un momento... -message.negotiation.file.transfer = Negociando transferencia de archivo con {0}. Aguarde un momento... -message.new.message = Nuevo mensaje de {0}. -message.new.spark.available = {0} est\u00e1 ahora disponible. \u00bfDesea instalarla? -message.nickname.in.use = Apodo en uso. Especifique otro apodo. -message.no.avatar.found = El usuario no ha configurado su avatar. -message.no.caller.id = Identificaci\u00f3n de llamadas no disponible. -message.no.description.available = No hay una descripci\u00f3n disponible -message.no.history.found = No existe un historial de conversaciones previas con este usuario. -message.no.results.found = El servidor no ha retornado resultados para la b\u00fasqueda. -message.no.room.to.join.error = No hay un cuarto al cual ingresar -message.no.subject.available = No hay un tema disponible -message.no.updates = No hay actualizaciones. -message.normal = Mensaje normal -message.number.to.call = Especifique el n\u00famero a discar -message.offline = El usuario no est\u00e1 conectado y recibir\u00e1 el mensaje cuando se conecte. -message.offline.error = El usuario no ser\u00e1 capaz de recibir mensajes diferidos. -message.participants.in.room = Participantes en el cuarto -message.password.error = Especificar una contrase\u00f1a para la cuenta. -message.password.private.room.error = Especifique una contrase\u00f1a para el cuarto privado -message.passwords.no.match = Las claves no son iguales. -message.please.join.in.conference = \u00danete conmigo al cuarto de conferencia. -message.plugins.not.available = Imposible contactar el repositorio de plugins. -message.prompt.plugin.uninstall = \u00bfEst\u00e1 seguro que desea desintalar {0}? -message.received.file = Ha recibido un archivo de {0}. -message.receiving.file = Est\u00e1 recibiendo un archivo de {0} -message.reconnect.attempting = Intentando... -message.reconnect.failed = Reconexi\u00f3n fallida. -message.reconnect.wait = Reconectando en {0} segundos. -message.register.transports = Registrar con los siguientes transportes. -message.registering = Registr\u00e1ndose en {0}. Aguarde un momento... -message.registration.transport.failed = No se ha podido registrar con el Transporte. -message.restart.required = Debe reiniciar el cliente para que sus cambios tomen efecto. \u00bfDesea hacerlo ahora? -message.restart.spark = Debe reiniciar el cliente para \n instalar la nueva versi\u00f3n. \u00bfDesea hacerlo ahora? -message.restart.spark.changes = El plugin ser\u00e1 borrado la pr\u00f3xima vez que se inicie Spark. -message.restart.spark.to.install = Debe reiniciar el cliente para instalar la nueva versi\u00f3n. \u00bfDesea hacerlo ahora? -message.room.creation.error = No se pudo crear el cuarto. -message.room.destroyed = Este cuarto ha sido destruido por el siguiente motivo: {0} -message.room.destruction.reason = \u00bfMotivo para destruir el cuarto? -message.room.information.for = Informaci\u00f3n del cuarto para {0} -message.save.profile = Para guardar los cambios a su perfil haga click en Salvar. -message.search.for.contacts = Buscar contactos. -message.search.for.other.people = Buscar otras personas en el servidor. -message.search.service.not.available = No se ha podido contactar al servicio de b\u00fasqueda. -message.searching.please.wait = Buscando. Aguarde un momento... -message.select.add.room.to.add = Seleccione cuarto a agregar a la lista. -message.select.one.or.more = Seleccione uno o m\u00e1s usuarios de su lista de contactos. -message.select.room.to.enter = Especifique cuarto a ingresar. -message.select.room.to.join = Seleccione cuarto a ingresar. -message.send.a.broadcast = Difundir mensaje -message.send.file.to.user = Enviar archivos a este usuario. -message.send.picture = Enviar foto de su escritorio. -message.send.to.these.people = Enviar a estas personas -message.sending.file.to = Enviando archivo a {0}. -message.sent.offline.files = Ha recibido un archivo mientras estaba desconectado. -message.server.unavailable = No se puede conectar al servidor: nombre inv\u00e1lido o servidor no disponible. -message.service.already.exists = El servicio ya se encuentra en su lista de servicios. -message.shared.group = Grupo compartido -message.spark.secure = Spark est\u00e1 ejecut\u00e1ndose en modo seguro. -message.specify.contact.jid = Por favor especifique el JID del contacto (ej: ddman@jabber.org) -message.specify.group = Especificar Grupo de contactos para agregar al nuevo usuario. -message.specify.information.for.conference = Especifique informaci\u00f3n del cuarto de conferencia. -message.specify.name.error = Especifique un nombre v\u00e1lido. -message.specify.users.to.join.conference = Especifique usuarios a invitar al cuarto. -message.specify.valid.time.error = Especifique un tiempo m\u00e1ximo y un puerto v\u00e1lido. -message.subject.change.error = No est\u00e1 permitido cambiar el tema del cuarto. -message.subject.has.been.changed.to = El tema ha sido cambiado a {0}. -message.supply.resource = Especifique un recurso v\u00e1lido. -message.supply.valid.port = Especifique un puerto v\u00e1lido. -message.supply.valid.timeout = Especifique un tiempo m\u00e1ximo v\u00e1lido. -message.timeout.error = El tiempo m\u00e1ximo debe ser de al menos 5 segundos. -message.total.downloaded = Total descargado -message.transfer.cancelled = La transferencia del archivo ha sido cancelada. -message.transfer.rate = Tasa de Transferencia -message.transfer.refused = La transferencia del archivo ha sido rechazada. -message.transfer.waiting.on.user = Esperando que {0} acepte la transferencia del archivo. -message.unable.to.load.profile = No se ha encontrado un perfil para {0} -message.unable.to.retrieve.last.activity = No se pudo determinar la \u00faltima actividad de {0} -message.unable.to.save.password = No se ha podido cambiar la contrase\u00f1a. Contacte el administrador del servidor. -message.unable.to.send.file = No ha sido capaz de transferir el archivo a {0}. -message.unrecoverable.error = Usuario o contrase\u00f1a no v\u00e1lida. -message.update.room.list = Actualizar lista de cuartos -message.updating.cancelled = La actualizaci\u00f3n ha sido cancelada. -message.user.banned = {0} ha sido censurado en este cuarto. -message.user.given.voice = {0} puede hablar en el cuarto. -message.user.granted.admin = {0} ha recibido permisos de administrador. -message.user.granted.membership = {0} ha recibido permisos de membres\u00eda. -message.user.granted.moderator = {0} ha recibido permisos de moderador. -message.user.granted.owner = {0} ha recibido permisos de due\u00f1o. -message.user.is.sending.you.a.file = {0} est\u00e1 enviando un archivo. -message.user.joined.room = {0} ha ingresado al cuarto. -message.user.kicked.from.room = {0} ha sido echado del cuarto. -message.user.left.room = {0} ha abandonado el cuarto. -message.user.nickname.changed = {0} es ahora conocido como {1}. -message.user.now.available.to.chat = {0} est\u00e1 en l\u00ednea en {1} -message.user.revoked.admin = Los privilegios de administrador han sido removidos para {0}. -message.user.revoked.membership = La membresia ha sido revocada para {0}. -message.user.revoked.moderator = Los privilegios de moderador han sido removidos para {0}. -message.user.revoked.owner = Los privilegios de due\u00f1o han sido removidos para {0}. -message.user.voice.revoked = Voz ha sido removida para {0}. -message.username.error = Especificar nombre de usuario para la cuenta. -message.username.password.error = Debe ingresar un nombre de usuario o contrase\u00f1a. -message.vcard.not.supported = El servidor no soporta VCards. No se ha podido salvar su VCard. -message.version = Versi\u00f3n: {0} -message.view.information.about.this.user = Ver informaci\u00f3n sobre este usuario. -message.waiting.for.user.to.join = Esperando que {0} se una. -message.went.offline = {0} se desconect\u00f3 a las {1} -message.you.have.been.banned = Ha sido censurado en este cuarto. -message.you.have.been.kicked = Ha sido echado del cuarto. -message.you.have.sent = Ha enviado un archivo a {0}. -message.your.admin.granted = Se le han otorgado permisos de administrador. -message.your.banned = Ha sido censurado en esta conversaci\u00f3n. -message.your.kicked = Has sido echado por {0}. -message.your.membership.granted = Se le han otorgado permisos de membresia. -message.your.membership.revoked = Su membresia ha sido revocada. -message.your.moderator.granted = Se le han otorgado permisos de moderador. -message.your.moderator.revoked = Sus privilegios de moderador han sido revocados. -message.your.ownership.granted = Se le han otorgado permisos de due\u00f1o. -message.your.ownership.revoked = Sus privilegios de due\u00f1o han sido revocados. -message.your.revoked.granted = Sus privilegios de administrador han sido revocados. -message.your.voice.granted = Se permiti\u00f3 el uso de voz en este chat. -message.your.voice.revoked = Su voz ha sido revocada. -no = No -not.registered = No registrado -occupants = Ocupantes -offline = Desconectado -ok = Ok -online = en l\u00ednea -open = Abrir -open.folder = Abrir carpeta -participants = Participantes -reject = Rechazar -retry = Reintentar -room.name = Nombre del cuarto -save = Guardar - -status.away = Ausente -status.custom.messages = Mensaje personalizado -status.do.not.disturb = No molestar -status.extended.away = Ausencia extendida -status.free.to.chat = Libre para chatear -status.on.phone = Al telefono -status.online = En l\u00ednea -status.pending = Pendiente -subject = Tema - -tab.available.plugins = Plugins disponibles -tab.avatar = Avatar -tab.business = Negocio -tab.conferences = Conferencias -tab.contacts = Contactos -tab.general = General -tab.home = Hogar -tab.installed.plugins = Plugins instalados -tab.personal = Personal -tab.proxy = Proxy - -title.about = Acerca de -title.account.create.registration = Registro de cuenta -title.account.created = Cuenta creada exitosamente -title.add.contact = Agregar contactos -title.add.contact.group = Agregar nuevo grupo de contactos -title.add.new.group = Agregar nuevo grupo -title.add.search.service = Agregar Servicio de B\u00fasqueda -title.add.to.roster = Agregar a Lista de contactos -title.address = Direcci\u00f3n -title.advanced.connection.preferences = Preferencias avanzadas de conexi\u00f3n -title.alert = Alerta -title.appearance = Apariencia -title.appearance.preferences = Personalizaci\u00f3n -title.appearance.showVCards = Motrar VCards en la Lista de Contactos -title.available.transports = Transportes disponibles -title.broadcast.message = Difundir mensaje -title.browse.conference.services = Ver servicios de conferencia -title.browse.room.service = Buscar cuartos de conferencia - {0} -title.cancelled = Cancelado -title.change.nickname = Cambiar apodo -title.change.subject = Cambiar tema -title.chat = Chat -title.choose.directory = Seleccione carpeta -title.choose.incoming.sound = Seleccione archivo de sonido entrante -title.choose.offline.sound = Seleccione archivo de sonido no conectado -title.choose.outgoing.sound = Seleccione archivo de sonido saliente -title.conference.invitation = Invitaci\u00f3n a conferencia -title.conference.rooms = Cuartos de conferencia -title.configure.chat.room = Configurar cuarto -title.configure.room = Configurar cuarto -title.confirmation = Confirmaci\u00f3n -title.create.new.account = Crear nueva cuenta -title.create.or.bookmark.room = Ingresar o guardar cuarto como favorito -title.create.or.join = Crear / Ingresar -title.create.problem = Hubo un problema al crear la cuenta -title.delete.file = \u00bfRealmente quieres eliminar este archivo? -title.dial.phone = Discar tel\u00e9fono -title.disable.transport = Deshabilitar transporte -title.download.complete = Descarga completa -title.downloading.im.client = Descargar Cliente IM -title.downloads = Descargas -title.edit.custom.message = Editar mensajes personalizados -title.edit.profile = Editar informaci\u00f3n de perfil -title.enter.reason = Ingresar motivo -title.error = Error -title.error.couldnt.open.file = \u00a1No se pudo abrir el archivo! Posiblemente un tipo de archivos desconocido. -title.error.delete.file = \u00a1No se pudo eliminar el archivo! -title.error.find.app = \u00a1No se pudo encontrar la aplicaci\u00f3n! -title.error.rename.file = \u00a1No se pudo renombrar el archivo! -title.file = Archivo -title.file.exists = Archivo existe -title.file.transfer = Transferencias de archivos -title.file.transfer.preferences = Preferencias de transferencia de archivos -title.filesize = Tama\u00f1o -title.find.conference.service = Buscar servicio de conferencia -title.find.contacts = Buscar contactos -title.gadugadu.registration = Credenciales de cuentas GaduGadu -title.general.chat.settings = Configuraci\u00f3n General de Chat -title.group.chat = Grupo de chat -title.group.chat.settings = Configuraciones de Chat grupal -title.gtalk.registration = Credenciales de cuenta GTalk -title.history.for = Historial de conversaci\u00f3n Con {0} -title.icq.registration = Registro de cuenta ICQ -title.incoming.call = Llamada entrante -title.input.fileexplorer = Por favor ingrese el nombre del Explorador de Archivos -title.input.newname = Por favor ingrese el nuevo nombre: -title.input.openwith = Por favor ingrese el nombre de la aplicaci\u00f3n que desea usar: -title.invite.to.conference = Invitar a conferencia -title.irc.registration = Registro de cuenta IRC -title.jabber.browser = Buscador -title.join.conference.room = Ingresar a cuarto de conferencia -title.last.activity = \u00daltima actividad -title.login = Ingresar -title.login.error = Error de inicio de sesi\u00f3n -title.login.settings = Configuraci\u00f3n de Login -title.lookup.profile = Buscar Perfil -title.msn.registration = Credenciales de cuentas MSN -title.name = Nombre -title.new.client.available = Nuevo Cliente disponible -title.new.roster.group = Nuevo grupo de contactos -title.new.version.available = Nueva Versi\u00f3n disponible -title.no.updates = No hay actualizaciones -title.notes = Notas -title.notification = Notificaci\u00f3n -title.notifications = Notificaciones -title.occupants = Ocupantes -title.on.the.phone = En el tel\u00e9fono -title.password = Contrase\u00f1a -title.passwords.no.match = Confirmar contrase\u00f1as. -title.person.search = B\u00fasqueda de Personas -title.plugins = Plugins -title.preferences = Preferencias -title.profile.information = Informaci\u00f3n de Perfil -title.profile.not.found = Perfil No Encontrado -title.qq.registration = Credenciales de cuenta QQ -title.register.account = Registrar Nueva cuenta -title.registration.error = Error de registro -title.reminder = Recordatorio -title.rename.roster.group = Renombrar grupo -title.room.destroyed = Cuarto destruido -title.room.information = Informaci\u00f3n del cuarto -title.roster = Lista de contactos -title.select.file.to.send = Seleccione los archivo(s) para enviar -title.set.status.message = Configurar mensaje de estado -title.simple.registration = Credenciales de cuenta SIMPLE -title.sound.preferences = Preferencias de sonido -title.sounds = Sonidos -title.spark.preferences = Preferencias de Spark -title.start.chat = Comenzar conversaci\u00f3n -title.status.message = Mensaje de estado -title.tasks = Tareas -title.transports = Transportes -title.tray.information = Informaci\u00f3n de bandeja -title.upgrading.client = Actualizando Cliente -title.version.and.time = Versi\u00f3n y Hora -title.view.bookmarks = Ver favoritos -title.view.profile.for = Viendo Perfil De {0} -title.view.room.information = Ver Informaci\u00f3n del cuarto -title.waiting.to.call = Esperando para hacer llamado -title.xmpp.registration = Credenciales de cuenta XMPP -title.yahoo.registration = Credenciales de cuenta Yahoo - -tooltip.appearance = Cambiar la apariencia de sus conversaciones. -tooltip.file.transfer = Preferencias de transferencia de archivos. -tooltip.notifications = Preferencias de notificaci\u00f3n para conversaciones entrantes. -tooltip.place.voice.call = Realizar llamada de voz -tooltip.send.email = Enviar un correo electr\u00f3nico -tooltip.start.chat = Comenzar una conversaci\u00f3n -tooltip.view.changelog = Ver registro de cambios -tooltip.view.history = Ver historial de conversaciones -tooltip.view.readme = Ver archivo Leeme - - -tree.conference.services = Servicios de conferencia -tree.users.in.room = Usuarios en el cuarto -unfiled = Sin clasificar -use.default = Usar predeterminado -user.has.signed.in = se ha conectado. -user.has.signed.off = se ha desconectado. -while.offline = mientras estaba desconectado -yes = Si - - -########################################## -# # -# # -# Missing Translation: # -# # -# # -########################################## - -administrator = Administrator -button.reject = Reject -button.login = &Login -button.re.detect = &Re-detect -checkbox.notify.typing.systemtray = &Show typing notification in the system tray -checkbox.notify.systemtray = Show new &messages in the system tray -checkbox.use.debugger.on.startup = Start debugger on startup -checkbox.use.krbconf = Use krb5.conf or krb5.ini -checkbox.use.krb.dns = Use DNS -checkbox.use.specify.below = Specify below -checkbox.use.pki.authentication = Use PKI authentication -label.na = n/a -label.cell = Cell -label.work = Work -label.home = Home -label.krb.realm = Realm -label.krb.kdc = KDC -label.which.pki.method = Which PKI method? -label.choose.file = Choose file -label.trust.store.password = Trust store password -label.enter.password = Enter password -label.move.focus.forwards = Move focus forwards -label.move.focus.backwards = Move focus backwards -label.keystore.location = Keystore location -label.truststore.location = Truststore location -label.pkcs.library.file = PKCS#11 library file -label.x509.certificate = X.509 certificate -label.apple.keychain = Apple KeyChain -label.add.to.roster = Add user to your roster -label.audio.device = &Audio device -label.video.device = &Video device -menuitem.bookmarks = Bookmarks -menuitem.add.groupchat.showjoinleavemessage = &Show join and leave messages -menuitem.add.groupchat.showrolesinsteadofstatus = Show chatroleicons instead of statusicons -menuitem.always.on.top = Always on top -menuitem.block.contact = Block contact -menuitem.unblock.contact = Unblock contact -menuitem.expand.all.groups = Expand all groups -menuitem.collapse.all.groups = Collapse all groups -menuitem.inivite.again = Invite again -menuitem.chatframe.option = Options -message.invite.to.groupchat = {0} is inviting you to join a group chat -message.enter.sametime = Enter your Sametime username and password below -message.enter.facebook = Enter your Facebook username and password below -message.enter.myspace = Enter your MySpace username and password below -message.nickname.not.acceptable = Nickname change is not enabled! -message.groupchat.require.password = This group chat room requires a password to enter -message.search.for.history = Search conversation history -tab.sso = SSO -tab.pki = PKI -title.password.required = Password required -title.task.notification = Task notification -title.client.logs = Client logs -title.bookmarks = Bookmarks -title.advanced.connection.usesso = Use Single Sign-On (SSO) via GSSAPI -title.general.media = Media settings -title.aim.registration = AIM account credentials -title.sametime.registration = Sametime account credentials -title.facebook.registration = Facebook account credentials -title.myspace.registration = MySpace account credentials -title.subscription.request = Subscription request -tooltip.place.a.call = Place a call to this individual - -#!# \ No newline at end of file diff --git a/src/resources/i18n/spark_i18n_fi.properties b/src/resources/i18n/spark_i18n_fi.properties deleted file mode 100644 index ad2daaf01..000000000 --- a/src/resources/i18n/spark_i18n_fi.properties +++ /dev/null @@ -1,976 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.0.1 -## Added key: 'message.restart.spark.changes' -## Added key: 'message.enter.icq' -## Added key: 'title.icq.registration' -## Added key: 'button.quit' -## -## -## -## 2.0.2 -## Added key: 'button.new' -## Added key: 'label.group' -## Added key: 'label.jabber.id' -## Added key: 'label.enter.group.name' -## Added key: 'title.new.roster.group' -## Added key: 'title.add.contact.group' -## Added key: 'message.add.contact.to.list' -## Added key: 'title.add.contact' -## Added key: 'tab.conferences' -## Added key: 'message.autenticating' -## Added key: 'title.file.transfer.preferences' -## Added key: 'menuitem.about' -## Added key: 'message.invalid.status' -## Added key: 'message.cannot.add.contact.to.shared.group -## Added key: 'message.specify.contact.jid' -## Added key: 'message.invalid.jid.error' -## Added key: 'message.specify.group' -## Added key: 'add' -## -## -## -## 2.0.5 -## Added key: 'Broadcast' -## Added key: 'label.user.on.public.network' -## Added key: 'label.network' -## -## -## 2.0.6 -## Added key: 'button.add.user' -## Added key: 'menuitem.sign.in' -## Added key: 'menuitem.sign.out' -## Added key: 'menuitem.sign.in.at.login' -## Added key: 'menuitem.enter.login.information' -## Added key: 'menuitem.delete.login.information' -## Added key: 'button.save' -## -## -## 2.5 -## Added key: 'button.start.chat' -## Added key: 'button.send.email' -## Added key: 'available' -## Added key: 'checkbox.tabs.on.top' -## Added key: 'user.has.signed.in' -## Added key: 'user.has.signed.off' -## Added key: 'label.unable.to.add.contact' -## Added key: 'label.conflict.error' -## Added key: 'message.room.creation.error' -## Added key: 'checkbox.allow.buzz' -## Added key: 'message.disconnected.group.chat.error' -## Added key: 'menuitem.show.offline.group' -## Added key: 'menuitem.move.to' -## Added key: 'menuitem.copy.to' - -## Added key: 'label.message.style' -## Added key: 'label.emoticons' -## Added key: 'checkbox.enable.emoticons' -## Added key: 'message.unable.to.retrieve.last.activity' -## Added key: 'checkbox.use.system.look.and.feel' -## -## 2.5.2 -## Added key: 'tooltip.place.voice.call' -## Added key: 'message.buzz.alert.notification' -## Added kye: 'message.buzz.sent' -## -## 2.5.2 -## Added key: 'menuitem.user.guide' -## -## -## -## 2.5.7 -## Added key: 'menuitem.languages' -## Added key: 'message.restart.required' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'message.send.to.these.people' -## Added key: 'message' -## Added key: 'message.normal' -## Added key: 'message.alert.notify' -## -## 2.5.8 -## Added key: 'message.enter.simple' -## Added key: 'message.enter.irc' -## Added key: 'message.enter.gadugadu' -## Added key: 'title.simple.registration' -## Added key: 'title.irc.registration' -## Added key: 'title.gadugadu.registration' -## Added key: 'message.username.error' -## Added key: 'message.password.error' -## Added key: 'message.nickname.error' -## -## 2.5.9 -## Added key: 'message.gateway.username.error. -## Added key: 'message.gateway.password.error. -## Added key: 'message.gateway.nickname.error. -## Added key: 'answer' -## Added key: 'online' -## Added key: 'online' -## Added key: 'offline' -## Added key: 'participants' -## Added key: 'unfiled' -## Added key: 'while.offline' -## Added key: 'action.clear' -## Added key: 'action.copy ' -## Added key: 'action.cut' -## Added key: 'action.paste' -## Added key: 'action.print' -## Added key: 'action.save' -## Added key: 'action.select.all' -## Added key: 'button.add2' -## Added key: 'button.copy.to.clipboard' -## Added key: 'button.reconnect2' -## Added key: 'button.tasks.active' -## Added key: 'button.tasks.all' -## Added key: 'button.view.notes' -## Added key: 'button.view.profile' -## Added key: 'button.view.tasklist' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.show.avatars.in.contaclist' -## Added key: 'checkbox.use.compression' -## Added key: 'group.empty' -## Added key: 'group.offline' -## Added key: 'label.add.task' -## Added key: 'label.chatroom.fontsize' -## Added key: 'label.contactlist.fontsize' -## Added key: 'label.due' -## Added key: 'label.show' -## Added key: 'label.timeformat' -## Added key: 'menuitem.dial' -## Added key: 'menuitem.view.logs' -## Added key: 'message.disconnected.shutdown' -## Added key: 'message.invalid.username.password' -## Added key: 'message.no.updates' -## Added key: 'message.reconnect.attempting' -## Added key: 'message.reconnect.failed' -## Added key: 'message.reconnect.wait' -## Added key: 'message.send.picture' -## Added key: 'message.server.unavailable' -## Added key: 'message.unrecoverable.error' -## Added key: 'message.waiting.for.user.to.join' -## Added key: 'status.available' -## Added key: 'status.away' -## Added key: 'status.custom.messages' -## Added key: 'status.do.not.disturb' -## Added key: 'status.extended.away' -## Added key: 'status.free.to.chat' -## Added key: 'status.on.phone' -## Added key: 'status.online' -## Added key: 'status.pending' -## Added key: 'title.about' -## Added key: 'title.appearance' -## Added key: 'title.appearance.preferences' -## Added key: 'title.login.error' -## Added key: 'title.no.updates' -## Added key: 'title.notes' -## Added key: 'title.tasks' -## Added key: 'tooltip.appearance' -## Added key: 'tooltip.file.transfer' -## Added key: 'tooltip.send.email' -## Added key: 'tooltip.start.chat' -## Added key: 'delete.log.permanently' -## Added key: 'delete.permanently' -## Added key: 'label.contactlist.avatarsize' -## Added key: 'title.qq.registration' -## Added key: 'message.enter.qq' -## -## 2.6.0 beta 1 -## Removed key status.available - -administrator = Pääkäyttäjä -apply = Ota käyttöön -ok = Ok -cancel = Peruuta -add = Lisää -use.default = Palauta oletukset -close = Sulje -create = Luo -invite = Kutsu -date = Päiväys -from = Lähettäjä -room.name = Huoneen nimi -join = Liity -description = Kuvaus -subject = Aihe -occupants = Osallistujat -accept = Hyväksy -answer = Vastaa -online = linjoilla -offline = Poissa linjoilta -reject = Hylkää -open = Avaa -open.folder = Avaa kansio -participants = Osallistujat -retry = Yritä uudelleen -active = Aktiivinen -not.registered = Ei rekisteröitynyt -save = Tallenna -unfiled = Luokittelematon -yes = Kyllä -no = Ei -while.offline = Poissaollessa -broadcast = Kuulutus -available = Paikalla -user.has.signed.in = kirjautui sisään. -user.has.signed.off = kirjautui ulos. -gateway.username.password.error = Käyttäjätunnus ja/tai salasana tarvitaan -delete.log.permanently = Poista logi -delete.permanently = Poista pysyvästi? - -action.clear = Tyhjennä -action.copy = Kopioi -action.cut = Leikkaa -action.paste = Liitä -action.print = Tulosta -action.save = Tallenna -action.select.all = Valitse kaikki - -button.create.account = &Lisää tili -button.close = &Sulje -button.advanced = &Lisäasetukset -button.browse = &Selaa... -button.browse2 = S&elaa... -button.browse3 = Se&laa... -button.approve = &Hyväksy -button.deny = &Hylkää -button.accept = &Hyväksy -button.profile = &Profiili -button.add.a.contact = &Lisää yhteystieto -button.reconnect = &Yhdistä uudelleen -button.reconnect2 = Yhdistä uudelleen -button.add = &Lisää -button.add2 = Li&sää -button.roster = &Tuttavalista -button.add.bookmark = Lisää kirjanmerkki -button.remove.bookmark = Poista kirjanmerkki -button.bookmark.room = &Lisää huone kirjanmerkkeihin -button.create.room = &Luo huone -button.join.room = &Liity huoneeseen -button.refresh = &Virkistä -button.find = &Etsi -button.update = &Päivitä -button.cancel = &Peruuta -button.decline = &Kieltäydy -button.join = &Liity -button.save.for.future.use = &Tallenna myähempää käyttää varten -button.register = &Rekisteröidy -button.dial.number = &Valitse numero -button.clear = &Tyhjennä -button.search = &Etsi -button.add.service = &Lisää palvelu -button.quit = Lopeta -button.new = &Uusi -button.add.user = &Lisää käyttäjä -button.save = &Tallenna -button.start.chat = Aloita keskustelu -button.send.email = Sähköposti -button.send = Lähetä -button.copy.to.clipboard = Kopioi leikepöydälle -button.tasks.active = Aktiivisena -button.tasks.all = Kaikki -button.view.notes = Näytä muistiinpanot -button.view.profile = Näytä koko profiili -button.view.tasklist = Näytä tehtävälista -button.reject = Hylkää -button.login = &Kirjaudu -button.unset.file.explorer = Poista tiedostoselainvalinta -button.re.detect = &Havaitse uudelleen - -checkbox.save.password = &Tallenna salasana -checkbox.auto.login = &Kirjaudu automaattisesti -checkbox.use.proxy.server = &Käytä välityspalvelinta -checkbox.auto.discover.port = &Etsi isäntä ja portti automaattisesti -checkbox.permanent = Huone &pysyvästi käytössä -checkbox.private.room = Huone &on yksityinen -checkbox.show.time.in.chat.window = &näytä aika keskusteluikkunassa -checkbox.show.notifications.in.conference = &Näytä huomautukset ryhmäkeskustelussa -checkbox.disable.chat.history = &älä tallenna keskusteluhistoriaa -checkbox.show.toaster = Näytä &Popup tyyppiset tiedotusikkunat -checkbox.window.to.front = &Ikkuna päällimmäiseksi -checkbox.play.sound.on.new.message = Soita viestin &merkkiääni -checkbox.play.sound.when.offline = Soita merkkiääni &offline tiedotuksista -checkbox.play.sound.on.outgoing.message = Merkkiääni viestin &lähetyksestä -checkbox.play.sound.on.invitation = Soita merkkiääni &ryhmäkeskustelukutsusta -checkbox.idle.enabled = &Automaattinen poissaoloilmoitus -checkbox.launch.on.startup = &Käynnistä automaattisesti -checkbox.notify.user.comes.online = Ilmoita kun käyttäjä tulee linjoille -checkbox.notify.user.goes.offline = Ilmoita kun käyttäjä poistuu linjoilta -checkbox.start.in.tray = &Käynnistä Spark piilotettuna -checkbox.split.chat.window = &Erilliset keskusteluikkunat (vaatii uudelleenkäynnistyksen) -checkbox.tabs.on.top = &Keskusteluvälilehdet aukeavat päällimmäisiksi (vaatii uudelleenkäynnistyksen) -checkbox.allow.buzz = Sal&li muiden käyttäjien painaa summeria. -checkbox.enable.emoticons = Hy&miöt käytössä -checkbox.use.system.look.and.feel = Käytä järjestelmän &teemaa (vaatii uudelleenkäynnistyksen) -checkbox.use.compression = Käytä Pa&kkausta -checkbox.show.avatars.in.contactlist = Näytä &hahmot yhteystiedoissa -checkbox.use.debugger.on.startup = Käynnistä debuggeri käynnistyessä -checkbox.broadcast.hide.offline.user = Piilota poissaolevat -checkbox.use.krbconf = Käytä krb5.conf tai krb5.ini -checkbox.use.krb.dns = Käytä DNS -checkbox.use.specify.below = Määrittele alla -checkbox.use.pki.authentication = Käytä PKI tunnistautumista -checkbox.disable.prev.chat.history = E&stä aiempien keskustelujen näyttäminen -checkbox.notify.typing.systemtray = &Näytä kirjoitushälytys tehtäväpalkissa -checkbox.notify.systemtray = Näytä uudet &viestit tehtäväpalkissa - -label.user.on.public.network = Käyttäjä julkisessa verkossa -label.change.password.to = &Uusi salasana -label.username = &Käyttäjänimi -label.name = &Nimi -label.room.name = &Huoneen nimi -label.room.topic = Puheen&aihe -label.password = &Salasana -label.confirm.password = &Varmista salasana -label.server = &Palvelin -label.create.account = &Tee uusi tili -label.close = &Sulje -label.ok = OK -label.cancel = Peruuta -label.use.default = Palauta oletukset -label.port = &Portti -label.auto.login = &Automaattinen sisäänkirjautuminen -label.old.ssl = &Vanha SSL PORT salaus -label.host = &Isäntä -label.resource = &Resurssi -label.protocol = &Protokolla -label.accounts = &Tilit -label.transfer.timeout = &Siirron aikakatkaisu (min): -label.transfer.download.directory = &Lataushakemisto: -label.find = &Etsi -label.rename.to = Nimeä uudelleen -label.contact.to.find = Etsittävä yhteystieto? -label.available.users.in.roster = &Paikalla olevat käyttäjät tuttavalistassa -label.time = Aika: {0} -label.add.conference.service = &Lisää keskustelupalvelu -label.add.jid = &Lisää JID -label.add.task = Lisää tehtävä -label.due = Erääntyvä -label.chatroom.fontsize = Keskusteluhuoneen &kirjasinkoko: -label.contactlist.fontsize = Yhteystietojen &kirjasinkoko: -label.contactlist.avatarsize = Yhteystietojen kuvien koko: -label.message = &Viesti -label.room = &Huone -label.invited.users = Kutsutut käyttäjät -label.new.nickname = Uusi lempinimi -label.server.address = &Palvelimen osoite -label.nickname = &Lempinimi -label.presence = &Läsnäolo -label.priority = K&iireellisyys -label.enter.address = Syötä osoite -label.jabber.address = &Jabber osoite -label.local.time = &Paikallinen aika -label.software = &Ohjelmisto -label.version = &Versio -label.os = &Käyttöjärjestelmä -label.show = Näytä: -label.timeformat = Käytä {0} -label.number = &Numero -label.dial = &Soita -label.minutes.before.stale.chat = &Hiljaisuuden kesto, jonka jälkeen huone muuttuu tunkkaiseksi(min) -label.company = &Yhtiö -label.street.address = &Katuosoite -label.city = &Kaupunki -label.state.and.province = L&ääni -label.postal.code = &Postinumero -label.country = &Maa -label.job.title = &Asema -label.department = &Osasto -label.phone = &Puhelin -label.fax = &Faksi -label.mobile = &Matkapuhelin -label.web.page = &Internetsivu -label.pager = &Piipperi -label.first.name = &Etunimi -label.middle.name = &Toinen etunimi -label.last.name = &Sukunimi -label.email.address = &Sähköpostiosoite -label.jid = &JID -label.search.service = &Hakupalvelu -label.xmpp.port = &XMPP Portti -label.response.timeout = &Vastauksen aikakatkaisu (sekuntia) -label.time.till.idle = &Aikaa joutilaana automaattiseen poissaolotilaan (min) -label.jabber.id = &Jabber ID -label.group = &Ryhmä -label.enter.group.name = Anna ryhmälle nimi -label.network = Verkko -label.unable.to.add.contact = Yhteystiedon lisäys ei onnistu -label.conflict.error = Kirjautuminen ei onnistu. Käyttäjä on kirjautunut sisään muualta -label.message.style = &Viestien ulkoasu -label.emoticons = &Hymiöt -label.cell = Kännykkä -label.work = Työ -label.home = Koti -label.downloads = Lataukset -label.received = Saapuneet -label.krb.realm = Piiri -label.krb.kdc = KDC -label.which.pki.method = Mikä PKI metodi? -label.choose.file = Valitse tiedosto -label.trust.store.password = Luota säilön salasanaan -label.enter.password = Anna salasana -label.move.focus.forwards = Siirrä kohdistin eteenpäin -label.move.focus.backwards = Siirrä kohdistin taaksepäin -label.keystore.location = Keystore sijainti -label.truststore.location = Truststore sijainti -label.pkcs.library.file = PKCS#11 kirjasto -label.x509.certificate = X.509 varmenne -label.add.to.roster = Lisää käyttäjä tuttavalistaasi -label.audio.device = &Äänilaite -label.video.device = &Kuvalaite - -message = &Viesti -message.normal = Tavallinen viesti -message.alert.notify = Tiedota hälytyksistä -message.username.error = Anna tilille nimi. -message.password.error = Anna tilille salasana. -message.confirmation.password.error = Syötä salasanan vahvistus. -message.account.error = Syötä palvelin, jolle tili luodaan. -message.registering = Rekisteröidytään {0}. Ole hyvä ja odota... -message.connection.failed = Yhistäminen ei onnistu {0} -message.create.account = Tiliä ei voitu luoda. -message.already.exists = Tili on jo olemassa. -message.account.created = Tili luotu. -message.account.create = Luo uusi tili. -message.connecting.please.wait = Yhdistetään, ole hyvä ja odota... -message.supply.valid.timeout = Anna hyväksyttävä aikakatkaisu aika. -message.supply.valid.port = Syötä hyväksyttävä porttinumero. -message.supply.resource = Syötä hyväksyttävä resurssi. -message.current.status = Tiedota tilastasi ja toiminnoistasi muille. -message.disconnected.error = Yhteytesi suljettiin virheen takia. -message.disconnected.group.chat.error = Yhteytesi suljettiin virheen takia. Sinun täytyy liittyä keskusteluhuoneisiin uudelleen yhdistämisen jälkeen. -message.disconnected.conflict.error = Yhteytesi suljettiin, koska nimelläsi on kirjauduttu toisesta paikasta. -message.disconnected.shutdown = Yhteytesi suljettiin, koska palvelin sammutettiin. -message.locked.workstation = Tietokone lukittu -message.away.idle = Poissa tietokoneelta -message.default.error = Virhe havaittiin. Ole hyvä ja ilmoita siitä osoitteeseen support@jivesoftware.com. -message.new.message = Uusi viesti käyttäjältä {0}. -message.send.file.to.user = Lähetä tiedostoja tälle käyttäjälle. -message.send.picture = Kaappaa ja lähetä mitä vain ruudultasi. -message.send.to.these.people = Lähetä näille käyttäjille -message.sent.offline.files = Sinulle on lähetetty tiedostoja poissaolevalta käyttäjältä. -message.spark.secure = Spark on suojatussa tilassa. -message.search.for.contacts = Etsi yhteystietoja. -message.end.conversation = Haluatko sulkea tämän keskustelun? -message.end.chat = Lopetetaanko ryhmäkeskustelu? -message.close.this.chat = Sulje tämä ryhmäkeskustelu -message.close.other.chats = Sulje muut ryhmäkeskustelut -message.close.stale.chats = Sulje pitkään hiljaisena olleet huoneet -message.last.message.received = Viimeisin viesti vastaanotettu {0} -message.shared.group = Jaettu ryhmä -message.is.shared.group = {0} on jaettu ryhmä. -message.delete.confirmation = Haluatko varmasti poistaa {0}? -message.idle.for = Joutilaana {0} minuuttia -message.enter.broadcast.message = Syötä valituille käyttäjille kuulutettava viesti. -message.name.of.group = Ryhmän nimi -message.approve.subscription = Sallitko käyttäjän {0} lisätä sinut yhteystietoihinsa? -message.add.user = Lisää käyttäjä yhteystietoihisi -message.general.error = Yhteys palvelimeen menetettiin {0} johdosta. -message.add.a.contact = Lisää yhteystieto -message.generic.reconnect.message = Yhteys palvelimeen menetettiin. Paina Yhdistä nappulaa kirjautuaksesi uudelleen. -message.select.one.or.more = Valitse yksi tai useampi käyttäjä yhteystiedoistasi. -message.add.conference.service = Lisää ryhmäkeskustelupalvelin. -message.service.already.exists = Palvelu on jo listattuna palvelulistassa. -message.searching.please.wait = Etsitään. Ole hyvä ja odota... -message.conference.service.error = Ryhmäkeskustelupalvelinta ei läydy -message.create.or.join.room = Liity ryhmäkeskusteluun tai luo uusi -message.specify.name.error = Anna hyväksyttävä nimi -message.password.private.room.error = Anna yksityiselle huoneelle salasana -message.passwords.no.match = Salasanat eivät täsmää. -message.enter.valid.jid = Syötä hyväksyttävä Jabber ID -message.please.join.in.conference = Ole hyvä ja liity ryhmäkeskusteluun. -message.invite.users.to.conference = Kutsu käyttäjiä ryhmäkeskusteluun. -message.specify.users.to.join.conference = Valitse tähän keskusteluhuoneeseen liittyvät käyttäjät. -message.no.room.to.join.error = Liityttäviä huoneita ei ole -message.participants.in.room = Huoneen keskustelijat -message.you.have.been.kicked = Sinut on potkittu pois huoneesta. -message.kicked.error = Et pysty potkimaan {0} pois tästä huoneesta. -message.you.have.been.banned = Sinulle on langetettu porttikielto tähän huoneeseen. -message.nickname.in.use = Nimimerkki on käytössä, valitse toinen nimimerkki ja yritä uudelleen -message.update.room.list = Virkistä huonelista -message.join.conference.room = Liity keskusteluhuoneeseen -message.select.add.room.to.add = Valitse palvelulistaan lisättävä huone. -message.bookmark.temporary.room.error = Väliaikaiseksi tarkoitettuja huoneita ei voi kirjanmerkitä. -message.select.room.to.join = Valitse huone johon haluat liittyä. -message.conference.info.error = Ryhmäkeskusteluista ei saatu tietoa. Yritä myöhemmin uudelleen. -message.add.favorite.room = Lisää suosikkihuone. -message.select.room.to.enter = Valitse huone johon haluat liittyä. -message.find.conference.services = Etsi ryhmäkeskustelupalvelimia -message.specify.information.for.conference = Anna keskusteluhuoneen tiedot. -message.no.description.available = Ei kuvausta saatavilla -message.no.subject.available = Ei aihetta saatavilla -message.room.information.for = Tiedot huoneelle {0} -message.view.information.about.this.user = Näytä käyttäjän tiedot -message.add.this.user.to.your.roster = Lisää käyttäjä tuttavalistaasi. -message.came.online = {0} on linjoilla {1} -message.went.offline = {0} meni pois linjoita {1} -message.offline.error = Käyttäjälle ei voi lähettää offline viestejä. -message.offline = Käyttäjä on poissa linjoilta ja saa viestin kirjautuessaan seuraavan kerran sisään. -message.is.typing.a.message = {0} kirjoittaa viestiä... -message.enter.new.subject = Kirjoita uusi aihe -message.confirm.destruction.of.room = Huoneen tuhoaminen poistaa kaikki käyttäjät huoneesta. Jatketaanko? -message.room.destruction.reason = Syy huoneen poistamiseen? -message.user.left.room = {0} poistui huoneesta. -message.user.joined.room = {0} tuli huoneeseen. -message.chat.session.ended = Keskustelu päättyi {0} -message.subject.change.error = Sinulla ei ole oikeuksia vaihtaa aihetta. -message.forbidden.error = Palvelin kielsi suorittamasi toiminnon. -message.gateway.username.error = Käyttäjänimi tarvitaan. -message.gateway.password.error = Salasana tarvitaan. -message.gateway.nickname.error = Nimimerkki tarvitaan. -message.room.destroyed = Huone tuhottiin. Tuhoamisen syy: {0} -message.subject.has.been.changed.to = Huoneen aiheeksi vaihdettiin "{0}". -message.user.kicked.from.room = {0} potkittiin ulos huoneesta. -message.user.given.voice = {0} sai luvan puhua tässä huoneessa -message.user.voice.revoked = Käyttäjältä {0} poistettiin lupa puhua. -message.user.banned = Käyttäjälle {0} annettiin porttikielto huoneeseen -message.user.granted.membership = Käyttäjälle {0} myönnettiin jäsenyys -message.user.revoked.membership = Jäsenyysoikeudet poistettiin käyttäjältä {0} -message.user.granted.moderator = {0} on nyt Moderaattori. -message.user.revoked.moderator = {0} ei enää ole Moderaattori. -message.user.granted.owner = {0} on huoneen omistaja. -message.user.revoked.owner = {0} ei enää ole huoneen omistaja. -message.user.granted.admin = {0} on nyt Järjestelmänvalvoja. -message.user.revoked.admin = Järjestelmänvalvojan oikeudet poistettiin käyttäjältä {0}. -message.user.nickname.changed = {0} vaihtoi nimimerkikseen {1}. -message.your.kicked = {0} potkaisi sinut ulos huoneesta. -message.your.voice.granted = Sinulle myönnettiin puheoikeus. -message.your.voice.revoked = Sinulta poistettiin puheoikeus. -message.your.banned = Sinulle annettiin porttikielto tähän huoneeseen. -message.your.membership.granted = Sinulle myönnettiin jäsenyys. -message.your.membership.revoked = Jäsenyytesi poistettiin. -message.your.moderator.granted = Sinulla on nyt Moderaattorin oikeudet. -message.your.moderator.revoked = Moderaattorin oikeutesi poistettiin. -message.your.ownership.granted = Sinulle on myönnetty huoneen omistajuus. -message.your.ownership.revoked = Omistajan oikeutesi tähän huoneeseen poistettiin. -message.your.admin.granted = Sinulle on myönnetty järjestelmänvalvojan oikeudet. -message.your.revoked.granted = Järjestelmänvalvojan oikeutesi poistettiin. -message.send.a.broadcast = Lähetä kuulutus -message.broadcast.from = Kuulutus henkilöltä {0} -message.enter.message.to.broadcast = Kirjoita viesti, joka kuulutetaan kaikille kontakteillesi. -message.broadcast.message.sent = Kuulutus lähetetty -message.broadcast.to = Kirjoita {0}:lle kuulutettava viesti -message.broadcasted.to = Viesti kuulutettu:\n{0} -message.user.now.available.to.chat = {0} on nyt linjoilla {1} -message.user.is.sending.you.a.file = {0} lähettää sinulle tiedoston. -message.file.transfer.canceled = Tiedoston siirto peruttu. -message.negotiate.file.transfer = Tiedostonsiirrosta sovitaan. Hetkinen... -message.negotiate.stream = Yhteysvirtaa avataan. Odota hetki... -message.receiving.file = {0} tarjoaa tiedostoa -message.click.to.open = Avaa -message.error.during.file.transfer = Tiedostonsiirrossa tapahtui virhe. -message.transfer.refused = Vastaanottaja kieltäytyi siirrosta. -message.transfer.cancelled = Tiedostonsiirto peruttiin. -message.received.file = Sait tiedoston käyttäjältä {0}. -message.file.exists.question = Tiedosto on jo olemassa. Ylikirjoita? -message.transfer.waiting.on.user = Odotetaan, että {0} hyväksyy tiedoston siirron... -message.negotiation.file.transfer = Sovitaan tiedostonsiirrosta käyttäjän {0} kanssa. Odota hetki... -message.unable.to.send.file = Tiedostonlähetys käyttäjälle {0} ei onnistu. -message.sending.file.to = Lähetetään tiedostoa käyttäjälle {0}. -message.you.have.sent = Olet lähettänyt tiedoston käyttäjälle {0}. -message.file.transfer.rejected = Tiedostonsiirto käyttäjälle {0} hylättiin. -message.disable.transport = Poista kirjautumistiedot {0}? -message.register.transports = Rekisteröidy näihin siirtoprotokolliin -message.enter.aim = Anna AIM käyttäjänimi ja salasana. -message.enter.msn = Anna MSN käyttäjänimi ja salasana. -message.enter.yahoo = Anna Yahoo käyttäjänimi ja salasana. -message.enter.icq = Anna ICQ käyttäjänimi ja salasana. -message.enter.simple = Anna SIMPLE käyttäjänimi ja salasana -message.enter.irc = Anna IRC käyttäjänimi ja salasana -message.enter.gadugadu = Anna GaduGadu käyttäjänimi ja salasana. -message.enter.qq = Syätä QQ numerosi ja salasanasi -message.username.password.error = Käyttäjänimi ja salasana tarvitaan. -message.registration.transport.failed = Siirtoprotokollan rekisteröinti epäonnistui. -message.client.information = Asiakasohjelman tiedot käyttäjälle {0} -message.calling = Soitetaan {0} -message.number.to.call = Anna numero, johon soitetaan -message.no.caller.id = Soittajan tunnistetta ei ole saatavilla -message.no.history.found = Keskusteluhistoriaa ei löytynyt tälle käyttäjälle. -message.prompt.plugin.uninstall = Haluatko poistaa lisäosan {0}? -message.loading.please.wait = Ladataan. Odota hetki... -message.plugins.not.available = Lisäosia tarjoavaan palvelimeen ei saada yhteyttä. -message.downloading = Ladataan {0} -message.downloading.spark.plug = Ladataan lisäosaa -message.unable.to.save.password = Salasanaa ei voitu tallentaa. Ota yhteyttä järjestelmänvalvojaan. -message.delete.all.history = Poista kaikki historiatiedot? -message.no.avatar.found = Henkilö ei ole asettanut itselleen hahmoa. -message.image.too.large = Kuva on liian suuri. Kuvan maksimikoko on 16 kilotavua. -message.save.profile = Tallentaaksesi muutokset paina nappia Tallenna. -message.unable.to.load.profile = Profiilin {0} lataaminen ei onnistu. -message.enter.jabber.id = Syötä Jabber ID -message.invalid.jabber.id = Antamasi Jabber ID ei ole kelvollinen -message.invalid.username.password = Virheellinen käyttäjänimi tai salasana -message.vcard.not.supported = Palvelin ei tue käyntikortteja. Käyntikorttiasi ei tallennettu. -message.search.service.not.available = Hakupalveluun ei saada yhteyttä. -message.no.results.found = Hakutuloksia ei läytynyt. -message.name.of.search.service.question = Hakupalvelun nimi? -message.search.for.other.people = Etsi palvelimelta muita käyttäjiä. -message.specify.valid.time.error = Anna hyväksyttävä katkaisuaika ja portti. -message.timeout.error = Aikakatkaisun rajan täytyy olla vähintään viisi sekuntia. -message.version = Versio: {0} -message.file.size = Tiedoston koko: {0} -message.restart.spark = Sinun täytyy sulkea ohjelma asentaaksesi uuden version, \n Käynnistetäänkö nyt? -message.restart.required = Muutosten toteuttamiseksi Spark täytyy käynnistää uudelleen. Käynnistetäänkö nyt? -message.updating.cancelled = Päivitys peruutettiin. -message.transfer.rate = Siirtonopeus -message.total.downloaded = Yhteensä ladattuna -message.new.spark.available = {0} on nyt saatavilla. Asennetaanko se nyt? -message.restart.spark.to.install = Ohjelma täytyy sulkea uuden version asennuksen ajaksi. Käynnistetäänkö ohjelma uudelleen nyt? -message.add.to.roster = Lisää tuttavalistaan -message.enter.room.password = Anna huoneen salasana -message.add.contact.to.list = Lisää käyttäjä yhteystiedoihin -message.autenticating = Tunnistaudutaan -message.invalid.status = Anna hyväksyttävä tilaviesti. -message.cannot.add.contact.to.shared.group = Et voi lisätä uusia henkilöitä jaettuun ryhmään. -message.specify.contact.jid = Anna yhteystiedon Jabber ID (esim. ddman@jabber.org) -message.invalid.jid.error = Antamasi JID on epäkelpo. -message.specify.group = Anna ryhmä johon uusi yhteystieto lisätään. -message.room.creation.error = Huonetta ei voitu luoda. -message.unable.to.retrieve.last.activity = Läsnäolotietoja ei saatu käyttäjälle {0} -message.buzz.alert.notification = Lähetä käyttäjälle summerihälytys. -message.buzz.sent = Käyttäjän summeria painettiin. -message.no.updates = Päivityksiä ei ole -message.reconnect.attempting = Yhdistetään... -message.reconnect.failed = Uudelleenyhdistys ei onnistunut -message.reconnect.wait = Yhdistetään uudelleen {0} sekunnin kuluttua. -message.server.unavailable = Palvelimeen ei saada yhteyttä, virheellinen nimi tai palvelin ei ole käytössä. -message.unrecoverable.error = Virheellinen käyttäjänimi tai salasana. -message.waiting.for.user.to.join = Odotellaan käyttäjän {0} liittymistä. -message.invite.to.groupchat = {0} pyytää sinua liittymään ryhmäkeskusteluun -message.enter.gtalk = Anna GTalk tunnus ja salasana alla -message.enter.sametime = Anna Sametime tunnus ja salasana alla -message.enter.facebook = Anna Facebook tunnus ja salasana alla -message.enter.myspace = Anna MySpace tunnus ja salasana alla -message.enter.xmpp = Anna XMPP tunnus ja salasana alla -message.file.transfer.notification = Tiedostonlähetysilmoitus -message.file.transfer.short.message = lähettää tiedostoa nimeltä\: -message.file.transfer.chat.window = Tiedostonlähetyspyyntö: -message.nickname.not.acceptable = Lempinimen vaihto ei käytössä! -message.restart.spark.changes = Liitännäinen poistetaan seuraavan Sparkin käynnistyksen yhteydessä -message.groupchat.require.password = Tämä ryhmäkeskusteluhuone vaatii salasanan -message.search.for.history = Etsi keskusteluhistoriasta - -status.away = Poissa -status.custom.messages = Muokatut viestit -status.do.not.disturb = Älä häiritse -status.extended.away = Poissa pitkään -status.free.to.chat = Vapaa keskustelemaan -status.on.phone = Puhelimessa -status.online = Linjoilla -status.pending = Tulossa linjoille - -title.about = Tietoja -title.passwords.no.match = Salasanat eivät täsmää, syötä ne uudelleen. -title.create.problem = Tilin luonnissa esiintyi ongelmia -title.account.created = Tili luotiin -title.create.new.account = Tee uusi tili -title.account.create.registration = Tilin rekisteröinti -title.register.account = Uusi tili rekisteröitiin -title.notification = Tiedonanto -title.advanced.connection.preferences = Edistyneet yhteysasetukset -title.preferences = Asetukset -title.error = Virhe -title.status.message = Tila Viesti -title.spark.preferences = Spark Asetukset -title.alert = Varoitus -title.tray.information = Tray Information -title.select.file.to.send = Valitse lähetettävät tiedostot -title.choose.directory = Valitse hakemisto -title.confirmation = Varmistus -title.last.activity = Viimeisin toimenpide -title.add.new.group = Lisää uusi ryhmä -title.add.to.roster = Lisää tuttavalistaan -title.find.contacts = Etsi yhteystietoja -title.rename.roster.group = Uudelleennimeä tuttavaryhmä -title.roster = Tuttavalista -title.create.or.join = Luo/Liity -title.conference.rooms = Keskusteluhuone -title.invite.to.conference = Kutsu keskusteluhuoneeseen -title.room.information = Huoneeen tiedot -title.change.nickname = Vaihda lempinimeä -title.group.chat = Ryhmäkeskustelu -title.create.or.bookmark.room = Liity tai lisää huone kirjanmerkkeihin -title.browse.room.service = Selaa keskusteluhuoneita - {0} -title.name = Nimi -title.address = Osoite -title.occupants = Osallistujat -title.browse.conference.services = Selaa keskustelupalvelinta -title.find.conference.service = Etsi keskustelupalvelu -title.configure.chat.room = Keskusteluhuoneen asetukset -title.conference.invitation = Kutsu keskusteluhuoneeseen -title.join.conference.room = Liity keskusteluhuoneeseen -title.view.room.information = Huoneen tiedot -title.configure.room = Huoneen asetukset -title.change.subject = Vaihda puheenaihetta -title.enter.reason = Anna syy -title.room.destroyed = Huone tuhottu -title.edit.custom.message = Muokkaa viestiä itse -title.set.status.message = Aseta tilaviesti -title.broadcast.message = Kuulutus -title.start.chat = Aloita keskustelu -title.view.bookmarks = Näytä kirjanmerkit -title.downloads = Lataukset -title.file.exists = Tiedosto on olemassa -title.disable.transport = Poista kirjautumistunnukset -title.available.transports = Käytössä olevat siirtoprotokollat -title.transports = Siirtoprotokollat -title.aim.registration = AIM Tilitiedot -title.msn.registration = MSN Tilitiedot -title.qq.registration = QQ Tilitiedot -title.yahoo.registration = Yahoo Tilitiedot -title.icq.registration = ICQ Tilitiedot -title.simple.registration = SIMPLE Tilitiedot -title.irc.registration = IRC Tilitiedot -title.gadugadu.registration = GaduGadu Tilitiedot -title.registration.error = Virhe rekisteröityessä -title.jabber.browser = Selain -title.version.and.time = Versio ja aika -title.waiting.to.call = Odotetaan puhelun yhdistymistä -title.incoming.call = Saapuva puhelu -title.on.the.phone = Puhelimessa -title.dial.phone = Valitse numero -title.history.for = Historiatiedot käyttäjälle {0} -title.reminder = Muistutus -title.plugins = Lisäosat -title.general.chat.settings = Yleiset keskusteluasetukset -title.chat = Keskustelu -title.notifications = Huomautukset -title.sound.preferences = ääniasetukset -title.sounds = Äänet -title.choose.incoming.sound = Saapuvan viestin merkkiääni -title.choose.outgoing.sound = Lähtevän viestin merkkiääni -title.choose.offline.sound = Poissaolon merkkiääni -title.edit.profile = Muokkaa profiilia -title.profile.information = Profiilin tiedot -title.profile.not.found = Profiilia ei löydy -title.view.profile.for = Profiili käyttäjälle {0} -title.lookup.profile = Profiilin tarkistus -title.add.search.service = Lisää hakupalvelu -title.person.search = Etsi henkilöä -title.login.settings = Kirjautumisasetukset -title.login = Kirjaudu -title.downloading.im.client = Lataa pikaviestiohjelma -title.upgrading.client = Ohjelman päivitys -title.cancelled = Peruutettu -title.new.version.available = Uusi versio saatavilla -title.new.client.available = Uusi asiakasohjelma saatavilla -title.password = Salasana -title.download.complete = Lataus valmistui -title.new.roster.group = Uusi tuttavalistan ryhmä -title.add.contact.group = Lisää uusi ryhmä -title.add.contact = Lisää uusi yhteystieto -title.file.transfer.preferences = Tiedostojen siirron asetukset -title.file.transfer = Tiedostojen siirrot -title.appearance = Ulkoasu -title.appearance.preferences = Tuunaus -title.login.error = Virhe kirjautuessa -title.no.updates = Ei päivityksiä -title.notes = Muistiinpanot -title.tasks = Tehtävät -title.password.required = Salasana vaaditaan -title.task.notification = Tehtäväilmoitus -title.client.logs = Työasemalogit -title.bookmarks = Kirjanmerkit -title.advanced.connection.usesso = Käytä kertakirjautumista (SSO) GSSAPI:n kautta -title.delete.file = Halutatko todella poistaa tiedoston? -title.error.couldnt.open.file = Tiedoston avaus ei onnistu -title.error.delete.file = Tiedoston poisto ei onnistu -title.error.find.app = Sovellusta ei löytynyt -title.error.rename.file = Tiedoston nimen muutos ei onnistu -title.file = Tiedosto -title.filesize = Koko -title.general.media = Media-asetukset -title.group.chat.settings = Ryhmäkeskusteluasetukset -title.gtalk.registration = GTalk tunnuksen tiedott -title.sametime.registration = Sametime tunnuksen tiedot -title.facebook.registration = Facebook tunnuksen tiedot -title.myspace.registration = MySpace tunnuksen tiedot -title.input.fileexplorer = Anna tiedostoselaimesi nimi: -title.input.newname = Anna uusI nimi\: -title.input.openwith = Anna käytettävän sovelluksen nimi: -title.xmpp.registration = XMPP tunnuksen tiedot -title.appearance.showVCards = Näytä &VCardit yhteystiedoissa -title.subscription.request = Lisäyspyyntö - -menuitem.contacts = Tuttavat -menuitem.actions = Toiminnot -menuitem.exit = Sulje -menuitem.plugins = &Liitännäiset -menuitem.logout.no.status = Kirjaudu ulos -menuitem.logout.with.status = Kirjaudu ulos ja aseta tila -menuitem.show.traffic = Näytä liikenne -menuitem.check.for.updates = Tarkista päivitykset? -menuitem.help = Ohjeet -menuitem.preferences = Asetukset -menuitem.about = Tietoja -menuitem.online.help = Online-tuki -menuitem.open = Avaa -menuitem.hide = Piilota -menuitem.status = Tila -menuitem.view.downloads = Näytä lataukset -menuitem.save = Tallenna -menuitem.add = Lisää -menuitem.add.contact = Lisää yhteystieto -menuitem.add.contact.group = Lisää yhteysryhmä -menuitem.remove.from.group = Poista ryhmästä -menuitem.start.a.chat = Aloita keskustelu -menuitem.rename = Nimeä uudelleen -menuitem.delete = Poista -menuitem.edit = Muokkaa -menuitem.remove.from.roster = Poista tuttavalistasta -menuitem.view.profile = Näytä profiili -menuitem.subscribe.to = Liity jäseneksi -menuitem.send.a.message = Viestin lähetys... -menuitem.show.empty.groups = Näytä tyhjät ryhmät -menuitem.send.a.file = Tiedostonsiirto -menuitem.view.last.activity = Näytä viimeisimmät aktiivisuustiedot -menuitem.unban = Poista porttikielto -menuitem.ban = Aseta porttikielto -menuitem.browse.service = Selaa palvelua -menuitem.remove.service = Poista palvelu -menuitem.join.room = Liity huoneeseen -menuitem.remove.bookmark = Poista kirjanmerkki -menuitem.join.on.startup = Liity käynnistyksen yhteydessä -menuitem.view.room.info = Näytä huoneen tiedot -menuitem.remove = Poista -menuitem.change.nickname = Vaihda lempinimeä -menuitem.block.user = Estä käyttäjä -menuitem.unblock.user = Pura esto käyttäjältä -menuitem.kick.user = Potkaise käyttäjä ulos -menuitem.voice = Puheoikeus -menuitem.revoke.voice = Mykistä käyttäjä -menuitem.grant.voice = Anna puheoikeus -menuitem.ban.user = Anna porttikielto käyttäjälle -menuitem.grant.moderator = Anna moderointioikeudet -menuitem.revoke.moderator = Poista moderointioikeudet -menuitem.invite.users = Kutsu käyttäjiä -menuitem.invite.group.to.conference = Kutsu ryhmäkeskusteluun -menuitem.start.a.conference = Aloita ryhmäkeskustelu... -menuitem.change.subject = Vaihda puheenaihetta -menuitem.destroy.room = Tuhoa huone -menuitem.set.status.message = Aseta tilaviesti... -menuitem.edit.status.message = Muokkaa tilaviestiä... -menuitem.broadcast.to.group = Kuuluta ryhmälle -menuitem.alert.when.online = Hälytä käyttäjän tullessa linjalle -menuitem.remove.alert.when.online = Poista hälytys -menuitem.save.as = Tallenna nimellä... -menuitem.view.client.version = Asiakasohjelman tiedot -menuitem.view.contact.history = Näytä yhteyshistoria -menuitem.edit.my.profile = &Muokkaa profiiliasi... -menuitem.lookup.profile = &Profiilin tarkastelu... -menuitem.add.as.contact = Lisää yhteystiedoksi -menuitem.chat = Keskustele -menuitem.sign.in = Liity -menuitem.sign.out = Poistu -menuitem.sign.in.at.login = Liity kirjautumisen yhteydessä -menuitem.enter.login.information = Syötä kirjautumistiedot -menuitem.delete.login.information = Poista kirjautumistiedot -menuitem.show.offline.group = Näytä poissaolevat tuttavat -menuitem.move.to = Siirrä kohteeseen -menuitem.copy.to = Kopioi kohteeseen -menuitem.user.guide = Käyttöopas -menuitem.languages = Valitse kieli -menuitem.dial = Soita -menuitem.view.logs = Näytä logit -menuitem.bookmarks = Kirjanmerkit -menuitem.add.groupchat.myname = Korosta &nimeni kun joku kirjottaa sen -menuitem.add.groupchat.mytext = &Korosta tekstini kun kirjoitan jotain -menuitem.add.groupchat.popname = Näytä &tiedotusikkuna-popup kun joku kirjoittaa nimeni -menuitem.add.groupchat.showjoinleavemessage = &Näytä liittymis- ja poistumisviestit -menuitem.add.groupchat.showrolesinsteadofstatus = Näytä keskusteluroolikuvakkeet tilakuvakkeiden sijaan -menuitem.always.on.top = Aina päällimmäisenä -menuitem.open.with = Käytä avaamiseen... -menuitem.block.contact = Estä henkilö -menuitem.unblock.contact = Pura henkilön esto -menuitem.show.offline.users = Näytä poissaolevat -menuitem.show.contact.statusmessage = Näytä tilaviesti -menuitem.bookmark.room = Kirjanmerkki huoneesta -menuitem.refresh = Päivitä -menuitem.create.room = Luo tai liity huoneeseen -menuitem.expand.all.groups = Laajenna kaikki ryhmät -menuitem.collapse.all.groups = Tiivistä kaikki ryhmät -menuitem.inivite.again = Kutsu uudelleen -menuitem.chatframe.option = Valinnat - -tree.conference.services = Keskustelupalvelut -tree.users.in.room = Huoneen keskustelijat - -tab.general = Yleinen -tab.proxy = Välityspalvelin -tab.contacts = Yhteystiedot -tab.installed.plugins = Asennetut lisäosat -tab.available.plugins = Saatavilla olevat lisäosat -tab.personal = Henkilökohtaiset -tab.business = Työ -tab.home = Koti -tab.avatar = Hahmo -tab.conferences = Ryhmäkeskustelut - -group.connection = Yhteys -group.conferences.found = Löytyneet ryhmäkeskustelut -group.comma.delimited = Pilkuin erotettu -group.general.information = Yleiset tiedot -group.chat.window.information = Keskusteluikkunan tiedot -group.notification.options = Huomautusten valinnat -group.search.form = Hakulomake -group.search.results = Hakutulokset -group.login.information = Kirjautumistiedot -group.empty = Tässä ryhmässä ei ole linjoilla olevia käyttäjiä. -group.offline = Poissa linjoilta -group.chat.name.notification = Nimesi on nähty... -group.chat.name.match = Nimesi on kirjoitettu ryhmäkeskustelussa: - -tooltip.place.a.call = Soita tälle henkilölle -tooltip.view.history = Näytä historiatiedot -tooltip.view.changelog = Näytä muutoshistoria -tooltip.view.readme = Näytä LueMinut tiedote -tooltip.notifications = Tiedoteasetukset saapuville keskusteluille. -tooltip.place.voice.call = Soita VOIP-puhelu. -tooltip.appearance = Vaihda keskusteluikkunoiden tyyliä. -tooltip.file.transfer = Tiedostonsiirron asetukset -tooltip.send.email = Lähetä sähköposti. -tooltip.start.chat = Aloita keskustelu. - - -########################################## -# # -# # -# Missing Translation: # -# # -# # -########################################## - - -label.na = n/a -label.apple.keychain = Apple KeyChain -tab.sso = SSO -tab.pki = PKI - -#!# \ No newline at end of file diff --git a/src/resources/i18n/spark_i18n_fr.properties b/src/resources/i18n/spark_i18n_fr.properties deleted file mode 100644 index 190fd293a..000000000 --- a/src/resources/i18n/spark_i18n_fr.properties +++ /dev/null @@ -1,864 +0,0 @@ -# French Translation by Ben LeBlond & Jonathan Pitre -# ben@jivesfotware.com - jakeld@gmail.com -# August 2011 - -# http://people.w3.org/rishida/tools/conversion/ -# \u00E0 = à -# \u00E2 = â -# \u00E7 = ç -# \u00E9 = é -# \u00E8 = è -# \u00EA = ê -# \u00F4 = ô -# \u00EE = î - -# Translation updated by Eric Ficheux -# May 2014 - -accept = Accepter -active = Actif -add = Ajouter -administrator = Administrateur -answer = R\u00E9pondre -apply = Appliquer -available = Disponible -broadcast = Diffuser un message a tout le monde -cancel = Annuler -close = Fermer -create = Cr\u00E9er -date = Date -description = Description -from = De -invite = Inviter -join = Rejoindre -message = Message -no = Non -not.registered = Non enregistr\u00E9 -occupants = Occupants -offline = D\u00E9connect\u00E9 -online = Connect\u00E9 -ok = OK -open = Ouvrir -open.folder = Ouvrir R\u00E9pertoire -participants = Participants -reject = Refuser -retry = R\u00E9essayer -room.name = Nom du Salon -save = Sauver -refresh = Refresh -subject = Sujet -unfiled = Non class\u00E9 -use.default = Utiliser les valeurs par d\u00E9faut -user.has.signed.in = s'est connect\u00E9. -user.has.signed.off = s'est d\u00E9connect\u00E9. -while.offline = Pendant que vous \u00EAtiez hors ligne -yes = Oui - -action.clear = Vider -action.copy = Copier -action.cut = Couper -action.paste = Coller -action.print = Imprimer -action.save = Sauver -action.select.all = Tout s\u00E9lectionner - -button.accept = &Accepter -button.add = &Ajouter -button.add.a.contact = &Ajouter un Contact -button.add.bookmark = &Ajouter un Signet -button.add.service = &Ajouter un Service -button.add.user = Ajouter un utilisateur -button.add2 = Ajouter -button.advanced = A&vanc\u00E9 -button.approve = &Approuver -button.bookmark.room = Salle de Discussion &Favorite -button.browse = &Parcourir -button.browse2 = P&arcourir -button.browse3 = Pa&rcourir -button.cancel = &Annuler -button.clear = &Effacer -button.close = &Fermer -button.copy.to.clipboard = Copier vers le presse-papier -button.create.account = &Cr\u00E9er un Compte -button.create.room = &Cr\u00E9er ou Joindre une Salle de Discussion -button.decline = &Refuser -button.deny = &Refuser -button.dial.number = &Composer Num\u00E9ro -button.find = &Rechercher -button.join = &Entrer -button.join.room = &Joindre la Salle de Discussion Selectionn\u00E9e -button.login = &Connexion -button.new = &Nouveau -button.profile = &Profil -button.quit = &Quitter -button.re.detect = &Re-d\u00E9tecter -button.reconnect = &Reconnecter -button.reconnect2 = &Reconnecter -button.refresh = &Actualiser -button.register = &S'enregistrer -button.reject = Refuser -button.remove.bookmark = Supprimer le Signet -button.roster = &Liste de Contacts -button.save = Sauver -button.save.for.future.use = &Sauvegarder pour plus tard -button.search = &Rechercher -button.send = Envoyer -button.send.email = Email -button.start.chat = Discuter -button.tasks.active = Actif -button.tasks.all = Tout -button.unset.file.explorer = D\u00E9selectionn\u00E9 le navigateur de fichier -button.update = &Mettre \u00E0 jour -button.view.notes = Voir les notes -bbutton.view.profile = Voir le profil complet -button.view.tasklist = Voir la liste des t\u00E2ches - -checkbox.allow.buzz = Autoriser les contacts \u00E0 vous interpeller -checkbox.auto.discover.port = &D\u00E9tecter automatiquement l'h\u00F4te et le port -checkbox.auto.login = &Login Automatique -checkbox.broadcast.dns.offline.user = Cacher les contacts d\u00E9connect\u00E9s -checkbox.disable.chat.history = &D\u00E9sactiver l'Historique de Conversation -checkbox.disable.prev.chat.history = &D\u00E9sactiver l'afichage des conversations pr\u00E9c\u00E9dentes dans le chat -checkbox.enable.emoticons = &Activer les smileys -checkbox.idle.enabled = &Mise en Veille Activ\u00E9e -checkbox.launch.on.startup = &Lancer au D\u00E9marrage -checkbox.notify.systemtray = Afficher les nouveaux &messages dans la barre d'\u00E9tat du systeme -checkbox.notify.typing.systemtray = &Affcher l'indicateur de frappe dans la barre d'\u00E9tat du systeme -checkbox.notify.user.comes.online = Me notifier quand un contact se &connecte -checkbox.notify.user.goes.offline = Me ¬ifier quand un contact se d\u00E9connecte -checkbox.permanent = Le salon est &permanent -checkbox.play.sound.on.invitation = Alerte sonore lors d'une &invitation -checkbox.play.sound.on.new.message = Alerte sonore lors d'un &nouveau message -checkbox.play.sound.on.outgoing.message = Alerte sonore lors de l'envoi d'un message -checkbox.play.sound.when.offline = Alerte sonore lorsqu'un utilisateur se &d\u00E9connecte -checkbox.private.room = Salon de Discussion Priv\u00E9 -checkbox.reconnect.panel.big = Afficher en tant que panneau -checkbox.reconnect.panel.icon = Afficher en tant qu'icône -checkbox.reconnect.panel.small = Afficher dans le groupe de contact -checkbox.reconnet.info = Indiquez le type d'affichage \u00E0 utiliser pour la reconnexion: -checkbox.save.password = &Enregistrer le Mot de Passe -checkbox.show.avatars.in.contactlist = Afficher les &avatars -checkbox.show.notifications.in.conference = &Afficher les Notifications en Conf\u00E9rence -checkbox.show.time.in.chat.window = &Afficher l'heure dans la fen\u00EAtre de conversation -checkbox.show.toaster = Afficher une notification &Popup -checkbox.split.chat.window = R\u00E9duire les &fen\u00EAtres (N\u00E9cessite de red\u00E9marrer Spark) -checkbox.start.in.tray = &D\u00E9marrer dans la zone d'iconification -checkbox.tabs.on.top = Fen\u00EAtre de discussion toujours visible (n\u00E9cessite de red\u00E9marrer) -checkbox.use.compression = Utiliser la compression -checkbox.use.debugger.on.startup = Lancer le d\u00E9bugger au d\u00E9marrage -checkbox.use.proxy.server = &Utiliser un Proxy -checkbox.use.system.look.and.feel = Utiliser l'ergonomie du syst\u00E8me (n\u00E9cessite de red\u00E9marrer) -checkbox.window.to.front = &Mettre la fen\u00EAtre en premier plan -checkbox.use.krbconf = Utilier krb5.conf ou krb5.ini -checkbox.use.krb.dns = Utilier le DNS -checkbox.use.specify.below = Indiquer ci-dessous -checkbox.use.pki.authentication = Utiliser l'authentification par PKI -checkbox.transport.tab.setting = Montrer les types de transports disponibles dans un onglet (red\u00E9marrage n\u00E9cessaire) -checkbox.conference.tab.setting = Montrer les services de conf\u00E9rence disponibles dans un onglet (red\u00E9marrage n\u00E9cessaire) - -delete.log.permanently = Effacer les logs d\u00E9finitivement -delete.permanently = Effacer d\u00E9finitivement? - -gateway.username.password.error = Identifiant et/ou mot de passe requis - -group.chat.name.match = Votre nom a \u00E9t\u00E9 prononc\u00E9 dans une conversation: -group.chat.name.notification = Quelqu'un parle de vous... -group.chat.window.information = Infos de la fen\u00EAtre de chat -group.comma.delimited = D\u00E9limit\u00E9 par virgule (CSV) -group.conferences.found = Services de conf\u00E9rence -group.connection = Connexion -group.empty = Il n'y a pas de contact connect\u00E9 dans ce groupe -group.general.information = Infos G\u00E9n\u00E9rales -group.login.information = Infos Login -group.notification.options = Options de Notification -group.offline = Contacts d\u00E9connect\u00E9s -group.search.form = Formulaire de Recherche -group.search.results = Resultats de Recherche - -label.accounts = &Comptes -label.add.conference.service = &Ajouter un Service de Conf\u00E9rence -label.add.jid = &Ajouter JID -label.add.task = Ajouter une t\u00E2che -label.auto.login = &Auto Login -label.audio.device = &P\u00E9riph\u00E9rique Audio -label.available.users.in.roster = &Contacts disponibles -label.cancel = Annuler -label.cell = Cell -label.change.password.to = &Changer le mot de passe -label.chatroom.fontsize = Taille de la &police de la fen\u00EAtre de discussion: -label.choose.file = Choisissez un fichier -label.city = &Ville -label.close = F&ermer -label.company = &Soci\u00E9t\u00E9 -label.confirm.password = &Confirmez le mot de passe -label.conflict.error = Impossible de vous connecter: vous \u00EAtes d\u00E9j\u00E0 connect\u00E9 -label.contact.to.find = Contact a Rechercher? -label.contactlist.avatarsize = Taille des avatars dans la liste de contacts: -label.contactlist.fontsize = Taille de la police de la liste des contacts: -label.country = P&ays -label.create.account = Cr\u00E9er un compte -label.department = D\u00E9partement -label.dial = &Num\u00E9roter -label.downloads = T\u00E9l\u00E9chargements -label.due = Pour le -label.email.address = &Adresse Email -label.emoticons = &Smileys -label.enter.address = Entrez l'Adresse -label.enter.group.name = Entrez un nouveau nom de groupe -label.enter.password = Entrez le mot de passe -label.fax = &Fax -label.find = &Rechercher -label.first.name = &Pr\u00E9nom -label.frequent.contacts = Frequent Contacts -label.group = &Groupe -label.home = Maison -label.host = &H\u00F4te -label.invited.users = Utilisateurs Invit\u00E9s -label.jabber.address = &Adresse Jabber -label.jabber.id = &Jabber ID -label.jid = &JID -label.job.title = &Fonction -label.keystore.location = Keystore location -label.krb.kdc = KDC -label.krb.realm = Realm -label.last.name = &Nom de famille -label.local.time = &Heure Locale -label.message = &Message -label.message.style = Style du message -label.middle.name = &Deuxi\u00E8me pr\u00E9nom -label.minutes.before.stale.chat = &Nombre de minutes avant qu'un salon de discussion inactif soit suspendu -label.mobile = &Mobile -label.move.focus.backwards = D\u00E9placer le focus vers l'arri\u00E8re -label.move.focus.forwards = D\u00E9placer le focus vers l'avant -label.na = sans objet -label.name = &Nom -label.network = R\u00E9seau -label.new.nickname = Nouveau Pseudo -label.nickname = &Pseudo -label.number = &Num\u00E9ro -label.ok = OK -label.old.ssl = &Utiliser l'ancienne m\u00E9thode SSL -label.os = &Syst\u00E8me d'exploitation -label.pager = &Pager -label.password = &Mot de Passe -label.passwordreset = R\u00E9initialiser le mot de passe -label.phone = &T\u00E9l\u00E9phone -label.pkcs.library.file = PKCS#11 library file -label.port = &Port -label.postal.code = &Code Postal -label.presence = &Pr\u00E9sence -label.priority = P&riorit\u00E9 -label.protocol = &Protocole -label.received = Recu -label.recent.conversation = Conversations r\u00E9centes -label.rename.to = &Renommer -label.resource = &Resource -label.response.timeout = &Temps maximal de r\u00E9ponse (sec) -label.room = &Salon -label.room.name = &Nom du Salon -label.room.topic = &Th\u00E8me -label.search.service = &Service de Recherche -label.server = &Serveur -label.server.address = &Adresse du Serveur -label.show = Montrer: -label.software = &Logiciel -label.state.and.province = Etat ou Province -label.street.address = &Adresse Postale -label.time = Heure\: (0) -label.time.till.idle = &Temps maximum avant mise en veille (min) -label.time.till.idlemessage = Message d'absence automatique -label.timeformat = Utilise {0} -label.transfer.download.directory = &R\u00E9pertoire de T\u00E9l\u00E9chargement -label.transfer.timeout = &Temps d'attente maximal pour un transfert de fichier (min)\: -label.trust.store.password = Trust store password -label.truststore.location = Truststore location -label.unable.to.add.contact = Impossible d'ajouter le contact -label.use.default = Utiliser les valeurs par d\u00E9faut -label.user.on.public.network = L'utilisateur est sur un r\u00E9seau public -label.username = &Nom d'utilisateur -label.version = &Version -label.video.device = &P\u00E9riph\u00E9rique Vid\u00E9o -label.web.page = &Site Web -label.which.pki.method = Quel type de PKI? -label.work = Travail -label.x509.certificate = Certificat X.509 -label.xmpp.port = &Port XMPP - -lookandfeel.change.now = Changer maintenant -lookandfeel.color.blue = Bleu -lookandfeel.color.green = Vert -lookandfeel.color.label = Couleurs -lookandfeel.color.opacity = Opacit\u00E9 -lookandfeel.color.red = Rouge -lookandfeel.color.saved = Couleur enregistr\u00E9e -lookandfeel.select = Choisir l'apparence -lookandfeel.tooltip.restart.no = Red\u00E9marrage non n\u00E9cessaire -lookandfeel.tooltip.restart.yes = Pour choisir une apparence, cliquer sur sauver et red\u00E9marrer Spark. - -menuitem.about = A propos -menuitem.actions = Actions -menuitem.add = Ajouter -menuitem.add.as.contact = Ajouter en tant que Contact -menuitem.add.contact = Ajouter Contact -menuitem.add.contact.group = Ajouter Groupe de Contact -menuitem.add.groupchat.auto.accept.invite = &Accepter automatiquement les invitations \u00E0 une discussion de groupe -menuitem.add.groupchat.myname = Mettre mon &nom en \u00E9vidence quand quelqu'un me cite -menuitem.add.groupchat.mytext = Mettre en \u00E9vidence le texte que j'\u00E9cris -menuitem.add.groupchat.popname = Afficher un &popup quand quelqu'un cite mon nom -menuitem.add.groupchat.random.colors = Couleurs al\u00E9atoires pour les noms -menuitem.add.groupchat.showjoinleavemessage = &Afficher les messages d'arriv\u00E9e et de d\u00E9part -menuitem.add.groupchat.showrolesinsteadofstatus = Afficher les ic\u00F4nes de r\u00F4le \u00E0 la place des ic\u00F4nes de statut -menuitem.affiliation = Affiliation -menuitem.alert.when.online = Notifier lorsque l'utilisateur est disponible -menuitem.always.on.top = Toujours visible -menuitem.ban = Bannir -menuitem.ban.user = Bannir l'utilisateur -menuitem.block.contact = Bloquer un contact -menuitem.block.user = Bloquer l'utilisateur -menuitem.bookmark.room = Ajouter le salon dans les marques pages -menuitem.bookmarks = Marques-pages -menuitem.broadcast.to.group = Envoyer un message \u00E0 tout le groupe -menuitem.browse.service = Voir les Services -menuitem.change.nickname = Changer de Nickname -menuitem.change.subject = Changer le Sujet -menuitem.chat = Conversation -menuitem.chatframe.option = Options -menuitem.check.for.updates = Mettre \u00E0 jour -menuitem.collapse.all.groups = R\u00E9duire tous les groupes -menuitem.contacts = Contacts -menuitem.copy.to = Copier vers -menuitem.create.room = Cr\u00E9er ou rejoindre un salon -menuitem.delete = Effacer -menuitem.delete.login.information = Supprimer les informations d'identification -menuitem.destroy.room = Fermer le Salon -menuitem.dial = Composer -menuitem.edit = Editer -menuitem.edit.my.profile = &Editer mon Profil -menuitem.edit.status.message = Editer les messages personalis\u00E9s... -menuitem.enter.login.information = Entre les informations d'identification -menuitem.exit = Sortir -menuitem.expand.all.groups = Afficher le contenu de tous les groupes -menuitem.grant.admin = Rendre admin -menuitem.grant.member = Rendre membre -menuitem.grant.owner = Rendre propri\u00E8taire -menuitem.grant.moderator = Rendre Mod\u00E9rateur -menuitem.grant.voice = Voice -menuitem.help = Aide -menuitem.hide = Cacher -menuitem.inivite.again = Inviter de nouveau -menuitem.invite.group.to.conference = Inviter le groupe \u00E0 cette conf\u00E9rence -menuitem.invite.users = Inviter Utilisateurs -menuitem.join.on.startup = Rejoindre au D\u00E9marrage -menuitem.join.room = Rejoindre le Salon -menuitem.kick.user = Kicker l'Utilisateur -menuitem.languages = Langages -menuitem.logout.no.status = Fermer cette Session -menuitem.logout.with.status = Fermer cette Session avec un message -menuitem.lookup.profile = &Rechercher le Profil -menuitem.move.to = D\u00E9placer vers -menuitem.online.help = Aide en Ligne -menuitem.open = Ouvrir -menuitem.open.with = Ouvrir avec... -menuitem.plugins = &Plugins -menuitem.preferences = Pr\u00E9f\u00E9rences -menuitem.refresh = Rafraichir -menuitem.remove = Enlever -menuitem.remove.alert.when.online = Enlever l'Alerte -menuitem.remove.bookmark = Retirer de mes Favoris -menuitem.remove.from.group = Supprimer le Groupe -menuitem.remove.from.roster = Retirer des Contacts -menuitem.remove.service = Enlever le Service -menuitem.rename = Renommer -menuitem.revoke.admin = R\u00E9voquer les droits admin -menuitem.revoke.member = R\u00E9voquer les droits de membre -menuitem.revoke.moderator = R\u00E9voquer les droits de Mod\u00E9rateur -menuitem.revoke.owner = R\u00E9voquer les droits propri\u00E9taire -menuitem.revoke.voice = R\u00E9voquer les droits de Voice -menuitem.save = Enregistrer -menuitem.save.as = Enregistrer sous... -menuitem.send.a.file = Envoyer un Fichier -menuitem.send.a.message = Envoyer un Message... -menuitem.set.status.message = Message d'\u00E9tat -menuitem.show.contact.statusmessage = Afficher un message d'\u00E9tat -menuitem.show.empty.groups = Montrer les Groupes Vides -menuitem.show.offline.group = Regrouper les contacts non connect\u00E9s -menuitem.show.offline.users = Montrer les contacts non connect\u00E9s -menuitem.show.traffic = Montrer la Fen\u00EAtre de Traffic -menuitem.sign.in = Se connecter -menuitem.sign.in.at.login = Se connecter apr\u00E8s l'identification -menuitem.sign.out = Se d\u00E9connecter -menuitem.start.a.chat = Commencer une Conversation -menuitem.start.a.conference = Commencer une Conf\u00E9rence -menuitem.status = Etat -menuitem.subscribe.to = Souscrire \u00E0 -menuitem.unban = D\u00E9bannir -menuitem.unblock.contact = D\u00E9bloquer un contact -menuitem.unblock.user = D\u00E9bloquer l'Utilisateur -menuitem.user.guide = Guide d'utilisation -menuitem.view.client.version = Voir Version du Client -menuitem.view.contact.history = Voir l'Historique de ce Contact -menuitem.view.downloads = Voir les T\u00E9l\u00E9chargements -menuitem.view.last.activity = Voir la derni\u00E8re activit\u00E9 -menuitem.view.logs = Consulter les logs -menuitem.view.profile = Voir Profil -menuitem.view.room.info = Voir les Infos du Salon -menuitem.voice = Voice - -message = Message -message.account.create = Cr\u00E9er un nouveau compte. -message.account.created = Le nouveau compte a \u00E9t\u00E9 cr\u00E9e. -message.account.error = Sp\u00E9cifiez le serveur sur lequel cr\u00E9er le compte. -message.add.a.contact = Ajouter un contact. -message.add.conference.service = Ajouter un Service de Conf\u00E9rence -message.add.contact.to.list = Ajouter l'utilisateur a mes Contacts -message.add.favorite.room = Ajouter \u00E0 mes salon favoris ou rejoindre directement. -message.add.this.user.to.your.roster = Ajouter cet utilisateur a mes Contacts. -message.add.to.roster = Ajouter aux Contacts -message.add.user = Ajouter cet utilisateur a vos Contacts? -message.alert.notify = Notification d'alerte -message.already.exists = Un compte existe d\u00E9ja avec ce nom d'utilisateur. Veuillez r\u00E9essayer. -message.approve.subscription = Permettre \u00E0 {0} de vous ajouter a ses Contacts? -message.autenticating = V\u00E9rification en cours -message.away.idle = Pas l\u00E0... (mise en veille) -message.bookmark.temporary.room.error = Impossible d'ajouter un Salon Temporaire \u00E0 vos favoris. -message.broadcast.from = Message group\u00E9 de {0} -message.broadcast.message.sent = Le message group\u00E9 a \u00E9t\u00E9 envoy\u00E9. -message.broadcast.no.text = SVP entrez le texte \u00E0 diffuser -message.broadcast.no.user.selected = SVP s\u00E9lectionner au moins un destinataire -message.broadcast.to = Entrez le message group\u00E9 \u00E1 {0} -message.broadcasted.to = Le message group\u00E9 a \u00E9t\u00E9 envoy\u00E9 aux utilisateurs suivants\: \n{0} -message.buzz.alert.notification = Solliciter l'attention -message.buzz.message = {0} veut votre attention -message.buzz.sent = La notification d'alerte a bien \u00E9t\u00E9 envoy\u00E9e \u00E0 l'utilisateur -message.calling = Appel de {0} en cours -message.came.online = {0} s'est connect\u00E9 \u00E0 {1} -message.cannot.add.contact.to.shared.group = Impossible d'ajouter de nouveaux contacts \u00E0 un Groupe Partag\u00E9. -message.chat.session.ended = Session de chat termin\u00E9e \u00E0 {0} -message.click.to.open = Cliquez pour ouvrir -message.client.information = Infos client de {0} -message.close.other.chats = Fermer les autres chats -message.close.stale.chats = Fermer les chats suspendus -message.close.this.chat = Fermer ce chat -message.conference.info.error = Impossible d'obtenir des infos sur cette conf\u00E9rence. Veuillez r\u00E9essayer plus tard. -message.conference.service.error = Service de conf\u00E9rence introuvable. -message.confirm.destruction.of.room = Supprimer le salon en enl\u00E8ve aussi tous ses utilisateurs. Continuer? -message.confirmation.password.error = Confirmez le mot de passe. -message.connecting.please.wait = Connexion en cours. Veuillez patienter... -message.connection.failed = Connexion \u00E0 {0} a \u00E9chou\u00E9e. -message.create.account = Le compte n'a pas pu \u00EAtre cr\u00E9e. -message.create.or.join.room = Cr\u00E9er ou rejoindre un salon -message.current.status = Permettre aux autres de voir votre \u00E9tat ou activit\u00E9. -message.default.error = Une Erreur a \u00E9t\u00E9 d\u00E9tect\u00E9e. Veuillez la transmettre https://community.igniterealtime.org, s'il vous plait. -message.delete.all.history = Effacer toutes les anciennes conversations? -message.delete.confirmation = Etes vous sur de vouloir effacer {0}? -message.disable.transport = Voulez-vous d\u00E9sactiver un transport d\u00E9ja actif? -message.disconnected.conflict.error = Votre connexion a \u00E9t\u00E9 ferm\u00E9e car un autre utilisateur du m\u00EAme nom s'est logg\u00E9 depuis un autre endroit. -message.disconnected.error = Votre connexion a \u00E9t\u00E9 ferm\u00E9e \u00E0 cause d'une erreur. -message.disconnected.group.chat.error = Vous avez \u00E9t\u00E9 d\u00E9connect\u00E9 suite \u00E0 une erreur, vous devrez entrer de nouveau dans ce salon de discussion apr\u00E8s vous \u00EAtre reconnect\u00E9 -message.disconnected.shutdown = Vous avez \u00E9t\u00E9 d\u00E9connect\u00E9 car le serveur vient de s'arr\u00EAter -message.downloading = T\u00E9l\u00E9chargement de {0} en cours -message.downloading.spark.plug = T\u00E9l\u00E9chargement du Spark-Plug -message.end.chat = Voulez-vous en finir avec ce chat? -message.end.conversation = Voulez-vous en finir avec cette session? -message.enter.aim = Entrez votre nom d'utilisateur et mot de passe AIM. -message.enter.broadcast.message = Entrez le message group\u00E9 \u00E0 envoyer aux utilisateurs selectionn\u00E9s. -message.enter.facebook = Indiquez votre identifiant et mot de passe Facebook ci-dessous -message.enter.gadugadu = Indiquez votre identifiant et mot de passe GaduGadu ci-dessous -message.enter.gtalk = Indiquez votre identifiant et mot de passe GTalk ci-dessous -message.enter.icq = Entrez votre nom d'utilisateur ICQ et votre mot de passe. -message.enter.irc = Indiquez votre identifiant et mot de passe IRC ci-dessous -message.enter.jabber.id = Entrez votre Jabber ID -message.enter.message.to.broadcast = Entrez le message group\u00E9 qui sera envoy\u00E9 \u00E0 tous vos Contacts. -message.enter.msn = Entrez votre nom d'utilisateur et mot de passe MSN. -message.enter.myspace = Indiquez votre identifiant et mot de passe MySpace ci-dessous -message.enter.new.subject = Entrez un nouveau sujet -message.enter.qq = Indiquez votre identifiant et mot de passe QQ ci-dessous -message.enter.room.password = Entrez le mot de passe du salon -message.enter.sametime = Indiquez votre identifiant et mot de passe Sametime ci-dessous -message.enter.simple = Indiquez votre identifiant et mot de passe SIMPLE ci-dessous -message.enter.valid.jid = Entrez un JID valide -message.enter.xmpp = Indiquez votre identifiant et mot de passe XMPP ci-dessous -message.enter.yahoo = Entrez votre nom d'utilisateur et mot de passe Yahoo. -message.error.during.file.transfer = Erreur s'est produite durant le transfert de fichier. -message.file.exists.question = Le fichier existe d\u00E9j\u00E0. Ecrire par dessus? -message.file.size = Taille du Fichier\: {0} -message.file.transfer.canceled = Vous avez annul\u00E9 le transfert du fichier. -message.file.transfer.chat.window = Demande de transfert de fichier: -message.file.transfer.file.too.big.error = Le fichier s\u00E9lectionn\u00E9 est trop gros.\nLa taille maximale est {0} le fichier s\u00E9lectionn\u00E9 est de {1} -message.file.transfer.file.too.big.warning = Le fichier s\u00E9lectionn\u00E9 est trop gros.\nProc\u00E9der malgr\u00E9 tout? -message.file.transfer.notification = Notification de transfert de fichier -message.file.transfer.rejected = Le fichier n'a pas \u00E9t\u00E9 accept\u00E9 par {0}. -message.file.transfer.short.message = vous envoie un fichier appel\u00E9\: -message.find.conference.services = Rechercher les Services de Conf\u00E9rence -message.forbidden.error = Une erreur de type inconnu \u00E0 \u00E9t\u00E9 re\u00E7ue du serveur. -message.gateway.nickname.error = Veuillez indiquer un pseudo -message.gateway.password.error = Veuillez indiquer un mot de passe -message.gateway.username.error = Veuillez indiquer un identifiant -message.general.error = Vous avez perdu votre connexion au serveur \u00E0 cause de {0}. -message.generic.reconnect.message = Vous avez perdu votre connexion au serveur. Cliquez sur le bouton ci-dessous pour vous reconnecter. -message.groupchat.registered.member = Enregistrement r\u00E9ussi avec {0} -message.groupchat.require.password = Cette salle de conf\u00E9rence n\u00E9cessite un mot de passe -message.idle.for = Mise en veille de {0} -message.image.too.large = La taille de cette image est trop grosse. Veuillez utiliser une image de 16k ou moins. -message.invalid.jabber.id = Jabber ID invalide -message.invalid.jid.error = Le JID utilis\u00E9 est invalide. -message.invalid.status = Veuillez entrer un message d'\u00E9tat valide. -message.invalid.username.password = Identifiant ou mot de passe invalide -message.invite.to.groupchat = {0} vous invite \u00E0 rejoindre une discussion de groupe -message.invite.users.to.conference = Inviter ces utilisateurs dans une salle de conf\u00E9rence. -message.is.shared.group = {0} est un groupe partag\u00E9. -message.is.typing.a.message = {0} tappe son message... -message.join.conference.room = Rejoindre la Salle de Conf\u00E9rence -message.kicked.error = Vous n'avez pas le droit de kicker {0}. -message.last.message.received = Dernier message re\u00E7u \u00E0 {0} -message.loading.please.wait = Chargement en cours. Veuillez patienter... -message.locked.workstation = L'utilisateur a verrouill\u00E9 sa station de travail. -message.name.of.group = Nom du Groupe -message.name.of.search.service.question = Nom du Service de Recherche? -message.negotiate.file.transfer = N\u00E9gociation du transfert de fichier en cours. Veuillez patienter... -message.negotiate.stream = N\u00E9gociation du transfert. Veuillez patienter... -message.negotiation.file.transfer = N\u00E9gociation du transfert de fichier avec {0}. Veuillez patienter... -message.new.message = Nouveau message de {0}. -message.new.spark.available = {0} est disponible. Souhaitez-vous l'installer? -message.nickname.in.use = Ce nickname est d\u00E9j\u00E0 utilis\u00E9. Veuillez en choisir un autre. -message.nickname.not.acceptable = Vous n'\u00EAtes pas autoris\u00E9 \u00E0 modifier votre pseudo! -message.no.avatar.found = Aucun avatar n'a \u00E9t\u00E9 configur\u00E9 par l'utilisateur. -message.no.caller.id = Aucune info d'appel disponible. -message.no.description.available = Aucune description disponible. -message.no.history.found = Il n'y a pas d'historique de conversation pour cet utilisateur. -message.no.results.found = Aucun r\u00E9sultat n'a \u00E9t\u00E9 donn\u00E9 par le serveur. -message.no.room.to.join.error = Pas de salons. -message.no.subject.available = Aucun sujet disponible -message.no.updates = Il n'y a pas de mises \u00E0 jour disponibles -message.normal = Message normal -message.number.to.call = Indiquez le num\u00E9ro \u00E0 composer -message.offline = L'utilisateur est d\u00E9connect\u00E9 et ne recevra ce message qu' \u00E0 sa prochaine connexion. -message.offline.error = L'utilisateur ne recevra h\u00E9las aucun message tant qu'il est d\u00E9connect\u00E9. -message.participants.in.room = Participants du Salon -message.password.error = Veuillez entrer un mot de passe pour ce compte. -message.password.private.room.error = Veuillez entrer un mot de pass pour ce salon priv\u00E9 -message.passwords.no.match = Les mots de passes ne correspondent pas. -message.please.join.in.conference = Rejoins-moi dans cette conf\u00E9rence. Merci. -message.plugins.not.available = Le d\u00E9p\u00F4t de plugins n'a pas pu \u00EAtre contact\u00E9. -message.prompt.plugin.uninstall = Souhaitez-vous d\u00E9sinstaller {0}? -message.received.file = Vous avez re\u00E7u un fichier de {0}. -message.receiving.file = Vous \u00EAtes en train de recevoir un ficher de {0} -message.reconnect.attempting = Essai... -message.reconnect.failed = Echecc de la reconnexion -message.reconnect.wait = Reconnexion dans {0} secondes -message.register.transports = S'enregistrer avec ces transports. -message.registering = Enregistrement avec {0} en cours. Veuillez patienter... -message.registration.transport.failed = Impossible de s'enregistrer avec ce Transport. -message.restart.required = Vous devez red\u00E9marrer Spark pour que ces changements soient effectifs. Voulez-vous red\u00E9marer maintenant? -message.restart.spark = Vous devrez red\u00E9marrer votre client pour installer cette nouvelle version. Voulez vous le faire tout de suite? -message.restart.spark.changes = Ce Plugin sera \u00E9limin\u00E9 lors du prochain red\u00E9marrage de Spark. -message.restart.spark.to.install = Vous devez \u00E9teindre votre client afin d'installer la derniere version. Souhaitez-vous faire cela tout de suite? -message.room.creation.error = La salle n'a pas pu \u00EAtre cr\u00E9\u00E9e -message.room.destroyed = Ce salon a \u00E9t\u00E9 detruit\: {0} -message.room.destruction.reason = Raison pour laquelle vous souhaitez d\u00E9truire ce salon? -message.room.information.for = Infos du Salon pour {0} -message.save.profile = Pour enregistrer votre profil, cliquez sur Sauver. -message.search.for.contacts = Recherche de Contacts. -message.search.for.history = Rechercher dans l'historique des conversations -message.search.for.other.people = Rechercher les utilisateurs de ce m\u00EAme serveur. -message.search.input.short = SVP fournir au moins cinq lettres. -message.search.service.not.available = Service de Recherche hors service. -message.searching.please.wait = Recherche en cours, veuillez patienter... -message.select.add.room.to.add = Veuillez \u00E9lectionner un salon a ajouter \u00E0 vos favoris. -message.select.one.or.more = S\u00E9lectionnez un ou plusieurs utilisateurs parmis vos Contacts. -message.select.room.to.enter = Indiquez le salon que vous souhaitez rejoindre. -message.select.room.to.join = Indiquez le salon que vous souhaitez rejoindre. -message.send.a.broadcast = Envoyez un message group\u00E9 -message.send.file.to.user = Envoyer des fichiers a cet utilisateur. -message.send.picture = Envoyez un screenshot. -message.send.to.these.people = Envoyer \u00E0 ces personnes -message.sending.file.to = Envoyer le fichier \u00E0 {0}. -message.sent.offline.files = On vous a envoy\u00E9 un/des fichier(s) offline. -message.server.unavailable = Connexion au serveur impossible: nom de serveur incorrect ou le serveur est hors ligne -message.service.already.exists = Ce service fait d\u00E9j\u00E0 partie de vos services. -message.shared.group = Groupe Partag\u00E9 -message.spark.secure = Spark tourne en mode s\u00E9curis\u00E9. -message.specify.contact.jid = Veuillez sp\u00E9cifier le JID du contact (ex. ddman@jabber.org) -message.specify.group = Indiquez le groupe auquel ajouter ce nouvel utilisateur. -message.specify.information.for.conference = Veuillez indiquer les infos de la conf\u00E9rence. -message.specify.name.error = Indiquez un nom valide. -message.specify.users.to.join.conference = Indiquez les utilisateurs autoris\u00E9s a rejoindre la conf\u00E9rence. -message.specify.valid.time.error = Veuillez indiquer un timeout et un port valide. -message.subject.change.error = Vous ne pouvez pas changer le sujet de ce salon. -message.subject.has.been.changed.to = Le sujet a \u00E9t\u00E9 chang\u00E9\: {0}. -message.supply.resource = Indiquez une resource valide. -message.supply.valid.port = Indiquez un port valide. -message.supply.valid.timeout = Indiquez une valeur de timeout valide -message.timeout.error = Le temps limite doit \u00EAtre d'au moins 5 secondes ou plus. -message.total.downloaded = Total T\u00E9l\u00E9charg\u00E9 -message.transfer.cancelled = Ce transfer a \u00E9t\u00E9 annul\u00E9. -message.transfer.complete = Le transfert de fichier a \u00E9t\u00E9 compl\u00E9t\u00E9 ({0}) -message.transfer.progressbar.text.received = {0} received @ {1} {2} -message.transfer.progressbar.text.sent = {0} sent @ {1} {2} -message.transfer.rate = Taux de Transfert -message.transfer.refused = Ce transfert de fichier a \u00E9t\u00E9 refus\u00E9. -message.transfer.waiting.on.user = En attente de {0} pour qu'il/elle accepte le tranfert. -message.unable.to.load.profile = Aucun profil trouv\u00E9 pour {0} -message.unable.to.retrieve.last.activity = Impossible de d\u00E9terminer la derni\u00E8re activit\u00E9 de {0} -message.unable.to.save.password = Impossible de changer le mot de passe. Veuillez contacter votre administrateur syst\u00E8me. -message.unable.to.send.file = Le transfert a {0} a \u00E9chou\u00E9. -message.unrecoverable.error = Identifiant ou mot de passe incorrect -message.update.room.list = Mise \u00E0 Jour de la liste de salons -message.updating.cancelled = Mise \u00E0 Jour annul\u00E9e. -message.user.banned = {0} a \u00E9t\u00E9 banni de ce salon. -message.user.given.voice = {0} a \u00E9t\u00E9 donn\u00E9 le droit voice dans ce salon. -message.user.granted.admin = {0} a \u00E9t\u00E9 donn\u00E9 les droits d'Administrateur. -message.user.granted.membership = {0} a \u00E9t\u00E9 donn\u00E9 les droits de membre. -message.user.granted.moderator = {0} a \u00E9t\u00E9 donn\u00E9 les droits de mod\u00E9rateur. -message.user.granted.owner = {0} a \u00E9t\u00E9 donn\u00E9 les droits de propri\u00E9taire. -message.user.is.sending.you.a.file = {0} vous envoie un fichier. -message.user.joined.room = {0} a rejoint le salon. -message.user.kicked.from.room = {0} a \u00E9t\u00E9 kick\u00E9 du salon. -message.user.left.room = {0} a quitt\u00E9 le salon. -message.user.nickname.changed = {0} est maintenant sous le nom {1}. -message.user.now.available.to.chat = {0} est connect\u00E9 \u00E0\u00A0{1} -message.user.revoked.admin = Les droits d'Administrateurs ont \u00E9t\u00E9 r\u00E9voqu\u00E9s de {0}. -message.user.revoked.membership = Les droits de membre ont \u00E9t\u00E9 r\u00E9voqu\u00E9s pour {0}. -message.user.revoked.moderator = Les droits de mod\u00E9rateur ont \u00E9t\u00E9 revoqu\u00E9s pour {0}. -message.user.revoked.owner = Les droits de propri\u00E9taire ont \u00E9t\u00E9 r\u00E9voqu\u00E9s pour {0}. -message.user.voice.revoked = Le droit Voice a \u00E9t\u00E9 r\u00E9voqu\u00E9 pour {0} -message.username.error = Indiquez un nom d'utilisateur pour le compte. -message.username.password.error = Le nom d'utilisateur et/ou mot de passe doit etre indique. -message.vcard.not.supported = Le Serveur n'est pas en mesure de supporter les VCards. Sauvegarde de votre VCard impossible. -message.version = Version\: {0} -message.view.information.about.this.user = Voir les information \u00E0 propos de cet utilisateur -message.waiting.for.user.to.join = En attente de {0} -message.went.offline = {0} s'est d\u00E9connect\u00E9 \u00E0 {1} -message.you.have.been.banned = Vous avez \u00E9t\u00E9 banni de ce salon -message.you.have.been.kicked = Vous avez \u00E9t\u00E9 kick\u00E9 de ce salon -message.you.have.sent = Vous avez envoy\u00E9 un fichier \u00E0 {0} -message.your.admin.granted = Vous avez re\u00E7u les droits d'Administrateur -message.your.banned = Vous avez \u00E9t\u00E9 banni de ce salon -message.your.kicked = Vous avez \u00E9t\u00E9 kick\u00E9 par {0} -message.your.membership.granted = Vous avez re\u00E7u les droits de membre. -message.your.membership.revoked = Vos droits de membre ont \u00E9t\u00E9 r\u00E9voqu\u00E9s -message.your.moderator.granted = Vous avez re\u00E7u les droits de mod\u00E9rateur. -message.your.moderator.revoked = Vos droits de mod\u00E9rateur ont \u00E9t\u00E9 r\u00E9voqu\u00E9s -message.your.ownership.granted = Vous avez re\u00E7u les droits de propri\u00E9taire. -message.your.ownership.revoked = Vos droits de propri\u00E9taire ont \u00E9t\u00E9 r\u00E9voqu\u00E9s. -message.your.revoked.granted = Vos droits d'Administrateur ont \u00E9t\u00E9 r\u00E9voqu\u00E9s. -message.your.voice.granted = Vous avez la parole dans cette discussion -message.your.voice.revoked = Vos droits Voice ont \u00E9t\u00E9 r\u00E9voqu\u00E9s. - -##Settings for the privacy plugin -pricacy.tooltip.preferences = Param\u00E8tres de confidentialit\u00E9 -privacy.border.block = Bloquer -privacy.border.information = Informations -privacy.button.no.list.selected = Pas de liste s\u00E9l\u00E9ctionn\u00E9e -privacy.dialog.add.list = Veuillez saisir le nom de famille -privacy.dialog.rem.list = Voulez-vous vraiment enlever {0}? -privacy.label.information = Utilisez le menu du clic droit pour ajouter ou supprimer des listes et \u00E9l\u00E9ments -privacy.label.iq.desc = Rechercher -privacy.label.list.is.active = Liste active en ce moment: -privacy.label.list.is.default = Liste par d\u00E9faut: -privacy.label.msg.desc = Messages -privacy.label.not.supported = Les r\u00E9glages vie priv\u00E9e ne sont pas possibles sur le serveur -privacy.label.pin.desc = Notifications de connexion -privacy.label.pout.desc = Notifications de d\u00E9connexion -privacy.label.preferences = Plugin vie priv\u00E9e -privacy.menu.activate.list = Activer -privacy.menu.add.contacts = Ajouter des Contacts \u00E0 la liste -privacy.menu.add.groups = Ajouter des Groupes \u00E0 la liste -privacy.menu.add.list = Ajouter une liste -privacy.menu.add.rem.items = Retirer {0} \u00E9l\u00E9ments de la liste -privacy.menu.default.list = Choisir par d\u00E9faut -privacy.menu.remove = Retirer -privacy.menu.remove.list = Supprimer une liste -privacy.menuitem.deactivate.current.list = D\u00E9sactiver {0} -privacy.name.for.default.list = Par d\u00E9faut -privacy.node.contacts = Contacts -privacy.node.groups = Groupes -privacy.pick.one.or.more = Choisir un ou plusieurs \u00E9l\u00E9ments \u00E0 ajouter \u00E0 la liste -privacy.root.node = Listes d'autorisations -privacy.status.menu.entry = Liste de r\u00E9glages vie priv\u00E9e -privacy.title.add.picker = Ajouter \u00E0 la liste -privacy.title.panel = Utilisez le bouton droit de la souris SVP -privacy.title.preferences = Plugin vie priv\u00E9e -privacy.tooltip.preferences = R\u00E9glages vie priv\u00E9e - -status.away = Absent -status.custom.messages = Messages personnalis\u00E9s -status.do.not.disturb = Ne pas d\u00E9ranger -status.extended.away = Absence prolong\u00E9e -status.free.to.chat = Disponible -status.on.phone = Au t\u00E9l\u00E9phone -status.online = Connect\u00E9 -status.pending = En attente - -##Stunfallback in media settings -stun.border.label = Serveur de redondance STUN -stun.server.addr = Serveur Stun: -stun.server.port = Port Stun: - -tab.available.plugins = Plugins Disponibles -tab.avatar = Avatar -tab.business = Business -tab.conferences = Conf\u00E9rences -tab.contacts = Contacts -tab.deactivated.plugins = Plugins d\u00E9sactiv\u00E9s -tab.general = G\u00E9n\u00E9ral -tab.home = Home -tab.installed.plugins = Plugins Install\u00E9s -tab.personal = Personnel -tab.pki = PKI -tab.proxy = Proxy -tab.sso = SSO - -title.about = A propos -title.account.create.registration = Cr\u00E9ation des Comptes -title.account.created = Compte Cr\u00E9e -title.add.contact = Ajouter Contact -title.add.contact.group = Ajouter Groupe -title.add.new.group = Ajouter Nouveau Groupe -title.add.search.service = Ajouter Service de Recherche -title.add.to.roster = Ajouter aux Contacts -title.address = Adresse -title.advanced.connection.preferences = Pr\u00E9f\u00E9rences de Connexion Avanc\u00E9es -title.advanced.connection.sso = Utiliser le Single Sign-On (SSO) -title.advanced.connection.sso.account = Ceci utilisera le compte du bureau pour "{0}" \u00E0 connecter au serveur. -title.advanced.connection.sso.noprincipal = Spark est incapable de trouver le principal \u00E0 utiliser pour le Single Sign-On. Ceci emp\u00EAche SSO de fonctionner. -title.advanced.connection.sso.unable = Impossible de connecter en utilisant le Single Sign-On. SVP v\u00E9rifiez votre principal et les param\u00E8tres du serveur. -title.advanced.connection.usesso = Se connecter via GSSAPI (SSO) -title.aim.registration = Compte AIM -title.alert = Alerte -title.appearance = Apparence -title.appearance.preferences = Personnalisation -title.appearance.showVCards = Montrer les &VCards dans la liste de contacts -title.available.transports = Transports Disponibles -title.bookmarks = Marques-pages -title.broadcast.message = Message group\u00E9 -title.browse.conference.services = Voir les services de conf\u00E9rence -title.browse.room.service = Voir les salles de conf\u00E9rence -title.cancelled = Annul\u00E9 -title.change.nickname = Changer de nickname -title.change.subject = Changer de sujet -title.chat = Chat -title.choose.directory = S\u00E9lectionnez un r\u00E9pertoire -title.choose.incoming.sound = S\u00E9lectionnez un fichier d'alerte sonore lors de messages entrants -title.choose.offline.sound = S\u00E9lectionnez un fichier d'alerte sonore pour les d\u00E9connexions -title.choose.outgoing.sound = S\u00E9lectionnez un fichier d'alerte sonore pour les messages sortants -title.client.logs = Logs client -title.conference.invitation = Invitation \u00E0 une Conf\u00E9rence -title.conference.rooms = Salles de conf\u00E9rence -title.configure.chat.room = Configurer le Salon de Discussion -title.configure.room = Configurer le Salon -title.confirmation = Confirmation -title.create.new.account = Cr\u00E9er un nouveau compte -title.create.or.bookmark.room = Rejoindre ou ajouter le salon aux favoris -title.create.or.join = Cr\u00E9er/Rejoindre -title.create.problem = Erreur de cr\u00E9ation du compte -title.delete.file = Voulez-vous vraiment supprimer le fichier? -title.dial.phone = T\u00E9l\u00E9phoner -title.disable.transport = D\u00E9sactiver le Transport -title.download.complete = T\u00E9l\u00E9chargement Termin\u00E9 -title.downloading.im.client = T\u00E9l\u00E9chargement du client d'IM -title.downloads = T\u00E9l\u00E9chargements -title.edit.custom.message = Editer les messages personnalis\u00E9s -title.edit.profile = Editer Profil -title.enter.reason = Donnez une raison -title.error = Erreur -title.error.couldnt.open.file = Impossible d'ouvrir le fichier -title.error.delete.file = Impossible d'effacer le fichier -title.error.find.app = Impossible de trouver l'application correspondante -title.error.rename.file = Impossible de renommer le fichier -title.facebook.registration = Identifiants Facebook -title.file = Fichier -title.file.exists = Le fichier existe d\u00E9j\u00E0 -title.file.transfer = Transfert de fichier -title.file.transfer.preferences = Pr\u00E9f\u00E9rences Transfert de Fichier -title.filesize = Taille -title.find.conference.service = Rechercher les Services de Conf\u00E9rence -title.find.contacts = Rechercher Contacts -title.gadugadu.registration = Identifiants GaduGadu -title.general.chat.settings = Param\u00E8tres de Chat -title.general.media = R\u00E9glages Multimedia -title.group.chat = Conf\u00E9rence -title.group.chat.settings = R\u00E9glages des groupes de discussion -title.gtalk.registration = Identifiants GTalk -title.history.for = Historique de conversation de {0} -title.icq.registration = Compte ICQ -title.incoming.call = Appel Entrant -title.input.fileexplorer = Saisissez le nom de votre navigateur: -title.input.newname = Saisissez le nouveau nom\: -title.input.openwith = Saisissez le nom de l'application que vous voulez utiliser: -title.invite.to.conference = Inviter \u00E0 une Conf\u00E9rence -title.irc.registration = Identifiants IRC -title.jabber.browser = Navigateur -title.join.conference.room = Rejoindre une Conf\u00E9rence -title.last.activity = Derni\u00E8re Activit\u00E9 -title.login = Login -title.login.error = Erreur de connexion -title.login.no.account = Impossible de d\u00E9terminer -title.login.settings = Param\u00E8tres de Login -title.lookup.profile = Voir Profil -title.msn.registration = Compte MSN -title.myspace.registration = Identifiants MySpace -title.name = Nom -title.new.client.available = Nouveau Client disponible -title.new.roster.group = Nouveau Groupe de Contacts -title.new.version.available = Nouvelle Version disponible -title.no.updates = Pas de mise \u00E0 jour -title.notes = Notes -title.notification = Notification -title.notifications = Notifications -title.occupants = Occupants -title.on.the.phone = Au t\u00E9l\u00E9phone -title.password = Mot de Passe -title.password.required = Mot de passe requis -title.passwords.no.match = Confirmez le mot de passe. -title.person.search = Recherche de Personne -title.plugins = Plugins -title.preferences = Pr\u00E9f\u00E9rences -title.profile.information = Infos de Profil -title.profile.not.found = Profil inexistant -title.qq.registration = Identifiants QQ -title.register.account = Cr\u00E9er un nouveau compte -title.registration.error = Erreur de cr\u00E9ation -title.reminder = Rappel -title.rename.roster.group = Renommer un group de contacts -title.room.destroyed = Salon Supprim\u00E9 -title.room.information = Infos du Salon -title.roster = Contacts -title.sametime.registration = Identifiants Sametime -title.select.file.to.send = Selectionnez un Fichier \u00E0 envoyer -title.set.status.message = Editer le message d'\u00E9tat -title.simple.registration = Identifiants SIMPLE -title.sound.preferences = Pr\u00E9f\u00E9rences Sonores -title.sounds = Sons -title.spark.preferences = Pr\u00E9f\u00E9rences Spark -title.start.chat = Ouvrir une conversation -title.status.message = Message d'\u00E9tat -title.subscription.request = Demande d'abonnement -title.task.notification = Notification de t\u00E2che -title.tasks = T\u00E2ches -title.transports = Transports -title.tray.information = Infos de la Zone d'iconification -title.upgrading.client = Mise \u00E0 Jour du Client -title.version.and.time = Version et Heure -title.view.bookmarks = Voir les Favoris -title.view.profile.for = Voir le Profil de {0} -title.view.room.information = Voir les Infos du Salon -title.waiting.to.call = Attente -title.xmpp.registration = Identifiants XMPP -title.yahoo.registration = Compte Yahoo - -tooltip.appearance = Changer l'apparence des conversations -tooltip.file.transfer = Pr\u00E9f\u00E9rences pour le transfert de fichiers -tooltip.notifications = Pr\u00E9f\u00E9rences de Notification pour les chat entrants -tooltip.place.a.call = Appeler cette Personne -tooltip.place.voice.call = Appeler cet utilisateur -tooltip.send.email = Envoyer un email -tooltip.start.chat = D\u00E9marrer une conversation -tooltip.view.changelog = Lire le Change Log -tooltip.view.history = Voir l'historique de conversation -tooltip.view.readme = Lire le ReadMe - -tree.conference.services = Service de Conf\u00E9rence -tree.users.in.room = Utilisateurs du Salon - -#!# diff --git a/src/resources/i18n/spark_i18n_it.properties b/src/resources/i18n/spark_i18n_it.properties deleted file mode 100644 index 5ca36f775..000000000 --- a/src/resources/i18n/spark_i18n_it.properties +++ /dev/null @@ -1,869 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.0.1 -## Added key: 'message.restart.spark.changes' -## Added key: 'message.enter.icq' -## Added key: 'title.icq.registration' -## Added key: 'button.quit' -## -## -## -## 2.0.2 -## Added key: 'button.new' -## Added key: 'label.group' -## Added key: 'label.jabber.id' -## Added key: 'label.enter.group.name' -## Added key: 'title.new.roster.group' -## Added key: 'title.add.contact.group' -## Added key: 'message.add.contact.to.list' -## Added key: 'title.add.contact' -## Added key: 'tab.conferences' -## Added key: 'message.autenticating' -## Added key: 'title.file.transfer.preferences' -## Added key: 'menuitem.about' -## Added key: 'message.invalid.status' -## Added key: 'message.cannot.add.contact.to.shared.group -## Added key: 'message.specify.contact.jid' -## Added key: 'message.invalid.jid.error' -## Added key: 'message.specify.group' -## Added key: 'add' -## -## -## -## 2.0.5 -## Added key: 'Broadcast' -## Added key: 'label.user.on.public.network' -## Added key: 'label.network' -## -## -## 2.0.6 -## Added key: 'button.add.user' -## Added key: 'menuitem.sign.in' -## Added key: 'menuitem.sign.out' -## Added key: 'menuitem.sign.in.at.login' -## Added key: 'menuitem.enter.login.information' -## Added key: 'menuitem.delete.login.information' -## Added key: 'button.save' -## -## -## 2.5 -## Added key: 'button.start.chat' -## Added key: 'button.send.email' -## Added key: 'available' -## Added key: 'checkbox.tabs.on.top' -## Added key: 'user.has.signed.in' -## Added key: 'user.has.signed.off' -## Added key: 'label.unable.to.add.contact' -## Added key: 'label.conflict.error' -## Added key: 'message.room.creation.error' -## Added key: 'checkbox.allow.buzz' -## Added key: 'message.disconnected.group.chat.error' -## Added key: 'menuitem.show.offline.group' -## Added key: 'menuitem.move.to' -## Added key: 'menuitem.copy.to' -## Added key: 'label.message.style' -## Added key: 'label.emoticons' -## Added key: 'checkbox.enable.emoticons' -## Added key: 'message.unable.to.retrieve.last.activity' -## Added key: 'checkbox.use.system.look.and.feel' -## -## 2.5.2 -## Added key: 'tooltip.place.voice.call' -## Added key: 'message.buzz.alert.notification' -## Added kye: 'message.buzz.sent' -## -## 2.5.2 -## Added key: 'menuitem.user.guide' -## -## -## -## 2.5.7 -## Added key: 'menuitem.languages' -## Added key: 'message.restart.required' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'message.send.to.these.people' -## Added key: 'message' -## Added key: 'message.normal' -## Added key: 'message.alert.notify' -## -## 2.5.8 -## Added key: 'message.enter.simple' -## Added key: 'message.enter.irc' -## Added key: 'message.enter.gadugadu' -## Added key: 'title.simple.registration' -## Added key: 'title.irc.registration' -## Added key: 'title.gadugadu.registration' -## Added key: 'message.username.error' -## Added key: 'message.password.error' -## Added key: 'message.nickname.error' -## -## 2.5.9 -## Added key: 'message.gateway.username.error. -## Added key: 'message.gateway.password.error. -## Added key: 'message.gateway.nickname.error. -## Added key: 'answer' -## Added key: 'online' -## Added key: 'online' -## Added key: 'offline' -## Added key: 'participants' -## Added key: 'unfiled' -## Added key: 'while.offline' -## Added key: 'action.clear' -## Added key: 'action.copy ' -## Added key: 'action.cut' -## Added key: 'action.paste' -## Added key: 'action.print' -## Added key: 'action.save' -## Added key: 'action.select.all' -## Added key: 'button.add2' -## Added key: 'button.copy.to.clipboard' -## Added key: 'button.reconnect2' -## Added key: 'button.tasks.active' -## Added key: 'button.tasks.all' -## Added key: 'button.view.notes' -## Added key: 'button.view.profile' -## Added key: 'button.view.tasklist' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.show.avatars.in.contaclist' -## Added key: 'checkbox.use.compression' -## Added key: 'group.empty' -## Added key: 'group.offline' -## Added key: 'label.add.task' -## Added key: 'label.chatroom.fontsize' -## Added key: 'label.contactlist.fontsize' -## Added key: 'label.due' -## Added key: 'label.show' -## Added key: 'label.timeformat' -## Added key: 'menuitem.dial' -## Added key: 'menuitem.view.logs' -## Added key: 'message.disconnected.shutdown' -## Added key: 'message.invalid.username.password' -## Added key: 'message.no.updates' -## Added key: 'message.reconnect.attempting' -## Added key: 'message.reconnect.failed' -## Added key: 'message.reconnect.wait' -## Added key: 'message.send.picture' -## Added key: 'message.server.unavailable' -## Added key: 'message.unrecoverable.error' -## Added key: 'message.waiting.for.user.to.join' -## Added key: 'status.available' -## Added key: 'status.away' -## Added key: 'status.custom.messages' -## Added key: 'status.do.not.disturb' -## Added key: 'status.extended.away' -## Added key: 'status.free.to.chat' -## Added key: 'status.on.phone' -## Added key: 'status.online' -## Added key: 'status.pending' -## Added key: 'title.about' -## Added key: 'title.appearance' -## Added key: 'title.appearance.preferences' -## Added key: 'title.login.error' -## Added key: 'title.no.updates' -## Added key: 'title.notes' -## Added key: 'title.tasks' -## Added key: 'tooltip.appearance' -## Added key: 'tooltip.file.transfer' -## Added key: 'tooltip.send.email' -## Added key: 'tooltip.start.chat' -## Added key: 'delete.log.permanently' -## Added key: 'delete.permanently' -## Added key: 'label.contactlist.avatarsize' -## -## 2.6.0 beta 1 -## Removed key status.available - -accept = Accetta -active = Attiva -add = Aggiungi -answer = Rispondi -available = Disponibile -broadcast = Messaggio a Tutti -cancel = Annulla -close = Chiudi -create = Crea -date = Data -description = Descrizione -from = Da -invite = Invita -join = Entra -no = No -not.registered = Non Registrato -occupants = Presenti -offline = Offline -ok = Ok -online = Online -open = Apri -open.folder = Apri Cartella -participants = Partecipanti -reject = Rifiuta -retry = Riprova -room.name = Nome Stanza -save = Salva -subject = Argomento -unfiled = Altri -use.default = Usa Predefinito -user.has.signed.in = \u00e8 entrato. -user.has.signed.off = \u00e8 uscito. -while.offline = Quando disconnesso -yes = Si - -action.clear = Pulisci -action.copy = Copia -action.cut = Taglia -action.paste = Incolla -action.print = Stampa -action.save = Salva -action.select.all = Seleziona tutto - -button.accept = &Accetta -button.add = &Aggiungi -button.add.a.contact = &Aggiungi Un Contatto -button.add.bookmark = Aggiungi Preferito -button.add.service = &Aggiungi Servizio -button.add.user = &Aggiungi Utente -button.add2 = A&ggiungi... -button.advanced = A&vanzate -button.approve = &Conferma -button.bookmark.room = &Stanza Preferita -button.browse = &Sfoglia... -button.browse2 = S&foglia... -button.browse3 = Sf&oglia... -button.cancel = &Annulla -button.clear = &Azzera -button.close = C&hiudi -button.copy.to.clipboard = Copia negli appunti -button.create.account = &Crea Account -button.create.room = &Crea o Entra nella Stanza -button.decline = &Rifiuta -button.deny = &Ignora -button.dial.number = &Numero di Telefono -button.find = &Trova -button.join = &Entra -button.join.room = &Entra nella Stanza Selezionata -button.new = &Nuovo -button.profile = &Profilo -button.quit = &Esci -button.reconnect = &Riconnetti -button.reconnect2 = Riconnetti -button.refresh = &Aggiorna -button.register = &Registrati -button.remove.bookmark = Elimina Preferito -button.roster = &Elenco -button.save = &Salva -button.save.for.future.use = &Salva per utilizzi futuri -button.search = &Cerca -button.send = Invia -button.send.email = Email -button.start.chat = Chat -button.tasks.active = Attivi -button.tasks.all = Tutti -button.update = &Aggiorna -button.view.notes = Mostra note -button.view.profile = Visualizza profilo completo -button.view.tasklist = Mostra lista impegni - -checkbox.allow.buzz = Abilita gli utenti ad attira&re la tua attenzione. -checkbox.auto.discover.port = &Rileva Automaticamente host e porta -checkbox.auto.login = &Login Automatico -checkbox.disable.chat.history = &Disattiva la Cronologia nella Chat -checkbox.enable.emoticons = Attiva Em&oticons -checkbox.idle.enabled = &Rileva Inattivit\u00e0 -checkbox.launch.on.startup = &Esegui all'avvio -checkbox.notify.user.comes.online = Notifica quando un utente si connette. -checkbox.notify.user.goes.offline = Notifica quando un utente si disconnette. -checkbox.permanent = La Stanza \u00e8 &permanente -checkbox.play.sound.on.invitation = Esegui file audio alla &ricezione di un invito -checkbox.play.sound.on.new.message = Esegui file audio quando arriva un nuovo &messaggio -checkbox.play.sound.on.outgoing.message = Esegui file audio quando viene &inviato un messaggio -checkbox.play.sound.when.offline = Esegui file audio quando un utente si &disconnette -checkbox.private.room = La stanza &\u00e8 privata -checkbox.save.password = &Salva Password -checkbox.show.avatars.in.contact.list = Mostra gli &avatars nella lista contatti -checkbox.show.notifications.in.conference = &Mostra notifiche nelle Stanze -checkbox.show.time.in.chat.window = &Mostra Orario nella Finestra di Chat -checkbox.show.toaster = Mostra &Popup a Comparsa -checkbox.split.chat.window = Dividi le &Finestre di chat (Richiede il riavvio di Spark) -checkbox.start.in.tray = &Avvia Spark nella Tray Bar -checkbox.tabs.on.top = Schede della &Chat appaiono in alto (Richiede il riavvio di Spark) -checkbox.use.compression = Usa Co&mpressione -checkbox.use.proxy.server = &Usa Proxy Server -checkbox.use.system.look.and.feel = Utilizza il Look and &Feel di sistema (Richiede il riavvio di Spark) -checkbox.window.to.front = &Porta la finestra in primo piano - -delete.log.permanently = Elimina definitivamente log -delete.permanently = Eliminare definitivamente? - -gateway.username.password.error = Devono essere inseriti username e/o password. - -group.chat.window.information = Informazioni sulla finestra di chat -group.comma.delimited = Delimitato da Virgola -group.conferences.found = Trovato un Servizio Conferenza -group.connection = Connessione -group.empty = Nessun contatto online in questo gruppo. -group.general.information = Informazioni Generali -group.login.information = Informazioni di Login -group.notification.options = Opzioni di Notifica -group.offline = Utenti Offline -group.search.form = Cerca in -group.search.results = Risultati della ricerca - -label.accounts = &Accounts -label.add.conference.service = &Aggiungi un servizio conferenza -label.add.jid = &Aggiungi JID -label.add.task = &Aggiungi impegno -label.auto.login = &Login Automatico -label.available.users.in.roster = &Utenti disponibili in Elenco -label.cancel = Annulla -label.change.password.to = &Cambia Password -label.chatroom.fontsize = Dimensione font finestra chat: -label.city = &Localit\u00e0 -label.close = C&hiudi -label.company = &Azienda -label.confirm.password = &Conferma Password -label.conflict.error = Impossibile loggarsi, l'account \u00e8 gi\u00e0 loggato. -label.contact.to.find = Cerca contatto -label.contactlist.avatarsize = -label.contactlist.fontsize = Dimensione font lista contatti: -label.country = N&azione -label.create.account = Crea un &Account -label.department = &Dipartimento -label.dial = &Chiama -label.due = Entro -label.email.address = &Email -label.emoticons = &Emoticons -label.enter.address = Inserisci Indirizzo -label.enter.group.name = Inserisci il nome del nuovo gruppo -label.fax = &Fax -label.find = &Cerca -label.first.name = &Nome -label.group = &Gruppo -label.host = &Host -label.invited.users = Utenti invitati -label.jabber.address = Indirizzo &Jabber -label.jabber.id = &Jabber ID -label.jid = &JID -label.job.title = &Posizione Lavorativa -label.last.name = &Cognome -label.local.time = &Ora Locale -label.message.style = &Stile Messaggi -label.middle.name = &Secondo Nome -label.minutes.before.stale.chat = &Minuti di inattivit\u00e0 massima per la stanza -label.mobile = &Cellulare -label.name = &Nome -label.network = Ret&e -label.new.nickname = Nuovo Nickname -label.nickname = &Nickname -label.number = &Numero -label.ok = OK -label.old.ssl = &Usa vecchio metodo su porta SSL -label.os = &Sistema Operativo -label.pager = &Cercapersone -label.password = &Password -label.phone = &Telefono -label.port = &Porta -label.postal.code = &CAP -label.presence = &Presenza -label.priority = P&riorit\u00e0 -label.protocol = &Protocollo -label.receieved = &Ricevuti -label.rename.to = Rinomina in -label.resource = &Risorsa -label.response.timeout = &Timeout di Risposta (sec) -label.room = &Stanza -label.room.name = &Nome Stanza -label.room.topic= &Argomento Stanza -label.search.service = &Servizio di Ricerca -label.server = &Server -label.server.address = &Indirizzo Server -label.show = Show: -label.software = &Software -label.state.and.province = &Regione -label.street.address = &Via -label.time = Orario: {0} -label.time.till.idle = &Intervallo di Inattivit\u00e0 (min) -label.timeformat = Usa {0} -label.transfer.download.directory = &Directory di Download: -label.transfer.timeout = &Timeout di Trasferimento(min): -label.unable.to.add.contact = Impossibile aggiungere il contatto. -label.use.default = Usa Predefinito -label.user.on.public.network = L'utente \u00e8 in una rete pubblica -label.username = &Nome Utente -label.version = &Versione -label.web.page = &Home Page -label.xmpp.port = Porta &XMPP - -menuitem.about = Versione -menuitem.actions = Azioni -menuitem.add = Aggiungi -menuitem.add.as.contact = Aggiungi come contatto -menuitem.add.contact = Aggiungi Contatti -menuitem.add.contact.group = Aggiungi Gruppi di contatti -menuitem.alert.when.online = Avverti quanto l'utente \u00e8 disponibile -menuitem.ban = Ban -menuitem.ban.user = Ban Utente -menuitem.block.user = Blocca Utente -menuitem.broadcast.to.group = Messaggio Broadcast al gruppo -menuitem.browse.service = Elenca Servizi -menuitem.change.nickname = Cambia Nickname -menuitem.change.subject = Cambia Argomento -menuitem.chat = Chat -menuitem.check.for.updates = Verifica la presenza di aggiornamenti -menuitem.contacts = Contatti -menuitem.copy.to = Copia in -menuitem.delete = Cancella -menuitem.delete.login.information = Cancella le Informazioni di Login -menuitem.destroy.room = Distruggi Stanza -menuitem.dial = Componi -menuitem.edit = Modifica -menuitem.edit.my.profile = &Modifica il tuo Profilo... -menuitem.edit.status.message = Modifica Messaggi di Stato personalizzati... -menuitem.enter.login.information = Inserisci le Informazioni di Login -menuitem.exit = Esci -menuitem.grant.moderator = Concedi Moderatore -menuitem.grant.voice = Concedi Voice -menuitem.help = Help -menuitem.hide = Nascondi -menuitem.invite.group.to.conference = Invita il gruppo in una stanza -menuitem.invite.users = Invita Utenti -menuitem.join.on.startup = Entra all'Avvio -menuitem.join.room = Entra nella Stanza -menuitem.kick.user = Espelli Utente -menuitem.languages = Lingue -menuitem.logout.no.status = Log out -menuitem.logout.with.status = Log out con motivazione -menuitem.lookup.profile = &Ricerca Profilo... -menuitem.move.to = Sposta in -menuitem.online.help = Online Help -menuitem.open = Apri -menuitem.plugins = &Plugins -menuitem.preferences = Preferenze -menuitem.remove = Elimina -menuitem.remove.alert.when.online = Elimina Alert -menuitem.remove.bookmark = Elimina Preferiti -menuitem.remove.from.group = Rimuovi dal Gruppo -menuitem.remove.from.roster = Rimuovi dall'Elenco -menuitem.remove.service = Rimuovi Servizio -menuitem.rename = Rinomina -menuitem.revoke.moderator = Rimuovi Moderatore -menuitem.revoke.voice = Rimuovi Voice -menuitem.save = Salva -menuitem.save.as = Salva come... -menuitem.send.a.file = Invia un File -menuitem.send.a.message = Invia un Messaggio... -menuitem.set.status.message = Imposta Messaggio di Stato... -menuitem.show.empty.groups = Mostra i Gruppi Vuoti -menuitem.show.offline.group = Raggruppa gli utenti offline -menuitem.show.traffic = Mostra finestra di Traffico -menuitem.sign.in = Login -menuitem.sign.in.at.login = Entra al Login -menuitem.sign.out = Logout -menuitem.start.a.chat = Avvia una Chat -menuitem.start.a.conference = Apri una stanza... -menuitem.status = Stato -menuitem.subscribe.to = Iscriviti A -menuitem.unban = Rimuovi Ban -menuitem.unblock.user = Sblocca Utente -menuitem.user.guide = Guida utente -menuitem.view.client.version = Visualizza Versione Client -menuitem.view.contact.history = Visualizza Storico dei Contatti -menuitem.view.downloads = Visualizza Downloads -menuitem.view.last.activity = Visualizza l'ultima Attivit\u00e0 -menuitem.view.logs = Visualizza Logs -menuitem.view.profile = Visualizza Profilo -menuitem.view.room.info = Visualizza Informazioni sulla Stanza -menuitem.voice = Voice - -message = &Messaggio -message.account.create = Crea un nuovo account di chat. -message.account.created = L'account \u00e8 stato creato. -message.account.error = Indica il server su cui creare l'account. -message.add.a.contact = Aggiungi un contatto. -message.add.conference.service = Aggiungi un servizio conferenza. -message.add.contact.to.list = Aggiungi l'utente all'elenco dei contatti -message.add.favorite.room = Inserisci la stanza nell'elenco dei preferiti o entraci direttamente. -message.add.this.user.to.your.roster = Aggiungi l'utente all'elenco degli amici. -message.add.to.roster = Aggiungi all'elenco -message.add.user = Aggiungi l'utente nel tuo elenco? -message.alert.notify = Richiesta attenzione -message.already.exists = Account gi\u00e0 esistente, indicare un nome diverso. -message.approve.subscription = Consenti a {0} di inserirti nel proprio elenco? -message.autenticating = Autenticazione in corso -message.away.idle = L'utente \u00e8 assente per inattivit\u00e0. -message.bookmark.temporary.room.error = Impossibile rendere preferita una stanza temporanea -message.broadcast.from = Messaggio broadcast da {0} -message.broadcast.message.sent = Il messaggio broadcast \u00e8 stato inviato. -message.broadcast.to = Digitare il messaggio broadcast da inviare a {0} -message.broadcasted.to = Il messaggio broadcast \u00e8 stato inviato ai seguenti utenti:\n{0} -message.buzz.alert.notification = Ottieni l'attenzione dell'utente. -message.buzz.sent = Invia una notifica all'utente. -message.calling = Chiamata a {0} in corso -message.came.online = {0} \u00e8 online dalle {1} -message.cannot.add.contact.to.shared.group = Impossibile aggiungere nuovi contatti ad un gruppo condiviso. -message.chat.session.ended = La sessione di chat \u00e8 terminata alle {0} -message.click.to.open = Fai click per aprire -message.client.information = Informazioni sul client di {0} -message.close.other.chats = Chiudi tutte le altre chat -message.close.stale.chats = Chiudi le chat inattive -message.close.this.chat = Termina questa chat -message.conference.info.error = Impossibile ottenere delle informazioni sulla stanza. Riprova pi\u00f9 tardi. -message.conference.service.error = Impossibile avviare il servizio conferenze. -message.confirm.destruction.of.room = Se elimini la stanza, disconnetterai tutti gli utenti presenti. Vuoi continuare? -message.confirmation.password.error = Conferma Password. -message.connecting.please.wait = Connessione in corso. Attendere prego... -message.connection.failed = Collegamento con {0} non riuscito. -message.create.account = Impossibile creare l'account. -message.create.or.join.room = Crea o Entra in una stanza di chat -message.current.status = Mostra agli altri il tuo stato. -message.default.error = E' stato rilevato un errore grave, per favore segnalare il problema all'amministratore. -message.delete.all.history = Eliminare tutte le conversazioni precedenti? -message.delete.confirmation = Confermi l''eliminazione di {0}? -message.disable.transport = Vuoi disattivare questo trasporto? -message.disconnected.conflict.error = La connessione \u00e8 stata chiusa a causa del login dello stesso utente da un altro computer. -message.disconnected.error = La connessione \u00e8 stata chiusa a causa di un errore. -message.disconnected.group.chat.error = La connessione \u00e8 stata chiusa a causa di un errore. Dovrai rientrare in questa stanza dopo esserti riconnesso. -message.disconnected.shutdown = La tua connessione \u00e8 stata chiusa perch\u00e9 il server \u00e8 stato spento. -message.downloading = Download di {0} in corso -message.downloading.spark.plug = Download di Spark-Plug in corso -message.end.chat = Terminare questa chat? -message.end.conversation = Terminare questa sessione? -message.enter.aim = Digita nei campi sottostanti il tuo nome utente e password per AIM. -message.enter.broadcast.message = Inserisci il messaggio broadcast per gli utenti selezionati. -message.enter.gadugadu = Digita nei campi sottostanti il tuo nome utente e password per GaduGadu. -message.enter.gtalk = Digita nei campi sottostanti il tuo nome utente e password per GTalk. -message.enter.icq = Digita nei campi sottostanti il tuo nome utente e password per ICQ. -message.enter.irc = Digita nei campi sottostanti l'username, la password, e il nickname per IRC. -message.enter.jabber.id = Digita Jabber ID -message.enter.message.to.broadcast = Inserisci il messaggio broadcast da inviare al tuo elenco. -message.enter.msn = Digita nei campi sottostanti il tuoi nome utente e password per MSN. -message.enter.new.subject = Digita un nuovo argomento -message.enter.room.password = Digita la Password della stanza -message.enter.simple = Digita nei campi sottostanti il tuo nome utente e password per SIMPLE. -message.enter.valid.jid = Inserisci un Jabber ID valido -message.enter.xmpp = Digita nei campi sottostanti il tuoi nome utente e password per XMPP. -message.enter.yahoo = Digita nei campi sottostanti il tuoi nome utente e password per Yahoo. -message.error.during.file.transfer = Si \u00e8 verificato un errore durante il trasferimento di un file. -message.file.exists.question = Il file esiste gi\u00e0. Vuoi sovrascriverlo? -message.file.size = Dimensione File: {0} -message.file.transfer.canceled = Hai annullato il trasferimento del file. -message.file.transfer.rejected = Il trasferimento del file non \u00e8 stato accettato da {0}. -message.find.conference.services = Trova Servizi Conferenza -message.forbidden.error = Operazione non permessa dal server. -message.gateway.nickname.error = Inserisci un nickname per l'account. -message.gateway.password.error = Inserisci una password per l'account. -message.gateway.username.error = Inserisci un nome utente per l'account. -message.general.error = Connessione al server terminata a causa di {0}. -message.generic.reconnect.message = Connessione al server terminata. Per rieffettuare il login, fare click sul pulsante Riconnetti. -message.idle.for = Inattivo per {0} -message.image.too.large = Hai scelto un'immagine troppo grande. Indica un immagine di 16k o di dimensioni minori. -message.invalid.jabber.id = Il Jabber ID indicato non \u00e8 valido -message.invalid.jid.error = Il JID indicato non \u00e8 valido. -message.invalid.status = Digita un messaggio di stato valido. -message.invalid.username.password = Username o password non validi. -message.invite.users.to.conference = Invita gli utenti ad una conferenza. -message.is.shared.group = {0} \u00e8 un gruppo condiviso. -message.is.typing.a.message = {0} sta digitando un messaggio... -message.join.conference.room = Entra in una Stanza -message.kicked.error = Non hai il permesso di espellere {0} da questa stanza. -message.last.message.received = Ultimo messaggio ricevuto alle {0} -message.loading.please.wait = Caricamento in corso. Attendere prego... -message.locked.workstation = L'utente ha bloccato il computer. -message.name.of.group = Nome del Gruppo -message.name.of.search.service.question = Indica il nome del servizio di riceca -message.negotiate.file.transfer = Negoziazione del trasferimento file in corso. Attendere prego... -message.negotiate.stream = Negoziazione della connessione in corso. Attendere prego... -message.negotiation.file.transfer = Negoziazione del file transfer con {0} in corso. Attendere prego... -message.new.message = Nuovo messaggio da {0}. -message.new.spark.available = {0} \u00e8 ora disponibile. Vuoi procedere con l''installazione? -message.nickname.in.use = Nickname gi\u00e0 in uso. Indicane un altro. -message.no.avatar.found = L'utente non ha configurato nessun avatar. -message.no.caller.id = Identificativo del chiamante non disponibile. -message.no.description.available = Nessuna descrizione disponibile -message.no.history.found = La cronologia non contiene conversazioni precedenti con questo utente. -message.no.results.found = La ricerca sul server non ha restituito nessun risultato. -message.no.room.to.join.error = Nessuna stanza in cui entrare -message.no.subject.available = Argomento non impostato -message.no.updates = Non sono disponibili aggiornamenti. -message.normal = Messaggio normale -message.number.to.call = Indicare il numero di telefono -message.offline = L'utente \u00e8 offline e ricever\u00e0 il tuo messaggio al prossimo login. -message.offline.error = L'utente non \u00e8 in grado di ricevere messaggi offline. -message.participants.in.room = Partecipanti -message.password.error = Inserisci la password per questo account. -message.password.private.room.error = Indica una password per la stanza privata -message.passwords.no.match = Le Password sono diverse. -message.please.join.in.conference = Hai ricevuto un invito ad entrare in una stanza. -message.plugins.not.available = Impossibile contattare il server dei plugins. -message.prompt.plugin.uninstall = Confermi di voler disinstallare {0}? -message.received.file = Hai appena ricevuto un file da {0}. -message.receiving.file = Stai ricevendo un file da {0} -message.reconnect.attempting = Nuovo tentativo... -message.reconnect.failed = Riconnessione fallita. -message.reconnect.wait = Riconnessione tra {0} secondi. -message.register.transports = Registrati con i trasporti disponibili. -message.registering = Registrazione in corso con {0}. Attendere prego... -message.registration.transport.failed = Impossibile registrarsi con il trasporto. -message.restart.spark = E' necessario terminare il client \n per installare una nuova versione. Procedere ora? -message.restart.spark.changes = Il Plugin sar\u00e0 disinstallato al prossimo riavvio di Spark. -message.restart.spark.to.install = E' necessario terminare il client per installare una nuova versione. Procedere ora? -message.restart.required = E' necessario riavviare Spark perch\u00e9 i cambiamenti abbiano effetto. Riavviare ora? -message.room.creation.error = La stanza non pu\u00f2 essere creata. -message.room.destroyed = La stanza \u00e8 stata eliminata per il seguente motivo: {0} -message.room.destruction.reason = Indica la ragione per cui distruggere la stanza? -message.room.information.for = Informazioni della stanza per {0} -message.save.profile = Per salvare le modifiche al tuo profilo, fai click su salva. -message.search.for.contacts = Ricerca Contatti. -message.search.for.other.people = Ricerca altre persone collegate al server. -message.search.service.not.available = Impossibile contattare i servizi di ricerca. -message.searching.please.wait = Ricerca in corso. Attendere prego... -message.select.add.room.to.add = Seleziona una stanza da inserire nell'elenco dei servizi. -message.select.one.or.more = Seleziona uno o pi\u00f9 utenti dal tuo elenco. -message.select.room.to.enter = Indica la stanza in cui entrare. -message.select.room.to.join = Indica la stanza in cui entrare. -message.send.a.broadcast = Invia un messaggio broadcast -message.send.file.to.user = Invia file a questo utente. -message.send.picture = Invia l'immagine del tuo desktop. -message.send.to.these.people = Invia a queste persone -message.sending.file.to = Trasferimento del file a {0} in corso. -message.sent.offline.files = Hai ricevuto dei files offline. -message.server.unavailable = Il server non \u00e8 raggiungibile. -message.service.already.exists = Il servizio \u00e8 gi\u00e0 presente nell'elenco. -message.shared.group = Gruppo Condiviso -message.spark.secure = Spark \u00e8 in esecuzione in modalit\u00e0 protetta. -message.specify.contact.jid = Indica il JID (ex. ddman@jabber.org) del contatto -message.specify.group = Indicare il gruppo di contatti in cui collocare l'utente. -message.specify.information.for.conference = Imposta le propriet\u00e0 della Stanza. -message.specify.name.error = Indica un nome valido. -message.specify.users.to.join.conference = Indica gli utenti da invitare in questa stanza. -message.specify.valid.time.error = Indica dei valori validi per il timeout e la porta. -message.subject.change.error = non hai il permesso di cambiare l'argomento della stanza. -message.subject.has.been.changed.to = Il nuovo argomento \u00e8 {0}. -message.supply.resource = Indica una risorsa valida. -message.supply.valid.port = Indica una porta valida. -message.supply.valid.timeout = Indica un timeout valido. -message.timeout.error = Il valore del timeout deve essere di minimo 5 secondi. -message.total.downloaded = Download totale -message.transfer.cancelled = Il trasferimento file \u00e8 stato annullato. -message.transfer.rate = Velocit\u00e0 del trasferimento -message.transfer.refused = Il trasferimento file \u00e8 stato rifiutato. -message.transfer.waiting.on.user = Attendi che {0} accetti il trasferimento del file. -message.unable.to.load.profile = Impossibile trovare il profilo di {0} -message.unable.to.retrieve.last.activity = Impossibile determinare l''ultima attivit\u00e0 per {0}. -message.unable.to.save.password = Impossibile cambiare la password. Prego contattare l'amministratore. -message.unable.to.send.file = Impossibile inviare il file a {0}. -message.unrecoverable.error = Errore non recuperabile. -message.update.room.list = Aggiorna l'elenco delle stanze -message.updating.cancelled = L'aggiornamento \u00e8 stato annullato. -message.user.banned = {0} \u00e8 stato bannato dalla stanza. -message.user.given.voice = {0} ha avuto il VOICE in questa stanza. -message.user.granted.admin = {0} ha ricevuto il privilegio di amministratore. -message.user.granted.membership = {0} ha ricevuto il privilegio di membro. -message.user.granted.moderator = {0} ha ricevuto il privilegio di moderatore. -message.user.granted.owner = {0} ha ricevuto il privilegio di proprietario. -message.user.is.sending.you.a.file = {0} ti sta trasmettendo un file. -message.user.joined.room = {0} \u00e8 entrato nella stanza. -message.user.kicked.from.room = {0} \u00e8 stato espulso dalla stanza. -message.user.left.room = {0} si \u00e8 disconnesso dalla stanza. -message.user.nickname.changed = {0} ha cambiato il suo Nickname in {1}. -message.user.now.available.to.chat = {0} \u00e8 online dalle {1} -message.user.revoked.admin = Il privilegio di amministratore \u00e8 stato revocato a {0}. -message.user.revoked.membership = Il privilegio di membro \u00e8 stato revocato a {0}. -message.user.revoked.moderator = Il privilegio di moderatore \u00e8 stato revocato a {0}. -message.user.revoked.owner = Il privilegio di proprietario \u00e8 stato revocato a {0}. -message.user.voice.revoked = Il VOICE di {0} \u00e8 stato revocato. -message.username.error = Inserisci l'username per l'account. -message.username.password.error = E' necessario digitare nome utente e password. -message.vcard.not.supported = Il server non supporta le VCards. Impossibile salvarle. -message.version = Versione: {0} -message.view.information.about.this.user = Visualizza informazioni su questo utente. -message.waiting.for.user.to.join = In attesa che entri l'utente {0}. -message.went.offline = {0} \u00e8 offline dalle {1} -message.you.have.been.banned = Sei stato bannato da questa stanza. -message.you.have.been.kicked = Sei stato espulso dalla stanza. -message.you.have.sent = Il trasferimento del file a {0} \u00e8 appena terminato. -message.your.admin.granted = Ti sono stati concessi i privilegi di administrator. -message.your.banned = Sei stato bannato da questa stanza. -message.your.kicked = Sei stato espulso da {0}. -message.your.membership.granted = Ti sono stati concessi i privilegi di membro. -message.your.membership.revoked = I privilegi di membro ti sono stati revocati. -message.your.moderator.granted = Ti sono stati concessi i privilegi di moderatore. -message.your.moderator.revoked = I privilegi di moderatore ti sono stati revocati. -message.your.ownership.granted = Ti sono stati concessi i privilegi di proprietario. -message.your.ownership.revoked = I privilegi di proprietario ti sono stati revocati. -message.your.revoked.granted = I privilegi di administrator ti sono stati revocati. -message.your.voice.granted = Hai avuto il VOICE in questa chat. -message.your.voice.revoked = Ti \u00e8 stato tolto il VOICE in questa chat. - -status.away = Torno subito -status.custom.messages = Messaggi personalizzati -status.do.not.disturb = Non disturbare -status.extended.away = Non al computer -status.free.to.chat = Pronto a chattare -status.on.phone = Al telefono -status.online = Disponibile -status.pending = In attesa - -tab.available.plugins = Plugins Disponibili -tab.avatar = Avatar -tab.business = Lavoro -tab.conferences = Stanze -tab.contacts = Contatti -tab.general = Generale -tab.home = Casa -tab.installed.plugins = Plugins Installati -tab.personal = Personale -tab.proxy = Proxy - -title.about = About -title.account.create.registration = Registrazione Account -title.account.created = Account Creato -title.add.contact = Aggiungi contatto -title.add.contact.group = Aggiungi Gruppo di Contatti -title.add.new.group = Aggiungi Nuovo Gruppo -title.add.search.service = Aggiungi Servizio di Ricerca -title.add.to.roster = Aggiungi all'Elenco -title.address = Indirizzo -title.advanced.connection.preferences = Preferenze Avanzate di Connessione -title.alert = Alert -title.appearance = Aspetto -title.appearance.preferences = Aspetto -title.available.transports = Trasporti Disponibili -title.broadcast.message = Messaggio Broadcast -title.browse.conference.services = Elenca i Servizi Conferenza -title.browse.room.service = Sfoglia Stanze - {0} -title.cancelled = Terminato -title.change.nickname = Cambia Nickname -title.change.subject = Cambia Argomento -title.chat = Chat -title.choose.directory = Scegli Directory -title.choose.incoming.sound = Scegli file audio da riprodurre all'arrivo -title.choose.offline.sound = Scegli file audio da riprodurre in offline -title.choose.outgoing.sound = Scegli file audio da riprodurre all'invio -title.conference.invitation = Invito alla stanza -title.conference.rooms = Stanze -title.configure.chat.room = Configura la Chat -title.configure.room = Configura la stanza -title.confirmation = Conferma -title.create.new.account = Crea Nuovo Account -title.create.or.bookmark.room = Entra nella stanza o mettila nei preferiti -title.create.or.join = Crea/Entra -title.create.problem = Problema nella Creazione Account -title.dial.phone = Chiama Numero -title.disable.transport = Disabilita Trasporto -title.download.complete = Download Completo -title.downloading.im.client = Download IM Client -title.downloads = Downloads -title.edit.custom.message = Modifica Messaggi Personalizzati -title.edit.profile = Modifica le Informazioni del Profilo -title.enter.reason = Inserisci Motivazione -title.error = Errore -title.file.exists = Il File Esiste -title.file.transfer = Trasferimento File -title.file.transfer.preferences = Preferenze di Trasferimento File -title.find.conference.service = Cerca i Servizi Conferenza -title.find.contacts = Ricerca Contatti -title.gadugadu.registration = Credenziali Account GaduGadu -title.general.chat.settings = Impostazioni Generali Chat -title.group.chat = Chat di gruppo -title.gtalk.registration = Credenziali Account GTalk -title.history.for = Cronologia delle conversazioni per {0} -title.icq.registration = Credenziali Account ICQ -title.irc.registration = Credenziali Account IRC -title.incoming.call = Chiamata in arrivo -title.invite.to.conference = Invita in una stanza -title.jabber.browser = Browser -title.join.conference.room = Entra nella stanza -title.last.activity = Ultima Attivit\u00e0 -title.login = Login -title.login.error = Errore di login -title.login.settings = Parametri di Login -title.lookup.profile = Ricerca del Profilo -title.msn.registration = Credenziali Account MSN -title.name = Nome -title.new.client.available = Nuovo Client Disponibile -title.new.roster.group = Nuovo Gruppo di Elenco -title.new.version.available = Nuova Versione disponibile -title.no.updates = Nessun aggiornamento -title.notes = Note -title.notification = Notifica -title.notifications = Notifiche -title.occupants = Presenti -title.on.the.phone = Al Telefono -title.password = Password -title.passwords.no.match = Conferma passwords. -title.person.search = Ricerca Persona -title.plugins = Plugins -title.preferences = Preferenze -title.profile.information = Informazioni Profilo -title.profile.not.found = Profilo Non Trovato -title.register.account = Registra nuovo Account -title.registration.error = Errore di Registrazione -title.reminder = Promemoria -title.rename.roster.group = Rinomina l'Elenco -title.room.destroyed = Stanza Distrutta -title.room.information = Informazioni Stanza -title.roster = Elenco -title.select.file.to.send = Seleziona i(l) file da inviare -title.set.status.message = Imposta messaggi di stato -title.simple.registration = Credenziali Account SIMPLE -title.sound.preferences = Preferenze suoni -title.sounds = Suoni -title.spark.preferences = Preferenze di Spark -title.start.chat = Avvia Chat -title.status.message = Messaggio di Status -title.tasks = Impegni -title.transports = Trasporti -title.tray.information = Informazioni sulla Tray -title.upgrading.client = Aggiornamento Client -title.version.and.time = Versione e Ora -title.view.bookmarks = Visualizza Preferiti -title.view.profile.for = Visualizzazione Profilo Per {0} -title.view.room.information = Visualizza informazioni sulla stanza -title.waiting.to.call = In attesa di effettuare la chiamata -title.xmpp.registration = Credenziali Account XMPP -title.yahoo.registration = Credenziali Account Yahoo - -tooltip.appearance = Modifica l'aspetto di Spark -tooltip.file.transfer = Impostazioni trasferimento file -tooltip.notifications = Notifica preferenze per le chat in arrivo. -tooltip.place.voice.call = Fai una chiamata vocale. -tooltip.send.email = Invia una e-mail. -tooltip.start.chat = Avvia una conversazione. -tooltip.view.changelog = Visualizza il ChangeLog -tooltip.view.history = Visualizza lo storico delle conversazioni -tooltip.view.readme = Visualizza ReadMe - -tree.conference.services = Servizi Conferenza -tree.users.in.room = Utenti nella Stanza - - -#!# \ No newline at end of file diff --git a/src/resources/i18n/spark_i18n_ja.properties b/src/resources/i18n/spark_i18n_ja.properties deleted file mode 100644 index b6e379c6d..000000000 --- a/src/resources/i18n/spark_i18n_ja.properties +++ /dev/null @@ -1,679 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.0.1 -## Added key: 'message.restart.spark.changes' -## Added key: 'message.enter.icq' -## Added key: 'title.icq.registration' -## Added key: 'button.quit' -## -## -## -## 2.0.2 -## Added key: 'button.new' -## Added key: 'label.group' -## Added key: 'label.jabber.id' -## Added key: 'label.enter.group.name' -## Added key: 'title.new.roster.group' -## Added key: 'title.add.contact.group' -## Added key: 'message.add.contact.to.list' -## Added key: 'title.add.contact' -## Added key: 'tab.conferences' -## Added key: 'message.autenticating' -## Added key: 'title.file.transfer.preferences' -## Added key: 'menuitem.about' -## Added key: 'message.invalid.status' -## Added key: 'message.cannot.add.contact.to.shared.group -## Added key: 'message.specify.contact.jid' -## Added key: 'message.invalid.jid.error' -## Added key: 'message.specify.group' -## Added key: 'add' -## -## -## -## 2.0.5 -## Added key: 'Broadcast' -## Added key: 'label.user.on.public.network' -## Added key: 'label.network' -## -## -## 2.0.6 -## Added key: 'button.add.user' -## Added key: 'menuitem.sign.in' -## Added key: 'menuitem.sign.out' -## Added key: 'menuitem.sign.in.at.login' -## Added key: 'menuitem.enter.login.information' -## Added key: 'menuitem.delete.login.information' -## Added key: 'button.save' -## -## -## 2.5 -## Added key: 'button.start.chat' -## Added key: 'button.send.email' -## Added key: 'available' -## Added key: 'checkbox.tabs.on.top' -## Added key: 'user.has.signed.in' -## Added key: 'user.has.signed.off' -## Added key: 'label.unable.to.add.contact' -## Added key: 'label.conflict.error' -## Added key: 'message.room.creation.error' -## Added key: 'checkbox.allow.buzz' -## Added key: 'message.disconnected.group.chat.error' -## Added key: 'menuitem.show.offline.group' -## Added key: 'menuitem.move.to' -## Added key: 'menuitem.copy.to' -## Added key: 'label.message.style' -## Added key: 'label.emoticons' -## Added key: 'checkbox.enable.emoticons' -## Added key: 'message.unable.to.retrieve.last.activity' -## Added key: 'checkbox.use.system.look.and.feel' -## -## 2.6 -## Added key: 'tooltip.place.voice.call' - -ok = Ok -cancel = \u30ad\u30e3\u30f3\u30bb\u30eb -add = \u8ffd\u52a0 -use.default = \u30c7\u30d5\u30a9\u30eb\u30c8 -close = \u9589\u3058\u308b -create = \u4f5c\u6210 -invite = \u62db\u5f85 -date = \u524a\u9664 -from = From -room.name = \u30eb\u30fc\u30e0\u540d -join = \u53c2\u52a0 -description = \u8a73\u7d30 -subject = \u5bfe\u8c61 -occupants = \u5360\u6709\u8005 -accept = \u627f\u8afe -reject = \u62d2\u7d76 -open = \u958b\u304f -open.folder = \u30d5\u30a9\u30eb\u30c0\u3092\u958b\u304f -retry = \u30ea\u30c8\u30e9\u30a4 -active = \u30a2\u30af\u30c6\u30a3\u30d6 -not.registered = \u767b\u9332\u3057\u3066\u3044\u306a\u3044 -save = \u4fdd\u5b58 -yes = \u306f\u3044 -no = \u3044\u3044\u3048 -broadcast = \u30d6\u30ed\u30fc\u30c9\u30ad\u30e3\u30b9\u30c8 -available = \u4f7f\u7528\u53ef\u80fd -user.has.signed.in = \u65e2\u306b\u30b5\u30a4\u30f3\u30a4\u30f3 -user.has.signed.off = \u65e2\u306b\u30b5\u30a4\u30f3\u30aa\u30d5 - - -button.create.account = \u30a2\u30ab\u30a6\u30f3\u30c8\u4f5c\u6210 -button.close = \u9589\u3058\u308b -button.advanced = \u4e0a\u7d1a\u8005\u7528 -button.browse = \u898b\u308b... -button.browse2 = \u898b\u308b... -button.browse3 = \u898b\u308b... -button.approve = \u8a8d\u53ef -button.deny = \u5426\u8a8d -button.accept = \u627f\u8afe -button.profile = \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb -button.add.a.contact = \u9023\u7d61\u5148\u3092\u8ffd\u52a0 -button.reconnect = \u518d\u63a5\u7d9a -button.add = \u8ffd\u52a0 -button.roster = \u540d\u7c3f -button.add.bookmark = \u30d6\u30c3\u30af\u30de\u30fc\u30af\u8ffd\u52a0 -button.remove.bookmark = \u30d6\u30c3\u30af\u30de\u30fc\u30af\u524a\u9664 -button.bookmark.room = \u30eb\u30fc\u30e0\u3092\u30d6\u30c3\u30af\u30de\u30fc\u30af -button.create.room = \u30eb\u30fc\u30e0\u3092\u4f5c\u6210 or \u53c2\u52a0 -button.join.room = \u9078\u629e\u3057\u305f\u30eb\u30fc\u30e0\u306b\u53c2\u52a0 -button.refresh = \u66f4\u65b0 -button.find = \u691c\u7d22 -button.update = \u66f4\u65b0 -button.cancel = \u30ad\u30e3\u30f3\u30bb\u30eb -button.decline = \u8f9e\u9000 -button.join = \u53c2\u52a0 -button.save.for.future.use = \u5229\u7528\u306e\u305f\u3081\u306e\u4fdd\u5b58 -button.register = \u767b\u9332 -button.dial.number = \u30c0\u30a4\u30a2\u30eb\u756a\u53f7 -button.clear = \u30af\u30ea\u30a2 -button.search = \u691c\u7d22 -button.add.service = \u30b5\u30fc\u30d3\u30b9\u8ffd\u52a0 -button.quit = \u7d42\u4e86 -button.new = \u65b0\u898f -button.add.user = \u30e6\u30fc\u30b6\u8ffd\u52a0 -button.save = \u4fdd\u5b58 -button.start.chat = \u30c1\u30e3\u30c3\u30c8 -button.send.email = \u30e1\u30fc\u30eb -button.send = \u9001\u308b - - - -checkbox.save.password = \u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u4fdd\u5b58 -checkbox.auto.login = \u30aa\u30fc\u30c8\u30ed\u30b0\u30a4\u30f3 -checkbox.use.proxy.server = \u30d7\u30ed\u30ad\u30b7\u30fc\u30b5\u30fc\u30d0\u30fc\u3092\u4f7f\u3046 -checkbox.auto.discover.port = \u81ea\u52d5\u7684\u306b\u30db\u30b9\u30c8\u3092\u898b\u3064\u3051\u308b -checkbox.permanent = \u6c38\u7d9a\u7684\u306a\u30eb\u30fc\u30e0 -checkbox.private.room = \u30d7\u30e9\u30a4\u30d9\u30fc\u30c8\u306a\u30eb\u30fc\u30e0 -checkbox.show.time.in.chat.window = \u30c1\u30e3\u30c3\u30c8\u30a6\u30a3\u30f3\u30c9\u30a6\u5185\u3067\u306e\u6642\u9593\u306e\u8868\u793a -checkbox.show.notifications.in.conference = \u4f1a\u8b70\u5ba4\u3067\u901a\u77e5\u3092\u8868\u793a -checkbox.disable.chat.history = \u30c1\u30e3\u30c3\u30c8\u5c65\u6b74\u306e\u7121\u52b9\u5316 -checkbox.show.toaster = \u30c8\u30fc\u30b9\u30c8\u30dd\u30c3\u30d7\u30a2\u30c3\u30d7\u3092\u8868\u793a -checkbox.window.to.front = \u30a6\u30a3\u30f3\u30c9\u30a6\u3092\u524d\u306b\u8868\u793a -checkbox.play.sound.on.new.message = \u65b0\u3057\u3044\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u5c4a\u3044\u305f\u3089\u901a\u77e5\u97f3\u3092\u9cf4\u3089\u3059 -checkbox.play.sound.when.offline = \u30e6\u30fc\u30b6\u304c\u30aa\u30d5\u30e9\u30a4\u30f3\u306b\u306a\u3063\u305f\u3089\u901a\u77e5\u97f3\u3092\u9cf4\u3089\u3059 -checkbox.play.sound.on.outgoing.message = \u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u9001\u308c\u305f\u3089\u901a\u77e5\u97f3\u3092\u9cf4\u3089\u3059 -checkbox.play.sound.on.invitation = \u62db\u5f85\u3092\u53d7\u3051\u305f\u3089\u901a\u77e5\u97f3\u3092\u9cf4\u3089\u3059 -checkbox.idle.enabled = \u30a2\u30a4\u30c9\u30eb\u3092\u6709\u52b9\u306b\u3059\u308b -checkbox.launch.on.startup = \u30b9\u30bf\u30fc\u30c8\u30a2\u30c3\u30d7\u3068\u540c\u6642\u306b\u8d77\u52d5\u3059\u308b -checkbox.start.in.tray = \u30b7\u30b9\u30c6\u30e0\u30c8\u30ec\u30a4\u3067\u30b9\u30bf\u30fc\u30c8 -checkbox.split.chat.window = \u30a6\u30a3\u30f3\u30c9\u30a6\u3092\u30c9\u30c3\u30af\u306b\u5165\u308c\u308b (\u518d\u8d77\u52d5\u304c\u5fc5\u8981) -checkbox.tabs.on.top = \u30c1\u30e3\u30c3\u30c8\u30bf\u30d6\u3092\u30c8\u30c3\u30d7\u306b\u8868\u793a (\u518d\u8d77\u52d5\u304c\u5fc5\u8981) -checkbox.allow.buzz = \u901a\u77e5\u97f3\u3092\u8a31\u53ef\u3059\u308b -checkbox.enable.emoticons = \u30a2\u30a4\u30b3\u30f3\u3092\u6709\u52b9\u306b\u3059\u308b -checkbox.use.system.look.and.feel = \u30b7\u30b9\u30c6\u30e0\u306e\u30eb\u30c3\u30af\uff06\u30d5\u30a3\u30fc\u30eb\u3092\u7528\u3044\u308b (\u518d\u8d77\u52d5\u304c\u5fc5\u8981) - - -label.user.on.public.network = \u30e6\u30fc\u30b6\u304c\u30d1\u30d6\u30ea\u30c3\u30af\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306b\u3044\u308b -label.change.password.to = \u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5909\u66f4 -label.username = \u30e6\u30fc\u30b6\u540d -label.name = \u540d\u524d -label.room.name = \u30eb\u30fc\u30e0\u540d -label.room.topic= \u30eb\u30fc\u30e0\u30c8\u30d4\u30c3\u30af -label.password = \u30d1\u30b9\u30ef\u30fc\u30c9 -label.confirm.password = \u30d1\u30b9\u30ef\u30fc\u30c9\u78ba\u8a8d -label.server = \u30b5\u30fc\u30d0\u30fc -label.create.account = \u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u4f5c\u6210 -label.close = \u9589\u3058\u308b -label.ok = OK -label.cancel = \u30ad\u30e3\u30f3\u30bb\u30eb -label.use.default = \u30c7\u30d5\u30a9\u30eb\u30c8\u3092\u7528\u3044\u308b -label.port = \u30dd\u30fc\u30c8 -label.auto.login = \u81ea\u52d5\u7684\u306b\u30ed\u30b0\u30a4\u30f3 -label.old.ssl = \u53e4\u3044SSL\u30dd\u30fc\u30c8\u30e2\u30fc\u30c9\u3092\u7528\u3044\u308b -label.host = \u30db\u30b9\u30c8 -label.resource = \u30ea\u30bd\u30fc\u30b9 -label.protocol = \u30d7\u30ed\u30c8\u30b3\u30eb -label.accounts = \u30a2\u30ab\u30a6\u30f3\u30c8 -label.receieved = \u53d7\u4fe1\u3055\u308c\u307e\u3057\u305f -label.transfer.timeout = \u901a\u4fe1\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8(\u5206): -label.transfer.download.directory = \u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea: -label.find = \u691c\u7d22 -label.rename.to = \u65b0\u3057\u3044\u540d\u524d -label.contact.to.find = \u9023\u7d61\u5148\u3092\u63a2\u3059 -label.available.users.in.roster = \u540d\u7c3f\u306e\u30e6\u30fc\u30b6\u3092\u6709\u52b9 -label.time = \u6642\u9593: {0} -label.add.conference.service = \u4f1a\u8b70\u30b5\u30fc\u30d3\u30b9\u3092\u8ffd\u52a0 -label.add.jid = JID\u3092\u8ffd\u52a0 -label.message = \u30e1\u30c3\u30bb\u30fc\u30b8 -label.room = \u30eb\u30fc\u30e0 -label.invited.users = \u62db\u5f85\u3057\u305f\u30e6\u30fc\u30b6 -label.new.nickname = \u65b0\u3057\u3044\u30cb\u30c3\u30af\u30cd\u30fc\u30e0 -label.server.address = \u30b5\u30fc\u30d0\u30fc\u30a2\u30c9\u30ec\u30b9 -label.nickname = \u30cb\u30c3\u30af\u30cd\u30fc\u30e0 -label.presence = \u51fa\u5e2d -label.priority = \u91cd\u8981\u5ea6 -label.enter.address = \u30a2\u30c9\u30ec\u30b9\u3092\u5165\u529b -label.jabber.address = Jabber\u30a2\u30c9\u30ec\u30b9 -label.local.time = \u30ed\u30fc\u30ab\u30eb\u30bf\u30a4\u30e0 -label.software = \u30d7\u30ed\u30b0\u30e9\u30e0 -label.version = \u30d0\u30fc\u30b8\u30e7\u30f3 -label.os = \u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0 -label.number = \u756a\u53f7 -label.dial = \u30c0\u30a4\u30a2\u30eb -label.minutes.before.stale.chat = \u5229\u7528\u3055\u308c\u306a\u3044\u30eb\u30fc\u30e0\u304c\u4e0d\u6d3b\u767a\u306b\u306a\u308b\u307e\u3067\u306e\u6642\u9593\uff08\u5206\uff09 -label.company = \u4f1a\u793e -label.street.address = \u756a\u5730 -label.city = \u5e02\u533a\u753a\u6751 -label.state.and.province = \u90fd\u9053\u5e9c\u770c -label.postal.code = \u90f5\u4fbf\u756a\u53f7 -label.country = \u56fd -label.job.title = \u80a9\u66f8\u304d -label.department = \u90e8\u7f72 -label.phone = \u96fb\u8a71\u756a\u53f7 -label.fax = \u30d5\u30a1\u30c3\u30af\u30b9 -label.mobile = \u643a\u5e2f\u96fb\u8a71 -label.web.page = \u30db\u30fc\u30e0\u30da\u30fc\u30b8 -label.pager = \u30dd\u30b1\u30d9\u30eb -label.first.name = \u540d\u524d -label.middle.name = \u30df\u30c9\u30eb\u30cd\u30fc\u30e0 -label.last.name = \u59d3 -label.email.address = \u96fb\u5b50\u30e1\u30fc\u30eb -label.jid = &JID -label.search.service = \u30b5\u30fc\u30d3\u30b9\u691c\u7d22 -label.xmpp.port = &XMPP \u30dd\u30fc\u30c8 -label.response.timeout = \u30ec\u30b9\u30dd\u30f3\u30b9\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8 (\u79d2) -label.time.till.idle = \u30a2\u30a4\u30c9\u30eb\u307e\u3067\u306e\u6642\u9593 (\u5206) -label.jabber.id = &Jabber ID -label.group = \u30b0\u30eb\u30fc\u30d7 -label.enter.group.name = \u30b0\u30eb\u30fc\u30d7\u540d\u3092\u5165\u529b -label.network = \u30cd\u30c3\u30c8\u30ef\u30fc\u30af -label.unable.to.add.contact = \u9023\u7d61\u5148\u306e\u8ffd\u52a0\u304c\u4e0d\u53ef -label.conflict.error = \u65e2\u306b\u30b5\u30a4\u30f3\u30a4\u30f3\u306e\u5834\u5408\u306f\u30ed\u30b0\u30a4\u30f3\u4e0d\u53ef -label.message.style = \u30e1\u30c3\u30bb\u30fc\u30b8\u30b9\u30bf\u30a4\u30eb -label.emoticons = \u611f\u60c5\u30a2\u30a4\u30b3\u30f3 - - -message.username.error = \u30e6\u30fc\u30b6\u30fc\u540d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.password.error = \u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.confirmation.password.error = \u78ba\u8a8d\u7528\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.account.error = \u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u4f5c\u6210\u3059\u308b\u30b5\u30fc\u30d0\u30fc\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.registering = {0}\u3092\u767b\u9332\u4e2d\u3002\u3057\u3070\u3089\u304f\u304a\u5f85\u3061\u304f\u3060\u3055\u3044\u3001 -message.connection.failed = {0}\u306b\u63a5\u7d9a\u3067\u304d\u307e\u305b\u3093\u3002 -message.create.account = \u30a2\u30ab\u30a6\u30f3\u30c8\u304c\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 -message.already.exists = \u30a2\u30ab\u30a6\u30f3\u30c8\u304c\u65e2\u306b\u5b58\u5728\u3057\u307e\u3059\u3001\u5225\u306e\u30e6\u30fc\u30b6\u540d\u3067\u8a66\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.account.created = \u65b0\u3057\u3044\u30a2\u30ab\u30a6\u30f3\u30c8\u306f\u65e2\u306b\u4f5c\u6210\u6e08\u307f\u3067\u3059\u3002 -message.account.create = \u65b0\u3057\u3044\u30c1\u30e3\u30c3\u30c8\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u4f5c\u6210\u3059\u308b\u3002 -message.connecting.please.wait = \u63a5\u7d9a\u4e2d\u3002\u3057\u3070\u3089\u304f\u304a\u5f85\u3061\u304f\u3060\u3055\u3044\u3001 -message.supply.valid.timeout = \u6b63\u3057\u3044\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u6642\u9593\u3092\u8a2d\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.supply.valid.port = \u6b63\u3057\u3044\u30dd\u30fc\u30c8\u756a\u982d\u3092\u8a2d\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.supply.resource = \u6b63\u3057\u3044\u30ea\u30bd\u30fc\u30b9\u3092\u8a2d\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.current.status = \u73fe\u5728\u306e\u72b6\u614b\u3092\u307b\u304b\u306e\u30e6\u30fc\u30b6\u306b\u77e5\u3089\u305b\u3066\u304f\u3060\u3055\u3044\u3002 -message.disconnected.error = \u3042\u306a\u305f\u306e\u63a5\u7d9a\u306f\u30a8\u30e9\u30fc\u306b\u3088\u308a\u30af\u30ed\u30fc\u30ba\u3055\u308c\u307e\u3057\u305f\u3002 -message.disconnected.group.chat.error = \u3042\u306a\u305f\u306e\u63a5\u7d9a\u306f\u30a8\u30e9\u30fc\u306b\u3088\u308a\u30af\u30ed\u30fc\u30ba\u3055\u308c\u307e\u3057\u305f\u3002\u518d\u63a5\u7d9a\u5f8c\u306b\u518d\u5ea6\u53c2\u52a0\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.disconnected.conflict.error = \u3042\u306a\u305f\u306e\u63a5\u7d9a\u306f\u540c\u3058\u30e6\u30fc\u30b6\u304c\u5225\u306e\u5834\u6240\u304b\u3089\u30ed\u30b0\u30a4\u30f3\u3057\u305f\u3053\u3068\u306b\u3088\u308a\u30af\u30ed\u30fc\u30ba\u3055\u308c\u307e\u3057\u305f\u3002 -message.locked.workstation = \u30e6\u30fc\u30b6\u306e\u30ef\u30fc\u30af\u30b9\u30c6\u30fc\u30b7\u30e7\u30f3\u304c\u30ed\u30c3\u30af\u3055\u308c\u307e\u3057\u305f\u3002 -message.away.idle = \u30a2\u30a4\u30c9\u30eb\u72b6\u614b\u306b\u3088\u308a\u96e2\u5e2d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.default.error = \u30a8\u30e9\u30fc\u3092\u691c\u77e5\u3057\u307e\u3057\u305f\u3002support@jivesoftware.com.\u3078\u30ec\u30dd\u30fc\u30c8\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.new.message = {0}\u304b\u3089\u65b0\u3057\u3044\u30e1\u30c3\u30bb\u30fc\u30b8\u3067\u3059\u3002 -message.send.file.to.user = \u3053\u306e\u30e6\u30fc\u30b6\u306b\u30d5\u30a1\u30a4\u30eb\u3092\u9001\u4fe1\u3057\u307e\u3059\u3002 -message.send.picture = \u753b\u9762\u306e\u5185\u5bb9\u3092\u30ad\u30e3\u30d7\u30c1\u30e3\u3057\u3066\u9001\u308b\u3002 -message.sent.offline.files = \u30aa\u30d5\u30e9\u30a4\u30f3\u30d5\u30a1\u30a4\u30eb\u3092\u3061\u3087\u3046\u3069\u9001\u308a\u307e\u3057\u305f\u3002 -message.spark.secure = Spark \u306f\u30bb\u30ad\u30e5\u30a2\u30e2\u30fc\u30c9\u3067\u5b9f\u884c\u3057\u3066\u3044\u307e\u3059\u3002 -message.search.for.contacts = \u9023\u7d61\u5148\u3092\u691c\u7d22 -message.end.conversation = \u3053\u306e\u30bb\u30c3\u30b7\u30e7\u30f3\u3092\u7d42\u3048\u307e\u3059\u304b\uff1f -message.end.chat = \u3053\u306e\u30c1\u30e3\u30c3\u30c8\u3092\u7d42\u3048\u307e\u3059\u304b\uff1f -message.close.this.chat = \u3053\u306e\u30c1\u30e3\u30c3\u30c8\u3092\u9589\u3058\u308b\u3002 -message.close.other.chats = \u4ed6\u306e\u3059\u3079\u3066\u306e\u30c1\u30e3\u30c3\u30c8\u3092\u9589\u3058\u308b\u3002 -message.close.stale.chats = \u53e4\u3044\u30c1\u30e3\u30c3\u30c8\u3092\u9589\u3058\u308b\u3002 -message.last.message.received = \u6700\u7d42\u53d7\u4fe1\u30e1\u30c3\u30bb\u30fc\u30b8\u6642\u523b {0} -message.shared.group = \u5171\u6709\u30b0\u30eb\u30fc\u30d7 -message.is.shared.group = {0}\u306f\u5171\u6709\u30b0\u30eb\u30fc\u30d7\u3067\u3059\u3002 -message.delete.confirmation = {0}\u3092\u524a\u9664\u3057\u307e\u3059\u304b\uff1f -message.idle.for = {0}\u306e\u305f\u3081\u30a2\u30a4\u30c9\u30eb\u72b6\u614b -message.enter.broadcast.message = \u9078\u629e\u3057\u305f\u30e6\u30fc\u30b6\u3078\u306e\u30d6\u30ed\u30fc\u30c9\u30ad\u30e3\u30b9\u30c8\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.name.of.group = \u30b0\u30eb\u30fc\u30d7\u306e\u540d\u524d -message.approve.subscription = {0}\u306b\u540d\u7c3f\u306e\u767b\u9332\u3092\u8a31\u53ef\u3057\u307e\u3059\u304b\uff1f -message.add.user = \u540d\u7c3f\u306b\u30e6\u30fc\u30b6\u3092\u767b\u9332\u3057\u307e\u3059\u304b\uff1f -message.general.error = {0}\u306b\u3088\u308a\u3001\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u63a5\u7d9a\u304c\u51fa\u6765\u306a\u304f\u306a\u308a\u307e\u3057\u305f\u3002 -message.add.a.contact = \u9023\u7d61\u5148\u3092\u8ffd\u52a0 -message.generic.reconnect.message = \u30b5\u30fc\u30d0\u30fc\u3078\u306e\u63a5\u7d9a\u304c\u51fa\u6765\u306a\u304f\u306a\u308a\u307e\u3057\u305f\u3002\u518d\u5ea6\u30ed\u30b0\u30a4\u30f3\u3059\u308b\u306b\u306f\u3001\u518d\u63a5\u7d9a\u30dc\u30bf\u30f3\u3092\u62bc\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.select.one.or.more = \u540d\u7c3f\u304b\u3089\uff11\u4eba\u304b\u3089\u305d\u308c\u4ee5\u4e0a\u306e\u30e6\u30fc\u30b6\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.add.conference.service = \u4f1a\u8b70\u30b5\u30fc\u30d3\u30b9\u3092\u8ffd\u52a0 -message.service.already.exists = \u30b5\u30fc\u30d3\u30b9\u306f\u65e2\u306b\u30ea\u30b9\u30c8\u306b\u5728\u308a\u307e\u3059\u3002 -message.searching.please.wait = \u691c\u7d22\u4e2d\u3002\u3057\u3070\u3089\u304f\u304a\u5f85\u3061\u304f\u3060\u3055\u3044... -message.conference.service.error = \u4f1a\u8b70\u5ba4\u3092\u898b\u308b\u3051\u308b\u3053\u3068\u304c\u51fa\u6765\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -message.create.or.join.room = \u4f1a\u8b70\u5ba4\u3092\u4f5c\u6210\u307e\u305f\u306f\u53c2\u52a0\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.specify.name.error = \u6b63\u3057\u3044\u540d\u524d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.password.private.room.error = \u30d7\u30e9\u30a4\u30d9\u30fc\u30c8\u30eb\u30fc\u30e0\u306e\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.passwords.no.match = \u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u4e00\u81f4\u3057\u307e\u305b\u3093\u3002 -message.enter.valid.jid = \u6b63\u3057\u3044 Jabber ID \u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.please.join.in.conference = \u79c1\u3082\u4f1a\u8b70\u306b\u53c2\u52a0\u3055\u305b\u3066\u304f\u3060\u3055\u3044\u3002 -message.invite.users.to.conference = \u4f1a\u8b70\u5ba4\u306b\u30e6\u30fc\u30b6\u3092\u62db\u5f85\u3059\u308b\u3002 -message.specify.users.to.join.conference = \u3053\u306e\u4f1a\u8b70\u5ba4\u306b\u53c2\u52a0\u3059\u308b\u30e6\u30fc\u30b6\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.no.room.to.join.error = \u53c2\u52a0\u3059\u308b\u30eb\u30fc\u30e0\u304c\u3042\u308a\u307e\u305b\u3093\u3002 -message.participants.in.room = \u30eb\u30fc\u30e0\u306e\u95a2\u4fc2\u8005 -message.you.have.been.kicked = \u3042\u306a\u305f\u306f\u3053\u306e\u90e8\u5c4b\u304b\u3089\u8ffd\u3044\u51fa\u3055\u308c\u307e\u3057\u305f\u3002 -message.kicked.error = {0}\u3092\u3053\u306e\u90e8\u5c4b\u304b\u3089\u8ffd\u3044\u51fa\u3059\u3053\u3068\u304c\u3067\u304d\u307e\u305b\u3093\u3002 -message.you.have.been.banned = \u3042\u306a\u305f\u306f\u3053\u306e\u90e8\u5c4b\u304b\u3089\u7981\u6b62\u3055\u308c\u307e\u3057\u305f\u3002 -message.nickname.in.use = \u30cb\u30c3\u30af\u30cd\u30fc\u30e0\u304c\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u4ed6\u306e\u30cb\u30c3\u30af\u30cd\u30fc\u30e0\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.update.room.list = \u30eb\u30fc\u30e0\u4e00\u89a7\u3092\u66f4\u65b0\u3059\u308b\u3002 -message.join.conference.room = \u4f1a\u8b70\u5ba4\u306b\u53c2\u52a0\u3059\u308b\u3002 -message.select.add.room.to.add = \u30b5\u30fc\u30d3\u30b9\u30ea\u30b9\u30c8\u306b\u8ffd\u52a0\u3059\u308b\u30eb\u30fc\u30e0\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.bookmark.temporary.room.error = \u30c6\u30f3\u30dd\u30e9\u30ea\u30eb\u30fc\u30e0\u306f\u30d6\u30c3\u30af\u30de\u30fc\u30af\u3059\u308b\u3053\u3068\u304c\u51fa\u6765\u307e\u305b\u3093\u3002 -message.select.room.to.join = \u53c2\u52a0\u3059\u308b\u30eb\u30fc\u30e0\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.conference.info.error = \u4f1a\u8b70\u5ba4\u60c5\u5831\u3092\u691c\u7d22\u3059\u308b\u3053\u3068\u304c\u51fa\u6765\u307e\u305b\u3093\u3002\u5f8c\u307b\u3069\u8a66\u3057\u3066\u307f\u3066\u304f\u3060\u3055\u3044\u3002 -message.add.favorite.room = \u30eb\u30fc\u30e0\u3092\u304a\u6c17\u306b\u5165\u308a\u30ea\u30b9\u30c8\u306b\u8ffd\u52a0\u3059\u308b\u304b\u3001\u76f4\u63a5\u53c2\u52a0\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.select.room.to.enter = \u5165\u5ba4\u3059\u308b\u30eb\u30fc\u30e0\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.find.conference.services = \u4f1a\u8b70\u5ba4\u30b5\u30fc\u30d3\u30b9\u3092\u63a2\u3059\u3002 -message.specify.information.for.conference = \u4f1a\u8b70\u5ba4\u306e\u60c5\u5831\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.no.description.available = \u5229\u7528\u53ef\u80fd\u306a\u8a73\u7d30\u304c\u3042\u308a\u307e\u305b\u3093\u3002 -message.no.subject.available = \u5229\u7528\u53ef\u80fd\u306a\u8a71\u984c\u304c\u3042\u308a\u307e\u305b\u3093\u3002 -message.room.information.for = {0}\u306e\u305f\u3081\u306e\u30eb\u30fc\u30e0\u60c5\u5831 -message.view.information.about.this.user = \u3053\u306e\u30e6\u30fc\u30b6\u306e\u60c5\u5831\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.add.this.user.to.your.roster = \u3053\u306e\u30e6\u30fc\u30b6\u3092\u53cb\u9054\u30ea\u30b9\u30c8\u306b\u8ffd\u52a0\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.came.online = {0}\u306f{1}\u306e\u70ba\u30aa\u30d5\u30e9\u30a4\u30f3\u3067\u3059\u3002 -message.went.offline = {0}\u306f{1}\u306e\u70ba\u30aa\u30d5\u30e9\u30a4\u30f3\u306b\u306a\u308a\u307e\u3057\u305f\u3002 -message.offline.error = \u30e6\u30fc\u30b6\u306f\u30aa\u30d5\u30e9\u30a4\u30f3\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u53d7\u3051\u53d6\u308b\u3053\u3068\u306f\u51fa\u6765\u307e\u305b\u3093\u3002 -message.offline = \u30e6\u30fc\u30b6\u304c\u30aa\u30d5\u30e9\u30a4\u30f3\u3067\u3059\u3001\u6b21\u56de\u30e6\u30fc\u30b6\u304c\u30ed\u30b0\u30a4\u30f3\u3057\u305f\u6642\u306b\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u53d7\u3051\u53d6\u3089\u308c\u307e\u3059\u3002 -message.is.typing.a.message = {0}\u306f\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u5165\u529b\u3057\u3066\u3044\u307e\u3059... -message.enter.new.subject = \u65b0\u305f\u306a\u8a71\u984c\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.confirm.destruction.of.room = \u30eb\u30fc\u30e0\u3092\u7834\u68c4\u3059\u308b\u3053\u3068\u306f\u3059\u3079\u3066\u306e\u30e6\u30fc\u30b6\u3092\u3053\u306e\u30eb\u30fc\u30e0\u304b\u3089\u524a\u9664\u3059\u308b\u3053\u3068\u306b\u306a\u308a\u307e\u3059\u304c\u3001\u7834\u68c4\u3057\u307e\u3059\u304b\uff1f -message.room.destruction.reason = \u30eb\u30fc\u30e0\u3092\u7834\u68c4\u3059\u308b\u7406\u7531\u306f\u3042\u308a\u307e\u3059\u304b\uff1f -message.user.left.room = {0}\u306f\u9000\u51fa\u3057\u307e\u3057\u305f\u3002 -message.user.joined.room = {0}\u306f\u30eb\u30fc\u30e0\u306b\u53c2\u52a0\u3057\u307e\u3057\u305f\u3002 -message.chat.session.ended = \u30c1\u30e3\u30c3\u30c8\u30bb\u30c3\u30b7\u30e7\u30f3\u306f{0}\u3067\u7d42\u308f\u308a\u307e\u3057\u305f\u3002 -message.subject.change.error = \u3053\u306e\u30eb\u30fc\u30e0\u306e\u8a71\u984c\u306e\u5909\u66f4\u306f\u8a31\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 -message.forbidden.error = \u30b5\u30fc\u30d0\u30fc\u304c\u30a8\u30e9\u30fc\u3092\u8fd4\u3057\u307e\u3057\u305f\u3002 -message.room.destroyed = \u30eb\u30fc\u30e0\u306f\u4ee5\u4e0b\u306e\u7406\u7531\u3067\u524a\u9664\u3055\u308c\u307e\u3057\u305f: {0} -message.subject.has.been.changed.to = \u8a71\u984c\u306f{0}\u306b\u5909\u66f4\u3055\u308c\u307e\u3057\u305f\u3002 -message.user.kicked.from.room = {0}\u306f\u30eb\u30fc\u30e0\u304b\u3089\u8ffd\u3044\u51fa\u3055\u308c\u307e\u3057\u305f\u3002 -message.user.given.voice = {0}\u306f\u3053\u306e\u30eb\u30fc\u30e0\u3067\u767a\u8a00\u3092\u4e0e\u3048\u307e\u3057\u305f\u3002 -message.user.voice.revoked = \u767a\u8a00\u306f{0}\u306e\u305f\u3081\u306b\u53d6\u308a\u6d88\u3055\u308c\u307e\u3057\u305f\u3002 -message.user.banned = {0}\u306f\u3053\u306e\u30eb\u30fc\u30e0\u304b\u3089\u3001\u7981\u6b62\u3055\u308c\u307e\u3057\u305f\u3002 -message.user.granted.membership = {0}\u306f\u30e1\u30f3\u30d0\u30fc\u30b7\u30c3\u30d7\u3092\u4e0e\u3048\u3089\u308c\u3066\u3044\u307e\u3059\u3002 -message.user.revoked.membership = \u30e1\u30f3\u30d0\u30fc\u30b7\u30c3\u30d7\u306f{0}\u306e\u305f\u3081\u306b\u53d6\u308a\u6d88\u3055\u308c\u307e\u3057\u305f\u3002 -message.user.granted.moderator = {0}\u306f\u53f8\u4f1a\u8005\u6a29\u9650\u3092\u4e0e\u3048\u3089\u308c\u3066\u3044\u307e\u3059\u3002 -message.user.revoked.moderator = \u53f8\u4f1a\u8005\u7279\u6a29\u306f{0}\u306e\u305f\u3081\u306b\u53d6\u308a\u6d88\u3055\u308c\u307e\u3057\u305f\u3002 -message.user.granted.owner = {0}\u306f\u30aa\u30fc\u30ca\u30fc\u6a29\u9650\u3092\u4e0e\u3048\u3089\u308c\u3066\u3044\u307e\u3059\u3002 -message.user.revoked.owner = \u30aa\u30fc\u30ca\u30fc\u7279\u6a29\u306f{0}\u306e\u305f\u3081\u306b\u53d6\u308a\u6d88\u3055\u308c\u307e\u3057\u305f\u3002 -message.user.granted.admin = {0}\u306f\u7ba1\u7406\u8005\u6a29\u9650\u3092\u4e0e\u3048\u3089\u308c\u3066\u3044\u307e\u3059\u3002 -message.user.revoked.admin = \u7ba1\u7406\u8005\u7279\u6a29\u306f{0}\u306e\u305f\u3081\u306b\u53d6\u308a\u6d88\u3055\u308c\u307e\u3057\u305f\u3002 -message.user.nickname.changed = {0}\u306f{1}\u3068\u3057\u3066\u8b58\u5225\u3055\u308c\u307e\u3057\u305f\u3002 -message.your.kicked = {0}\u306b\u3088\u3063\u3066\u8ffd\u3044\u51fa\u3055\u308c\u307e\u3057\u305f\u3002 -message.your.voice.granted = \u3053\u306e\u30c1\u30e3\u30c3\u30c8\u306b\u5bfe\u3057\u3066\u767a\u8a00\u3092\u3057\u307e\u3057\u305f\u3002 -message.your.voice.revoked = \u3042\u306a\u305f\u306e\u767a\u8a00\u306f\u53d6\u308a\u6d88\u3055\u308c\u307e\u3057\u305f\u3002 -message.your.banned = \u3042\u306a\u305f\u306f\u3053\u306e\u30eb\u30fc\u30e0\u304b\u3089\u7981\u6b62\u3055\u308c\u307e\u3057\u305f\u3002 -message.your.membership.granted = \u30e1\u30f3\u30d0\u30fc\u30b7\u30c3\u30d7\u304c\u4e0e\u3048\u3089\u308c\u307e\u3057\u305f\u3002 -message.your.membership.revoked = \u30e1\u30f3\u30d0\u30fc\u30b7\u30c3\u30d7\u304c\u53d6\u308a\u6d88\u3055\u308c\u307e\u3057\u305f\u3002 -message.your.moderator.granted = \u53f8\u4f1a\u8005\u6a29\u9650\u304c\u4e0e\u3048\u3089\u308c\u307e\u3057\u305f\u3002 -message.your.moderator.revoked = \u53f8\u4f1a\u8005\u6a29\u9650\u304c\u53d6\u308a\u6d88\u3055\u308c\u307e\u3057\u305f\u3002 -message.your.ownership.granted = \u30aa\u30fc\u30ca\u30fc\u6a29\u9650\u304c\u4e0e\u3048\u3089\u308c\u307e\u3057\u305f\u3002 -message.your.ownership.revoked = \u30aa\u30fc\u30ca\u30fc\u6a29\u9650\u304c\u53d6\u308a\u6d88\u3055\u308c\u307e\u3057\u305f\u3002 -message.your.admin.granted = \u7ba1\u7406\u6a29\u9650\u304c\u4e0e\u3048\u3089\u308c\u307e\u3057\u305f\u3002 -message.your.revoked.granted = \u7ba1\u7406\u6a29\u9650\u304c\u53d6\u308a\u6d88\u3055\u308c\u307e\u3057\u305f\u3002 -message.send.a.broadcast = \u30d6\u30ed\u30fc\u30c9\u30ad\u30e3\u30b9\u30c8\u3092\u9001\u4fe1\u3057\u307e\u3057\u305f\u3002 -message.broadcast.from = {0}\u304b\u3089\u30d6\u30ed\u30fc\u30c9\u30ad\u30e3\u30b9\u30c8\u3055\u308c\u307e\u3057\u305f\u3002 -message.enter.message.to.broadcast = \u540d\u7c3f\u4e00\u89a7\u3078\u306e\u30d6\u30ed\u30fc\u30c9\u30ad\u30e3\u30b9\u30c8\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.broadcast.message.sent = \u30d6\u30ed\u30fc\u30c9\u30ad\u30e3\u30b9\u30c8\u30e1\u30c3\u30bb\u30fc\u30b8\u306f\u9001\u4fe1\u3055\u308c\u307e\u3057\u305f\u3002 -message.broadcast.to = {0}\u3078\u306e\u30d6\u30ed\u30fc\u30c9\u30ad\u30e3\u30b9\u30c8\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.broadcasted.to = \u30e1\u30c3\u30bb\u30fc\u30b8\u306f\u4ee5\u4e0b\u306e\u30e6\u30fc\u30b6\u306b\u30d6\u30ed\u30fc\u30c9\u30ad\u30e3\u30b9\u30c8\u3055\u308c\u307e\u3057\u305f\u3002\n{0} -message.user.now.available.to.chat = {0}\u306f{1}\u3067\u30aa\u30f3\u30e9\u30a4\u30f3\u4e2d -message.user.is.sending.you.a.file = {0}\u306f\u30d5\u30a1\u30a4\u30eb\u3092\u3042\u306a\u305f\u306b\u9001\u4fe1\u3057\u3066\u3044\u307e\u3059\u3002 -message.file.transfer.canceled = \u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u3092\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u307e\u3057\u305f\u3002 -message.negotiate.file.transfer = \u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u3092\u4ea4\u6e09\u4e2d\u3002\u3057\u3070\u3089\u304f\u304a\u5f85\u3061\u304f\u3060\u3055\u3044... -message.negotiate.stream = \u30b3\u30cd\u30af\u30b7\u30e7\u30f3\u30b9\u30c8\u30ea\u30fc\u30e0\u3092\u4ea4\u6e09\u4e2d\u3002\u3057\u3070\u3089\u304f\u304a\u5f85\u3061\u304f\u3060\u3055\u3044... -message.receiving.file = {0}\u304b\u3089\u30d5\u30a1\u30a4\u30eb\u3092\u53d7\u4fe1\u4e2d -message.click.to.open = \u30af\u30ea\u30c3\u30af\u3067\u958b\u304f -message.error.during.file.transfer = \u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u8d77\u3053\u308a\u307e\u3057\u305f\u3002 -message.transfer.refused = \u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u306f\u62d2\u5426\u3055\u308c\u307e\u3057\u305f\u3002 -message.transfer.cancelled = \u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u306f\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f\u3002 -message.received.file = {0}\u304b\u3089\u30d5\u30a1\u30a4\u30eb\u3092\u53d7\u4fe1\u3057\u307e\u3057\u305f\u3002 -message.file.exists.question = \u30d5\u30a1\u30a4\u30eb\u306f\u65e2\u306b\u5b58\u5728\u3057\u3066\u3044\u307e\u3059\u3002\u4e0a\u66f8\u304d\u307e\u3059\u304b\uff1f -message.transfer.waiting.on.user = {0}\u304c\u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u3092\u8a31\u53ef\u3059\u308b\u306e\u3092\u5f85\u3063\u3066\u3044\u307e\u3059\u3002 -message.negotiation.file.transfer = {0}\u3078\u306e\u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u3092\u4ea4\u6e09\u4e2d\u3002\u3057\u3070\u3089\u304f\u304a\u5f85\u3061\u304f\u3060\u3055\u3044... -message.unable.to.send.file = {0}\u3078\u30d5\u30a1\u30a4\u30eb\u9001\u4fe1\u304c\u51fa\u6765\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -message.sending.file.to = {0}\u3078\u30d5\u30a1\u30a4\u30eb\u3092\u9001\u4fe1\u4e2d\u3002 -message.you.have.sent = {0}\u306b\u30d5\u30a1\u30a4\u30eb\u3092\u9001\u4fe1\u3057\u307e\u3057\u305f\u3002 -message.file.transfer.rejected = {0}\u306f\u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u3092\u62d2\u5426\u3057\u3066\u3044\u307e\u3059\u3002 -message.disable.transport = {0}\u306e\u30ed\u30b0\u30a4\u30f3\u60c5\u5831\u3092\u524a\u9664\u3057\u3066\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f -message.register.transports = \u5229\u7528\u53ef\u80fd\u306a\u901a\u4fe1\u3092\u8a2d\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.enter.aim = AIM\u306e\u30e6\u30fc\u30b6\u540d\u3068\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.enter.msn = MSN\u306e\u30e6\u30fc\u30b6\u540d\u3068\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.enter.yahoo = Yahoo\u306e\u30e6\u30fc\u30b6\u540d\u3068\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.enter.icq = ICQ\u306e\u30e6\u30fc\u30b6\u540d\u3068\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.username.password.error = \u30e6\u30fc\u30b6\u540d\u3068\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u8a2d\u5b9a\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 -message.registration.transport.failed = \u30b2\u30fc\u30c8\u30a6\u30a8\u30a4\u306e\u767b\u9332\u304c\u51fa\u6765\u307e\u305b\u3093\u3002 -message.client.information = {0}\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u60c5\u5831 -message.calling = {0}\u3092\u547c\u3073\u51fa\u3057\u4e2d -message.number.to.call = \u30c0\u30a4\u30a2\u30eb\u3059\u308b\u756a\u53f7\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.no.caller.id = \u5229\u7528\u53ef\u80fd\u306a\u767a\u4fe1\u8005ID\u304c\u3042\u308a\u307e\u305b\u3093\u3002 -message.no.history.found = \u3053\u306e\u30e6\u30fc\u30b6\u306e\u4f1a\u8a71\u30ed\u30b0\u304c\u3042\u308a\u307e\u305b\u3093\u3002 -message.prompt.plugin.uninstall = {0}\u3092\u30a2\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u307e\u3059\u3001\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f -message.restart.spark.changes = Spark\u3092\u518d\u8d77\u52d5\u5f8c\u306b\u30d7\u30e9\u30b0\u30a4\u30f3\u304c\u6709\u52b9\u306b\u306a\u308a\u307e\u3059\u3002 -message.loading.please.wait = \u30ed\u30fc\u30c9\u4e2d\u3002\u3057\u3070\u3089\u304f\u304a\u5f85\u3061\u304f\u3060\u3055\u3044... -message.plugins.not.available = \u30d7\u30e9\u30b0\u30a4\u30f3\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u63a5\u7d9a\u3067\u304d\u307e\u305b\u3093\u3002 -message.downloading = {0}\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d -message.downloading.spark.plug = Spark-Plug\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d -message.unable.to.save.password = \u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5909\u66f4\u3067\u304d\u307e\u305b\u3093\u3002\u30b5\u30fc\u30d0\u30fc\u3092\u3082\u3046\u4e00\u5ea6\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.delete.all.history = \u3059\u3079\u3066\u306e\u4f1a\u8a71\u30ed\u30b0\u3092\u524a\u9664\u3057\u307e\u3059\u304b\uff1f -message.no.avatar.found = \u30a2\u30d0\u30bf\u30fc\u7121\u3057\u306b\u8a2d\u5b9a\u3055\u308c\u307e\u3057\u305f\u3002 -message.image.too.large = \u3053\u306e\u753b\u50cf\u306f\u4f7f\u7528\u3059\u308b\u306e\u306b\u5927\u304d\u3059\u304e\u307e\u3059\u300216KB\u3088\u308a\u5c0f\u3055\u3044\u30b5\u30a4\u30ba\u3067\u8a2d\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.save.profile = \u3042\u306a\u305f\u306e\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u3092\u5909\u66f4\u4fdd\u5b58\u3059\u308b\u306b\u306f\u3001\u300c\u4fdd\u5b58\u300d\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.unable.to.load.profile = {0}\u306e\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u3092\u767b\u9332\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -message.enter.jabber.id = Jabber ID \u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.invalid.jabber.id = \u6b63\u3057\u3044 Jabber ID \u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 -message.vcard.not.supported = \u30b5\u30fc\u30d0\u306f VCards \u5f62\u5f0f\u3092\u30b5\u30dd\u30fc\u30c8\u3057\u307e\u305b\u3093\u3002\u3042\u306a\u305f\u306e VCard \u3092\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3002 -message.search.service.not.available = \u691c\u7d22\u30b5\u30fc\u30d3\u30b9\u306b\u63a5\u7d9a\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -message.no.results.found = \u30b5\u30fc\u30d0\u30fc\u304c\u691c\u7d22\u7d50\u679c\u3092\u4f55\u3082\u8fd4\u3057\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -message.name.of.search.service.question = \u691c\u7d22\u30b5\u30fc\u30d3\u30b9\u540d\u3067\u3059\u304b\uff1f -message.search.for.other.people = \u30b5\u30fc\u30d0\u4e0a\u3067\u307b\u304b\u306e\u4eba\u3092\u63a2\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.specify.valid.time.error = \u30dd\u30fc\u30c8\u3068\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u306f\u6b63\u3057\u304f\u8a2d\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.timeout.error = \u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u6642\u9593\u306f5\u79d2\u304b\u305d\u308c\u4ee5\u4e0a\u306e\u5024\u3067\u8a2d\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.version = \u30d0\u30fc\u30b8\u30e7\u30f3: {0} -message.file.size = \u30d5\u30a1\u30a4\u30eb\u30b5\u30a4\u30ba: {0} -message.restart.spark = \u6700\u65b0\u7248\u306e\u30bd\u30d5\u30c8\u30a6\u30a8\u30a2\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u305f\u3081\u306b\n\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u306b\u306a\u308a\u307e\u3059\u3002\u518d\u8d77\u52d5\u3057\u307e\u3059\u304b\uff1f -message.updating.cancelled = \u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u306f\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f\u3002 -message.transfer.rate = \u901a\u4fe1\u30ec\u30fc\u30c8 -message.total.downloaded = \u3059\u3079\u3066\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3055\u308c\u307e\u3057\u305f\u3002 -message.new.spark.available = {0}\u306f\u6709\u52b9\u3067\u3059\u3002\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u307e\u3059\u304b\uff1f -message.restart.spark.to.install = \u6700\u65b0\u7248\u306e\u30bd\u30d5\u30c8\u30a6\u30a8\u30a2\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u305f\u3081\u306b\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u3067\u3059\u3002\u518d\u8d77\u52d5\u3057\u307e\u3059\u304b\uff1f -message.add.to.roster = \u540d\u7c3f\u306b\u8ffd\u52a0 -message.enter.room.password = \u30eb\u30fc\u30e0\u306e\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.add.contact.to.list = \u3042\u306a\u305f\u306e\u9023\u7d61\u5148\u306b\u30e6\u30fc\u30b6\u3092\u8ffd\u52a0\u3057\u307e\u3057\u305f\u3002 -message.autenticating = \u30ed\u30b0\u30a4\u30f3\u4e2d -message.invalid.status = \u30b9\u30c6\u30fc\u30bf\u30b9\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u5165\u529b\u304c\u4e0d\u6b63\u3067\u3059\u3002 -message.cannot.add.contact.to.shared.group = \u5171\u6709\u30b0\u30eb\u30fc\u30d7\u3078\u306e\u9023\u7d61\u5148\u306e\u8ffd\u52a0\u304c\u51fa\u6765\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -message.specify.contact.jid = \u30b3\u30f3\u30bf\u30af\u30c8\u3059\u308b JID \u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 (\u4f8b ddman@jabber.org) -message.invalid.jid.error = JID \u304c\u4e0d\u6b63\u3067\u3059\u3002 -message.specify.group = \u65b0\u898f\u30e6\u30fc\u30b6\u3092\u8ffd\u52a0\u3059\u308b\u30b0\u30eb\u30fc\u30d7\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.room.creation.error = \u30eb\u30fc\u30e0\u306e\u4f5c\u6210\u304c\u51fa\u6765\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -message.unable.to.retrieve.last.activity = {0}\u306e\u6700\u5f8c\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u3092\u6c7a\u5b9a\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 - - -title.passwords.no.match = \u30d1\u30b9\u30ef\u30fc\u30c9\u78ba\u8a8d -title.create.problem = \u30a2\u30ab\u30a6\u30f3\u30c8\u4f5c\u6210\u306b\u95a2\u3059\u308b\u554f\u984c -title.account.created = \u30a2\u30ab\u30a6\u30f3\u30c8\u304c\u4f5c\u6210\u3055\u308c\u307e\u3057\u305f\u3002 -title.create.new.account = \u65b0\u898f\u30a2\u30ab\u30a6\u30f3\u30c8\u4f5c\u6210 -title.account.create.registration = \u30a2\u30ab\u30a6\u30f3\u30c8\u767b\u9332 -title.register.account = \u65b0\u3057\u3044\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u4f5c\u6210\u3059\u308b -title.notification = \u901a\u77e5 -title.advanced.connection.preferences = \u4e0a\u7d1a\u8005\u7528\u63a5\u7d9a\u8a2d\u5b9a -title.preferences = \u8a2d\u5b9a -title.error = \u30a8\u30e9\u30fc -title.status.message = \u30b9\u30c6\u30fc\u30bf\u30b9\u30e1\u30c3\u30bb\u30fc\u30b8 -title.spark.preferences = Spark\u8a2d\u5b9a -title.alert = \u30a2\u30e9\u30fc\u30c8 -title.tray.information = \u30c8\u30ec\u30a4\u60c5\u5831 -title.select.file.to.send = \u9001\u4fe1\u3059\u308b\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e -title.choose.directory = \u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u9078\u629e -title.confirmation = \u78ba\u8a8d -title.last.activity = \u6700\u5f8c\u306e\u884c\u52d5 -title.add.new.group = \u65b0\u898f\u30b0\u30eb\u30fc\u30d7\u3092\u8ffd\u52a0 -title.add.to.roster = \u540d\u7c3f\u306b\u8ffd\u52a0 -title.find.contacts = \u9023\u7d61\u5148\u3092\u63a2\u3059 -title.rename.roster.group = \u540d\u7c3f\u306e\u30b0\u30eb\u30fc\u30d7\u3092\u540d\u79f0\u5909\u66f4 -title.roster = \u540d\u7c3f -title.create.or.join = \u4f5c\u6210/\u53c2\u52a0 -title.conference.rooms = \u4f1a\u8b70\u5ba4 -title.invite.to.conference = \u4f1a\u8b70\u306b\u8a98\u3046 -title.room.information = \u30eb\u30fc\u30e0\u60c5\u5831 -title.change.nickname = \u30cb\u30c3\u30af\u30cd\u30fc\u30e0\u5909\u66f4 -title.group.chat = \u30b0\u30eb\u30fc\u30d7\u30c1\u30e3\u30c3\u30c8 -title.create.or.bookmark.room = \u30d6\u30c3\u30af\u30de\u30fc\u30af\u30eb\u30fc\u30e0\u306b\u53c2\u52a0\u3059\u308b\u3002 -title.browse.room.service = \u4f1a\u8b70\u5ba4\u53c2\u7167 - {0} -title.name = \u540d\u524d -title.address = \u30a2\u30c9\u30ec\u30b9 -title.occupants = \u4f4f\u4eba -title.browse.conference.services = \u4f1a\u8b70\u30b5\u30fc\u30d3\u30b9\u3092\u53c2\u7167\u3059\u308b\u3002 -title.find.conference.service = \u4f1a\u8b70\u30b5\u30fc\u30d3\u30b9\u3092\u691c\u7d22\u3059\u308b\u3002 -title.configure.chat.room = \u30c1\u30e3\u30c3\u30c8\u30eb\u30fc\u30e0\u3092\u8a2d\u5b9a\u3059\u308b\u3002 -title.conference.invitation = \u4f1a\u8b70\u306b\u8a98\u3046 -title.join.conference.room = \u4f1a\u8b70\u5ba4\u306b\u53c2\u52a0\u3059\u308b\u3002 -title.view.room.information = \u30eb\u30fc\u30e0\u60c5\u5831\u3092\u53c2\u7167\u3059\u308b\u3002 -title.configure.room = \u30eb\u30fc\u30e0\u3092\u8a2d\u5b9a\u3059\u308b\u3002 -title.change.subject = \u8a71\u984c\u3092\u5909\u3048\u308b -title.enter.reason = \u7406\u7531\u3092\u5165\u529b -title.room.destroyed = \u30eb\u30fc\u30e0\u306f\u7834\u68c4\u3055\u308c\u307e\u3057\u305f\u3002 -title.edit.custom.message = \u30ab\u30b9\u30bf\u30e0\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u7de8\u96c6\u3059\u308b\u3002 -title.set.status.message = \u72b6\u614b\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u8a2d\u5b9a\u3059\u308b\u3002 -title.broadcast.message = \u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u30d6\u30ed\u30fc\u30c9\u30ad\u30e3\u30b9\u30c8\u3059\u308b\u3002 -title.start.chat = \u30c1\u30e3\u30c3\u30c8\u958b\u59cb -title.view.bookmarks = \u30d6\u30c3\u30af\u30de\u30fc\u30af\u3092\u53c2\u7167 -title.downloads = \u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 -title.file.exists = \u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728 -title.disable.transport = \u30ed\u30b0\u30a4\u30f3\u60c5\u5831\u3092\u7834\u68c4 -title.available.transports = \u5229\u7528\u53ef\u80fd\u306a\u901a\u4fe1 -title.transports = \u901a\u4fe1 -title.aim.registration = AIM \u30a2\u30ab\u30a6\u30f3\u30c8\u8a3c\u660e\u66f8 -title.msn.registration = MSN \u30a2\u30ab\u30a6\u30f3\u30c8\u8a3c\u660e\u66f8 -title.yahoo.registration = Yahoo \u30a2\u30ab\u30a6\u30f3\u30c8\u8a3c\u660e\u66f8 -title.icq.registration = ICQ \u30a2\u30ab\u30a6\u30f3\u30c8\u8a3c\u660e\u66f8 -title.registration.error = \u767b\u9332\u30a8\u30e9\u30fc -title.jabber.browser = \u30d6\u30e9\u30a6\u30b6 -title.version.and.time = \u30d0\u30fc\u30b8\u30e7\u30f3\u3068\u6642\u9593 -title.waiting.to.call = \u7740\u4fe1\u5f85\u3061 -title.incoming.call = \u7740\u4fe1 -title.on.the.phone = \u96fb\u8a71\u306b\u95a2\u3057\u3066 -title.dial.phone = \u30c0\u30a4\u30a2\u30eb\u30d5\u30a9\u30f3 -title.history.for = {0}\u306e\u4f1a\u8a71\u5c65\u6b74 -title.reminder = \u30ea\u30de\u30a4\u30f3\u30c0 -title.plugins = \u30d7\u30e9\u30b0\u30a4\u30f3 -title.general.chat.settings = \u30c1\u30e3\u30c3\u30c8\u8a2d\u5b9a -title.chat = \u30c1\u30e3\u30c3\u30c8 -title.notifications = \u901a\u77e5 -title.sound.preferences = \u30b5\u30a6\u30f3\u30c9\u8a2d\u5b9a -title.sounds = \u30b5\u30a6\u30f3\u30c9 -title.choose.incoming.sound = \u5165\u5ba4\u6642\u306e\u30b5\u30a6\u30f3\u30c9\u3092\u9078\u629e -title.choose.outgoing.sound = \u9000\u51fa\u6642\u306e\u30b5\u30a6\u30f3\u30c9\u3092\u9078\u629e -title.choose.offline.sound = \u30aa\u30d5\u30e9\u30a4\u30f3\u6642\u306e\u30b5\u30a6\u30f3\u30c9\u3092\u9078\u629e -title.edit.profile = \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u60c5\u5831\u3092\u7de8\u96c6\u3059\u308b\u3002 -title.profile.information = \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u60c5\u5831 -title.profile.not.found = \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 -title.view.profile.for = {0}\u306e\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u3092\u53c2\u7167\u4e2d -title.lookup.profile = \u30eb\u30c3\u30af\u30a2\u30c3\u30d7\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb -title.add.search.service = \u691c\u7d22\u30b5\u30fc\u30d3\u30b9\u8ffd\u52a0 -title.person.search = \u4eba\u7269\u691c\u7d22 -title.login.settings = \u30ed\u30b0\u30a4\u30f3\u8a2d\u5b9a -title.login = \u30ed\u30b0\u30a4\u30f3 -title.downloading.im.client = IM \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 -title.upgrading.client = \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3092\u30a2\u30c3\u30d7\u30b0\u30ec\u30fc\u30c9\u4e2d -title.cancelled = \u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f\u3002 -title.new.version.available = \u65b0\u898f\u30d0\u30fc\u30b8\u30e7\u30f3\u304c\u5229\u7528\u53ef\u80fd\u3067\u3059\u3002 -title.new.client.available = \u65b0\u898f\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u5229\u7528\u53ef\u80fd\u3067\u3059\u3002 -title.password = \u30d1\u30b9\u30ef\u30fc\u30c9 -title.download.complete = \u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u5b8c\u4e86 -title.new.roster.group = \u65b0\u898f\u540d\u7c3f\u30b0\u30eb\u30fc\u30d7 -title.add.contact.group = \u9023\u7d61\u5148\u30b0\u30eb\u30fc\u30d7\u3092\u8ffd\u52a0 -title.add.contact = \u9023\u7d61\u5148\u3092\u8ffd\u52a0 -title.file.transfer.preferences = \u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u8a2d\u5b9a -title.file.transfer = \u30d5\u30a1\u30a4\u30eb\u8ee2\u9001 - -menuitem.contacts = \u9023\u7d61\u5148 -menuitem.actions = \u30a2\u30af\u30b7\u30e7\u30f3 -menuitem.exit = \u7d42\u4e86 -menuitem.plugins = \u30d7\u30e9\u30b0\u30a4\u30f3 -menuitem.logout.no.status = \u30ed\u30b0\u30a2\u30a6\u30c8 -menuitem.logout.with.status = \u308f\u3051\u3042\u3063\u3066\u30ed\u30b0\u30a2\u30a6\u30c8 -menuitem.show.traffic = \u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u30a6\u30a3\u30f3\u30c9\u30a6\u306e\u8868\u793a -menuitem.check.for.updates = \u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u306e\u30c1\u30a7\u30c3\u30af -menuitem.help = \u30d8\u30eb\u30d7 -menuitem.preferences = \u8a2d\u5b9a -menuitem.about = \u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u306b\u3064\u3044\u3066 -menuitem.online.help = \u30aa\u30f3\u30e9\u30a4\u30f3\u30d8\u30eb\u30d7 -menuitem.open = \u958b\u304f -menuitem.hide = \u96a0\u3059 -menuitem.status = \u30b9\u30c6\u30fc\u30bf\u30b9 -menuitem.view.downloads = \u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3092\u898b\u308b -menuitem.save = \u4fdd\u5b58 -menuitem.add = \u8ffd\u52a0 -menuitem.add.contact = \u9023\u7d61\u5148\u3092\u8ffd\u52a0 -menuitem.add.contact.group = \u9023\u7d61\u5148\u30b0\u30eb\u30fc\u30d7\u3092\u8ffd\u52a0 -menuitem.remove.from.group = \u30b0\u30eb\u30fc\u30d7\u304b\u3089\u524a\u9664 -menuitem.start.a.chat = \u30c1\u30e3\u30c3\u30c8\u958b\u59cb -menuitem.rename = \u540d\u79f0\u5909\u66f4 -menuitem.delete = \u524a\u9664 -menuitem.edit = \u7de8\u96c6 -menuitem.remove.from.roster = \u540d\u7c3f\u304b\u3089\u524a\u9664 -menuitem.view.profile = \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u53c2\u7167 -menuitem.subscribe.to = \u7f72\u540d\u3059\u308b -menuitem.send.a.message = \u9078\u629e\u3057\u305f\u30e6\u30fc\u30b6\u306b\u898b\u51fa\u3057\u3092\u9001\u4fe1\u3059\u308b... -menuitem.show.empty.groups = \u7a7a\u306e\u30b0\u30eb\u30fc\u30d7\u3092\u53c2\u7167 -menuitem.send.a.file = \u30d5\u30a1\u30a4\u30eb\u3092\u9001\u308b -menuitem.view.last.activity = \u6700\u5f8c\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u3092\u53c2\u7167 -menuitem.unban = \u89e3\u7981\u3059\u308b -menuitem.ban = \u7981\u6b62\u3059\u308b -menuitem.browse.service = \u30b5\u30fc\u30d3\u30b9\u3092\u898b\u308b -menuitem.remove.service = \u30b5\u30fc\u30d3\u30b9\u3092\u524a\u9664 -menuitem.join.room = \u30eb\u30fc\u30e0\u306b\u53c2\u52a0 -menuitem.remove.bookmark = \u30d6\u30c3\u30af\u30de\u30fc\u30af\u3092\u524a\u9664 -menuitem.join.on.startup = \u30b9\u30bf\u30fc\u30c8\u30a2\u30c3\u30d7\u6642\u306b\u53c2\u52a0 -menuitem.view.room.info = \u30eb\u30fc\u30e0\u306e\u60c5\u5831\u3092\u53c2\u7167 -menuitem.remove = \u524a\u9664 -menuitem.change.nickname = \u30cb\u30c3\u30af\u30cd\u30fc\u30e0\u3092\u5909\u66f4 -menuitem.block.user = \u30e6\u30fc\u30b6\u3092\u30d6\u30ed\u30c3\u30af -menuitem.unblock.user = \u30e6\u30fc\u30b6\u30d6\u30ed\u30c3\u30af\u3092\u89e3\u9664 -menuitem.kick.user = \u30e6\u30fc\u30b6\u3092\u8ffd\u3044\u51fa\u3059 -menuitem.voice = \u767a\u8a00 -menuitem.revoke.voice = \u767a\u8a00\u3092\u5ec3\u6b62 -menuitem.grant.voice = \u767a\u8a00\u3092\u627f\u8afe -menuitem.ban.user = \u30e6\u30fc\u30b6\u3092\u7981\u6b62\u3059\u308b\u3002 -menuitem.grant.moderator = \u53f8\u4f1a\u8005\u3092\u627f\u8afe -menuitem.revoke.moderator = \u53f8\u4f1a\u8005\u3092\u5ec3\u6b62 -menuitem.invite.users = \u30e6\u30fc\u30b6\u3092\u62db\u5f85 -menuitem.invite.group.to.conference = \u30b0\u30eb\u30fc\u30d7\u3092\u4f1a\u8b70\u306b\u62db\u5f85\u3059\u308b -menuitem.start.a.conference = \u4f1a\u8b70\u958b\u59cb... -menuitem.change.subject = \u8a71\u984c\u3092\u5909\u3048\u308b -menuitem.destroy.room = \u30eb\u30fc\u30e0\u3092\u5ec3\u6b62 -menuitem.set.status.message = \u30b9\u30c6\u30fc\u30bf\u30b9\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u30bb\u30c3\u30c8\u3059\u308b... -menuitem.edit.status.message = \u30b9\u30c6\u30fc\u30bf\u30b9\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u7de8\u96c6\u3059\u308b... -menuitem.broadcast.to.group = \u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u30b0\u30eb\u30fc\u30d7\u306b\u30d6\u30ed\u30fc\u30c9\u30ad\u30e3\u30b9\u30c8\u3059\u308b -menuitem.alert.when.online = \u30e6\u30fc\u30b6\u30fc\u304c\u6709\u52b9\u306b\u306a\u3063\u305f\u3089\u901a\u77e5\u3059\u308b -menuitem.remove.alert.when.online = \u901a\u77e5\u3092\u524a\u9664 -menuitem.save.as = \u5225\u540d\u3067\u4fdd\u5b58... -menuitem.view.client.version = \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u53c2\u7167 -menuitem.view.contact.history = \u9023\u7d61\u5c65\u6b74\u3092\u53c2\u7167 -menuitem.edit.my.profile = \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u3092\u7de8\u96c6... -menuitem.lookup.profile = \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u3092\u53c2\u7167... -menuitem.add.as.contact = \u9023\u7d61\u5148\u3068\u3057\u3066\u8ffd\u52a0 -menuitem.chat = \u30c1\u30e3\u30c3\u30c8 -menuitem.sign.in = \u30b5\u30a4\u30f3\u30a4\u30f3 -menuitem.sign.out = \u30b5\u30a4\u30f3\u30a2\u30a6\u30c8 -menuitem.sign.in.at.login = \u30ed\u30b0\u30a4\u30f3\u6642\u306b\u30b5\u30a4\u30f3\u30a4\u30f3 -menuitem.enter.login.information = \u30ed\u30b0\u30a4\u30f3\u60c5\u5831\u3092\u5165\u529b -menuitem.delete.login.information = \u30ed\u30b0\u30a4\u30f3\u60c5\u5831\u3092\u524a\u9664 -menuitem.show.offline.group = \u30aa\u30d5\u30e9\u30a4\u30f3\u30e6\u30fc\u30b6\u3092\u30b0\u30eb\u30fc\u30d7 -menuitem.move.to = \u79fb\u52d5 -menuitem.copy.to = \u30b3\u30d4\u30fc - -tree.conference.services = \u4f1a\u8b70\u30b5\u30fc\u30d3\u30b9 -tree.users.in.room = \u30e6\u30fc\u30b6\u304c\u30eb\u30fc\u30e0\u306b\u3044\u307e\u3059 - -tab.general = \u4e00\u822c -tab.proxy = \u30d7\u30ed\u30ad\u30b7 -tab.contacts = \u9023\u7d61\u5148 -tab.installed.plugins = \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u6e08\u307f\u30d7\u30e9\u30b0\u30a4\u30f3 -tab.available.plugins = \u5229\u7528\u53ef\u80fd\u306a\u30d7\u30e9\u30b0\u30a4\u30f3 -tab.personal = \u500b\u4eba -tab.business = \u4ed5\u4e8b -tab.home = \u5bb6 -tab.avatar = \u30a2\u30d0\u30bf\u30fc -tab.conferences = \u4f1a\u8b70 - -group.connection = \u63a5\u7d9a -group.conferences.found = \u4f1a\u8b70\u30b5\u30fc\u30d3\u30b9\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f -group.comma.delimited = \u30b3\u30f3\u30de\u30c7\u30ea\u30df\u30bf -group.general.information = \u4e00\u822c\u60c5\u5831 -group.chat.window.information = \u30c1\u30e3\u30c3\u30c8\u30a6\u30a3\u30f3\u30c9\u30a6\u60c5\u5831 -group.notification.options = \u901a\u77e5\u30aa\u30d7\u30b7\u30e7\u30f3 -group.search.form = \u691c\u7d22\u958b\u59cb -group.search.results = \u691c\u7d22\u7d50\u679c -group.login.information = \u30ed\u30b0\u30a4\u30f3\u60c5\u5831 - -tooltip.place.a.call = \u3053\u306e\u4eba\u306b\u96fb\u8a71\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -tooltip.view.history = \u4f1a\u8a71\u5c65\u6b74\u53c2\u7167 -tooltip.view.changelog = \u5909\u66f4\u30ed\u30b0\u53c2\u7167 -tooltip.view.readme = ReadMe\u53c2\u7167 -tooltip.notifications = \u30c1\u30e3\u30c3\u30c8\u547c\u3073\u304b\u3051\u6642\u306e\u901a\u77e5\u8a2d\u5b9a -tooltip.place.voice.call = \u767a\u8a00\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -#!# \ No newline at end of file diff --git a/src/resources/i18n/spark_i18n_ko.properties b/src/resources/i18n/spark_i18n_ko.properties deleted file mode 100644 index 9a784eed0..000000000 --- a/src/resources/i18n/spark_i18n_ko.properties +++ /dev/null @@ -1,971 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.0.1 -## Added key: 'message.restart.spark.changes' -## Added key: 'message.enter.icq' -## Added key: 'title.icq.registration' -## Added key: 'button.quit' -## -## -## -## 2.0.2 -## Added key: 'button.new' -## Added key: 'label.group' -## Added key: 'label.jabber.id' -## Added key: 'label.enter.group.name' -## Added key: 'title.new.roster.group' -## Added key: 'title.add.contact.group' -## Added key: 'message.add.contact.to.list' -## Added key: 'title.add.contact' -## Added key: 'tab.conferences' -## Added key: 'message.autenticating' -## Added key: 'title.file.transfer.preferences' -## Added key: 'menuitem.about' -## Added key: 'message.invalid.status' -## Added key: 'message.cannot.add.contact.to.shared.group -## Added key: 'message.specify.contact.jid' -## Added key: 'message.invalid.jid.error' -## Added key: 'message.specify.group' -## Added key: 'add' -## -## -## -## 2.0.5 -## Added key: 'Broadcast' -## Added key: 'label.user.on.public.network' -## Added key: 'label.network' -## -## -## 2.0.6 -## Added key: 'button.add.user' -## Added key: 'menuitem.sign.in' -## Added key: 'menuitem.sign.out' -## Added key: 'menuitem.sign.in.at.login' -## Added key: 'menuitem.enter.login.information' -## Added key: 'menuitem.delete.login.information' -## Added key: 'button.save' -## -## -## 2.5 -## Added key: 'button.start.chat' -## Added key: 'button.send.email' -## Added key: 'available' -## Added key: 'checkbox.tabs.on.top' -## Added key: 'user.has.signed.in' -## Added key: 'user.has.signed.off' -## Added key: 'label.unable.to.add.contact' -## Added key: 'label.conflict.error' -## Added key: 'message.room.creation.error' -## Added key: 'checkbox.allow.buzz' -## Added key: 'message.disconnected.group.chat.error' -## Added key: 'menuitem.show.offline.group' -## Added key: 'menuitem.move.to' -## Added key: 'menuitem.copy.to' -## Added key: 'label.message.style' -## Added key: 'label.emoticons' -## Added key: 'checkbox.enable.emoticons' -## Added key: 'message.unable.to.retrieve.last.activity' -## Added key: 'checkbox.use.system.look.and.feel' -## -## 2.5.2 -## Added key: 'tooltip.place.voice.call' -## Added key: 'message.buzz.alert.notification' -## Added kye: 'message.buzz.sent' -## -## 2.5.2 -## Added key: 'menuitem.user.guide' -## -## -## -## 2.5.7 -## Added key: 'menuitem.languages' -## Added key: 'message.restart.required' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'message.send.to.these.people' -## Added key: 'message' -## Added key: 'message.normal' -## Added key: 'message.alert.notify' -## -## 2.5.8 -## Added key: 'message.enter.simple' -## Added key: 'message.enter.irc' -## Added key: 'message.enter.gadugadu' -## Added key: 'title.simple.registration' -## Added key: 'title.irc.registration' -## Added key: 'title.gadugadu.registration' -## Added key: 'message.username.error' -## Added key: 'message.password.error' -## Added key: 'message.nickname.error' -## -## 2.5.9 -## Added key: 'message.gateway.username.error. -## Added key: 'message.gateway.password.error. -## Added key: 'message.gateway.nickname.error. -## Added key: 'answer' -## Added key: 'online' -## Added key: 'online' -## Added key: 'offline' -## Added key: 'participants' -## Added key: 'unfiled' -## Added key: 'while.offline' -## Added key: 'action.clear' -## Added key: 'action.copy ' -## Added key: 'action.cut' -## Added key: 'action.paste' -## Added key: 'action.print' -## Added key: 'action.save' -## Added key: 'action.select.all' -## Added key: 'button.add2' -## Added key: 'button.copy.to.clipboard' -## Added key: 'button.reconnect2' -## Added key: 'button.tasks.active' -## Added key: 'button.tasks.all' -## Added key: 'button.view.notes' -## Added key: 'button.view.profile' -## Added key: 'button.view.tasklist' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.show.avatars.in.contaclist' -## Added key: 'checkbox.use.compression' -## Added key: 'group.empty' -## Added key: 'group.offline' -## Added key: 'label.add.task' -## Added key: 'label.chatroom.fontsize' -## Added key: 'label.contactlist.fontsize' -## Added key: 'label.due' -## Added key: 'label.show' -## Added key: 'label.timeformat' -## Added key: 'menuitem.dial' -## Added key: 'menuitem.view.logs' -## Added key: 'message.disconnected.shutdown' -## Added key: 'message.invalid.username.password' -## Added key: 'message.no.updates' -## Added key: 'message.reconnect.attempting' -## Added key: 'message.reconnect.failed' -## Added key: 'message.reconnect.wait' -## Added key: 'message.send.picture' -## Added key: 'message.server.unavailable' -## Added key: 'message.unrecoverable.error' -## Added key: 'message.waiting.for.user.to.join' -## Added key: 'status.available' -## Added key: 'status.away' -## Added key: 'status.custom.messages' -## Added key: 'status.do.not.disturb' -## Added key: 'status.extended.away' -## Added key: 'status.free.to.chat' -## Added key: 'status.on.phone' -## Added key: 'status.online' -## Added key: 'status.pending' -## Added key: 'title.about' -## Added key: 'title.appearance' -## Added key: 'title.appearance.preferences' -## Added key: 'title.login.error' -## Added key: 'title.no.updates' -## Added key: 'title.notes' -## Added key: 'title.tasks' -## Added key: 'tooltip.appearance' -## Added key: 'tooltip.file.transfer' -## Added key: 'tooltip.send.email' -## Added key: 'tooltip.start.chat' -## Added key: 'delete.log.permanently' -## Added key: 'delete.permanently' -## Added key: 'label.contactlist.avatarsize' -## Added key: 'title.qq.registration' -## Added key: 'message.enter.qq' -## -## 2.6.0 -## -## Added key: 'apply' -## Added key: 'title.subscription.request' -## Added key: 'label.add.to.roster' -## Added key: 'label.audio.device' -## Added key: 'label.video.device' -## Added key: 'button.re.detect' - - - -accept = \uc218\ub77d -active = \ud65c\uc131\ud654 -add = \ucd94\uac00 -answer = \ub300\ub2f5 -apply = \uc801\uc6a9 -available = \uc0ac\uc6a9\uac00\ub2a5 -broadcast = \ube0c\ub85c\ub4dc\ucf00\uc2a4\ud2b8 -cancel = \ucde8\uc18c -close = \ub2eb\uae30 -create = \uc0dd\uc131 -date = \ub0a0\uc9dc -description = \uc124\uba85 -from = \ubd80\ud130 -invite = \ucd08\ub300 -join = \ucc38\uc5ec -no = \uac70\uc808 -not.registered = \ub4f1\ub85d\ub418\uc9c0 \uc54a\uc74c -occupants = \uc778\uc6d0\uc218 -offline = \uc624\ud504\ub77c\uc778 -online = \uc628\ub77c\uc778 -ok = \ud655\uc778 -online = \uc628\ub77c\uc778 -open = \uc5f4\uae30 -open.folder = \ud3f4\ub354 \uc5f4\uae30 -participants = \ucc38\uc5ec\uc790 -reject = \uac70\uc808 -retry = \uc7ac\uc2dc\ub3c4 -room.name = \ub300\ud654\ubc29 \uc774\ub984 -save = \uc800\uc7a5 -subject = \uc8fc\uc81c -unfiled = .\uae30\ud0c0 -use.default = \uae30\ubcf8\uac12 -user.has.signed.in = has signed in. -user.has.signed.off = has signed off. -while.offline = \uc624\ud504\ub77c\uc778 \ub3d9\uc548 -yes = \uc608 - -action.clear = \uc9c0\uc6b0\uae30 -action.copy = \ubcf5\uc0ac -action.cut = \uc790\ub974\uae30 -action.paste = \ubd99\uc5ec\ub123\uae30 -action.print = \uc778\uc1c4 -action.save = \uc800\uc7a5 -action.select.all = \ubaa8\ub450 \uc120\ud0dd - -button.accept = \uc218\ub77d(&A) -button.reject = \uac70\uc808(&R) -button.add = \ucd94\uac00(&A) -button.add.a.contact = \uce5c\uad6c \ucd94\uac00(&A) -button.add.bookmark = \ubd81\ub9c8\ud06c \ucd94\uac00 -button.add.service = \uc11c\ube44\uc2a4 \ucd94\uac00(&A) -button.add.user = \uce5c\uad6c \ucd94\uac00(&A) -button.add2 = \ucd94\uac00(&D) -button.advanced = \uae30\ud0c0 \uc124\uc815 -button.approve = \uc2b9\uc778 -button.bookmark.room = \ucc45\uac08\ud53c \ubaa8\uc74c(&B) -button.browse = \ucc3e\uc544\ubcf4\uae30(&b)... -button.browse2 = \ucc3e\uc544\ubcf4\uae30... -button.browse3 = \ucc3e\uc544\ubcf4\uae30... -button.cancel = \ucde8\uc18c -button.clear = \uc9c0\uc6b0\uae30 -button.close = \ub2eb\uae30 -button.copy.to.clipboard = \ud074\ub9bd\ubcf4\ub4dc \ubcf5\uc0ac -button.create.account = \uacc4\uc815 \uc0dd\uc131 -button.create.room = \ub300\ud654\ubc29 \uc0dd\uc131/\ucc38\uc5ec -button.decline = &Decline -button.deny = \uac70\uc808 -button.dial.number = \uc804\ud654\ubc88\ud638 -button.find = \uac80\uc0c9 -button.join = \ucc38\uc5ec -button.join.room = \uc120\ud0dd\ud55c \ub300\ud654\ubc29 \ucc38\uc5ec -button.new = \uc0c8\ub85c\ud558\uae30 -button.profile = \ud504\ub85c\ud544 -button.quit = \ub098\uac00\uae30 -button.reconnect = \ub2e4\uc2dc \uc5f0\uacb0 -button.reconnect2 = \ub2e4\uc2dc \uc5f0\uacb0 -button.refresh = \uc0c8\ub85c\ud558\uae30 -button.register = \ub4f1\ub85d -button.remove.bookmark = \ucc45\uac08\ud53c \uc81c\uac70 -button.roster = \uce5c\uad6c \uc120\ud0dd -button.save = \uc800\uc7a5 -button.save.for.future.use = \ub2e4\uc74c\uc5d0 \uc0ac\uc6a9\ud558\uae30 \uc704\ud574 \uc800\uc7a5 -button.search = \uac80\uc0c9 -button.send = \ubcf4\ub0b4\uae30 -button.send.email = \uc774\uba54\uc77c -button.start.chat = \ub300\ud654 -button.tasks.active = \ud560\uc77c -button.tasks.all = \ubaa8\ub450 -button.unset.file.explorer = \ud30c\uc77c \ube0c\ub77c\uc6b0\uc800 \uc124\uc815\ud558\uc9c0 \uc54a\uc74c -button.update = \uc5c5\ub370\uc774\ud2b8 -button.view.notes = \uba54\ubaa8 \ubcf4\uae30 -button.view.profile = \ud504\ub85c\ud544 \ubaa8\ub450 \ubcf4\uae30 -button.view.tasklist = \uc791\uc5c5 \ub9ac\uc2a4\ud2b8 \ubcf4\uae30 -button.re.detect = \ub2e4\uc2dc \uac80\uc0c9 - -checkbox.allow.buzz = \ub0b4 \ucc44\ud305\ucc3d\uc744 \uc8fc\ubaa9\uc2dc\ud0ac \ubaa9\uc801\uc73c\ub85c \ud754\ub4dc\ub294 \uac83\uc744 \ud5c8\ub77d(&z) -checkbox.auto.discover.port = \uc790\ub3d9\uc73c\ub85c \ud638\uc2a4\ud2b8\uc640 \ud3ec\ud2b8\ubc88\ud638 \uc54c\uc544\ub0b4\uae30(&A) -checkbox.auto.login = \uc790\ub3d9 \ub85c\uadf8\uc778(&A) -checkbox.disable.chat.history = \ucc44\ud305 \uae30\ub85d\ud558\uc9c0 \uc54a\uc74c(&D) -checkbox.disable.prev.chat.history = \uc774\uc804 \ucc44\ud305 \uae30\ub85d \ubcf4\ub294 \uac83 \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc74c(&D) -checkbox.enable.emoticons = \uc774\ubaa8\ud2f0\ucf58 \uc0ac\uc6a9\ud558\uae30(&o) -checkbox.idle.enabled = \uc790\ub9ac\ube44\uc6c0 \uae30\ub2a5 -checkbox.launch.on.startup = \uc6b4\uc601\uccb4\uc81c \uc2dc\uc791\uc2dc \uc2e4\ud589 -checkbox.notify.user.comes.online = \uce5c\uad6c\uac00 \ub85c\uadf8\uc778\ud560\ub54c \uc54c\ub824\uc8fc\uae30 -checkbox.notify.user.goes.offline = \uce5c\uad6c\uac00 \uc624\ud504\ub77c\uc778\ud560\ub54c \uc54c\ub824\uc8fc\uae30 -checkbox.notify.typing.systemtray = \uc2dc\uc2a4\ud15c \ud2b8\ub808\uc774\uc5d0 \ud0c0\uc774\ud551 \uc54c\ub9bc \ubcf4\uc774\uae30 -checkbox.notify.systemtray = \uc2dc\uc2a4\ud15c \ud2b8\ub808\uc774\uc5d0 \uc0c8\uba54\uc2dc\uc9c0 \ubcf4\uc774\uae30 -checkbox.permanent = \uc601\uad6c\uc801\uc778 \ubc29\uc73c\ub85c \uc0dd\uc131(&p) -checkbox.play.sound.on.invitation = \ucd08\ub300\ub420\ub54c \uc18c\ub9ac \uc7ac\uc0dd -checkbox.play.sound.on.new.message = \uc0c8\ub85c\uc6b4 \uba54\uc2dc\uc9c0\uac00 \ub3c4\ucc29\ud560\ub54c \uc18c\ub9ac \uc7ac\uc0dd -checkbox.play.sound.on.outgoing.message = \uba54\uc2dc\uc9c0 \uc804\uc1a1\ub420\ub54c \uc18c\ub9ac \uc7ac\uc0dd -checkbox.play.sound.when.offline = \uce5c\uad6c\uac00 \uc624\ud504\ub77c\uc778\uc77c\ub54c \uc18c\ub9ac \uc7ac\uc0dd -checkbox.private.room = \ube44\uacf5\uac1c \ubc29\uc73c\ub85c \uc0dd\uc131(&I) -checkbox.save.password = \ube44\ubc00\ubc88\ud638 \uc800\uc7a5 -checkbox.show.avatars.in.contactlist = \uce5c\uad6c\ubaa9\ub85d\uc5d0 \uc544\ubc14\ud0c0 \ubcf4\uc774\uae30 -checkbox.show.notifications.in.conference = &\ud68c\uc758\uc2e4\uc5d0 \uc54c\ub9bc \ubcf4\uc774\uae30 -checkbox.show.time.in.chat.window = \ub300\ud654\ucc3d\uc5d0 \uc2dc\uac04\uc815\ubcf4 \ubcf4\uc774\uae30 -checkbox.show.toaster = \ud31d\uc5c5\uc73c\ub85c \ubcf4\uc774\uae30 -checkbox.split.chat.window = Dock &Windows (\ud504\ub85c\uadf8\ub7a8 \uc7ac\uc2dc\uc791\uc2dc \uc801\uc6a9) -checkbox.start.in.tray = \uc2dc\uc2a4\ud15c \ud2b8\ub808\uc774\uc5d0 \uc2dc\uc791 -checkbox.tabs.on.top = \ub300\ud654\ud0ed\uc774 \uc704\uc5d0 \ubcf4\uc784 (\ud504\ub85c\uadf8\ub7a8 \uc7ac\uc2dc\uc791\uc2dc \uc801\uc6a9) -checkbox.use.compression = \uc555\ucd95 \uc0ac\uc6a9 -checkbox.use.debugger.on.startup = Start &Debugger on startup -checkbox.use.proxy.server = Proxy \uc11c\ubc84 \uc0ac\uc6a9 -checkbox.use.system.look.and.feel = \uc2dc\uc2a4\ud15c \ud14c\ub9c8 \uc0ac\uc6a9 (\ud504\ub85c\uadf8\ub7a8 \uc7ac\uc2dc\uc791\uc2dc \uc801\uc6a9) -checkbox.window.to.front = \uc708\ub3c4\uc6b0\ub97c \uc55e\uc73c\ub85c \ubcf4\ub0b4\uae30 -checkbox.broadcast.hide.offline.user = \uc624\ud504\ub77c\uc778 \uce5c\uad6c \uc228\uae30\uae30 -checkbox.use.krbconf = Use krb5.conf or krb5.ini -checkbox.use.krb.dns = DNS \uc0ac\uc6a9 -checkbox.use.specify.below = \uc544\ub798 \uc785\ub825 -checkbox.use.pki.authentication = PKI \uc778\uc99d \uc0ac\uc6a9 - -delete.log.permanently = \uc601\uad6c\ud788 \ub85c\uadf8 \uc0ad\uc81c -delete.permanently = \uc601\uad6c\ud788 \uc0ad\uc81c\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? - -gateway.username.password.error = \uc544\uc774\ub514\ub098 \ube44\ubc00\ubc88\ud638\uac00 \uc785\ub825\ub418\uc5b4\uc57c \ud569\ub2c8\ub2e4. - -group.chat.window.information = \ub300\ud654\ucc3d \uc815\ubcf4 -group.comma.delimited = \ucf64\ub9c8(,)\ub85c \uad6c\ubd84\ub428 -group.conferences.found = \ud68c\uc758 \uc11c\ube44\uc2a4\ub97c \ucc3e\uc74c -group.connection = \uc5f0\uacb0 -group.empty = \uc774 \uadf8\ub8f9\uc5d0 \uc628\ub77c\uc778 \uce5c\uad6c\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. -group.general.information = \uc77c\ubc18 \uc815\ubcf4 -group.login.information = \ub85c\uadf8\uc778 \uc815\ubcf4 -group.notification.options = \uc54c\ub9bc \uc635\uc158 -group.offline = \uc624\ud504\ub77c\uc778 \uadf8\ub8f9 -group.search.form = \uac80\uc0c9\ud3fc -group.search.results = \uac80\uc0c9 \uacb0\uacfc -group.chat.name.notification = \uc774\ub984 \ubcf4\uc774\uae30... -group.chat.name.match = \ub2f9\uc2e0 \uc774\ub984\uc774 \uadf8\ub8f9\ub300\ud654\uc5d0\uc11c \ub9d0\ud574\uc84c\uc2b5\ub2c8\ub2e4. - -label.na = n/a -label.cell = \ud734\ub300\uc804\ud654 -label.work = \uadfc\ubb34\ucc98 -label.home = \uc9d1 -label.accounts = \uacc4\uc815 \uc0dd\uc131 -label.add.conference.service = \ud68c\uc758 \uc11c\ube44\uc2a4 \ucd94\uac00\ud558\uae30 -label.add.jid = JID \ucd94\uac00 -label.add.task = \uc791\uc5c5 \ucd94\uac00 -label.auto.login = \uc790\ub3d9 \ub85c\uadf8\uc778 -label.available.users.in.roster = \uac00\ub2a5\ud55c \uce5c\uad6c\ub4e4 -label.cancel = \ucde8\uc18c -label.change.password.to = \uc0c8 \ube44\ubc00\ubc88\ud638 -label.chatroom.fontsize = \ub300\ud654\ucc3d \ud3f0\ud2b8 \ud06c\uae30: -label.city = \ub3c4\uc2dc -label.close = \ub2eb\uae30 -label.company = \ud68c\uc0ac -label.confirm.password = \ube44\ubc00\ubc88\ud638 \ud655\uc778 -label.conflict.error = \uacc4\uc815\uc740 \uc774\ubbf8 \uc11c\uba85\ub418\uc5c8\uae30 \ub54c\ubb38\uc5d0 \ub85c\uadf8\uc778\uc774 \ubd88\uac00\ub2a5\ud568 -label.contact.to.find = \uce5c\uad6c \uac80\uc0c9 -label.contactlist.avatarsize = \ub9ac\uc2a4\ud2b8 \uc544\ubc14\ud0c0 \ud06c\uae30: -label.contactlist.fontsize = \ub9ac\uc2a4\ud2b8 \ud3f0\ud2b8 \ud06c\uae30: -label.country = \uad6d\uac00/\uc9c0\uc5ed -label.create.account = \uacc4\uc815 \uc0dd\uc131(&A) -label.department = \ubd80\uc11c(&D) -label.dial = \uc804\ud654(&D) -label.downloads = \ub2e4\uc6b4\ub85c\ub4dc -label.due = \ub9cc\uae30\uc77c -label.email.address = \uc774\uba54\uc77c \uc8fc\uc18c(&E) -label.emoticons = \uc774\ubaa8\ud2f0\ucf58(&E) -label.enter.address = \uc8fc\uc18c \uc785\ub825 -label.enter.group.name = \uc0c8 \uadf8\ub8f9 \uc774\ub984 \uc785\ub825 -label.fax = \ud329\uc2a4 -label.find = \uac80\uc0c9 -label.first.name = \uc774\ub984 -label.group = \uadf8\ub8f9 -label.host = \ud638\uc2a4\ud2b8 -label.invited.users = \uce5c\uad6c \ucd08\ub300 -label.jabber.address = &Jabber \uc8fc\uc18c -label.jabber.id = &Jabber ID -label.jid = &JID -label.job.title = \uc9c1\ud568 -label.last.name = \uc131 -label.local.time = \uc9c0\uc5ed \uc2dc\uac04 -label.message = \uba54\uc2dc\uc9c0 -label.message.style = \uba54\uc2dc\uc9c0 \ud615\uc2dd -label.middle.name = \uc774\ub984 -label.minutes.before.stale.chat = \ub2e4\uc74c \uc2dc\uac04\uc774 \uc9c0\ub098\uba74 \uc790\ub9ac\ube44\uc6c0\uc73c\ub85c \ud45c\uc2dc(\ubd84) -label.mobile = \ud734\ub300\ud3f0 -label.name = \uc774\ub984(&N) -label.network = \ub124\ud2b8\uc6cc\ud06c(&K) -label.new.nickname = \uc0c8 \ubcc4\uba85 -label.nickname = \ubcc4\uba85(&c) -label.number = \ubc88\ud638(&N) -label.ok = \ud655\uc778 -label.old.ssl = \uad6c SSL \ud3ec\ud2b8 \ubc29\uc2dd \uc0ac\uc6a9(&U) -label.os = \uc6b4\uc601\uccb4\uc81c(&O) -label.pager = \ud638\ucd9c(\uae30) \ubc88\ud638(&P) -label.password = \ube44\ubc00\ubc88\ud638(&P) -label.phone = \uc804\ud654(&P) -label.port = \ud3ec\ud2b8(&P) -label.postal.code = \uc6b0\ud3b8\ubc88\ud638(&P) -label.presence = \uc788\uc74c -label.priority = \uc6b0\uc120\uc21c\uc704 -label.protocol = \ud504\ub85c\ud1a0\ucf5c -label.received = \uc218\uc2e0 -label.rename.to = \uc774\ub984 \ubcc0\uacbd\ud558\uae30 -label.resource = \uc790\uc6d0(&R) -label.response.timeout = \uc751\ub2f5 \uc2dc\uac04(sec) \ucd08\uacfc(&R) -label.room = \ub300\ud654\ubc29 -label.room.name = \ub300\ud654\ubc29 \uc774\ub984 -label.room.topic= \ud1a0\ub860\uc8fc\uc81c(&T) -label.search.service = \uac80\uc0c9 \uc11c\ube44\uc2a4(&S) -label.server = \uc11c\ubc84(&S) -label.server.address = \uc11c\ubc84 \uc8fc\uc18c(&S) -label.show = \ubcf4\uae30: -label.software = \uc18c\ud504\ud2b8\uc6e8\uc5b4 -label.state.and.province = \uc2dc/\ub3c4(&t) -label.street.address = \uc0c1\uc138\uc8fc\uc18c(&S) -label.time = \uc2dc\uac04: {0} -label.time.till.idle = \uc790\ub9ac\ube44\uc6c0 \uc2dc\uac04(\ubd84)(&T) : -label.timeformat = \uc0ac\uc6a9 {0} -label.transfer.download.directory = \ub2e4\uc6b4\ub85c\ub4dc \ub514\ub809\ud1a0\ub9ac(&D): -label.transfer.timeout = \uc804\uc1a1 \uc2dc\uac04 \uc81c\ud55c(\ubd84)(&T): -label.unable.to.add.contact = \uce5c\uad6c\ub97c \ucd94\uac00\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -label.use.default = \uae30\ubcf8\uac12 \uc0ac\uc6a9 -label.user.on.public.network = \uc0ac\uc6a9\uc790\uac00 \uacf5\uc6a9 \ub124\ud2b8\uc6cc\ud06c \uc0c1\uc5d0 \uc788\uc74c -label.username = \uc0ac\uc6a9\uc790\uba85(&U) -label.version = \ubc84\uc804(&V) -label.web.page = \ud648\ud398\uc774\uc9c0(&W) -label.xmpp.port = &XMPP \ud3ec\ud2b8 -label.krb.realm = \uad00\uc2ec\uc601\uc5ed -label.krb.kdc = KDC -label.which.pki.method = \uc5b4\ub5a4 PKI \ubc29\ubc95\uc785\ub2c8\uae4c? -label.choose.file = \ud30c\uc77c\uc744 \uace0\ub974\uc2ed\uc2dc\uc694 -label.trust.store.password = \uc554\ud638\ud654\ub418\uc5b4 \ud328\uc2a4\uc6cc\ub4dc\uac00 \uc800\uc7a5\ub429\ub2c8\ub2e4. -label.enter.password = \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\uc2ed\uc2dc\uc694. -label.move.focus.forwards = \ud3ec\ucee4\uc2a4\ub97c \uc55e\uc73c\ub85c \uc774\ub3d9 -label.move.focus.backwards = \ud3ec\ucee4\uc2a4\ub97c \ub4a4\ub85c \uc774\ub3d9 -label.keystore.location = Keystore \uc704\uce58 -label.truststore.location = TrustStore \uc704\uce58 -label.pkcs.library.file = PKCS#11 Library File -label.x509.certificate = X.509 Certificate -label.apple.keychain = Apple KeyChain -label.add.to.roster = \uce5c\uad6c \ucd94\uac00 -label.audio.device = \uc624\ub514\uc624 \ub514\ubc14\uc774\uc2a4 -label.video.device = \ube44\ub514\uc624 \ub514\ubc14\uc774\uc2a4 - -menuitem.about = \uc815\ubcf4 -menuitem.actions = \ub3d9\uc791 -menuitem.bookmarks = \ubd81\ub9c8\ud06c -menuitem.add = \ucd94\uac00 -menuitem.add.as.contact = \uce5c\uad6c \ucd94\uac00 -menuitem.add.contact = \uce5c\uad6c \ucd94\uac00 -menuitem.add.contact.group = \uadf8\ub8f9 \ucd94\uac00 -menuitem.add.groupchat.myname = \uc0c1\ub300\ubc29\uc5d0 \ub0b4 \uc774\ub984 \uac15\uc870\ud558\uae30 -menuitem.add.groupchat.mytext = \ub0b4\uae00\uc5d0 \uac15\uc870\ud558\uae30 -menuitem.add.groupchat.popname= \ub0b4 \uc774\ub984\uc744 \uc774\uc57c\uae30\ud560\ub54c \ud31d\uc5c5\ucc3d \ubcf4\uc774\uae30 -menuitem.add.groupchat.showjoinleavemessage = \uc785\uc7a5\ud560\ub54c\uc640 \ub098\uac08\ub54c \uba54\uc2dc\uc9c0 \ubcf4\uc774\uae30 -menuitem.always.on.top = \ud56d\uc0c1 \uc704\ub85c\ud558\uae30 -menuitem.alert.when.online = \uce5c\uad6c\uac00 \uc790\ub9ac\uc5d0 \uc788\uc74c\uc77c\ub54c \uc54c\ub9ac\uae30 -menuitem.ban = \uae08\uc9c0 -menuitem.ban.user = \uc0ac\uc6a9\uc790 \uae08\uc9c0 -menuitem.block.user = \uc0ac\uc6a9\uc790 \ucc28\ub2e8 -menuitem.broadcast.to.group = \uadf8\ub8f9\uc5d0 \uc804\uccb4\uc54c\ub9bc \uba54\uc2dc\uc9c0 -menuitem.browse.service = \ud0d0\uc0c9 \uc11c\ube44\uc2a4 -menuitem.change.nickname = \ubcc4\uba85 \ubcc0\uacbd -menuitem.change.subject = \uc8fc\uc81c \ubcc0\uacbd -menuitem.chat = \ub300\ud654 -menuitem.check.for.updates = \uc5c5\ub370\uc774\ud2b8 \uccb4\ud06c -menuitem.contacts = \uce5c\uad6c -menuitem.copy.to = \ubcf5\uc0ac -menuitem.delete = \uc0ad\uc81c -menuitem.delete.login.information = \ub85c\uadf8\uc778 \uc815\ubcf4 \uc0ad\uc81c -menuitem.destroy.room = \ubc29 \uc5c6\uc560\uae30 -menuitem.dial = \uc804\ud654\uac78\uae30 -menuitem.edit = \ud3b8\uc9d1 -menuitem.edit.my.profile = \ub0b4 \ud504\ub85c\ud544 \ud3b8\uc9d1(&E)... -menuitem.edit.status.message = \uc0c1\ud0dc \uba54\uc2dc\uc9c0 \ud3b8\uc9d1... -menuitem.enter.login.information = \ub85c\uadf8\uc778 \uc815\ubcf4 \uc785\ub825 -menuitem.exit = \uc885\ub8cc -menuitem.grant.moderator = \uc6b4\uc601\uc790 \uc218\ub77d -menuitem.grant.voice = \uc74c\uc131\ucc44\ud305 \uc218\ub77d -menuitem.help = \ub3c4\uc6c0\ub9d0 -menuitem.hide = \uc228\uae30\uae30 -menuitem.invite.group.to.conference = \ud68c\uc758\uc5d0 \uadf8\ub8f9 \ucd08\ub300 -menuitem.invite.users = \uce5c\uad6c \ucd08\ub300\ud558\uae30 -menuitem.join.on.startup = \uc2dc\uc791\uc2dc \ucc38\uc5ec\ud558\uae30 -menuitem.join.room = \ub300\ud654\ubc29 \ucc38\uc5ec -menuitem.kick.user = \uc0ac\uc6a9\uc790 \ub0b4\ubcf4\ub0b4\uae30 -menuitem.languages = \uc5b8\uc5b4 -menuitem.logout.no.status = \ub85c\uadf8\uc544\uc6c3 -menuitem.logout.with.status = ... \uc774\uc720\ub85c \ub85c\uadf8\uc544\uc6c3 -menuitem.lookup.profile = \ud504\ub85c\ud544 \uac80\uc0c9... -menuitem.move.to = \uc774\ub3d9 -menuitem.online.help = Spark \ud3ec\ub7fc -menuitem.open = \uc5f4\uae30 -menuitem.open.with = \uc5f4\uae30... -menuitem.plugins = \ud50c\ub7ec\uadf8\uc778 -menuitem.preferences = \ud658\uacbd \uc124\uc815 -menuitem.remove = \uc81c\uac70 -menuitem.remove.alert.when.online = \uc54c\ub9bc \uc81c\uac70 -menuitem.remove.bookmark = \ubd81\ub9c8\ud06c \uc81c\uac70 -menuitem.remove.from.group = \uadf8\ub8f9\uc5d0\uc11c \uc81c\uac70 -menuitem.remove.from.roster = \uce5c\uad6c \ub9ac\uc2a4\ud2b8\uc5d0\uc11c \uc81c\uac70 -menuitem.remove.service = \uc11c\ube44\uc2a4 \uc81c\uac70 -menuitem.rename = \uc774\ub984 \ubcc0\uacbd -menuitem.revoke.moderator = \uc6b4\uc601\uc790 \ucde8\uc18c -menuitem.revoke.voice = \uc74c\uc131 \ucde8\uc18c -menuitem.save = \uc800\uc7a5 -menuitem.save.as = \ub2e4\ub978 \uc774\ub984\uc73c\ub85c \uc800\uc7a5\ud558\uae30... -menuitem.send.a.file = \ud30c\uc77c \ubcf4\ub0b4\uae30 -menuitem.send.a.message = \uc120\ud0dd\ub41c \uce5c\uad6c\ub4e4\uc5d0\uac8c \ube0c\ub85c\ub4dc\ucf00\uc2a4\ud2b8 \ubcf4\ub0b4\uae30... -menuitem.set.status.message = \uc0c1\ud0dc \uba54\uc2dc\uc9c0 \uc124\uc815... -menuitem.show.empty.groups = \ube44\uc5b4\uc788\ub294 \uadf8\ub8f9 \ubcf4\uc774\uae30 -menuitem.show.offline.group = \uc624\ud504\ub77c\uc778 \uce5c\uad6c\ub4e4 \uadf8\ub8f9 -menuitem.show.traffic = \ud2b8\ub798\ud53d \uc708\ub3c4\uc6b0 \ubcf4\uae30 -menuitem.sign.in = \ub85c\uadf8\uc778 -menuitem.sign.in.at.login = \ub85c\uadf8\uc778\uc2dc \ub85c\uadf8\uc778 -menuitem.sign.out = \ub85c\uadf8 \uc544\uc6c3 -menuitem.start.a.chat = \ub300\ud654 \uc2dc\uc791 -menuitem.start.a.conference = \ud68c\uc758 \uc2dc\uc791... -menuitem.status = \uc0c1\ud0dc -menuitem.subscribe.to = \uae30\ubd80 -menuitem.unban = \uc811\uadfc \ud5c8\uc6a9 -menuitem.unblock.user = \uc0ac\uc6a9\uc790 \ucc28\ub2e8 -menuitem.user.guide = \uc0ac\uc6a9\uc790 \ub3c4\uc6c0\ub9d0 -menuitem.view.client.version = \ud074\ub77c\uc774\uc5b8\ud2b8 \ubc84\uc804 \ubcf4\uae30 -menuitem.view.contact.history = \ub300\ud654\uae30\ub85d \ubcf4\uae30 -menuitem.view.downloads = \ub2e4\uc6b4\ub85c\ub4dc \ud3f4\ub354 -menuitem.view.last.activity = \ub9c8\uc9c0\ub9c9 \ud65c\ub3d9 \ubcf4\uae30 -menuitem.view.logs = \ub85c\uadf8 \ubcf4\uae30 -menuitem.view.profile = \ud504\ub85c\ud544 \ubcf4\uae30 -menuitem.view.room.info = \ub300\ud654\ubc29 \uc815\ubcf4 \ubcf4\uae30 -menuitem.voice = \uc74c\uc131\ub300\ud654 -menuitem.show.offline.users = \uc624\ud504\ub77c\uc778 \uce5c\uad6c \ubcf4\uae30 -menuitem.show.contact.statusmessage = \uc0c1\ud0dc \uba54\uc2dc\uc9c0 \ubcf4\uae30 -menuitem.join.room = \uc120\ud0dd\ub41c \ub300\ud654\ubc29 \ucc38\uc5ec\ud558\uae30 -menuitem.bookmark.room = \ubd81\ub9c8\ud06c\ubc29 -menuitem.refresh = \uc0c8\ub85c\ud558\uae30 -menuitem.create.room = \ub300\ud654\ubc29 \uc0dd\uc131/\ucc38\uc5ec -menuitem.expand.all.groups = \ubaa8\ub4e0 \uadf8\ub8f9 \ud3bc\uccd0 \ubcf4\uc774\uae30 -menuitem.collapse.all.groups = \ubaa8\ub4e0 \uadf8\ub8f9 \ub2eb\uae30 -menuitem.inivite.again = \ub2e4\uc2dc \ucd08\ub300 -menuitem.chatframe.option = \uc635\uc158 - -message.invite.to.groupchat = {0} \uac00 \ub2f9\uc2e0\uc744 \uadf8\ub8f9\ub300\ud654\uc5d0 \ucd08\ub300\ud558\uc600\uc2b5\ub2c8\ub2e4. -message = \uba54\uc2dc\uc9c0 -message.account.create = \uc0c8\ub85c\uc6b4 \ucc44\ud305 \uacc4\uc815\uc744 \uc0dd\uc131\ud569\ub2c8\ub2e4. -message.account.created = \uc0c8\ub85c\uc6b4 \uacc4\uc815\uc774 \uc0dd\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.account.error = \uacc4\uc815 \ucd94\uac00\ud558\uae30 \uc704\ud574 \uc11c\ubc84\ub97c \uc785\ub825\ud558\uc138\uc694. -message.add.a.contact = \uce5c\uad6c \ucd94\uac00 -message.add.conference.service = \ud68c\uc758 \uc11c\ube44\uc2a4 \ucd94\uac00. -message.add.contact.to.list = \uce5c\uad6c \ub9ac\uc2a4\ud2b8\uc5d0 \ucd94\uac00\ud558\uae30 -message.add.favorite.room = \uc990\uaca8\ucc3e\uae30 \ub9ac\uc2a4\ud2b8\uc5d0 \ucd94\uac00\ud558\uac70\ub098 \uc9c1\uc811 \ucc38\uc5ec -message.add.this.user.to.your.roster = \uce5c\uad6c \ubaa9\ub85d\uc5d0 \ucd94\uac00 -message.add.to.roster = \uce5c\uad6c \ub9ac\uc2a4\ud2b8\uc5d0 \ucd94\uac00 -message.add.user = \uce5c\uad6c\ub97c \ucd94\uac00\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? -message.alert.notify = \uc54c\ub9bc \uba54\uc2dc\uc9c0 -message.already.exists = \uacc4\uc815\uc774 \uc774\ubbf8 \uc874\uc7ac\ud569\ub2c8\ub2e4. \ub2e4\ub978 ID\ub85c \uc785\ub825\ud558\uc138\uc694 -message.approve.subscription = \uc0c1\ub300\ubc29 {0}\uc758 \uc8fc\uc18c\ub85d\uc5d0 \ucd94\uac00\ud558\ub294 \uac83\uc744 \ud5c8\ub77d\ud558\uc2ed\ub2c8\uae4c? -message.autenticating = \ub85c\uadf8\uc778\uc911\uc785\ub2c8\ub2e4. -message.away.idle = \uc7a5\uc2dc\uac04 \uc790\ub9ac \ube44\uc6c0 -message.bookmark.temporary.room.error = \uc784\uc2dc\ubc29\uc744 \ubd81\ub9c8\ud06c\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -message.broadcast.from = {0}\ub85c\ubd80\ud130 \uc628 \uc804\uccb4\uc54c\ub9bc -message.broadcast.message.sent = \uc804\uccb4 \uc54c\ub9bc \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0c8\uc74c -message.broadcast.to = {0}\uc5d0\uac8c \ubcf4\ub0bc \uc804\uccb4\uc54c\ub9bc \uba54\uc2dc\uc9c0\ub97c \uc785\ub825\ud558\uc138\uc694 -message.broadcasted.to = \uc774 \uba54\uc2dc\uc9c0\ub294 \ub2e4\uc74c \uc0ac\uc6a9\uc790\uc5d0\uac8c \uc804\uccb4\uc54c\ub9bc\ub418\uc5c8\uc74c:\n{0} -message.buzz.alert.notification = \uc0c1\ub300\uc758 \ucc44\ud305\ucc3d\uc744 \ud754\ub4ed\ub2c8\ub2e4. -message.buzz.sent = \uc0c1\ub300\ubc29\uc5d0\uac8c \uc8fc\ubaa9 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0c8\uc2b5\ub2c8\ub2e4. -message.calling = {0}\uc5d0\uac8c \uc804\ud654\uc911... -message.came.online = {0} \uc740(\ub294) {1} \ud604\uc7ac \uc628\ub77c\uc778 \uc0c1\ud0dc\uc785\ub2c8\ub2e4 -message.cannot.add.contact.to.shared.group = \uacf5\uc720 \uadf8\ub8f9\uc5d0 \uc0c8 \uce5c\uad6c\ub97c \ucd94\uac00\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -message.chat.session.ended = {0}\uc0c1\uc758 \ucc44\ud305 \uc138\uc158\uc740 \uc885\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.click.to.open = \uc5f4\uc5b4 \ubcfc\ub824\uba74 \ud074\ub9ad\ud558\uc138\uc694 -message.client.information = {0}\uc758 \ud074\ub77c\uc774\uc5b8\ud2b8 \uc815\ubcf4 -message.close.other.chats = \ubaa8\ub4e0 \ub300\ud654\ucc3d \ub2eb\uae30 -message.close.stale.chats = \uc624\ub798\ub41c \ucc44\ud305 \ub2eb\uae30 -message.close.this.chat = \ud604\uc7ac \ucc44\ud305\ucc3d \ub2eb\uae30 -message.conference.info.error = \ud68c\uc758 \uc815\ubcf4\ub97c \uac80\uc0c9\ud560 \uc218\uc5c6\uc2b5\ub2c8\ub2e4. \uc7a0\uc2dc \ud6c4 \ub2e4\uc2dc \uc2dc\ub3c4\ud574\uc8fc\uc2ed\uc2dc\uc624. -message.conference.service.error = \ud68c\uc758 \uc11c\ube44\uc2a4\uac00 \uc874\uc7ac\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. -message.confirm.destruction.of.room = \uc5c6\uc5b4\uc9c4 \ubc29\uc758 \ubaa8\ub4e0 \uc0ac\uc6a9\uc790\ub294 \uc774 \ubc29\uc73c\ub85c \ubd80\ud130 \uc0ad\uc81c \ub429\ub2c8\ub2e4. \uacc4\uc18d\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? -message.confirmation.password.error = \ud655\uc778 \ube44\ubc00\ubc88\ud638 \uc785\ub825 -message.connecting.please.wait = \uc5f0\uacb0\uc911\uc785\ub2c8\ub2e4. \uae30\ub2e4\ub9ac\uc138\uc694... -message.connection.failed = {0} \uc5d0 \uc5f0\uacb0\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4.. -message.create.account = \uacc4\uc815\uc744 \uc0dd\uc131\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -message.create.or.join.room = \ud68c\uc758 \ub300\ud654\ubc29\uc744 \ucd94\uac00\ub098 \ucc38\uc11d -message.current.status = \ub0b4 \uc0c1\ud0dc\ub098 \ud65c\ub3d9\uc744 \ub2e4\ub978 \uc0ac\ub78c\uc5d0\uac8c \uc54c\ub9ac\uae30 -message.default.error = \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.. support@jivesoftware.com\uc5d0 \uc54c\ub824\uc8fc\uc138\uc694. -message.delete.all.history = \uc9c0\ub09c \ub300\ud654\ub97c \ubaa8\ub450 \uc9c0\uc6b8\uae4c\uc694? -message.delete.confirmation = {0} \uc0ad\uc81c\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? -message.disable.transport = {0} \ub85c\ubd80\ud130 \ub85c\uadf8\uc778 \uc815\ubcf4\ub97c \uc81c\uac70\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? -message.disconnected.conflict.error = \uac19\uc740 \uc0ac\uc6a9\uac00 \ub2e4\ub978 \uc7a5\uc18c\uc5d0\uc11c \ub85c\uadf8\uc778 \ud588\uae30 \ub54c\ubb38\uc5d0 \ud604\uc7ac \uc811\uc18d\uc740 \ub04a\uc5b4\uc84c\uc2b5\ub2c8\ub2e4. -message.disconnected.error = \uc5d0\ub7ec\ub85c \uc778\ud558\uc5ec \uc5f0\uacb0\uc774 \ub04a\uacbc\uc2b5\ub2c8\ub2e4. -message.disconnected.group.chat.error = \uc5f0\uacb0 \uc624\ub958\ub85c \uc778\ud574 \ub04a\uacbc\uc2b5\ub2c8\ub2e4. \ub2e4\uc2dc \uc5f0\uacb0\ud558\uc2ed\uc2dc\uc694. -message.disconnected.shutdown = \uc11c\ubc84\uac00 \uc885\ub8cc\ub418\uc5b4 \uc5f0\uacb0\uc774 \ub04a\uacbc\uc2b5\ub2c8\ub2e4. -message.downloading = {0} \ub2e4\uc6b4\ub85c\ub4dc \uc911 -message.downloading.spark.plug = \ud50c\ub7ec\uadf8 \ub2e4\uc6b4\ub85c\ub4dc\uc911 -message.end.chat = \uc774 \ucc44\ud305\uc744 \uc885\ub8cc\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? -message.end.conversation = \uc9c0\uae08 \uc138\uc158\uc744 \uc885\ub8cc\ud558\uae38 \uc6d0\ud558\uc138\uc694? -message.enter.aim = AIM \uc0ac\uc6a9\uc790\uba85\uacfc \ube44\ubc00\ubc88\ud638\ub97c \uc544\ub798\uc5d0 \uc785\ub825\ud558\uc138\uc694. -message.enter.broadcast.message = \uc120\ud0dd\ub41c \uce5c\uad6c\ub4e4\uc5d0\uac8c \ube0c\ub85c\ub4dc\ucf00\uc2a4\ud2b8 \uba54\uc2dc\uc9c0 \ubcf4\ub0b4\uae30 -message.enter.gadugadu = GaduGadu \uc0ac\uc6a9\uc790\uba85\uacfc \ube44\ubc00\ubc88\ud638\ub97c \uc544\ub798\uc5d0 \uc785\ub825\ud558\uc138\uc694. -message.enter.gtalk = GTalik \uc0ac\uc6a9\uc790\uba85\uacfc \ube44\ubc00\ubc88\ud638\ub97c \uc544\ub798\uc5d0 \uc785\ub825\ud558\uc138\uc694 -message.enter.icq = ICQ \uc0ac\uc6a9\uc790\uba85\uacfc \ube44\ubc00\ubc88\ud638\ub97c \uc544\ub798\uc5d0 \uc785\ub825\ud558\uc138\uc694. -message.enter.irc = IRC \uc0ac\uc6a9\uc790\uba85\uacfc \ube44\ubc00\ubc88\ud638\ub97c \uc544\ub798\uc5d0 \uc785\ub825\ud558\uc138\uc694. -message.enter.sametime = SameTime \uc0ac\uc6a9\uc790\uba85\uacfc \ube44\ubc00\ubc88\ud638\ub97c \uc544\ub798\uc5d0 \uc785\ub825\ud558\uc138\uc694. -message.enter.facebook = FaceBook \uc0ac\uc6a9\uc790\uba85\uacfc \ube44\ubc00\ubc88\ud638\ub97c \uc544\ub798\uc5d0 \uc785\ub825\ud558\uc138\uc694. -message.enter.myspace = Myspace \uc0ac\uc6a9\uc790\uba85\uacfc \ube44\ubc00\ubc88\ud638\ub97c \uc544\ub798\uc5d0 \uc785\ub825\ud558\uc138\uc694. -message.enter.jabber.id = Jabber \uc0ac\uc6a9\uc790\uba85\uc744 \uc544\ub798\uc5d0 \uc785\ub825\ud558\uc138\uc694. -message.enter.message.to.broadcast = \uc8fc\uc18c\ub85d\uc758 \ubaa8\ub450\uc5d0\uac8c \uc804\uccb4\uc54c\ub9bc \ud560 \uba54\uc2dc\uc9c0\ub97c \uc785\ub825\ud558\uc138\uc694.. -message.enter.msn = MSN \uc0ac\uc6a9\uc790\uba85\uacfc \ube44\ubc00\ubc88\ud638\ub97c \uc544\ub798\uc5d0 \uc785\ub825\ud558\uc138\uc694. -message.enter.new.subject = \uc0c8\ub85c\uc6b4 \uc8fc\uc81c\ub97c \uc785\ub825\ud558\uc138\uc694 -message.enter.qq = QQ \ubc88\ud638\uc640 \ube44\ubc00\ubc88\ud638\ub97c \uc544\ub798\uc5d0 \uc785\ub825\ud558\uc138\uc694 -message.enter.room.password = \ubc29 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\uc138\uc694 -message.enter.simple = Simple\uc5d0 \uc811\uc18d\ud558\uae30 \uc704\ud574 \ub2f9\uc2e0\uc758 \uc0ac\uc6a9\uc790\uba85\uacfc \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\uc138\uc694. -message.enter.valid.jid = \uc720\ud6a8\ud55c Jabber ID \uc785\ub825 -message.enter.xmpp = XMPP\uc5d0 \uc811\uc18d\ud558\uae30 \uc704\ud574 \ub2f9\uc2e0\uc758 \uc0ac\uc6a9\uc790\uba85\uacfc \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\uc138\uc694. -message.enter.yahoo = Yahoo\uc5d0 \uc811\uc18d\ud558\uae30 \uc704\ud574 \ub2f9\uc2e0\uc758 \uc0ac\uc6a9\uc790\uba85\uacfc \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\uc138\uc694. -message.error.during.file.transfer = \ud30c\uc77c \uc804\uc1a1\uc911 \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4. -message.file.exists.question = \ud30c\uc77c\uc774 \uc874\uc7ac\ud569\ub2c8\ub2e4. \ub36e\uc5b4\uc4f0\uc2dc\uaca0\uc2b5\ub2c8\uae4c? -message.file.size = \ud30c\uc77c \ud06c\uae30: {0} -message.file.transfer.canceled = \ud30c\uc77c \uc804\uc1a1 \ucde8\uc18c\ud588\uc2b5\ub2c8\ub2e4. -message.file.transfer.rejected = \ud30c\uc77c \uc804\uc1a1\uc740 {0}\uc5d0\uac8c \ubc1b\uc544\ub4e4\uc5ec\uc9c0\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4.. -message.file.transfer.notification = \ud30c\uc77c \uc804\uc1a1 \uc54c\ub9bc -message.file.transfer.short.message = \uc774 \ub2f9\uc2e0\uc5d0\uac8c \ud30c\uc77c\uc744 \ubcf4\ub0c5\ub2c8\ub2e4. -message.file.transfer.chat.window = \ud30c\uc77c \uc804\uc1a1 \uc694\uccad: -message.find.conference.services = \ud68c\uc758 \uc11c\ube44\uc2a4 \uac80\uc0c9 -message.forbidden.error = \uc11c\ubc84\ub85c \ubd80\ud130 \uc811\uadfc \uae08\uc9c0 \uc5d0\ub7ec\uac00 \uc218\uc2e0\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.gateway.username.error = ID\ub97c \uc785\ub825\ud574\uc57c\ud569\ub2c8\ub2e4. -message.gateway.password.error = \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud574\uc57c \ud569\ub2c8\ub2e4. -message.gateway.nickname.error = \ubcc4\uba85\uc744 \uc785\ub825\ud574\uc57c\ud569\ub2c8\ub2e4. -message.general.error = {0}\uc758 \uc774\uc720\ub85c \uc11c\ubc84\uc640\uc758 \uc5f0\uacb0\uc774 \ub04a\uacbc\uc2b5\ub2c8\ub2e4. -message.generic.reconnect.message = \uc5f0\uacb0\uc774 \ub04a\uacbc\uc2b5\ub2c8\ub2e4. \uc544\ub798\uc5d0 \uc7ac\uc5f0\uacb0\uc744 \ud074\ub9ad\ud558\uc5ec \ub2e4\uc2dc \ub85c\uadf8\uc778\ud558\uc2ed\uc2dc\uc694. -message.idle.for = Idle for {0} -message.image.too.large = \uc774\ubbf8\uc9c0\uac00 \ub108\ubb34 \ud07d\ub2c8\ub2e4. \uc774\ubbf8\uc9c0 \ud06c\uae30\uac00 16k\ubcf4\ub2e4 \uc791\uc544\uc57c\ud569\ub2c8\ub2e4. -message.invalid.jabber.id = \uc720\ud6a8\ud55c Jabber ID\uac00 \uc544\ub2d9\ub2c8\ub2e4. -message.invalid.jid.error = \uc9c0\uc815\ub41c JID\uac00 \uc798\ubabb\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.invalid.status = \uc720\ud6a8\ud55c \uc0c1\ud0dc \uba54\uc2dc\uc9c0\ub97c \uc9c0\uc815\ud569\ub2c8\ub2e4. -message.invalid.username.password = ID\ub098 \ube44\ubc00\ubc88\ud638\uac00 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. -message.invite.users.to.conference = \ud68c\uc758\uc2e4\uc5d0 \ucd08\ub300\ud569\ub2c8\ub2e4. -message.is.shared.group = {0}\uc740 \uacf5\uc720\ub41c \uadf8\ub8f9\uc785\ub2c8\ub2e4. -message.is.typing.a.message = {0} \uc774 \uba54\uc2dc\uc9c0 \uc785\ub825\uc911\uc785\ub2c8\ub2e4.... -message.join.conference.room = \ud68c\uc758\uc2e4\uc5d0 \ucc38\uc11d -message.kicked.error = \ub2f9\uc2e0\uc740 {0}\uc744(\ub97c) \uc774 \ubc29\uc5d0\uc11c \ucd94\ubc29\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -message.last.message.received = {0}\ub85c\ubd80\ud130 \ub9c8\uc9c0\ub9c9 \uba54\uc2dc\uc9c0\uac00 \ubc1b\uc544\uc84c\uc2b5\ub2c8\ub2e4 -message.loading.please.wait = \ub85c\ub529\uc911\uc785\ub2c8\ub2e4. \uae30\ub2e4\ub9ac\uc138\uc694... -message.locked.workstation = \uc0ac\uc6a9\uc790\ub294 \uadf8\ub4e4\uc758 \uc6cc\ud06c\uc2a4\ud14c\uc774\uc158\uc73c\ub85c \uc7a0\uad88\uc84c\uc2b5\ub2c8\ub2e4. -message.name.of.group = \uadf8\ub8f9 \uc774\ub984 -message.name.of.search.service.question = \uac80\uc0c9 \uc11c\ube44\uc2a4 \uc774\ub984? -message.negotiate.file.transfer = \ud30c\uc77c\uc804\uc1a1 \uc900\ube44 \uc911 \uc785\ub2c8\ub2e4. \uae30\ub2e4\ub824\uc8fc\uc138\uc694... -message.negotiate.stream = \uc2a4\ud2b8\ub9bc \uc5f0\uacb0\uc744 \uc900\ube44 \uc911 \uc785\ub2c8\ub2e4. \uae30\ub2e4\ub824\uc8fc\uc138\uc694... -message.negotiation.file.transfer = {0}\uc5d0\uac8c \ud30c\uc77c\uc804\uc1a1 \uc900\ube44 \uc911 \uc785\ub2c8\ub2e4. \uae30\ub2e4\ub824\uc8fc\uc138\uc694... -message.new.message = {0}\ub85c\ubd80\ud130 \uc0c8\ub85c\uc6b4 \uba54\uc2dc\uc9c0. -message.new.spark.available = {0}\uc740 \ud604\uc7ac \uc124\uce58 \uac00\ub2a5\ud569\ub2c8\ub2e4. \uc124\uce58 \ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? -message.nickname.in.use = \ubcc4\uba85\uc774 \uc0ac\uc6a9\uc911\uc785\ub2c8\ub2e4. \ub2e4\ub978 \ubcc4\uba85\uc744 \uc785\ub825\ud558\uc138\uc694. -message.no.avatar.found = \uc544\ubc14\ud0c0\ub97c \uc218\uc815\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -message.no.caller.id = \uc720\ud6a8\ud55c \ud638\ucd9c\uc790 ID\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. -message.no.description.available = \uc720\ud6a8\ud55c \uc124\uba85\uc774 \uc5c6\uc2b5\ub2c8\ub2e4 -message.no.history.found = \uc9c0\ub09c \ub300\ud654 \uae30\ub85d\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. -message.no.results.found = \uac80\uc0c9\ub41c \uacb0\uacfc\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. -message.no.room.to.join.error = \ub4e4\uc5b4\uac08 \ubc29\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. -message.no.subject.available = \uc81c\ubaa9\uc744 \uc0ac\uc6a9\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -message.no.updates = \uc5c5\ub370\uc774\ud2b8\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. -message.normal = \uba54\uc2dc\uc9c0 -message.number.to.call = \uc804\ud654\ub97c \uac78\uae30 \uc704\ud574 \ubc88\ud638\ub97c \uc9c0\uc815\ud558\uc138\uc694 -message.offline = \uc0ac\uc6a9\uc790\ub294 \uc624\ud504\ub77c\uc778 \uc0c1\ud0dc\uc5ec\uc11c \uc774 \uba54\uc2dc\uc9c0\ub294 \uc0ac\uc6a9\uc790\uac00 \ub2e4\uc74c\ubc88 \ub85c\uadf8\uc778 \ud560 \ub54c \ubc1b\uc744 \uac83 \uc785\ub2c8\ub2e4. -message.offline.error = \uc0ac\uc6a9\uc790\ub294 \uc624\ud504\ub77c\uc778 \uba54\uc2dc\uc9c0\ub97c \ubc1b\uc744 \uc218 \uc5c6\uc744 \uac83 \uc785\ub2c8\ub2e4. -message.participants.in.room = \ubc29\uc5d0 \ucc38\uc5ec\ud558\uc600\uc2b5\ub2c8\ub2e4 -message.password.error = \uc774 \uacc4\uc815\uc744 \uc704\ud55c \uc554\ud638\ub97c \uc9c0\uc815\ud558\uc138\uc694. -message.password.private.room.error = \ube44\uacf5\uac1c \ubc29\uc744 \uc704\ud574 \uc554\ud638\ub97c \uc9c0\uc815\ud558\uc138\uc694 -message.passwords.no.match = \ube44\ubc00\ubc88\ud638\uac00 \ud2c0\ub9bd\ub2c8\ub2e4. -message.please.join.in.conference = \ud68c\uc758\uc5d0 \ucc38\uc11d\ud574\uc8fc\uc138\uc694. -message.plugins.not.available = \ud50c\ub7ec\uadf8\uc778 \uc800\uc7a5\uc18c\uc5d0 \uc811\uc18d\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -message.prompt.plugin.uninstall = \uc815\ub9d0 {0}\uc744(\ub97c) \uc81c\uac70\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? -message.received.file = {0}\ub85c\ubd80\ud130 \ud30c\uc77c\uc744 \ubc1b\uc558\uc2b5\ub2c8\ub2e4. -message.receiving.file = {0}\ub85c\ubd80\ud130 \ud30c\uc77c\uc744 \ubc1b\uace0 \uc788\uc2b5\ub2c8\ub2e4. -message.reconnect.attempting = \uc5f0\uacb0\uc911... -message.reconnect.failed = \uc7ac\uc2dc\ub3c4 \uc2e4\ud328 -message.reconnect.wait = \uc7ac\uc5f0\uacb0\uc911 {0} \ucd08. -message.register.transports = \uc720\uc6a9\ud55c \uc804\uc1a1\uc5d0 \ub4f1\ub85d\ud558\uae30. -message.registering = {0} \ub4f1\ub85d\uc911\uc785\ub2c8\ub2e4. \uae30\ub2e4\ub9ac\uc138\uc694.. -message.registration.transport.failed = \uac8c\uc774\ud2b8\uc6e8\uc774\uc5d0 \ub4f1\ub85d \ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -message.restart.spark = \uc0c8\ub85c\uc6b4 \ubc84\uc804\uc758 \uc124\uce58\ub97c \uc704\ud574 \ud074\ub77c\uc774\uc5b8\ud2b8\ub97c \n\uc7ac\uc2dc\uc791\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4. \uc9c0\uae08 \uc124\uce58\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? -message.restart.spark.changes = \ud50c\ub7ec\uadf8\uc778\uc740 \ub2e4\uc74c\ubc88 Spark \uc2dc\uc791\uc2dc \uc0ad\uc81c\ub420 \uac83\uc785\ub2c8\ub2e4. -message.restart.spark.to.install = \ucd5c\uc2e0 \ubc84\uc804\uc744 \uc124\uce58 \ud558\uae30 \uc704\ud574 \ud074\ub77c\uc774\uc5b8\ud2b8\ub97c \uc885\ub8cc\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4. \uc9c0\uae08 \uc885\ub8cc \ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? -message.restart.required = \uc7ac\uc2dc\uc791\uc774 \ud544\uc694\ud569\ub2c8\ub2e4. \uc7ac\uc2dc\uc791 \ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? -message.room.creation.error = \uc774\ubc29\uc740 \uc0dd\uc131\ud560\uc218\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. -message.room.destroyed = \uc774 \ubc29\uc740 \ub2e4\uc74c\uc758 \uc774\uc720\ub85c \ud3d0\uc1c4\ub418\uc5c8\uc2b5\ub2c8\ub2e4: {0} -message.room.destruction.reason = \ubc29\uc744 \uc5c6\uc560\ub294 \uc774\uc720\ub294? -message.room.information.for = {0} \ubc29\uc815\ubcf4 -message.save.profile = \ubcc0\uacbd\ub41c \ud504\ub85c\ud544\uc744 \uc800\uc7a5\ud558\uae30 \uc704\ud574 \uc800\uc7a5\ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uc138\uc694. -message.search.for.contacts = \uce5c\uad6c \uac80\uc0c9 -message.search.for.other.people = \uc11c\ubc84\uc5d0\uc11c \uce5c\uad6c \uac80\uc0c9. -message.search.service.not.available = \uac80\uc0c9 \uc11c\ube44\uc2a4 \uc811\uc18d\uc774 \ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. -message.searching.please.wait = \uac80\uc0c9\uc911\uc785\ub2c8\ub2e4. \uae30\ub2e4\ub9ac\uc138\uc694... -message.select.add.room.to.add = \ub2f9\uc2e0\uc758 \uc11c\ube44\uc2a4 \ubaa9\ub85d\uc5d0 \ucd94\uac00\ud558\uae30 \uc704\ud574 \ubc29\uc744 \uc120\ud0dd\ud558\uc138\uc694. -message.select.one.or.more = \uce5c\uad6c\ub97c \uc120\ud0dd\ud558\uc138\uc694. -message.select.room.to.enter = \ub4e4\uc5b4\uac00\uae30 \uc704\ud55c \ubc29\uc744 \uc9c0\uc815\ud558\uc138\uc694. -message.select.room.to.join = \ub4e4\uc5b4\uac00\uae30 \uc704\ud574 \ubc29\uc744 \uc120\ud0dd\ud558\uc138\uc694. -message.send.a.broadcast = \ube0c\ub85c\ub4dc\ucf00\uc2a4\ud2b8 \ubcf4\ub0b4\uae30 -message.send.file.to.user = \ud30c\uc77c \ubcf4\ub0b4\uae30 -message.send.picture = \ucef4\ud4e8\ud130 \ud654\uba74\uc744 \ucea1\uccd0\ud574\uc11c \ubcf4\ub0b4\uae30 -message.send.to.these.people = \uc120\ud0dd\ud55c \uce5c\uad6c\ub4e4\uc5d0\uac8c \ubcf4\ub0b4\uae30 -message.sending.file.to = {0} \uc5d0\uac8c \ud30c\uc77c \ubcf4\ub0b4\ub294 \uc911\uc785\ub2c8\ub2e4. -message.sent.offline.files = \ub2f9\uc2e0\uc740 \ubc29\uae08 \uc624\ud504\ub77c\uc778 \ud30c\uc77c\uc744 \uc804\uc1a1\ud588\uc2b5\ub2c8\ub2e4. -message.server.unavailable = \uc11c\ubc84\uc5d0 \uc5f0\uacb0\ud560 \uc218\uc5c6\uc2b5\ub2c8\ub2e4 : \uc798\ubabb\ub41c \uc774\ub984\uc774\ub098 \uc11c\ubc84\uc5d0 \uc5f0\uacb0\ud560 \uc218\uc5c6\uc2b5\ub2c8\ub2e4. -message.service.already.exists = \uc11c\ube44\uc2a4 \ub9ac\uc2a4\ud2b8\uc5d0 \uc774\ubbf8 \uc788\uc2b5\ub2c8\ub2e4. -message.shared.group = \uacf5\uc720 \uadf8\ub8f9 -message.spark.secure = Spark\ub294 \uc554\ud638\ubaa8\ub4dc\uc5d0\uc11c \uc2e4\ud589\uc911\uc785\ub2c8\ub2e4. -message.specify.contact.jid = \uce5c\uad6c JDI\ub97c \uc9c0\uc815\ud558\uc138\uc694(\uc608. ddman@jabber.org) -message.specify.group = \uc0c8\ub85c\uc6b4 \uc0ac\uc6a9\uc790 \ucd94\uac00\ub97c \uc704\ud574 \uce5c\uad6c \uadf8\ub8f9\uc744 \uc9c0\uc815\ud558\uc138\uc694. -message.specify.information.for.conference = \ucee8\ud37c\ub7f0\uc2a4 \ubc29\uc758 \uc815\ubcf4\ub97c \uc9c0\uc815\ud558\uc138\uc694. -message.specify.name.error = \uc720\ud6a8\ud55c \uc774\ub984\uc744 \uc9c0\uc815\ud558\uc138\uc694. -message.specify.users.to.join.conference = \uc774 \ucee8\ud37c\ub7f0\uc2a4 \ubc29\uc5d0 \ucc38\uc5ec\ud560 \uc0ac\uc6a9\uc790\ub97c \uc9c0\uc815\ud558\uc138\uc694. -message.specify.valid.time.error = \uc720\ud6a8\ud55c \ud0c0\uc784\uc544\uc6c3\uacfc \ud3ec\ud2b8\ub97c \uc9c0\uc815\ud558\uc138\uc694. -message.subject.change.error = \ub2f9\uc2e0\uc740 \uc774 \ubc29\uc758 \uc8fc\uc81c\ub97c \ubc14\uafb8\ub3c4\ub85d \ud5c8\ub77d\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. -message.subject.has.been.changed.to = \uc8fc\uc81c\uac00 {0}(\uc73c)\ub85c \ubc14\uafd4\uc84c\uc2b5\ub2c8\ub2e4. -message.supply.resource = \uc720\ud6a8\ud55c \uc790\uc6d0\uc744 \uc801\uc73c\uc138\uc694. -message.supply.valid.port = \uc720\ud6a8\ud55c \ud3ec\ud2b8 \ubc88\ud638\ub97c \uc801\uc73c\uc138\uc694. -message.supply.valid.timeout = \uc720\ud6a8\ud55c \ud0c0\uc784\uc544\uc6c3 \uac12\uc744 \uc801\uc73c\uc138\uc694. -message.timeout.error = \uc81c\ud55c \uc2dc\uac04\uc774 5 \ucd08 \uc774\uc0c1\uc774\uc5b4\uc57c\ud569\ub2c8\ub2e4. -message.total.downloaded = \ucd1d \ub2e4\uc6b4\ub85c\ub4dc -message.transfer.cancelled = \ud30c\uc77c \uc804\uc1a1\uc774 \ucde8\uc18c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.transfer.rate = \uc804\uc1a1 \uc18d\ub3c4 -message.transfer.refused = \ud30c\uc77c \uc804\uc1a1\uc774 \uac70\ubd80\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.transfer.waiting.on.user = \ud30c\uc77c \uc804\uc1a1\uc744 \uc704\ud574 {0} \uc758 \uc218\ub77d\uc744 \uae30\ub2e4\ub9bd\ub2c8\ub2e4. -message.unable.to.load.profile = {0]\uc744(\ub97c) \uc704\ud55c \ud504\ub85c\ud30c\uc77c\uc744 \uc704\uce58\uc2dc\ud0ac \uc218 \uc5c6\uc2b5\ub2c8\ub2e4 -message.unable.to.retrieve.last.activity = {0}\uc744(\ub97c) \uc704\ud55c \ub9c8\uc9c0\ub9c9 \ub3d9\uc791\uc744 \uacb0\uc815\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -message.unable.to.save.password = \ube44\ubc00 \ubc88\ud638\ub97c \ubcc0\uacbd\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. \uc11c\ubc84 \uad00\ub9ac\uc790\uc5d0\uac8c \ubb38\uc758\ud558\uc2ed\uc2dc\uc694. -message.unable.to.send.file = {0} \uc5d0\uac8c \ud30c\uc77c\uc744 \ubcf4\ub0bc\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -message.unrecoverable.error = ID\ub098 \ube44\ubc00\ubc88\ud638\uac00 \ud2c0\ub838\uc2b5\ub2c8\ub2e4. -message.update.room.list = \ub300\ud654\ubc29 \ub9ac\uc2a4\ud2b8 \uc5c5\ub370\uc774\ud2b8 -message.updating.cancelled = \uc5c5\ub370\uc774\ud2b8\uac00 \ucde8\uc18c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.user.banned = {0}\uc740(\ub294) \uc774 \ubc29\uc5d0\uc11c \uae08\uc9c0 \ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.user.given.voice = \uc774 \ubc29\uc5d0\uc11c {0}\uc5d0\uac8c \ubc1c\uc5b8\uad8c\uc774 \uc8fc\uc5b4\uc84c\uc2b5\ub2c8\ub2e4. -message.user.granted.admin = {0}\uc5d0\uac8c \uad00\ub9ac\uc790 \uad8c\ud55c\uc774 \ubd80\uc5ec\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.user.granted.membership = {0}\uc5d0\uac8c \uba64\ubc84\uc27d \ud2b9\uad8c\uc774 \ubd80\uc5ec\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.user.granted.moderator = {0}\uc5d0\uac8c \uc9c4\ud589\uc790 \uad8c\ud55c\uc774 \uc8fc\uc5b4\uc84c\uc2b5\ub2c8\ub2e4.. -message.user.granted.owner = {0}\uc5d0\uac8c \uc18c\uc720\uc790 \uad8c\ud55c\uc774 \ubd80\uc5ec\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.user.is.sending.you.a.file = {0} \uc774(\uac00) \ub2f9\uc2e0\uc5d0\uac8c \ud30c\uc77c\uc744 \ubcf4\ub0b4\ub824\uace0 \ud569\ub2c8\ub2e4. -message.user.joined.room = {0} \uc774 \ub4e4\uc5b4\uc654\uc2b5\ub2c8\ub2e4. -message.user.kicked.from.room = {0}\uc740(\ub294) \ubc29\uc5d0\uc11c \ucd94\ubc29\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.user.left.room = {0}\uc740(\ub294) \ubc29\uc5d0 \ub0a8\uaca8\uc84c\uc2b5\ub2c8\ub2e4. -message.user.nickname.changed = {0}\uc740(\ub294) {1}\ub85c\uc11c \ud604\uc7ac \uc54c\ub824\uc84c\uc2b5\ub2c8\ub2e4. -message.user.now.available.to.chat = {0}\uc740(\ub294) {1}\uc5d0 \uc628\ub77c\uc778 \uc0c1\ud0dc\uc785\ub2c8\ub2e4. -message.user.revoked.admin = {0} \ub54c\ubb38\uc5d0 \uad00\ub9ac\uc790 \uad8c\ud55c\uc774 \ucca0\ud68c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.user.revoked.membership = {0} \ub54c\ubb38\uc5d0 \uba64\ubc84\uc27d \uad8c\ud55c\uc774 \ucca0\ud68c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.user.revoked.moderator = {0} \ub54c\ubb38\uc5d0 \uc9c4\ud589\uc790 \uad8c\ud55c\uc774 \ucca0\ud68c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.user.revoked.owner = {0} \ub54c\ubb38\uc5d0 \uc18c\uc720\uc790 \uad8c\ud55c\uc774 \ucca0\ud68c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.user.voice.revoked = {0} \ub54c\ubb38\uc5d0 \ubc1c\uc5b8\uad8c\uc774 \ucca0\ud68c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.username.error = \uacc4\uc815\uc758 \uc0ac\uc6a9\uc790\uc774\ub984\uc744 \uc9c0\uc815\ud558\uc138\uc694. -message.username.password.error = \uc544\uc774\ub514 \ubc0f \ube44\ubc00\ubc88\ud638 \uc785\ub825\ub418\uc5b4\uc57c \ud569\ub2c8\ub2e4. -message.vcard.not.supported = \uc11c\ubc84\uc5d0 VCard\ub97c \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uc800\uc7a5\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -message.version = \ubc84\uc83c: {0} -message.view.information.about.this.user = \uce5c\uad6c \uc815\ubcf4 -message.waiting.for.user.to.join = {0} \uac00 \ub4e4\uc5b4\uc624\uae30 \uc704\ud574 \ub300\uae30\uc911 -message.went.offline = {0} \uc740(\ub294) {1} \ud604\uc7ac \uc624\ud504\ub77c\uc778 \uc0c1\ud0dc\ub85c \ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.you.have.been.banned = \ub2f9\uc2e0\uc740 \uc774 \ubc29\uc5d0 \ucc28\ub2e8\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.you.have.been.kicked = \uc774 \ubc29 \ubc16\uc73c\ub85c \ucad3\uaca8\ub0ac\uc2b5\ub2c8\ub2e4. -message.you.have.sent = {0} \uc5d0\uac8c \ud30c\uc77c \uc804\uc1a1\ud588\uc2b5\ub2c8\ub2e4. -message.your.admin.granted = \uad00\ub9ac\uc790 \uad8c\ud55c\uc774 \ubd80\uc5ec\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.your.banned = \ub2f9\uc2e0\uc740 \uc774 \ubc29\uc5d0 \ucc28\ub2e8\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.your.kicked = \ub2f9\uc2e0\uc740 {0}\uc5d0 \uc758\ud574 \ucd94\ubc29\ub418\uc5c8\uc2b5\ub2c8\ub2e4.. -message.your.membership.granted = \ud68c\uc6d0 \uad8c\ud55c\uc774 \ubd80\uc5ec\ub42c\uc2b5\ub2c8\ub2e4. -message.your.membership.revoked = \ud68c\uc6d0 \uc790\uaca9\uc774 \ucde8\uc18c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.your.moderator.granted = \uc6b4\uc601\uc790 \uad8c\ud55c\uc774 \ubd80\uc5ec\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.your.moderator.revoked = \uc6b4\uc601\uc790 \uad8c\ud55c\uc774 \ucde8\uc18c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.your.ownership.granted = \uc18c\uc720\uc790 \uad8c\ud55c\uc774 \uc8fc\uc5b4\uc84c\uc2b5\ub2c8\ub2e4. -message.your.ownership.revoked = \uc18c\uc720\uc790 \uad8c\ud55c\uc774 \ucca0\ud68c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.your.revoked.granted = \uad00\ub9ac\uc790 \uad8c\ud55c\uc774 \ucde8\uc18c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.your.voice.granted = \ud604\uc7ac \ucc44\ud305\uc5d0\uc11c \ubc1c\uc5b8\uad8c\uc774 \uc8fc\uc5b4\uc84c\uc2b5\ub2c8\ub2e4. -message.your.voice.revoked = \uc74c\uc131\ub300\ud654\uac00 \ucde8\uc18c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -message.groupchat.require.password = \uc774 \uadf8\ub8f9 \ub300\ud654\ubc29\uc740 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud574\uc57c\ud569\ub2c8\ub2e4. -message.search.for.history = \ub300\ud654\uae30\ub85d \uac80\uc0c9 - -status.available = \uc790\ub9ac\uc788\uc74c -status.away = \uc790\ub9ac\ube44\uc6c0 -status.custom.messages = \uc0ac\uc6a9\uc790 \uba54\uc2dc\uc9c0 -status.do.not.disturb = \ub2e4\ub978\uc6a9\ubb34\uc911 -status.extended.away = \uc790\ub9ac\ube44\uc6c0 -status.free.to.chat = \ub300\ud654 \uac00\ub2a5 -status.on.phone = \uc804\ud654\uc911 -status.online = \uc628\ub77c\uc778 -status.pending = \uae30\ub2e4\ub9bc - -tab.available.plugins = \uc0ac\uc6a9\uac00\ub2a5\ud55c \ud50c\ub7ec\uadf8\uc778 -tab.avatar = \uc0ac\uc9c4 -tab.business = \uc9c1\uc7a5 -tab.conferences = \ud68c\uc758 -tab.contacts = \ub300\ud654 -tab.general = \uc77c\ubc18\uc0ac\ud56d -tab.home = \uc9d1 -tab.installed.plugins = \uc124\uce58\ub41c \ud50c\ub7ec\uadf8\uc778 -tab.personal = \uac1c\uc778 -tab.proxy = Proxy -tab.sso = SSO -tab.pki = PKI - -title.about = Spark \uc815\ubcf4 -title.password.required = \ube44\ubc00\ubc88\ud638 \ud544\uc694\ud568 -title.task.notification = \uc791\uc5c5 \uc54c\ub9bc -title.client.logs = \ud074\ub77c\uc774\uc5b8\ud2b8 \ub85c\uadf8 -title.advanced.connection.preferences = \uace0\uae09 \uc5f0\uacb0 \uc124\uc815 -title.account.create.registration = \uacc4\uc815 \ub4f1\ub85d -title.bookmarks = \ubd81\ub9c8\ud06c -title.account.created = \uacc4\uc815 \ucd94\uac00\ub418\uc5c8\uc2b5\ub2c8\ub2e4. -title.add.contact = \uce5c\uad6c \ucd94\uac00 -title.add.contact.group = \uce5c\uad6c \uadf8\ub8f9 \ucd94\uac00 -title.add.new.group = \uc0c8 \uadf8\ub8f9 \ucd94\uac00 -title.add.search.service = \uac80\uc0c9 \uc11c\ube44\uc2a4 \ucd94\uac00 -title.add.to.roster = \uce5c\uad6c \ub9ac\uc2a4\ud2b8\uc5d0 \ucd94\uac00 -title.address = \uc8fc\uc18c -title.advanced.connection.preferences = \uace0\uae09 \uc5f0\uacb0 \uc124\uc815 -title.advanced.connection.usesso = GSAPI \ub97c \ud1b5\ud574\uc11c Sign-on(SSO) \ub97c \uc0ac\uc6a9\ud569\ub2c8\ub2e4.(&U) -title.alert = \uc54c\ub9bc -title.appearance = \uc678\ubaa8 -title.appearance.preferences = \uc0ac\uc6a9\uc790 \uc815\uc758 -title.available.transports = \uc0ac\uc6a9 \uac00\ub2a5\ud55c \uc804\uc1a1 -title.broadcast.message = \ube0c\ub85c\ub4dc\ucf00\uc2a4\ud2b8 \uba54\uc2dc\uc9c0 -title.browse.conference.services = \ud68c\uc758 \uc11c\ube44\uc2a4 \ud0d0\uc0c9 -title.browse.room.service = \ud68c\uc758\uc2e4 \ud0d0\uc0c9 - {0} -title.cancelled = \ucde8\uc18c\ub428 -title.change.nickname = \ubcc4\uba85 \ubcc0\uacbd -title.change.subject = \uc8fc\uc81c \ubcc0\uacbd -title.chat = \ub300\ud654 -title.choose.directory = \ub514\ub809\ud1a0\ub9ac \uc120\ud0dd -title.choose.incoming.sound = \ub4e4\uc5b4\uc634 \uc18c\ub9ac \ud30c\uc77c\uc744 \uc120\ud0dd\ud558\uc138\uc694 -title.choose.offline.sound = \uc624\ud504\ub77c\uc778 \uc18c\ub9ac \ud30c\uc77c\uc744 \uc120\ud0dd\ud558\uc138\uc694 -title.choose.outgoing.sound = \ub098\uac10 \uc18c\ub9ac \ud30c\uc77c\uc744 \uc120\ud0dd\ud558\uc138\uc694 -title.conference.invitation = \ud68c\uc758 \ucd08\ub300 -title.conference.rooms = \ud68c\uc758\uc2e4 -title.configure.chat.room = \ub300\ud654\ubc29 \uc124\uc815 -title.configure.room = \ub300\ud654\ubc29 \uc124\uc815 -title.confirmation = \ud655\uc778 -title.create.new.account = \uc0c8 \uacc4\uc815 \uc0dd\uc131 -title.create.or.bookmark.room = \ucc38\uc5ec \ub610\ub294 \ubd81\ub9c8\ud06c\ubc29 -title.create.or.join = \uc0dd\uc131/\ucc38\uc5ec -title.create.problem = \uacc4\uc815 \uc0dd\uc131 \ubb38\uc81c -title.delete.file = \uc774 \ud30c\uc77c\uc744 \uc0ad\uc81c\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? -title.dial.phone = \uc804\ud654\uac78\uae30 -title.disable.transport = \ub85c\uadf8\uc778 \uc815\ubcf4 \uc0ad\uc81c -title.download.complete = \ub2e4\uc6b4\ub85c\ub4dc \uc644\ub8cc -title.downloading.im.client = IM \ud074\ub77c\uc774\uc5b8\ud2b8 \ub2e4\uc6b4\ub85c\ub4dc -title.downloads = \ub2e4\uc6b4\ub85c\ub4dc -title.edit.custom.message = \uc0ac\uc6a9\uc790 \uba54\uc2dc\uc9c0 \ud3b8\uc9d1 -title.edit.profile = \ud504\ub85c\ud544 \uc815\ubcf4 \ud3b8\uc9d1 -title.enter.reason = \uba54\uc2dc\uc9c0 \uc785\ub825 -title.error = \uc5d0\ub7ec -title.error.couldnt.open.file = \ud30c\uc77c\uc744 \uc5f4\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. \uc54c\ub824\uc9c0\uc9c0 \uc54a\uc740 \ud30c\uc77c \ud615\uc2dd\uc785\ub2c8\ub2e4. -title.error.delete.file = \ud30c\uc77c \uc0ad\uc81c\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4! -title.error.find.app = \uc5b4\ud50c\ub9ac\ucf00\uc774\uc158\uacfc \ub9e4\uce6d\ud560 \ud30c\uc77c\uc744 \ucc3e\uc744\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -title.error.rename.file = \ud30c\uc77c\uba85 \ubcc0\uacbd\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4.! -title.file = \ud30c\uc77c -title.filesize = \ud06c\uae30 -title.file.exists = \ud30c\uc77c\uc774 \uc874\uc7ac\ud569\ub2c8\ub2e4. -title.file.transfer = \ud30c\uc77c \uc804\uc1a1 -title.file.transfer.preferences = \ud30c\uc77c \uc804\uc1a1 \uc124\uc815 -title.find.conference.service = \ud68c\uc758 \uc11c\ube44\uc2a4 \uac80\uc0c9 -title.find.contacts = \uce5c\uad6c \uac80\uc0c9 -title.gadugadu.registration = GaduGadu \uacc4\uc815\uc778\uc99d -title.general.media = \ubbf8\ub514\uc5b4 \uc124\uc815 -title.general.chat.settings = \uc77c\ubc18 \ub300\ud654 \uc124\uc815 -title.group.chat = \uadf8\ub8f9 \ub300\ud654 -title.group.chat.settings = \uadf8\ub8f9 \ub300\ud654 \uc124\uc815 -title.gtalk.registration = G talk \uacc4\uc815\uc778\uc99d -title.history.for = {0} \uc744 \uc704\ud55c \ub300\ud654\ub0b4\uc6a9 -title.icq.registration = ICQ \uacc4\uc815\uc778\uc99d -title.irc.registration = IRC \uacc4\uc815 \uc778\uc99d -title.sametime.registration = Sametime \uacc4\uc815\uc778\uc99d -title.facebook.registration = Facebook \uacc4\uc815\uc778\uc99d -title.myspace.registration = MySpace \uacc4\uc815\uc778\uc99d -title.incoming.call = \uc804\ud654 \uc624\ub294 \uc911 -title.input.fileexplorer = \ud0d0\uc0c9\uae30\uc5d0\uc11c \uc774\ub984 \uc785\ub825: -title.input.newname = \uc0c8 \uc774\ub984 \uc785\ub825: -title.input.openwith = \ub2f9\uc2e0\uc774 \uc0ac\uc6a9\ud558\uace0 \uc2f6\uc740 \uc5b4\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0 \uc774\ub984\uc744 \ub123\uc5b4\uc8fc\uc2ed\uc2dc\uc694. -title.invite.to.conference = \ud68c\uc758\uc5d0 \ucd08\ub300\ud569\ub2c8\ub2e4. -title.jabber.browser = \ud0d0\uc0c9 -title.join.conference.room = \ud68c\uc758\ubc29\uc5d0 \ucc38\uc5ec -title.last.activity = \ub9c8\uc9c0\ub9c9 \ub3d9\uc791 -title.login = \ub85c\uadf8\uc778 -title.login.error = \ub85c\uadf8\uc778 \uc2e4\ud328 -title.login.settings = \ub85c\uadf8\uc778 \uc124\uc815 -title.lookup.profile = \ud504\ub85c\ud544 \uac80\uc0c9 -title.msn.registration = MSN \uacc4\uc815 \uc778\uc99d -title.name = \uc774\ub984 -title.new.client.available = \uc0c8\ub85c\uc6b4 \ud074\ub77c\uc774\uc5b8\ud2b8 \uc0ac\uc6a9\uac00\ub2a5 -title.new.roster.group = \uc0c8 \uadf8\ub8f9 -title.new.version.available = \uc0c8\ub85c\uc6b4 \ubc84\uc804\uc774 \uc788\uc2b5\ub2c8\ub2e4. -title.no.updates = \uc5c5\ub370\uc774\ud2b8\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. -title.notes = \ub178\ud2b8 -title.notification = \uacf5\uc9c0 -title.notifications = \uc54c\ub9bc -title.occupants = \uc778\uc6d0\uc218 -title.on.the.phone = \uc804\ud654\uc911 -title.password = \ube44\ubc00\ubc88\ud638 -title.passwords.no.match = \ube44\ubc00\ubc88\ud638 \ud655\uc778. -title.person.search = \uce5c\uad6c \uac80\uc0c9 -title.plugins = \ud50c\ub7ec\uadf8\uc778 -title.preferences = \uc124\uc815 -title.profile.information = \ud504\ub85c\ud544 \uc815\ubcf4 -title.profile.not.found = \ud504\ub85c\ud544\uc744 \ucc3e\uc744\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -title.qq.registration = QQ \uacc4\uc815 \uc778\uc99d -title.register.account = \uc0c8 \uacc4\uc815 \ub4f1\ub85d -title.registration.error = \ub4f1\ub85d \uc5d0\ub7ec -title.reminder = \uc54c\ub9bc -title.rename.roster.group = \uadf8\ub8f9 \uc774\ub984 \ubc14\uafb8\uae30 -title.room.destroyed = \ubc29\uc774 \ud3d0\uc1c4\ub428 -title.room.information = \ub300\ud654\ubc29 \uc815\ubcf4 -title.roster = \uce5c\uad6c \ub9ac\uc2a4\ud2b8 -title.select.file.to.send = \uc804\uc1a1\ud560 \ud30c\uc77c \uc120\ud0dd -title.set.status.message = \uc0c1\ud0dc \uba54\uc2dc\uc9c0 \uc124\uc815 -title.simple.registration = SIMPLE \uacc4\uc815 \uc778\uc99d -title.sound.preferences = \uc18c\ub9ac \uc124\uc815 -title.sounds = \uc18c\ub9ac -title.spark.preferences = Spark \uc124\uc815 -title.start.chat = \ub300\ud654 \uc2dc\uc791 -title.status.message = \uc0c1\ud0dc \uba54\uc2dc\uc9c0 -title.tasks = \uc791\uc5c5 -title.transports = \uc804\uc1a1 -title.tray.information = \ud2b8\ub808\uc774 \uc815\ubcf4 -title.upgrading.client = \ud074\ub77c\uc774\uc5b8\ud2b8 \uc5c5\uadf8\ub808\uc774\ub4dc\uc911 -title.version.and.time = \ubc84\uc83c\uacfc \uc2dc\uac04 -title.view.bookmarks = \ubd81\ub9c8\ud06c \ubcf4\uae30 -title.view.profile.for = {0} \ud504\ub85c\ud544 -title.view.room.information = \ubc29\uc815\ubcf4 \ubcf4\uae30 -title.waiting.to.call = \uc804\ud654\uc5f0\uacb0\uc744 \uc704\ud574 \uae30\ub2e4\ub824\uc8fc\uc2ed\uc2dc\uc624. -title.xmpp.registration = xmpp \uacc4\uc815\uc778\uc99d -title.yahoo.registration = \uc57c\ud6c4 \uacc4\uc815 \uc778\uc99d -title.appearance.showVCards = \uce5c\uad6c \ub9ac\uc2a4\ud2b8\uc5d0\uc11c \ud504\ub85c\ud544 \uc815\ubcf4 \ubcf4\uc774\uae30 -title.subscription.request= \uad6c\ub3c5\uc774 \ud544\uc694\ud569\ub2c8\ub2e4. - -tooltip.place.a.call = \uc804\ud654 \uac78\uae30 -tooltip.appearance = \ub2f9\uc2e0\uc758 \ub300\ud654\uc758 \ubaa8\uc591\uc744 \ubc14\uafc9\ub2c8\ub2e4. -tooltip.file.transfer = \ud30c\uc77c \uc804\uc1a1 \uc124\uc815 -tooltip.notifications = \ub4e4\uc5b4\uc624\ub294 \ucc44\ud305 \uc120\ud638 \uc54c\ub9bc -tooltip.place.voice.call = \uc74c\uc131 \uc804\ud654 \ud558\uae30. -tooltip.send.email = \uc774\uba54\uc77c \ubcf4\ub0b4\uae30. -tooltip.start.chat = \ub300\ud654 \uc2dc\uc791. -tooltip.view.changelog = \ubcc0\uacbd \ub85c\uadf8 \ubcf4\uae30 -tooltip.view.history = \uc9c0\ub09c \ub300\ud654 \ubcf4\uae30 -tooltip.view.readme = ReadMe \ubcf4\uae30 - -tree.conference.services = \ud68c\uc758 \uc11c\ube44\uc2a4 -tree.users.in.room = \ubc29\uc5d0 \uc788\ub294 \uce5c\uad6c\ub4e4 - -#!# \ No newline at end of file diff --git a/src/resources/i18n/spark_i18n_ky.properties b/src/resources/i18n/spark_i18n_ky.properties deleted file mode 100644 index 1a98dfa87..000000000 --- a/src/resources/i18n/spark_i18n_ky.properties +++ /dev/null @@ -1,946 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.0.1 -## Added key: 'message.restart.spark.changes' -## Added key: 'message.enter.icq' -## Added key: 'title.icq.registration' -## Added key: 'button.quit' -## -## -## -## 2.0.2 -## Added key: 'button.new' -## Added key: 'label.group' -## Added key: 'label.jabber.id' -## Added key: 'label.enter.group.name' -## Added key: 'title.new.roster.group' -## Added key: 'title.add.contact.group' -## Added key: 'message.add.contact.to.list' -## Added key: 'title.add.contact' -## Added key: 'tab.conferences' -## Added key: 'message.autenticating' -## Added key: 'title.file.transfer.preferences' -## Added key: 'menuitem.about' -## Added key: 'message.invalid.status' -## Added key: 'message.cannot.add.contact.to.shared.group -## Added key: 'message.specify.contact.jid' -## Added key: 'message.invalid.jid.error' -## Added key: 'message.specify.group' -## Added key: 'add' -## -## -## -## 2.0.5 -## Added key: 'Broadcast' -## Added key: 'label.user.on.public.network' -## Added key: 'label.network' -## -## -## 2.0.6 -## Added key: 'button.add.user' -## Added key: 'menuitem.sign.in' -## Added key: 'menuitem.sign.out' -## Added key: 'menuitem.sign.in.at.login' -## Added key: 'menuitem.enter.login.information' -## Added key: 'menuitem.delete.login.information' -## Added key: 'button.save' -## -## -## 2.5 -## Added key: 'button.start.chat' -## Added key: 'button.send.email' -## Added key: 'available' -## Added key: 'checkbox.tabs.on.top' -## Added key: 'user.has.signed.in' -## Added key: 'user.has.signed.off' -## Added key: 'label.unable.to.add.contact' -## Added key: 'label.conflict.error' -## Added key: 'message.room.creation.error' -## Added key: 'checkbox.allow.buzz' -## Added key: 'message.disconnected.group.chat.error' -## Added key: 'menuitem.show.offline.group' -## Added key: 'menuitem.move.to' -## Added key: 'menuitem.copy.to' -## Added key: 'label.message.style' -## Added key: 'label.emoticons' -## Added key: 'checkbox.enable.emoticons' -## Added key: 'message.unable.to.retrieve.last.activity' -## Added key: 'checkbox.use.system.look.and.feel' -## -## 2.5.2 -## Added key: 'tooltip.place.voice.call' -## Added key: 'message.buzz.alert.notification' -## Added kye: 'message.buzz.sent' -## -## 2.5.2 -## Added key: 'menuitem.user.guide' -## -## -## -## 2.5.7 -## Added key: 'menuitem.languages' -## Added key: 'message.restart.required' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'message.send.to.these.people' -## Added key: 'message' -## Added key: 'message.normal' -## Added key: 'message.alert.notify' -## -## 2.5.8 -## Added key: 'message.enter.simple' -## Added key: 'message.enter.irc' -## Added key: 'message.enter.gadugadu' -## Added key: 'title.simple.registration' -## Added key: 'title.irc.registration' -## Added key: 'title.gadugadu.registration' -## Added key: 'message.username.error' -## Added key: 'message.password.error' -## Added key: 'message.nickname.error' -## -## 2.5.9 -## Added key: 'message.gateway.username.error. -## Added key: 'message.gateway.password.error. -## Added key: 'message.gateway.nickname.error. -## Added key: 'answer' -## Added key: 'online' -## Added key: 'online' -## Added key: 'offline' -## Added key: 'participants' -## Added key: 'unfiled' -## Added key: 'while.offline' -## Added key: 'action.clear' -## Added key: 'action.copy ' -## Added key: 'action.cut' -## Added key: 'action.paste' -## Added key: 'action.print' -## Added key: 'action.save' -## Added key: 'action.select.all' -## Added key: 'button.add2' -## Added key: 'button.copy.to.clipboard' -## Added key: 'button.reconnect2' -## Added key: 'button.tasks.active' -## Added key: 'button.tasks.all' -## Added key: 'button.view.notes' -## Added key: 'button.view.profile' -## Added key: 'button.view.tasklist' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.show.avatars.in.contaclist' -## Added key: 'checkbox.use.compression' -## Added key: 'group.empty' -## Added key: 'group.offline' -## Added key: 'label.add.task' -## Added key: 'label.chatroom.fontsize' -## Added key: 'label.contactlist.fontsize' -## Added key: 'label.due' -## Added key: 'label.show' -## Added key: 'label.timeformat' -## Added key: 'menuitem.dial' -## Added key: 'menuitem.view.logs' -## Added key: 'message.disconnected.shutdown' -## Added key: 'message.invalid.username.password' -## Added key: 'message.no.updates' -## Added key: 'message.reconnect.attempting' -## Added key: 'message.reconnect.failed' -## Added key: 'message.reconnect.wait' -## Added key: 'message.send.picture' -## Added key: 'message.server.unavailable' -## Added key: 'message.unrecoverable.error' -## Added key: 'message.waiting.for.user.to.join' -## Added key: 'status.available' -## Added key: 'status.away' -## Added key: 'status.custom.messages' -## Added key: 'status.do.not.disturb' -## Added key: 'status.extended.away' -## Added key: 'status.free.to.chat' -## Added key: 'status.on.phone' -## Added key: 'status.online' -## Added key: 'status.pending' -## Added key: 'title.about' -## Added key: 'title.appearance' -## Added key: 'title.appearance.preferences' -## Added key: 'title.login.error' -## Added key: 'title.no.updates' -## Added key: 'title.notes' -## Added key: 'title.tasks' -## Added key: 'tooltip.appearance' -## Added key: 'tooltip.file.transfer' -## Added key: 'tooltip.send.email' -## Added key: 'tooltip.start.chat' -## Added key: 'delete.log.permanently' -## Added key: 'delete.permanently' -## Added key: 'label.contactlist.avatarsize' -## Added key: 'title.qq.registration' -## Added key: 'message.enter.qq' -## -## 2.6.0 -## -## Added key: 'apply' - -## -## Author: Ilyas Bakirov -## Contact: just_ilyas [at] yahoo [dot] com -## Modified: 28.10.2009 -## -## -## 2.6.0 beta 1 -## Removed key status.available - -accept= \u041a\u0430\u0431\u044b\u043b \u0430\u043b\u0443\u0443 -action.clear=\u0422\u0430\u0437\u0430\u043b\u043e\u043e -action.copy=\u041a\u04e9\u0447\u04af\u0440\u04af\u04af -action.cut=\u041a\u0435\u0441\u04af\u04af -action.paste=\u041a\u043e\u044e\u0443 -action.print=\u0411\u0430\u0441\u043c\u0430\u043b\u043e\u043e -action.save=\u0421\u0430\u043a\u0442\u043e\u043e -action.select.all=\u0411\u0430\u0440\u0434\u044b\u0433\u044b\u043d \u0442\u0430\u043d\u0434\u043e\u043e -active= \u0410\u043a\u0442\u0438\u0432\u0434\u04af\u04af -add= \u041a\u043e\u0448\u0443\u0443 -answer=\u0416\u043e\u043e\u043f \u0431\u0435\u0440\u04af\u04af -apply=\u0410\u0442\u043a\u0430\u0440\u0443\u0443 -available= \u0422\u0430\u0440\u043c\u0430\u043a\u0442\u0430 -broadcast= \u041a\u04e9\u043f\u0442\u04af\u043a \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430 -button.accept=&\u041a\u0430\u0431\u044b\u043b \u0430\u043b\u0443\u0443 -button.add= &\u041a\u043e\u0448\u0443\u0443 -button.add.a.contact= \u041a\u043e&\u043d\u0442\u0430\u043a\u0442 \u043a\u043e\u0448\u0443\u0443 -button.add.bookmark= \u042d\u0441\u0431\u0435\u043b\u0433\u0438\u043d\u0438 \u043a\u043e\u0448\u0443\u0443 -button.add.service= \u041a\u044b&\u0437\u043c\u0430\u0442\u0442\u044b \u043a\u043e\u0448\u0443\u0443 -button.add.user= \u041a\u043e&\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u043a\u043e\u0448\u0443\u0443 -button.add2=\u041a\u043e&\u0448\u0443\u0443 -button.advanced= \u041a\u043e&\u0448\u0443\u043c\u0447\u0430 -button.approve= &\u0423\u0440\u0443\u043a\u0441\u0430\u0442 \u0431\u0435\u0440\u04af\u04af -button.bookmark.room=&\u0411\u04e9\u043b\u043c\u04e9\u043d\u04af \u044d\u0441\u0431\u0435\u043b\u0433\u0438\u043b\u04e9\u04e9 -button.browse= &\u0410\u0440\u0430\u043b\u043e\u043e... -button.browse2= \u0410&\u0440\u0430\u043b\u043e\u043e... -button.browse3= \u0410\u0440&\u0430\u043b\u043e\u043e... -button.cancel= \u0410&\u0439\u043d\u0443\u0443 -button.clear= &\u0422\u0430\u0437\u0430\u043b\u043e\u043e -button.close=&\u0416\u0430\u0431\u0443\u0443 -button.copy.to.clipboard=\u0411\u0443\u0444\u0435\u0440\u0433\u0435 \u043a\u04e9\u0447\u04af\u0440\u04af\u04af -button.create.account= \u041a&\u0430\u0442\u0442\u0430\u043b\u0443\u0443 -button.create.room= \u0411\u04e9&\u043b\u043c\u04e9\u043d\u04af \u0442\u04af\u0437\u04af\u04af \u0436\u0435 \u043a\u0438\u0440\u04af\u04af -button.decline= &\u0427\u0435\u0442\u043a\u0435 \u043a\u0430\u0433\u0443\u0443 -button.deny= \u0427&\u0435\u0442\u043a\u0435 \u043a\u0430\u0433\u0443\u0443 -button.dial.number= &\u041d\u043e\u043c\u0435\u0440\u0434\u0438 \u0442\u0435\u0440\u04af\u04af -button.find= \u0422\u0430&\u0431\u0443\u0443 -button.join= \u041a\u043e&\u0448\u0443\u043b\u0443\u0443 -button.join.room= \u0422\u0430\u043d\u0434\u0430\u043b&\u0433\u0430\u043d \u0431\u04e9\u043b\u043c\u04e9\u0433\u04e9 \u043a\u0438\u0440\u04af\u04af -button.new= &\u0416\u0430\u04a3\u044b -button.profile= \u041f\u0440&\u043e\u0444\u0438\u043b\u044c -button.quit=&\u0427\u044b\u0433\u0443\u0443 -button.reconnect= \u041a\u0430&\u0439\u0440\u0430\u0434\u0430\u043d \u0442\u0443\u0442\u0430\u0448\u0443\u0443 -button.reconnect2=\u041a\u0430\u0439\u0440\u0430\u0434\u0430\u043d \u0442\u0443\u0442\u0430\u0448\u0443\u0443 -button.refresh= \u0416&\u0430\u04a3\u044b\u043b\u043e\u043e -button.register= \u041a\u0430&\u0442\u0442\u0430\u043b\u0443\u0443 -button.reject=&\u0427\u0435\u0442\u043a\u0435 \u043a\u0430\u0433\u0443\u0443 -button.remove.bookmark= \u042d\u0441\u0431\u0435\u043b\u0433\u0438\u043d\u0438 \u0430\u043b\u044b\u043f \u0441\u0430\u043b\u0443\u0443 -button.roster= \u041a&\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0438\u0437\u043c\u0435\u0441\u0438 -button.save= &\u0421\u0430\u043a\u0442\u043e\u043e -button.save.for.future.use= \u041a\u0438\u0439\u0438&\u043d\u043a\u0438 \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0448\u0442\u0430\u0440\u0433\u0430 \u04af\u0447\u04af\u043d \u0441\u0430\u043a\u0442\u043e\u043e -button.search= &\u0418\u0437\u0434\u04e9\u04e9 -button.send=\u0416\u04e9\u043d\u04e9\u0442\u04af\u04af -button.send.email= Email -button.start.chat= \u0427\u0430\u0442 -button.tasks.active=\u0410\u043a\u0442\u0438\u0432\u0434\u04af\u04af -button.tasks.all=\u0411\u0430\u0440\u0434\u044b\u0433\u044b -button.unset.file.explorer= Unset File Browser -button.update= &\u0416\u0430\u04a3\u044b\u043b\u043e\u043e -button.view.notes=\u042d\u0441\u043a\u0435\u0440\u0442\u043c\u0435\u043b\u0435\u0440\u0434\u0438 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -button.view.profile=\u0422\u043e\u043b\u0443\u043a \u043f\u0440\u043e\u0444\u0438\u043b\u0434\u0438 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -button.view.tasklist=\u0422\u0430\u043f\u0448\u0438\u0440\u043c\u0430\u043b\u0430\u0440 \u0442\u0438\u0437\u043c\u0435\u0441\u0438\u043d \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -cancel= \u0410\u0439\u043d\u0443\u0443 -checkbox.allow.buzz= \u0421\u0438\u0437\u0434\u0438 \u00ab\u043e\u0439\u0433\u043e\u0442\u0443\u0443\u00bb \u0430\u0440\u0430\u043a\u0435\u0442\u0438\u043d\u0435 \u0443\u0440\u0443\u043a\u0441\u0430\u0442 \u0431\u0435\u0440\u04af\u04af. -checkbox.auto.discover.port= &\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b\u043a \u0442\u04af\u0440\u0434\u04e9 \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0438 \u0436\u0430\u043d\u0430 \u043f\u043e\u0440\u0442\u0442\u0443 \u0442\u0430\u0431\u0443\u0443 -checkbox.auto.login= \u0410&\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b\u043a \u043a\u0438\u0440\u04af\u04af -checkbox.broadcast.hide.offline.user= \u04e9\u0447\u04af\u043a \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440\u0434\u044b \u0436\u0430\u0448\u044b\u0440\u0443\u0443 -checkbox.disable.chat.history= \u0427\u0430\u0442 &\u0442\u0430\u0440\u044b\u0445\u044b\u043d \u0438\u0448\u0442\u0435\u043d \u0447\u044b\u0433\u0430\u0440\u0443\u0443 -checkbox.disable.prev.chat.history= &\u041c\u0443\u0440\u0443\u043d\u043a\u0443 \u0441\u04af\u0439\u043b\u04e9\u0448\u04af\u04af\u043b\u04e9\u0440\u0434\u04af \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af\u0441\u04af\u043d \u04e9\u0447\u04af\u0440\u04af\u04af -checkbox.enable.emoticons= \u041a\u04af\u043b\u043a\u04af \u0441\u04af\u0440\u04e9\u0442\u0431\u0435\u043b\u0433\u0438\u043b\u0435\u0440\u0434\u0438 \u0436\u0430\u043d\u0434\u044b\u0440\u0443\u0443 -checkbox.idle.enabled=\u00ab\u041e\u0440\u0443\u043d\u0434\u0430 \u044d\u043c\u0435\u0441\u00bb &\u0436\u0430\u043d\u0434\u044b\u0440\u0443\u0443 -checkbox.launch.on.startup= &\u0416\u04af\u043a\u0442\u04e9\u043b\u04af\u04af\u0434\u04e9 \u0431\u0430\u0448\u0442\u043e\u043e -checkbox.notify.systemtray=\u0416\u0430\u04a3\u044b \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430\u043b\u0430\u0440\u0434\u044b \u0441\u0438\u0441\u0442\u0435\u043c\u0434\u0438\u043a \u0442\u0440\u0435\u0439\u0434\u0435 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -checkbox.notify.typing.systemtray=\u0416\u0430\u0437\u044b\u043f \u0436\u0430\u0442\u043a\u0430\u043d\u0434\u044b\u0433\u044b\u043d \u0441\u0438\u0441\u0442\u0435\u043c\u0434\u0438\u043a \u0442\u0440\u0435\u0439\u0434\u0435 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -checkbox.notify.user.comes.online=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0442\u0430\u0440\u043c\u0430\u043a\u043a\u0430 \u043a\u0438\u0440\u0433\u0435\u043d\u0434\u0435 \u044d\u0441\u0442\u0435\u0442\u04af\u04af -checkbox.notify.user.goes.offline=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0442\u0430\u0440\u043c\u0430\u043a\u0442\u0430\u043d \u0447\u044b\u043a\u043a\u0430\u043d\u0434\u0430 \u044d\u0441\u0442\u0435\u0442\u04af\u04af -checkbox.permanent= \u0422&\u0443\u0440\u0430\u043a\u0442\u0443\u0443 \u0431\u04e9\u043b\u043c\u04e9 -checkbox.play.sound.on.invitation= \u0427\u0430\u043a\u044b\u0440\u0443\u0443\u043d\u0443 \u043a\u0430\u0431\u044b\u043b \u0430&\u043b\u0443\u0443\u0434\u0430 \u04af\u043d\u0434\u04af \u043e\u0439\u043d\u043e\u0442\u0443\u0443 -checkbox.play.sound.on.new.message= \u0416\u0430\u04a3\u044b &\u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430\u043b\u0430\u0440 \u04af\u0447\u04af\u043d \u04af\u043d\u0434\u04af \u043e\u0439\u043d\u043e\u0442\u0443\u0443 -checkbox.play.sound.on.outgoing.message=\u041a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430\u043d\u044b &\u0436\u04e9\u043d\u04e9\u0442\u04af\u04af\u0434\u04e9 \u04af\u043d\u0434\u04af \u043e\u0439\u043d\u043e\u0442\u0443\u0443 -checkbox.play.sound.when.offline= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0442\u0430\u0440\u043c\u0430\u043a\u0442\u0430\u043d &\u0447\u044b\u043a\u043a\u0430\u043d\u0434\u0430 \u04af\u043d\u0434\u04af \u043e\u0439\u043d\u043e\u0442\u0443\u0443 -checkbox.private.room= \u0416\u0435\u043a\u0435 &\u0431\u04e9\u043b\u043c\u04e9 -checkbox.save.password= &\u0421\u044b\u0440\u0441\u04e9\u0437\u0434\u04af \u0441\u0430\u043a\u0442\u043e\u043e -checkbox.show.avatars.in.contactlist=&C\u04af\u0440\u04e9\u0442\u0431\u0435\u043b\u0433\u0438\u043b\u0435\u0440\u0434\u0438 \u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0438\u0437\u043c\u0435\u0441\u0438\u043d\u0434\u0435 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -checkbox.show.notifications.in.conference= &\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f\u043b\u0430\u0440\u0434\u0430 \u044d\u0441\u043a\u0435\u0440\u0442\u04af\u04af\u043b\u04e9\u0440\u0434\u04af \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -checkbox.show.time.in.chat.window= &\u0427\u0430\u0442 \u0442\u0435\u0440\u0435\u0437\u0435\u0441\u0438\u043d\u0434\u0435 \u0443\u0431\u0430\u043a\u044b\u0442\u0442\u044b \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -checkbox.show.toaster= \u0410\u0440 \u0431\u0438\u0440 &\u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430\u043d\u044b \u0431\u0438\u043b\u0434\u0438\u0440\u04af\u04af -checkbox.split.chat.window= \u0422\u0435\u0440\u0435\u0437\u0435\u043b\u0435\u0440\u0433\u0435 &\u0436\u0430\u0431\u044b\u0448\u0442\u044b\u0440\u0443\u0443 (\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430\u043d\u044b \u043a\u0430\u0439\u0440\u0430\u0434\u0430\u043d \u0431\u0430\u0448\u0442\u043e\u043e \u043a\u0435\u0440\u0435\u043a) -checkbox.start.in.tray= &\u0421\u0438\u0441\u0442\u0435\u043c\u0434\u0438\u043a \u0442\u0440\u0435\u0439\u0434\u0435 \u0431\u0430\u0448\u0442\u043e\u043e -checkbox.tabs.on.top= \u0427\u0430\u0442\u0442\u044b \u0442\u0435\u0440\u0435\u0437\u0435\u043b\u0435\u0440\u0434\u0438\u043d \u04af\u0441\u0442\u04af\u043d\u04e9\u043d \u0430\u0447\u0443\u0443 (\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430\u043d\u044b \u043a\u0430\u0439\u0440\u0430\u0434\u0430\u043d \u0431\u0430\u0448\u0442\u043e\u043e \u043a\u0435\u0440\u0435\u043a) -checkbox.use.compression=Use Co&mpression -checkbox.use.debugger.on.startup=\u0411\u0430\u0448\u0442\u0430\u043b\u044b\u0448\u0442\u0430 &Debugger'\u0434\u0438 \u0431\u0430\u0448\u0442\u043e\u043e -checkbox.use.krb.dns=DNS \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443 -checkbox.use.krbconf=krb5.conf \u0436\u0435 krb5.ini \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443 -checkbox.use.pki.authentication= &PKI \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u044b\u044f\u0441\u044b\u043d \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443 -checkbox.use.proxy.server= Pro&xy \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0438 \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443 -checkbox.use.specify.below=\u0422\u04e9\u043c\u04e9\u043d\u0434\u04e9 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -checkbox.use.system.look.and.feel= \u0422\u0435\u043c\u0430\u043b\u0430\u0440\u0434\u044b \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443 (System Look And &Feel) (\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430\u043d\u044b \u043a\u0430\u0439\u0440\u0430\u0434\u0430\u043d \u0431\u0430\u0448\u0442\u043e\u043e \u043a\u0435\u0440\u0435\u043a) -checkbox.window.to.front=&\u0422\u0435\u0440\u0435\u0437\u0435\u043d\u0438 \u0430\u043b\u0434\u044b\u0433\u0430 \u0430\u043b\u044b\u043f \u043a\u0435\u043b\u04af\u04af -close=\u0416\u0430\u0431\u0443\u0443 -create= \u0422\u04af\u0437\u04af\u04af -date= \u0414\u0430\u0442\u0430 -delete.log.permanently=Permanently delete log -delete.permanently= Permanently delete? -description= \u041a\u044b\u0441\u043a\u0430\u0447\u0430 \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442 -from= \u041a\u0438\u043c\u0434\u0435\u043c -gateway.username.password.error=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b \u0436\u0430\u043d\u0430/\u0436\u0435 \u0421\u044b\u0440\u0441\u04e9\u0437 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u043b\u04af\u0448\u04af \u043a\u0435\u0440\u0435\u043a. -group.chat.name.match=\u0421\u0438\u0437\u0434\u0438\u043d \u0430\u0442\u044b\u04a3\u044b\u0437 \u0433\u0440\u0443\u043f\u043f\u0430 \u0447\u0430\u0442\u044b\u043d\u0434\u0430 \u0430\u0439\u0442\u044b\u043b\u0434\u044b: -group.chat.name.notification=\u0410\u0442\u044b\u04a3\u044b\u0437 \u043a\u04e9\u0440\u04af\u043b\u0434\u04af... -group.chat.window.information= \u0427\u0430\u0442 \u0436\u04e9\u043d\u04af\u043d\u0434\u04e9 \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442 -group.comma.delimited= Comma Delimited -group.conferences.found=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f \u043a\u044b\u0437\u043c\u0430\u0442\u0442\u0430\u0440\u044b \u0442\u0430\u0431\u044b\u043b\u0434\u044b -group.connection= \u0422\u0443\u0442\u0430\u0448\u0443\u0443 -group.empty=\u0411\u0443\u043b \u0433\u0440\u0443\u043f\u043f\u0430\u0434\u0430\u043d \u044d\u0447 \u043a\u0438\u043c\u0438\u0441\u0438 \u0442\u0430\u0440\u043c\u0430\u043a\u0442\u0430 \u0436\u043e\u043a. -group.general.information= \u041d\u0435\u0433\u0438\u0437\u0433\u0438 \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442 -group.login.information=\u041b\u043e\u0433\u0438\u043d \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u044b -group.notification.options= \u042d\u0441\u0442\u0435\u0442\u04af\u04af \u044b\u0440\u0430\u0441\u0442\u043e\u043e\u043b\u043e\u0440\u0443 -group.offline=\u0422\u0430\u0440\u043c\u0430\u043a\u0442\u0430 \u044d\u043c\u0435\u0441 \u0433\u0440\u0443\u043f\u043f\u0430\u0441\u044b -group.search.form=\u0418\u0437\u0434\u04e9\u04e9 -group.search.results=\u0418\u0437\u0434\u04e9\u04e9 \u0436\u044b\u0439\u044b\u043d\u0442\u044b\u0433\u044b -invite= \u0427\u0430\u043a\u044b\u0440\u0443\u0443 -join=\u041a\u043e\u0448\u0443\u043b\u0443\u0443 -label.accounts=&\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440 -label.add.conference.service= \u041a\u043e\u043d\u0444\u0435&\u0440\u0435\u043d\u0446\u0438\u044f\u043b\u0430\u0440 \u0441\u0435\u0440\u0432\u0435\u0440\u0438\u043d \u043a\u043e\u0448\u0443\u0443 -label.add.jid= JID &\u043a\u043e\u0448\u0443\u0443 -label.add.task=\u0422\u0430\u043f\u0448\u044b\u0440\u043c\u0430 \u043a\u043e\u0448\u0443\u0443 -label.auto.login= &\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b\u043a \u043a\u0438\u0440\u04af\u04af -label.available.users.in.roster= &\u0411\u0430\u0440 \u0431\u043e\u043b\u0433\u043e\u043d \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440 -label.cancel= \u0410\u0439\u043d\u0443\u0443 -label.cell=Cell -label.change.password.to= &\u0421\u044b\u0440\u0441\u04e9\u0437\u0434\u04af \u0430\u043b\u043c\u0430\u0448\u0442\u044b\u0440\u0443\u0443 -label.chatroom.fontsize=\u0427\u0430\u0442 &\u0431\u04e9\u043b\u043c\u04e9\u043d\u04af\u043d \u0444\u043e\u043d\u0442 \u04e9\u043b\u0447\u04e9\u043c\u04af: -label.choose.file=\u0424\u0430\u0439\u043b\u0434\u044b \u0442\u0430\u043d\u0434\u0430\u04a3\u044b\u0437 -label.city= &\u0428\u0430\u0430\u0440 -label.close=&\u0416\u0430\u0431\u0443\u0443 -label.company= \u041a&\u043e\u043c\u043f\u0430\u043d\u0438\u044f -label.confirm.password= \u0421\u044b&\u0440\u0441\u04e9\u0437\u0434\u04af \u043a\u0430\u0439\u0442\u0430\u043b\u043e\u043e -label.conflict.error= \u0422\u0443\u0442\u0430\u0448\u0443\u0443 \u043c\u04af\u043c\u043a\u04af\u043d \u044d\u043c\u0435\u0441. \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0431\u0430\u0448\u043a\u0430 \u0436\u0435\u0440\u0434\u0435\u043d \u0442\u0443\u0442\u0430\u0448\u0442\u044b. -label.contact.to.find= \u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0442\u044b \u0442\u0430\u0431\u0443\u0443 -label.contactlist.avatarsize=\u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0438\u0437\u043c\u0435\u0434\u0435 \u0430\u0432\u0430\u0442\u0430\u0440 \u04e9\u043b\u0447\u04e9\u043c\u04af: -label.contactlist.fontsize=\u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0438\u0437\u043c\u0435\u043d\u0438\u043d &\u0444\u043e\u043d\u0442 \u04e9\u043b\u0447\u04e9\u043c\u04af: -label.country= &\u04e8\u043b\u043a\u04e9 -label.create.account= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d &\u0442\u04af\u0437\u04af\u04af -label.department=&\u041e\u0442\u0434\u0435\u043b -label.dial= \u0422&\u0435\u0440\u04af\u04af -label.downloads=\u0416\u04af\u043a\u0442\u04e9\u04e9\u043b\u04e9\u0440 -label.due=Due -label.email.address= &Email \u0430\u0434\u0440\u0435\u0441\u0438 -label.emoticons= &\u041a\u04af\u043b\u043a\u04af \u0441\u04af\u0440\u04e9\u0442\u0431\u0435\u043b\u0433\u0438\u043b\u0435\u0440\u0438 -label.enter.address= \u0410\u0434\u0440\u0435\u0441\u0442\u0438 \u043a\u0438\u0440\u0438\u04a3\u0438\u0437 -label.enter.group.name= \u0413\u0440\u0443\u043f\u043f\u0430\u043d\u044b\u043d \u0436\u0430\u04a3\u044b \u0430\u0442\u044b\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437 -label.enter.password=\u0421\u044b\u0440\u0441\u04e9\u0437\u0434\u04af \u043a\u0438\u0440\u0438\u04a3\u0438\u0437 -label.fax= &\u0424\u0430\u043a\u0441 -label.find= &\u0422\u0430\u0431\u0443\u0443 -label.first.name=&\u0410\u0442\u044b -label.group=&\u0413\u0440\u0443\u043f\u043f\u0430 -label.home=\u04ae\u0439 -label.host=&\u0421\u0435\u0440\u0432\u0435\u0440 -label.invited.users= \u0427\u0430\u043a\u044b\u0440\u044b\u043b\u0433\u0430\u043d \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440 -label.jabber.address= &Jabber \u0430\u0434\u0440\u0435\u0441\u0438 -label.jabber.id= &Jabber ID -label.jid= &JID -label.job.title=&\u041a\u044b\u0437\u043c\u0430\u0442\u044b -label.krb.kdc=KDC -label.krb.realm=Realm -label.last.name= &\u0424\u0430\u043c\u0438\u043b\u0438\u044f -label.local.time= \u0416&\u0435\u0440\u0433\u0438\u043b\u0438\u043a\u0442\u04af\u04af \u0443\u0431\u0430\u043a\u044b\u0442 -label.message= &\u041a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430 -label.message.style= \u041a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430 &\u0441\u0442\u0438\u043b\u0438 -label.middle.name= &\u0410\u0442\u0430\u0441\u044b\u043d\u044b\u043d \u0430\u0442\u044b -label.minutes.before.stale.chat=&\u0410\u043a\u0442\u0438\u0432\u0434\u04af\u04af \u044d\u043c\u0435\u0441 \u0431\u04e9\u043b\u043c\u04e9\u043d\u04af\u043d \u044d\u0441\u043a\u0438\u0440\u04af\u04af\u0441\u04af\u043d\u04e9 \u04e9\u0442\u043a\u04e9\u043d \u0443\u0431\u0430\u043a\u044b\u0442\u044b -label.mobile= &\u0423\u044e\u043b\u0434\u0443\u043a \u0442\u0435\u043b\u0435\u0444\u043e\u043d -label.move.focus.backwards=\u0424\u043e\u043a\u0443\u0441\u0442\u0443 \u0430\u043b\u0434\u044b\u0433\u0430 \u0436\u044b\u043b\u0434\u044b\u0440\u0443\u0443 -label.move.focus.forwards=\u0424\u043e\u043a\u0443\u0441\u0442\u0443 \u0430\u0440\u0442\u043a\u0430 \u0436\u044b\u043b\u0434\u044b\u0440\u0443\u0443 -label.na=\u0436\u043e\u043a -label.name= &\u0410\u0442\u044b -label.network= &\u0422\u0430\u0440\u043c\u0430\u043a -label.new.nickname= \u0416\u0430\u04a3\u044b \u0442\u0430\u043a\u043c\u0430 \u044b\u0441\u044b\u043c\u044b -label.nickname= \u0422\u0430\u043a&\u043c\u0430 \u044b\u0441\u044b\u043c\u044b -label.number= &\u041d\u043e\u043c\u0435\u0440\u0438 -label.ok= OK -label.old.ssl= \u00abOLD SSL port\u00bb \u043c\u0435\u0442\u043e\u0434\u0443\u043d &\u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443 -label.os= &\u041e\u0421 -label.pager= &\u041f\u0435\u0439\u0434\u0436\u0435\u0440 -label.password= &\u0421\u044b\u0440\u0441\u04e9\u0437 -label.phone= \u0422\u0435\u043b\u0435&\u0444\u043e\u043d -label.port= \u041f\u043e\u0440&\u0442 -label.postal.code= \u041f\u043e\u0447\u0442\u0430 &\u0438\u043d\u0434\u0435\u043a\u0441\u0438 -label.presence= &\u0421\u0442\u0430\u0442\u0443\u0441 -label.priority= \u041f&\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 -label.protocol= \u041f&\u0440\u043e\u0442\u043e\u043a\u043e\u043b -label.received=\u041a\u044b&\u0431\u044b\u043b \u0430\u043b\u044b\u043d\u0434\u044b -label.rename.to= \u0410\u0442\u044b\u043d \u0430\u043b\u043c\u0430\u0448\u0442\u044b\u0440\u0443\u0443 -label.resource= &\u0420\u0435\u0441\u0443\u0440\u0441 -label.response.timeout= &\u0416\u043e\u043e\u043f \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0443 (\u0441\u0435\u043a) -label.room= &\u0411\u04e9\u043b\u043c\u04e9 -label.room.name= \u0411\u04e9\u043b\u043c\u04e9\u043d\u04af\u043d &\u0430\u0442\u044b -label.room.topic= \u0411\u04e9\u043b\u043c\u04e9\u043d\u04af\u043d &\u0442\u0435\u043c\u0430\u0441\u044b -label.search.service=&\u0418\u0437\u0434\u04e9\u04e9 \u0441\u0435\u0440\u0432\u0438\u0441\u0438 -label.server= \u0421\u0435\u0440&\u0432\u0435\u0440 -label.server.address= \u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0438\u043d \u0430\u0434\u0440\u0435\u0441\u0438 -label.show=\u041a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af: -label.software= &\u041a\u043b\u0438\u0435\u043d\u0442\u0438 -label.state.and.province= \u041e&\u0431\u043b\u0430\u0441\u0442\u044c -label.street.address= \u0410&\u0434\u0440\u0435\u0441 -label.time= \u0423\u0431\u0430\u043a\u044b\u0442: {0} -label.time.till.idle= \u00ab\u041e\u0440\u0443\u043d\u0434\u0430 \u044d\u043c\u0435\u0441\u00bb \u04e9\u0442\u043a\u04e9\u043d \u0443\u0431\u0430\u043a\u044b\u0442 (\u043c\u0438\u043d) -label.timeformat=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443 {0} -label.transfer.download.directory=&\u041f\u0430\u043f\u043a\u0430\u0433\u0430 \u0441\u0430\u043a\u0442\u043e\u043e: -label.transfer.timeout= \u04e8\u0442\u043a\u04e9\u0437\u04af\u04af \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0443 (\u043c\u0438\u043d\u0443\u0442\u0430 \u043c\u0435\u043d\u0435\u043d): -label.trust.store.password= Trust Store \u0441\u044b\u0440\u0441\u04e9\u0437\u04af -label.unable.to.add.contact= \u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u043a\u043e\u0448\u0443\u043b\u0433\u0430\u043d \u0436\u043e\u043a. -label.use.default= \u0410\u043b\u0434\u044b\u043d\u0430\u043b\u0430 -label.user.on.public.network= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0436\u0430\u043b\u043f\u044b \u0442\u0430\u0440\u043c\u0430\u043a \u0438\u0447\u0438\u043d\u0434\u0435 -label.username= \u041a&\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b -label.version= &\u0412\u0435\u0440\u0441\u0438\u044f\u0441\u044b -label.web.page= &\u0412\u0435\u0431 \u0431\u0430\u0440\u0430\u043a\u0447\u0430\u0441\u044b -label.which.pki.method=\u041a\u0430\u0439\u0441\u044b PKI \u043c\u0435\u0442\u043e\u0434\u0443? -label.work=\u0416\u0443\u043c\u0443\u0448\u0443 -label.xmpp.port= &XMPP \u043f\u043e\u0440\u0442\u0443 -menuitem.about= \u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0436\u04e9\u043d\u04af\u043d\u0434\u04e9 -menuitem.actions= \u0410\u043c\u0430\u043b\u0434\u0430\u0440 -menuitem.add= \u041a\u043e\u0448\u0443\u0443 -menuitem.add.as.contact= \u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0442\u044b \u043a\u043e\u0448\u0443\u0443 -menuitem.add.contact=\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0442\u044b \u043a\u043e\u0448\u0443\u0443 -menuitem.add.contact.group= \u0413\u0440\u0443\u043f\u043f\u0430\u043d\u044b \u043a\u043e\u0448\u0443\u0443 -menuitem.add.groupchat.myname=\u041c\u0435\u043d\u0438\u043d \u0430\u0442\u044b\u043c \u0430\u0439\u0442\u044b\u043b\u0433\u0430\u043d\u0434\u0430 \u0430\u0442\u044b\u043c\u0434\u044b \u0436\u0430\u0440\u043a\u044b\u0440\u0430\u0442\u0443\u0443 -menuitem.add.groupchat.mytext=\u041c\u0435\u043d \u0441\u04af\u0439\u043b\u04e9\u0433\u04e9\u043d\u0434\u04e9 \u0442\u0435\u043a\u0441\u0442\u0442\u0438 \u0436\u0430\u0440\u043a\u044b\u0440\u0430\u0442\u0443\u0443 -menuitem.add.groupchat.popname= Show custom toaster popup when someone says my name -menuitem.add.groupchat.showjoinleavemessage=\u041a\u043e\u0448\u0443\u043b\u0443\u0443 \u0436\u0430\u043d\u0430 \u0447\u044b\u0433\u0443\u0443 \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430\u043b\u044b\u0440\u0434\u044b \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -menuitem.alert.when.online= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0442\u0430\u0440\u043c\u0430\u043a\u043a\u0430 \u043a\u0438\u0440\u0433\u0435\u043d\u0434\u0435 \u044d\u0441\u0442\u0435\u0442\u04af\u04af -menuitem.always.on.top=\u0410\u0440 \u0434\u0430\u0439\u044b\u043c \u04af\u0441\u0442\u04af\u0434\u04e9 -menuitem.ban= \u0427\u0435\u043a\u0442\u04e9\u04e9 -menuitem.ban.user= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043d\u0443 \u0447\u0435\u043a\u0442\u04e9\u04e9 -menuitem.block.user= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043d\u0443 \u0431\u043b\u043e\u043a\u0442\u043e\u043e -menuitem.bookmark.room= Bookmark Room -menuitem.bookmarks=\u042d\u0441\u0431\u0435\u043b\u0433\u0435\u043b\u0435\u0440 -menuitem.broadcast.to.group=\u0413\u0440\u0443\u043f\u043f\u0430\u0433\u0430 \u043a\u04e9\u043f\u0442\u04af\u043a \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430\u043d\u044b \u0436\u04e9\u043d\u04e9\u0442\u04af\u04af -menuitem.browse.service=\u041a\u044b\u0437\u043c\u0430\u0442\u0442\u044b \u0430\u0440\u0430\u043b\u043e\u043e -menuitem.change.nickname= \u0422\u0430\u043a\u043c\u0430 \u044b\u0441\u044b\u043c\u0434\u044b \u0430\u043b\u043c\u0430\u0448\u0442\u044b\u0440\u0443\u0443 -menuitem.change.subject= \u0422\u0435\u043c\u0430\u043d\u044b \u0430\u043b\u043c\u0430\u0448\u0442\u044b\u0440\u0443\u0443 -menuitem.chat= \u0427\u0430\u0442 -menuitem.chatframe.option=\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440 -menuitem.check.for.updates= \u0416\u0430\u04a3\u044b\u043b\u043e\u043e\u043b\u043e\u0440\u0434\u0443 \u0442\u0435\u043a\u0448\u0435\u0440\u04af\u04af -menuitem.collapse.all.groups=\u0411\u0430\u0440\u0434\u044b\u043a \u0433\u0440\u0443\u043f\u043f\u0430\u043b\u0430\u0440\u0434\u044b \u0436\u044b\u044e -menuitem.contacts= \u041a\u043e\u043d\u0442\u0430\u043a\u0442 -menuitem.copy.to= \u041a\u04e9\u0447\u04af\u0440\u04af\u04af -menuitem.create.room=\u0411\u04e9\u043b\u043c\u04e9\u043d\u04af \u0442\u04af\u0437\u04af\u04af \u0436\u0435 \u043a\u043e\u0448\u0443\u043b\u0443\u0443 -menuitem.delete= \u04e8\u0447\u04af\u0440\u04af\u04af -menuitem.delete.login.information=\u041a\u0430\u0442\u0442\u0430\u043b\u0443\u0443 \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u0430\u0440\u044b\u043d \u04e9\u0447\u04af\u0440\u04af\u04af -menuitem.destroy.room= \u0411\u04e9\u043b\u043c\u04e9\u043d\u04af \u0431\u0443\u0437\u0443\u0443 -menuitem.dial=\u0422\u0435\u0440\u04af\u04af -menuitem.edit= \u041e\u043d\u0434\u043e\u043e -menuitem.edit.my.profile= &\u041f\u0440\u043e\u0444\u0438\u043b\u0434\u0438 \u043e\u043d\u0434\u043e\u043e... -menuitem.edit.status.message= \u0421\u0442\u0430\u0442\u0443\u0441\u0442\u0430\u0440\u0434\u044b \u043e\u043d\u0434\u043e\u043e... -menuitem.enter.login.information= \u041a\u0430\u0442\u0442\u0430\u043b\u0443\u0443 \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u0430\u0440\u044b\u043d \u043a\u0438\u0440\u04af\u04af -menuitem.exit=\u0427\u044b\u0433\u0443\u0443 -menuitem.expand.all.groups=\u0411\u0430\u0440\u0434\u044b\u043a \u0433\u0440\u0443\u043f\u043f\u0430\u043b\u0430\u0440\u0434\u044b \u0436\u0430\u0439\u043d\u043e\u043e -menuitem.grant.moderator= \u041c\u043e\u0434\u0435\u0440\u0430\u0442\u043e\u0440 \u0443\u043a\u0443\u043a\u0442\u0430\u0440\u044b\u043d \u0431\u0435\u0440\u04af\u04af -menuitem.grant.voice= \u0421\u04af\u0439\u043b\u04e9\u04e9 \u0443\u043a\u0443\u0433\u0443\u043d \u0431\u0435\u0440\u04af\u04af -menuitem.help= \u0416\u0430\u0440\u0434\u0430\u043c -menuitem.hide=\u0416\u0430\u0448\u044b\u0440\u0443\u0443 -menuitem.inivite.again=\u041a\u0430\u0439\u0440\u0430\u0434\u0430\u043d \u0447\u0430\u043a\u044b\u0440\u0443\u0443 -menuitem.invite.group.to.conference=\u0413\u0440\u0443\u043f\u043f\u0430\u043d\u044b \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f\u0433\u0430 \u0447\u0430\u043a\u044b\u0440\u0443\u0443 -menuitem.invite.users= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440\u0434\u044b \u0447\u0430\u043a\u044b\u0440\u0443\u0443 -menuitem.join.on.startup= \u0416\u04af\u043a\u0442\u04e9\u043b\u04af\u04af\u0434\u04e9 \u043a\u0438\u0440\u04af\u04af -menuitem.join.room= \u0411\u04e9\u043b\u043c\u04e9\u0433\u04e9 \u043a\u0438\u0440\u04af\u04af -menuitem.kick.user= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043d\u0443 \u0430\u0439\u0434\u0430\u043f \u0441\u0430\u043b\u0443\u0443 -menuitem.languages=\u0422\u0438\u043b\u0434\u0435\u0440 -menuitem.logout.no.status=\u0422\u0430\u0440\u043c\u0430\u043a\u0442\u0430\u043d \u0447\u044b\u0433\u0443\u0443 -menuitem.logout.with.status= \u0421\u0435\u0431\u0435\u043f \u043c\u0435\u043d\u0435\u043d \u0447\u044b\u0433\u0443\u0443 -menuitem.lookup.profile= \u041f\u0440\u043e&\u0444\u0438\u043b\u0434\u0438 \u043a\u04e9\u0440\u04af\u04af... -menuitem.move.to= \u0416\u044b\u043b\u0434\u044b\u0440\u0443\u0443 -menuitem.online.help= Spark \u0444\u043e\u0440\u0443\u043c\u0434\u0430\u0440\u044b -menuitem.open= \u0410\u0447\u0443\u0443 -menuitem.open.with=\u041c\u0435\u043d\u0435\u043d \u0430\u0447\u0443\u0443... -menuitem.plugins= \u041f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440 -menuitem.preferences= \u042b\u0440\u0430\u0441\u0442\u043e\u043e\u043b\u043e\u0440 -menuitem.refresh=\u0416\u0430\u04a3\u044b\u043b\u043e\u043e -menuitem.remove=\u0410\u043b\u044b\u043f \u0441\u0430\u043b\u0443\u0443 -menuitem.remove.alert.when.online= \u042d\u0441\u043a\u0435\u0440\u0442\u04af\u04af\u043d\u04af \u0430\u043b\u044b\u043f \u0441\u0430\u043b\u0443\u0443 -menuitem.remove.bookmark=\u042d\u0441\u0431\u0435\u043b\u0433\u0435\u043d\u0438 \u0430\u043b\u044b\u043f \u0441\u0430\u043b\u0443\u0443 -menuitem.remove.from.group=\u0413\u0440\u0443\u043f\u043f\u0430\u0434\u0430\u043d \u0430\u043b\u044b\u043f \u0441\u0430\u043b\u0443\u0443 -menuitem.remove.from.roster=\u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0438\u0437\u043c\u0435\u0434\u0435\u043d \u0430\u043b\u044b\u043f \u0441\u0430\u043b\u0443\u0443 -menuitem.remove.service=\u041a\u044b\u0437\u043c\u0430\u0442\u0442\u044b \u0430\u043b\u044b\u043f \u0441\u0430\u043b\u0443\u0443 -menuitem.rename= \u0410\u0442\u044b\u043d \u0430\u043b\u043c\u0430\u0448\u0442\u044b\u0440\u0443\u0443 -menuitem.revoke.moderator=\u041c\u043e\u0434\u0435\u0440\u0430\u0442\u043e\u0440 \u0443\u043a\u0443\u0433\u0443\u043d \u0430\u043b\u044b\u043f \u0441\u0430\u043b\u0443\u0443 -menuitem.revoke.voice= \u0421\u04af\u0439\u043b\u04e9\u04e9 \u0443\u043a\u0443\u0433\u0443\u043d \u0430\u043b\u044b\u043f \u0441\u0430\u043b\u0443\u0443 -menuitem.save= \u0421\u0430\u043a\u0442\u043e\u043e -menuitem.save.as=\u0416\u0430\u04a3\u044b\u0447\u0430 \u0441\u0430\u043a\u0442\u043e\u043e... -menuitem.send.a.file= \u0424\u0430\u0439\u043b \u0436\u04e9\u043d\u04e9\u0442\u04af\u04af -menuitem.send.a.message=\u0422\u0430\u043d\u0434\u0430\u043b\u0433\u0430\u043d \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440\u0433\u0430 \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430\u043d\u044b \u0436\u04e9\u043d\u04e9\u0442\u04af\u04af... -menuitem.set.status.message=\u0421\u0442\u0430\u0442\u0443\u0441\u0442\u0443 \u043e\u0440\u043d\u043e\u0442\u0443\u0443... -menuitem.show.contact.statusmessage=C\u0442\u0430\u0442\u0443\u0441\u0443\u043d \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -menuitem.show.empty.groups=\u0411\u043e\u0448 \u0433\u0440\u0443\u043f\u043f\u0430\u043b\u0430\u0440\u0434\u044b \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -menuitem.show.offline.group=\u0422\u0430\u0440\u043c\u0430\u043a\u0442\u0430 \u044d\u043c\u0435\u0441 \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440\u0434\u044b \u0436\u044b\u0439\u043d\u043e\u043e -menuitem.show.offline.users=\u0422\u0430\u0440\u043c\u0430\u043a\u0442\u0430 \u044d\u043c\u0435\u0441 \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440\u0434\u044b \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -menuitem.show.traffic= \u0422\u0440\u0430\u0444\u0438\u043a \u0442\u0435\u0440\u0435\u0437\u0435\u0441\u0438\u043d \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -menuitem.sign.in= \u0412\u043e\u0439\u0442\u0438 -menuitem.sign.in.at.login=\u0416\u04af\u043a\u0442\u04e9\u043b\u04af\u04af\u0434\u04e9 \u043a\u0438\u0440\u04af\u04af -menuitem.sign.out=\u0422\u0430\u0440\u043c\u0430\u043a\u0442\u0430\u043d \u0447\u044b\u0433\u0443\u0443 -menuitem.start.a.chat= \u0427\u0430\u0442\u0442\u044b \u0431\u0430\u0448\u0442\u043e\u043e -menuitem.start.a.conference=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f\u043d\u044b \u0431\u0430\u0448\u0442\u043e\u043e... -menuitem.status= \u0421\u0442\u0430\u0442\u0443\u0441 -menuitem.subscribe.to= \u0416\u0430\u0437\u044b\u043b\u0443\u0443 -menuitem.unban=\u0427\u0435\u043a\u0442\u04e9\u04e9\u043d\u04af \u0430\u043b\u044b\u043f \u0441\u0430\u043b\u0443\u0443 -menuitem.unblock.user= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043d\u0443 \u0431\u043b\u043e\u043a\u0442\u043e\u043d \u0430\u043b\u044b\u043f \u0441\u0430\u043b\u0443\u0443 -menuitem.user.guide= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u0441\u044b -menuitem.view.client.version= \u041a\u043b\u0438\u0435\u043d\u0442 \u0432\u0435\u0440\u0441\u0438\u044f\u0441\u044b\u043d \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -menuitem.view.contact.history= \u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0430\u0440\u044b\u0445\u044b\u043d \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -menuitem.view.downloads= \u0416\u04af\u043a\u0442\u04e9\u04e9\u043b\u04e9\u0440 \u043f\u0430\u043f\u043a\u0430\u0441\u044b\u043d \u0430\u0447\u0443\u0443 -menuitem.view.last.activity=\u0410\u043a\u044b\u0440\u043a\u044b \u0430\u043a\u0442\u0438\u0432\u0434\u04af\u04af\u043b\u04af\u043a \u0443\u0431\u0430\u043a\u044b\u0442\u044b\u043d \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -menuitem.view.logs=\u041b\u043e\u0433\u0434\u043e\u0440\u0434\u0443 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -menuitem.view.profile= \u041f\u0440\u043e\u0444\u0438\u043b\u0434\u0438 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -menuitem.view.room.info= \u0411\u04e9\u043b\u043c\u04e9 \u0436\u04e9\u043d\u04af\u043d\u0434\u04e9 \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u044b \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -menuitem.voice= \u0421\u04af\u0439\u043b\u04e9\u04e9 \u0443\u043a\u0443\u0433\u0443 -message=\u041a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430 -message.account.create= \u0416\u0430\u04a3\u044b \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u0442\u04af\u0437\u04af\u04af. -message.account.created=\u0416\u0430\u04a3\u044b \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0442\u04af\u0437\u04af\u043b\u0434\u04af. -message.account.error= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0442\u04af\u0437\u04af\u043b\u04af\u04af\u0447\u04af \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0438 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04a3\u04af\u0437. -message.add.a.contact=\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0442\u044b \u043a\u043e\u0448\u0443\u0443 -message.add.conference.service=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f \u043a\u044b\u0437\u043c\u0430\u0442\u044b\u043d \u043a\u043e\u0448\u0443\u0443. -message.add.contact.to.list= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043d\u0443 \u043a\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0438\u0437\u043c\u0435\u0441\u0438\u043d\u0435 \u043a\u043e\u0448\u0443\u0443 -message.add.favorite.room=\u0411\u04e9\u043b\u043c\u04e9\u043d\u04af \u0436\u0430\u043a\u0442\u044b\u0440\u044b\u043b\u0433\u0430\u043d\u0434\u0430\u0440\u0433\u0430 \u043a\u043e\u0448\u0443\u0443 \u0436\u0435 \u0434\u0430\u0440\u043e\u043e \u043a\u0438\u0440\u04af\u04af. -message.add.this.user.to.your.roster=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043d\u0443 \u043a\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0438\u0437\u043c\u0435\u0441\u0438\u043d\u0435 \u043a\u043e\u0448\u0443\u0443. -message.add.to.roster=\u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0438\u0437\u043c\u0435\u0441\u0438\u043d\u0435 \u043a\u043e\u0448\u0443\u0443 -message.add.user=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u043a\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0438\u0437\u043c\u0435\u0433\u0435 \u043a\u043e\u0448\u0443\u043b\u0441\u0443\u043d\u0431\u0443? -message.alert.notify=\u042d\u0441\u043a\u0435\u0440\u0442\u04af\u04af -message.already.exists=\u041c\u044b\u043d\u0434\u0430\u0439 \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b \u0430\u043b\u0434\u0430 \u043a\u0430\u0447\u0430\u043d \u0431\u0430\u0440. \u0411\u0430\u0448\u043a\u0430 \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u043f \u043a\u04e9\u0440\u04af\u04a3\u04af\u0437. -message.approve.subscription= {0} \u0441\u0438\u0437\u0434\u0438 \u0430\u043b\u0430\u0440\u0434\u044b\u043d \u043a\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0438\u0437\u043c\u0435\u0441\u0438\u043d\u0435 \u043a\u043e\u0448\u0443\u0443\u0433\u0430 \u0443\u0440\u0443\u043a\u0441\u0430\u0442 \u0431\u0435\u0440\u0435\u0441\u0438\u0437\u0431\u0438? -message.autenticating= \u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f -message.away.idle=\u00ab\u041e\u0440\u0443\u043d\u0434\u0430 \u044d\u043c\u0435\u0441\u00bb (\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u043b\u0431\u0430\u0439 \u043a\u0430\u043b\u0433\u0430\u043d\u0434\u044b\u0433\u044b\u043d\u0430\u043d) -message.bookmark.temporary.room.error=\u0423\u0431\u0430\u043a\u0442\u044b\u043b\u0443\u0443 \u0431\u04e9\u043b\u043c\u04e9\u043b\u04e9\u0440\u0434\u04af \u044d\u0441\u0431\u0435\u043b\u0433\u0438\u043b\u0435\u0440\u0433\u0435 \u043a\u043e\u0448\u043e \u0430\u043b\u0431\u0430\u0439\u0441\u044b\u0437 -message.broadcast.from= \u041a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430 {0} \u0430\u0442\u044b\u043d\u0430\u043d -message.broadcast.message.sent=\u041a\u04e9\u043f\u0442\u04af\u043a \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430 \u0436\u04e9\u043d\u04e9\u0442\u04af\u043b\u0434\u04af\u04af. -message.broadcast.to={0} \u0436\u04e9\u043d\u04e9\u0442\u04af\u04af\u043b\u04af\u0447\u04af \u0442\u0435\u043a\u0441\u0442\u0442\u0438 \u043a\u0438\u0440\u0438\u04a3\u0438\u0437 -message.broadcasted.to=\u041a\u04e9\u043f\u0442\u04af\u043a \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430 \u0442\u04e9\u043c\u04e9\u043d\u043a\u04af \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440\u0433\u0430 \u0436\u04e9\u043d\u04e9\u0442\u04af\u043b\u0434\u04af:\u000a{0} -message.buzz.alert.notification= Get the user's attention. -message.buzz.sent= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043d\u0443 \u00ab\u043e\u0439\u0433\u043e\u0442\u0443\u0443\u00bb -message.calling= {0} \u0447\u0430\u043b\u044b\u043f \u0436\u0430\u0442\u0430\u0442 -message.came.online= {0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 {1} \u0431\u0435\u0440\u0438 \u0442\u0430\u0440\u043c\u0430\u043a\u0442\u0430 -message.cannot.add.contact.to.shared.group=\u0411\u04e9\u043b\u04af\u0448\u0442\u04af\u0440\u04af\u043b\u0433\u04e9\u043d \u0433\u0440\u0443\u043f\u043f\u0430\u0433\u0430 \u0436\u0430\u04a3\u044b \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440\u0434\u044b \u043a\u043e\u0448\u0430\u043b\u0431\u0430\u0439\u0441\u044b\u0437. -message.chat.session.ended= \u0427\u0430\u0442 {0} \u0443\u0431\u0430\u043a\u044b\u0442\u044b\u043d\u0434\u0430 \u0431\u04af\u0442\u0442\u04af -message.click.to.open=\u0410\u0447\u0443\u0443 -message.client.information={0} \u04af\u0447\u04af\u043d \u043a\u043b\u0438\u0435\u043d\u0442 \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u044b -message.close.other.chats=\u0411\u0430\u0448\u043a\u0430 \u0447\u0430\u0442\u0442\u0430\u0440\u0434\u044b \u0436\u0430\u0431\u0443\u0443 -message.close.stale.chats=\u042d\u0441\u043a\u0438\u0440\u0433\u0435\u043d \u0447\u0430\u0442\u0442\u0430\u0440\u0434\u044b \u0436\u0430\u0431\u0443\u0443 -message.close.this.chat=\u0411\u0443\u043b \u0447\u0430\u0442\u0442\u044b \u0436\u0430\u0431\u0443\u0443 -message.conference.info.error= \u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0444\u0438\u044f \u0436\u04e9\u043d\u04af\u043d\u0434\u04e9 \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442 \u0430\u043b\u0443\u0443 \u043c\u04af\u043c\u043a\u04af\u043d \u044d\u043c\u0435\u0441. \u041a\u0438\u0439\u0438\u043d\u0447\u0435\u0440\u0435\u043a \u043a\u0430\u0439\u0442\u0430\u043b\u0430\u043f \u043a\u04e9\u0440\u04af\u04a3\u04af\u0437. -message.conference.service.error=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f \u043a\u044b\u0437\u043c\u0430\u0442\u044b \u0442\u0430\u0431\u044b\u043b\u0433\u0430\u043d \u0436\u043e\u043a. -message.confirm.destruction.of.room=\u0411\u0443\u0437\u0443\u043b\u0443\u0443\u0447\u0443 \u0431\u04e9\u043b\u043c\u04e9\u0434\u04e9 \u0431\u0430\u0440 \u0431\u043e\u043b\u0433\u043e\u043d \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440 \u0431\u04e9\u043b\u043c\u04e9\u0434\u04e9\u043d \u0430\u0439\u0434\u0430\u043b\u044b\u043d\u044b\u043f \u0441\u0430\u043b\u044b\u043d\u0430\u0442. \u0423\u043b\u0430\u043d\u0442\u0443\u0443? -message.confirmation.password.error=\u0421\u044b\u0440\u0441\u04e9\u0437\u0434\u04af \u043a\u0430\u0439\u0440\u0430 \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.connecting.please.wait=\u0422\u0443\u0442\u0430\u0448\u0443\u0443. \u041a\u04af\u0442\u04e9 \u0442\u0443\u0440\u0443\u04a3\u0443\u0437... -message.connection.failed={0} \u043c\u0435\u043d\u0435\u043d \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0448 \u0436\u043e\u043a. -message.create.account=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b \u0442\u04af\u0437\u04af\u043b\u0433\u04e9\u043d \u0436\u043e\u043a. -message.create.or.join.room=\u0411\u04e9\u043b\u043c\u04e9\u043d\u04af \u0442\u04af\u0437\u04af\u04af \u0436\u0435 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446 \u0447\u0430\u0442 \u0431\u04e9\u043b\u043c\u04e9\u0441\u04af\u043d\u04e9 \u043a\u043e\u0448\u0443\u043b\u0443\u0443 -message.current.status= \u0421\u0442\u0430\u0442\u0443\u0441\u0442\u0443 \u0431\u0430\u0448\u043a\u0430\u043b\u0430\u0440\u0433\u0430 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af. -message.default.error=\u041a\u0430\u0442\u0430 \u0442\u0430\u0431\u044b\u043b\u0434\u044b. \u0421\u0443\u0440\u0430\u043d\u044b\u0447, \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u043b\u0433\u04e9\u043d \u0430\u0434\u0440\u0435\u0441\u043a\u0435 support@jivesoftware.com \u0431\u0438\u043b\u0434\u0438\u0440\u0438\u04a3\u0438\u0437. -message.delete.all.history=\u0411\u0430\u0440\u0434\u044b\u043a \u0441\u04af\u0439\u043b\u04e9\u0448\u04af\u04af \u0442\u0430\u0440\u044b\u0445\u0442\u0430\u0440\u044b \u04e9\u0447\u04af\u0440\u04af\u043b\u0441\u04af\u043d\u0431\u04af? -message.delete.confirmation={0} \u04e9\u0447\u04af\u0440\u04af\u043b\u0441\u04af\u043d\u0431\u04af? -message.disable.transport={0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u044b \u04e9\u0447\u04af\u0440\u04af\u043b\u0441\u04af\u043d\u0431\u04af? -message.disconnected.conflict.error=\u0411\u0430\u0448\u043a\u0430 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0434\u0435\u043d \u0441\u0438\u0437\u0434\u0438\u043d \u0430\u0442\u044b\u04a3\u044b\u0437 \u043c\u0435\u043d\u0435\u043d \u043a\u0438\u0440\u0433\u0435\u043d\u0434\u0438\u0433\u0438\u043d\u0435\u043d \u0441\u0438\u0437\u0434\u0438\u043d \u0442\u0443\u0442\u0430\u0448\u0443\u0443\u04a3\u0443\u0437 \u0436\u0430\u0431\u044b\u043b\u0434\u044b. -message.disconnected.error= \u0422\u0443\u0442\u0430\u0448\u0443\u0443 \u0438\u0439\u0433\u0438\u043b\u0438\u043a\u0441\u0438\u0437 \u0430\u044f\u043a\u0442\u0430\u0434\u044b. -message.disconnected.group.chat.error= \u0422\u0443\u0442\u0430\u0448\u0443\u0443 \u0438\u0439\u0433\u0438\u043b\u0438\u043a\u0441\u0438\u0437 \u0430\u044f\u043a\u0442\u0430\u0434\u044b. \u041a\u0430\u0439\u0440\u0430 \u0442\u0443\u0442\u0430\u0448\u0443\u0443\u0434\u0430\u043d \u043a\u0438\u0439\u0438\u043d \u0431\u04e9\u043b\u043c\u04e9\u0433\u04e9 \u043a\u0430\u0439\u0440\u0430 \u043a\u0438\u0440\u0438\u0448\u0438\u04a3\u0438\u0437 \u043a\u0435\u0440\u0435\u043a. -message.disconnected.shutdown=\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0438\u043d \u04e9\u0447\u04af\u04af\u0441\u04af\u043d\u04e9 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0448\u0442\u0443\u0443 \u0441\u0438\u0437\u0434\u0438\u043d \u0442\u0443\u0442\u0430\u0448\u0443\u0443\u04a3\u0443\u0437 \u0436\u0430\u0431\u044b\u043b\u0434\u044b. -message.downloading={0} \u0436\u04af\u043a\u0442\u04e9\u04e9\u043b\u04af\u043f \u0436\u0430\u0442\u0430\u0442 -message.downloading.spark.plug=Spark-Plug \u0436\u04af\u043a\u0442\u04e9\u043b\u04af\u043f \u0436\u0430\u0442\u0430\u0442 -message.end.chat= \u0427\u0430\u0442\u0442\u044b \u0430\u044f\u043a\u0442\u043e\u043e? -message.end.conversation= \u0421\u04af\u0439\u043b\u04e9\u0448\u04af\u04af\u043d\u04af \u0430\u044f\u043a\u0442\u043e\u043e? -message.enter.aim=AIM \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u0436\u0430\u043d\u0430 \u0441\u044b\u0440\u0441\u04e9\u0437\u04af\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437\u0438\u043c\u044f \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. -message.enter.broadcast.message= \u0422\u0430\u043d\u0434\u0430\u043b\u0433\u0430\u043d \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440 \u04af\u0447\u04af\u043d \u043a\u04e9\u043f\u0442\u04af\u043a \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430\u043d\u044b \u043a\u0438\u0440\u0433\u0438\u0437\u0438\u04a3\u0438\u0437. -message.enter.facebook=Facebook \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u0436\u0430\u043d\u0430 \u0441\u044b\u0440\u0441\u04e9\u0437\u04af\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.enter.gadugadu=GaduGadu \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u0436\u0430\u043d\u0430 \u0441\u044b\u0440\u0441\u04e9\u0437\u04af\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.enter.gtalk=GTalk \u043a\u043e\u043e\u043b\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u0436\u0430\u043d\u0430 \u0441\u044b\u0440\u0441\u04e9\u0437\u04af\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437 \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. -message.enter.icq=ICQ \u043d\u043e\u043c\u0435\u0440\u0438\u043d \u0436\u0430\u043d\u0430 \u0441\u044b\u0440\u0441\u04e9\u0437\u04af\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.enter.irc=IRC \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d, \u0441\u044b\u0440\u0441\u04e9\u0437\u04af\u043d \u0436\u0430\u043d\u0430 \u0442\u0430\u043a\u043c\u0430 \u044b\u0441\u044b\u043c\u044b\u04a3\u044b\u0437\u044b \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.enter.jabber.id=Jabber ID'\u043d\u0438 \u043a\u0438\u0440\u0438\u04a3\u0438\u0437 -message.enter.message.to.broadcast= \u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0438\u0437\u043c\u0435\u0441\u0438\u043d\u0434\u0435 \u0431\u0430\u0440\u0434\u044b\u043a \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440\u0433\u0430 \u0436\u04e9\u043d\u04e9\u0442\u04af\u043b\u04af\u04af\u0447\u04af \u043a\u04e9\u043f\u0442\u04af\u043a \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430\u043d\u044b \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.enter.msn=MSN \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u0436\u0430\u043d\u0430 \u0441\u044b\u0440\u0441\u04e9\u0437\u04af\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.enter.myspace=MySpace \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u0436\u0430\u043d\u0430 \u0441\u044b\u0440\u0441\u04e9\u0437\u04af\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.enter.new.subject= \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043c\u0443 -message.enter.qq=QQ \u043d\u043e\u043c\u0435\u0440\u0438\u043d \u0436\u0430\u043d\u0430 \u0441\u044b\u0440\u0441\u04e9\u0437\u04af\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.enter.room.password= \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u043a\u043e\u043c\u043d\u0430\u0442\u044b -message.enter.sametime=Sametime \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u0436\u0430\u043d\u0430 \u0441\u044b\u0440\u0441\u04e9\u0437\u04af\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.enter.simple=SIMPLE \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u0436\u0430\u043d\u0430 \u0441\u044b\u0440\u0441\u04e9\u0437\u04af\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.enter.valid.jid=\u0422\u0443\u0443\u0440\u0430 Jabber ID \u043a\u0438\u0440\u0438\u04a3\u0438\u0437 -message.enter.xmpp=XMPP \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u0436\u0430\u043d\u0430 \u0441\u044b\u0440\u0441\u04e9\u0437\u04af\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.enter.yahoo=Yahoo \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u0436\u0430\u043d\u0430 \u0441\u044b\u0440\u0441\u04e9\u0437\u04af\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.error.during.file.transfer= \u0424\u0430\u0439\u043b\u0434\u044b \u0436\u04e9\u043d\u04e9\u0442\u04af\u04af\u0434\u04e9 \u043a\u0430\u0442\u0430 \u0447\u044b\u043a\u0442\u044b. -message.file.exists.question= \u041c\u044b\u043d\u0434\u0430\u0439 \u0444\u0430\u0439\u043b \u0431\u0430\u0440. \u04ae\u0441\u0442\u04af\u043d\u04e9\u043d \u0436\u0430\u0437\u044b\u043b\u0441\u044b\u043d\u0431\u044b? -message.file.size=\u0424\u0430\u0439\u043b\u0434\u044b\u043d \u04e9\u043b\u0447\u04e9\u043c\u04af: {0} -message.file.transfer.canceled=\u0412\u044b \u043e\u0442\u043c\u0435\u043d\u0438\u043b\u0438 \u043f\u0440\u0438\u0451\u043c \u0444\u0430\u0439\u043b\u0430. -message.file.transfer.chat.window=\u0424\u0430\u0439\u043b \u0436\u04e9\u043d\u04e9\u0442\u04af\u04af \u0442\u0430\u043b\u0430\u0431\u044b: -message.file.transfer.notification=\u0424\u0430\u0439\u043b\u0434\u044b \u0436\u04e9\u043d\u04e9\u0442\u04af\u04af \u044d\u0441\u043a\u0435\u0440\u0442\u04af\u04af\u0441\u04af -message.file.transfer.rejected= {0} \u0444\u0430\u0439\u043b \u0436\u0438\u0431\u0435\u0440\u04af\u04af\u043d\u04af \u0442\u0430\u0441\u0442\u044b\u043a\u0442\u0430\u0433\u0430\u043d \u0436\u043e\u043a. -message.file.transfer.short.message= \u0441\u0438\u0437\u0433\u0435 \u0444\u0430\u0439\u043b\u0434\u044b \u0436\u0438\u0431\u0435\u0440\u0438\u043f \u0436\u0430\u0442\u0430\u0442: -message.find.conference.services=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f \u043a\u044b\u0437\u043c\u0430\u0442\u0442\u0430\u0440\u044b\u043d \u0438\u0437\u0434\u04e9\u04e9 -message.forbidden.error=\u0421\u0435\u0440\u0432\u0435\u0440 \u0436\u0435\u0442\u04af\u04af \u043a\u0430\u0442\u0430\u0441\u044b\u043d \u0431\u0438\u043b\u0434\u0438\u0440\u0434\u0438. -message.gateway.nickname.error=\u0422\u0430\u043a\u043c\u0430 \u044b\u0441\u044b\u043c\u044b \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u043b\u04af\u0448\u04af \u043a\u0435\u0440\u0435\u043a. -message.gateway.password.error=\u0421\u044b\u0440\u0441\u04e9\u0437 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u043b\u04af\u0448\u04af \u043a\u0435\u0440\u0435\u043a. -message.gateway.username.error=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u043b\u04af\u0448\u04af \u043a\u0435\u0440\u0435\u043a. -message.general.error={0} \u0441\u0435\u0431\u0435\u0431\u0438\u043d\u0435\u043d \u0441\u0435\u0440\u0432\u0435\u0440 \u043c\u0435\u043d\u0435\u043d \u0442\u0443\u0442\u0430\u0448\u0443\u0443 \u0436\u043e\u0433\u043e\u043b\u0443\u043f \u043a\u0435\u0442\u0442\u0438. -message.generic.reconnect.message=\u0421\u0435\u0440\u0432\u0435\u0440 \u043c\u0435\u043d\u0435\u043d \u0442\u0443\u0442\u0430\u0448\u0443\u0443 \u0436\u043e\u0433\u043e\u043b\u0443\u043f \u043a\u0435\u0442\u0442\u0438. \u041a\u0430\u0439\u0440\u0430 \u0442\u0443\u0442\u0430\u0448\u0443\u0443 \u04af\u0447\u04af\u043d \u00ab\u041a\u0430\u0439\u0440\u0430\u0434\u0430\u043d \u0442\u0443\u0442\u0430\u0448\u0443\u0443\u00bb \u0431\u0430\u0441\u043a\u044b\u0447\u044b\u043d \u0431\u0430\u0441\u044b\u04a3\u044b\u0437. -message.groupchat.require.password=\u0411\u0443\u043b \u0447\u0430\u0442 \u0433\u0440\u0443\u043f\u043f\u0430\u0441\u044b \u043a\u0438\u0440\u04af\u04af\u0433\u04e9 \u0441\u044b\u0440\u0441\u04e9\u0437\u0434\u04af \u0442\u0430\u043b\u0430\u043f \u043a\u044b\u043b\u0430\u0442. -message.idle.for={0} \u0430\u043a\u0442\u0438\u0432\u0434\u04af\u04af \u044d\u043c\u0435\u0441 -message.image.too.large=\u0421\u04af\u0440\u04e9\u0442 \u04e9\u0442\u04e9 \u0447\u043e\u04a3. 16k \u0436\u0435 \u043a\u0438\u0447\u0438\u043d\u0435\u043a\u0435\u0439 \u0441\u04af\u0440\u04e9\u0442\u0442\u04af \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04a3\u04af\u0437. -message.invalid.jabber.id=\u0422\u0443\u0443\u0440\u0430 \u044d\u043c\u0435\u0441 Jabber ID -message.invalid.jid.error= JID \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439. -message.invalid.status= \u0422\u0443\u0443\u0440\u0430 \u0441\u0442\u0430\u0442\u0443\u0441 \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430\u0441\u044b\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.invalid.username.password=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b \u0436\u0435 \u0441\u044b\u0440\u0441\u04e9\u0437 \u0442\u0443\u0443\u0440\u0430 \u044d\u043c\u0435\u0441. -message.invite.to.groupchat={0} \u0447\u0430\u0442 \u0433\u0440\u0443\u043f\u043f\u0430\u0441\u044b\u043d\u0430 \u0447\u0430\u043a\u044b\u0440\u044b\u043f \u0436\u0430\u0442\u0430\u0442. -message.invite.users.to.conference=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440\u0434\u044b \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f \u0431\u04e9\u043b\u043c\u04e9\u0441\u04af\u043d\u04e9 \u0447\u0430\u043a\u044b\u0440\u0443\u0443. -message.is.shared.group= {0} \u0431\u0443\u043b \u0431\u04e9\u043b\u04af\u0448\u0442\u04af\u0440\u04af\u043b\u0433\u04e9\u043d \u0433\u0440\u0443\u043f\u043f. -message.is.typing.a.message= {0} \u0436\u0430\u0437\u044b\u043f \u0436\u0430\u0442\u0430\u0442... -message.join.conference.room=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f \u0431\u04e9\u043b\u043c\u04e9\u0441\u04af\u043d\u04e9 \u043a\u0438\u0440\u04af\u04af -message.kicked.error= \u0421\u0438\u0437 \u0431\u04e9\u043b\u043c\u04e9\u0434\u04e9\u043d {0} \u0430\u0439\u0434\u0430\u043f \u0441\u0430\u043b\u0430\u043b\u0431\u0430\u0439\u0441\u044b\u0437. -message.last.message.received={0} \u0430\u043a\u044b\u0440\u043a\u044b \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430 \u0430\u043b\u044b\u043d\u0434\u044b -message.loading.please.wait=\u0416\u04af\u043a\u0442\u04e9\u043b\u04af\u04af. \u041a\u04af\u0442\u04e9 \u0442\u0443\u0440\u0443\u04a3\u0443\u0437... -message.locked.workstation= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0434\u0438 \u043a\u0443\u043b\u0443\u043f\u0442\u0430\u043b\u0433\u0430\u043d. -message.name.of.group=\u0413\u0440\u0443\u043f\u043f\u0430\u043d\u044b\u043d \u0430\u0442\u044b -message.name.of.search.service.question=\u0418\u0437\u0434\u04e9\u04e9 \u043a\u044b\u0437\u043c\u0430\u0442\u044b\u043d\u044b\u043d \u0430\u0442\u044b? -message.negotiate.file.transfer= \u0424\u0430\u0439\u043b\u0434\u044b \u0436\u0438\u0431\u0435\u0440\u04af\u04af \u04af\u0447\u04af\u043d \u0442\u0443\u0442\u0430\u0448\u0443\u0443 \u043e\u0440\u043d\u043e\u0442\u0443\u043b\u0443\u043f \u0436\u0430\u0442\u0430\u0442. \u041a\u04af\u0442\u04e9 \u0442\u0443\u0440\u0443\u04a3\u0443\u0437... -message.negotiate.stream= \u0422\u0443\u0442\u0430\u0448\u0443\u0443 \u043e\u0440\u043d\u043e\u0442\u0443\u043b\u0443\u043f \u0436\u0430\u0442\u0430\u0442. \u041a\u04af\u0442\u04e9 \u0442\u0443\u0440\u0443\u04a3\u0443\u0437... -message.negotiation.file.transfer={0} \u0444\u0430\u0439\u043b\u0434\u044b \u0436\u0438\u0431\u0435\u0440\u04af\u04af \u04af\u0447\u04af\u043d \u0442\u0443\u0442\u0430\u0448\u0443\u0443 \u043e\u0440\u043d\u043e\u0442\u0443\u043b\u0443\u043f \u0436\u0430\u0442\u0430\u0442. \u041a\u04af\u0442\u04e9 \u0442\u0443\u0440\u0443\u04a3\u0443\u0437... -message.new.message={0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u0434\u0430\u043d \u0436\u0430\u04a3\u044b \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430. -message.new.spark.available= {0} \u0431\u0430\u0440. \u041e\u0440\u043d\u043e\u0442\u0443\u0443? -message.nickname.in.use= \u0422\u0430\u043a\u043c\u0430 \u044b\u0441\u044b\u043c\u044b \u0431\u043e\u0448 \u044d\u043c\u0435\u0441. \u0411\u0430\u0448\u043a\u0430\u0441\u044b\u043d \u0442\u0430\u043d\u0434\u0430\u04a3\u044b\u0437 -message.no.avatar.found= \u0410\u0432\u0430\u0442\u0430\u0440 \u0442\u0430\u0431\u044b\u043b\u0433\u0430\u043d \u0436\u043e\u043a. -message.no.caller.id= Caller ID \u0442\u0430\u0431\u044b\u043b\u0433\u0430\u043d \u0436\u043e\u043a. -message.no.description.available=\u041a\u044b\u0441\u043a\u0430\u0447\u0430 \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442 \u0442\u0430\u0431\u044b\u043b\u0433\u0430\u043d \u0436\u043e\u043a -message.no.history.found=\u0411\u0443\u043b \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u04af\u0447\u04af\u043d \u0441\u04af\u0439\u043b\u04e9\u0448\u04af\u04af \u0442\u0430\u0440\u044b\u0445\u0447\u0430\u0441\u044b \u0436\u043e\u043a. -message.no.results.found=\u042d\u0447 \u043d\u0435\u0440\u0441\u0435 \u0442\u0430\u0431\u044b\u043b\u0433\u0430\u043d \u0436\u043e\u043a. -message.no.room.to.join.error=\u041a\u0438\u0440\u04af\u04af\u0433\u04e9 \u044d\u0447 \u043a\u0430\u043d\u0434\u0430\u0439 \u0431\u04e9\u043b\u043c\u04e9 \u0436\u043e\u043a -message.no.subject.available=\u042d\u0447 \u043a\u0430\u043d\u0434\u0430\u0439 \u0442\u0435\u043c\u0430 \u0436\u043e\u043a -message.no.updates=\u042d\u0447 \u043a\u0430\u043d\u0434\u0430\u0439 \u0436\u0430\u04a3\u044b\u043b\u043e\u043e\u043b\u043e\u0440 \u0436\u043e\u043a -message.normal=\u0416\u04e9\u043d\u04e9\u043a\u04e9\u0439 \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430 -message.number.to.call=\u0422\u0435\u0440\u04af\u04af \u04af\u0447\u04af\u043d \u043d\u043e\u043c\u0435\u0440\u0434\u0438 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04a3\u04af\u0437 -message.offline= \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u0441\u044f. -message.offline.error=\u042d\u0433\u0435\u0440\u0434\u0435 \u0431\u0443\u043b \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0442\u0430\u0440\u043c\u0430\u043a\u0442\u0430 \u044d\u043c\u0435\u0441 \u0431\u043e\u043b\u0433\u043e\u043d\u0434\u043e, \u0430\u043d\u0434\u0430 \u0430\u043b \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430\u043b\u0430\u0440\u0434\u044b \u043a\u0430\u0431\u044b\u043b \u0430\u043b\u0431\u0430\u0439\u0442. -message.participants.in.room=\u0411\u04e9\u043b\u043c\u04e9\u0434\u04e9 \u043a\u0430\u0442\u044b\u0448\u0443\u0443\u0447\u0443\u043b\u0430\u0440 -message.password.error=\u0421\u044b\u0440\u0441\u04e9\u0437\u0434\u04af \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.password.private.room.error=\u0416\u0435\u043a\u0435 \u0431\u04e9\u043b\u043c\u04e9 \u04af\u0447\u04af\u043d \u0441\u044b\u0440\u0441\u04e9\u0437\u0434\u04af \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04a3\u04af\u0437 -message.passwords.no.match= \u0421\u044b\u0440\u0441\u04e9\u0437\u0434\u04e9\u0440 \u0442\u0443\u0443\u0440\u0430 \u043a\u0435\u043b\u0433\u0435\u043d \u0436\u043e\u043a. -message.please.join.in.conference= \u0421\u0443\u0440\u0430\u043d\u044b\u0447, \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f\u0433\u0430 \u043a\u043e\u0448\u0443\u043b\u0443\u04a3\u0443\u0437. -message.plugins.not.available= \u041f\u043b\u0430\u0433\u0438\u043d \u0431\u0443\u043b\u0430\u0433\u044b\u043d\u0430 \u0442\u0443\u0442\u0430\u0448\u044b\u043b\u0433\u0430\u043d \u0436\u043e\u043a. -message.prompt.plugin.uninstall= {0} \u0430\u043b\u044b\u043f \u0441\u0430\u043b\u044b\u043d\u0441\u044b\u043d\u0431\u044b? -message.received.file={0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u0434\u0430\u043d \u0444\u0430\u0439\u043b\u0434\u044b \u0430\u043b\u0434\u044b\u043d\u044b\u0437. -message.receiving.file={0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u0434\u0430\u043d \u0444\u0430\u0439\u043b\u0434\u044b \u0430\u043b\u044b\u043f \u0436\u0430\u0442\u0430\u0441\u044b\u0437 -message.reconnect.attempting=\u0410\u0440\u0430\u043a\u0435\u0442\u0442\u0435\u043d\u04af\u04af... -message.reconnect.failed=\u041a\u0430\u0439\u0440\u0430\u0434\u0430\u043d \u0442\u0443\u0442\u0430\u0448\u0443\u0443 \u0438\u0439\u0433\u0438\u043b\u0438\u043a\u0441\u0438\u0437 \u0430\u044f\u043a\u0442\u0430\u0434\u044b. -message.reconnect.wait={0} \u0441\u0435\u043a\u0443\u043d\u0434 \u0438\u0447\u0438\u043d\u0434\u0435 \u043a\u0430\u0439\u0440\u0430\u0434\u0430\u043d \u0442\u0443\u0442\u0430\u0448\u0443\u0443. -message.register.transports=\u0411\u0430\u0440 \u0431\u043e\u043b\u0433\u043e\u043d \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u0442\u043e\u0440\u0434\u0443 \u043a\u0430\u0442\u0442\u043e\u043e. -message.registering={0} \u043a\u0430\u0442\u0442\u0430\u043b\u044b\u043f \u0436\u0430\u0442\u0430\u0442. \u041a\u04af\u0442\u04e9 \u0442\u0443\u0440\u0443\u04a3\u0443\u0437... -message.registration.transport.failed=\u041a\u0430\u0442\u0442\u0430\u043b\u0443\u0443 \u043c\u04af\u043c\u043a\u04af\u043d \u044d\u043c\u0435\u0441. -message.restart.required=\u04e8\u0437\u0433\u04e9\u0440\u0442\u04af\u04af\u043b\u04e9\u0440 \u0438\u0448\u043a\u0435 \u043a\u0438\u0440\u04af\u04af\u0441\u04af \u04af\u0447\u04af\u043d Spark \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430\u0441\u044b\u043d \u043a\u0430\u0439\u0440\u0430\u0434\u0430\u043d \u0431\u0430\u0448\u0442\u043e\u043e \u043a\u0435\u0440\u0435\u043a \u041a\u0430\u0439\u0440\u0430\u0434\u0430\u043d \u0431\u0430\u0448\u0442\u0430\u043b\u0441\u044b\u043d\u0431\u044b? -message.restart.spark= \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043a\u0440\u044b\u0442\u044c Spark \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438.\u000a \u0417\u0430\u043a\u0440\u044b\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441? -message.restart.spark.changes= \u041f\u043b\u0430\u0433\u0438\u043d Spark \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430\u0441\u044b \u043a\u0438\u0439\u0438\u043d\u043a\u0438 \u0436\u043e\u043b\u0443 \u043a\u0430\u0439\u0440\u0430\u0434\u0430\u043d \u0431\u0430\u0448\u0442\u0430\u043b\u0433\u0430\u043d\u0434\u0430 \u0430\u043b\u044b\u043d\u044b\u043f \u0441\u0430\u043b\u044b\u043d\u0430\u0442. -message.restart.spark.to.install= \u0416\u0430\u04a3\u044b \u0432\u0435\u0440\u0441\u0438\u044f\u043d\u044b \u043e\u0440\u043d\u043e\u0442\u0443\u0443 \u04af\u0447\u04af\u043d Spark \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430\u0441\u044b\u043d \u0436\u0430\u0431\u0443\u0443 \u043a\u0435\u0440\u0435\u043a. \u0410\u0437\u044b\u0440 \u0436\u0430\u0431\u044b\u043b\u0441\u044b\u043d\u0431\u044b? -message.room.creation.error=\u0411\u04e9\u043b\u043c\u04e9 \u0442\u04af\u0437\u04af\u043b\u0433\u04e9\u043d \u0436\u043e\u043a. -message.room.destroyed=\u0411\u04e9\u043b\u043c\u04e9 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u043b\u0433\u04e9\u043d \u0441\u0435\u0431\u0435\u0431\u0438 \u043c\u0435\u043d\u0435\u043d \u0431\u0443\u0437\u0443\u043b\u0434\u0443: {0} -message.room.destruction.reason= \u0411\u04e9\u043b\u043c\u04e9\u043d\u04af\u043d \u0431\u0443\u0437\u0443\u043b\u0443\u0448 \u0441\u0435\u0431\u0435\u0431\u0438? -message.room.information.for={0} \u0431\u04e9\u043b\u043c\u04e9 \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u044b -message.save.profile= \u041f\u0440\u043e\u0444\u0438\u043b\u0434\u0438\u043d \u04e9\u0437\u0433\u04e9\u0440\u04af\u04af\u043b\u04e9\u0440\u04af\u043d \u0441\u0430\u043a\u0442\u043e\u043e \u04af\u0447\u04af\u043d \u00ab\u0421\u0430\u043a\u0442\u043e\u043e\u00bb \u0431\u0430\u0441\u043a\u044b\u0447\u044b\u043d \u0431\u0430\u0441\u044b\u04a3\u044b\u0437. -message.search.for.contacts=\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0442\u0430\u0440\u0434\u044b \u0442\u0430\u0431\u0443\u0443. -message.search.for.other.people=\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0435 \u0430\u0434\u0430\u043c\u0434\u0430\u0440\u0434\u044b \u0438\u0437\u0434\u04e9\u04e9. -message.search.service.not.available=\u0418\u0437\u0434\u04e9\u04e9 \u043a\u044b\u0437\u043c\u0430\u0442\u044b \u043c\u0435\u043d\u0435\u043d \u0442\u0443\u0442\u0430\u0448\u0443\u0443 \u0436\u043e\u043a. -message.searching.please.wait=\u0418\u0437\u0434\u0435\u043b\u0438\u043f \u0436\u0430\u0442\u0430\u0442. \u041a\u04af\u0442\u04e9 \u0442\u0443\u0440\u0443\u04a3\u0443\u0437... -message.select.add.room.to.add=\u0411\u04e9\u043b\u043c\u04e9\u043d\u04af \u0441\u0438\u0437\u0434\u0438\u043d \u043a\u044b\u0437\u043c\u0430\u0442\u0442\u0430\u0440 \u0442\u0438\u0437\u043c\u0435\u0441\u0438\u043d\u0435 \u043a\u043e\u0448\u0443\u0443 \u04af\u0447\u04af\u043d \u0442\u0430\u043d\u0434\u0430\u04a3\u044b\u0437. -message.select.one.or.more=\u0411\u0438\u0440\u0434\u0438 \u0436\u0435 \u0431\u0438\u0440 \u043d\u0435\u0447\u0435 \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043d\u0443 \u0442\u0430\u043d\u0434\u0430\u04a3\u044b\u0437. -message.select.room.to.enter=\u041a\u0438\u0440\u04af\u04af \u04af\u0447\u04af\u043d \u0431\u04e9\u043b\u043c\u04e9\u043d\u04af \u0442\u0430\u043d\u0434\u0430\u04a3\u044b\u0437. -message.select.room.to.join=\u041a\u043e\u0448\u0443\u043b\u0443\u0443 \u04af\u0447\u04af\u043d \u0431\u04e9\u043b\u043c\u04e9\u043d\u04af \u0442\u0430\u043d\u0434\u0430\u04a3\u044b\u0437. -message.send.a.broadcast=\u041a\u04e9\u043f\u0442\u04af\u043a \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430\u043d\u044b \u0436\u04e9\u043d\u04e9\u0442\u04af\u04af -message.send.file.to.user=\u0424\u0430\u0439\u043b\u0434\u044b \u0431\u0443\u043b \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u0433\u0430 \u0436\u04e9\u043d\u04e9\u0442\u04af\u04af. -message.send.picture= \u042d\u043a\u0440\u0430\u043d \u0441\u04af\u0440\u04e9\u0442\u04af\u043d \u043a\u04e9\u0447\u04af\u0440\u04af\u04af \u0436\u0430\u043d\u0430 \u0436\u04e9\u043d\u04e9\u0442\u04af\u04af. -message.send.to.these.people=\u0411\u0443\u043b \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440\u0433\u0430 \u0436\u04e9\u043d\u04e9\u0442\u04af\u04af -message.sending.file.to={0} \u04af\u0447\u04af\u043d \u0444\u0430\u0439\u043b \u0436\u0438\u0431\u0435\u0440\u0438\u043b\u0438\u043f \u0436\u0430\u0442\u0430\u0442. -message.sent.offline.files= You have just been sent offline file(s). -message.server.unavailable=\u0421\u0435\u0440\u0432\u0435\u0440 \u043c\u0435\u043d\u0435\u043d \u0442\u0443\u0442\u0430\u0448\u044b\u043b\u0433\u0430\u043d \u0436\u043e\u043a: \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0438\u043d \u0430\u0442\u044b \u0442\u0443\u0443\u0440\u0430 \u044d\u043c\u0435\u0441 \u0436\u0435 \u0441\u0435\u0440\u0432\u0435\u0440 \u043c\u0435\u043d\u0435\u043d \u0442\u0443\u0442\u0430\u0448\u0443\u0443 \u043c\u04af\u043c\u043a\u04af\u043d \u044d\u043c\u0435\u0441. -message.service.already.exists=\u041a\u044b\u0437\u043c\u0430\u0442 \u0430\u043b\u0434\u0430 \u043a\u0430\u0447\u0430\u043d \u043a\u043e\u0448\u0443\u043b\u0433\u0430\u043d. -message.shared.group=\u0411\u04e9\u043b\u04af\u0448\u0442\u04af\u0440\u04af\u043b\u0433\u04e9\u043d \u0433\u0440\u0443\u043f\u043f\u0430 -message.spark.secure= Spark \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430\u0441\u044b \u0448\u0438\u0444\u0440\u043b\u0435\u043d\u0433\u0435\u043d \u0442\u0443\u0442\u0430\u0448\u0443\u0443 \u0440\u0435\u0436\u0438\u043c\u0434\u0435 \u0438\u0448\u0442\u0435\u043f \u0436\u0430\u0442\u0430\u0442. -message.specify.contact.jid= \u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0442\u044b\u043d JID \u0431\u0435\u043b\u0433\u0438\u0441\u0438\u043d \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04a3\u04af\u0437 (\u043c\u0438\u0441\u0430\u043b\u044b: ilyas@jabber.org) -message.specify.group=\u0416\u0430\u04a3\u044b \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043d\u0443 \u043a\u043e\u0448\u0443\u0443 \u04af\u0447\u04af\u043d \u0433\u0440\u0443\u043f\u043f\u0430\u043d\u044b \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04a3\u04af\u0437. -message.specify.information.for.conference=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f \u0431\u04e9\u043b\u043c\u04e9\u043d\u04af\u043d \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u044b\u043d \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04a3\u04af\u0437. -message.specify.name.error=\u0422\u0443\u0443\u0440\u0430 \u0430\u0442\u0442\u044b \u043a\u0438\u0440\u0433\u0438\u0437\u0438\u04a3\u0438\u0437. -message.specify.users.to.join.conference=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f\u0433\u0430 \u043a\u043e\u0448\u0443\u043b\u0443\u0443\u0447\u0443 \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440\u0434\u044b \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04a3\u04af\u0437. -message.specify.valid.time.error= \u0422\u0443\u0443\u0440\u0430 \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u0443\u0431\u0430\u043a\u044b\u0442\u044b\u043d \u0436\u0430\u043d\u0430 \u043f\u043e\u0440\u0442\u0442\u0443 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04a3\u04af\u0437. -message.subject.change.error=\u0411\u0443\u043b \u0431\u04e9\u043b\u043c\u04e9\u0434\u04e9 \u0442\u0435\u043c\u0430\u043d\u044b \u04e9\u0437\u0433\u04e9\u0440\u0442\u04e9 \u0430\u043b\u0431\u0430\u0439\u0441\u044b\u0437. -message.subject.has.been.changed.to=\u0422\u0435\u043c\u0430 \u04e9\u0437\u0433\u04e9\u0440\u0434\u04af: {0}. -message.supply.resource=\u0422\u0443\u0443\u0440\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u0442\u0443 \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.supply.valid.port=\u0422\u0443\u0443\u0440\u0430 \u043f\u043e\u0440\u0442\u0442\u0443 \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.supply.valid.timeout=\u0422\u0443\u0443\u0440\u0430 \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u0443\u0431\u0430\u043a\u044b\u0442\u044b\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -message.timeout.error= \u0422\u0430\u0439\u043c\u0430\u0443\u0442 \u0443\u0431\u0430\u043a\u044b\u0442\u044b 5 \u0441\u0435\u043a. \u0436\u0435 \u0430\u043d\u0434\u0430\u043d \u043a\u04e9\u043f \u0431\u043e\u043b\u0443\u0448\u0443 \u043a\u0435\u0440\u0435\u043a. -message.total.downloaded=\u0416\u0430\u043b\u043f\u044b \u0436\u04af\u043a\u0442\u04e9\u04e9\u043b\u04e9\u0440 -message.transfer.cancelled=\u041f\u0440\u0438\u0451\u043c \u0444\u0430\u0439\u043b\u0430 \u043e\u0442\u043c\u0435\u043d\u0451\u043d. -message.transfer.rate=\u042b\u043b\u0434\u0430\u043c\u0434\u044b\u0433\u044b -message.transfer.refused=\u0424\u0430\u0439\u043b\u0434\u044b \u043a\u0430\u0431\u044b\u043b \u0430\u043b\u0443\u0443 \u0447\u0435\u0442\u043a\u0435 \u043a\u0430\u0433\u044b\u043b\u0434\u044b. -message.transfer.waiting.on.user={0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043d\u0443\u043d \u0444\u0430\u0439\u043b\u0434\u044b \u043a\u0430\u0431\u044b\u043b \u0430\u043b\u0443\u0443\u0441\u0443 \u043a\u04af\u0442\u04af\u043b\u04af\u043f \u0436\u0430\u0442\u0430\u0442. -message.unable.to.load.profile={0} \u04af\u0447\u04af\u043d \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0442\u0430\u0431\u044b\u043b\u0433\u0430\u043d \u0436\u043e\u043a -message.unable.to.retrieve.last.activity={0} \u04af\u0447\u04af\u043d \u0430\u043a\u044b\u0440\u043a\u044b \u0430\u043a\u0442\u0438\u0432\u0434\u04af\u04af\u043b\u04af\u043a \u0443\u0431\u0430\u043a\u044b\u0442\u044b \u0430\u043d\u044b\u043a\u0442\u0430\u043b\u0433\u0430\u043d \u0436\u043e\u043a. -message.unable.to.save.password= \u0421\u044b\u0440\u0441\u04e9\u0437\u0434\u04af \u04e9\u0437\u0433\u04e9\u0440\u0442\u04af\u04af \u043c\u04af\u043c\u043a\u04af\u043d \u044d\u043c\u0435\u0441. \u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0438\u043d \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0443\u043d\u0430 \u043a\u0430\u0439\u0440\u044b\u043b\u044b\u04a3\u044b\u0437. -message.unable.to.send.file={0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u0433\u0430 \u0444\u0430\u0439\u043b \u0436\u04e9\u043d\u04e9\u0442\u04e9 \u0430\u043b\u0431\u0430\u0439\u0441\u044b\u0437. -message.unrecoverable.error=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b \u0436\u0435 \u0441\u044b\u0440\u0441\u04e9\u0437\u0443 \u0442\u0443\u0443\u0440\u0430 \u044d\u043c\u0435\u0441. -message.update.room.list=\u0411\u04e9\u043b\u043c\u04e9\u043b\u04e9\u0440 \u0442\u0438\u0437\u043c\u0435\u0441\u0438\u043d \u0436\u0430\u04a3\u044b\u043b\u043e\u043e -message.updating.cancelled= \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u043e. -message.user.banned= {0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0431\u0443\u043b \u0431\u04e9\u043b\u043c\u04e9\u0434\u04e9 \u0447\u0435\u043a\u0442\u0435\u043b\u0433\u0435\u043d. -message.user.given.voice= {0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0431\u0443\u043b \u0431\u04e9\u043b\u043c\u04e9\u0434\u04e9 \u0441\u04af\u0439\u043b\u04e9\u0448\u04af\u04af \u0443\u043a\u0443\u0433\u0443\u043d\u0430 \u044d\u044d \u0431\u043e\u043b\u0434\u0443. -message.user.granted.admin= {0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u0443\u043a\u0443\u043a\u0442\u0430\u0440\u044b\u043d\u0430 \u044d\u044d \u0431\u043e\u043b\u0434\u0443. -message.user.granted.membership= {0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u043a\u043e\u0448\u0443\u043c\u0447\u0430 \u0443\u043a\u0443\u043a\u0442\u0430\u0440\u0433\u0430 \u044d\u044d \u0431\u043e\u043b\u0434\u0443. -message.user.granted.moderator= {0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u043c\u043e\u0434\u0435\u0440\u0430\u0442\u043e\u0440 \u0443\u043a\u0443\u043a\u0442\u0430\u0440\u044b\u043d\u0430 \u044d\u044d \u0431\u043e\u043b\u0434\u0443. -message.user.granted.owner= {0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0431\u04e9\u043b\u043c\u04e9 \u0442\u04af\u0437\u04af\u04af \u0443\u043a\u0443\u0433\u0443\u043d\u0430 \u044d\u044d \u0431\u043e\u043b\u0434\u0443. -message.user.is.sending.you.a.file= {0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0441\u0438\u0437\u0433\u0435 \u0444\u0430\u0439\u043b \u0436\u04e9\u043d\u04e9\u0442\u04af\u043f \u0436\u0430\u0442\u0430\u0442. -message.user.joined.room= {0} \u0431\u04e9\u043b\u043c\u04e9\u0433\u04e9 \u043a\u043e\u0448\u0443\u043b\u0434\u0443. -message.user.kicked.from.room= {0} \u0431\u04e9\u043b\u043c\u04e9\u0434\u04e9\u043d \u0430\u0439\u0434\u0430\u043b\u044b\u043f \u0447\u044b\u043a\u0442\u044b. -message.user.left.room= {0} \u0431\u04e9\u043b\u043c\u04e9\u0434\u04e9\u043d \u0447\u044b\u043a\u0442\u044b. -message.user.nickname.changed= {0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0442\u0430\u043a\u043c\u0430 \u044b\u0441\u044b\u043c\u044b\u043d {1} \u0434\u0435\u043f \u04e9\u0437\u0433\u04e9\u0440\u0442\u0442\u04af. -message.user.now.available.to.chat= {0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 {1} \u0431\u0435\u0440\u0438 \u0442\u0430\u0440\u043c\u0430\u043a\u0442\u0430 -message.user.revoked.admin={0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043d\u0443\u043d \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u0443\u043a\u0443\u043a\u0442\u0430\u0440\u044b \u0430\u043b\u044b\u043d\u0434\u044b. -message.user.revoked.membership={0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043d\u0443\u043d \u043a\u043e\u0448\u0443\u043c\u0447\u0430 \u0443\u043a\u0443\u043a\u0442\u0430\u0440\u044b \u0430\u043b\u044b\u043d\u0434\u044b. -message.user.revoked.moderator={0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043d\u0443\u043d \u043c\u043e\u0434\u0435\u0440\u0430\u0442\u043e\u0440 \u0443\u043a\u0443\u043a\u0442\u0430\u0440\u044b \u0430\u043b\u044b\u043d\u0434\u044b. -message.user.revoked.owner={0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043d\u0443\u043d \u0431\u04e9\u043b\u043c\u04e9 \u0442\u04af\u0437\u04af\u04af \u0443\u043a\u0443\u043a\u0442\u0430\u0440\u044b \u0430\u043b\u044b\u043d\u0434\u044b. -message.user.voice.revoked={0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043d\u0443\u043d \u0441\u04af\u0439\u043b\u04e9\u04e9 \u0443\u043a\u0443\u0433\u0443 \u0430\u043b\u044b\u043d\u0434\u044b. -message.username.error=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u043a\u0438\u0440\u0433\u0438\u0437\u0438\u04a3\u0438\u0437. -message.username.password.error=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b \u0436\u0430\u043d\u0430/\u0436\u0435 \u0441\u044b\u0440\u0441\u04e9\u0437 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u043b\u04af\u0448\u04af \u043a\u0435\u0440\u0435\u043a. -message.vcard.not.supported= \u0421\u0435\u0440\u0432\u0435\u0440 VCards \u043a\u043e\u043b\u0434\u043e\u0431\u043e\u0439\u0442. \u0421\u0438\u0437\u0434\u0438\u043d VCard \u0441\u0430\u043a\u0442\u0430\u043b\u0433\u0430\u043d \u0436\u043e\u043a. -message.version= \u0412\u0435\u0440\u0441\u0438\u044f\u0441\u044b: {0} -message.view.information.about.this.user=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0436\u04e9\u043d\u04af\u043d\u0434\u04e9 \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u044b \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af. -message.waiting.for.user.to.join={0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u043a\u043e\u0448\u0443\u043b\u0443\u0443\u0433\u0430 \u043a\u04af\u0442\u04af\u043b\u04af\u043f \u0436\u0430\u0442\u0430\u0442. -message.went.offline= {0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 {1} \u0431\u0435\u0440\u0438 \u0442\u0430\u0440\u043c\u0430\u0442\u0430 \u044d\u043c\u0435\u0441 -message.you.have.been.banned=\u0421\u0438\u0437 \u0431\u0443\u043b \u0431\u04e9\u043b\u043c\u04e9\u0434\u04e9\u043d \u0447\u0435\u043a\u0442\u0435\u043b\u0434\u0438\u04a3\u0438\u0437. -message.you.have.been.kicked=\u0421\u0438\u0437\u0434\u0438 \u0431\u0443\u043b \u0431\u04e9\u043b\u043c\u04e9\u0434\u04e9\u043d \u0430\u0439\u0434\u0430\u043f \u0441\u0430\u043b\u044b\u0448\u0442\u044b. -message.you.have.sent=\u0421\u0438\u0437 {0} \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u0433\u0430 \u0444\u0430\u0439\u043b \u0436\u04e9\u043d\u04e9\u0442\u0442\u04af\u04a3\u04af\u0437. -message.your.admin.granted= \u0421\u0438\u0437\u0433\u0435 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u0443\u043a\u0443\u043a\u0442\u0430\u0440\u044b \u0431\u0435\u0440\u0438\u043b\u0434\u0438. -message.your.banned= \u0421\u0438\u0437 \u0431\u0443\u043b \u0431\u04e9\u043b\u043c\u04e9\u0434\u04e9\u043d \u0447\u0435\u043a\u0442\u0435\u043b\u0434\u0438\u04a3\u0438\u0437. -message.your.kicked={0} \u0441\u0438\u0437\u0434\u0438 \u0430\u0439\u0434\u0430\u043f \u0441\u0430\u043b\u0434\u044b. -message.your.membership.granted=\u0421\u0438\u0437\u0433\u0435 \u043a\u043e\u0448\u0443\u043c\u0447\u0430 \u0443\u043a\u0443\u043a\u0442\u0430\u0440 \u0431\u0435\u0440\u0438\u043b\u0434\u0438. -message.your.membership.revoked= \u0421\u0438\u0437\u0434\u0435\u043d \u043a\u043e\u0448\u0443\u043c\u0447\u0430 \u0443\u043a\u0443\u043a\u0442\u0430\u0440 \u0430\u043b\u044b\u043d\u0434\u044b. -message.your.moderator.granted= \u0421\u0438\u0437\u0433\u0435 \u043c\u043e\u0434\u0435\u0440\u0430\u0442\u043e\u0440 \u0443\u043a\u0443\u043a\u0442\u0430\u0440\u044b \u0431\u0435\u0440\u0438\u043b\u0434\u0438. -message.your.moderator.revoked= \u0421\u0438\u0437\u0434\u0435\u043d \u043c\u043e\u0434\u0435\u0440\u0430\u0442\u043e\u0440 \u0443\u043a\u0443\u043a\u0442\u0430\u0440\u044b \u0430\u043b\u044b\u043d\u0434\u044b. -message.your.ownership.granted= \u0421\u0438\u0437\u0433\u0435 \u0431\u04e9\u043b\u043c\u04e9 \u0442\u04af\u0437\u04af\u04af \u0443\u043a\u0443\u043a\u0442\u0430\u0440\u044b \u0431\u0435\u0440\u0438\u043b\u0434\u0438. -message.your.ownership.revoked= \u0421\u0438\u0437\u0434\u0435\u043d \u0431\u04e9\u043b\u043c\u04e9 \u0442\u04af\u0437\u04af\u04af \u0443\u043a\u0443\u043a\u0442\u0430\u0440\u044b \u0430\u043b\u044b\u043d\u0434\u044b. -message.your.revoked.granted= \u0421\u0438\u0437\u0434\u0435\u043d \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u0443\u043a\u0443\u043a\u0442\u0430\u0440\u044b \u0430\u043b\u044b\u043d\u0434\u044b. -message.your.voice.granted= \u0421\u0438\u0437\u0433\u0435 \u0441\u04af\u0439\u043b\u04e9\u04e9 \u0443\u043a\u0443\u0433\u0443 \u0431\u0435\u0440\u0438\u043b\u0434\u0438. -message.your.voice.revoked= \u0421\u0438\u0437\u0434\u0435\u043d \u0441\u04af\u0439\u043b\u04e9\u04e9 \u0443\u043a\u0443\u0433\u0443 \u0430\u043b\u044b\u043d\u0434\u044b. -no= \u0416\u043e\u043a -not.registered= \u041a\u0430\u0442\u0442\u0430\u043b\u0431\u0430\u0433\u0430\u043d -occupants= \u041a\u0430\u0442\u044b\u0448\u0443\u0443\u0447\u0443\u043b\u0430\u0440 -offline=\u0422\u0430\u0440\u043c\u0430\u043a\u0442\u0430 \u044d\u043c\u0435\u0441 -## -ok= OK -online=\u0442\u0430\u0440\u043c\u0430\u043a\u0442\u0430 -open= \u0410\u0447\u0443\u0443 -open.folder= \u041f\u0430\u043f\u043a\u0430\u043d\u044b \u0430\u0447\u0443\u0443 -participants=\u041a\u0430\u0442\u044b\u0448\u0443\u0443\u0447\u0443\u043b\u0430\u0440 -reject= \u0427\u0435\u0442\u043a\u0435 \u043a\u0430\u0433\u0443\u0443 -retry= \u041a\u0430\u0439\u0442\u0430\u043b\u043e\u043e -room.name= \u0411\u04e9\u043b\u043c\u04e9\u043d\u04af\u043d \u0430\u0442\u044b -save= \u0421\u0430\u043a\u0442\u043e\u043e -status.away=\u041e\u0440\u0443\u043d\u0434\u0430 \u044d\u043c\u0435\u0441 -status.custom.messages=\u0416\u04e9\u043d\u04e9\u043a\u04e9\u0439 \u0442\u0435\u043a\u0441\u0442 -status.do.not.disturb=\u0422\u044b\u043d\u0447\u044b\u043c\u0434\u044b \u0430\u043b\u0431\u0430 -status.extended.away=\u041a\u0435\u04a3\u0435\u0439\u0442\u0438\u043b\u0433\u0435\u043d \u00ab\u041e\u0440\u0443\u043d\u0434\u0430 \u044d\u043c\u0435\u0441\u00bb -status.free.to.chat=\u0421\u04af\u0439\u043b\u04e9\u0448\u04af\u04af\u0433\u04e9 \u0434\u0430\u044f\u0440 -status.on.phone=\u0422\u0435\u043b\u0435\u0444\u043e\u043d\u0434\u043e -status.online=\u0422\u0430\u0440\u043c\u0430\u043a\u0442\u0430 -status.pending=\u041a\u04af\u0442\u04af\u043b\u04af\u04af\u0434\u04e9 -subject= \u0422\u0435\u043c\u0430 -tab.available.plugins=\u0411\u0430\u0440 \u0431\u043e\u043b\u0433\u043e\u043d \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440 -tab.avatar=\u0410\u0432\u0430\u0442\u0430\u0440 -tab.business= \u0416\u0443\u043c\u0443\u0448 -tab.conferences= \u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f\u043b\u0430\u0440 -tab.contacts= \u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0442\u0430\u0440 -tab.general=\u041d\u0435\u0433\u0438\u0437\u0433\u0438 -tab.home= \u04ae\u0439 -tab.installed.plugins=\u041e\u0440\u043d\u043e\u0442\u0443\u043b\u0433\u0430\u043d \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440 -tab.personal=\u0416\u0435\u043a\u0435 -tab.pki=PKI -tab.proxy= Proxy -tab.sso=SSO -title.about=\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0436\u04e9\u043d\u04af\u043d\u0434\u04e9 -title.account.create.registration= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u043a\u0430\u0442\u0442\u043e\u043e -title.account.created= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b \u0442\u04af\u0437\u04af\u043b\u0434\u04af -title.add.contact= \u0414\u043e\u0431\u0430\u0432\u0438\u0442 \u043a\u043e\u043d\u0442\u0430\u043a\u0442 -title.add.contact.group=\u0413\u0440\u0443\u043f\u043f\u0430\u043d\u044b \u043a\u043e\u0448\u0443\u0443 -title.add.new.group=\u0416\u0430\u04a3\u044b \u0433\u0440\u0443\u043f\u043f\u0430\u043d\u044b \u043a\u043e\u0448\u0443\u0443 -title.add.search.service=\u0418\u0437\u0434\u04e9\u04e9 \u043a\u044b\u0437\u043c\u0430\u0442\u044b\u043d \u043a\u043e\u0448\u0443\u0443 -title.add.to.roster=\u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0438\u0437\u043c\u0435\u0441\u0438\u043d\u0435 \u043a\u043e\u0448\u0443\u0443 -title.address= \u0410\u0434\u0440\u0435\u0441 -title.advanced.connection.preferences= \u041a\u043e\u0448\u0443\u043c\u0447\u0430 \u0442\u0443\u0442\u0430\u0448\u0443\u0443 \u044b\u0440\u0430\u0441\u0442\u043e\u043e\u043b\u043e\u0440\u0443 -title.advanced.connection.usesso= &Single Sign-On (SSO) via GSSAPI \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443 -title.alert=\u041a\u04e9\u04a3\u04af\u043b \u0431\u0443\u0440\u0443\u04a3\u0443\u0437 -title.appearance=\u041a\u04e9\u0440\u04af\u043d\u04af\u0448 -title.appearance.preferences=\u041a\u04e9\u0440\u04af\u043d\u04af\u0448 \u044b\u0440\u0430\u0441\u0442\u043e\u043e\u043b\u043e\u0440\u0443 -title.appearance.showVCards=\u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0438\u0437\u043c\u0435\u0441\u0438\u043d\u0434\u0435 VCard \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -title.available.transports=\u0411\u0430\u0440 \u0431\u043e\u043b\u0433\u043e\u043d \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u0442\u043e\u0440 -title.bookmarks=\u042d\u0441\u0431\u0435\u043b\u0433\u0435\u043b\u0435\u0440 -title.broadcast.message=\u041a\u04e9\u043f\u0442\u04af\u043a \u043a\u0430\u0431\u0430\u0440\u043b\u0430\u043c\u0430 -title.browse.conference.services=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f \u043a\u044b\u0437\u043c\u0430\u0442\u0442\u0430\u0440\u0434\u044b\u043d \u0442\u0438\u0437\u043c\u0435\u0441\u0438 -title.browse.room.service=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f\u043b\u0430\u0440 \u0442\u0438\u0437\u043c\u0435\u0441\u0438 - {0} -title.cancelled=\u041a\u0430\u043b\u0442\u044b\u0440\u044b\u043b\u0434\u044b -title.change.nickname=\u0422\u0430\u043a\u043c\u0430 \u044b\u0441\u044b\u043c\u0434\u044b \u0430\u043b\u043c\u0430\u0448\u0442\u044b\u0440\u0443\u0443 -title.change.subject=\u0422\u0435\u043c\u0430\u043d\u044b \u0430\u043b\u043c\u0430\u0448\u0442\u044b\u0440\u0443\u0443 -title.chat=\u0427\u0430\u0442 -title.choose.directory=\u041a\u0430\u0442\u0430\u043b\u043e\u0433\u0434\u0443 \u0442\u0430\u043d\u0434\u0430\u04a3\u044b\u0437 -title.choose.incoming.sound=\u041a\u0435\u043b\u04af\u04af\u0447\u04af \u0447\u0430\u043b\u0443\u0443 \u04af\u0447\u04af\u043d \u04af\u043d\u0434\u04af \u0442\u0430\u043d\u0434\u0430\u04a3\u044b\u0437 -title.choose.offline.sound=\u00ab\u0422\u0430\u0440\u043c\u0430\u043a\u0442\u0430 \u044d\u043c\u0435\u0441\u00bb \u04af\u043d\u04af\u043d \u0442\u0430\u043d\u0434\u0430\u04a3\u044b\u0437 -title.choose.outgoing.sound= \u0427\u0430\u043b\u0443\u0443 \u04af\u043d\u04af\u043d \u0442\u0430\u043d\u0434\u0430\u04a3\u044b\u0437 -title.client.logs=\u041a\u043b\u0438\u0435\u043d\u0442 \u043b\u043e\u0433\u0434\u043e\u0440\u0443 -title.conference.invitation=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f\u0433\u0430 \u0447\u0430\u043a\u044b\u0440\u0443\u0443 -title.conference.rooms=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f \u0431\u04e9\u043b\u04af\u043c\u0434\u04e9\u0440\u04af -title.configure.chat.room=\u0411\u04e9\u043b\u043c\u04e9 \u044b\u0440\u0430\u0441\u0442\u043e\u043e\u043b\u043e\u0440\u0443 -title.configure.room=\u0411\u04e9\u043b\u043c\u04e9\u043d\u04af \u044b\u0440\u0430\u0441\u0442\u043e\u043e -title.confirmation=\u0422\u0430\u0441\u0442\u044b\u043a\u0442\u043e\u043e -title.create.new.account= \u0416\u0430\u04a3\u044b \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u0442\u04af\u0437\u04af\u04af -title.create.or.bookmark.room= \u041a\u0438\u0440\u04af\u04af \u0436\u0435 \u0431\u04e9\u043b\u043c\u04e9\u043d\u04af \u044d\u0441\u0431\u0435\u043b\u0435\u0440\u0433\u0435 \u043a\u043e\u0448\u0443\u0443 -title.create.or.join=\u0422\u04af\u0437\u04af\u04af/\u041a\u0438\u0440\u04af\u04af -title.create.problem= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u0442\u04af\u0437\u04af\u04af\u0434\u04e9 \u043a\u044b\u0439\u044b\u043d\u0447\u044b\u043b\u044b\u043a\u0442\u0430\u0440 \u0447\u044b\u043a\u0442\u044b -title.delete.file=\u0421\u0438\u0437 \u0444\u0430\u0439\u043b\u0434\u044b \u04e9\u0447\u04af\u0440\u04af\u04af\u043d\u04af \u043a\u0430\u0430\u043b\u0430\u0439\u0441\u044b\u0437\u0431\u044b? -title.dial.phone=\u0422\u0435\u043b\u0435\u0444\u043e\u043d\u0433\u043e \u0447\u0430\u043b\u0443\u0443 -title.disable.transport= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u0430\u0440\u044b\u043d \u04e9\u0447\u04af\u0440\u04af\u04af -title.download.complete=\u0416\u04af\u043a\u0442\u04e9\u04e9 \u0430\u044f\u043a\u0442\u0430\u043b\u0434\u044b -title.downloading.im.client=IM \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0438 \u0436\u04af\u043a\u0442\u04e9\u04e9 -title.downloads=\u0416\u04af\u043a\u0442\u04e9\u04e9\u043b\u04e9\u0440 -title.edit.custom.message=\u0416\u04e9\u043d\u04e9\u043a\u04e9\u0439 \u0441\u0442\u0430\u0442\u0443\u0441\u0442\u0430\u0440\u0434\u044b \u043e\u043d\u0434\u043e\u043e -title.edit.profile=\u041f\u0440\u043e\u0444\u0438\u043b\u0434\u0438 \u043e\u043d\u0434\u043e\u043e -title.enter.reason=\u0421\u0435\u0431\u0435\u043f\u0442\u0438 \u043a\u0438\u0440\u0438\u04a3\u0438\u0437 -title.error=\u041a\u0430\u0442\u0430 -title.error.couldnt.open.file=\u0424\u0430\u0439\u043b \u0430\u0447\u044b\u043b\u0433\u0430\u043d \u0436\u043e\u043a! \u0411\u0430\u043b\u043a\u0438\u043c \u0444\u0430\u0439\u043b \u0442\u0438\u0431\u0438 \u0431\u0435\u043b\u0433\u0438\u0441\u0438\u0437! -title.error.delete.file=\u0424\u0430\u0439\u043b \u04e9\u0447\u04af\u0440\u04af\u043b\u0433\u04e9\u043d \u0436\u043e\u043a! -title.error.find.app=\u0422\u0443\u0448 \u043a\u0435\u043b\u0433\u0435\u043d \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0442\u0430\u0431\u044b\u043b\u0433\u0430\u043d \u0436\u043e\u043a! -title.error.rename.file=\u0424\u0430\u0439\u043b\u0434\u044b\u043d \u0430\u0442\u044b \u0430\u043b\u043c\u0430\u0448\u0442\u044b\u0440\u044b\u043b\u0433\u0430\u043d \u0436\u043e\u043a! -title.facebook.registration= Facebook \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u0430\u0440\u044b -title.file=\u0424\u0430\u0439\u043b -title.file.exists= \u0424\u0430\u0439\u043b \u0430\u043b\u0434\u0430 \u043a\u0430\u0447\u0430\u043d \u0431\u0430\u0440 -title.file.transfer=\u0424\u0430\u0439\u043b \u0436\u04e9\u043d\u04e9\u0442\u04af\u04af -title.file.transfer.preferences= \u0424\u0430\u0439\u043b \u0436\u04e9\u043d\u04e9\u0442\u04af\u04af \u044b\u0440\u0430\u0441\u0442\u043e\u043e\u043b\u043e\u0440\u0443 -title.filesize=\u0424\u0430\u0439\u043b \u04e9\u043b\u0447\u04e9\u043c\u04af -title.find.conference.service=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f \u043a\u044b\u0437\u043c\u0430\u0442\u0442\u0430\u0440\u044b\u043d \u0442\u0430\u0431\u0443\u0443 -title.find.contacts=\u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0430\u0431\u0443\u0443 -title.gadugadu.registration= GaduGadu \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u0430\u0440\u044b -title.general.chat.settings=\u041d\u0435\u0433\u0438\u0437\u0433\u0438 \u0447\u0430\u0442 \u044b\u0440\u0430\u0441\u0442\u043e\u043e\u043b\u043e\u0440\u0443 -title.general.media=\u041c\u0435\u0434\u0438\u044f \u044b\u0440\u0430\u0441\u0442\u043e\u043e\u043b\u043e\u0440\u0443 -title.group.chat=\u0413\u0440\u0443\u043f\u043f\u0430\u043b\u044b\u043a \u0447\u0430\u0442 -title.group.chat.settings=\u0413\u0440\u0443\u043f\u043f\u0430\u043b\u044b\u043a \u0447\u0430\u0442 \u044b\u0440\u0430\u0441\u0442\u043e\u043e\u043b\u043e\u0440\u0443 -title.gtalk.registration= GTalk \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u0430\u0440\u044b -title.history.for={0} \u0441\u04af\u0439\u043b\u04e9\u0448\u04af\u04af \u0442\u0430\u0440\u044b\u0445\u044b -title.icq.registration= ICQ \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u0430\u0440\u044b -title.incoming.call= \u0416\u0430\u04a3\u044b \u0447\u0430\u043b\u0443\u0443 -title.input.fileexplorer=\u0424\u0430\u0439\u043b \u0430\u0440\u0430\u043b\u0430\u0433\u044b\u0447 \u0430\u0442\u044b\u043d \u043a\u0438\u0440\u0433\u0438\u0437\u0438\u04a3\u0438\u0437: -title.input.newname=\u0416\u0430\u04a3\u044b \u0430\u0442\u044b\u043d \u043a\u0438\u0440\u0433\u0438\u0437\u0438\u04a3\u0438\u0437: -title.input.openwith=\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0436\u0430\u0440\u0434\u0430\u043c\u044b \u043c\u0435\u043d\u0435\u043d \u0430\u0447\u0443\u0443 \u04af\u0447\u04af\u043d \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430\u043d\u044b\u043d \u0430\u0442\u044b\u043d \u043a\u0438\u0440\u0433\u0438\u0437\u0438\u04a3\u0438\u0437: -title.invite.to.conference=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f\u0433\u0430 \u0447\u0430\u043a\u044b\u0440\u0443\u0443 -title.irc.registration= IRC \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u0430\u0440\u044b -title.jabber.browser=\u0410\u0440\u0430\u043b\u0430\u0433\u044b\u0447 -title.join.conference.room=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f\u0433\u0430 \u043a\u043e\u0448\u0443\u043b\u0443\u0443 -title.last.activity=\u0410\u043a\u044b\u0440\u043a\u044b \u0430\u043a\u0442\u0438\u0432\u0434\u04af\u04af\u043b\u04af\u0433\u04af -title.login=\u0411\u0430\u0439\u043b\u0430\u043d\u044b\u0448 -title.login.error=\u041a\u0438\u0440\u04af\u04af \u043a\u0430\u0442\u0430\u0441\u044b -title.login.settings= \u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u043a\u0438\u0440\u04af\u04af \u044b\u0440\u0430\u0441\u0442\u043e\u043e\u043b\u043e\u0440\u0443 -title.lookup.profile=\u041f\u0440\u043e\u0444\u0438\u043b\u0434\u0438\u043d \u043a\u04e9\u0440\u04af\u043d\u04af\u0448\u04af -title.msn.registration= MSN \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u0430\u0440\u044b -title.myspace.registration= MySpace \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u0430\u0440\u044b -title.name=\u0410\u0442\u044b -title.new.client.available= \u0416\u0430\u04a3\u044b \u043a\u043b\u0438\u0435\u043d\u0442 \u0431\u0430\u0440 -title.new.roster.group=\u0416\u0430\u04a3\u044b \u0433\u0440\u0443\u043f\u043f\u0430 -title.new.version.available= \u0416\u0430\u04a3\u044b \u0432\u0435\u0440\u0441\u0438\u044f\u0441\u044b \u0431\u0430\u0440 -title.no.updates=\u0416\u0430\u04a3\u044b\u043b\u043e\u043e\u043b\u043e\u0440 \u0436\u043e\u043a -title.notes=\u042d\u0441\u043a\u0435\u0440\u0442\u043c\u0435\u043b\u0435\u0440 -title.notification= \u042d\u0441\u043a\u0435\u0440\u0442\u04af\u04af -title.notifications=\u042d\u0441\u043a\u0435\u0440\u0442\u04af\u04af\u043b\u04e9\u0440 -title.occupants=\u041a\u0430\u0442\u044b\u0448\u0443\u0443\u0447\u0443\u043b\u0430\u0440 -title.on.the.phone=\u0422\u0435\u043b\u0435\u0444\u043e\u043d\u0434\u043e -title.password=\u0421\u044b\u0440\u0441\u04e9\u0437 -title.password.required=\u0421\u044b\u0440\u0441\u04e9\u0437 \u0442\u0430\u043b\u0430\u043f \u043a\u044b\u043b\u044b\u043d\u0430\u0442 -title.passwords.no.match= \u0421\u044b\u0440\u0441\u04e9\u0437\u0434\u04e9\u0440\u0434\u04af \u043a\u0430\u0439\u0440\u0430\u0434\u0430\u043d \u043a\u0438\u0440\u0438\u04a3\u0438\u0437. -title.person.search=\u0410\u0434\u0430\u043c\u0434\u0430\u0440\u0434\u044b \u0438\u0437\u0434\u04e9\u04e9 -title.plugins= \u041f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440 -title.preferences=\u042b\u0440\u0430\u0441\u0442\u043e\u043e\u043b\u043e\u0440 -title.profile.information=\u041f\u0440\u043e\u0444\u0438\u043b\u044c \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u044b -title.profile.not.found= \u041f\u0440\u043e\u0444\u0438\u043b\u044c \u0442\u0430\u0431\u044b\u043b\u0433\u0430\u043d \u0436\u043e\u043a -title.qq.registration= QQ \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u0430\u0440\u044b -title.register.account= \u0416\u0430\u04a3\u044b \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443 \u0430\u0442\u044b\u043d \u043a\u0430\u0442\u0442\u043e\u043e -title.registration.error= \u041a\u0430\u0442\u0442\u043e\u043e \u043a\u0430\u0442\u0430\u0441\u044b -title.reminder= \u042d\u0441\u0442\u0435\u0442\u04af\u04af -title.rename.roster.group= \u0413\u0440\u0443\u043f\u043f\u0430\u043d\u044b\u043d \u0430\u0442\u044b\u043d \u0430\u043b\u043c\u0430\u0448\u0442\u044b\u0440\u0443\u0443 -title.room.destroyed= \u0411\u04e9\u043b\u043c\u04e9 \u0431\u0443\u0437\u0443\u043b\u0434\u0443 -title.room.information= \u0411\u04e9\u043b\u043c\u04e9 \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u044b -title.roster=\u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u0442\u0438\u0437\u043c\u0435\u0441\u0438 -title.sametime.registration= Sametime \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u0430\u0440\u044b -title.select.file.to.send=\u0424\u0430\u0439\u043b\u0434\u044b \u0442\u0430\u043d\u0434\u043e\u043e -title.set.status.message=\u0421\u0442\u0430\u0442\u0443\u0441\u0442\u0443 \u043e\u0440\u043d\u043e\u0442\u0443\u0443 -title.simple.registration=SIMPLE \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u0430\u0440\u044b -title.sound.preferences=\u04ae\u043d\u0434\u04e9\u0440 \u044b\u0440\u0430\u0441\u0442\u043e\u043e\u043b\u043e\u0440\u0443 -title.sounds=\u04ae\u043d\u0434\u04e9\u0440 -title.spark.preferences=Spark \u044b\u0440\u0430\u0441\u0442\u043e\u043e\u043b\u043e\u0440\u0443 -title.start.chat=\u0427\u0430\u0442\u0442\u044b \u0431\u0430\u0448\u0442\u043e\u043e -title.status.message= \u0421\u0442\u0430\u0442\u0443\u0441 -title.task.notification=\u0422\u0430\u043f\u0448\u044b\u0440\u043c\u0430 \u044d\u0441\u0442\u0435\u0442\u04af\u04af\u0441\u04af -title.tasks=\u0422\u0430\u043f\u0448\u044b\u0440\u043c\u0430\u043b\u0430\u0440 -title.transports= \u0422\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u0442\u043e\u0440 -title.tray.information=\u0422\u0440\u0435\u0439 \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u044b -title.upgrading.client=IM \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0438 \u0436\u0430\u04a3\u044b\u043b\u043e\u043e -title.version.and.time= \u0412\u0435\u0440\u0441\u0438\u044f\u0441\u044b \u0436\u0430\u043d\u0430 \u0443\u0431\u0430\u043a\u044b\u0442\u044b -title.view.bookmarks= \u042d\u0441\u0431\u0435\u043b\u0433\u0435\u043b\u0435\u0440\u0434\u0438 \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -title.view.profile.for={0} \u043f\u0440\u043e\u0444\u0438\u043b\u0438 -title.view.room.information=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u044b -title.waiting.to.call=\u0427\u0430\u043b\u0443\u0443 \u043a\u04af\u0442\u04af\u043b\u04af\u04af\u0434\u04e9 -title.xmpp.registration= XMPP \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u0430\u0440\u044b -title.yahoo.registration= Yahoo \u043c\u0430\u0430\u043b\u044b\u043c\u0430\u0442\u0442\u0430\u0440\u044b -tooltip.appearance=\u0421\u04af\u0439\u043b\u04e9\u0448\u04af\u04af \u043a\u04e9\u0440\u04af\u043d\u04af\u0448\u04af\u043d \u04e9\u0437\u0433\u04e9\u0440\u0442\u04af\u04af. -tooltip.file.transfer=\u0424\u0430\u0439\u043b \u0436\u04e9\u043d\u04e9\u0442\u04af\u04af \u044b\u0440\u0430\u0441\u0442\u043e\u043e\u043b\u043e\u0440\u0443. -tooltip.notifications= \u041a\u0435\u043b\u0433\u0435\u043d \u0447\u0430\u0442\u0442\u0430\u0440 \u04af\u0447\u04af\u043d \u0431\u0438\u043b\u0434\u0438\u0440\u04af\u04af \u044b\u0440\u0430\u0441\u0442\u043e\u043e\u043b\u043e\u0440\u0443. -tooltip.place.a.call=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u0433\u0430 \u0447\u0430\u043b\u0443\u0443 -tooltip.place.voice.call=\u041a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u0433\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d \u0447\u0430\u043b\u0443\u0443. -tooltip.send.email=e-mail \u0436\u04e9\u043d\u04e9\u0442\u04af\u04af. -tooltip.start.chat=\u0421\u04af\u0439\u043b\u04e9\u0448\u04af\u04af\u043d\u04af \u0431\u0430\u0448\u0442\u043e\u043e. -tooltip.view.changelog=\u04e8\u0437\u0433\u04e9\u0440\u04af\u04af\u043b\u04e9\u0440 \u0442\u0430\u0440\u044b\u0445\u044b\u043d \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -tooltip.view.history=\u0421\u04af\u0439\u043b\u04e9\u0448\u04af\u04af \u0442\u0430\u0440\u044b\u0445\u044b\u043d \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -tooltip.view.readme=ReadMe \u043a\u04e9\u0440\u0441\u04e9\u0442\u04af\u04af -tree.conference.services=\u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044f \u043a\u044b\u0437\u043c\u0430\u0442\u0442\u0430\u0440\u044b -tree.users.in.room=\u0411\u04e9\u043b\u043c\u04e9\u0434\u04e9 \u043a\u043e\u043b\u0434\u043e\u043d\u0443\u0443\u0447\u0443\u043b\u0430\u0440 -unfiled=\u0422\u043e\u043b\u0442\u0443\u0440\u0443\u043b\u0431\u0430\u0433\u0430\u043d -use.default= \u0410\u043b\u044b\u0434\u043d\u0430\u043b\u0430 -user.has.signed.in= \u043a\u0438\u0440\u0434\u0438. -user.has.signed.off= \u0447\u044b\u043a\u0442\u044b. -while.offline=\u0422\u0430\u0440\u043c\u0430\u043a\u0442\u0430 \u044d\u043c\u0435\u0441 \u0443\u0431\u0430\u043a\u044b\u0442\u044b\u043d\u0434\u0430 -yes= \u041e\u043e\u0431\u0430 - - -#!# \ No newline at end of file diff --git a/src/resources/i18n/spark_i18n_lt.properties b/src/resources/i18n/spark_i18n_lt.properties deleted file mode 100644 index 5c0f7e039..000000000 --- a/src/resources/i18n/spark_i18n_lt.properties +++ /dev/null @@ -1,1054 +0,0 @@ -## -## Spark Resource Bundle -## Spark Lithuanian Resource Bundle -## -## Copyright (C) Rytis Umbrasas, 2009 -## Distributed under the same license as Spark -## -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.0.1 -## Added key: 'message.restart.spark.changes' -## Added key: 'message.enter.icq' -## Added key: 'title.icq.registration' -## Added key: 'button.quit' -## -## -## -## 2.0.2 -## Added key: 'button.new' -## Added key: 'label.group' -## Added key: 'label.jabber.id' -## Added key: 'label.enter.group.name' -## Added key: 'title.new.roster.group' -## Added key: 'title.add.contact.group' -## Added key: 'message.add.contact.to.list' -## Added key: 'title.add.contact' -## Added key: 'tab.conferences' -## Added key: 'message.autenticating' -## Added key: 'title.file.transfer.preferences' -## Added key: 'menuitem.about' -## Added key: 'message.invalid.status' -## Added key: 'message.cannot.add.contact.to.shared.group -## Added key: 'message.specify.contact.jid' -## Added key: 'message.invalid.jid.error' -## Added key: 'message.specify.group' -## Added key: 'add' -## -## -## -## 2.0.5 -## Added key: 'Broadcast' -## Added key: 'label.user.on.public.network' -## Added key: 'label.network' -## -## -## 2.0.6 -## Added key: 'button.add.user' -## Added key: 'menuitem.sign.in' -## Added key: 'menuitem.sign.out' -## Added key: 'menuitem.sign.in.at.login' -## Added key: 'menuitem.enter.login.information' -## Added key: 'menuitem.delete.login.information' -## Added key: 'button.save' -## -## -## 2.5 -## Added key: 'button.start.chat' -## Added key: 'button.send.email' -## Added key: 'available' -## Added key: 'checkbox.tabs.on.top' -## Added key: 'user.has.signed.in' -## Added key: 'user.has.signed.off' -## Added key: 'label.unable.to.add.contact' -## Added key: 'label.conflict.error' -## Added key: 'message.room.creation.error' -## Added key: 'checkbox.allow.buzz' -## Added key: 'message.disconnected.group.chat.error' -## Added key: 'menuitem.show.offline.group' -## Added key: 'menuitem.move.to' -## Added key: 'menuitem.copy.to' -## Added key: 'label.message.style' -## Added key: 'label.emoticons' -## Added key: 'checkbox.enable.emoticons' -## Added key: 'message.unable.to.retrieve.last.activity' -## Added key: 'checkbox.use.system.look.and.feel' -## -## 2.5.2 -## Added key: 'tooltip.place.voice.call' -## Added key: 'message.buzz.alert.notification' -## Added kye: 'message.buzz.sent' -## -## 2.5.2 -## Added key: 'menuitem.user.guide' -## -## -## -## 2.5.7 -## Added key: 'menuitem.languages' -## Added key: 'message.restart.required' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'message.send.to.these.people' -## Added key: 'message' -## Added key: 'message.normal' -## Added key: 'message.alert.notify' -## -## 2.5.8 -## Added key: 'message.enter.simple' -## Added key: 'message.enter.irc' -## Added key: 'message.enter.gadugadu' -## Added key: 'title.simple.registration' -## Added key: 'title.irc.registration' -## Added key: 'title.gadugadu.registration' -## Added key: 'message.username.error' -## Added key: 'message.password.error' -## Added key: 'message.nickname.error' -## -## 2.5.9 -## Added key: 'message.gateway.username.error. -## Added key: 'message.gateway.password.error. -## Added key: 'message.gateway.nickname.error. -## Added key: 'answer' -## Added key: 'online' -## Added key: 'online' -## Added key: 'offline' -## Added key: 'participants' -## Added key: 'unfiled' -## Added key: 'while.offline' -## Added key: 'action.clear' -## Added key: 'action.copy ' -## Added key: 'action.cut' -## Added key: 'action.paste' -## Added key: 'action.print' -## Added key: 'action.save' -## Added key: 'action.select.all' -## Added key: 'button.add2' -## Added key: 'button.copy.to.clipboard' -## Added key: 'button.reconnect2' -## Added key: 'button.tasks.active' -## Added key: 'button.tasks.all' -## Added key: 'button.view.notes' -## Added key: 'button.view.profile' -## Added key: 'button.view.tasklist' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.show.avatars.in.contaclist' -## Added key: 'checkbox.use.compression' -## Added key: 'group.empty' -## Added key: 'group.offline' -## Added key: 'label.add.task' -## Added key: 'label.chatroom.fontsize' -## Added key: 'label.contactlist.fontsize' -## Added key: 'label.due' -## Added key: 'label.show' -## Added key: 'label.timeformat' -## Added key: 'menuitem.dial' -## Added key: 'menuitem.view.logs' -## Added key: 'message.disconnected.shutdown' -## Added key: 'message.invalid.username.password' -## Added key: 'message.no.updates' -## Added key: 'message.reconnect.attempting' -## Added key: 'message.reconnect.failed' -## Added key: 'message.reconnect.wait' -## Added key: 'message.send.picture' -## Added key: 'message.server.unavailable' -## Added key: 'message.unrecoverable.error' -## Added key: 'message.waiting.for.user.to.join' -## Added key: 'status.available' -## Added key: 'status.away' -## Added key: 'status.custom.messages' -## Added key: 'status.do.not.disturb' -## Added key: 'status.extended.away' -## Added key: 'status.free.to.chat' -## Added key: 'status.on.phone' -## Added key: 'status.online' -## Added key: 'status.pending' -## Added key: 'title.about' -## Added key: 'title.appearance' -## Added key: 'title.appearance.preferences' -## Added key: 'title.login.error' -## Added key: 'title.no.updates' -## Added key: 'title.notes' -## Added key: 'title.tasks' -## Added key: 'tooltip.appearance' -## Added key: 'tooltip.file.transfer' -## Added key: 'tooltip.send.email' -## Added key: 'tooltip.start.chat' -## Added key: 'delete.log.permanently' -## Added key: 'delete.permanently' -## Added key: 'label.contactlist.avatarsize' -## Added key: 'title.qq.registration' -## Added key: 'message.enter.qq' -## -## 2.6.0 -## -## Added key: 'apply' -## -## 2.6.0 beta 1 -## Removed key status.available - -accept = Priimti -active = Aktyvu -add = Prid\u0117ti -administrator = Administratorius -answer = Atsakymas -apply = Taikyti -available = Prieinamas -broadcast = Transliavimas -cancel = At\u0161aukti -close = U\u017everti -create = Sukurti -date = Data -description = Pavadinimas -from = Siunt\u0117jas -invite = Pakviesti -join = Prisiju&ngti -no = Ne -not.registered = Neregistruota -occupants = Lankytoj\u0173 sk.: -offline = Atsijung\u0119s -ok = Gerai -online = Prisijung\u0117 -open = Atverti -open.folder = Atverti aplank\u0105 -participants = Dalyviai -reject = Atmesti -retry = Pakartoti -room.name = Kambario vardas -save = \u012era\u0161yti -subject = Tema -unfiled = Ne\u012fra\u0161yta -use.default = Naudoti kaip numatyta -user.has.signed.in = Prisijung\u0117 -user.has.signed.off = Atsijung\u0117 -while.offline = Kol atsijung\u0119s -yes = Taip - -action.clear = Valyti -action.copy = Kopijuoti -action.cut = I\u0161kirpti -action.paste = \u012eklijuoti -action.print = Spausdinti -action.save = \u012era\u0161yti -action.select.all = \u017dym\u0117ti visk\u0105 - -button.accept = &Priimti -button.reject = &Atmesti -button.add = P&rid\u0117ti -button.add.a.contact = Prid\u0117ti &adresat\u0105 -button.add.bookmark = Prid\u0117ti \u017eym\u0105 -button.add.service = Prid\u0117ti &tarnyb\u0105 -button.add.user = Prid\u0117ti a&bonent\u0105 -button.add2 = Pri&d\u0117ti -button.advanced = Prisij&ungimo nuostatos -button.approve = Pa&tvirtinti -button.bookmark.room = Pasi\u017eym\u0117ti kambar\u012f -button.browse = &Nar\u0161yti\u2026 -button.browse2 = N&ar\u0161yti\u2026 -button.browse3 = Na&r\u0161yti\u2026 -button.cancel = &At\u0161aukti -button.clear = &Valyti -button.close = U\u017everti -button.copy.to.clipboard = Kopijuoti i\u0161karpin\u0117n -button.create.account = Paskyros &suk\u016brimas -button.create.room = Sukurti arba prisijungti &kambar\u012f -button.decline = &Atmesti -button.deny = &Nepriimti -button.dial.number = Numeris &skambinimui -button.find = &Ie\u0161koti -button.join = P&risijungti -button.join.room = Prisijungti prie pasirinktojo &kambario -button.login = P&risijungti -button.new = &Nauja -button.profile = &Profilis -button.quit = &Baigti -button.reconnect = &Prisijungti i\u0161 naujo -button.reconnect2 = Prisijungti i\u0161 naujo -button.refresh = &Atnaujinti -button.register = &Registruoti -button.remove.bookmark = Pa\u0161alinti \u017eym\u0105 -button.roster = &S\u0105ra\u0161as -button.save = \u012e&ra\u0161yti -button.save.for.future.use = \u012era\u0161yti paskesniam &naudojimui -button.search = &Ie\u0161koti -button.send = Si\u0173sti -button.send.email = Pa\u0161tas -button.start.chat = Pokalbis -button.tasks.active = Aktualios -button.tasks.all = Visos -button.unset.file.explorer = Nustatyti byl\u0173 per\u017ei\u016br\u0105 i\u0161 naujo -button.update = &Atnaujinti -button.view.notes = Per\u017ei\u016br\u0117ti u\u017era\u0161us -button.view.profile = Per\u017ei\u016br\u0117ti profil\u012f -button.view.tasklist = Per\u017ei\u016br\u0117ti u\u017eduotis -button.re.detect = &Aptikti i\u0161 naujo - -checkbox.allow.buzz = &Leisti pa\u0161nekovams purtyti j\u016bs\u0173 pokalbio lang\u0105 -checkbox.auto.discover.port = &Automatinis serverio ir jo prievado aptikimas -checkbox.auto.login = A&utomati\u0161kai prisijungti -checkbox.login.as.invisible = &Prisijungti nematomam -checkbox.disable.chat.history = I\u0161j&ungti pokalbi\u0173 \u017eurnal\u0105 -checkbox.sort.asc.history = R\u016b\u0161iuo&ti \u017einutes kontakto istorijoje datos did\u0117jimo tvarka -checkbox.disable.prev.chat.history = &I\u0161jungti ankstesni\u0173 pokalbi\u0173 rodym\u0105 -checkbox.enable.emoticons = &Rodyti jaustukus -checkbox.graying.out = U\u017epilkinti neaktyvius adresatus (reikalingas perkrovimas) -checkbox.idle.enabled = \u012ejungti neveikos rodym\u0105 -checkbox.launch.on.startup = Paleisti startavus -checkbox.reconnet.info = Nurodyti pakartotino prisijungimo rodym\u0105: -checkbox.reconnect.panel.big = Rodyti kaip Panel\u0119 -checkbox.reconnect.panel.small = Rodyti adresat\u0173 grup\u0117je -checkbox.reconnect.panel.icon = Rodyti kaip ikon\u0105 -checkbox.notify.user.comes.online = Rodyti kito prisijungim\u0105 -checkbox.notify.user.goes.offline = Rodyti kito atsijungim\u0105 -checkbox.notify.typing.systemtray = Sistemos juostel\u0117je rodyti kada ra\u0161oma -checkbox.notify.systemtray = Nauj\u0173 \u017einu\u010di\u0173 rodymas sistemos juostel\u0117je -checkbox.permanent = &Kambarys ilgam -checkbox.play.sound.on.invitation = Pagroti gavus pakvieti&m\u0105 -checkbox.play.sound.on.new.message = Pagroti &gavus nauj\u0105 \u017einut\u0119 -checkbox.play.sound.on.outgoing.message = Pagroti &i\u0161siun\u010diant \u017einut\u0119 -checkbox.play.sound.when.offline = Pagroti, kai kitas &atsijungia -checkbox.private.room = Priva&tus Kambarys -checkbox.save.password = \u012es&iminti slapta\u017eod\u012f -checkbox.show.avatars.in.contactlist = Adres\u0173 s\u0105ra\u0161e rodyti ps&eudoportretus -checkbox.show.notifications.in.conference = &Rodyti prane\u0161imus konferencij\u0173 kambariuose -checkbox.show.time.in.chat.window = P&okalbio lange rodyti laik\u0105 -checkbox.show.toaster = Rodyti i\u0161\u0161okant\u012f prane\u0161im\u0105 -checkbox.disable.asterisk.toaster = I\u0161jungti skambu\u010Dio i\u0161\u0161okant\u012F prane\u0161im\u0105 -checkbox.split.chat.window = Lango \u012ft&virtinimas (reik\u0117s i\u0161 naujo paleisti program\u0105) -checkbox.start.in.tray = &Startuoti sistemos juostel\u0117je -checkbox.click.single.tray = &Naudoti vien\u0105 paspaudim\u0105 sistemos juostel\u0117je, kad pakelti Spark \u012f priek\u012f -checkbox.tabs.on.top = &Pokalbi\u0173 korteles rodyti vir\u0161uje (reik\u0117s i\u0161 naujo paleisti program\u0105) -checkbox.use.compression = Nau&doti suspaudim\u0105 -checkbox.use.debugger.on.startup = S&tartavus \u012fjungti klaid\u0173 paie\u0161kos veiksen\u0105 -checkbox.use.proxy.server = Na&udoti tarpin\u012f server\u012f -checkbox.use.system.look.and.feel = Naudoti operacin\u0117s sistemos i\u0161vaizd\u0105 (reik\u0117s i\u0161 naujo paleisti program\u0105) -checkbox.window.to.front = &I\u0161kelti prane\u0161imo lang\u0105 \u012f ekrano priek\u012f -checkbox.broadcast.hide.offline.user = Sl\u0117pti atsijungusius -checkbox.use.krbconf = Naudoti krb5.conf ir krb5.ini bylas -checkbox.use.krb.dns = Naudoti sri\u010di\u0173 vard\u0173 server\u012f (DNS) -checkbox.use.specify.below = Apib\u016bdinimas \u017eemiau -checkbox.use.pki.authentication = &PKI autentifikavimo naudojimas -checkbox.transport.tab.setting = Rodyti prieinamus ry\u0161io kanalus kortel\u0117je (reikalingas perkrovimas) -checkbox.conference.tab.setting = Rodyti grupini\u0173 pokalbi\u0173 tarnyb\u0105 kortel\u0117je (reikalingas perkrovimas) -checkbox.use.hostname.as.resource = Na&udoti kompiuterio vard\u0105 kaip resurs\u0105 -checkbox.use.version.as.resource = Naudot&i Spark versij\u0105 kaip resurs\u0105 - -delete.log.permanently = Visi\u0161kas \u017eurnalo pa\u0161alinimas -delete.permanently = Galutinai pa\u0161alinti? - -gateway.username.password.error = Reik\u0117s pateikti abonento vard\u0105 ir/arba slapta\u017eod\u012f - -group.chat.window.information = Pokalbio lango informacija -group.comma.delimited = Atskirta kableliu -group.conferences.found = Atrasta konferencij\u0173 tarnyba -group.connection = Jungtis -group.empty = Prisijungusi\u0173 \u0161ioje grup\u0117je n\u0117ra -group.general.information = Bendra informacija -group.login.information = Prisijungimo informacija -group.notification.options = Prane\u0161im\u0173 nuostatos -group.offline = Atsijungusi\u0173j\u0173 grup\u0117 -group.search.form = Paie\u0161kos anketa -group.search.results = Paie\u0161kos rezultatai -group.chat.name.notification = Apie jus kalba\u2026 -group.chat.name.match = J\u016bs\u0173 vard\u0105 pamin\u0117jo grupiniame pokalbyje: - -label.na = n\u0117ra ira\u0161o -label.cell = Mobilus nr. -label.work = Darbinis nr. -label.home = Nam\u0173 nr. -label.accounts = Pas&kyra -label.add.conference.service = &Konferencij\u0173 tarnybos prid\u0117jimas -label.add.jid = &Pakviesti ir -label.add.task = Pridedama u\u017eduotis -label.auto.login = &Automatinis prisijungimas -label.available.users.in.roster = &Galimi partneriai visame s\u0105ra\u0161e -label.avatar = Pseudoportretas: -label.cancel = At\u0161aukti -label.change.password.to = \u012er&a\u0161ykite nauj\u0105 slapta\u017eod\u012f -label.chatroom.fontsize = Pokalbi\u0173 kambario \u0161riftas: -label.city = &Miestas -label.close = &U\u017everti -label.company = &Organizacija -label.confirm.password = &Slapta\u017eodis pakartotinai -label.conflict.error = Negalima prisijungti, nes jau prisijungta. -label.contact.to.find = Rasti pokalbio partner\u012f -label.recent.conversation = Paskutiniai pokalbiai -label.frequent.contacts = Da\u017eni pokalbi\u0173 partneriai -label.contactlist.avatarsize = Pseudoportreto dydis: -label.contactlist.fontsize = Adres\u0173 \u0161rifto dydis: -label.country = \u0160a&lis -label.create.account = Sukurti paskyr\u0105 -label.department = &Skyrius -label.dial = &Skambinti -label.display.time = Rodymo laikas: -label.downloads = Siuntos -label.due = Iki -label.email.address = Pa\u0161to &adresas -label.emoticons = &Jaustukai -label.enter.address = Kalb\u0117sim su adresatu: -label.enter.group.name = Naujos grup\u0117s \u012fvedimas -label.fax = &Faksas -label.find = &Ie\u0161koti -label.first.name = &Vardas -label.group = &Grup\u0117 -label.host = S&erveris -label.invited.users = Pakviestieji -label.jabber.address = &Jabber adresas -label.jabber.id = &Jabber ID -label.jid = &JID -label.job.title = &Pareigos -label.last.name = Pa&vard\u0117 -label.local.time = &Vietinis laikas -label.message = \u017dinu&t\u0117 -label.message.style = \u017dinut\u0117s &stilius -label.middle.name = &Antras vardas -label.maximum.history.page.entries = Maksimalus \u012fra\u0161\u0173 s&kai\u010dius \u017eurnalo puslapyje -label.minutes.before.stale.chat = Po &kiek minu\u010di\u0173 neaktyvus kambarys pasidaro blankus -label.mobile = &Mobilaus tel. nr. -label.name = &Vardas -label.network = Tin&klas -label.new.nickname = Naujas pseudonimas -label.nickname = Pseu&donimas -label.number = &Numeris -label.ok = Gerai -label.old.ssl = &Naudoti sen\u0105 SSL prievado metod\u0105 -label.os = &Operacin\u0117 sistema -label.pager = Prane\u0161im\u0173 &gaviklis -label.password = S&lapta\u017eodis -label.phone = &Telefonas -label.port = P&rievadas -label.postal.code = Pa\u0161to &kodas -label.presence = &B\u016bsena -label.priority = Prioritetai -label.protocol = &Protokolas -label.received = &Gautas -label.rename.to = Pervardyti \u012f -label.resource = &Resursas -label.response.timeout = R&eakcijos laikas (sek.) -label.room = &Kambarys -label.room.name = &Kambario vardas -label.room.topic = Kambario pokalbio tema -label.search = Ie\u0161koti -label.search.service = &Ie\u0161kos paslauga -label.seconds = sekund\u0117s -label.server = &Serveris -label.server.address = &Serverio adresas -label.show = Rodomos: -label.software = &Programin\u0117 \u012franga -label.state.and.province = &Valstija/Rajonas -label.street.address = &Pa\u0161to adresas -label.time = Laikas: {0} -label.time.till.idle = Neveikos laikas &iki abonentas dar laikomas aktyviu (min.) -label.time.till.idlemessage = Pasitrauk\u0119s nuo kompiuterio -label.timeformat = Laiko formatas {0} -label.transfer.download.directory = &Parsiuntimo vieta: -label.transfer.timeout = &Kiek laukti siuntimo patvirtinimo (min.): -label.unable.to.add.contact = Nepavyko prid\u0117ti adresato. -label.use.default = Naudoti numatyt\u0105 -label.user.on.public.network = Abonentas yra vie\u0161ajame tinkle -label.username = &Abonento vardas -label.version = &Versija -label.web.page = &Tinklalapis -label.xmpp.port = &XMPP prievadas -label.krb.realm = Realm -label.krb.kdc = KDC -label.which.pki.method = Kuris PKI metodas? -label.choose.file = Pasirinkti byl\u0105 -label.trust.store.password = Patikim\u0173 sertifikat\u0173 saugyklos slapta\u017eodis -label.enter.password = \u012evesti slapta\u017eod\u012f -label.move.focus.forwards = Fokusas pirmyn -label.move.focus.backwards = Fokusas atgal -label.keystore.location = Rakt\u0173 saugyklos vieta -label.truststore.location = Patikim\u0173 sertifikat\u0173 saugyklos vieta -label.pkcs.library.file = PKCS#11 bibliotekos byla -label.x509.certificate = X.509 sertifikatas -label.apple.keychain = Apple KeyChain -label.add.to.roster = Prid\u0117ti abonent\u0105 \u012f adresat\u0173 s\u0105ra\u0161\u0105 -label.audio.device = &Garso \u012frenginys -label.video.device = &Vaizdo \u012frenginys - -menuitem.about = Apie -menuitem.actions = Veiksmai -menuitem.bookmarks = \u017dym\u0117s -menuitem.add = Prid\u0117ti -menuitem.add.as.contact = Prid\u0117ti kaip adresat\u0105 -menuitem.add.contact = Prid\u0117ti adresat\u0105 -menuitem.add.contact.group = Prid\u0117ti adresat\u0173 grup\u0119 -menuitem.add.groupchat.myname = I\u0161ry\u0161kinti mano vard\u0105, kai apie j\u012f u\u017esimena kiti -menuitem.add.groupchat.mytext = I\u0161ry\u0161kinti mano tekst\u0105, kai k\u0105 nors ra\u0161au -menuitem.add.groupchat.popname = Parodyti i\u0161\u0161okant\u012f prane\u0161im\u0105, kai kas nors mane pamini -menuitem.add.groupchat.showjoinleavemessage = Rodyti informacij\u0105 apie prisijungim\u0105 ir atsijungim\u0105 -menuitem.add.groupchat.showrolesinsteadofstatus = Rodyti pokalbio roles vietoje b\u016bsenos ikon\u0173 -menuitem.add.groupchat.auto.accept.invite = &Automati\u0161kai priimti grupinio pokalbio kvietimus -menuitem.add.groupchat.random.colors = Vardams suteikiamos &atsitiktin\u0117s spalvos -menuitem.always.on.top = Visada vir\u0161uje -menuitem.alert.when.online = Informuoti, kai abonentas taps pasiekiamas -menuitem.ban = U\u017edrausti -menuitem.ban.user = U\u017edrausti abonent\u0105 -menuitem.block.user = Blokuoti abonent\u0105 -menuitem.broadcast.to.group = Transliuoti \u017eini\u0105 grupei -menuitem.browse.service = Tarnybos per\u017ei\u016bra -menuitem.change.nickname = Keisti pseudonim\u0105 -menuitem.change.subject = Keisti tem\u0105 -menuitem.chat = Pokalbis -menuitem.check.for.updates = Ie\u0161koti programos atnaujinim\u0173 -menuitem.connect = Failas -menuitem.contacts = Adresatai -menuitem.copy.to = Kopijuoti \u012f grup\u0119 -menuitem.delete = Pa\u0161alinti -menuitem.delete.login.information = Pa\u0161alinti prisijungimo informacij\u0105 -menuitem.destroy.room = Pa\u0161alinti kambar\u012f -menuitem.dial = Skambinti -menuitem.edit = Redaguoti -menuitem.edit.my.profile = &Redaguoti mano profil\u012f\u2026 -menuitem.edit.status.message = Redaguoti b\u016bsen\u0173 vardus\u2026 -menuitem.enter.login.information = Prisijungimo informacijos \u012fvedimas -menuitem.exit = I\u0161jungti -menuitem.affiliation = Teisi\u0173 priskyrimas -menuitem.grant.moderator = Paskirti pri\u017ei\u016br\u0117toju -menuitem.grant.member = Suteikti naryst\u0119 -menuitem.grant.admin = Paskirti administratoriumi -menutiem.grant.owner = Paskirti savininku -menuitem.grant.voice = Suteikti balso teis\u0119 -menuitem.help = \u017dinynas -menuitem.hide = Sl\u0117pti -menuitem.invite.group.to.conference = Pakviesti grup\u0119 \u012f konferencij\u0105 -menuitem.invite.users = Pakviesti abonentus -menuitem.join.on.startup = Startavus automati\u0161kai prisijungti -menuitem.join.room = Prisijungti kambar\u012f -menuitem.kick.user = I\u0161pra\u0161yti abonent\u0105 -menuitem.languages = Pasirinkti kalb\u0105 -menuitem.logout.no.status = Atsijungti -menuitem.logout.with.status = Atsijungti nurodant prie\u017east\u012f -menuitem.lookup.profile = &Ie\u0161koti profilio\u2026 -menuitem.move.to = Perkelti \u012f grup\u0119 -menuitem.online.help = \u201eSpark\u201c naudotoj\u0173 forumai internete -menuitem.open = Atverti -menuitem.open.with = Atverti naudojant\u2026 -menuitem.plugins = Priedai -menuitem.preferences = Nuostatos -menuitem.remove = Pa\u0161alinti -menuitem.remove.alert.when.online = Pa\u0161alinti informacijos apie prisijungim\u0105 u\u017esakym\u0105 -menuitem.remove.bookmark = Pa\u0161alinti \u017eym\u0105 -menuitem.remove.from.group = Pa\u0161alinti i\u0161 grup\u0117s -menuitem.remove.from.roster = Pa\u0161alinti i\u0161 s\u0105ra\u0161o -menuitem.block.contact = Blokuoti abonent\u0105 -menuitem.unblock.contact = Atblokuoti abonent\u0105 -menuitem.remove.service = Tarnybos pa\u0161alinimas -menuitem.rename = Keisti vard\u0105 -menuitem.revoke.moderator = At\u0161aukti pri\u017ei\u016br\u0117toj\u0105 -menuitem.revoke.voice = Atimti bals\u0105 -menuitem.revoke.member = At\u0161aukti naryst\u0119 -menuitem.revoke.admin = At\u0161aukti administratori\u0173 -menuitem.revoke.owner = At\u0161aukti savininko privilegij\u0105 -menuitem.save = \u012era\u0161yti -menuitem.save.as = \u012era\u0161yti vardu\u2026 -menuitem.send.a.file = Si\u0173sti byl\u0105 -menuitem.send.a.message = Transliuoti pasirinktiems abonentams\u2026 -menuitem.set.status.message = Parinkti b\u016bsen\u0105\u2026 -menuitem.show.empty.groups = Rodyti tu\u0161\u010dias grupes -menuitem.show.offline.group = Rodyti atsijungusi\u0173j\u0173 grup\u0119 -menuitem.show.traffic = Rodyti tinklo apkrov\u0105 -menuitem.sign.in = \u012esiregistruoti -menuitem.sign.in.at.login = \u012esiregistruoti prisijungiant -menuitem.sign.out = I\u0161siregistruoti -menuitem.start.a.chat = Prad\u0117ti pokalb\u012f -menuitem.start.a.conference = Prad\u0117ti konferencij\u0105\u2026 -menuitem.status = B\u016bsena -menuitem.subscribe.to = U\u017esiprenumeruoti -menuitem.unban = Atblokuoti -menuitem.unblock.user = Atblokuoti abonent\u0105 -menuitem.user.guide = \u017dinyno turinys -menuitem.view.client.version = Informacija apie naudojam\u0105 programin\u0119 \u012frang\u0105 -menuitem.view.contact.history = Per\u017ei\u016br\u0117ti pokalbi\u0173 \u017eurnal\u0105 -menuitem.view.downloads = Per\u017ei\u016br\u0117ti siuntas -menuitem.view.last.activity = Paskiausi\u0173 veiksm\u0173 per\u017ei\u016bra -menuitem.view.logs = \u017durnalas -menuitem.view.profile = Per\u017ei\u016br\u0117ti profil\u012f -menuitem.view.room.info = Per\u017ei\u016br\u0117ti informacij\u0105 apie kambar\u012f -menuitem.voice = Balsas -menuitem.show.offline.users = Rodyti neprisijungusius abonentus -menuitem.show.contact.statusmessage = Parodyti b\u016bsen\u0105 -menuitem.bookmark.room = Pasi\u017eym\u0117ti kambar\u012f -menuitem.refresh = Atnaujinti -menuitem.create.room = Sukurti arba aplankyti pokalbi\u0173 kambar\u012f -menuitem.expand.all.groups = Vis\u0173 grupi\u0173 i\u0161skleidimas -menuitem.collapse.all.groups = Vis\u0173 grupi\u0173 sutraukimas -menuitem.inivite.again = V\u0117l pakviesti -menuitem.chatframe.option = Parinktys -menuitem.add.groupchat.invitetobookmark = Automati\u0161kai kviesti vartotojus \u012f pa\u017eym\u0117t\u0105 kambar\u012f - -message.invite.to.groupchat = {0} Jus pakviet\u0117 prisijungti \u012f pokalbi\u0173 grup\u0119. -message = Transliuojamas prane\u0161imas -message.account.create = Naujos paskyros suk\u016brimas -message.account.created = Nauja paskyra sukurta -message.account.error = Nurodykite kuriamos paskyros server\u012f -message.add.a.contact = Prid\u0117ti adresat\u0105 -message.add.conference.service = Konferencijos prid\u0117jimas -message.add.contact.to.list = Adresin\u0117s papildymas dar vienu abonentu -message.add.favorite.room = Pasi\u017eym\u0117ti reikaling\u0105 kambar\u012f, arba prisijungti prie pokalbi\u0173 jame -message.add.this.user.to.your.roster = Prid\u0117ti \u0161\u012f abonent\u0105 \u012f bi\u010diuli\u0173 s\u0105ra\u0161\u0105 -message.add.to.roster = Prid\u0117ti \u012f s\u0105ra\u0161\u0105 -message.add.user = Ar prid\u0117ti abonent\u0105 \u012f s\u0105ra\u0161\u0105? -message.alert.notify = \u012esp\u0117jimas -message.already.exists = Tokia paskyra jau yra. Pabandykite kit\u0105 vard\u0105. -message.approve.subscription = Ar Leisite abonentui {0} Jus \u012ftraukti \u012f jo adresin\u0119? -message.autenticating = Autentifikavimas -message.away.idle = Neaktyvus -message.bookmark.temporary.room.error = Laikini kambariai negali b\u016bti pasi\u017eymimi. -message.broadcast.from = \u017dini\u0105 transliavo {0} -message.broadcast.no.user.selected = Pra\u0161om pasirinkti bent vien\u0105 adresat\u0105 -message.broadcast.no.text = Pra\u0161om \u012fvesti \u017einut\u0119 transliavimui -message.broadcast.message.sent = Transliuota \u017einia jau i\u0161si\u0173sta -message.broadcast.to = \u012eveskite k\u0105 transliuosite gav\u0117jams {0} -message.broadcasted.to = Transliavote \u0161iems abonentams:\n {0} -message.buzz.alert.notification = Atkreipti d\u0117mes\u012f -message.buzz.message = {0} nori j\u016bs\u0173 d\u0117mesio -message.buzz.sent = Nusi\u0173sti abonentui i\u0161kvietim\u0105 -message.calling = Skambinama {0} -message.came.online = {0} prisijung\u0117 {1} -message.cannot.add.contact.to.shared.group = Jau bendrintos adresat\u0173 grup\u0117s papildyti negalima -message.chat.session.ended = Pokalbis baigtas {0} -message.click.to.open = Spragtelt, kad atverti -message.client.information = Kliento informacija {0} -message.close.other.chats = U\u017everti visus kitus pokalbius -message.close.stale.chats = U\u017everti nevykstan\u010dius pokalbius -message.close.this.chat = U\u017everti \u0161\u012f pokalb\u012f -message.conference.info.error = Nepavyko gauti informacijos apie konferencij\u0105. Pra\u0161om pabandyti v\u0117liau. -message.conference.service.error = Nepavyksta rasti konferencijos. -message.confirm.destruction.of.room = \u0160alinant kambar\u012f, bus pa\u0161alinti ir visi jame esantys abonentai. T\u0119sti? -message.confirmation.password.error = Patvirtinkite slapta\u017eod\u012f. -message.connecting.please.wait = Lukterkite, jungiamasi\u2026 -message.connection.failed = Nepavyko prisijungti prie: {0}. -message.create.account = Paskyros sukurti nepavyko. -message.create.or.join.room = Sukurti arba prisijungti prie konferencij\u0173 kambario. -message.current.status = \u010cia galima kitus informuoti apie atsijungimo prie\u017eastis. -message.default.error = \u012evyko programos klaida. Pra\u0161om apie tai angli\u0161kai prane\u0161ti adresu support@jivesoftware.com. -message.delete.all.history = Ar pa\u0161alinti visus ankstesnius pokalbius? -message.delete.confirmation = Ar tikrai norite pa\u0161alinti {0}? -message.disable.transport = Ar pa\u0161alinti prisijungimo prie {0} informacij\u0105? -message.disconnected.conflict.error = Atsijungta, nes \u0161is abonentas prisijung\u0117 kitoje tinklo vietoje. -message.disconnected.error = Sutrikus normaliam programos darbui teko atsijungti. -message.disconnected.group.chat.error = Atsijungta, nes sutriko normalus programos darbas. Po pakartotino prisijungimo, teks i\u0161 naujo apsilankyti \u0161iame kambaryje. -message.disconnected.shutdown = Atsijungta, nes ka\u017ekod\u0117l pokalbi\u0173 serveris buvo i\u0161jungtas. -message.downloading = Parsiun\u010diama {0} -message.downloading.spark.plug = Parsiun\u010diamas \u201eSpark\u201c programos priedas. -message.end.chat = Ar jau baigsite pokalb\u012f? -message.end.conversation = Ar jau baigsite \u0161i\u0105 diskusij\u0105? -message.enter.aim = \u017demiau \u012fveskite tinklo \u201eAIM\u201c abonento vard\u0105 ir slapta\u017eod\u012f. -message.enter.broadcast.message = \u012era\u0161ykite \u017eini\u0105, kuri\u0105 transliuosite pasirinktiems abonentams. -message.enter.gadugadu = \u012eveskite \u201eGaduGadu\u201c tinklo abonento vard\u0105 ir slapta\u017eod\u012f. -message.enter.gtalk = \u017demiau \u012fveskite \u201eGTalk\u201c tinklo abonento vard\u0105 ir slapta\u017eod\u012f. -message.enter.icq = \u017demiau \u012fveskite \u201eICQ\u201c tinklo abonento vard\u0105 ir slapta\u017eod\u012f. -message.enter.irc = \u017demiau \u012fveskite \u201eIRC\u201c tinklo abonento vard\u0105 ir slapta\u017eod\u012f. -message.enter.sametime = \u017demiau \u012fveskite \u201eSametime\u201c tinklo abonento vard\u0105 ir slapta\u017eod\u012f. -message.enter.facebook = \u017demiau \u012fveskite \u201eFacebook\u201c tinklo abonento vard\u0105 ir slapta\u017eod\u012f. -message.enter.myspace = \u017demiau \u012fveskite \u201eMySpace\u201c tinklo abonento vard\u0105 ir slapta\u017eod\u012f. -message.enter.jabber.id = \u012eveskite \u201eJabber\u201c tinklo identifikatori\u0173 (JID) -message.enter.message.to.broadcast = \u012eveskite \u017eini\u0105, kuri\u0105 transliuosite visam abonent\u0173 s\u0105ra\u0161ui. -message.enter.msn = \u017demiau \u012fveskite \u201eMSN\u201c tinklo abonento vard\u0105 ir slapta\u017eod\u012f. -message.enter.new.subject = \u012eveskite nauj\u0105 tem\u0105 -message.enter.qq = \u017demiau \u012fveskite \u201eQQ\u201c tinklo numer\u012f. -message.enter.room.password = \u012eveskite kambario slapta\u017eod\u012f. -message.enter.simple = \u017demiau \u012fveskite \u201eSIMPLE\u201c tinklo abonento vard\u0105 ir slapta\u017eod\u012f. -message.enter.valid.jid = \u012eveskite teising\u0105 \u201eJabber\u201c tinklo identifikatori\u0173 (JID) -message.enter.xmpp = \u017demiau \u012fveskite \u201eXMPP\u201c tinklo abonento vard\u0105 ir slapta\u017eod\u012f. -message.enter.yahoo = \u012eveskite \u201eYAHOO\u201c tinklo abonento vard\u0105 ir slapta\u017eod\u012f. -message.error.during.file.transfer = D\u0117l siuntimo klaidos bylos i\u0161si\u0173sti nepavyko. -message.file.exists.question = Byla jau egzistuoja. Ar perra\u0161yti i\u0161 naujo? -message.file.size = Bylos dydis: {0} -message.file.transfer.canceled = At\u0161auktas bylos siuntimas. -message.file.transfer.rejected = Bylos siuntimo nepatvirtino {0}. -message.file.transfer.notification = Bylos siuntimo prane\u0161imas -message.file.transfer.short.message = Jums siun\u010diamas byla, kurios pavadinimas: -message.file.transfer.chat.window = Bylos persiuntimo pra\u0161ymas: -message.file.transfer.file.too.big.error = Pasirinkta byla per didel\u0117.\nMaksimalus bylos dydis {0}. Pasirinkta byla yra {1} dyd\u017eio. -message.file.transfer.file.too.big.warning = Pasirinkta byla yra labai didel\u0117.\nT\u0119sti vis tiek? -message.find.conference.services = Konferencij\u0173 suradimas -message.forbidden.error = Serveris atsiunt\u0117 prane\u0161im\u0105 apie baisi\u0105 klaid\u0105. Tokios netoleruosime! -message.gateway.username.error = Turi b\u016bti pateiktas abonento vardas -message.gateway.password.error = Turi b\u016bti pateiktas slapta\u017eodis -message.gateway.nickname.error = Pseudonimas turi b\u016bti pateiktas -message.general.error = Praradote ry\u0161\u012f su serveriu. Problemos prie\u017eastis: {0}. -message.generic.reconnect.message = Praradote ry\u0161\u012f su serveriu. Spragtelkite \u017eemiau esant\u012f mygtuk\u0105 \u201ePrisijungti i\u0161 naujo\u201c -message.idle.for = Neaktyvu jau {0} -message.image.too.large = Paveikslo byla per didel\u0117. Paveiksl\u0117lis tur\u0117t\u0173 b\u016bti ne didesnis kaip 16k. -message.invalid.jabber.id = Netinkamas Jabber ID. -message.invalid.jid.error = Nurodytas identifikatorius JID yra neteisingas. -message.invalid.status = Nurodykite teising\u0105 b\u016bsen\u0105. -message.invalid.username.password = Netinkamas slapta\u017eodis arba abonento vardas. -message.invite.users.to.conference = Pakvieskite \u012f konferencij\u0173 kambar\u012f ir kitus (nurodysite kvie\u010diamojo JID arba pasirinksite j\u012f s\u0105ra\u0161e). -message.is.shared.group = {0} yra bendrinama grup\u0117. -message.is.typing.a.message = {0} ra\u0161o\u2026 -message.join.conference.room = Prisijungti prie konferencij\u0173 kambario -message.kicked.error = J\u016bs negalite i\u0161pra\u0161yti {0} i\u0161 kambario. -message.last.message.received = Paskiausia \u017einut\u0117 gauta nuo {0} -message.loading.please.wait = Kraunama. Pra\u0161om lukterti\u2026 -message.locked.workstation = Abonentas u\u017erakino savo kompiuter\u012f. -message.name.of.group = Grup\u0117s vardas -message.name.of.search.service.question = Koks paie\u0161kos tarnybos vardas? -message.negotiate.file.transfer = Vyksta derybos d\u0117l bylos persiuntimo. Pra\u0161ome palaukti... -message.negotiate.stream = Vyksta derybos d\u0117l jung\u010di\u0173 sraut\u0173. Pra\u0161ome palaukti... -message.negotiation.file.transfer = Deramasi d\u0117l bylos persiuntimo su {0}. Pra\u0161ome palaukti... -message.new.message = Nauja \u017einut\u0117 nuo {0}. -message.new.spark.available = {0} pasiekiamas. Ar pageidausite \u012fdiegti? -message.nickname.in.use = \u0160is pseudonimas jau naudojamas. Susigalvokite kit\u0105. -message.nickname.not.acceptable = N\u0117ra \u0105jungta galimyb\u0117 keisti pseudonimus! -message.no.avatar.found = Pseudoportretas dar nenurodytas. -message.no.caller.id = N\u0117ra skambintojo identifikatoriaus. -message.no.description.available = Be apra\u0161ymo. -message.no.history.found = \u0160iam abonentui n\u0117ra pokalbi\u0173 \u017eurnalo. -message.no.results.found = Apie paie\u0161kos rezultatus serveris informacijos nepateik\u0117. -message.no.room.to.join.error = N\u0117ra kambario, kur b\u016bt\u0173 galima prisijungti. -message.no.subject.available = Be temos -message.no.updates = Atnaujinim\u0173 n\u0117ra -message.normal = \u012eprastas prane\u0161imas -message.number.to.call = Nurodykite numer\u012f skambinimui. -message.offline = \u017dinut\u0117s gav\u0117jas atsijung\u0119s. \u017dinut\u0119 jis gaus, kai prisijungs. -message.offline.error = N\u0117ra galimyb\u0117s gauti \u017einu\u010di\u0173 atsijungus. -message.participants.in.room = Pokalbi\u0173 kambario lankytojai -message.password.error = Nurodykite \u0161ios paskyros slapta\u017eod\u012f. -message.password.private.room.error = Nurodykite privataus kambario slapta\u017eod\u012f. -message.passwords.no.match = Nesutapo slapta\u017eod\u017eiai. -message.please.join.in.conference = Kvie\u010diame apsilankyti ir dalyvauti naujai sukurtame pokalbi\u0173 kambaryje. -message.plugins.not.available = Nepavyksta prisijungti prie pried\u0173 saugyklos. -message.prompt.plugin.uninstall = Ar tikrai norite i\u0161jungti pried\u0105 {0}? -message.received.file = Gavote bylas, Siunt\u0117jas {0}. -message.receiving.file = Gaunate bylas. Siunt\u0117jas {0} -message.reconnect.attempting = Bandom jungtis i\u0161 naujo\u2026 -message.reconnect.failed = Pakartotinai prisijungti nepavyko. -message.reconnect.wait = V\u0117l jungsim\u0117s po {0} sek. -message.register.transports = Registruotis ry\u0161io kanaluose. -message.registering = Registruojamasi \u012f {0}. Lukterkite\u2026 -message.registration.transport.failed = Nepavyko prisijungti prie ry\u0161io kanalo. -message.restart.spark = Naujos versijos \u012fdiegimui reikia i\u0161jungti program\u0105.\n Ar i\u0161jungti? -message.restart.spark.changes = Priedas galutinai bus pa\u0161alintas kit\u0105 kart\u0105 startuojant \u201eSpark\u201c program\u0105. -message.restart.spark.to.install = Naujausios versijos \u012fdiegimui reik\u0117s i\u0161jungti program\u0105. I\u0161jungti dabar? -message.restart.required = Kad pakeitimai \u012fsigaliot\u0173, reikia startuoti program\u0105 i\u0161 naujo. Startuoti i\u0161 naujo dabar? -message.room.creation.error = Kambario sukurti nepavyko. -message.room.destroyed = Kambarys pa\u0161alintas. Prie\u017eastis: {0} -message.room.destruction.reason = Kokia kambario pa\u0161alinimo prie\u017eastis? -message.room.information.for = Informacija apie kambar\u012f {0} -message.save.profile = Paspaud\u0119 mygtuk\u0105 \u201e\u012era\u0161yti\u201c i\u0161saugosite atliktus pakeitimus. -message.search.for.contacts = Pokalbio partneri\u0173 paie\u0161ka. -message.search.for.other.people = Kit\u0173 \u017emoni\u0173 paie\u0161ka serveryje -message.search.service.not.available = Nepavyksta prisijungti prie paie\u0161kos tarnybos. -message.searching.please.wait = Ie\u0161koma. Lukterkite\u2026 -message.select.add.room.to.add = Pasirinkite kambar\u012f, kur\u012f pageidausite \u012ftraukti \u012f paie\u0161kos tarnybos s\u0105ra\u0161us. -message.select.one.or.more = Pasirinkite vien\u0105 ar kelis abonentus. -message.select.room.to.enter = Nurodykite kambar\u012f, kuriame lankysit\u0117s. -message.select.room.to.join = Pasirinkite kambar\u012f, \u012f kurio pokalbius jungsit\u0117s. -message.send.a.broadcast = Transliuoti \u017eini\u0105 -message.send.file.to.user = Si\u0173sti abonentui byl\u0105 -message.send.picture = Si\u0173sti ekrano vaizd\u0105 -message.send.to.these.people = Transliuojamo prane\u0161imo gav\u0117j\u0173 parinkimas -message.sending.file.to = Bylos siuntimas adresatams {0}. -message.sent.offline.files = I\u0161siunt\u0117te byl\u0105(as) atsijungus. -message.server.unavailable = Nepavyksta prisijungti prie serverio. Gal neteisingas serverio vardas arba jis dabar yra nepasiekiamas. -message.service.already.exists = Paslauga jau yra. -message.shared.group = Bendrinta grup\u0117 -message.spark.secure = Saugioji \u201eSpark\u201c veiksena. -message.specify.contact.jid = Pra\u0161om nurodyti abonento \u201eJID\u201c (pvz. vardenis@jabber.org). -message.specify.group = Nurodykite adres\u0173 grup\u0119, \u012f kuri\u0105 \u012ftrauksim nauj\u0105 abonent\u0105. -message.specify.information.for.conference = Nurodykite informacij\u0105 apie konferencij\u0173 kambar\u012f. -message.specify.name.error = Nurodykite teising\u0105 vard\u0105. -message.specify.users.to.join.conference = Nurodykite abonentus, kurie jungsis \u012f konferencij\u0173 kambar\u012f. -message.specify.valid.time.error = Teisingai nurodykite laukimo laik\u0105 ir prievad\u0105. -message.subject.change.error = Jums neleid\u017eiama keisti \u0161io kambario pokalbi\u0173 temos. -message.subject.has.been.changed.to = Tema pakeista \u012f {0}. -message.supply.resource = Reikia pateikti teising\u0105 resurs\u0105. -message.supply.valid.port = Pateikti teising\u0105 prievad\u0105. -message.supply.valid.timeout = Pateikti teising\u0105 laukimo laiko reik\u0161m\u0119. -message.timeout.error = Laukimo laikas tur\u0117t\u0173 b\u016bti bent 5 sek. arba ilgesnis. -message.total.downloaded = Parsi\u0173stos bylos -message.transfer.cancelled = Bylos siuntimas at\u0161auktas. -message.transfer.complete = Bylos siuntimas u\u017ebaigtas ({0}) -message.transfer.progressbar.text.received = {0} gauta @ {1} {2} -message.transfer.progressbar.text.sent = {0} i\u0161si\u0173sta @ {1} {2} -message.transfer.rate = Siuntimo sparta -message.transfer.refused = Bylos siuntimas buvo atmestas. -message.transfer.waiting.on.user = Laukiama kol {0} patvirtins bylos siuntim\u0105. -message.unable.to.load.profile = Nepavyko rasti profilio {0} vietos. -message.unable.to.retrieve.last.activity = Nepavyko rasti profilio {0}. -message.unable.to.save.password = Nepavyko pasikeisti slapta\u017eod\u017eio. Galb\u016bt to neleid\u017eia administratorius. -message.unable.to.send.file = Jums nepavyko nusi\u0173sti bylos gav\u0117jui {0}. -message.unrecoverable.error = Neteisingas abonento vardas arba slapta\u017eodis. -message.update.room.list = Kambari\u0173 s\u0105ra\u0161o atnaujinimas. -message.updating.cancelled = Atnaujinimas at\u0161auktas. -message.user.banned = {0} \u0161iame kambaryje buvo u\u017edraustas. -message.user.given.voice = {0} gavo galimyb\u0119 \u0161iame kambaryje kalb\u0117ti. -message.user.granted.admin = {0} gavo administravimo privilegijas. -message.user.granted.membership = {0} gavo eilinio nario privilegijas. -message.user.granted.moderator = {0} gavo pri\u017ei\u016br\u0117tojo privilegijas. -message.user.granted.owner = {0} gavo savininko privilegijas. -message.user.is.sending.you.a.file = {0} Jums siun\u010dia byl\u0105. -message.user.joined.room = {0} apsilank\u0117 kambaryje. -message.user.kicked.from.room = {0} buvo i\u0161mestas i\u0161 kambario. -message.user.left.room = {0} i\u0161\u0117jo i\u0161 kambario. -message.user.nickname.changed = {0} dabar bus \u017einomas kaip {1}. -message.user.now.available.to.chat = {0} prisijung\u0117 {1} -message.user.revoked.admin = Administratoriaus privilegijos at\u0161auktos abonentui {0}. -message.user.revoked.membership = Naryst\u0117s privilegijos at\u0161auktos abonentui {0}. -message.user.revoked.moderator = Pri\u017ei\u016br\u0117tojo privilegijos at\u0161auktos abonentui {0}. -message.user.revoked.owner = Savininko privilegijos at\u0161auktos abonentui {0}. -message.user.voice.revoked = Atimtas balsas i\u0161 {0}. -message.username.error = Nurodykite abonento vard\u0105 ir slapta\u017eod\u012f. -message.username.password.error = Turi b\u016bti pateiktas abonento vardas ir/arba slapta\u017eodis. -message.vcard.not.supported = Serveris nepalaiko \u201eVCards\u201c vizitini\u0173 korteli\u0173. Tokios kortel\u0117s \u012fra\u0161yti nepavyko. -message.version = Versija: {0} -message.view.information.about.this.user = Informacija apie abonent\u0105 -message.waiting.for.user.to.join = Laukiama kol {0} prisijungs. -message.went.offline = {0} atsijung\u0117 {1} -message.you.have.been.banned = J\u016bs esate nepageidaujamas \u0161iame kambaryje. \u010cia Jums dalyvauti neleista. -message.you.have.been.kicked = Nepykite, bet i\u0161 \u0161io kambario esate i\u0161mestas. -message.you.have.sent = I\u0161siunt\u0117te byl\u0105 adresatui {0}. -message.your.admin.granted = Jums suteiktos administratoriaus privilegijos. -message.your.banned = \u0160iame kambaryje jums dalyvauti u\u017edrausta. -message.your.kicked = Jus i\u0161met\u0117 {0}. -message.your.membership.granted = Jums suteiktos naryst\u0117s privilegijos. -message.your.membership.revoked = J\u016bs\u0173 naryst\u0117 at\u0161aukta. -message.your.moderator.granted = Jums suteiktos pri\u017ei\u016br\u0117tojo privilegijos. -message.your.moderator.revoked = Netekote pri\u017ei\u016br\u0117tojo privilegij\u0173. -message.your.ownership.granted = Jums suteiktos savininko privilegijos. -message.your.ownership.revoked = Netekote savininko privilegij\u0173. -message.your.revoked.granted = Netekote administratoriaus privilegij\u0173. -message.your.voice.granted = \u0160iame pokalbyje Jums suteiktas balsas. -message.your.voice.revoked = Netekote balso. -message.groupchat.require.password = \u0160i pokalbi\u0173 grup\u0117 priims, jei \u012fvesite slapta\u017eod\u012f. -message.groupchat.registered.member = S\u0117kmingai prisiregistravote prie {0} -message.search.for.history = Ie\u0161koti pokalbio \u017eurnale - -status.away = Pasitrauk\u0119s -status.custom.messages = Susikurtos b\u016bsenos -status.do.not.disturb = Netrukdykite -status.extended.away = I\u0161vyk\u0119s -status.free.to.chat = Mielai pasikalb\u0117siu -status.on.phone = Kalbu telefonu -status.online = Prisijung\u0119s -status.pending = Laukiama -status.invisible = Nematomas -status.offline = Atsijung\u0119s - -tab.available.plugins = Galimi priedai -tab.avatar = Pseudoportretas -tab.business = Darboviet\u0117 -tab.conferences = Konferencijos -tab.contacts = Adresin\u0117 -tab.general = Bendra -tab.home = Namai -tab.installed.plugins = \u012ediegti priedai -tab.deactivated.plugins = I\u0161jungti priedai -tab.personal = Asmuo -tab.proxy = Tarpinis serveris -tab.sso = SSO -tab.pki = PKI - -title.about = Apie -title.password.required = Reikalingas slapta\u017eodis -title.task.notification = Prane\u0161imas apie u\u017eduot\u012f -title.client.logs = \u017durnalo \u012fra\u0161ai -title.advanced.connection.preferences = P&risijungimo nuostatos i\u0161samiau -title.account.create.registration = Paskyros registravimas -title.bookmarks = \u017dymos -title.account.created = Paskyra s\u0117kmingai sukurta -title.add.contact = Prid\u0117ti adresat\u0105 -title.add.contact.group = Adresat\u0173 grup\u0117s prid\u0117jimas -title.add.new.group = Naujos grup\u0117s prid\u0117jimas -title.add.search.service = Paie\u0161kos tarnybos prid\u0117jimas -title.add.to.roster = \u012etraukti \u012f s\u0105ra\u0161\u0105 -title.address = Adresas -title.advanced.connection.usesso = Naudoti Single Sign-On (SSO) via GSSAPI -title.advanced.connection.sso.account = Prisijungimui prie serverio bus panaudota vartotojo paskyra "{0}" -title.advanced.connection.sso.unable = Nepavyko prisijungti naudojant Single Sign-On. Pra\u0161ome patikrinti prisijungimo duomenis ir serverio nustatymus. -title.advanced.connection.sso.noprincipal = Spark negali rasti tinkamos paskyros prisijungimui su Single Sign-On. Tai neleis naudotis SSO. -title.alert = Prane\u0161imas -title.appearance = I\u0161vaizda -title.appearance.preferences = Adaptavimas -title.available.transports = Galimi ry\u0161io kanalai -title.broadcast.message = Transliuoti \u017eini\u0105 -title.browse.conference.services = Konferencij\u0173 per\u017ei\u016bra -title.browse.room.service = Pokalbi\u0173 kambari\u0173 per\u017ei\u016bra - {0} -title.cancelled = At\u0161aukta -title.change.nickname = Pseudonimo pakeitimas -title.change.subject = Temos pakeitimas -title.chat = Pokalbis -title.choose.directory = Katalogo pasirinkimas -title.choose.incoming.sound = \u017dinut\u0117s gavimo ar prisijungimo garsinio signalo parinkimas -title.choose.offline.sound = Atsijungimo garsinio signalo parinkimas -title.choose.outgoing.sound = \u017dinut\u0117s i\u0161siuntimo garsinio signalo parinkimas -title.conference.invitation = Pakvietimas \u012f konferencij\u0105 -title.conference.rooms = Konferencij\u0173 kambariai -title.configure.chat.room = Pokalbi\u0173 kambario konfig\u016bravimas -title.configure.room = Konfig\u016bruoti kambar\u012f -title.confirmation = Patvirtinimas -title.create.new.account = Naujos paskyros suk\u016brimas -title.create.or.bookmark.room = Prisijungti prie konferencijos arba pasi\u017eym\u0117ti kambar\u012f -title.create.or.join = Sukurti/Prisijungti -title.create.problem = Paskyros suk\u016brimo problema -title.delete.file = Ar tikrai norite pa\u0161alinti \u0161i\u0105 byl\u0105? -title.dial.phone = Skambinti VOIP telefonu -title.disable.transport = Prisijungimo kanalo informacijos pa\u0161alinimas -title.download.complete = Parsiuntimas baigtas -title.downloading.im.client = Parsisi\u0173sti trump\u0173j\u0173 \u017einu\u010di\u0173 \u201eIM\u201c kliento program\u0105 -title.downloads = Parsi\u0173sta -title.edit.custom.message = Susikurt\u0173 b\u016bsen\u0173 redagavimas -title.edit.profile = Profilio informacijos redagavimas -title.enter.reason = Prie\u017easties \u012fvedimas -title.error = Klaida -title.error.couldnt.open.file = Nepavyko atverti bylos! Patikrinkite ar teisingas bylos tipas. -title.error.delete.file = Nepavyko pa\u0161alinti bylos! -title.error.find.app = Nepavyko rasti tinkamos programos! -title.error.rename.file = Nepavyko pakeisti bylos vardo! -title.file = Byla -title.filesize = Dydis -title.file.exists = Byla jau egzistuoja -title.file.transfer = Byl\u0173 siuntimas -title.file.transfer.preferences = Byl\u0173 siuntimo nuostatos -title.find.conference.service = Ie\u0161koti konferencij\u0173 -title.find.contacts = Ie\u0161koti abonent\u0173 -title.gadugadu.registration = \u201eGaduGadu\u201c paskyros kredencialai -title.general.media = Medijos nuostatos -title.general.chat.settings = Bendrosios pokalbi\u0173 nuostatos -title.group.chat = Grupiniai pokalbiai -title.group.chat.settings = Grupini\u0173 pokalbi\u0173 nuostatos -title.gtalk.registration = GTalk paskyros kredencialai -title.history.for = Pokalbio su {0} \u017eurnalas -title.icq.registration = ICQ paskyros kredencialai -title.irc.registration = IRC paskyros kredencialai -title.aim.registration = AIM paskyros kredencialai -title.sametime.registration = Sametime paskyros kredencialai -title.facebook.registration = Facebook paskyros kredencialai -title.myspace.registration = MySpace paskyros kredencialai -title.incoming.call = Skambutis -title.input.fileexplorer = \u012eveskite byl\u0173 nar\u0161ykl\u0117s vard\u0105: -title.input.newname = Pra\u0161om \u012fvesti nauj\u0105 vard\u0105: -title.input.openwith = Nurodykite programos, kuri\u0105 naudosite vard\u0105: -title.invite.to.conference = Pakviesti \u012f konferencij\u0105 -title.jabber.browser = Nar\u0161ykl\u0117 -title.join.conference.room = Prisijungti prie konferencij\u0173 -title.last.activity = Paskiausi veiksmai -title.login = Prisijungimas -title.login.error = Prisijungimo klaida -title.login.settings = Prisij&ungimo nuostatos -title.login.no.account = Nepavyksta nustatyti -title.lookup.profile = Ie\u0161koti profilio -title.msn.registration = MSN paskyros kredencialai -title.name = Vardas -title.new.client.available = Galimas naujas klientas -title.new.roster.group = Nauja viso s\u0105ra\u0161o grup\u0117 -title.new.version.available = Galima nauja versija -title.no.updates = Atnaujinim\u0173 n\u0117ra -title.notes = U\u017era\u0161ai -title.notification = Prane\u0161imas -title.notifications = Prane\u0161imai -title.occupants = Lankytoj\u0173 sk. -title.on.the.phone = Kalba telefonu -title.password = Slapta\u017eodis -title.passwords.no.match = Slapta\u017eod\u017eio patvirtinimas -title.person.search = Asmens paie\u0161ka -title.plugins = Priedai -title.preferences = Nuostatos -title.profile.information = Profilio informacija -title.profile.not.found = Profilis nerastas -title.qq.registration = QQ paskyros kredencialai -title.register.account = Naujos paskyros registravimas -title.registration.error = Registracijos klaida -title.reminder = Priminimas -title.rename.roster.group = Keisti s\u0105ra\u0161o grup\u0117s vard\u0105 -title.room.destroyed = Kambarys pa\u0161alintas -title.room.information = Informacija apie kambar\u012f -title.roster = Visi abonentai -title.select.file.to.send = Bylos(\u0173) siuntimui parinkimas -title.set.status.message = Si\u0173sti b\u016bsenos \u017eini\u0105 -title.simple.registration = SIMPLE paskyros kredencialai -title.sound.preferences = Gars\u0173 nuostatos -title.sounds = Garsai -title.spark.preferences = \u201eSpark\u201c programos nuostatos -title.start.chat = Prad\u0117ti pokalb\u012f -title.status.message = Informacija apie b\u016bsen\u0105 -title.tasks = U\u017eduotys -title.transports = Ry\u0161io kanalai -title.tray.information = Informacija sistemin\u0117je eilut\u0117je -title.upgrading.client = Programos atnaujinimas -title.version.and.time = Versija ir laikas -title.view.bookmarks = Parodyti \u017eymas -title.view.profile.for = Profilis {0} -title.view.room.information = Informacija apie kambar\u012f -title.waiting.to.call = Laukiama skambu\u010dio -title.xmpp.registration = XMPP paskyros kredencialai -title.yahoo.registration = Yahoo paskyros kredencialai -title.appearance.showVCards = Vizitini\u0173 korteli\u0173 \u201eVCards\u201c rodymas adresat\u0173 s\u0105ra\u0161e -title.subscription.request = Prenumeratos pra\u0161ymas - -tooltip.place.a.call = Skambinimas asmeniui VOIP telefonu -tooltip.appearance = Pokalbi\u0173 aplinkos i\u0161vaizdos keitimas -tooltip.file.transfer = Byl\u0173 siuntimo nuostatos -tooltip.notifications = Prane\u0161im\u0173 apie \u017einutes nuostatos -tooltip.place.voice.call = Skambinti asmeniui VOIP telefonu -tooltip.send.email = Si\u0173sti el. lai\u0161k\u0105 -tooltip.start.chat = Prad\u0117ti pokalb\u012f -tooltip.view.changelog = Per\u017ei\u016br\u0117ti pakeitim\u0173 \u017eurnal\u0105 -tooltip.view.history = Per\u017ei\u016br\u0117ti pokalbi\u0173 \u017eurnal\u0105 -tooltip.view.readme = Skaityti \u201eReadMe\u201c byl\u0105 - -tree.conference.services = Konferencijos -tree.users.in.room = Kambaryje apsilank\u0119 - -lookandfeel.select = Pasirinkti programos i\u0161vaizd\u0105 -lookandfeel.change.now = Pakeisti dabar -lookandfeel.tooltip.restart.no = Programos perkrovimas nereikalingas -lookandfeel.tooltip.restart.yes = Kad \u012fjungti programos sistemin\u0119 i\u0161vaizd\u0105, paspauskite \u012era\u0161yti ir perkraukite Spark -lookandfeel.color.label = Spalvos -lookandfeel.color.red = Raudona -lookandfeel.color.green = \u017Dalia -lookandfeel.color.blue = M\u0117lyna -lookandfeel.color.opacity = Nepermatomumas -lookandfeel.color.saved = Spalva i\u0161saugota - - -##Settings for the privacy plugin -privacy.title.preferences = Sparko privatumo nustatymai -privacy.title.panel = Pra\u0161ome naudoti de\u0161in\u012f pel\u0117s mygtuk\u0105 -privacy.label.iq.desc = U\u017eklausa -privacy.label.pin.desc = Gaunama b\u016bsena -privacy.label.pout.desc = Siun\u010diama b\u016bsena -privacy.label.msg.desc = \u017Dinut\u0117s -privacy.border.information = Privatumo informacija -privacy.label.information = Naudokite de\u0161inio paspaudimo meniu, kad prid\u0117ti ar i\u0161trinti s\u0105ra\u0161us ar punktus -privacy.root.node = Privatumo s\u0105ra\u0161ai -privacy.label.preferences = Privatumo \u012fskiepis -pricacy.tooltip.preferences = Sparko privatumo nustatymai -privacy.label.list.is.active = AKTYVUS -privacy.label.list.is.default = NUMATYTASIS -privacy.border.block = Blokuoti -privacy.pick.one.or.more = Pasirinkite vien\u0105 ar daugiau punkt\u0173, kad prid\u0117ti \u012f s\u0105ra\u0161\u0105 -privacy.title.add.picker = Prid\u0117ti punktus \u012f s\u0105ra\u0161\u0105 -privacy.node.contacts = Adresatai -privacy.node.groups = Grup\u0117s -privacy.menu.add.contacts = Prid\u0117ti adresat\u0105 \u012f s\u0105ra\u0161\u0105 -privacy.menu.add.groups = Prid\u0117ti grup\u0119 \u012f s\u0105ra\u0161\u0105 -privacy.menu.add.rem.items = I\u0161trinti {0} punktus i\u0161 s\u0105ra\u0161o -privacy.menu.remove = I\u0161trinti -privacy.menu.activate.list = Aktyvuoti -privacy.menu.default.list = Nustatyti kaip numatyt\u0105j\u012f -privacy.menu.add.list = Prid\u0117ti s\u0105ra\u0161\u0105 -privacy.menu.remove.list = I\u0161trinti s\u0105ra\u0161\u0105 -privacy.dialog.add.list = Pra\u0161me nurodyti s\u0105ra\u0161o vard\u0105 -privacy.dialog.rem.list = Ar tikrai norite i\u0161trinti {0}? -privacy.status.menu.entry = Privatumo s\u0105ra\u0161ai -privacy.name.for.default.list = Numatytasis -privacy.button.no.list.selected = Nepasirinktas s\u0105ra\u0161as -privacy.menuitem.deactivate.current.list = Deaktyvuoti {0} -privacy.label.not.supported = Privatumo s\u0105ra\u0161ai nepalaikomi serverio - -##Stunfallback in media settings -stun.border.label = STUN pagalbinis serveris -stun.server.addr = Stun serveris: -stun.server.port = Stun prievadas: - -#!# diff --git a/src/resources/i18n/spark_i18n_nl.properties b/src/resources/i18n/spark_i18n_nl.properties deleted file mode 100644 index b18cee450..000000000 --- a/src/resources/i18n/spark_i18n_nl.properties +++ /dev/null @@ -1,663 +0,0 @@ -## -## Spark Resource Bundle -## -## Dutch -## R. van Zantvoort, August 2007 -## -## Current version: 1.3.2 -## -##(build 9054 synced) with my proposed additions -## - - -accept = Accepteer -active = Actief -add = Toevoegen -answer = Beantwoorden -available = Beschikbaar -broadcast = Bericht rondsturen -cancel = Annuleren -close = Sluiten -create = Aanmaken -date = Datum -description = Beschrijving -from = Van -invite = Uitnodigen -join = Binnengaan -no = Nee -not.registered = Niet geregistreerd -occupants = Aanwezigen -offline = Afgemeld -ok = OK -online = aangemeld -open = Openen -open.folder = Open Map -participants = Deelnemers -reject = Afwijzen -retry = Opnieuw -room.name = Naam ruimte -save = Opslaan -subject = Onderwerp -unfiled = Niet gegroepeerd -use.default = Standaardinstellingen -user.has.signed.in = heeft zich aangemeld. -user.has.signed.off = heeft zich afgemeld. -while.offline = Tijdens afwezigheid -yes = Ja - -action.clear = Legen -action.copy = Kopi\u0091ren -action.cut = Knippen -action.paste = Plakken -action.print = Afdrukken -action.save = Opslaan -action.select.all = Alles selecteren - -button.accept = &Accepteren -button.add = &Toevoegen -button.add2 = Toe&voegen -button.add.a.contact = &Contact toevoegen... -button.add.bookmark = Bladwijzer toevoegen -button.add.service = &Dienst toevoegen -button.add.user = &Gebruiker toevoegen -button.advanced = Gea&vanceerd -button.approve = &Toestaan -button.bookmark.room = &Bladwijzer van deze ruimte maken -button.browse = &Bladeren... -button.browse2 = Blade&ren... -button.browse3 = Blad&eren... -button.cancel = &Annuleren -button.clear = &Legen -button.close = S&luiten -button.copy.to.clipboard = Naar Klembord kopi\u0091ren -button.create.account = &Account aanmaken -button.create.room = &Maak of ga naar ruimte -button.decline = &Weigeren -button.deny = &Weigeren -button.dial.number = &Nummer bellen -button.find = &Zoeken -button.join = &Meedoen -button.join.room = Ruimte &binnengaan -button.new = &Nieuw -button.profile = &Profiel -button.quit = &Afsluiten -button.reconnect = &Opnieuw -button.reconnect2 = Opnieuw verbinden -button.refresh = &Vernieuwen -button.register = &Registreer -button.remove.bookmark = Bladwijzer verwijderen -button.roster = &Contactlijst -button.save = Op&slaan -button.save.for.future.use = &Opslaan voor later gebruik -button.search = &Zoeken -button.send = &Zend -button.send.email = E-mail -button.start.chat = Conversatie -button.tasks.active = Lopende -button.tasks.all = Alle -button.update = &Bijwerken -button.view.notes = Notitieblok -button.view.profile = Bekijk volledig profiel -button.view.tasklist = Bekijk taaklijst - -checkbox.allow.buzz = Sta buz&zen toe -checkbox.auto.discover.port = Ontdek server en poort &automatisch -checkbox.auto.login = &Automatisch aanmelden -checkbox.disable.chat.history = &Opslag van conversaties uitschakelen -checkbox.enable.emoticons = Em&oticons aan -checkbox.idle.enabled = &Automatisch afwezigheid detecteren -checkbox.launch.on.startup = Start bij &opstarten -checkbox.notify.user.comes.online = Melding als een gebruiker zich aanmeldt -checkbox.notify.user.goes.offline = Melding als een gebruiker zich afmeldt -checkbox.permanent = &Permanente ruimte -checkbox.play.sound.on.invitation = Geluid bij &ontvangen uitnodiging -checkbox.play.sound.on.new.message = Geluid bij &nieuw bericht -checkbox.play.sound.on.outgoing.message = Geluid bij &verzenden bericht -checkbox.play.sound.when.offline = Geluid bij &afmelden gebruiker -checkbox.private.room = P&riv\u00e9ruimte -checkbox.save.password = Wachtwoord &opslaan -checkbox.show.avatars.in.contactlist = Toon &Avatars in Contactlijst -checkbox.show.notifications.in.conference = Toon &meldingen in ruimtes -checkbox.show.time.in.chat.window = Toon &tijd in venster -checkbox.show.toaster = Toon een &toast popup -checkbox.split.chat.window = Combineer &Vensters (Vereist herstart van Spark) -checkbox.start.in.tray = Start in &systeemvak -checkbox.use.system.look.and.feel = Gebruik de systeeminstellingen (Na herstart van Spark) -checkbox.tabs.on.top = &Conversatie tabs altijd vooraan (Herstart vereist) -checkbox.use.compression = Gebruik &Compressie -checkbox.use.proxy.server = Proxy &server gebruiken -checkbox.window.to.front = &Breng venster naar voren - -group.chat.window.information = Conversatievenster informatie -group.comma.delimited = Komma-gescheiden -group.conferences.found = Conferentiediensten -group.connection = Verbinding -group.empty = Er zijn geen aangemelde gebruikers in deze groep. -group.general.information = Algemene informatie -group.login.information = Aanmeldingsinformatie -group.notification.options = Meldingsvoorkeuren -group.offline = Niet aangemeld -group.search.form = Zoekformulier -group.search.results = Zoekresultaten - -label.accounts = A&ccounts -label.add.conference.service = &Conferentiedienst toevoegen -label.add.jid = &JID toevoegen -label.add.task = Taak toevoegen -label.auto.login = &Automatisch aanmelden -label.available.users.in.roster = &Beschikbare gebruikers in contactlijst -label.cancel = Annuleer -label.change.password.to = &Verander wachtwoord -label.chatroom.fontsize = Chat &Ruimte lettergrootte: -label.city = P&laats -label.close = S&luiten -label.company = &Bedrijf -label.confirm.password = &Bevestig wachtwoord -label.conflict.error = Aanmelden niet mogelijk omdat de account reeds is aangemeld. -label.contact.to.find = Zoek contact -label.contactlist.fontsize = Contact &Lijst lettergrootte: -label.country = &Land -label.create.account = Maak &account aan -label.department = &Afdeling -label.dial = &Bellen -label.due = Verloopt -label.email.address = &Email adres -label.emoticons = &Emoticons -label.enter.address = Geef adres op -label.enter.group.name = Geef nieuwe groepnaam op -label.fax = &Fax -label.find = &Zoeken -label.first.name = &Voornaam -label.group = &Groep -label.host = &Host -label.invited.users = Uitgenodigde gebruikers -label.jabber.address = &Jabber adres -label.jabber.id = &Jabber ID -label.jid = &JID -label.job.title = &Functie -label.last.name = &Achternaam -label.local.time = &Lokale tijd -label.message.style = &Bericht opmaak -label.middle.name = Verdere &namen -label.minutes.before.stale.chat = &Minuten voor een inactieve ruimte bevriest -label.mobile = &Mobiel -label.name = &Naam -label.new.nickname = Nieuwe alias -label.nickname = A&lias -label.network = Netwer&k -label.number = &Nummer -label.ok = OK -label.old.ssl = Gebruik OUDE &SSL poort methode -label.os = &Besturingssysteem -label.pager = Pa&ger -label.password = &Wachtwoord -label.phone = &Telefoon -label.port = &Poort -label.postal.code = &Postcode -label.presence = &Aanwezigheid -label.priority = &Prioriteit -label.protocol = P&rotocol -label.received = &Ontvangen -label.rename.to = Hernoemen naar -label.resource = &Medium -label.response.timeout = Maximale antwoord&tijd (sec) -label.room = &Ruimte -label.room.name = &Naam ruimte -label.room.topic= &Onderwerp -label.search.service = &Zoek dienst -label.server = &Server -label.server.address = &Server adres -label.show = Toon: -label.software = &Software -label.state.and.province = Staat/P&rovincie -label.street.address = &Straatnaam -label.time = Tijd: {0} -label.time.till.idle = &Tijd tot automatisch afwezig (min): -label.timeformat = Invoeren als {0} -label.transfer.download.directory = &Download map: -label.transfer.timeout = &Maximale overdrachttijd (min): -label.unable.to.add.contact = Persoon toevoegen mislukt. -label.use.default = Standaardinstellingen -label.user.on.public.network = Gebruiker is op een publiek netwerk -label.username = Gebruikers&naam -label.version = &Versie -label.web.page = &Webpagina -label.xmpp.port = &XMPP poort - -menuitem.about = Over -menuitem.actions = Acties -menuitem.add = Toevoegen -menuitem.add.as.contact = Voeg als contact toe -menuitem.add.contact = Contact toevoegen -menuitem.add.contact.group = Contactgroep toevoegen -menuitem.alert.when.online = Melding wanneer gebruiker beschikbaar is -menuitem.ban = Verbannen -menuitem.ban.user = Verban gebruiker -menuitem.block.user = Blokkeer gebruiker -menuitem.broadcast.to.group = Bericht aan hele groep versturen -menuitem.browse.service = In dienst bladeren -menuitem.change.nickname = Verander alias -menuitem.change.subject = Onderwerp veranderen -menuitem.chat = Conversatie -menuitem.check.for.updates = Controleer op updates -menuitem.contacts = Contacten -menuitem.dial = Bellen -menuitem.delete = Verwijderen -menuitem.delete.login.information = Verwijder aanmeldingsinformatie -menuitem.destroy.room = Ruimte opheffen -menuitem.edit = Bewerken -menuitem.edit.my.profile = Mijn profiel &bewerken... -menuitem.edit.status.message = Eigen statusmeldingen bewerken... -menuitem.enter.login.information = Geef aanmeldingsinformatie -menuitem.exit = Afsluiten -menuitem.grant.moderator = Maak moderator -menuitem.grant.voice = Geef stemrecht -menuitem.help = Help -menuitem.hide = Verbergen -menuitem.invite.group.to.conference = Groep voor conferentie uitnodigen -menuitem.invite.users = Gebruikers uitnodigen -menuitem.join.on.startup = Meedoen bij opstarten -menuitem.join.room = Ruimte binnengaan -menuitem.kick.user = Verwijder gebruiker -menuitem.languages = Talen -menuitem.logout.no.status = Afmelden -menuitem.logout.with.status = Afmelden met reden... -menuitem.lookup.profile = Profiel &opzoeken -menuitem.copy.to = Kopi\u0091ren naar -menuitem.move.to = Verplaatsen naar -menuitem.online.help = Spark Fora -menuitem.open = Openen -menuitem.plugins = &Plugins... -menuitem.preferences = Voorkeuren... -menuitem.remove = Verwijder -menuitem.remove.alert.when.online = Verwijder waarschuwing -menuitem.remove.bookmark = Bladwijzer verwijderen -menuitem.remove.from.group = Uit groep verwijderen -menuitem.remove.from.roster = Uit Rooster Verwijderen -menuitem.remove.service = Dienst verwijderen -menuitem.rename = Hernoemen -menuitem.revoke.moderator = Geen moderator meer -menuitem.revoke.voice = Trek stemrecht in -menuitem.save = Opslaan -menuitem.save.as = Opslaan als... -menuitem.send.a.file = Bestand versturen -menuitem.send.a.message = Bericht versturen aan geselecteerde gebruikers... -menuitem.set.status.message = Statusmelding instellen... -menuitem.show.empty.groups = Lege groepen tonen -menuitem.show.offline.group = Afgemeldde gebruikers in aparte groep -menuitem.show.traffic = Debug- en verkeersmonitor -menuitem.sign.in = Aanmelden -menuitem.sign.in.at.login = Automatisch aanmelden -menuitem.sign.out = Afmelden -menuitem.start.a.chat = Conversatie beginnen -menuitem.start.a.conference = Conferentie beginnen... -menuitem.status = Status -menuitem.subscribe.to = Abonneer op -menuitem.unban = Weer toestaan -menuitem.unblock.user = Deblokkeer gebruiker -menuitem.user.guide = Gebruikers Handleiding -menuitem.view.client.version = Clientversie -menuitem.view.contact.history = Geschiedenis bekijken -menuitem.view.downloads = Gedownloade bestanden -menuitem.view.last.activity = Laatste activiteit bekijken -menuitem.view.logs = Logboeken bekijken -menuitem.view.profile = Profiel bekijken -menuitem.view.room.info = Informatie ruimte bekijken -menuitem.voice = Stemrecht - -message = &Bericht -message.account.create = Maak een nieuwe account aan. -message.account.created = Nieuwe account is aangemaakt. -message.account.error = Geef de server waar de account op moet worden aangemaakt op. -message.add.a.contact = Contact toevoegen... -message.add.conference.service = Conferentiedienst toevoegen. -message.add.contact.to.list = Voeg een gebruiker toe aan de lijst met contacten. -message.add.favorite.room = Voeg ruimte toe aan de favorietenlijst of ga meteen naar binnen. -message.add.this.user.to.your.roster = Voeg deze gebruiker aan de contactlijst toe. -message.add.to.roster = Aan contactlijst toevoegen -message.add.user = Gebruiker aan contactlijst toevoegen? -message.alert.notify = Waarschuwing -message.already.exists = Account bestaat reeds. Probeer een andere gebruikersnaam. -message.approve.subscription = Sta {0} toe om mij aan hun rooster toe te voegen? -message.autenticating = Bezig met authoriseren... -message.away.idle = Afwezig wegens inactiviteit. -message.bookmark.temporary.room.error = Kan geen bladwijzers maken van tijdelijke ruimtes. -message.broadcast.from = Bericht van {0} -message.broadcast.message.sent = Het bericht is verzonden. -message.broadcast.to = Geef bericht om te versturen aan {0} -message.broadcasted.to = Het bericht is verstuurd naar de volgende gebruikers:\n{0} -message.buzz.alert.notification = Vraagt de gebruiker om aandacht. -message.buzz.sent = Melding naar gebruiker verstuurd. -message.calling = Belt {0} -message.came.online = {0} is online gekomen op {1} -message.cannot.add.contact.to.shared.group = Er kunnnen geen contacten worden toegevoegd aan gedeelde groepen. -message.chat.session.ended = Conversatie is ge\u00ebindigd op {0} -message.click.to.open = Klik om te openen -message.client.information = Client informatie van {0} -message.close.other.chats = Sluit alle andere conversaties -message.close.stale.chats = Sluit bevroren conversaties -message.close.this.chat = Sluit deze conversatie -message.conference.info.error = Informatie over de conferentie kon niet worden verkregen worden. Probeer a.u.b. later nog eens. -message.conference.service.error = Kon de conferentiedienst niet vinden. -message.confirm.destruction.of.room = Bij het opheffen van de ruimte worden alle gebruikers uit de ruimte verwijderd. Doorgaan? -message.confirmation.password.error = Bevestig het opgegeven wachtwoord. -message.connecting.please.wait = Bezig met verbinden. Een moment a.u.b.... -message.connection.failed = Geen verbinding mogelijk met {0}. -message.create.account = Account kon niet worden aangemaakt. -message.create.or.join.room = Maak of doe mee in een conferentie ruimte -message.current.status = Toon anderen de huidige status of activiteit. -message.default.error = Er is een fout veroorzaakt. Meld deze a.u.b. aan support@jivesoftware.com. -message.delete.all.history = Alle voorgaande conversaties verwijderen? -message.delete.confirmation = {0} echt verwijderen? -message.disable.transport = De aanmeldingsgegevens uit {0} verwijderen? -message.disconnected.conflict.error = De verbinding werd verbroken omdat dezelfde gebruiker op een andere locatie is aangemeld. -message.disconnected.group.chat.error = De verbinding werd verbroken door een fout. Na heraanmelden zult u deze ruimte opnieuw moeten binnengaan. -message.disconnected.error = De verbinding werd verbroken door een fout. -message.disconnected.shutdown = De verbinding werd verbroken omdat de server uitgeschakeld werd. -message.downloading = Bezig met downloaden van {0} -message.downloading.spark.plug = Spark-Plug downloaden -message.end.chat = Deze conversatie be\u00ebindigen? -message.end.conversation = Deze sessie be\u00ebindigen? -message.enter.aim = Geef AIM gebruikersnaam en wachtwoord. -message.enter.broadcast.message = Bericht om aan geselecteerde gebruikers te versturen: -message.enter.gtalk = Geef GTalk gebruikersnaam en wachtwoord. -message.enter.icq = Geef ICQ gebruikersnaam en wachtwoord. -message.enter.jabber.id = Geef Jabber ID -message.enter.message.to.broadcast = Geef bericht om naar de hele contactlijst te versturen. -message.enter.msn = Geef MSN gebruikersnaam en wachtwoord. -message.enter.new.subject = Geef het nieuwe onderwerp -message.enter.room.password = Geef wachtwoord voor de ruimte -message.enter.valid.jid = Geef een geldige Jabber ID op. -message.enter.xmpp = Geef XMPP gebruikersnaam en wachtwoord. -message.enter.yahoo = Geef gebruikersnaam en wachtwoord om verbinding met Yahoo te maken. -message.error.during.file.transfer = Er was een fout gedurende de overdracht. -message.file.exists.question = Het bestand bestaat reeds. Overschrijven? -message.file.size = Formaat: {0} -message.file.transfer.canceled = Bestandsoverdracht werd geannuleerd. -message.file.transfer.rejected = Het bestand werd geweigerd door {0}. -message.find.conference.services = Zoek conferentie diensten. -message.forbidden.error = Verboden fout van de server ontvangen. -message.general.error = De verbinding met de server werd verbroken door {0}. -message.generic.reconnect.message = De verbinding met de server is verbroken. Om opnieuw aan te melden, klik op "Opnieuw". -message.idle.for = Geen activiteit in de afgelopen {0} minuten -message.image.too.large = Dit bestand is te groot om te gebruiken. Bestand mag maximaal 16Kb zijn. -message.invalid.jabber.id = Geen geldige Jabber ID -message.invalid.jid.error = De opgegeven JID is ongeldig. -message.invalid.status = Geef een geldige statusmelding op. -message.invalid.username.password = Verkeerde gebruikersnaam of wachtwoord. -message.invite.users.to.conference = Nodig gebruikers uit in een conferentieruimte. -message.is.shared.group = {0} is een gedeelde groep. -message.is.typing.a.message = {0} typt een bericht... -message.join.conference.room = Conferentie ruimte binnengaan -message.kicked.error = Ik kan {0} niet uit deze ruimte schoppen. -message.last.message.received = Laatste bericht ontvangen op {0} -message.loading.please.wait = Bezig met laden. Moment geduld a.u.b.... -message.locked.workstation = Gebruiker heeft de werkplek op slot gezet. -message.name.of.group = Groepnaam: -message.name.of.search.service.question = Naam van zoekdienst? -message.negotiate.file.transfer = Bestandsoverdracht wordt opgezet. Moment geduld a.u.b.... -message.negotiate.stream = Datastroom wordt opgezet. Moment geduld a.u.b.... -message.negotiation.file.transfer = Overdracht met {0} aan het opzetten. Moment geduld a.u.b.... -message.new.message = Nieuw bericht van {0}. -message.new.spark.available = {0} is nu beschikbaar. Deze nu installeren? -message.nickname.in.use = Alias reeds in gebruik. Geef een andere alias op. -message.no.avatar.found = Gebruiker heeft geen avatar ingesteld. -message.no.caller.id = Geen nummer beschikbaar. -message.no.description.available = Geen beschrijving beschikbaar -message.no.history.found = Er is geen conversatie geschiedenis met deze gebruiker. -message.no.results.found = Er waren geen resultaten. -message.no.room.to.join.error = Geen ruimtes om binnen te gaan. -message.no.subject.available = Geen onderwerp beschikbaar -message.no.updates = Er zijn geen updates. -message.normal = Normaal bericht -message.number.to.call = Nummer om te bellen -message.offline = De gebruiker is niet aangemeld, maar zal het bericht ontvangen bij de eerstvolgende aanmelding. -message.offline.error = De gebruiker zal niet in staat zijn om offline berichten te ontvangen. -message.participants.in.room = Aanwezigen in ruimte -message.password.error = Geef een wachtwoord op. -message.password.private.room.error = Geef wachtwoord voor de priv\u00e9 ruimte. -message.passwords.no.match = Wachtwoorden komen niet overeen. -message.please.join.in.conference = Doe mee aan mijn conferentie. -message.plugins.not.available = Plugin server is onbereikbaar. -message.prompt.plugin.uninstall = Plugin {0} de\u00efnstalleren? -message.received.file = Bestand van {0} ontvangen. -message.receiving.file = Bestand van {0} wordt ontvangen. -message.reconnect.attempting = Herverbinden... -message.reconnect.failed = Herverbinden mislukt. -message.reconnect.wait = Herverbinden over {0} seconden. -message.register.transports = Registreer bij deze beschikbare koppeling. -message.registering = Registreren bij {0}. Een moment a.u.b.... -message.registration.transport.failed = Registratie bij transport is mislukt. -message.restart.spark = De client moet worden afgesloten \n om de nieuwe versie te installeren. Nu direct afsluiten? -message.restart.spark.changes = Plugin zal verwijderd worden bij eerstvolgende start van Spark. -message.restart.spark.to.install = Spark moet opnieuw gestart worden om de laatste versie te installeren. Nu opnieuw starten? -message.restart.required = Spark moet opnieuw gestart worden om deze wijzigingen toe te passen. Nu opnieuw starten? -message.room.creation.error = De ruimte kon niet aangemaakt worden. -message.room.destroyed = Deze ruimte is opgeheven om de volgende reden: -message.room.destruction.reason = Reden voor de opheffing van de ruimte? -message.room.information.for = Informatie ruimte voor {0} -message.save.profile = Om wijzigingen in het profiel op te slaan, klik Opslaan. -message.search.for.contacts = Zoek naar contacten. -message.search.for.other.people = Andere personen zoeken op deze server -message.search.service.not.available = De zoekdienst is onbereikbaar. -message.searching.please.wait = Bezig met zoeken. Moment geduld a.u.b.... -message.select.add.room.to.add = Kies een ruimte om aan de dienstenlijst toe te voegen. -message.select.one.or.more = Selecteer \u00e9\u00e9n of meer gebruikers in de contactlijst. -message.select.room.to.enter = Geef ruimte om binnnen te gaan. -message.select.room.to.join = Kies een ruimte om binnen te gaan. -message.send.a.broadcast = Bericht versturen -message.send.file.to.user = Verstuur bestand(en) naar deze gebruiker. -message.send.picture = Verstuur afbeelding van wat er op het scherm staat. -message.send.to.these.people = Verstuur naar deze personen -message.sending.file.to = Bezig met verzenden bestand naar {0}. -message.sent.offline.files = Offline bestand(en) ontvangen. -message.service.already.exists = Dienst staat reeds in de lijst. -message.server.unavailable = Kan geen verbinding met de server krijgen: Ongeldige naam of server onbereikbaar. -message.shared.group = Gedeelde groep -message.spark.secure = Spark draait in beveiligde modus. -message.specify.contact.jid = Geef het JID van het contact op (bijv. ddman@jabber.org) -message.specify.group = Geef een groep voor de nieuwe gebruiker op. -message.specify.information.for.conference = Geef informatie voor de conferentieruimte. -message.specify.name.error = Geef een geldige naam op. -message.specify.users.to.join.conference = Geef gebruikers op die meedoen aan deze conferentie. -message.specify.valid.time.error = Geef een geldige maximumtijd en poort op. -message.subject.change.error = Onvoldoende rechten om het onderwerp van de ruimte te veranderen. -message.subject.has.been.changed.to = Het onderwerp is veranderd naar {0}. -message.supply.resource = Geef een geldig medium op. -message.supply.valid.port = Geef een geldige poort op. -message.supply.valid.timeout = Geef een geldige antwoordtijd op. -message.timeout.error = De tijd moet minimaal 5 seconden zijn. -message.total.downloaded = Totaal gedownload -message.transfer.cancelled = De overdracht werd geannuleerd. -message.transfer.rate = Snelheid -message.transfer.refused = Het bestand werd geweigerd. -message.transfer.waiting.on.user = Wacht op {0} om bestand te accepteren. -message.unable.to.load.profile = Kan profiel van {0} niet vinden. -message.unable.to.retrieve.last.activity = Laatste activiteit ophalen voor {0} mislukt. -message.unable.to.save.password = Wachtwoord kon niet worden gewijzigd. Neem contact op met de server beheerder. -message.unable.to.send.file = Bestand naar {0} versturen mislukt. -message.unrecoverable.error = Verkeerde gebruikersnaam of wachtwoord. -message.update.room.list = Lijst van ruimtes bijwerken -message.updating.cancelled = Bijwerken is geannuleerd. -message.user.banned = {0} is uit deze ruimte verbannen. -message.user.given.voice = {0} heeft stemrecht in deze ruimte gekregen. -message.user.granted.admin = {0} heeft beheerdersrechten gekregen. -message.user.granted.membership = {0} heeft lidmaatschapsrechten gekregen. -message.user.granted.moderator = {0} heeft moderator rechten gekregen. -message.user.granted.owner = {0} heeft eigenaarsrechten gekregen. -message.user.is.sending.you.a.file = {0} probeert een bestand op te sturen. -message.user.joined.room = {0} is de ruimte binnengekomen. -message.user.kicked.from.room = {0} is uit de ruimte verwijderd. -message.user.left.room = {0} heeft de ruimte verlaten. -message.user.nickname.changed = {0} staat voortaan bekend als {1}. -message.user.now.available.to.chat = {0} is online op {1} -message.user.revoked.admin = Beheerdersrechten van {0} zijn ingetrokken. -message.user.revoked.membership = Lidmaatschap van {0} is ingetrokken. -message.user.revoked.moderator = Moderator rechten van {0} zijn ingetrokken. -message.user.revoked.owner = Eigenaarsrechten van {0} zijn ingetrokken. -message.user.voice.revoked = Stemrecht van {0} is ingetrokken. -message.username.error = Geef een gebruikersnaam op. -message.username.password.error = Gebruikersnaam en/of wachtwoord moeten gegeven worden. -message.vcard.not.supported = De server heeft geen ondersteuning voor VCards. VCard kon niet worden opgeslagen. -message.version = Versie: {0} -message.view.information.about.this.user = Bekijk informatie over deze gebruiker. -message.waiting.for.user.to.join = Wacht op {0} om mee te doen. -message.went.offline = {0} is offline gegaan op {1} -message.you.have.been.banned = Ik ben verbannen uit deze ruimte. -message.you.have.been.kicked = Ik ben uit deze ruimte geschopt. -message.you.have.sent = Bestand naar {0} verstuurd. -message.your.admin.granted = Beheerdersrechten verkregen. -message.your.banned = Verbannnen uit deze ruimte. -message.your.kicked = Verwijderd door {0}. -message.your.membership.granted = Lidmaatschapsrechten verkregen. -message.your.membership.revoked = Lidmaatschap ingetrokken. -message.your.moderator.granted = Moderatorrechten verkregen. -message.your.moderator.revoked = Moderatorrechten ingetrokken. -message.your.ownership.granted = Eigenaarsrechten verkregen. -message.your.ownership.revoked = Eigenaarsrechten ingetrokken. -message.your.revoked.granted = Beheerdersrechten ingetrokken. -message.your.voice.granted = Stemrecht in deze conversatie gekregen. -message.your.voice.revoked = Stemrecht in deze conversatie ingetrokken. - -status.away = Afwezig -status.custom.messages = Statusmeldingen -status.do.not.disturb = Niet storen -status.extended.away = Langdurig afwezig -status.free.to.chat = Vrij om te praten -status.on.phone = Aan de telefoon -status.online = Aanwezig -status.pending = In aanvraag - -tab.available.plugins = Beschikbare plugins -tab.avatar = Avatar -tab.business = Zakelijk -tab.conferences = Conferenties -tab.contacts = Contacten -tab.general = Algemeen -tab.home = Priv\u008e -tab.installed.plugins = Ge\u0095nstalleerde plugins -tab.personal = Persoonlijk -tab.proxy = Proxy - -title.about = Versie informatie -title.account.create.registration = Accountregistratie -title.account.created = Account aangemaakt -title.add.contact = Contact toevoegen -title.add.contact.group = Contactgroep toevoegen -title.add.new.group = Voeg groep toe -title.add.search.service = Toevoegen Zoekdienst. -title.add.to.roster = Voeg aan contactlijst toe -title.address = Adres -title.advanced.connection.preferences = Geavanceerde verbindingsinstellingen -title.aim.registration = AIM Aanmeldingsgegevens -title.alert = Waarschuwing -title.appearance = Uiterlijk -title.appearance.preferences = Vormgeving uiterlijk -title.available.transports = Beschikbare koppelingen -title.broadcast.message = Bericht versturen -title.browse.conference.services = Conferentie diensten bladeren -title.browse.room.service = Conferentieruimtes bladeren - {0} -title.cancelled = Geannuleerd -title.change.nickname = Wijzig alias -title.change.subject = Verander onderwerp -title.chat = Conversatie -title.choose.directory = Kies directory -title.choose.incoming.sound = Binnenkomend geluid kiezen -title.choose.offline.sound = Offline geluid kiezen -title.choose.outgoing.sound = Uitgaand geluid kiezen -title.conference.invitation = Conferentie uitnodiging -title.conference.rooms = Conferentieruimtes -title.configure.chat.room = Configureer Conversatie ruimte -title.configure.room = Eigenschappen ruimte -title.confirmation = Bevestiging -title.create.new.account = Nieuwe account -title.create.or.bookmark.room = Bladwijzer maken of ruimte binnengaan -title.create.or.join = Aanmaken/Binnengaan -title.create.problem = Probleem bij aanmaken account -title.dial.phone = Bellen -title.disable.transport = Aanmeldgegevens verwijderen -title.download.complete = Download Voltooid -title.downloading.im.client = IM client aan het downloaden -title.downloads = Downloads -title.edit.custom.message = Eigen statusmeldingen bewerken -title.edit.profile = Profielinformatie bewerken -title.enter.reason = Geef reden op -title.error = Fout -title.file.exists = Bestand bestaat reeds -title.file.transfer = Bestandsoverdracht -title.file.transfer.preferences = Voorkeuren bestandsoverdracht -title.find.conference.service = Conferentie dienst zoeken -title.find.contacts = Zoek contacten -title.general.chat.settings = Algemene conversatie instellingen -title.group.chat = Groepsconversatie -title.gtalk.registration = GTalk Aanmeldingsgegevens -title.history.for = Conversatiegeschiedenis met {0} -title.icq.registration = ICQ Aanmeldingsgegevens -title.incoming.call = Binnenkomend gesprek -title.invite.to.conference = Uitnodigen voor conferentie -title.jabber.browser = Browser -title.join.conference.room = Conferentie ruimte binnengaan -title.last.activity = Laatste activeit -title.login = Aanmelden -title.login.error = Fout bij aanmelden -title.login.settings = Instellingen aanmelden -title.lookup.profile = Zoek profiel op -title.msn.registration = MSN Aanmeldingsgegevens -title.name = Naam -title.new.client.available = Nieuwe client beschikbaar -title.new.roster.group = Nieuwe contactgroep -title.new.version.available = Nieuwe versie beschikbaar -title.notes = Notities -title.no.updates = Meest recente versie aanwezig -title.notification = Melding -title.notifications = Meldingen -title.occupants = Aanwezigen -title.on.the.phone = Aan de telefoon -title.password = Wachtwoord -title.passwords.no.match = Controleer wachtwoorden -title.person.search = Personen zoeken -title.plugins = Plugins -title.preferences = Voorkeuren -title.profile.information = Profielinformatie -title.profile.not.found = Profiel niet gevonden -title.register.account = Registreer nieuwe account -title.registration.error = Registratie fout -title.reminder = Herinnering -title.rename.roster.group = Hernoem Groep -title.room.destroyed = Ruimte opgeheven -title.room.information = Ruimte informatie -title.roster = Contactlijst -title.select.file.to.send = Selecteer bestanden -title.set.status.message = Statusmelding instellen -title.sound.preferences = Geluidsvoorkeuren -title.sounds = Geluiden -title.spark.preferences = Spark voorkeuren -title.start.chat = Conversatie beginnen -title.status.message = Statusmelding -title.tasks = Nog te doen -title.transports = Koppelingen -title.tray.information = Systeemvak informatie -title.upgrading.client = Client aan het upgraden -title.version.and.time = Versie en tijd -title.view.bookmarks = Bladwijzers bekijken -title.view.profile.for = Profiel van {0} -title.view.room.information = Ruimte informatie -title.waiting.to.call = Wacht met bellen -title.xmpp.registration = XMPP Aanmeldingsgegevens -title.yahoo.registration = Yahoo Aanmeldingsgegevens - -tooltip.appearance = Verander het uiterlijk en de vormgeving van de conversaties. -tooltip.notifications = Meldingsvoorkeuren voor binnenkomende conversaties. -tooltip.file.transfer = Instellingen voor het verzenden en ontvangen van bestanden. -tooltip.place.voice.call = Bel deze persoon op -tooltip.send.email = Verstuur een e-mail -tooltip.start.chat = Begin een gesprek -tooltip.view.changelog = Bekijk wijzigingslogboek -tooltip.view.history = Bekijk conversatie geschiedenis -tooltip.view.readme = Lees ReadMe - -tree.conference.services = Conferentie diensten -tree.users.in.room = Gebruikers in ruimte - - -#!# \ No newline at end of file diff --git a/src/resources/i18n/spark_i18n_pl.properties b/src/resources/i18n/spark_i18n_pl.properties deleted file mode 100644 index 158dc8839..000000000 --- a/src/resources/i18n/spark_i18n_pl.properties +++ /dev/null @@ -1,910 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.7.0 build 659 -## -## Tlumaczenie do wyciagnietego pliku jezykowego z wersji 2.7.0 build 659 -## -## Tlumaczenie splodzil i skorektowal Martini26 (marek_marcin@o2.pl) - polskie korekty mile widziane ;) - -accept = Akceptuj -active = Aktywny -add = Dodaj -administrator = Administrator -answer = Odpowiedz -apply = Zatwierd\u017a -available = Dost\u0119pny -broadcast = Wiadomo\u015b\u0107 grupowa -cancel = Anuluj -close = Zamknij -create = Utw\u00f3rz -date = Data -description = Opis -from = Od -invite = Zapro\u015b -join = Do\u0142\u0105cz -no = Nie -not.registered = Nie zarejestrowany -occupants = Zaj\u0119ty przez -offline = Niedost\u0119pny -online = Dost\u0119pny -ok = Ok -open = Otw\u00f3rz -open.folder = Otw\u00f3rz katalog -participants = Uczestnicy -reject = Odrzu\u0107 -retry = Powt\u00f3rz -room.name = Nazwa pokoju -save = Zapisz -refresh = Od\u015bwie\u017c -subject = Temat -unfiled = Niewype\u0142nione -use.default = U\u017cyj domy\u015blnych -user.has.signed.in = zalogowa\u0142 si\u0119. -user.has.signed.off = wylogowa\u0142 si\u0119. -while.offline = W trybie niedost\u0119pnym -yes = Tak - -action.clear = Wyczy\u015b\u0107 -action.copy = Kopiuj -action.cut = Wytnij -action.paste = Wklej -action.print = Drukuj -action.save = Zapisz -action.select.all = Zaznacz wszystko - -button.accept = Akceptuj -button.reject = Odrzu\u0107 -button.add = Dodaj -button.add.a.contact = Dodaj kontakt -button.add.bookmark = Dodaj zak\u0142adk\u0119 -button.add.service = Dodaj us\u0142ug\u0119 -button.add.user = Dodaj u\u017cytkownika -button.add2 = Dodaj -button.advanced = Zaawansowane -button.approve = Zatwierd\u017a -button.bookmark.room = Dodaj pok\u00f3j -button.browse = Przegl\u0105daj -button.browse2 = Przegl\u0105daj -button.browse3 = Przegl\u0105daj -button.cancel = Anuluj -button.clear = Wyczy\u015b\u0107 -button.close = Zamknij -button.copy.to.clipboard = Kopiuj do schowka -button.create.account = Utw\u00f3rz konto -button.create.room = Utw\u00f3rz lub do\u0142\u0105cz do pokoju -button.decline = Odrzu\u0107 -button.deny = Zablokuj -button.dial.number = Wybierz numer -button.find = Znajd\u017a -button.join = Do\u0142\u0105cz -button.join.room = Do\u0142\u0105cz do wybranego pokoju -button.login = Zaloguj -button.new = Nowy -button.profile = Profil -button.quit = Wyjd\u017a -button.reconnect = Po\u0142\u0105cz ponownie -button.reconnect2 = Po\u0142\u0105cz ponownie -button.refresh = Od\u015bwie\u017c -button.register = Zarejestruj -button.remove.bookmark = Usu\u0144 zak\u0142adk\u0119 -button.roster = Lista wsp\u00f3\u0142dzielona -button.save = Zapisz -button.save.for.future.use = Zapami\u0119taj -button.search = Szukaj -button.send = Wy\u015blij -button.send.email = E-mail -button.start.chat = Rozmowa -button.tasks.active = Aktywne -button.tasks.all = Wszystkie -button.unset.file.explorer = Nieustawiona przegl\u0105darka plik\u00f3w -button.update = Aktualizuj -button.view.notes = Zobacz notatki -button.view.profile = Zobacz pe\u0142ny profil -button.view.tasklist = Zobacz list\u0119 zada\u0144 -button.re.detect = Wykryj ponownie - -checkbox.allow.buzz = Zezw\u00f3l u\u017cytkownikom na przesy\u0142anie alert\u00f3w -checkbox.auto.discover.port = Automatycznie wykryj hosta i port -checkbox.auto.login = Automatyczne logowanie -checkbox.login.as.invisible = Zaloguj jako niewidoczny -checkbox.disable.chat.history = Wy\u0142\u0105cz histori\u0119 rozm\u00f3w -checkbox.sort.asc.history = Sortuj histori\u0119 kontaktu wed\u0142ug daty rosn\u0105co -checkbox.disable.prev.chat.history = Wy\u0142\u0105cz histori\u0119 rozmowy w okienku -checkbox.enable.emoticons = W\u0142\u0105cz emotikony -checkbox.idle.enabled = W\u0142\u0105cz opcj\u0119 Zaraz wracam -checkbox.launch.on.startup = Uruchom przy starcie systemu -checkbox.reconnet.info = Okre\u015blenie wy\u015bwietlania ponownego po\u0142\u0105czenia -checkbox.reconnect.panel.big = Wy\u015bwietl jako panel -checkbox.reconnect.panel.small = Wy\u015bwietl w grupie kontakt\u00f3w -checkbox.reconnect.panel.icon = Wy\u015bwietl jako ikona -checkbox.notify.user.comes.online = Powiadom o zmianach statusu u\u017cytkownik\u00f3w na aktywny -checkbox.notify.user.goes.offline = Powiadom o zmianach statusu u\u017cytkownik\u00f3w na nieaktywny -checkbox.notify.typing.systemtray = Pokazuj na pasku systemowym kiedy u\u017cytkownik pisze -checkbox.notify.systemtray = Pokazuj nowe wiadomo\u015bci na pasku systemowym -checkbox.permanent = Pok\u00f3j zawsze aktywny -checkbox.play.sound.on.invitation = Odtw\u00f3rz d\u017awi\u0119k kiedy nadejdzie zaproszenie -checkbox.play.sound.on.new.message = Odtw\u00f3rz d\u017awi\u0119k kiedy nadejdzie nowa wiadomo\u015b\u0107 -checkbox.play.sound.on.outgoing.message = Odtw\u00f3rz d\u017awi\u0119k podczas wysy\u0142ania wiadomo\u015bci -checkbox.play.sound.when.offline = Odtw\u00f3rz d\u017awi\u0119k kiedy u\u017cytkownik si\u0119 wyloguje -checkbox.private.room = Pok\u00f3j jest prywatny -checkbox.save.password = Zapisz has\u0142o -checkbox.show.avatars.in.contactlist = Pokazuj awatary na li\u015bcie kontakt\u00f3w -checkbox.show.notifications.in.conference = Pokazuj powiadomienia w pokojach -checkbox.show.time.in.chat.window = Pokazuj czas w oknie rozmowy -checkbox.show.toaster = Pokazuj wyskakuj\u0105ce okienko -checkbox.split.chat.window = Podziel okna rozm\u00f3w (wymagany restart) -checkbox.start.in.tray = Wy\u015bwietlaj zak\u0142adki rozm\u00f3w na g\u00f3rze (wymagany restart) -checkbox.click.single.tray = Pojedyncze klikni\u0119cie ikony w trayu wywo\u0142uje g\u0142\u00f3wne okno Sparka -checkbox.tabs.on.top = Zak\u0142adki rozmowy na wierzchu (wymagany restart) -checkbox.use.compression = U\u017cywaj kompresji -checkbox.use.debugger.on.startup = Uruchom \u015bledzenie b\u0142\u0119d\u00f3w przy starcie -checkbox.use.proxy.server = U\u017cyj serwera proxy -checkbox.use.system.look.and.feel = U\u017cywaj systemowego wygl\u0105du (wymagany restart) -checkbox.window.to.front = Zawsze na wierzchu -checkbox.broadcast.hide.offline.user = Ukrywaj nieaktywnych u\u017cytkownik\u00f3w -checkbox.use.krbconf = U\u017cyj krb5.conf lub krb5.ini -checkbox.use.krb.dns = U\u017cyj DNS -checkbox.use.specify.below = Okre\u015bl poni\u017csze opcje -checkbox.use.pki.authentication = U\u017cyj autoryzacji PKI -checkbox.transport.tab.setting = Pokazuj dost\u0119pne bramy w tabeli (wymaga restartu) -checkbox.conference.tab.setting = Poka\u017c us\u0142ug\u0119 konferencji na karcie (wymaga restartu) - -delete.log.permanently = Usu\u0144 dziennik zdarze\u0144 -delete.permanently = Usun\u0105\u0107 trwale? - -gateway.username.password.error = U\u017cytkownik i/lub has\u0142o musz\u0105 zosta\u0107 wpisane - -group.chat.window.information = Informacje okna rozm\u00f3w -group.comma.delimited = Rozdzielone przecinkiem -group.conferences.found = Znalezione us\u0142ugi konferencji -group.connection = Po\u0142\u0105czenie -group.empty = W tej grupie nie ma aktywnych kontakt\u00f3w -group.general.information = Zmiana has\u0142a -group.login.information = Informacje o logowaniu -group.notification.options = Opcje powiadomie\u0144 -group.offline = Grupa u\u017cytkownik\u00f3w niedost\u0119pnych -group.search.form = Wyszukaj -group.search.results = Wyniki wyszukiwania -group.chat.name.notification = Widz\u0119 Twoj\u0105 nazw\u0119 -group.chat.name.match = Twoje imi\u0119 zosta\u0142o u\u017cyte w rozmowie: - -label.na = brak -label.cell = Tel. kom\u00f3rkowy -label.work = Praca -label.home = Dom -label.accounts = Konta -label.passwordreset = Resetuj has\u0142o -label.add.conference.service = Dodaj us\u0142ug\u0119 konferencji -label.add.jid = Dodaj JID -label.add.task = Dodaj zadanie -label.auto.login = Autologowanie -label.available.users.in.roster = Dost\u0119pni u\u017cytkownicy na li\u015bcie -label.cancel = Anuluj -label.change.password.to = Zmie\u0144 has\u0142o na -label.chatroom.fontsize = Rozmiar czcionki w pokoju rozm\u00f3w -label.city = Miasto -label.close = Zamknij -label.company = Firma -label.confirm.password = Potwierd\u017a has\u0142o -label.conflict.error = Nie mo\u017cna zalogowa\u0107, kto\u015b jest ju\u017c zalogowany na to konto -label.contact.to.find = Znajd\u017a kontakt -label.recent.conversation = Ostatnie rozmowy -label.frequent.contacts = Cz\u0119ste kontakty -label.contactlist.avatarsize = Rozmiar awatar\u00f3w na li\u015bcie kontakt\u00f3w: -label.contactlist.fontsize = Rozmiar czcionki listy kontakt\u00f3w: -label.country = Kraj -label.create.account = Utw\u00f3rz konto -label.department = Wydzia\u0142 -label.dial = Wybieranie -label.downloads = \u015aci\u0105gni\u0119te pliki -label.due = Pow\u00f3d -label.email.address = Adres e-mail -label.emoticons = Emotikony -label.enter.address = Wpisz adres -label.enter.group.name = Wpisz nazw\u0119 nowej grupy -label.fax = Fax -label.find = Znajd\u017a -label.first.name = Imi\u0119 -label.group = Grupa -label.host = Host -label.invited.users = Zaproszeni u\u017cytkownicy -label.jabber.address = Adres Jabbera -label.jabber.id = ID Jabbera -label.jid = JID -label.job.title = Stanowisko -label.last.name = Nazwisko -label.local.time = Czas lokalny -label.message = Wiadomo\u015b\u0107 -label.message.style = Styl wiadomo\u015bci -label.middle.name = Drugie imi\u0119 -label.minutes.before.stale.chat = Ilo\u015b\u0107 minut po kt\u00f3rych nieaktywne okno zostanie przedawnione -label.mobile = Telefon kom\u00f3rkowy -label.name = Imi\u0119 -label.network = Sie\u0107 -label.new.nickname = Nowy pseudonim -label.nickname = Pseudonim -label.number = Numer -label.ok = OK -label.old.ssl = U\u017cywaj starej metody SLL -label.os = Wersja systemu -label.pager = Pager -label.password = Has\u0142o -label.phone = Telefon -label.port = Port -label.postal.code = Kod pocztowy -label.presence = Obecno\u015b\u0107 -label.priority = Priorytet -label.protocol = Protok\u00f3\u0142 -label.received = Otrzymane -label.rename.to = Zmie\u0144 nazw\u0119 -label.resource = Zasoby -label.response.timeout = Czas oczekiwania na odpowied\u017a (sek.) -label.room = Pok\u00f3j -label.room.name = Nazwa pokoju -label.room.topic = Temat pokoju -label.search.service = Szukaj us\u0142ug -label.server = Serwer -label.server.address = Adres serwera -label.show = Poka\u017c: -label.software = Komunikator -label.state.and.province = Wojew\u00f3dztwo -label.street.address = Ulica -label.time = Czas: {0} -label.time.till.idle = Czas przej\u015bcia w stan bezczynno\u015bci (min) -label.time.till.idlemessage = Wiadomo\u015b\u0107 po automatycznym przej\u015bciu w stan bezczynno\u015bci -label.timeformat = U\u017cyj {0} -label.transfer.download.directory = Katalog pobranych plik\u00f3w: -label.transfer.timeout = Czas wyga\u015bni\u0119cia transferu (min): -label.unable.to.add.contact = Nie mo\u017cna doda\u0107 kontaktu -label.use.default = U\u017cyj domy\u015blnych -label.user.on.public.network = U\u017cytkownik jest w sieci publicznej -label.username = Nazwa u\u017cytkownika -label.version = Wersja -label.web.page = Strona WWW -label.xmpp.port = Port XMPP -label.krb.realm = Realm -label.krb.kdc = KDC -label.which.pki.method = Jaka metoda PKI? -label.choose.file = Wybierz plik -label.trust.store.password = Przechowuj bezpiecznie has\u0142o -label.enter.password = Wpisz has\u0142o -label.move.focus.forwards = Przejd\u017a dalej -label.move.focus.backwards = Przejd\u017a wstecz -label.keystore.location = Lokalizacja pliku kluczy -label.truststore.location = Lokalizacja pliku hase\u0142 -label.pkcs.library.file = Plik bibliotek PKCS#11 -label.x509.certificate = Certyfikat X.509 -label.apple.keychain = Zastosuj KeyChain -label.add.to.roster = Dodaj u\u017cytkownika do Twojej listy -label.audio.device = Urz\u0105dzenie audio -label.video.device = Urz\u0105dzenie video - -menuitem.about = O programie -menuitem.actions = Czynno\u015bci -menuitem.bookmarks = Zak\u0142adki -menuitem.add = Dodaj -menuitem.add.as.contact = Dodaj jako kontakt -menuitem.add.contact = Dodaj kontakt -menuitem.add.contact.group = Dodaj grup\u0119 kontakt\u00f3w -menuitem.add.groupchat.myname = Pod\u015bwietlaj moj\u0105 nazw\u0119 u\u017cytkownika, kiedy kto\u015b j\u0105 napisze -menuitem.add.groupchat.mytext = Pod\u015bwietlaj moje wypowiedzi -menuitem.add.groupchat.popname = Pokazuj wyskakuj\u0105ce okienko kiedy kto\u015b napisze moj\u0105 nazw\u0119 u\u017cytkownika -menuitem.add.groupchat.showjoinleavemessage = Wy\u015bwietlaj wiadomo\u015bci o do\u0142\u0105czeniu i opuszczeniu u\u017cytkownik\u00f3w -menuitem.add.groupchat.showrolesinsteadofstatus = Pokazuj ikony r\u00f3l zamiast ikon statusu -menuitem.add.groupchat.auto.accept.invite = Automatycznie akceptuj zaproszenia do rozm\u00f3w grupowych -menuitem.add.groupchat.random.colors = Nazwiska maj\u0105 losowe kolory -menuitem.always.on.top = Zawsze na wierzchu -menuitem.alert.when.online = Powiadom o dost\u0119pno\u015bci u\u017cytkownika -menuitem.ban = Zablokuj -menuitem.ban.user = Zablokuj u\u017cytkownika -menuitem.block.user = Zablokuj u\u017cytkownika -menuitem.broadcast.to.group = Wy\u015blij wiadomo\u015b\u0107 grupow\u0105 -menuitem.browse.service = Przegl\u0105daj us\u0142ugi -menuitem.change.nickname = Zmie\u0144 pseudonim -menuitem.change.subject = Zmie\u0144 temat -menuitem.chat = Rozmowa -menuitem.check.for.updates = Sprawd\u017a aktualizacje -menuitem.contacts = Kontakty -menuitem.copy.to = Kopiuj do -menuitem.delete = Usu\u0144 -menuitem.delete.login.information = Usu\u0144 informacje o logowaniu -menuitem.destroy.room = Usu\u0144 pok\u00f3j -menuitem.dial = Zadzwo\u0144 -menuitem.edit = Edytuj -menuitem.edit.my.profile = Edytuj m\u00f3j profil -menuitem.edit.status.message = Edytuj opis statusu -menuitem.enter.login.information = Wprowad\u017a informacje logowania -menuitem.exit = Wyjd\u017a -menuitem.affiliation = Przynale\u017cno\u015b\u0107 -menuitem.grant.moderator = Zezw\u00f3l na moderowanie -menuitem.grant.member = Przydziel uprawnienia cz\u0142onkowskie -menuitem.grant.admin = Przydziel uprawnienia administratora -menuitem.grant.owner = Przydziel uprawnienia w\u0142asno\u015bci -menuitem.grant.voice = Zezw\u00f3l na po\u0142\u0105czenie g\u0142osowe -menuitem.help = Pomoc -menuitem.hide = Ukryj -menuitem.invite.group.to.conference = Zapro\u015b grup\u0119 u\u017cytkownik\u00f3w do konferencji -menuitem.invite.users = Zapro\u015b u\u017cytkownik\u00f3w -menuitem.join.on.startup = Do\u0142\u0105cz przy starcie -menuitem.join.room = Do\u0142\u0105cz do wybranego pokoju -menuitem.kick.user = Wyrzu\u0107 u\u017cytkownika -menuitem.languages = J\u0119zyki -menuitem.logout.no.status = Wyloguj -menuitem.logout.with.status = Wyloguj z opisem -menuitem.lookup.profile = Przeszukaj profil -menuitem.move.to = Przenie\u015b do -menuitem.online.help = Forum Sparka (online) -menuitem.open = Otw\u00f3rz -menuitem.open.with = Otw\u00f3rz za pomoc\u0105 -menuitem.plugins = Wtyczki -menuitem.preferences = Ustawienia Sparka -menuitem.remove = Usu\u0144 -menuitem.remove.alert.when.online = Usu\u0144 alert -menuitem.remove.bookmark = Usu\u0144 zak\u0142adk\u0119 -menuitem.remove.from.group = Usu\u0144 z grupy -menuitem.remove.from.roster = Usu\u0144 z listy kontakt\u00f3w -menuitem.block.contact = Zablokuj kontakt -menuitem.unblock.contact = Odblokuj kontakt -menuitem.remove.service = Usu\u0144 us\u0142ug\u0119 -menuitem.rename = Zmie\u0144 nazw\u0119 -menuitem.revoke.moderator = Odbierz uprawnienia moderatora -menuitem.revoke.voice = Odbierz uprawnienia do po\u0142\u0105czenia g\u0142osowego -menuitem.revoke.member = Odbierz uprawnienia cz\u0142onkowskie -menuitem.revoke.admin = Odbierz uprawnienia administratora -menuitem.revoke.owner = Odbierz uprawnienia w\u0142asno\u015bci -menuitem.save = Zapisz -menuitem.save.as = Zapisz jako -menuitem.send.a.file = Wy\u015blij plik -menuitem.send.a.message = Wy\u015blij wiadomo\u015b\u0107 grupow\u0105 do wybranych u\u017cytkownik\u00f3w -menuitem.set.status.message = Ustaw opis statusu -menuitem.show.empty.groups = Poka\u017c puste grupy -menuitem.show.offline.group = Poka\u017c grup\u0119 u\u017cytkownik\u00f3w nieaktywnych -menuitem.show.traffic = Poka\u017c okno statystyk ruchu -menuitem.sign.in = Zapisz si\u0119 -menuitem.sign.in.at.login = Zapisz si\u0119 przy logowaniu -menuitem.sign.out = Wypisz si\u0119 -menuitem.start.a.chat = Rozpocznij rozmow\u0119 -menuitem.start.a.conference = Rozpocznij konferencj\u0119 -menuitem.status = Status -menuitem.subscribe.to = Zapisz si\u0119 do -menuitem.unban = Odblokuj -menuitem.unblock.user = Odblokuj u\u017cytkownika -menuitem.user.guide = Przewodnik u\u017cytkownika -menuitem.view.client.version = Poka\u017c wersj\u0119 klienta -menuitem.view.contact.history = Poka\u017c histori\u0119 kontaktu -menuitem.view.downloads = Poka\u017c pobrane pliki -menuitem.view.last.activity = Poka\u017c ostatni\u0105 aktywno\u015b\u0107 -menuitem.view.logs = Poka\u017c logi -menuitem.view.profile = Poka\u017c profil -menuitem.view.room.info = Poka\u017c informacje o pokoju -menuitem.voice = Rozmowa g\u0142osowa -menuitem.show.offline.users = Poka\u017c nieaktywnych u\u017cytkownik\u00f3w -menuitem.show.contact.statusmessage = Poka\u017c status -menuitem.bookmark.room = Dodaj pok\u00f3j do ulubionych -menuitem.refresh = Od\u015bwie\u017c -menuitem.create.room = Stw\u00f3rz lub do\u0142\u0105cz do pokoju -menuitem.expand.all.groups = Rozwi\u0144 wszystkie grupy -menuitem.collapse.all.groups = Zwi\u0144 wszystkie grupy -menuitem.inivite.again = Zapro\u015b ponownie -menuitem.chatframe.option = Opcje -menuitem.add.groupchat.invitetobookmark = Automatycznie zapro\u015b u\u017cytkownik\u00f3w do zaznaczonego pokoju - -message.invite.to.groupchat = {0} zaprasza Ci\u0119 do rozmowy grupowej -message = Wiadomo\u015b\u0107 -message.account.create = Utw\u00f3rz nowe konto -message.account.created = Nowe konto zosta\u0142o utworzone -message.account.error = Wska\u017c serwer na kt\u00f3rym chcesz utworzy\u0107 konto -message.add.a.contact = Dodaj kontakt -message.add.conference.service = Dodaj us\u0142ug\u0119 konferencji -message.add.contact.to.list = Dodaj u\u017cytkownika do listy kontakt\u00f3w -message.add.favorite.room = Dodaj pok\u00f3j do ulubionych lub po\u0142\u0105cz bezpo\u015brednio -message.add.this.user.to.your.roster = Dodaj u\u017cytkownika do listy znajomych -message.add.to.roster = Dodaj do grupy kontakt\u00f3w -message.add.user = Doda\u0107 do grupy kontakt\u00f3w? -message.alert.notify = Powiadomienie alarmowe -message.already.exists = Konto ju\u017c istnieje, u\u017cyj innej nazwy u\u017cytkownika -message.approve.subscription = Czy zezwoli\u0107 {0} na dodanie Ciebie do jej/jego grupy kontakt\u00f3w? -message.autenticating = Uwierzytelnianie -message.away.idle = Zaraz wracam -message.bookmark.temporary.room.error = Nie mo\u017cesz dodawa\u0107 tymczasowych pokoi do ulubionych -message.broadcast.from = Wiadomo\u015b\u0107 grupowa od {0} -message.broadcast.no.user.selected = Prosz\u0119 wybierz przynajmniej jednego odbiorc\u0119 -message.broadcast.no.text = Prosz\u0119 wprowad\u017a tekst dla wiadomo\u015bci grupowej enter text to broadcast -message.broadcast.message.sent = Wiadomo\u015b\u0107 grupowa zosta\u0142a wys\u0142ana -message.broadcast.to = Wpisz wiadomo\u015b\u0107 i wy\u015blij do {0} -message.broadcasted.to = Wiadomo\u015b\u0107 zosta\u0142a wys\u0142ana do nast\u0119puj\u0105cych u\u017cytkownik\u00f3w\:\n{0} -message.buzz.alert.notification = Zwr\u00f3\u0107 uwag\u0119 u\u017cytkownika -message.buzz.message = {0} chce zwr\u00f3ci\u0107 Twoj\u0105 uwag\u0119 -message.buzz.sent = Wy\u015blij alert do u\u017cytkownika -message.calling = Dzwoni do {0} -message.came.online = {0} pojawi\u0142 si\u0119 o {1} -message.cannot.add.contact.to.shared.group = Nie mo\u017cesz doda\u0107 nowych kontakt\u00f3w do wsp\u00f3\u0142dzielonej grupy -message.chat.session.ended = Rozmowa zosta\u0142a zako\u0144czona o {0} -message.click.to.open = Kliknij aby otworzy\u0107 -message.client.information = Informacja o kliencie u\u017cytkownika {0} -message.close.other.chats = Zamknij wszystkie pozosta\u0142e okna rozmowy -message.close.stale.chats = Zamknij nieaktywne okna rozmowy -message.close.this.chat = Zamknij to okno rozmowy -message.conference.info.error = Nie mo\u017cna uzyska\u0107 informacji o konferencji, spr\u00f3buj ponownie p\u00f3\u017aniej -message.conference.service.error = Nie mo\u017cna zlokalizowa\u0107 us\u0142ugi konferencji -message.confirm.destruction.of.room = Usuni\u0119cie pokoju roz\u0142\u0105czy wszystkich uczestnik\u00f3w, kontynuowa\u0107? -message.confirmation.password.error = Powt\u00f3rz has\u0142o -message.connecting.please.wait = \u0141\u0105czenie, prosz\u0119 czeka\u0107 -message.connection.failed = Nie mo\u017cna nawi\u0105za\u0107 po\u0142\u0105czenia z {0} -message.create.account = Nie mo\u017cna utworzy\u0107 konta -message.create.or.join.room = Utw\u00f3rz lub do\u0142\u0105cz do konferencji -message.current.status = Poka\u017c innym sw\u00f3j aktualny status -message.default.error = Wyst\u0105pi\u0142 nieoczekiwany b\u0142\u0105d. Skontaktuj si\u0119 z support@jivesoftware.com -message.delete.all.history = Wykasowa\u0107 wszystkie poprzednie rozmowy? -message.delete.confirmation = Czy jeste\u015b pewien, \u017ce chcesz usun\u0105\u0107 {0}? -message.disable.transport = Usun\u0105\u0107 informacje o logowaniu z {0}? -message.disconnected.conflict.error = Taki u\u017cytkownik jest ju\u017c zalogowany, po\u0142\u0105czenie przerwane -message.disconnected.error = Wyst\u0105pi\u0142 b\u0142\u0105d, po\u0142\u0105czenie przerwane -message.disconnected.group.chat.error = Po\u0142\u0105czenie zosta\u0142o zamkni\u0119te z powodu b\u0142\u0119du, do\u0142\u0105cz ponownie do pokoju -message.disconnected.shutdown = Po\u0142\u0105czenie przerwane z powodu niedost\u0119pno\u015bci serwera -message.downloading = Pobieranie {0} -message.downloading.spark.plug = Pobieranie wtyczki -message.end.chat = Czy chcesz zako\u0144czy\u0107 t\u0105 rozmow\u0119? -message.end.conversation = Czy chcesz zako\u0144czy\u0107 t\u0105 sesj\u0119? -message.enter.aim = Podaj login i has\u0142o AIM -message.enter.broadcast.message = Wpisz wiadomo\u015b\u0107 do wys\u0142ania dla okre\u015blonych u\u017cytkownik\u00f3w -message.enter.gadugadu = Podaj numer i has\u0142o us\u0142ugi Gadu-Gadu -message.enter.gtalk = Podaj login i has\u0142o us\u0142ugi Gtalk -message.enter.icq = Podaj login i has\u0142o us\u0142ugi ICQ -message.enter.irc = Podaj login i has\u0142o us\u0142ugi IRC -message.enter.sametime = Podaj login i has\u0142o us\u0142ugi Sametime -message.enter.facebook = Podaj login i has\u0142o us\u0142ugi Facebook -message.enter.myspace = Podaj login i has\u0142o us\u0142ugi MySpace -message.enter.jabber.id = Podaj Jabber ID -message.enter.message.to.broadcast = Wpisz wiadomo\u015b\u0107 do wys\u0142ania do wszystkich -message.enter.msn = Podaj login i has\u0142o us\u0142ugi MSN -message.enter.new.subject = Wpisz nowy temat -message.enter.qq = Podaj login i has\u0142o us\u0142ugi QQ -message.enter.room.password = Podaj has\u0142o dost\u0119pu do pokoju -message.enter.simple = Podaj login i has\u0142o us\u0142ugi SIMPLE -message.enter.valid.jid = Wpisz poprawny Jabber ID -message.enter.xmpp = Podaj login i has\u0142o us\u0142ugi XMPP -message.enter.yahoo = Podaj login i has\u0142o us\u0142ugi Yahoo -message.error.during.file.transfer = Wyst\u0105pi\u0142 b\u0142\u0105d podczas wysy\u0142ania pliku -message.file.exists.question = Plik ju\u017c istnieje, zast\u0105pi\u0107? -message.file.size = Rozmiar pliku: {0} -message.file.transfer.canceled = Anulowa\u0142e\u015b wysy\u0142anie pliku -message.file.transfer.rejected = Wysy\u0142anie pliku nie zosta\u0142o zaakceptowane przez {0} -message.file.transfer.dirnull = Katalog dla pobieranego pliku jest niew\u0142a\u015bciwy -message.file.transfer.nodir = Katalog dla pobieranego pliku nie istnieje -message.file.transfer.cantwritedir = Nie mo\u017cna zapisa\u0107 pobieranego pliku w katalogu -message.file.transfer.notification = Powiadomienie o wysy\u0142aniu pliku -message.file.transfer.short.message = chce wys\u0142a\u0107 plik: -message.file.transfer.chat.window = Czy chcesz odebra\u0107 plik: -message.file.transfer.file.too.big.error = Wybrany plik jest za du\u017cy. Maksymalny rozmiar pliku to {0} wybrany plik ma {1} -message.file.transfer.file.too.big.warning = Wybrany plik jest za du\u017cy. Kontynuowa\u0107? -message.file.transfer.direrror.setdir = Kliknij aby zmieni\u0107 katalog -message.find.conference.services = Znajd\u017a us\u0142ugi konferencyjne -message.forbidden.error = Otrzymano niedozwolony b\u0142\u0105d z serwera -message.gateway.username.error = Pole 'u\u017cytkownik' nie mo\u017ce by\u0107 puste -message.gateway.password.error = Musi zosta\u0107 podane has\u0142o -message.gateway.nickname.error = Pole 'pseudonim' nie mo\u017ce by\u0107 puste -message.general.error = Utracono po\u0142\u0105czenie z serwerem z powodu {0} -message.generic.reconnect.message = Utracono po\u0142\u0105czenie z serwerem, aby zalogowa\u0107 si\u0119 ponownie kliknij 'Po\u0142\u0105cz ponownie' -message.idle.for = Nieaktywny przez {0} -message.image.too.large = Za du\u017cy plik, obraz musi mie\u0107 rozmiar 16k lub mniejszy -message.invalid.jabber.id = Nieprawid\u0142owy Jabber ID -message.invalid.jid.error = Nieprawid\u0142owy JID -message.invalid.status = Nieprawid\u0142owy opis statusu -message.invalid.username.password = Niepoprawna nazwa u\u017cytkownika lub has\u0142o -message.invite.users.to.conference = Zapro\u015b u\u017cytkownik\u00f3w do pokoju konferencyjnego -message.is.shared.group = {0} jest grup\u0105 wsp\u00f3\u0142dzielon\u0105 -message.is.typing.a.message = {0} pisze wiadomo\u015b\u0107 -message.join.conference.room = Do\u0142\u0105cz do pokoju konferencyjnego -message.kicked.error = Nie masz uprawnie\u0144 aby usun\u0105\u0107 {0} z tego pokoju -message.last.message.received = Ostatnia wiadomo\u015b\u0107 otrzymana o {0} -message.loading.please.wait = \u0141adowanie. Prosz\u0119 czeka\u0107 -message.locked.workstation = U\u017cytkownik zablokowa\u0142 komputer -message.name.of.group = Nazwa grupy -message.name.of.search.service.question = Nazwa szukanej us\u0142ugi? -message.negotiate.file.transfer = Negocjowanie przesy\u0142u pliku, prosz\u0119 czeka\u0107 -message.negotiate.stream = Negocjowanie strumienia po\u0142\u0105czenia, prosz\u0119 czeka\u0107 -message.negotiation.file.transfer = Negocjowanie transferu pliku z {0}, prosz\u0119 czeka\u0107 -message.new.message = Nowa wiadomo\u015b\u0107 od {0} -message.new.spark.available = {0} jest dost\u0119pny. Czy chcesz zainstalowa\u0107? -message.nickname.in.use = Pseudonim jest ju\u017c zaj\u0119ty, podaj inny -message.nickname.not.acceptable = Opcja zmiany pseudonimu niedost\u0119pna! -message.no.avatar.found = U\u017cytkownik nie skonfigurowa\u0142 swojego awatara -message.no.caller.id = Brak ID dzwoni\u0105cego -message.no.description.available = Brak opisu -message.no.history.found = Historia rozm\u00f3w z tym u\u017cytkownikiem nie istnieje -message.no.results.found = Nie znaleziono szukanej frazy -message.no.room.to.join.error = Brak pokoju do do\u0142\u0105czenia -message.no.subject.available = Brak tematu -message.no.updates = Nie ma nowych aktualizacji -message.normal = Zwyk\u0142a wiadomo\u015b\u0107 -message.number.to.call = Wybierz numer do rozmowy g\u0142osowej -message.offline = U\u017cytkownik jest niedost\u0119pny, otrzyma t\u0105 wiadomo\u015b\u0107 przy nast\u0119pnym logowaniu -message.offline.error = U\u017cytkownik nie b\u0119dzie m\u00f3g\u0142 otrzymywa\u0107 wiadomo\u015bci offline -message.participants.in.room = Uczestnicy w pokoju -message.password.error = Podaj poprawne has\u0142o -message.password.private.room.error = Podaj poprawne has\u0142o do pokoju -message.passwords.no.match = Has\u0142a nie s\u0105 identyczne -message.please.join.in.conference = Do\u0142\u0105cz do mnie w konferencji -message.plugins.not.available = Nie mo\u017cna skontaktowa\u0107 si\u0119 z repozytorium wtyczek -message.prompt.plugin.uninstall = Czy jeste\u015b pewien, \u017ce chcesz wy\u0142\u0105czy\u0107 {0}? -message.received.file = Otrzyma\u0142e\u015b plik od {0} -message.receiving.file = Odbierasz plik od {0} -message.reconnect.attempting = Pr\u00f3buj\u0119 ponownie po\u0142\u0105czy\u0107 -message.reconnect.failed = Nie uda\u0142o si\u0119 po\u0142\u0105czy\u0107 ponownie -message.reconnect.wait = Ponowna pr\u00f3ba po\u0142\u0105czenia za {0} sekund -message.register.transports = Po\u0142\u0105cz do jednej z dost\u0119pnych bram -message.registering = \u0141\u0105cz\u0119 z {0}, prosz\u0119 czeka\u0107 -message.registration.transport.failed = Po\u0142\u0105czenie do podanej bramy niemo\u017cliwe -message.restart.spark = Musisz wy\u0142\u0105czy\u0107 Sparka aby zainstalowa\u0107 now\u0105 wersj\u0119, czy chcesz kontynuowa\u0107? -message.restart.spark.changes = Wtyczka zostanie usuni\u0119ta przy ponownym uruchomieniu komunikatora -message.restart.spark.to.install = Musisz wy\u0142\u0105czy\u0107 komunikator, aby zainstalowa\u0107 jego ostatni\u0105 wersj\u0119, chcesz to zrobi\u0107 teraz? -message.restart.required = Wymagany restart komunikatora aby wprowadzi\u0107 zmiany, zrestartowa\u0107 teraz? -message.room.creation.error = Nie mo\u017cna utworzy\u0107 pokoju -message.room.destroyed = Ten pok\u00f3j zosta\u0142 usuni\u0119ty z nast\u0119puj\u0105cego powodu: {0} -message.room.destruction.reason = Pow\u00f3d usuni\u0119cia pokoju? -message.room.information.for = Informacje o pokoju {0} -message.save.profile = Aby zapisa\u0107 zmiany w profilu, naci\u015bnij Zapisz -message.search.for.contacts = Szukaj kontakt\u00f3w -message.search.for.other.people = Szukaj innych os\u00f3b na serwerze -message.search.input.short = Podaj przynajmniej pi\u0119\u0107 liter. -message.search.service.not.available = Nie mo\u017cna skontaktowa\u0107 si\u0119 z us\u0142ug\u0105 wyszukiwania -message.searching.please.wait = Trwa wyszukiwanie, prosz\u0119 czeka\u0107 -message.select.add.room.to.add = Wybierz pok\u00f3j do dodania do listy us\u0142ug -message.select.one.or.more = Wybierz jednego lub wi\u0119cej u\u017cytkownik\u00f3w z listy kontakt\u00f3w -message.select.room.to.enter = Okre\u015bl pok\u00f3j, do kt\u00f3rego do\u0142\u0105czy\u0107 -message.select.room.to.join = Wybierz pok\u00f3j do do\u0142\u0105czenia -message.send.a.broadcast = Wy\u015blij wiadomo\u015b\u0107 grupow\u0105 -message.send.file.to.user = Wy\u015blij pliki do tego u\u017cytkownika -message.send.picture = Uchwy\u0107 i wy\u015blij zrzut ekranu -message.send.to.these.people = Wy\u015blij do tych os\u00f3b -message.sending.file.to = Wysy\u0142anie pliku do {0} -message.sent.offline.files = Otrzyma\u0142e\u015b plik(i) w trybie offline. -message.server.unavailable = Nie mo\u017cna po\u0142\u0105czy\u0107 z serwerem: nieprawid\u0142owa nazwa lub serwer niedost\u0119pny -message.service.already.exists = Us\u0142uga znajduje si\u0119 ju\u017c na li\u015bcie -message.shared.group = Grupa wsp\u00f3\u0142dzielona -message.spark.secure = Spark dzia\u0142a w trybie bezpiecznym -message.specify.contact.jid = Prosz\u0119 poda\u0107 JID kontaktu (np. ddman@jabber.org) -message.specify.group = Okre\u015b grup\u0119, do kt\u00f3rej doda\u0107 nowego u\u017cytkownika -message.specify.information.for.conference = Okre\u015bl informacje o pokoju konferencyjnym -message.specify.name.error = Podaj poprawn\u0105 nazw\u0119 -message.specify.users.to.join.conference = Okre\u015bl u\u017cytkownik\u00f3w do\u0142\u0105czanych do tego pokoju konferencyjnego -message.specify.valid.time.error = Podaj poprawny czas nieaktywno\u015bci i port -message.subject.change.error = Nie masz uprawnie\u0144 do zmiany tematu tego pokoju -message.subject.has.been.changed.to = {1} zmieni\u0142 temat na {0} -message.supply.resource = Podaj poprawne \u017ar\u00f3d\u0142o -message.supply.valid.port = Podaj poprawny port -message.supply.valid.timeout = Podaj poprawn\u0105 warto\u015b\u0107 czasu oczekiwania -message.timeout.error = Czas oczekiwania musi wynosi\u0107 minimum 5 sekund -message.total.downloaded = Ilo\u015b\u0107 wszystkich pobra\u0144 plik\u00f3w -message.transfer.cancelled = Przesy\u0142anie pliku zosta\u0142o anulowane -message.transfer.complete = Transfer pliku zosta\u0142 uko\u0144czony ({0}) -message.transfer.progressbar.text.received = {0} otrzymano @ {1} {2} -message.transfer.progressbar.text.sent = {0} wys\u0142ano @ {1} {2} -message.transfer.rate = Pr\u0119dko\u015b\u0107 przesy\u0142ania -message.transfer.refused = Przesy\u0142anie pliku odrzucone -message.transfer.waiting.on.user = Oczekiwanie na akceptacj\u0119 {0} przesy\u0142ania pliku -message.unable.to.load.profile = Nie mo\u017cna zlokalizowa\u0107 profilu dla {0} -message.unable.to.retrieve.last.activity = Nie mo\u017cna ustali\u0107 ostatniej aktywno\u015b\u0107 dla {0} -message.unable.to.save.password = Nie mo\u017cna zmieni\u0107 has\u0142a, skontaktuj si\u0119 z administratorem systemu -message.unable.to.send.file = Nie uda\u0142o si\u0119 wys\u0142a\u0107 pliku do {0} -message.unrecoverable.error = Niepoprawna nazwa u\u017cytkownika lub has\u0142o -message.update.room.list = Uaktualnij list\u0119 pokoi -message.updating.cancelled = Aktualizacja zosta\u0142a anulowana -message.user.banned = {0} zosta\u0142 zablokowany w tym pokoju. Pow\u00f3d: {1} -message.user.given.voice = {0} otrzyma\u0142 mo\u017cliwo\u015b\u0107 rozmowy g\u0142osowej w tym pokoju -message.user.granted.admin = {0} otrzyma\u0142 uprawnienia administracyjne -message.user.granted.membership = {0} otrzyma\u0142 uprawnienia cz\u0142onkowskie -message.user.granted.moderator = {0} otrzyma\u0142 uprawnienia moderatora -message.user.granted.owner = {0} otrzyma\u0142 uprawnienia w\u0142a\u015bciciela -message.user.is.sending.you.a.file = {0} wysy\u0142a do Ciebie plik -message.user.joined.room = {0} do\u0142\u0105czy\u0142 do pokoju -message.user.kicked.from.room = {0} zosta\u0142 usuni\u0119ty z pokoju przez {1}. Pow\u00f3d: {2} -message.user.left.room = {0} opu\u015bci\u0142 pok\u00f3j -message.user.nickname.changed = {0} jest znany jako {1} -message.user.now.available.to.chat = {0} jest dost\u0119pny od {1} -message.user.revoked.admin = Uprawnienia administratora zosta\u0142y odebrane u\u017cytkownikowi {0} -message.user.revoked.membership = Cz\u0142onkowstwo zosta\u0142o odebrane u\u017cytkownikowi {0} -message.user.revoked.moderator = Uprawnienia moderatora zosta\u0142y odebrane u\u017cytkownikowi {0} -message.user.revoked.owner = Uprawnienia w\u0142a\u015bciciela zosta\u0142y odebrane u\u017cytkownikowi {0} -message.user.voice.revoked = Mo\u017cliwo\u015b\u0107 rozmowy g\u0142osowej zosta\u0142a odebrana u\u017cytkownikowi {0} -message.username.error = Podaj nazw\u0119 u\u017cytkownika dla konta -message.username.password.error = Nazwa u\u017cytkownika i/lub has\u0142o nie mog\u0105 by\u0107 puste -message.vcard.not.supported = Serwer nie obs\u0142uguje wizyt\u00f3wek, nie mo\u017cna zapisa\u0107 wizyt\u00f3wki -message.version = Wersja: {0} -message.view.information.about.this.user = Zobacz informacje o tym u\u017cytkowniku -message.waiting.for.user.to.join = Oczekiwanie na po\u0142\u0105czenie u\u017cytkownika {0} -message.went.offline = {0} przeszed\u0142 w tryb niedost\u0119pny o {0} -message.you.have.been.banned = Zosta\u0142e\u015b zablokowany w tym pokoju -message.you.have.been.kicked = Zosta\u0142e\u015b wyrzucony z tego pokoju -message.you.have.sent = Wys\u0142a\u0142e\u015b plik do {0} -message.your.admin.granted = Otrzyma\u0142e\u015b uprawnienia administracyjne -message.your.banned = Zosta\u0142e\u015b zablokowany w tym pokoju -message.your.kicked = Zosta\u0142e\u015b wyrzucony przez {0} -message.your.membership.granted = Otrzyma\u0142e\u015b uprawnienia cz\u0142onkowskie -message.your.membership.revoked = Twoje cz\u0142onkowstwo zosta\u0142o anulowane -message.your.moderator.granted = Otrzyma\u0142e\u015b uprawnienia moderatora -message.your.moderator.revoked = Twoje uprawnienia moderatora zosta\u0142y anulowane -message.your.ownership.granted = Otrzyma\u0142e\u015b uprawnienia w\u0142a\u015bciciela -message.your.ownership.revoked = Twoje uprawnienia w\u0142a\u015bciciela zosta\u0142y anulowane -message.your.revoked.granted = Twoje uprawnienia administracyjne zosta\u0142y anulowane -message.your.voice.granted = Otrzyma\u0142e\u015b mo\u017cliwo\u015b\u0107 rozmowy g\u0142osowej w tej rozmowie -message.your.voice.revoked = Anulowano twoje uprawnienia do rozmowy g\u0142osowej -message.groupchat.require.password = Aby wej\u015b\u0107 do tego pokoju wymagane jest has\u0142o -message.groupchat.registered.member = Pomy\u015blnie zarejestrowany w {0} -message.search.for.history = Przeszukaj histori\u0119 rozmowy -message.search.period.month.one = miesi\u0105c na stronie -message.search.period.year.one = rok na stronie -message.search.period.none = poka\u017c wszystko na stronie -message.search.page.timeperiod = wybierz przedzia\u0142 czasu, jaki ma by\u0107 wy\u015bwietlony na stronie -message.search.page.counter = aktualny numer strony i og\u00f3lna ilo\u015b\u0107 stron -message.search.page.right = strona do przodu -message.search.page.left = strona do ty\u0142u - -status.away = Zaraz wracam -status.custom.messages = Opisy -status.do.not.disturb = Nie przeszkadza\u0107 -status.extended.away = B\u0119d\u0119 p\u00f3\u017aniej -status.free.to.chat = Mog\u0119 rozmawia\u0107 -status.on.phone = Telefonuj\u0119 -status.online = Dost\u0119pny -status.pending = Oczekuj\u0105cy -status.invisible = Niewidoczny -status.offline = Niedost\u0119pny - -tab.available.plugins = Dost\u0119pne wtyczki -tab.avatar = Awatar -tab.business = Praca -tab.conferences = Konferencje -tab.contacts = Kontakty -tab.general = Og\u00f3lne -tab.home = Dom -tab.installed.plugins = Zainstalowane wtyczki -tab.deactivated.plugins = Wy\u0142\u0105czone wtyczki -tab.personal = Osobiste -tab.proxy = Proxy -tab.sso = SSO -tab.pki = PKI - -title.about = O programie -title.password.required = Wymagane has\u0142o -title.task.notification = Powiadomienie o zadaniu -title.client.logs = Logi -title.advanced.connection.preferences = Zaawansowane opcje po\u0142\u0105czenia -title.account.create.registration = Rejestracja konta -title.bookmarks = Ulubione -title.account.created = Konto utworzone -title.add.contact = Dodaj kontakt -title.add.contact.group = Dodaj kontakt grupowy -title.add.new.group = Dodaj now\u0105 grup\u0119 -title.add.search.service = Dodaj us\u0142ug\u0119 wyszukiwania -title.add.to.roster = Dodaj do listy -title.address = Adres -title.advanced.connection.sso = U\u017cywam metody Using Single Sign-On (SSO) -title.advanced.connection.usesso = U\u017cyj metody Single Sign-On (SSO) via GSSAPI -title.advanced.connection.sso.account = To u\u017cyje konta logowania do pulpitu dla "{0}" aby zalogowa\u0107 do serwera. -title.advanced.connection.sso.unable = Nie mo\u017cna po\u0142\u0105czy\u0107 u\u017cywaj\u0105c Single Sign-On. Sprawd\u017a ustawienia. -title.advanced.connection.sso.noprincipal = Spark nie mo\u017ce znale\u017a\u0107 og\u00f3lnych ustawie\u0144 dla Single Sign-On. Pozwoli to zapobiec u\u017cywania SSO. -title.alert = Alert -title.appearance = Wygl\u0105d -title.appearance.preferences = Dostosuj -title.available.transports = Dost\u0119pne bramy -title.broadcast.message = Wiadomo\u015b\u0107 grupowa -title.browse.conference.services = Przegl\u0105daj us\u0142ugi konferencyjne -title.browse.room.service = Przegl\u0105daj pokoje konferencyjne - {0} -title.cancelled = Anulowano -title.change.nickname = Zmie\u0144 pseudonim -title.change.subject = Zmie\u0144 temat -title.chat = Rozmowa -title.choose.directory = Wybierz katalog -title.choose.incoming.sound = Wybierz plik d\u017awi\u0119kowy wiadomo\u015bci przychodz\u0105cej -title.choose.offline.sound = Wybierz plik d\u017awi\u0119kowy przej\u015bcia w tryb offline -title.choose.outgoing.sound = Wybierz plik d\u017awi\u0119kowy wiadomo\u015bci wychodz\u0105cej -title.conference.invitation = Zaproszenie do konferencji -title.conference.rooms = Pokoje konferencyjne -title.configure.chat.room = Konfiguruj pok\u00f3j rozm\u00f3w -title.configure.room = Konfiguruj pok\u00f3j -title.confirmation = Potwierdzenie -title.create.new.account = Utw\u00f3rz nowe konto -title.create.or.bookmark.room = Do\u0142\u0105cz lub za\u0142\u00f3\u017c pok\u00f3j -title.create.or.join = Utw\u00f3rz/do\u0142\u0105cz -title.create.problem = Problem z utworzeniem nowego konta -title.delete.file = Czy na pewno chcesz usun\u0105\u0107 ten plik? -title.dial.phone = Zadzwo\u0144 -title.disable.transport = Usu\u0144 informacj\u0119 logowania -title.download.complete = Pobieranie uko\u0144czone -title.downloading.im.client = Pobierz klienta IM -title.downloads = Pobrane pliki -title.edit.custom.message = Edytuj wiadomo\u015bci -title.edit.profile = Edytuj informacje o profilu -title.enter.reason = Podaj pow\u00f3d -title.error = B\u0142\u0105d -title.error.couldnt.open.file = Nie mo\u017cna otworzy\u0107 pliku -title.error.delete.file = Nie mo\u017cna usun\u0105\u0107 pliku -title.error.find.app = Nie mo\u017cna znale\u017a\u0107 odpowiedniej aplikacji -title.error.rename.file = Nie mo\u017cna zmieni\u0107 nazwy pliku -title.file = Plik -title.filesize = Rozmiar -title.file.exists = Plik istnieje -title.file.transfer = Transfer pliku -title.file.transfer.preferences = Ustawienia transferu plik\u00f3w -title.find.conference.service = Znajd\u017a us\u0142ug\u0119 konferencyjn\u0105 -title.find.contacts = Znajd\u017a kontakty -title.gadugadu.registration = Ustawienia konta Gadu-Gadu -title.general.media = Ustawienia audio -title.general.chat.settings = Ustawienia rozmowy -title.group.chat = Rozmowa grupowa -title.group.chat.settings = Ustawienia rozmowy grupowej -title.gtalk.registration = Ustawienia konta Gtalk -title.history.for = Historia rozm\u00f3w dla {0} -title.icq.registration = Ustawienia konta ICQ -title.aim.registration = Ustawienia konta AIM -title.irc.registration = Ustawienia konta IRC -title.sametime.registration = Ustawienia konta Sametime -title.facebook.registration = Ustawienia konta Facebook -title.myspace.registration = Ustawienia konta MySpace -title.incoming.call = Po\u0142\u0105czenie przychodz\u0105ce -title.input.fileexplorer = Wstaw nazw\u0119 przegl\u0105darki plik\u00f3w: -title.input.newname = Wpisz now\u0105 nazw\u0119: -title.input.openwith = Wpisz nazw\u0119 aplikacji, kt\u00f3rej zamierzasz u\u017cywa\u0107: -title.invite.to.conference = Zapro\u015b do konferencji -title.jabber.browser = Przegl\u0105darka -title.join.conference.room = Do\u0142\u0105cz do pokoju konferencyjnego -title.last.activity = Ostatnia aktywno\u015b\u0107 -title.login = Login -title.login.error = B\u0142\u0105d logowania -title.login.settings = Ustawienia logowania -title.login.no.account = Nie mo\u017cna okre\u015bli\u0107 -title.lookup.profile = Przegl\u0105daj profil -title.msn.registration = Ustawienia konta MSN -title.name = Nazwa -title.new.client.available = Dost\u0119pna nowa wersja klienta -title.new.roster.group = Nowa wsp\u00f3\u0142dzielona grupa kontakt\u00f3w -title.new.version.available = Dost\u0119pna nowa wersja -title.no.updates = Brak nowych aktualizacji -title.notes = Notatki -title.notification = Powiadomienie -title.notifications = Powiadomienia -title.occupants = Uczestnicy -title.on.the.phone = W trakcie rozmowy -title.password = Has\u0142o -title.passwords.no.match = Potwierd\u017a has\u0142o -title.person.search = Szukaj osoby -title.plugins = Wtyczki -title.preferences = Ustawienia -title.profile.information = Informacja o profilu -title.profile.not.found = Nie znaleziono profilu -title.qq.registration = Ustawienia konta QQ -title.register.account = Zarejestruj nowe konto -title.registration.error = B\u0142\u0105d rejestracji -title.reminder = Przypomnienie -title.rename.roster.group = Zmie\u0144 nazw\u0119 wsp\u00f3\u0142dzielonej grupy kontakt\u00f3w -title.room.destroyed = Pok\u00f3j zosta\u0142 zamkni\u0119ty -title.room.information = Informacja o pokoju -title.roster = Wsp\u00f3\u0142dzielona grupa kontakt\u00f3w -title.select.file.to.send = Wybierz plik(i) do wys\u0142ania -title.set.status.message = Ustaw status -title.simple.registration = Ustawienia konta SIMPLE -title.sound.preferences = Ustawienia d\u017awi\u0119k\u00f3w -title.sounds = D\u017awi\u0119ki -title.spark.preferences = Ustawienia Spark -title.start.chat = Rozpocznij rozmow\u0119 -title.status.message = Status -title.tasks = Zadania -title.transports = Bramy -title.tray.information = Informacja na pasku systemowym -title.upgrading.client = Aktualizacja klienta -title.version.and.time = Wersja i czas -title.view.bookmarks = Poka\u017c ulubione -title.view.profile.for = Informacje o profilu u\u017cytkownika {0} -title.view.room.information = Poka\u017c informacj\u0119 o pokoju -title.waiting.to.call = Oczekiwanie na rozmow\u0119 g\u0142osow\u0105 -title.xmpp.registration = Ustawienia konta XMPP -title.yahoo.registration = Ustawienia konta Yahoo -title.appearance.showVCards = Pokazuj wizyt\u00f3wki na li\u015bcie kontakt\u00f3w -title.subscription.request = Pro\u015bba o dodanie - -tooltip.place.a.call = Zadzwo\u0144 do tej osoby -tooltip.appearance = Zmie\u0144 wygl\u0105d okna rozm\u00f3w -tooltip.file.transfer = Ustawienia transferu plik\u00f3w -tooltip.notifications = Ustawienia powiadomie\u0144 dla nadchodz\u0105cych rozm\u00f3w -tooltip.place.voice.call = Zadzwo\u0144 do tego u\u017cytkownika -tooltip.send.email = Wy\u015blij e-mail -tooltip.start.chat = Rozpocznij rozmow\u0119 -tooltip.view.changelog = Podgl\u0105d dziennika zdarze\u0144 -tooltip.view.history = Podgl\u0105d historii rozm\u00f3w -tooltip.view.readme = Zobacz plik readme - -tree.conference.services = Us\u0142ugi konferencyjne -tree.users.in.room = U\u017cytkownicy w pokoju - -lookandfeel.select = Wybierz systemowy wygl\u0105d -lookandfeel.change.now = Zmie\u0144 teraz -lookandfeel.tooltip.restart.no = Nie jest wymagany restart -lookandfeel.tooltip.restart.yes = Aby w\u0142\u0105czy\u0107 systemowy wygl\u0105d naci\u015bnij Zapisz i zresetuj Sparka. -lookandfeel.color.label = Kolory -lookandfeel.color.red = Czerwony -lookandfeel.color.green = Zielony -lookandfeel.color.blue = Niebieski -lookandfeel.color.opacity = Przezroczysto\u015b\u0107 -lookandfeel.color.saved = Kolor zapisany - -##Ustawienia wtyczki prywatnosci -privacy.title.preferences = W\u0142a\u015bciwo\u015bci prywatno\u015bci Sparka -privacy.title.panel = Prosz\u0119 u\u017cyj prawego przycisku myszy -privacy.label.iq.desc = Zapytanie -privacy.label.pin.desc = Obecno\u015b\u0107 -privacy.label.pout.desc = Nieobecno\u015b\u0107 -privacy.label.msg.desc = Wiadomo\u015bci -privacy.border.information = Informacje o prywatno\u015bci -privacy.label.information = U\u017cyj menu prawego przycisku myszy aby doda\u0107 lub usun\u0105\u0107 listy lub elementy -privacy.root.node = Listy prywatno\u015bci -privacy.label.preferences = Wtyczka prywatno\u015bci -pricacy.tooltip.preferences = Ustawienia prywatno\u015bci Sparka -privacy.label.list.is.active = AKTYWNA -privacy.label.list.is.default = DOMY\u015aLNA -privacy.border.block = Zablokuj -privacy.pick.one.or.more = Wybierz jeden lub wi\u0119cej element\u00f3w aby doda\u0107 do listy -privacy.title.add.picker = Dodaj elementy do listy -privacy.node.contacts = Kontakty -privacy.node.groups = Grupy -privacy.menu.add.contacts = Dodaj kontakty do listy -privacy.menu.add.groups = Dodaj grupy do listy -privacy.menu.add.rem.items = Usu\u0144 {0} elementy z listy -privacy.menu.remove = Usu\u0144 -privacy.menu.activate.list = Aktywuj -privacy.menu.default.list = Ustaw jako domy\u015blne -privacy.menu.add.list = Dodaj list\u0119 -privacy.menu.remove.list = Usu\u0144 list\u0119 -privacy.dialog.add.list = Wpisz nazw\u0119 listy -privacy.dialog.rem.list = Czy na pewno chcesz usun\u0105\u0107 {0}? -privacy.status.menu.entry = Listy prywatno\u015bci -privacy.name.for.default.list = Domy\u015blna -privacy.button.no.list.selected = Nie wybrano listy -privacy.menuitem.deactivate.current.list = Deaktywuj obecn\u0105 list\u0119 {0} -privacy.label.not.supported = Prywatne listy nie s\u0105 obs\u0142ugiwane przez serwer. - -##Ustawienia stunfallback w mediach -stun.border.label = Awaryjny serwer STUN -stun.server.addr = Serwer STUN: -stun.server.port = Port STUN: - -composing = {0} pisze... -paused = {0} przesta\u0142 pisa\u0107 -active = {0} zwraca uwag\u0119 -inactive = {0} robi co\u015b innego -gone = {0} robi co\u015b innego - -#!# -action.viewlog=Zobacz plik logu - -dialog.confirm.to.reveal.visibility.title=Jeste\u015b pewny? -dialog.confirm.to.reveal.visibility.msg=Je\u015bli b\u0119dziesz kontynuowa\u0142, Twoja niewidoczno\u015b\u0107 zostanie wy\u0142\u0105czona -dialog.confirm.close.all.conferences.if.invisible.msg=Je\u015bli b\u0119dziesz kontynuowa\u0142 wszystkie pokoje konferencyjne zostan\u0105 zamkni\u0119te \ No newline at end of file diff --git a/src/resources/i18n/spark_i18n_pt_BR.properties b/src/resources/i18n/spark_i18n_pt_BR.properties deleted file mode 100644 index 95ebaeee4..000000000 --- a/src/resources/i18n/spark_i18n_pt_BR.properties +++ /dev/null @@ -1,772 +0,0 @@ -# Spark - -ok = Ok -cancel = Cancelar -use.default = Usar Padr\u00e3o -close = Fechar -create = Criar -invite = Convidar -date = data -add = Adicionar -from = De -room.name = Nome da Sala -join = Participar -description = Descri\u00e7\u00e3o -subject = Assunto -occupants = Ocupantes -accept = Aceitar -reject = Rejeitar -open = Abrir -open.folder = Abrir Pasta -retry = Repetir -active = Ativo -not.registered = N\u00e3o Registrado -save = Salvar -yes = Sim -no = N\u00e3o -message = Mensagem - -button.create.account = &Criar Conta -button.close = &Fechar -button.advanced = A&van\u00e7ado -button.browse = &Listar... -button.browse2 = &Listar... -button.browse3 = &Listar... -button.approve = &Aprovar -button.deny = &Rejeitar -button.accept = &Aceitar -button.profile = &Perfil -button.add.a.contact = &Adicionar Contato -button.reconnect = &Reconectar -button.add = &Adicionar -button.roster = &Contatos -button.add.bookmark = Adicionar Marcador -button.remove.bookmark = Remover Marcador -button.bookmark.room = &Marcar Sala -button.create.room = &Criar ou entrar em sala -button.join.room = &Entrar na Sala Selecionada -button.refresh = &Atualizar -button.find = &Encontrar -button.update = &Atualizar -button.cancel = &Cancelar -button.decline = &N\u00e3o Aceitar -button.join = &Participar -button.save.for.future.use = &Salvar -button.register = &Registrar -button.dial.number = &Chamar N\u00famero -button.clear = &Limpar -button.search = &Procurar -button.add.service = &Adicionar Servi\u00e7o -button.new = &Novo -button.view.tasklist = Ver tarefas -button.view.notes = Ver notas - -checkbox.save.password = &Salvar Senha -checkbox.enable.emoticons = Habilitar Em&oticons -checkbox.auto.login = &Login Autom\u00e1tico -checkbox.use.proxy.server = &Usar Proxy -checkbox.auto.discover.port = &Resolver endere\u00e7o e porta automaticamente -checkbox.permanent = Sala &permanente -checkbox.private.room = Sala pri&vada -checkbox.show.time.in.chat.window = &Mostrar hora na janela de chat -checkbox.show.notifications.in.conference = &Mostrar notifica\u00e7\u00f5es nas salas de confer\u00eancia -checkbox.disable.chat.history = &Desabilitar Hist\u00f3rico de Chat -checkbox.show.toaster = Mostrar Popup estilo torradeira -checkbox.window.to.front = &Trazer Janela para o Topo -checkbox.play.sound.on.new.message = Tocar sons quando &receber mensagem -checkbox.play.sound.when.offline = Tocar sons quando usu\u00e1rio ficar &offline -checkbox.play.sound.on.outgoing.message = Tocar sons quando &enviar mensagem -checkbox.play.sound.on.invitation = Tocar sons quando receber convite -checkbox.allow.buzz = Permitir que usu\u00e1rios chamem sua aten\u00e7\u00e3o -checkbox.idle.enabled = &Ausente Habilidado -checkbox.launch.on.startup = &Executar ao Iniciar -checkbox.start.in.tray = &Iniciar na Bandeja -checkbox.split.chat.window = Dock &Windows (Necessita reiniciar) -checkbox.notify.user.goes.offline = Notificar quando usu\u00e1rio ficar offline. -checkbox.notify.user.comes.online = Notificar quando usu\u00e1rio ficar online. -checkbox.use.system.look.and.feel = Usar gr\u00e1ficos do sistema (Necess\u00e1rio Reiniciar) - -label.change.password.to = &Trocar senha para -label.chatroom.fontsize = Tamanho da fonte no Chat: -label.username = &Usu\u00e1rio -label.name = &Nome -label.room.name = &Nome da Sala -label.room.topic = &T\u00f3pico da Sala -label.password = &Senha -label.confirm.password = &Confirme a senha -label.server = &Servidor -label.create.account = Criar &Conta -label.close = Fe&char -label.ok = OK -label.cancel = Cancelar -label.use.default = Usar \u00e3 -label.port = &Porta -label.response.timeout = &Tempo de Resposta Esgotado -label.auto.login = &Login Autom\u00e1tico -label.contactlist.fontsize = Tamanho da fonte da &lista de contatos: -label.old.ssl = &Usar m\u00e9todo antigo de porta SSL -label.host = &Endere\u00e7o -label.resource = &Recursos -label.protocol = &Protocolo -label.accounts = &Contas -label.transfer.timeout = &Tempo M\u00e1ximo de Transfer\u00eancia(min): -label.transfer.download.directory = &Pasta de Download: -label.find = &Encontrar -label.rename.to = Renomear para -label.contact.to.find = Contato a ser Encontrado? -label.available.users.in.roster = &Usu\u00e1rios Online na Lista de Contatos -label.time = Tempo: {0} -label.add.conference.service = &Adicionar Servi\u00e7o de Confer\u00eancia -label.add.jid = &Adicionar JID -label.message = &Mensagem -label.room = &Sala -label.invited.users = Usu\u00e1rios Convidados -label.new.nickname = Novo Apelido -label.server.address = &Endere\u00e7o do Servidor -label.nickname = &Apelido -label.presence = &Presen\u00e7a -label.priority = P&rioridade -label.enter.address = Endere\u00e7o -label.jabber.address = &Endere\u00e7o Jabber -label.local.time = &Hora Local -label.software = &Software -label.version = &Vers\u00e3o -label.os = &Sistema Operacional -label.number = &N\u00famero -label.dial = &Chamar -label.minutes.before.stale.chat = &Minutos necess\u00e1rios para que a Sala fique obsoleta -label.company = &Empresa -label.street.address = &Endere\u00e7o -label.city = &Cidade -label.state.and.province = E&stado -label.postal.code = &CEP -label.country = &Pa\u00eds -label.job.title = &Profiss\u00e3o -label.department = &Departamento -label.phone = &Telefone -label.fax = &Fax -label.mobile = &Celular -label.web.page = &P\u00e1gina Web -label.pager = &Pager -label.first.name = &Primeiro Nome -label.middle.name = &Nome do Meio -label.last.name = &\u00faltimo Nome -label.email.address = &Endere\u00e7o de Email -label.jid = &JID -label.search.service = &Servi\u00e7os de Procura -label.xmpp.port = &Porta XMPP -label.time.till.idle = &Tempo antes de Ausentar (min) -label.group = &Grupo -label.enter.group.name = Digite o nome do grupo - -message.username.error = Especificar um nome de usu\u00e1rio para esta conta. -message.password.error = Especificar uma senha para esta conta. -message.confirmation.password.error = Especificar senha de confirma\u00e7\u00e3o. -message.account.error = Especificar o servidor em que a conta ser\u00e1 criada. -message.registering = Registrando como {0}. Aguarde... -message.connection.failed = Imposs\u00edvel Conectar{0}. -message.create.account = A conta n\u00e3o pode ser criada. -message.already.exists = A conta j\u00e1 existe. Tente um nome de usu\u00e1rio diferente. -message.account.created = Nova conta criada. -message.account.create = Criar uma nova conta de Chat. -message.connecting.please.wait = Conectando. Aguarde... -message.supply.valid.timeout = Informe um tempo de resposta v\u00e1lido. -message.supply.valid.port = Informe uma porta v\u00e1lida. -message.supply.resource = Informe um recurso v\u00e1lido. -message.current.status = Permitir que outros usu\u00e1rios vejam meu estado atual. -message.disconnected.error = Ocorreu um erro e sua conex\u00e3o foi fechada.. -message.disconnected.conflict.error = Sua conex\u00e3o foi desconectada pois o seu usu\u00e1rio logou em outro local. -message.locked.workstation = Usu\u00e1rio bloqueou sua esta\u00e7\u00e3o de trabalho. -message.away.idle = Ausente por Inatividade. -message.default.error = Um erro foi encontrado. Informe ao support@jivesoftware.com. -message.new.message = Nova mensagem de {0}. -message.send.file.to.user = Enviar arquivos para este usu\u00e1rio. -message.send.picture = Enviar a imagem de seu desktop. -message.sent.offline.files = You have just been sent offline file(s). -message.spark.secure = Spark est\u00e1 funcionando em modo seguro. -message.search.for.contacts = Buscar Contatos. -message.end.conversation = Voc\u00ea deseja terminar esta sess\u00e3o? -message.end.chat = Voc\u00ea deseja terminar este Chat? -message.close.this.chat = Fechar este Chat -message.close.other.chats = Fechar os outros Chats -message.close.stale.chats = Fechar Chats obsoletos -message.last.message.received = \u00faltima mensagem recebida em {0} -message.shared.group = Grupo compartilhado -message.is.shared.group = {0} \u00e9 um grupo compartilhado. -message.delete.confirmation = Voc\u00ea tem certeza que deseja remover {0}? -message.idle.for = Ausente por {0} -message.enter.broadcast.message = Entre com a mensagem a ser enviada aos usu\u00e1rios selecionados. -message.name.of.group = Nome do Grupo -message.approve.subscription = Permitir {0} que adicione voc\u00ea na lista dele? -message.add.user = Adicionar usu\u00e1rio a sua lista? -message.general.error = Voc\u00ea perdeu sua conex\u00e3o com o servidor devido a {0}. -message.add.a.contact = Adicionar Contato. -message.generic.reconnect.message = Voc\u00ea perdeu sua conex\u00e3o com o servidor. Para conectar novamente click em Reconectar -message.select.one.or.more = Seleciona um ou mais usu\u00e1rios de sua lista. -message.add.conference.service = Adicionar um servi\u00e7o de confer\u00eancia. -message.service.already.exists = Servi\u00e7o j\u00e1 se encontra em sua lista. -message.searching.please.wait = Procurando. Aguarde... -message.conference.service.error = Imposs\u00edvel localizar o servi\u00e7o de confer\u00eancia. -message.create.or.join.room = Criar ou participar de uma sala de confer\u00eancia -message.specify.name.error = Especifique um nome v\u00e1lido. -message.password.private.room.error = Especifique a senha para a sala privada. -message.passwords.no.match = Senhas n\u00e3o coincidem. -message.enter.valid.jid = Informe um JID v\u00e1lido -message.please.join.in.conference = Por favor me adicione a confer\u00eancia. -message.invite.users.to.conference = Convidar usu\u00e1rios para a sala de confer\u00eancia. -message.specify.users.to.join.conference = Especificar usu\u00e1rios desta sala de confer\u00eancia. -message.no.room.to.join.error = Nenhuma sala para participar -message.participants.in.room = Participantes na Sala -message.you.have.been.kicked = Voc\u00ea foi expulso desta sala. -message.kicked.error = Voc\u00ea n\u00e3o pode expulsar {0} desta sala. -message.you.have.been.banned = Voc\u00ea foi banido desta sala. -message.nickname.in.use = Apelido em uso. Selecione outro. -message.update.room.list = Atualizar a lista da sala -message.join.conference.room = Participar da sala de confer\u00eancia -message.select.add.room.to.add = Selecione uma sala para adicionar a sua lista de servi\u00e7os -message.bookmark.temporary.room.error = Voc\u00ea n\u00e3o pode marcar salas tempor\u00e1rias -message.select.room.to.join = Selecione a sala para entrar. -message.conference.info.error = Imposs\u00edvel receber informa\u00e7\u00f5es de confer\u00eancia. Tenter mais tarde. -message.add.favorite.room = Adicionar aos favoritos ou participar da Sala. -message.select.room.to.enter = Especifique a sala para entrar. -message.find.conference.services = Encontrar servi\u00e7os de confer\u00eancia -message.specify.information.for.conference = Especifique as informa\u00e7\u00f5es para a sala de confer\u00eancia -message.no.description.available = N\u00e3o h\u00e1 descri\u00e7\u00e3o dispon\u00edvel -message.no.subject.available = N\u00e3o h\u00e1 t\u00edtulo dispon\u00edvel -message.room.information.for = Informa\u00e7\u00e3o sobre a sala para {0} -message.view.information.about.this.user = Ver informa\u00e7\u00f5es deste usu\u00e1rio. -message.add.this.user.to.your.roster = Adicionar a lista de Amigos. -message.came.online = {0} ficou online as {1} -message.went.offline = {0} ficou offline as {1} -message.offline.error = O usu\u00e1rio n\u00e3o poder\u00e1 receber mensagens offline. -message.offline = O usu\u00e1rio receber\u00e1 as mensagens na pr\u00f3xima conex\u00e3o. -message.is.typing.a.message = {0} est\u00e1 digitando... -message.enter.new.subject = Entre o novo assunto -message.confirm.destruction.of.room = Remover a sala, remove todos os usu\u00e1rios que nela est\u00e3o. Continuar? -message.room.destruction.reason = Motivo para remover a sala? -message.user.left.room = {0} saiu da sala. -message.user.joined.room = {0} entrou na sala. -message.chat.session.ended = Chat encerrou as {0} -message.subject.change.error = Voc\u00ea n\u00e3o pode mudar o assunto desta sala. -message.forbidden.error = Erro de permiss\u00e3o recebido. -message.room.destroyed = A sala foi removida pela seguinte raz\u00e3o: {0} -message.subject.has.been.changed.to = O assunto mudou para {0}. -message.user.kicked.from.room = {0} foi expulso da sala. -message.user.given.voice = Foi dado a palavra a {0} nesta sala. -message.user.voice.revoked = Palavra revogada para {0}. -message.user.banned = {0} foi banido desta sala. -message.user.granted.membership = {0} foi dado privil\u00e9gios de membro. -message.user.revoked.membership = Remo\u00e7\u00e3o do membro {0}. -message.user.granted.moderator = {0} possui privilegios de moderador. -message.user.revoked.moderator = Privilegios de Modeerador revogados para {0}. -message.user.granted.owner = {0} possui privil\u00e9gios de criador. -message.user.revoked.owner = Privil\u00e9gios de Criador foram revogados para {0}. -message.user.granted.admin = {0} possui Privil\u00e9gios de Administrador. -message.user.revoked.admin = Privil\u00e9gios de Administrador foram revogados para {0}. -message.user.nickname.changed = {0} agora \u00e9 {1}. -message.your.kicked = Voc\u00ea foi expulso de {0}. -message.your.voice.granted = Voc\u00ea recebeu a palavra neste Chat. -message.your.voice.revoked = Sua palavra foi revogada. -message.your.banned = Voc\u00ea foi expulso desta sala. -message.your.membership.granted = Voc\u00ea possui privil\u00e9gios de membro. -message.your.membership.revoked = Sua associa\u00e7\u00e3o foi revogada. -message.your.moderator.granted = Voc\u00ea possui privil\u00e9gios de moderador. -message.your.moderator.revoked = Your moderator privileges have been revoked. -message.your.ownership.granted = Voc\u00ea possui privil\u00e9gios de criador. -message.your.ownership.revoked = Seus privil\u00e9gios de criador foram revogados. -message.your.admin.granted = Voc\u00ea possui privil\u00e9gios de administrador. -message.your.revoked.granted = Seus privil\u00e9gios de administrador foram revogados. -message.send.a.broadcast = Enviar Mensagem em massa -message.broadcast.from = Mensagem em massa de {0} -message.enter.message.to.broadcast = Entre com a mensagem a ser enviada para toda sua lista de contatos. -message.broadcast.message.sent = A mensagem foi enviada em massa. -message.broadcast.to = Entre com a mensagem as ser enviada para {0} -message.broadcasted.to = A mensagem foi enviada aos seguintes usu\u00e1rios:\n{0} -message.user.now.available.to.chat = {0} est\u00e1 online as {1} -message.user.is.sending.you.a.file = {0} est\u00e1 lhe enviando um arquivo. -message.file.transfer.canceled = Voc\u00ea cancelou a transfer\u00eancia do arquivo. -message.negotiate.file.transfer = Negociando transfer\u00eancia de Arquivo. Aguarde... -message.negotiate.stream = Negociando transmiss\u00e3o. Aguarde... -message.receiving.file = Voc\u00ea est\u00e1 recebendo um arquivo de {0} -message.click.to.open = Clique para abrir -message.error.during.file.transfer = Ocorreu um erro durante a transfer\u00eancia. -message.transfer.refused = A transfer\u00eancia foi recusada. -message.transfer.cancelled = A transfer\u00eancia foi cancelada. -message.received.file = Voc\u00ea recebeu um arquivo de {0}. -message.file.exists.question = O arquivo j\u00e1 existe. Deseja substituir? -message.transfer.waiting.on.user = Aguardando {0} aceitar a transfer\u00eancia. -message.negotiation.file.transfer = Negociando a transfer\u00eancia com {0}. Please wait... -message.unable.to.send.file = Voc\u00ea n\u00e3o pode enviar o arquivo para {0}. -message.sending.file.to = Enviando arquivo para {0}. -message.you.have.sent = Voc\u00ea enviou um arquivo para {0}. -message.file.transfer.rejected = A transfer\u00eancia de arquivo n\u00e3o \u00e9 aceita por {0}. -message.disable.transport = Voc\u00ea deseja desabilitar os transportes? -message.register.transports = Registrar com os transportes instalados. -message.enter.aim = Entre com seu usu\u00e1rio e senha do AIM abaixo. -message.enter.msn = Entre com seu usu\u00e1rio e senha do MSN abaixo. -message.enter.yahoo = Entre com seu usu\u00e1rio e senha do Yahoo. -message.username.password.error = Usu\u00e1rio e Senha n\u00e3o necessitam ser informados. -message.registration.transport.failed = N\u00e3o foi poss\u00edvel registrar com transporte. -message.client.information = Informa\u00e7\u00e3o do Cliente para {0} -message.calling = Chamando {0} -message.number.to.call = Especifique o numero a ser chamado -message.no.caller.id = Sem identifica\u00e7\u00e3o -message.no.history.found = N\u00e3o h\u00e1 hist\u00f3rico de conversas com este usu\u00e1rio. -message.prompt.plugin.uninstall = Voc\u00ea tem certeza que deseja desinstalar {0}? -message.loading.please.wait = Carregando. Aguarde... -message.plugins.not.available = N\u00e3o foi poss\u00edvel contactar o reposit\u00f3rio de plugins. -message.downloading = Realizando o Download {0} -message.downloading.spark.plug = Realizando o Download do Spark-Plug -message.unable.to.save.password = N\u00e3o foi poss\u00edvel alterar a senha. Contate o seu administrador. -message.delete.all.history = Excluir todas as conversas anteriores?? -message.no.avatar.found = Usu\u00e1rio n\u00e3o possui Avatar. -message.image.too.large = Esta imagem \u00e9 muito grande para ser usada. Especifique uma imagem de 16k ou menos. -message.save.profile = Para salvar seu perfil, clique em Salvar. -message.unable.to.load.profile = Imposs\u00edvel localizar perfil de {0} -message.enter.jabber.id = Entre com o ID Jabber -message.invalid.jabber.id = ID Jabber inv\u00e1lido -message.vcard.not.supported = Servidor n\u00e3o suporta VCards. Imposs\u00edvel salvar. -message.search.service.not.available = N\u00e3o foi poss\u00edvel contactar o servi\u00e7o de busca. -message.no.results.found = N\u00e3o foi retornado nenhum resultado de busca. -message.name.of.search.service.question = Nome do servi\u00e7o de busca? -message.search.for.other.people = Buscar outras pessoas no servidor. -message.specify.valid.time.error = Especifique o tempo m\u00e1ximo e a porta. -message.timeout.error = O tempo m\u00e1ximo deve ser de 5 segundos ou mais. -message.version = Vers\u00e3o: {0} -message.file.size = Tamanho do Arquivo: {0} -message.restart.spark = Voc\u00ea precisa reiniciar o cliente para instalar a nova vers\u00e3o. Deseja fazer isto agora? -message.updating.cancelled = A atualiza\u00e7\u00e3o foi cancelada. -message.transfer.rate = Taxa de transfer\u00eancia -message.total.downloaded = Total recebido -message.new.spark.available = {0} est\u00e1 dispon\u00edvel. Voc\u00ea deseja instalar? -message.restart.spark.to.install = Voc\u00ea precisa reiniciar o cliente para instalar a mais nova vers\u00e3o. Deseja fazer isto agora? -message.add.to.roster = Adicionar a lista -message.add.contact.to.list = Adicionar usu\u00e1rio na lista de contatos -message.send.to.these.people = Enviar para as seguintes pessoas -message.normal = Mensagem Normal -message.alert.notify = Notificar como Alerta - -title.passwords.no.match = Confirme a senha. -title.appearance = Apar\u00eancia -title.appearance.preferences = Personaliza\u00e7\u00e3o -title.create.problem = Problema na cria\u00e7\u00e3o de conta -title.account.created = Conta criada -title.create.new.account = Criar nova conta -title.account.create.registration = Registro de conta -title.register.account = Registrar nova conta -title.notification = Notifica\u00e7\u00e3o -title.advanced.connection.preferences = Prefer\u00eancias Avan\u00e7adas de Conex\u00e3o -title.error = Erro -title.status.message = Messagem de Status -title.spark.preferences = Preferencias -title.alert = Alerta -title.tray.information = Tray Information -title.select.file.to.send = Selecione Arquivo(s) Para Enviar -title.choose.directory = Selecione a Pasta -title.confirmation = Confirma\u00e7\u00e3o -title.last.activity = Ultima atividade -title.add.new.group = Adicionar novo grupo -title.add.to.roster = Adicionar a Lista -title.find.contacts = Buscar Contatos -title.rename.roster.group = Renomear Grupo de Contato -title.roster = Lista de Contato -title.create.or.join = Criar/Participar -title.conference.rooms = Salas de Confer\u00eancia -title.invite.to.conference = Convidar para a Confer\u00eancia -title.room.information = Informa\u00e7\u00f5es da Sala -title.change.nickname = Trocar Apelido -title.group.chat = Chat em Grupo -title.create.or.bookmark.room = Entrar em Sala Marcada -title.browse.room.service = Listar Salas de Confer\u00eancia - {0} -title.name = Nome -title.address = Endere\u00e7o -title.occupants = Ocupantes -title.browse.conference.services = Listar servi\u00e7os de Confer\u00eancia -title.find.conference.service = Encontrar servi\u00e7os de confer\u00eancia -title.configure.chat.room = Configurar Janela de Chat -title.conference.invitation = Convite de Confer\u00eancia -title.join.conference.room = Entrar em Sala de Confer\u00eancia -title.view.room.information = Ver Informa\u00e7\u00f5es da Sala -title.configure.room = Configurar Sala -title.change.subject = Trocar Assunto -title.enter.reason = Entre com o Motivo -title.room.destroyed = Sala Removida -title.edit.custom.message = Editar Mensagens Customizadas -title.set.status.message = Selecionar status -title.broadcast.message = Espalhar Mensagem -title.start.chat = Iniciar Chat -title.view.bookmarks = Ver Marcadores -title.downloads = Downloads -title.file.exists = Arquivo Encontrado -title.disable.transport = Disabilitar Transporte -title.available.transports = Transportes dispon\u00edveis -title.transports = Transportes -title.aim.registration = Registro AIM -title.msn.registration = Registro MSN -title.yahoo.registration = Registro Yahoo -title.registration.error = Erro ao Registrar -title.jabber.browser = Listar -title.version.and.time = Vers\u00e3o e Hora -title.waiting.to.call = Aguardando para fazer liga\u00e7\u00e3o -title.incoming.call = Liga\u00e7\u00e3o Recebida -title.on.the.phone = No Telefone -title.dial.phone = Chamar Telefone -title.history.for = Hist\u00f3rico de Chat com {0} -title.reminder = Alerta -title.plugins = Plugins -title.preferences = Prefer\u00eancias -title.general.chat.settings = Prefer\u00eancias Gerais de Chat -title.chat = Chat -title.notifications = Notifica\u00e7\u00f5es -title.sound.preferences = Prefer\u00eancias de Som -title.sounds = Sons -title.choose.incoming.sound = Escolha o som de Recebimento -title.choose.outgoing.sound = Escolha o som de Envio -title.choose.offline.sound = Escolha o som de Desconectado -title.edit.profile = Editar informa\u00e7\u00f5es do Perfil -title.profile.information = Informa\u00e7\u00f5es do Perfil -title.profile.not.found = Perfil n\u00e3o Encontrado -title.view.profile.for = Vendo o perfil de {0} -title.lookup.profile = Verificar Perfil -title.add.search.service = Adicionar Servi\u00e7o de Pesquisa -title.person.search = Busca de Pessoas -title.login.settings = Prefer\u00eancias de Login -title.login = Login -title.downloading.im.client = Fazer Download do Cliente de IM -title.upgrading.client = Atualizando Cliente -title.cancelled = Cancelado -title.new.version.available = Nova Vers\u00e3o Dispon\u00edvel -title.new.client.available = Novo Cliente Dispon\u00edvel -title.file.transfer.preferences = Prefer\u00eancias de Transfer\u00eancia -title.file.transfer = Transfer\u00eancia de Arquivo -title.add.contact = Adicionar Contato -title.new.roster.group = Novo Grupo - -menuitem.about = Sobre -menuitem.contacts = Contatos -menuitem.actions = A\u00e7\u00f5es -menuitem.exit = Sair -menuitem.plugins = &Plugins -menuitem.logout.no.status = Log out -menuitem.logout.with.status = Log out com motivo -menuitem.show.traffic = Ver Janela de Tr\u00e1fego -menuitem.check.for.updates = Verificar Atualiza\u00e7\u00f5es -menuitem.help = Ajuda -menuitem.preferences = Prefer\u00eancias -menuitem.online.help = Ajuda Online -menuitem.open = Abrir -menuitem.hide = Esconder -menuitem.status = Status -menuitem.view.downloads = Ver Downloads -menuitem.view.logs = Ver Logs -menuitem.save = Salvar -menuitem.add = Adicionar -menuitem.add.contact = Adicionar Contato -menuitem.add.contact.group = Adicionar Grupo de Contatos -menuitem.remove.from.group = Remover Grupo de Contatos -menuitem.start.a.chat = Iniciar um Chat -menuitem.rename = Renomear -menuitem.delete = Remover -menuitem.edit = Editar -menuitem.remove.from.roster = Remover da Lista -menuitem.view.profile = Ver Perfil -menuitem.subscribe.to = Inscrever em -menuitem.send.a.message = Enviar mensagem... -menuitem.show.empty.groups = Mostrar grupos vazios -menuitem.send.a.file = Enviar arquivo -menuitem.view.last.activity = Ver \u00faltima atividade -menuitem.unban = Remover banido -menuitem.ban = Banir -menuitem.browse.service = Listar Servi\u00e7os -menuitem.remove.service = Remover Servi\u00e7o -menuitem.join.room = Entrar na Sala -menuitem.remove.bookmark = Remover marcador -menuitem.join.on.startup = Entrar ao Iniciar -menuitem.view.room.info = Ver Informa\u00e7\u00f5es da Sala -menuitem.remove = Remover -menuitem.change.nickname = Trocar Apelido -menuitem.block.user = Bloquear Usu\u00e1rio -menuitem.unblock.user = Desbloquear Usu\u00e1rio -menuitem.kick.user = Expulsar Usu\u00e1rio -menuitem.voice = Palavra -menuitem.revoke.voice = Revogar Palavra -menuitem.grant.voice = Conceder Palavre -menuitem.ban.user = Banir Usu\u00e1rio -menuitem.grant.moderator = Permitir Moderador -menuitem.revoke.moderator = Revogar Moderador -menuitem.invite.users = Convidar Usu\u00e1rios -menuitem.invite.group.to.conference = Convidar Grupo para Confer\u00eancia -menuitem.start.a.conference = Iniciar uma Confer\u00eancia... -menuitem.change.subject = Mudar Assunto -menuitem.destroy.room = Remover Sala -menuitem.set.status.message = Mudar mensagem de Status... -menuitem.edit.status.message = Editar mensagens customizadas... -menuitem.broadcast.to.group = Enviar mensagem para grupo -menuitem.alert.when.online = Alertar quando o usu\u00e1rio estiver online -menuitem.remove.alert.when.online = Remover Alerta -menuitem.save.as = Salvar como... -menuitem.view.client.version = Ver vers\u00e3o do Cliente -menuitem.view.contact.history = Ver hist\u00f3rico do Contato -menuitem.edit.my.profile = &Editar meu Perfil... -menuitem.lookup.profile = &Verificar Perfil... -menuitem.add.as.contact = Adicionar como contato -menuitem.chat = Chat -menuitem.show.offline.group = Agrupar usu\u00e1rios offline -menuitem.move.to = Mover para -menuitem.copy.to = Copiar para - -tree.conference.services = Servi\u00e7os de Confer\u00eancia -tree.users.in.room = Usu\u00e1rios na Sala - -status.away = Ausente -status.custom.messages = Mensagem personalizada -status.do.not.disturb = N\u00e3o incomode -status.extended.away = Aus\u00eancia extendida -status.free.to.chat = Dispon\u00edvel para conversar -status.on.phone = Ao Telefone -status.online = Online -status.pending = Pendente - -tab.general = Geral -tab.proxy = Proxy -tab.contacts = Contatos -tab.installed.plugins = Plugins Instalados -tab.available.plugins = Plugins Dispon\u00edveis -tab.personal = Pessoal -tab.business = Corporativo -tab.home = Resid\u00eancia -tab.avatar = Avatar -tab.conferences = Confer\u00eancias - -group.connection = Conex\u00e3o -group.conferences.found = Servi\u00e7o de Confer\u00eancia Encontrado -group.comma.delimited = Delimitado por v\u00edrgula -group.general.information = Informa\u00e7\u00f5es Gerais -group.chat.window.information = Informa\u00e7\u00f5es da Janela de Chat -group.notification.options = Op\u00e7\u00f5es de Notifica\u00e7\u00e3o -group.search.form = Formul\u00e1rio de Busca -group.search.results = Resultados da Busca -group.login.information = Informa\u00e7\u00e3o de Login - -tooltip.place.a.call = Chamar este usu\u00e1rio -tooltip.view.history = Ver hist\u00f3rico de conversas -tooltip.view.changelog = Ver Log de mudan\u00e7as -tooltip.view.readme = Ver LeiaMe -tooltip.notifications = Prefer\u00eancias de notifica\u00e7\u00e3o de novos Chats. -available = Dispon\u00edvel -broadcast = Espalhar -offline = Offline -online = Online -participants = Participantes -unfiled = Indefinido -user.has.signed.in = Usu\u00e1rio entrou -user.has.signed.off = Usu\u00e1rio saiu -while.offline = Enquanto Offline -action.clear = Limpar -action.copy = Copiar -action.cut = Recortar -action.paste = Colar -action.print = Imprimir -action.save = Salvar -action.select.all = Selecionar Tudo -button.add.user = Adicionar Usu\u00e1rio -button.add2 = Adicionar -button.copy.to.clipboard = Copiar -button.quit = Sair -button.save = Salvar -button.send = Enviar -button.send.email = Enviar Email -button.start.chat = Iniciar Chat -button.tasks.active = Ativas -button.tasks.all = Todas -button.view.profile = Ver Perfil -checkbox.show.avatars.in.contactlist = Mostrar Avatar na lista de contatos -checkbox.tabs.on.top = Mostrar Chat no Topo (Necessita Reiniciar) -checkbox.use.compression = Usar Compress\u00e3o -delete.log.permanently = Apagar Permanentemente -delete.permanently = Apagar Permanentemente? -gateway.username.password.error = Informe Usu\u00e1rio e Senha. -group.empty = Nenhum usu\u00e1rio online. -group.offline = Grupo Offline -label.add.task = Adicionar tarefa -label.conflict.error = -label.emoticons = &Emoticons -label.message.style = Estilo &Mensagem -label.network = &Rede -label.received = &Recebido -label.show = Mostrar: -label.timeformat = Usar {0} -label.unable.to.add.contact = Imposs\u00edvel adicionar contato. -label.user.on.public.network = Usu\u00e1rio est\u00e1 em uma rede p\u00fablica -menuitem.delete.login.information = Remover informa\u00e7\u00e3o de login -menuitem.dial = Discar -menuitem.enter.login.information = Entrar com informa\u00e7\u00e3o de login -menuitem.languages = Tradu\u00e7\u00f5es -menuitem.sign.in.at.login = Conectar ao iniciar -menuitem.sign.out = Sair -menuitem.user.guide = Guia do Usu\u00e1rio -message.autenticating = Autenticando -message.buzz.alert.notification = Chamar Aten\u00e7\u00e3o -message.buzz.sent = Enviar alerta ao usu\u00e1rio. -message.cannot.add.contact.to.shared.group = Voc\u00ea n\u00e3o pode adicionar contatos a um grupo compartilhado. -message.enter.xmpp = Entre com seu usu\u00e1rio e senha XMPP. -message.invalid.status = Especifique um status v\u00e1lido. -message.invalid.username.password = Usu\u00e1rio e Senha inv\u00e1lidos. -message.no.updates = N\u00e3o h\u00e1 updates. -message.reconnect.attempting = Tentando... -message.reconnect.failed = Reconex\u00e3o Falhou. -message.reconnect.wait = Reconectando em {0} segundos. -message.restart.spark.changes = O plugin ser\u00e1 removido na pr\u00f3xima inicializa\u00e7\u00e3o. -title.about = Sobre -title.download.complete = Download completo -title.notes = Notas -title.password = Senha -tooltip.place.voice.call = Chamar este Usu\u00e1rio -tooltip.send.email = Enviar Email -tooltip.start.chat = Iniciar conversa - - - - -########################################## -# # -# # -# Missing Translation: # -# # -# # -########################################## - -administrator = Administrator -answer = Answer -apply = Apply -button.reject = Reject -button.login = &Login -button.reconnect2 = Reconnect -button.unset.file.explorer = Unset File Browser -button.re.detect = &Re-detect -checkbox.disable.prev.chat.history = Disable &showing previous conversation in chat -checkbox.notify.typing.systemtray = &Show typing notification in the system tray -checkbox.notify.systemtray = Show new &messages in the system tray -checkbox.use.debugger.on.startup = Start debugger on startup -checkbox.broadcast.hide.offline.user = Hide offline user -checkbox.use.krbconf = Use krb5.conf or krb5.ini -checkbox.use.krb.dns = Use DNS -checkbox.use.specify.below = Specify below -checkbox.use.pki.authentication = Use PKI authentication -group.chat.name.notification = Seen your name... -group.chat.name.match = Your name has been said in group chat: -label.na = n/a -label.cell = Cell -label.work = Work -label.home = Home -label.contactlist.avatarsize = Contact list avatar &size: -label.downloads = Downloads -label.due = Due -label.jabber.id = Jabber ID -label.krb.realm = Realm -label.krb.kdc = KDC -label.which.pki.method = Which PKI method? -label.choose.file = Choose file -label.trust.store.password = Trust store password -label.enter.password = Enter password -label.move.focus.forwards = Move focus forwards -label.move.focus.backwards = Move focus backwards -label.keystore.location = Keystore location -label.truststore.location = Truststore location -label.pkcs.library.file = PKCS#11 library file -label.x509.certificate = X.509 certificate -label.apple.keychain = Apple KeyChain -label.add.to.roster = Add user to your roster -label.audio.device = &Audio device -label.video.device = &Video device -menuitem.bookmarks = Bookmarks -menuitem.add.groupchat.myname = Highlight my &name when someone says it -menuitem.add.groupchat.mytext = &Highlight my text when I say something -menuitem.add.groupchat.popname = Show &toast popup when someone says my name -menuitem.add.groupchat.showjoinleavemessage = &Show join and leave messages -menuitem.add.groupchat.showrolesinsteadofstatus = Show chatroleicons instead of statusicons -menuitem.always.on.top = Always on top -menuitem.open.with = Open with... -menuitem.block.contact = Block contact -menuitem.unblock.contact = Unblock contact -menuitem.sign.in = Sign in -menuitem.show.offline.users = Show offline users -menuitem.show.contact.statusmessage = Show status message -menuitem.bookmark.room = Bookmark room -menuitem.refresh = Refresh -menuitem.create.room = Create or join room -menuitem.expand.all.groups = Expand all groups -menuitem.collapse.all.groups = Collapse all groups -menuitem.inivite.again = Invite again -menuitem.chatframe.option = Options -message.invite.to.groupchat = {0} is inviting you to join a group chat -message.disconnected.group.chat.error = Your connection was closed due to an error, you will need to re-join this room after reconnecting -message.disconnected.shutdown = Your connection was closed because the server was shut down -message.enter.gadugadu = Enter your GaduGadu username and password below -message.enter.gtalk = Enter your GTalk username and password below -message.enter.icq = Enter your ICQ username and password below -message.enter.irc = Enter your IRC username, password and nickname below -message.enter.sametime = Enter your Sametime username and password below -message.enter.facebook = Enter your Facebook username and password below -message.enter.myspace = Enter your MySpace username and password below -message.enter.qq = Enter your QQ Number and password below -message.enter.room.password = Enter room password -message.enter.simple = Enter your SIMPLE username and password below -message.file.transfer.notification = File transfer notification -message.file.transfer.short.message = is sending you a file called\: -message.file.transfer.chat.window = File transfer request: -message.gateway.username.error = Username needs to be supplied -message.gateway.password.error = Password needs to be supplied -message.gateway.nickname.error = Nickname needs to be supplied -message.invalid.jid.error = The JID specified is invalid -message.nickname.not.acceptable = Nickname change is not enabled! -message.restart.required = You will need to restart Spark to have your changes take effect, restart now? -message.room.creation.error = The room could not be created -message.server.unavailable = Can't connect to server: invalid name or server not reachable -message.specify.contact.jid = Please specify the contact JID (ex. ddman@jabber.org) -message.specify.group = Specify contact group to add the new user to -message.unable.to.retrieve.last.activity = Unable to determine last activity for {0} -message.unrecoverable.error = Invalid username or password -message.waiting.for.user.to.join = Waiting for {0} to join -message.groupchat.require.password = This group chat room requires a password to enter -message.search.for.history = Search conversation history -tab.sso = SSO -tab.pki = PKI -title.password.required = Password required -title.task.notification = Task notification -title.client.logs = Client logs -title.bookmarks = Bookmarks -title.add.contact.group = Add contact group -title.advanced.connection.usesso = Use Single Sign-On (SSO) via GSSAPI -title.delete.file = Do you really want to delete this file? -title.error.couldnt.open.file = Could not open the file -title.error.delete.file = Could not delete file -title.error.find.app = Could not find a matching application -title.error.rename.file = Could not rename the file -title.file = File -title.filesize = Size -title.gadugadu.registration = GaduGadu account credentials -title.general.media = Media settings -title.group.chat.settings = Group chat settings -title.gtalk.registration = GTalk account credentials -title.icq.registration = ICQ account credentials -title.irc.registration = IRC account credentials -title.sametime.registration = Sametime account credentials -title.facebook.registration = Facebook account credentials -title.myspace.registration = MySpace account credentials -title.input.fileexplorer = Please input the name of your file browser: -title.input.newname = Please input the new name\: -title.input.openwith = Please input the name of the application which you want to use: -title.login.error = Login error -title.no.updates = No updates -title.qq.registration = QQ account credentials -title.simple.registration = SIMPLE account credentials -title.tasks = Tasks -title.xmpp.registration = XMPP account credentials -title.appearance.showVCards = Show &VCards in the contact list -title.subscription.request = Subscription request -tooltip.appearance = Change the appearance of your conversations -tooltip.file.transfer = Preferences for file transfer - - -#!# \ No newline at end of file diff --git a/src/resources/i18n/spark_i18n_ru_RU.properties b/src/resources/i18n/spark_i18n_ru_RU.properties deleted file mode 100644 index 76dd7a530..000000000 --- a/src/resources/i18n/spark_i18n_ru_RU.properties +++ /dev/null @@ -1,958 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.0.1 -## Added key: 'message.restart.spark.changes' -## Added key: 'message.enter.icq' -## Added key: 'title.icq.registration' -## Added key: 'button.quit' -## -## -## -## 2.0.2 -## Added key: 'button.new' -## Added key: 'label.group' -## Added key: 'label.jabber.id' -## Added key: 'label.enter.group.name' -## Added key: 'title.new.roster.group' -## Added key: 'title.add.contact.group' -## Added key: 'message.add.contact.to.list' -## Added key: 'title.add.contact' -## Added key: 'tab.conferences' -## Added key: 'message.autenticating' -## Added key: 'title.file.transfer.preferences' -## Added key: 'menuitem.about' -## Added key: 'message.invalid.status' -## Added key: 'message.cannot.add.contact.to.shared.group -## Added key: 'message.specify.contact.jid' -## Added key: 'message.invalid.jid.error' -## Added key: 'message.specify.group' -## Added key: 'add' -## -## -## -## 2.0.5 -## Added key: 'Broadcast' -## Added key: 'label.user.on.public.network' -## Added key: 'label.network' -## -## -## 2.0.6 -## Added key: 'button.add.user' -## Added key: 'menuitem.sign.in' -## Added key: 'menuitem.sign.out' -## Added key: 'menuitem.sign.in.at.login' -## Added key: 'menuitem.enter.login.information' -## Added key: 'menuitem.delete.login.information' -## Added key: 'button.save' -## -## -## 2.5 -## Added key: 'button.start.chat' -## Added key: 'button.send.email' -## Added key: 'available' -## Added key: 'checkbox.tabs.on.top' -## Added key: 'user.has.signed.in' -## Added key: 'user.has.signed.off' -## Added key: 'label.unable.to.add.contact' -## Added key: 'label.conflict.error' -## Added key: 'message.room.creation.error' -## Added key: 'checkbox.allow.buzz' -## Added key: 'message.disconnected.group.chat.error' -## Added key: 'menuitem.show.offline.group' -## Added key: 'menuitem.move.to' -## Added key: 'menuitem.copy.to' -## Added key: 'label.message.style' -## Added key: 'label.emoticons' -## Added key: 'checkbox.enable.emoticons' -## Added key: 'message.unable.to.retrieve.last.activity' -## Added key: 'checkbox.use.system.look.and.feel' -## -## 2.5.2 -## Added key: 'tooltip.place.voice.call' -## Added key: 'message.buzz.alert.notification' -## Added kye: 'message.buzz.sent' -## -## 2.5.2 -## Added key: 'menuitem.user.guide' -## -## -## -## Added key: 'title.subscription.request' -## Added key: 'label.add.to.roster' -## Added key: 'label.audio.device' -## Added key: 'label.video.device' -## Added key: 'button.re.detect' - - - - -ok = Ok -cancel = \u041e\u0442\u043c\u0435\u043d\u0430 -add = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c -apply = \u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c -broadcast = \u0420\u0430\u0441\u0441\u044b\u043b\u043a\u0430 -use.default = \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e -close = \u0417\u0430\u043a\u0440\u044b\u0442\u044c -create = \u0421\u043e\u0437\u0434\u0430\u0442\u044c -invite = \u041f\u0440\u0438\u0433\u043b\u0430\u0441\u0438\u0442\u044c -date = \u0414\u0430\u0442\u0430 -from = \u041e\u0442 -room.name = \u0418\u043c\u044f \u043a\u043e\u043c\u043d\u0430\u0442\u044b -join = \u0412\u043e\u0439\u0442\u0438 -description = \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 -subject = \u0422\u0435\u043c\u0430 -occupants = \u0423\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432 -accept = \u041f\u0440\u0438\u043d\u044f\u0442\u044c -reject = \u041e\u0442\u043a\u043b\u043e\u043d\u0438\u0442\u044c -open = \u041e\u0442\u043a\u0440\u044b\u0442\u044c -open.folder = \u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043f\u0430\u043f\u043a\u0443 -online = \u0412 \u0441\u0435\u0442\u0438 -offline = \u041d\u0435 \u0432 \u0441\u0435\u0442\u0438 -retry = \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c -active = Active -not.registered = \u041d\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d -save = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c -yes = \u0414\u0430 -no = \u041d\u0435\u0442 -broadcast = Broadcast -available = \u0412 \u0441\u0435\u0442\u0438 -user.has.signed.in = \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0441\u044f. -user.has.signed.off = \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u043b\u0441\u044f. - - -button.create.account = \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c -button.close = \u0417\u0430\u043a\u0440\u044b\u0442\u044c -button.advanced = \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e -button.browse = \u0412\u044b\u0431\u0440\u0430\u0442\u044c... -button.browse2 = \u0412\u044b\u0431\u0440\u0430\u0442\u044c... -button.browse3 = \u0412\u044b\u0431\u0440\u0430\u0442\u044c... -button.approve = \u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c -button.deny = \u041e\u0442\u043a\u0430\u0437\u0430\u0442\u044c -button.accept = \u041f\u0440\u0438\u043d\u044f\u0442\u044c -button.profile = \u041f\u0440\u043e\u0444\u0438\u043b\u044c -button.add.a.contact = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0430\u043a\u0442 -button.reconnect = \u041f\u0435\u0440\u0435\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f -button.add = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c -button.roster = \u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u043b\u0438\u0441\u0442 -button.add.bookmark = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0443 -button.remove.bookmark = \u0423\u0431\u0440\u0430\u0442\u044c \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0443 -button.bookmark.room = \u041a\u043e\u043c\u043d\u0430\u0442\u0443 \u0432 \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0438 -button.create.room = \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u043b\u0438 \u0432\u043e\u0439\u0442\u0438 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 -button.join.room = \u0412\u043e\u0439\u0442\u0438 \u0432 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u0443\u044e \u043a\u043e\u043c\u043d\u0430\u0442\u0443 -button.refresh = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c -button.find = \u041d\u0430\u0439\u0442\u0438 -button.update = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c -button.cancel = \u041e\u0442\u043c\u0435\u043d\u0430 -button.decline = \u041e\u0442\u043a\u043b\u043e\u043d\u0438\u0442\u044c -button.join = \u0412\u043e\u0439\u0442\u0438 -button.login = \u0412\u043e\u0439\u0442\u0438 -button.save.for.future.use = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f -button.register = \u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c -button.dial.number = \u041d\u0430\u0431\u0440\u0430\u0442\u044c \u043d\u043e\u043c\u0435\u0440 -button.clear = \u041e\u0442\u0447\u0438\u0441\u0442\u0438\u0442\u044c -button.search = \u041f\u043e\u0438\u0441\u043a -button.add.service = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 -button.quit = \u0412\u044b\u0445\u043e\u0434 \u0438\u0437 Spark -button.new = \u041d\u043e\u0432\u044b\u0439 -button.add.user = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f -button.save = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c -button.start.chat = \u0427\u0430\u0442 -button.tasks.active = \u0410\u043a\u0442\u0438\u0432\u043d\u044b\u0435 -button.tasks.all = \u0412\u0441\u0435 -button.send.email = Email -button.send = \u041f\u043e\u0441\u043b\u0430\u0442\u044c -button.view.notes = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0417\u0430\u043c\u0435\u0442\u043a\u0438 -button.view.profile = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e -button.view.tasklist = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0421\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0434\u0430\u0447 -button.re.detect = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c - - - -checkbox.save.password = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c -checkbox.auto.login = \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0432\u0445\u043e\u0434 -checkbox.login.as.invisible = \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f "\u043d\u0435\u0432\u0438\u0434\u0438\u043c\u043a\u043e\u0439" -checkbox.broadcast.hide.offline.user = \u0421\u043f\u0440\u044f\u0442\u0430\u0442\u044c \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043d\u0438\u043a\u043e\u0432 "\u043d\u0435 \u0432 \u0441\u0435\u0442\u0438" -checkbox.use.proxy.server = \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Proxy \u0441\u0435\u0440\u0432\u0435\u0440 -checkbox.auto.discover.port = \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0430\u0439\u0442\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u043f\u043e\u0440\u0442 -checkbox.permanent = \u041f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u0430\u044f \u043a\u043e\u043c\u043d\u0430\u0442\u0430 -checkbox.private.room = \u041b\u0438\u0447\u043d\u0430\u044f \u043a\u043e\u043c\u043d\u0430\u0442\u0430 -checkbox.show.time.in.chat.window = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0432 \u043e\u043a\u043d\u0435 \u0447\u0430\u0442\u0430 -checkbox.show.avatars.in.contactlist = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c &Avatars \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u043e\u0432 -checkbox.show.notifications.in.conference = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 -checkbox.disable.chat.history = \u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0447\u0430\u0442\u0430 -checkbox.sort.asc.history = \u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u0430 \u043f\u043e \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u043d\u0438\u044e \u0434\u0430\u0442\u044b -checkbox.show.toaster = \u0423\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0442\u044c \u043e \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0438 -checkbox.window.to.front = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0432\u0435\u0440\u0445 \u043e\u043a\u043e\u043d -checkbox.notify.user.comes.online = \u041e\u043f\u043e\u0432\u0435\u0449\u0430\u0442\u044c \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0445\u043e\u0434\u0438\u0442 \u0432 \u0441\u0435\u0442\u044c -checkbox.notify.user.goes.offline = \u041e\u043f\u043e\u0432\u0435\u0449\u0430\u0442\u044c \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0438\u0437 \u0441\u0435\u0442\u0438 -checkbox.notify.typing.systemtray = \u041e\u043f\u043e\u0432\u0435\u0449\u0430\u0442\u044c \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0431\u0438\u0440\u0430\u0435\u0442 \u0442\u0435\u043a\u0441\u0442 (\u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0439 \u0442\u0440\u0435\u0439) -checkbox.notify.systemtray = \u041e\u043f\u043e\u0432\u0435\u0449\u0430\u0442\u044c \u043e \u043d\u043e\u0432\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u0445 (\u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0439 \u0442\u0440\u0435\u0439) -checkbox.play.sound.on.new.message = \u041f\u0440\u043e\u0438\u0433\u0440\u0430\u0442\u044c \u0437\u0432\u0443\u043a \u043f\u0440\u0438 \u043d\u043e\u0432\u043e\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0438 -checkbox.play.sound.when.offline = \u041f\u0440\u043e\u0438\u0433\u0440\u0430\u0442\u044c \u0437\u0432\u0443\u043a \u043f\u0440\u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f -checkbox.play.sound.on.outgoing.message = \u041f\u0440\u043e\u0438\u0433\u0440\u0430\u0442\u044c \u0437\u0432\u0443\u043a \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f -checkbox.play.sound.on.invitation = \u041f\u0440\u043e\u0438\u0433\u0440\u0430\u0442\u044c \u0437\u0432\u0443\u043a \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043f\u0440\u0438\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u044f -checkbox.idle.enabled = \u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u00ab\u041e\u0442\u043e\u0448\u0435\u043b\u00bb -checkbox.launch.on.startup = \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 -checkbox.reconnet.info = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 -checkbox.reconnect.panel.big = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0430\u043d\u0435\u043b\u044c -checkbox.reconnect.panel.small = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0433\u0440\u0443\u043f\u043f -checkbox.reconnect.panel.icon = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0438\u043a\u043e\u043d\u043a\u0443 -checkbox.start.in.tray = \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0432\u0451\u0440\u043d\u0443\u0442\u044b\u043c \u0432 \u0442\u0440\u0435\u0439 -checkbox.click.single.tray = \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d\u043e\u0447\u043d\u044b\u0439 \u043a\u043b\u0438\u043a \u0432 \u0442\u0440\u0435\u0435 \u0447\u0442\u043e\u0431\u044b \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c Spark -checkbox.split.chat.window = \u041f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u0442\u044c \u043a \u043e\u043a\u043d\u0430\u043c (\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a) -checkbox.tabs.on.top = \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0447\u0430\u0442 \u043f\u043e\u0432\u0435\u0440\u0445 \u043e\u043a\u043e\u043d (\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a) -checkbox.use.compression = \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0436\u0430\u0442\u0438\u0435 -checkbox.use.debugger.on.startup = \u041d\u0430\u0447\u0430\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043a\u0443 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 -checkbox.allow.buzz = \u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u00ab\u0431\u0443\u0434\u0438\u0442\u044c\u00bb \u0432\u0430\u0441. -checkbox.enable.emoticons = \u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0441\u043c\u0430\u0439\u043b\u0438\u043a\u0438 -checkbox.use.system.look.and.feel = \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043c\u044b (System Look And &Feel) (\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a) -checkbox.disable.prev.chat.history = \u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u043a\u0430\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0431\u0435\u0441\u0435\u0434 \u0432 \u0447\u0430\u0442\u0435 -checkbox.use.hostname.as.resource = \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u044f \u0445\u043e\u0441\u0442\u0430 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u0430 -checkbox.use.version.as.resource = \u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e Spark \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u0430 - - -label.user.on.public.network = User is on a public network -label.change.password.to = \u0421\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0430 -label.username = \u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f -label.name = \u0418\u043c\u044f -label.room.name = \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u043d\u0430\u0442\u044b -label.room.topic= \u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043a\u043e\u043c\u043d\u0430\u0442\u044b -label.password = \u041f\u0430\u0440\u043e\u043b\u044c -label.confirm.password = \u041f\u043e\u0432\u0442\u043e\u0440 \u043f\u0430\u0440\u043e\u043b\u044f -label.server = \u0421\u0435\u0440\u0432\u0435\u0440 -label.chatroom.fontsize = \u0420\u0430\u0437\u043c\u0435\u0440 \u0448\u0440\u0438\u0444\u0442\u0430 \u0432 \u0447\u0430\u0442\u0435: -label.create.account = \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c -label.contactlist.avatarsize = \u0420\u0430\u0437\u043c\u0435\u0440 \u0430\u0432\u0430\u0442\u0430\u0440\u0430 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u043e\u0432: -label.contactlist.fontsize = \u0420\u0430\u0437\u043c\u0435\u0440 \u0448\u0440\u0438\u0444\u0442\u0430 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u043e\u0432: -label.close = \u0417\u0430\u043a\u0440\u044b\u0442\u044c -label.ok = OK -label.cancel = \u041e\u0442\u043c\u0435\u043d\u0430 -label.use.default = \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e -label.port = \u041f\u043e\u0440\u0442 -label.auto.login = \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0432\u0445\u043e\u0434 -label.old.ssl = \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u00abOLD SSL port\u00bb -label.host = \u0421\u0435\u0440\u0432\u0435\u0440 -label.resource = \u0420\u0435\u0441\u0443\u0440\u0441 -label.protocol = \u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b -label.accounts = \u0423\u0447\u0435\u0442\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 -label.receieved = \u041f\u043e\u0441\u043b\u0430\u043d\u043e -label.transfer.timeout = \u0422\u0430\u0439\u043c\u0430\u0443\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438(\u043c\u0438\u043d\u0443\u0442): -label.transfer.download.directory = \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0432 \u043f\u0430\u043f\u043a\u0443: -label.find = \u041d\u0430\u0439\u0442\u0438 -label.rename.to = \u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c -label.contact.to.find = \u041d\u0430\u0439\u0442\u0438 \u043a\u043e\u043d\u0442\u0430\u043a\u0442 -label.available.users.in.roster = \u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0432 \u0440\u043e\u0441\u0442\u0435\u0440\u0435 -label.time = \u0412\u0440\u0435\u043c\u044f: {0} -label.add.conference.service = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0439 -label.add.jid = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c JID -label.add.task = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 -label.message = \u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 -label.room = \u041a\u043e\u043c\u043d\u0430\u0442\u0430 -label.invited.users = \u041f\u0440\u0438\u0433\u043b\u0430\u0441\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 -label.new.nickname = \u041d\u043e\u0432\u044b\u0439 \u043d\u0438\u043a -label.server.address = \u0410\u0434\u0440\u0435\u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 -label.show = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c: -label.nickname = \u041d\u0438\u043a -label.presence = \u0421\u0442\u0430\u0442\u0443\u0441 -label.priority = \u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 -label.enter.address = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0430\u0434\u0440\u0435\u0441 -label.jabber.address = &Jabber \u0430\u0434\u0440\u0435\u0441 -label.local.time = \u041c\u0435\u0441\u0442\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f -label.software = \u041a\u043b\u0438\u0435\u043d\u0442 -label.version = \u0412\u0435\u0440\u0441\u0438\u044f -label.os = \u041e\u0421 -label.number = \u041d\u043e\u043c\u0435\u0440 -label.dial = \u041d\u0430\u0431\u0440\u0430\u0442\u044c -label.display.time = \u0412 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 -label.due = \u0421\u0440\u043e\u043a -label.minutes.before.stale.chat = \u041c\u0438\u043d\u0443\u0442 \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u0434\u043e \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043c\u043d\u0430\u0442\u044b -label.company = \u041a\u043e\u043c\u043f\u0430\u043d\u0438\u044f -label.street.address = \u0410\u0434\u0440\u0435\u0441 -label.city = \u0413\u043e\u0440\u043e\u0434 -label.state.and.province = \u041e\u0431\u043b\u0430\u0441\u0442\u044c -label.postal.code = \u041f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441 -label.country = \u0421\u0442\u0440\u0430\u043d\u0430 -label.job.title = \u0414\u043e\u043b\u0436\u043d\u043e\u0441\u0442\u044c -label.department = \u041e\u0442\u0434\u0435\u043b -label.phone = \u0422\u0435\u043b\u0435\u0444\u043e\u043d -label.fax = &Fax -label.mobile = \u041c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0439 -label.web.page = \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 -label.pager = \u041f\u0435\u0439\u0434\u0436\u0435\u0440 -label.first.name = \u0418\u043c\u044f -label.middle.name = \u041e\u0442\u0447\u0435\u0441\u0442\u0432\u043e -label.last.name = \u0424\u0430\u043c\u0438\u043b\u0438\u044f -label.email.address = &Email \u0430\u0434\u0440\u0435\u0441 -label.jid = &JID -label.search.service = \u0421\u0435\u0440\u0432\u0438\u0441 \u043f\u043e\u0438\u0441\u043a\u0430 -label.seconds = \u0421\u0435\u043a\u0443\u043d\u0434(-\u044b) -label.xmpp.port = &XMPP \u043f\u043e\u0440\u0442 -label.response.timeout = \u0422\u0430\u0439\u043c\u0430\u0443\u0442 (\u0441\u0435\u043a) -label.time.till.idle = \u00ab\u041e\u0442\u043e\u0448\u0435\u043b\u00bb \u0447\u0435\u0440\u0435\u0437 (\u043c\u0438\u043d) -label.time.till.idlemessage = \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0432\u0438\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 -label.timeformat = \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 {0} -label.jabber.id = &Jabber ID -label.group = \u0413\u0440\u0443\u043f\u043f\u0430 -label.enter.group.name = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u043e\u0432\u043e\u0435 \u0438\u043c\u044f \u0433\u0440\u0443\u043f\u043f\u044b -label.network = \u0421\u0435\u0442\u044c -label.unable.to.add.contact = \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0430\u043a\u0442. -label.conflict.error = \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f. \u0423\u0436\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d \u0441 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430. -label.message.style = \u0421\u0442\u0438\u043b\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f -label.emoticons = \u0421\u043c\u0430\u0439\u043b\u0438\u043a\u0438 -label.user.on.public.network = \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438\u0437 \u0441\u0435\u0442\u0438 -label.add.to.roster = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u043e\u0432 -label.audio.device = \u0410\u0443\u0434\u0438\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 -label.video.device = \u0412\u0438\u0434\u0435\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 - -message.alert.notify = \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 -message.username.error = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. -message.password.error = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u044c. -message.confirmation.password.error = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u041f\u043e\u0432\u0442\u043e\u0440 \u043f\u0430\u0440\u043e\u043b\u044f. -message.account.error = \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0443\u0447\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438. -message.registering = \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f {0}. \u0416\u0434\u0438\u0442\u0435... -message.connection.failed = \u041d\u0435\u0442 \u0441\u0432\u044f\u0437\u0438 \u0441 {0}. -message.create.account = \u0423\u0447\u0435\u0442\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0430. -message.already.exists = \u0423\u0447\u0435\u0442\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0434\u0440\u0443\u0433\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. -message.account.created = \u0423\u0447\u0435\u0442\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0430. -message.account.create = \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c. -message.connecting.please.wait = \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435. \u0416\u0434\u0438\u0442\u0435... -message.supply.valid.timeout = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0430. -message.supply.valid.port = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u043f\u043e\u0440\u0442. -message.supply.resource = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u0440\u0435\u0441\u0443\u0440\u0441. -message.current.status = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0434\u0440\u0443\u0433\u0438\u043c \u0412\u0430\u0448 \u0441\u0442\u0430\u0442\u0443\u0441. -message.disconnected.error = \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u043e\u0441\u044c \u043e\u0448\u0438\u0431\u043a\u043e\u0439. -message.disconnected.group.chat.error = \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u043e\u0441\u044c \u043e\u0448\u0438\u0431\u043a\u043e\u0439. \u0412\u0430\u043c \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0439\u0442\u0438 \u0437\u0430\u043d\u043e\u0432\u043e \u0432 \u044d\u0442\u0443 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f. -message.disconnected.conflict.error = \u0412\u044b \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u0438\u0437-\u0437\u0430 \u0432\u0445\u043e\u0434\u0430 \u0412\u0430\u0448\u0435\u0439 \u0443\u0447\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u0441 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430. -message.locked.workstation = \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043b \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440. -message.away.idle = \u00ab\u041e\u0442\u043e\u0448\u0435\u043b\u00bb \u0438\u0437-\u0437\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u044f. -message.default.error = \u041e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0430 \u043e\u0448\u0438\u0431\u043a\u0430. \u0421\u043e\u043e\u0431\u0449\u0438\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043d\u0430 support@jivesoftware.com. -message.new.message = \u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 {0}. -message.send.file.to.user = \u041f\u043e\u0441\u043b\u0430\u0442\u044c \u0444\u0430\u0439\u043b \u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e. -message.send.picture = \u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u043f\u043e\u0441\u043b\u0430\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441 \u044d\u043a\u0440\u0430\u043d\u0430. -message.send.to.these.people = \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c -message.sent.offline.files = You have just been sent offline file(s). -message.spark.secure = Spark \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d \u043f\u043e \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c\u0443 \u043a\u0430\u043d\u0430\u043b\u0443. -message.search.for.contacts = \u041d\u0430\u0439\u0442\u0438 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u044b. -message.end.conversation = \u0417\u0430\u043a\u0440\u044b\u0442\u044c \u044d\u0442\u0443 \u0431\u0435\u0441\u0435\u0434\u0443? -message.end.chat = \u0417\u0430\u043a\u0440\u044b\u0442\u044c \u044d\u0442\u043e\u0442 \u0447\u0430\u0442? -message.close.this.chat = \u0417\u0430\u043a\u0440\u044b\u0442\u044c \u0447\u0430\u0442 -message.close.other.chats = \u0417\u0430\u043a\u0440\u044b\u0442\u044c \u0432\u0441\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u0447\u0430\u0442\u044b -message.close.stale.chats = \u0417\u0430\u043a\u0440\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u0435 \u0447\u0430\u0442\u044b -message.last.message.received = \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u0432 {0} -message.shared.group = Shared Group -message.is.shared.group = {0} is a shared group. -message.delete.confirmation = \u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c {0}? -message.idle.for = \u041d\u0435\u0430\u043a\u0442\u0438\u0432\u0435\u043d {0} -message.enter.broadcast.message = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. -message.name.of.group = \u0418\u043c\u044f \u0433\u0440\u0443\u043f\u043f\u044b -message.approve.subscription = \u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c {0} \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0412\u0430\u0441 \u0432 \u0438\u0445 \u043a\u043e\u043d\u0442\u0430\u043a\u0442 \u043b\u0438\u0441\u0442? -message.add.user = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u043a\u043e\u043d\u0442\u0430\u043a\u0442 \u043b\u0438\u0441\u0442? -message.general.error = \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u043d\u043e \u0438\u0437-\u0437\u0430 {0}. -message.add.a.contact = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0430\u043a\u0442. -message.generic.reconnect.message = \u0412\u044b \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0414\u043b\u044f \u043f\u0435\u0440\u0435\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u041f\u0435\u0440\u0435\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f\u00bb. -message.select.one.or.more = \u0412\u044b\u0431\u0435\u0440\u0435\u0442\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. -message.add.conference.service = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0439. -message.service.already.exists = \u0421\u0435\u0440\u0432\u0438\u0441 \u0443\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d. -message.searching.please.wait = \u041f\u043e\u0438\u0441\u043a. \u0416\u0434\u0438\u0442\u0435... -message.conference.service.error = \u0421\u0435\u0440\u0432\u0438\u0441 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d. -message.create.or.join.room = \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u043b\u0438 \u0432\u043e\u0439\u0442\u0438 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 -message.specify.name.error = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435. -message.password.private.room.error = \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u044c \u043a \u043b\u0438\u0447\u043d\u043e\u0439 \u043a\u043e\u043c\u043d\u0430\u0442\u0435 -message.passwords.no.match = \u041f\u0430\u0440\u043e\u043b\u0438 \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442. -message.enter.valid.jid = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 Jabber ID -message.please.join.in.conference = \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u0435\u0441\u044c \u043a \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438. -message.invite.users.to.conference = \u041f\u0440\u0438\u0433\u043b\u0430\u0441\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443. -message.specify.users.to.join.conference = \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u044b\u0445 \u043a \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438. -message.participants.in.room = \u0423\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0435 -message.you.have.been.kicked = \u0412\u0430\u0441 \u043a\u0438\u043a\u043d\u0443\u043b\u0438 \u0438\u0437 \u043a\u043e\u043c\u043d\u0430\u0442\u044b. -message.kicked.error = \u0412\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u043a\u0438\u043a\u043d\u0443\u0442\u044c {0} \u0438\u0437 \u043a\u043e\u043c\u043d\u0430\u0442\u044b. -message.you.have.been.banned = \u0412\u0430\u0441 \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u043b\u0438 \u0432 \u044d\u0442\u043e\u0439 \u043a\u043e\u043c\u043d\u0430\u0442\u0435. -message.nickname.in.use = \u041d\u0438\u043a \u0443\u0436\u0435 \u0437\u0430\u043d\u044f\u0442. \u0412\u044b\u0431\u0435\u0440\u0435\u0442\u0435 \u0434\u0440\u0443\u0433\u043e\u0439 -message.nickname.not.acceptable = \u0421\u043c\u0435\u043d\u0430 \u043d\u0438\u043a\u0430 \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u0430! -message.update.room.list = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043c\u043d\u0430\u0442 -message.join.conference.room = \u0412\u043e\u0439\u0442\u0438 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 -message.select.add.room.to.add = \u0412\u044b\u0431\u0435\u0440\u0435\u0442\u0435 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432 \u0412\u0430\u0448 \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. -message.bookmark.temporary.room.error = \u0412\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u043d\u0430\u0442\u044b -message.select.room.to.join = \u0412\u044b\u0431\u0435\u0440\u0435\u0442\u0435 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u0430. -message.conference.info.error = \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u043f\u043e\u0437\u0436\u0435. -message.add.favorite.room = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043c\u043d\u0430\u0442\u0443 \u0432 \u0438\u0437\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u0438\u043b\u0438 \u0432\u043e\u0439\u0442\u0438 \u0441\u0440\u0430\u0437\u0443.. -message.select.room.to.enter = \u0412\u044b\u0431\u0435\u0440\u0435\u0442\u0435 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u0430. -message.find.conference.services = \u041f\u043e\u0438\u0441\u043a \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0439 -message.specify.information.for.conference = \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u043a\u043e\u043c\u043d\u0430\u0442\u044b. -message.no.avatar.found = \u0410\u0432\u0430\u0442\u0430\u0440 \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d. -message.no.caller.id = Caller ID \u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d. -message.no.description.available = \u041d\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f -message.no.history.found = \u041d\u0435\u0442 \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. -message.no.results.found = \u041f\u043e\u0438\u0441\u043a \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0430\u0448\u0435\u043b. -message.no.room.to.join.error = \u041d\u0435\u0442 \u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u0430 -message.no.subject.available = \u041d\u0435\u0442 \u0442\u0435\u043c\u044b -message.no.updates = \u041d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439. -message.normal = \u041f\u0440\u043e\u0441\u0442\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 -message.room.information.for = \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0434\u043b\u044f \u043a\u043e\u043c\u043d\u0430\u0442\u044b {0} -message.view.information.about.this.user = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435. -message.add.this.user.to.your.roster = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u043a\u043e\u043d\u0442\u0430\u043a\u0442 \u043b\u0438\u0441\u0442. -message.came.online = {0} \u0432 \u0441\u0435\u0442\u0438 \u0441 {1} -message.went.offline = {0} \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d \u0441 {1} -message.offline.error = \u042d\u0442\u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0435\u0441\u043b\u0438 \u043e\u043d \u043d\u0435 \u0432 \u0441\u0435\u0442\u0438. -message.offline = \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u0441\u044f. -message.is.typing.a.message = {0} \u043f\u0438\u0448\u0435\u0442... -message.enter.new.subject = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043c\u0443 -message.confirm.destruction.of.room = \u0423\u043d\u0438\u0447\u0442\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0432\u044b\u0433\u043e\u043d\u0438\u0442 \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438\u0437 \u044d\u0442\u043e\u0439 \u043a\u043e\u043c\u043d\u0430\u0442\u044b. \u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c? -message.room.destruction.reason = \u041f\u0440\u0438\u0447\u0438\u043d\u0430 \u0443\u043d\u0438\u0447\u0442\u043e\u0436\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043d\u0430\u0442\u044b? -message.user.left.room = {0} \u0432\u044b\u0448\u0435\u043b \u0438\u0437 \u043a\u043e\u043c\u043d\u0430\u0442\u044b. -message.user.joined.room = {0} \u0432\u043e\u0448\u0435\u043b \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443. -message.chat.session.ended = \u0427\u0430\u0442 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0441\u044f \u0432 {0} -message.subject.change.error = \u0412\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0442\u0435\u043c\u0443 \u0432 \u044d\u0442\u043e\u0439 \u043a\u043e\u043c\u043d\u0430\u0442\u0435. -message.forbidden.error = \u0421\u0435\u0440\u0432\u0435\u0440 \u0441\u043e\u043e\u0431\u0449\u0438\u043b \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430. -message.room.destroyed = \u042d\u0442\u0430 \u043a\u043e\u043c\u043d\u0430\u0442\u0430 \u0431\u044b\u043b\u0430 \u0443\u043d\u0438\u0447\u0442\u043e\u0436\u0435\u043d\u0430 \u043f\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435: {0} -message.subject.has.been.changed.to = \u0422\u0435\u043c\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0430 \u043d\u0430 {0}. -message.user.kicked.from.room = {0} \u0431\u044b\u043b \u0432\u044b\u0433\u043d\u0430\u043d \u0438\u0437 \u043a\u043e\u043c\u043d\u0430\u0442\u044b. -message.user.given.voice = {0} \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043f\u0440\u0430\u0432\u043e \u0433\u043e\u043b\u043e\u0441\u0430 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0435. -message.user.voice.revoked = \u041e\u0442\u043c\u0435\u043d\u0435\u043d\u043e \u043f\u0440\u0430\u0432\u043e \u0433\u043e\u043b\u043e\u0441\u0430 \u0434\u043b\u044f {0}. -message.user.banned = {0} \u0431\u044b\u043b \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d \u0432 \u044d\u0442\u043e\u0439 \u043a\u043e\u043c\u043d\u0430\u0442\u0435. -message.user.granted.membership = {0} \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0430. -message.user.revoked.membership = \u041e\u0442\u043c\u0435\u043d\u0435\u043d\u044b \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0430 \u0434\u043b\u044f {0}. -message.user.granted.moderator = {0} \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043f\u0440\u0430\u0432\u0430 \u043c\u043e\u0434\u0435\u0440\u0430\u0442\u043e\u0440\u0430. -message.user.revoked.moderator = \u041e\u0442\u043c\u0435\u043d\u0435\u043d\u044b \u043f\u0440\u0430\u0432\u0430 \u043c\u043e\u0434\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0434\u043b\u044f {0}. -message.user.granted.owner = {0} \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043f\u0440\u0430\u0432\u0430 \u0441\u043e\u0437\u0434\u0430\u0442\u0435\u043b\u044f \u043a\u043e\u043c\u043d\u0430\u0442\u044b. -message.user.revoked.owner = \u041e\u0442\u043c\u0435\u043d\u0435\u043d\u044b \u043f\u0440\u0430\u0432\u0430 \u0441\u043e\u0437\u0434\u0430\u0442\u0435\u043b\u044f \u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0434\u043b\u044f {0}. -message.user.granted.admin = {0} \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043f\u0440\u0430\u0432\u0430 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 \u043a\u043e\u043c\u043d\u0430\u0442\u044b. -message.user.revoked.admin = \u041e\u0442\u043c\u0435\u043d\u0435\u043d\u044b \u043f\u0440\u0430\u0432\u0430 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 \u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0434\u043b\u044f {0}. -message.user.nickname.changed = {0} \u0441\u043c\u0435\u043d\u0438\u043b \u043d\u0438\u043a \u043d\u0430 {1}. -message.your.kicked = \u0412\u0430\u0441 \u0432\u044b\u0433\u043d\u0430\u043b {0}. -message.your.voice.granted = \u0412\u0430\u043c \u0434\u0430\u043b\u0438 \u043f\u0440\u0430\u0432\u043e \u0433\u043e\u043b\u043e\u0441\u0430. -message.your.voice.revoked = \u0423 \u0412\u0430\u0441 \u043e\u0442\u043d\u044f\u043b\u0438 \u043f\u0440\u0430\u0432\u043e \u0433\u043e\u043b\u043e\u0441\u0430. -message.your.banned = \u0412\u0430\u043c \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u043b\u0438 \u0432\u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u044d\u0442\u0443 \u043a\u043e\u043c\u043d\u0430\u0442\u0443. -message.your.membership.granted = \u0412\u0430\u043c \u0434\u0430\u043b\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0430. -message.your.membership.revoked = \u0423 \u0412\u0430\u0441 \u043e\u0442\u043d\u044f\u043b\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0430. -message.your.moderator.granted = \u0412\u0430\u043c \u0434\u0430\u043b\u0438 \u043f\u0440\u0430\u0432\u0430 \u043c\u043e\u0434\u0435\u0440\u0430\u0442\u043e\u0440\u0430. -message.your.moderator.revoked = \u0423 \u0412\u0430\u0441 \u043e\u0442\u043d\u044f\u043b\u0438 \u043f\u0440\u0430\u0432\u0430 \u043c\u043e\u0434\u0435\u0440\u0430\u0442\u043e\u0440\u0430. -message.your.ownership.granted = \u0412\u0430\u043c \u0434\u0430\u043b\u0438 \u043f\u0440\u0430\u0432\u0430 \u0441\u043e\u0437\u0434\u0430\u0442\u0435\u043b\u044f \u043a\u043e\u043c\u043d\u0430\u0442\u044b. -message.your.ownership.revoked = \u0423 \u0412\u0430\u0441 \u043e\u0442\u043d\u044f\u043b\u0438 \u043f\u0440\u0430\u0432\u0430 \u0441\u043e\u0437\u0434\u0430\u0442\u0435\u043b\u044f \u043a\u043e\u043c\u043d\u0430\u0442\u044b. -message.your.admin.granted = \u0412\u0430\u043c \u0434\u0430\u043b\u0438 \u043f\u0440\u0430\u0432\u0430 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 \u043a\u043e\u043c\u043d\u0430\u0442\u044b. -message.your.revoked.granted = \u0423 \u0412\u0430\u0441 \u043e\u0442\u043d\u044f\u043b\u0438 \u043f\u0440\u0430\u0432\u0430 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 \u043a\u043e\u043c\u043d\u0430\u0442\u044b. -message.send.a.broadcast = \u041f\u043e\u0441\u043b\u0430\u0442\u044c \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0443 -message.broadcast.from = \u0420\u0430\u0441\u0441\u044b\u043b\u043a\u0430 \u043e\u0442 {0} -message.enter.message.to.broadcast = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043a\u0441\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0432 \u0412\u0430\u0448\u0435\u043c \u043a\u043e\u043d\u0442\u0430\u043a\u0442 \u043b\u0438\u0441\u0442\u0435. -message.broadcast.message.sent = \u0420\u0430\u0441\u0441\u044b\u043b\u043a\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430. -message.broadcast.to = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043a\u0441\u0442 \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438 \u0434\u043b\u044f {0} -message.broadcasted.to = \u0420\u0430\u0441\u0441\u044b\u043b\u043a\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c:\n{0} -message.user.now.available.to.chat = {0} \u0432 \u0441\u0435\u0442\u0438 \u0441 {1} -message.user.is.sending.you.a.file = {0} \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u0442 \u0412\u0430\u043c \u0444\u0430\u0439\u043b. -message.file.transfer.canceled = \u0412\u044b \u043e\u0442\u043c\u0435\u043d\u0438\u043b\u0438 \u043f\u0440\u0438\u0451\u043c \u0444\u0430\u0439\u043b\u0430. -message.negotiate.file.transfer = \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0441\u0432\u044f\u0437\u0438 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u0430. \u0416\u0434\u0438\u0442\u0435... -message.negotiate.stream = \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043a\u0430\u043d\u0430\u043b\u0430 \u0441\u0432\u044f\u0437\u0438. \u0416\u0434\u0438\u0442\u0435... -message.receiving.file = \u0412\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0435 \u0444\u0430\u0439\u043b \u043e\u0442 {0} -message.click.to.open = \u041e\u0442\u043a\u0440\u044b\u0442\u044c -message.error.during.file.transfer = \u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u0430. -message.transfer.refused = \u041f\u0440\u0438\u0451\u043c \u0444\u0430\u0439\u043b\u0430 \u043e\u0442\u043a\u043b\u043e\u043d\u0451\u043d. -message.transfer.cancelled = \u041f\u0440\u0438\u0451\u043c \u0444\u0430\u0439\u043b\u0430 \u043e\u0442\u043c\u0435\u043d\u0451\u043d. -message.received.file = \u0412\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0444\u0430\u0439\u043b \u043e\u0442 {0}. -message.file.exists.question = \u0424\u0430\u0439\u043b \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442. \u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c? -message.transfer.waiting.on.user = \u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 {0} \u0434\u043b\u044f \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u0451\u043c\u0430 \u0444\u0430\u0439\u043b\u0430. -message.negotiation.file.transfer = \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u0432\u044f\u0437\u044c \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u0430 {0}. \u0416\u0434\u0438\u0442\u0435... -message.unable.to.send.file = \u0412\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043b\u0430\u0442\u044c \u0444\u0430\u0439\u043b {0}. -message.sending.file.to = \u041f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0444\u0430\u0439\u043b \u0434\u043b\u044f {0}. -message.you.have.sent = \u0412\u044b \u043f\u043e\u0441\u043b\u0430\u043b\u0438 \u0444\u0430\u0439\u043b \u0434\u043b\u044f {0}. -message.file.transfer.rejected = {0} \u043d\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u043b \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0444\u0430\u0439\u043b\u0430. -message.disable.transport = \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0443\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f {0}? -message.register.transports = \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043e\u0432. -message.enter.aim = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0412\u0430\u0448\u0435 AIM \u0438\u043c\u044f \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. -message.enter.msn = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0412\u0430\u0448\u0435 \u0438\u043c\u044f \u0432 MSN \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. -message.enter.gtalk = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0412\u0430\u0448\u0435 \u0438\u043c\u044f \u0432 GTalk \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. -message.enter.xmpp = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0412\u0430\u0448\u0435 \u0438\u043c\u044f \u0432 XMPP \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. -message.enter.yahoo = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0412\u0430\u0448\u0435 \u0438\u043c\u044f \u0432 Yahoo \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. -message.enter.icq = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0412\u0430\u0448 \u043d\u043e\u043c\u0435\u0440 ICQ \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. -message.username.password.error = \u0418\u043c\u044f \u0438/\u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u044b. -message.registration.transport.failed = \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u0430. -message.client.information = \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u0434\u043b\u044f {0} -message.calling = \u0412\u044b\u0437\u044b\u0432\u0430\u044e {0} -message.number.to.call = \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u043e\u043c\u0435\u0440 \u0434\u043b\u044f \u043d\u0430\u0431\u043e\u0440\u0430 -message.prompt.plugin.uninstall = \u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 {0}? -message.restart.spark.changes = \u041f\u043b\u0430\u0433\u0438\u043d \u0431\u0443\u0434\u0435\u0442 \u0443\u0434\u0430\u043b\u0451\u043d \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430 Spark. -message.loading.please.wait = \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430. \u0416\u0434\u0438\u0442\u0435... -message.plugins.not.available = \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044e \u043f\u043b\u0430\u0433\u0438\u043d\u0430. -message.downloading = \u0417\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043e {0} -message.downloading.spark.plug = \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f Spark-Plug -message.unable.to.save.password = \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044c \u043a \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. -message.delete.all.history = \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u0441\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e? -message.image.too.large = \u041a\u0430\u0440\u0442\u0438\u043d\u043a\u0430 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u0430\u044f. \u0412\u044b\u0431\u0435\u0440\u0435\u0442\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 16k \u0438\u043b\u0438 \u043c\u0435\u043d\u044c\u0448\u0435. -message.save.profile = \u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0444\u0438\u043b\u044f, \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c. -message.unable.to.load.profile = \u041d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0434\u043b\u044f {0} -message.enter.jabber.id = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 Jabber ID -message.invalid.jabber.id = \u041d\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 Jabber ID -message.vcard.not.supported = \u0421\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 VCards. \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0412\u0430\u0448 VCard. -message.search.service.not.available = \u041d\u0435\u0442 \u0441\u0432\u044f\u0437\u0438 \u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c \u043f\u043e\u0438\u0441\u043a\u0430. -message.name.of.search.service.question = \u0418\u043c\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043f\u043e\u0438\u0441\u043a\u0430? -message.search.for.other.people = \u041f\u043e\u0438\u0441\u043a \u043b\u044e\u0434\u0435\u0439 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435. -message.specify.valid.time.error = \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u0438 \u043f\u043e\u0440\u0442. -message.timeout.error = \u0422\u0430\u0439\u043c\u0430\u0443\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 5 \u0441\u0435\u043a. -message.version = \u0412\u0435\u0440\u0441\u0438\u044f: {0} -message.file.size = \u0420\u0430\u0437\u043c\u0435\u0440 \u0444\u0430\u0439\u043b\u0430: {0} -message.restart.spark = \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043a\u0440\u044b\u0442\u044c Spark \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438.\n \u0417\u0430\u043a\u0440\u044b\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441? -message.updating.cancelled = \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u043e. -message.transfer.rate = \u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c -message.total.downloaded = \u0412\u0441\u0435\u0433\u043e \u0441\u043a\u0430\u0447\u0435\u043d\u043e -message.new.spark.available = {0} \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c? -message.restart.spark.to.install = \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043a\u0440\u044b\u0442\u044c Spark \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438. \u0417\u0430\u043a\u0440\u044b\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441? -message.add.to.roster = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0430\u043a\u0442 \u043b\u0438\u0441\u0442 -message.enter.room.password = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u043a\u043e\u043c\u043d\u0430\u0442\u044b -message.add.contact.to.list = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u043a\u043e\u043d\u0442\u0430\u043a\u0442 \u043b\u0438\u0441\u0442 -message.autenticating = \u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f -message.invalid.status = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u0443\u0441\u0430. -message.cannot.add.contact.to.shared.group = \u0412\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u044b \u0432 \u041e\u0431\u0449\u0438\u0435 \u0433\u0440\u0443\u043f\u043f\u044b. -message.specify.contact.jid = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 JID \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 ddman@jabber.org) -message.invalid.jid.error = JID \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439. -message.specify.group = \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u0433\u0440\u0443\u043f\u043f\u0443 \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u0430. -message.room.creation.error = \u041a\u043e\u043c\u043d\u0430\u0442\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0430. -message.unable.to.retrieve.last.activity = \u041d\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f {0}. -message.buzz.alert.notification = \u041f\u0440\u0438\u0432\u043b\u0435\u0447\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. -message.buzz.message = {0} \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0432\u0430\u0448\u0435\u0433\u043e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f -message.buzz.sent = \u00ab\u0420\u0430\u0437\u0431\u0443\u0434\u0438\u0442\u044c\u00bb \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. -message.received.file = \u0412\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0444\u0430\u0438\u043b \u043e\u0442 {0} -message.receiving.file = \u0412\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0435 \u0444\u0430\u0438\u043b \u043e\u0442 {0} -message.reconnect.attempting = \u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u043f\u0435\u0440\u0435\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f... -message.reconnect.failed = \u041d\u0435\u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u0435\u0440\u0435\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f -message.reconnect.wait = \u041f\u0435\u0440\u0435\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 {0} \u0441\u0435\u043a. -message.unable.to.use.hostname.as.resource = \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u044f \u0445\u043e\u0441\u0442\u0430 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u0430 - -title.appearance = \u0412\u043d\u0435\u0448\u043d\u0438\u0439 \u0432\u0438\u0434 -title.appearance.preferences = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0432\u0438\u0434\u0430 -title.appearance.showVCards = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c VCards \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u043e\u0432 -title.bookmarks = \u0417\u0430\u043a\u043b\u0430\u0434\u043a\u0438 -title.general.media = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043c\u0435\u0434\u0438\u0430 -title.no.updates = \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e -title.notes = \u0417\u0430\u043c\u0435\u0442\u043a\u0438 -title.passwords.no.match = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u0438 \u0437\u0430\u043d\u043e\u0432\u043e. -title.create.problem = \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c \u0443\u0447\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 -title.account.created = \u0423\u0447\u0435\u0442\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0430 -title.create.new.account = \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c -title.account.create.registration = \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0443\u0447\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 -title.register.account = \u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c -title.advanced.connection.preferences = \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f -title.preferences = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 -title.error = \u041e\u0448\u0438\u0431\u043a\u0430 -title.status.message = \u0421\u0442\u0430\u0442\u0443\u0441 -title.tasks = \u0421\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0434\u0430\u0447 -title.spark.preferences = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Spark -title.alert = \u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435 -title.tray.information = \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0432 \u0442\u0440\u0435\u0435 -title.select.file.to.send = \u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0444\u0430\u0439\u043b(\u044b) -title.choose.directory = \u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 -title.confirmation = \u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 -title.last.activity = \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c -title.add.new.group = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u0443 -title.add.to.roster = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0430\u043a\u0442 \u043b\u0438\u0441\u0442 -title.find.contacts = \u041d\u0430\u0439\u0442\u0438 \u043a\u043e\u043d\u0442\u0430\u043a\u0442 -title.rename.roster.group = \u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u0443 -title.roster = \u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u043b\u0438\u0441\u0442 -title.create.or.join = \u0421\u043e\u0437\u0434\u0430\u0442\u044c/\u0412\u043e\u0439\u0442\u0438 -title.conference.rooms = \u041a\u043e\u043c\u043d\u0430\u0442\u044b \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0439 -title.invite.to.conference = \u041f\u0440\u0438\u0433\u043b\u0430\u0441\u0438\u0442\u044c \u0432 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044e -title.room.information = \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043a\u043e\u043c\u043d\u0430\u0442\u0435 -title.change.nickname = \u0421\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0438\u043a -title.group.chat = \u0413\u0440\u0443\u043f\u043f\u043e\u0432\u043e\u0439 \u0447\u0430\u0442 -title.group.chat.settings = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0413\u0440\u0443\u043f\u043f\u043e\u0432\u043e\u0433\u043e \u0427\u0430\u0442\u0430 -title.create.or.bookmark.room = \u0412\u043e\u0439\u0442\u0438 \u0438\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0438 -title.browse.room.service = \u0421\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0439 - {0} -title.name = \u0418\u043c\u044f -title.address = \u0410\u0434\u0440\u0435\u0441 -title.occupants = \u0423\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0438 -title.browse.conference.services = \u0421\u043f\u0438\u0441\u043e\u043a \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0439 -title.find.conference.service = \u041f\u043e\u0438\u0441\u043a \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0439 -title.configure.chat.room = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u043e\u043c\u043d\u0430\u0442\u044b -title.conference.invitation = \u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044e -title.join.conference.room = \u0412\u043e\u0439\u0442\u0438 \u0432 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044e -title.view.room.information = \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 -title.configure.room = \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043a\u043e\u043c\u043d\u0430\u0442\u0443 -title.change.subject = \u0421\u043c\u0435\u043d\u0438\u0442\u044c \u0442\u0435\u043c\u0443 -title.enter.reason = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u0443 -title.room.destroyed = \u041a\u043e\u043c\u043d\u0430\u0442\u0430 \u0443\u043d\u0438\u0447\u0442\u043e\u0436\u0435\u043d\u0430 -title.edit.custom.message = \u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0443\u0441\u044b -title.set.status.message = \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0442\u0430\u0442\u0443\u0441 -title.broadcast.message = \u0420\u0430\u0441\u0441\u044b\u043b\u043a\u0430 -title.start.chat = \u041d\u0430\u0447\u0430\u0442\u044c \u0447\u0430\u0442 -title.view.bookmarks = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0438 -title.downloads = \u0417\u0430\u043a\u0430\u0447\u043a\u0438 -title.file.exists = \u0424\u0430\u0439\u043b \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 -title.disable.transport = \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0443\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 -title.available.transports = \u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u044b -title.transports = \u0422\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u044b -title.aim.registration = AIM \u0434\u0430\u043d\u043d\u044b\u0435 -title.gtalk.registration = GTalk \u0434\u0430\u043d\u043d\u044b\u0435 -title.xmpp.registration = XMPP \u0434\u0430\u043d\u043d\u044b\u0435 -title.msn.registration = MSN \u0434\u0430\u043d\u043d\u044b\u0435 -title.yahoo.registration = Yahoo \u0434\u0430\u043d\u043d\u044b\u0435 -title.icq.registration = ICQ \u0434\u0430\u043d\u043d\u044b\u0435 -title.registration.error = \u041e\u0448\u0438\u0431\u043a\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 -title.jabber.browser = \u0421\u043f\u0438\u0441\u043e\u043a -title.version.and.time = \u0412\u0435\u0440\u0441\u0438\u044f \u0438 \u0432\u0440\u0435\u043c\u044f -title.waiting.to.call = \u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u0437\u0432\u043e\u043d\u043a\u0430 -title.incoming.call = \u0412\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0437\u0432\u043e\u043d\u043e\u043a -title.on.the.phone = \u041d\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0435 -title.dial.phone = \u041f\u043e\u0437\u0432\u043e\u043d\u0438\u0442\u044c -title.history.for = \u0418\u0441\u0442\u043e\u0440\u0438\u044f \u0434\u043b\u044f {0} -title.reminder = \u041d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u0435 -title.plugins = \u041f\u043b\u0430\u0433\u0438\u043d\u044b -title.general.chat.settings = \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 -title.chat = \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 -title.notifications = \u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f -title.sound.preferences = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0432\u0443\u043a\u0430 -title.sounds = \u0417\u0432\u0443\u043a\u0438 -title.choose.incoming.sound = \u0412\u044b\u0431\u0435\u0440\u0435\u0442\u0435 \u0437\u0432\u0443\u043a \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0437\u0432\u043e\u043d\u043a\u0430 -title.choose.outgoing.sound = \u0412\u044b\u0431\u0435\u0440\u0435\u0442\u0435 \u0437\u0432\u0443\u043a \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0437\u0432\u043e\u043d\u043a\u0430 -title.choose.offline.sound = \u0412\u044b\u0431\u0435\u0440\u0435\u0442\u0435 \u0437\u0432\u0443\u043a \u00ab\u041e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u00bb -title.edit.profile = \u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u044c -title.profile.information = \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0444\u0438\u043b\u044f -title.profile.not.found = \u041f\u0440\u043e\u0444\u0438\u043b\u044c \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d -title.view.profile.for = \u041f\u0440\u043e\u0444\u0438\u043b\u044c \u0434\u043b\u044f {0} -title.lookup.profile = \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u043f\u0440\u043e\u0444\u0438\u043b\u044f -title.add.search.service = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043f\u043e\u0438\u0441\u043a\u0430 -title.person.search = \u041f\u043e\u0438\u0441\u043a \u043b\u044e\u0434\u0435\u0439 -title.login.settings = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0443\u0447\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 -title.login = \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 -title.downloading.im.client = \u0421\u043a\u0430\u0447\u0430\u0442\u044c IM \u043a\u043b\u0438\u0435\u043d\u0442 -title.upgrading.client = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c IM \u043a\u043b\u0438\u0435\u043d\u0442 -title.cancelled = \u041e\u0442\u043c\u0435\u043d\u0435\u043d\u043e -title.new.version.available = \u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f -title.new.client.available = \u0414\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 -title.password = \u041f\u0430\u0440\u043e\u043b\u044c -title.download.complete = \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430 -title.new.roster.group = \u041d\u043e\u0432\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430 -title.add.contact.group = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u0443 -title.add.contact = \u0414\u043e\u0431\u0430\u0432\u0438\u0442 \u043a\u043e\u043d\u0442\u0430\u043a\u0442 -title.file.transfer.preferences = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 -title.file.transfer = \u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 -title.subscription.request= \u0417\u0430\u043f\u0440\u043e\u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 - -menuitem.always.on.top = \u0412\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u0432\u0435\u0440\u0445 -menuitem.bookmarks = \u0417\u0430\u043a\u043b\u0430\u0434\u043a\u0438 -menuitem.languages = \u042f\u0437\u044b\u043a -menuitem.contacts = \u041a\u043e\u043d\u0442\u0430\u043a\u0442\u044b -menuitem.actions = \u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f -menuitem.exit = \u0412\u044b\u0445\u043e\u0434 -menuitem.plugins = \u041f\u043b\u0430\u0433\u0438\u043d\u044b -menuitem.logout.no.status = \u0412\u044b\u0439\u0442\u0438 -menuitem.logout.with.status = \u0412\u044b\u0439\u0442\u0438 \u0443\u043a\u0430\u0437\u0430\u0432 \u043f\u0440\u0438\u0447\u0438\u043d\u0443 -menuitem.show.traffic = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u043a\u043d\u043e \u0442\u0440\u0430\u0444\u0438\u043a\u0430 -menuitem.check.for.updates = \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f -menuitem.help = \u041f\u043e\u043c\u043e\u0449\u044c -menuitem.preferences = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 -menuitem.about = \u041e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435 -menuitem.online.help = Spark \u0444\u043e\u0440\u0443\u043c\u044b -menuitem.user.guide = \u0418\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f -menuitem.open = \u041e\u0442\u043a\u0440\u044b\u0442\u044c -menuitem.hide = \u0421\u043a\u0440\u044b\u0442\u044c -menuitem.status = \u0421\u0442\u0430\u0442\u0443\u0441 -menuitem.view.downloads = \u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043f\u0430\u043f\u043a\u0443 \u0437\u0430\u043a\u0430\u0447\u0435\u043a -menuitem.save = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c -menuitem.add = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c -menuitem.add.contact = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0430\u043a\u0442... -menuitem.add.contact.group = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u0443... -menuitem.add.groupchat.myname = \u041f\u043e\u0434\u0441\u0432\u0435\u0442\u0438\u0442\u044c \u043c\u043e\u0451 \u0438\u043c\u044f \u043a\u043e\u0433\u0434\u0430 \u0435\u0433\u043e \u043f\u0440\u043e\u0438\u0437\u043d\u043e\u0441\u044f\u0442 -menuitem.add.groupchat.mytext = \u041f\u043e\u0434\u0441\u0432\u0435\u0442\u0438\u0442\u044c \u043c\u043e\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f -menuitem.add.groupchat.popname = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u044e\u0449\u0435\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0438\u0437\u043d\u043e\u0441\u044f\u0442 \u043c\u043e\u0435 \u0438\u043c\u044f -menuitem.add.groupchat.showjoinleavemessage = \u041e\u043f\u043e\u0432\u0435\u0449\u0430\u0442\u044c \u043f\u0440\u0438 \u0432\u0445\u043e\u0434\u0435/\u0432\u044b\u0445\u043e\u0434\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 -menuitem.add.groupchat.showrolesinsteadofstatus = Show chat role icons instead of presence icons -menuitem.add.groupchat.auto.accept.invite = \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043f\u0440\u0438\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u044f \u043a \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 -menuitem.add.groupchat.random.colors = \u0421\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0435 \u0446\u0432\u0435\u0442\u0430 \u0434\u043b\u044f \u0438\u043c\u0451\u043d -menuitem.remove.from.group = \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u0437 \u0433\u0440\u0443\u043f\u043f\u044b -menuitem.start.a.chat = \u041d\u0430\u0447\u0430\u0442\u044c \u0447\u0430\u0442... -menuitem.rename = \u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c -menuitem.delete = \u0423\u0434\u0430\u043b\u0438\u0442\u044c -menuitem.edit = \u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c -menuitem.remove.from.roster = \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u0437 \u043a\u043e\u043d\u0442\u0430\u043a\u0442 \u043b\u0438\u0441\u0442\u0430 -menuitem.block.contact = \u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0430\u043a\u0442 -menuitem.unblock.contact = \u0420\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0430\u043a\u0442 -menuitem.subscribe.to = \u041f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f -menuitem.send.a.message = \u0420\u0430\u0441\u0441\u044b\u043b\u043a\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c... -menuitem.show.empty.groups = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u0435 \u0433\u0440\u0443\u043f\u043f\u044b -menuitem.send.a.file = \u041f\u043e\u0441\u043b\u0430\u0442\u044c \u0444\u0430\u0439\u043b -menuitem.view.last.activity = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 -menuitem.view.logs = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043b\u043e\u0433\u0438 -menuitem.view.profile = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u044c -menuitem.view.room.info = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043a\u043e\u043c\u043d\u0430\u0442\u0435 -menuitem.expand.all.groups = \u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0432\u0441\u0435 \u0413\u0440\u0443\u043f\u043f\u044b -menuitem.collapse.all.groups = \u0421\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0432\u0441\u0435 \u0413\u0440\u0443\u043f\u043f\u044b -menuitem.unban = \u0423\u0431\u0440\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u0435\u0442 -menuitem.ban = \u0417\u0430\u043f\u0440\u0435\u0442\u0438\u0442\u044c -menuitem.browse.service = \u0421\u043f\u0438\u0441\u043e\u043a \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 -menuitem.remove.service = \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 -menuitem.join.room = \u0412\u043e\u0439\u0442\u0438 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 -menuitem.remove.bookmark = \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0443 -menuitem.join.on.startup = \u0412\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 -menuitem.remove = \u0423\u0434\u0430\u043b\u0438\u0442\u044c -menuitem.change.nickname = \u0421\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0438\u043a -menuitem.block.user = \u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f -menuitem.unblock.user = \u0420\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f -menuitem.kick.user = \u0412\u044b\u0433\u043d\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f -menuitem.voice = \u041f\u0440\u0430\u0432\u043e \u0433\u043e\u043b\u043e\u0441\u0430 -menuitem.revoke.voice = \u041e\u0442\u043d\u044f\u0442\u044c \u043f\u0440\u0430\u0432\u043e \u0433\u043e\u043b\u043e\u0441\u0430 -menuitem.grant.voice = \u0414\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u043e \u0433\u043e\u043b\u043e\u0441\u0430 -menuitem.ban.user = \u0417\u0430\u043f\u0440\u0435\u0442\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f -menuitem.grant.moderator = \u0414\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u043c\u043e\u0434\u0435\u0440\u0430\u0442\u043e\u0440\u0430 -menuitem.revoke.moderator = \u041e\u0442\u043d\u044f\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u043c\u043e\u0434\u0435\u0440\u0430\u0442\u043e\u0440\u0430 -menuitem.invite.users = \u041f\u0440\u0438\u0433\u043b\u0430\u0441\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 -menuitem.invite.group.to.conference = \u041f\u0440\u0438\u0433\u043b\u0430\u0441\u0438\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u0443 \u0432 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044e -menuitem.start.a.conference = \u041d\u0430\u0447\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u044e... -menuitem.change.subject = \u0421\u043c\u0435\u043d\u0438\u0442\u044c \u0442\u0435\u043c\u0443 -menuitem.destroy.room = \u0423\u043d\u0438\u0447\u0442\u043e\u0436\u0438\u0442\u044c \u043a\u043e\u043c\u043d\u0430\u0442\u0443 -menuitem.set.status.message = \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0442\u0430\u0442\u0443\u0441... -menuitem.edit.status.message = \u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0443\u0441\u044b... -menuitem.broadcast.to.group = \u0420\u0430\u0441\u0441\u044b\u043b\u043a\u0430 \u0433\u0440\u0443\u043f\u043f\u0435 -menuitem.alert.when.online = \u0421\u043e\u043e\u0431\u0449\u0438\u0442\u044c \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0431\u0443\u0434\u0435\u0442 \u0432 \u0441\u0435\u0442\u0438 -menuitem.remove.alert.when.online = \u0423\u0431\u0440\u0430\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 -menuitem.save.as = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a... -menuitem.view.client.version = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e \u043a\u043b\u0438\u0435\u043d\u0442\u0430 -menuitem.view.contact.history = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u0441\u0442\u043e\u0440\u0438\u044e -menuitem.edit.my.profile = \u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u044c... -menuitem.lookup.profile = \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u044c... -menuitem.add.as.contact = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0430\u043a\u0442 -menuitem.chat = \u0427\u0430\u0442 -menuitem.chatframe.option = \u041e\u043f\u0446\u0438\u0438 -menuitem.sign.in = \u0412\u043e\u0439\u0442\u0438 -menuitem.sign.out = \u0412\u044b\u0439\u0442\u0438 -menuitem.sign.in.at.login = \u0412\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 -menuitem.enter.login.information = \u0412\u0432\u0435\u0441\u0442\u0438 \u0443\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 -menuitem.delete.login.information = \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0443\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 -menuitem.show.offline.group = \u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0435 \u0432 \u0441\u0435\u0442\u0438 -menuitem.show.offline.users = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u044b \u043d\u0435 \u0432 \u0441\u0435\u0442\u0438 -menuitem.show.contact.statusmessage = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0443\u0441 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 -menuitem.move.to = \u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 -menuitem.copy.to = \u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 - -tree.conference.services = \u0421\u0435\u0440\u0432\u0438\u0441\u044b \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0439 -tree.users.in.room = \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0435 - -lookandfeel.select = \u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 Look & Feel -lookandfeel.change.now = \u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441 -lookandfeel.tooltip.restart.no = \u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f -lookandfeel.tooltip.restart.yes = \u0414\u043b\u044f \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0421\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0433\u043e Look&Feel \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 Spark. -lookandfeel.color.label = \u0426\u0432\u0435\u0442\u0430 -lookandfeel.color.red = \u041a\u0440\u0430\u0441\u043d\u044b\u0439 -lookandfeel.color.green = \u0417\u0435\u043b\u0451\u043d\u044b\u0439 -lookandfeel.color.blue = \u0421\u0438\u043d\u0438\u0439 -lookandfeel.color.opacity = \u041f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0441\u0442\u044c -lookandfeel.color.saved = \u0426\u0432\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d - -tab.general = \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 -tab.proxy = \u041f\u0440\u043e\u043a\u0441\u0438 -tab.contacts = \u041a\u043e\u043d\u0442\u0430\u043a\u0442\u044b -tab.installed.plugins = \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b -tab.available.plugins = \u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b -tab.personal = \u041b\u0438\u0447\u043d\u043e\u0435 -tab.business = \u0420\u0430\u0431\u043e\u0442\u0430 -tab.home = \u0414\u043e\u043c -tab.avatar = \u0418\u043a\u043e\u043d\u043a\u0430 -tab.conferences = \u041a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 - -group.connection = \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 -group.conferences.found = \u041d\u0430\u0439\u0434\u0435\u043d\u044b \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0439 -group.comma.delimited = \u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u044f\u0442\u043e\u0439 -group.general.information = \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f -group.chat.window.information = \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0447\u0430\u0442\u0435 -group.notification.options = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 -group.search.form = \u041f\u043e\u0438\u0441\u043a -group.search.results = \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u043e\u0438\u0441\u043a\u0430 -group.login.information = \u0414\u0430\u043d\u043d\u044b\u0435 \u0443\u0447\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 - -tooltip.place.a.call = \u041f\u043e\u0437\u0432\u043e\u043d\u0438\u0442\u044c -tooltip.view.history = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u0441\u0442\u043e\u0440\u0438\u044e -tooltip.view.changelog = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 -tooltip.view.readme = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c ReadMe -tooltip.notifications = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0447\u0430\u0442\u043e\u0432. -tooltip.place.voice.call = \u0417\u0432\u043e\u043d\u043e\u043a. - -status.away = \u041e\u0442\u043e\u0448\u0435\u043b -status.custom.messages = \u041f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 -status.do.not.disturb = \u041d\u0435 \u0431\u0435\u0441\u043f\u043e\u043a\u043e\u0438\u0442\u044c -status.extended.away = \u041d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d -status.free.to.chat = \u0413\u043e\u0442\u043e\u0432 \u043f\u043e\u0431\u043e\u043b\u0442\u0430\u0442\u044c -status.on.phone = \u0413\u043e\u0432\u043e\u0440\u044e \u043f\u043e \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0443 -status.online = \u0412 \u0441\u0435\u0442\u0438 -status.pending = \u0412 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0438 - -##Settings for the privacy plugin -privacy.title.preferences = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0441\u0442\u0438 Spark -privacy.title.panel = \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043f\u0440\u0430\u0432\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443 \u043c\u044b\u0448\u0438 -privacy.label.iq.desc = \u0417\u0430\u043f\u0440\u043e\u0441\u044b -privacy.label.pin.desc = \u0412\u0438\u0434\u0435\u0442\u044c \u0435\u0433\u043e \u0441\u0442\u0430\u0442\u0443\u0441 -privacy.label.pout.desc = \u0412\u0438\u0434\u0435\u0442\u044c \u0432\u0430\u0448 \u0441\u0442\u0430\u0442\u0443\u0441 -privacy.label.msg.desc = \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f -privacy.border.information = \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f -privacy.label.information = \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043f\u0440\u0430\u0432\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443 \u043c\u044b\u0448\u0438 \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f/\u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0435\u0439 -privacy.root.node = \u041f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435 \u0441\u043f\u0438\u0441\u043a\u0438 -privacy.label.preferences = \u041f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0441\u0442\u044c -pricacy.tooltip.preferences = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0441\u0442\u0438 Spark -privacy.label.list.is.active = \u0410\u041a\u0422\u0418\u0412\u041d\u042b\u0419 -privacy.label.list.is.default = \u041f\u041e \u0423\u041c\u041e\u041b\u0427\u0410\u041d\u0418\u042e -privacy.border.block = \u0417\u0430\u043f\u0440\u0435\u0442\u0438\u0442\u044c -privacy.pick.one.or.more = \u0412\u044b\u0431\u0438\u0440\u0438\u0442\u0435 \u043e\u0434\u043d\u0443 \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432 \u0441\u043f\u0438\u0441\u043e\u043a -privacy.title.add.picker = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a -privacy.node.contacts = \u041a\u043e\u043d\u0442\u0430\u043a\u0442\u044b -privacy.node.groups = \u0413\u0440\u0443\u043f\u043f\u044b -privacy.menu.add.contacts = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u044b \u0432 \u0441\u043f\u0438\u0441\u043e\u043a -privacy.menu.add.groups = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u0443 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a -privacy.menu.add.rem.items = \u0423\u0434\u0430\u043b\u0438\u0442\u044c {0} \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 -privacy.menu.remove = \u0423\u0434\u0430\u043b\u0438\u0442\u044c -privacy.menu.activate.list = \u0410\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c -privacy.menu.default.list = \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c "\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e" -privacy.menu.add.list = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a -privacy.menu.remove.list = \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a -privacy.dialog.add.list = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 -privacy.dialog.rem.list = \u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c {0}? -privacy.status.menu.entry = \u041f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435 \u0441\u043f\u0438\u0441\u043a\u0438 -privacy.name.for.default.list = \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e -privacy.button.no.list.selected = \u041d\u0435\u0442 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430 - -##Stunfallback in media settings -stun.border.label = \u0417\u0430\u043f\u0430\u0441\u043d\u043e\u0439 STUN \u0441\u0435\u0440\u0432\u0435\u0440 -stun.server.addr = STUN \u0441\u0435\u0440\u0432\u0435\u0440: -stun.server.port = STUN \u043f\u043e\u0440\u0442: - -composing = {0} \u043f\u0438\u0448\u0435\u0442... -paused = {0} \u043f\u0440\u0435\u043a\u0440\u0430\u0442\u0438\u043b \u043f\u0438\u0441\u0430\u0442\u044c -active = {0} \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 -inactive = {0} \u0434\u0435\u043b\u0430\u0435\u0442 \u0447\u0442\u043e-\u0442\u043e \u0435\u0449\u0451 -gone = {0} \u0434\u0435\u043b\u0430\u0435\u0442 \u0447\u0442\u043e-\u0442\u043e \u0435\u0449\u0451 - -#!# -title.about=\u041e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435 -button.add2=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c -administrator=\u0410\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 -dialog.confirm.to.reveal.visibility.title=\u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b? -label.avatar=\u0410\u0432\u0430\u0442\u0430\u0440 -label.choose.file=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0444\u0430\u0439\u043b -message.search.page.timeperiod=\u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0435\u0440\u0438\u043e\u0434 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0437\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f -action.clear=\u041e\u0442\u0447\u0438\u0441\u0442\u0438\u0442\u044c -message.file.transfer.direrror.setdir=\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0437\u0434\u0435\u0441\u044c, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043a\u0430\u0442\u0430\u043b\u043e\u0433 -action.copy=\u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c -button.copy.to.clipboard=\u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0431\u0443\u0432\u0435\u0440 \u043e\u0431\u043c\u0435\u043d\u0430 -title.error.delete.file=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0444\u0430\u0439\u043b -title.error.find.app=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0439\u0442\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 -title.error.couldnt.open.file=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0444\u0430\u0439\u043b -title.error.rename.file=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b -menuitem.create.room=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u043b\u0438 \u0432\u043e\u0439\u0442\u0438 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 -action.cut=\u0412\u044b\u0440\u0435\u0437\u0430\u0442\u044c -privacy.menuitem.deactivate.current.list=\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c {0} -tab.deactivated.plugins=\u041e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b -menuitem.dial=\u041d\u0430\u0431\u0440\u0430\u0442\u044c -checkbox.use.krbconf=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c krb5.conf \u0438\u043b\u0438 krb5.ini -checkbox.use.krb.dns=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c DNS -button.reconnect2=\u041f\u0435\u0440\u0435\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f -participants=\u0423\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0438 -refresh=\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c -action.paste=\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c -action.print=\u041f\u0435\u0447\u0430\u0442\u044c -action.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c -action.select.all=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0451 -button.reject=\u041e\u0442\u043a\u043b\u043e\u043d\u0438\u0442\u044c -checkbox.use.specify.below=\u0423\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0438\u0436\u0435 -checkbox.use.pki.authentication=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043f\u043e\u0434\u043b\u0438\u043d\u043d\u043e\u0441\u0442\u0438 PKI -delete.log.permanently=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0436\u0443\u0440\u043d\u0430\u043b \u043d\u0430\u0432\u0441\u0435\u0433\u0434\u0430 -delete.permanently=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043d\u0430\u0432\u0441\u0435\u0433\u0434\u0430? -group.empty=\u0412 \u044d\u0442\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u0435 \u043d\u0435\u0442 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u0441\u0435\u0442\u0438 -group.offline=\u041e\u0444\u0444\u043b\u0430\u0439\u043d \u0433\u0440\u0443\u043f\u043f\u0430 -label.work=\u0420\u0430\u0431\u043e\u0442\u0430 -label.home=\u0414\u043e\u043c -label.passwordreset=\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f -label.downloads=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0438 -label.search=\u0418\u0441\u043a\u0430\u0442\u044c -menuitem.grant.admin=\u0414\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 -menuitem.grant.owner=\u0414\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u0432\u043b\u0430\u0434\u0435\u043b\u044c\u0446\u0430 -menuitem.grant.member=\u0414\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0430 -menuitem.open.with=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0432 ... -menuitem.revoke.member=\u041e\u0442\u043d\u044f\u0442\u044c \u043f\u0440\u0430\u0432\u043e \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0430 -menuitem.revoke.admin=\u041e\u0442\u043d\u044f\u0442\u044c \u043f\u0440\u0430\u0432\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 -title.delete.file=\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b? -message.file.transfer.nodir=\u041a\u0430\u0442\u0430\u043b\u043e\u0433 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 -message.file.transfer.dirnull=\u041a\u0430\u0442\u0430\u043b\u043e\u0433 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u043d\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u0435\u043d -label.enter.password=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u044c -message.enter.facebook=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0412\u0430\u0448\u0435 \u0438\u043c\u044f \u0432 Facebook \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. -message.enter.gadugadu=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0412\u0430\u0448\u0435 \u0438\u043c\u044f \u0432 GaduGadu \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. -message.enter.irc=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0412\u0430\u0448\u0435 \u0438\u043c\u044f \u0432 IRC \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. -message.enter.myspace=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0412\u0430\u0448\u0435 \u0438\u043c\u044f \u0432 MySpace \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. -message.enter.qq=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0412\u0430\u0448\u0435 \u043d\u043e\u043c\u0435\u0440 \u0432 QQ \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. -message.enter.sametime=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0412\u0430\u0448\u0435 \u0438\u043c\u044f \u0432 Sametime \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. -message.enter.simple=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0412\u0430\u0448\u0435 \u0438\u043c\u044f \u0432 SIMPLE \u0438 \u043f\u0430\u0440\u043e\u043b\u044c. -title.facebook.registration=\u0423\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 Facebook -title.file=\u0424\u0430\u0439\u043b -message.file.transfer.notification=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 -message.file.transfer.chat.window=\u0417\u0430\u043f\u0440\u043e\u0441 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u043e\u0432: -title.gadugadu.registration=\u0423\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 GaduGadu -dialog.confirm.to.reveal.visibility.msg=\u0415\u0441\u043b\u0438 \u0432\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0435\u0441\u044c \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u043d\u0435\u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0430 -message.unrecoverable.error=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c -dialog.confirm.close.all.conferences.if.invisible.msg=\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0432\u0441\u0435 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446-\u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043a\u0440\u044b\u0442\u044b -message.invalid.username.password=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c -status.invisible=\u041d\u0435\u0432\u0438\u0434\u0438\u043c\u044b\u0439 -menuitem.inivite.again=\u041f\u0440\u0438\u0433\u043b\u0430\u0441\u0438\u0442\u044c \u0441\u043d\u043e\u0432\u0430 -title.irc.registration=\u0423\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 IRC -message.file.transfer.short.message=\u043f\u043e\u0441\u044b\u043b\u0430\u0435\u0442 \u0432\u0430\u043c \u0444\u0430\u0439\u043b \u0441 \u0438\u043c\u0435\u043d\u0435\u043c: -label.keystore.location=\u0420\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043a\u043b\u044e\u0447\u0435\u0439 -title.login.error=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 -message=\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 -title.myspace.registration=\u0423\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 MySpace -title.notification=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 -status.offline=\u041d\u0435 \u0432 \u0441\u0435\u0442\u0438 -message.search.period.month.one=\u043e\u0434\u0438\u043d \u043c\u0435\u0441\u044f\u0446 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 -message.search.period.year.one=\u043e\u0434\u0438\u043d \u0433\u043e\u0434 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 -title.password.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0430\u0440\u043e\u043b\u044c -tab.pki=PKI -message.broadcast.no.text=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043a\u0441\u0442 \u0434\u043b\u044f \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438 -title.input.openwith=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043c\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c: -title.input.fileexplorer=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043c\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u043e\u0431\u043e\u0437\u0440\u0435\u0432\u0430\u0442\u0435\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432: -title.input.newname=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u043e\u0432\u043e\u0435 \u0438\u043c\u044f: -message.search.input.short=\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u0445\u043e\u0442\u044f \u0431\u044b \u043f\u044f\u0442\u044c \u0431\u0443\u043a\u0432. -message.broadcast.no.user.selected=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u044f -tooltip.file.transfer=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 -privacy.label.not.supported=\u0421\u043f\u0438\u0441\u043a\u0438 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0441\u0442\u0438 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c. -menuitem.refresh=\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c -menuitem.revoke.owner=\u041e\u0442\u043d\u044f\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u0432\u043b\u0430\u0434\u0435\u043b\u044c\u0446\u0430 -title.sametime.registration=\u0423\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 Sametime -title.qq.registration=\u0423\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 QQ -message.search.for.history=\u0418\u0441\u043a\u0430\u0442\u044c \u0432 \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u043a\u0438 -tooltip.send.email=\u041f\u043e\u0441\u043b\u0430\u0442\u044c e-mail -message.search.period.none=\u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0441\u0435 \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 -title.simple.registration=\u0423\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 SIMPLE -title.filesize=\u0420\u0430\u0437\u043c\u0435\u0440 -tooltip.start.chat=\u041d\u0430\u0447\u0430\u0442\u044c \u0440\u0430\u0437\u0433\u043e\u0432\u043e\u0440 -message.groupchat.registered.member=\u0423\u0441\u043f\u0435\u0448\u043d\u0430\u044f \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f: {0} -message.search.page.left=\u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043d\u0430\u0437\u0430\u0434 -message.search.page.right=\u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0432\u043f\u0435\u0440\u0435\u0434 -message.file.transfer.file.too.big.warning=\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0432\u0435\u043b\u0438\u043a.\n\u0412\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c? -message.groupchat.require.password=\u042d\u0442\u0430 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446-\u043a\u043e\u043c\u043d\u0430\u0442\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u0430 -action.viewlog=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043b\u043e\u0433 -message.restart.required=\u0412\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Spark, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u0441\u0442\u0443\u043f\u0438\u043b\u0438 \u0432 \u0441\u0438\u043b\u0443. \u041f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435 \u0441\u0435\u0439\u0447\u0430\u0441? -message.disconnected.shutdown=\u0412\u0430\u0448\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u0437\u0430\u043a\u0440\u044b\u0442\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0441\u0435\u0440\u0432\u0435\u0440 \u0431\u044b\u043b \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d -message.invite.to.groupchat={0} \u043f\u0440\u0438\u0433\u043b\u0430\u0448\u0430\u0435\u0442 \u0432\u0430\u0441 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c\u0441\u044f \u043a \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u043e\u043c\u0443 \u0447\u0430\u0442\u0443 -message.file.transfer.file.too.big.error=\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0432\u0435\u043b\u0438\u043a.\\n\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0444\u0430\u0439\u043b\u0430 {0}, \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b - {1} -message.search.page.counter=\u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0438\u043d\u0434\u0435\u043a\u0441 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u0441\u0435\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 -label.x509.certificate=\u0421\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 X.509 -message.server.unavailable=\u041d\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443: \u043d\u0435\u0432\u0435\u0440\u043d\u043e\u0435 \u0438\u043c\u044f \u0438\u043b\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d diff --git a/src/resources/i18n/spark_i18n_sv.properties b/src/resources/i18n/spark_i18n_sv.properties deleted file mode 100644 index 156029e88..000000000 --- a/src/resources/i18n/spark_i18n_sv.properties +++ /dev/null @@ -1,735 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.0.1 -## Added key: 'message.restart.spark.changes' -## Added key: 'message.enter.icq' -## Added key: 'title.icq.registration' -## Added key: 'button.quit' -## -## -## -## 2.0.2 -## Added key: 'button.new' -## Added key: 'label.group' -## Added key: 'label.jabber.id' -## Added key: 'label.enter.group.name' -## Added key: 'title.new.roster.group' -## Added key: 'title.add.contact.group' -## Added key: 'message.add.contact.to.list' -## Added key: 'title.add.contact' -## Added key: 'tab.conferences' -## Added key: 'message.autenticating' -## Added key: 'title.file.transfer.preferences' -## Added key: 'menuitem.about' -## Added key: 'message.invalid.status' -## Added key: 'message.cannot.add.contact.to.shared.group -## Added key: 'message.specify.contact.jid' -## Added key: 'message.invalid.jid.error' -## Added key: 'message.specify.group' -## Added key: 'add' -## -## -## -## 2.0.5 -## Added key: 'Broadcast' -## Added key: 'label.user.on.public.network' -## Added key: 'label.network' -## -## -## 2.0.6 -## Added key: 'button.add.user' -## Added key: 'menuitem.sign.in' -## Added key: 'menuitem.sign.out' -## Added key: 'menuitem.sign.in.at.login' -## Added key: 'menuitem.enter.login.information' -## Added key: 'menuitem.delete.login.information' -## Added key: 'button.save' -## -## -## 2.5 -## Added key: 'button.start.chat' -## Added key: 'button.send.email' -## Added key: 'available' -## Added key: 'checkbox.tabs.on.top' -## Added key: 'user.has.signed.in' -## Added key: 'user.has.signed.off' -## Added key: 'label.unable.to.add.contact' -## Added key: 'label.conflict.error' -## Added key: 'message.room.creation.error' -## Added key: 'checkbox.allow.buzz' -## Added key: 'message.disconnected.group.chat.error' -## Added key: 'menuitem.show.offline.group' -## Added key: 'menuitem.move.to' -## Added key: 'menuitem.copy.to' -## Added key: 'label.message.style' -## Added key: 'label.emoticons' -## Added key: 'checkbox.enable.emoticons' -## Added key: 'message.unable.to.retrieve.last.activity' -## Added key: 'checkbox.use.system.look.and.feel' -## -## 2.5.2 -## Added key: 'tooltip.place.voice.call' -## Added key: 'message.buzz.alert.notification' -## Added kye: 'message.buzz.sent' -## -## 2.5.2 -## Added key: 'menuitem.user.guide' -## -## -## -## 2.5.7 -## Added key: 'menuitem.languages' -## Added key: 'message.restart.required' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'message.send.to.these.people' -## Added key: 'message' -## Added key: 'message.normal' -## Added key: 'message.alert.notify' -## -## 2.5.8 -## Added key: 'message.enter.simple' -## Added key: 'message.enter.irc' -## Added key: 'message.enter.gadugadu' -## Added key: 'title.simple.registration' -## Added key: 'title.irc.registration' -## Added key: 'title.gadugadu.registration' -## Added key: 'message.username.error' -## Added key: 'message.password.error' -## Added key: 'message.nickname.error' - - -ok = Ok -cancel = Avbryt -add = Lägg till -use.default = Använd standard -close = Stäng -create = Skapa -invite = Bjud in -date = Datum -from = Från -room.name = Rum namn -join = Gå med -description = Beskrivning -subject = Rubrik -occupants = Invånare -accept = Godkän -reject = Avslå -open = Öppna -open.folder = Öppna mapp -retry = Försök igen -active = Aktiv -not.registered = Ej registrerad -save = Spara -yes = Ja -no = Nej -broadcast = Broadcast -available = Online -user.has.signed.in = har loggat in. -user.has.signed.off = har loggat ut. -message = Meddelande - - -button.create.account = &Skapa konto -button.close = S&täng -button.advanced = Av&ancerad -button.browse = &Bläddra... -button.browse2 = B&läddra... -button.browse3 = Bl&äddra... -button.approve = &Godkänn -button.deny = &Neka -button.accept = &Acceptera -button.profile = &Profil -button.add.a.contact = &Lägg till kontakt -button.reconnect = &Återanslut -button.add = &Lägg till -button.roster = &Deltagarlista -button.add.bookmark = Lägg till bokmärke -button.remove.bookmark = Ta bort bokmärke -button.bookmark.room = &Bokmärk rummet -button.create.room = &Skapa eller anslut till ett rum -button.join.room = &Anslut valt rum -button.refresh = &Uppdatera -button.find = &Hitta -button.update = &Uppdatera -button.cancel = &Avbryt -button.decline = &Neka -button.join = &Gå med -button.save.for.future.use = &För framtida behov -button.register = &Registrera -button.dial.number = &Slå nummer -button.clear = &Rensa -button.search = &Sök -button.add.service = &Lägg till tjänst -button.quit = &Avsluta -button.new = &Ny -button.add.user = &Lägg till användare -button.save = &Spara -button.start.chat = Chatt -button.send.email = Epost -button.send = Skicka - - - -checkbox.save.password = &Spara lösenord -checkbox.auto.login = &Automatisk login -checkbox.use.proxy.server = &Använd Proxy Server -checkbox.auto.discover.port = &Upptäck server och port automatiskt -checkbox.permanent = Rummet är &permanent -checkbox.private.room = Rummet &är privat -checkbox.show.time.in.chat.window = &Visa tid i chatt fönstret -checkbox.perform.spell.check = &Utför stavningskontroll i bakgrunden -checkbox.show.notifications.in.conference = &Visa meddelanden i konferensrummet -checkbox.disable.chat.history = &Stäng av chatt historik -checkbox.show.toaster = Visa &Popup -checkbox.window.to.front = &Flytta fönstret längst fram -checkbox.play.sound.on.new.message = Spela upp ljud vid nytt &meddelande -checkbox.play.sound.when.offline = Spela upp ljud vid när användare &loggar ut -checkbox.play.sound.on.outgoing.message = Spela upp ljud vid när meddelande &skickas -checkbox.play.sound.on.invitation = Spela upp ljud när &du får en inbjudan -checkbox.idle.enabled = &Viloläge aktivt -checkbox.launch.on.startup = &Autostart -checkbox.start.in.tray = &Starta i meddelandefältet -checkbox.split.chat.window = Docka &Fönstret (kräver omstart) -checkbox.tabs.on.top = &Chat tabs appear on top (kräver omstart) -checkbox.allow.buzz = Tillåt användare ringa dig. -checkbox.enable.emoticons = Tillått Kä&nsloikoner -checkbox.use.system.look.and.feel = Använd systemet utseende (kräver omstart) -checkbox.notify.user.goes.offline = Meddela när en användare loggar ut. -checkbox.notify.user.comes.online = Meddela när en användare loggar in. - - -label.user.on.public.network = Användaren är på ett publikt nätverk -label.change.password.to = &Byt lösenord till -label.username = &Användarnamn -label.name = &Namn -label.room.name = &Rummets Namn -label.room.topic= Rummets &rubrik -label.password = &Lösenord -label.confirm.password = &Bekräfta lösenord -label.server = &Server -label.create.konton = Skapa &konto -label.close = S&täng -label.ok = OK -label.cancel = Avbryt -label.use.default = Använd standard -label.port = &Port -label.auto.login = &Autologin -label.old.ssl = &Använd gamla SSL port metoden -label.host = &Värd -label.resource = &Resurs -label.protocol = &Protokoll -label.kontons = &Konton -label.receieved = &Mottaget -label.transfer.timeout = &Överförings timeout(min): -label.transfer.download.directory = &Mapp för nedladdning: -label.find = &Hitta -label.rename.to = Byt namn till -label.contact.to.find = Hitta kontakt -label.available.users.in.roster = &Användare på deltagarlistan -label.time = Tid: {0} -label.add.conference.service = &Lägg till konferenstjänst -label.add.jid = &Lägg till JID -label.message = &Meddelande -label.room = &Rum -label.invited.users = Bjud in användare -label.new.nickname = Nytt smeknamn -label.server.address = &Server adress -label.nickname = Sm&eknamn -label.presence = &Närvaro -label.priority = P&rioritet -label.enter.address = Ange adress -label.jabber.address = &Jabber adress -label.local.time = &Lokal tid -label.software = &Programvara -label.version = &Version -label.os = &Operativ system -label.number = &Nummer -label.dial = &Ring -label.minutes.before.stale.chat = &Minuter innan ett rum blir inaktivt -label.company = &Företag -label.street.address = &Gatuadress -label.city = &Stad -label.state.and.province = Län -label.postal.code = &Postnummer -label.country = L&and -label.job.title = &Titel -label.department = &Avdelning -label.phone = &Telefon -label.fax = &Fax -label.mobile = &Mobil -label.web.page = &Hemsida -label.pager = &Personsökare -label.first.name = &Förnamn -label.middle.name = &Mellannamn -label.last.name = &Efternamn -label.email.address = &Epost adress -label.jid = &JID -label.search.service = &Sök tjänst -label.xmpp.port = &XMPP Port -label.response.timeout = &Timeout för svarstid (sekunder) -label.time.till.idle = &Tid innan inaktiv (min) -label.jabber.id = &Jabber ID -label.group = &Grupp -label.enter.group.name = Ange nytt grupp namn -label.network = Nätver&k -label.unable.to.add.contact = Kan ej lägga till kontakt. -label.conflict.error = Kan ej logga in då kontot redan är inloggat. -label.message.style = &Meddelande stil -label.emoticons = &Känsloikoner -label.accounts = Konton - -message.username.error = Ange ett användarnamn för kontot. -message.password.error = Ange ett lösenord för kontot. -message.confirmation.password.error = Bekräfta lösenordet. -message.konton.error = Ange servern som kontot ska skapas på. -message.registering = Registrerar med {0}. Var god vänta... -message.connection.failed = Kan ej ansluta till {0}. -message.create.konton = Kontot kan inte skapas. -message.already.exists = Kontot finns redan. Försök med ett annat användarnamn. -message.konton.created = Nytt konto har skapats. -message.konton.create = Skapa ett nytt konto. -message.connecting.please.wait = Ansluter. Vänta... -message.supply.valid.timeout = Ange ett giltigt timeout värde. -message.supply.valid.port = Ange en giltig port. -message.supply.resource = Ange en giltig resurs. -message.current.status = Låt andra veta din nuvarande status. -message.disconnected.error = Din anslutning avbröts pga. ett fel. -message.disconnected.group.chat.error = Din anslutning avbröts pga. ett fel. Du måste återansluta till grupprummet. -message.disconnected.conflict.error = Din anslutning avbröts pga. eftersom du loggade in på en annan dator. -message.locked.workstation = Användare har låst sin dator -message.away.idle = Frånvarande pga. inaktivtet. -message.default.error = Ett allmänt fel har uppståt. Skicka felrapport till support@jivesoftware.com. -message.new.message = Nytt meddelande från {0}. -message.send.file.to.user = Skicka filer till denna användare. -message.send.picture = Fånga och skicka allt som syns på skärmen. -message.sent.offline.files = Du har skickat offline fil(er). -message.spark.secure = Klientet körs i säkert läge. -message.search.for.contacts = Sök efter kontakter. -message.end.conversation = Vill du avsluta denna session? -message.end.chat = Vill du avsluta denna chatt? -message.close.this.chat = Stänga denna chatt -message.close.other.chats = Stänga alla andra chattfönster -message.close.stale.chats = Stäng inaktiva chattfönster -message.last.message.received = Senaste meddelande togs emot {0} -message.shared.group = Delade grupper -message.is.shared.group = {0} är en delad grupp. -message.delete.confirmation = Vill du verkligen radera {0}? -message.idle.for = Inaktiv i {0} -message.enter.broadcast.message = Ange meddelande att skicka till valda användare. -message.name.of.group = Namn på grupp -message.approve.subscription = Tillått {0} att lägga till dig på sin användarlista? -message.add.user = Lägga till användaren på din lista? -message.general.error = Du har tappat kontakten med servern beroende på {0}. -message.add.a.contact = Lägg till en kontakt. -message.generic.reconnect.message = Du har tappat kontakten med servern. För att logga in igen, klicka på knappen nedan. -message.select.one.or.more = Välj en eller flera från din användarlista -message.add.conference.service = Lägg till en konferenstjänst. -message.service.already.exists = Tjänsten finns redan på din servicelista. -message.searching.please.wait = Söker. Vänligen vänta... -message.conference.service.error = Kan inte hitta konferenstjänsten. -message.create.or.join.room = Create or join a conference chat room -message.specify.name.error = Specify a valid name. -message.password.private.room.error = Specify password for the private room -message.passwords.no.match = Passwords do not match. -message.enter.valid.jid = Enter a valid Jabber ID -message.please.join.in.conference = Please join me in a conference. -message.invite.users.to.conference = Invite users to a conference room. -message.specify.users.to.join.conference = Specify users to join this conference room. -message.no.room.to.join.error = No room to join -message.participants.in.room = Participants In Room -message.you.have.been.kicked = You have been kicked out of this room. -message.kicked.error = You are not able to kick {0} out of this room. -message.you.have.been.banned = You have been banned from this room. -message.nickname.in.use = Nickname in use. Please specify another Nickname -message.update.room.list = Update Room List -message.join.conference.room = Join Conference Room -message.select.add.room.to.add = Please select a room to add to your service list. -message.bookmark.temporary.room.error = You cannot bookmark temporary rooms -message.select.room.to.join = Select room to join. -message.conference.info.error = Unable to retrieve conference information. Please try back later. -message.add.favorite.room = Add room to favorites list or join directly. -message.select.room.to.enter = Specify room to enter. -message.find.conference.services = Find conference services -message.specify.information.for.conference = Specify information for conference room. -message.no.description.available = No description available -message.no.subject.available = No subject available -message.room.information.for = Room information for {0} -message.view.information.about.this.user = View information about this user. -message.add.this.user.to.your.roster = Add this user to your buddy list. -message.came.online = {0} is online at {1} -message.went.offline = {0} went offline at {1} -message.offline.error = The user will be unable to receive offline messages. -message.offline = The user is offline and will receive the message on their next login. -message.is.typing.a.message = {0} is typing a message... -message.enter.new.subject = Enter new subject -message.confirm.destruction.of.room = Destroying the room removes all users from the room. Continue? -message.room.destruction.reason = Reason for destroying the room? -message.user.left.room = {0} has left the room. -message.user.joined.room = {0} has joined the room. -message.chat.session.ended = Chat session has ended on {0} -message.subject.change.error = You are not allowed to change the subject of this room. -message.forbidden.error = Received a forbidden error from the server. -message.room.destroyed = This room has been destroyed due to the following reason: {0} -message.subject.has.been.changed.to = The subject has been changed to {0}. -message.user.kicked.from.room = {0} has been kicked out of the room. -message.user.given.voice = {0} has been given a voice in this room. -message.user.voice.revoked = Voice has been revoked for {0}. -message.user.banned = {0} has been banned from this room. -message.user.granted.membership = {0} has been given membership priviliges. -message.user.revoked.membership = Membership has been revoked for {0}. -message.user.granted.moderator = {0} has been granted moderator privileges. -message.user.revoked.moderator = Moderator priviliges have been revoked for {0}. -message.user.granted.owner = {0} has been granted owner privileges. -message.user.revoked.owner = Owner priviliges have been revoked for {0}. -message.user.granted.admin = {0} has been granted administrator priviliges. -message.user.revoked.admin = Administrator privileges have been revoked for {0}. -message.user.nickname.changed = {0} is now known as {1}. -message.your.kicked = You have been kicked by {0}. -message.your.voice.granted = You have been given a voice in this chat. -message.your.voice.revoked = Your voice has been revoked. -message.your.banned = You have been banned from this room. -message.your.membership.granted = You have been granted membership privileges. -message.your.membership.revoked = Your membership has been revoked. -message.your.moderator.granted = You have been granted moderator privileges. -message.your.moderator.revoked = Your moderator privileges have been revoked. -message.your.ownership.granted = Your have been granted owner privileges. -message.your.ownership.revoked = Your owner privilieges have been revoked. -message.your.admin.granted = You have been granted administrator privileges. -message.your.revoked.granted = Your admin privileges have been revoked. -message.send.a.broadcast = Send a broadcast -message.broadcast.from = Broadcast from {0} -message.enter.message.to.broadcast = Enter message to broadcast to your entire roster list. -message.broadcast.message.sent = The broadcast message has been sent. -message.broadcast.to = Enter message to broadcast to {0} -message.broadcasted.to = The message has been broadcasted to the following users:\n{0} -message.user.now.available.to.chat = {0} is online at {1} -message.user.is.sending.you.a.file = {0} is sending you a file. -message.file.transfer.canceled = You have cancelled the file transfer. -message.negotiate.file.transfer = Negotiating file transfer. Please wait... -message.negotiate.stream = Negotiating connection stream. Please wait... -message.receiving.file = You are receiving a file from {0} -message.click.to.open = Click to open -message.error.during.file.transfer = There was an error during file transfer. -message.transfer.refused = The file transfer was refused. -message.transfer.cancelled = The file transfer was cancelled. -message.received.file = You have received a file from {0}. -message.file.exists.question = The file already exists. Overwrite? -message.transfer.waiting.on.user = Waiting for {0} to accept file transfer. -message.negotiation.file.transfer = Negotiating file transfer with {0}. Please wait... -message.unable.to.send.file = You were unable to send the file to {0}. -message.sending.file.to = Sending file to {0}. -message.you.have.sent = You have sent a file to {0}. -message.file.transfer.rejected = The file transfer was not accepted by {0}. -message.disable.transport = Remove login information from {0}? -message.register.transports = Register with these available transports. -message.enter.aim = Ange ditt AIM användardnamn och lösenord nedan. -message.enter.msn = Ange ditt MSN användardnamn och lösenord nedan. -message.enter.gtalk = Ange ditt GTalk användardnamn och lösenord nedan. -message.enter.xmpp = Ange ditt XMPP användardnamn och lösenord nedan. -message.enter.yahoo = Ange ditt användardnamn och lösenord nedan till Yahoo. -message.enter.icq = Ange ditt ICQ användardnamn och lösenord nedan. -message.enter.irc = Ange ditt IRC användardnamn,smeknamn och lösenord nedan. -message.enter.simple = Ange ditt SIMPLE användardnamn och lösenord nedan. -message.enter.gadugadu = Enter your GaduGadu username and password below. -message.username.error = Du måste ange användarnamn. -message.password.error = Du måste ange lösenord. -message.nickname.error = Du måste ange smeknamn. -message.username.password.error = Användarnamn och/eller lösenord måste anges. -message.registration.transport.failed = Kan inte registrera med gateway. -message.client.information = Klient information för {0} -message.calling = Ringer {0} -message.number.to.call = Ange nummer att ringa -message.no.caller.id = Inget called ID tillgängligt. -message.no.history.found = Det finns ingen historik för denna användare. -message.prompt.plugin.uninstall = Vill du verkligen avinstallera {0}? -message.restart.spark.changes = Plugin kommer att tas bort vid omstart av klienten. -message.loading.please.wait = Laddar. Vänliga vänta... -message.plugins.not.available = Inga plugins tillgängliga. -message.downloading = Laddar ner {0} -message.downloading.spark.plug = Laddar ner plugins -message.unable.to.save.password = Kan inte byta lösenord. Kontakta den systemansvarige. -message.delete.all.history = Radera all historik? -message.no.avatar.found = Ingen minatyrbild finns för denna användare. -message.image.too.large = För stor bild. Välj en bild som är 16k elle mindre. -message.save.profile = För att spara din profil, klicka på Spara. -message.unable.to.load.profile = Kan inte hitta profil för {0} -message.enter.jabber.id = Ange Jabber ID -message.invalid.jabber.id = Ingen giltigt Jabber ID -message.vcard.not.supported = Servern stödjer inte VCard. Kan inte spara ditt VCard. -message.search.service.not.available = Kan inte kontakta sök tjänsten. -message.no.results.found = Inget sökresultat returnerades från servern. -message.name.of.search.service.question = Namn på söktjänst? -message.search.for.other.people = Sök efter andra användare på servern. -message.specify.valid.time.error = Ange ett giltigt timeout värde och port. -message.timeout.error = Timeout värdet måste vara 5 sekunder eller större. -message.version = Version: {0} -message.file.size = Fil storlek: {0} -message.restart.spark = Du måste avsluta klienten för att \n installera den nya versionen. Vill du göra det nu? -message.updating.cancelled = Uppdateringen avbröts. -message.transfer.rate = Överförings hastighet -message.total.downloaded = Totalt nedladdat -message.new.spark.available = {0} är tillgänlig. Vill du installera? -message.restart.spark.to.install = Du måste avsluta klienten för att \n installera den nya versionen. Vill du göra det nu? -message.add.to.roster = Lägg till på användarlista -message.enter.room.password = Ange lösenord för grupprum -message.add.contact.to.list = Lägg till användaren på kontaktlista -message.autenticating = Autentiserar -message.invalid.status = Ange ett giltigt status meddelande. -message.cannot.add.contact.to.shared.group = Du kan inte lägga till kontakter på en delad grupp. -message.specify.contact.jid = Ange ett giltigt JID (ex. user@jabber.org) -message.invalid.jid.error = Felaktigt JID konto angivet. -message.specify.group = Ange kontaktgruppen som användaren ska tillhöra. -message.room.creation.error = Grupprummet kan inte skapas. -message.unable.to.retrieve.last.activity = Kan inte avgöra senaste aktivitet för {0}. -message.buzz.alert.notification = Påkalla användarens uppmärksamhet. -message.buzz.sent = Skicka larm till användaren. -message.restart.required = Du måste starta om klienten för att ändringarna ska börja gälla. Starta om nu? -message.send.to.these.people = Skicka till dessa människor -message.normal = Normalt meddelande -message.alert.notify = Larm meddelande -message.account.create = Här kan ni skapa ett nytt konto om server tillåter det. - -title.account.create.registration = Skapa nytt konto -title.passwords.no.match = Bekräfta lösenorden. -title.create.problem = Problem med att skapa kontot -title.konton.created = Kontor skapat -title.create.new.konton = Skapa nytt konto -title.konton.create.registration = Registrera konto -title.register.konton = Registrera nytt konto -title.notification = Notifieringar -title.advanced.connection.preferences = Avancerade anslutningar -title.preferences = Förinställningar -title.error = Fel -title.status.message = Status meddelande -title.spark.preferences = Klient inställningar -title.alert = Varning -title.tray.information = Tray Information -title.select.file.to.send = Väl fil(er) att sända -title.choose.directory = Välj katalog -title.confirmation = Bekräfta -title.last.activity = Senaste aktivitet -title.add.new.group = Lägg till ny grupp -title.add.to.roster = Lätt till på användarlista -title.find.contacts = Sök kontakter -title.rename.roster.group = Bytt namn användarlist gruppen -title.roster = Användarlista -title.create.or.join = Skapa/Anslut -title.conference.rooms = Konferens rum -title.invite.to.conference = Bjud in till konferens -title.room.information = Rumsinformation -title.change.nickname = Bytt smeknamn -title.group.chat = Grupp chatt -title.create.or.bookmark.room = Anslut eller bokmärk rum -title.browse.room.service = Bläddra efter konferensrum - {0} -title.name = Namn -title.address = Adress -title.occupants = Deltagare -title.browse.conference.services = Bläddra konferens tjänster -title.find.conference.service = Sök konferens tjänster -title.configure.chat.room = Konfigurera grupprum för chatt -title.conference.invitation = Bjud in till konferens -title.join.conference.room = Anslut till konferensrum -title.view.room.information = Visa grupprums information -title.configure.room = Konfigurera grupprum -title.change.subject = Ändra rubrik -title.enter.reason = Ange anledning -title.room.destroyed = Grupprum borttaget -title.edit.custom.message = Agen eget meddelande -title.set.status.message = Ange Status meddelande -title.broadcast.message = Skicka meddelande -title.start.chat = Starta chatt -title.view.bookmarks = Visa bokmärken -title.downloads = Nedladdningar -title.file.exists = Fil finns redan -title.disable.transport = Ta bort login information -title.available.transports = Tillgängliga transportgateways -title.transports = Transportgateways -title.aim.registration = AIM konton uppgifter -title.gtalk.registration = GTalk konton uppgifter -title.xmpp.registration = XMPP konton uppgifter -title.msn.registration = MSN konton uppgifter -title.yahoo.registration = Yahoo konton uppgifter -title.icq.registration = ICQ konton uppgifter -title.irc.registration = IRC konton uppgifter -title.simple.registration = SIMPLE konton uppgifter -title.gadugadu.registration = GaduGadu konton uppgifter -title.registration.error = Registreringsfel -title.jabber.browser = Bläddrare -title.version.and.time = Version och tid -title.waiting.to.call = Väntar på att ringa -title.incoming.call = Inkommande samtal -title.on.the.phone = Är i telefon -title.dial.phone = Ring nummer -title.history.for = Konversationshistorik för {0} -title.reminder = Påminnelse -title.plugins = Plugins -title.general.chat.settings = Allmänna chatt inställningar -title.chat = Chatt -title.notifications = Meddelanden -title.sound.preferences = Ljudinställningar -title.sounds = Ljud -title.choose.incoming.sound = Välj fil för inkommande ljud -title.choose.outgoing.sound = Välj fil för utgående ljud -title.choose.offline.sound = Välj fil för offline ljud -title.edit.profile = Editera profil information -title.profile.information = Profil information -title.profile.not.found = Profil hittades ej -title.view.profile.for = Visar profil för {0} -title.lookup.profile = Slå upp profil -title.add.search.service = Lägg till söktjänst -title.person.search = Sök efter person -title.login.settings = Login inställningar -title.login = Login -title.downloading.im.client = Ladda ner chatt Client -title.upgrading.client = Uppgradera klient -title.cancelled = Avbruten -title.new.version.available = Ny version tillgänlig -title.new.client.available = Ny klient tillgänlig -title.password = Lösenord -title.download.complete = Nedladdning komplett -title.new.roster.group = Ny användarlista -title.add.contact.group = Lägg till kontaktgrupp -title.add.contact = Lägg till kontakt -title.file.transfer.preferences = Filöverings inställningar -title.file.transfer = Fil överföring - -menuitem.contacts = Kontakter -menuitem.actions = Kommandon -menuitem.exit = Avsluta -menuitem.plugins = &Plugin -menuitem.logout.no.status = Logga ut -menuitem.logout.with.status = Logga ut och ange status -menuitem.show.traffic = Visa trafikfönster -menuitem.check.for.updates = Sök efter uppdateringar -menuitem.help = Hjälp -menuitem.preferences = Inställningar -menuitem.about = Om -menuitem.online.help = Internet forum -menuitem.user.guide = Användar guide -menuitem.open = Öppna -menuitem.hide = Dölj -menuitem.status = Status -menuitem.view.downloads = Visa nedladdningar -menuitem.save = Spara -menuitem.add = Lägg till -menuitem.add.contact = Lägg till kontakt -menuitem.add.contact.group = Lägg till grupp -menuitem.remove.from.group = Ta bort från grupp -menuitem.start.a.chat = Starta en chatt -menuitem.rename = Byt namn -menuitem.delete = Radera -menuitem.edit = Editera -menuitem.remove.from.roster = Ta bort från deltagarlista -menuitem.view.profile = Visa profil -menuitem.subscribe.to = Prenumera på -menuitem.send.a.message = Skicka meddelande till valda användare... -menuitem.show.empty.groups = Visa tomma grupper -menuitem.send.a.file = Skicka en fil -menuitem.view.last.activity = Visa senaste aktivitet -menuitem.unban = Avblockera -menuitem.ban = Blockera -menuitem.browse.service = Bläddra bland tjänster -menuitem.remove.service = Ta bort tjänst -menuitem.join.room = Anslut till grupprum -menuitem.remove.bookmark = Ta bort bokmärke -menuitem.join.on.startup = Anslut vid uppstart -menuitem.view.room.info = Visa rums information -menuitem.remove = Ta bort -menuitem.change.nickname = Ange smeknamn -menuitem.block.user = Blockera användare -menuitem.unblock.user = Avblockera användare -menuitem.kick.user = Sparka användare -menuitem.voice = Röst -menuitem.revoke.voice = Ta bort röst -menuitem.grant.voice = Tillåt röst -menuitem.ban.user = Blockera användare -menuitem.grant.moderator = Ge Moderator rättighet -menuitem.revoke.moderator = Ta bort Moderator -menuitem.invite.users = Bjud in användare -menuitem.invite.group.to.conference = Bjud in grupp till konferens -menuitem.start.a.conference = Starta en konferens... -menuitem.change.subject = Byt rubrik -menuitem.destroy.room = Ta bort grupprum -menuitem.set.status.message = Ange status meddelande... -menuitem.edit.status.message = Ange eget status meddelande... -menuitem.broadcast.to.group = Skicka meddelande till grupp -menuitem.alert.when.online = Larma när en användare är online -menuitem.remove.alert.when.online = Ta bort larm -menuitem.save.as = Spara som... -menuitem.view.client.version = Visa klient version -menuitem.view.contact.history = Visa kontakt historik -menuitem.edit.my.profile = &Editera min profil... -menuitem.lookup.profile = &Visa profil... -menuitem.add.as.contact = Lägg till som kontakt -menuitem.chat = Chatta -menuitem.sign.in = Logga in -menuitem.sign.out = Logga ut -menuitem.sign.in.at.login = Logga in vid uppstart -menuitem.enter.login.information = Ange login information -menuitem.delete.login.information = Radera login information -menuitem.show.offline.group = Gruppera offline användare -menuitem.move.to = Flytta till -menuitem.copy.to = Kopiera till -menuitem.languages = Språk - -tree.conference.services = Konferenstjänster -tree.users.in.room = Användare i grupprum - -tab.general = Generell -tab.proxy = Proxy -tab.contacts = Kontakter -tab.installed.plugins = Installerade plugins -tab.available.plugins = Tillgängliga plugins -tab.personal = Personligt -tab.business = Företag -tab.home = Hem -tab.avatar = Minibild -tab.conferences = Konferenser - -group.connection = Anslutning -group.conferences.found = Konferenstjänst hittad -group.comma.delimited = Komma separerad -group.general.information = Generell information -group.chat.window.information = Chatt fönster information -group.notification.options = Påminnelse inställningar -group.search.form = Sök formulär -group.search.results = Sök resultat -group.login.information = Login information - -tooltip.place.a.call = Ring upp denna individ -tooltip.view.history = Visa konversations historik -tooltip.view.changelog = Visa ändrings logg -tooltip.view.readme = Visa Readme -tooltip.notifications = Påminnelse inställningar för inkommande meddelanden. -tooltip.place.voice.call = Ring upp med röst. - - -#!# \ No newline at end of file diff --git a/src/resources/i18n/spark_i18n_tr.properties b/src/resources/i18n/spark_i18n_tr.properties deleted file mode 100644 index 4ac8a2769..000000000 --- a/src/resources/i18n/spark_i18n_tr.properties +++ /dev/null @@ -1,911 +0,0 @@ -## -## Spark Resource Bundle -## -## Turkish translator: Ali Erkan IMREK -## Please contact for translation errors and ideas. -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "+ -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.0.1 -## Added key: 'message.restart.spark.changes' -## Added key: 'message.enter.icq' -## Added key: 'title.icq.registration' -## Added key: 'button.quit' -## -## -## -## 2.0.2 -## Added key: 'button.new' -## Added key: 'label.group' -## Added key: 'label.jabber.id' -## Added key: 'label.enter.group.name' -## Added key: 'title.new.roster.group' -## Added key: 'title.add.contact.group' -## Added key: 'message.add.contact.to.list' -## Added key: 'title.add.contact' -## Added key: 'tab.conferences' -## Added key: 'message.autenticating' -## Added key: 'title.file.transfer.preferences' -## Added key: 'menuitem.about' -## Added key: 'message.invalid.status' -## Added key: 'message.cannot.add.contact.to.shared.group -## Added key: 'message.specify.contact.jid' -## Added key: 'message.invalid.jid.error' -## Added key: 'message.specify.group' -## Added key: 'add' -## -## -## -## 2.0.5 -## Added key: 'Broadcast' -## Added key: 'label.user.on.public.network' -## Added key: 'label.network' -## -## -## 2.0.6 -## Added key: 'button.add.user' -## Added key: 'menuitem.sign.in' -## Added key: 'menuitem.sign.out' -## Added key: 'menuitem.sign.in.at.login' -## Added key: 'menuitem.enter.login.information' -## Added key: 'menuitem.delete.login.information' -## Added key: 'button.save' -## -## -## 2.5 -## Added key: 'button.start.chat' -## Added key: 'button.send.email' -## Added key: 'available' -## Added key: 'checkbox.tabs.on.top' -## Added key: 'user.has.signed.in' -## Added key: 'user.has.signed.off' -## Added key: 'label.unable.to.add.contact' -## Added key: 'label.conflict.error' -## Added key: 'message.room.creation.error' -## Added key: 'checkbox.allow.buzz' -## Added key: 'message.disconnected.group.chat.error' -## Added key: 'menuitem.show.offline.group' -## Added key: 'menuitem.move.to' -## Added key: 'menuitem.copy.to' -## Added key: 'label.message.style' -## Added key: 'label.emoticons' -## Added key: 'checkbox.enable.emoticons' -## Added key: 'message.unable.to.retrieve.last.activity' -## Added key: 'checkbox.use.system.look.and.feel' -## -## 2.5.2 -## Added key: 'tooltip.place.voice.call' -## Added key: 'message.buzz.alert.notification' -## Added kye: 'message.buzz.sent' -## -## 2.5.2 -## Added key: 'menuitem.user.guide' -## -## -## -## 2.5.7 -## Added key: 'menuitem.languages' -## Added key: 'message.restart.required' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'message.send.to.these.people' -## Added key: 'message' -## Added key: 'message.normal' -## Added key: 'message.alert.notify' -## -## 2.5.8 -## Added key: 'message.enter.simple' -## Added key: 'message.enter.irc' -## Added key: 'message.enter.gadugadu' -## Added key: 'title.simple.registration' -## Added key: 'title.irc.registration' -## Added key: 'title.gadugadu.registration' -## Added key: 'message.username.error' -## Added key: 'message.password.error' -## Added key: 'message.nickname.error' -## -## 2.5.9 -## Added key: 'message.gateway.username.error. -## Added key: 'message.gateway.password.error. -## Added key: 'message.gateway.nickname.error. -## Added key: 'answer' -## Added key: 'online' -## Added key: 'online' -## Added key: 'offline' -## Added key: 'participants' -## Added key: 'unfiled' -## Added key: 'while.offline' -## Added key: 'action.clear' -## Added key: 'action.copy ' -## Added key: 'action.cut' -## Added key: 'action.paste' -## Added key: 'action.print' -## Added key: 'action.save' -## Added key: 'action.select.all' -## Added key: 'button.add2' -## Added key: 'button.copy.to.clipboard' -## Added key: 'button.reconnect2' -## Added key: 'button.tasks.active' -## Added key: 'button.tasks.all' -## Added key: 'button.view.notes' -## Added key: 'button.view.profile' -## Added key: 'button.view.tasklist' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.show.avatars.in.contaclist' -## Added key: 'checkbox.use.compression' -## Added key: 'group.empty' -## Added key: 'group.offline' -## Added key: 'label.add.task' -## Added key: 'label.chatroom.fontsize' -## Added key: 'label.contactlist.fontsize' -## Added key: 'label.due' -## Added key: 'label.show' -## Added key: 'label.timeformat' -## Added key: 'menuitem.dial' -## Added key: 'menuitem.view.logs' -## Added key: 'message.disconnected.shutdown' -## Added key: 'message.invalid.username.password' -## Added key: 'message.no.updates' -## Added key: 'message.reconnect.attempting' -## Added key: 'message.reconnect.failed' -## Added key: 'message.reconnect.wait' -## Added key: 'message.send.picture' -## Added key: 'message.server.unavailable' -## Added key: 'message.unrecoverable.error' -## Added key: 'message.waiting.for.user.to.join' -## Added key: 'status.available' -## Added key: 'status.away' -## Added key: 'status.custom.messages' -## Added key: 'status.do.not.disturb' -## Added key: 'status.extended.away' -## Added key: 'status.free.to.chat' -## Added key: 'status.on.phone' -## Added key: 'status.online' -## Added key: 'status.pending' -## Added key: 'title.about' -## Added key: 'title.appearance' -## Added key: 'title.appearance.preferences' -## Added key: 'title.login.error' -## Added key: 'title.no.updates' -## Added key: 'title.notes' -## Added key: 'title.tasks' -## Added key: 'tooltip.appearance' -## Added key: 'tooltip.file.transfer' -## Added key: 'tooltip.send.email' -## Added key: 'tooltip.start.chat' -## Added key: 'delete.log.permanently' -## Added key: 'delete.permanently' -## Added key: 'label.contactlist.avatarsize' -## Added key: 'title.qq.registration' -## Added key: 'message.enter.qq' -## -## 2.6.0 -## -## Added key: 'apply' - -accept = Kabul -active = Aktif -add = Ekle -answer = Cevap -apply = Uygula -available = Kullan\u0131labilir -broadcast = Yay\u0131n -cancel = \u0130ptal -close = Kapat -create = Olu\u015ftur -date = Tarih -description = A\u00e7\u0131klama -from = gelen -invite = Davet -join = Kat\u0131l -no = Hay\u0131r -not.registered = Kay\u0131tl\u0131 de\u011fil -occupants = Yerle\u015fikler -offline = \u00e7evrimd\u0131\u015f\u0131 -ok = Tamam -online = \u00e7evrimi\u00e7i -open = A\u00e7\u0131k -open.folder = Dizin a\u00e7 -participants = Kat\u0131l\u0131mc\u0131lar -reject = Reddet -retry = Tekrar dene -room.name = Oda ad\u0131 -save = Kaydet -subject = Konu -unfiled = Dosyalanmam\u0131\u015f -use.default = \u00d6ntan\u0131ml\u0131y\u0131 kullan -user.has.signed.in = giri\u015f yapt\u0131. -user.has.signed.off = \u00e7\u0131k\u0131\u015f yapt\u0131. -while.offline = \u00e7evrimd\u0131\u015f\u0131 s\u00fcresince -yes = Evet - -action.clear = Temizle -action.copy = Kopyala -action.cut = Kes -action.paste = Yap\u0131\u015ft\u0131r -action.print = Yazd\u0131r -action.save = Kaydet -action.select.all = T\u00fcm\u00fcn\u00fc se\u00e7 - -button.accept = &Kabul et -button.add = &Ekle -button.add.a.contact = &Bir ba\u011flant\u0131 ekle -button.add.bookmark = Yer imi ekle -button.add.service = &Servis ekle -button.add.user = &Kullan\u0131c\u0131 ekle -button.add2 = Ekl&e -button.advanced = &Geli\u015fmi\u015f -button.approve = &Onayla -button.bookmark.room = &Oday\u0131 imle -button.browse = &Tara... -button.browse2 = Ta&ra... -button.browse3 = T&ara... -button.cancel = &\u0130ptal -button.clear = &Temizle -button.close = Ka&pat -button.copy.to.clipboard = Panoya kopyala -button.create.account = &Hesap olu\u015ftur -button.create.room = &Oda olu\u015ftur veya kat\u0131l -button.decline = &Reddet -button.deny = &Yok say -button.dial.number = &Numaray\u0131 ara -button.find = &Bul -button.join = &Kat\u0131l -button.join.room = &Se\u00e7ilen odaya kat\u0131l -button.new = &Yeni -button.profile = &Profil -button.quit = &\u00c7\u0131k -button.reconnect = &Tekrar ba\u011flan -button.reconnect2 = Tekrar ba\u011flan -button.refresh = &Tazele -button.register = &Kaydet -button.remove.bookmark = Yer imini sil -button.roster = &Liste -button.save = &Kaydet -button.save.for.future.use = &Sonra kullanmak i\u00e7in kaydet -button.search = &Ara -button.send = G\u00f6nder -button.send.email = E-posta -button.start.chat = Sohbet -button.tasks.active = Aktif -button.tasks.all = T\u00fcm\u00fc -button.unset.file.explorer = Dosya taray\u0131c\u0131s\u0131 kurulmam\u0131\u015f -button.update = &G\u00fcncelle -button.view.notes = Notlar\u0131 g\u00f6ster -button.view.profile = Tam profili g\u00f6ster -button.view.tasklist = G\u00f6rev listesini g\u00f6ster - -checkbox.allow.buzz = Kullan\u0131c\u0131lar size uyar\u0131 titre\u015fimi g\u00f6nderebilsin. -checkbox.auto.discover.port = &Sunucu ve portu otomatik bul. -checkbox.auto.login = &Otomatik giri\u015f -checkbox.disable.chat.history = &Sohbet ge\u00e7mi\u015fini kapat -checkbox.disable.prev.chat.history = &Sohbette \u00f6nceki kay\u0131tlar\u0131n g\u00f6r\u00fcnt\u00fclenmesini kapat -checkbox.enable.emoticons = &Duygu ifadelerini a\u00e7 -checkbox.idle.enabled = &Idle Enabled -checkbox.launch.on.startup = &A\u00e7\u0131l\u0131\u015fta \u00e7al\u0131\u015ft\u0131r -checkbox.notify.user.comes.online = Kullan\u0131c\u0131 oturum a\u00e7t\u0131\u011f\u0131nda uyar -checkbox.notify.user.goes.offline = Kullan\u0131c\u0131 oturum kapatt\u0131\u011f\u0131nda uyar -checkbox.perform.spell.check = &Arkaplanda yaz\u0131m denetimi yap -checkbox.permanent =Oda &kal\u0131c\u0131d\u0131r -checkbox.play.sound.on.invitation = &Davet al\u0131nd\u0131\u011f\u0131nda ses \u00e7al -checkbox.play.sound.on.new.message = &Yeni mesaj al\u0131nd\u0131\u011f\u0131nda ses \u00e7al -checkbox.play.sound.on.outgoing.message = &Mesaj g\u00f6nderildi\u011finde ses \u00e7al -checkbox.play.sound.when.offline = Kullan\u0131c\u0131 oturum &kapatt\u0131\u011f\u0131nda ses \u00e7al -checkbox.private.room = Oda \u00f6&zeldir -checkbox.save.password = Parolay\u0131 &kaydet -checkbox.show.avatars.in.contactlist = Ba\u011flant\u0131 listesinde &avatarlar\u0131 g\u00f6ster -checkbox.show.notifications.in.conference = &Konferans odas\u0131nda uyar\u0131lar\u0131 g\u00f6ster -checkbox.show.time.in.chat.window = &Sohbet penceresinde zaman\u0131 g\u00f6ster -checkbox.show.toaster = Show a &Toast Popup -checkbox.split.chat.window = &Ta\u015f\u0131nabilir pencereler (yeniden ba\u015flat\u0131lmal\u0131) -checkbox.start.in.tray = &Sistem \u00e7ekmecesinde ba\u015flat -checkbox.tabs.on.top = Sohbet sekmelerini &\u00f6ne getir (yeniden ba\u015flat\u0131lmal\u0131) -checkbox.use.compression = S\u0131&k\u0131\u015ft\u0131rma kullan -checkbox.use.proxy.server = &Vekil sunucu kullan -checkbox.use.system.look.and.feel = Sistem aray\u00fcz g\u00f6r\u00fcn\u00fcm\u00fcn\u00fc kullan (yeniden ba\u015flat\u0131lmal\u0131) -checkbox.window.to.front = &Pencereyi \u00f6ne getir -checkbox.broadcast.hide.offline.user = \u00c7evrimd\u0131\u015f\u0131 kullan\u0131c\u0131lar\u0131 gizle - -delete.log.permanently = G\u00fcnl\u00fckleri kal\u0131c\u0131 olarak sil -delete.permanently = Kal\u0131c\u0131 olarak silinsin mi? - -gateway.username.password.error = Kullan\u0131c\u0131 ad\u0131 ve/veya parola gerekli. - -group.chat.window.information = Sohbet penceresi bilgisi -group.comma.delimited = Virg\u00fclle ayr\u0131lm\u0131\u015f -group.conferences.found = Konferans servisleri bulundu -group.connection = Ba\u011flant\u0131 -group.empty = Bu grupta hi\u00e7 \u00e7evrimi\u00e7i ba\u011flant\u0131 yok. -group.general.information = Genel bilgi -group.login.information = Giri\u015f bilgisi -group.notification.options = Uyar\u0131 ayarlar\u0131 -group.offline = \u00c7evrimd\u0131\u015f\u0131 -group.search.form = Arama formu -group.search.results = Arama sonu\u00e7lar\u0131 -group.chat.name.notification = G\u00f6r\u00fcnen isminiz... -group.chat.name.match = Ad\u0131n\u0131z grup sohbetinde ge\u00e7ti: - -label.accounts = &Hesaplar -label.add.conference.service = &Konferans servisi ekle -label.add.jid = &JID Ekle -label.add.task = G\u00f6rev ekle -label.auto.login = &Otomatik giri\u015f -label.available.users.in.roster = &Listemdeki kullan\u0131c\u0131lar -label.cancel = \u0130ptal -label.change.password.to = &Yeni Parolay\u0131 girin -label.chatroom.fontsize = Sohbet odas\u0131 &yaz\u0131tipi boyutu: -label.city = &\u015eehir -label.close = &Kapat -label.company = &Kurulu\u015f -label.confirm.password = Parolay\u0131 &onayla -label.conflict.error = Giri\u015f yap\u0131lamad\u0131, zaten giri\u015f yap\u0131lm\u0131\u015f. -label.contact.to.find = Ki\u015fi bul -label.contactlist.avatarsize = Ki\u015fi listesi &avatar boyutu: -label.contactlist.fontsize = K\u0130\u015fi listesi &yaz\u0131tipi boyutu: -label.country = &\u00dclke -label.create.account = &Hesap olu\u015ftur -label.department = &B\u00f6l\u00fcm -label.dial = &Dial -label.downloads = \u0130ndirmeler -label.due = Due -label.email.address = &E-posta adresi -label.emoticons = &Duygu ifadeleri -label.enter.address = Adres girin -label.enter.group.name = Yeni grup ad\u0131 girin -label.fax = &Faks -label.find = &Bul -label.first.name = &\u0130lk isim -label.group = &Grup -label.host = &Sunucu -label.invited.users = Davetli kullan\u0131c\u0131lar -label.jabber.address = &Jabber adresi -label.jabber.id = &Jabber ID -label.jid = &JID -label.job.title = &\u0130\u015f ba\u015fl\u0131\u011f\u0131 -label.last.name = &Soyad -label.local.time = &Yerel saat -label.message = &Mesaj -label.message.style = &Mesaj t\u00fcr\u00fc -label.middle.name = &\u0130kinci isim -label.minutes.before.stale.chat = &Aktif olmayan oda hareketsiz say\u0131lmadan \u00f6nce beklenecek dakika -label.mobile = &Mobil -label.name = &\u0130sim -label.network = A&\u011f -label.new.nickname = Yeni takma ad -label.nickname = Takma &ad -label.number = &Numara -label.ok = Tamam -label.old.ssl = &Eski SSL portu y\u00f6ntemini kullan -label.os = &\u0130\u015fletim sistemi -label.pager = &Sayfalay\u0131c\u0131 -label.password = &Parola -label.phone = &Telefon -label.port = &Port -label.postal.code = &Posta kodu -label.presence = &G\u00f6r\u00fcn\u00fc\u015f -label.priority = &\u00d6ncelik -label.protocol = &Protokol -label.received = &Received -label.rename.to = Ad\u0131n\u0131 \u015f\u00f6yle de\u011fi\u015ftir -label.resource = &Kaynak -label.response.timeout = &Cevap zaman a\u015f\u0131m\u0131 (san) -label.room = &Oda -label.room.name = O&da ad\u0131 -label.room.topic= Oda &konusu -label.search.service = &Arama servisi -label.server = &Sunucu -label.server.address = &Sunucu adresi -label.show = G\u00f6ster: -label.software = &Yaz\u0131l\u0131m -label.state.and.province = Eyalet/&B\u00f6lge -label.street.address = &Sokak -label.time = Zaman: {0} -label.time.till.idle = &Bo\u015fa \u00e7\u0131kma s\u00fcresi (dak) -label.timeformat = Kullan {0} -label.transfer.download.directory = &\u015eu dizine indir: -label.transfer.timeout = &Aktar\u0131m zaman a\u015f\u0131m\u0131 (dak): -label.unable.to.add.contact = Ki\u015fi eklenemedi. -label.use.default = \u00d6ntan\u0131ml\u0131y\u0131 kullan -label.user.on.public.network = Kullan\u0131c\u0131 genel a\u011fda -label.username = &Kullan\u0131c\u0131 ad\u0131 -label.version = &S\u00fcr\u00fcm -label.web.page = &Web sayfas\u0131 -label.xmpp.port = &XMPP Port - -menuitem.about = Hakk\u0131nda -menuitem.actions = Eylemler -menuitem.add = Ekle -menuitem.add.as.contact = Bir ba\u011flant\u0131 ekle -menuitem.add.contact = Ba\u011flant\u0131 ekle -menuitem.add.contact.group = Ba\u011flant\u0131 grubu ekle -menuitem.add.groupchat.myname = Sohbette ad\u0131m ge\u00e7ti\u011finde vurgula -menuitem.add.groupchat.mytext = Bir \u015feyler yazd\u0131\u011f\u0131mda yazd\u0131klar\u0131m\u0131 vurgula -menuitem.add.groupchat.popname= Bir sohbette ad\u0131m ge\u00e7ti\u011finde uyar\u0131 penceresi g\u00f6ster -menuitem.alert.when.online = Kullan\u0131c\u0131 uygun oldu\u011funda uyar -menuitem.ban = Yasak -menuitem.ban.user = Kullan\u0131c\u0131y\u0131 yasakla -menuitem.block.user = Kullan\u0131c\u0131y\u0131 engelle -menuitem.broadcast.to.group = Gruba yay\u0131n mesaj\u0131 -menuitem.browse.service = Servisi tara -menuitem.change.nickname = Takma ad de\u011fi\u015ftir -menuitem.change.subject = Konu de\u011fi\u015ftir -menuitem.chat = Sohbet -menuitem.check.for.updates = G\u00fcncellemelere bak -menuitem.contacts = Ba\u011flant\u0131lar -menuitem.copy.to = Kopyala -menuitem.delete = Sil -menuitem.delete.login.information = Giri\u015f bilgisini sil -menuitem.destroy.room = Oday\u0131 yok et -menuitem.dial = Sesli ara -menuitem.edit = D\u00fczenle -menuitem.edit.my.profile = &Profilimi d\u00fczenle... -menuitem.edit.status.message = \u00d6zel durum mesaj\u0131n\u0131 d\u00fczenle... -menuitem.enter.login.information = Ba\u011flant\u0131 bilgisini gir -menuitem.exit = \u00c7\u0131k -menuitem.grant.moderator = Ba\u015fkanl\u0131k haklar\u0131 -menuitem.grant.voice = Yazma hakk\u0131 ver -menuitem.help = Yard\u0131m -menuitem.hide = Gizle -menuitem.invite.group.to.conference = Konferansa grup davet et -menuitem.invite.users = Kullan\u0131c\u0131lar\u0131 davet et -menuitem.join.on.startup = A\u00e7\u0131l\u0131\u015fta kat\u0131l -menuitem.join.room = Odaya kat\u0131l -menuitem.kick.user = Kullan\u0131c\u0131y\u0131 d\u0131\u015far\u0131 at -menuitem.languages = Diller -menuitem.logout.no.status = Oturumu kapat -menuitem.logout.with.status = Durum mesaj\u0131 ile oturumu kapat -menuitem.lookup.profile = &Profile bak... -menuitem.move.to = Ta\u015f\u0131 -menuitem.online.help = Spark forumlar\u0131 -menuitem.open = A\u00e7 -menuitem.open.with = Birlikte a\u00e7... -menuitem.plugins = &Eklentiler -menuitem.preferences = Se\u00e7enekler -menuitem.remove = Sil -menuitem.remove.alert.when.online = Alarm\u0131 sil -menuitem.remove.bookmark = Yer imini sil -menuitem.remove.from.group = Gruptan sil -menuitem.remove.from.roster = Listemden sil -menuitem.remove.service = Servisi sil -menuitem.rename = Yeniden adland\u0131r -menuitem.revoke.moderator = Ba\u015fkanl\u0131\u011f\u0131 geri al -menuitem.revoke.voice = Yazma hakk\u0131n\u0131 al -menuitem.save = Kaydet -menuitem.save.as = Farkl\u0131 kaydet... -menuitem.send.a.file = Bir dosya g\u00f6nder -menuitem.send.a.message = Se\u00e7ili kullan\u0131c\u0131lara mesaj yay\u0131nla... -menuitem.set.status.message = Durum mesaj\u0131n\u0131 de\u011fi\u015ftir... -menuitem.show.empty.groups = Bo\u015f gruplar\u0131 g\u00f6ster -menuitem.show.offline.group = \u00c7evrimd\u0131\u015f\u0131 gruplar\u0131 g\u00f6ster -menuitem.show.traffic = Ak\u0131\u015f penceresini g\u00f6ster -menuitem.sign.in = Oturum a\u00e7 -menuitem.sign.in.at.login = Giri\u015f yap -menuitem.sign.out = Oturumu kapat -menuitem.start.a.chat = Bir sohbete ba\u015fla -menuitem.start.a.conference = Bir konferansa ba\u015fla... -menuitem.status = Durum -menuitem.subscribe.to = Kay\u0131t ol -menuitem.unban = Yasa\u011f\u0131 kald\u0131r -menuitem.unblock.user = Engellemeyi kald\u0131r -menuitem.user.guide = Kullan\u0131c\u0131 rehberi -menuitem.view.client.version = \u0130stemci s\u00fcr\u00fcm\u00fcn\u00fc g\u00f6ster -menuitem.view.contact.history = Ba\u011flant\u0131 ge\u00e7mi\u015fini g\u00f6ster -menuitem.view.downloads = \u0130ndirmeleri g\u00f6ster -menuitem.view.last.activity = Son hareketleri g\u00f6ster -menuitem.view.logs = G\u00fcnl\u00fckleri g\u00f6ster -menuitem.view.profile = Profili g\u00f6ster -menuitem.view.room.info = Oda bilgisini g\u00f6ster -menuitem.voice = Ses -menuitem.show.offline.users = \u00c7evrimd\u0131\u015f\u0131 kullan\u0131c\u0131lar\u0131 g\u00f6ster -menuitem.show.contact.statusmessage = Durum mesajlar\u0131n\u0131 g\u00f6ster -menuitem.join.room = Se\u00e7ili odaya kat\u0131l -menuitem.bookmark.room = Oday\u0131 yer imlerine ekle -menuitem.refresh = Yenile -menuitem.create.room = Bir oda olu\u015ftur veya kat\u0131l - -message = Mesaj -message.account.create = Yeni bir sohbet hesab\u0131 olu\u015ftur.. -message.account.created = Yeni sohbet hesab\u0131 olu\u015fturuldu. -message.account.error = Hesap olu\u015fturmak i\u00e7in bir sunucu belirtin. -message.add.a.contact = Bir ba\u011flant\u0131 ekle. -message.add.conference.service = Bir konferans servisi ekle. -message.add.contact.to.list = Ba\u011flant\u0131 listenize bir kullan\u0131c\u0131 ekleyin -message.add.favorite.room = Oday\u0131 favori listenize ekleyin veya hemen kat\u0131l\u0131n. -message.add.this.user.to.your.roster = Bu kullan\u0131c\u0131y\u0131 arkada\u015f listenize ekleyin. -message.add.to.roster = Listeme ekle. -message.add.user = Kullan\u0131c\u0131 listenize eklensin mi? -message.alert.notify = Alarm uyar\u0131s\u0131 -message.already.exists = Hesap zaten mevcut. L\u00fctfen farkl\u0131 bir kullan\u0131c\u0131 ad\u0131 se\u00e7in. -message.approve.subscription = {0}, sizi listesine ekleyecek, izin veriyor musunuz? -message.autenticating = Kimlik do\u011frulan\u0131yor -message.away.idle = Uzakta, ilgisiz -message.bookmark.temporary.room.error = Ge\u00e7ici odalar\u0131 yer imlerine ekleyemezsiniz. -message.broadcast.from = {0} taraf\u0131ndan yay\u0131n mesaj\u0131 -message.broadcast.message.sent = Yay\u0131n mesaj\u0131 g\u00f6nderildi. -message.broadcast.to = {0} taraf\u0131na g\u00f6nderilecek mesaj\u0131 girin. -message.broadcasted.to = Mesaj \u015fu kullan\u0131c\u0131lara yay\u0131nland\u0131::\n{0} -message.buzz.alert.notification = Kullan\u0131c\u0131lar\u0131n alarm uyar\u0131lar\u0131n\u0131 al. -message.buzz.sent = Kullan\u0131c\u0131ya bir alarm uyar\u0131s\u0131 g\u00f6nder. -message.calling = {0} aran\u0131yor -message.came.online = {0}, {1} taraf\u0131nda \u00e7evrimi\u00e7i -message.cannot.add.contact.to.shared.group = Payla\u015f\u0131lan gruba yeni ba\u011flant\u0131lar eklenemedi. -message.chat.session.ended = {0} \u00fczerindeki sohbet sonland\u0131 -message.click.to.open = T\u0131kla ve a\u00e7 -message.client.information = {0} i\u00e7in ba\u011flant\u0131 bilgisi -message.close.other.chats = Di\u011fer t\u00fcm sohbetleri kapat -message.close.stale.chats = Hareketsiz sohbetleri kapat -message.close.this.chat = Bu sohbeti kapat -message.conference.info.error = Konferans bilgisi al\u0131namad\u0131. L\u00fctfen sonra tekrar deneyin. -message.conference.service.error = Konferans servisi konumland\u0131r\u0131lamad\u0131. -message.confirm.destruction.of.room = Oda yok ediliyor, odadaki t\u00fcm kullan\u0131c\u0131lar silinir, devam edilsin mi? -message.confirmation.password.error = Onaylama parolas\u0131 tan\u0131mlay\u0131n. -message.connecting.please.wait = Ba\u011flan\u0131yor, l\u00fctfen bekleyin... -message.connection.failed = {0} taraf\u0131na ba\u011flan\u0131lamad\u0131. -message.create.account = Hesap olu\u015fturulamad\u0131. -message.create.or.join.room = Bir konferans sohbet odas\u0131 olu\u015ftur veya kat\u0131l. -message.current.status = Di\u011ferlerinin sizin durumunuzu ve hareketlerinizi bilmesine izin verin. -message.default.error = Bir hata tespit edildi. Bunu l\u00fctfen support@jivesoftware.com adresine rapor edin. -message.delete.all.history = Sohbet ge\u00e7mi\u015finin tamam\u0131 silinsin mi? -message.delete.confirmation = {0}, bunu silmek istedi\u011finizden emin misiniz? -message.disable.transport = {0} taraf\u0131ndan al\u0131nan ba\u011flant\u0131 bilgisi silinsin mi? -message.disconnected.conflict.error = Ba\u015fka bir konumdan ayn\u0131 kullan\u0131c\u0131 giri\u015f yapt\u0131\u011f\u0131 i\u00e7in ba\u011flant\u0131n\u0131z kapand\u0131. -message.disconnected.error = Ba\u011flant\u0131n\u0131z bir hata nedeniyle kapand\u0131. -message.disconnected.group.chat.error = Ba\u011flant\u0131n\u0131z bir hata nedeniyle kapand\u0131. Tekrar kullan\u0131c\u0131 giri\u015fi yapt\u0131ktan sonra odaya tekrar girmeniz gerekecek. -message.disconnected.shutdown = Ba\u011flant\u0131n\u0131z kapand\u0131 \u00e7\u00fcnk\u00fc sunucu kapat\u0131ld\u0131. -message.downloading = {0} indiriliyor -message.downloading.spark.plug = Spark-Plug indiriliyor -message.end.chat = Bu sohbeti sonland\u0131rmak istiyor musunuz? -message.end.conversation = Bu oturumu sonland\u0131rmak istiyor musunuz? -message.enter.aim = AIM kullan\u0131c\u0131 ad\u0131n\u0131z\u0131 ve parolan\u0131z\u0131 a\u015fa\u011f\u0131ya girin. -message.enter.broadcast.message = Se\u00e7ilen kullan\u0131c\u0131lara yay\u0131nlanacak mesaj\u0131 girin. -message.enter.gadugadu = GaduGadu kullan\u0131c\u0131 ad\u0131n\u0131z\u0131 ve parolan\u0131z\u0131 a\u015fa\u011f\u0131ya girin. -message.enter.gtalk = Gtalk kullan\u0131c\u0131 ad\u0131n\u0131z\u0131 ve parolan\u0131z\u0131 a\u015fa\u011f\u0131ya girin. -message.enter.icq = ICQ kullan\u0131c\u0131 ad\u0131n\u0131z\u0131 ve parolan\u0131z\u0131 a\u015fa\u011f\u0131ya girin. -message.enter.irc = IRC kullan\u0131c\u0131 ad\u0131n\u0131z\u0131, parolan\u0131z\u0131 ve takma ad\u0131n\u0131z\u0131 a\u015fa\u011f\u0131ya girin. -message.enter.jabber.id = Jabber ID girin -message.enter.message.to.broadcast = T\u00fcm g\u00f6rev listenize yay\u0131nlanacak mesaj\u0131 girin. -message.enter.msn = MSN kullan\u0131c\u0131 ad\u0131n\u0131z\u0131 ve parolan\u0131z\u0131 a\u015fa\u011f\u0131ya girin. -message.enter.new.subject = Yeni konuyu girin -message.enter.qq = QQ Numaran\u0131z\u0131 ve parolan\u0131z\u0131 a\u015fa\u011f\u0131ya girin. -message.enter.room.password = Oda parolas\u0131n\u0131 girin -message.enter.simple = SIMPLE Sunucusu i\u00e7in kullan\u0131c\u0131 ad\u0131n\u0131z\u0131 ve parolan\u0131z\u0131 a\u015fa\u011f\u0131ya girin. -message.enter.valid.jid = Ge\u00e7erli bir Jabber ID girin. -message.enter.xmpp = XMPP Sunucusu i\u00e7in kullan\u0131c\u0131 ad\u0131n\u0131z\u0131 ve parolan\u0131z\u0131 a\u015fa\u011f\u0131ya girin. -message.enter.yahoo = Kullan\u0131c\u0131 ad\u0131n\u0131z\u0131 ve parolan\u0131z\u0131n girerek Yahoo’ya ba\u011flan\u0131n. -message.error.during.file.transfer = Dosya aktar\u0131m\u0131 s\u0131ras\u0131nda bir hata olu\u015ftu. -message.file.exists.question = Dosya zaten mevcut, \u00fczerine yaz\u0131ls\u0131n m\u0131? -message.file.size = Dosya boyutu: {0} -message.file.transfer.canceled = Dosyan\u0131n aktar\u0131m\u0131n\u0131 iptal ettiniz. -message.file.transfer.rejected = Dosyan\u0131n aktar\u0131m\u0131 {0} taraf\u0131ndan kabul edilmedi. -message.file.transfer.notification = Dosya aktar\u0131m uyar\u0131s\u0131 -message.file.transfer.short.message = is sending you a file called: -message.file.transfer.chat.window = Dosya aktar\u0131m iste\u011fi: -message.find.conference.services = Konferans servislerini bul -message.forbidden.error = Sunucudan yasaklanma hatas\u0131 al\u0131nd\u0131. -message.gateway.username.error = Ge\u00e7erli bir kullan\u0131c\u0131 ad\u0131 gerekli. -message.gateway.password.error = Ge\u00e7erli bir parola gerekli. -message.gateway.nickname.error = Ge\u00e7erli bir takma ad gerekli. -message.general.error = {0} nedeniyle sunucu ile ba\u011flant\u0131y\u0131 kaybettiniz. -message.generic.reconnect.message = Sunucu ile ba\u011flat\u0131n\u0131z\u0131 kaybettiniz. Tekrar giri\u015f yapmak i\u00e7in Tekrar Ba\u011flan d\u00fc\u011fmesine t\u0131klay\u0131n. -message.idle.for = {0} bo\u015fta -message.image.too.large = Bu dosya kullanmak i\u00e7in \u00e7ok b\u00fcy\u00fck, 16kb veya daha k\u00fc\u00e7\u00fck boyutlu bir dosya se\u00e7in. -message.invalid.jabber.id = Jabber ID ge\u00e7ersiz. -message.invalid.jid.error = JID ge\u00e7ersiz. -message.invalid.status = Ge\u00e7erli bir durum mesaj\u0131 belirtin. -message.invalid.username.password = Ge\u00e7ersiz kullan\u0131c\u0131 ad\u0131 veya parola. -message.invite.users.to.conference = Kullan\u0131c\u0131lar\u0131 konferans odas\u0131na davet et. -message.is.shared.group = {0} payla\u015f\u0131lan bir grup. -message.is.typing.a.message = {0} bir mesaj yaz\u0131yor... -message.join.conference.room = Konferans odas\u0131na kat\u0131l. -message.kicked.error = {0} sizin taraf\u0131n\u0131zdan odadan at\u0131lamaz. -message.last.message.received = {0} taraf\u0131ndan son mesaj g\u00f6nderildi. -message.loading.please.wait = Y\u00fckleniyor, l\u00fctfen bekleyin... -message.locked.workstation = Kullan\u0131c\u0131 bilgisayar\u0131n\u0131 kilitlemi\u015f. -message.name.of.group = Grup ad\u0131 -message.name.of.search.service.question = Arama servisinin ad\u0131 nedir? -message.negotiate.file.transfer = Dosya aktar\u0131m\u0131 \u00e7\u00f6z\u00fcmleniyor. L\u00fctfen bekleyin... -message.negotiate.stream = Ak\u0131\u015f ba\u011flant\u0131s\u0131 \u00e7\u00f6z\u00fcmleniyor. L\u00fctfen bekleyin... -message.negotiation.file.transfer = {0} ile dosya aktar\u0131m\u0131 \u00e7\u00f6z\u00fcmleniyor. L\u00fctfen bekleyin... -message.new.message = {0} taraf\u0131ndan yeni mesaj. -message.new.spark.available = {0} kullan\u0131labilir. Kurmak ister misiniz? -message.nickname.in.use = Takma ad kullan\u0131l\u0131yor, ba\u015fka bir takma ad se\u00e7in. -message.no.avatar.found = Kullan\u0131c\u0131 avatar kullanm\u0131yor. -message.no.caller.id = Arama ID kullan\u0131lam\u0131yor. -message.no.description.available = A\u00e7\u0131klama yok. -message.no.history.found = Bu kullan\u0131c\u0131 i\u00e7in sohbet ge\u00e7mi\u015fi yok. -message.no.results.found = Sunucuda hi\u00e7 arama sonucu bulunamad\u0131. -message.no.room.to.join.error = Kat\u0131lacak oda yok -message.no.subject.available = No subject available -message.no.updates = Hi\u00e7 g\u00fcncelleme yok. -message.normal = Normal Mesaj -message.number.to.call = Arama numaras\u0131 -message.offline = Kullan\u0131c\u0131 \u00e7evrimd\u0131\u015f\u0131 ve mesaj\u0131 sonraki oturumu a\u00e7t\u0131\u011f\u0131nda alacak. -message.offline.error = Kullan\u0131c\u0131 \u00e7evrimd\u0131\u015f\u0131 mesajlar\u0131 alamayacak. -message.participants.in.room = Odadaki kat\u0131l\u0131mc\u0131lar -message.password.error = Bu hesab\u0131n parolas\u0131n\u0131 girin. -message.password.private.room.error = \u00d6zel odan\u0131n parolas\u0131n\u0131 girin. -message.passwords.no.match = Parola uyu\u015fmuyor. -message.please.join.in.conference = L\u00fctfen beni konferansa ekle. -message.plugins.not.available = Eklenti deposuna ba\u011flan\u0131lamad\u0131. -message.prompt.plugin.uninstall = Bunu kald\u0131rmak istedi\u011finizden emin misiniz?: {0} -message.received.file = {0} taraf\u0131ndan g\u00f6nderilen dosya al\u0131nd\u0131.. -message.receiving.file = {0} taraf\u0131ndan g\u00f6nderilen dosya al\u0131n\u0131yor. -message.reconnect.attempting = \u00c7al\u0131\u015f\u0131yor... -message.reconnect.failed = Tekrar ba\u011flan\u0131lamad\u0131. -message.reconnect.wait = {0} saniye i\u00e7inde ba\u011flan\u0131yor. -message.register.transports = Register with these available transports. -message.registering = {0} ile kay\u0131t yap\u0131l\u0131yor. L\u00fctfen bekleyin... -message.registration.transport.failed = Kay\u0131t yap\u0131lamad\u0131. -message.restart.spark = Yeni s\u00fcr\u00fcm\u00fc kurmak i\u00e7in \n Spark'\u0131 kapatman\u0131z gerekecek.Bunu \u015fimdi yapmak ister misiniz? -message.restart.spark.changes = Eklenti Spark’\u0131n sonraki \u00e7al\u0131\u015ft\u0131r\u0131lmas\u0131nda silinmi\u015f olacak. -message.restart.spark.to.install = Son s\u00fcr\u00fcm\u00fc kurmak i\u00e7in Spark’\u0131 kapatmal\u0131s\u0131n\u0131z. Bunu \u015fimdi yapmak ister misiniz? -message.restart.required = De\u011fi\u015fikliklerin etkin olmas\u0131 i\u00e7in Spark’\u0131 yeniden ba\u015flatmal\u0131s\u0131n\u0131z, yeniden ba\u015flat\u0131ls\u0131n m\u0131? -message.room.creation.error = Oda olu\u015fturulamad\u0131. -message.room.destroyed = Bu oda \u015fu nedenden dolay\u0131 silindi: {0} -message.room.destruction.reason = Oday\u0131 silmenizin nedeni nedir? -message.room.information.for = {0} izin oda bilgisi -message.save.profile = De\u011fi\u015fiklikleri profilinize kaydetmek i\u00e7in Kaydet’e t\u0131klay\u0131n. -message.search.for.contacts = Ba\u011flant\u0131lar\u0131 ara. -message.search.for.other.people = Sunucu \u00fczerinde di\u011fer ki\u015fileri ara. -message.search.service.not.available = Arama servisine ba\u011flan\u0131lamad\u0131. -message.searching.please.wait = Aran\u0131yor. L\u00fctfen bekleyin... -message.select.add.room.to.add = Servis listenize eklemek i\u00e7in bir oda se\u00e7in. -message.select.one.or.more = G\u00f6rev listenizden bir veya birka\u00e7 kullan\u0131c\u0131 se\u00e7in. -message.select.room.to.enter = Girmek i\u00e7in bir oda tan\u0131mlay\u0131n. -message.select.room.to.join = Kat\u0131lmak i\u00e7in bir oda se\u00e7in. -message.send.a.broadcast = Bir yay\u0131n g\u00f6nder -message.send.file.to.user = Dosyalar\u0131 bu kullan\u0131c\u0131ya g\u00f6nder. -message.send.picture = Ekran g\u00f6r\u00fcnt\u00fcs\u00fcn\u00fc yakala ve g\u00f6nder. -message.send.to.these.people = Bu ki\u015filere g\u00f6nder -message.sending.file.to = {0} kullan\u0131c\u0131s\u0131na dosya aktar\u0131l\u0131yor. -message.sent.offline.files = \u00c7evrimd\u0131\u015f\u0131 dosyalar\u0131 g\u00f6nderdiniz. -message.server.unavailable = Sunucuya ba\u011flan\u0131lamad\u0131: ge\u00e7ersiz isim veya sunucu eri\u015filemez durumda. -message.service.already.exists = Servis zaten servis listenizde. -message.shared.group = Payla\u015f\u0131lm\u0131\u015f grup. -message.spark.secure = Spark \u015fimdi g\u00fcvenli modda \u00e7al\u0131\u015f\u0131yor. -message.specify.contact.jid = L\u00fctfen ba\u011flant\u0131 JID'i belirleyin. (\u00f6rn: ddman@jabber.org) -message.specify.group = Yeni kullan\u0131c\u0131lar eklemek i\u00e7in ba\u011flant\u0131 grubu belirleyin. -message.specify.information.for.conference = Konferans odas\u0131 i\u00e7in bilgi girin. -message.specify.name.error = Ge\u00e7erli bir isim girin. -message.specify.users.to.join.conference = Bu konferans odas\u0131na belirli kullan\u0131c\u0131lar kat\u0131l\u0131r. -message.specify.valid.time.error = Ge\u00e7erli bir zaman a\u015f\u0131m\u0131 s\u00fcresi ve port girin. -message.subject.change.error = Bu odan\u0131n konusunu de\u011fi\u015ftirmek i\u00e7in yetkiniz yok. -message.subject.has.been.changed.to = Konu {0} olarak de\u011fi\u015ftirildi. -message.supply.resource = Ge\u00e7erli bir kaynak girin. -message.supply.valid.port = Ge\u00e7erli bir port girin. -message.supply.valid.timeout = Ge\u00e7erli bir zaman a\u015f\u0131m\u0131 s\u00fcresi girin. -message.timeout.error = Zaman a\u015f\u0131m\u0131 5 saniye veya daha fazla olmal\u0131d\u0131r. -message.total.downloaded = Toplan indirilen -message.transfer.cancelled = Dosyan\u0131n aktar\u0131m\u0131 iptal edildi. -message.transfer.rate = Aktar\u0131m h\u0131z\u0131 -message.transfer.refused = Dosyan\u0131n aktar\u0131m\u0131 reddedildi. -message.transfer.waiting.on.user = {0}, dosya aktar\u0131m\u0131n\u0131 kabul etmesi i\u00e7in bekleniyor. -message.unable.to.load.profile = {0} i\u00e7in profil y\u00fcklenemedi. -message.unable.to.retrieve.last.activity = {0} i\u00e7in son etkinlik belirlenemedi. -message.unable.to.save.password = Parola de\u011fi\u015ftirilemedi. L\u00fctfen sunucu y\u00f6neticisine ba\u015fvurun. -message.unable.to.send.file = {0} kullan\u0131c\u0131s\u0131na dosyay\u0131 g\u00f6nderemediniz. -message.unrecoverable.error = Ge\u00e7ersiz kullan\u0131c\u0131 ad\u0131 veya parola. -message.update.room.list = Oda listesini g\u00fcncelle -message.updating.cancelled = G\u00fcngelleme iptal edildi. -message.user.banned = {0} bu odadan yasakland\u0131. -message.user.given.voice = {0} kullan\u0131c\u0131s\u0131n\u0131n yazma hakk\u0131 var. -message.user.granted.admin = {0} kullan\u0131c\u0131s\u0131na y\u00f6neticilik haklar\u0131 verildi. -message.user.granted.membership = {0} kullan\u0131c\u0131s\u0131na \u00fcyelik haklar\u0131 verildi. -message.user.granted.moderator = {0} kullan\u0131c\u0131s\u0131na ba\u015fkanl\u0131k haklar\u0131 verildi. -message.user.granted.owner = {0} kullan\u0131c\u0131s\u0131na sahiplik haklar\u0131 verildi. -message.user.is.sending.you.a.file = {0} size bir dosya g\u00f6nderiyor. -message.user.joined.room = {0} odaya kat\u0131ld\u0131. -message.user.kicked.from.room = {0} Odan\u0131n d\u0131\u015f\u0131na at\u0131ld\u0131. -message.user.left.room = {0} odadan ayr\u0131ld\u0131. -message.user.nickname.changed = {0}, \u015fimdi {1} olarak biliniyor. -message.user.now.available.to.chat = {0}, {1} taraf\u0131nda \u00e7evrimi\u00e7i oldu -message.user.revoked.admin = {0} i\u00e7in y\u00f6netici yetkileriniz iptal edildi. -message.user.revoked.membership = {0} i\u00e7in \u00fcyeli\u011finiz iptal edildi. -message.user.revoked.moderator = {0} i\u00e7in ba\u015fkanl\u0131k yetkileriniz iptal edildi. -message.user.revoked.owner = {0} i\u00e7in sahiplik yetkileriniz iptal edildi. -message.user.voice.revoked = {0} kullan\u0131c\u0131s\u0131n\u0131n yazma hakk\u0131 yok. -message.username.error = Hesap i\u00e7in bir kullan\u0131c\u0131 ad\u0131 belirleyin. -message.username.password.error = Kullan\u0131c\u0131 ad\u0131 ve/veya parola gerekli. -message.vcard.not.supported = Sunucu VCard'lar\u0131 desteklemiyor. VCard'\u0131n\u0131z kaydedilemedi. -message.version = S\u00fcr\u00fcm: {0} -message.view.information.about.this.user = Bu kullan\u0131c\u0131 i\u00e7in bilgi g\u00f6ster. -message.waiting.for.user.to.join = Kat\u0131lmas\u0131 i\u00e7in beklenen: {0} -message.went.offline = {0}, {1} taraf\u0131nda \u00e7evrimd\u0131\u015f\u0131 oldu -message.you.have.been.banned = Bu odadan yasakland\u0131n\u0131z. -message.you.have.been.kicked = Bu odan\u0131n d\u0131\u015f\u0131na at\u0131ld\u0131n\u0131z. -message.you.have.sent = {0} kullan\u0131c\u0131s\u0131na bir dosya g\u00f6nderdiniz. -message.your.admin.granted = Y\u00f6netici yetkileriniz verildi. -message.your.banned = Bu oda i\u00e7in yasaklanm\u0131\u015fs\u0131n\u0131z. -message.your.kicked = {0} taraf\u0131ndan at\u0131ld\u0131n\u0131z. -message.your.membership.granted = \u00dcye yetkileriniz verildi. -message.your.membership.revoked = \u00dcyeli\u011finiz iptal edildi. -message.your.moderator.granted = Ba\u015fkanl\u0131k yetkileriniz verildi. -message.your.moderator.revoked = Ba\u015fkanl\u0131k yetkileriniz iptal edildi. -message.your.ownership.granted = Sahiplik yetkileriniz verildi. -message.your.ownership.revoked = Sahiplik yetkileriniz iptal edildi. -message.your.revoked.granted = Y\u00f6netici yetkileriniz iptal edildi. -message.your.voice.granted = Bu sohbet i\u00e7in yazma hakk\u0131 verildi. -message.your.voice.revoked = Yazma hakk\u0131n\u0131z iptal edildi. - -status.available = Uygun -status.away = Hemen d\u00f6necek -status.custom.messages = \u00d6zel durum -status.do.not.disturb = Rahats\u0131z etme -status.extended.away = Uzakta -status.free.to.chat = Sohbete a\u00e7\u0131k -status.on.phone = Sesli g\u00f6r\u00fc\u015fmede -status.online = \u00c7evrimi\u00e7i -status.pending = Beklemede - -tab.available.plugins = Kullan\u0131labilir eklentiler -tab.avatar = Avatar -tab.business = \u0130\u015f -tab.conferences = Konferanslar -tab.contacts = Ba\u011flant\u0131lar -tab.general = Genel -tab.home = Ev -tab.installed.plugins = Y\u00fckl\u00fc eklentiler -tab.personal = Ki\u015fisel -tab.proxy = Vekil sunucu - -title.about = Hakk\u0131nda -title.account.create.registration = Hesap kayd\u0131 -title.account.created = Hesap olu\u015fturuldu -title.add.contact = Ba\u011flant\u0131 ekle -title.add.contact.group = Yeni ba\u011flant\u0131 grubu ekle -title.add.new.group = Yeni grup ekle -title.add.search.service = Arama servisi ekle -title.add.to.roster = Listeme ekle -title.address = Adres -title.advanced.connection.preferences = Geli\u015fmi\u015f ba\u011flant\u0131 se\u00e7enekleri -title.alert = Alarm -title.appearance = G\u00f6r\u00fcn\u00fc\u015f -title.appearance.preferences = \u00d6zelle\u015ftirmeler -title.available.transports = Kullan\u0131labilir ta\u015f\u0131malar -title.broadcast.message = Duyuru mesaj\u0131 -title.browse.conference.services = Konferans servislerini tara -title.browse.room.service = konferans odalar\u0131n\u0131 tara - {0} -title.cancelled = \u0130ptal edildi -title.change.nickname = Takma ad\u0131 de\u011fi\u015ftir -title.change.subject = Konuyu de\u011fi\u015ftir -title.chat = Sohbet -title.choose.directory = Dizini se\u00e7 -title.choose.incoming.sound = Gelen ses dosyas\u0131n\u0131 se\u00e7 -title.choose.offline.sound = \u00c7evrimd\u0131\u015f\u0131 ses dosyas\u0131n\u0131 se\u00e7 -title.choose.outgoing.sound = Giden ses dosyas\u0131n\u0131 se\u00e7 -title.conference.invitation = Konferans daveti -title.conference.rooms = Konferans odalar\u0131 -title.configure.chat.room = Sohbet odas\u0131n\u0131 ayarla -title.configure.room = Oday\u0131 ayarla -title.confirmation = Onaylama -title.create.new.account = Yeni hesap olu\u015ftur -title.create.or.bookmark.room = Odaya kat\u0131l veya yer imlerine ekle -title.create.or.join = Olu\u015ftur/kat\u0131l -title.create.problem = Hesap olu\u015fturma sorunu -title.delete.file = Bu dosyay\u0131 ger\u00e7eten silmek istiyor musunuz? -title.dial.phone = Telefonu ara -title.disable.transport = Oturum a\u00e7ma bilgisini sil -title.download.complete = \u0130ndirme tamamland\u0131 -title.downloading.im.client = IM \u0130stemcisini indir -title.downloads = \u0130ndirmeler -title.edit.custom.message = \u00d6zel mesajlar\u0131 d\u00fczenle -title.edit.profile = Profil bilgisini d\u00fczenle -title.enter.reason = Nedeni girin -title.error = Hata -title.error.couldnt.open.file = Dosya a\u00e7\u0131lamad\u0131, bilinmeyen bir tipte olabilir. -title.error.delete.file = Dosya silinemedi. -title.error.find.app = E\u015fle\u015fen bir uygulama bulunamad\u0131. -title.error.rename.file = Dosya ad\u0131 de\u011fi\u015ftirilemedi. -title.file = Dosya -title.filesize = Boyut -title.file.exists = Dosya mevcut -title.file.transfer = Dosya transferi -title.file.transfer.preferences = Dosya transferi ayarlar\u0131 -title.find.conference.service = Konferans servisi bul -title.find.contacts = Ba\u011flant\u0131lar\u0131 bul -title.gadugadu.registration = GaduGadu Hesap kimli\u011fi -title.general.chat.settings = Genel sohbet ayarlar\u0131 -title.group.chat = Grup sohbeti -title.group.chat.settings = Grup sohbeti ayarlar\u0131 -title.gtalk.registration = GTalk Hesap kimli\u011fi -title.history.for = {0} i\u00e7in sohbet ge\u00e7mi\u015fi -title.icq.registration = ICQ Hesap kimli\u011fi -title.irc.registration = IRC Hesap kimli\u011fi -title.incoming.call = Gelen arama -title.input.fileexplorer = L\u00fctfen dosya taray\u0131c\u0131n\u0131z\u0131n ad\u0131n\u0131 girin: -title.input.newname = L\u00fctfen yeni ad\u0131 girin: -title.input.openwith = L\u00fctfen kullanmak istedi\u011finiz uygulaman\u0131n ad\u0131n\u0131 girin: -title.invite.to.conference = Konferansa davet et -title.jabber.browser = Taray\u0131c\u0131 -title.join.conference.room = Konferans odas\u0131na kat\u0131l -title.last.activity = Son etkinlik -title.login = Oturum a\u00e7 -title.login.error = Oturum a\u00e7ma hatas\u0131 -title.login.settings = Oturum a\u00e7ma ayarlar\u0131 -title.lookup.profile = Profile bak -title.msn.registration = MSN Hesap kimli\u011fi -title.name = \u0130sim -title.new.client.available = Yeni istemci kullan\u0131labilir -title.new.roster.group = Yeni liste grubu -title.new.version.available = Yeni s\u00fcr\u00fcm kullan\u0131labilir -title.no.updates = G\u00fcncelleme yok -title.notes = Notlar -title.notification = Uyar\u0131 -title.notifications = Uyar\u0131lar -title.occupants = Occupants -title.on.the.phone = Sesli g\u00f6r\u00fc\u015fmede -title.password = Parola -title.passwords.no.match = Parolay\u0131 onayla. -title.person.search = Ki\u015fi ara -title.plugins = Eklentiler -title.preferences = \u00d6zellikler -title.profile.information = Profil bilgisi -title.profile.not.found = Profil bulunamad\u0131 -title.qq.registration = QQ Hesab\u0131 kimlikleri -title.register.account = Yeni hesap kaydet -title.registration.error = Kay\u0131t hatas\u0131 -title.reminder = Hat\u0131rlat\u0131c\u0131 -title.rename.roster.group = Grubun ad\u0131n\u0131 de\u011fi\u015ftir -title.room.destroyed = Oda silindi -title.room.information =Oda bilgisi -title.roster = Liste -title.select.file.to.send = G\u00f6nderilecek dosyalar\u0131 se\u00e7 -title.set.status.message = Durum mesaj\u0131n\u0131 ayarla -title.simple.registration = Basit hesap kimlikleri -title.sound.preferences = Ses ayarlar\u0131 -title.sounds = Sesler -title.spark.preferences = Spark ayarlar\u0131 -title.start.chat = Sohbet ba\u015flat -title.status.message = Durum mesaj\u0131 -title.tasks = G\u00f6revler -title.transports = Ta\u015f\u0131malar -title.tray.information = Sistem tepsisi bilgisi -title.upgrading.client = \u0130stemci g\u00fcncellemesi -title.version.and.time = S\u00fcr\u00fcm ve zaman -title.view.bookmarks = Yer imlerini g\u00f6r\u00fcnt\u00fcle -title.view.profile.for = {0} Profili g\u00f6r\u00fcnt\u00fcleniyor -title.view.room.information = Oda bilgisini g\u00f6r\u00fcnt\u00fcle -title.waiting.to.call = \u00c7a\u011fr\u0131 i\u00e7in bekleniyor -title.xmpp.registration = XMPP Hesap kimli\u011fi -title.yahoo.registration = Yahoo hesap kimli\u011fi -title.appearance.showVCards = Ba\u011flant\u0131 listesinde VCard'lar\u0131 g\u00f6r\u00fcnt\u00fcle - -tooltip.appearance = Sohbetinizin g\u00f6r\u00fcn\u00fcm\u00fcn\u00fc de\u011fi\u015ftirin. -tooltip.file.transfer = Dosya transferi ayarlar\u0131. -tooltip.notifications = Gelen istekler i\u00e7in uyar\u0131 ayarlar\u0131. -tooltip.place.voice.call = Bu kullan\u0131c\u0131ya bir telefon \u00e7a\u011fr\u0131s\u0131 yap. -tooltip.send.email = E-posta g\u00f6nder. -tooltip.start.chat = Sohbeti ba\u015flat. -tooltip.view.changelog = De\u011fi\u015fiklik kay\u0131tlar\u0131n\u0131 g\u00f6r\u00fcnt\u00fcle -tooltip.view.history = Sohbet ge\u00e7mi\u015fini g\u00f6r\u00fcnt\u00fcle -tooltip.view.readme = Readme dosyas\u0131n\u0131 oku - -tree.conference.services = Konferans servisleri -tree.users.in.room = Odadaki kullan\u0131c\u0131lar - - - - -#!# \ No newline at end of file diff --git a/src/resources/i18n/spark_i18n_uk_UA.properties b/src/resources/i18n/spark_i18n_uk_UA.properties deleted file mode 100644 index 107750a31..000000000 --- a/src/resources/i18n/spark_i18n_uk_UA.properties +++ /dev/null @@ -1,1118 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.0.1 -## Added key: 'message.restart.spark.changes' -## Added key: 'message.enter.icq' -## Added key: 'title.icq.registration' -## Added key: 'button.quit' -## -## -## -## 2.0.2 -## Added key: 'button.new' -## Added key: 'label.group' -## Added key: 'label.jabber.id' -## Added key: 'label.enter.group.name' -## Added key: 'title.new.roster.group' -## Added key: 'title.add.contact.group' -## Added key: 'message.add.contact.to.list' -## Added key: 'title.add.contact' -## Added key: 'tab.conferences' -## Added key: 'message.autenticating' -## Added key: 'title.file.transfer.preferences' -## Added key: 'menuitem.about' -## Added key: 'message.invalid.status' -## Added key: 'message.cannot.add.contact.to.shared.group -## Added key: 'message.specify.contact.jid' -## Added key: 'message.invalid.jid.error' -## Added key: 'message.specify.group' -## Added key: 'add' -## -## -## -## 2.0.5 -## Added key: 'Broadcast' -## Added key: 'label.user.on.public.network' -## Added key: 'label.network' -## -## -## 2.0.6 -## Added key: 'button.add.user' -## Added key: 'menuitem.sign.in' -## Added key: 'menuitem.sign.out' -## Added key: 'menuitem.sign.in.at.login' -## Added key: 'menuitem.enter.login.information' -## Added key: 'menuitem.delete.login.information' -## Added key: 'button.save' -## -## -## 2.5 -## Added key: 'button.start.chat' -## Added key: 'button.send.email' -## Added key: 'available' -## Added key: 'checkbox.tabs.on.top' -## Added key: 'user.has.signed.in' -## Added key: 'user.has.signed.off' -## Added key: 'label.unable.to.add.contact' -## Added key: 'label.conflict.error' -## Added key: 'message.room.creation.error' -## Added key: 'checkbox.allow.buzz' -## Added key: 'message.disconnected.group.chat.error' -## Added key: 'menuitem.show.offline.group' -## Added key: 'menuitem.move.to' -## Added key: 'menuitem.copy.to' -## Added key: 'label.message.style' -## Added key: 'label.emoticons' -## Added key: 'checkbox.enable.emoticons' -## Added key: 'message.unable.to.retrieve.last.activity' -## Added key: 'checkbox.use.system.look.and.feel' -## -## 2.5.2 -## Added key: 'tooltip.place.voice.call' -## Added key: 'message.buzz.alert.notification' -## Added key: 'message.buzz.sent' -## -## 2.5.2 -## Added key: 'menuitem.user.guide' -## -## -## -## 2.5.7 -## Added key: 'menuitem.languages' -## Added key: 'message.restart.required' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'message.send.to.these.people' -## Added key: 'message' -## Added key: 'message.normal' -## Added key: 'message.alert.notify' -## -## 2.5.8 -## Added key: 'message.enter.simple' -## Added key: 'message.enter.irc' -## Added key: 'message.enter.gadugadu' -## Added key: 'title.simple.registration' -## Added key: 'title.irc.registration' -## Added key: 'title.gadugadu.registration' -## Added key: 'message.username.error' -## Added key: 'message.password.error' -## Added key: 'message.nickname.error' -## -## 2.5.9 -## Added key: 'message.gateway.username.error. -## Added key: 'message.gateway.password.error. -## Added key: 'message.gateway.nickname.error. -## Added key: 'answer' -## Added key: 'online' -## Added key: 'online' -## Added key: 'offline' -## Added key: 'participants' -## Added key: 'unfiled' -## Added key: 'while.offline' -## Added key: 'action.clear' -## Added key: 'action.copy ' -## Added key: 'action.cut' -## Added key: 'action.paste' -## Added key: 'action.print' -## Added key: 'action.save' -## Added key: 'action.select.all' -## Added key: 'button.add2' -## Added key: 'button.copy.to.clipboard' -## Added key: 'button.reconnect2' -## Added key: 'button.tasks.active' -## Added key: 'button.tasks.all' -## Added key: 'button.view.notes' -## Added key: 'button.view.profile' -## Added key: 'button.view.tasklist' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.show.avatars.in.contaclist' -## Added key: 'checkbox.use.compression' -## Added key: 'group.empty' -## Added key: 'group.offline' -## Added key: 'label.add.task' -## Added key: 'label.chatroom.fontsize' -## Added key: 'label.contactlist.fontsize' -## Added key: 'label.due' -## Added key: 'label.show' -## Added key: 'label.timeformat' -## Added key: 'menuitem.dial' -## Added key: 'menuitem.view.logs' -## Added key: 'message.disconnected.shutdown' -## Added key: 'message.invalid.username.password' -## Added key: 'message.no.updates' -## Added key: 'message.reconnect.attempting' -## Added key: 'message.reconnect.failed' -## Added key: 'message.reconnect.wait' -## Added key: 'message.send.picture' -## Added key: 'message.server.unavailable' -## Added key: 'message.unrecoverable.error' -## Added key: 'message.waiting.for.user.to.join' -## Added key: 'status.available' -## Added key: 'status.away' -## Added key: 'status.custom.messages' -## Added key: 'status.do.not.disturb' -## Added key: 'status.extended.away' -## Added key: 'status.free.to.chat' -## Added key: 'status.on.phone' -## Added key: 'status.online' -## Added key: 'status.pending' -## Added key: 'title.about' -## Added key: 'title.appearance' -## Added key: 'title.appearance.preferences' -## Added key: 'title.login.error' -## Added key: 'title.no.updates' -## Added key: 'title.notes' -## Added key: 'title.tasks' -## Added key: 'tooltip.appearance' -## Added key: 'tooltip.file.transfer' -## Added key: 'tooltip.send.email' -## Added key: 'tooltip.start.chat' -## Added key: 'delete.log.permanently' -## Added key: 'delete.permanently' -## Added key: 'label.contactlist.avatarsize' -## Added key: 'title.qq.registration' -## Added key: 'message.enter.qq' -## -## 2.6.0 -## -## Added key: 'apply' -## Added key: 'title.subscription.request' -## Added key: 'label.add.to.roster' -## Added key: 'label.audio.device' -## Added key: 'label.video.device' -## Added key: 'button.re.detect' -## -## 2.6.0 beta 1 -## Added key: 'menuitem.block.contact' -## Added key: 'menuitem.unblock.contact' -## Removed key: 'status.available' -## Added key: 'message.nickname.not.acceptable' -## Added key: 'button.login' -## Added key: 'administrator' -## Added key: 'menuitem.add.groupchat.showrolesinsteadofstatus' -## Added key: 'checkbox.click.single.tray' -## 2.7.0 beta 1 -## Added key: 'message.search.period.month.one' -## Added key: 'message.search.period.year.one' -## Added key: 'message.search.period.none' -## Added key: 'message.search.page.timeperiod' -## Added key: 'message.search.page.counter' -## Added key: 'message.search.page.right' -## Added key: 'message.search.page.left' -## Added key: 'checkbox.sort.asc.history' -## Added key: 'message.file.transfer.dirnull' -## Added key: 'message.file.transfer.nodir' -## Added key: 'message.file.transfer.cantwritedir' -## Added key: 'message.file.transfer.direrror.setdir' - -accept = \u041F\u0440\u0438\u0439\u043D\u044F\u0442\u0438 -active = \u0410\u043A\u0442\u0438\u0432\u043D\u0438\u0439 -add = \u0414\u043E\u0434\u0430\u0442\u0438 -administrator = \u0410\u0434\u043C\u0456\u043D -answer = \u0412\u0456\u0434\u043F\u043E\u0432\u0456\u0434\u044C -apply = \u0417\u0430\u0441\u0442\u043E\u0441\u0443\u0432\u0430\u0442\u0438 -available = \u041C\u043E\u0436\u043B\u0438\u0432\u0438\u0439 -broadcast = \u0422\u0440\u0430\u043D\u0441\u043B\u044E\u0432\u0430\u0442\u0438 -cancel = \u0421\u043A\u0430\u0441\u0443\u0432\u0430\u0442\u0438 -close = \u0417\u0430\u043A\u0440\u0438\u0442\u0438 -create = \u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 -date = \u0414\u0430\u0442\u0430 -description = \u041E\u043F\u0438\u0441 -from = \u0417 -invite = \u0417\u0430\u043F\u0440\u043E\u0441\u0438\u0442\u0438 -join = \u041F\u0440\u0438\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C -no = \u041D\u0456 -not.registered = \u041D\u0435 \u0437\u0430\u0440\u0435\u0454\u0441\u0442\u0440\u043E\u0432\u0430\u043D\u043E -occupants = \u041C\u0435\u0448\u043A\u0430\u043D\u0435\u0446\u044C -offline = \u041D\u0435 \u0432 \u043C\u0435\u0440\u0435\u0436\u0456 -online = \u0412 \u043C\u0435\u0440\u0435\u0436\u0456 -ok = \u0413\u0430\u0440\u0430\u0437\u0434 -open = \u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 -open.folder = \u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u0442\u0435\u043A\u0443 -participants = \u0423\u0447\u0430\u0441\u043D\u0438\u043A -refresh = \u041E\u043D\u043E\u0432\u0438\u0442\u0438 -reject = \u0412\u0456\u0434\u0445\u0438\u043B\u0438\u0442\u0438 -retry = \u0421\u043F\u0440\u043E\u0431\u0443\u0432\u0430\u0442\u0438 \u0449\u0435 -room.name = \u041D\u0430\u0437\u0432\u0430 \u0433\u0440\u0443\u043F\u0438 -save = \u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 -subject = \u0422\u0435\u043C\u0430 -unfiled = \u041D\u0435\u0437\u0430\u043F\u043E\u0432\u043D\u0435\u043D\u043E -use.default = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0441\u0442\u0430\u043D\u0434\u0430\u0440\u0442 -user.has.signed.in = \u0417\u0430\u0439\u0448\u043E\u0432 -user.has.signed.off = \u0412\u0438\u0439\u0448\u043E\u0432 -while.offline = \u041F\u043E\u043A\u0438 \u043D\u0435 \u0432 \u043C\u0435\u0440\u0435\u0436\u0456 -yes = \u0422\u0430\u043A - -action.clear = \u041E\u0447\u0438\u0441\u0442\u0438\u0442\u0438 -action.copy = \u041A\u043E\u043F\u0456\u044E\u0432\u0430\u0442\u0438 -action.cut = \u0412\u0438\u0440\u0456\u0437\u0430\u0442\u0438 -action.paste = \u0412\u0441\u0442\u0430\u0432\u0438\u0442\u0438 -action.print = \u0414\u0440\u0443\u043A\u0443\u0432\u0430\u0442\u0438 -action.save = \u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 -action.select.all = \u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0432\u0441\u0435 - -button.accept = \u041F\u0440\u0438\u0439\u043D\u044F\u0442\u0438 -button.add = \u0414\u043E\u0434\u0430\u0442\u0438 -button.add.a.contact = \u0414\u043E\u0434\u0430\u0442\u0438 \u043A\u043E\u043D\u0442\u0430\u043A\u0442 -button.add.bookmark = \u0414\u043E\u0434\u0430\u0442\u0438 \u0437\u0430\u043A\u043B\u0430\u0434\u043A\u0443 -button.add.service = \u0414\u043E\u0434\u0430\u0442\u0438 \u0441\u043B\u0443\u0436\u0431\u0443 -button.add.user = \u0414\u043E\u0434\u0430\u0442\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 -button.add2 = \u0414\u043E\u0434\u0430\u0442\u0438 -button.advanced = \u0414&\u043E\u0434\u0430\u0442\u043A\u043E\u0432\u043E -button.approve = \u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 -button.bookmark.room = \u0417\u0440\u043E\u0431\u0438\u0442\u0438 \u0437\u0430\u043A\u043B\u0430\u0434\u043A\u0443 -button.browse = &\u0412\u0438\u0431\u0440\u0430\u0442\u0438... -button.browse2 = \u0412\u0438\u0431\u0440\u0430\u0442\u0438... -button.browse3 = \u0412\u0438\u0431\u0440\u0430\u0442\u0438... -button.cancel = \u0412\u0456\u0434\u0445\u0438\u043B\u0438\u0442\u0438 -button.clear = \u041E\u0447\u0438\u0441\u0442\u0438\u0442\u0438 -button.close = \u0417\u0430\u043A\u0440\u0438\u0442\u0438 -button.copy.to.clipboard = \u0421\u043A\u043E\u043F\u0456\u044E\u0432\u0430\u0442\u0438 \u0434\u043E \u0431\u0443\u0444\u0435\u0440\u0430 \u043E\u0431\u043C\u0456\u043D\u0443 -button.create.account = \u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 -button.create.room = \u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0430\u0431\u043E \u043F\u0440\u0438\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C \u0434\u043E \u0433\u0440\u0443\u043F\u0438 -button.decline = \u0412\u0456\u0434\u0445\u0438\u043B\u0438\u0442\u0438 -button.deny = \u0417\u0430\u0431\u043E\u0440\u043E\u043D\u0438\u0442\u0438 -button.dial.number = \u041D\u0430\u0431\u0440\u0430\u0442\u0438 \u043D\u043E\u043C\u0435\u0440 -button.find = \u0417\u043D\u0430\u0439\u0442\u0438 -button.join = \u041F\u0440\u0438\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C -button.join.room = \u041F\u0440\u0438\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C \u0434\u043E \u043E\u0431\u0440\u0430\u043D\u043E\u0457 \u0433\u0440\u0443\u043F\u0438 -button.login = &\u0412\u0432\u0456\u0439\u0442\u0438 -button.new = \u041D\u043E\u0432\u0438\u0439 -button.profile = \u041F\u0440\u043E\u0444\u0430\u0439\u043B -button.quit = \u0412\u0438\u0445\u0456\u0434 -button.re.detect = &\u0412\u0438\u0437\u043D\u0430\u0447\u0438\u0442\u0438 \u0437\u0430\u043D\u043E\u0432\u043E -button.reconnect = \u0417'\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C \u0437\u0430\u043D\u043E\u0432\u043E -button.reconnect2 = \u0417'\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C \u0437\u0430\u043D\u043E\u0432\u043E -button.refresh = \u041E\u043D\u043E\u0432\u0438\u0442\u0438 -button.register = \u0417\u0430\u0440\u0435\u0454\u0441\u0442\u0440\u0443\u0432\u0430\u0442\u0438 -button.reject = \u0412\u0456\u0434\u0445\u0438\u043B\u0438\u0442\u0438 -button.remove.bookmark = \u0412\u0438\u043B\u0443\u0447\u0438\u0442\u0438 \u0437\u0430\u043A\u043B\u0430\u0434\u043A\u0443 -button.roster = \u0421\u043F\u0438\u0441\u043E\u043A -button.save = \u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 -button.save.for.future.use = \u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0434\u043B\u044F \u043C\u0430\u0439\u0431\u0443\u0442\u043D\u044C\u043E\u0433\u043E \u0432\u0436\u0438\u0442\u043A\u0443 -button.search = \u041F\u043E\u0448\u0443\u043A -button.send = \u041D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438 -button.send.email = E-\u0430\u0434\u0440\u0435\u0441\u0430 -button.start.chat = \u0411\u0430\u043B\u0430\u0447\u043A\u0438 -button.tasks.active = \u0410\u043A\u0442\u0438\u0432\u043D\u0438\u0439 -button.tasks.all = \u0423\u0441\u0456 -button.unset.file.explorer = Unset File Browser -button.update = \u041E\u043D\u043E\u0432\u0438\u0442\u0438 -button.view.notes = \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F -button.view.profile = \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0443\u0432\u0435\u0441\u044C \u043F\u0440\u043E\u0444\u0430\u0439\u043B -button.view.tasklist = \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0441\u043F\u0438\u0441\u043E\u043A \u0437\u0430\u0432\u0434\u0430\u043D\u044C - -checkbox.allow.buzz = \u0414\u043E\u0437\u0432\u0438\u043B\u0438\u0442\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430\u043C &\u0434\u0437\u0438\u043D\u044C\u043A\u0430\u0442\u0438 \u0442\u043E\u0431\u0456 -checkbox.auto.discover.port = \u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u043D\u043E \u0432\u0438\u044F\u0432\u043B\u044F\u0442\u0438 \u0445\u043E\u0441\u0442 \u0456 \u043F\u043E\u0440\u0442 -checkbox.auto.login = &\u0410\u0432\u0442\u043E\u043B\u043E\u0433\u0456\u043D -checkbox.login.as.invisible = \u0417&\u0430\u0439\u0442\u0438 \u043D\u0435\u043F\u043E\u043C\u0456\u0442\u043D\u043E -checkbox.disable.chat.history = &\u0412\u0456\u0434\u043C\u0456\u043D\u0438\u0442\u0438 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043D\u043D\u044F \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u044C -checkbox.sort.asc.history = \u0412\u043F\u043E\u0440\u044F\u0434\u043A\u0443\u0432\u0430\u0442\u0438 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F \u0437\u0430 \u0434\u0430\u0442\u043E\u044E -checkbox.disable.prev.chat.history = \u0412\u0456\u0434\u043C\u0456\u043D\u0438\u0442\u0438 &\u043F\u043E\u043A\u0430\u0437 \u043F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0456\u0445 \u0440\u043E\u0437\u043C\u043E\u0432 -checkbox.enable.emoticons = \u0414&\u043E\u0437\u0432\u043E\u043B\u0438\u0442\u0438 \u0435\u043C\u043E\u0446\u0456\u0457 -checkbox.graying.out = \u0417\u0430\u0442\u0456\u043D\u0438\u0442\u0438 \u043D\u0435\u0430\u043A\u0442\u0438\u0432\u043D\u0456 \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u0438(\u043F\u043E\u0442\u0440\u0456\u0431\u0435\u043D \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A) -checkbox.idle.enabled = &\u041D\u0435\u0430\u043A\u0442\u0438\u0432\u043D\u0456\u0441\u0442\u044C \u0434\u043E\u0437\u0432\u043E\u043B\u0435\u043D\u0430 -checkbox.launch.on.startup = &\u0417\u0430\u043F\u0443\u0441\u043A\u0430\u0442\u0438 \u043F\u0440\u0438 \u0432\u0432\u0456\u043C\u043A\u043D\u0435\u043D\u043D\u0456 -checkbox.reconnet.info = \u0412\u043A\u0430\u0437\u0430\u0442\u0438 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F \u043F\u0440\u0438 \u0432\u0456\u0434\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u0456 \u0437\u0432'\u044F\u0437\u043A\u0443: -checkbox.reconnect.panel.big = \u0412\u0456\u0434\u043E\u0431\u0440\u0430\u0437\u0438\u0442\u0438 \u044F\u043A \u043F\u0430\u043D\u0435\u043B\u044C -checkbox.reconnect.panel.small = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u0432 \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u043D\u0456\u0439 \u0433\u0440\u0443\u043F\u0456 -checkbox.reconnect.panel.icon = \u0412\u0456\u0434\u043E\u0431\u0440\u0430\u0437\u0438\u0442\u0438 \u044F\u043A \u043C\u0430\u043B\u044E\u043D\u043E\u043A -checkbox.notify.user.comes.online = \u041F\u043E\u0432\u0456\u0434\u043E\u043C\u0438\u0442\u0438, \u043A\u043E\u043B\u0438 &\u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447 \u0432\u0438\u0439\u0434\u0435 \u043D\u0430 \u0437\u0432'\u044F\u0437\u043E\u043A -checkbox.notify.user.goes.offline = &\u041F\u043E\u0432\u0456\u0434\u043E\u043C\u0438\u0442\u0438, \u043A\u043E\u043B\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447 \u0440\u043E\u0437\u0456\u0440\u0432\u0435 \u0437\u0432'\u044F\u0437\u043E\u043A -checkbox.notify.typing.systemtray = \u041F\u043E\u0432\u0456\u0434\u043E\u043C\u0438\u0442\u0438 \u043F\u0440\u043E \u043D\u0430\u0431\u0456\u0440 \u0441\u0438\u043C\u0432\u043E\u043B\u0456\u0432 -checkbox.notify.systemtray = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u043D\u043E\u0432\u0456 &\u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F \u0443 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u043E\u043C\u0443 \u043B\u043E\u0442\u043A\u0443 -checkbox.permanent = \u041F\u043E\u0441\u0442\u0456\u0439\u043D\u0430 \u0433\u0440\u0443\u043F\u0430 -checkbox.play.sound.on.invitation = \u0417\u0432\u0443\u043A \u043F\u0440\u0438 \u043E\u0442\u0440\u0438\u043C\u0430\u043D\u0456 \u0437\u0430\u043F\u0440\u043E\u0448\u0435\u043D\u043D\u044F -checkbox.play.sound.on.new.message = \u0417\u0432\u0443\u043A \u043F\u0440\u0438 \u043D\u043E\u0432\u043E\u043C\u0443 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u0456 -checkbox.play.sound.on.outgoing.message = \u0417\u0432\u0443\u043A \u043F\u0440\u0438 \u043D\u0430\u0434\u0441\u0438\u043B\u0430\u043D\u043D\u0456 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F -checkbox.play.sound.when.offline = \u0417\u0432\u0443\u043A, \u043A\u043E\u043B\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447 \u0432\u0456\u0434\u043A\u043B\u044E\u0447\u0438\u0432\u0441\u044F -checkbox.private.room = \u0417\u0430\u0445\u0438\u0449\u0435\u043D\u0430 \u0433\u0440\u0443\u043F\u0430 -checkbox.save.password = \u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C -checkbox.show.avatars.in.contactlist = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 &\u0437\u043D\u0430\u0447\u043A\u0438 \u0432 \u0441\u043F\u0438\u0441\u043A\u0443 \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u0456\u0432 -checkbox.show.notifications.in.conference = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 &\u043E\u043F\u043E\u0432\u0456\u0449\u0435\u043D\u043D\u044F \u0432 \u0433\u0440\u0443\u043F\u0456 -checkbox.show.time.in.chat.window = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u0447\u0430\u0441 \u0443 \u0432\u0456\u043A\u043D\u0456 -checkbox.show.toaster = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u0441\u043F\u043B\u0438\u0432\u0430\u044E\u0447\u0456 \u0432\u0456\u043A\u043D\u0430 -checkbox.disable.asterisk.toaster = \u0417\u0430\u0431\u043E\u0440\u043E\u043D\u0438\u0442\u0438 \u0441\u043F\u043B\u0438\u0432\u0430\u044E\u0447\u0456 \u0432\u0456\u043A\u043D\u0430 -checkbox.split.chat.window = \u0421\u0442\u0438\u043A\u0443\u0432\u0430\u0442\u0438 \u0432\u0456\u043A\u043D\u0430 (\u043F\u043E\u0442\u0440\u0456\u0431\u0435\u043D \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A) -checkbox.start.in.tray = &\u0421\u0442\u0430\u0440\u0442\u0443\u0432\u0430\u0442\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u043E\u043C\u0443 \u043B\u043E\u0442\u043A\u0443 -checkbox.click.single.tray = &\u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438 \u043E\u0434\u0438\u043D\u0430\u0440\u043D\u0439 \u043A\u043B\u0456\u043A \u0432 \u0441\u0438\u0442\u0435\u043C\u043D\u043E\u043C\u0443 \u043B\u043E\u0442\u043A\u0443 -checkbox.tabs.on.top = \u0412\u0456\u043A\u043D\u0430 \u0431\u0430\u043B\u0430\u0447\u043E\u043A \u0443\u0433\u043E\u0440\u0456 (\u043F\u043E\u0442\u0440\u0456\u0431\u0435\u043D \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A) -checkbox.use.compression = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u0442\u0438\u0441\u043A\u0430\u043D\u043D\u044F -checkbox.use.debugger.on.startup = \u0417\u0430\u043F\u0443\u0441\u043A\u0430\u0442\u0438 \u0432\u0456\u0434\u043B\u0430\u0434\u043D\u0438\u043A \u043F\u0440\u0438 \u0432\u0432\u0456\u043C\u043A\u043D\u0435\u043D\u043D\u0456 -checkbox.use.proxy.server = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438 \u043F\u0440\u043E\u043A\u0441\u0456-\u0441\u043B\u0443\u0436\u0431\u0443 -checkbox.use.system.look.and.feel = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u0438\u0442\u0435\u043C\u043D\u0438\u0439 \u043F\u043E\u0448\u0443\u043A (\u043F\u043E\u0442\u0440\u0456\u0431\u0435\u043D \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A) -checkbox.window.to.front = \u041F\u0435\u0440\u0435\u043D\u0435\u0441\u0442\u0438 \u0432\u0456\u043A\u043D\u043E -checkbox.broadcast.hide.offline.user = \u0421\u0445\u043E\u0432\u0430\u0442\u0438 \u0432\u0456\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0445 -checkbox.use.krbconf = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438 krb5.conf \u0430\u0431\u043E krb5.ini -checkbox.use.krb.dns = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u043B\u0443\u0436\u0431\u0443 \u0434\u043E\u043C\u0435\u043D\u043D\u0438\u0445 \u0456\u043C\u0435\u043D -checkbox.use.specify.below = \u0412\u043A\u0430\u0437\u0430\u0442\u0438 \u043D\u0438\u0436\u0447\u0435 -checkbox.use.pki.authentication = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u0442\u0438 PKI \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044E -checkbox.transport.tab.setting = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u043C\u043E\u0436\u043B\u0438\u0432\u0456 \u0442\u0440\u0430\u043D\u0441\u043F\u043E\u0440\u0442\u0438 (\u043F\u043E\u0442\u0440\u0456\u0431\u0435\u043D \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A) -checkbox.conference.tab.setting = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u044E (\u043F\u043E\u0442\u0440\u0456\u0431\u0435\u043D \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A) -checkbox.use.hostname.as.resource = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438 \u043D\u0430\u0437\u0432\u0443 \u043A\u043E\u043C\u043F\u0430 \u044F\u043A \u0434\u0436\u0435\u0440\u0435\u043B\u043E -checkbox.use.version.as.resource = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438 \u0432\u0435\u0440\u0432\u0441\u0456\u044E \u0421\u043F\u0430\u0440\u043A\u0430 \u044F\u043A \u0434\u0436\u0435\u0440\u0435\u043B\u043E - -delete.log.permanently = \u041F\u043E\u0441\u0442\u0456\u0439\u043D\u043E \u0432\u0438\u043B\u0443\u0447\u0430\u0442\u0438 \u0436\u0443\u0440\u043D\u0430\u043B -delete.permanently = \u0412\u0438\u043B\u0443\u0447\u0430\u0442\u0438 \u043F\u043E\u0441\u0442\u0456\u0439\u043D\u043E? - -gateway.username.password.error = \u041F\u043E\u0442\u0440\u0456\u0431\u043D\u043E \u0432\u0432\u0435\u0441\u0442\u0438 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0435 \u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0456 \u043F\u0430\u0440\u043E\u043B\u044C - -group.chat.window.information = \u0406\u043D\u0444\u043E -group.comma.delimited = \u0412\u0456\u0434\u0434\u0456\u043B\u0435\u043D\u043D\u044F \u043A\u043E\u043C\u0430\u043C\u0438 -group.conferences.found = \u0417\u043D\u0430\u0439\u0434\u0435\u043D\u043E \u0441\u043B\u0443\u0436\u0431\u0443 \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0439 -group.connection = \u0417'\u0454\u0434\u043D\u0430\u043D\u043D\u044F -group.empty = \u041D\u0435\u043C\u0430 \u043D\u0430 \u0437\u0432'\u044F\u0437\u043A\u0443 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432 \u0437 \u0433\u0440\u0443\u043F\u0438 -group.general.information = \u0417\u0430\u0433\u0430\u043B\u044C\u043D\u0435 \u0456\u043D\u0444\u043E -group.login.information = \u0406\u043D\u0444\u043E \u043F\u0440\u043E \u043B\u043E\u0433\u0456\u043D -group.notification.options = \u0412\u0430\u0440\u0456\u044F\u043D\u0442\u0438 \u043E\u043F\u043E\u0432\u0456\u0449\u0435\u043D\u044C -group.offline = \u041E\u0444\u0444\u043B\u0430\u0439\u043D\u043E\u0432\u0430 \u0433\u0440\u0443\u043F\u0430 -group.search.form = \u041F\u043E\u0448\u0443\u043A\u043E\u0432\u0430 \u0444\u043E\u0440\u043C\u0430 -group.search.results = \u0420\u0435\u0437\u0443\u043B\u044C\u0442\u0438 \u043F\u043E\u0448\u0443\u043A\u0443 -group.chat.name.notification = \u0412\u0456\u0434\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u0442\u0432\u043E\u0433\u043E \u0456\u043C\u0435\u043D\u0456... -group.chat.name.match = \u0406\u043C'\u044F \u0432 \u0433\u0440\u0443\u043F\u0456: - -label.na = \u043D\u0435 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0438\u0439 -label.cell = \u0421\u043E\u0442\u0430 -label.work = \u041F\u0440\u0430\u0446\u044F -label.home = \u0414\u0456\u043C -label.accounts = \u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0456 \u0437\u0430\u043F\u0438\u0441\u0438 -label.passwordreset = \u0417\u043C\u0456\u043D\u0438\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C -label.add.conference.service = \u0414\u043E\u0434\u0430\u0442\u0438 \u0441\u043B\u0443\u0436\u0431\u0443 \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0439 -label.add.jid = \u0414\u043E\u0434\u0430\u0442\u0438 \u0434\u0436\u0430\u0431\u0435\u0440 \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 -label.add.task = \u0414\u043E\u0434\u0430\u0442\u0438 \u0437\u0430\u0432\u0434\u0430\u043D\u043D\u044F -label.auto.login = \u0410\u0432\u0442\u043E\u043B\u043E\u0433\u0456\u043D -label.available.users.in.roster = \u0421\u043F\u0438\u0441\u043E\u043A \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0438\u0445 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432 -label.avatar = \u0417\u043D\u0430\u0447\u043E\u043A -label.cancel = \u0412\u0456\u0434\u0445\u0438\u043B\u0438\u0442\u0438 -label.change.password.to = \u0417\u043C\u0456\u043D\u0438\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C \u043D\u0430 -label.chatroom.fontsize = \u0420\u043E\u0437\u043C\u0456\u0440 \u0448\u0440\u0438\u0444\u0442\u0430 \u0432 \u0433\u0440\u0443\u043F\u0456 -label.city = \u041C\u0456\u0441\u0442\u043E -label.close = \u0417\u0430\u043A\u0440\u0438\u0442\u0438 -label.company = \u041A\u043E\u043C\u043F\u0430\u043D\u0456\u044F -label.confirm.password = &\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C -label.conflict.error = \u0423\u0436\u0435 \u0454 \u0442\u0430\u043A\u0438\u0439 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 -label.contact.to.find = \u0417\u043D\u0430\u0439\u0442\u0438 \u043A\u043E\u043D\u0442\u0430\u043A\u0442 -label.recent.conversation = \u041E\u0441\u0442\u0430\u043D\u043D\u0456 \u0431\u0435\u0441\u0456\u0434\u0438 -label.frequent.contacts = \u0427\u0430\u0441\u0442\u0456 \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u0438 -label.contactlist.avatarsize = \u0420\u043E\u0437\u043C\u0456\u0440 \u0437\u043D\u0430\u0447\u043A\u0456\u0432: -label.contactlist.fontsize = \u0420\u043E\u0437\u043C\u0456\u0440 \u0448\u0440\u0438\u0444\u0442\u0430 \u0441\u043F\u0438\u0441\u043A\u0443 \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u0456\u0432: -label.country = \u041A\u0440\u0430\u0457\u043D\u0430 -label.create.account = \u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 -label.department = \u0412\u0456\u0434\u0434\u0456\u043B -label.dial = \u0422\u0435\u043B\u0435\u0444\u043E\u043D\u0443\u0432\u0430\u0442\u0438 -label.display.time = \u0412\u0456\u0434\u043E\u0431\u0440\u0430\u0437\u0438\u0442\u0438 \u0447\u0430\u0441: -label.downloads = \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 -label.due = \u0417\u0433\u0456\u0434\u043D\u043E -label.email.address = E-\u0430\u0434\u0440\u0435\u0441\u0430 -label.emoticons = &\u0415\u043C\u043E\u0446\u0456\u0457 -label.enter.address = \u0412\u0432\u0435\u0441\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443 -label.enter.group.name = \u0412\u0432\u0435\u0441\u0442\u0438 \u043D\u0430\u0437\u0432\u0443 \u0433\u0440\u0443\u043F\u0438 -label.fax = \u0424\u0430\u043A\u0441 -label.find = \u0417\u043D\u0430\u0439\u0442\u0438 -label.first.name = \u0406\u043C'\u044F -label.group = \u0413\u0440\u0443\u043F -label.host = \u0425\u043E\u0441\u0442 -label.invited.users = \u0417\u0430\u043F\u0440\u043E\u0448\u0435\u043D\u0456 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456 -label.jabber.address = \u0414\u0436\u0430\u0431\u0435\u0440-\u0430\u0434\u0440\u0435\u0441\u0430 -label.jabber.id = \u0414\u0436\u0430\u0431\u0435\u0440 \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 -label.jid = \u0414\u0416\u0456\u0434 -label.job.title = \u041F\u043E\u0441\u0430\u0434\u0430 -label.last.name = \u041F\u0440\u0456\u0437\u0432\u0438\u0449\u0435 -label.local.time = \u041C\u0456\u0441\u0446\u0435\u0432\u0438\u0439 \u0447\u0430\u0441 -label.message = \u041F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F -label.message.style = \u0421\u0442\u0438\u043B\u044C \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F -label.middle.name = \u041F\u043E \u0431\u0430\u0442\u044C\u043A\u043E\u0432\u0456 -label.minutes.before.stale.chat = &\u0427\u0430\u0441 \u0430\u043A\u0442\u0443\u0430\u043B\u044C\u043D\u043E\u0441\u0442\u0456 \u0431\u0435\u0441\u0456\u0434\u0438 -label.mobile = \u041C\u043E\u0431\u0456\u043B\u044C\u043D\u0438\u0439 -label.name = \u0406\u043C'\u044F -label.network = \u041C\u0435\u0440\u0435\u0436\u0430 -label.new.nickname = \u041D\u043E\u0432\u0435 \u043F\u0440\u0456\u0437\u0432\u0438\u0441\u044C\u043A\u043E -label.nickname = \u041F\u0440\u0456\u0437\u0432\u0441\u044C\u043A\u043E -label.number = \u041D\u043E\u043C\u0435\u0440 -label.ok = \u0413\u0430\u0440\u0430\u0437\u0434 -label.old.ssl = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0442\u0438 \u0441\u0442\u0430\u0440\u0438\u0439 SSL \u043C\u0435\u0442\u043E\u0434 -label.os = \u041E\u043F\u0435\u0440\u0430\u0446\u0456\u0439\u043D\u0430 \u0441\u0438\u0441\u0442\u0435\u043C\u0430 -label.pager = \u0414\u043E\u0434\u0430\u0442\u043A\u043E\u0432\u0456 \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u0438 -label.password = &\u043F\u0430\u0440\u043E\u043B\u044C -label.phone = \u0422\u0435\u043B\u0435\u0444\u043E\u043D -label.port = \u041F\u043E\u0440\u0442 -label.postal.code = \u041F\u043E\u0448\u0442\u043E\u0432\u0438\u0439 \u0456\u043D\u0434\u0435\u043A\u0441 -label.presence = \u041F\u0440\u0438\u0441\u0443\u0442\u043D\u0456\u0441\u0442\u044C -label.priority = \u041F\u0440\u0456\u043E\u0440\u0438\u0442\u0435\u0442 -label.protocol = \u041F\u0440\u043E\u0442\u043E\u043A\u043E\u043B -label.received = \u041E\u0442\u0440\u0438\u043C\u0430\u043D\u043E -label.rename.to = \u041F\u0435\u0440\u0435\u0439\u043C\u0435\u043D\u0443\u0432\u0430\u0442\u0438 \u043D\u0430 -label.resource = \u0414\u0416\u0435\u0440\u0435\u043B\u043E -label.response.timeout = &\u0417\u0430\u0442\u0440\u0438\u043C\u043A\u0430 \u0443 \u0441\u0435\u043A\u0443\u043D\u0434\u0430\u0445 -label.room = \u041A\u0456\u043C\u043D\u0430\u0442\u0430 -label.room.name = \u041D\u0430\u0437\u0432\u0430 \u0433\u0440\u0443\u043F\u0438 -label.room.topic = \u0422\u0435\u043C\u0430 \u0433\u0440\u0443\u043F\u0438 -label.search = \u041F\u043E\u0448\u0443\u043A -label.search.service = \u041F\u043E\u0448\u0443\u043A\u043E\u0432\u0430 \u0441\u043B\u0443\u0436\u0431\u0430 -label.seconds = \u0421\u0435\u043A\u0443\u043D\u0434\u0438 -label.server = &\u0421\u0435\u0440\u0432\u0435\u0440 -label.server.address = \u0410\u0434\u0440\u0435\u0441\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 -label.show = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438: -label.software = \u041F\u0440\u043E\u0433\u0440\u0430\u043C\u0430 -label.state.and.province = \u0414\u0435\u0440\u0436\u0430\u0432\u0430/\u043E\u0431\u043B\u0430\u0441\u0442\u044C -label.street.address = \u0412\u0443\u043B\u0438\u0446\u044F -label.time = \u0427\u0430\u0441: {0} -label.time.till.idle = &\u0427\u0430\u0441 \u0434\u043E \u0441\u0442\u0430\u043D\u0443 \u043D\u0435\u0430\u043A\u0442\u0438\u0432\u043D\u043E\u0441\u0442\u0456 (\u0445\u0432) -label.time.till.idlemessage = \u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u043D\u0435 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F \u043F\u0440\u043E \u043D\u0435\u0430\u043A\u0442\u0438\u0432\u043D\u0456\u0441\u0442\u044C -label.timeformat = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438 \u0444\u043E\u0440\u043C\u0430\u0442 \u0447\u0430\u0441\u0443 {0} -label.transfer.download.directory = &\u0422\u0435\u043A\u0430 \u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u044C: -label.transfer.timeout = &\u0417\u0430\u0442\u0440\u0438\u043C\u043A\u0430 \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0456 (\u0445\u0432): -label.unable.to.add.contact = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u043F\u0435\u0440\u0435\u0434\u0430\u0442\u0438 \u043A\u043E\u043D\u0442\u0430\u043A\u0442 -label.use.default = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u0442\u0430\u043D\u0434\u0430\u0440\u0442 -label.user.on.public.network = \u041A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456 \u0443 \u043F\u0443\u0431\u043B\u0456\u0447\u043D\u0456\u0439 \u043C\u0435\u0440\u0435\u0436\u0456 -label.username = &\u0406\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 -label.version = \u0412\u0435\u0440\u0441\u0456\u044F -label.web.page = \u0421\u0442\u043E\u0440\u0456\u043D\u043A\u0430 -label.xmpp.port = &XMPP \u043F\u043E\u0440\u0442 -label.krb.realm = \u0426\u0430\u0440\u0438\u043D\u0430 -label.krb.kdc = KDC -label.which.pki.method = \u042F\u043A\u0438\u0439 PKI \u043C\u0435\u0442\u043E\u0434? -label.choose.file = \u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0444\u0430\u0439\u043B -label.trust.store.password = \u0414\u043E\u0437\u0432\u043E\u043B\u044F\u0442\u0438 \u0437\u0431\u0435\u0440\u0456\u0433\u0430\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C -label.enter.password = \u0412\u0435\u0434\u0438 \u043F\u0430\u0440\u043E\u043B\u044C -label.move.focus.forwards = \u0417\u043C\u0456\u0441\u0442\u0438\u0442\u0438 \u0444\u043E\u043A\u0443\u0441 \u0443\u043F\u0435\u0440\u0435\u0434 -label.move.focus.backwards = \u0417\u043C\u0456\u0441\u0442\u0438\u0442\u0438 \u0444\u043E\u043A\u0443\u0441 \u043D\u0430\u0437\u0430\u0434 -label.keystore.location = \u041C\u0456\u0441\u0446\u0435 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043D\u043D\u044F \u043A\u043B\u044E\u0447\u0456\u0432 -label.truststore.location = \u041C\u0456\u0441\u0446\u0435 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043D\u043D\u044F \u0434\u043E\u0432\u0456\u0440\u0435\u043D\u0438\u0445 \u0432\u0456\u0434\u043E\u043C\u043E\u0441\u0442\u0435\u0439 -label.pkcs.library.file = PKCS#11 \u0442\u0435\u043A\u0430 -label.x509.certificate = X.509 \u043F\u043E\u0441\u0432\u0456\u0434\u0447\u0435\u043D\u043D\u044F -label.apple.keychain = \u041B\u0430\u043D\u0446\u044E\u0436\u043E\u043A \u043A\u043B\u044E\u0447\u0456\u0432 \u0415\u043F\u043B -label.add.to.roster = \u0414\u043E\u0434\u0430\u0442\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432 \u0441\u043F\u0438\u0441\u043E\u043A -label.audio.device = &\u0413\u043E\u043B\u043E\u0441\u043E\u0432\u0438\u0439 \u043F\u0440\u0438\u0441\u0442\u0440\u0456\u0439 -label.video.device = &\u0412\u0456\u0434\u0435\u043E \u043F\u0440\u0438\u0441\u0442\u0440\u0456\u0439 - -menuitem.about = \u041F\u0440\u043E \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u0438 -menuitem.actions = \u0414\u0456\u0457 -menuitem.bookmarks = \u0417\u0430\u043A\u043B\u0430\u0434\u043A\u0438 -menuitem.add = \u0414\u043E\u0434\u0430\u0442\u0438 -menuitem.add.as.contact = \u0414\u043E\u0434\u0430\u0442\u0438 \u043A\u043E\u043D\u0442\u0430\u043A\u0442 \u044F\u043A -menuitem.add.contact = \u0414\u043E\u0434\u0430\u0442\u0438 \u043A\u043E\u043D\u0442\u0430\u043A\u0442 -menuitem.add.contact.group = \u0414\u043E\u0434\u0430\u0442\u0438 \u0433\u0440\u0443\u043F\u0443 -menuitem.add.groupchat.myname = \u041F\u0456\u0434\u0441\u0432\u0456\u0442\u0438\u0442\u0438 \u043C\u043E\u0454 \u0456\u043C'\u044F, \u044F\u043A\u0449\u043E \u0445\u0442\u043E\u0441\u044C \u043D\u0430\u0437\u0438\u0432\u0430\u0454 \u0439\u043E\u0433\u043E -menuitem.add.groupchat.mytext = \u041F\u0456\u0434\u0441\u0432\u0456\u0442\u0438\u0442\u0438 \u043C\u0456\u0439 \u0442\u0435\u043A\u0441\u0442, \u044F\u043A\u0449\u043E \u044F \u043F\u0438\u0448\u0443 \u0449\u043E\u0441\u044C -menuitem.add.groupchat.popname = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u0441\u043F\u043B\u0438\u0432\u0430\u044E\u0447\u0435 \u0432\u0456\u043A\u043D\u043E, \u044F\u043A\u0449\u043E \u0445\u0442\u043E\u0441\u044C \u043D\u0430\u0437\u0438\u0432\u0430\u0454 \u043C\u043E\u0454 \u0456\u043C'\u044F -menuitem.add.groupchat.showjoinleavemessage = &\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F \u043F\u0440\u043E \u043F\u0440\u0438\u0454\u0434\u043D\u0430\u043D\u043D\u044F -menuitem.add.groupchat.showrolesinsteadofstatus = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u0440\u043E\u043B\u044C\u043E\u0432\u0456 \u0437\u043D\u0430\u0447\u043A\u0438 -menuitem.add.groupchat.auto.accept.invite = &\u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u043D\u043E \u043F\u0440\u0438\u0439\u043C\u0430\u0442\u0438 \u0437\u0430\u043F\u0440\u043E\u0448\u0435\u043D\u043D\u044F \u0432 \u0433\u0440\u0443\u043F\u0438 -menuitem.add.groupchat.random.colors = \u0412\u0438\u043F\u0430\u0434\u043A\u043E\u0432\u0456 \u0431\u0430\u0440\u0432\u0438 \u0434\u043B\u044F \u0456\u043C\u0435\u043D -menuitem.always.on.top = \u0417\u0430\u0432\u0448\u0435 \u0432\u0433\u043E\u0440\u0456 -menuitem.alert.when.online = \u041F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u044F\u0442\u0438, \u043A\u043E\u043B\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447 \u0441\u0442\u0430\u043D\u0435 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0438\u0439 -menuitem.ban = \u0412 \u0431\u0430\u043D\u044E -menuitem.ban.user = \u041A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447 \u0432 \u0431\u0430\u043D\u0456 -menuitem.block.user = \u0411\u043B\u043E\u043A\u0443\u0432\u0430\u0442\u0438 -menuitem.broadcast.to.group = \u0422\u0440\u0430\u043D\u0441\u043B\u044E\u0432\u0430\u0442\u0438 \u0432 \u0433\u0440\u0443\u043F\u0443 -menuitem.browse.service = \u0421\u043B\u0443\u0436\u0431\u0430 \u0432\u0438\u0431\u043E\u0440\u0443 -menuitem.change.nickname = \u0417\u043C\u0456\u043D\u0438\u0442\u0438 \u043F\u0440\u0456\u0437\u0432\u0438\u0441\u044C\u043A\u043E -menuitem.change.subject = \u0417\u043C\u0456\u043D\u0438\u0442\u0438 \u0442\u0435\u043C\u0443 -menuitem.chat = \u0411\u0430\u043B\u0430\u0447\u043A\u0438 -menuitem.check.for.updates = \u041F\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 &\u043E\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F -menuitem.connect = \u0424\u0430\u0439\u043B -menuitem.contacts = \u041A\u043D\u0442\u0430\u043A\u0442\u0438 -menuitem.copy.to = \u0421\u043A\u043E\u043F\u0456\u044E\u0432\u0430\u0442\u0438 -menuitem.delete = \u0412\u0438\u043B\u0443\u0447\u0438\u0442\u0438 -menuitem.delete.login.information = \u0412\u0438\u043B\u0443\u0447\u0438\u0442\u0438 \u0440\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u0439\u043D\u0443 \u0456\u043D\u0444\u0443 -menuitem.destroy.room = \u0412\u0438\u043B\u0443\u0447\u0438\u0442\u0438 \u0433\u0440\u0443\u043F\u0443 -menuitem.dial = \u0422\u0435\u043B\u0435\u0444\u043E\u043D\u0443\u0432\u0430\u0442\u0438 -menuitem.edit = \u0420\u0435\u0434\u0430\u043A\u0442\u0443\u0432\u0430\u0442\u0438 -menuitem.edit.my.profile = \u0420\u0435\u0434\u0430\u043A\u0442\u0443\u0432\u0430\u0442\u0438 \u043F\u0440\u043E\u0444\u0430\u0439\u043B -menuitem.edit.status.message = \u0420\u0435\u0434\u0430\u043A\u0442\u0443\u0432\u0430\u0442\u0438 \u0441\u0442\u0430\u0442\u0443\u0441 -menuitem.enter.login.information = \u0412\u0432\u0435\u0441\u0442\u0438 \u0440\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u0439\u043D\u0443 \u0456\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0456\u044E -menuitem.exit = \u0412\u0438\u0439\u0442\u0438 -menuitem.affiliation = \u041F\u0440\u0438\u0454\u0434\u043D\u0430\u043D\u043D\u044F -menuitem.grant.moderator = \u041D\u0430\u0434\u0430\u0442\u0438 \u043F\u0440\u0430\u0432\u0430 \u043C\u043E\u0434\u0435\u0440\u0430\u0442\u043E\u0440\u0430 -menuitem.grant.member = \u041D\u0430\u0434\u0430\u0442\u0438 \u043F\u0440\u0430\u0432\u0430 \u0443\u0447\u0430\u0441\u043D\u0438\u043A\u0430 -menuitem.grant.admin = \u041D\u0430\u0434\u0430\u0442\u0438 \u043F\u0440\u0430\u0432\u0430 \u0430\u0434\u043C\u0456\u043D\u0430 -menuitem.grant.owner = \u041D\u0430\u0434\u0430\u0442\u0438 \u043F\u0440\u0430\u0432\u0430 \u0432\u043B\u0430\u0441\u043D\u0438\u043A\u0430 -menuitem.grant.voice = \u041D\u0430\u0434\u0430\u0442\u0438 \u043F\u0440\u0430\u0432\u0430 \u0433\u043E\u043B\u043E\u0441\u0443 -menuitem.help = \u041F\u043E\u043C\u0456\u0447 -menuitem.hide = \u0421\u0445\u043E\u0432\u0430\u0442\u0438 -menuitem.invite.group.to.conference = \u0417\u0430\u043F\u0440\u043E\u0441\u0438\u0442\u0438 \u0433\u0440\u0443\u043F\u0443 \u0434\u043E \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0457 -menuitem.invite.users = \u0417\u0430\u043F\u0440\u043E\u0441\u0438\u0442\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432 -menuitem.join.on.startup = \u041F\u0440\u0438\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C \u0434\u043E \u0441\u0442\u0430\u0440\u0442\u0430\u043F\u0443 -menuitem.join.room = \u041F\u0440\u0438\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C \u0434\u043E \u0432\u0438\u0431\u0440\u0430\u043D\u043E\u0457 \u0433\u0440\u0443\u043F\u0438 -menuitem.kick.user = \u0428\u0442\u0443\u0440\u0445\u043D\u0443\u0442\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 -menuitem.languages = \u041C\u043E\u0432\u0438 -menuitem.logout.no.status = \u0412\u0438\u0439\u0442\u0438 -menuitem.logout.with.status = \u0412\u0438\u0439\u0442\u0438 \u0447\u0435\u0440\u0435\u0437 -menuitem.lookup.profile = \u0428\u0443\u043A\u0430\u0442\u0438 \u043F\u0440\u043E\u0444\u0430\u0439\u043B -menuitem.move.to = \u041F\u0435\u0440\u0435\u043C\u0456\u0441\u0442\u0438\u0442\u0438 \u0434\u043E -menuitem.online.help = \u0424\u043E\u0440\u0443\u043C\u0438 -menuitem.open = \u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 -menuitem.open.with = \u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u0437 -menuitem.plugins = \u0412\u0441\u0438\u0430\u0432\u043A\u0438 -menuitem.preferences = \u0412\u043F\u043E\u0434\u043E\u0431\u0430\u043D\u043D\u044F -menuitem.remove = \u0412\u0438\u043B\u0443\u0447\u0438\u0442\u0438 -menuitem.remove.alert.when.online = \u041F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F \u043F\u0440\u043E \u0432\u0438\u043B\u0443\u0447\u0435\u043D\u043D\u044F -menuitem.remove.bookmark = \u0412\u0438\u043B\u0443\u0447\u0438\u0442\u0438 \u0437\u0430\u043A\u043B\u0430\u0434\u043A\u0443 -menuitem.remove.from.group = \u0412\u0438\u043B\u0443\u0447\u0438\u0442\u0438 \u0437 \u0433\u0440\u0443\u043F\u0438 -menuitem.remove.from.roster = \u0412\u0438\u043B\u0443\u0447\u0438\u0442\u0438 \u0437\u0456 \u0441\u043F\u0438\u0441\u043A\u0443 -menuitem.block.contact = \u0411\u043B\u043E\u043A\u0443\u0432\u0430\u0442\u0438 \u043A\u043E\u043D\u0442\u0430\u043A\u0442 -menuitem.unblock.contact = \u0420\u043E\u0437\u0431\u043B\u043E\u043A\u0443\u0432\u0430\u0442\u0438 \u043A\u043E\u043D\u0442\u0430\u043A\u0442 -menuitem.remove.service = \u0412\u0438\u043B\u0443\u0447\u0438\u0442\u0438 \u0441\u043B\u0443\u0436\u0431\u0443 -menuitem.rename = \u041F\u0435\u0440\u0435\u0439\u043C\u0435\u043D\u0443\u0432\u0430\u0442\u0438 -menuitem.revoke.moderator = \u0412\u0456\u0434\u043A\u043B\u0438\u043A\u0430\u0442\u0438 \u043C\u043E\u0434\u0435\u0440\u0430\u0442\u043E\u0440\u0430 -menuitem.revoke.voice = \u0412\u0456\u0434\u043A\u043B\u0438\u043A\u0430\u0442\u0438 \u0433\u043E\u043B\u043E\u0441 -menuitem.revoke.member = \u0412\u0456\u0434\u043A\u043B\u0438\u043A\u0430\u0442\u0438 \u0443\u0447\u0430\u0441\u043D\u0438\u043A\u0430 -menuitem.revoke.admin = \u0412\u0456\u0434\u043A\u043B\u0438\u043A\u0430\u0442\u0438 \u0430\u0434\u043C\u0456\u043D\u0430 -menuitem.revoke.owner = \u0412\u0456\u0434\u043A\u043B\u0438\u043A\u0430\u0442\u0438 \u0432\u043B\u0430\u0441\u043D\u0438\u043A\u0430 -menuitem.save = \u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 -menuitem.save.as = \u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u044F\u043A... -menuitem.send.a.file = \u041D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438 \u0444\u0430\u0439\u043B -menuitem.send.a.message = \u0422\u0440\u0430\u043D\u0441\u043B\u044E\u0432\u0430\u0442\u0438 \u043E\u0431\u0440\u0430\u043D\u0438\u043C \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430\u043C... -menuitem.set.status.message = \u0412\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0438 \u0441\u0442\u0430\u0442\u0443\u0441 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F... -menuitem.show.empty.groups = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u043F\u0443\u0441\u0442\u0456 \u0433\u0440\u0443\u043F\u0438 -menuitem.show.offline.group = \u0417\u0433\u0440\u0443\u043F\u0443\u0432\u0430\u0442\u0438 \u043D\u0435\u043F\u0456\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0445 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432 -menuitem.show.traffic = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u0432\u0456\u043A\u043D\u043E \u0442\u0440\u0430\u0444\u0456\u043A\u0443 -menuitem.sign.in = \u0417\u0430\u0440\u0435\u0454\u0441\u0442\u0440\u0443\u0432\u0430\u0442\u0438\u0441\u044C -menuitem.sign.in.at.login = \u0417\u0430\u0440\u0435\u0454\u0441\u0442\u0440\u0443\u0432\u0430\u0442\u0438\u0441\u044C \u043F\u0440\u0438 -menuitem.sign.out = \u0412\u0456\u0434\u043A\u043B\u044E\u0447\u0438\u0442\u0438\u0441\u044C -menuitem.start.a.chat = \u041F\u043E\u0447\u0430\u0442\u0438 \u0431\u0435\u0441\u0456\u0434\u0443 -menuitem.start.a.conference = \u041F\u043E\u0447\u0430\u0442\u0438 \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u044E -menuitem.status = \u0421\u0442\u0430\u0442\u0443\u0441 -menuitem.subscribe.to = \u041F\u0456\u0434\u043F\u0438\u0441\u0430\u0442\u0438\u0441\u044C \u043D\u0430 -menuitem.unban = \u0420\u043E\u0437\u0431\u0430\u043D\u0438\u0442\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0443 \u0441\u043F\u0438\u0441\u043A\u0443 -menuitem.unblock.user = \u0420\u043E\u0437\u0431\u043B\u043E\u043A\u0443\u0432\u0430\u0442\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432 \u0441\u043F\u0438\u0441\u043A\u0443 -menuitem.user.guide = \u041A\u0435\u0440\u0456\u0432\u043D\u0438\u0446\u0442\u0432\u043E \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 -menuitem.view.client.version = \u0412\u0435\u0440\u0441\u0456\u044F \u043A\u043B\u0456\u0454\u043D\u0442\u0430 -menuitem.view.contact.history = \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0438\u0442\u0438 \u0456\u0441\u0442\u043E\u0440\u0456\u044E \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u0456\u0432 -menuitem.view.downloads = \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F -menuitem.view.last.activity = \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u043E\u0441\u0442\u0430\u043D\u043D\u044E \u0430\u043A\u0442\u0438\u0432\u043D\u0456\u0441\u0442\u044C -menuitem.view.logs = \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0436\u0443\u0440\u043D\u0430\u043B -menuitem.view.profile = \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0436\u0443\u0440\u043D\u0430\u043B -menuitem.view.room.info = \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0456\u043D\u0444\u043E \u0433\u0440\u0443\u043F\u0438 -menuitem.voice = \u0413\u043E\u043B\u043E\u0441 -menuitem.show.offline.users = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u043D\u0435\u0430\u043A\u0442\u0438\u0432\u043D\u0438\u0445 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432 -menuitem.show.contact.statusmessage = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u0441\u0442\u0430\u0442\u0443\u0441 -menuitem.bookmark.room = \u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0437\u0430\u043A\u043B\u0430\u0434\u043A\u0443 -menuitem.refresh = \u041E\u043D\u043E\u0432\u0438\u0442\u0438 -menuitem.create.room = \u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0430\u0431\u043E \u043F\u0440\u0438\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C \u0434\u043E \u0433\u0440\u0443\u043F\u0438 -menuitem.expand.all.groups = \u0420\u043E\u0437\u0433\u043E\u0440\u043D\u0443\u0442\u0438 \u0432\u0441\u0456 \u0433\u0440\u0443\u043F\u0438 -menuitem.collapse.all.groups = \u0417\u0433\u043E\u0440\u043D\u0443\u0442\u0438 \u0432\u0441\u0456 \u0433\u0440\u0443\u043F\u0438 -menuitem.inivite.again = \u0417\u0430\u043F\u0440\u043E\u0441\u0438\u0442\u0438 \u0437\u043D\u043E\u0432 -menuitem.chatframe.option = \u041C\u043E\u0436\u043B\u0438\u0432\u043E\u0441\u0442\u0456 -menuitem.add.groupchat.invitetobookmark = \u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u043D\u043E \u0437\u0430\u043F\u0440\u043E\u0448\u0443\u0432\u0430\u0442\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432 \u0434\u043E \u0437\u0430\u043A\u043B\u0430\u0434\u0435\u043D\u043E\u0457 \u0433\u0440\u0443\u043F\u0438. - -message.invite.to.groupchat = {0} \u0437\u0430\u043F\u0440\u043E\u0448\u0443\u0454 \u0442\u0435\u0431\u0435 \u0434\u043E \u0433\u0440\u0443\u043F\u0438 -message = \u041F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F -message.account.create = \u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043D\u043E\u0432\u0438\u0439 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 -message.account.created = \u0417\u0430\u043F\u0438\u0441 \u0441\u0442\u0432\u043E\u0440\u0435\u043D\u043E -message.account.error = \u0412\u043A\u0430\u0437\u0430\u0442\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u0435 \u0441\u0442\u0432\u043E\u0440\u0438\u0442\u0438 -message.add.a.contact = \u0414\u043E\u0434\u0430\u0442\u0438 \u043A\u043E\u043D\u0442\u0430\u043A\u0442 -message.add.conference.service = \u0414\u043E\u0434\u0430\u0442\u0438 \u0441\u043B\u0443\u0436\u0431\u0443 \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0439 -message.add.contact.to.list = \u0414\u043E\u0434\u0430\u0442\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0434\u043E \u0441\u043F\u0438\u0441\u043A\u0443 \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u0456\u0432 -message.add.favorite.room = \u0414\u043E\u0434\u0430\u0442\u0438 \u0433\u0440\u0443\u043F\u0443 \u0434\u043E \u0443\u043B\u044E\u0431\u043B\u0435\u043D\u0438\u0445 -message.add.this.user.to.your.roster = \u0414\u043E\u0434\u0430\u0442\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432 \u0434\u0440\u0443\u0437\u0456 -message.add.to.roster = \u0414\u043E\u0434\u0430\u0442\u0438 \u0441\u043F\u0438\u0441\u043E\u043A -message.add.user = \u0414\u043E\u0434\u0430\u0442\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432 \u0441\u043F\u0438\u0441\u043E\u043A? -message.alert.notify = \u041E\u043F\u043E\u0432\u0456\u0449\u0435\u043D\u043D\u044F -message.already.exists = \u0421\u043F\u0440\u043E\u0431\u0443\u0439 \u0456\u043D\u0430\u043A\u0448\u0435 \u0456\u043C'\u044F -message.approve.subscription = \u0414\u043E\u0437\u0432\u043E\u043B\u0438\u0442\u0438 {0} \u0434\u043E\u0434\u0430\u0442\u0438 \u0442\u0435\u0431\u0435 \u0432 \u0441\u043F\u0438\u0441\u043E\u043A? -message.autenticating = \u0410\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F -message.away.idle = \u0412\u0456\u0434\u0441\u0443\u0442\u043D\u0456\u0439 \u0447\u0435\u0440\u0435\u0437 \u043F\u0440\u043E\u0441\u0442\u0456\u0439 -message.bookmark.temporary.room.error = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437\u0430\u043A\u043B\u0430\u0441\u0442\u0438 \u0442\u0438\u043C\u0447\u0430\u0441\u043E\u0432\u0456 \u0433\u0440\u0443\u043F\u0438 -message.broadcast.from = \u0422\u0440\u0430\u043D\u0441\u043B\u044E\u0432\u0430\u0442\u0438 \u0432\u0456\u0434 {0} -message.broadcast.no.user.selected = \u0412\u0438\u0431\u0435\u0440\u0438 \u0445\u043E\u0447 \u043E\u0434\u043D\u043E\u0433\u043E \u043E\u0442\u0440\u0438\u043C\u0443\u0432\u0430\u0447\u0430 -message.broadcast.no.text = \u041D\u0430\u043F\u0438\u0448\u0438 \u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u0442\u0440\u0430\u043D\u0441\u043B\u044E\u0432\u0430\u043D\u043D\u044F -message.broadcast.message.sent = \u041F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F \u043D\u0430\u0434\u0456\u0441\u043B\u0430\u043D\u043E -message.broadcast.to = \u0412\u0432\u0435\u0434\u0438 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F \u0434\u043E {0} -message.broadcasted.to = \u041F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F \u0442\u0440\u0430\u043D\u0441\u043B\u044C\u043E\u0432\u0430\u043D\u043E \u0434\u043E users\:\n{0} -message.buzz.alert.notification = \u0417\u0432\u0435\u0440\u043D\u0443\u0442\u0438 \u0443\u0432\u0430\u0433\u0443 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 -message.buzz.message = {0} \u043F\u0440\u0433\u043D\u0435 \u0442\u0432\u043E\u0454\u0457 \u0443\u0432\u0430\u0433\u0438 -message.buzz.sent = \u0417\u0430\u043F\u0440\u043E\u0441\u0438\u0442\u0438 \u0443\u0432\u0430\u0433\u0438 -message.calling = \u0422\u0435\u043B\u0435\u0444\u043E\u043D\u0443\u0454 {0} -message.came.online = {0} \u043D\u0430 \u0437\u0432'\u044F\u0437\u043A\u0443 \u0437 {1} -message.cannot.add.contact.to.shared.group = \u0422\u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0448 \u0434\u043E\u0434\u0430\u0442\u0438 \u043A\u043E\u043D\u0442\u0430\u043A\u0442 \u0432 \u0433\u0440\u0443\u043F\u0443 -message.chat.session.ended = \u0421\u0435\u0441\u0456\u044F \u0437\u0430\u043A\u0456\u043D\u0447\u0435\u043D\u0430 {0} -message.click.to.open = \u041D\u0430\u0442\u0438\u0441\u043D\u0438, \u0449\u043E\u0431 \u0432\u0456\u0434\u043A\u0440\u0438\u0442\u0438 -message.client.information = \u0406\u043D\u0444\u043E \u0434\u043B\u044F {0} -message.close.other.chats = \u0417\u0430\u043A\u0440\u0438\u0442\u0438 \u0432\u0441\u0456 \u0431\u0435\u0441\u0456\u0434\u0438 -message.close.stale.chats = \u0417\u0430\u043A\u0440\u0438\u0442\u0438 \u0432\u0441\u0456 \u0437\u0430\u0441\u0442\u0430\u0440\u0456\u043B\u0456 \u0431\u0435\u0441\u0456\u0434\u0438 -message.close.this.chat = \u0417\u0430\u043A\u0440\u0438\u0442\u0438 \u0446\u044E \u0431\u0435\u0441\u0456\u0434\u0443 -message.conference.info.error = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u043E\u0442\u0440\u0438\u043C\u0430\u0442\u0438 \u0456\u043D\u0444\u0443, \u0441\u043F\u0440\u043E\u0431\u0443\u0439 \u043F\u0456\u0437\u043D\u0456\u0448\u0435 -message.conference.service.error = \u043D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0432\u0438\u0437\u043D\u0430\u0447\u0438\u0442\u0438 \u0441\u043B\u0443\u0436\u0431\u0443 \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0439 -message.confirm.destruction.of.room = \u0412\u0438\u043B\u0443\u0447\u0435\u043D\u043D\u044F \u0433\u0440\u0443\u043F\u0438 \u043F\u0440\u0438\u0432\u0435\u0434\u0435 \u0434\u043E \u0432\u0438\u043B\u0443\u0447\u0435\u043D\u043D\u044F \u0432\u0441\u0456\u0445 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432, \u043F\u0440\u043E\u0434\u043E\u0432\u0436\u0438\u0442\u0438? -message.confirmation.password.error = \u0412\u043A\u0430\u0437\u0430\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C \u0434\u043B\u044F \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043D\u044F -message.connecting.please.wait = \u0417\u0430\u0447\u0435\u043A\u0430\u0439... -message.connection.failed = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437'\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C \u0437 {0} -message.create.account = \u0417\u0430\u043F\u0438\u0441 \u043D\u0435 \u0441\u0442\u0432\u043E\u0440\u0435\u043D\u043E -message.create.or.join.room = \u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0430\u0431\u043E \u0434\u043E\u043B\u0443\u0447\u0438\u0442\u0438\u0441\u044C \u0434\u043E \u0433\u0440\u0443\u043F\u0438 -message.current.status = \u0414\u043E\u0437\u0432\u043E\u043B\u0438\u0442\u0438 \u0437\u043D\u0430\u0442\u0438 \u043C\u0456\u0439 \u0441\u0442\u0430\u0442\u0443\u0441 \u0447\u0438 \u0430\u043A\u0442\u0438\u0432\u043D\u0456\u0441\u0442\u044C -message.default.error = \u041F\u043E\u043C\u0438\u043B\u043A\u0430. \u0412\u0456\u0434\u0437\u0432\u0456\u0442\u0443\u0439 \u0434\u043E support@jivesoftware.com -message.delete.all.history = \u0412\u0438\u043B\u0443\u0447\u0438\u0442\u0438 \u043F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0456 \u0440\u043E\u0437\u043C\u043E\u0432\u0438? -message.delete.confirmation = \u0412\u043F\u0435\u0432\u043D\u0435\u043D\u043E \u0432\u0438\u043B\u0443\u0447\u0430\u0454\u0448 {0}? -message.disable.transport = \u0412\u0438\u043B\u0443\u0447\u0438\u0442\u0438 \u0440\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u0439\u043D\u0443 \u0456\u043D\u0444\u0443 \u0437 {0}? -message.disconnected.conflict.error = \u0417'\u0454\u0434\u043D\u0430\u043D\u043D\u044F \u0440\u043E\u0437\u0456\u0440\u0432\u0430\u043D\u043E \u0447\u0435\u0440\u0435\u0437 \u0456\u0441\u043D\u0443\u0432\u0430\u043D\u043D\u044F \u0442\u0430\u043A\u043E\u0433\u043E \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 -message.disconnected.error = \u0417'\u0454\u0434\u043D\u0430\u043D\u043D\u044F \u0440\u043E\u0437\u0456\u0440\u0432\u0430\u043D\u043E \u0447\u0435\u0440\u0435\u0437 \u043F\u043E\u043C\u0438\u043B\u043A\u0443 -message.disconnected.group.chat.error = \u0417'\u0454\u0434\u043D\u0430\u043D\u043D\u044F \u0440\u043E\u0437\u0456\u0440\u0432\u0430\u043D\u043E \u0447\u0435\u0440\u0435\u0437 \u043F\u043E\u043C\u0438\u043B\u043A\u0443, \u0421\u043F\u0430\u0440\u043A \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u043D\u043E \u043F\u0440\u0438\u0454\u0434\u043D\u0430\u0454\u0442\u044C\u0441\u044F \u0434\u043E \u043A\u0430\u043D\u0430\u043B\u0456\u0432 \u043F\u0456\u0441\u043B\u044F \u0432\u0456\u0434\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F -message.disconnected.shutdown = \u0417'\u0454\u0434\u043D\u0430\u043D\u043D\u044F \u0440\u043E\u0437\u0456\u0440\u0432\u0430\u043D\u043E \u043D\u0430 \u0441\u0442\u043E\u0440\u043E\u043D\u0456 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 -message.downloading = \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0443\u0454\u0442\u044C\u0441\u044F {0} -message.downloading.spark.plug = \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0443\u0454\u0442\u044C\u0441\u044F \u0432\u0441\u0442\u0430\u0432\u043A\u0430 -message.end.chat = \u0417\u0430\u043A\u0456\u043D\u0447\u0438\u0442\u0438 \u0440\u043E\u0437\u043C\u043E\u0432\u0443? -message.end.conversation = \u0417\u0430\u043A\u0456\u043D\u0447\u0438\u0442\u0438 \u0441\u0435\u0441\u0456\u044E? -message.enter.aim = \u0412\u0432\u0435\u0434\u0438 AIM \u0456\u043C'\u044F \u0456 \u043F\u0430\u0440\u043E\u043B\u044C -message.enter.broadcast.message = \u0412\u0432\u0435\u0434\u0438 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F \u0434\u043B\u044F \u0442\u0440\u0430\u043D\u0441\u043B\u044E\u0432\u0430\u043D\u043D\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430\u043C -message.enter.gadugadu = \u0412\u0432\u0435\u0434\u0438 GaduGadu \u0456\u043C'\u044F \u0456 \u043F\u0430\u0440\u043E\u043B\u044C -message.enter.gtalk = \u0412\u0432\u0435\u0434\u0438 gtalk \u0456\u043C'\u044F \u0456 \u043F\u0430\u0440\u043E\u043B\u044C -message.enter.icq = \u0412\u0432\u0435\u0434\u0438 ICQ \u0456\u043C'\u044F \u0456 \u043F\u0430\u0440\u043E\u043B\u044C -message.enter.irc = \u0412\u0432\u0435\u0434\u0438 IRC \u0456\u043C'\u044F \u0456 \u043F\u0430\u0440\u043E\u043B\u044C -message.enter.sametime = \u0412\u0432\u0435\u0434\u0438 Sametime \u0456\u043C'\u044F \u0456 \u043F\u0430\u0440\u043E\u043B\u044C -message.enter.facebook = \u0412\u0432\u0435\u0434\u0438 Facebook \u0456\u043C'\u044F \u0456 \u043F\u0430\u0440\u043E\u043B\u044C -message.enter.myspace = \u0412\u0432\u0435\u0434\u0438 MySpace \u0456\u043C'\u044F \u0456 \u043F\u0430\u0440\u043E\u043B\u044C -message.enter.jabber.id = \u0412\u0432\u0435\u0434\u0438 \u0414\u0436\u0430\u0431\u0435\u0440 \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 -message.enter.message.to.broadcast = \u0412\u0432\u0435\u0434\u0438 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F \u0434\u043B\u044F \u0442\u0440\u0430\u043D\u0441\u043B\u044E\u0432\u0430\u043D\u043D\u044F \u0432\u043D\u0443\u0442\u0440\u0456\u0448\u043D\u044C\u043E\u043C\u0443 \u0441\u043F\u0438\u0441\u043A\u0443 -message.enter.msn = \u0412\u0432\u0435\u0434\u0438 MSN \u0456\u043C'\u044F \u0456 \u043F\u0430\u0440\u043E\u043B\u044C -message.enter.new.subject = \u0412\u0432\u0435\u0434\u0438 \u043D\u043E\u0432\u0443 \u0442\u0435\u043C\u0443 -message.enter.qq = \u0412\u0432\u0435\u0434\u0438 QQ \u043D\u043E\u043C\u0435\u0440 \u0456 \u043F\u0430\u0440\u043E\u043B\u044C -message.enter.room.password = \u0412\u0432\u0435\u0434\u0438 \u043F\u0430\u0440\u043E\u043B\u044C \u0434\u043E \u0433\u0440\u0443\u043F\u0438 -message.enter.simple = \u0412\u0432\u0435\u0434\u0438 SIMPLE \u0456\u043C'\u044F \u0456 \u043F\u0430\u0440\u043E\u043B\u044C -message.enter.valid.jid = \u0412\u0432\u0435\u0434\u0438 \u0434\u0456\u0439\u0441\u043D\u0438\u0439 \u0434\u0436\u0430\u0431\u0435\u0440 \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 -message.enter.xmpp = \u0412\u0432\u0435\u0434\u0438 XMPP \u0456\u043C'\u044F \u0456 \u043F\u0430\u0440\u043E\u043B\u044C -message.enter.yahoo = \u0412\u0432\u0435\u0434\u0438 Yahoo \u0456\u043C'\u044F \u0456 \u043F\u0430\u0440\u043E\u043B\u044C -message.error.during.file.transfer = \u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u043F\u0440\u0438 \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0444\u0430\u0439\u043B\u0443 -message.file.exists.question = \u0424\u0430\u0439\u043B \u0432\u0436\u0435 \u0456\u0441\u043D\u0443\u0454, \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0438\u0441\u0430\u0442\u0438? -message.file.size = \u0420\u043E\u0437\u043C\u0456\u0440 \u0444\u0430\u0439\u043B\u0443: {0} -message.file.transfer.canceled = \u0422\u0438 \u0432\u0456\u0434\u043C\u0456\u043D\u0438\u0432 \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0434\u0430\u043D\u0438\u0445 -message.file.transfer.rejected = \u041F\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0444\u0430\u0439\u043B\u0443 \u043D\u0435 \u043F\u0440\u0438\u0439\u043D\u044F\u0442\u0430 {0} -message.file.transfer.dirnull = \u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0430 \u0442\u0435\u043A\u0430 \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0444\u0430\u0439\u043B\u0443 -message.file.transfer.nodir = \u0422\u0435\u043A\u0430 \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0444\u0430\u0439\u043B\u0443 \u043D\u0435 \u0456\u0441\u043D\u0443\u0454 -message.file.transfer.cantwritedir \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437\u0430\u043F\u0438\u0441\u0430\u0442\u0438 \u0432 \u0442\u0435\u043A\u0443 -message.file.transfer.notification = \u0421\u043F\u043E\u0432\u0456\u0449\u0435\u043D\u043D\u044F \u043F\u0440\u043E \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0434\u0430\u043D\u0438\u0445 -message.file.transfer.short.message = \u043D\u0430\u0434\u0441\u0438\u043B\u0430\u0454 \u0432\u0430\u043C \u0444\u0430\u0439\u043B\: -message.file.transfer.chat.window = \u0417\u0430\u043F\u0438\u0442 \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0444\u0430\u0439\u043B\u0443: -message.file.transfer.file.too.big.error = \u0412\u0438\u0431\u0440\u0430\u043D\u0438\u0439 \u0444\u0430\u0439\u043B \u043D\u0430\u0434\u0442\u043E \u0432\u0435\u043B\u0438\u043A\u0438\u0439.\n\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u043E \u043C\u043E\u0436\u043B\u0438\u0432\u0438\u0439 \u0440\u043E\u0437\u043C\u0456\u0440 {0}, \u0430 \u0432\u0438\u0431\u0440\u0430\u043D\u0438\u0439 \u0444\u0430\u0439\u043B \u043C\u0430\u0454 {1} -message.file.transfer.file.too.big.warning = \u0412\u0438\u0431\u0440\u0430\u043D\u0438\u0439 \u0444\u0430\u0439\u043B \u043D\u0430\u0434\u0442\u043E \u0432\u0435\u043B\u0438\u043A\u0438\u0439.\n\u041F\u0440\u043E\u0434\u043E\u0432\u0436\u0438\u0442\u0438 \u0432\u0441\u0435 \u043E\u0434\u043D\u043E? -message.file.transfer.direrror.setdir = \u041D\u0430\u0442\u0438\u0441\u043D\u0438 \u0442\u0443\u0442, \u0449\u043E\u0431 \u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u0442\u0435\u043A\u0443 -message.find.conference.services = \u0417\u043D\u0430\u0439\u0442\u0438 \u0441\u043B\u0443\u0436\u0431\u0438 \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0439 -message.forbidden.error = \u041E\u0442\u0440\u0438\u043C\u0430\u043D\u043E \u043F\u043E\u043C\u0438\u043B\u043A\u0443 \u0437\u0430\u0431\u043E\u0440\u043E\u043D\u0438 \u0432\u0456\u0434 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 -message.gateway.username.error = \u041F\u043E\u0442\u0440\u0456\u0431\u043D\u043E \u0432\u0432\u0435\u0441\u0442\u0438 \u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 -message.gateway.password.error = \u041F\u043E\u0442\u0440\u0456\u0431\u043D\u043E \u0432\u0432\u0435\u0441\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C -message.gateway.nickname.error = \u041F\u043E\u0442\u0440\u0456\u0431\u043D\u043E \u0432\u0432\u0435\u0441\u0442\u0438 \u043D\u0456\u043A -message.general.error = \u0417\u0432'\u044F\u0437\u043E\u043A \u0456\u0437 \u0441\u0435\u0440\u0432\u0435\u0440\u043E\u043C \u0440\u043E\u0437\u0456\u0440\u0432\u0430\u043D\u043E \u0447\u0435\u0440\u0435\u0437 {0} -message.generic.reconnect.message = \u0417\u0432'\u044F\u0437\u043E\u043A \u0456\u0437 \u0441\u0435\u0440\u0432\u0435\u0440\u043E\u043C \u0440\u043E\u0437\u0456\u0440\u0432\u0430\u043D\u043E, \u0449\u043E\u0431 \u043F\u0456\u0434'\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C \u0437\u043D\u043E\u0432\u0443, \u043D\u0430\u0442\u0438\u0441\u043D\u0438 \u043A\u043D\u043E\u043F\u043A\u0443 \u0432\u043D\u0438\u0437\u0443 -message.idle.for = \u041D\u0435\u0430\u043A\u0442\u0438\u0432\u043D\u0438\u0439 {0} -message.image.too.large = \u041C\u0430\u043B\u044E\u043D\u043E\u043A \u043D\u0430\u0434\u0442\u043E \u0432\u0435\u043B\u0438\u043A\u0438\u0439, \u043C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0438\u0439 \u0440\u043E\u0437\u043C\u0456\u0440 16 \u043A\u0456\u043B\u043E\u0431\u0430\u0439\u0442 -message.invalid.jabber.id = \u0425\u0438\u0431\u043D\u0438\u0439 \u0434\u0436\u0430\u0431\u0435\u0440-\u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 -message.invalid.jid.error = \u0414\u0416\u0406\u0414-\u0456\u043D\u0432\u0430\u043B\u0456\u0434 -message.invalid.status = \u0412\u043A\u0430\u0436\u0438 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0438\u0439 \u0441\u0442\u0430\u0442\u0443\u0441 -message.invalid.username.password = \u0425\u0438\u0431\u043D\u0435 \u0456\u043C'\u044F \u0447\u0438 \u043F\u0430\u0440\u043E\u043B\u044C -message.invite.users.to.conference = \u0417\u0430\u043F\u0440\u043E\u0441\u0438\u0442\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432 \u0434\u043E \u0433\u0440\u0443\u043F\u0438 -message.is.shared.group = {0} \u0437\u0430\u043F\u0440\u043E\u0441\u0438\u0432 \u0434\u043E \u0433\u0440\u0443\u043F\u0438 -message.is.typing.a.message = {0} \u043F\u0438\u0448\u0435 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F -message.join.conference.room = \u041F\u0440\u0438\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044F \u0434\u043E \u0433\u0440\u0443\u043F\u0438 -message.kicked.error = \u0422\u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0448 \u0432\u0438\u043A\u0438\u0434\u0430\u0442\u0438 {0} \u0437 \u0446\u0456\u0454\u0457 \u0433\u0440\u0443\u043F\u0438 -message.last.message.received = \u041E\u0441\u0442\u0430\u043D\u043D\u0454 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F \u043E\u0442\u0440\u0438\u043C\u0430\u043D\u043E {0} -message.loading.please.wait = \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0443\u0454\u0442\u044C\u0441\u044F... -message.locked.workstation = \u041A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447 \u0437\u0430\u0431\u043B\u043E\u043A\u043E\u0432\u0430\u043D\u0438\u0439 \u043D\u0430 \u0439\u043E\u0433\u043E \u0440\u043E\u0431\u043E\u0447\u0456\u0439 \u0441\u0442\u0430\u043D\u0446\u0456\u0457 -message.name.of.group = \u041D\u0430\u0437\u0432\u0430 \u0433\u0440\u0443\u043F\u0438 -message.name.of.search.service.question = \u041D\u0430\u0437\u0432\u0430 \u043F\u043E\u0448\u0443\u043A\u043E\u0432\u043E\u0433\u043E \u0441\u0435\u0440\u0432\u0456\u0441\u0443? -message.negotiate.file.transfer = \u0412\u0456\u0434\u0431\u0443\u0432\u0430\u0454\u0442\u044C\u0441\u044F \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0444\u0430\u0439\u043B\u0456\u0432... -message.negotiate.stream = \u0412\u0456\u0434\u0431\u0443\u0432\u0430\u0454\u0442\u044C\u0441\u044F \u0437'\u0454\u0434\u043D\u0430\u043D\u043D\u044F \u043F\u043E\u0442\u043E\u043A\u0456\u0432... -message.negotiation.file.transfer = \u0412\u0456\u0434\u0431\u0443\u0432\u0430\u0454\u0442\u044C\u0441\u044F \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0444\u0430\u0439\u043B\u0456\u0432... {0} -message.new.message = \u041D\u043E\u0432\u0435 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F \u0432\u0456\u0434 {0} -message.new.spark.available = {0} \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0438\u0439, \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0438? -message.nickname.in.use = \u041D\u0456\u043A \u0443\u0436\u0435 \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u043D\u043E, \u0431\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u0432\u043A\u0430\u0436\u0438 \u0456\u043D\u0448\u0438\u0439 -message.nickname.not.acceptable = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u043D\u0456\u043A! -message.no.avatar.found = \u041A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447 \u043D\u0435 \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u0432 \u0432\u0438\u0433\u043B\u044F\u0434 -message.no.caller.id = \u041D\u0435 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0438\u0439 \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u0430\u0431\u043E\u043D\u0435\u043D\u0442\u0430 -message.no.description.available = \u041D\u0435\u043C\u0430 \u043E\u043F\u0438\u0441\u0443 -message.no.history.found = \u041D\u0435\u043C\u0430 \u043F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0456\u0445 \u0440\u043E\u0437\u043C\u043E\u0432 -message.no.results.found = \u041D\u0435\u043C\u0430 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0456\u0432 \u043F\u043E\u0448\u0443\u043A\u0443 -message.no.room.to.join.error = \u041D\u0435\u043C\u0430 \u043A\u0456\u043C\u043D\u0430\u0442 \u0434\u043B\u044F \u043F\u0440\u0438\u0454\u0434\u043D\u0430\u043D\u043D\u044F -message.no.subject.available = \u041D\u0435\u043C\u0430 \u0442\u0435\u043C\u0438 -message.no.updates = \u041D\u0435\u043C\u0430 \u043E\u043D\u043E\u0432\u043B\u0435\u043D\u044C -message.normal = \u041D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u0435 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F -message.number.to.call = \u0412\u0432\u0435\u0434\u0438 \u043D\u043E\u043C\u0435\u0440, \u0449\u043E\u0431 \u0437\u0430\u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0443\u0432\u0430\u0442\u0438 -message.offline = \u041A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447 \u043D\u0435 \u0432 \u043C\u0435\u0440\u0435\u0436\u0456, \u0432\u0456\u043D \u043E\u0442\u0440\u0438\u043C\u0430\u0454 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F, \u043A\u043E\u043B\u0438 \u0437'\u044F\u0432\u0438\u0442\u044C\u0441\u044F -message.offline.error = \u0426\u0435\u0439 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447 \u043D\u0435 \u043C\u043E\u0436\u0435 \u043E\u0442\u0440\u0438\u043C\u0443\u0432\u0430\u0442\u0438 \u043E\u0444\u043B\u0430\u0439\u043D\u043E\u0432\u0456 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F -message.participants.in.room = \u0423\u0447\u0430\u0441\u043D\u0438\u043A\u0456\u0432 \u0432 \u0433\u0440\u0443\u043F\u0456 -message.password.error = \u0412\u043A\u0430\u0436\u0438 \u043F\u0430\u0440\u043E\u043B\u044C \u0434\u043B\u044F \u0446\u044C\u043E\u0433\u043E \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 -message.password.private.room.error = \u0412\u043A\u0430\u0436\u0438 \u043F\u0430\u0440\u043E\u043B\u044C \u0434\u043E \u0433\u0440\u0443\u043F\u0438 -message.passwords.no.match = \u041F\u0430\u0440\u043E\u043B\u044C \u043D\u0435 \u0441\u043F\u0456\u0432\u043F\u0430\u0434\u0430\u0454 -message.please.join.in.conference = \u041F\u0440\u0438\u0439\u043C\u0456\u0442\u044C \u043C\u0435\u043D\u0435 \u0434\u043E \u0433\u0440\u0443\u043F\u0438 -message.plugins.not.available = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437'\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C \u0437 \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0456\u0454\u043C -message.prompt.plugin.uninstall = \u0412\u043F\u0435\u0432\u043D\u0435\u043D\u0438\u0439, \u0449\u043E \u0445\u043E\u0447\u0435\u0448 \u0432\u0438\u043B\u0443\u0447\u0438\u0442\u0438 {0}? -message.received.file = \u0422\u0438 \u043E\u0442\u0440\u0438\u043C\u0430\u0432 \u0444\u0430\u0439\u043B \u0432\u0456\u0434 {0} -message.receiving.file = \u0422\u0438 \u043E\u0442\u0440\u0438\u043C\u0443\u0454\u0448 \u0444\u0430\u0439\u043B \u0432\u0456\u0434 {0} -message.reconnect.attempting = \u0421\u043F\u0440\u043E\u0431\u0430 \u043F\u043E\u0432\u0442\u043E\u0440\u043D\u043E\u0433\u043E \u0437'\u0454\u0434\u043D\u0430\u043D\u043D\u044F... -message.reconnect.failed = \u041D\u0435\u0432\u0434\u0430\u0447\u0430 -message.reconnect.wait = \u041F\u043E\u0432\u0442\u043E\u0440\u043D\u0435 \u0437'\u0454\u0434\u043D\u0430\u043D\u043D\u044F \u0447\u0435\u0440\u0435\u0437 {0} \u0441\u0435\u043A\u0443\u043D\u0434 -message.register.transports = \u0417\u0430\u0440\u0435\u0454\u0441\u0442\u0440\u0443\u0432\u0430\u0442\u0438\u0441\u044C \u0447\u0435\u0440\u0435\u0437 \u043C\u043E\u0436\u043B\u0438\u0432\u0438\u0439 \u0442\u0440\u0430\u043D\u0441\u043F\u043E\u0440\u0442 -message.registering = \u0420\u0435\u0454\u0441\u0442\u0440\u0443\u0454\u0442\u044C\u0441\u044F {0}, \u0437\u0430\u0447\u0435\u043A\u0430\u0439... -message.registration.transport.failed = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437\u0430\u0440\u0435\u0454\u0441\u0442\u0440\u0443\u0432\u0430\u0442\u0438 \u0448\u043B\u044E\u0437 -message.restart.spark = \u041F\u043E\u0442\u0440\u0456\u0431\u043D\u043E \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u0438 \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u0443, \u0449\u043E\u0431 \n \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0438 \u043D\u043E\u0432\u0443 \u0432\u0435\u0440\u0441\u0456\u044E, \u0437\u0440\u043E\u0431\u0438\u0442\u0438 \u0446\u0435 \u0437\u0430\u0440\u0430\u0437? -message.restart.spark.changes = \u0414\u043E\u0434\u0430\u0442\u043E\u043A \u0431\u0443\u0434\u0435 \u0432\u0438\u043B\u0443\u0447\u0435\u043D\u043E \u043F\u0456\u0441\u043B\u044F \u043D\u0430\u0441\u0442\u0443\u043F\u043D\u043E\u0433\u043E \u0437\u0430\u043F\u0443\u0441\u043A\u0443 \u0421\u043F\u0430\u0440\u043A -message.restart.spark.to.install = \u041F\u043E\u0442\u0440\u0456\u0431\u043D\u043E \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u0438 \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u0443, \u0449\u043E\u0431 \n \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0438 \u043D\u043E\u0432\u0443 \u0432\u0435\u0440\u0441\u0456\u044E, \u0437\u0440\u043E\u0431\u0438\u0442\u0438 \u0446\u0435 \u0437\u0430\u0440\u0430\u0437? -message.restart.required = \u041F\u043E\u0442\u0440\u0456\u0431\u043D\u043E \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u0438 \u0421\u043F\u0430\u0440\u043A, \u0449\u043E\u0431 \u0430\u043A\u0442\u0443\u0430\u043B\u0456\u0437\u0443\u0432\u0430\u0442\u0438 \u0437\u043C\u0456\u043D\u0438, \u0437\u0440\u043E\u0431\u0438\u0442\u0438 \u0446\u0435 \u0437\u0430\u0440\u0430\u0437? -message.room.creation.error = \u0413\u0440\u0443\u043F\u0430 \u043D\u0435 \u043C\u043E\u0436\u0435 \u0431\u0443\u0442\u0438 \u0441\u0442\u0432\u043E\u0440\u0435\u043D\u0430 -message.room.destroyed = \u0413\u0440\u0443\u043F\u0443 \u0440\u043E\u0437\u0444\u043E\u0440\u043C\u043E\u0432\u0430\u043D\u043E \u0447\u0435\u0440\u0435\u0437: {0} -message.room.destruction.reason = \u041F\u0440\u0438\u0447\u0438\u043D\u0430? -message.room.information.for = \u0413\u0440\u0443\u043F\u043E\u0432\u0430 \u0456\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0456\u044F \u0434\u043B\u044F {0} -message.save.profile = \u041D\u0430\u0442\u0438\u0441\u043D\u0438 \u0437\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0434\u043B\u044F \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043D\u043D\u044F -message.search.for.contacts = \u041F\u043E\u0448\u0443\u043A \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u0456\u0432 -message.search.input.short = \u0412\u043A\u0430\u0436\u0438 \u0449\u043E\u043D\u0430\u0439\u043C\u0435\u043D\u0448\u0435 5 \u0431\u0443\u043A\u0432 -message.search.for.other.people = \u041F\u043E\u0448\u0443\u043A \u043B\u044E\u0434\u0435\u0439 \u043D\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0456 -message.search.service.not.available = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437'\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C \u0437 \u043F\u043E\u0448\u0443\u043A\u043E\u0432\u043E\u0433\u043E \u0441\u043B\u0443\u0436\u0431\u043E\u044E -message.searching.please.wait = \u0428\u0443\u043A\u0430\u044E... -message.select.add.room.to.add = \u0412\u0438\u0431\u0435\u0440\u0438 \u0433\u0440\u0443\u043F\u0443, \u0449\u043E\u0431 \u0434\u043E\u0434\u0430\u0442\u0438 \u0434\u043E \u0441\u043F\u0438\u0441\u043A\u0443 -message.select.one.or.more = \u0412\u0438\u0431\u0435\u0440\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432 \u0437\u0456 \u0441\u043F\u0438\u0441\u043A\u0443 -message.select.room.to.enter = \u0412\u043A\u0430\u0436\u0438 \u0433\u0440\u0443\u043F\u0443, \u0449\u043E\u0431 \u0437\u0430\u0439\u0442\u0438 -message.select.room.to.join = \u0412\u0438\u0431\u0435\u0440\u0438 \u0433\u0440\u0443\u043F\u0443, \u0449\u043E\u0431 \u043F\u0440\u0438\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C -message.send.a.broadcast = \u0422\u0440\u0430\u043D\u0441\u043B\u044E\u0432\u0430\u0442\u0438 -message.send.file.to.user = \u041D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438 \u0444\u0430\u0439\u043B\u0438 \u0446\u044C\u043E\u043C\u0443 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0443 -message.send.picture = \u0417\u0430\u0445\u043E\u043F\u0438\u0442\u0438 \u0456 \u043D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438 \u0437\u043D\u0456\u043C\u043E\u043A \u0435\u043A\u0440\u0430\u043D\u0443 -message.send.to.these.people = \u041D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438 \u0446\u0438\u043C \u043B\u044E\u0434\u044F\u043C -message.sending.file.to = \u041D\u0430\u0434\u0441\u0438\u043B\u0430\u043D\u043D\u044F \u0444\u0430\u0439\u043B\u0443 \u0434\u043E {0} -message.sent.offline.files = \u0422\u0438 \u0449\u043E\u0439\u043D\u043E \u043D\u0430\u0434\u0456\u0441\u043B\u0430\u0432 \u0444\u0430\u0439\u043B(\u0438). -message.server.unavailable = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437'\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C \u0456\u0437 \u0441\u0435\u0440\u0432\u0435\u0440\u043E\u043C: \u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0438\u0439 \u0430\u0431\u043E \u0445\u0438\u0431\u043D\u0435 \u0456\u043C'\u044F -message.service.already.exists = \u0421\u043B\u0443\u0436\u0431\u0430 \u0432\u0436\u0435 \u0454 \u0432 \u0441\u043F\u0438\u0441\u043A\u0443 -message.shared.group = \u0421\u043F\u0456\u043B\u044C\u043D\u0430 \u0433\u0440\u0443\u043F\u0430 -message.spark.secure = \u0421\u043F\u0430\u0440\u043A \u043F\u0440\u0430\u0446\u044E\u0454 \u0432 \u0437\u0430\u0445\u0438\u0449\u0435\u043D\u043E\u043C\u0443 \u0440\u0435\u0436\u0438\u043C\u0456 -message.specify.contact.jid = \u0412\u043A\u0430\u0436\u0438 \u0414\u0416\u0406\u0414 (\u043A\u043E\u043B\u0438\u0448\u043D\u0456\u0439 ddman@jabber.org) -message.specify.group = \u0412\u043A\u0430\u0436\u0438 \u0433\u0440\u0443\u043F\u0443, \u0449\u043E\u0431 \u0434\u043E\u0434\u0430\u0442\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 -message.specify.information.for.conference = \u0412\u043A\u0430\u0436\u0438 \u0456\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0456\u044E \u0434\u043B\u044F \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0457 -message.specify.name.error = \u0412\u043A\u0430\u0436\u0438 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0435 \u0456\u043C'\u044F -message.specify.users.to.join.conference = \u0412\u043A\u0430\u0436\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432, \u0449\u043E\u0431 \u043F\u0440\u0438\u0454\u0434\u043D\u0430\u0442\u0438 \u0434\u043E \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0457 -message.specify.valid.time.error = \u0412\u043A\u0430\u0436\u0438 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0443 \u0437\u0430\u0442\u0440\u0438\u043C\u043A\u0443 \u0456 \u043F\u043E\u0440\u0442 -message.subject.change.error = \u041D\u0435 \u0434\u043E\u0437\u0432\u043E\u043B\u0435\u043D\u043E \u0437\u043C\u0456\u043D\u044E\u0432\u0430\u0442\u0438 \u0442\u0435\u043C\u0443 \u0433\u0440\u0443\u043F\u0438 -message.subject.has.been.changed.to = {1} \u0437\u043C\u0456\u043D\u0438\u0432 \u0442\u0435\u043C\u0443 \u043D\u0430 "{0}" -message.supply.resource = \u0412\u043A\u0430\u0436\u0438 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0435 \u0434\u0436\u0435\u0440\u0435\u043B\u043E -message.supply.valid.port = \u0412\u043A\u0430\u0436\u0438 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0438\u0439 \u043F\u043E\u0440\u0442 -message.supply.valid.timeout = \u0412\u043A\u0430\u0436\u0438 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0438\u0439 \u0447\u0430\u0441 \u0456 \u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F -message.timeout.error = \u0417\u0430\u0442\u0440\u0438\u043C\u043A\u0430 \u043C\u0430\u0431\u0443\u0442\u0438 5 \u0441\u0435\u043A\u0443\u043D\u0434 \u0430\u0431\u043E \u0431\u0456\u043B\u044C\u0448\u043E\u044E -message.total.downloaded = \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043E \u043F\u043E\u0432\u043D\u0456\u0441\u0442\u044E -message.transfer.cancelled = \u041F\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0444\u0430\u0439\u043B\u0456\u0432 \u0432\u0456\u0434\u0445\u0438\u043B\u0435\u043D\u043E -message.transfer.complete = \u041F\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0431\u0443\u043B\u043E \u0437\u0430\u043A\u0456\u043D\u0447\u0435\u043D\u043E ({0}) -message.transfer.progressbar.text.received = {0} \u043E\u0442\u0440\u0438\u043C\u0430\u043D\u043E @ {1} {2} -message.transfer.progressbar.text.sent = {0} \u043D\u0430\u0434\u0456\u0441\u043B\u0430\u043D\u043E @ {1} {2} -message.transfer.rate = \u0428\u0432\u0438\u0434\u043A\u0456\u0441\u0442\u044C \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0456 -message.transfer.refused = \u0423 \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0444\u0430\u0439\u043B\u0456\u0432 \u0432\u0456\u0434\u043C\u043E\u0432\u043B\u0435\u043D\u043E -message.transfer.waiting.on.user = \u041E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u043D\u044F \u043D\u0430 {0} \u0434\u043B\u044F \u043F\u0440\u0438\u0439\u043D\u044F\u0442\u0442\u044F \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0444\u0430\u0439\u043B\u0456\u0432 -message.unable.to.load.profile = \u041D\u0435\u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437\u043D\u0430\u0439\u0442\u0438 \u043F\u0440\u043E\u0444\u0430\u0439\u043B \u0434\u043B\u044F {0} -message.unable.to.retrieve.last.activity = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0432\u0438\u0437\u043D\u0430\u0447\u0438\u0442\u0438 \u043E\u0441\u0442\u0430\u043D\u043D\u044E \u0430\u043A\u0442\u0438\u0432\u043D\u0456\u0441\u0442\u044C \u0434\u043B\u044F {0} -message.unable.to.save.password = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C, \u0437\u0432\u0435\u0440\u043D\u0438\u0441\u044C \u0434\u043E \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 -message.unable.to.send.file = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u043D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438 \u0444\u0430\u0439\u043B \u0434\u043E {0} -message.unable.to.use.hostname.as.resource = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0456\u043C'\u044F \u0445\u043E\u0441\u0442\u0430 \u044F\u043A \u0434\u0436\u0435\u0440\u0435\u043B\u043E -message.unrecoverable.error = \u0425\u0438\u0431\u043D\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C \u0430\u0431\u043E \u0456\u043C'\u044F -message.update.room.list = \u041E\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F \u0441\u043F\u0438\u0441\u043A\u0443 -message.updating.cancelled = \u041E\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F \u0432\u0456\u0434\u0445\u0438\u043B\u0435\u043D\u044F -message.user.banned = {0} \u0437\u0430\u0431\u0430\u043D\u0435\u043D\u0438\u0439. \u041F\u0440\u0438\u0447\u0438\u043D\u0430: {1} -message.user.given.voice = {0} \u043E\u0442\u0440\u0438\u043C\u0430\u0432 \u0433\u043E\u043B\u043E\u0441 -message.user.granted.admin = {0} \u043E\u0442\u0440\u0438\u043C\u0430\u0432 \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u0438\u0432\u043D\u0456 \u043F\u0440\u0438\u0432\u0456\u043B\u0435\u0457 -message.user.granted.membership = {0} \u0441\u0442\u0430\u0432 \u0443\u0447\u0430\u0441\u043D\u0438\u043A\u043E\u043C -message.user.granted.moderator = {0} \u043E\u0442\u0440\u0438\u043C\u0430\u0432 \u043F\u0440\u0430\u0432\u0430 \u043C\u043E\u0434\u0435\u0440\u0430\u0442\u043E\u0440\u0430 -message.user.granted.owner = {0} \u043E\u0442\u0440\u0438\u043C\u0430\u0432 \u043F\u0440\u0430\u0432\u0430 \u0432\u043B\u0430\u0441\u043D\u0438\u043A\u0430 -message.user.is.sending.you.a.file = {0} \u043D\u0430\u0434\u0441\u0438\u043B\u0430\u0454 \u0432\u0430\u043C \u0444\u0430\u0439\u043B -message.user.joined.room = {0} \u0432\u0432\u0456\u0439\u0448\u043E\u0432 \u0434\u043E \u0447\u0430\u0442\u0443 -message.user.kicked.from.room = \u0423\u0447\u0430\u0441\u043D\u0438\u043A\u0430 {0} \u0432\u0438\u043B\u0443\u0447\u0438\u0432 \u0437 \u0447\u0430\u0442\u0443 {1}. \u041F\u0440\u0438\u0447\u0438\u043D\u0430: {2} -message.user.left.room = {0} \u043F\u043E\u043A\u0438\u043D\u0443\u0432 \u0447\u0430\u0442 -message.user.nickname.changed = {0} \u0432\u0456\u0434\u043E\u043C\u0438\u0439 \u044F\u043A {1} -message.user.now.available.to.chat = {0} \u043D\u0430 \u0437\u0432'\u044F\u0437\u043A\u0443 \u0437 {1} -message.user.revoked.admin = \u041F\u0440\u0430\u0432\u0430 \u0430\u0434\u043C\u0456\u043D\u0430 \u0432\u0456\u0434\u043A\u043B\u0438\u043A\u0430\u043D\u0456 \u0443 {0} -message.user.revoked.membership = \u0423\u0447\u0430\u0441\u0442\u044C {0} \u0431\u0443\u043B\u0430 \u0432\u0456\u0434\u043A\u043B\u0438\u043A\u0430\u043D\u0430 -message.user.revoked.moderator = \u041F\u0440\u0430\u0432\u0430 \u043C\u043E\u0434\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u0432\u0456\u0434\u043A\u043B\u0438\u043A\u0430\u043D\u0456 \u0443 {0} -message.user.revoked.owner = \u041F\u0440\u0430\u0432\u0430 \u0432\u043B\u0430\u0441\u043D\u0438\u043A\u0430 \u0432\u0456\u0434\u043A\u043B\u0438\u043A\u0430\u043D\u0456 \u0443 {0} -message.user.voice.revoked = \u0413\u043E\u043B\u043E\u0441\u043E\u0432\u0456 \u043C\u043E\u0436\u043B\u0438\u0432\u043E\u0441\u0442\u0456 \u0431\u0443\u043B\u0438 \u0432\u0456\u0434\u043A\u043B\u0438\u043A\u0430\u043D\u0456 \u0443 {0} -message.username.error = \u0412\u043A\u0430\u0436\u0438 \u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0434\u043B\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 -message.username.password.error = \u041F\u043E\u0442\u0440\u0456\u0431\u043D\u043E \u0432\u043A\u0430\u0437\u0430\u0442\u0438 \u0456\u043C'\u044F \u0456 \u043F\u0430\u0440\u043E\u043B\u044C -message.vcard.not.supported = \u0421\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454 VCard, \u043D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0442\u0432\u043E\u044E VCard -message.version = \u0412\u0435\u0440\u0441\u0456\u044F: {0} -message.view.information.about.this.user = \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 \u0456\u043D\u0444\u043E \u043F\u0440\u043E \u0446\u044C\u043E\u0433\u043E \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 -message.waiting.for.user.to.join = \u041E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u043D\u044F \u043D\u0430 \u043F\u0440\u0438\u0454\u0434\u043D\u0430\u043D\u043D\u044F {0} -message.went.offline = {0} \u0440\u043E\u0437\u0456\u0440\u0432\u0430\u0432 \u0437\u0432'\u044F\u0437\u043E\u043A \u0437 {1} -message.you.have.been.banned = \u0422\u0435\u0431\u0435 \u0437\u0430\u0431\u0430\u043D\u0438\u043B\u0438 -message.you.have.been.kicked = \u0422\u0435\u0431\u0435 \u0432\u0438\u043B\u0443\u0447\u0438\u043B\u0438 \u0437 \u0446\u044C\u043E\u0433\u043E \u0447\u0430\u0442\u0443 -message.you.have.sent = \u0422\u0438 \u043D\u0430\u0434\u0456\u0441\u043B\u0430\u0432 \u0447\u0430\u0442 \u0434\u043E {0} -message.your.admin.granted = \u0422\u043E\u0431\u0456 \u043D\u0430\u0434\u0430\u043D\u043E \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u0438\u0432\u043D\u0456 \u043F\u0440\u0438\u0432\u0456\u043B\u0435\u0457 -message.your.banned = \u0422\u0435\u0431\u0435 \u0437\u0430\u0431\u0430\u043D\u0438\u043B\u0438 -message.your.kicked = \u0422\u0435\u0431\u0435 \u0432\u0438\u043B\u0443\u0447\u0438\u0432 {0} -message.your.membership.granted = \u0422\u043E\u0431\u0456 \u043D\u0430\u0434\u0430\u043D\u043E \u043F\u0440\u0430\u0432\u0430 \u0443\u0447\u0430\u0441\u043D\u0438\u043A\u0430 -message.your.membership.revoked = \u041F\u0440\u0430\u0432\u0430 \u0443\u0447\u0430\u0441\u043D\u0438\u043A\u0430 \u0432\u0456\u0434\u043A\u043B\u0438\u043A\u0430\u043D\u043E -message.your.moderator.granted = \u0422\u043E\u0431\u0456 \u043D\u0430\u0434\u0430\u043D\u043E \u043F\u0440\u0430\u0432\u0430 \u043C\u043E\u0434\u0435\u0440\u0430\u0442\u043E\u0440\u0430 -message.your.moderator.revoked = \u041F\u0440\u0430\u0432\u0430 \u043C\u043E\u0434\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u0432\u0456\u0434\u043A\u043B\u0438\u043A\u0430\u043D\u043E -message.your.ownership.granted = \u0422\u043E\u0431\u0456 \u043D\u0430\u0434\u0430\u043D\u043E \u043F\u0440\u0430\u0432\u0430 \u0432\u043B\u0430\u0441\u043D\u0438\u043A\u0430 -message.your.ownership.revoked = \u041F\u0440\u0430\u0432\u0430 \u0432\u043B\u0430\u0441\u043D\u0438\u043A\u0430 \u0432\u0456\u0434\u043A\u043B\u0438\u043A\u0430\u043D\u043E -message.your.revoked.granted = \u041F\u0440\u0430\u0432\u0430 \u0430\u0434\u043C\u0456\u043D\u0430 \u0432\u0456\u0434\u043A\u043B\u0438\u043A\u0430\u043D\u043E -message.your.voice.granted = \u0422\u043E\u0431\u0456 \u043D\u0430\u0434\u0430\u043D\u043E \u043C\u043E\u0436\u043B\u0438\u0432\u0456\u0441\u0442\u044C \u0441\u043F\u0456\u043B\u043A\u0443\u0432\u0430\u0442\u0438\u0441\u044C \u0433\u043E\u043B\u043E\u0441\u043E\u043C -message.your.voice.revoked = \u0413\u043E\u043B\u043E\u0441\u043E\u0432\u0456 \u043C\u043E\u0436\u043B\u0438\u0432\u043E\u0441\u0442\u0456 \u0432\u0456\u0434\u043A\u043B\u0438\u043A\u0430\u043D\u043E -message.groupchat.require.password = \u0414\u043B\u044F \u0432\u0445\u043E\u0434\u0443 \u0432 \u0433\u0440\u0443\u043F\u043E\u0432\u0438\u0439 \u0447\u0430\u0442 \u043F\u043E\u0442\u0440\u0456\u0431\u0435\u043D \u043F\u0430\u0440\u043E\u043B\u044C -message.groupchat.registered.member = \u0423\u0441\u043F\u0456\u0448\u043D\u043E \u0437\u0430\u0440\u0435\u0454\u0441\u0442\u0440\u043E\u0432\u0430\u043D\u043E {0} -message.search.for.history = \u041F\u043E\u0448\u0443\u043A \u043C\u0438\u043D\u0443\u043B\u0438\u0445 \u0440\u043E\u0437\u043C\u043E\u0432 -message.search.period.month.one = \u043E\u0434\u0438\u043D \u043C\u0456\u0441\u044F\u0446\u044C \u043D\u0430 \u0441\u0442\u043E\u0440\u0456\u043D\u043A\u0443 -message.search.period.year.one = \u043E\u0434\u0438\u043D \u0440\u0456\u043A \u043D\u0430 \u0441\u0442\u043E\u0440\u0456\u043D\u043A\u0443 -message.search.period.none = \u0432\u0441\u0456 \u043D\u0430 \u043E\u0434\u043D\u0456\u0439 \u0441\u0442\u043E\u0440\u0456\u043D\u0446\u0456 -message.search.page.timeperiod = \u0412\u0438\u0431\u0435\u0440\u0438 \u043F\u0440\u043E\u043C\u0456\u0436\u043E\u043A \u0447\u0430\u0441\u0443 \u0434\u043B\u044F \u0432\u0456\u0434\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u044C -message.search.page.counter = \u041F\u043E\u0442\u043E\u0447\u043D\u0438\u0439 \u043D\u043E\u043C\u0435\u0440 \u0441\u0442\u043E\u0440\u0456\u043D\u043A\u0438 \u0456 \u043A\u0456\u043B\u044C\u043A\u0456\u0441\u0442\u044C \u0443\u0441\u0456\u0445 \u0441\u0442\u043E\u0440\u0456\u043D\u043E\u043A -message.search.page.right = \u043D\u0430 \u043E\u0434\u043D\u0443 \u0441\u0442\u043E\u0440\u0456\u043D\u043A\u0443 \u0432\u043F\u0435\u0440\u0435\u0434 -message.search.page.left = \u043D\u0430 \u043E\u0434\u043D\u0443 \u0441\u0442\u043E\u0440\u0456\u043D\u043A\u0443 \u043D\u0430\u0437\u0430\u0434 - -status.away = \u0412\u0456\u0434\u0456\u0439\u0448\u043E\u0432 -status.custom.messages = \u041A\u043B\u0456\u0454\u043D\u0442\u0441\u044C\u043A\u0456 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F -status.do.not.disturb = \u0414\u0430\u0439\u0442\u0435 \u0441\u043F\u043E\u043A\u0456\u0439 -status.extended.away = \u0434\u0430\u0432\u043D\u043E \u0432\u0456\u0434\u0456\u0439\u0448\u043E\u0432 -status.free.to.chat = \u0412\u0456\u043B\u044C\u043D\u0438\u0439 \u0434\u043B\u044F \u0441\u043F\u0456\u043B\u043A\u0443\u0432\u0430\u043D\u043D\u044F -status.on.phone = \u041D\u0430 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0456 -status.online = \u041D\u0430 \u0437\u0432'\u044F\u0437\u043A\u0443 -status.pending = \u0412 \u043E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u043D\u0456 -status.invisible = \u041F\u0440\u0438\u0445\u043E\u0432\u0430\u043D\u0438\u0439 -status.offline = \u041E\u0444\u043B\u0430\u0439\u043D - -tab.available.plugins = \u041C\u043E\u0436\u043B\u0438\u0432\u0456 \u0434\u043E\u0434\u0430\u0442\u043A\u0438 -tab.avatar = \u0417\u043D\u0430\u0447\u043E\u043A -tab.business = \u0411\u0456\u0437\u043D\u0435\u0441 -tab.conferences = \u041A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0457 -tab.contacts = \u041A\u043E\u043D\u0442\u0430\u043A\u0442\u0438 -tab.general = \u0417\u0430\u0433\u0430\u043B\u044C\u043D\u0435 -tab.home = \u0414\u0456\u043C -tab.installed.plugins = \u0412\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u0456 \u0434\u043E\u0434\u0430\u0442\u043A\u0438 -tab.deactivated.plugins = \u0414\u0435\u0430\u043A\u0442\u0438\u0432\u043E\u0432\u0430\u043D\u0456 \u0434\u043E\u0434\u0430\u0442\u043A\u0438 -tab.personal = \u041E\u0441\u043E\u0431\u0438\u0441\u0442\u0435 -tab.proxy = \u041F\u0440\u043E\u043A\u0441\u0456 -tab.sso = SSO -tab.pki = PKI - -title.about = \u041F\u0440\u043E \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u0443 -title.password.required = \u041F\u043E\u0442\u0440\u0456\u0431\u0435\u043D \u043F\u0430\u0440\u043E\u043B\u044C -title.task.notification = \u0421\u043F\u043E\u0432\u0456\u0449\u0435\u043D\u043D\u044F \u043F\u0440\u043E \u0437\u0430\u0432\u0434\u0430\u043D\u043D\u044F -title.client.logs = \u0416\u0443\u0440\u043D\u0430\u043B \u043A\u043B\u0456\u0454\u043D\u0442\u0430 -title.advanced.connection.preferences = \u0414\u043E\u0434\u0430\u0442\u043A\u043E\u0432\u0456 \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u0437\u0432'\u044F\u0437\u043A\u0443 -title.account.create.registration = \u0420\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044F -title.bookmarks = \u0417\u0430\u043A\u043B\u0430\u0434\u043A\u0438 -title.account.created = \u0421\u0442\u0432\u043E\u0440\u0435\u043D\u043E \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 -title.add.contact = \u0414\u043E\u0434\u0430\u0442\u0438 \u043A\u043E\u043D\u0442\u0430\u043A\u0442 -title.add.contact.group = \u0414\u043E\u0434\u0430\u0442\u0438 \u0433\u0440\u0443\u043F\u0443 \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u0456\u0432 -title.add.new.group = \u0414\u043E\u0434\u0430\u0442\u0438 \u043D\u043E\u0432\u0443 \u0433\u0440\u0443\u043F\u0443 -title.add.search.service = \u0414\u043E\u0434\u0430\u0442\u0438 \u043F\u043E\u0448\u0443\u043A\u043E\u0432\u0443 \u0441\u043B\u0443\u0436\u0431\u0443 -title.add.to.roster = \u0414\u043E\u0434\u0430\u0442\u0438 \u0434\u043E \u0441\u043F\u0438\u0441\u043A\u0443 -title.address = \u0410\u0434\u0440\u0435\u0441\u0430 -title.advanced.connection.sso = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u043D\u043D\u044F \u043E\u0434\u0438\u043D\u0430\u0440\u043D\u043E\u0457 \u043F\u0456\u0434\u043F\u0438\u0441\u043A\u0438 (SSO) -title.advanced.connection.usesso = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u043D\u043D\u044F \u043E\u0434\u0438\u043D\u0430\u0440\u043D\u043E\u0457 \u043F\u0456\u0434\u043F\u0438\u0441\u043A\u0438 \u0447\u0435\u0440\u0435\u0437 GSSAPI -title.advanced.connection.sso.account = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u043D\u043D\u044F \u043B\u043E\u043A\u0430\u043B\u044C\u043D\u043E\u0433\u043E \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 "{0}" \u0434\u043B\u044F \u0432\u0445\u043E\u0434\u0443 \u043D\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 -title.advanced.connection.sso.unable = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437'\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u044E\u0447\u0438 \u043E\u0434\u0438\u043D\u0430\u0440\u043D\u0443 \u043F\u0456\u0434\u043F\u0438\u0441\u043A\u0443. \u0411\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430 \u043F\u0435\u0440\u0435\u0432\u0456\u0440 \u0441\u0435\u0440\u0432\u0435\u0440\u043D\u0456 \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F -title.advanced.connection.sso.noprincipal = \u0421\u043F\u0430\u0440\u043A \u043D\u0435 \u043C\u043E\u0436\u0435 \u0437\u043D\u0430\u0439\u0442\u0438\u043E\u0441\u043D\u043E\u0432\u043D\u0456 \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u0434\u043B\u044F \u043E\u0434\u0438\u043D\u0430\u0440\u043D\u043E\u0457 \u043F\u0456\u0434\u043F\u0438\u0441\u043A\u0438. -title.alert = \u0417\u0430\u0441\u0442\u043E\u0440\u043E\u0433\u0430 -title.appearance = \u0412\u0438\u0433\u043B\u044F\u0434 -title.appearance.preferences = \u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F -title.available.transports = \u041C\u043E\u0436\u043B\u0438\u0432\u0456 \u0442\u0440\u0430\u043D\u0441\u043F\u043E\u0440\u0442\u0438 -title.broadcast.message = \u0422\u0440\u0430\u043D\u0441\u043B\u044E\u0432\u0430\u043D\u043D\u044F \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F -title.browse.conference.services = \u0412\u0438\u0431\u0456\u0440 \u0441\u043B\u0443\u0436\u0431\u0438 \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0439 -title.browse.room.service = \u0412\u0438\u0431\u0456\u0440 \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0439 - {0} -title.cancelled = \u0412\u0456\u0434\u0445\u0438\u043B\u0435\u043D\u043E -title.change.nickname = \u0417\u043C\u0456\u043D\u0438\u0442\u0438 \u0456\u043C'\u044F -title.change.subject = \u0417\u043C\u0456\u043D\u0438\u0442\u0438 \u0442\u0435\u043C\u0443 -title.chat = \u0427\u0430\u0438 -title.choose.directory = \u0412\u0438\u0431\u0456\u0440 \u0442\u0435\u043A\u0438 -title.choose.incoming.sound = \u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0437\u0432\u0443\u043A -title.choose.offline.sound = \u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0437\u0432\u0443\u043A -title.choose.outgoing.sound = \u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0437\u0432\u0443\u043A -title.conference.invitation = \u0417\u0430\u043F\u0440\u043E\u0448\u0435\u043D\u043D\u044F \u0434\u043E \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0457 -title.conference.rooms = \u041A\u0456\u043C\u043D\u0430\u0442\u0438 \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0439 -title.configure.chat.room = \u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F -title.configure.room = \u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u043A\u0456\u043C\u043D\u0430\u0442\u0438 -title.confirmation = \u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043D\u044F -title.create.new.account = \u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043D\u043E\u0432\u0438\u0439 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 -title.create.or.bookmark.room = \u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0430\u0431\u043E \u0437\u0430\u043A\u043B\u0430\u0441\u0442\u0438 \u043A\u0456\u043C\u043D\u0430\u0442\u0430 -title.create.or.join = \u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0430\u0431\u043E \u043F\u0440\u0438\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C -title.create.problem = \u041D\u0435\u0432\u0434\u0430\u0447\u0430 \u0441\u0442\u0432\u043E\u0440\u0435\u043D\u043D\u044F -title.delete.file = \u0421\u043F\u0440\u0430\u0432\u0434\u0456 \u0445\u043E\u0447\u0435\u0448 \u0432\u0438\u043B\u0443\u0447\u0438\u0442\u0438 \u0446\u0435\u0439 \u0444\u0430\u0439\u043B? -title.dial.phone = \u0414\u0417\u0432\u043E\u043D\u0438\u0442\u0438 -title.disable.transport = \u0412\u0438\u043B\u0443\u0447\u0438\u0442\u0438 \u0432\u0456\u0434\u043E\u043C\u043E\u0441\u0442\u0456 -title.download.complete = \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u0437\u0430\u043A\u0456\u043D\u0447\u0435\u043D\u043E -title.downloading.im.client = \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u043A\u043B\u0456\u0454\u043D\u0442 \u0434\u043B\u044F \u0456\u043D\u0442\u0435\u0440\u043D\u0435\u0442-\u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u044C -title.downloads = \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F -title.edit.custom.message = \u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F -title.edit.profile = \u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 \u0432\u0456\u0434\u043E\u043C\u043E\u0441\u0442\u0456 \u043F\u0440\u043E\u0444\u0430\u0439\u043B\u0443 -title.enter.reason = \u0412\u0432\u0435\u0434\u0438 \u043F\u0440\u0438\u0447\u0438\u043D\u0443 -title.error = \u041F\u043E\u043C\u0438\u043B\u043A\u0430 -title.error.couldnt.open.file = \u043D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0432\u0456\u0434\u0440\u0438\u0442\u0438 \u0444\u0430\u0439\u043B -title.error.delete.file = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0432\u0438\u043B\u0443\u0447\u0438\u0442\u0438 \u0444\u0430\u0439\u043B -title.error.find.app = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437\u043D\u0430\u0439\u0442\u0438 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0434\u043D\u0438\u0439 \u0434\u043E\u0434\u0430\u0442\u043E\u043A -title.error.rename.file = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u043F\u0435\u0440\u0435\u0439\u043C\u0435\u043D\u0443\u0432\u0430\u0442\u0438 \u0444\u0430\u0439\u043B -title.file = \u0424\u0430\u0439\u043B -title.filesize = \u0420\u043E\u0437\u043C\u0456\u0440 -title.file.exists = \u0424\u0430\u0439\u043B \u0456\u0441\u043D\u0446\u0454 -title.file.transfer = \u041F\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0444\u0430\u0439\u043B\u0443 -title.file.transfer.preferences = \u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0444\u0430\u0439\u043B\u0443 -title.find.conference.service = \u0417\u043D\u0430\u0439\u0442\u0438 \u0441\u043B\u0443\u0436\u0431\u0443 \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0439 -title.find.contacts = \u0417\u043D\u0430\u0439\u0442\u0438 \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u0438 -title.gadugadu.registration = \u0412\u0456\u0440\u0447\u0456 \u0433\u0440\u0430\u043C\u043E\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0430 \u0490\u0430\u0434\u0443\u0490\u0430\u0434\u0443 -title.general.media = \u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u0441\u0435\u0440\u0435\u0434\u043E\u0432\u0438\u0449\u0430 -title.general.chat.settings = \u0417\u0430\u0433\u0430\u043B\u044C\u043D\u0456 \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F -title.group.chat = \u0413\u0440\u0443\u043F\u043E\u0432\u0438\u0439 \u0447\u0430\u0442 -title.group.chat.settings = \u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u0433\u0440\u0443\u043F\u043E\u0432\u043E\u0433\u043E \u0447\u0430\u0442\u0443 -title.gtalk.registration = GTalk \u0432\u0456\u0440\u0447\u0456 \u0433\u0440\u0430\u043C\u043E\u0442\u0438 -title.history.for = \u041C\u0438\u043D\u0443\u043B\u0456 \u0440\u043E\u0437\u043C\u043E\u0432\u0438 \u0437 {0} -title.icq.registration = ICQ \u0432\u0456\u0440\u0447\u0456 \u0433\u0440\u0430\u043C\u043E\u0442\u0438 -title.irc.registration = IRC \u0432\u0456\u0440\u0447\u0456 \u0433\u0440\u0430\u043C\u043E\u0442\u0438 -title.aim.registration = AIM \u0432\u0456\u0440\u0447\u0456 \u0433\u0440\u0430\u043C\u043E\u0442\u0438 -title.sametime.registration = Sametime \u0432\u0456\u0440\u0447\u0456 \u0433\u0440\u0430\u043C\u043E\u0442\u0438 -title.facebook.registration = \u0412\u0456\u0440\u0447\u0456 \u0433\u0440\u0430\u043C\u043E\u0442\u0438 \u0424\u0435\u0439\u0441\u0431\u0443\u043A\u0430 -title.myspace.registration = MySpace \u0432\u0456\u0440\u0447\u0456 \u0433\u0440\u0430\u043C\u043E\u0442\u0438 -title.incoming.call = \u0412\u0445\u0456\u0434\u043D\u0438\u0439 \u0434\u0437\u0432\u0456\u043D\u043E\u043A -title.input.fileexplorer = \u0412\u0432\u0435\u0434\u0438 \u043D\u0430\u0437\u0432\u0443 \u0442\u0432\u043E\u0433\u043E \u0444\u0430\u0439\u043B\u043E\u0432\u043E\u0433\u043E \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430: -title.input.newname = \u0412\u0432\u0435\u0434\u0438 \u043D\u043E\u0432\u0435 \u0456\u043C'\u044F: -title.input.openwith = \u0412\u0432\u0435\u0434\u0438 \u043D\u0430\u0437\u0432\u0443 \u0434\u043E\u0434\u0430\u0442\u043A\u0430 \u0434\u043B\u044F \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u043D\u043D\u044F: -title.invite.to.conference = \u0417\u0430\u043F\u0440\u043E\u0441\u0438\u0442\u0438 \u0434\u043E \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0457 -title.jabber.browser = \u0411\u0440\u0430\u0443\u0437\u0435\u0440 -title.join.conference.room = \u041F\u0440\u0438\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044C \u0434\u043E \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0457 -title.last.activity = \u041E\u0441\u0442\u0430\u043D\u043D\u044F \u0430\u043A\u0442\u0438\u0432\u043D\u0456\u0441\u0442\u044C -title.login = \u041B\u043E\u0433\u0456\u043D -title.login.error = \u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u0432\u0445\u043E\u0434\u0443 -title.login.settings = \u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u0432\u0445\u043E\u0434\u0443 -title.login.no.account = \u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0432\u0438\u0437\u043D\u0430\u0447\u0438\u0442\u0438 -title.lookup.profile = \u041F\u043E\u0448\u0443\u043A \u043F\u0440\u043E\u0444\u0430\u0439\u043B\u0443 -title.msn.registration = MSN \u0432\u0456\u0440\u0447\u0456 \u0433\u0440\u0430\u043C\u043E\u0442\u0438 -title.name = \u0406\u043C'\u044F -title.new.client.available = \u0414\u043E\u0441\u0442\u0443\u043F\u043D\u0438\u0439 \u043D\u043E\u0432\u0438\u0439 \u043A\u043B\u0456\u0454\u043D\u0442 -title.new.roster.group = \u041D\u043E\u0432\u0438\u0439 \u0441\u043F\u0438\u0441\u043E\u043A \u0433\u0440\u0443\u043F -title.new.version.available = \u0414\u043E\u0441\u0442\u0443\u043F\u043D\u0430 \u043D\u043E\u0432\u0430 \u0432\u0435\u0440\u0441\u0456\u044F -title.no.updates = \u041D\u0435\u043C\u0430 \u043E\u043D\u043E\u0432\u043B\u0435\u043D\u044C -title.notes = \u041D\u043E\u0442\u0430\u0442\u043A\u0438 -title.notification = \u0421\u043F\u043E\u0432\u0456\u0449\u0435\u043D\u043D\u044F -title.notifications = \u0421\u043F\u043E\u0432\u0456\u0449\u0435\u043D\u043D\u044F -title.occupants = \u041C\u0435\u0448\u043A\u0430\u043D\u0446\u0456 -title.on.the.phone = \u041D\u0430 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0456 -title.password = \u041F\u0430\u0440\u043E\u043B\u044C -title.passwords.no.match = \u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u0456 -title.person.search = \u041F\u043E\u0448\u0443\u043A \u043E\u0441\u0456\u0431 -title.plugins = \u0414\u043E\u0434\u0430\u0442\u043A\u0438 -title.preferences = \u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F -title.profile.information = \u0412\u0456\u0434\u043E\u043C\u043E\u0441\u0442\u0456 \u043F\u0440\u043E\u0444\u0430\u0439\u043B\u0443 -title.profile.not.found = \u041F\u0440\u043E\u0444\u0430\u0439\u043B \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E -title.qq.registration = \u0420\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044F \u0432 QQ -title.register.account = \u0420\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044F \u043D\u043E\u0432\u043E\u0433\u043E \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 -title.registration.error = \u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u0440\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u0457 -title.reminder = \u041D\u0430\u0433\u0430\u0434\u0443\u0432\u0430\u0447 -title.rename.roster.group = \u041F\u0435\u0440\u0435\u0439\u043C\u0435\u043D\u0443\u0432\u0430\u0442\u0438 \u0441\u043F\u0438\u0441\u043E\u043A -title.room.destroyed = \u041A\u0456\u043C\u043D\u0430\u0442\u0443 \u0437\u043D\u0438\u0449\u0435\u043D\u043E -title.room.information = \u0406\u043D\u0444\u043E \u043F\u0440\u043E \u043A\u0456\u043C\u043D\u0430\u0442\u0443 -title.roster = \u0421\u043F\u0438\u0441\u043E\u043A -title.select.file.to.send = \u0412\u0438\u0431\u0435\u0440\u0438 \u0444\u0430\u0439\u043B\u0438, \u0449\u043E\u0431 \u043D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438 -title.set.status.message = \u0412\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0438 \u0441\u0442\u0430\u0442\u0443\u0441 -title.simple.registration = SIMPLE \u0440\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044F -title.sound.preferences = \u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u0437\u0432\u0443\u043A\u0443 -title.sounds = \u0417\u0432\u0443\u043A\u0438 -title.spark.preferences = \u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F -title.start.chat = \u0420\u043E\u0437\u043F\u043E\u0447\u0430\u0442\u0438 \u0447\u0430\u0442 -title.status.message = \u0421\u0442\u0430\u0442\u0443\u0441 -title.tasks = \u0417\u0430\u0432\u0434\u0430\u043D\u043D\u044F -title.transports = \u0422\u0440\u0430\u043D\u0441\u043F\u043E\u0440\u0442\u0438 -title.tray.information = \u0406\u043D\u0444\u043E \u043F\u0440\u043E \u043B\u043E\u0442\u043E\u043A -title.upgrading.client = \u043E\u043D\u043E\u0432\u0438\u0442\u0438 \u043A\u043B\u0456\u0454\u043D\u0442\u0430 -title.version.and.time = \u0412\u0435\u0440\u0441\u0456\u044F \u0456 \u0447\u0430\u0441 -title.view.bookmarks = \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0437\u0430\u043A\u043B\u0430\u0434\u043A\u0438 -title.view.profile.for = \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u043F\u0440\u043E\u0444\u0430\u0439\u043B {0} -title.view.room.information = \u041F\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0456\u043D\u0444\u043E \u043A\u0456\u043C\u043D\u0430\u0442\u0438 -title.waiting.to.call = \u041E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u043D\u044F \u0434\u0437\u0432\u0456\u043D\u043A\u0430 -title.xmpp.registration = XMPP \u0440\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044F -title.yahoo.registration = Yahoo \u0440\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044F -title.appearance.showVCards = \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 &VCards \u0432 \u0441\u043F\u0438\u0441\u043A\u0443 \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u0456\u0432 -title.subscription.request = \u0417\u0430\u043F\u0438\u0442 \u043F\u0456\u0434\u043F\u0438\u0441\u043A\u0438 - -tooltip.place.a.call = \u0414\u0417\u0432\u0456\u043D\u043E\u043A \u0434\u043E \u0446\u0456\u0454\u0457 \u043E\u0441\u043E\u0431\u0438 -tooltip.appearance = \u0417\u043C\u0456\u043D\u0438\u0442\u0438 \u0432\u0438\u0433\u043B\u044F\u0434 \u0440\u043E\u0437\u043C\u043E\u0432\u0438 -tooltip.file.transfer = \u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0444\u0430\u0439\u043B\u0456\u0432 -tooltip.notifications = \u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u0441\u043F\u043E\u0432\u0456\u0449\u0435\u043D\u044C \u043F\u0440\u043E \u0432\u0445\u0456\u0434\u043D\u0456 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F -tooltip.place.voice.call = \u0414\u0417\u0432\u0456\u043D\u043E\u043A \u0434\u043E \u0446\u044C\u043E\u0433\u043E \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 -tooltip.send.email = \u041D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438 \u043D\u0430 \u0435-\u0430\u0434\u0440\u0435\u0441\u0443 -tooltip.start.chat = \u0420\u043E\u0437\u043F\u043E\u0447\u0430\u0442\u0438 \u0440\u043E\u0437\u043C\u043E\u0432\u0443 -tooltip.view.changelog = \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0436\u0443\u0440\u043D\u0430\u043B \u0437\u043C\u0456\u043D -tooltip.view.history = \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u043C\u0438\u043D\u0443\u043B\u0456 \u0437\u043C\u0456\u043D\u0438 -tooltip.view.readme = \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 readme - -tree.conference.services = \u0421\u043B\u0443\u0436\u0431\u0438 \u043A\u043E\u043D\u0444\u0435\u0440\u0435\u043D\u0446\u0456\u0439 -tree.users.in.room = \u041A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456 \u0432 \u043A\u0456\u043C\u043D\u0430\u0442\u0456 - -lookandfeel.select = \u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0440\u0435\u0436\u0438\u043C \u0411\u0430\u0447\u0438\u0442\u0438 & \u0412\u0456\u0434\u0447\u0443\u0432\u0430\u0442\u0438 -lookandfeel.change.now = \u0417\u043C\u0456\u043D\u0438\u0442\u0438 \u0437\u0430\u0440\u0430\u0437 -lookandfeel.tooltip.restart.no = \u041D\u0435 \u043F\u043E\u0442\u0440\u0456\u0431\u043D\u043E \u043F\u0435\u0440\u0435\u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438 -lookandfeel.tooltip.restart.yes = \u0429\u043E\u0431 \u043F\u0435\u0440\u0435\u043A\u043B\u044E\u0447\u0438\u0442\u0438\u0441\u044C \u0432 \u0440\u0435\u0436\u0438\u043C \u0411\u0430\u0447\u0438\u0442\u0438 & \u0412\u0456\u0434\u0447\u0443\u0432\u0430\u0442\u0438 \u043D\u0430\u0442\u0438\u0441\u043D\u0438 \u0437\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0456 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438 \u0421\u043F\u0430\u0440\u043A. -lookandfeel.color.label = \u0411\u0430\u0440\u0432\u0438 -lookandfeel.color.red = \u0427\u0435\u0440\u0432\u043E\u043D\u0438\u0439 -lookandfeel.color.green = \u0417\u0435\u043B\u0435\u043D\u0438\u0439 -lookandfeel.color.blue = \u0411\u043B\u0430\u043A\u0438\u0442\u043D\u0438\u0439 -lookandfeel.color.opacity = \u0422\u0443\u043C\u0430\u043D\u043D\u0456\u0441\u0442\u044C -lookandfeel.color.saved = \u0411\u0430\u0440\u0432\u0438 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043D\u043E - -##\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u043F\u0440\u0438\u0432\u0430\u0442\u043D\u043E\u0441\u0442\u0456 -privacy.title.preferences = \u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u043F\u0440\u0438\u0432\u0430\u0442\u043D\u043E\u0441\u0442\u0456 -privacy.title.panel = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438 \u043F\u0440\u0430\u0432\u0443 \u043A\u043D\u043E\u043F\u043A\u0443 \u043C\u0430\u043D\u0456\u043F\u0443\u043B\u044F\u0442\u043E\u0440\u0430 -privacy.label.iq.desc = \u0417\u0430\u043F\u0438\u0442 -privacy.label.pin.desc = \u041F\u0440\u0438\u0441\u0443\u0442\u043D\u0456\u0441\u0442\u044C \u0432 -privacy.label.pout.desc = \u041F\u0440\u0438\u0441\u0443\u0442\u043D\u0456\u0441\u0442\u044C \u0437\u0430 \u043C\u0435\u0436\u0430\u043C\u0438 -privacy.label.msg.desc = \u041F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F -privacy.border.information = \u0406\u043D\u0444\u043E \u043F\u0440\u0438\u0432\u0430\u0442\u043D\u043E\u0441\u0442\u0456 -privacy.label.information = \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438 \u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442\u043D\u0435 \u043C\u0435\u043D\u044E \u0434\u043B\u044F \u0434\u043E\u0434\u0430\u0432\u0430\u043D\u043D\u044F \u0441\u043F\u0438\u0441\u043A\u0456\u0432 \u0442\u0430 \u0456\u043D. -privacy.root.node = \u0421\u043F\u0438\u0441\u043A\u0438 \u043F\u0440\u0438\u0432\u0430\u0442\u043D\u043E\u0441\u0442\u0456 -privacy.label.preferences = \u0414\u043E\u0434\u0430\u0442\u043E\u043A \u0434\u043B\u044F \u043F\u0440\u0438\u0432\u0430\u0442\u043D\u043E\u0441\u0442\u0456 -pricacy.tooltip.preferences = \u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u043F\u0440\u0438\u0432\u0430\u0442\u043D\u043E\u0441\u0442\u0456 -privacy.label.list.is.active = \u0410\u043A\u0442\u0438\u0432\u043D\u0438\u0439 \u0441\u043F\u0438\u0441\u043E\u043A: -privacy.label.list.is.default = \u0421\u0442\u0430\u043D\u0434\u0430\u0440\u043D\u0438\u0439 \u0441\u043F\u0438\u0441\u043E\u043A: -privacy.border.block = \u0411\u043B\u043E\u043A -privacy.pick.one.or.more = \u0414\u043E\u0434\u0430\u0442\u0438 \u043A\u0456\u043B\u044C\u043A\u0430 \u043E\u0431'\u0454\u043A\u0442\u0456\u0432 \u0432 \u0441\u043F\u0438\u0441\u043E\u043A -privacy.title.add.picker = \u0414\u043E\u0434\u0430\u0442\u0438 \u0432 \u0441\u043F\u0438\u0441\u043E\u043A -privacy.node.contacts = \u041A\u043E\u043D\u0442\u0430\u043A\u0442\u0438 -privacy.node.groups = \u0413\u0440\u0443\u043F\u0438 -privacy.menu.add.contacts = \u0414\u043E\u0434\u0430\u0442\u0438 \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u0438 \u0432 \u0441\u043F\u0438\u0441\u043E\u043A -privacy.menu.add.groups = \u0414\u043E\u0434\u0430\u0442\u0438 \u0433\u0440\u0443\u043F\u0438 \u0432 \u0441\u043F\u0438\u0441\u043E\u043A -privacy.menu.add.rem.items = \u0412\u0438\u043B\u0443\u0447\u0438\u0442\u0438 {0} \u0437\u0456 \u0441\u043F\u0438\u0441\u043A\u0443 -privacy.menu.remove = \u0412\u0438\u043B\u0443\u0447\u0438\u0442\u0438 -privacy.menu.activate.list = \u0410\u043A\u0442\u0438\u0432\u0443\u0432\u0430\u0442\u0438 -privacy.menu.default.list = \u0412\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0438 \u044F\u043A \u0441\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u043D\u0438\u0439 -privacy.menu.add.list = \u0414\u043E\u0434\u0430\u0442\u0438 \u0441\u043F\u0438\u0441\u043E\u043A -privacy.menu.remove.list = \u0412\u0438\u043B\u0443\u0447\u0438\u0442\u0438 \u0441\u043F\u0438\u0441\u043E\u043A -privacy.dialog.add.list = \u0412\u0432\u0435\u0434\u0438 \u043D\u0430\u0437\u0432\u0443 \u0441\u043F\u0438\u0441\u043A\u0443 -privacy.dialog.rem.list = \u0421\u043F\u0440\u0430\u0432\u0434\u0456 \u0445\u043E\u0447\u0435\u0448 \u0432\u0438\u043B\u0443\u0447\u0438\u0442\u0438 {0}? -privacy.status.menu.entry = \u041F\u0440\u0438\u0432\u0430\u0442\u043D\u0456 \u0441\u043F\u0438\u0441\u043A\u0438 -privacy.name.for.default.list = \u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0442 -privacy.button.no.list.selected = \u041D\u0435\u043C\u0430 \u0432\u0438\u0431\u0440\u0430\u043D\u0438\u0445 \u0441\u043F\u0438\u0441\u043A\u0456\u0432 -privacy.menuitem.deactivate.current.list = \u0414\u0435\u0430\u043A\u0442\u0438\u0432\u0443\u0432\u0430\u0442\u0438 {0} -privacy.label.not.supported = \u0421\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454 \u043F\u0440\u0438\u0432\u0430\u0442\u043D\u0456 \u0441\u043F\u0438\u0441\u043A\u0438. - -##Stunfallback in media settings -stun.border.label = STUN fallback server -stun.server.addr = STUN \u0441\u0435\u0440\u0432\u0435\u0440: -stun.server.port = STUN \u043F\u043E\u0440\u0442: -composing = {0} \u043F\u0438\u0448\u0435... -paused = {0} \u043F\u0435\u0440\u0435\u0441\u0442\u0430\u0432 \u043F\u0438\u0441\u0430\u0442\u0438 -active = {0} \u0437\u0432\u0435\u0440\u0442\u0430\u0454 \u0443\u0432\u0430\u0433\u0443 -inactive = {0} \u0440\u043E\u0431\u0438\u0442\u044C \u0449\u043E\u0441\u044C \u0456\u043D\u0435 -gone = {0} \u0437\u0430\u0439\u043D\u044F\u0442\u0438\u043C \u0447\u0438\u043C\u043E\u0441\u044C \u0456\u043D\u0448\u0438\u043C - -#!# -action.viewlog=\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0436\u0443\u0440\u043D\u0430\u043B -dialog.confirm.to.reveal.visibility.title=\u0422\u0438 \u0432\u043F\u0435\u0432\u043D\u0435\u043D\u0438\u0439? -dialog.confirm.to.reveal.visibility.msg=\u042F\u043A\u0449\u043E \u0442\u0438 \u043F\u0440\u043E\u0434\u043E\u0432\u0436\u0438\u0448, \u0442\u0432\u043E\u044F \u043D\u0435\u0432\u0438\u0434\u0438\u043C\u0456\u0441\u0442\u044C \u0431\u0443\u0434\u0435 \u0440\u043E\u0437\u043A\u0440\u0438\u0442\u0430 -dialog.confirm.close.all.conferences.if.invisible.msg=\u042F\u043A\u0449\u043E \u0442\u0438 \u043F\u0440\u043E\u0434\u043E\u0432\u0436\u0438\u0448, \u0432\u0441\u0456 \u043A\u0456\u043C\u043D\u0430\u0442\u0438 \ No newline at end of file diff --git a/src/resources/i18n/spark_i18n_zh_CN.properties b/src/resources/i18n/spark_i18n_zh_CN.properties deleted file mode 100644 index b6dbfd0c5..000000000 --- a/src/resources/i18n/spark_i18n_zh_CN.properties +++ /dev/null @@ -1,1094 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.0.1 -## Added key: 'message.restart.spark.changes' -## Added key: 'message.enter.icq' -## Added key: 'title.icq.registration' -## Added key: 'button.quit' -## -## -## -## 2.0.2 -## Added key: 'button.new' -## Added key: 'label.group' -## Added key: 'label.jabber.id' -## Added key: 'label.enter.group.name' -## Added key: 'title.new.roster.group' -## Added key: 'title.add.contact.group' -## Added key: 'message.add.contact.to.list' -## Added key: 'title.add.contact' -## Added key: 'tab.conferences' -## Added key: 'message.autenticating' -## Added key: 'title.file.transfer.preferences' -## Added key: 'menuitem.about' -## Added key: 'message.invalid.status' -## Added key: 'message.cannot.add.contact.to.shared.group -## Added key: 'message.specify.contact.jid' -## Added key: 'message.invalid.jid.error' -## Added key: 'message.specify.group' -## Added key: 'add' -## -## -## -## 2.0.5 -## Added key: 'Broadcast' -## Added key: 'label.user.on.public.network' -## Added key: 'label.network' -## -## -## 2.0.6 -## Added key: 'button.add.user' -## Added key: 'menuitem.sign.in' -## Added key: 'menuitem.sign.out' -## Added key: 'menuitem.sign.in.at.login' -## Added key: 'menuitem.enter.login.information' -## Added key: 'menuitem.delete.login.information' -## Added key: 'button.save' -## -## -## 2.5 -## Added key: 'button.start.chat' -## Added key: 'button.send.email' -## Added key: 'available' -## Added key: 'checkbox.tabs.on.top' -## Added key: 'user.has.signed.in' -## Added key: 'user.has.signed.off' -## Added key: 'label.unable.to.add.contact' -## Added key: 'label.conflict.error' -## Added key: 'message.room.creation.error' -## Added key: 'checkbox.allow.buzz' -## Added key: 'message.disconnected.group.chat.error' -## Added key: 'menuitem.show.offline.group' -## Added key: 'menuitem.move.to' -## Added key: 'menuitem.copy.to' -## Added key: 'label.message.style' -## Added key: 'label.emoticons' -## Added key: 'checkbox.enable.emoticons' -## Added key: 'message.unable.to.retrieve.last.activity' -## Added key: 'checkbox.use.system.look.and.feel' -## -## 2.5.2 -## Added key: 'tooltip.place.voice.call' -## Added key: 'message.buzz.alert.notification' -## Added key: 'message.buzz.sent' -## -## 2.5.2 -## Added key: 'menuitem.user.guide' -## -## -## -## 2.5.7 -## Added key: 'menuitem.languages' -## Added key: 'message.restart.required' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'message.send.to.these.people' -## Added key: 'message' -## Added key: 'message.normal' -## Added key: 'message.alert.notify' -## -## 2.5.8 -## Added key: 'message.enter.simple' -## Added key: 'message.enter.irc' -## Added key: 'message.enter.gadugadu' -## Added key: 'title.simple.registration' -## Added key: 'title.irc.registration' -## Added key: 'title.gadugadu.registration' -## Added key: 'message.username.error' -## Added key: 'message.password.error' -## Added key: 'message.nickname.error' -## -## 2.5.9 -## Added key: 'message.gateway.username.error. -## Added key: 'message.gateway.password.error. -## Added key: 'message.gateway.nickname.error. -## Added key: 'answer' -## Added key: 'online' -## Added key: 'online' -## Added key: 'offline' -## Added key: 'participants' -## Added key: 'unfiled' -## Added key: 'while.offline' -## Added key: 'action.clear' -## Added key: 'action.copy ' -## Added key: 'action.cut' -## Added key: 'action.paste' -## Added key: 'action.print' -## Added key: 'action.save' -## Added key: 'action.select.all' -## Added key: 'button.add2' -## Added key: 'button.copy.to.clipboard' -## Added key: 'button.reconnect2' -## Added key: 'button.tasks.active' -## Added key: 'button.tasks.all' -## Added key: 'button.view.notes' -## Added key: 'button.view.profile' -## Added key: 'button.view.tasklist' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.show.avatars.in.contaclist' -## Added key: 'checkbox.use.compression' -## Added key: 'group.empty' -## Added key: 'group.offline' -## Added key: 'label.add.task' -## Added key: 'label.chatroom.fontsize' -## Added key: 'label.contactlist.fontsize' -## Added key: 'label.due' -## Added key: 'label.show' -## Added key: 'label.timeformat' -## Added key: 'menuitem.dial' -## Added key: 'menuitem.view.logs' -## Added key: 'message.disconnected.shutdown' -## Added key: 'message.invalid.username.password' -## Added key: 'message.no.updates' -## Added key: 'message.reconnect.attempting' -## Added key: 'message.reconnect.failed' -## Added key: 'message.reconnect.wait' -## Added key: 'message.send.picture' -## Added key: 'message.server.unavailable' -## Added key: 'message.unrecoverable.error' -## Added key: 'message.waiting.for.user.to.join' -## Added key: 'status.available' -## Added key: 'status.away' -## Added key: 'status.custom.messages' -## Added key: 'status.do.not.disturb' -## Added key: 'status.extended.away' -## Added key: 'status.free.to.chat' -## Added key: 'status.on.phone' -## Added key: 'status.online' -## Added key: 'status.pending' -## Added key: 'title.about' -## Added key: 'title.appearance' -## Added key: 'title.appearance.preferences' -## Added key: 'title.login.error' -## Added key: 'title.no.updates' -## Added key: 'title.notes' -## Added key: 'title.tasks' -## Added key: 'tooltip.appearance' -## Added key: 'tooltip.file.transfer' -## Added key: 'tooltip.send.email' -## Added key: 'tooltip.start.chat' -## Added key: 'delete.log.permanently' -## Added key: 'delete.permanently' -## Added key: 'label.contactlist.avatarsize' -## Added key: 'title.qq.registration' -## Added key: 'message.enter.qq' -## -## 2.6.0 -## -## Added key: 'apply' -## Added key: 'title.subscription.request' -## Added key: 'label.add.to.roster' -## Added key: 'label.audio.device' -## Added key: 'label.video.device' -## Added key: 'button.re.detect' -## -## 2.6.0 beta 1 -## Added key: 'menuitem.block.contact' -## Added key: 'menuitem.unblock.contact' -## Removed key: 'status.available' -## Added key: 'message.nickname.not.acceptable' -## Added key: 'button.login' -## Added key: 'administrator' -## Added key: 'menuitem.add.groupchat.showrolesinsteadofstatus' -## Added key: 'checkbox.click.single.tray' -## 2.7.0 beta 1 -## Added key: 'message.search.period.month.one' -## Added key: 'message.search.period.year.one' -## Added key: 'message.search.period.none' -## Added key: 'message.search.page.timeperiod' -## Added key: 'message.search.page.counter' -## Added key: 'message.search.page.right' -## Added key: 'message.search.page.left' -## Added key: 'checkbox.sort.asc.history' -## Added key: 'message.file.transfer.dirnull' -## Added key: 'message.file.transfer.nodir' -## Added key: 'message.file.transfer.cantwritedir' -## Added key: 'message.file.transfer.direrror.setdir' - -accept = \u63A5\u53D7 -active = {0} is paying attention -add = \u6DFB\u52A0 -administrator = Administrator -answer = \u56DE\u7B54 -apply = \u5E94\u7528 -available = \u7A7A\u95F2 -broadcast = \u5E7F\u64AD -cancel = \u53D6\u6D88 -close = \u5173\u95ED -create = \u521B\u5EFA -date = \u65E5\u671F -description = \u63CF\u8FF0 -from = \u4ECE -invite = \u9080\u8BF7 -join = \u52A0\u5165 -no = \u5426 -not.registered = \u672A\u6CE8\u518C -occupants = \u5360\u6709\u8005 -offline = \u79BB\u7EBF -online = \u5728\u7EBF -ok = \u786E\u5B9A -open = \u6253\u5F00 -open.folder = \u6253\u5F00\u8D44\u6599\u5939 -participants = \u53C2\u4E0E\u8005 -reject = \u62D2\u7EDD -retry = \u91CD\u8BD5 -room.name = \u623F\u95F4\u540D\u5B57 -save = \u4FDD\u5B58 -refresh = \u5237\u65B0 -subject = \u4E3B\u9898 -unfiled = \u6211\u7684\u8054\u7CFB\u4EBA -use.default = \u4F7F\u7528\u9884\u8BBE -user.has.signed.in = \u5DF2\u767B\u5F55 -user.has.signed.off = \u5DF2\u79BB\u5F00 -while.offline = \u6B63\u79BB\u7EBF -yes = \u662F -action.clear = \u6E05\u9664 -action.copy = \u590D\u5236 -action.cut = \u526A\u5207 -action.paste = \u7C98\u8D34 -action.print = \u6253\u5370 -action.save = \u4FDD\u5B58 -action.select.all = \u5168\u9009 -button.accept = (&A) \u63A5\u53D7 -button.reject = \u62D2\u7EDD -button.add = &Add -button.add.a.contact = (&A) \u6DFB\u52A0\u8054\u7CFB\u4EBA -button.add.bookmark = \u6DFB\u52A0\u4E66\u7B7E -button.add.service = (&A) \u6DFB\u52A0\u670D\u52A1 -button.add.user = (&A) \u6DFB\u52A0\u7528\u6237 -button.add2 = \u589E\u52A0 -button.advanced = (&V) \u9AD8\u7EA7 -button.approve = (&A) \u6279\u51C6 -button.bookmark.room = (&B) \u4E66\u7B7E\u623F\u95F4 -button.browse = (&B) \u6D4F\u89C8\u2026 -button.browse2 = (&R) \u6D4F\u89C8\u2026 -button.browse3 = (&O) \u6D4F\u89C8\u2026 -button.cancel = (&C) \u53D6\u6D88 -button.clear = (&C) \u6E05\u9664 -button.close = (&L) \u5173\u95ED -button.copy.to.clipboard = \u590D\u5236\u5230\u526A\u8D34\u677F -button.create.account = (&C) \u521B\u5EFA\u8D26\u53F7 -button.create.room = (&C) \u521B\u5EFA\u6216\u52A0\u5165\u623F\u95F4 -button.decline = (&D) \u62D2\u7EDD -button.deny = (&D) \u5426\u8BA4 -button.dial.number = (&D) \u62E8\u53F7\u76D8\u6570\u5B57 -button.find = (&F) \u641C\u5BFB -button.join = &Join -button.join.room = (&J) \u52A0\u5165\u9009\u62E9\u7684\u623F\u95F4 -button.login = (&L) \u767B\u5F55 -button.new = (&N) \u6DFB\u52A0 -button.profile = (&P) \u7B80\u4ECB -button.quit = (&Q) \u79BB\u5F00 -button.reconnect = (&R) \u91CD\u65B0\u8FDE\u63A5 -button.reconnect2 = \u91CD\u65B0\u8FDE\u63A5 -button.refresh = (&R) \u5237\u65B0 -button.register = (&R) \u8BB0\u6570\u5668 -button.remove.bookmark = \u79FB\u9664\u4E66\u7B7E -button.roster = (&R) \u8054\u7CFB\u4EBA\u540D\u5355 -button.save = (&S)\u4FDD\u5B58 -button.save.for.future.use = (&S) \u4FDD\u5B58\u4EE5\u5907\u4EE5\u540E\u4F7F\u7528 -button.search = (&S) \u641C\u5BFB -button.send = \u53D1\u9001 -button.send.email = \u7535\u5B50\u90AE\u4EF6 -button.start.chat = \u4EA4\u8C08 -button.tasks.active = \u6D3B\u52A8 -button.tasks.all = \u6240\u6709 -button.unset.file.explorer = \u53D6\u6D88\u6587\u4EF6\u6D4F\u89C8\u5668 -button.update = (&U) \u66F4\u65B0 -button.view.notes = \u67E5\u770B\u8BB0\u4E8B\u672C -button.view.profile = \u67E5\u770B\u5168\u90E8\u6863\u6848 -button.view.tasklist = \u67E5\u770B\u4EFB\u52A1\u5217\u8868 -button.re.detect = \u91CD\u65B0\u68C0\u6D4B -checkbox.allow.buzz = (&Z)\u5141\u8BB8\u7528\u6237\u7ED9\u4F60\u53D1\u4FE1\u53F7 -checkbox.auto.discover.port = (&A) \u81EA\u52A8\u68C0\u6D4B\u4E3B\u673A\u548C\u7AEF\u53E3 -checkbox.auto.login = (&A) \u81EA\u52A8\u767B\u5F55 -checkbox.login.as.invisible = (&L) \u9690\u8EAB\u767B\u5F55 -checkbox.disable.chat.history = (&D) \u5BF9\u8BDD\u5386\u53F2\u4E0D\u53EF\u7528 -checkbox.sort.asc.history = \u6309\u7167\u65E5\u671F\u5347\u5E8F\u6392\u5217\u8054\u7CFB\u4EBA\u5386\u53F2\u6D88\u606F -checkbox.disable.prev.chat.history = \u4E0D\u663E\u793A\u4EE5\u5F80\u804A\u5929\u8BB0\u5F55 -checkbox.enable.emoticons = (&O) \u663E\u793A\u8868\u60C5 -checkbox.graying.out = \u7A7A\u95F2\u8054\u7CFB\u4EBA\u53D8\u6DE1\uFF08\u9700\u8981\u91CD\u542F\uFF09 -checkbox.idle.enabled = (&I) \u5141\u8BB8\u7A7A\u95F2\u7B49\u5F85 -checkbox.launch.on.startup = (&L) \u968F\u7CFB\u7EDF\u542F\u52A8 -checkbox.reconnet.info = \u6307\u5B9A\u91CD\u65B0\u8FDE\u63A5\u7684\u663E\u793A\u65B9\u5F0F\uFF1A -checkbox.reconnect.panel.big = \u6309\u7167\u9762\u677F\u65B9\u5F0F\u663E\u793A -checkbox.reconnect.panel.small = \u6309\u7167\u8054\u7CFB\u4EBA\u5206\u7EC4\u65B9\u5F0F\u663E\u793A -checkbox.reconnect.panel.icon = \u6309\u7167\u56FE\u6807\u65B9\u5F0F\u663E\u793A -checkbox.notify.user.comes.online = \u6709\u7528\u6237\u4E0A\u7EBF\u65F6\u901A\u77E5 -checkbox.notify.user.goes.offline = \u6709\u7528\u6237\u4E0B\u7EBF\u65F6\u901A\u77E5 -checkbox.notify.typing.systemtray = \u7CFB\u7EDF\u6258\u76D8\u663E\u793A\u6253\u5B57\u4FE1\u606F -checkbox.notify.systemtray = \u7CFB\u7EDF\u6258\u76D8\u663E\u793A\u65B0\u6D88\u606F -checkbox.permanent = (&P) \u804A\u5929\u5BA4\u4E3A\u56FA\u5B9A\u7684 -checkbox.play.sound.on.invitation = (&I) \u5F53\u6536\u5230\u9080\u8BF7\u65F6\u64AD\u653E\u58F0\u97F3 -checkbox.play.sound.on.new.message = (&A) \u5F53\u6536\u5230\u65B0\u6D88\u606F\u65F6\u64AD\u653E\u58F0\u97F3 -checkbox.play.sound.on.outgoing.message = (&S) \u5F53\u53D1\u9001\u6D88\u606F\u65F6\u64AD\u653E\u58F0\u97F3 -checkbox.play.sound.when.offline = (&O) \u5F53\u7528\u6237\u79BB\u7EBF\u65F6\u64AD\u653E\u58F0\u97F3 -checkbox.private.room = (&I) \u804A\u5929\u5BA4\u662F\u79C1\u6709\u7684 -checkbox.save.password = (&S) \u4FDD\u5B58\u5BC6\u7801 -checkbox.show.avatars.in.contactlist = (&A)\u5728\u8054\u7CFB\u4EBA\u5217\u8868\u4E2D\u663E\u793A\u5934\u50CF -checkbox.show.notifications.in.conference = (&S) \u5728\u4F1A\u8BAE\u5BA4\u663E\u793A\u901A\u77E5 -checkbox.show.time.in.chat.window = (&S) \u5728\u5BF9\u8BDD\u7A97\u53E3\u663E\u793A\u65F6\u95F4 -checkbox.show.toaster = (&T) \u663E\u793A\u4E00\u4E2A\u5F39\u51FA\u7A97\u53E3 -checkbox.split.chat.window = (&W) \u804A\u5929\u7A97\u53E3\u505C\u9760 (\u8981\u6C42\u91CD\u65B0\u542F\u52A8) -checkbox.start.in.tray = (&S) \u542F\u52A8\u540E\u663E\u793A\u5230\u7CFB\u7EDF\u6258\u76D8\u4E2D -checkbox.click.single.tray = (&U) \u5355\u51FB\u6258\u76D8\u56FE\u6807\u5F39\u51FASpark -checkbox.tabs.on.top = (&C) \u8054\u7CFB\u4EBA\u6807\u7B7E\u7F6E\u9876\u7AEF(\u8981\u6C42\u91CD\u65B0\u542F\u52A8) -checkbox.use.compression = (&m)\u542F\u7528\u538B\u7F29 -checkbox.use.debugger.on.startup = \u542F\u52A8\u65F6\u8FDB\u5165\u8C03\u8BD5\u6A21\u5F0F -checkbox.use.proxy.server = (&U) \u4F7F\u7528\u4EE3\u7406\u670D\u52A1\u5668 -checkbox.use.system.look.and.feel = (&F) \u4F7F\u7528\u7CFB\u7EDF\u5916\u89C2(\u8981\u6C42\u91CD\u65B0\u542F\u52A8) -checkbox.window.to.front = (&B) \u7A97\u53E3\u7F6E\u4E8E\u6700\u524D\u9762 -checkbox.broadcast.hide.offline.user = \u9690\u85CF\u79BB\u7EBF\u8054\u7CFB\u4EBA -checkbox.use.krbconf = \u4F7F\u7528krb5.conf \u6216 krb5.ini -checkbox.use.krb.dns = \u4F7F\u7528DNS -checkbox.use.specify.below = \u8BF4\u660E\u5982\u4E0B -checkbox.use.pki.authentication = \u7528PKI\u9A8C\u8BC1 -checkbox.transport.tab.setting = \u5728\u6807\u7B7E\u680F\u4E0A\u4E2D\u663E\u793A\u53EF\u7528\u7684\u4F20\u8F93\u65B9\u5F0F(\u8981\u6C42\u91CD\u65B0\u542F\u52A8) -checkbox.conference.tab.setting = \u5728\u6807\u7B7E\u680F\u4E0A\u663E\u793A\u4F1A\u8BAE\u5BA4\u670D\u52A1(\u8981\u6C42\u91CD\u65B0\u542F\u52A8) -checkbox.use.hostname.as.resource = \u7528\u4E3B\u673A\u540D\u4F5C\u4E3A\u8D44\u6E90\u540D\u79F0 -checkbox.use.version.as.resource = \u7528Spark\u7248\u672C\u53F7\u4F5C\u4E3A\u8D44\u6E90\u540D\u79F0 -delete.log.permanently = \u6C38\u4E45\u6027\u5220\u9664\u65E5\u5FD7 -delete.permanently = \u6C38\u4E45\u6027\u5220\u9664? -gateway.username.password.error = \u9700\u8981\u63D0\u4F9B\u7528\u6237\u540D\u548C\u5BC6\u7801. -group.chat.window.information = \u804A\u5929\u7A97\u53E3\u4FE1\u606F -group.comma.delimited = \u4EE5\u9017\u53F7\u9694\u5F00 -group.conferences.found = \u627E\u5230\u4F1A\u8BAE\u670D\u52A1 -group.connection = \u8FDE\u7EBF -group.empty = \u8BE5\u7EC4\u6CA1\u6709\u8054\u7CFB\u4EBA\u5728\u7EBF. -group.general.information = \u4E00\u822C\u4FE1\u606F -group.login.information = \u767B\u5F55\u4FE1\u606F -group.notification.options = \u901A\u77E5\u9009\u62E9 -group.offline = \u79BB\u7EBF\u7684\u8054\u7CFB\u4EBA -group.search.form = \u641C\u5BFB -group.search.results = \u641C\u5BFB\u7ED3\u679C -group.chat.name.notification = \u89C1\u4F60\u7684\u540D\u5B57... -group.chat.name.match = \u4F60\u7684\u540D\u5B57\u51FA\u73B0\u5728\u7FA4\u804A\u4E2D\uFF1A -label.na = \u4E0D\u53EF\u7528 -label.cell = Cell -label.work = \u5DE5\u4F5C -label.home = \u5BB6 -label.accounts = (&A) \u8D26\u53F7 -label.passwordreset = \u91CD\u7F6E\u5BC6\u7801 -label.add.conference.service = (&A) \u6DFB\u52A0\u4F1A\u8BAE\u670D\u52A1 -label.add.jid = (&A) \u6DFB\u52A0JID -label.add.task = \u6DFB\u52A0\u4EFB\u52A1 -label.auto.login = (&A) \u81EA\u52A8\u767B\u5F55 -label.available.users.in.roster = (&A) \u5728\u7EBF\u8054\u7CFB\u4EBA\u5217\u8868 -label.avatar = \u5934\u50CF: -label.cancel = \u53D6\u6D88 -label.change.password.to = (&C) \u6539\u53D8\u5BC6\u7801 -label.chatroom.fontsize = (&R)\u804A\u5929\u5BA4\u5B57\u4F53: -label.city = (&C) \u57CE\u5E02 -label.close = (&L) \u5173\u95ED -label.company = (&C) \u516C\u53F8 -label.confirm.password = (&C) \u786E\u8BA4\u5BC6\u7801 -label.conflict.error = \u8D26\u53F7\u5DF2\u767B\u5F55\uFF0C\u65E0\u6CD5\u91CD\u590D\u767B\u5F55\u3002 -label.contact.to.find = \u67E5\u627E\u8054\u7CFB\u4EBA -label.recent.conversation = \u6700\u8FD1\u7684\u5BF9\u8BDD -label.frequent.contacts = \u5E38\u7528\u8054\u7CFB\u4EBA -label.contactlist.avatarsize = \u8054\u7CFB\u4EBA\u5217\u8868\u5934\u50CF\u5927\u5C0F: -label.contactlist.fontsize = (&L)\u8054\u7CFB\u4EBA\u5217\u8868\u5B57\u4F53\u5927\u5C0F: -label.country = (&O) \u56FD\u5BB6 -label.create.account = (&A) \u65B0\u5EFA\u8D26\u53F7 -label.department = (&D) \u90E8\u95E8 -label.dial = (&D) \u62E8\u53F7\u76D8 -label.display.time = \u663E\u793A\u65F6\u95F4: -label.downloads = \u4E0B\u8F7D -label.due = Due -label.email.address = (&E) \u7535\u5B50\u90AE\u4EF6 -label.emoticons = (&E) \u8868\u60C5 -label.enter.address = \u8F93\u5165\u5730\u5740 -label.enter.group.name = \u8F93\u5165\u65B0\u7684\u7EC4\u540D -label.fax = (&F) \u4F20\u771F -label.find = (&F) \u67E5\u627E -label.first.name = (&F) \u540D\u5B57 -label.group = (&G) \u7EC4 -label.host = (&H) \u4E3B\u673A -label.invited.users = \u88AB\u9080\u8BF7\u7684\u7528\u6237 -label.jabber.address = &Jabber\u5730\u5740 -label.jabber.id = &Jabber \u8D26\u53F7 -label.jid = &JID -label.job.title = (&J) \u804C\u79F0 -label.last.name = (&L) \u59D3 -label.local.time = (&L) \u672C\u5730\u65F6\u95F4 -label.message = (&M) \u6D88\u606F -label.message.style = (&M) \u6D88\u606F\u6A21\u5F0F -label.middle.name = (&M) \u4E2D\u95F4\u540D -label.minutes.before.stale.chat = (&M) \u4E0D\u6D3B\u52A8\u804A\u5929\u5BA4\u7A7A\u95F2\u5206\u949F\u6570 -label.mobile = (&M) \u79FB\u52A8\u7535\u8BDD -label.name = (&N) \u540D\u5B57 -label.network = (&K) \u7F51\u7EDC -label.new.nickname = \u65B0\u7684\u6635\u79F0 -label.nickname = (&C) \u6635\u79F0 -label.number = (&N) \u6570\u5B57 -label.ok = \u786E\u8BA4 -label.old.ssl = (&U) \u4F7F\u7528\u65E7SSL\u7AEF\u53E3 -label.os = (&O) \u64CD\u4F5C\u7CFB\u7EDF -label.pager = (&P) \u4F20\u547C\u673A -label.password = (&P) \u5BC6\u7801 -label.phone = (&P) \u7535\u8BDD -label.port = (&P) \u7AEF\u53E3 -label.postal.code = (&P) \u90AE\u653F\u7F16\u7801 -label.presence = (&P) \u5B58\u5728 -label.priority = (&R) \u4F18\u5148\u7EA7 -label.protocol = (&P) \u534F\u8BAE -label.received = (&R)\u63A5\u6536 -label.rename.to = \u91CD\u65B0\u547D\u540D -label.resource = (&R) \u8D44\u6E90 -label.response.timeout = (&R) \u54CD\u5E94\u8D85\u65F6(\u79D2) -label.room = &Room -label.room.name = (&R) \u804A\u5929\u5BA4\u540D\u79F0 -label.room.topic = (&T) \u804A\u5929\u5BA4\u9898\u76EE -label.search = Search -label.search.service = (&S) \u641C\u7D22\u670D\u52A1 -label.seconds = Seconds -label.server = (&S) \u670D\u52A1\u5668 -label.server.address = (&S) \u670D\u52A1\u5668\u5730\u5740 -label.show = \u663E\u793A: -label.software = (&S) \u8F6F\u4EF6 -label.state.and.province = (&T) \u5DDE/\u7701 -label.street.address = (&S) \u8857\u9053\u5730\u5740 -label.time = \u65F6\u95F4\uFF1A {0} -label.time.till.idle = (&T) \u7A7A\u95F2\u91CD\u62E8\u65F6\u95F4(\u5206\u949F) -label.time.till.idlemessage = (&E) \u7A7A\u95F2\u81EA\u52A8\u6D88\u606F -label.timeformat = Use {0} -label.transfer.download.directory = (&D) \u4E0B\u8F7D\u76EE\u5F55\uFF1A -label.transfer.timeout = (&T) \u4F20\u8F93\u8D85\u65F6(\u5206\u949F) \uFF1A -label.unable.to.add.contact = \u65E0\u6CD5\u6DFB\u52A0\u8054\u7CFB\u4EBA\u3002 -label.use.default = \u4F7F\u7528\u9ED8\u8BA4 -label.user.on.public.network = \u7528\u6237\u4F4D\u4E8E\u4E00\u4E2A\u516C\u5171\u7F51\u7EDC\u4E0A -label.username = (&U) \u7528\u6237 -label.version = (&V) \u7248\u672C -label.web.page = (&W) \u7F51\u9875 -label.xmpp.port = (&X) XMPP\u7AEF\u53E3 -label.krb.realm = \u9886\u5730 -label.krb.kdc = KDC -label.which.pki.method = \u54EA\u4E2APKI\u65B9\u6CD5\uFF1F -label.choose.file = \u9009\u62E9\u6587\u4EF6 -label.trust.store.password = \u53EF\u4FE1\u5BC6\u7801\u5B58\u50A8 -label.enter.password = \u8F93\u5165\u5BC6\u7801 -label.move.focus.forwards = \u5411\u524D\u79FB\u52A8\u7126\u70B9 -label.move.focus.backwards = \u5411\u540E\u79FB\u52A8\u7126\u70B9 -label.keystore.location = Keystore location -label.truststore.location = Truststore location -label.pkcs.library.file = PKCS#11 library file -label.x509.certificate = X.509 certificate -label.apple.keychain = Apple KeyChain -label.add.to.roster = \u52A0\u5230\u8054\u7CFB\u4EBA\u5217\u8868 -label.audio.device = \u97F3\u9891\u8BBE\u5907 -label.video.device = \u89C6\u9891\u8BBE\u5907 -menuitem.about = \u5173\u4E8E -menuitem.actions = \u6D3B\u52A8 -menuitem.bookmarks = \u6536\u85CF -menuitem.add = \u6DFB\u52A0 -menuitem.add.as.contact = \u4F5C\u4E3A\u8054\u7CFB\u4EBA\u6DFB\u52A0 -menuitem.add.contact = \u6DFB\u52A0\u8054\u7CFB\u4EBA -menuitem.add.contact.group = \u6DFB\u52A0\u8054\u7CFB\u4EBA\u7EC4 -menuitem.add.groupchat.myname = \u9AD8\u4EAE\u6211\u7684\u540D\u5B57 -menuitem.add.groupchat.mytext = \u9AD8\u4EAE\u6211\u7684\u6587\u5B57 -menuitem.add.groupchat.popname = \u63D0\u5230\u6211\u540D\u5B57\u65F6\u5F39\u51FA -menuitem.add.groupchat.showjoinleavemessage = \u663E\u793A\u52A0\u5165\u9000\u51FA\u4FE1\u606F -menuitem.add.groupchat.showrolesinsteadofstatus = \u663E\u793A\u804A\u5929\u89D2\u8272\u56FE\u6807\u800C\u4E0D\u662F\u5728\u7EBF\u72B6\u6001\u56FE\u6807 -menuitem.add.groupchat.auto.accept.invite = \u81EA\u52A8\u63A5\u6536\u7FA4\u804A\u9080\u8BF7 -menuitem.add.groupchat.random.colors = \u540D\u5B57\u663E\u793A\u968F\u673A\u989C\u8272 -menuitem.always.on.top = \u4E3B\u9762\u677F\u603B\u5728\u6700\u524D\u9762 -menuitem.alert.when.online = \u7528\u6237\u5728\u7EBF\u65F6\u663E\u793A\u901A\u77E5 -menuitem.ban = \u7981\u6B62 -menuitem.ban.user = \u7981\u6B62\u4F7F\u7528\u8005 -menuitem.block.user = \u963B\u6B62\u4F7F\u7528\u8005 -menuitem.broadcast.to.group = \u5BF9\u7EC4\u5E7F\u64AD -menuitem.browse.service = \u6D4F\u89C8\u670D\u52A1 -menuitem.change.nickname = \u4FEE\u6539\u6635\u79F0 -menuitem.change.subject = \u6539\u53D8\u4E3B\u9898 -menuitem.chat = \u804A\u5929 -menuitem.check.for.updates = \u68C0\u67E5\u66F4\u65B0 -menuitem.contacts = \u8054\u7CFB\u4EBA -menuitem.copy.to = \u590D\u5236\u5230 -menuitem.delete = \u5220\u9664 -menuitem.delete.login.information = \u5220\u9664\u767B\u5F55\u4FE1\u606F -menuitem.destroy.room = \u64A4\u9500\u623F\u95F4 -menuitem.dial = \u62E8\u53F7 -menuitem.edit = \u7F16\u8F91 -menuitem.edit.my.profile = \u7F16\u8F91\u6211\u7684\u7B80\u4ECB ... -menuitem.edit.status.message = \u7F16\u8F91\u81EA\u5B9A\u4E49\u72B6\u6001\u6D88\u606F ... -menuitem.enter.login.information = \u8F93\u5165\u767B\u5F55\u4FE1\u606F -menuitem.exit = \u9000\u51FA -menuitem.affiliation = Affiliation -menuitem.grant.moderator = \u6388\u4E88\u4E3B\u6301\u4EBA -menuitem.grant.member = \u6388\u4E88\u6210\u5458 -menuitem.grant.admin = \u6388\u4E88\u7BA1\u7406\u5458 -menuitem.grant.owner = \u6388\u4E88\u6240\u6709\u8005 -menuitem.grant.voice = \u6388\u4E88\u53D1\u8A00\u6743 -menuitem.help = \u5E2E\u52A9 -menuitem.hide = \u9690\u85CF -menuitem.invite.group.to.conference = \u9080\u8BF7\u7EC4\u5230\u4F1A\u8BAE\u4E2D -menuitem.invite.users = \u9080\u8BF7\u4F7F\u7528\u8005 -menuitem.join.on.startup = \u7CFB\u7EDF\u542F\u52A8\u65F6\u8FDE\u63A5 -menuitem.join.room = \u8FDE\u63A5\u623F\u95F4 -menuitem.kick.user = \u8E22\u51FA\u4F7F\u7528\u8005 -menuitem.languages = \u8BED\u8A00 -menuitem.logout.no.status = \u767B\u51FA -menuitem.logout.with.status = \u8BB0\u5F55\u767B\u51FA\u7684\u7406\u7531 -menuitem.lookup.profile = \u67E5\u770B\u7B80\u4ECB ... -menuitem.move.to = \u79FB\u52A8\u5230 -menuitem.online.help = \u8054\u673A\u5E2E\u52A9 -menuitem.open = \u6253\u5F00 -menuitem.open.with = \u6253\u5F00\u65B9\u5F0F... -menuitem.plugins = \u63D2\u4EF6\u7BA1\u7406 -menuitem.preferences = \u8BBE\u7F6E -menuitem.remove = \u79FB\u9664 -menuitem.remove.alert.when.online = \u64A4\u9500\u901A\u77E5 -menuitem.remove.bookmark = \u79FB\u9664\u4E66\u7B7E -menuitem.remove.from.group = \u4ECE\u7EC4\u4E2D\u79FB\u9664 -menuitem.remove.from.roster = \u4ECE\u540D\u5355\u4E2D\u79FB\u9664 -menuitem.block.contact = \u62C9\u9ED1\u8054\u7CFB\u4EBA -menuitem.unblock.contact = \u89E3\u9501\u8054\u7CFB\u4EBA -menuitem.remove.service = \u79FB\u9664\u670D\u52A1 -menuitem.rename = \u91CD\u65B0\u547D\u540D -menuitem.revoke.moderator = \u64A4\u9500\u4E3B\u6301\u4EBA -menuitem.revoke.voice = \u64A4\u9500\u58F0\u97F3 -menuitem.revoke.member = Revoke Membership -menuitem.revoke.admin = Revoke Admin -menuitem.revoke.owner = Revoke Ownership -menuitem.save = \u4FDD\u5B58 -menuitem.save.as = \u53E6\u5B58\u4E3A ... -menuitem.send.a.file = \u4F20\u9001\u4E00\u4E2A\u6863\u6848 -menuitem.send.a.message = \u5C06\u5E7F\u64AD\u9001\u5F80\u6307\u5B9A\u7684\u4F7F\u7528\u8005 ... -menuitem.set.status.message = \u8BBE\u7F6E\u72B6\u6001\u6D88\u606F ... -menuitem.show.empty.groups = \u663E\u793A\u7A7A\u7EC4 -menuitem.show.offline.group = \u5BF9\u79BB\u7EBF\u4F7F\u7528\u8005\u5206\u7EC4 -menuitem.show.traffic = \u663E\u793A\u901A\u4FE1\u91CF\u7A97\u53E3 -menuitem.sign.in = \u7B7E\u5230 -menuitem.sign.in.at.login = \u5728\u767B\u5F55\u7B7E\u5230 -menuitem.sign.out = \u79BB\u5F00 -menuitem.start.a.chat = \u53D1\u9001\u5373\u65F6\u6D88\u606F -menuitem.start.a.conference = \u5F00\u59CB\u4E00\u4E2A\u4F1A\u8BAE ... -menuitem.status = \u72B6\u6001 -menuitem.subscribe.to = \u540C\u610F -menuitem.unban = \u53D6\u6D88\u7981\u6B62 -menuitem.unblock.user = \u53D6\u6D88\u963B\u6B62\u4F7F\u7528\u8005 -menuitem.user.guide = \u7528\u6237\u624B\u518C -menuitem.view.client.version = \u67E5\u770B\u5BA2\u6237\u7AEF\u7248\u672C -menuitem.view.contact.history = \u67E5\u770B\u804A\u5929\u8BB0\u5F55 -menuitem.view.downloads = \u67E5\u770B\u4E0B\u8F7D -menuitem.view.last.activity = \u67E5\u770B\u6700\u540E\u4E00\u4E2A\u6D3B\u52A8 -menuitem.view.logs = \u67E5\u770B\u65E5\u5FD7 -menuitem.view.profile = \u67E5\u770B\u7B80\u4ECB -menuitem.view.room.info = \u67E5\u770B\u623F\u95F4\u4FE1\u606F -menuitem.voice = \u58F0\u97F3 -menuitem.show.offline.users = \u663E\u793A\u79BB\u7EBF\u7528\u6237 -menuitem.show.contact.statusmessage = \u663E\u793A\u72B6\u6001\u4FE1\u606F -menuitem.bookmark.room = \u6536\u85CF\u804A\u5929\u5BA4 -menuitem.refresh = \u5237\u65B0 -menuitem.create.room = \u521B\u5EFA\u5E76\u52A0\u5165\u804A\u5929\u5BA4 -menuitem.expand.all.groups = \u5C55\u5F00\u5168\u90E8\u5206\u7EC4 -menuitem.collapse.all.groups = \u6536\u8D77\u5206\u7EC4 -menuitem.inivite.again = \u91CD\u65B0\u9080\u8BF7 -menuitem.chatframe.option = \u9009\u9879 -menuitem.add.groupchat.invitetobookmark = \u81EA\u52A8\u9080\u8BF7\u8054\u7CFB\u4EBA\u81F3\u4E66\u7B7E\u4E2D\u7684\u804A\u5929\u5BA4 -message.invite.to.groupchat = {0} \u9080\u8BF7\u60A8\u52A0\u5165\u7FA4\u804A -message = \u6D88\u606F -message.account.create = \u521B\u5EFA\u65B0\u8D26\u53F7. -message.account.created = \u65B0\u8D26\u53F7\u521B\u5EFA\u6210\u529F\u3002 -message.account.error = \u8BF7\u6307\u5B9A\u9700\u8981\u65B0\u5EFA\u8D26\u53F7\u7684\u670D\u52A1\u5668\u3002 -message.add.a.contact = \u6DFB\u52A0\u8054\u7CFB\u4EBA\u3002 -message.add.conference.service = \u6DFB\u52A0\u4E00\u9879\u4F1A\u8BAE\u670D\u52A1\u3002 -message.add.contact.to.list = \u6DFB\u52A0\u4E00\u540D\u7528\u6237\u5230\u4F60\u7684\u8054\u7EDC\u540D\u5355 -message.add.favorite.room = \u6DFB\u52A0\u804A\u5929\u5BA4\u5230\u6536\u85CF\u5217\u8868\u6216\u76F4\u63A5\u52A0\u5165\u3002 -message.add.this.user.to.your.roster = \u6DFB\u52A0\u8BE5\u7528\u6237\u5230\u4F60\u7684\u597D\u53CB\u540D\u5355\u3002 -message.add.to.roster = \u6DFB\u52A0\u5230\u540D\u5355 -message.add.user = \u6DFB\u52A0\u7528\u6237\u5230\u4F60\u7684\u8054\u7CFB\u4EBA\u540D\u5355\uFF1F -message.alert.notify = \u901A\u77E5 -message.already.exists = \u8D26\u53F7\u5DF2\u7ECF\u5B58\u5728\u3002 \u8BF7\u5C1D\u8BD5\u4E0D\u540C\u7684\u7528\u6237\u540D\u3002 -message.approve.subscription = \u51C6\u8BB8{0}\u6DFB\u52A0\u4F60\u5230\u4ED6\u4EEC\u7684\u8054\u7CFB\u4EBA\u540D\u5355\uFF1F -message.autenticating = \u9A8C\u8BC1 -message.away.idle = \u7A7A\u95F2\u663E\u793A\u79BB\u5F00\u3002 -message.bookmark.temporary.room.error = \u4F60\u4E0D\u80FD\u4E3A\u4E34\u65F6\u623F\u95F4\u6DFB\u52A0\u4E66\u7B7E -message.broadcast.from = \u5E7F\u64AD\u6D88\u606F\u6765\u81EA\u4E8E{0} -message.broadcast.no.user.selected = \u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u540D\u63A5\u6536\u4EBA -message.broadcast.no.text = \u8BF7\u8F93\u5165\u5E7F\u64AD\u7684\u6587\u5B57 -message.broadcast.message.sent = \u53D1\u9001\u4E86\u5E7F\u64AD\u6D88\u606F\u3002 -message.broadcast.to = \u53D1\u9001\u5E7F\u64AD\u6D88\u606F\u81F3{0} -message.broadcasted.to = \u6D88\u606F\u5BF9\u4EE5\u4E0B\u7528\u6237\u5E7F\u64AD\u4E86:{0} -message.buzz.alert.notification = \u83B7\u5F97\u7528\u6237\u7684\u6CE8\u610F\u3002 -message.buzz.message = {0} \u5E0C\u671B\u5F97\u5230\u60A8\u7684\u6CE8\u610F -message.buzz.sent = \u53D1\u9001\u901A\u77E5\u7ED9\u7528\u6237. -message.calling = \u547C\u53EB{0} -message.came.online = {0}\u4E0A\u7EBF\u4E8E{1} -message.cannot.add.contact.to.shared.group = \u4E0D\u80FD\u6DFB\u52A0\u65B0\u7684\u8054\u7CFB\u4EBA\u5230\u4E00\u4E2A\u5171\u6709\u7684\u5C0F\u7EC4\u3002 -message.chat.session.ended = \u5BF9\u8BDD\u7ED3\u675F\u4E8E{0} -message.click.to.open = \u70B9\u51FB\u4EE5\u6253\u5F00 -message.client.information = {0}\u7684\u5BA2\u6237\u7AEF\u4FE1\u606F -message.close.other.chats = \u7ED3\u675F\u5176\u4ED6\u5BF9\u8BDD -message.close.stale.chats = \u7ED3\u675F\u4E0D\u6D3B\u52A8\u7684\u5BF9\u8BDD -message.close.this.chat = \u7ED3\u675F\u5F53\u524D\u5BF9\u8BDD -message.conference.info.error = \u65E0\u6CD5\u68C0\u7D22\u4F1A\u8BAE\u4FE1\u606F\u3002\u8BF7\u7A0D\u5019\u518D\u5C1D\u8BD5\u3002 -message.conference.service.error = \u65E0\u6CD5\u5B9A\u4F4D\u4F1A\u8BAE\u670D\u52A1\u3002 -message.confirm.destruction.of.room = \u64A4\u9500\u804A\u5929\u5BA4\u5C06\u79FB\u9664\u6240\u6709\u7684\u7528\u6237\u3002 \u7EE7\u7EED\uFF1F -message.confirmation.password.error = \u6307\u5B9A\u786E\u8BA4\u5BC6\u7801\u3002 -message.connecting.please.wait = \u6B63\u5728\u8FDE\u63A5\u3002 \u8BF7\u7B49\u5F85\u2026 -message.connection.failed = \u65E0\u6CD5\u8FDE\u63A5\u5230{0}\u3002 -message.create.account = \u4E0D\u80FD\u521B\u5EFA\u8BE5\u8D26\u53F7\u3002 -message.create.or.join.room = \u521B\u5EFA\u6216\u52A0\u5165\u4E00\u4E2A\u4F1A\u8BAE\u804A\u5929\u5BA4 -message.current.status = \u540C\u610F\u5176\u4ED6\u4EBA\u77E5\u9053\u4F60\u7684\u5F53\u524D\u72B6\u6001\u6216\u6D3B\u52A8\u3002 -message.default.error = \u68C0\u6D4B\u5230\u9519\u8BEF\u3002 \u8BF7\u5411support@jivesoftware.com\u62A5\u544A\u3002 -message.delete.all.history = \u5220\u9664\u6240\u6709\u65E9\u5148\u5BF9\u8BDD\uFF1F -message.delete.confirmation = \u662F\u5426\u5220\u9664{0} \uFF1F -message.disable.transport = \u53D6\u6D88\u767B\u5F55\u4FE1\u606F\u4ECE{0} \uFF1F -message.disconnected.conflict.error = \u8FDE\u63A5\u88AB\u5173\u95ED\uFF0C\u5F53\u524D\u8D26\u53F7\u5DF2\u5728\u5176\u5B83\u5730\u65B9\u767B\u5F55\u3002 -message.disconnected.error = \u53D1\u751F\u4E00\u4E2A\u9519\u8BEF\uFF0C\u8FDE\u63A5\u88AB\u5173\u95ED\u3002 -message.disconnected.group.chat.error = \u53D1\u751F\u4E00\u4E2A\u9519\u8BEF\uFF0C\u8FDE\u63A5\u88AB\u5173\u95ED\u3002 \u4F60\u53EF\u80FD\u9700\u8981\u5728\u91CD\u65B0\u8FDE\u63A5\u540E\u518D\u52A0\u5165\u6B64\u804A\u5929\u5BA4\u3002 -message.disconnected.shutdown = \u7531\u4E8E\u670D\u52A1\u5668\u5173\u95ED\uFF0C\u60A8\u7684\u8FDE\u63A5\u88AB\u7EC8\u6B62. -message.downloading = \u4E0B\u8F7D{0} -message.downloading.spark.plug = \u4E0B\u8F7D\u63D2\u4EF6 -message.end.chat = \u4F60\u8981\u7ED3\u675F\u6B64\u6B21\u5BF9\u8BDD\u5417\uFF1F -message.end.conversation = \u4F60\u8981\u7ED3\u675F\u672C\u6B21\u4F1A\u8BAE\u5417\uFF1F -message.enter.aim = \u8BF7\u8F93\u5165\u4F60\u7684AIM\u8D26\u53F7\u548C\u5BC6\u7801\u3002 -message.enter.broadcast.message = \u8F93\u5165\u6D88\u606F\u5BF9\u5DF2\u7ECF\u9009\u62E9\u7684\u7528\u6237\u5E7F\u64AD\u3002 -message.enter.gadugadu = \u8BF7\u8F93\u5165\u60A8\u7684 GaduGadu \u8D26\u53F7\u548C\u5BC6\u7801. -message.enter.gtalk = \u8BF7\u8F93\u5165\u60A8\u7684 GTalk \u8D26\u53F7\u548C\u5BC6\u7801. -message.enter.icq = \u8BF7\u8F93\u5165\u4F60\u7684 ICQ \u8D26\u53F7\u548C\u5BC6\u7801\u3002 -message.enter.irc = \u8BF7\u8F93\u5165\u60A8\u7684 IRC \u8D26\u53F7\uFF0C\u5BC6\u7801\u548C\u6635\u79F0. -message.enter.sametime = \u8BF7\u8F93\u5165\u60A8\u7684 Sametime\u7528\u6237\u540D\u548C\u5BC6\u7801 -message.enter.facebook = \u8F93\u5165Facebook\u7684\u8D26\u53F7\u548C\u5BC6\u7801 -message.enter.myspace = \u8F93\u5165\u4F60\u7684 MySpace \u8D26\u53F7\u548C\u5BC6\u7801 -message.enter.jabber.id = \u8F93\u5165jabber ID -message.enter.message.to.broadcast = \u5BF9\u6240\u6709\u8054\u7CFB\u4EBA\u53D1\u9001\u5E7F\u64AD\u6D88\u606F\u3002 -message.enter.msn = \u8F93\u5165\u4F60\u7684 MSN \u8D26\u53F7\u548C\u5BC6\u7801\u3002 -message.enter.new.subject = \u8F93\u5165\u65B0\u7684\u4E3B\u9898 -message.enter.qq = \u8BF7\u8F93\u5165\u60A8\u7684 QQ \u53F7\u7801\u548C\u5BC6\u7801 -message.enter.room.password = \u8F93\u5165\u804A\u5929\u5BA4\u5BC6\u7801 -message.enter.simple = \u8BF7\u8F93\u5165\u60A8\u7684 SIMPLE \u8D26\u53F7\u548C\u5BC6\u7801. -message.enter.valid.jid = \u8F93\u5165\u5408\u6CD5\u7684jabber\u53F7\u7801 -message.enter.xmpp = \u8BF7\u8F93\u5165\u60A8\u7684 XMPP \u7528\u6237\u540D\u548C\u5BC6\u7801. -message.enter.yahoo = \u8F93\u5165\u4F60\u7684\u7528\u6237\u540D\u548C\u5BC6\u7801\u8FDE\u63A5\u5230\u96C5\u864E\u3002 -message.error.during.file.transfer = \u5728\u6587\u4EF6\u4F20\u8F93\u671F\u95F4\u53D1\u751F\u9519\u8BEF\u3002 -message.file.exists.question = \u6587\u4EF6\u5DF2\u7ECF\u5B58\u5728\u3002 \u91CD\u5199\uFF1F -message.file.size = \u6587\u4EF6\u5927\u5C0F\uFF1A {0} -message.file.transfer.canceled = \u4F60\u53D6\u6D88\u4E86\u6587\u4EF6\u4F20\u8F93\u3002 -message.file.transfer.rejected = \u6587\u4EF6\u4F20\u8F93\u672A\u88AB{0}\u63A5\u53D7\u3002 -message.file.transfer.dirnull = \u6587\u4EF6\u4F20\u8F93\u7528\u7684\u4E0B\u8F7D\u6587\u4EF6\u5939\u4E0D\u53EF\u7528 -message.file.transfer.nodir = \u6587\u4EF6\u4F20\u8F93\u7528\u7684\u4E0B\u8F7D\u6587\u4EF6\u5939\u4E0D\u5B58\u5728 -message.file.transfer.cantwritedir = \u6587\u4EF6\u4F20\u8F93\u65E0\u6CD5\u5199\u5165\u6587\u4EF6\u5939 -message.file.transfer.notification = \u6587\u4EF6\u4F20\u8F93\u63D0\u793A -message.file.transfer.short.message = \u6709\u6587\u4EF6\u4F20\u8F93\u547C\u5165 -message.file.transfer.chat.window = \u6587\u4EF6\u4F20\u8F93\u8BF7\u6C42 -message.file.transfer.file.too.big.error = \u9009\u4E2D\u7684\u6587\u4EF6\u592A\u5927\u4E86\u3002\n\u6700\u5927\u4E0D\u8D85\u8FC7{0}\uFF0C\u4F46\u662F\u9009\u4E2D\u7684\u6587\u4EF6\u5927\u5C0F\u4E3A{1} -message.file.transfer.file.too.big.warning = \u9009\u4E2D\u7684\u6587\u4EF6\u592A\u5927\u4E86\u3002\n\u7EE7\u7EED\uFF1F -message.file.transfer.direrror.setdir = \u70B9\u51FB\u6B64\u5904\u6539\u53D8\u6587\u4EF6\u5939 -message.find.conference.services = \u67E5\u627E\u4F1A\u8BAE\u670D\u52A1 -message.forbidden.error = \u4ECE\u670D\u52A1\u5668\u63A5\u53D7\u4E86\u4E00\u4E2A\u7981\u6B62\u7684\u9519\u8BEF\u3002 -message.gateway.username.error = \u7528\u6237\u540D\u9700\u8F93\u5165 -message.gateway.password.error = \u5FC5\u987B\u63D0\u4F9B\u5BC6\u7801 -message.gateway.nickname.error = \u5FC5\u987B\u63D0\u4F9B\u6635\u79F0. -message.general.error = \u4F60\u65AD\u5F00\u4E86\u4E0E\u670D\u52A1\u5668\u7684\u8FDE\u63A5\u7531\u4E8E{0}\u3002 -message.generic.reconnect.message = \u4F60\u65AD\u5F00\u4E86\u4E0E\u670D\u52A1\u5668\u7684\u8FDE\u63A5\u3002 \u8981\u91CD\u65B0\u767B\u5F55\uFF0C\u8BF7\u70B9\u51FB\u4E0B\u9762\u7684\u91CD\u65B0\u8FDE\u63A5\u6309\u94AE\u3002 -message.idle.for = \u95F2\u7F6E\u4E3A{0} -message.image.too.large = \u8FD9\u4E2A\u56FE\u50CF\u592A\u5927\u4E0D\u80FD\u4F7F\u7528\u3002 \u8BF7\u6307\u5B9A\u56FE\u50CF16k\u6216\u66F4\u5C0F\u3002 -message.invalid.jabber.id = \u4E0D\u662F\u5408\u6CD5\u7684jabber ID -message.invalid.jid.error = \u6307\u5B9A\u7684JID\u662F\u65E0\u6548\u7684\u3002 -message.invalid.status = \u6307\u5B9A\u4E00\u5219\u6709\u6548\u7684\u72B6\u6001\u6D88\u606F\u3002 -message.invalid.username.password = \u9519\u8BEF\u7684\u7528\u6237\u540D\u6216\u5BC6\u7801. -message.invite.users.to.conference = \u9080\u8BF7\u7528\u6237\u5230\u4F1A\u8BAE\u5BA4\u3002 -message.is.shared.group = {0}\u662F\u4E00\u4E2A\u5171\u6709\u7684\u5C0F\u7EC4\u3002 -message.is.typing.a.message = {0}\u6B63\u5728\u952E\u5165\u6D88\u606F\u2026 -message.join.conference.room = \u52A0\u5165\u4F1A\u8BAE\u5BA4 -message.kicked.error = \u4F60\u4E0D\u80FD\u628A{0}\u8E22\u51FA\u6B64\u804A\u5929\u5BA4\u3002 -message.last.message.received = \u6700\u540E\u4E00\u6761\u6D88\u606F\u6536\u4E8E{0} -message.loading.please.wait = \u8F7D\u5165\u4E2D\u3002 \u8BF7\u7B49\u5F85\u2026 -message.locked.workstation = \u7528\u6237\u5DF2\u9501\u5B9A\u5DE5\u4F5C\u7AD9\u3002 -message.name.of.group = \u5206\u7EC4\u7684\u540D\u79F0 -message.name.of.search.service.question = \u641C\u7D22\u670D\u52A1\u7684\u540D\u5B57\uFF1F -message.negotiate.file.transfer = \u534F\u8BAE\u7684\u6587\u4EF6\u4F20\u8F93\u3002 \u8BF7\u7B49\u5F85\u2026 -message.negotiate.stream = \u8C08\u5224\u5BF9\u8BDD\u5C55\u5F00\u3002 \u8BF7\u7B49\u5F85\u2026 -message.negotiation.file.transfer = \u534F\u8BAE\u6587\u4EF6\u4F20\u8F93\u4E0E{0}\u3002 \u8BF7\u7B49\u5F85\u2026 -message.new.message = \u65B0\u7684\u6D88\u606F\u6765\u81EA{0}\u3002 -message.new.spark.available = {0}\u73B0\u5728\u662F\u53EF\u7528\u7684\u3002 \u662F\u5426\u5B89\u88C5\uFF1F -message.nickname.in.use = \u6635\u79F0\u5728\u4F7F\u7528\u4E2D\u3002 \u8BF7\u6307\u5B9A\u53E6\u4E00\u4E2A\u6635\u79F0 -message.nickname.not.acceptable = \u4E0D\u5141\u8BB8\u4FEE\u6539\u6635\u79F0\uFF01 -message.no.avatar.found = \u7528\u6237\u672A\u914D\u7F6E\u663E\u793A\u5934\u50CF\u3002 -message.no.caller.id = \u65E0\u53EF\u7528\u7684\u6765\u7535\u663E\u793A\u3002 -message.no.description.available = \u6CA1\u6709\u53EF\u7528\u7684\u63CF\u8FF0 -message.no.history.found = \u6CA1\u6709\u8FD9\u540D\u7528\u6237\u4EA4\u8C08\u7684\u5386\u53F2\u7EAA\u5F55\u3002 -message.no.results.found = \u670D\u52A1\u5668\u672A\u8FD4\u56DE\u641C\u7D22\u7ED3\u679C\u3002 -message.no.room.to.join.error = \u65E0\u53EF\u52A0\u5165\u7684\u804A\u5929\u5BA4 -message.no.subject.available = \u6CA1\u6709\u53EF\u7528\u7684\u4E3B\u9898 -message.no.updates = \u5F53\u524D\u6CA1\u6709\u53EF\u7528\u7684\u66F4\u65B0. -message.normal = \u666E\u901A\u6D88\u606F -message.number.to.call = \u6307\u5B9A\u6570\u5B57\u62E8\u53F7 -message.offline = \u5BF9\u65B9\u73B0\u5728\u6CA1\u6709\u5728\u7EBF\uFF0C\u5C06\u5728\u4E0B\u6B21\u767B\u5F55\u65F6\u6536\u5230\u60A8\u7684\u6D88\u606F. -message.offline.error = \u7528\u6237\u65E0\u6CD5\u6536\u5230\u79BB\u7EBF\u6D88\u606F\u3002 -message.participants.in.room = \u804A\u5929\u5BA4\u6210\u5458 -message.password.error = \u4E3A\u8FD9\u4E2A\u8D26\u53F7\u6307\u5B9A\u5BC6\u7801\u3002 -message.password.private.room.error = \u4E3A\u79C1\u6709\u804A\u5929\u5BA4\u6307\u5B9A\u5BC6\u7801 -message.passwords.no.match = \u5BC6\u7801\u4E0D\u5339\u914D\u3002 -message.please.join.in.conference = \u8BF7\u628A\u6211\u52A0\u5165\u4F1A\u8BAE\u4E2D\u3002 -message.plugins.not.available = \u65E0\u6CD5\u8FDE\u63A5\u5230\u63D2\u4EF6\u5E93\u3002 -message.prompt.plugin.uninstall = \u662F\u5426\u786E\u5B9A\u5378\u8F7D{0} \uFF1F -message.received.file = \u4F60\u4ECE{0}\u63A5\u6536\u4E86\u4E00\u4E2A\u6587\u4EF6\u3002 -message.receiving.file = \u4F60\u6B63\u5728\u4ECE{0}\u63A5\u6536\u4E00\u4E2A\u6587\u4EF6 -message.reconnect.attempting = \u5C1D\u8BD5\u4E2D... -message.reconnect.failed = \u91CD\u65B0\u8FDE\u63A5\u5931\u8D25. -message.reconnect.wait = {0} \u79D2\u540E\u91CD\u65B0\u8FDE\u63A5. -message.register.transports = \u6CE8\u518C\u6240\u6709\u53EF\u7528\u7684\u4F20\u9001\u65B9\u5F0F\u3002 -message.registering = \u6B63\u5728\u6CE8\u518C{0}\u3002 \u8BF7\u7B49\u5F85\u2026 -message.registration.transport.failed = \u65E0\u6CD5\u5411\u7F51\u7BA1\u6CE8\u518A\u3002 -message.restart.spark = \u4F60\u9700\u8981\u5173\u95ED\u5BA2\u6237\u7AEF\u4EE5\u5B89\u88C5\u6700\u65B0\u7684\u7248\u672C\u3002 \u662F\u5426\u73B0\u5728\u5B89\u88C5\uFF1F -message.restart.spark.changes = \u63D2\u4EF6\u5C06\u5728\u4E0B\u6B21\u542F\u52A8\u65F6\u88AB\u79FB\u9664\u3002 -message.restart.spark.to.install = \u4F60\u9700\u8981\u5173\u95ED\u5BA2\u6237\u7AEF\u4EE5\u5B89\u88C5\u6700\u65B0\u7684\u7248\u672C\u3002 \u662F\u5426\u73B0\u5728\u5B89\u88C5\uFF1F -message.restart.required = \u8981\u4F7F\u65B0\u8BBE\u7F6E\u751F\u6548\uFF0C\u5FC5\u987B\u5173\u95ED\u5E76\u91CD\u65B0\u542F\u52A8.\n\u8981\u7ACB\u5373\u91CD\u65B0\u542F\u52A8\u5417? -message.room.creation.error = \u804A\u5929\u5BA4\u4E0D\u80FD\u88AB\u521B\u5EFA\u3002 -message.room.destroyed = \u6B64\u804A\u5929\u5BA4\u5DF2\u88AB\u64A4\u9500\uFF0C\u539F\u56E0\u5982\u4E0B\uFF1A {0} -message.room.destruction.reason = \u64A4\u9500\u804A\u5929\u5BA4\u7684\u539F\u56E0\uFF1F -message.room.information.for = {0}\u804A\u5929\u5BA4\u4FE1\u606F -message.save.profile = \u8981\u4FDD\u5B58\u5BF9\u4F60\u7684\u4FE1\u606F\u7684\u4FEE\u6539\uFF0C\u8BF7\u70B9\u51FB\u4FDD\u5B58\u3002 -message.search.for.contacts = \u641C\u5BFB\u8054\u7CFB\u4EBA\u3002 -message.search.input.short = \u8BF7\u81F3\u5C11\u8F93\u51655\u4E2A\u5B57\u6BCD -message.search.for.other.people = \u641C\u5BFB\u672C\u670D\u52A1\u5668\u4E0A\u7684\u5176\u4ED6\u7528\u6237\u3002 -message.search.service.not.available = \u65E0\u6CD5\u8FDE\u63A5\u5230\u641C\u7D22\u670D\u52A1\u3002 -message.searching.please.wait = \u6B63\u5728\u641C\u5BFB\u3002 \u8BF7\u7B49\u5F85\u2026 -message.select.add.room.to.add = \u8BF7\u9009\u62E9\u4E00\u95F4\u804A\u5929\u5BA4\u6DFB\u52A0\u5230\u4F60\u7684\u670D\u52A1\u540D\u5355\u3002 -message.select.one.or.more = \u5728\u8054\u7CFB\u4EBA\u540D\u5355\u4E2D\u9009\u62E9\u4E00\u4E2A\u6216\u591A\u4E2A\u7528\u6237\u3002 -message.select.room.to.enter = \u6307\u5B9A\u804A\u5929\u5BA4\u8FDB\u5165\u3002 -message.select.room.to.join = \u9009\u62E9\u804A\u5929\u5BA4\u52A0\u5165\u3002 -message.send.a.broadcast = \u53D1\u9001\u5E7F\u64AD\u6D88\u606F -message.send.file.to.user = \u53D1\u9001\u6587\u4EF6\u5230\u8FD9\u540D\u7528\u6237\u3002 -message.send.picture = \u6355\u6349\u5C4F\u5E55\u5E76\u53D1\u9001\u3002 -message.send.to.these.people = \u53D1\u9001\u7ED9\u8FD9\u4E9B\u4EBA -message.sending.file.to = \u6B63\u5728\u53D1\u9001\u6587\u4EF6\u5230{0}\u3002 -message.sent.offline.files = \u4F60\u6536\u5230\u4E86\u79BB\u7EBF\u6587\u4EF6\u3002 -message.server.unavailable = \u65E0\u6CD5\u8FDE\u63A5\u5230\u670D\u52A1\u5668: \u4E0D\u53EF\u8FBE\u7684\u4E3B\u673A\u540D\u6216\u5730\u5740. -message.service.already.exists = \u670D\u52A1\u5DF2\u7ECF\u5728\u4F60\u7684\u670D\u52A1\u540D\u5355\u3002 -message.shared.group = \u5171\u6709\u7684\u5C0F\u7EC4 -message.spark.secure = \u7A0B\u5E8F\u8FD0\u884C\u5728\u5B89\u5168\u6A21\u5F0F\u4E0B\u3002 -message.specify.contact.jid = \u8BF7\u6307\u5B9A\u8054\u7CFB\u4EBA\u7684JID (\u4F8B\u5982\uFF1Addman@jabber.org) -message.specify.group = \u6307\u5B9A\u8054\u7EDC\u5C0F\u7EC4\u6DFB\u52A0\u65B0\u7684\u7528\u6237\u3002 -message.specify.information.for.conference = \u4E3A\u4F1A\u8BAE\u5BA4\u6307\u5B9A\u4FE1\u606F\u3002 -message.specify.name.error = \u6307\u5B9A\u4E00\u4E2A\u5408\u6CD5\u7684\u540D\u5B57\u3002 -message.specify.users.to.join.conference = \u6307\u5B9A\u7528\u6237\u52A0\u5165\u8FD9\u95F4\u4F1A\u8BAE\u5BA4\u3002 -message.specify.valid.time.error = \u6307\u5B9A\u4E00\u4E2A\u5408\u6CD5\u7684\u8D85\u65F6\u65F6\u95F4\u548C\u7AEF\u53E3\u3002 -message.subject.change.error = \u4F60\u6CA1\u6709\u6743\u9650\u6539\u53D8\u8FD9\u4E2A\u804A\u5929\u5BA4\u7684\u4E3B\u9898\u3002 -message.subject.has.been.changed.to = \u4E3B\u9898\u88AB\u66F4\u6539\u4E3A{0}\u3002 -message.supply.resource = \u63D0\u4F9B\u4E00\u4E2A\u6709\u6548\u7684\u8D44\u6E90\u3002 -message.supply.valid.port = \u63D0\u4F9B\u4E00\u4E2A\u6709\u6548\u7684\u7AEF\u53E3\u3002 -message.supply.valid.timeout = \u63D0\u4F9B\u4E00\u4E2A\u6709\u6548\u7684\u8D85\u65F6\u65F6\u95F4\u3002 -message.timeout.error = \u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u5927\u6216\u7B49\u4E8E5\u79D2\u3002 -message.total.downloaded = \u5171\u8BA1\u4E0B\u8F7D\u4E86 -message.transfer.cancelled = \u6587\u4EF6\u4F20\u8F93\u88AB\u53D6\u6D88\u4E86\u3002 -message.transfer.complete = \u6587\u4EF6\u4F20\u8F93\u5B8C\u6210({0}) -message.transfer.progressbar.text.received = {0} \u63A5\u6536 @ {1} {2} -message.transfer.progressbar.text.sent = {0} \u53D1\u9001 @ {1} {2} -message.transfer.rate = \u4F20\u9001\u7387 -message.transfer.refused = \u6587\u4EF6\u4F20\u8F93\u88AB\u62D2\u7EDD\u4E86\u3002 -message.transfer.waiting.on.user = \u7B49\u5F85{0}\u63A5\u53D7\u6587\u4EF6\u7684\u4F20\u8F93\u3002 -message.unable.to.load.profile = \u65E0\u6CD5\u83B7\u53D6{0}\u7684\u4E2A\u4EBA\u4FE1\u606F -message.unable.to.retrieve.last.activity = \u65E0\u6CD5\u786E\u5B9A{0}\u7684\u6700\u540E\u6D3B\u52A8\u3002 -message.unable.to.save.password = \u65E0\u6CD5\u6539\u53D8\u5BC6\u7801\u3002 \u8BF7\u67E5\u770B\u4F60\u7684\u670D\u52A1\u5668\u7BA1\u7406\u3002 -message.unable.to.send.file = \u4F60\u65E0\u6CD5\u53D1\u9001\u6587\u4EF6\u5230{0}\u3002 -message.unable.to.use.hostname.as.resource = \u65E0\u6CD5\u5C06\u4E3B\u673A\u540D\u4F5C\u4E3A\u8D44\u6E90\u540D\u79F0\u4F7F\u7528 -message.unrecoverable.error = \u9519\u8BEF\u7684\u7528\u6237\u540D\u6216\u5BC6\u7801. -message.update.room.list = \u66F4\u65B0\u804A\u5929\u5BA4\u5217\u8868 -message.updating.cancelled = \u66F4\u65B0\u88AB\u53D6\u6D88\u4E86\u3002 -message.user.banned = {0}\u88AB\u8FD9\u4E2A\u804A\u5929\u5BA4\u5C4F\u853D\u4E86\u3002 -message.user.given.voice = {0}\u5728\u804A\u5929\u5BA4\u4E2D\u64AD\u653E\u4E86\u8BED\u97F3\u3002 -message.user.granted.admin = {0}\u88AB\u6388\u4E88\u4E86\u7BA1\u7406\u5458\u6743\u9650\u3002 -message.user.granted.membership = {0}\u88AB\u7ED9\u4E88\u4F1A\u5458\u5F85\u9047\u3002 -message.user.granted.moderator = {0}\u88AB\u6388\u4E88\u4E86\u4E3B\u6301\u4EBA\u6743\u9650\u3002 -message.user.granted.owner = {0}\u88AB\u6388\u4E88\u4E86\u6240\u6709\u8005\u6743\u9650\u3002 -message.user.is.sending.you.a.file = {0}\u6B63\u5728\u5411\u4F60\u53D1\u9001\u4E00\u4E2A\u6587\u4EF6\u3002 -message.user.joined.room = {0}\u52A0\u5165\u804A\u5929\u5BA4\u3002 -message.user.kicked.from.room = {0}\u88AB\u8E22\u51FA\u6B64\u804A\u5929\u5BA4\u3002 -message.user.left.room = {0}\u79BB\u5F00\u804A\u5929\u5BA4\u3002 -message.user.nickname.changed = {0}\u73B0\u5728\u6539\u540D\u4E3A{1}\u3002 -message.user.now.available.to.chat = {0}\u4E0A\u7EBF\u4E8E{1} -message.user.revoked.admin = \u7BA1\u7406\u5458\u6743\u9650\u88AB\u53D6\u6D88\u4E86\u4E3A{0}\u3002 -message.user.revoked.membership = \u4F1A\u5458\u8D44\u683C\u88AB\u53D6\u6D88\u4E86\u4E3A{0}\u3002 -message.user.revoked.moderator = \u4E3B\u6301\u4EBA\u6743\u9650\u88AB\u53D6\u6D88\u4E86\u4E3A{0}\u3002 -message.user.revoked.owner = \u6240\u6709\u8005\u6743\u9650\u88AB\u53D6\u6D88\u4E86\u4E3A{0}\u3002 -message.user.voice.revoked = \u58F0\u97F3\u88AB\u53D6\u6D88\u4E86\u4E3A{0}\u3002 -message.username.error = \u4E3A\u8D26\u53F7\u6307\u5B9A\u7528\u6237\u540D\u3002 -message.username.password.error = \u9700\u8981\u63D0\u4F9B\u7528\u6237\u540D\u548C\u5BC6\u7801\u3002 -message.vcard.not.supported = \u670D\u52A1\u5668\u4E0D\u652F\u6301VCards\u3002 \u65E0\u6CD5\u4FDD\u5B58\u4F60\u7684VCard\u3002 -message.version = \u7248\u672C\uFF1A {0} -message.view.information.about.this.user = \u67E5\u770B\u7528\u6237\u4FE1\u606F\u3002 -message.waiting.for.user.to.join = \u7B49\u5F85 {0} \u7684\u52A0\u5165. -message.went.offline = {0}\u8131\u673A\u4E8E{1} -message.you.have.been.banned = \u4F60\u88AB\u6B64\u804A\u5929\u5BA4\u5C4F\u853D\u4E86\u3002 -message.you.have.been.kicked = \u4F60\u88AB\u8E22\u51FA\u6B64\u804A\u5929\u5BA4 -message.you.have.sent = \u4F60\u53D1\u9001\u4E86\u4E00\u4E2A\u6587\u4EF6\u5230{0}\u3002 -message.your.admin.granted = \u4F60\u88AB\u6388\u4E88\u4E86\u7BA1\u7406\u5458\u6743\u9650\u3002 -message.your.banned = \u4F60\u88AB\u8FD9\u4E2A\u804A\u5929\u5BA4\u5C4F\u853D\u4E86\u3002 -message.your.kicked = \u4F60\u88AB{0}\u8E22\u4E86\u3002 -message.your.membership.granted = \u4F60\u88AB\u6388\u4E88\u4E86\u4F1A\u5458\u6743\u9650\u3002 -message.your.membership.revoked = \u4F60\u7684\u4F1A\u5458\u8D44\u683C\u88AB\u53D6\u6D88\u4E86\u3002 -message.your.moderator.granted = \u4F60\u88AB\u6388\u4E88\u4E86\u8C03\u89E3\u4EBA\u6743\u9650\u3002 -message.your.moderator.revoked = \u4F60\u7684\u8C03\u89E3\u4EBA\u6743\u9650\u88AB\u53D6\u6D88\u4E86\u3002 -message.your.ownership.granted = \u4F60\u88AB\u6388\u4E88\u4E86\u6240\u6709\u8005\u6743\u9650\u3002 -message.your.ownership.revoked = \u4F60\u7684\u6240\u6709\u8005\u6743\u9650\u88AB\u53D6\u6D88\u4E86\u3002 -message.your.revoked.granted = \u4F60\u7684\u7BA1\u7406\u5458\u6743\u9650\u88AB\u53D6\u6D88\u4E86\u3002 -message.your.voice.granted = \u4F60\u5728\u5BF9\u8BDD\u4E2D\u4F7F\u7528\u4E86\u8BED\u97F3\u3002 -message.your.voice.revoked = \u4F60\u7684\u58F0\u97F3\u88AB\u53D6\u6D88\u4E86\u3002 -message.groupchat.require.password = \u672C\u804A\u5929\u5BA4\u9700\u5BC6\u7801\u8FDB\u5165 -message.groupchat.registered.member = Successfully registered with {0} -message.search.for.history = Search conversation history -message.search.period.month.one = one month per page -message.search.period.year.one = one year per page -message.search.period.none = show all on one page -message.search.page.timeperiod = choose the timespan of messages, which are displayed per page -message.search.page.counter = the current index of your page and the amount of all pages -message.search.page.right = navigate one page forward -message.search.page.left = navigate one page backward -status.away = \u79BB\u5F00 -status.custom.messages = \u81EA\u5B9A\u4E49\u6D88\u606F -status.do.not.disturb = \u6B63\u5FD9 -status.extended.away = \u79BB\u5F00 -status.free.to.chat = \u7A7A\u95F2 -status.on.phone = \u7535\u8BDD\u4E2D -status.online = \u5728\u7EBF -status.pending = \u6302\u8D77 -status.invisible = \u9690\u8EAB -#status.offline = \u79BB\u7EBF -tab.available.plugins = \u53EF\u7528\u7684\u63D2\u4EF6 -tab.avatar = \u663E\u793A\u56FE\u7247 -tab.business = \u5546\u52A1 -tab.conferences = \u4F1A\u8BAE -tab.contacts = \u8054\u7CFB\u4EBA -tab.general = \u4E00\u822C -tab.home = \u5BB6\u5EAD -tab.installed.plugins = \u5DF2\u5B89\u88C5\u7684\u63D2\u4EF6 -tab.deactivated.plugins = \u672A\u6FC0\u6D3B\u7684\u63D2\u4EF6 -tab.personal = \u4E2A\u4EBA -tab.proxy = \u4EE3\u7406\u670D\u52A1\u5668 -tab.sso = \u5355\u70B9\u767B\u9646 -tab.pki = PKI -title.about = \u5173\u4E8E -title.password.required = \u9700\u5BC6\u7801 -title.task.notification = \u4EFB\u52A1\u63D0\u793A -title.client.logs = \u5BA2\u6237\u7AEF\u65E5\u5FD7 -title.advanced.connection.preferences = \u9AD8\u7EA7\u8FDE\u63A5\u8BBE\u7F6E -title.account.create.registration = \u8D26\u53F7\u6CE8\u518C -title.bookmarks = \u6536\u85CF -title.account.created = \u8D26\u53F7\u5EFA\u7ACB -title.add.contact = \u6DFB\u52A0\u8054\u7CFB\u4EBA -title.add.contact.group = \u6DFB\u52A0\u8054\u7CFB\u4EBA\u7EC4 -title.add.new.group = \u6DFB\u52A0\u65B0\u7EC4 -title.add.search.service = \u52A0\u641C\u5BFB\u670D\u52A1 -title.add.to.roster = \u6DFB\u52A0\u5230\u540D\u5355 -title.address = \u5730\u5740 -title.advanced.connection.sso = \u4F7F\u7528\u5355\u70B9\u767B\u5F55 (SSO) -title.advanced.connection.usesso = \u901A\u8FC7 GSSAPI \u4F7F\u7528\u5355\u70B9\u767B\u5F55 (SSO) -title.advanced.connection.sso.account = This will use the Desktop Account for "{0}" to login to the server. -title.advanced.connection.sso.unable = Unable to connect using Single Sign-On. Please check your principal and server settings. -title.advanced.connection.sso.noprincipal = Spark is unable to find the principal to use for Single Sign-On. This will prevent SSO from working. -title.alert = \u8B66\u62A5 -title.appearance = \u663E\u793A\u6837\u5F0F -title.appearance.preferences = \u81EA\u5B9A\u4E49 -title.available.transports = \u53EF\u7528\u7684\u4F20\u9001\u65B9\u5F0F -title.broadcast.message = \u5E7F\u64AD\u6D88\u606F -title.browse.conference.services = \u6D4F\u89C8\u4F1A\u8BAE\u670D\u52A1 -title.browse.room.service = \u6D4F\u89C8\u4F1A\u8BAE\u5BA4 - {0} -title.cancelled = \u88AB\u53D6\u6D88 -title.change.nickname = \u4FEE\u6539\u6635\u79F0 -title.change.subject = \u4FEE\u6539\u4E3B\u9898 -title.chat = \u804A\u5929 -title.choose.directory = \u9009\u62E9\u76EE\u5F55 -title.choose.incoming.sound = \u9009\u62E9\u4F20\u5165\u7684\u8BED\u97F3\u6863\u6848 -title.choose.offline.sound = \u9009\u62E9\u79BB\u7EBF\u58F0\u97F3\u6863\u6848 -title.choose.outgoing.sound = \u9009\u62E9\u8F93\u51FA\u7684\u58F0\u97F3\u6863\u6848 -title.conference.invitation = \u4F1A\u8BAE\u9080\u8BF7 -title.conference.rooms = \u4F1A\u8BAE\u5BA4 -title.configure.chat.room = \u8BBE\u7F6E\u804A\u5929\u5BA4 -title.configure.room = \u8BBE\u7F6E\u623F\u95F4 -title.confirmation = \u786E\u8BA4 -title.create.new.account = \u5EFA\u7ACB\u65B0\u8D26\u53F7 -title.create.or.bookmark.room = \u8FDE\u63A5\u6216\u4E66\u7B7E\u623F\u95F4 -title.create.or.join = \u5EFA\u7ACB/\u8FDE\u63A5 -title.create.problem = \u8D26\u53F7\u521B\u5EFA\u95EE\u9898 -title.delete.file = \u771F\u7684\u8981\u5220\u9664\u8FD9\u4E2A\u6587\u4EF6\u5417\uFF1F -title.dial.phone = \u62E8\u7535\u8BDD -title.disable.transport = \u79FB\u9664\u767B\u5F55\u4FE1\u606F -title.download.complete = \u4E0B\u8F7D\u5B8C\u6210 -title.downloading.im.client = \u4E0B\u8F7D IM \u5BA2\u6237\u7AEF -title.downloads = \u4E0B\u8F7D -title.edit.custom.message = \u7F16\u8F91\u7528\u6237\u72B6\u6001 -title.edit.profile = \u7F16\u8F91\u7B80\u4ECB\u4FE1\u606F -title.enter.reason = \u8F93\u5165\u7406\u7531 -title.error = \u9519\u8BEF -title.error.couldnt.open.file = \u65E0\u6CD5\u6253\u5F00\u6587\u4EF6\uFF0C\u672A\u77E5\u6587\u4EF6\u7C7B\u578B\uFF01 -title.error.delete.file = \u5220\u9664\u6587\u4EF6\u5931\u8D25\uFF01 -title.error.find.app = \u672A\u627E\u5230\u76F8\u5E94\u7684\u5E94\u7528\u7A0B\u5E8F\uFF01 -title.error.rename.file = \u672A\u80FD\u5BF9\u6587\u4EF6\u91CD\u547D\u540D\uFF01 -title.file = \u6587\u4EF6 -title.filesize = \u6587\u4EF6\u5927\u5C0F -title.file.exists = \u6587\u4EF6\u5B58\u5728 -title.file.transfer = \u6587\u4EF6\u4F20\u8F93 -title.file.transfer.preferences = \u6587\u4EF6\u4F20\u8F93\u8BBE\u7F6E -title.find.conference.service = \u67E5\u627E\u4F1A\u8BAE\u670D\u52A1 -title.find.contacts = \u67E5\u627E\u8054\u7CFB\u4EBA -title.gadugadu.registration = GaduGadu \u8D26\u53F7\u8BBE\u7F6E -title.general.media = \u591A\u5A92\u4F53\u8BBE\u7F6E -title.general.chat.settings = \u5E38\u89C4\u804A\u5929\u8BBE\u7F6E -title.group.chat = \u7FA4\u804A -title.group.chat.settings = \u7FA4\u804A\u8BBE\u7F6E -title.gtalk.registration = GTalk \u8D26\u53F7\u8BBE\u7F6E -title.history.for = \u4E0E{0}\u7684\u804A\u5929\u8BB0\u5F55 -title.icq.registration = ICQ \u8D26\u53F7\u8BBE\u7F6E -title.irc.registration = IRC \u8D26\u53F7\u8BBE\u7F6E -title.aim.registration = AIM\u6CE8\u518C -title.sametime.registration = Sametime\u8D26\u53F7 -title.facebook.registration = Facebook\u8D26\u53F7 -title.myspace.registration = MySpace\u8D26\u53F7 -title.incoming.call = \u8FDE\u5165\u7684\u7535\u8BDD -title.input.fileexplorer = \u8F93\u5165\u60A8\u7684\u6587\u4EF6\u6D4F\u89C8\u5668\u540D\u79F0 -title.input.newname = \u8F93\u5165\u65B0\u7684\u540D\u79F0\uFF1A -title.input.openwith = \u8F93\u5165\u5E94\u7528\u7A0B\u5E8F\u540D\u79F0\uFF1A -title.invite.to.conference = \u9080\u8BF7\u5230\u4F1A\u8BAE -title.jabber.browser = \u6D4F\u89C8\u5668 -title.join.conference.room = \u8FDE\u63A5\u4F1A\u8BAE\u5BA4 -title.last.activity = \u6700\u540E\u4E00\u4E2A\u6D3B\u52A8 -title.login = \u767B\u5F55 -title.login.error = \u767B\u5F55\u51FA\u9519 -title.login.settings = \u767B\u5F55\u8BBE\u7F6E -title.login.no.account = Unable to determine -title.lookup.profile = \u67E5\u770B\u7B80\u4ECB -title.msn.registration = MSN \u8D26\u53F7\u8BBE\u7F6E -title.name = \u540D\u5B57 -title.new.client.available = \u65B0\u7684\u53EF\u7528\u5BA2\u6237\u7AEF -title.new.roster.group = \u65B0\u540D\u5355\u7EC4 -title.new.version.available = \u65B0\u7684\u53EF\u7528\u7248\u672C -title.no.updates = \u5F53\u524D\u65E0\u53EF\u7528\u66F4\u65B0 -title.notes = \u8BB0\u4E8B\u672C -title.notification = \u901A\u77E5 -title.notifications = \u901A\u77E5 -title.occupants = \u5360\u6709\u8005 -title.on.the.phone = \u7535\u8BDD\u4E2D -title.password = \u5BC6\u7801 -title.passwords.no.match = \u786E\u8BA4\u5BC6\u7801\u3002 -title.person.search = \u67E5\u627E\u8054\u7CFB\u4EBA -title.plugins = \u63D2\u4EF6 -title.preferences = \u8BBE\u7F6E -title.profile.information = \u4E2A\u4EBA\u8D44\u6599 -title.profile.not.found = \u6CA1\u627E\u5230\u4E2A\u4EBA\u8D44\u6599 -title.qq.registration = QQ \u8D26\u53F7\u8BBE\u7F6E -title.register.account = \u6CE8\u518C\u65B0\u8D26\u53F7 -title.registration.error = \u6CE8\u518C\u9519\u8BEF -title.reminder = \u63D0\u9192 -title.rename.roster.group = \u91CD\u547D\u540D\u8054\u7CFB\u4EBA\u7EC4 -title.room.destroyed = \u623F\u95F4\u64A4\u9500 -title.room.information = \u623F\u95F4\u4FE1\u606F -title.roster = \u540D\u5355 -title.select.file.to.send = \u9009\u62E9\u8981\u53D1\u9001\u7684\u6587\u4EF6 -title.set.status.message = \u8BBE\u7F6E\u72B6\u6001\u6D88\u606F -title.simple.registration = SIMPLE \u8D26\u53F7\u8BBE\u7F6E -title.sound.preferences = \u58F0\u97F3\u8BBE\u7F6E -title.sounds = \u58F0\u97F3 -title.spark.preferences = \u8BBE\u7F6E -title.start.chat = \u5F00\u59CB\u804A\u5929 -title.status.message = \u72B6\u6001\u6D88\u606F -title.tasks = \u4EFB\u52A1 -title.transports = \u4F20\u9001\u65B9\u5F0F -title.tray.information = \u6258\u76D8\u4FE1\u606F -title.upgrading.client = \u5347\u7EA7\u5BA2\u6237\u7AEF -title.version.and.time = \u7248\u672C\u548C\u65F6\u95F4 -title.view.bookmarks = \u67E5\u770B\u4E66\u7B7E -title.view.profile.for = \u67E5\u770B{0}\u7684\u4E2A\u4EBA\u4FE1\u606F -title.view.room.information = \u67E5\u770B\u623F\u95F4\u4FE1\u606F -title.waiting.to.call = \u7B49\u4FAF\u6253\u7535\u8BDD -title.xmpp.registration = XMPP \u8D26\u53F7\u8BBE\u7F6E -title.yahoo.registration = Yahoo \u8D26\u53F7\u8BBE\u7F6E -title.appearance.showVCards = \u8054\u7CFB\u4EBA\u5217\u8868\u91CC\u663E\u793A\u540D\u7247 -title.subscription.request = \u6DFB\u52A0\u597D\u53CB\u8BF7\u6C42 -tooltip.place.a.call = \u4E0E\u4E00\u4EBA\u901A\u8BDD -tooltip.appearance = \u4FEE\u6539\u4F1A\u8BDD\u663E\u793A\u6837\u5F0F. -tooltip.file.transfer = \u6587\u4EF6\u4F20\u8F93\u8BBE\u7F6E -tooltip.notifications = \u63A5\u6536\u6D88\u606F\u901A\u77E5\u8BBE\u7F6E -tooltip.place.voice.call = \u8BF7\u81F4\u7535\u8BED\u97F3\u5BF9\u8BDD -tooltip.send.email = \u53D1\u9001\u90AE\u4EF6. -tooltip.start.chat = \u5F00\u59CB\u804A\u5929. -tooltip.view.changelog = \u67E5\u770B\u53D8\u5316\u8BB0\u5F55 -tooltip.view.history = \u67E5\u770B\u4F1A\u8BDD\u5386\u53F2\u8BB0\u5F55 -tooltip.view.readme = \u67E5\u770B ReadMe -tree.conference.services = \u4F1A\u8BAE\u670D\u52A1 -tree.users.in.room = \u5728\u623F\u95F4\u7684\u4F7F\u7528\u8005 -lookandfeel.select = \u9009\u62E9\u89C6\u611F -lookandfeel.change.now = \u7ACB\u5373\u6539\u53D8 -lookandfeel.tooltip.restart.no = \u65E0\u9700\u91CD\u542F -lookandfeel.tooltip.restart.yes = \u8981\u5207\u6362\u7CFB\u7EDF\u89C6\u611F\u6309\u4FDD\u5B58\u6309\u94AE\u5E76\u91CD\u542FSpark -lookandfeel.color.label = \u989C\u8272 -lookandfeel.color.red = \u7EA2 -lookandfeel.color.green = \u7EFF -lookandfeel.color.blue = \u84DD -lookandfeel.color.opacity = \u900F\u660E\u5EA6 -lookandfeel.color.saved = \u989C\u8272\u4FDD\u5B58\u6210\u529F -privacy.title.preferences = Spark Privacy Preferences -privacy.title.panel = Please use right mouse button -privacy.label.iq.desc = Query -privacy.label.pin.desc = Presence in -privacy.label.pout.desc = Presence out -privacy.label.msg.desc = Messages -privacy.border.information = Privacy Information -privacy.label.information = Use right click menu to add or delete lists or items -privacy.root.node = Privacy Lists -privacy.label.preferences = Privacy Plugin -pricacy.tooltip.preferences = Spark privacy settings -privacy.label.list.is.active = Current active list: -privacy.label.list.is.default = Default list: -privacy.border.block = Block -privacy.pick.one.or.more = Pick one or more items to add to the list -privacy.title.add.picker = Add Items to List -privacy.node.contacts = Contacts -privacy.node.groups = Groups -privacy.menu.add.contacts = Add Contacts to list -privacy.menu.add.groups = Add Groups to list -privacy.menu.add.rem.items = Remove {0} items from list -privacy.menu.remove = Remove -privacy.menu.activate.list = Activate -privacy.menu.default.list = Set as default -privacy.menu.add.list = Add list -privacy.menu.remove.list = Remove list -privacy.dialog.add.list = Please enter list name -privacy.dialog.rem.list = Do you really want to remove {0}? -privacy.status.menu.entry = Privacy Lists -privacy.name.for.default.list = Default -privacy.button.no.list.selected = No list selected -privacy.menuitem.deactivate.current.list = Deactivate {0} -privacy.label.not.supported = Privacy lists are not supported by server. -stun.border.label = STUN fallback server -stun.server.addr = STUN Server: -stun.server.port = STUN Port: -composing = {0} \u6B63\u5728\u8F93\u5165... -paused = {0} \u5DF2\u7ECF\u505C\u6B62\u8F93\u5165 -inactive = {0} \u6B63\u5728\u5E72\u5176\u4ED6\u4E8B\u60C5 -gone = {0} \u5DF2\u7ECF\u79BB\u5F00 -action.viewlog = \u663E\u793A\u65E5\u5FD7 -dialog.confirm.to.reveal.visibility.title = Are you sure? -dialog.confirm.to.reveal.visibility.msg = If you are going to proceed your invisibility will be revealed -dialog.confirm.close.all.conferences.if.invisible.msg = If you want to proceed all conference room will be closed diff --git a/src/resources/i18n/spark_i18n_zh_TW.properties b/src/resources/i18n/spark_i18n_zh_TW.properties deleted file mode 100644 index 61a21e45b..000000000 --- a/src/resources/i18n/spark_i18n_zh_TW.properties +++ /dev/null @@ -1,1142 +0,0 @@ -## -## Spark Resource Bundle -## -## Additional locales can be specified by creating a new resource file in this -## directory using the following conventions: -## -## spark_i18n "_" language "_" country ".properties" -## spark_i18n "_" language ".properties" -## -## e.g. -## spark_i18n_en.propertis <- English resources -## spark_i18n_en_US.properties <- American US resources -## spark_i18n_de.properties <- German resources -## spark_i18n_ja.properties <- Japanese resources -## -## Please note that the two digit language code should be lower case, and the -## two digit country code should be in uppercase. Often, it is not necessary to -## specify the country code. -## -## A full list of language codes can be found at -## http://www-old.ics.uci.edu/pub/ietf/http/related/iso639.txt -## and a full list of country codes can be found at -## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html -## -## In property strings that are parameterized, single quotes can be used to -## quote the "{" (curly brace) if necessary. A real single quote is represented by ''. -## -## REVISION HISTORY (by Spark version): -## -## 2.0.1 -## Added key: 'message.restart.spark.changes' -## Added key: 'message.enter.icq' -## Added key: 'title.icq.registration' -## Added key: 'button.quit' -## -## -## -## 2.0.2 -## Added key: 'button.new' -## Added key: 'label.group' -## Added key: 'label.jabber.id' -## Added key: 'label.enter.group.name' -## Added key: 'title.new.roster.group' -## Added key: 'title.add.contact.group' -## Added key: 'message.add.contact.to.list' -## Added key: 'title.add.contact' -## Added key: 'tab.conferences' -## Added key: 'message.autenticating' -## Added key: 'title.file.transfer.preferences' -## Added key: 'menuitem.about' -## Added key: 'message.invalid.status' -## Added key: 'message.cannot.add.contact.to.shared.group -## Added key: 'message.specify.contact.jid' -## Added key: 'message.invalid.jid.error' -## Added key: 'message.specify.group' -## Added key: 'add' -## -## -## -## 2.0.5 -## Added key: 'Broadcast' -## Added key: 'label.user.on.public.network' -## Added key: 'label.network' -## -## -## 2.0.6 -## Added key: 'button.add.user' -## Added key: 'menuitem.sign.in' -## Added key: 'menuitem.sign.out' -## Added key: 'menuitem.sign.in.at.login' -## Added key: 'menuitem.enter.login.information' -## Added key: 'menuitem.delete.login.information' -## Added key: 'button.save' -## -## -## 2.5 -## Added key: 'button.start.chat' -## Added key: 'button.send.email' -## Added key: 'available' -## Added key: 'checkbox.tabs.on.top' -## Added key: 'user.has.signed.in' -## Added key: 'user.has.signed.off' -## Added key: 'label.unable.to.add.contact' -## Added key: 'label.conflict.error' -## Added key: 'message.room.creation.error' -## Added key: 'checkbox.allow.buzz' -## Added key: 'message.disconnected.group.chat.error' -## Added key: 'menuitem.show.offline.group' -## Added key: 'menuitem.move.to' -## Added key: 'menuitem.copy.to' -## Added key: 'label.message.style' -## Added key: 'label.emoticons' -## Added key: 'checkbox.enable.emoticons' -## Added key: 'message.unable.to.retrieve.last.activity' -## Added key: 'checkbox.use.system.look.and.feel' -## -## 2.5.2 -## Added key: 'tooltip.place.voice.call' -## Added key: 'message.buzz.alert.notification' -## Added key: 'message.buzz.sent' -## -## 2.5.2 -## Added key: 'menuitem.user.guide' -## -## -## -## 2.5.7 -## Added key: 'menuitem.languages' -## Added key: 'message.restart.required' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'message.send.to.these.people' -## Added key: 'message' -## Added key: 'message.normal' -## Added key: 'message.alert.notify' -## -## 2.5.8 -## Added key: 'message.enter.simple' -## Added key: 'message.enter.irc' -## Added key: 'message.enter.gadugadu' -## Added key: 'title.simple.registration' -## Added key: 'title.irc.registration' -## Added key: 'title.gadugadu.registration' -## Added key: 'message.username.error' -## Added key: 'message.password.error' -## Added key: 'message.nickname.error' -## -## 2.5.9 -## Added key: 'message.gateway.username.error. -## Added key: 'message.gateway.password.error. -## Added key: 'message.gateway.nickname.error. -## Added key: 'answer' -## Added key: 'online' -## Added key: 'online' -## Added key: 'offline' -## Added key: 'participants' -## Added key: 'unfiled' -## Added key: 'while.offline' -## Added key: 'action.clear' -## Added key: 'action.copy ' -## Added key: 'action.cut' -## Added key: 'action.paste' -## Added key: 'action.print' -## Added key: 'action.save' -## Added key: 'action.select.all' -## Added key: 'button.add2' -## Added key: 'button.copy.to.clipboard' -## Added key: 'button.reconnect2' -## Added key: 'button.tasks.active' -## Added key: 'button.tasks.all' -## Added key: 'button.view.notes' -## Added key: 'button.view.profile' -## Added key: 'button.view.tasklist' -## Added key: 'checkbox.notify.user.comes.online' -## Added key: 'checkbox.notify.user.goes.offline' -## Added key: 'checkbox.show.avatars.in.contaclist' -## Added key: 'checkbox.use.compression' -## Added key: 'group.empty' -## Added key: 'group.offline' -## Added key: 'label.add.task' -## Added key: 'label.chatroom.fontsize' -## Added key: 'label.contactlist.fontsize' -## Added key: 'label.due' -## Added key: 'label.show' -## Added key: 'label.timeformat' -## Added key: 'menuitem.dial' -## Added key: 'menuitem.view.logs' -## Added key: 'message.disconnected.shutdown' -## Added key: 'message.invalid.username.password' -## Added key: 'message.no.updates' -## Added key: 'message.reconnect.attempting' -## Added key: 'message.reconnect.failed' -## Added key: 'message.reconnect.wait' -## Added key: 'message.send.picture' -## Added key: 'message.server.unavailable' -## Added key: 'message.unrecoverable.error' -## Added key: 'message.waiting.for.user.to.join' -## Added key: 'status.available' -## Added key: 'status.away' -## Added key: 'status.custom.messages' -## Added key: 'status.do.not.disturb' -## Added key: 'status.extended.away' -## Added key: 'status.free.to.chat' -## Added key: 'status.on.phone' -## Added key: 'status.online' -## Added key: 'status.pending' -## Added key: 'title.about' -## Added key: 'title.appearance' -## Added key: 'title.appearance.preferences' -## Added key: 'title.login.error' -## Added key: 'title.no.updates' -## Added key: 'title.notes' -## Added key: 'title.tasks' -## Added key: 'tooltip.appearance' -## Added key: 'tooltip.file.transfer' -## Added key: 'tooltip.send.email' -## Added key: 'tooltip.start.chat' -## Added key: 'delete.log.permanently' -## Added key: 'delete.permanently' -## Added key: 'label.contactlist.avatarsize' -## Added key: 'title.qq.registration' -## Added key: 'message.enter.qq' -## -## 2.6.0 -## -## Added key: 'apply' -## Added key: 'title.subscription.request' -## Added key: 'label.add.to.roster' -## Added key: 'label.audio.device' -## Added key: 'label.video.device' -## Added key: 'button.re.detect' -## -## 2.6.0 beta 1 -## Added key: 'menuitem.block.contact' -## Added key: 'menuitem.unblock.contact' -## Removed key: 'status.available' -## Added key: 'message.nickname.not.acceptable' -## Added key: 'button.login' -## Added key: 'administrator' -## Added key: 'menuitem.add.groupchat.showrolesinsteadofstatus' -## Added key: 'checkbox.click.single.tray' -## -## 2.6.4 -## Added key: 'menuitem.add.groupchat.showrolesinsteadofstatus' -## Added key: 'menuitem.add.groupchat.auto.accept.invite' -## Added key: 'menuitem.add.groupchat.random.colors' -## Added key: 'label.time.till.idlemessage' -## Added key: 'lookandfeel.select' -## Added key: 'lookandfeel.change.now' -## Added key: 'lookandfeel.color.label' -## Added key: 'lookandfeel.color.red' -## Added key: 'lookandfeel.color.green' -## Added key: 'lookandfeel.color.blue' -## Added key: 'lookandfeel.color.opacity' -## Added key: 'lookandfeel.color.saved' -## Added key: 'checkbox.transport.tab.setting' -## Added key: 'checkbox.conference.tab.setting' -## Added key: 'checkbox.reconnet.info' -## Added key: 'checkbox.reconnect.panel.big' -## Added key: 'checkbox.reconnect.panel.small' -## Added key: 'checkbox.reconnect.panel.icon' -## -## 2.7.0 beta 1 -## Added key: 'message.search.period.month.one' -## Added key: 'message.search.period.year.one' -## Added key: 'message.search.period.none' -## Added key: 'message.search.page.timeperiod' -## Added key: 'message.search.page.counter' -## Added key: 'message.search.page.right' -## Added key: 'message.search.page.left' -## Added key: 'checkbox.sort.asc.history' -## Added key: 'message.file.transfer.dirnull' -## Added key: 'message.file.transfer.nodir' -## Added key: 'message.file.transfer.cantwritedir' -## Added key: 'message.file.transfer.direrror.setdir' - - -ok = \u78BA\u5B9A -cancel = \u53D6\u6D88 -add = \u65B0\u589E -use.default = \u4F7F\u7528\u9810\u8A2D -close = \u95DC\u9589 -create = \u5275\u5EFA -invite = \u9080\u8ACB -date = \u65E5\u671F -from = \u5F9E -room.name = \u6703\u8B70\u5BA4\u540D\u7A31 -join = \u52A0\u5165 -description = \u63CF\u8FF0 -subject = \u4E3B\u984C -occupants = \u6703\u8B70\u5BA4\u623F\u5BA2 -accept = \u63A5\u53D7 -reject = \u62D2\u7D55 -open = \u6253\u958B -open.folder = \u6253\u958B\u8CC7\u6599\u593E -retry = \u91CD\u8A66 -active = \u6D3B\u8E8D -not.registered = \u672A\u8A3B\u518A -save = \u5132\u5B58 -yes = \u662F -no = \u5426 -broadcast = \u5EE3\u64AD -available = \u7A7A\u9592 -user.has.signed.in = \u5DF2\u7C3D\u5230 -user.has.signed.off = \u5DF2\u7C3D\u96E2 -unfiled = \u672A\u5206\u985E -refresh = \u5237\u65B0 -participants = \u53C3\u8207\u8005 -online = \u5728\u7DDA -offline = \u96E2\u7DDA -administrator = \u7BA1\u7406\u8005 -answer = \u56DE\u8986 -apply = \u61C9\u7528 -while.offline = \u7576\u524D\u96E2\u7DDA - -action.clear = \u6E05\u9664 -action.copy = \u8907\u88FD -action.cut = \u526A\u4E0B -action.paste = \u8CBC\u4E0A -action.print = \u5370\u51FA -action.save = \u5132\u5b58 -action.select.all = \u5168\u9078 - -button.create.account = (&C) \u5275\u5EFA\u5E33\u6236 -button.close = (&L) \u95DC\u9589 -button.copy.to.clipboard = \u8907\u88FD\u5230\u526A\u8CBC\u7C3F -button.advanced = (&V) \u9032\u968E -button.browse = (&B) \u700F\u89BD\u2026 -button.browse2 = (&R) \u700F\u89BD\u2026 -button.browse3 = (&O) \u700F\u89BD\u2026 -button.approve = (&A) \u6279\u51C6 -button.deny = (&D) \u5426\u8A8D -button.accept = (&A) \u63A5\u53D7 -button.reject = \u99C1\u56DE -button.profile = (&P) \u7C21\u4ECB -button.add.a.contact = (&A) \u65B0\u589E\u806F\u7D61\u4EBA -button.reconnect = (&R) \u91CD\u65B0\u9023\u63A5 -button.reconnect2 = \u91CD\u65B0\u9023\u63A5 -button.add = (&A) \u65B0\u589E -button.add2 = \u65B0\u589E -button.roster = (&R) \u806f\u7d61\u4eba\u540d\u55ae -button.add.bookmark = \u65B0\u589E\u66F8\u7C3D -button.remove.bookmark = \u79FB\u9664\u66F8\u7C3D -button.bookmark.room = (&B) \u66F8\u7C3D\u623F\u9593 -button.create.room = (&C) \u5275\u5EFA\u6216\u52A0\u5165\u623F\u9593 -button.join.room = (&J) \u52A0\u5165\u9078\u64C7\u7684\u623F\u9593 -button.login = \u767B\u5165 -button.refresh = (&R) \u5237\u65B0 -button.find = (&F) \u641C\u5C0B -button.update = (&U) \u66F4\u65B0 -button.cancel = (&C) \u53D6\u6D88 -button.decline = (&D) \u62D2\u7D55 -button.join = (&J) \u52A0\u5165 -button.save.for.future.use = (&S) \u5132\u5B58\u4EE5\u5099\u4EE5\u5F8C\u4F7F\u7528 -button.register = (&R) \u8A3B\u518A -button.dial.number = (&D) \u64A5\u865F -button.clear = (&C) \u6E05\u9664 -button.search = (&S) \u641C\u5C0B -button.add.service = (&A) \u65B0\u589E\u670D\u52D9 -button.quit = (&Q) \u96E2\u958B -button.new = (&N) \u65B0\u589E -button.add.user = (&A) \u65B0\u589E\u5E33\u6236 -button.save = (&S) \u5132\u5b58 -button.start.chat = \u804A\u5929 -button.send.email = \u96FB\u5B50\u90F5\u4EF6 -button.send = \u767C\u9001 -button.tasks.active = \u6D3B\u8E8D -button.tasks.all = \u5168\u90E8 -button.unset.file.explorer = \u672A\u8A2D\u7F6E\u6587\u4EF6\u700F\u89BD\u5668 -button.view.notes = \u67E5\u770B\u7B46\u8A18 -button.view.profile = \u67E5\u770B\u5B8C\u6574\u500B\u4EBA\u8CC7\u6599 -button.view.tasklist = \u67E5\u770B\u4EFB\u52D9\u5217\u8868 -button.re.detect = \u91CD\u65B0\u6AA2\u6E2C - -checkbox.save.password = (&S) \u4FDD\u5B58\u5BC6\u78BC -checkbox.auto.login = (&A) \u555f\u52d5 Spark \u5f8c\u81ea\u52d5\u767b\u5165 -checkbox.login.as.invisible = \u96E2\u7DDA\u72C0\u614B\u767B\u5165 -checkbox.use.proxy.server = (&U) \u4f7f\u7528\u4ee3\u7406\u4f3a\u670d\u5668 -checkbox.auto.discover.port = (&A) \u81ea\u52d5\u6aa2\u6e2c\u4e3b\u6a5f\u548c\u9023\u63a5\u57e0 -checkbox.permanent = (&P) \u6703\u8B70\u5BA4\u662F\u56FA\u5B9A\u7684 -checkbox.private.room = (&I) \u6703\u8B70\u5BA4\u662F\u79C1\u4EBA\u7684 -checkbox.show.time.in.chat.window = \u804a\u5929\u8996\u7a97\u986f\u793a\u6642\u9593 -checkbox.show.notifications.in.conference = (&S) \u5728\u6703\u8B70\u5BA4\u986F\u793A\u901A\u77E5 -checkbox.disable.chat.history = (&D) \u4e0d\u555f\u52d5\u804a\u5929\u8a18\u9304\u529f\u80fd -checkbox.show.toaster = (&T) \u986F\u793A\u4E00\u500B\u5F48\u51FA\u7A97\u53E3 -checkbox.window.to.front = (&B) \u7A97\u53E3\u7F6E\u65BC\u6700\u524D\u9762 -checkbox.play.sound.on.new.message = (&A) \u7576\u6536\u5230\u65B0\u6D88\u606F\u6642\u64AD\u653E\u8072\u97F3 -checkbox.play.sound.when.offline = (&O) \u7576\u806f\u7d61\u4eba\u96e2\u7dda\u6642\u64ad\u653e\u8072\u97f3 -checkbox.play.sound.on.outgoing.message = (&S) \u7576\u767C\u9001\u6D88\u606F\u6642\u64AD\u653E\u8072\u97F3 -checkbox.play.sound.on.invitation = (&I) \u7576\u6536\u5230\u9080\u8ACB\u6642\u64AD\u653E\u8072\u97F3 -checkbox.idle.enabled = (&I) \u555f\u52d5\u9592\u7f6e\u72c0\u614b -checkbox.launch.on.startup = (&L) \u958B\u6A5F\u6642\u555F\u52D5 Spark -checkbox.start.in.tray = (&S) \u555F\u52D5\u5F8C\u986F\u793A\u81F3\u6642\u9593\u5DE5\u5177\u5217\u5167 -checkbox.split.chat.window = (&W) \u804A\u5929\u8996\u7A97\u501A\u9760\u684C\u9762(\u9700\u91cd\u65b0\u555f\u52d5 Spark) -checkbox.tabs.on.top = (&C) \u804a\u5929\u8996\u7a97\u7f6e\u9802(\u9700\u91cd\u65b0\u555f\u52d5 Spark) -checkbox.use.compression = \u4F7F\u7528\u58D3\u7E2E -checkbox.use.debugger.on.startup = \u5728\u958B\u6A5F\u6642\u555f\u52D5\u5075\u932F\u7A0B\u5E8F -checkbox.allow.buzz = (&Z) \u5141\u8a31\u806f\u7d61\u4eba\u4e3b\u52d5\u7d66\u60a8\u767c\u8a0a\u606f -checkbox.enable.emoticons = (&O) \u555F\u52D5\u8868\u60C5\u7B26\u865F\u529F\u80FD -checkbox.use.system.look.and.feel = (&F) \u4F7F\u7528\u7CFB\u7D71\u5916\u89C0(\u9700\u91cd\u65b0\u555f\u52d5 Spark) -checkbox.use.hostname.as.resource = \u4f7f\u7528\u4e3b\u6a5f\u540d\u4f5c\u70ba\u4f86\u6e90 -checkbox.use.version.as.resource = \u4f7f\u7528 Spark \u7248\u672c\u4f5c\u70ba\u4f86\u6e90 -checkbox.use.pki.authentication = \u4F7F\u7528PKI\u8A8D\u8B49 -checkbox.broadcast.hide.offline.user = \u96b1\u85cf\u96e2\u7dda\u806f\u7d61\u4eba -checkbox.show.avatars.in.contactlist = \u5728\u806f\u7d61\u4eba\u5217\u8868\u986f\u793a\u982d\u50cf -checkbox.click.single.tray = \u6ED1\u9F20\u9EDE\u64CA\u4E00\u4E0B\u5373\u53EF\u9032\u5165Spark\u7684\u7CFB\u7D71\u524D\u53F0 -checkbox.sort.asc.history = \u5C0D\u8A71\u8A18\u9304\u4F9D\u65E5\u671F\u7531\u9060\u800C\u8FD1\u6392\u5E8F -checkbox.disable.prev.chat.history = \u4e0d\u986f\u793a\u4e4b\u524d\u7684\u804a\u5929\u8a18\u9304 -checkbox.graying.out = \u6de1\u5316\u9592\u7f6e\u806f\u7d61\u4eba(\u9700\u91cd\u65b0\u555f\u52d5 Spark) -checkbox.reconnet.info = \u6307\u5B9A\u91CD\u65B0\u9023\u63A5\u7684\u986F\u793A\u65B9\u5F0F\uFF1A -checkbox.reconnect.panel.big = \u6309\u7167\u9762\u677F\u65B9\u5F0F\u986F\u793A -checkbox.reconnect.panel.small = \u6309\u7167\u806F\u7E6B\u4EBA\u5206\u7D44\u65B9\u5F0F\u986F\u793A -checkbox.reconnect.panel.icon = \u6309\u7167\u5716\u6A19\u65B9\u5F0F\u986F\u793A -checkbox.notify.user.comes.online = \u7576\u806f\u7d61\u4eba\u4e0a\u7dda\u6642\u901a\u77e5 -checkbox.notify.user.goes.offline = \u7576\u806f\u7d61\u4eba\u96e2\u7dda\u6642\u901a\u77e5 -checkbox.notify.typing.systemtray = \u5728\u7CFB\u7D71\u4EFB\u52D9\u6B04\u4E0A\u986F\u793A\u6B63\u5728\u6253\u5B57\u8A0A\u606F -checkbox.notify.systemtray = \u5728\u6642\u9593\u5DE5\u5177\u5217\u4E0A\u8DF3\u51FA\u65B0\u8A0A\u606F\u901A\u77E5 -checkbox.use.krbconf = \u4F7F\u7528krb5.conf\u6216krb5.ini -checkbox.use.krb.dns = \u4F7F\u7528DNS -checkbox.use.specify.below = \u6307\u5B9A\u65B9\u5F0F\u5982\u4E0B -checkbox.transport.tab.setting = \u5728\u6A19\u7C64\u4E2D\u986F\u793A\u53EF\u7528\u7684\u50B3\u8F38\u670D\u52D9(\u9700\u91cd\u65b0\u555f\u52d5 Spark) -checkbox.conference.tab.setting = \u5728\u6A19\u7C64\u4E2D\u986F\u793A\u6703\u8B70\u670D\u52D9(\u9700\u91cd\u65b0\u555f\u52d5 Spark) -checkbox.display.time = \u986f\u793a\u6642\u9593 {0} \u79d2 - -delete.log.permanently = \u6C38\u4E45\u522A\u9664\u65E5\u8A8C -delete.permanently = \u6C38\u4E45\u522A\u9664\u55CE? - -gateway.username.password.error = \u9700\u8981\u63D0\u4F9B\u7528\u6236\u540D\u7A31\u548C\u5BC6\u78BC - -group.connection = \u9023\u7DDA -group.conferences.found = \u627E\u5230\u6703\u8B70\u670D\u52D9 -group.comma.delimited = \u4ee5\u9017\u865f\u5206\u9694 -group.general.information = \u4E00\u822C\u8CC7\u8A0A -group.chat.window.information = \u804a\u5929\u8996\u7a97\u8cc7\u8a0a -group.notification.options = \u901a\u77e5\u9078\u9805 -group.search.form = \u641c\u5c0b\u6e05\u55ae -group.search.results = \u641C\u5C0B\u7D50\u679C -group.login.information = \u767B\u5165\u8CC7\u8A0A -group.empty = \u6b64\u7fa4\u7d44\u7121\u5728\u7dda\u806f\u7d61\u4eba -group.offline = \u96e2\u7dda\u806f\u7d61\u4eba\u7fa4\u7d44 -group.chat.name.notification = \u770b\u898b\u4f60\u7684\u540d\u5b57... -group.chat.name.match = \u6709\u4eba\u5728\u7fa4\u7d44\u804a\u5929\u5ba4\u4e2d\u63d0\u5230\u4f60\u7684\u540d\u5b57: - -label.user.on.public.network = \u806f\u7d61\u4eba\u4f4d\u65bc\u516c\u5171\u7db2\u8def\u4e0a -label.change.password.to = (&C) \u8b8a\u66f4\u5bc6\u78bc -label.username = (&U) \u7528\u6236\u540d\u7a31 -label.name = (&N) \u540d\u5b57 -label.room.name = (&R) \u6703\u8b70\u5ba4\u540d\u7a31 -label.room.topic = (&T) \u6703\u8b70\u5ba4\u4e3b\u984c -label.password = (&P) \u5bc6\u78bc -label.confirm.password = (&C) \u78ba\u8a8d\u5bc6\u78bc -label.server = (&S) \u4f3a\u670d\u5668 -label.create.account = (&A) \u5efa\u7acb\u65b0\u5e33\u6236 -label.close = (&L) \u95DC\u9589 -label.ok = \u78BA\u8A8D -label.cancel = \u53D6\u6D88 -label.use.default = \u4f7f\u7528\u9810\u8a2d -label.port = (&P) \u9023\u63a5\u57e0 -label.auto.login = (&A) \u555f\u52d5 Spark \u5f8c\u81ea\u52d5\u767b\u5165 -label.old.ssl = (&U) \u4f7f\u7528\u820a\u7684\u9023\u63a5\u57e0 -label.host = (&H) \u4E3B\u6A5F -label.resource = (&R) \u8CC7\u6E90 -label.protocol = (&P) \u5354\u8B70 -label.accounts = (&A) \u5E33\u6236 -label.receieved = (&R) \u63A5\u53D7 -label.transfer.timeout = (&T) \u50B3\u8F38\u8D85\u6642(\u5206\u9418) \uFF1A -label.transfer.download.directory = (&D) \u4e0b\u8f09\u6a94\u6848\u5b58\u653e\u76ee\u9304 -label.find = (&F) \u5c0b\u627e -label.rename.to = \u91CD\u65B0\u547D\u540D -label.contact.to.find = \u5c0b\u627e\u806f\u7d61\u4eba -label.available.users.in.roster = (&A) \u5728\u7DDA\u806F\u7D61\u4EBA\u5217\u8868 -label.time = \u6642\u9593\uFF1A {0} -label.add.conference.service = (&A) \u65B0\u589E\u6703\u8B70\u670D\u52D9 -label.add.jid = (&A) \u65b0\u589eJID -label.message = (&M) \u8a0a\u606f -label.room = (&R) \u6703\u8b70\u5ba4 -label.invited.users = \u88ab\u9080\u8acb\u7684\u806f\u7d61\u4eba -label.new.nickname = \u65b0\u7684\u66b1\u7a31 -label.server.address = (&S) \u4f3a\u670d\u5668\u4f4d\u5740 -label.nickname = (&C) \u66b1\u7a31 -label.presence = (&P) \u5B58\u5728 -label.priority = (&R) \u512a\u5148 -label.enter.address = \u9032\u5165\u4f4d\u5740 -label.jabber.address = &Jabber\u4f4d\u5740 -label.local.time = (&L) \u672C\u5730\u6642\u9593 -label.software = (&S) \u8edf\u9ad4 -label.version = (&V) \u7248\u672C -label.os = (&O) \u64CD\u4F5C\u7CFB\u7D71 -label.number = (&N) \u865f\u78bc -label.dial = (&D) \u64a5\u865f -label.minutes.before.stale.chat = (&M) \u6703\u8b70\u5ba4\u591a\u4e45\u5f8c\u9032\u5165\u66ab\u505c\u6a21\u5f0f -label.company = (&C) \u516C\u53F8 -label.street.address = (&S) \u8857\u9053\u5730\u5740 -label.city = (&C) \u57CE\u5E02 -label.state.and.province = (&T) \u5DDE/\u7701 -label.postal.code = (&P) \u90f5\u905e\u5340\u865f -label.country = (&O) \u56FD\u5BB6 -label.job.title = (&J) \u8077\u7A31 -label.department = (&D) \u90E8\u9580 -label.phone = (&P) \u96FB\u8A71 -label.fax = (&F) \u50B3\u771F -label.mobile = (&M) \u624b\u6a5f\u865f\u78bc -label.web.page = (&W) \u7DB2\u9801 -label.pager = (&P) \u547c\u53eb\u5668 -label.first.name = (&F) \u540D\u5B57 -label.middle.name = (&M) \u4E2D\u9593\u540D -label.last.name = (&L) \u59D3 -label.email.address = (&E) \u96FB\u5B50\u90F5\u4EF6 -label.jid = &JID -label.search.service = (&S) \u641c\u5c0b\u670d\u52d9 -label.xmpp.port = (&X) XMPP \u9023\u63a5\u57e0 -label.response.timeout = (&R) \u56de\u61c9\u903e\u6642(\u79D2) -label.time.till.idle = (&T) \u9592\u7f6e\u6642\u91cd\u65b0\u9023\u63a5\u6642\u9593(\u5206\u9418) -label.jabber.id = &Jabber \u7DE8\u865F -label.group = (&G) \u7fa4\u7d44 -label.enter.group.name = \u8f38\u5165\u65b0\u7684\u7fa4\u7d44\u540d\u7a31 -label.network = (&K) \u7db2\u8def -label.unable.to.add.contact = \u7121\u6CD5\u65B0\u589E\u806F\u7D61\u4EBA\u3002 -label.conflict.error = \u5e33\u6236\u5df2\u7d93\u767b\u5165\uff0c\u7121\u6cd5\u91cd\u8986\u767b\u5165 -label.message.style = (&M) \u8a0a\u606f\u6a23\u5f0f -label.emoticons = (&E) \u8868\u60C5 -label.which.pki.method = \u5176\u4E2DPKI\u65B9\u6CD5\uFF1F -label.keystore.location = \u9470\u5319\u5132\u5B58\u4F4D\u7F6E -label.choose.file = \u9078\u64C7\u6A94\u6848 -label.truststore.location = \u4FE1\u4EFB\u5EAB\u4F4D\u7F6E -label.trust.store.password = \u4FE1\u4EFB\u5EAB\u5BC6\u78BC -label.pkcs.library.file = PKCS#11\u5EAB\u6587\u4EF6 -label.apple.keychain = Apple\u9470\u5319\u5708 -label.na = n/a -label.cell = \u5143\u4ef6 -label.work = \u5de5\u4f5c -label.home = \u9996\u9801 -label.passwordreset = \u91cd\u8a2d\u5bc6\u78bc -label.add.task = \u65b0\u589e\u4efb\u52d9 -label.avatar = \u982d\u50cf\u5716\u7247: -label.chatroom.fontsize = \u804a\u5929\u5ba4\u5b57\u9ad4\u5927\u5c0f: -label.recent.conversation = \u6700\u8fd1\u7684\u5c0d\u8a71 -label.frequent.contacts = \u5e38\u7528\u806f\u7d61\u4eba -label.contactlist.avatarsize = \u806f\u7d61\u4eba\u5217\u8868\u982d\u50cf\u5716\u7247\u5927\u5c0f: -label.contactlist.fontsize = \u806f\u7d61\u4eba\u5217\u8868\u5b57\u9ad4\u5927\u5c0f: -label.display.time = \u986f\u793a\u6642\u9593: -label.downloads = \u4e0b\u8f09 -label.due = \u61c9\u6709 -label.search = \u641c\u5c0b -label.seconds = \u79d2 -label.show = \u986f\u793a: -label.time.till.idlemessage = \u9592\u7f6e\u6642\u81ea\u52d5\u986f\u793a\u8a0a\u606f -label.timeformat = \u6642\u9593: {0} -label.krb.realm = \u5340\u57df -label.krb.kdc = KDC -label.enter.password = \u8f38\u5165\u5bc6\u78bc -label.move.focus.forwards = \u7126\u9ede\u79fb\u52d5\u81f3\u524d\u65b9 -label.move.focus.backwards = \u7126\u9ede\u79fb\u52d5\u81f3\u5f8c\u65b9 -label.x509.certificate = X.509 \u8b49\u66f8 -label.add.to.roster = \u65b0\u589e\u806f\u7d61\u4eba\u5230\u540d\u55ae\u4e2d -label.audio.device = \u97f3\u983b\u8a2d\u5099 -label.video.device = \u8996\u983b\u8a2d\u5099 - -menuitem.contacts = \u806f\u7d61\u4eba -menuitem.actions = \u6D3B\u52D5 -menuitem.exit = \u96e2\u958b -menuitem.plugins = \u63D2\u4EF6 -menuitem.logout.no.status = \u767B\u51FA -menuitem.logout.with.status = \u8A18\u9304\u767B\u51FA\u7684\u7406\u7531 -menuitem.show.traffic = \u986f\u793a\u901a\u4fe1\u91cf\u8996\u7a97 -menuitem.check.for.updates = \u6AA2\u67E5\u66F4\u65B0 -menuitem.help = \u8aaa\u660e -menuitem.preferences = \u8A2D\u5B9A -menuitem.about = \u95DC\u65BC -menuitem.online.help = \u7dda\u4e0a\u8aaa\u660e -menuitem.open = \u6253\u958B -menuitem.hide = \u96B1\u85CF -menuitem.status = \u72C0\u614B -menuitem.view.downloads = \u67e5\u770b\u4e0b\u8f09\u76ee\u9304 -menuitem.save = \u5132\u5b58 -menuitem.add = \u65B0\u589E -menuitem.add.contact = \u65b0\u589e\u806f\u7d61\u4eba -menuitem.add.contact.group = \u65b0\u589e\u806f\u7d61\u4eba\u7fa4\u7d44 -menuitem.remove.from.group = \u5f9e\u7fa4\u7d44\u4e2d\u79fb\u9664 -menuitem.start.a.chat = \u958b\u59cb\u804a\u5929 -menuitem.rename = \u91CD\u65B0\u547D\u540D -menuitem.delete = \u522A\u9664 -menuitem.edit = \u7DE8\u8F2F -menuitem.remove.from.roster = \u5F9E\u540D\u55AE\u4E2D\u79FB\u9664 -menuitem.view.profile = \u67E5\u770B\u7C21\u4ECB -menuitem.subscribe.to = \u540C\u610F -menuitem.send.a.message = \u5c07\u5ee3\u64ad\u8a0a\u606f\u9001\u7d66\u6307\u5b9a\u7684\u806f\u7d61\u4eba ... -menuitem.show.empty.groups = \u986f\u793a\u7a7a\u7684\u7fa4\u7d44 -menuitem.send.a.file = \u50b3\u9001\u6a94\u6848 -menuitem.view.last.activity = \u67E5\u770B\u6700\u5F8C\u4E00\u500B\u6D3B\u52D5 -menuitem.unban = \u53D6\u6D88\u7981\u6B62 -menuitem.ban = \u7981\u6B62 -menuitem.browse.service = \u700F\u89BD\u670D\u52D9 -menuitem.remove.service = \u79FB\u9664\u670D\u52D9 -menuitem.join.room = \u52a0\u5165\u9078\u64c7\u7684\u6703\u8b70\u5ba4 -menuitem.remove.bookmark = \u79FB\u9664\u66F8\u7C64 -menuitem.join.on.startup = \u7CFB\u7D71\u555F\u52D5\u6642\u9023\u63A5 -menuitem.view.room.info = \u67e5\u770b\u6703\u8b70\u5ba4\u8cc7\u8a0a -menuitem.remove = \u79FB\u9664 -menuitem.change.nickname = \u4fee\u6539\u66b1\u7a31 -menuitem.block.user = \u5c01\u9396\u6b64\u7528\u6236 -menuitem.unblock.user = \u89e3\u9664\u5c01\u9396\u6b64\u7528\u6236 -menuitem.kick.user = \u8e22\u9664\u6b64\u7528\u6236 -menuitem.voice = \u767c\u8a00 -menuitem.revoke.voice = \u53d6\u6d88\u767c\u8a00\u6b0a -menuitem.grant.voice = \u6388\u4E88\u767C\u8A00\u6B0A -menuitem.ban.user = \u7981\u6b62\u6b64\u7528\u6236 -menuitem.grant.moderator = \u6388\u4E88\u4E3B\u6301\u4EBA -menuitem.revoke.moderator = \u64A4\u92B7\u4E3B\u6301\u4EBA -menuitem.invite.users = \u9080\u8ACB\u4F7F\u7528\u8005 -menuitem.invite.group.to.conference = \u9080\u8acb\u7fa4\u7d44\u5230\u6703\u8b70\u4e2d -menuitem.start.a.conference = \u958b\u555f\u6703\u8b70\u5ba4 ... -menuitem.change.subject = \u8b8a\u66f4\u4e3b\u984c -menuitem.destroy.room = \u64a4\u92b7\u6703\u8b70\u5ba4 -menuitem.set.status.message = \u8a2d\u7f6e\u72c0\u614b\u6d88\u606f ... -menuitem.edit.status.message = \u7de8\u8f2f\u81ea\u5b9a\u7fa9\u72c0\u614b\u6d88\u606f ... -menuitem.broadcast.to.group = \u5c0d\u7fa4\u7d44\u5ee3\u64ad -menuitem.alert.when.online = \u7528\u6236\u5728\u7DDA\u6642\u986F\u793A\u901A\u77E5 -menuitem.remove.alert.when.online = \u64A4\u92B7\u901A\u77E5 -menuitem.save.as = \u53e6\u5b58\u70ba ... -menuitem.view.client.version = \u67E5\u770B\u5BA2\u6236\u7AEF\u7248\u672C -menuitem.view.contact.history = \u67E5\u770B\u4EA4\u8AC7\u7684\u6B77\u53F2 -menuitem.edit.my.profile = \u7de8\u8f2f\u6211\u7684\u500b\u4eba\u7c21\u4ecb ... -menuitem.lookup.profile = \u67e5\u95b1\u500b\u4eba\u7c21\u4ecb ... -menuitem.add.as.contact = \u65b0\u589e\u70ba\u806f\u7d61\u4eba -menuitem.chat = \u804a\u5929 -menuitem.sign.in = \u7C3D\u5230 -menuitem.sign.out = \u7C3D\u96E2 -menuitem.sign.in.at.login = \u767b\u5165\u6642\u7c3d\u5230 -menuitem.enter.login.information = \u8F38\u5165\u767B\u5165\u8CC7\u8A0A -menuitem.delete.login.information = \u522A\u9664\u767B\u5165\u8CC7\u8A0A -menuitem.show.offline.group = \u986f\u793a\u7fa4\u7d44\u96e2\u7dda\u806f\u7d61\u4eba -menuitem.move.to = \u79FB\u52D5\u5230 -menuitem.copy.to = \u8907\u88FD\u5230 -menuitem.bookmarks = \u66f8\u7c64 -menuitem.add.groupchat.myname = \u6709\u4eba\u63d0\u5230\u6211\u7684\u540d\u5b57\u6642,\u6a19\u8a18\u51fa\u6211\u7684\u540d\u5b57 -menuitem.add.groupchat.mytext = \u6211\u5728\u767c\u8a00\u6642,\u6a19\u8a18\u51fa\u6211\u7684\u804a\u5929\u8a0a\u606f -menuitem.add.groupchat.popname = \u6709\u4eba\u63d0\u5230\u6211\u7684\u540d\u5b57\u6642,\u5f48\u51fa\u63d0\u793a\u8996\u7a97 -menuitem.add.groupchat.showjoinleavemessage = \u986f\u793a\u52a0\u5165\u8207\u96e2\u958b\u8a0a\u606f -menuitem.add.groupchat.showrolesinsteadofstatus = \u986f\u793a\u804a\u5929\u89d2\u8272\u5716\u6a19\u53d6\u4ee3\u72c0\u614b\u5716\u6a19 -menuitem.add.groupchat.auto.accept.invite = \u81ea\u52d5\u63a5\u53d7\u7fa4\u7d44\u804a\u5929\u9080\u8acb -menuitem.add.groupchat.random.colors = \u66b1\u7a31\u7684\u984f\u8272\u96a8\u6a5f\u6307\u793a -menuitem.always.on.top = Spark \u9762\u677f\u7e3d\u662f\u5728\u6700\u524d\u9762 -menuitem.dial = \u64a5\u865f -menuitem.affiliation = \u806f\u7d61 -menuitem.grant.member = \u6388\u4e88\u6703\u54e1\u8cc7\u683c -menuitem.grant.admin = \u6388\u4e88\u7ba1\u7406\u8005\u8cc7\u683c -menuitem.grant.owner = \u6388\u4e88\u64c1\u6709\u8005\u8cc7\u683c -menuitem.languages = \u8a9e\u8a00\u9078\u64c7 -menuitem.open.with = \u958b\u555f... -menuitem.block.contact = \u5c01\u9396\u6b64\u806f\u7d61\u4eba -menuitem.unblock.contact = \u89e3\u9664\u5c01\u9396\u6b64\u806f\u7d61\u4eba -menuitem.revoke.member = \u53d6\u6d88\u6703\u54e1\u8cc7\u683c -menuitem.revoke.admin = \u53d6\u6d88\u7ba1\u7406\u8005\u8cc7\u683c -menuitem.revoke.owner = \u53d6\u6d88\u64c1\u6709\u8005\u8cc7\u683c -menuitem.user.guide = \u64cd\u4f5c\u8aaa\u660e -menuitem.view.logs = \u67e5\u770b\u65e5\u8a8c -menuitem.show.offline.users = \u986f\u793a\u96e2\u7dda\u806f\u7d61\u4eba -menuitem.show.contact.statusmessage = \u986f\u793a\u806f\u7d61\u4eba\u72c0\u614b\u6d88\u606f -menuitem.bookmark.room = \u66f8\u7c64\u5ba4 -menuitem.refresh = \u5237\u65b0 -menuitem.create.room = \u65b0\u5275\u6216\u52a0\u5165\u6703\u8b70\u5ba4 -menuitem.expand.all.groups = \u5c55\u958b\u6240\u6709\u7fa4\u7d44 -menuitem.collapse.all.groups = \u7e2e\u5c0f\u6240\u6709\u7fa4\u7d44 -menuitem.inivite.again = \u518d\u6b21\u9080\u8acb -menuitem.chatframe.option = \u9078\u9805 -menuitem.add.groupchat.invitetobookmark = \u81ea\u52d5\u9080\u8acb\u806f\u7d61\u4eba\u5230\u66f8\u7c64\u5ba4 - -message.invite.to.groupchat = \u9080\u8acb\u60a8\u52a0\u5165\u7fa4\u7d44\u804a\u5929 ... -message = \u8a0a\u606f -message.account.create = \u65b0\u5275\u4e00\u500b\u804a\u5929\u5e33\u6236 -message.account.created = \u65b0\u5e33\u6236\u5df2\u5275\u5efa -message.account.error = \u5728\u6307\u5b9a\u7684\u4f3a\u670d\u5668\u4e0a\u5275\u5efa\u5e33\u6236 -message.add.a.contact = \u65b0\u589e\u806f\u7d61\u4eba -message.add.conference.service = \u65b0\u589e\u6703\u8b70\u670d\u52d9 -message.add.contact.to.list = \u5c07\u7528\u6236\u65b0\u589e\u5230\u60a8\u7684\u806f\u7d61\u4eba\u5217\u8868 -message.add.favorite.room = \u65b0\u589e\u6b64\u6703\u8b70\u5ba4\u5230\u6700\u611b\u6e05\u55ae,\u6216\u76f4\u63a5\u52a0\u5165\u6b64\u6703\u8b70\u5ba4 -message.add.this.user.to.your.roster = \u5c07\u6b64\u806f\u7d61\u4eba\u65b0\u589e\u5230\u4f60\u7684\u597d\u53cb\u5217\u8868 -message.add.to.roster = \u65b0\u589e\u5230\u540d\u55ae\u5217\u8868\u4e2d -message.add.user = \u5c07\u806f\u7d61\u4eba\u52a0\u5165\u60a8\u7684\u540d\u55ae\u5217\u8868\u4e2d\u55ce? -message.alert.notify = \u7dca\u6025\u901a\u77e5 -message.already.exists = \u5e33\u6236\u5df2\u5b58\u5728,\u8acb\u5617\u8a66\u4f7f\u7528\u4e0d\u540c\u7684\u7528\u6236\u540d -message.approve.subscription = \u5141\u8a31\u5728\u4ed6\u5011\u7684\u540d\u55ae\u5217\u8868\u4e2d\u65b0\u589e\u60a8\u55ce? -message.autenticating = \u8a8d\u8b49 -message.away.idle = \u7531\u65bc\u9592\u7f6e\u904e\u4e45,\u56e0\u6b64\u986f\u793a\u96e2\u958b -message.bookmark.temporary.room.error = \u4e0d\u53ef\u5c07\u81e8\u6642\u7684\u6703\u8b70\u5ba4\u8a2d\u70ba\u66f8\u7c64\u5ba4 -message.broadcast.from = \u5f9e ... \u5ee3\u64ad -message.broadcast.no.user.selected = \u81f3\u5c11\u9078\u64c7\u4e00\u500b\u63a5\u6536\u8005 -message.broadcast.no.text = \u8f38\u5165\u6587\u5b57\u5ee3\u64ad -message.broadcast.message.sent = \u8a72\u5ee3\u64ad\u8a0a\u606f\u5df2\u767c\u9001 -message.broadcast.to = \u8f38\u5165\u7684\u8a0a\u606f\u5ee3\u64ad\u5230 ... -message.broadcasted.to = \u8a72\u8a0a\u606f\u5df2\u88ab\u5ee3\u64ad\u7d66\u4ee5\u4e0b\u7528\u6236 : -message.buzz.alert.notification = \u7372\u53d6\u7528\u6236\u7684\u95dc\u6ce8 -message.buzz.message = \u5e0c\u671b\u5f97\u5230\u4f60\u7684\u95dc\u6ce8 -message.buzz.sent = \u8acb\u7528\u6236\u95dc\u6ce8 -message.calling = \u547c\u53eb -message.came.online = {0} \u5728\u7dda {1} -message.cannot.add.contact.to.shared.group = \u4e0d\u80fd\u5728\u5171\u4eab\u7fa4\u7d44\u4e2d\u65b0\u589e\u65b0\u7684\u806f\u7d61\u4eba -message.chat.session.ended = \u804a\u5929\u5c0d\u8a71\u5df2\u7d93\u7d50\u675f -message.click.to.open = \u9ede\u64ca\u5f8c\u958b\u555f -message.client.information = \u5ba2\u6236\u4fe1\u606f -message.close.other.chats = \u95dc\u9589\u6240\u6709\u5176\u4ed6\u7684\u804a\u5929 -message.close.stale.chats = \u95dc\u9589\u4e4b\u524d\u7684\u804a\u5929\u8a18\u9304 -message.close.this.chat = \u95dc\u9589\u9019\u500b\u804a\u5929\u8996\u7a97 -message.conference.info.error = \u7121\u6cd5\u6aa2\u7d22\u6703\u8b70\u4fe1\u606f,\u8acb\u7a0d\u5f8c\u518d\u8a66 -message.conference.service.error = \u7121\u6cd5\u627e\u5230\u6703\u8b70\u670d\u52d9 -message.confirm.destruction.of.room = \u522a\u9664\u6b64\u6703\u8b70\u5ba4\u5c07\u4f7f\u88e1\u9762\u7684\u806f\u7e6b\u4eba\u96e2\u958b,\u662f\u5426\u7e7c\u7e8c? -message.confirmation.password.error = \u6307\u5b9a\u78ba\u8a8d\u904e\u7684\u5bc6\u78bc -message.connecting.please.wait = \u9023\u63a5\u4e2d,\u8acb\u7a0d\u5019 ... -message.connection.failed = \u7121\u6cd5\u9023\u63a5\u5230 ... -message.create.account = \u7121\u6cd5\u5275\u5efa\u5e33\u6236 -message.create.or.join.room = \u5275\u5efa\u6216\u52a0\u5165\u6703\u8b70\u804a\u5929\u5ba4 -message.current.status = \u8b93\u5225\u4eba\u77e5\u9053\u4f60\u7684\u7576\u524d\u72c0\u614b\u6216\u6d3b\u52d5 -message.default.error = \u5df2\u6aa2\u6e2c\u5230\u932f\u8aa4,\u8acb\u56de\u5831 support@jivesoftware.com -message.delete.all.history = \u522a\u9664\u4ee5\u524d\u6240\u6709\u7684\u5c0d\u8a71? -message.delete.confirmation = \u4f60\u78ba\u5b9a\u8981\u522a\u9664? -message.disable.transport = \u5f9e ... \u79fb\u9664\u767b\u5165\u4fe1\u606f\u55ce? -message.disconnected.conflict.error = \u60a8\u5df2\u5f9e\u4ed6\u8655\u767b\u5165,\u56e0\u6b64\u6b64\u8655\u9023\u63a5\u88ab\u95dc\u9589 -message.disconnected.error = \u7531\u65bc\u60a8\u7684\u9023\u63a5\u932f\u8aa4,\u56e0\u6b64\u88ab\u95dc\u9589 -message.disconnected.group.chat.error = \u7531\u65bc\u767c\u751f\u932f\u8aa4,\u6240\u4ee5\u60a8\u7684\u9023\u63a5\u88ab\u95dc\u9589.\u91cd\u65b0\u9023\u63a5\u6210\u529f\u6642, Spark \u6703\u81ea\u52d5\u91cd\u65b0\u9023\u63a5\u5230\u6b64\u9023\u63a5\u57e0 -message.disconnected.shutdown = \u56e0\u4f3a\u670d\u5668\u88ab\u95dc\u9589,\u6240\u4ee5\u60a8\u7684\u9023\u63a5\u88ab\u95dc\u9589 -message.downloading = \u4e0b\u8f09\u4e2d -message.downloading.spark.plug = \u4e0b\u8f09 Spark \u63d2\u4ef6 -message.end.chat = \u4f60\u60f3\u7d50\u675f\u9019\u5834\u804a\u5929\u55ce? -message.end.conversation = \u4f60\u60f3\u7d50\u675f\u9019\u5834\u6703\u8b70\u55ce? -message.enter.aim = \u5728\u4e0b\u65b9\u8f38\u5165\u60a8\u7684 AIM \u7528\u6236\u540d\u7a31\u548c\u5bc6\u78bc -message.enter.broadcast.message = \u8f38\u5165\u8a0a\u606f\u5ee3\u64ad\u5230\u9078\u5b9a\u7684\u7528\u6236 -message.enter.gadugadu = \u4ee5\u4e0b\u8f38\u5165\u60a8\u7684 GaduGadu \u7528\u6236\u540d\u7a31\u548c\u5bc6\u78bc -message.enter.gtalk = \u4ee5\u4e0b\u8f38\u5165\u60a8\u7684 GTalk \u7528\u6236\u540d\u7a31\u548c\u5bc6\u78bc -message.enter.icq = \u4ee5\u4e0b\u8f38\u5165\u60a8\u7684 ICQ \u7528\u6236\u540d\u7a31\u548c\u5bc6\u78bc -message.enter.irc = \u4ee5\u4e0b\u8f38\u5165\u60a8\u7684 IRC \u7528\u6236\u540d\u7a31, \u5bc6\u78bc\u548c\u66b1\u7a31 -message.enter.sametime = \u4ee5\u4e0b\u8f38\u5165\u60a8\u7684 Sametime \u7528\u6236\u540d\u7a31\u548c\u5bc6\u78bc -message.enter.facebook = \u4ee5\u4e0b\u8f38\u5165\u60a8\u7684 Facebook \u7528\u6236\u540d\u7a31\u548c\u5bc6\u78bc -message.enter.myspace = \u4ee5\u4e0b\u8f38\u5165\u60a8\u7684 MySpace \u7528\u6236\u540d\u7a31\u548c\u5bc6\u78bc -message.enter.jabber.id = \u8f38\u5165 Jabber ID -message.enter.message.to.broadcast = \u8f38\u5165\u8a0a\u606f\u5ee3\u64ad\u5230\u6574\u500b\u540d\u55ae\u5217\u8868 -message.enter.msn = \u4ee5\u4e0b\u8f38\u5165\u60a8\u7684 MSN \u7528\u6236\u540d\u7a31\u548c\u5bc6\u78bc -message.enter.new.subject = \u8f38\u5165\u65b0\u7684\u4e3b\u984c -message.enter.qq = \u4ee5\u4e0b\u8f38\u5165\u60a8\u7684 QQ \u865f\u78bc\u548c\u5bc6\u78bc -message.enter.room.password = \u8f38\u5165\u6703\u8b70\u5ba4\u5bc6\u78bc -message.enter.simple = \u4ee5\u4e0b\u8f38\u5165\u60a8\u7684 SIMPLE \u7528\u6236\u540d\u7a31\u548c\u5bc6\u78bc -message.enter.valid.jid = \u8f38\u5165\u4e00\u500b\u6709\u6548\u7684 Jabber ID -message.enter.xmpp = \u4ee5\u4e0b\u8f38\u5165\u60a8\u7684 XMPP \u7528\u6236\u540d\u7a31\u548c\u5bc6\u78bc -message.enter.yahoo = \u8f38\u5165\u60a8\u7684\u7528\u6236\u540d\u7a31\u548c\u5bc6\u78bc\u9023\u63a5\u5230 Yahoo -message.error.during.file.transfer = \u6587\u4ef6\u50b3\u9001\u904e\u7a0b\u4e2d\u6709\u932f\u8aa4\u767c\u751f -message.file.exists.question = \u6b64\u6a94\u6848\u5df2\u7d93\u5b58\u5728,\u78ba\u5b9a\u53d6\u4ee3\u5b83\u55ce? -message.file.size = \u6587\u4ef6\u5927\u5c0f : -message.file.transfer.canceled = \u60a8\u5df2\u53d6\u6d88\u6587\u4ef6\u50b3\u8f38 -message.file.transfer.rejected = \u6b64\u6587\u4ef6\u4e0d\u80fd\u88ab\u50b3\u8f38 -message.file.transfer.dirnull = \u6587\u4ef6\u4e0b\u8f09\u76ee\u9304\u7121\u6548 -message.file.transfer.nodir = \u6587\u4ef6\u4e0b\u8f09\u7684\u76ee\u9304\u4e0d\u5b58\u5728 -message.file.transfer.cantwritedir = \u4e0d\u80fd\u5beb\u5165\u8a72\u76ee\u9304\u7684\u6587\u4ef6\u50b3\u8f38 -message.file.transfer.notification = \u6587\u4ef6\u50b3\u8f38\u901a\u77e5 -message.file.transfer.short.message = \u5411\u60a8\u767c\u9001\u4e00\u500b\u540d\u70ba : -message.file.transfer.chat.window = \u6587\u4ef6\u50b3\u8f38\u8acb\u6c42: -message.file.transfer.file.too.big.error = \u9078\u64c7\u7684\u6587\u4ef6\u6a94\u6848\u592a\u5927,\u9078\u64c7\u7684\u6587\u4ef6\u5927\u5c0f\u6700\u5927\u9650\u5236\u70ba : -message.file.transfer.file.too.big.warning = \u9078\u5b9a\u7684\u6587\u4ef6\u904e\u5927.\u4ecd\u7136\u7e7c\u7e8c\u55ce? -message.file.transfer.direrror.setdir = \u9ede\u64ca\u6b64\u8655\u66f4\u6539\u76ee\u9304 -message.find.conference.services = \u641c\u5c0b\u6703\u8b70\u670d\u52d9 -message.forbidden.error = \u5f9e\u4f3a\u670d\u5668\u4e0a\u63a5\u6536\u5230\u4e00\u500b\u932f\u8aa4\u8a0a\u606f -message.gateway.username.error = \u9700\u8981\u63d0\u4f9b\u7528\u6236\u540d\u7a31 -message.gateway.password.error = \u9700\u8981\u63d0\u4f9b\u5bc6\u78bc -message.gateway.nickname.error = \u9700\u8981\u63d0\u4f9b\u66b1\u7a31 -message.general.error = \u7531\u65bc {0} , \u60a8\u5df2\u5f9e\u4f3a\u670d\u5668\u4e2d\u65b7\u7dda -message.generic.reconnect.message = \u60a8\u5df2\u5f9e\u4f3a\u670d\u5668\u65b7\u7dda, \u8acb\u9ede\u64ca\u4e0b\u9762\u7684\u91cd\u65b0\u9023\u63a5\u6309\u9215\u91cd\u65b0\u767b\u5165 -message.idle.for = \u9592\u7f6e {0} -message.image.too.large = \u6b64\u5716\u7247\u662f\u592a\u5927\u800c\u4e0d\u80fd\u4f7f\u7528, \u8acb\u6307\u5b9a\u5716\u50cf\u70ba 16K \u6216\u66f4\u5c0f -message.invalid.jabber.id = \u4e0d\u662f\u6709\u6548\u7684 Jabber ID -message.invalid.jid.error = \u6307\u5b9a\u7684 JID \u7121\u6548 -message.invalid.status = \u6307\u5b9a\u4e00\u500b\u6709\u6548\u7684\u72c0\u614b\u8a0a\u606f -message.invalid.username.password = \u7121\u6548\u7684\u7528\u6236\u540d\u7a31\u6216\u5bc6\u78bc -message.invite.users.to.conference = \u9080\u8acb\u806f\u7d61\u4eba\u5230\u6703\u8b70\u5ba4 -message.is.shared.group = {0} \u662f\u4e00\u500b\u5171\u4eab\u7fa4\u7d44 -message.is.typing.a.message = {0} \u6b63\u5728\u8f38\u5165\u8a0a\u606f... -message.join.conference.room = \u52a0\u5165\u6703\u8b70\u5ba4 -message.kicked.error = \u4f60\u662f\u4e0d\u662f\u80fd\u5920\u8e22\u9664 {0} \u96e2\u958b\u9019\u500b\u6703\u8b70\u5ba4 -message.last.message.received = \u6536\u5230\u7684\u6700\u5f8c\u4e00\u689d\u6d88\u606f {0} -message.loading.please.wait = \u8f09\u5165\u4e2d. \u8acb\u7a0d\u5019... -message.locked.workstation = \u7528\u6236\u5df2\u9396\u5b9a\u5176\u5de5\u4f5c\u7ad9 -message.name.of.group = \u7fa4\u7d44\u540d\u7a31 -message.name.of.search.service.question = \u641c\u5c0b\u670d\u52d9\u540d\u7a31? -message.negotiate.file.transfer = \u5c0d\u8ac7\u6587\u4ef6\u50b3\u8f38\u4e2d, \u8acb\u7a0d\u5019... -message.negotiate.stream = \u5c0d\u8ac7\u6d41\u7a0b\u9023\u63a5\u4e2d, \u8acb\u7a0d\u5019... -message.negotiation.file.transfer = \u5c0d\u8ac7\u6587\u4ef6\u50b3\u8f38 {0}, \u8acb\u7a0d\u5019... -message.new.message = \u65b0\u8a0a\u606f\u4f86\u81ea {0} -message.new.spark.available = {0} \u73fe\u5728\u662f\u53ef\u7528\u7684, \u4f60\u60f3\u5b89\u88dd\u55ce? -message.nickname.in.use = \u66b1\u7a31\u5df2\u88ab\u4f7f\u7528, \u8acb\u6307\u5b9a\u5176\u4ed6\u66b1\u7a31 -message.nickname.not.acceptable = \u66b1\u7a31\u8b8a\u66f4\u672a\u555f\u7528! -message.no.avatar.found = \u7528\u6236\u6c92\u6709\u8a2d\u5b9a\u982d\u50cf\u5716\u793a -message.no.caller.id = \u7121\u4f86\u96fb\u986f\u793a\u53ef\u7528 -message.no.description.available = \u6c92\u6709\u53ef\u7528\u7684\u63cf\u8ff0 -message.no.history.found = \u7121\u8207\u8a72\u806f\u7d61\u4eba\u4ee5\u524d\u7684\u5c0d\u8a71\u6b77\u53f2\u7d00\u9304 -message.no.results.found = \u7531\u4f3a\u670d\u5668\u56de\u8986\u7121\u641c\u5c0b\u7d50\u679c -message.no.room.to.join.error = \u6c92\u6709\u6703\u8b70\u5ba4\u53ef\u52a0\u5165 -message.no.subject.available = \u7121\u4e3b\u984c\u53ef\u7528 -message.no.updates = \u6c92\u6709\u66f4\u65b0 -message.normal = \u4e00\u822c\u8a0a\u606f -message.number.to.call = \u6307\u5b9a\u8981\u64a5\u6253\u7684\u865f\u78bc -message.offline = \u806f\u7d61\u4eba\u8655\u65bc\u96e2\u7dda\u72c0\u614b,\u4e0b\u6b21\u767b\u5165\u6642\u5c07\u6536\u5230\u96e2\u7dda\u8a0a\u606f -message.offline.error = \u806f\u7d61\u4eba\u5c07\u7121\u6cd5\u63a5\u6536\u96e2\u7dda\u6d88\u606f -message.participants.in.room = \u6703\u8b70\u5ba4\u5167\u7684\u53c3\u8207\u8005 -message.password.error = \u6307\u5b9a\u6b64\u5e33\u6236\u7684\u5bc6\u78bc -message.password.private.room.error = \u6307\u5b9a\u5bc6\u78bc\u7684\u79c1\u4eba\u6703\u8b70\u5ba4 -message.passwords.no.match = \u5bc6\u78bc\u4e0d\u76f8\u7b26 -message.please.join.in.conference = \u8acb\u52a0\u5165\u6211\u7684\u6703\u8b70 -message.plugins.not.available = \u7121\u6cd5\u806f\u7e6b\u7684\u63d2\u4ef6\u5eab -message.prompt.plugin.uninstall = \u4f60\u78ba\u5b9a\u8981\u505c\u7528 {0} \u55ce? -message.received.file = \u60a8\u5f9e {0} \u6536\u5230\u4e00\u500b\u6587\u4ef6 -message.receiving.file = \u60a8\u5f9e {0} \u6536\u5230\u6587\u4ef6 -message.reconnect.attempting = \u5617\u8a66\u4e2d... -message.reconnect.failed = \u91cd\u65b0\u9023\u63a5\u5931\u6557 -message.reconnect.wait = \u5728 {0} \u79d2\u91cd\u65b0\u9023\u63a5 -message.register.transports = \u9019\u4e9b\u53ef\u7528\u50b3\u8f38\u8a3b\u518a -message.registering = \u8a3b\u518a\u4e2d {0}, \u8acb\u7a0d\u5019... -message.registration.transport.failed = \u7121\u6cd5\u8207\u9580\u6236\u8a3b\u518a -message.restart.spark = \u60a8\u5c07\u9700\u8981\u95dc\u9589\u5ba2\u6236\u7aef\u5b89\u88dd\u65b0\u7248\u672c, \u4f60\u60f3\u73fe\u5728\u505a\u55ce? -message.restart.spark.changes = \u4e0b\u6b21\u555f\u52d5 Spark \u6642,\u63d2\u4ef6\u5c07\u88ab\u79fb\u9664 -message.restart.spark.to.install = \u60a8\u9700\u8981\u95dc\u9589\u5ba2\u6236\u7aef\u5b89\u88dd\u6700\u65b0\u7248\u672c, \u4f60\u60f3\u73fe\u5728\u505a\u55ce? -message.restart.required = \u60a8\u5c07\u9700\u8981\u91cd\u65b0\u555f\u52d5 Spark \u4f7f\u66f4\u6539\u751f\u6548, \u73fe\u5728\u91cd\u65b0\u555f\u52d5\u55ce? -message.room.creation.error = \u7121\u6cd5\u5275\u5efa\u6703\u8b70\u5ba4 -message.room.destroyed = \u9019\u500b\u6703\u8b70\u5ba4\u5df2\u88ab\u64a4\u92b7,\u7531\u65bc\u4ee5\u4e0b\u539f\u56e0: {0} -message.room.destruction.reason = \u64a4\u92b7\u6b64\u6703\u8b70\u5ba4\u7684\u539f\u56e0? -message.room.information.for = \u6703\u8b70\u5ba4\u8cc7\u8a0a {0} -message.save.profile = \u8981\u5132\u5b58\u60a8\u66f4\u6539\u7684\u500b\u4eba\u8cc7\u6599, \u9ede\u9078\u5132\u5b58 -message.search.for.contacts = \u641c\u5c0b\u806f\u7d61\u4eba -message.search.input.short = \u8acb\u63d0\u4f9b\u81f3\u5c11\u4e94\u500b\u5b57\u6bcd. -message.search.for.other.people = \u5728\u6b64\u4f3a\u670d\u5668\u4e0a\u641c\u5c0b\u5176\u4ed6\u806f\u7d61\u4eba -message.search.service.not.available = \u806f\u7e6b\u4e0d\u5230\u641c\u5c0b\u670d\u52d9 -message.searching.please.wait = \u641c\u5c0b\u4e2d, \u8acb\u7a0d\u5019... -message.select.add.room.to.add = \u8acb\u9078\u64c7\u4e00\u500b\u6703\u8b70\u662f\u65b0\u589e\u5230\u60a8\u7684\u670d\u52d9\u5217\u8868 -message.select.one.or.more = \u5728\u4f60\u7684\u540d\u55ae\u4e2d\u9078\u64c7\u4e00\u500b\u6216\u591a\u500b\u7528\u6236 -message.select.room.to.enter = \u6307\u5b9a\u9032\u5165\u6703\u8b70\u5ba4 -message.select.room.to.join = \u9078\u64c7\u52a0\u5165\u6703\u8b70\u5ba4 -message.send.a.broadcast = \u767c\u9001\u5ee3\u64ad -message.send.file.to.user = \u767c\u9001\u6587\u4ef6\u7d66\u6b64\u7528\u6236 -message.send.picture = \u5728\u87a2\u5e55\u4e0a\u622a\u53d6\u5716\u793a -message.send.to.these.people = \u767c\u9001\u7d66\u9019\u4e9b\u4eba -message.sending.file.to = \u767c\u9001\u6587\u4ef6 {0} -message.sent.offline.files = \u4f60\u88ab\u767c\u9001\u96e2\u7dda\u6587\u4ef6 -message.server.unavailable = \u7121\u6cd5\u9023\u63a5\u5230\u4f3a\u670d\u5668: \u7121\u6548\u7684\u540d\u7a31\u6216\u4f3a\u670d\u5668\u7121\u6cd5\u5230\u9054 -message.service.already.exists = \u670d\u52d9\u5df2\u7d93\u5728\u4f60\u7684\u670d\u52d9\u5217\u8868\u4e2d -message.shared.group = \u5171\u4eab\u7fa4\u7d44 -message.spark.secure = Spark \u662f\u5728\u5b89\u5168\u6a21\u5f0f\u4e0b\u904b\u884c -message.specify.contact.jid = \u8acb\u8a3b\u660e\u806f\u7d61\u4eba\u7684 JID (\u4f8b\u5982. ddman@jabber.org) -message.specify.group = \u5c07\u65b0\u7528\u6236\u65b0\u589e\u81f3\u6307\u5b9a\u7684\u806f\u7d61\u4eba\u7fa4\u7d44 -message.specify.information.for.conference = \u6307\u5b9a\u6703\u8b70\u5ba4\u8a0a\u606f -message.specify.name.error = \u6307\u5b9a\u4e00\u500b\u6709\u6548\u7684\u540d\u7a31 -message.specify.users.to.join.conference = \u6307\u5b9a\u7528\u6236\u52a0\u5165\u9019\u500b\u6703\u8b70\u5ba4 -message.specify.valid.time.error = \u6307\u5b9a\u4e00\u500b\u6709\u6548\u7684\u8d85\u6642\u548c\u9023\u63a5\u57e0 -message.subject.change.error = \u60a8\u7121\u6b0a\u66f4\u6539\u6b64\u623f\u9593\u7684\u4e3b\u984c -message.subject.has.been.changed.to = {1} \u6539\u8b8a\u6703\u8b70\u4e3b\u984c\u70ba "{0}" -message.supply.resource = \u63d0\u4f9b\u4e00\u500b\u6709\u6548\u7684\u8cc7\u6e90 -message.supply.valid.port = \u63d0\u4f9b\u4e00\u500b\u6709\u6548\u7684\u9023\u63a5\u57e0 -message.supply.valid.timeout = \u63d0\u4f9b\u4e00\u500b\u6709\u6548\u7684\u8d85\u6642\u503c -message.timeout.error = \u8d85\u6642\u503c\u5fc5\u9808\u662f 5 \u79d2\u6216\u66f4\u5927 -message.total.downloaded = \u7e3d\u4e0b\u8f09 -message.transfer.cancelled = \u6587\u4ef6\u50b3\u8f38\u88ab\u53d6\u6d88 -message.transfer.complete = \u6587\u4ef6\u50b3\u8f38\u5b8c\u6210 ({0}) -message.transfer.progressbar.text.received = {0} \u63a5\u53d7 @ {1} {2} -message.transfer.progressbar.text.sent = {0} \u767c\u9001 @ {1} {2} -message.transfer.rate = \u50b3\u8f38\u901f\u7387 -message.transfer.refused = \u6587\u4ef6\u50b3\u8f38\u88ab\u62d2\u7d55 -message.transfer.waiting.on.user = \u7b49\u5f85 {0} \u63a5\u53d7\u6587\u4ef6\u50b3\u8f38 -message.unable.to.load.profile = \u7121\u6cd5\u5f9e {0} \u627e\u5230\u500b\u4eba\u7c21\u4ecb -message.unable.to.retrieve.last.activity = \u7121\u6cd5\u78ba\u5b9a\u6700\u5f8c\u4e00\u500b\u6d3b\u52d5 {0} -message.unable.to.save.password = \u7121\u6cd5\u66f4\u6539\u5bc6\u78bc, \u8acb\u806f\u7e6b\u60a8\u7684\u4f3a\u670d\u5668\u7ba1\u7406\u54e1 -message.unable.to.send.file = \u4f60\u7121\u6cd5\u5c07\u6587\u4ef6\u767c\u9001\u5230 {0} -message.unable.to.use.hostname.as.resource = \u7121\u6cd5\u4f7f\u7528\u4e3b\u6a5f\u540d\u4f5c\u70ba\u8cc7\u6e90 -message.unrecoverable.error = \u7121\u6548\u7684\u7528\u6236\u540d\u7a31\u6216\u5bc6\u78bc -message.update.room.list = \u66f4\u65b0\u6703\u8b70\u5ba4\u5217\u8868 -message.updating.cancelled = \u66f4\u65b0\u5df2\u88ab\u53d6\u6d88 -message.user.banned = {0} \u5df2\u88ab\u7981\u6b62\u9032\u5165\u9019\u500b\u6703\u8b70\u5ba4.\u539f\u56e0: {1} -message.user.given.voice = {0} \u5728\u9019\u500b\u6703\u8b70\u5ba4\u4e2d\u88ab\u6388\u4e88\u767c\u8a00\u6b0a -message.user.granted.admin = {0} \u5df2\u88ab\u6388\u4e88\u7ba1\u7406\u54e1\u6b0a\u9650 -message.user.granted.membership = {0} \u5df2\u88ab\u6388\u4e88\u6703\u54e1\u6b0a\u9650 -message.user.granted.moderator = {0} \u5df2\u88ab\u6388\u4e88\u4e3b\u6301\u4eba\u6b0a\u9650 -message.user.granted.owner = {0} \u5df2\u88ab\u6388\u4e88\u64c1\u6709\u8005\u6b0a\u9650 -message.user.is.sending.you.a.file = {0} \u6b63\u5728\u767c\u9001\u60a8\u7684\u6587\u4ef6 -message.user.joined.room = {0} \u5df2\u52a0\u5165\u6703\u8b70\u5ba4 -message.user.kicked.from.room = {0} \u5df2\u7d93\u7531 {1} \u8e22\u51fa\u4e86\u623f\u9593 .\u539f\u56e0: {2} -message.user.left.room = {0} \u5df2\u7d93\u96e2\u958b\u6703\u8b70\u5ba4 -message.user.nickname.changed = {0} \u73fe\u5728\u88ab\u7a31\u70ba {1} -message.user.now.available.to.chat = {0} \u5728\u7dda\u4e0a {1} -message.user.revoked.admin = \u7ba1\u7406\u54e1\u6b0a\u9650\u5df2\u88ab\u64a4\u92b7 {0} -message.user.revoked.membership = \u6703\u54e1\u8cc7\u683c\u5df2\u88ab\u64a4\u92b7 {0} -message.user.revoked.moderator = \u4e3b\u6301\u4eba\u6b0a\u9650\u5df2\u88ab\u64a4\u92b7 {0} -message.user.revoked.owner = \u6240\u6709\u8005\u6b0a\u9650\u5df2\u88ab\u64a4\u92b7 {0} -message.user.voice.revoked = \u767c\u8a00\u6b0a\u5df2\u7d93\u88ab\u64a4\u92b7 {0} -message.username.error = \u6307\u5b9a\u4e00\u500b\u7528\u6236\u540d\u7a31\u4f5c\u70ba\u5e33\u6236 -message.username.password.error = \u9700\u8981\u63d0\u4f9b\u7528\u6236\u540d\u7a31\u548c\u5bc6\u78bc -message.vcard.not.supported = \u4f3a\u670d\u5668\u4e0d\u652f\u6301\u96fb\u5b50\u540d\u7247,\u7121\u6cd5\u4fdd\u5b58\u60a8\u7684\u96fb\u5b50\u540d\u7247 -message.version = \u7248\u672c: {0} -message.view.information.about.this.user = \u67e5\u770b\u95dc\u65bc\u9019\u500b\u806f\u7d61\u4eba\u7684\u8cc7\u6599 -message.waiting.for.user.to.join = \u7b49\u5f85 {0} \u52a0\u5165 -message.went.offline = {0} \u96e2\u7dda {1} -message.you.have.been.banned = \u60a8\u5df2\u88ab\u7981\u6b62\u9032\u5165\u9019\u500b\u6703\u8b70\u5ba4 -message.you.have.been.kicked = \u4f60\u88ab\u8e22\u51fa\u9019\u500b\u623f\u9593 -message.you.have.sent = \u60a8\u767c\u9001\u4e86\u6587\u4ef6 -message.your.admin.granted = \u60a8\u5df2\u88ab\u6388\u4e88\u7ba1\u7406\u54e1\u6b0a\u9650 -message.your.banned = \u60a8\u5df2\u88ab\u7981\u6b62\u9032\u5165\u9019\u500b\u6703\u8b70\u5ba4 -message.your.kicked = \u60a8\u5df2\u7531{0}\u88ab\u8e22\u51fa -message.your.membership.granted = \u60a8\u5df2\u88ab\u6388\u4e88\u6703\u54e1\u6b0a\u9650 -message.your.membership.revoked = \u60a8\u7684\u6703\u54e1\u8cc7\u683c\u5df2\u88ab\u64a4\u92b7 -message.your.moderator.granted = \u60a8\u5df2\u88ab\u6388\u4e88\u4e3b\u6301\u4eba\u6b0a\u9650 -message.your.moderator.revoked = \u60a8\u7684\u4e3b\u6301\u4eba\u6b0a\u9650\u5df2\u88ab\u64a4\u92b7 -message.your.ownership.granted = \u60a8\u5df2\u88ab\u6388\u4e88\u64c1\u6709\u8005\u6b0a\u9650 -message.your.ownership.revoked = \u60a8\u7684\u64c1\u6709\u6b0a\u9650\u5df2\u88ab\u64a4\u92b7 -message.your.revoked.granted = \u4f60\u7684\u7ba1\u7406\u6b0a\u9650\u5df2\u88ab\u64a4\u92b7 -message.your.voice.granted = \u5728\u9019\u500b\u6703\u8b70\u4e2d\u4f60\u5df2\u88ab\u6388\u4e88\u767c\u8a00\u6b0a -message.your.voice.revoked = \u4f60\u7684\u767c\u8a00\u6b0a\u5df2\u88ab\u64a4\u92b7 -message.groupchat.require.password = \u9019\u500b\u7fa4\u7d44\u6703\u8b70\u5ba4\u9700\u8981\u8f38\u5165\u5bc6\u78bc\u624d\u80fd\u9032\u5165 -message.groupchat.registered.member = \u8a3b\u518a\u6210\u529f -message.search.for.history = \u67e5\u8a62\u804a\u5929\u7684\u6b77\u53f2\u8a18\u9304 -message.search.period.month.one = \u6bcf\u9801\u986f\u793a\u4e00\u500b\u6708\u7684\u8a0a\u606f -message.search.period.year.one = \u6bcf\u9801\u986f\u793a\u4e00\u5e74\u7684\u8a0a\u606f -message.search.period.none = \u6240\u6709\u8a0a\u606f\u986f\u793a\u5728\u4e00\u500b\u9801\u9762\u4e0a -message.search.page.timeperiod = \u9078\u64c7\u4f7f\u7528\u4ec0\u9ebc\u6642\u9593\u8de8\u5ea6\u986f\u793a\u8a0a\u606f,\u5176\u4e2d\u6bcf\u9801\u986f\u793a -message.search.page.counter = \u4f60\u7684\u9801\u9762\u5728\u7576\u524d\u7d22\u5f15\u7684\u6240\u6709\u7db2\u9801\u7684\u6578\u91cf -message.search.page.right = \u4e0b\u4e00\u9801 -message.search.page.left = \u4e0a\u4e00\u9801 - -status.away = \u96e2\u958b -status.custom.messages = \u81ea\u5b9a\u7fa9\u6d88\u606f -status.do.not.disturb = \u8acb\u52ff\u6253\u64fe -status.extended.away = \u9577\u6642\u9593\u96e2\u958b -status.free.to.chat = \u6709\u7a7a\u804a\u5929 -status.on.phone = \u96fb\u8a71\u4e2d -status.online = \u5728\u7dda\u4e0a -status.pending = \u9023\u63a5\u4e2d -status.invisible = \u96b1\u85cf\u6a21\u5f0f -status.offline = \u96e2\u7dda - -tab.general = \u4E00\u822C -tab.proxy = \u4ee3\u7406\u4f3a\u670d\u5668 -tab.contacts = \u806f\u7d61\u4eba -tab.installed.plugins = \u5DF2\u5B89\u88DD\u7684\u63D2\u4EF6 -tab.available.plugins = \u53EF\u7528\u7684\u63D2\u4EF6 -tab.personal = \u500B\u4EBA -tab.business = \u5546\u52D9 -tab.home = \u5BB6\u5EAD -tab.avatar = \u986f\u793a\u982d\u50cf\u5716\u7247 -tab.conferences = \u6703\u8B70 -tab.deactivated.plugins = \u5df2\u505c\u7528\u7684\u63d2\u4ef6 -tab.sso = SSO -tab.pki = PKI - -title.passwords.no.match = \u78BA\u8A8D\u5BC6\u78BC\u3002 -title.create.problem = \u5efa\u7acb\u5e33\u6236\u554f\u984c -title.account.created = \u5efa\u7acb\u5e33\u6236 -title.create.new.account = \u5EFA\u7ACB\u65B0\u5E33\u6236 -title.account.create.registration = \u5e33\u6236\u8a3b\u518a -title.register.account = \u8a3b\u518a\u65b0\u5e33\u6236 -title.notification = \u901A\u77E5 -title.advanced.connection.preferences = \u9032\u968e\u8a2d\u5b9a -title.preferences = \u8a2d\u5b9a -title.error = \u932F\u8AA4 -title.status.message = \u986f\u793a\u72c0\u614b\u8a0a\u606f -title.spark.preferences = Spark \u504f\u597d\u8a2d\u5b9a -title.alert = \u8B66\u5831 -title.tray.information = \u6258\u76E4\u4FE1\u606F -title.select.file.to.send = \u9078\u64C7\u8981\u767C\u9001\u7684\u6587\u4EF6 -title.choose.directory = \u9078\u64C7\u76EE\u9304 -title.confirmation = \u78BA\u8A8D -title.last.activity = \u67e5\u770b\u6700\u5f8c\u4e00\u500b\u6d3b\u52d5 -title.add.new.group = \u65b0\u589e\u7fa4\u7d44 -title.add.to.roster = \u65B0\u589E\u5230\u540D\u55AE -title.find.contacts = \u5c0b\u627e\u806f\u7d61\u4eba -title.rename.roster.group = \u540d\u55ae\u7fa4\u7d44\u91cd\u65b0\u547d\u540d -title.roster = \u540D\u55AE -title.create.or.join = \u65b0\u5efa\u6216\u52a0\u5165 -title.conference.rooms = \u6703\u8B70\u5BA4 -title.invite.to.conference = \u9080\u8acb\u53c3\u8207\u6703\u8b70 -title.room.information = \u6703\u8b70\u5ba4\u8cc7\u8a0a -title.change.nickname = \u66f4\u6539\u66b1\u7a31 -title.group.chat = \u7fa4\u7d44\u804a\u5929 -title.create.or.bookmark.room = \u52a0\u5165\u6216\u65b0\u589e\u66f8\u7c64\u5ba4 -title.browse.room.service = \u700F\u89BD\u6703\u8B70\u5BA4 -title.name = \u540d\u7a31 -title.address = \u5730\u5740 -title.advanced.connection.sso = \u4F7F\u7528\u55AE\u9EDE\u767B\u5165 -title.advanced.connection.usesso = \u901A\u904EGSSAPI\u4F7F\u7528\u55AE\u9EDE\u767B\u9304 -title.advanced.connection.sso.noprincipal = Spark\u7121\u6CD5\u627E\u5230\u4F7F\u7528\u55AE\u9EDE\u767B\u9304\u7684\u4E3B\u9AD4\u3002\u9019\u5C07\u9632\u6B62SSO\u7121\u6CD5\u6B63\u5E38\u5DE5\u4F5C\u3002 -title.occupants = \u6703\u8b70\u5ba4\u4e2d\u4e00\u822c\u53c3\u8207\u8005 -title.browse.conference.services = \u700f\u89bd\u6703\u8b70\u5ba4\u670d\u52d9 -title.find.conference.service = \u5c0b\u627e\u6703\u8b70\u670d\u52d9 -title.configure.chat.room = \u8a2d\u5b9a\u6703\u8b70\u5ba4 -title.conference.invitation = \u6703\u8b70\u5ba4\u9080\u8acb -title.join.conference.room = \u52a0\u5165\u6703\u8b70\u5ba4 -title.view.room.information = \u67e5\u770b\u6703\u8b70\u5ba4\u8cc7\u8a0a -title.configure.room = \u8a2d\u5b9a\u6703\u8b70\u5ba4\u8cc7\u8a0a -title.change.subject = \u8b8a\u66f4\u4e3b\u984c -title.enter.reason = \u8F38\u5165\u7406\u7531 -title.room.destroyed = \u64a4\u92b7\u6703\u8b70\u5ba4 -title.edit.custom.message = \u7de8\u8f2f\u81ea\u5b9a\u7fa9\u72c0\u614b\u6d88\u606f -title.set.status.message = \u8A2D\u5B9A\u72C0\u614B\u6D88\u606F -title.broadcast.message = \u5ee3\u64ad\u8a0a\u606f -title.start.chat = \u958b\u59cb\u804a\u5929 -title.view.bookmarks = \u67E5\u770B\u66F8\u7C64 -title.downloads = \u4E0B\u8F09 -title.file.exists = \u6A94\u6848\u5B58\u5728 -title.disable.transport = \u522a\u9664\u767b\u5165\u8cc7\u8a0a -title.available.transports = \u53ef\u7528\u7684\u50b3\u8f38\u65b9\u5f0f -title.transports = \u50b3\u8f38\u65b9\u5f0f -title.aim.registration = AIM \u5e33\u865f\u8a2d\u7f6e -title.msn.registration = MSN \u5e33\u865f\u8a2d\u7f6e -title.yahoo.registration = Yahoo \u5E33\u6236\u6191\u8B49 -title.icq.registration = ICQ \u5e33\u865f\u8a2d\u7f6e -title.registration.error = \u8A3B\u518A\u932F\u8AA4 -title.jabber.browser = \u700F\u89BD\u5668 -title.version.and.time = \u7248\u672C\u548C\u6642\u9593 -title.waiting.to.call = \u7b49\u5f85\u547c\u53eb -title.incoming.call = \u547c\u53eb -title.on.the.phone = \u96fb\u8a71\u4e2d -title.dial.phone = \u64a5\u6253\u96fb\u8a71 -title.history.for = \u804a\u5929\u6b77\u53f2\u8a18\u9304 -title.reminder = \u63D0\u9192 -title.plugins = \u63D2\u4EF6 -title.general.chat.settings = \u4e00\u822c\u804a\u5929\u8a2d\u5b9a -title.chat = \u804a\u5929 -title.notifications = \u901A\u77E5 -title.sound.preferences = \u8072\u97F3\u8A2D\u5B9A -title.sounds = \u8072\u97F3 -title.choose.incoming.sound = \u9078\u64C7\u50B3\u5165\u7684\u8A9E\u97F3\u6A94\u6848 -title.choose.outgoing.sound = \u9078\u64C7\u8F38\u51FA\u7684\u8072\u97F3\u6A94\u6848 -title.choose.offline.sound = \u9078\u64C7\u96E2\u7DDA\u8072\u97F3\u6A94\u6848 -title.edit.profile = \u7de8\u8f2f\u500b\u4eba\u7c21\u4ecb -title.profile.information = \u7C21\u4ECB\u8CC7\u8A0A -title.profile.not.found = \u627e\u4e0d\u5230\u500b\u4eba\u7c21\u4ecb -title.view.profile.for = \u67e5\u770b\u500b\u4eba\u7c21\u4ecb -title.lookup.profile = \u67e5\u95b1\u500b\u4eba\u7c21\u4ecb -title.add.search.service = \u65b0\u589e\u641c\u5c0b\u670d\u52d9 -title.person.search = \u5c0b\u627e\u806f\u7d61\u4eba -title.login.settings = \u767B\u5165\u8A2D\u5B9A -title.login = \u767B\u5165 -title.downloading.im.client = \u4e0b\u8f09 IM \u5ba2\u6236\u7aef -title.upgrading.client = \u66f4\u65b0\u5ba2\u6236\u7aef -title.cancelled = \u88AB\u53D6\u6D88 -title.new.version.available = \u53ef\u7528\u7684\u65b0\u7248\u672c -title.new.client.available = \u53ef\u7528\u7684\u7684\u65b0\u5ba2\u6236\u7aef -title.password = \u5BC6\u78BC -title.download.complete = \u4E0B\u8F09\u5B8C\u6210 -title.new.roster.group = \u65b0\u540d\u55ae\u7fa4\u7d44 -title.add.contact.group = \u65b0\u589e\u806f\u7d61\u4eba\u7fa4\u7d44 -title.add.contact = \u65b0\u589e\u806f\u7d61\u4eba -title.file.transfer.preferences = \u6A94\u6848\u50B3\u8F38\u8A2D\u5B9A -title.file.transfer = \u6A94\u6848\u50B3\u8F38 -title.about = \u95dc\u65bc -title.password.required = \u9700\u8981\u8f38\u5165\u5bc6\u78bc -title.task.notification = \u4efb\u52d9\u901a\u77e5 -title.client.logs = \u5ba2\u6236\u7aef\u65e5\u8a8c -title.bookmarks = \u66f8\u7c64 -title.advanced.connection.sso.account = \u5c07\u4f7f\u7528\u684c\u9762\u5e33\u6236\u767b\u5165\u5230\u670d\u52d9\u5668 -title.advanced.connection.sso.unable = \u7121\u6cd5\u4f7f\u7528\u55ae\u9ede\u767b\u9304\u9023\u63a5,\u8acb\u6aa2\u67e5\u4f60\u7684\u4e3b\u6a5f\u548c\u4f3a\u670d\u5668\u8a2d\u5b9a -title.appearance = \u5916\u89c0 -title.appearance.preferences = \u81ea\u5b9a\u7fa9 -title.delete.file = \u771f\u7684\u8981\u522a\u9664\u9019\u500b\u6587\u4ef6\u55ce? -title.error.couldnt.open.file = \u7121\u6cd5\u6253\u958b\u6587\u4ef6 -title.error.delete.file = \u7121\u6cd5\u522a\u9664\u6587\u4ef6 -title.error.find.app = \u7121\u6cd5\u627e\u5230\u5408\u9069\u7684\u61c9\u7528 -title.error.rename.file = \u6587\u4ef6\u7121\u6cd5\u91cd\u65b0\u547d\u540d -title.file = \u6a94\u6848 -title.filesize = \u5927\u5c0f -title.gadugadu.registration = GaduGadu \u5e33\u865f\u8a2d\u7f6e -title.general.media = \u5a92\u9ad4\u8a2d\u7f6e -title.group.chat.settings = \u7fa4\u804a\u8a2d\u5b9a -title.gtalk.registration = GTalk \u5e33\u6236\u6191\u8b49 -title.irc.registration = IRC \u5e33\u865f\u8a2d\u7f6e -title.sametime.registration = Sametime \u5e33\u865f\u8a2d\u7f6e -title.facebook.registration = Facebook \u5e33\u865f\u8a2d\u7f6e -title.myspace.registration = MySpace \u5e33\u865f\u8a2d\u7f6e -title.input.fileexplorer = \u8acb\u8f38\u5165\u60a8\u7684\u6587\u4ef6\u700f\u89bd\u5668\u7684\u540d\u7a31: -title.input.newname = \u8acb\u8f38\u5165\u65b0\u7684\u540d\u7a31: -title.input.openwith = \u8acb\u8f38\u5165\u60a8\u60f3\u8981\u4f7f\u7528\u7684\u61c9\u7528\u7a0b\u5e8f\u7684\u540d\u7a31: -title.login.no.account = \u7121\u6cd5\u78ba\u5b9a -title.login.error = \u767b\u5165\u932f\u8aa4 -title.no.updates = \u7121\u66f4\u65b0 -title.notes = \u6ce8\u610f\u4e8b\u9805 -title.qq.registration = QQ \u5e33\u865f\u8a2d\u7f6e -title.xmpp.registration = XMPP \u5e33\u865f\u8a2d\u7f6e -title.simple.registration = SIMPLE \u5e33\u6236\u6191\u8b49 -title.tasks = \u4efb\u52d9 -title.appearance.showVCards = \u5728\u806f\u7d61\u4eba\u5217\u8868\u4e2d\u67e5\u770b\u96fb\u5b50\u540d\u7247 -title.subscription.request = \u8a62\u554f\u8a02\u95b1\u9700\u6c42 - -tooltip.place.a.call = \u8acb\u547c\u53eb\u6b64\u806f\u7d61\u4eba -tooltip.view.history = \u67e5\u770b\u5c0d\u8a71\u6b77\u53f2\u8a18\u9304 -tooltip.view.changelog = \u67e5\u770b\u8b8a\u66f4\u65e5\u8a8c -tooltip.view.readme = \u67e5\u770b\u95dc\u65bc\u6211 -tooltip.notifications = \u804a\u5929\u547c\u53eb\u504f\u597d\u901a\u77e5 -tooltip.place.voice.call = \u64a5\u6253\u96fb\u8a71\u7d66\u6b64\u806f\u7d61\u4eba -tooltip.appearance = \u6539\u8b8a\u804a\u5929\u8996\u7a97\u7684\u5916\u89c0 -tooltip.file.transfer = \u6587\u4ef6\u50b3\u8f38\u504f\u597d -tooltip.send.email = \u767c\u9001\u96fb\u5b50\u90f5\u4ef6 -tooltip.start.chat = \u958b\u59cb\u5c0d\u8a71 - -tree.conference.services = \u6703\u8B70\u670D\u52D9 -tree.users.in.room = \u5728\u6703\u8b70\u5ba4\u7684\u4f7f\u7528\u8005 - -lookandfeel.select = \u9078\u64c7\u5916\u89c0\u6a23\u5f0f -lookandfeel.change.now = \u7acb\u5373\u8b8a\u66f4 -lookandfeel.tooltip.restart.no = \u4e0d\u9700\u8981\u91cd\u65b0\u555f\u52d5 -lookandfeel.tooltip.restart.yes = \u66f4\u63db\u5916\u89c0\u6a23\u5f0f\u9700\u6309\u5132\u5b58\u4e14\u91cd\u65b0\u555f\u52d5 Spark -lookandfeel.color.label = \u984f\u8272 -lookandfeel.color.red = \u7d05\u8272 -lookandfeel.color.green = \u7da0\u8272 -lookandfeel.color.blue = \u85cd\u8272 -lookandfeel.color.opacity = \u900f\u660e\u5ea6 -lookandfeel.color.saved = \u5132\u5b58\u8272\u5f69\u8a2d\u5b9a - - -##Settings for the privacy plugin -privacy.title.preferences = Spark \u96B1\u79C1\u504F\u597D -privacy.title.panel = \u4F7F\u7528\u6ED1\u9F20\u53F3\u9375 -privacy.label.iq.desc = \u8a62\u554f -privacy.label.pin.desc = \u52a0\u5165 -privacy.label.pout.desc = \u79FB\u9664 -privacy.label.msg.desc = \u8a0A\u606F -privacy.border.information = \u96B1\u79C1\u8CC7\u8A0A -privacy.label.information = \u4f7f\u7528\u53f3\u9375\u9ede\u64ca\u9078\u55ae\u4ee5\u65b0\u589e\u6216\u522a\u9664\u9805\u76ee -privacy.root.node = \u96b1\u79c1\u5217\u8868 -privacy.label.preferences = \u96b1\u79c1\u63d2\u4ef6 -pricacy.tooltip.preferences = Spark \u96b1\u79c1\u8a2d\u5b9a -privacy.label.list.is.active = \u7576\u524d\u5de5\u4f5c\u5217\u8868: -privacy.label.list.is.default = \u9810\u8a2d\u5217\u8868: -privacy.border.block = \u5340\u584a -privacy.pick.one.or.more = \u9078\u64c7\u4e00\u500b\u6216\u591a\u500b\u9805\u76ee\u65b0\u589e\u5230\u5217\u8868 -privacy.title.add.picker = \u65b0\u589e\u9805\u76ee\u5230\u5217\u8868 -privacy.node.contacts = \u806f\u7d61\u65b9\u5f0f -privacy.node.groups = \u7fa4\u7d44 -privacy.menu.add.contacts = \u65b0\u589e\u806f\u7d61\u4eba\u5230\u5217\u8868 -privacy.menu.add.groups = \u65b0\u589e\u7fa4\u7d44\u5230\u5217\u8868 -privacy.menu.add.rem.items = \u5f9e\u5217\u8868\u4e2d\u522a\u9664\u9805\u76ee -privacy.menu.remove = \u79fb\u9664 -privacy.menu.activate.list = \u555f\u52d5 -privacy.menu.default.list = \u8a2d\u5b9a\u70ba\u9810\u8a2d -privacy.menu.add.list = \u65b0\u589e\u5217\u8868 -privacy.menu.remove.list = \u79fb\u9664\u5217\u8868 -privacy.dialog.add.list = \u8acb\u8f38\u5165\u5217\u8868\u540d\u7a31 -privacy.dialog.rem.list = \u78ba\u5b9a\u8981\u522a\u9664\u55ce? -privacy.status.menu.entry = \u96b1\u79c1\u5217\u8868 -privacy.name.for.default.list = \u9810\u8a2d -privacy.button.no.list.selected = \u672a\u9078\u64c7\u5217\u8868 -privacy.menuitem.deactivate.current.list = \u95dc\u9589 -privacy.label.not.supported = \u96b1\u79c1\u5217\u8868\u4e0d\u662f\u7531\u4f3a\u670d\u5668\u652f\u6301 - -##Stunfallback in media settings -stun.border.label = STUN \u5099\u7528\u4F3A\u670D\u5668 -stun.server.addr = Stun \u4F3A\u670D\u5668: -stun.server.port = Stun \u9023\u63A5\u57E0: - -composing = \u6B63\u5728\u6253\u5B57\u4E2D... -paused = \u5DF2\u505C\u6B62\u6253\u5B57 -active = {0} \u6B63\u5728\u89C0\u770B -inactive = \u6B63\u5728\u505A\u5176\u4ED6\u4E8B\u60C5 -gone = \u6B63\u5728\u505A\u5176\u4ED6\u4E8B\u60C5 - -#!# -action.viewlog = \u67E5\u770B\u6B77\u53F2\u8A0A\u606F - -dialog.confirm.to.reveal.visibility.title = \u4F60\u78BA\u5B9A\u55CE? -dialog.confirm.to.reveal.visibility.msg = \u7E7C\u7E8C\u57F7\u884C,\u96B1\u5F62\u767B\u5165\u72C0\u614B\u5C07\u88AB\u53D6\u6D88 -dialog.confirm.close.all.conferences.if.invisible.msg = \u7E7C\u7E8C\u57F7\u884C,\u6240\u6709\u6703\u8B70\u5BA4\u5C07\u88AB\u95DC\u9589 \ No newline at end of file diff --git a/src/resources/images/Away-24x24.png b/src/resources/images/Away-24x24.png deleted file mode 100644 index 492198189..000000000 Binary files a/src/resources/images/Away-24x24.png and /dev/null differ diff --git a/src/resources/images/DoNotDisturb-24x24.png b/src/resources/images/DoNotDisturb-24x24.png deleted file mode 100644 index eba4b689b..000000000 Binary files a/src/resources/images/DoNotDisturb-24x24.png and /dev/null differ diff --git a/src/resources/images/User1_32x32.png b/src/resources/images/User1_32x32.png deleted file mode 100644 index e12702c28..000000000 Binary files a/src/resources/images/User1_32x32.png and /dev/null differ diff --git a/src/resources/images/add_24x24.png b/src/resources/images/add_24x24.png deleted file mode 100644 index a871081ed..000000000 Binary files a/src/resources/images/add_24x24.png and /dev/null differ diff --git a/src/resources/images/aim-gray.gif b/src/resources/images/aim-gray.gif deleted file mode 100644 index 623c17c41..000000000 Binary files a/src/resources/images/aim-gray.gif and /dev/null differ diff --git a/src/resources/images/aim.gif b/src/resources/images/aim.gif deleted file mode 100644 index fc944c293..000000000 Binary files a/src/resources/images/aim.gif and /dev/null differ diff --git a/src/resources/images/alert.png b/src/resources/images/alert.png deleted file mode 100644 index 14f7465bd..000000000 Binary files a/src/resources/images/alert.png and /dev/null differ diff --git a/src/resources/images/blank_24x24.png b/src/resources/images/blank_24x24.png deleted file mode 100644 index ff0368b95..000000000 Binary files a/src/resources/images/blank_24x24.png and /dev/null differ diff --git a/src/resources/images/blue-steel-background.png b/src/resources/images/blue-steel-background.png deleted file mode 100644 index b05716e9b..000000000 Binary files a/src/resources/images/blue-steel-background.png and /dev/null differ diff --git a/src/resources/images/blueArrowRight.png b/src/resources/images/blueArrowRight.png deleted file mode 100644 index 9ce870f72..000000000 Binary files a/src/resources/images/blueArrowRight.png and /dev/null differ diff --git a/src/resources/images/bullet_ball_glass_clear.png b/src/resources/images/bullet_ball_glass_clear.png deleted file mode 100644 index f0bbd027d..000000000 Binary files a/src/resources/images/bullet_ball_glass_clear.png and /dev/null differ diff --git a/src/resources/images/call.png b/src/resources/images/call.png deleted file mode 100644 index 1882f470c..000000000 Binary files a/src/resources/images/call.png and /dev/null differ diff --git a/src/resources/images/clipboard.png b/src/resources/images/clipboard.png deleted file mode 100644 index 52e4ddc13..000000000 Binary files a/src/resources/images/clipboard.png and /dev/null differ diff --git a/src/resources/images/close.png b/src/resources/images/close.png deleted file mode 100644 index 014f53e88..000000000 Binary files a/src/resources/images/close.png and /dev/null differ diff --git a/src/resources/images/close_dark.png b/src/resources/images/close_dark.png deleted file mode 100644 index 87a082c64..000000000 Binary files a/src/resources/images/close_dark.png and /dev/null differ diff --git a/src/resources/images/close_white.png b/src/resources/images/close_white.png deleted file mode 100644 index b76a93c20..000000000 Binary files a/src/resources/images/close_white.png and /dev/null differ diff --git a/src/resources/images/colors.png b/src/resources/images/colors.png deleted file mode 100644 index 1d75e5bce..000000000 Binary files a/src/resources/images/colors.png and /dev/null differ diff --git a/src/resources/images/conference_32x32.png b/src/resources/images/conference_32x32.png deleted file mode 100644 index 43daac90e..000000000 Binary files a/src/resources/images/conference_32x32.png and /dev/null differ diff --git a/src/resources/images/default_avatar_32x32.png b/src/resources/images/default_avatar_32x32.png deleted file mode 100644 index 52bc1d225..000000000 Binary files a/src/resources/images/default_avatar_32x32.png and /dev/null differ diff --git a/src/resources/images/default_avatar_64x64.png b/src/resources/images/default_avatar_64x64.png deleted file mode 100644 index 4a6ad0f2a..000000000 Binary files a/src/resources/images/default_avatar_64x64.png and /dev/null differ diff --git a/src/resources/images/document_attachment-32x32.png b/src/resources/images/document_attachment-32x32.png deleted file mode 100644 index 755a5b0d0..000000000 Binary files a/src/resources/images/document_attachment-32x32.png and /dev/null differ diff --git a/src/resources/images/document_exchange.png b/src/resources/images/document_exchange.png deleted file mode 100644 index 745916fcb..000000000 Binary files a/src/resources/images/document_exchange.png and /dev/null differ diff --git a/src/resources/images/document_info.png b/src/resources/images/document_info.png deleted file mode 100644 index b35fef43d..000000000 Binary files a/src/resources/images/document_info.png and /dev/null differ diff --git a/src/resources/images/document_into.png b/src/resources/images/document_into.png deleted file mode 100644 index 3dce3fae5..000000000 Binary files a/src/resources/images/document_into.png and /dev/null differ diff --git a/src/resources/images/dummyContact.png b/src/resources/images/dummyContact.png deleted file mode 100644 index 5149ea57d..000000000 Binary files a/src/resources/images/dummyContact.png and /dev/null differ diff --git a/src/resources/images/emoticons/angry.png b/src/resources/images/emoticons/angry.png deleted file mode 100644 index 02a3f0161..000000000 Binary files a/src/resources/images/emoticons/angry.png and /dev/null differ diff --git a/src/resources/images/emoticons/blush.png b/src/resources/images/emoticons/blush.png deleted file mode 100644 index 82e7456d8..000000000 Binary files a/src/resources/images/emoticons/blush.png and /dev/null differ diff --git a/src/resources/images/emoticons/confused.png b/src/resources/images/emoticons/confused.png deleted file mode 100644 index d5e4be299..000000000 Binary files a/src/resources/images/emoticons/confused.png and /dev/null differ diff --git a/src/resources/images/emoticons/cool.png b/src/resources/images/emoticons/cool.png deleted file mode 100644 index 090464c8a..000000000 Binary files a/src/resources/images/emoticons/cool.png and /dev/null differ diff --git a/src/resources/images/emoticons/cry.png b/src/resources/images/emoticons/cry.png deleted file mode 100644 index f34b7fddd..000000000 Binary files a/src/resources/images/emoticons/cry.png and /dev/null differ diff --git a/src/resources/images/emoticons/devil.png b/src/resources/images/emoticons/devil.png deleted file mode 100644 index 57e60eedc..000000000 Binary files a/src/resources/images/emoticons/devil.png and /dev/null differ diff --git a/src/resources/images/emoticons/eyeRoll.gif b/src/resources/images/emoticons/eyeRoll.gif deleted file mode 100644 index 0e8270737..000000000 Binary files a/src/resources/images/emoticons/eyeRoll.gif and /dev/null differ diff --git a/src/resources/images/emoticons/grin.png b/src/resources/images/emoticons/grin.png deleted file mode 100644 index 3932d475f..000000000 Binary files a/src/resources/images/emoticons/grin.png and /dev/null differ diff --git a/src/resources/images/emoticons/happy.png b/src/resources/images/emoticons/happy.png deleted file mode 100644 index ae922204a..000000000 Binary files a/src/resources/images/emoticons/happy.png and /dev/null differ diff --git a/src/resources/images/emoticons/laugh.png b/src/resources/images/emoticons/laugh.png deleted file mode 100644 index 1574cc384..000000000 Binary files a/src/resources/images/emoticons/laugh.png and /dev/null differ diff --git a/src/resources/images/emoticons/love.png b/src/resources/images/emoticons/love.png deleted file mode 100644 index d5580218e..000000000 Binary files a/src/resources/images/emoticons/love.png and /dev/null differ diff --git a/src/resources/images/emoticons/mischief.png b/src/resources/images/emoticons/mischief.png deleted file mode 100644 index 5da82ffcf..000000000 Binary files a/src/resources/images/emoticons/mischief.png and /dev/null differ diff --git a/src/resources/images/emoticons/party.gif b/src/resources/images/emoticons/party.gif deleted file mode 100644 index e43f28089..000000000 Binary files a/src/resources/images/emoticons/party.gif and /dev/null differ diff --git a/src/resources/images/emoticons/plain.png b/src/resources/images/emoticons/plain.png deleted file mode 100644 index 2a0459185..000000000 Binary files a/src/resources/images/emoticons/plain.png and /dev/null differ diff --git a/src/resources/images/emoticons/sad.png b/src/resources/images/emoticons/sad.png deleted file mode 100644 index d336ce2bc..000000000 Binary files a/src/resources/images/emoticons/sad.png and /dev/null differ diff --git a/src/resources/images/emoticons/shocked.png b/src/resources/images/emoticons/shocked.png deleted file mode 100644 index b02c7bcc3..000000000 Binary files a/src/resources/images/emoticons/shocked.png and /dev/null differ diff --git a/src/resources/images/emoticons/silly.png b/src/resources/images/emoticons/silly.png deleted file mode 100644 index 7688458af..000000000 Binary files a/src/resources/images/emoticons/silly.png and /dev/null differ diff --git a/src/resources/images/emoticons/sleepy.gif b/src/resources/images/emoticons/sleepy.gif deleted file mode 100644 index d40769fb6..000000000 Binary files a/src/resources/images/emoticons/sleepy.gif and /dev/null differ diff --git a/src/resources/images/emoticons/wink.png b/src/resources/images/emoticons/wink.png deleted file mode 100644 index aa25da943..000000000 Binary files a/src/resources/images/emoticons/wink.png and /dev/null differ diff --git a/src/resources/images/end_button_24x24.png b/src/resources/images/end_button_24x24.png deleted file mode 100644 index 882335806..000000000 Binary files a/src/resources/images/end_button_24x24.png and /dev/null differ diff --git a/src/resources/images/find.png b/src/resources/images/find.png deleted file mode 100644 index d70e4ae62..000000000 Binary files a/src/resources/images/find.png and /dev/null differ diff --git a/src/resources/images/folders.png b/src/resources/images/folders.png deleted file mode 100644 index 44a6c9783..000000000 Binary files a/src/resources/images/folders.png and /dev/null differ diff --git a/src/resources/images/gray-background.png b/src/resources/images/gray-background.png deleted file mode 100644 index fa0867962..000000000 Binary files a/src/resources/images/gray-background.png and /dev/null differ diff --git a/src/resources/images/gtalk-gray.png b/src/resources/images/gtalk-gray.png deleted file mode 100644 index c073495d9..000000000 Binary files a/src/resources/images/gtalk-gray.png and /dev/null differ diff --git a/src/resources/images/gtalk.png b/src/resources/images/gtalk.png deleted file mode 100644 index d2910948f..000000000 Binary files a/src/resources/images/gtalk.png and /dev/null differ diff --git a/src/resources/images/help_24x24.png b/src/resources/images/help_24x24.png deleted file mode 100644 index 0a3fcc3a8..000000000 Binary files a/src/resources/images/help_24x24.png and /dev/null differ diff --git a/src/resources/images/history-24x24.png b/src/resources/images/history-24x24.png deleted file mode 100644 index c5af4d1fb..000000000 Binary files a/src/resources/images/history-24x24.png and /dev/null differ diff --git a/src/resources/images/icq-gray.gif b/src/resources/images/icq-gray.gif deleted file mode 100644 index b16991795..000000000 Binary files a/src/resources/images/icq-gray.gif and /dev/null differ diff --git a/src/resources/images/icq-gray.png b/src/resources/images/icq-gray.png deleted file mode 100644 index 8b4f60eae..000000000 Binary files a/src/resources/images/icq-gray.png and /dev/null differ diff --git a/src/resources/images/icq.gif b/src/resources/images/icq.gif deleted file mode 100644 index 800af9c18..000000000 Binary files a/src/resources/images/icq.gif and /dev/null differ diff --git a/src/resources/images/icq.png b/src/resources/images/icq.png deleted file mode 100644 index 70f70bb0b..000000000 Binary files a/src/resources/images/icq.png and /dev/null differ diff --git a/src/resources/images/id_card.png b/src/resources/images/id_card.png deleted file mode 100644 index a8e9d6f7a..000000000 Binary files a/src/resources/images/id_card.png and /dev/null differ diff --git a/src/resources/images/im_available_stale.png b/src/resources/images/im_available_stale.png deleted file mode 100644 index aec752584..000000000 Binary files a/src/resources/images/im_available_stale.png and /dev/null differ diff --git a/src/resources/images/im_away.png b/src/resources/images/im_away.png deleted file mode 100644 index a98f68b74..000000000 Binary files a/src/resources/images/im_away.png and /dev/null differ diff --git a/src/resources/images/im_away_stale.png b/src/resources/images/im_away_stale.png deleted file mode 100644 index 4742be3bf..000000000 Binary files a/src/resources/images/im_away_stale.png and /dev/null differ diff --git a/src/resources/images/im_dnd.png b/src/resources/images/im_dnd.png deleted file mode 100644 index 49e3ed677..000000000 Binary files a/src/resources/images/im_dnd.png and /dev/null differ diff --git a/src/resources/images/im_dnd_stale.png b/src/resources/images/im_dnd_stale.png deleted file mode 100644 index f64bcf225..000000000 Binary files a/src/resources/images/im_dnd_stale.png and /dev/null differ diff --git a/src/resources/images/im_free_chat.png b/src/resources/images/im_free_chat.png deleted file mode 100644 index e89d7de2b..000000000 Binary files a/src/resources/images/im_free_chat.png and /dev/null differ diff --git a/src/resources/images/im_free_chat_stale.png b/src/resources/images/im_free_chat_stale.png deleted file mode 100644 index 82aa5143a..000000000 Binary files a/src/resources/images/im_free_chat_stale.png and /dev/null differ diff --git a/src/resources/images/im_invisible.png b/src/resources/images/im_invisible.png deleted file mode 100644 index 8f882c075..000000000 Binary files a/src/resources/images/im_invisible.png and /dev/null differ diff --git a/src/resources/images/im_unavailable.png b/src/resources/images/im_unavailable.png deleted file mode 100644 index f0bbd027d..000000000 Binary files a/src/resources/images/im_unavailable.png and /dev/null differ diff --git a/src/resources/images/im_unavailable_stale.png b/src/resources/images/im_unavailable_stale.png deleted file mode 100644 index 8f882c075..000000000 Binary files a/src/resources/images/im_unavailable_stale.png and /dev/null differ diff --git a/src/resources/images/irc-gray.png b/src/resources/images/irc-gray.png deleted file mode 100644 index 9957dd10a..000000000 Binary files a/src/resources/images/irc-gray.png and /dev/null differ diff --git a/src/resources/images/irc.png b/src/resources/images/irc.png deleted file mode 100644 index 6a6322fa1..000000000 Binary files a/src/resources/images/irc.png and /dev/null differ diff --git a/src/resources/images/lightning16.png b/src/resources/images/lightning16.png deleted file mode 100644 index bec2e9d98..000000000 Binary files a/src/resources/images/lightning16.png and /dev/null differ diff --git a/src/resources/images/login_dialog_background.png b/src/resources/images/login_dialog_background.png deleted file mode 100644 index b315152ea..000000000 Binary files a/src/resources/images/login_dialog_background.png and /dev/null differ diff --git a/src/resources/images/mail_32x32.png b/src/resources/images/mail_32x32.png deleted file mode 100644 index 0b7c44cb2..000000000 Binary files a/src/resources/images/mail_32x32.png and /dev/null differ diff --git a/src/resources/images/message-32x32.png b/src/resources/images/message-32x32.png deleted file mode 100644 index 6b851f02b..000000000 Binary files a/src/resources/images/message-32x32.png and /dev/null differ diff --git a/src/resources/images/message_away.png b/src/resources/images/message_away.png deleted file mode 100644 index fead7b7b1..000000000 Binary files a/src/resources/images/message_away.png and /dev/null differ diff --git a/src/resources/images/message_dnd.png b/src/resources/images/message_dnd.png deleted file mode 100644 index bf8f82247..000000000 Binary files a/src/resources/images/message_dnd.png and /dev/null differ diff --git a/src/resources/images/messages_48x48.png b/src/resources/images/messages_48x48.png deleted file mode 100644 index 3a1eb08bb..000000000 Binary files a/src/resources/images/messages_48x48.png and /dev/null differ diff --git a/src/resources/images/minus-sign.png b/src/resources/images/minus-sign.png deleted file mode 100644 index 0d416ec24..000000000 Binary files a/src/resources/images/minus-sign.png and /dev/null differ diff --git a/src/resources/images/mobilephone.png b/src/resources/images/mobilephone.png deleted file mode 100644 index 0fe2c3000..000000000 Binary files a/src/resources/images/mobilephone.png and /dev/null differ diff --git a/src/resources/images/msn-gray.png b/src/resources/images/msn-gray.png deleted file mode 100644 index 616edbf6f..000000000 Binary files a/src/resources/images/msn-gray.png and /dev/null differ diff --git a/src/resources/images/msn.png b/src/resources/images/msn.png deleted file mode 100644 index 247f607d2..000000000 Binary files a/src/resources/images/msn.png and /dev/null differ diff --git a/src/resources/images/off-phone.png b/src/resources/images/off-phone.png deleted file mode 100644 index f3473cd3f..000000000 Binary files a/src/resources/images/off-phone.png and /dev/null differ diff --git a/src/resources/images/on-phone.png b/src/resources/images/on-phone.png deleted file mode 100644 index f7d6a1e18..000000000 Binary files a/src/resources/images/on-phone.png and /dev/null differ diff --git a/src/resources/images/palette_24x24.png b/src/resources/images/palette_24x24.png deleted file mode 100644 index d4e2bc7f8..000000000 Binary files a/src/resources/images/palette_24x24.png and /dev/null differ diff --git a/src/resources/images/phone_call.png b/src/resources/images/phone_call.png deleted file mode 100644 index aced012e8..000000000 Binary files a/src/resources/images/phone_call.png and /dev/null differ diff --git a/src/resources/images/photo_scenery.png b/src/resources/images/photo_scenery.png deleted file mode 100644 index ceeebd356..000000000 Binary files a/src/resources/images/photo_scenery.png and /dev/null differ diff --git a/src/resources/images/plug-sign.png b/src/resources/images/plug-sign.png deleted file mode 100644 index 9429408c4..000000000 Binary files a/src/resources/images/plug-sign.png and /dev/null differ diff --git a/src/resources/images/plus-sign.png b/src/resources/images/plus-sign.png deleted file mode 100644 index 9429408c4..000000000 Binary files a/src/resources/images/plus-sign.png and /dev/null differ diff --git a/src/resources/images/powered_by.png b/src/resources/images/powered_by.png deleted file mode 100644 index 11b5bed7b..000000000 Binary files a/src/resources/images/powered_by.png and /dev/null differ diff --git a/src/resources/images/privacy_icon.png b/src/resources/images/privacy_icon.png deleted file mode 100644 index f55adeabf..000000000 Binary files a/src/resources/images/privacy_icon.png and /dev/null differ diff --git a/src/resources/images/privacy_message_allow.png b/src/resources/images/privacy_message_allow.png deleted file mode 100644 index 8755978a4..000000000 Binary files a/src/resources/images/privacy_message_allow.png and /dev/null differ diff --git a/src/resources/images/privacy_message_deny.png b/src/resources/images/privacy_message_deny.png deleted file mode 100644 index 7bd6e5d43..000000000 Binary files a/src/resources/images/privacy_message_deny.png and /dev/null differ diff --git a/src/resources/images/privacy_presence_in_allow.png b/src/resources/images/privacy_presence_in_allow.png deleted file mode 100644 index 142d10bb5..000000000 Binary files a/src/resources/images/privacy_presence_in_allow.png and /dev/null differ diff --git a/src/resources/images/privacy_presence_in_deny.png b/src/resources/images/privacy_presence_in_deny.png deleted file mode 100644 index dfe64002c..000000000 Binary files a/src/resources/images/privacy_presence_in_deny.png and /dev/null differ diff --git a/src/resources/images/privacy_presence_out_allow.png b/src/resources/images/privacy_presence_out_allow.png deleted file mode 100644 index df908beac..000000000 Binary files a/src/resources/images/privacy_presence_out_allow.png and /dev/null differ diff --git a/src/resources/images/privacy_presence_out_deny.png b/src/resources/images/privacy_presence_out_deny.png deleted file mode 100644 index 955db18be..000000000 Binary files a/src/resources/images/privacy_presence_out_deny.png and /dev/null differ diff --git a/src/resources/images/privacy_query_allow.png b/src/resources/images/privacy_query_allow.png deleted file mode 100644 index 30e2ff49b..000000000 Binary files a/src/resources/images/privacy_query_allow.png and /dev/null differ diff --git a/src/resources/images/privacy_query_deny.png b/src/resources/images/privacy_query_deny.png deleted file mode 100644 index 209250c41..000000000 Binary files a/src/resources/images/privacy_query_deny.png and /dev/null differ diff --git a/src/resources/images/profile.png b/src/resources/images/profile.png deleted file mode 100644 index 6dbcc2cb3..000000000 Binary files a/src/resources/images/profile.png and /dev/null differ diff --git a/src/resources/images/profile_24x24.png b/src/resources/images/profile_24x24.png deleted file mode 100644 index 70e78af3a..000000000 Binary files a/src/resources/images/profile_24x24.png and /dev/null differ diff --git a/src/resources/images/profile_32x32.png b/src/resources/images/profile_32x32.png deleted file mode 100644 index c50ae6deb..000000000 Binary files a/src/resources/images/profile_32x32.png and /dev/null differ diff --git a/src/resources/images/search_32x32.png b/src/resources/images/search_32x32.png deleted file mode 100644 index 0396d4458..000000000 Binary files a/src/resources/images/search_32x32.png and /dev/null differ diff --git a/src/resources/images/secondary_background_image.png b/src/resources/images/secondary_background_image.png deleted file mode 100644 index 23a677ba6..000000000 Binary files a/src/resources/images/secondary_background_image.png and /dev/null differ diff --git a/src/resources/images/send_file_24x24.png b/src/resources/images/send_file_24x24.png deleted file mode 100644 index 39c31646b..000000000 Binary files a/src/resources/images/send_file_24x24.png and /dev/null differ diff --git a/src/resources/images/settings24x24.png b/src/resources/images/settings24x24.png deleted file mode 100644 index f0194c6b3..000000000 Binary files a/src/resources/images/settings24x24.png and /dev/null differ diff --git a/src/resources/images/simple-gray.png b/src/resources/images/simple-gray.png deleted file mode 100644 index f2a5db94f..000000000 Binary files a/src/resources/images/simple-gray.png and /dev/null differ diff --git a/src/resources/images/simple.png b/src/resources/images/simple.png deleted file mode 100644 index a8196177b..000000000 Binary files a/src/resources/images/simple.png and /dev/null differ diff --git a/src/resources/images/spark.png b/src/resources/images/spark.png deleted file mode 100644 index 46ab7c433..000000000 Binary files a/src/resources/images/spark.png and /dev/null differ diff --git a/src/resources/images/spark_tray_connecting-16x16.png b/src/resources/images/spark_tray_connecting-16x16.png deleted file mode 100644 index c762fcc88..000000000 Binary files a/src/resources/images/spark_tray_connecting-16x16.png and /dev/null differ diff --git a/src/resources/images/spark_tray_connecting-24x24.png b/src/resources/images/spark_tray_connecting-24x24.png deleted file mode 100644 index b4c9f707b..000000000 Binary files a/src/resources/images/spark_tray_connecting-24x24.png and /dev/null differ diff --git a/src/resources/images/spark_tray_message-24x24.png b/src/resources/images/spark_tray_message-24x24.png deleted file mode 100644 index ca160434e..000000000 Binary files a/src/resources/images/spark_tray_message-24x24.png and /dev/null differ diff --git a/src/resources/images/spark_tray_offline-16x16.png b/src/resources/images/spark_tray_offline-16x16.png deleted file mode 100644 index c762fcc88..000000000 Binary files a/src/resources/images/spark_tray_offline-16x16.png and /dev/null differ diff --git a/src/resources/images/spark_tray_offline-24x24.png b/src/resources/images/spark_tray_offline-24x24.png deleted file mode 100644 index 09e2743e5..000000000 Binary files a/src/resources/images/spark_tray_offline-24x24.png and /dev/null differ diff --git a/src/resources/images/spark_tray_typing-24x24.png b/src/resources/images/spark_tray_typing-24x24.png deleted file mode 100644 index 5d2d39e38..000000000 Binary files a/src/resources/images/spark_tray_typing-24x24.png and /dev/null differ diff --git a/src/resources/images/star_admin.png b/src/resources/images/star_admin.png deleted file mode 100644 index eedc0e423..000000000 Binary files a/src/resources/images/star_admin.png and /dev/null differ diff --git a/src/resources/images/star_moderator.png b/src/resources/images/star_moderator.png deleted file mode 100644 index 0cec9251a..000000000 Binary files a/src/resources/images/star_moderator.png and /dev/null differ diff --git a/src/resources/images/star_owner.png b/src/resources/images/star_owner.png deleted file mode 100644 index 3200f51f9..000000000 Binary files a/src/resources/images/star_owner.png and /dev/null differ diff --git a/src/resources/images/steel.png b/src/resources/images/steel.png deleted file mode 100644 index c588c2267..000000000 Binary files a/src/resources/images/steel.png and /dev/null differ diff --git a/src/resources/images/sticky.png b/src/resources/images/sticky.png deleted file mode 100644 index 06216e84c..000000000 Binary files a/src/resources/images/sticky.png and /dev/null differ diff --git a/src/resources/images/text_ok.png b/src/resources/images/text_ok.png deleted file mode 100644 index e034a2a44..000000000 Binary files a/src/resources/images/text_ok.png and /dev/null differ diff --git a/src/resources/images/toolbar.png b/src/resources/images/toolbar.png deleted file mode 100644 index 02cb432ba..000000000 Binary files a/src/resources/images/toolbar.png and /dev/null differ diff --git a/src/resources/images/top_bottom_background_image.png b/src/resources/images/top_bottom_background_image.png deleted file mode 100644 index 582e00697..000000000 Binary files a/src/resources/images/top_bottom_background_image.png and /dev/null differ diff --git a/src/resources/images/transfer-24x24.png b/src/resources/images/transfer-24x24.png deleted file mode 100644 index 32403b384..000000000 Binary files a/src/resources/images/transfer-24x24.png and /dev/null differ diff --git a/src/resources/images/transport.png b/src/resources/images/transport.png deleted file mode 100644 index 4f590469e..000000000 Binary files a/src/resources/images/transport.png and /dev/null differ diff --git a/src/resources/images/user1.png b/src/resources/images/user1.png deleted file mode 100644 index 61a0351e6..000000000 Binary files a/src/resources/images/user1.png and /dev/null differ diff --git a/src/resources/images/user1_message-24x24.png b/src/resources/images/user1_message-24x24.png deleted file mode 100644 index 34200b8f1..000000000 Binary files a/src/resources/images/user1_message-24x24.png and /dev/null differ diff --git a/src/resources/images/user2.png b/src/resources/images/user2.png deleted file mode 100644 index f72aa562f..000000000 Binary files a/src/resources/images/user2.png and /dev/null differ diff --git a/src/resources/images/user4.png b/src/resources/images/user4.png deleted file mode 100644 index 0158ffd34..000000000 Binary files a/src/resources/images/user4.png and /dev/null differ diff --git a/src/resources/images/user_headset24.png b/src/resources/images/user_headset24.png deleted file mode 100644 index 61a0351e6..000000000 Binary files a/src/resources/images/user_headset24.png and /dev/null differ diff --git a/src/resources/images/xmpp-gray.png b/src/resources/images/xmpp-gray.png deleted file mode 100644 index 851e9a6ad..000000000 Binary files a/src/resources/images/xmpp-gray.png and /dev/null differ diff --git a/src/resources/images/yahoo-gray.png b/src/resources/images/yahoo-gray.png deleted file mode 100644 index b8a916cd3..000000000 Binary files a/src/resources/images/yahoo-gray.png and /dev/null differ diff --git a/src/resources/images/yahoo.png b/src/resources/images/yahoo.png deleted file mode 100644 index d1564d7fd..000000000 Binary files a/src/resources/images/yahoo.png and /dev/null differ diff --git a/src/resources/jniwrap.dll b/src/resources/jniwrap.dll deleted file mode 100644 index 1f4c06558..000000000 Binary files a/src/resources/jniwrap.dll and /dev/null differ diff --git a/src/resources/jniwrap.lic b/src/resources/jniwrap.lic deleted file mode 100644 index c86f6ef1b..000000000 --- a/src/resources/jniwrap.lic +++ /dev/null @@ -1,11 +0,0 @@ -Thu Oct 19 14:56:36 EEST 2006 - -Jive Software -NEVER -Runtime -Not for development -win32/x86 -5lwtbvc0j4copm5e2qnjhgfv33h0nqbesyx4lfr2479w4lp4j2grqi4378utxg8t1h5rjgboe1fwxmx0 -55yhidf684qsae1pqf8pphen1gqnspw0mrygd2z10589rng339noyvxigs6e98jwql3kl59v8xr0h3en -Version: 3.x -Product: JNIWrapper diff --git a/src/resources/macros/TurbineMacros.vm b/src/resources/macros/TurbineMacros.vm deleted file mode 100644 index bc978d374..000000000 --- a/src/resources/macros/TurbineMacros.vm +++ /dev/null @@ -1,111 +0,0 @@ -## ==================================================================== -## The Apache Software License, Version 1.1 -## -## Copyright (c) 2001-2003 The Apache Software Foundation. All rights -## reserved. -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions -## are met: -## -## 1. Redistributions of source code must retain the above copyright -## notice, this list of conditions and the following disclaimer. -## -## 2. Redistributions in binary form must reproduce the above copyright -## notice, this list of conditions and the following disclaimer in -## the documentation and/or other materials provided with the -## distribution. -## -## 3. The end-user documentation included with the redistribution, -## if any, must include the following acknowledgment: -## "This product includes software developed by the -## Apache Software Foundation (http://www.apache.org/)." -## Alternately, this acknowledgment may appear in the software itself, -## if and wherever such third-party acknowledgments normally appear. -## -## 4. The names "Apache" and "Apache Software Foundation" and -## "Apache Turbine" must not be used to endorse or promote products -## derived from this software without prior written permission. For -## written permission, please contact apache@apache.org. -## -## 5. Products derived from this software may not be called "Apache", -## "Apache Turbine", nor may "Apache" appear in their name, without -## prior written permission of the Apache Software Foundation. -## -## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED -## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -## OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -## DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR -## ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -## SUCH DAMAGE. -## ==================================================================== -## -## This software consists of voluntary contributions made by many -## individuals on behalf of the Apache Software Foundation. For more -## information on the Apache Software Foundation, please see -## . -## -## @author Henning P. Schmiedehausen -## @version $Id: TurbineMacros.vm 18715 2005-04-05 17:10:46 -0700 (Tue, 05 Apr 2005) bill $ - -## -## Build the ... tag of a web page with VelocityOnly Layout -## - -#macro (TurbineHtmlHead) - - #if ($!page.Title) - $page.Title - #end - #if ($page.MetaTags.size() > 0) - #foreach($metaTag in $page.MetaTags.keySet()) - - #end - #end - #if ($page.HttpEquivs.size() > 0) - #foreach($httpEquiv in $page.HttpEquivs.keySet()) - - #end - #end - #if ($page.StyleSheets.size() > 0) - #foreach( $styleSheet in $page.StyleSheets ) - - #end - #end - #if ($page.Styles.size() > 0) - - #end - #if ($page.Scripts.size() > 0) - #foreach( $script in $page.Scripts ) - - #end - #end - -#end - -## -## Build the Tags for the Body start tag of a web page with VelocityOnly Layout -## -## - -#macro (TurbineHtmlBodyAttributes) -#if ($page.BodyAttributes.size() > 0) - #foreach( $attributeName in $page.BodyAttributes.keySet() ) - $attributeName = "$page.BodyAttributes.get($attributeName)" - #end -#end -#end diff --git a/src/resources/sounds/bell.wav b/src/resources/sounds/bell.wav deleted file mode 100644 index a69824de9..000000000 Binary files a/src/resources/sounds/bell.wav and /dev/null differ diff --git a/src/resources/sounds/incoming.wav b/src/resources/sounds/incoming.wav deleted file mode 100644 index 00a00445b..000000000 Binary files a/src/resources/sounds/incoming.wav and /dev/null differ diff --git a/src/resources/sounds/outgoing.wav b/src/resources/sounds/outgoing.wav deleted file mode 100644 index c82405f28..000000000 Binary files a/src/resources/sounds/outgoing.wav and /dev/null differ diff --git a/src/resources/startup.bat b/src/resources/startup.bat deleted file mode 100644 index a5bf80118..000000000 --- a/src/resources/startup.bat +++ /dev/null @@ -1,21 +0,0 @@ -if %PROCESSOR_ARCHITECTURE%==x86 ( - rem 32 bit -) else ( - set SPARK64=64 -) - - -:run -if "%1" == "-debug" goto debug -if "%1" == "-noconsole" goto noconsole -java -Dappdir=.. -cp ../lib/jdom.jar;../lib/log4j.jar;../lib/lti-civil.jar;../lib/jspeex.jar;../lib/libjitsi.jar;../lib/zrtp4j-light.jar;../lib/jna.jar;../lib/bcpkix.jar;../lib/bcprov.jar;../lib/bccontrib.jar;../lib/ice4j.jar;../lib/osgi.core.jar;../lib/fmj.jar;../lib/startup.jar;../lib/windows%SPARK64%/jdic.jar;../resources;../lib/windows%SPARK64%; -Djava.library.path="../lib/windows%SPARK64%/" org.jivesoftware.launcher.Startup -goto end - -:noconsole -javaw -Dappdir=.. -cp ../lib/jdom.jar;../lib/log4j.jar;../lib/lti-civil.jar;../lib/jspeex.jar;../lib/libjitsi.jar;../lib/zrtp4j-light.jar;../lib/jna.jar;../lib/bcpkix.jar;../lib/bcprov.jar;../lib/ice4j.jar;../lib/osgi.core.jar../lib/fmj.jar;../lib/startup.jar;../lib/windows%SPARK64%/jdic.jar;../resources;../lib/windows%SPARK64%; -Djava.library.path="../lib/windows%SPARK64%/" org.jivesoftware.launcher.Startup -goto end - -:debug -start "Spark" "%JAVA_HOME%\bin\java" -Ddebugger=true -Ddebug.mode=true -XX:+HeapDumpOnOutOfMemoryError -Xdebug -Xint -server -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 -Dappdir=.. -cp ../lib/jdom.jar;../lib/log4j.jar;../lib/lti-civil.jar;../lib/jspeex.jar;../lib/libjitsi.jar;../lib/zrtp4j-light.jar;../lib/fmj.jar;../lib/jna.jar;../lib/ice4j.jar;../lib/bcpkix.jar;../lib/bcprov.jar;../lib/osgi.core.jar;../lib/startup.jar;../lib/windows%SPARK64%/jdic.jar;../resources;../lib/windows%SPARK64%/; org.jivesoftware.launcher.Startup -goto end -:end diff --git a/src/resources/startup.sh b/src/resources/startup.sh deleted file mode 100644 index ad1762a07..000000000 --- a/src/resources/startup.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -scriptdir="`dirname ${0}`"; -cd "${scriptdir}/.."; -wd="`pwd`"; -libdir="${wd}/lib"; - -classpath="\ -${libdir}/jdom.jar:\ -${libdir}/log4j.jar:\ -${libdir}/lti-civil.jar:\ -${libdir}/fmj.jar:\ -${libdir}/jspeex.jar:\ -${libdir}/libjitsi.jar:\ -${libdir}/zrtp4j-light.jar:\ -${libdir}/jna.jar:\ -${libdir}/bcpkix.jar:\ -${libdir}/bcprov.jar:\ -${libdir}/bccontrib.jar:\ -${libdir}/ice4j.jar:\ -${libdir}/osgi.core.jar:\ -${libdir}/startup.jar:\ -${libdir}/linux/jdic.jar:\ -${wd}/resources\ -"; - -# add java library path folder depending on architecture -case "`uname -m`" in - "x86_64") - javalibrarypath="-Djava.library.path=${libdir}/linux64"; - ;; - - "*") - javalibrarypath="-Djava.library.path=${libdir}/linux"; - ;; -esac; - -echo "using classpath: ${classpath}"; - -mainclass="org.jivesoftware.launcher.Startup"; - -if [ "${1}" = "-debug" ]; then - -java -Ddebugger=true \ --Ddebug.mode=true \ --XX:+HeapDumpOnOutOfMemoryError \ --Xdebug \ --Xint \ --server \ --Xnoagent \ --Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 \ --Dappdir=${wd} \ -${javalibrarypath} \ --cp ${classpath} \ -${mainclass} - -else - - java \ --Dappdir=${wd} \ -${javalibrarypath} \ --cp ${classpath} \ -${mainclass} - -fi; - diff --git a/src/resources/systeminfo.dll b/src/resources/systeminfo.dll deleted file mode 100644 index c81686958..000000000 Binary files a/src/resources/systeminfo.dll and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Footer.html b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Footer.html deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Header.html b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Header.html deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/Content.html b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/Content.html deleted file mode 100644 index ec630a867..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/Content.html +++ /dev/null @@ -1,17 +0,0 @@ -
        -
        %sender%
        %service%
        -
        -
        -
        -
        -
        -
        -
        -
        -

        %time%%message%

        -
        -
        -
        -
        -
        -
        diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/Context.html b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/Context.html deleted file mode 100644 index cc1d2d62d..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/Context.html +++ /dev/null @@ -1,17 +0,0 @@ -
        -
        %sender%
        %service%
        -
        -
        -
        -
        -
        -
        -
        -
        -

        %time%%message%

        -
        -
        -
        -
        -
        -
        \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/NextContent.html b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/NextContent.html deleted file mode 100644 index eaace0f95..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/NextContent.html +++ /dev/null @@ -1,3 +0,0 @@ -
        -

        %time%%message%

        -
        \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/NextContext.html b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/NextContext.html deleted file mode 100644 index eaace0f95..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/NextContext.html +++ /dev/null @@ -1,3 +0,0 @@ -
        -

        %time%%message%

        -
        \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/buddy_icon.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/buddy_icon.png deleted file mode 100644 index c345d9b13..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/buddy_icon.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/buddy_icon_alt.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/buddy_icon_alt.png deleted file mode 100644 index d6261112e..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Incoming/buddy_icon_alt.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/.DS_Store b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/.DS_Store deleted file mode 100644 index 5008ddfcf..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/.DS_Store and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/Content.html b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/Content.html deleted file mode 100644 index a060b38da..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/Content.html +++ /dev/null @@ -1,17 +0,0 @@ -
        -
        %sender%
        %service%
        -
        -
        -
        -
        -
        -
        -
        -
        -

        %time%%message%

        -
        -
        -
        -
        -
        -
        diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/Context.html b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/Context.html deleted file mode 100644 index 8f24f8cc6..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/Context.html +++ /dev/null @@ -1,17 +0,0 @@ -
        -
        %sender%
        %service%
        -
        -
        -
        -
        -
        -
        -
        -
        -

        %time%%message%

        -
        -
        -
        -
        -
        -
        \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/NextContent.html b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/NextContent.html deleted file mode 100644 index eaace0f95..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/NextContent.html +++ /dev/null @@ -1,3 +0,0 @@ -
        -

        %time%%message%

        -
        \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/NextContext.html b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/NextContext.html deleted file mode 100644 index eaace0f95..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/NextContext.html +++ /dev/null @@ -1,3 +0,0 @@ -
        -

        %time%%message%

        -
        \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/buddy_icon.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/buddy_icon.png deleted file mode 100644 index c345d9b13..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/buddy_icon.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/buddy_icon_alt.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/buddy_icon_alt.png deleted file mode 100644 index d6261112e..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Outgoing/buddy_icon_alt.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Status.html b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Status.html deleted file mode 100644 index 0c91f7292..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Status.html +++ /dev/null @@ -1,5 +0,0 @@ -
        -
        %message%
        -
        %time%
        -
        -
        \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/.DS_Store b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/.DS_Store deleted file mode 100644 index 5008ddfcf..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/.DS_Store and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBO-Left Alternate Icon.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBO-Left Alternate Icon.css deleted file mode 100644 index 15f5ffd2b..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBO-Left Alternate Icon.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("../styles/defaults.css"); -@import url("../styles/layout_alternate_left.css"); -@import url("../styles/green_blue_orange_alternate_left.css"); diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBO-No Icon.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBO-No Icon.css deleted file mode 100644 index 4b96f4691..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBO-No Icon.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("../styles/defaults.css"); -@import url("../styles/layout_hidden.css"); -@import url("../styles/green_blue_orange_left.css"); \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBO-Right Alternate Icon.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBO-Right Alternate Icon.css deleted file mode 100644 index 922fc6b16..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBO-Right Alternate Icon.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("../styles/defaults.css"); -@import url("../styles/layout_alternate_right.css"); -@import url("../styles/green_blue_orange_alternate_right.css"); diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBO-Right Icon.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBO-Right Icon.css deleted file mode 100644 index 460a9fb90..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBO-Right Icon.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("../styles/defaults.css"); -@import url("../styles/layout_right.css"); -@import url("../styles/green_blue_orange_right.css"); \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBP-Left Alternate Icon.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBP-Left Alternate Icon.css deleted file mode 100644 index 3f8d68165..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBP-Left Alternate Icon.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("../styles/defaults.css"); -@import url("../styles/layout_alternate_left.css"); -@import url("../styles/green_blue_purple_alternate_left.css"); diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBP-Left Icon.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBP-Left Icon.css deleted file mode 100644 index 73e95e61d..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBP-Left Icon.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("../styles/defaults.css"); -@import url("../styles/layout_left.css"); -@import url("../styles/green_blue_purple_left.css"); \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBP-No Icon.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBP-No Icon.css deleted file mode 100644 index a5da333c2..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBP-No Icon.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("../styles/defaults.css"); -@import url("../styles/layout_hidden.css"); -@import url("../styles/green_blue_purple_left.css"); \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBP-Right Alternate Icon.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBP-Right Alternate Icon.css deleted file mode 100644 index c53043af0..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBP-Right Alternate Icon.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("../styles/defaults.css"); -@import url("../styles/layout_alternate_right.css"); -@import url("../styles/green_blue_purple_alternate_right.css"); diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBP-Right Icon.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBP-Right Icon.css deleted file mode 100644 index 08cd72b13..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/GBP-Right Icon.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("../styles/defaults.css"); -@import url("../styles/layout_right.css"); -@import url("../styles/green_blue_purple_right.css"); \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/RBP-Left Alternate Icon.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/RBP-Left Alternate Icon.css deleted file mode 100644 index 4f87db443..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/RBP-Left Alternate Icon.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("../styles/defaults.css"); -@import url("../styles/layout_alternate_left.css"); -@import url("../styles/red_blue_purple_alternate_left.css"); diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/RBP-Left Icon.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/RBP-Left Icon.css deleted file mode 100644 index e5870407e..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/RBP-Left Icon.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("../styles/defaults.css"); -@import url("../styles/layout_left.css"); -@import url("../styles/red_blue_purple_left.css"); \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/RBP-No Icon.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/RBP-No Icon.css deleted file mode 100644 index 1cada277e..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/RBP-No Icon.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("../styles/defaults.css"); -@import url("../styles/layout_hidden.css"); -@import url("../styles/red_blue_purple_left.css"); \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/RBP-Right Alternate Icon.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/RBP-Right Alternate Icon.css deleted file mode 100644 index acd71eab1..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/RBP-Right Alternate Icon.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("../styles/defaults.css"); -@import url("../styles/layout_alternate_right.css"); -@import url("../styles/red_blue_purple_alternate_right.css"); diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/RBP-Right Icon.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/RBP-Right Icon.css deleted file mode 100644 index 78f64b64c..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/Variants/RBP-Right Icon.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("../styles/defaults.css"); -@import url("../styles/layout_right.css"); -@import url("../styles/red_blue_purple_right.css"); \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/.DS_Store b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/.DS_Store deleted file mode 100644 index 5008ddfcf..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/.DS_Store and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/arrow.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/arrow.png deleted file mode 100644 index 1a7fa39c6..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/arrow.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/background.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/background.png deleted file mode 100644 index 44cdb47f1..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/background.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/buddy_background.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/buddy_background.png deleted file mode 100644 index 3c5d3267f..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/buddy_background.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/.DS_Store b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/.DS_Store deleted file mode 100644 index 5008ddfcf..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/.DS_Store and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_bot_left.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_bot_left.png deleted file mode 100644 index 967a69b00..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_bot_left.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_bot_right.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_bot_right.png deleted file mode 100644 index fddc4e90f..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_bot_right.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_context_bot_left.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_context_bot_left.png deleted file mode 100644 index 09bd71540..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_context_bot_left.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_context_bot_right.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_context_bot_right.png deleted file mode 100644 index 6e108a970..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_context_bot_right.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_context_top_fill.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_context_top_fill.png deleted file mode 100644 index e8f359dd6..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_context_top_fill.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_context_top_left.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_context_top_left.png deleted file mode 100644 index 36f58f9c3..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_context_top_left.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_context_top_right.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_context_top_right.png deleted file mode 100644 index c2584e2a7..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_context_top_right.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_top_fill.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_top_fill.png deleted file mode 100644 index f28124ca7..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_top_fill.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_top_left.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_top_left.png deleted file mode 100644 index 5cbb490ca..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_top_left.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_top_right.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_top_right.png deleted file mode 100644 index 3211e45e4..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/message/message_top_right.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/.DS_Store b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/.DS_Store deleted file mode 100644 index 5008ddfcf..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/.DS_Store and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/.DS_Store b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/.DS_Store deleted file mode 100644 index 5008ddfcf..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/.DS_Store and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/blue/.DS_Store b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/blue/.DS_Store deleted file mode 100644 index 5008ddfcf..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/blue/.DS_Store and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/blue/sender_context_left.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/blue/sender_context_left.png deleted file mode 100644 index 5f9e9c03d..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/blue/sender_context_left.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/blue/sender_left.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/blue/sender_left.png deleted file mode 100644 index b671c16a4..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/blue/sender_left.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/green/.DS_Store b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/green/.DS_Store deleted file mode 100644 index 5008ddfcf..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/green/.DS_Store and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/green/sender_context_left.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/green/sender_context_left.png deleted file mode 100644 index c1a551c41..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/green/sender_context_left.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/green/sender_left.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/green/sender_left.png deleted file mode 100644 index 346cdbe2d..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/green/sender_left.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/red/sender_context_left.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/red/sender_context_left.png deleted file mode 100644 index d0a1501c6..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/red/sender_context_left.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/red/sender_left.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/red/sender_left.png deleted file mode 100644 index 1f7baf9ae..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/red/sender_left.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/sender_context_right.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/sender_context_right.png deleted file mode 100644 index 7a3a75da0..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/sender_context_right.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/sender_right.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/sender_right.png deleted file mode 100644 index 4c8972eb3..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/flipped/sender_right.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/sender_context_fill.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/sender_context_fill.png deleted file mode 100644 index 6d7ef6005..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/sender_context_fill.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/sender_fill.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/sender_fill.png deleted file mode 100644 index f73c046c9..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/sender_fill.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/.DS_Store b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/.DS_Store deleted file mode 100644 index 5008ddfcf..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/.DS_Store and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/blue/.DS_Store b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/blue/.DS_Store deleted file mode 100644 index 5008ddfcf..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/blue/.DS_Store and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/blue/sender_context_right.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/blue/sender_context_right.png deleted file mode 100644 index cec2171b7..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/blue/sender_context_right.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/blue/sender_right.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/blue/sender_right.png deleted file mode 100644 index 0de5eb16a..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/blue/sender_right.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/green/.DS_Store b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/green/.DS_Store deleted file mode 100644 index 5008ddfcf..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/green/.DS_Store and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/green/sender_context_right.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/green/sender_context_right.png deleted file mode 100644 index c5261b5c3..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/green/sender_context_right.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/green/sender_right.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/green/sender_right.png deleted file mode 100644 index b730928ee..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/green/sender_right.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/red/sender_context_right.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/red/sender_context_right.png deleted file mode 100644 index d79b17882..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/red/sender_context_right.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/red/sender_right.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/red/sender_right.png deleted file mode 100644 index 424939d52..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/red/sender_right.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/sender_context_left.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/sender_context_left.png deleted file mode 100644 index ea1811fdc..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/sender_context_left.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/sender_left.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/sender_left.png deleted file mode 100644 index b64b18c57..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/sender/standard/sender_left.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/.DS_Store b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/.DS_Store deleted file mode 100644 index 5008ddfcf..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/.DS_Store and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/gray/status_fill.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/gray/status_fill.png deleted file mode 100644 index 4fae7b1d7..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/gray/status_fill.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/gray/status_left.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/gray/status_left.png deleted file mode 100644 index cdcd6b03f..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/gray/status_left.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/gray/status_right.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/gray/status_right.png deleted file mode 100644 index f44b26a8b..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/gray/status_right.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/orange/status_fill.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/orange/status_fill.png deleted file mode 100644 index 1c7d55d45..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/orange/status_fill.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/orange/status_left.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/orange/status_left.png deleted file mode 100644 index bd84f2132..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/orange/status_left.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/orange/status_right.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/orange/status_right.png deleted file mode 100644 index 169b3e831..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/orange/status_right.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/purple/status_fill.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/purple/status_fill.png deleted file mode 100644 index c7e3389c4..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/purple/status_fill.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/purple/status_left.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/purple/status_left.png deleted file mode 100644 index db3c8a258..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/purple/status_left.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/purple/status_right.png b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/purple/status_right.png deleted file mode 100644 index 4d7990f2a..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/images/status/purple/status_right.png and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/main.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/main.css deleted file mode 100644 index 8fc03461a..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/main.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("styles/defaults.css"); -@import url("styles/layout_left.css"); -@import url("styles/green_blue_orange_left.css"); \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/.DS_Store b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/.DS_Store deleted file mode 100644 index 5008ddfcf..000000000 Binary files a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/.DS_Store and /dev/null differ diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/defaults.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/defaults.css deleted file mode 100644 index 94cdf22f5..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/defaults.css +++ /dev/null @@ -1,66 +0,0 @@ -body {margin: 10px 15px 10px 15px;} - - -p {margin: 0px;overflow: hidden;} - -.spacer {clear: both;} - -.nameheader { - font-family: "Myriad"; - font-size: 11px; - font-weight: 900; - font-style: normal; - opacity: 1.0; - #border: 1px solid #999999; - } -.name { - #border: 1px solid #999999; - } -.protocol { - b#order: 1px solid #999999; - } - -.message { - font-size: 11px; - color: #454545; - text-shadow: 0px 1px 0px rgba(255,255,255,0.9); - } -.messagetime { - font-family: "Helvetica"; - font-size: 11px; - color: #999999; - float: right; - padding-top: 2px; - vertical-align: baseline; - } -.messagetime.consecutive { - padding-left: 11px; - } - -.status { - font-family: "Myriad"; - font-size: 11px; - font-weight: bold; - color: rgba(255,255,255,1.0); - #border: 1px solid #999999; - } -.statusmessage { - text-align: left; - #border: 1px solid #999999; - } -.statustime { - text-align: right; - #border: 1px solid #999999; - } - -.nextmessageline { - border-bottom: 1px dotted #CCCCCC; - height: 1px; - margin-top: 2px; - margin-bottom: 2px; - } - -#chat { - overflow: hidden; - margin-bottom: 10px; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_orange_alternate_left.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_orange_alternate_left.css deleted file mode 100644 index 75de6ae2a..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_orange_alternate_left.css +++ /dev/null @@ -1,58 +0,0 @@ -@import url("message_common.css"); - -.out.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(84,155,38,0.8); - } -.out.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(84,155,38,0.5); - } -.in.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(39,55,152,0.8); - } -.in.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(39,55,152,0.5); - } - -.out.content .name { - background: url("../images/sender/standard/sender_left.png") left top no-repeat; - } -.out.context .name { - background: url("../images/sender/standard/sender_context_left.png") left top no-repeat; - } -.in.content .name { - background: url("../images/sender/flipped/sender_right.png") right top no-repeat; - } -.in.context .name { - background: url("../images/sender/flipped/sender_context_right.png") right top no-repeat; - } - -.out.content .protocol { - background: url("../images/sender/standard/green/sender_right.png") right top no-repeat; - color: rgba(84,155,38,0.4); - } -.out.context .protocol { - background: url("../images/sender/standard/green/sender_context_right.png") right top no-repeat; - color: rgba(84,155,38,0.3); - } -.in.content .protocol { - background: url("../images/sender/flipped/blue/sender_left.png") left top no-repeat; - color: rgba(39,55,152,0.4); - } -.in.context .protocol { - background: url("../images/sender/flipped/blue/sender_context_left.png") left top no-repeat; - color: rgba(39,55,152,0.3); - } - -.status { - background: url("../images/status/orange/status_fill.png") top repeat-x; - } -.statusmessage { - background: url("../images/status/orange/status_left.png") left top no-repeat; - } -.statustime { - background: url("../images/status/orange/status_right.png") right top no-repeat; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_orange_alternate_right.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_orange_alternate_right.css deleted file mode 100644 index 0fcc1fc2a..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_orange_alternate_right.css +++ /dev/null @@ -1,58 +0,0 @@ -@import url("message_common.css"); - -.out.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(84,155,38,0.8); - } -.out.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(84,155,38,0.5); - } -.in.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(39,55,152,0.8); - } -.in.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(39,55,152,0.5); - } - -.out.content .name { - background: url("../images/sender/flipped/sender_right.png") right top no-repeat; - } -.out.context .name { - background: url("../images/sender/flipped/sender_context_right.png") right top no-repeat; - } -.in.content .name { - background: url("../images/sender/standard/sender_left.png") left top no-repeat; - } -.in.context .name { - background: url("../images/sender/standard/sender_context_left.png") left top no-repeat; - } - -.out.content .protocol { - background: url("../images/sender/flipped/green/sender_left.png") left top no-repeat; - color: rgba(84,155,38,0.4); - } -.out.context .protocol { - background: url("../images/sender/flipped/green/sender_context_left.png") left top no-repeat; - color: rgba(84,155,38,0.3); - } -.in.content .protocol { - background: url("../images/sender/standard/blue/sender_right.png") right top no-repeat; - color: rgba(39,55,152,0.4); - } -.in.context .protocol { - background: url("../images/sender/standard/blue/sender_context_right.png") right top no-repeat; - color: rgba(39,55,152,0.3); - } - -.status { - background: url("../images/status/orange/status_fill.png") top repeat-x; - } -.statusmessage { - background: url("../images/status/orange/status_left.png") left top no-repeat; - } -.statustime { - background: url("../images/status/orange/status_right.png") right top no-repeat; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_orange_left.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_orange_left.css deleted file mode 100644 index 7a6b0de9b..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_orange_left.css +++ /dev/null @@ -1,59 +0,0 @@ -@import url("message_common.css"); - -.out.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(84,155,38,0.8); - } -.out.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(84,155,38,0.5); - } -.in.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(39,55,152,0.8); - } -.in.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(39,55,152,0.5); - } - -.out.content .name { - background: url("../images/sender/standard/sender_left.png") left top no-repeat; - } -.out.context .name { - background: url("../images/sender/standard/sender_context_left.png") left top no-repeat; - } -.in.content .name { - background: url("../images/sender/standard/sender_left.png") left top no-repeat; - } -.in.context .name { - background: url("../images/sender/standard/sender_context_left.png") left top no-repeat; - } - -.out.content .protocol { - background: url("../images/sender/standard/green/sender_right.png") right top no-repeat; - color: rgba(84,155,38,0.4); - } -.out.context .protocol { - background: url("../images/sender/standard/green/sender_context_right.png") right top no-repeat; - color: rgba(84,155,38,0.3); - } -.in.content .protocol { - background: url("../images/sender/standard/blue/sender_right.png") right top no-repeat; - color: rgba(39,55,152,0.4); - } - -.in.context .protocol { - background: url("../images/sender/standard/blue/sender_context_right.png") right top no-repeat; - color: rgba(39,55,152,0.3); - } - -.status { - background: url("../images/status/orange/status_fill.png") top repeat-x; - } -.statusmessage { - background: url("../images/status/orange/status_left.png") left top no-repeat; - } -.statustime { - background: url("../images/status/orange/status_right.png") right top no-repeat; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_orange_right.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_orange_right.css deleted file mode 100644 index 6dffa21e9..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_orange_right.css +++ /dev/null @@ -1,58 +0,0 @@ -@import url("message_common.css"); - -.out.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(84,155,38,0.8); - } -.out.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(84,155,38,0.5); - } -.in.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(39,55,152,0.8); - } -.in.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(39,55,152,0.5); - } - -.out.content .name { - background: url("../images/sender/flipped/sender_right.png") right top no-repeat; - } -.out.context .name { - background: url("../images/sender/flipped/sender_context_right.png") right top no-repeat; - } -.in.content .name { - background: url("../images/sender/flipped/sender_right.png") right top no-repeat; - } -.in.context .name { - background: url("../images/sender/flipped/sender_context_right.png") right top no-repeat; - } - -.out.content .protocol { - background: url("../images/sender/flipped/green/sender_left.png") left top no-repeat; - color: rgba(84,155,38,0.4); - } -.out.context .protocol { - background: url("../images/sender/flipped/green/sender_context_left.png") left top no-repeat; - color: rgba(84,155,38,0.3); - } -.in.content .protocol { - background: url("../images/sender/flipped/blue/sender_left.png") left top no-repeat; - color: rgba(39,55,152,0.4); - } -.in.context .protocol { - background: url("../images/sender/flipped/blue/sender_context_left.png") left top no-repeat; - color: rgba(39,55,152,0.3); - } - -.status { - background: url("../images/status/orange/status_fill.png") top repeat-x; - } -.statusmessage { - background: url("../images/status/orange/status_left.png") left top no-repeat; - } -.statustime { - background: url("../images/status/orange/status_right.png") right top no-repeat; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_purple_alternate_left.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_purple_alternate_left.css deleted file mode 100644 index 3b219283a..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_purple_alternate_left.css +++ /dev/null @@ -1,58 +0,0 @@ -@import url("message_common.css"); - -.out.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(84,155,38,0.8); - } -.out.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(84,155,38,0.5); - } -.in.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(39,55,152,0.8); - } -.in.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(39,55,152,0.5); - } - -.out.content .name { - background: url("../images/sender/standard/sender_left.png") left top no-repeat; - } -.out.context .name { - background: url("../images/sender/standard/sender_context_left.png") left top no-repeat; - } -.in.content .name { - background: url("../images/sender/flipped/sender_right.png") right top no-repeat; - } -.in.context .name { - background: url("../images/sender/flipped/sender_context_right.png") right top no-repeat; - } - -.out.content .protocol { - background: url("../images/sender/standard/green/sender_right.png") right top no-repeat; - color: rgba(84,155,38,0.4); - } -.out.context .protocol { - background: url("../images/sender/standard/green/sender_context_right.png") right top no-repeat; - color: rgba(84,155,38,0.3); - } -.in.content .protocol { - background: url("../images/sender/flipped/blue/sender_left.png") left top no-repeat; - color: rgba(39,55,152,0.4); - } -.in.context .protocol { - background: url("../images/sender/flipped/blue/sender_context_left.png") left top no-repeat; - color: rgba(39,55,152,0.3); - } - -.status { - background: url("../images/status/purple/status_fill.png") top repeat-x; - } -.statusmessage { - background: url("../images/status/purple/status_left.png") left top no-repeat; - } -.statustime { - background: url("../images/status/purple/status_right.png") right top no-repeat; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_purple_alternate_right.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_purple_alternate_right.css deleted file mode 100644 index 768276bb3..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_purple_alternate_right.css +++ /dev/null @@ -1,58 +0,0 @@ -@import url("message_common.css"); - -.out.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(84,155,38,0.8); - } -.out.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(84,155,38,0.5); - } -.in.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(39,55,152,0.8); - } -.in.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(39,55,152,0.5); - } - -.out.content .name { - background: url("../images/sender/flipped/sender_right.png") right top no-repeat; - } -.out.context .name { - background: url("../images/sender/flipped/sender_context_right.png") right top no-repeat; - } -.in.content .name { - background: url("../images/sender/standard/sender_left.png") left top no-repeat; - } -.in.context .name { - background: url("../images/sender/standard/sender_context_left.png") left top no-repeat; - } - -.out.content .protocol { - background: url("../images/sender/flipped/green/sender_left.png") left top no-repeat; - color: rgba(84,155,38,0.4); - } -.out.context .protocol { - background: url("../images/sender/flipped/green/sender_context_left.png") left top no-repeat; - color: rgba(84,155,38,0.3); - } -.in.content .protocol { - background: url("../images/sender/standard/blue/sender_right.png") right top no-repeat; - color: rgba(39,55,152,0.4); - } -.in.context .protocol { - background: url("../images/sender/standard/blue/sender_context_right.png") right top no-repeat; - color: rgba(39,55,152,0.3); - } - -.status { - background: url("../images/status/purple/status_fill.png") top repeat-x; - } -.statusmessage { - background: url("../images/status/purple/status_left.png") left top no-repeat; - } -.statustime { - background: url("../images/status/purple/status_right.png") right top no-repeat; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_purple_left.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_purple_left.css deleted file mode 100644 index 2efd64b45..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_purple_left.css +++ /dev/null @@ -1,59 +0,0 @@ -@import url("message_common.css"); - -.out.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(84,155,38,0.8); - } -.out.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(84,155,38,0.5); - } -.in.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(39,55,152,0.8); - } -.in.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(39,55,152,0.5); - } - -.out.content .name { - background: url("../images/sender/standard/sender_left.png") left top no-repeat; - } -.out.context .name { - background: url("../images/sender/standard/sender_context_left.png") left top no-repeat; - } -.in.content .name { - background: url("../images/sender/standard/sender_left.png") left top no-repeat; - } -.in.context .name { - background: url("../images/sender/standard/sender_context_left.png") left top no-repeat; - } - -.out.content .protocol { - background: url("../images/sender/standard/green/sender_right.png") right top no-repeat; - color: rgba(84,155,38,0.4); - } -.out.context .protocol { - background: url("../images/sender/standard/green/sender_context_right.png") right top no-repeat; - color: rgba(84,155,38,0.3); - } -.in.content .protocol { - background: url("../images/sender/standard/blue/sender_right.png") right top no-repeat; - color: rgba(39,55,152,0.4); - } - -.in.context .protocol { - background: url("../images/sender/standard/blue/sender_context_right.png") right top no-repeat; - color: rgba(39,55,152,0.3); - } - -.status { - background: url("../images/status/purple/status_fill.png") top repeat-x; - } -.statusmessage { - background: url("../images/status/purple/status_left.png") left top no-repeat; - } -.statustime { - background: url("../images/status/purple/status_right.png") right top no-repeat; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_purple_right.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_purple_right.css deleted file mode 100644 index dc771d5d5..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/green_blue_purple_right.css +++ /dev/null @@ -1,58 +0,0 @@ -@import url("message_common.css"); - -.out.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(84,155,38,0.8); - } -.out.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(84,155,38,0.5); - } -.in.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(39,55,152,0.8); - } -.in.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(39,55,152,0.5); - } - -.out.content .name { - background: url("../images/sender/flipped/sender_right.png") right top no-repeat; - } -.out.context .name { - background: url("../images/sender/flipped/sender_context_right.png") right top no-repeat; - } -.in.content .name { - background: url("../images/sender/flipped/sender_right.png") right top no-repeat; - } -.in.context .name { - background: url("../images/sender/flipped/sender_context_right.png") right top no-repeat; - } - -.out.content .protocol { - background: url("../images/sender/flipped/green/sender_left.png") left top no-repeat; - color: rgba(84,155,38,0.4); - } -.out.context .protocol { - background: url("../images/sender/flipped/green/sender_context_left.png") left top no-repeat; - color: rgba(84,155,38,0.3); - } -.in.content .protocol { - background: url("../images/sender/flipped/blue/sender_left.png") left top no-repeat; - color: rgba(39,55,152,0.4); - } -.in.context .protocol { - background: url("../images/sender/flipped/blue/sender_context_left.png") left top no-repeat; - color: rgba(39,55,152,0.3); - } - -.status { - background: url("../images/status/purple/status_fill.png") top repeat-x; - } -.statusmessage { - background: url("../images/status/purple/status_left.png") left top no-repeat; - } -.statustime { - background: url("../images/status/purple/status_right.png") right top no-repeat; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_all.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_all.css deleted file mode 100644 index 18af6d710..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_all.css +++ /dev/null @@ -1,62 +0,0 @@ -.in {margin-bottom: 0px;} -.out {margin-bottom: 0px;} - -.message { - margin-left: 0px; - padding: 0px 11px 12px 0px; - } -.messagetop { - position: relative; - height: 12px; - top: -8px; - padding: 0px 0px 0px 0px; - margin: 0px 12px 0px 12px; - } -.messagetopleft { - position: relative; - float: left; - height: 12px; - top: 0px; - left: -12px; - padding: 0px 12px 0px 0px; - margin: 0px -13px 0px 0px; - } -.messagetopright { - position: relative; - float: right; - height: 12px; - top: 0px; - right: -12px; - padding: 0px 0px 0px 12px; - margin: 0px 0px 0px -13px; - } -.messagetextcontainer { - position: relative; - margin: -8px 0px 0px 0px; - padding: 0px 0px 0px 12px; - } -.status { - position: relative; - height: 23px; - top: 0px; - padding: 0px 0px 0px 0px; - margin: 0px 30px 0px 30px; - } -.statusmessage { - position: relative; - float: left; - height: 23px; - top: 0px; - left: -30px; - padding: 5px 30px 0px 12px; - margin: 0px 0px 0px 0px; - } -.statustime { - position: relative; - float: right; - height: 23px; - top: 0px; - right: -30px; - padding: 5px 12px 0px 18px; - margin: 0px 0px 0px 0px; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_alternate_left.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_alternate_left.css deleted file mode 100644 index 5909906bf..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_alternate_left.css +++ /dev/null @@ -1,96 +0,0 @@ -@import url("layout_all.css"); - -.out .nameheader { - position: relative; - height: 25px; - top: 0px; - padding: 0px 0px 0px 0px; - margin: 0px 77px 0px 25px; - } -.in .nameheader { - position: relative; - height: 25px; - top: 0px; - padding: 0px 0px 0px 0px; - margin: 0px 24px 0px 78px; - } -.out .name { - position: relative; - float: left; - height: 25px; - top: 0px; - left: -25px; - padding: 4px 0px 0px 12px; - margin: 0px 0px 0px 0px; - } -.in .name { - position: relative; - float: right; - height: 25px; - top: 0px; - right: -25px; - padding: 4px 12px 0px 0px; - margin: 0px 0px 0px 0px; - } -.out .protocol { - position: relative; - float: right; - height: 25px; - top: 0px; - right: -78px; - padding: 6px 12px 0px 66px; - margin: 0px 0px -2px 0px; - } -.in .protocol { - position: relative; - float: left; - height: 25px; - top: 0px; - left: -78px; - padding: 6px 66px 0px 12px; - margin: 0px 0px -2px 0px; - } -.messagecontainer { - padding: 0px 0px 0px 0px; - } -.out .messagecontainer { - margin: 0px 0px 0px 48px; - } -.in .messagecontainer { - margin: 0px 48px 0px 0px; - } -.buddyicon { - position: relative; - top: -6px; - z-index: 4; - } -.buddyicon img { - height: 32px; - width: 32px; - z-index: 3; - } -.junkIcon { - #background: url("../images/buddy_background.png") top left no-repeat; - #height: 40px; - #width: 40px; - #padding: 2px 0px 0px 4px; - #border: 1px solid #999999; - } -.junkIcon img { - #margin-top: 2px; - #margin-left: 4px; - } -.out .buddyicon { - float: left; - margin-left: 10px; - margin-right: 0px; - margin-bottom: 0px; - margin-top: 0px; - } -.in .buddyicon { - float: right; - margin-left: 0px; - margin-bottom: 0px; - margin-top: 0px; - margin-right: 10px; - } diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_alternate_right.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_alternate_right.css deleted file mode 100644 index 4c53b4a6d..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_alternate_right.css +++ /dev/null @@ -1,92 +0,0 @@ -@import url("layout_all.css"); - -.in .nameheader { - position: relative; - height: 25px; - top: 0px; - padding: 0px 0px 0px 0px; - margin: 0px 77px 0px 25px; - } -.out .nameheader { - position: relative; - height: 25px; - top: 0px; - padding: 0px 0px 0px 0px; - margin: 0px 24px 0px 78px; - } -.in .name { - position: relative; - float: left; - height: 25px; - top: 0px; - left: -25px; - padding: 4px 0px 0px 12px; - margin: 0px 0px 0px 0px; - } -.out .name { - position: relative; - float: right; - height: 25px; - top: 0px; - right: -25px; - padding: 4px 12px 0px 0px; - margin: 0px 0px 0px 0px; - } -.in .protocol { - position: relative; - float: right; - height: 25px; - top: 0px; - right: -78px; - padding: 6px 12px 0px 66px; - margin: 0px 0px -2px 0px; - } -.out .protocol { - position: relative; - float: left; - height: 25px; - top: 0px; - left: -78px; - padding: 6px 66px 0px 12px; - margin: 0px 0px -2px 0px; - } -.messagecontainer { - padding: 0px 0px 0px 0px; - } -.in .messagecontainer { - margin: 0px 0px 0px 48px; - } -.out .messagecontainer { - margin: 0px 48px 0px 0px; - } -.buddyicon { - position: relative; - top: -6px; - #background: url("../images/buddy_background.png") top left no-repeat; - #height: 40px; - #width: 40px; - z-index: 4; - #padding: 2px 0px 0px 4px; - #border: 1px solid #999999; - } -.buddyicon img { - height: 32px; - width: 32px; - #margin-top: 2px; - #margin-left: 4px; - z-index: 3; - } -.in .buddyicon { - float: left; - margin-left: 10px; - margin-right: 0px; - margin-bottom: 0px; - margin-top: 0px; - } -.out .buddyicon { - float: right; - margin-left: 0px; - margin-bottom: 0px; - margin-top: 0px; - margin-right: 10px; - } diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_hidden.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_hidden.css deleted file mode 100644 index 04e2e4565..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_hidden.css +++ /dev/null @@ -1,32 +0,0 @@ -@import url("layout_all.css"); - -.nameheader { - position: relative; - height: 25px; - top: 0px; - padding: 0px 0px 0px 0px; - margin: 0px 77px 0px 25px; - } -.name { - position: relative; - float: left; - height: 25px; - top: 0px; - left: -25px; - padding: 4px 0px 0px 12px; - margin: 0px 0px 0px 0px; - } -.protocol { - position: relative; - float: right; - height: 25px; - top: 0px; - right: -78px; - padding: 6px 12px 0px 66px; - margin: 0px 0px -2px 0px; - } -.messagecontainer { - padding: 0px 0px 0px 0px; - margin: 0px 0px 0px 0px; - } -.buddyicon {display: none;} \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_left.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_left.css deleted file mode 100644 index 220e0df76..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_left.css +++ /dev/null @@ -1,57 +0,0 @@ -@import url("layout_all.css"); - -.nameheader { - position: relative; - height: 25px; - top: 0px; - padding: 0px 0px 0px 0px; - margin: 0px 77px 0px 25px; - } -.name { - position: relative; - float: left; - height: 25px; - top: 0px; - left: -25px; - padding: 4px 0px 0px 12px; - margin: 0px 0px 0px 0px; - } -.protocol { - position: relative; - float: right; - height: 25px; - top: 0px; - right: -78px; - padding: 6px 12px 0px 50px; - margin: 0px 0px -2px 0px; - } -.messagecontainer { - padding: 0px 0px 0px 0px; - margin: 0px 0px 0px 48px; - } -.buddyicon img { - height: 32px; - width: 32px; - z-index: 3; - } -.buddyicon { - position: relative; - top: -6px; - z-index: 4; - float: left; - margin-left: 10px; - margin-right: 0px; - margin-bottom: 0px; - margin-top: 0px; - } -.junkIcon { - #background: url("../images/buddy_background.png") top left no-repeat; - #height: 40px; - #width: 40px; - #padding: 2px 0px 0px 4px; - #border: 1px solid #999999; - } -.junkIcon img { - #margin-top: 2px; - #margin-left: 4px; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_right.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_right.css deleted file mode 100644 index bfdb78b6f..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/layout_right.css +++ /dev/null @@ -1,53 +0,0 @@ -@import url("layout_all.css"); - -.nameheader { - position: relative; - height: 25px; - top: 0px; - padding: 0px 0px 0px 0px; - margin: 0px 24px 0px 78px; - } -.name { - position: relative; - float: right; - height: 25px; - top: 0px; - right: -25px; - padding: 4px 12px 0px 0px; - margin: 0px 0px 0px 0px; - } -.protocol { - position: relative; - float: left; - height: 25px; - top: 0px; - left: -78px; - padding: 6px 66px 0px 12px; - margin: 0px 0px -2px 0px; - } -.messagecontainer { - padding: 0px 0px 0px 0px; - margin: 0px 48px 0px 0px; - } -.buddyicon { - position: relative; - top: -6px; - #background: url("../images/buddy_background.png") top left no-repeat; - #height: 40px; - #width: 40px; - z-index: 4; - float: right; - margin-left: 0px; - margin-bottom: 0px; - margin-top: 0px; - margin-right: 10px; - #padding: 2px 0px 0px 4px; - #border: 1px solid #999999; - } -.buddyicon img { - height: 32px; - width: 32px; - #margin-top: 2px; - #margin-left: 4px; - z-index: 3; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/message_common.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/message_common.css deleted file mode 100644 index 79617915f..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/message_common.css +++ /dev/null @@ -1,34 +0,0 @@ -body { - background: #FFFFFF url("../images/background.png") bottom fixed repeat-x; - } - -.content .message { - background: url("../images/message/message_bot_right.png") bottom right no-repeat; - } -.context .message { - background: url("../images/message/message_context_bot_right.png") bottom right no-repeat; - } -.content .messagetextcontainer { - background: url("../images/message/message_bot_left.png") bottom left no-repeat; - } -.context .messagetextcontainer { - background: url("../images/message/message_context_bot_left.png") bottom left no-repeat; - } -.content .messagetop { - background: url("../images/message/message_top_fill.png") top repeat-x; - } -.context .messagetop { - background: url("../images/message/message_context_top_fill.png") top repeat-x; - } -.content .messagetopleft { - background: url("../images/message/message_top_left.png") left top no-repeat; - } -.context .messagetopleft { - background: url("../images/message/message_context_top_left.png") left top no-repeat; - } -.content .messagetopright { - background: url("../images/message/message_top_right.png") right top no-repeat; - } -.context .messagetopright { - background: url("../images/message/message_context_top_right.png") right top no-repeat; - } diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/red_blue_purple_alternate_left.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/red_blue_purple_alternate_left.css deleted file mode 100644 index f52f34859..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/red_blue_purple_alternate_left.css +++ /dev/null @@ -1,58 +0,0 @@ -@import url("message_common.css"); - -.out.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(170,17,17,0.8); - } -.out.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(170,17,17,0.5); - } -.in.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(39,55,152,0.8); - } -.in.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(39,55,152,0.5); - } - -.out.content .name { - background: url("../images/sender/standard/sender_left.png") left top no-repeat; - } -.out.context .name { - background: url("../images/sender/standard/sender_context_left.png") left top no-repeat; - } -.in.content .name { - background: url("../images/sender/flipped/sender_right.png") right top no-repeat; - } -.in.context .name { - background: url("../images/sender/flipped/sender_context_right.png") right top no-repeat; - } - -.out.content .protocol { - background: url("../images/sender/standard/red/sender_right.png") right top no-repeat; - color: rgba(170,17,17,0.4); - } -.out.context .protocol { - background: url("../images/sender/standard/red/sender_context_right.png") right top no-repeat; - color: rgba(170,17,17,0.3); - } -.in.content .protocol { - background: url("../images/sender/flipped/blue/sender_left.png") left top no-repeat; - color: rgba(39,55,152,0.4); - } -.in.context .protocol { - background: url("../images/sender/flipped/blue/sender_context_left.png") left top no-repeat; - color: rgba(39,55,152,0.3); - } - -.status { - background: url("../images/status/purple/status_fill.png") top repeat-x; - } -.statusmessage { - background: url("../images/status/purple/status_left.png") left top no-repeat; - } -.statustime { - background: url("../images/status/purple/status_right.png") right top no-repeat; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/red_blue_purple_alternate_right.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/red_blue_purple_alternate_right.css deleted file mode 100644 index d5bebedaa..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/red_blue_purple_alternate_right.css +++ /dev/null @@ -1,58 +0,0 @@ -@import url("message_common.css"); - -.out.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(170,17,17,0.8); - } -.out.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(170,17,17,0.5); - } -.in.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(39,55,152,0.8); - } -.in.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(39,55,152,0.5); - } - -.out.content .name { - background: url("../images/sender/flipped/sender_right.png") right top no-repeat; - } -.out.context .name { - background: url("../images/sender/flipped/sender_context_right.png") right top no-repeat; - } -.in.content .name { - background: url("../images/sender/standard/sender_left.png") left top no-repeat; - } -.in.context .name { - background: url("../images/sender/standard/sender_context_left.png") left top no-repeat; - } - -.out.content .protocol { - background: url("../images/sender/flipped/red/sender_left.png") left top no-repeat; - color: rgba(170,17,17,0.4); - } -.out.context .protocol { - background: url("../images/sender/flipped/red/sender_context_left.png") left top no-repeat; - color: rgba(170,17,17,0.3); - } -.in.content .protocol { - background: url("../images/sender/standard/blue/sender_right.png") right top no-repeat; - color: rgba(39,55,152,0.4); - } -.in.context .protocol { - background: url("../images/sender/standard/blue/sender_context_right.png") right top no-repeat; - color: rgba(39,55,152,0.3); - } - -.status { - background: url("../images/status/purple/status_fill.png") top repeat-x; - } -.statusmessage { - background: url("../images/status/purple/status_left.png") left top no-repeat; - } -.statustime { - background: url("../images/status/purple/status_right.png") right top no-repeat; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/red_blue_purple_left.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/red_blue_purple_left.css deleted file mode 100644 index bd28044cc..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/red_blue_purple_left.css +++ /dev/null @@ -1,59 +0,0 @@ -@import url("message_common.css"); - -.out.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(170,17,17,0.8); - } -.out.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(170,17,17,0.5); - } -.in.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(39,55,152,0.8); - } -.in.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(39,55,152,0.5); - } - -.out.content .name { - background: url("../images/sender/standard/sender_left.png") left top no-repeat; - } -.out.context .name { - background: url("../images/sender/standard/sender_context_left.png") left top no-repeat; - } -.in.content .name { - background: url("../images/sender/standard/sender_left.png") left top no-repeat; - } -.in.context .name { - background: url("../images/sender/standard/sender_context_left.png") left top no-repeat; - } - -.out.content .protocol { - background: url("../images/sender/standard/red/sender_right.png") right top no-repeat; - color: rgba(170,18,18,0.4); - } -.out.context .protocol { - background: url("../images/sender/standard/red/sender_context_right.png") right top no-repeat; - color: rgba(170,18,18,0.3); - } -.in.content .protocol { - background: url("../images/sender/standard/blue/sender_right.png") right top no-repeat; - color: rgba(39,55,152,0.4); - } - -.in.context .protocol { - background: url("../images/sender/standard/blue/sender_context_right.png") right top no-repeat; - color: rgba(39,55,152,0.3); - } - -.status { - background: url("../images/status/purple/status_fill.png") top repeat-x; - } -.statusmessage { - background: url("../images/status/purple/status_left.png") left top no-repeat; - } -.statustime { - background: url("../images/status/purple/status_right.png") right top no-repeat; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/red_blue_purple_right.css b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/red_blue_purple_right.css deleted file mode 100644 index 8b34a4988..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/styles/red_blue_purple_right.css +++ /dev/null @@ -1,58 +0,0 @@ -@import url("message_common.css"); - -.out.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(178,18,18,0.8); - } -.out.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(178,18,18,0.5); - } -.in.content .nameheader { - background: url("../images/sender/sender_fill.png") top repeat-x; - color: rgba(39,55,152,0.8); - } -.in.context .nameheader { - background: url("../images/sender/sender_context_fill.png") top repeat-x; - color: rgba(39,55,152,0.5); - } - -.out.content .name { - background: url("../images/sender/flipped/sender_right.png") right top no-repeat; - } -.out.context .name { - background: url("../images/sender/flipped/sender_context_right.png") right top no-repeat; - } -.in.content .name { - background: url("../images/sender/flipped/sender_right.png") right top no-repeat; - } -.in.context .name { - background: url("../images/sender/flipped/sender_context_right.png") right top no-repeat; - } - -.out.content .protocol { - background: url("../images/sender/flipped/red/sender_left.png") left top no-repeat; - color: rgba(178,18,18,0.4); - } -.out.context .protocol { - background: url("../images/sender/flipped/red/sender_context_left.png") left top no-repeat; - color: rgba(178,18,18,0.3); - } -.in.content .protocol { - background: url("../images/sender/flipped/blue/sender_left.png") left top no-repeat; - color: rgba(39,55,152,0.4); - } -.in.context .protocol { - background: url("../images/sender/flipped/blue/sender_context_left.png") left top no-repeat; - color: rgba(39,55,152,0.3); - } - -.status { - background: url("../images/status/purple/status_fill.png") top repeat-x; - } -.statusmessage { - background: url("../images/status/purple/status_left.png") left top no-repeat; - } -.statustime { - background: url("../images/status/purple/status_right.png") right top no-repeat; - } \ No newline at end of file diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/template.html b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/template.html deleted file mode 100644 index 96fc43f65..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/template.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - -%header% -
        -
        -%footer% -
        - - diff --git a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/test.html b/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/test.html deleted file mode 100644 index 54d6f2b37..000000000 --- a/src/resources/themes/Satin.AdiumMessageStyle/Contents/Resources/test.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - - - - -
        -
        Evan has gone offline
        -
        11:26:20
        -
        -
        - -
        -
        Evan come back online
        -
        11:26:45
        -
        -
        - -
        -
        Jeff (Me)
        Yahoo!
        -
        -
        -
        -
        -
        -
        -

        This is going to be a message from the past5:27:45

        -
        -

        Instant Messaging is really fun!!!20:29

        -
        -

        Right?20:50

        -
        -
        -
        -
        -
        - -
        -
        Evan (Buddy)
        AIM
        -
        -
        -
        -
        -
        -
        -

        Not if your life depended on it5:28:01

        -
        -
        -
        -
        -
        - -
        -
        Evan has gone away: this is going to be a really long status message so I can make sure wrapping is handled correctly...
        -
        11:28:13
        -
        -
        - -
        -
        A really long alias if it will fit into this view
        AIM
        -
        -
        -
        -
        -
        -
        -

        This is a new message11:29:20

        -
        -

        Instant Messaging is supposed to be fun...29:41

        -
        -

        Right?30:50

        -
        -
        -
        -
        -
        - -
        -
        Evan has gone idle
        -
        11:31:05
        -
        -
        - -
        -
        Jeff (Me)
        Yahoo!
        -
        -
        -
        -
        -
        -
        -

        If given the opportunity, a person would write a book about their life story. It may be the most boring thing in the world to read, but you're the one who put them on your buddy list ;).11:31:50

        -
        -
        -
        -
        -
        - -
        -
        Evan (Buddy)
        Yahoo!
        -
        -
        -
        -
        -
        -
        -

        If given the opportunity, a person would write a book about their life story. It may be the most boring thing in the world to read, but you're the one who put them on your buddy list ;).11:38:20

        -
        -
        -
        -
        -
        - -
        -
        Jeff (Me)
        Yahoo!
        -
        -
        -
        -
        -
        -
        -

        I have no idea what you're talking about!11:40:10

        -
        -
        -
        -
        -
        - - \ No newline at end of file diff --git a/src/resources/themes/pin/Contents/Resources/Header.html b/src/resources/themes/pin/Contents/Resources/Header.html deleted file mode 100644 index c1206f4cb..000000000 --- a/src/resources/themes/pin/Contents/Resources/Header.html +++ /dev/null @@ -1,9 +0,0 @@ -
        -
        -
        -
        - %timeOpened{%B %e, %Y}% -
        -
        -
        -
        diff --git a/src/resources/themes/pin/Contents/Resources/Incoming/Content.html b/src/resources/themes/pin/Contents/Resources/Incoming/Content.html deleted file mode 100644 index ae3ad5bf8..000000000 --- a/src/resources/themes/pin/Contents/Resources/Incoming/Content.html +++ /dev/null @@ -1,29 +0,0 @@ -
        -
        - -
        - -
        -
        -
        -
        - %sender% -
        -
        -
        -
        -
        -
        - %time% -
        -
        - %message% -
        -
        -
        -
        -
        -
        -
        -
        -
        diff --git a/src/resources/themes/pin/Contents/Resources/Incoming/Context.html b/src/resources/themes/pin/Contents/Resources/Incoming/Context.html deleted file mode 100644 index 59c64e7d6..000000000 --- a/src/resources/themes/pin/Contents/Resources/Incoming/Context.html +++ /dev/null @@ -1,30 +0,0 @@ -
        -
        - -
        - -
        -
        -
        -
        - %sender% -
        -
        -
        -
        -
        -
        - %time% -
        -
        - • %message% -
        -
        -
        -
        -
        -
        -
        -
        -
        -
        diff --git a/src/resources/themes/pin/Contents/Resources/Incoming/NextContent.html b/src/resources/themes/pin/Contents/Resources/Incoming/NextContent.html deleted file mode 100644 index 945bee4f9..000000000 --- a/src/resources/themes/pin/Contents/Resources/Incoming/NextContent.html +++ /dev/null @@ -1,9 +0,0 @@ -
        -
        - %time% -
        -
        - %message% -
        -
        -
        diff --git a/src/resources/themes/pin/Contents/Resources/Incoming/NextContext.html b/src/resources/themes/pin/Contents/Resources/Incoming/NextContext.html deleted file mode 100644 index 0215664c9..000000000 --- a/src/resources/themes/pin/Contents/Resources/Incoming/NextContext.html +++ /dev/null @@ -1,9 +0,0 @@ -
        -
        - %time% -
        -
        - • %message% -
        -
        -
        diff --git a/src/resources/themes/pin/Contents/Resources/Incoming/filetransfer.html b/src/resources/themes/pin/Contents/Resources/Incoming/filetransfer.html deleted file mode 100644 index 4555bf249..000000000 --- a/src/resources/themes/pin/Contents/Resources/Incoming/filetransfer.html +++ /dev/null @@ -1,25 +0,0 @@ -
        -
        - %icon%
        - - %title% - -
        - - %filename% - -  %filesize% -
        - - Accept  - Reject - - - -
        -
        - diff --git a/src/resources/themes/pin/Contents/Resources/Outgoing/Content.html b/src/resources/themes/pin/Contents/Resources/Outgoing/Content.html deleted file mode 100644 index 3345a4903..000000000 --- a/src/resources/themes/pin/Contents/Resources/Outgoing/Content.html +++ /dev/null @@ -1,29 +0,0 @@ -
        -
        - -
        - -
        -
        -
        -
        - %sender% -
        -
        -
        -
        -
        -
        - %time% -
        -
        - %message% -
        -
        -
        -
        -
        -
        -
        -
        -
        diff --git a/src/resources/themes/pin/Contents/Resources/Outgoing/Context.html b/src/resources/themes/pin/Contents/Resources/Outgoing/Context.html deleted file mode 100644 index cd5a758e0..000000000 --- a/src/resources/themes/pin/Contents/Resources/Outgoing/Context.html +++ /dev/null @@ -1,30 +0,0 @@ -
        -
        - -
        - -
        -
        -
        -
        - %sender% -
        -
        -
        -
        -
        -
        - %time% -
        -
        - • %message% -
        -
        -
        -
        -
        -
        -
        -
        -
        -
        diff --git a/src/resources/themes/pin/Contents/Resources/Outgoing/NextContent.html b/src/resources/themes/pin/Contents/Resources/Outgoing/NextContent.html deleted file mode 100644 index 945bee4f9..000000000 --- a/src/resources/themes/pin/Contents/Resources/Outgoing/NextContent.html +++ /dev/null @@ -1,9 +0,0 @@ -
        -
        - %time% -
        -
        - %message% -
        -
        -
        diff --git a/src/resources/themes/pin/Contents/Resources/Outgoing/NextContext.html b/src/resources/themes/pin/Contents/Resources/Outgoing/NextContext.html deleted file mode 100644 index 0215664c9..000000000 --- a/src/resources/themes/pin/Contents/Resources/Outgoing/NextContext.html +++ /dev/null @@ -1,9 +0,0 @@ -
        -
        - %time% -
        -
        - • %message% -
        -
        -
        diff --git a/src/resources/themes/pin/Contents/Resources/Outgoing/filetransfer.html b/src/resources/themes/pin/Contents/Resources/Outgoing/filetransfer.html deleted file mode 100644 index 7a62e95c4..000000000 --- a/src/resources/themes/pin/Contents/Resources/Outgoing/filetransfer.html +++ /dev/null @@ -1,17 +0,0 @@ -
        -
        - %icon%
        - - %title% - -
        - - %filename% - -  %filesize% -
        - - Cancel - -
        -
        \ No newline at end of file diff --git a/src/resources/themes/pin/Contents/Resources/Status.html b/src/resources/themes/pin/Contents/Resources/Status.html deleted file mode 100644 index 9548619c3..000000000 --- a/src/resources/themes/pin/Contents/Resources/Status.html +++ /dev/null @@ -1,12 +0,0 @@ -
        -
        -
        -
        - %message% -
        -
        - %time% -
        -
        -
        -
        diff --git a/src/resources/themes/pin/Contents/Resources/Variants/Blue Background.css b/src/resources/themes/pin/Contents/Resources/Variants/Blue Background.css deleted file mode 100644 index e04c07961..000000000 --- a/src/resources/themes/pin/Contents/Resources/Variants/Blue Background.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url(../styles/background_blue.css); -@import url(../styles/basestyle.css); \ No newline at end of file diff --git a/src/resources/themes/pin/Contents/Resources/Variants/Dark Gray Background.css b/src/resources/themes/pin/Contents/Resources/Variants/Dark Gray Background.css deleted file mode 100644 index f72310ffb..000000000 --- a/src/resources/themes/pin/Contents/Resources/Variants/Dark Gray Background.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url(../styles/background_dark_gray.css); -@import url(../styles/basestyle.css); \ No newline at end of file diff --git a/src/resources/themes/pin/Contents/Resources/Variants/Green Background.css b/src/resources/themes/pin/Contents/Resources/Variants/Green Background.css deleted file mode 100644 index 982b99077..000000000 --- a/src/resources/themes/pin/Contents/Resources/Variants/Green Background.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url(../styles/background_green.css); -@import url(../styles/basestyle.css); \ No newline at end of file diff --git a/src/resources/themes/pin/Contents/Resources/Variants/Light Gray Background.css b/src/resources/themes/pin/Contents/Resources/Variants/Light Gray Background.css deleted file mode 100644 index 1ea1ced90..000000000 --- a/src/resources/themes/pin/Contents/Resources/Variants/Light Gray Background.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url(../styles/background_light_gray.css); -@import url(../styles/basestyle.css); \ No newline at end of file diff --git a/src/resources/themes/pin/Contents/Resources/Variants/Red Background.css b/src/resources/themes/pin/Contents/Resources/Variants/Red Background.css deleted file mode 100644 index 472f70d0c..000000000 --- a/src/resources/themes/pin/Contents/Resources/Variants/Red Background.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url(../styles/background_red.css); -@import url(../styles/basestyle.css); \ No newline at end of file diff --git a/src/resources/themes/pin/Contents/Resources/Variants/Yellow Background.css b/src/resources/themes/pin/Contents/Resources/Variants/Yellow Background.css deleted file mode 100644 index 5e730a476..000000000 --- a/src/resources/themes/pin/Contents/Resources/Variants/Yellow Background.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url(../styles/background_yellow.css); -@import url(../styles/basestyle.css); \ No newline at end of file diff --git a/src/resources/themes/pin/Contents/Resources/images/background_black.png b/src/resources/themes/pin/Contents/Resources/images/background_black.png deleted file mode 100644 index aeed4a2c5..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/background_black.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/background_blue.png b/src/resources/themes/pin/Contents/Resources/images/background_blue.png deleted file mode 100644 index 45d640359..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/background_blue.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/background_dark_gray.png b/src/resources/themes/pin/Contents/Resources/images/background_dark_gray.png deleted file mode 100644 index 64d940598..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/background_dark_gray.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/background_green.png b/src/resources/themes/pin/Contents/Resources/images/background_green.png deleted file mode 100644 index 64e765115..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/background_green.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/background_light_gray.png b/src/resources/themes/pin/Contents/Resources/images/background_light_gray.png deleted file mode 100644 index b2e6511ff..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/background_light_gray.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/background_pane.png b/src/resources/themes/pin/Contents/Resources/images/background_pane.png deleted file mode 100644 index 63f9a23ba..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/background_pane.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/background_red.png b/src/resources/themes/pin/Contents/Resources/images/background_red.png deleted file mode 100644 index e2c1d861c..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/background_red.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/background_yellow.png b/src/resources/themes/pin/Contents/Resources/images/background_yellow.png deleted file mode 100644 index 83d639800..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/background_yellow.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/corner_bottom_left.png b/src/resources/themes/pin/Contents/Resources/images/corner_bottom_left.png deleted file mode 100644 index 694c3effc..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/corner_bottom_left.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/corner_bottom_right.png b/src/resources/themes/pin/Contents/Resources/images/corner_bottom_right.png deleted file mode 100644 index 4592d130d..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/corner_bottom_right.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/corner_top_left.png b/src/resources/themes/pin/Contents/Resources/images/corner_top_left.png deleted file mode 100644 index f5d64903a..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/corner_top_left.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/corner_top_right.png b/src/resources/themes/pin/Contents/Resources/images/corner_top_right.png deleted file mode 100644 index 4bb13c57f..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/corner_top_right.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/edge_left.png b/src/resources/themes/pin/Contents/Resources/images/edge_left.png deleted file mode 100644 index c0a80a841..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/edge_left.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/header_bottom.png b/src/resources/themes/pin/Contents/Resources/images/header_bottom.png deleted file mode 100644 index 10da8afc5..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/header_bottom.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/header_top.png b/src/resources/themes/pin/Contents/Resources/images/header_top.png deleted file mode 100644 index 064ea05ab..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/header_top.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/newspaper_texture.png b/src/resources/themes/pin/Contents/Resources/images/newspaper_texture.png deleted file mode 100644 index 120202c33..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/newspaper_texture.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/photo.png b/src/resources/themes/pin/Contents/Resources/images/photo.png deleted file mode 100644 index 901dd1d43..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/photo.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/status_bottom_left.png b/src/resources/themes/pin/Contents/Resources/images/status_bottom_left.png deleted file mode 100644 index cfe060b67..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/status_bottom_left.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/images/status_bottom_right.png b/src/resources/themes/pin/Contents/Resources/images/status_bottom_right.png deleted file mode 100644 index 0edb82f99..000000000 Binary files a/src/resources/themes/pin/Contents/Resources/images/status_bottom_right.png and /dev/null differ diff --git a/src/resources/themes/pin/Contents/Resources/main.css b/src/resources/themes/pin/Contents/Resources/main.css deleted file mode 100644 index cdb53f492..000000000 --- a/src/resources/themes/pin/Contents/Resources/main.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url(styles/background_black.css); -@import url(styles/basestyle.css); \ No newline at end of file diff --git a/src/resources/themes/pin/Contents/Resources/prototype-1.4.0.js b/src/resources/themes/pin/Contents/Resources/prototype-1.4.0.js deleted file mode 100644 index 0e85338ba..000000000 --- a/src/resources/themes/pin/Contents/Resources/prototype-1.4.0.js +++ /dev/null @@ -1,1781 +0,0 @@ -/* Prototype JavaScript framework, version 1.4.0 - * (c) 2005 Sam Stephenson - * - * Prototype is freely distributable under the terms of an MIT-style license. - * For details, see the Prototype web site: http://prototype.conio.net/ - * -/*--------------------------------------------------------------------------*/ - -var Prototype = { - Version: '1.4.0', - ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', - - emptyFunction: function() {}, - K: function(x) {return x} -} - -var Class = { - create: function() { - return function() { - this.initialize.apply(this, arguments); - } - } -} - -var Abstract = new Object(); - -Object.extend = function(destination, source) { - for (property in source) { - destination[property] = source[property]; - } - return destination; -} - -Object.inspect = function(object) { - try { - if (object == undefined) return 'undefined'; - if (object == null) return 'null'; - return object.inspect ? object.inspect() : object.toString(); - } catch (e) { - if (e instanceof RangeError) return '...'; - throw e; - } -} - -Function.prototype.bind = function() { - var __method = this, args = $A(arguments), object = args.shift(); - return function() { - return __method.apply(object, args.concat($A(arguments))); - } -} - -Function.prototype.bindAsEventListener = function(object) { - var __method = this; - return function(event) { - return __method.call(object, event || window.event); - } -} - -Object.extend(Number.prototype, { - toColorPart: function() { - var digits = this.toString(16); - if (this < 16) return '0' + digits; - return digits; - }, - - succ: function() { - return this + 1; - }, - - times: function(iterator) { - $R(0, this, true).each(iterator); - return this; - } -}); - -var Try = { - these: function() { - var returnValue; - - for (var i = 0; i < arguments.length; i++) { - var lambda = arguments[i]; - try { - returnValue = lambda(); - break; - } catch (e) {} - } - - return returnValue; - } -} - -/*--------------------------------------------------------------------------*/ - -var PeriodicalExecuter = Class.create(); -PeriodicalExecuter.prototype = { - initialize: function(callback, frequency) { - this.callback = callback; - this.frequency = frequency; - this.currentlyExecuting = false; - - this.registerCallback(); - }, - - registerCallback: function() { - setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - onTimerEvent: function() { - if (!this.currentlyExecuting) { - try { - this.currentlyExecuting = true; - this.callback(); - } finally { - this.currentlyExecuting = false; - } - } - } -} - -/*--------------------------------------------------------------------------*/ - -function $() { - var elements = new Array(); - - for (var i = 0; i < arguments.length; i++) { - var element = arguments[i]; - if (typeof element == 'string') - element = document.getElementById(element); - - if (arguments.length == 1) - return element; - - elements.push(element); - } - - return elements; -} -Object.extend(String.prototype, { - stripTags: function() { - return this.replace(/<\/?[^>]+>/gi, ''); - }, - - stripScripts: function() { - return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); - }, - - extractScripts: function() { - var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); - var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); - return (this.match(matchAll) || []).map(function(scriptTag) { - return (scriptTag.match(matchOne) || ['', ''])[1]; - }); - }, - - evalScripts: function() { - return this.extractScripts().map(eval); - }, - - escapeHTML: function() { - var div = document.createElement('div'); - var text = document.createTextNode(this); - div.appendChild(text); - return div.innerHTML; - }, - - unescapeHTML: function() { - var div = document.createElement('div'); - div.innerHTML = this.stripTags(); - return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; - }, - - toQueryParams: function() { - var pairs = this.match(/^\??(.*)$/)[1].split('&'); - return pairs.inject({}, function(params, pairString) { - var pair = pairString.split('='); - params[pair[0]] = pair[1]; - return params; - }); - }, - - toArray: function() { - return this.split(''); - }, - - camelize: function() { - var oStringList = this.split('-'); - if (oStringList.length == 1) return oStringList[0]; - - var camelizedString = this.indexOf('-') == 0 - ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) - : oStringList[0]; - - for (var i = 1, len = oStringList.length; i < len; i++) { - var s = oStringList[i]; - camelizedString += s.charAt(0).toUpperCase() + s.substring(1); - } - - return camelizedString; - }, - - inspect: function() { - return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; - } -}); - -String.prototype.parseQuery = String.prototype.toQueryParams; - -var $break = new Object(); -var $continue = new Object(); - -var Enumerable = { - each: function(iterator) { - var index = 0; - try { - this._each(function(value) { - try { - iterator(value, index++); - } catch (e) { - if (e != $continue) throw e; - } - }); - } catch (e) { - if (e != $break) throw e; - } - }, - - all: function(iterator) { - var result = true; - this.each(function(value, index) { - result = result && !!(iterator || Prototype.K)(value, index); - if (!result) throw $break; - }); - return result; - }, - - any: function(iterator) { - var result = true; - this.each(function(value, index) { - if (result = !!(iterator || Prototype.K)(value, index)) - throw $break; - }); - return result; - }, - - collect: function(iterator) { - var results = []; - this.each(function(value, index) { - results.push(iterator(value, index)); - }); - return results; - }, - - detect: function (iterator) { - var result; - this.each(function(value, index) { - if (iterator(value, index)) { - result = value; - throw $break; - } - }); - return result; - }, - - findAll: function(iterator) { - var results = []; - this.each(function(value, index) { - if (iterator(value, index)) - results.push(value); - }); - return results; - }, - - grep: function(pattern, iterator) { - var results = []; - this.each(function(value, index) { - var stringValue = value.toString(); - if (stringValue.match(pattern)) - results.push((iterator || Prototype.K)(value, index)); - }) - return results; - }, - - include: function(object) { - var found = false; - this.each(function(value) { - if (value == object) { - found = true; - throw $break; - } - }); - return found; - }, - - inject: function(memo, iterator) { - this.each(function(value, index) { - memo = iterator(memo, value, index); - }); - return memo; - }, - - invoke: function(method) { - var args = $A(arguments).slice(1); - return this.collect(function(value) { - return value[method].apply(value, args); - }); - }, - - max: function(iterator) { - var result; - this.each(function(value, index) { - value = (iterator || Prototype.K)(value, index); - if (value >= (result || value)) - result = value; - }); - return result; - }, - - min: function(iterator) { - var result; - this.each(function(value, index) { - value = (iterator || Prototype.K)(value, index); - if (value <= (result || value)) - result = value; - }); - return result; - }, - - partition: function(iterator) { - var trues = [], falses = []; - this.each(function(value, index) { - ((iterator || Prototype.K)(value, index) ? - trues : falses).push(value); - }); - return [trues, falses]; - }, - - pluck: function(property) { - var results = []; - this.each(function(value, index) { - results.push(value[property]); - }); - return results; - }, - - reject: function(iterator) { - var results = []; - this.each(function(value, index) { - if (!iterator(value, index)) - results.push(value); - }); - return results; - }, - - sortBy: function(iterator) { - return this.collect(function(value, index) { - return {value: value, criteria: iterator(value, index)}; - }).sort(function(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - }).pluck('value'); - }, - - toArray: function() { - return this.collect(Prototype.K); - }, - - zip: function() { - var iterator = Prototype.K, args = $A(arguments); - if (typeof args.last() == 'function') - iterator = args.pop(); - - var collections = [this].concat(args).map($A); - return this.map(function(value, index) { - iterator(value = collections.pluck(index)); - return value; - }); - }, - - inspect: function() { - return '#'; - } -} - -Object.extend(Enumerable, { - map: Enumerable.collect, - find: Enumerable.detect, - select: Enumerable.findAll, - member: Enumerable.include, - entries: Enumerable.toArray -}); -var $A = Array.from = function(iterable) { - if (!iterable) return []; - if (iterable.toArray) { - return iterable.toArray(); - } else { - var results = []; - for (var i = 0; i < iterable.length; i++) - results.push(iterable[i]); - return results; - } -} - -Object.extend(Array.prototype, Enumerable); - -Array.prototype._reverse = Array.prototype.reverse; - -Object.extend(Array.prototype, { - _each: function(iterator) { - for (var i = 0; i < this.length; i++) - iterator(this[i]); - }, - - clear: function() { - this.length = 0; - return this; - }, - - first: function() { - return this[0]; - }, - - last: function() { - return this[this.length - 1]; - }, - - compact: function() { - return this.select(function(value) { - return value != undefined || value != null; - }); - }, - - flatten: function() { - return this.inject([], function(array, value) { - return array.concat(value.constructor == Array ? - value.flatten() : [value]); - }); - }, - - without: function() { - var values = $A(arguments); - return this.select(function(value) { - return !values.include(value); - }); - }, - - indexOf: function(object) { - for (var i = 0; i < this.length; i++) - if (this[i] == object) return i; - return -1; - }, - - reverse: function(inline) { - return (inline !== false ? this : this.toArray())._reverse(); - }, - - shift: function() { - var result = this[0]; - for (var i = 0; i < this.length - 1; i++) - this[i] = this[i + 1]; - this.length--; - return result; - }, - - inspect: function() { - return '[' + this.map(Object.inspect).join(', ') + ']'; - } -}); -var Hash = { - _each: function(iterator) { - for (key in this) { - var value = this[key]; - if (typeof value == 'function') continue; - - var pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, - - keys: function() { - return this.pluck('key'); - }, - - values: function() { - return this.pluck('value'); - }, - - merge: function(hash) { - return $H(hash).inject($H(this), function(mergedHash, pair) { - mergedHash[pair.key] = pair.value; - return mergedHash; - }); - }, - - toQueryString: function() { - return this.map(function(pair) { - return pair.map(encodeURIComponent).join('='); - }).join('&'); - }, - - inspect: function() { - return '#'; - } -} - -function $H(object) { - var hash = Object.extend({}, object || {}); - Object.extend(hash, Enumerable); - Object.extend(hash, Hash); - return hash; -} -ObjectRange = Class.create(); -Object.extend(ObjectRange.prototype, Enumerable); -Object.extend(ObjectRange.prototype, { - initialize: function(start, end, exclusive) { - this.start = start; - this.end = end; - this.exclusive = exclusive; - }, - - _each: function(iterator) { - var value = this.start; - do { - iterator(value); - value = value.succ(); - } while (this.include(value)); - }, - - include: function(value) { - if (value < this.start) - return false; - if (this.exclusive) - return value < this.end; - return value <= this.end; - } -}); - -var $R = function(start, end, exclusive) { - return new ObjectRange(start, end, exclusive); -} - -var Ajax = { - getTransport: function() { - return Try.these( - function() {return new ActiveXObject('Msxml2.XMLHTTP')}, - function() {return new ActiveXObject('Microsoft.XMLHTTP')}, - function() {return new XMLHttpRequest()} - ) || false; - }, - - activeRequestCount: 0 -} - -Ajax.Responders = { - responders: [], - - _each: function(iterator) { - this.responders._each(iterator); - }, - - register: function(responderToAdd) { - if (!this.include(responderToAdd)) - this.responders.push(responderToAdd); - }, - - unregister: function(responderToRemove) { - this.responders = this.responders.without(responderToRemove); - }, - - dispatch: function(callback, request, transport, json) { - this.each(function(responder) { - if (responder[callback] && typeof responder[callback] == 'function') { - try { - responder[callback].apply(responder, [request, transport, json]); - } catch (e) {} - } - }); - } -}; - -Object.extend(Ajax.Responders, Enumerable); - -Ajax.Responders.register({ - onCreate: function() { - Ajax.activeRequestCount++; - }, - - onComplete: function() { - Ajax.activeRequestCount--; - } -}); - -Ajax.Base = function() {}; -Ajax.Base.prototype = { - setOptions: function(options) { - this.options = { - method: 'post', - asynchronous: true, - parameters: '' - } - Object.extend(this.options, options || {}); - }, - - responseIsSuccess: function() { - return this.transport.status == undefined - || this.transport.status == 0 - || (this.transport.status >= 200 && this.transport.status < 300); - }, - - responseIsFailure: function() { - return !this.responseIsSuccess(); - } -} - -Ajax.Request = Class.create(); -Ajax.Request.Events = - ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; - -Ajax.Request.prototype = Object.extend(new Ajax.Base(), { - initialize: function(url, options) { - this.transport = Ajax.getTransport(); - this.setOptions(options); - this.request(url); - }, - - request: function(url) { - var parameters = this.options.parameters || ''; - if (parameters.length > 0) parameters += '&_='; - - try { - this.url = url; - if (this.options.method == 'get' && parameters.length > 0) - this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; - - Ajax.Responders.dispatch('onCreate', this, this.transport); - - this.transport.open(this.options.method, this.url, - this.options.asynchronous); - - if (this.options.asynchronous) { - this.transport.onreadystatechange = this.onStateChange.bind(this); - setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); - } - - this.setRequestHeaders(); - - var body = this.options.postBody ? this.options.postBody : parameters; - this.transport.send(this.options.method == 'post' ? body : null); - - } catch (e) { - this.dispatchException(e); - } - }, - - setRequestHeaders: function() { - var requestHeaders = - ['X-Requested-With', 'XMLHttpRequest', - 'X-Prototype-Version', Prototype.Version]; - - if (this.options.method == 'post') { - requestHeaders.push('Content-type', - 'application/x-www-form-urlencoded'); - - /* Force "Connection: close" for Mozilla browsers to work around - * a bug where XMLHttpReqeuest sends an incorrect Content-length - * header. See Mozilla Bugzilla #246651. - */ - if (this.transport.overrideMimeType) - requestHeaders.push('Connection', 'close'); - } - - if (this.options.requestHeaders) - requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); - - for (var i = 0; i < requestHeaders.length; i += 2) - this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); - }, - - onStateChange: function() { - var readyState = this.transport.readyState; - if (readyState != 1) - this.respondToReadyState(this.transport.readyState); - }, - - header: function(name) { - try { - return this.transport.getResponseHeader(name); - } catch (e) {} - }, - - evalJSON: function() { - try { - return eval(this.header('X-JSON')); - } catch (e) {} - }, - - evalResponse: function() { - try { - return eval(this.transport.responseText); - } catch (e) { - this.dispatchException(e); - } - }, - - respondToReadyState: function(readyState) { - var event = Ajax.Request.Events[readyState]; - var transport = this.transport, json = this.evalJSON(); - - if (event == 'Complete') { - try { - (this.options['on' + this.transport.status] - || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(transport, json); - } catch (e) { - this.dispatchException(e); - } - - if ((this.header('Content-type') || '').match(/^text\/javascript/i)) - this.evalResponse(); - } - - try { - (this.options['on' + event] || Prototype.emptyFunction)(transport, json); - Ajax.Responders.dispatch('on' + event, this, transport, json); - } catch (e) { - this.dispatchException(e); - } - - /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ - if (event == 'Complete') - this.transport.onreadystatechange = Prototype.emptyFunction; - }, - - dispatchException: function(exception) { - (this.options.onException || Prototype.emptyFunction)(this, exception); - Ajax.Responders.dispatch('onException', this, exception); - } -}); - -Ajax.Updater = Class.create(); - -Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { - initialize: function(container, url, options) { - this.containers = { - success: container.success ? $(container.success) : $(container), - failure: container.failure ? $(container.failure) : - (container.success ? null : $(container)) - } - - this.transport = Ajax.getTransport(); - this.setOptions(options); - - var onComplete = this.options.onComplete || Prototype.emptyFunction; - this.options.onComplete = (function(transport, object) { - this.updateContent(); - onComplete(transport, object); - }).bind(this); - - this.request(url); - }, - - updateContent: function() { - var receiver = this.responseIsSuccess() ? - this.containers.success : this.containers.failure; - var response = this.transport.responseText; - - if (!this.options.evalScripts) - response = response.stripScripts(); - - if (receiver) { - if (this.options.insertion) { - new this.options.insertion(receiver, response); - } else { - Element.update(receiver, response); - } - } - - if (this.responseIsSuccess()) { - if (this.onComplete) - setTimeout(this.onComplete.bind(this), 10); - } - } -}); - -Ajax.PeriodicalUpdater = Class.create(); -Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { - initialize: function(container, url, options) { - this.setOptions(options); - this.onComplete = this.options.onComplete; - - this.frequency = (this.options.frequency || 2); - this.decay = (this.options.decay || 1); - - this.updater = {}; - this.container = container; - this.url = url; - - this.start(); - }, - - start: function() { - this.options.onComplete = this.updateComplete.bind(this); - this.onTimerEvent(); - }, - - stop: function() { - this.updater.onComplete = undefined; - clearTimeout(this.timer); - (this.onComplete || Prototype.emptyFunction).apply(this, arguments); - }, - - updateComplete: function(request) { - if (this.options.decay) { - this.decay = (request.responseText == this.lastText ? - this.decay * this.options.decay : 1); - - this.lastText = request.responseText; - } - this.timer = setTimeout(this.onTimerEvent.bind(this), - this.decay * this.frequency * 1000); - }, - - onTimerEvent: function() { - this.updater = new Ajax.Updater(this.container, this.url, this.options); - } -}); -document.getElementsByClassName = function(className, parentElement) { - var children = ($(parentElement) || document.body).getElementsByTagName('*'); - return $A(children).inject([], function(elements, child) { - if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) - elements.push(child); - return elements; - }); -} - -/*--------------------------------------------------------------------------*/ - -if (!window.Element) { - var Element = new Object(); -} - -Object.extend(Element, { - visible: function(element) { - return $(element).style.display != 'none'; - }, - - toggle: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - Element[Element.visible(element) ? 'hide' : 'show'](element); - } - }, - - hide: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - element.style.display = 'none'; - } - }, - - show: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - element.style.display = ''; - } - }, - - remove: function(element) { - element = $(element); - element.parentNode.removeChild(element); - }, - - update: function(element, html) { - $(element).innerHTML = html.stripScripts(); - setTimeout(function() {html.evalScripts()}, 10); - }, - - getHeight: function(element) { - element = $(element); - return element.offsetHeight; - }, - - classNames: function(element) { - return new Element.ClassNames(element); - }, - - hasClassName: function(element, className) { - if (!(element = $(element))) return; - return Element.classNames(element).include(className); - }, - - addClassName: function(element, className) { - if (!(element = $(element))) return; - return Element.classNames(element).add(className); - }, - - removeClassName: function(element, className) { - if (!(element = $(element))) return; - return Element.classNames(element).remove(className); - }, - - // removes whitespace-only text node children - cleanWhitespace: function(element) { - element = $(element); - for (var i = 0; i < element.childNodes.length; i++) { - var node = element.childNodes[i]; - if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) - Element.remove(node); - } - }, - - empty: function(element) { - return $(element).innerHTML.match(/^\s*$/); - }, - - scrollTo: function(element) { - element = $(element); - var x = element.x ? element.x : element.offsetLeft, - y = element.y ? element.y : element.offsetTop; - window.scrollTo(x, y); - }, - - getStyle: function(element, style) { - element = $(element); - var value = element.style[style.camelize()]; - if (!value) { - if (document.defaultView && document.defaultView.getComputedStyle) { - var css = document.defaultView.getComputedStyle(element, null); - value = css ? css.getPropertyValue(style) : null; - } else if (element.currentStyle) { - value = element.currentStyle[style.camelize()]; - } - } - - if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) - if (Element.getStyle(element, 'position') == 'static') value = 'auto'; - - return value == 'auto' ? null : value; - }, - - setStyle: function(element, style) { - element = $(element); - for (name in style) - element.style[name.camelize()] = style[name]; - }, - - getDimensions: function(element) { - element = $(element); - if (Element.getStyle(element, 'display') != 'none') - return {width: element.offsetWidth, height: element.offsetHeight}; - - // All *Width and *Height properties give 0 on elements with display none, - // so enable the element temporarily - var els = element.style; - var originalVisibility = els.visibility; - var originalPosition = els.position; - els.visibility = 'hidden'; - els.position = 'absolute'; - els.display = ''; - var originalWidth = element.clientWidth; - var originalHeight = element.clientHeight; - els.display = 'none'; - els.position = originalPosition; - els.visibility = originalVisibility; - return {width: originalWidth, height: originalHeight}; - }, - - makePositioned: function(element) { - element = $(element); - var pos = Element.getStyle(element, 'position'); - if (pos == 'static' || !pos) { - element._madePositioned = true; - element.style.position = 'relative'; - // Opera returns the offset relative to the positioning context, when an - // element is position relative but top and left have not been defined - if (window.opera) { - element.style.top = 0; - element.style.left = 0; - } - } - }, - - undoPositioned: function(element) { - element = $(element); - if (element._madePositioned) { - element._madePositioned = undefined; - element.style.position = - element.style.top = - element.style.left = - element.style.bottom = - element.style.right = ''; - } - }, - - makeClipping: function(element) { - element = $(element); - if (element._overflow) return; - element._overflow = element.style.overflow; - if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') - element.style.overflow = 'hidden'; - }, - - undoClipping: function(element) { - element = $(element); - if (element._overflow) return; - element.style.overflow = element._overflow; - element._overflow = undefined; - } -}); - -var Toggle = new Object(); -Toggle.display = Element.toggle; - -/*--------------------------------------------------------------------------*/ - -Abstract.Insertion = function(adjacency) { - this.adjacency = adjacency; -} - -Abstract.Insertion.prototype = { - initialize: function(element, content) { - this.element = $(element); - this.content = content.stripScripts(); - - if (this.adjacency && this.element.insertAdjacentHTML) { - try { - this.element.insertAdjacentHTML(this.adjacency, this.content); - } catch (e) { - if (this.element.tagName.toLowerCase() == 'tbody') { - this.insertContent(this.contentFromAnonymousTable()); - } else { - throw e; - } - } - } else { - this.range = this.element.ownerDocument.createRange(); - if (this.initializeRange) this.initializeRange(); - this.insertContent([this.range.createContextualFragment(this.content)]); - } - - setTimeout(function() {content.evalScripts()}, 10); - }, - - contentFromAnonymousTable: function() { - var div = document.createElement('div'); - div.innerHTML = '
        ' + this.content + '
        '; - return $A(div.childNodes[0].childNodes[0].childNodes); - } -} - -var Insertion = new Object(); - -Insertion.Before = Class.create(); -Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { - initializeRange: function() { - this.range.setStartBefore(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.parentNode.insertBefore(fragment, this.element); - }).bind(this)); - } -}); - -Insertion.Top = Class.create(); -Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { - initializeRange: function() { - this.range.selectNodeContents(this.element); - this.range.collapse(true); - }, - - insertContent: function(fragments) { - fragments.reverse(false).each((function(fragment) { - this.element.insertBefore(fragment, this.element.firstChild); - }).bind(this)); - } -}); - -Insertion.Bottom = Class.create(); -Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { - initializeRange: function() { - this.range.selectNodeContents(this.element); - this.range.collapse(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.appendChild(fragment); - }).bind(this)); - } -}); - -Insertion.After = Class.create(); -Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { - initializeRange: function() { - this.range.setStartAfter(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.parentNode.insertBefore(fragment, - this.element.nextSibling); - }).bind(this)); - } -}); - -/*--------------------------------------------------------------------------*/ - -Element.ClassNames = Class.create(); -Element.ClassNames.prototype = { - initialize: function(element) { - this.element = $(element); - }, - - _each: function(iterator) { - this.element.className.split(/\s+/).select(function(name) { - return name.length > 0; - })._each(iterator); - }, - - set: function(className) { - this.element.className = className; - }, - - add: function(classNameToAdd) { - if (this.include(classNameToAdd)) return; - this.set(this.toArray().concat(classNameToAdd).join(' ')); - }, - - remove: function(classNameToRemove) { - if (!this.include(classNameToRemove)) return; - this.set(this.select(function(className) { - return className != classNameToRemove; - }).join(' ')); - }, - - toString: function() { - return this.toArray().join(' '); - } -} - -Object.extend(Element.ClassNames.prototype, Enumerable); -var Field = { - clear: function() { - for (var i = 0; i < arguments.length; i++) - $(arguments[i]).value = ''; - }, - - focus: function(element) { - $(element).focus(); - }, - - present: function() { - for (var i = 0; i < arguments.length; i++) - if ($(arguments[i]).value == '') return false; - return true; - }, - - select: function(element) { - $(element).select(); - }, - - activate: function(element) { - element = $(element); - element.focus(); - if (element.select) - element.select(); - } -} - -/*--------------------------------------------------------------------------*/ - -var Form = { - serialize: function(form) { - var elements = Form.getElements($(form)); - var queryComponents = new Array(); - - for (var i = 0; i < elements.length; i++) { - var queryComponent = Form.Element.serialize(elements[i]); - if (queryComponent) - queryComponents.push(queryComponent); - } - - return queryComponents.join('&'); - }, - - getElements: function(form) { - form = $(form); - var elements = new Array(); - - for (tagName in Form.Element.Serializers) { - var tagElements = form.getElementsByTagName(tagName); - for (var j = 0; j < tagElements.length; j++) - elements.push(tagElements[j]); - } - return elements; - }, - - getInputs: function(form, typeName, name) { - form = $(form); - var inputs = form.getElementsByTagName('input'); - - if (!typeName && !name) - return inputs; - - var matchingInputs = new Array(); - for (var i = 0; i < inputs.length; i++) { - var input = inputs[i]; - if ((typeName && input.type != typeName) || - (name && input.name != name)) - continue; - matchingInputs.push(input); - } - - return matchingInputs; - }, - - disable: function(form) { - var elements = Form.getElements(form); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - element.blur(); - element.disabled = 'true'; - } - }, - - enable: function(form) { - var elements = Form.getElements(form); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - element.disabled = ''; - } - }, - - findFirstElement: function(form) { - return Form.getElements(form).find(function(element) { - return element.type != 'hidden' && !element.disabled && - ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); - }); - }, - - focusFirstElement: function(form) { - Field.activate(Form.findFirstElement(form)); - }, - - reset: function(form) { - $(form).reset(); - } -} - -Form.Element = { - serialize: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - var parameter = Form.Element.Serializers[method](element); - - if (parameter) { - var key = encodeURIComponent(parameter[0]); - if (key.length == 0) return; - - if (parameter[1].constructor != Array) - parameter[1] = [parameter[1]]; - - return parameter[1].map(function(value) { - return key + '=' + encodeURIComponent(value); - }).join('&'); - } - }, - - getValue: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - var parameter = Form.Element.Serializers[method](element); - - if (parameter) - return parameter[1]; - } -} - -Form.Element.Serializers = { - input: function(element) { - switch (element.type.toLowerCase()) { - case 'submit': - case 'hidden': - case 'password': - case 'text': - return Form.Element.Serializers.textarea(element); - case 'checkbox': - case 'radio': - return Form.Element.Serializers.inputSelector(element); - } - return false; - }, - - inputSelector: function(element) { - if (element.checked) - return [element.name, element.value]; - }, - - textarea: function(element) { - return [element.name, element.value]; - }, - - select: function(element) { - return Form.Element.Serializers[element.type == 'select-one' ? - 'selectOne' : 'selectMany'](element); - }, - - selectOne: function(element) { - var value = '', opt, index = element.selectedIndex; - if (index >= 0) { - opt = element.options[index]; - value = opt.value; - if (!value && !('value' in opt)) - value = opt.text; - } - return [element.name, value]; - }, - - selectMany: function(element) { - var value = new Array(); - for (var i = 0; i < element.length; i++) { - var opt = element.options[i]; - if (opt.selected) { - var optValue = opt.value; - if (!optValue && !('value' in opt)) - optValue = opt.text; - value.push(optValue); - } - } - return [element.name, value]; - } -} - -/*--------------------------------------------------------------------------*/ - -var $F = Form.Element.getValue; - -/*--------------------------------------------------------------------------*/ - -Abstract.TimedObserver = function() {} -Abstract.TimedObserver.prototype = { - initialize: function(element, frequency, callback) { - this.frequency = frequency; - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - this.registerCallback(); - }, - - registerCallback: function() { - setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - onTimerEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - } -} - -Form.Element.Observer = Class.create(); -Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.Observer = Class.create(); -Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { - getValue: function() { - return Form.serialize(this.element); - } -}); - -/*--------------------------------------------------------------------------*/ - -Abstract.EventObserver = function() {} -Abstract.EventObserver.prototype = { - initialize: function(element, callback) { - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - if (this.element.tagName.toLowerCase() == 'form') - this.registerFormCallbacks(); - else - this.registerCallback(this.element); - }, - - onElementEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - }, - - registerFormCallbacks: function() { - var elements = Form.getElements(this.element); - for (var i = 0; i < elements.length; i++) - this.registerCallback(elements[i]); - }, - - registerCallback: function(element) { - if (element.type) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - Event.observe(element, 'click', this.onElementEvent.bind(this)); - break; - case 'password': - case 'text': - case 'textarea': - case 'select-one': - case 'select-multiple': - Event.observe(element, 'change', this.onElementEvent.bind(this)); - break; - } - } - } -} - -Form.Element.EventObserver = Class.create(); -Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.EventObserver = Class.create(); -Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { - getValue: function() { - return Form.serialize(this.element); - } -}); -if (!window.Event) { - var Event = new Object(); -} - -Object.extend(Event, { - KEY_BACKSPACE: 8, - KEY_TAB: 9, - KEY_RETURN: 13, - KEY_ESC: 27, - KEY_LEFT: 37, - KEY_UP: 38, - KEY_RIGHT: 39, - KEY_DOWN: 40, - KEY_DELETE: 46, - - element: function(event) { - return event.target || event.srcElement; - }, - - isLeftClick: function(event) { - return (((event.which) && (event.which == 1)) || - ((event.button) && (event.button == 1))); - }, - - pointerX: function(event) { - return event.pageX || (event.clientX + - (document.documentElement.scrollLeft || document.body.scrollLeft)); - }, - - pointerY: function(event) { - return event.pageY || (event.clientY + - (document.documentElement.scrollTop || document.body.scrollTop)); - }, - - stop: function(event) { - if (event.preventDefault) { - event.preventDefault(); - event.stopPropagation(); - } else { - event.returnValue = false; - event.cancelBubble = true; - } - }, - - // find the first node with the given tagName, starting from the - // node the event was triggered on; traverses the DOM upwards - findElement: function(event, tagName) { - var element = Event.element(event); - while (element.parentNode && (!element.tagName || - (element.tagName.toUpperCase() != tagName.toUpperCase()))) - element = element.parentNode; - return element; - }, - - observers: false, - - _observeAndCache: function(element, name, observer, useCapture) { - if (!this.observers) this.observers = []; - if (element.addEventListener) { - this.observers.push([element, name, observer, useCapture]); - element.addEventListener(name, observer, useCapture); - } else if (element.attachEvent) { - this.observers.push([element, name, observer, useCapture]); - element.attachEvent('on' + name, observer); - } - }, - - unloadCache: function() { - if (!Event.observers) return; - for (var i = 0; i < Event.observers.length; i++) { - Event.stopObserving.apply(this, Event.observers[i]); - Event.observers[i][0] = null; - } - Event.observers = false; - }, - - observe: function(element, name, observer, useCapture) { - var element = $(element); - useCapture = useCapture || false; - - if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.attachEvent)) - name = 'keydown'; - - this._observeAndCache(element, name, observer, useCapture); - }, - - stopObserving: function(element, name, observer, useCapture) { - var element = $(element); - useCapture = useCapture || false; - - if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.detachEvent)) - name = 'keydown'; - - if (element.removeEventListener) { - element.removeEventListener(name, observer, useCapture); - } else if (element.detachEvent) { - element.detachEvent('on' + name, observer); - } - } -}); - -/* prevent memory leaks in IE */ -Event.observe(window, 'unload', Event.unloadCache, false); -var Position = { - // set to true if needed, warning: firefox performance problems - // NOT neeeded for page scrolling, only if draggable contained in - // scrollable elements - includeScrollOffsets: false, - - // must be called before calling withinIncludingScrolloffset, every time the - // page is scrolled - prepare: function() { - this.deltaX = window.pageXOffset - || document.documentElement.scrollLeft - || document.body.scrollLeft - || 0; - this.deltaY = window.pageYOffset - || document.documentElement.scrollTop - || document.body.scrollTop - || 0; - }, - - realOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.scrollTop || 0; - valueL += element.scrollLeft || 0; - element = element.parentNode; - } while (element); - return [valueL, valueT]; - }, - - cumulativeOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - } while (element); - return [valueL, valueT]; - }, - - positionedOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - if (element) { - p = Element.getStyle(element, 'position'); - if (p == 'relative' || p == 'absolute') break; - } - } while (element); - return [valueL, valueT]; - }, - - offsetParent: function(element) { - if (element.offsetParent) return element.offsetParent; - if (element == document.body) return element; - - while ((element = element.parentNode) && element != document.body) - if (Element.getStyle(element, 'position') != 'static') - return element; - - return document.body; - }, - - // caches x/y coordinate pair to use with overlap - within: function(element, x, y) { - if (this.includeScrollOffsets) - return this.withinIncludingScrolloffsets(element, x, y); - this.xcomp = x; - this.ycomp = y; - this.offset = this.cumulativeOffset(element); - - return (y >= this.offset[1] && - y < this.offset[1] + element.offsetHeight && - x >= this.offset[0] && - x < this.offset[0] + element.offsetWidth); - }, - - withinIncludingScrolloffsets: function(element, x, y) { - var offsetcache = this.realOffset(element); - - this.xcomp = x + offsetcache[0] - this.deltaX; - this.ycomp = y + offsetcache[1] - this.deltaY; - this.offset = this.cumulativeOffset(element); - - return (this.ycomp >= this.offset[1] && - this.ycomp < this.offset[1] + element.offsetHeight && - this.xcomp >= this.offset[0] && - this.xcomp < this.offset[0] + element.offsetWidth); - }, - - // within must be called directly before - overlap: function(mode, element) { - if (!mode) return 0; - if (mode == 'vertical') - return ((this.offset[1] + element.offsetHeight) - this.ycomp) / - element.offsetHeight; - if (mode == 'horizontal') - return ((this.offset[0] + element.offsetWidth) - this.xcomp) / - element.offsetWidth; - }, - - clone: function(source, target) { - source = $(source); - target = $(target); - target.style.position = 'absolute'; - var offsets = this.cumulativeOffset(source); - target.style.top = offsets[1] + 'px'; - target.style.left = offsets[0] + 'px'; - target.style.width = source.offsetWidth + 'px'; - target.style.height = source.offsetHeight + 'px'; - }, - - page: function(forElement) { - var valueT = 0, valueL = 0; - - var element = forElement; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - - // Safari fix - if (element.offsetParent==document.body) - if (Element.getStyle(element,'position')=='absolute') break; - - } while (element = element.offsetParent); - - element = forElement; - do { - valueT -= element.scrollTop || 0; - valueL -= element.scrollLeft || 0; - } while (element = element.parentNode); - - return [valueL, valueT]; - }, - - clone: function(source, target) { - var options = Object.extend({ - setLeft: true, - setTop: true, - setWidth: true, - setHeight: true, - offsetTop: 0, - offsetLeft: 0 - }, arguments[2] || {}) - - // find page position of source - source = $(source); - var p = Position.page(source); - - // find coordinate system to use - target = $(target); - var delta = [0, 0]; - var parent = null; - // delta [0,0] will do fine with position: fixed elements, - // position:absolute needs offsetParent deltas - if (Element.getStyle(target,'position') == 'absolute') { - parent = Position.offsetParent(target); - delta = Position.page(parent); - } - - // correct by body offsets (fixes Safari) - if (parent == document.body) { - delta[0] -= document.body.offsetLeft; - delta[1] -= document.body.offsetTop; - } - - // set position - if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; - if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; - if(options.setWidth) target.style.width = source.offsetWidth + 'px'; - if(options.setHeight) target.style.height = source.offsetHeight + 'px'; - }, - - absolutize: function(element) { - element = $(element); - if (element.style.position == 'absolute') return; - Position.prepare(); - - var offsets = Position.positionedOffset(element); - var top = offsets[1]; - var left = offsets[0]; - var width = element.clientWidth; - var height = element.clientHeight; - - element._originalLeft = left - parseFloat(element.style.left || 0); - element._originalTop = top - parseFloat(element.style.top || 0); - element._originalWidth = element.style.width; - element._originalHeight = element.style.height; - - element.style.position = 'absolute'; - element.style.top = top + 'px';; - element.style.left = left + 'px';; - element.style.width = width + 'px';; - element.style.height = height + 'px';; - }, - - relativize: function(element) { - element = $(element); - if (element.style.position == 'relative') return; - Position.prepare(); - - element.style.position = 'relative'; - var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); - var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); - - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.height = element._originalHeight; - element.style.width = element._originalWidth; - } -} - -// Safari returns margins on body which is incorrect if the child is absolutely -// positioned. For performance reasons, redefine Position.cumulativeOffset for -// KHTML/WebKit only. -if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { - Position.cumulativeOffset = function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - if (element.offsetParent == document.body) - if (Element.getStyle(element, 'position') == 'absolute') break; - - element = element.offsetParent; - } while (element); - - return [valueL, valueT]; - } -} \ No newline at end of file diff --git a/src/resources/themes/pin/Contents/Resources/styles/background_black.css b/src/resources/themes/pin/Contents/Resources/styles/background_black.css deleted file mode 100644 index b9a2e22fc..000000000 --- a/src/resources/themes/pin/Contents/Resources/styles/background_black.css +++ /dev/null @@ -1,4 +0,0 @@ -body { - margin: 20px; - background: url(../images/background_black.png) bottom repeat; -} diff --git a/src/resources/themes/pin/Contents/Resources/styles/background_blue.css b/src/resources/themes/pin/Contents/Resources/styles/background_blue.css deleted file mode 100644 index 9a6b1402b..000000000 --- a/src/resources/themes/pin/Contents/Resources/styles/background_blue.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: url(../images/background_blue.png) bottom repeat; -} diff --git a/src/resources/themes/pin/Contents/Resources/styles/background_dark_gray.css b/src/resources/themes/pin/Contents/Resources/styles/background_dark_gray.css deleted file mode 100644 index 5c7e87027..000000000 --- a/src/resources/themes/pin/Contents/Resources/styles/background_dark_gray.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: url(../images/background_dark_gray.png) bottom repeat; -} diff --git a/src/resources/themes/pin/Contents/Resources/styles/background_green.css b/src/resources/themes/pin/Contents/Resources/styles/background_green.css deleted file mode 100644 index 3ac916591..000000000 --- a/src/resources/themes/pin/Contents/Resources/styles/background_green.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: url(../images/background_green.png) bottom repeat; -} diff --git a/src/resources/themes/pin/Contents/Resources/styles/background_light_gray.css b/src/resources/themes/pin/Contents/Resources/styles/background_light_gray.css deleted file mode 100644 index 70c531362..000000000 --- a/src/resources/themes/pin/Contents/Resources/styles/background_light_gray.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: url(../images/background_light_gray.png) bottom repeat; -} diff --git a/src/resources/themes/pin/Contents/Resources/styles/background_red.css b/src/resources/themes/pin/Contents/Resources/styles/background_red.css deleted file mode 100644 index 50501a598..000000000 --- a/src/resources/themes/pin/Contents/Resources/styles/background_red.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: url(../images/background_red.png) bottom repeat; -} diff --git a/src/resources/themes/pin/Contents/Resources/styles/background_yellow.css b/src/resources/themes/pin/Contents/Resources/styles/background_yellow.css deleted file mode 100644 index 5b80b8b6a..000000000 --- a/src/resources/themes/pin/Contents/Resources/styles/background_yellow.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: url(../images/background_yellow.png) bottom repeat; -} diff --git a/src/resources/themes/pin/Contents/Resources/styles/basestyle.css b/src/resources/themes/pin/Contents/Resources/styles/basestyle.css deleted file mode 100644 index 317fcc4a3..000000000 --- a/src/resources/themes/pin/Contents/Resources/styles/basestyle.css +++ /dev/null @@ -1,136 +0,0 @@ -.buddyicon { - height: 64px; - width: 64px; - position: relative; - float: right; - z-index: -2; - padding-top: 20px; - padding-right: 8px; - -} - -.photo { - height: 90px; - width: 80px; - position: relative; - float: right; - z-index: 2; - margin-top: 2px; -} - -.top { - min-width: 250px; -} - -.topleftcorner { - background: url(../images/corner_top_left.png) top left no-repeat; -} - -.toprightcorner { - padding-top: 46px; - padding-bottom: 14px; - padding-right: 5px; - padding-left: 5px; - margin-left: 74px; - font-family: Lucida Handwriting; - font-size: 12px; - background: url(../images/corner_top_right.png) top repeat-x; -} - -.left { - background: url(../images/edge_left.png) top left repeat-y; -} - -.margintimestamp { - padding-left: 15px; - float: left; - font-family: Lucida Handwriting; - font-size: 12px; -} - -.right { - padding-right: 15px; - padding-left: 5px; - margin-left: 74px; - background: url(../images/background_pane.png) top repeat; -} - -.msg1 { - min-width: 250px; -} - -.msg2 { - min-width: 250px; -} - -.bottomleftcorner { - background: url(../images/corner_bottom_left.png) top left no-repeat; -} - -.bottomrightcorner { - padding-bottom: 10px; - background: url(../images/corner_bottom_right.png) top right no-repeat; -} - -.header { - min-width: 250px; - padding: 0px 10px; -} - -.headertop { - background: url(../images/header_top.png) top no-repeat; - padding-top: 50px; -} - -.headermiddle { - background: url(../images/newspaper_texture.png) top repeat; - font-family: Capitals; - font-size: 10px; - color: rgba(35,35,35); - padding: 0px 10px; -} - -.headerbottom { - background: url(../images/header_bottom.png) top right repeat-x; - padding-top: 35px; -} - -.statusupdate { - width: 150px; - margin: 0px auto; - padding-top: 10px; - padding-bottom: 10px; - padding-right: 15px; - padding-left: 15px; - font-family: Lucida Handwriting; - font-size: 14px; - background: rgb(255,255,115); -} - -.statusbottom { - width: 200px; - margin: 0px auto; - font-family: Lucida Handwriting; - font-size: 10px; -} - -.statusbottomleft { - background: url(../images/status_bottom_left.png) top left no-repeat; - padding-left: 10px; -} - -.statusbottomright { - background: url(../images/status_bottom_right.png) top right repeat-x; - padding-top: 3px; - padding-bottom: 32px; - padding-right: 20px; - font-size: 10px; -} - -.context { - text-decoration: line-through; -} - -IMG { - position: absolute; -} diff --git a/src/resources/themes/pin/Contents/Resources/template.html b/src/resources/themes/pin/Contents/Resources/template.html deleted file mode 100644 index 7963a13da..000000000 --- a/src/resources/themes/pin/Contents/Resources/template.html +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - -%header% -

        -
        -%footer% -
        - - diff --git a/src/resources/themes/prototype-1.4.0.js b/src/resources/themes/prototype-1.4.0.js deleted file mode 100644 index 0e85338ba..000000000 --- a/src/resources/themes/prototype-1.4.0.js +++ /dev/null @@ -1,1781 +0,0 @@ -/* Prototype JavaScript framework, version 1.4.0 - * (c) 2005 Sam Stephenson - * - * Prototype is freely distributable under the terms of an MIT-style license. - * For details, see the Prototype web site: http://prototype.conio.net/ - * -/*--------------------------------------------------------------------------*/ - -var Prototype = { - Version: '1.4.0', - ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', - - emptyFunction: function() {}, - K: function(x) {return x} -} - -var Class = { - create: function() { - return function() { - this.initialize.apply(this, arguments); - } - } -} - -var Abstract = new Object(); - -Object.extend = function(destination, source) { - for (property in source) { - destination[property] = source[property]; - } - return destination; -} - -Object.inspect = function(object) { - try { - if (object == undefined) return 'undefined'; - if (object == null) return 'null'; - return object.inspect ? object.inspect() : object.toString(); - } catch (e) { - if (e instanceof RangeError) return '...'; - throw e; - } -} - -Function.prototype.bind = function() { - var __method = this, args = $A(arguments), object = args.shift(); - return function() { - return __method.apply(object, args.concat($A(arguments))); - } -} - -Function.prototype.bindAsEventListener = function(object) { - var __method = this; - return function(event) { - return __method.call(object, event || window.event); - } -} - -Object.extend(Number.prototype, { - toColorPart: function() { - var digits = this.toString(16); - if (this < 16) return '0' + digits; - return digits; - }, - - succ: function() { - return this + 1; - }, - - times: function(iterator) { - $R(0, this, true).each(iterator); - return this; - } -}); - -var Try = { - these: function() { - var returnValue; - - for (var i = 0; i < arguments.length; i++) { - var lambda = arguments[i]; - try { - returnValue = lambda(); - break; - } catch (e) {} - } - - return returnValue; - } -} - -/*--------------------------------------------------------------------------*/ - -var PeriodicalExecuter = Class.create(); -PeriodicalExecuter.prototype = { - initialize: function(callback, frequency) { - this.callback = callback; - this.frequency = frequency; - this.currentlyExecuting = false; - - this.registerCallback(); - }, - - registerCallback: function() { - setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - onTimerEvent: function() { - if (!this.currentlyExecuting) { - try { - this.currentlyExecuting = true; - this.callback(); - } finally { - this.currentlyExecuting = false; - } - } - } -} - -/*--------------------------------------------------------------------------*/ - -function $() { - var elements = new Array(); - - for (var i = 0; i < arguments.length; i++) { - var element = arguments[i]; - if (typeof element == 'string') - element = document.getElementById(element); - - if (arguments.length == 1) - return element; - - elements.push(element); - } - - return elements; -} -Object.extend(String.prototype, { - stripTags: function() { - return this.replace(/<\/?[^>]+>/gi, ''); - }, - - stripScripts: function() { - return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); - }, - - extractScripts: function() { - var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); - var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); - return (this.match(matchAll) || []).map(function(scriptTag) { - return (scriptTag.match(matchOne) || ['', ''])[1]; - }); - }, - - evalScripts: function() { - return this.extractScripts().map(eval); - }, - - escapeHTML: function() { - var div = document.createElement('div'); - var text = document.createTextNode(this); - div.appendChild(text); - return div.innerHTML; - }, - - unescapeHTML: function() { - var div = document.createElement('div'); - div.innerHTML = this.stripTags(); - return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; - }, - - toQueryParams: function() { - var pairs = this.match(/^\??(.*)$/)[1].split('&'); - return pairs.inject({}, function(params, pairString) { - var pair = pairString.split('='); - params[pair[0]] = pair[1]; - return params; - }); - }, - - toArray: function() { - return this.split(''); - }, - - camelize: function() { - var oStringList = this.split('-'); - if (oStringList.length == 1) return oStringList[0]; - - var camelizedString = this.indexOf('-') == 0 - ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) - : oStringList[0]; - - for (var i = 1, len = oStringList.length; i < len; i++) { - var s = oStringList[i]; - camelizedString += s.charAt(0).toUpperCase() + s.substring(1); - } - - return camelizedString; - }, - - inspect: function() { - return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; - } -}); - -String.prototype.parseQuery = String.prototype.toQueryParams; - -var $break = new Object(); -var $continue = new Object(); - -var Enumerable = { - each: function(iterator) { - var index = 0; - try { - this._each(function(value) { - try { - iterator(value, index++); - } catch (e) { - if (e != $continue) throw e; - } - }); - } catch (e) { - if (e != $break) throw e; - } - }, - - all: function(iterator) { - var result = true; - this.each(function(value, index) { - result = result && !!(iterator || Prototype.K)(value, index); - if (!result) throw $break; - }); - return result; - }, - - any: function(iterator) { - var result = true; - this.each(function(value, index) { - if (result = !!(iterator || Prototype.K)(value, index)) - throw $break; - }); - return result; - }, - - collect: function(iterator) { - var results = []; - this.each(function(value, index) { - results.push(iterator(value, index)); - }); - return results; - }, - - detect: function (iterator) { - var result; - this.each(function(value, index) { - if (iterator(value, index)) { - result = value; - throw $break; - } - }); - return result; - }, - - findAll: function(iterator) { - var results = []; - this.each(function(value, index) { - if (iterator(value, index)) - results.push(value); - }); - return results; - }, - - grep: function(pattern, iterator) { - var results = []; - this.each(function(value, index) { - var stringValue = value.toString(); - if (stringValue.match(pattern)) - results.push((iterator || Prototype.K)(value, index)); - }) - return results; - }, - - include: function(object) { - var found = false; - this.each(function(value) { - if (value == object) { - found = true; - throw $break; - } - }); - return found; - }, - - inject: function(memo, iterator) { - this.each(function(value, index) { - memo = iterator(memo, value, index); - }); - return memo; - }, - - invoke: function(method) { - var args = $A(arguments).slice(1); - return this.collect(function(value) { - return value[method].apply(value, args); - }); - }, - - max: function(iterator) { - var result; - this.each(function(value, index) { - value = (iterator || Prototype.K)(value, index); - if (value >= (result || value)) - result = value; - }); - return result; - }, - - min: function(iterator) { - var result; - this.each(function(value, index) { - value = (iterator || Prototype.K)(value, index); - if (value <= (result || value)) - result = value; - }); - return result; - }, - - partition: function(iterator) { - var trues = [], falses = []; - this.each(function(value, index) { - ((iterator || Prototype.K)(value, index) ? - trues : falses).push(value); - }); - return [trues, falses]; - }, - - pluck: function(property) { - var results = []; - this.each(function(value, index) { - results.push(value[property]); - }); - return results; - }, - - reject: function(iterator) { - var results = []; - this.each(function(value, index) { - if (!iterator(value, index)) - results.push(value); - }); - return results; - }, - - sortBy: function(iterator) { - return this.collect(function(value, index) { - return {value: value, criteria: iterator(value, index)}; - }).sort(function(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - }).pluck('value'); - }, - - toArray: function() { - return this.collect(Prototype.K); - }, - - zip: function() { - var iterator = Prototype.K, args = $A(arguments); - if (typeof args.last() == 'function') - iterator = args.pop(); - - var collections = [this].concat(args).map($A); - return this.map(function(value, index) { - iterator(value = collections.pluck(index)); - return value; - }); - }, - - inspect: function() { - return '#'; - } -} - -Object.extend(Enumerable, { - map: Enumerable.collect, - find: Enumerable.detect, - select: Enumerable.findAll, - member: Enumerable.include, - entries: Enumerable.toArray -}); -var $A = Array.from = function(iterable) { - if (!iterable) return []; - if (iterable.toArray) { - return iterable.toArray(); - } else { - var results = []; - for (var i = 0; i < iterable.length; i++) - results.push(iterable[i]); - return results; - } -} - -Object.extend(Array.prototype, Enumerable); - -Array.prototype._reverse = Array.prototype.reverse; - -Object.extend(Array.prototype, { - _each: function(iterator) { - for (var i = 0; i < this.length; i++) - iterator(this[i]); - }, - - clear: function() { - this.length = 0; - return this; - }, - - first: function() { - return this[0]; - }, - - last: function() { - return this[this.length - 1]; - }, - - compact: function() { - return this.select(function(value) { - return value != undefined || value != null; - }); - }, - - flatten: function() { - return this.inject([], function(array, value) { - return array.concat(value.constructor == Array ? - value.flatten() : [value]); - }); - }, - - without: function() { - var values = $A(arguments); - return this.select(function(value) { - return !values.include(value); - }); - }, - - indexOf: function(object) { - for (var i = 0; i < this.length; i++) - if (this[i] == object) return i; - return -1; - }, - - reverse: function(inline) { - return (inline !== false ? this : this.toArray())._reverse(); - }, - - shift: function() { - var result = this[0]; - for (var i = 0; i < this.length - 1; i++) - this[i] = this[i + 1]; - this.length--; - return result; - }, - - inspect: function() { - return '[' + this.map(Object.inspect).join(', ') + ']'; - } -}); -var Hash = { - _each: function(iterator) { - for (key in this) { - var value = this[key]; - if (typeof value == 'function') continue; - - var pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, - - keys: function() { - return this.pluck('key'); - }, - - values: function() { - return this.pluck('value'); - }, - - merge: function(hash) { - return $H(hash).inject($H(this), function(mergedHash, pair) { - mergedHash[pair.key] = pair.value; - return mergedHash; - }); - }, - - toQueryString: function() { - return this.map(function(pair) { - return pair.map(encodeURIComponent).join('='); - }).join('&'); - }, - - inspect: function() { - return '#'; - } -} - -function $H(object) { - var hash = Object.extend({}, object || {}); - Object.extend(hash, Enumerable); - Object.extend(hash, Hash); - return hash; -} -ObjectRange = Class.create(); -Object.extend(ObjectRange.prototype, Enumerable); -Object.extend(ObjectRange.prototype, { - initialize: function(start, end, exclusive) { - this.start = start; - this.end = end; - this.exclusive = exclusive; - }, - - _each: function(iterator) { - var value = this.start; - do { - iterator(value); - value = value.succ(); - } while (this.include(value)); - }, - - include: function(value) { - if (value < this.start) - return false; - if (this.exclusive) - return value < this.end; - return value <= this.end; - } -}); - -var $R = function(start, end, exclusive) { - return new ObjectRange(start, end, exclusive); -} - -var Ajax = { - getTransport: function() { - return Try.these( - function() {return new ActiveXObject('Msxml2.XMLHTTP')}, - function() {return new ActiveXObject('Microsoft.XMLHTTP')}, - function() {return new XMLHttpRequest()} - ) || false; - }, - - activeRequestCount: 0 -} - -Ajax.Responders = { - responders: [], - - _each: function(iterator) { - this.responders._each(iterator); - }, - - register: function(responderToAdd) { - if (!this.include(responderToAdd)) - this.responders.push(responderToAdd); - }, - - unregister: function(responderToRemove) { - this.responders = this.responders.without(responderToRemove); - }, - - dispatch: function(callback, request, transport, json) { - this.each(function(responder) { - if (responder[callback] && typeof responder[callback] == 'function') { - try { - responder[callback].apply(responder, [request, transport, json]); - } catch (e) {} - } - }); - } -}; - -Object.extend(Ajax.Responders, Enumerable); - -Ajax.Responders.register({ - onCreate: function() { - Ajax.activeRequestCount++; - }, - - onComplete: function() { - Ajax.activeRequestCount--; - } -}); - -Ajax.Base = function() {}; -Ajax.Base.prototype = { - setOptions: function(options) { - this.options = { - method: 'post', - asynchronous: true, - parameters: '' - } - Object.extend(this.options, options || {}); - }, - - responseIsSuccess: function() { - return this.transport.status == undefined - || this.transport.status == 0 - || (this.transport.status >= 200 && this.transport.status < 300); - }, - - responseIsFailure: function() { - return !this.responseIsSuccess(); - } -} - -Ajax.Request = Class.create(); -Ajax.Request.Events = - ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; - -Ajax.Request.prototype = Object.extend(new Ajax.Base(), { - initialize: function(url, options) { - this.transport = Ajax.getTransport(); - this.setOptions(options); - this.request(url); - }, - - request: function(url) { - var parameters = this.options.parameters || ''; - if (parameters.length > 0) parameters += '&_='; - - try { - this.url = url; - if (this.options.method == 'get' && parameters.length > 0) - this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; - - Ajax.Responders.dispatch('onCreate', this, this.transport); - - this.transport.open(this.options.method, this.url, - this.options.asynchronous); - - if (this.options.asynchronous) { - this.transport.onreadystatechange = this.onStateChange.bind(this); - setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); - } - - this.setRequestHeaders(); - - var body = this.options.postBody ? this.options.postBody : parameters; - this.transport.send(this.options.method == 'post' ? body : null); - - } catch (e) { - this.dispatchException(e); - } - }, - - setRequestHeaders: function() { - var requestHeaders = - ['X-Requested-With', 'XMLHttpRequest', - 'X-Prototype-Version', Prototype.Version]; - - if (this.options.method == 'post') { - requestHeaders.push('Content-type', - 'application/x-www-form-urlencoded'); - - /* Force "Connection: close" for Mozilla browsers to work around - * a bug where XMLHttpReqeuest sends an incorrect Content-length - * header. See Mozilla Bugzilla #246651. - */ - if (this.transport.overrideMimeType) - requestHeaders.push('Connection', 'close'); - } - - if (this.options.requestHeaders) - requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); - - for (var i = 0; i < requestHeaders.length; i += 2) - this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); - }, - - onStateChange: function() { - var readyState = this.transport.readyState; - if (readyState != 1) - this.respondToReadyState(this.transport.readyState); - }, - - header: function(name) { - try { - return this.transport.getResponseHeader(name); - } catch (e) {} - }, - - evalJSON: function() { - try { - return eval(this.header('X-JSON')); - } catch (e) {} - }, - - evalResponse: function() { - try { - return eval(this.transport.responseText); - } catch (e) { - this.dispatchException(e); - } - }, - - respondToReadyState: function(readyState) { - var event = Ajax.Request.Events[readyState]; - var transport = this.transport, json = this.evalJSON(); - - if (event == 'Complete') { - try { - (this.options['on' + this.transport.status] - || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(transport, json); - } catch (e) { - this.dispatchException(e); - } - - if ((this.header('Content-type') || '').match(/^text\/javascript/i)) - this.evalResponse(); - } - - try { - (this.options['on' + event] || Prototype.emptyFunction)(transport, json); - Ajax.Responders.dispatch('on' + event, this, transport, json); - } catch (e) { - this.dispatchException(e); - } - - /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ - if (event == 'Complete') - this.transport.onreadystatechange = Prototype.emptyFunction; - }, - - dispatchException: function(exception) { - (this.options.onException || Prototype.emptyFunction)(this, exception); - Ajax.Responders.dispatch('onException', this, exception); - } -}); - -Ajax.Updater = Class.create(); - -Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { - initialize: function(container, url, options) { - this.containers = { - success: container.success ? $(container.success) : $(container), - failure: container.failure ? $(container.failure) : - (container.success ? null : $(container)) - } - - this.transport = Ajax.getTransport(); - this.setOptions(options); - - var onComplete = this.options.onComplete || Prototype.emptyFunction; - this.options.onComplete = (function(transport, object) { - this.updateContent(); - onComplete(transport, object); - }).bind(this); - - this.request(url); - }, - - updateContent: function() { - var receiver = this.responseIsSuccess() ? - this.containers.success : this.containers.failure; - var response = this.transport.responseText; - - if (!this.options.evalScripts) - response = response.stripScripts(); - - if (receiver) { - if (this.options.insertion) { - new this.options.insertion(receiver, response); - } else { - Element.update(receiver, response); - } - } - - if (this.responseIsSuccess()) { - if (this.onComplete) - setTimeout(this.onComplete.bind(this), 10); - } - } -}); - -Ajax.PeriodicalUpdater = Class.create(); -Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { - initialize: function(container, url, options) { - this.setOptions(options); - this.onComplete = this.options.onComplete; - - this.frequency = (this.options.frequency || 2); - this.decay = (this.options.decay || 1); - - this.updater = {}; - this.container = container; - this.url = url; - - this.start(); - }, - - start: function() { - this.options.onComplete = this.updateComplete.bind(this); - this.onTimerEvent(); - }, - - stop: function() { - this.updater.onComplete = undefined; - clearTimeout(this.timer); - (this.onComplete || Prototype.emptyFunction).apply(this, arguments); - }, - - updateComplete: function(request) { - if (this.options.decay) { - this.decay = (request.responseText == this.lastText ? - this.decay * this.options.decay : 1); - - this.lastText = request.responseText; - } - this.timer = setTimeout(this.onTimerEvent.bind(this), - this.decay * this.frequency * 1000); - }, - - onTimerEvent: function() { - this.updater = new Ajax.Updater(this.container, this.url, this.options); - } -}); -document.getElementsByClassName = function(className, parentElement) { - var children = ($(parentElement) || document.body).getElementsByTagName('*'); - return $A(children).inject([], function(elements, child) { - if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) - elements.push(child); - return elements; - }); -} - -/*--------------------------------------------------------------------------*/ - -if (!window.Element) { - var Element = new Object(); -} - -Object.extend(Element, { - visible: function(element) { - return $(element).style.display != 'none'; - }, - - toggle: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - Element[Element.visible(element) ? 'hide' : 'show'](element); - } - }, - - hide: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - element.style.display = 'none'; - } - }, - - show: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - element.style.display = ''; - } - }, - - remove: function(element) { - element = $(element); - element.parentNode.removeChild(element); - }, - - update: function(element, html) { - $(element).innerHTML = html.stripScripts(); - setTimeout(function() {html.evalScripts()}, 10); - }, - - getHeight: function(element) { - element = $(element); - return element.offsetHeight; - }, - - classNames: function(element) { - return new Element.ClassNames(element); - }, - - hasClassName: function(element, className) { - if (!(element = $(element))) return; - return Element.classNames(element).include(className); - }, - - addClassName: function(element, className) { - if (!(element = $(element))) return; - return Element.classNames(element).add(className); - }, - - removeClassName: function(element, className) { - if (!(element = $(element))) return; - return Element.classNames(element).remove(className); - }, - - // removes whitespace-only text node children - cleanWhitespace: function(element) { - element = $(element); - for (var i = 0; i < element.childNodes.length; i++) { - var node = element.childNodes[i]; - if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) - Element.remove(node); - } - }, - - empty: function(element) { - return $(element).innerHTML.match(/^\s*$/); - }, - - scrollTo: function(element) { - element = $(element); - var x = element.x ? element.x : element.offsetLeft, - y = element.y ? element.y : element.offsetTop; - window.scrollTo(x, y); - }, - - getStyle: function(element, style) { - element = $(element); - var value = element.style[style.camelize()]; - if (!value) { - if (document.defaultView && document.defaultView.getComputedStyle) { - var css = document.defaultView.getComputedStyle(element, null); - value = css ? css.getPropertyValue(style) : null; - } else if (element.currentStyle) { - value = element.currentStyle[style.camelize()]; - } - } - - if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) - if (Element.getStyle(element, 'position') == 'static') value = 'auto'; - - return value == 'auto' ? null : value; - }, - - setStyle: function(element, style) { - element = $(element); - for (name in style) - element.style[name.camelize()] = style[name]; - }, - - getDimensions: function(element) { - element = $(element); - if (Element.getStyle(element, 'display') != 'none') - return {width: element.offsetWidth, height: element.offsetHeight}; - - // All *Width and *Height properties give 0 on elements with display none, - // so enable the element temporarily - var els = element.style; - var originalVisibility = els.visibility; - var originalPosition = els.position; - els.visibility = 'hidden'; - els.position = 'absolute'; - els.display = ''; - var originalWidth = element.clientWidth; - var originalHeight = element.clientHeight; - els.display = 'none'; - els.position = originalPosition; - els.visibility = originalVisibility; - return {width: originalWidth, height: originalHeight}; - }, - - makePositioned: function(element) { - element = $(element); - var pos = Element.getStyle(element, 'position'); - if (pos == 'static' || !pos) { - element._madePositioned = true; - element.style.position = 'relative'; - // Opera returns the offset relative to the positioning context, when an - // element is position relative but top and left have not been defined - if (window.opera) { - element.style.top = 0; - element.style.left = 0; - } - } - }, - - undoPositioned: function(element) { - element = $(element); - if (element._madePositioned) { - element._madePositioned = undefined; - element.style.position = - element.style.top = - element.style.left = - element.style.bottom = - element.style.right = ''; - } - }, - - makeClipping: function(element) { - element = $(element); - if (element._overflow) return; - element._overflow = element.style.overflow; - if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') - element.style.overflow = 'hidden'; - }, - - undoClipping: function(element) { - element = $(element); - if (element._overflow) return; - element.style.overflow = element._overflow; - element._overflow = undefined; - } -}); - -var Toggle = new Object(); -Toggle.display = Element.toggle; - -/*--------------------------------------------------------------------------*/ - -Abstract.Insertion = function(adjacency) { - this.adjacency = adjacency; -} - -Abstract.Insertion.prototype = { - initialize: function(element, content) { - this.element = $(element); - this.content = content.stripScripts(); - - if (this.adjacency && this.element.insertAdjacentHTML) { - try { - this.element.insertAdjacentHTML(this.adjacency, this.content); - } catch (e) { - if (this.element.tagName.toLowerCase() == 'tbody') { - this.insertContent(this.contentFromAnonymousTable()); - } else { - throw e; - } - } - } else { - this.range = this.element.ownerDocument.createRange(); - if (this.initializeRange) this.initializeRange(); - this.insertContent([this.range.createContextualFragment(this.content)]); - } - - setTimeout(function() {content.evalScripts()}, 10); - }, - - contentFromAnonymousTable: function() { - var div = document.createElement('div'); - div.innerHTML = '' + this.content + '
        '; - return $A(div.childNodes[0].childNodes[0].childNodes); - } -} - -var Insertion = new Object(); - -Insertion.Before = Class.create(); -Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { - initializeRange: function() { - this.range.setStartBefore(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.parentNode.insertBefore(fragment, this.element); - }).bind(this)); - } -}); - -Insertion.Top = Class.create(); -Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { - initializeRange: function() { - this.range.selectNodeContents(this.element); - this.range.collapse(true); - }, - - insertContent: function(fragments) { - fragments.reverse(false).each((function(fragment) { - this.element.insertBefore(fragment, this.element.firstChild); - }).bind(this)); - } -}); - -Insertion.Bottom = Class.create(); -Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { - initializeRange: function() { - this.range.selectNodeContents(this.element); - this.range.collapse(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.appendChild(fragment); - }).bind(this)); - } -}); - -Insertion.After = Class.create(); -Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { - initializeRange: function() { - this.range.setStartAfter(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.parentNode.insertBefore(fragment, - this.element.nextSibling); - }).bind(this)); - } -}); - -/*--------------------------------------------------------------------------*/ - -Element.ClassNames = Class.create(); -Element.ClassNames.prototype = { - initialize: function(element) { - this.element = $(element); - }, - - _each: function(iterator) { - this.element.className.split(/\s+/).select(function(name) { - return name.length > 0; - })._each(iterator); - }, - - set: function(className) { - this.element.className = className; - }, - - add: function(classNameToAdd) { - if (this.include(classNameToAdd)) return; - this.set(this.toArray().concat(classNameToAdd).join(' ')); - }, - - remove: function(classNameToRemove) { - if (!this.include(classNameToRemove)) return; - this.set(this.select(function(className) { - return className != classNameToRemove; - }).join(' ')); - }, - - toString: function() { - return this.toArray().join(' '); - } -} - -Object.extend(Element.ClassNames.prototype, Enumerable); -var Field = { - clear: function() { - for (var i = 0; i < arguments.length; i++) - $(arguments[i]).value = ''; - }, - - focus: function(element) { - $(element).focus(); - }, - - present: function() { - for (var i = 0; i < arguments.length; i++) - if ($(arguments[i]).value == '') return false; - return true; - }, - - select: function(element) { - $(element).select(); - }, - - activate: function(element) { - element = $(element); - element.focus(); - if (element.select) - element.select(); - } -} - -/*--------------------------------------------------------------------------*/ - -var Form = { - serialize: function(form) { - var elements = Form.getElements($(form)); - var queryComponents = new Array(); - - for (var i = 0; i < elements.length; i++) { - var queryComponent = Form.Element.serialize(elements[i]); - if (queryComponent) - queryComponents.push(queryComponent); - } - - return queryComponents.join('&'); - }, - - getElements: function(form) { - form = $(form); - var elements = new Array(); - - for (tagName in Form.Element.Serializers) { - var tagElements = form.getElementsByTagName(tagName); - for (var j = 0; j < tagElements.length; j++) - elements.push(tagElements[j]); - } - return elements; - }, - - getInputs: function(form, typeName, name) { - form = $(form); - var inputs = form.getElementsByTagName('input'); - - if (!typeName && !name) - return inputs; - - var matchingInputs = new Array(); - for (var i = 0; i < inputs.length; i++) { - var input = inputs[i]; - if ((typeName && input.type != typeName) || - (name && input.name != name)) - continue; - matchingInputs.push(input); - } - - return matchingInputs; - }, - - disable: function(form) { - var elements = Form.getElements(form); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - element.blur(); - element.disabled = 'true'; - } - }, - - enable: function(form) { - var elements = Form.getElements(form); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - element.disabled = ''; - } - }, - - findFirstElement: function(form) { - return Form.getElements(form).find(function(element) { - return element.type != 'hidden' && !element.disabled && - ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); - }); - }, - - focusFirstElement: function(form) { - Field.activate(Form.findFirstElement(form)); - }, - - reset: function(form) { - $(form).reset(); - } -} - -Form.Element = { - serialize: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - var parameter = Form.Element.Serializers[method](element); - - if (parameter) { - var key = encodeURIComponent(parameter[0]); - if (key.length == 0) return; - - if (parameter[1].constructor != Array) - parameter[1] = [parameter[1]]; - - return parameter[1].map(function(value) { - return key + '=' + encodeURIComponent(value); - }).join('&'); - } - }, - - getValue: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - var parameter = Form.Element.Serializers[method](element); - - if (parameter) - return parameter[1]; - } -} - -Form.Element.Serializers = { - input: function(element) { - switch (element.type.toLowerCase()) { - case 'submit': - case 'hidden': - case 'password': - case 'text': - return Form.Element.Serializers.textarea(element); - case 'checkbox': - case 'radio': - return Form.Element.Serializers.inputSelector(element); - } - return false; - }, - - inputSelector: function(element) { - if (element.checked) - return [element.name, element.value]; - }, - - textarea: function(element) { - return [element.name, element.value]; - }, - - select: function(element) { - return Form.Element.Serializers[element.type == 'select-one' ? - 'selectOne' : 'selectMany'](element); - }, - - selectOne: function(element) { - var value = '', opt, index = element.selectedIndex; - if (index >= 0) { - opt = element.options[index]; - value = opt.value; - if (!value && !('value' in opt)) - value = opt.text; - } - return [element.name, value]; - }, - - selectMany: function(element) { - var value = new Array(); - for (var i = 0; i < element.length; i++) { - var opt = element.options[i]; - if (opt.selected) { - var optValue = opt.value; - if (!optValue && !('value' in opt)) - optValue = opt.text; - value.push(optValue); - } - } - return [element.name, value]; - } -} - -/*--------------------------------------------------------------------------*/ - -var $F = Form.Element.getValue; - -/*--------------------------------------------------------------------------*/ - -Abstract.TimedObserver = function() {} -Abstract.TimedObserver.prototype = { - initialize: function(element, frequency, callback) { - this.frequency = frequency; - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - this.registerCallback(); - }, - - registerCallback: function() { - setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - onTimerEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - } -} - -Form.Element.Observer = Class.create(); -Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.Observer = Class.create(); -Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { - getValue: function() { - return Form.serialize(this.element); - } -}); - -/*--------------------------------------------------------------------------*/ - -Abstract.EventObserver = function() {} -Abstract.EventObserver.prototype = { - initialize: function(element, callback) { - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - if (this.element.tagName.toLowerCase() == 'form') - this.registerFormCallbacks(); - else - this.registerCallback(this.element); - }, - - onElementEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - }, - - registerFormCallbacks: function() { - var elements = Form.getElements(this.element); - for (var i = 0; i < elements.length; i++) - this.registerCallback(elements[i]); - }, - - registerCallback: function(element) { - if (element.type) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - Event.observe(element, 'click', this.onElementEvent.bind(this)); - break; - case 'password': - case 'text': - case 'textarea': - case 'select-one': - case 'select-multiple': - Event.observe(element, 'change', this.onElementEvent.bind(this)); - break; - } - } - } -} - -Form.Element.EventObserver = Class.create(); -Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.EventObserver = Class.create(); -Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { - getValue: function() { - return Form.serialize(this.element); - } -}); -if (!window.Event) { - var Event = new Object(); -} - -Object.extend(Event, { - KEY_BACKSPACE: 8, - KEY_TAB: 9, - KEY_RETURN: 13, - KEY_ESC: 27, - KEY_LEFT: 37, - KEY_UP: 38, - KEY_RIGHT: 39, - KEY_DOWN: 40, - KEY_DELETE: 46, - - element: function(event) { - return event.target || event.srcElement; - }, - - isLeftClick: function(event) { - return (((event.which) && (event.which == 1)) || - ((event.button) && (event.button == 1))); - }, - - pointerX: function(event) { - return event.pageX || (event.clientX + - (document.documentElement.scrollLeft || document.body.scrollLeft)); - }, - - pointerY: function(event) { - return event.pageY || (event.clientY + - (document.documentElement.scrollTop || document.body.scrollTop)); - }, - - stop: function(event) { - if (event.preventDefault) { - event.preventDefault(); - event.stopPropagation(); - } else { - event.returnValue = false; - event.cancelBubble = true; - } - }, - - // find the first node with the given tagName, starting from the - // node the event was triggered on; traverses the DOM upwards - findElement: function(event, tagName) { - var element = Event.element(event); - while (element.parentNode && (!element.tagName || - (element.tagName.toUpperCase() != tagName.toUpperCase()))) - element = element.parentNode; - return element; - }, - - observers: false, - - _observeAndCache: function(element, name, observer, useCapture) { - if (!this.observers) this.observers = []; - if (element.addEventListener) { - this.observers.push([element, name, observer, useCapture]); - element.addEventListener(name, observer, useCapture); - } else if (element.attachEvent) { - this.observers.push([element, name, observer, useCapture]); - element.attachEvent('on' + name, observer); - } - }, - - unloadCache: function() { - if (!Event.observers) return; - for (var i = 0; i < Event.observers.length; i++) { - Event.stopObserving.apply(this, Event.observers[i]); - Event.observers[i][0] = null; - } - Event.observers = false; - }, - - observe: function(element, name, observer, useCapture) { - var element = $(element); - useCapture = useCapture || false; - - if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.attachEvent)) - name = 'keydown'; - - this._observeAndCache(element, name, observer, useCapture); - }, - - stopObserving: function(element, name, observer, useCapture) { - var element = $(element); - useCapture = useCapture || false; - - if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.detachEvent)) - name = 'keydown'; - - if (element.removeEventListener) { - element.removeEventListener(name, observer, useCapture); - } else if (element.detachEvent) { - element.detachEvent('on' + name, observer); - } - } -}); - -/* prevent memory leaks in IE */ -Event.observe(window, 'unload', Event.unloadCache, false); -var Position = { - // set to true if needed, warning: firefox performance problems - // NOT neeeded for page scrolling, only if draggable contained in - // scrollable elements - includeScrollOffsets: false, - - // must be called before calling withinIncludingScrolloffset, every time the - // page is scrolled - prepare: function() { - this.deltaX = window.pageXOffset - || document.documentElement.scrollLeft - || document.body.scrollLeft - || 0; - this.deltaY = window.pageYOffset - || document.documentElement.scrollTop - || document.body.scrollTop - || 0; - }, - - realOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.scrollTop || 0; - valueL += element.scrollLeft || 0; - element = element.parentNode; - } while (element); - return [valueL, valueT]; - }, - - cumulativeOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - } while (element); - return [valueL, valueT]; - }, - - positionedOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - if (element) { - p = Element.getStyle(element, 'position'); - if (p == 'relative' || p == 'absolute') break; - } - } while (element); - return [valueL, valueT]; - }, - - offsetParent: function(element) { - if (element.offsetParent) return element.offsetParent; - if (element == document.body) return element; - - while ((element = element.parentNode) && element != document.body) - if (Element.getStyle(element, 'position') != 'static') - return element; - - return document.body; - }, - - // caches x/y coordinate pair to use with overlap - within: function(element, x, y) { - if (this.includeScrollOffsets) - return this.withinIncludingScrolloffsets(element, x, y); - this.xcomp = x; - this.ycomp = y; - this.offset = this.cumulativeOffset(element); - - return (y >= this.offset[1] && - y < this.offset[1] + element.offsetHeight && - x >= this.offset[0] && - x < this.offset[0] + element.offsetWidth); - }, - - withinIncludingScrolloffsets: function(element, x, y) { - var offsetcache = this.realOffset(element); - - this.xcomp = x + offsetcache[0] - this.deltaX; - this.ycomp = y + offsetcache[1] - this.deltaY; - this.offset = this.cumulativeOffset(element); - - return (this.ycomp >= this.offset[1] && - this.ycomp < this.offset[1] + element.offsetHeight && - this.xcomp >= this.offset[0] && - this.xcomp < this.offset[0] + element.offsetWidth); - }, - - // within must be called directly before - overlap: function(mode, element) { - if (!mode) return 0; - if (mode == 'vertical') - return ((this.offset[1] + element.offsetHeight) - this.ycomp) / - element.offsetHeight; - if (mode == 'horizontal') - return ((this.offset[0] + element.offsetWidth) - this.xcomp) / - element.offsetWidth; - }, - - clone: function(source, target) { - source = $(source); - target = $(target); - target.style.position = 'absolute'; - var offsets = this.cumulativeOffset(source); - target.style.top = offsets[1] + 'px'; - target.style.left = offsets[0] + 'px'; - target.style.width = source.offsetWidth + 'px'; - target.style.height = source.offsetHeight + 'px'; - }, - - page: function(forElement) { - var valueT = 0, valueL = 0; - - var element = forElement; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - - // Safari fix - if (element.offsetParent==document.body) - if (Element.getStyle(element,'position')=='absolute') break; - - } while (element = element.offsetParent); - - element = forElement; - do { - valueT -= element.scrollTop || 0; - valueL -= element.scrollLeft || 0; - } while (element = element.parentNode); - - return [valueL, valueT]; - }, - - clone: function(source, target) { - var options = Object.extend({ - setLeft: true, - setTop: true, - setWidth: true, - setHeight: true, - offsetTop: 0, - offsetLeft: 0 - }, arguments[2] || {}) - - // find page position of source - source = $(source); - var p = Position.page(source); - - // find coordinate system to use - target = $(target); - var delta = [0, 0]; - var parent = null; - // delta [0,0] will do fine with position: fixed elements, - // position:absolute needs offsetParent deltas - if (Element.getStyle(target,'position') == 'absolute') { - parent = Position.offsetParent(target); - delta = Position.page(parent); - } - - // correct by body offsets (fixes Safari) - if (parent == document.body) { - delta[0] -= document.body.offsetLeft; - delta[1] -= document.body.offsetTop; - } - - // set position - if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; - if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; - if(options.setWidth) target.style.width = source.offsetWidth + 'px'; - if(options.setHeight) target.style.height = source.offsetHeight + 'px'; - }, - - absolutize: function(element) { - element = $(element); - if (element.style.position == 'absolute') return; - Position.prepare(); - - var offsets = Position.positionedOffset(element); - var top = offsets[1]; - var left = offsets[0]; - var width = element.clientWidth; - var height = element.clientHeight; - - element._originalLeft = left - parseFloat(element.style.left || 0); - element._originalTop = top - parseFloat(element.style.top || 0); - element._originalWidth = element.style.width; - element._originalHeight = element.style.height; - - element.style.position = 'absolute'; - element.style.top = top + 'px';; - element.style.left = left + 'px';; - element.style.width = width + 'px';; - element.style.height = height + 'px';; - }, - - relativize: function(element) { - element = $(element); - if (element.style.position == 'relative') return; - Position.prepare(); - - element.style.position = 'relative'; - var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); - var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); - - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.height = element._originalHeight; - element.style.width = element._originalWidth; - } -} - -// Safari returns margins on body which is incorrect if the child is absolutely -// positioned. For performance reasons, redefine Position.cumulativeOffset for -// KHTML/WebKit only. -if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { - Position.cumulativeOffset = function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - if (element.offsetParent == document.body) - if (Element.getStyle(element, 'position') == 'absolute') break; - - element = element.offsetParent; - } while (element); - - return [valueL, valueT]; - } -} \ No newline at end of file diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Demo.html b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Demo.html deleted file mode 100644 index 6078ad109..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Demo.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - -
        -
        - - - - -
        - %sender% -
        -
        - - - - - - - - - - - - - -
        - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. -
        Torrey @ 4:55 am
        -
        -
        - testing 1 -
        %sender% @ %time%
        -
        -
        -
        - testing 123 -
        %sender% @ %time%
        -
        -
        -
        - testing 123testing 123testing 123testing 123 - testing 123testing 123 -
        %sender% @ %time%
        -
        -
        -
        -
        -
        - -
        - - - - -
        - %sender% -
        -
        - - - - - - - - - - - - - -
        - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas aliquam sapien. Aliquam sed erat eu leo bibendum egestas. Praesent mauris. Quisque eget eros et neque scelerisque convallis. Phasellus orci. Pellentesque interdum tellus a erat. venenatis tristique. -
        Torrey @ 4:55 am
        -
        -
        -
        -
        - -
        - - \ No newline at end of file diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Header.html b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Header.html deleted file mode 100644 index b71506372..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Header.html +++ /dev/null @@ -1,5 +0,0 @@ -
        -
        -
        -
        -
        \ No newline at end of file diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/Content.html b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/Content.html deleted file mode 100644 index 91741d6fb..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/Content.html +++ /dev/null @@ -1,30 +0,0 @@ -
        - - - - -
        - -
        -
        - - - - - - - - - - - - - -
        - %message% -
        %sender% @ %time%
        - -
        -
        -
        -
        diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/Context.html b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/Context.html deleted file mode 100644 index b1aca2722..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/Context.html +++ /dev/null @@ -1,30 +0,0 @@ -
        - - - - -
        - -
        -
        - - - - - - - - - - - - - -
        - %message% -
        %sender% @ %time%
        - -
        -
        -
        -
        diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/NextContent.html b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/NextContent.html deleted file mode 100644 index 4aec8ab98..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/NextContent.html +++ /dev/null @@ -1,10 +0,0 @@ -
        -
        -
        - - %message% -
        %time%
        -
        - -
        - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/NextContext.html b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/NextContext.html deleted file mode 100644 index 18b8dc46b..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/NextContext.html +++ /dev/null @@ -1,7 +0,0 @@ -
        -
        - - %message% -
        %time%
        -
        - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/Thumbs.db b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/Thumbs.db deleted file mode 100644 index f1ffef03a..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/Thumbs.db and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/buddy_icon.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/buddy_icon.png deleted file mode 100644 index 1d9f5f338..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Incoming/buddy_icon.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/Content.html b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/Content.html deleted file mode 100644 index 7822cac46..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/Content.html +++ /dev/null @@ -1,31 +0,0 @@ -
        - - - - -
        - -
        -
        - - - - - - - - - - - - - -
        - - %message% -
        %sender% @ %time%
        - -
        -
        -
        -
        diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/Context.html b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/Context.html deleted file mode 100644 index 7822cac46..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/Context.html +++ /dev/null @@ -1,31 +0,0 @@ -
        - - - - -
        - -
        -
        - - - - - - - - - - - - - -
        - - %message% -
        %sender% @ %time%
        - -
        -
        -
        -
        diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/NextContent.html b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/NextContent.html deleted file mode 100644 index 4367197d6..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/NextContent.html +++ /dev/null @@ -1,9 +0,0 @@ -
        -
        -
        - %message% -
        %time%
        -
        - -
        - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/NextContext.html b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/NextContext.html deleted file mode 100644 index 1f8477141..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/NextContext.html +++ /dev/null @@ -1,6 +0,0 @@ -
        -
        - %message% -
        %time%
        -
        - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/Thumbs.db b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/Thumbs.db deleted file mode 100644 index 7bad0d53c..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/Thumbs.db and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/buddy_icon.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/buddy_icon.png deleted file mode 100644 index 1d9f5f338..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Outgoing/buddy_icon.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Status.html b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Status.html deleted file mode 100644 index b8168e869..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Status.html +++ /dev/null @@ -1,27 +0,0 @@ -
        - - - - -
        -
        - - - - - - - - - - - - - -
        - %message% -
        %time%
        -
        -
        -
        -
        diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Template.html b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Template.html deleted file mode 100644 index fc33012a0..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Template.html +++ /dev/null @@ -1,351 +0,0 @@ - - - - - - - - - - - - - -%header% -
        -
        -%footer% -
        -
        - - \ No newline at end of file diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Thumbs.db b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Thumbs.db deleted file mode 100644 index d38969573..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Thumbs.db and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/#Untitled-2# b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/#Untitled-2# deleted file mode 100644 index 361856d57..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/#Untitled-2# +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Yellow on Blue.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/yellowIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Green Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Green Alternating.css deleted file mode 100644 index 5b910ebbf..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Green Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Blue on Green.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/blueIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Green No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Green No Names Alt.css deleted file mode 100644 index ebad31401..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Green No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Blue on Green Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Green No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Green No Names.css deleted file mode 100644 index 2a0902c36..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Green No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Blue on Green.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Green.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Green.css deleted file mode 100644 index b4cd6dccb..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Green.css +++ /dev/null @@ -1,95 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#bddff8; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/blueIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/blueCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/blueCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/blueCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/blueBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/blueBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/blueCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/blueCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#ddf0fe; - border-bottom:1px solid #fff; -} - -/*incoming */ - -.incomingItem .timeStamp { - color:#b3cf77; -} - - -.incomingItem .myBubble .indicator { - background:url("../images/greenIndicator.png") no-repeat top left; -} - -.incomingItem .timeStamp { - color:#b3cf77; -} - -.incomingItem .tableBubble .tl { - background:url("../images/greenCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/greenCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/greenCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/greenBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/greenBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/greenCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/greenCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#f4f2cb; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Red Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Red Alternating.css deleted file mode 100644 index 5481c10bd..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Red Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Blue on Red.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/blueIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Red No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Red No Names Alt.css deleted file mode 100644 index 9818a6c7e..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Red No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Blue on Red Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Red No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Red No Names.css deleted file mode 100644 index 3ac8c9ab6..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Red No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Blue on Red.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Red.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Red.css deleted file mode 100644 index a62ca464e..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Red.css +++ /dev/null @@ -1,89 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#bddff8; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/blueIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/blueCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/blueCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/blueCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/blueBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/blueBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/blueCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/blueCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#ddf0fe; - border-bottom:1px solid #fff; -} - - -/*incoming */ - -.incomingItem .timeStamp { - color:#f8b1b1; -} - -.incomingItem .myBubble .indicator { - background:url("../images/redIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/redCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/redCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/redCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/redBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/redBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/redCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/redCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#ffdada; - border-bottom:1px solid #fff; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Steel Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Steel Alternating.css deleted file mode 100644 index 8473d1fed..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Steel Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Blue on Steel.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/blueIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Steel No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Steel No Names Alt.css deleted file mode 100644 index 1925d5c53..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Steel No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Blue on Steel Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Steel No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Steel No Names.css deleted file mode 100644 index 573aa58bb..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Steel No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Blue on Steel.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Steel.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Steel.css deleted file mode 100644 index c51bdffd2..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Steel.css +++ /dev/null @@ -1,91 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#bddff8; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/blueIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/blueCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/blueCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/blueCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/blueBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/blueBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/blueCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/blueCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#ddf0fe; - border-bottom:1px solid #fff; -} - - -/*incoming */ - -.incomingItem .timeStamp { - color:#d2d2d2; -} - -.incomingItem .myBubble .indicator { - background:url("../images/steelIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/steelCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/steelCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/steelCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/steelBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/steelBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/steelCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/steelCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#ececec; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Yellow Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Yellow Alternating.css deleted file mode 100644 index d7927fc8a..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Yellow Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Blue on Yellow.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/blueIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Yellow No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Yellow No Names Alt.css deleted file mode 100644 index 38d374d34..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Yellow No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Blue on Yellow Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Yellow No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Yellow No Names.css deleted file mode 100644 index 3fdc8cd62..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Yellow No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Blue on Yellow.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Yellow.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Yellow.css deleted file mode 100644 index ac977be4b..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Blue on Yellow.css +++ /dev/null @@ -1,91 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#bddff8; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/blueIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/blueCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/blueCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/blueCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/blueBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/blueBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/blueCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/blueCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#ddf0fe; - border-bottom:1px solid #fff; -} - - -/*incoming */ - -.incomingItem .timeStamp { - color:#dbd789; -} - -.incomingItem .myBubble .indicator { - background:url("../images/yellowIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/yellowCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/yellowCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/yellowCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/yellowBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/yellowBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/yellowCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/yellowCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#f4f2cb; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Blue Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Blue Alternating.css deleted file mode 100644 index 272c0d0c4..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Blue Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Green on Blue.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/greenIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Blue No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Blue No Names Alt.css deleted file mode 100644 index 973f91a10..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Blue No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Green on Blue Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Blue No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Blue No Names.css deleted file mode 100644 index 0d92eb0bc..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Blue No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Green on Blue.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Blue.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Blue.css deleted file mode 100644 index d1ca563ea..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Blue.css +++ /dev/null @@ -1,91 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#b3cf77; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/greenIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/greenCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/greenCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/greenCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/greenBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/greenBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/greenCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/greenCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#e2efc4; - border-bottom:1px solid #fff; -} - - -/*incoming */ - -.incomingItem .timeStamp { - color:#bddff8; -} - -.incomingItem .myBubble .indicator { - background:url("../images/blueIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/blueCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/blueCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/blueCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/blueBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/blueBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/blueCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/blueCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#ddf0fe; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Red Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Red Alternating.css deleted file mode 100644 index e656dc0ed..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Red Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Green on Red.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/greenIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Red No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Red No Names Alt.css deleted file mode 100644 index 5fd248244..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Red No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Green on Red Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Red No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Red No Names.css deleted file mode 100644 index 23dae8198..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Red No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Green on Red.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Red.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Red.css deleted file mode 100644 index 269611cf1..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Red.css +++ /dev/null @@ -1,91 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#b3cf77; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/greenIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/greenCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/greenCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/greenCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/greenBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/greenBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/greenCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/greenCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#e2efc4; - border-bottom:1px solid #fff; -} - - -/*incoming */ - -.incomingItem .timeStamp { - color:#f8b1b1; -} - -.incomingItem .myBubble .indicator { - background:url("../images/redIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/redCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/redCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/redCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/redBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/redBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/redCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/redCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#ffdada; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Steel Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Steel Alternating.css deleted file mode 100644 index 3c14f7fa8..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Steel Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Green on Steel.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/greenIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Steel No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Steel No Names Alt.css deleted file mode 100644 index cfd6bb938..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Steel No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Green on Steel Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Steel No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Steel No Names.css deleted file mode 100644 index 41bc9de58..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Steel No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Green on Steel.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Steel.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Steel.css deleted file mode 100644 index d8116f50c..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Steel.css +++ /dev/null @@ -1,91 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#b3cf77; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/greenIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/greenCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/greenCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/greenCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/greenBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/greenBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/greenCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/greenCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#e2efc4; - border-bottom:1px solid #fff; -} - - -/*incoming */ - -.incomingItem .timeStamp { - color:#d2d2d2; -} - -.incomingItem .myBubble .indicator { - background:url("../images/steelIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/steelCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/steelCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/steelCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/steelBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/steelBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/steelCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/steelCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#ececec; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Yellow Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Yellow Alternating.css deleted file mode 100644 index d0553e806..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Yellow Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Green on Yellow.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/greenIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Yellow No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Yellow No Names Alt.css deleted file mode 100644 index 27adc3348..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Yellow No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Green on Yellow Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Yellow No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Yellow No Names.css deleted file mode 100644 index 8c8cb2865..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Yellow No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Green on Yellow.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Yellow.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Yellow.css deleted file mode 100644 index 4b32ff2d8..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Green on Yellow.css +++ /dev/null @@ -1,91 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#b3cf77; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/greenIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/greenCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/greenCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/greenCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/greenBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/greenBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/greenCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/greenCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#e2efc4; - border-bottom:1px solid #fff; -} - - -/*incoming */ - -.incomingItem .timeStamp { - color:#dbd789; -} - -.incomingItem .myBubble .indicator { - background:url("../images/yellowIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/yellowCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/yellowCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/yellowCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/yellowBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/yellowBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/yellowCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/yellowCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#f4f2cb; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Blue Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Blue Alternating.css deleted file mode 100644 index 5d241fb22..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Blue Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Red on Blue.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/redIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Blue No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Blue No Names Alt.css deleted file mode 100644 index 2e80935aa..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Blue No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Red on Blue Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Blue No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Blue No Names.css deleted file mode 100644 index da98b5c1c..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Blue No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Red on Blue.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Blue.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Blue.css deleted file mode 100644 index fb4a32132..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Blue.css +++ /dev/null @@ -1,90 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#f8b1b1; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/redIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/redCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/redCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/redCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/redBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/redBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/redCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/redCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#ffdada; - border-bottom:1px solid #fff; -} - - - -/*incoming */ - -.incomingItem .timeStamp { - color:#bddff8; -} - -.incomingItem .myBubble .indicator { - background:url("../images/blueIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/blueCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/blueCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/blueCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/blueBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/blueBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/blueCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/blueCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#ddf0fe; - border-bottom:1px solid #fff; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Green Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Green Alternating.css deleted file mode 100644 index db8effab4..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Green Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Red on Green.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/redIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Green No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Green No Names Alt.css deleted file mode 100644 index 9a230f22d..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Green No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Red on Green Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Green No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Green No Names.css deleted file mode 100644 index 1bbc2a56e..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Green No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Red on Green.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Green.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Green.css deleted file mode 100644 index 52759b0d5..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Green.css +++ /dev/null @@ -1,95 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#f8b1b1; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/redIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/redCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/redCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/redCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/redBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/redBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/redCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/redCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#ffdada; - border-bottom:1px solid #fff; -} - -/*incoming */ - -.incomingItem .timeStamp { - color:#b3cf77; -} - - -.incomingItem .myBubble .indicator { - background:url("../images/greenIndicator.png") no-repeat top left; -} - -.incomingItem .timeStamp { - color:#b3cf77; -} - -.incomingItem .tableBubble .tl { - background:url("../images/greenCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/greenCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/greenCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/greenBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/greenBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/greenCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/greenCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#f4f2cb; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Steel Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Steel Alternating.css deleted file mode 100644 index ad7eb15a3..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Steel Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Red on Steel.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/redIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Steel No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Steel No Names Alt.css deleted file mode 100644 index 9c6ab55d0..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Steel No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Red on Steel Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Steel No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Steel No Names.css deleted file mode 100644 index aa2b60ab3..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Steel No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Red on Steel.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Steel.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Steel.css deleted file mode 100644 index 4e5484701..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Steel.css +++ /dev/null @@ -1,93 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#f8b1b1; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/redIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/redCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/redCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/redCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/redBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/redBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/redCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/redCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#ffdada; - border-bottom:1px solid #fff; -} - - - - -/*incoming */ - -.incomingItem .timeStamp { - color:#d2d2d2; -} - -.incomingItem .myBubble .indicator { - background:url("../images/steelIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/steelCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/steelCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/steelCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/steelBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/steelBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/steelCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/steelCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#ececec; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Yellow Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Yellow Alternating.css deleted file mode 100644 index b264d7d5a..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Yellow Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Red on Yellow.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/redIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Yellow No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Yellow No Names Alt.css deleted file mode 100644 index dc4394ed4..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Yellow No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Red on Yellow Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Yellow No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Yellow No Names.css deleted file mode 100644 index 9ca44ec0f..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Yellow No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Red on Yellow.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Yellow.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Yellow.css deleted file mode 100644 index a420d9a0f..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Red on Yellow.css +++ /dev/null @@ -1,91 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#f8b1b1; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/redIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/redCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/redCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/redCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/redBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/redBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/redCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/redCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#ffdada; - border-bottom:1px solid #fff; -} - - - - -/*incoming */ - -.incomingItem .timeStamp { - color:#dbd789; -} - -.incomingItem .myBubble .indicator { - background:url("../images/yellowIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/yellowCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/yellowCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/yellowCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/yellowBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/yellowBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/yellowCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/yellowCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#f4f2cb; - border-bottom:1px solid #fff; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Blue Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Blue Alternating.css deleted file mode 100644 index 8c15ec2b5..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Blue Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Steel on Blue.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/steelIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Blue No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Blue No Names Alt.css deleted file mode 100644 index 7edfcb1b2..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Blue No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Steel on Blue Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Blue No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Blue No Names.css deleted file mode 100644 index f7058b9b4..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Blue No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Steel on Blue.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Blue.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Blue.css deleted file mode 100644 index 05eb960c4..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Blue.css +++ /dev/null @@ -1,92 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#d2d2d2; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/steelIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/steelCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/steelCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/steelCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/steelBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/steelBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/steelCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/steelCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#ececec; - border-bottom:1px solid #fff; -} - - - -/*incoming */ - -.incomingItem .timeStamp { - color:#bddff8; -} - -.incomingItem .myBubble .indicator { - background:url("../images/blueIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/blueCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/blueCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/blueCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/blueBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/blueBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/blueCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/blueCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#ddf0fe; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Green Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Green Alternating.css deleted file mode 100644 index 69474f0a0..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Green Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Steel on Green.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/steelIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Green No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Green No Names Alt.css deleted file mode 100644 index 6fc5606d8..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Green No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Steel on Green Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Green No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Green No Names.css deleted file mode 100644 index f07264ba2..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Green No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Steel on Green.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Green.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Green.css deleted file mode 100644 index 1d683ac5f..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Green.css +++ /dev/null @@ -1,97 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#d2d2d2; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/steelIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/steelCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/steelCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/steelCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/steelBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/steelBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/steelCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/steelCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#ececec; - border-bottom:1px solid #fff; -} - - - -/*incoming */ - -.incomingItem .timeStamp { - color:#b3cf77; -} - - -.incomingItem .myBubble .indicator { - background:url("../images/greenIndicator.png") no-repeat top left; -} - -.incomingItem .timeStamp { - color:#b3cf77; -} - -.incomingItem .tableBubble .tl { - background:url("../images/greenCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/greenCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/greenCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/greenBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/greenBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/greenCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/greenCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#f4f2cb; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Red Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Red Alternating.css deleted file mode 100644 index 64a783b25..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Red Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Steel on Red.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/steelIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Red No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Red No Names Alt.css deleted file mode 100644 index 995f329c6..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Red No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Steel on Red Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Red No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Red No Names.css deleted file mode 100644 index b5e622eb8..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Red No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Steel on Red.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Red.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Red.css deleted file mode 100644 index 04ba68e2e..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Red.css +++ /dev/null @@ -1,89 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#d2d2d2; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/steelIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/steelCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/steelCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/steelCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/steelBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/steelBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/steelCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/steelCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#ececec; - border-bottom:1px solid #fff; -} - - -/*incoming */ - -.incomingItem .timeStamp { - color:#f8b1b1; -} - -.incomingItem .myBubble .indicator { - background:url("../images/redIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/redCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/redCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/redCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/redBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/redBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/redCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/redCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#ffdada; - border-bottom:1px solid #fff; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Yellow Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Yellow Alternating.css deleted file mode 100644 index 024923009..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Yellow Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Steel on Yellow.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/steelIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Yellow No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Yellow No Names Alt.css deleted file mode 100644 index 9ab928c17..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Yellow No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Steel on Yellow Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Yellow No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Yellow No Names.css deleted file mode 100644 index ecf786185..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Yellow No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Steel on Yellow.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Yellow.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Yellow.css deleted file mode 100644 index 91f6ade3b..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Steel on Yellow.css +++ /dev/null @@ -1,92 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#d2d2d2; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/steelIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/steelCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/steelCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/steelCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/steelBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/steelBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/steelCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/steelCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#ececec; - border-bottom:1px solid #fff; -} - - - -/*incoming */ - -.incomingItem .timeStamp { - color:#dbd789; -} - -.incomingItem .myBubble .indicator { - background:url("../images/yellowIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/yellowCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/yellowCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/yellowCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/yellowBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/yellowBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/yellowCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/yellowCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#f4f2cb; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Blue Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Blue Alternating.css deleted file mode 100644 index 361856d57..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Blue Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Yellow on Blue.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/yellowIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Blue No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Blue No Names Alt.css deleted file mode 100644 index 2e31a7c4a..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Blue No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Yellow on Blue Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Blue No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Blue No Names.css deleted file mode 100644 index 808377f41..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Blue No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Yellow on Blue.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Blue.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Blue.css deleted file mode 100644 index caae09498..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Blue.css +++ /dev/null @@ -1,91 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#dbd789; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/yellowIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/yellowCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/yellowCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/yellowCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/yellowBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/yellowBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/yellowCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/yellowCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#e2efc4; - border-bottom:1px solid #fff; -} - - -/*incoming */ - -.incomingItem .timeStamp { - color:#bddff8; -} - -.incomingItem .myBubble .indicator { - background:url("../images/blueIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/blueCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/blueCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/blueCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/blueBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/blueBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/blueCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/blueCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#ddf0fe; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Green Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Green Alternating.css deleted file mode 100644 index cb88dfbc7..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Green Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Yellow on Green.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/yellowIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Green No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Green No Names Alt.css deleted file mode 100644 index 24fe8efd3..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Green No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Yellow on Green Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Green No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Green No Names.css deleted file mode 100644 index 0c7d12bce..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Green No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Yellow on Green.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Green.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Green.css deleted file mode 100644 index 880e62ae4..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Green.css +++ /dev/null @@ -1,96 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#dbd789; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/yellowIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/yellowCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/yellowCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/yellowCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/yellowBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/yellowBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/yellowCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/yellowCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#f4f2cb; - border-bottom:1px solid #fff; -} - - -/*incoming */ - -.incomingItem .timeStamp { - color:#b3cf77; -} - - -.incomingItem .myBubble .indicator { - background:url("../images/greenIndicator.png") no-repeat top left; -} - -.incomingItem .timeStamp { - color:#b3cf77; -} - -.incomingItem .tableBubble .tl { - background:url("../images/greenCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/greenCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/greenCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/greenBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/greenBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/greenCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/greenCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#e2efc4; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Red Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Red Alternating.css deleted file mode 100644 index 592b8c40d..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Red Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Yellow on Red.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/yellowIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Red No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Red No Names Alt.css deleted file mode 100644 index fe464d9b3..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Red No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Yellow on Red Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Red No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Red No Names.css deleted file mode 100644 index f35c8a20f..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Red No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Yellow on Red.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Red.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Red.css deleted file mode 100644 index e4930edd7..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Red.css +++ /dev/null @@ -1,91 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#dbd789; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/yellowIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/yellowCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/yellowCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/yellowCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/yellowBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/yellowBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/yellowCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/yellowCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#e2efc4; - border-bottom:1px solid #fff; -} - - -/*incoming */ - -.incomingItem .timeStamp { - color:#f8b1b1; -} - -.incomingItem .myBubble .indicator { - background:url("../images/redIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/redCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/redCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/redCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/redBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/redBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/redCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/redCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#ffdada; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Steel Alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Steel Alternating.css deleted file mode 100644 index a019487e9..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Steel Alternating.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("Yellow on Steel.css"); -@import url("../alternating.css"); - - -.outgoingItem .myBubble .indicator { - background:url("../images/yellowIndicator2.png") no-repeat top left; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Steel No Names Alt.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Steel No Names Alt.css deleted file mode 100644 index 273bcbb9f..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Steel No Names Alt.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Yellow on Steel Alternating.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Steel No Names.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Steel No Names.css deleted file mode 100644 index 1f8d314da..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Steel No Names.css +++ /dev/null @@ -1,2 +0,0 @@ -@import url("Yellow on Steel.css"); -@import url("../noname.css"); diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Steel.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Steel.css deleted file mode 100644 index 4983dedbb..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/Variants/Yellow on Steel.css +++ /dev/null @@ -1,91 +0,0 @@ -@import url("../main.css"); - -/* outgoing */ - - -.outgoingItem .timeStamp { - color:#dbd789; -} - -.outgoingItem .myBubble .indicator { - background:url("../images/yellowIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("../images/yellowCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("../images/yellowCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("../images/yellowCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("../images/yellowBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("../images/yellowBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("../images/yellowCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("../images/yellowCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#e2efc4; - border-bottom:1px solid #fff; -} - - -/*incoming */ - -.incomingItem .timeStamp { - color:#d2d2d2; -} - -.incomingItem .myBubble .indicator { - background:url("../images/steelIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("../images/steelCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("../images/steelCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("../images/steelCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("../images/steelBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("../images/steelBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("../images/steelCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("../images/steelCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#ececec; - border-bottom:1px solid #fff; -} - - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/alternating.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/alternating.css deleted file mode 100644 index 2b2114721..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/alternating.css +++ /dev/null @@ -1,16 +0,0 @@ - -.outgoingItem .avatar { - float:right; -} - -.outgoingItem .indicator { - float:right; - position:relative; - left:11px; - top:8px; -} - -.myBubble { - margin-right:40px; -} - diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/DummyContact.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/DummyContact.png deleted file mode 100644 index 5149ea57d..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/DummyContact.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/Thumbs.db b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/Thumbs.db deleted file mode 100644 index 9783c9076..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/Thumbs.db and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/alert.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/alert.png deleted file mode 100644 index ad59ebc05..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/alert.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueBackground.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueBackground.gif deleted file mode 100644 index 1aad572c9..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueBackground.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueBackground.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueBackground.png deleted file mode 100644 index c3eecf553..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueBackground.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueCurves.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueCurves.gif deleted file mode 100644 index 90e382352..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueCurves.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueCurves.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueCurves.png deleted file mode 100644 index 7a6afe1af..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueCurves.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueIndicator.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueIndicator.gif deleted file mode 100644 index 3a1b40a00..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueIndicator.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueIndicator.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueIndicator.png deleted file mode 100644 index 29b65cbc0..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueIndicator.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueIndicator2.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueIndicator2.png deleted file mode 100644 index d7c36215d..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueIndicator2.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueIndicatorAlt.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueIndicatorAlt.gif deleted file mode 100644 index aaacb893c..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/blueIndicatorAlt.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenBackground.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenBackground.gif deleted file mode 100644 index a11a52d7f..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenBackground.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenBackground.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenBackground.png deleted file mode 100644 index dfeb36e53..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenBackground.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenCurves.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenCurves.gif deleted file mode 100644 index 165892ab7..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenCurves.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenCurves.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenCurves.png deleted file mode 100644 index 13fae75dd..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenCurves.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenIndicator.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenIndicator.gif deleted file mode 100644 index b6409c7b8..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenIndicator.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenIndicator.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenIndicator.png deleted file mode 100644 index 381db8225..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenIndicator.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenIndicator2.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenIndicator2.png deleted file mode 100644 index 1dedb3165..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenIndicator2.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenIndicatorAlt.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenIndicatorAlt.gif deleted file mode 100644 index 3ccbc23d7..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/greenIndicatorAlt.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redBackground.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redBackground.gif deleted file mode 100644 index ce1443e4d..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redBackground.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redBackground.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redBackground.png deleted file mode 100644 index bbacbc7a1..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redBackground.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redCurves.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redCurves.gif deleted file mode 100644 index 55e496d2a..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redCurves.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redCurves.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redCurves.png deleted file mode 100644 index 3e7065a96..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redCurves.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redIndicator.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redIndicator.gif deleted file mode 100644 index 58e189c15..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redIndicator.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redIndicator.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redIndicator.png deleted file mode 100644 index 9c906a94e..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redIndicator.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redIndicator2.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redIndicator2.png deleted file mode 100644 index 1f625a09f..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redIndicator2.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redIndicatorAlt.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redIndicatorAlt.gif deleted file mode 100644 index 1f9c4f1d9..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/redIndicatorAlt.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/silverBackground.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/silverBackground.gif deleted file mode 100644 index b2798a4c9..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/silverBackground.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/silverCurves.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/silverCurves.gif deleted file mode 100644 index b7bca3034..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/silverCurves.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelBackground.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelBackground.gif deleted file mode 100644 index c292710d5..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelBackground.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelBackground.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelBackground.png deleted file mode 100644 index b1180d3c4..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelBackground.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelCurves.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelCurves.gif deleted file mode 100644 index 663c5c32f..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelCurves.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelCurves.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelCurves.png deleted file mode 100644 index e1ddeb0dc..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelCurves.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelHeading.jpg b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelHeading.jpg deleted file mode 100644 index a319c7e2f..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelHeading.jpg and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelIndicator.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelIndicator.gif deleted file mode 100644 index 0d91eed96..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelIndicator.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelIndicator.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelIndicator.png deleted file mode 100644 index 48a3af574..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelIndicator.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelIndicator2.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelIndicator2.png deleted file mode 100644 index 1a34ac716..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelIndicator2.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelIndicatorAlt.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelIndicatorAlt.gif deleted file mode 100644 index 5d7686d76..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/steelIndicatorAlt.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/typing-left.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/typing-left.png deleted file mode 100644 index e5448a564..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/typing-left.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/typing-right.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/typing-right.png deleted file mode 100644 index 1e997d4cb..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/typing-right.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowBackground.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowBackground.gif deleted file mode 100644 index adcdb5d55..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowBackground.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowBackground.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowBackground.png deleted file mode 100644 index ea79d0682..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowBackground.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowCurves.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowCurves.gif deleted file mode 100644 index c8bf931c0..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowCurves.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowCurves.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowCurves.png deleted file mode 100644 index b4133bae0..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowCurves.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowHeading.jpg b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowHeading.jpg deleted file mode 100644 index bd6f04967..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowHeading.jpg and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowIndicator.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowIndicator.gif deleted file mode 100644 index 537414c08..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowIndicator.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowIndicator.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowIndicator.png deleted file mode 100644 index bfaf23025..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowIndicator.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowIndicator2.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowIndicator2.png deleted file mode 100644 index c59fe2b57..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowIndicator2.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowIndicatorAlt.gif b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowIndicatorAlt.gif deleted file mode 100644 index f3cd7b025..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowIndicatorAlt.gif and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowTL.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowTL.png deleted file mode 100644 index 2bdfa6516..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowTL.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowTR.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowTR.png deleted file mode 100644 index 1aff191d9..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/images/yellowTR.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/incoming_icon.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/incoming_icon.png deleted file mode 100644 index 7080fd625..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/incoming_icon.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/main.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/main.css deleted file mode 100644 index 3171e6676..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/main.css +++ /dev/null @@ -1,289 +0,0 @@ -* { - word-wrap: break-word; -} - -#header1 { - position: fixed; - top: 0px; - left: 0px; - right: 0px; - margin: 0; - padding: 10px; - overflow: auto; - color: white; - font-family: Lucida Grande; - text-align: center; - font-size: 10px; - font-weight: regular; - background: rgba(0,0,0,.65); - z-index: 999; -} - -#heading { - position: fixed; - top: 0px; - left: 0px; - margin: 0; - padding: 5px; - font-weight: regular; - background-color:#fbfbed; - z-index: 999; - width:100%; - height:45px; - border-bottom:2px solid #d5d5d5; - background:url("images/steelHeading.jpg") repeat-x top left; - -} - -#heading .conversationIncomingIcon { - position:absolute; - left:5px; - top:5px; -} - -#heading .conversationIncomingIcon img { - width:48px; - height:48px; -} - -#heading .conversationWith { - position:relative; - left:60px; - margin:5px 0 0 0; - font: bold 16px Myriad Pro, Myriad, Lucida Grande, Trebuchet MS, Arial; - overflow:hide; -} - -#heading .conversationTime { - position:relative; - left:60px; - color:#6d6d6d; - font: bold 10px Myriad Pro, Myriad, Lucida Grande, Trebuchet MS, Arial; -} - -body { - margin-top: 65px; - background-color: white; - color: black; -} - -.status_container { - font: 10px Myriad, Lucida Grande, Arial; -} - - -body { -} - -.followUp { - clear:right; - height:1px; - font-size:1px; - line-height:1px; - margin:4px 0 4px 0; -} - -.chatItem { - opacity:0.96; -} - -.tableBubble { - width:100%; -} - -.tableBubble .tl { - height:8px; -} - -.tableBubble .tr { - width:8px; - height:8px; -} - -.message { - padding:0 1em 0 1.25em; - font-size:0.8em; - word-wrap: break-word; -} - - -.tableBubble .message img { - vertical-align:middle; -} - -.tableBubble .messageRight { - width:1px; -} - -.tableBubble .bl { - height:10px; -} - -.tableBubble .br { - width:8px; - height:10px; -} - -.tableBubble .timeStamp { - margin:2px; - margin-left:7px; - text-align:right; - float:right; -} - -.myBubble .indicator { - position:absolute; - top:8px; - left:0; - width:13px; - height:11px; -} - -.myBubble { - position:relative; - padding-left:10px; - margin-left:33px; - margin-right:10px; -} - -.chatItem .avatar { - width:26px; - height:26px; - float:left; -} - -/****** STatus ******/ - -.statusMessage { - opacity:0.8; - color:#676767; -} - -.statusMessage .myBubble .indicator { - background:url("images/steelIndicator.png") no-repeat top left; -} - -.statusMessage .tableBubble .tl { - background:url("images/steelCurves.png") no-repeat top left; -} - -.statusMessage .tableBubble .tr { - background:url("images/steelCurves.png") no-repeat top right; -} - -.statusMessage .tableBubble .head { - background:url("images/steelCurves.png") no-repeat -10px 0; -} - -.statusMessage .tableBubble .message { - background:url("images/steelBackground.png") repeat-y top left; -} - -.statusMessage .tableBubble .messageRight { - background:url("images/steelBackground.png") repeat-y top right; -} - -.statusMessage .tableBubble .bl { - background:url("images/steelCurves.png") no-repeat bottom left; -} - -.statusMessage .tableBubble .br { - background:url("images/steelCurves.png") no-repeat bottom right; -} - -.statusMessage .followUp { - background-color:#f4f2cb; - border-bottom:1px solid #fff; -} - -.statusMessage .timeStamp { - color:#676767; -} - - -/*incoming */ - -.incomingItem .myBubble .indicator { - background:url("images/yellowIndicator.png") no-repeat top left; -} - -.incomingItem .tableBubble .tl { - background:url("images/yellowCurves.png") no-repeat top left; -} - -.incomingItem .tableBubble .tr { - background:url("images/yellowCurves.png") no-repeat top right; -} - -.incomingItem .tableBubble .head { - background:url("images/yellowCurves.png") no-repeat -10px 0; -} - -.incomingItem .tableBubble .message { - background:url("images/yellowBackground.png") repeat-y top left; -} - -.incomingItem .tableBubble .messageRight { - background:url("images/yellowBackground.png") repeat-y top right; -} - -.incomingItem .tableBubble .bl { - background:url("images/yellowCurves.png") no-repeat bottom left; -} - -.incomingItem .tableBubble .br { - background:url("images/yellowCurves.png") no-repeat bottom right; -} - -.incomingItem .followUp { - background-color:#f4f2cb; - border-bottom:1px solid #fff; -} - -.incomingItem .timeStamp { - color:#dbd789; -} - -/* outgoing */ - - -.outgoingItem .myBubble .indicator { - background:url("images/greenIndicator.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tl { - background:url("images/greenCurves.png") no-repeat top left; -} - -.outgoingItem .tableBubble .tr { - background:url("images/greenCurves.png") no-repeat top right; -} - -.outgoingItem .tableBubble .head { - background:url("images/greenCurves.png") no-repeat -10px 0; -} - -.outgoingItem .tableBubble .message { - background:url("images/greenBackground.png") repeat-y top left; -} - -.outgoingItem .tableBubble .messageRight { - background:url("images/greenBackground.png") repeat-y top right; -} - -.outgoingItem .tableBubble .bl { - background:url("images/greenCurves.png") no-repeat bottom left; -} - -.outgoingItem .tableBubble .br { - background:url("images/greenCurves.png") no-repeat bottom right; -} - -.outgoingItem .followUp { - background-color:#e2efc4; - border-bottom:1px solid #fff; -} - -.outgoingItem .timeStamp { - color:#b3cf77; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/noname.css b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/noname.css deleted file mode 100644 index 9d905a997..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/noname.css +++ /dev/null @@ -1,3 +0,0 @@ -.name { - display:none; -} diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/outgoing_icon.png b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/outgoing_icon.png deleted file mode 100644 index 7080fd625..000000000 Binary files a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/outgoing_icon.png and /dev/null differ diff --git a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/temp.html b/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/temp.html deleted file mode 100644 index bf6165dcb..000000000 --- a/src/resources/themes/renkoo2.3/renkoo.AdiumMessageStyle/Contents/Resources/temp.html +++ /dev/null @@ -1,351 +0,0 @@ - - - - - - - - - - - - - -
        -
        -
        - -
        -
        - - \ No newline at end of file diff --git a/src/resources/themes/sparkEmoticonSet.zip b/src/resources/themes/sparkEmoticonSet.zip deleted file mode 100644 index 321088f8f..000000000 Binary files a/src/resources/themes/sparkEmoticonSet.zip and /dev/null differ diff --git a/src/resources/themes/template.html b/src/resources/themes/template.html deleted file mode 100644 index 4f307be14..000000000 --- a/src/resources/themes/template.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - - -%header% -
        -
        -%footer% -
        - - diff --git a/src/xtra/emoticons/Default.adiumemoticonset.zip b/src/xtra/emoticons/Default.adiumemoticonset.zip deleted file mode 100644 index 7662cd63d..000000000 Binary files a/src/xtra/emoticons/Default.adiumemoticonset.zip and /dev/null differ diff --git a/src/xtra/emoticons/GTalk.AdiumEmoticonset.zip b/src/xtra/emoticons/GTalk.AdiumEmoticonset.zip deleted file mode 100644 index 10475489b..000000000 Binary files a/src/xtra/emoticons/GTalk.AdiumEmoticonset.zip and /dev/null differ diff --git a/src/xtra/emoticons/POPO.adiumemoticonset.zip b/src/xtra/emoticons/POPO.adiumemoticonset.zip deleted file mode 100644 index 388b416ad..000000000 Binary files a/src/xtra/emoticons/POPO.adiumemoticonset.zip and /dev/null differ diff --git a/src/xtra/emoticons/sparkEmoticonSet.zip b/src/xtra/emoticons/sparkEmoticonSet.zip deleted file mode 100644 index 321088f8f..000000000 Binary files a/src/xtra/emoticons/sparkEmoticonSet.zip and /dev/null differ